30 #include "navier_stokes.h" 
   34 #include "meshes/one_d_lagrangian_mesh.h" 
   37 #include "meshes/collapsible_channel_mesh.h" 
   41 using namespace oomph;
 
  111  void position(
const Vector<double>& zeta, Vector<double>& r)
 const 
  122  void position(
const unsigned& t, 
const Vector<double>& zeta,
 
  123                Vector<double>& r)
 const 
  138                  DenseMatrix<double> &drdzeta,
 
  139                  RankThreeTensor<double> &ddrdzeta)
 const 
  187                           const Vector<double>& x,
 
  188                           const Vector<double>& n,
 
  189                           Vector<double>& traction)
 
  209  void load(
const Vector<double>& xi, 
const Vector<double>& x,
 
  210            const Vector<double>& N, Vector<double>& 
load)
 
  212   for(
unsigned i=0;i<2;i++) 
 
  232 template <
class ELEMENT>
 
  241                        const unsigned& ncollapsible,
 
  242                        const unsigned& ndown,
 
  245                        const double& lcollapsible, 
 
  253 #ifdef MACRO_ELEMENT_NODE_UPDATE 
  299    Bulk_mesh_pt->node_update();
 
  303  void doc_solution(DocInfo& doc_info,ofstream& trace_file);
 
  306  void set_initial_condition();
 
  311  void create_traction_elements(
const unsigned &b, 
 
  312                                Mesh* 
const &bulk_mesh_pt,
 
  313                                Mesh* 
const &traction_mesh_pt);
 
  340 #ifdef MACRO_ELEMENT_NODE_UPDATE 
  377 template <
class ELEMENT>
 
  380  const unsigned& ncollapsible,
 
  381  const unsigned& ndown,
 
  384  const double& lcollapsible, 
 
  390  Ncollapsible=ncollapsible;
 
  394  Lcollapsible=lcollapsible;
 
  400  Problem::Max_residuals=1000.0;
 
  405  add_time_stepper_pt(
new BDF<2>);
 
  414   (Ncollapsible,Lcollapsible,undeformed_wall_pt);
 
  420  MeshAsGeomObject* wall_geom_object_pt=
 
  421   new MeshAsGeomObject(Wall_mesh_pt); 
 
  424 #ifdef MACRO_ELEMENT_NODE_UPDATE 
  429   (nup, ncollapsible, ndown, ny,
 
  430    lup, lcollapsible, ldown, ly,
 
  438  Bulk_mesh_pt->node_update();
 
  445   (nup, ncollapsible, ndown, ny,
 
  446    lup, lcollapsible, ldown, ly,
 
  457  Applied_fluid_traction_mesh_pt = 
new Mesh;
 
  461  create_traction_elements(5,Bulk_mesh_pt,Applied_fluid_traction_mesh_pt);
 
  464  add_sub_mesh(Bulk_mesh_pt);
 
  465  add_sub_mesh(Applied_fluid_traction_mesh_pt);
 
  466  add_sub_mesh(Wall_mesh_pt);
 
  477  unsigned n_element=Bulk_mesh_pt->nelement();
 
  478  for(
unsigned e=0;e<n_element;e++)
 
  481    ELEMENT* el_pt = 
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
 
  499  unsigned num_nod= bulk_mesh_pt()->nboundary_node(ibound);
 
  500  for (
unsigned inod=0;inod<num_nod;inod++)
 
  502    for(
unsigned i=0;i<2;i++)
 
  504      bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(i);
 
  509  for(ibound=2;ibound<5;ibound++)
 
  511    num_nod= bulk_mesh_pt()->nboundary_node(ibound);
 
  512    for (
unsigned inod=0;inod<num_nod;inod++)
 
  514      for(
unsigned i=0;i<2;i++)
 
  516        bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(i);
 
  523  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
 
  524  for (
unsigned inod=0;inod<num_nod;inod++)
 
  526    bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(1);
 
  532  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
 
  533  for (
unsigned inod=0;inod<num_nod;inod++)
 
  535    bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(1);
 
  544  unsigned n_el=Applied_fluid_traction_mesh_pt->nelement();
 
  545  for(
unsigned e=0;e<n_el;e++)
 
  548    NavierStokesTractionElement<ELEMENT> *el_pt = 
 
  549     dynamic_cast< NavierStokesTractionElement<ELEMENT>*
>(
 
  550      Applied_fluid_traction_mesh_pt->element_pt(e));
 
  563  n_element = wall_mesh_pt()->nelement();
 
  564  for(
unsigned e=0;e<n_element;e++)
 
  567    FSIHermiteBeamElement *elem_pt = 
 
  568     dynamic_cast<FSIHermiteBeamElement*
>(wall_mesh_pt()->element_pt(e));
 
  581    elem_pt->undeformed_beam_pt() = undeformed_wall_pt;
 
  587    elem_pt->set_normal_pointing_out_of_fluid();
 
  598  for(
unsigned b=0;b<2;b++)
 
  601    wall_mesh_pt()->boundary_node_pt(b,0)->pin_position(0); 
 
  602    wall_mesh_pt()->boundary_node_pt(b,0)->pin_position(1);
 
  613  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
 
  614  unsigned control_nod=num_nod/2;
 
  615  Left_node_pt= bulk_mesh_pt()->boundary_node_pt(ibound, control_nod);
 
  619  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
 
  620  control_nod=num_nod/2;
 
  621  Right_node_pt= bulk_mesh_pt()->boundary_node_pt(ibound, control_nod);
 
  625  Wall_node_pt=wall_mesh_pt()->node_pt(Ncollapsible/2);
 
  639  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
 
  640  for (
unsigned inod=0;inod<num_nod;inod++)
 
  642    bulk_mesh_pt()->boundary_node_pt(ibound, inod)->
 
  643     set_auxiliary_node_update_fct_pt(
 
  644      FSI_functions::apply_no_slip_on_moving_wall);
 
  652  FSI_functions::setup_fluid_load_info_for_solid_elements<ELEMENT,2>
 
  653   (
this,3,Bulk_mesh_pt,Wall_mesh_pt);
 
  656  cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl; 
 
  667 template <
class ELEMENT>
 
  669                                                        ofstream& trace_file)
 
  673 #ifdef MACRO_ELEMENT_NODE_UPDATE 
  676  if (CommandLineArgs::Argc>1)
 
  678    FSI_functions::doc_fsi<MacroElementNodeUpdateNode>(Bulk_mesh_pt,Wall_mesh_pt,doc_info);
 
  684  if (CommandLineArgs::Argc>1)
 
  686    FSI_functions::doc_fsi<AlgebraicNode>(Bulk_mesh_pt,Wall_mesh_pt,doc_info);
 
  699  sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
 
  701  some_file.open(filename);
 
  702  bulk_mesh_pt()->output(some_file,npts);
 
  706  sprintf(filename,
"%s/beam%i.dat",doc_info.directory().c_str(),
 
  708  some_file.open(filename);
 
  709  wall_mesh_pt()->output(some_file,npts);
 
  714  trace_file << time_pt()->time() << 
" " 
  715             << Wall_node_pt->x(1) << 
" " 
  716             << Left_node_pt->value(0) << 
" " 
  717             << Right_node_pt->value(0) << 
" " 
  729 template <
class ELEMENT>
 
  731  const unsigned &b, Mesh* 
const &bulk_mesh_pt, Mesh* 
const &traction_mesh_pt)
 
  735  unsigned n_element = bulk_mesh_pt->nboundary_element(b);
 
  738  for(
unsigned e=0;e<n_element;e++)
 
  741    ELEMENT* bulk_elem_pt = 
dynamic_cast<ELEMENT*
> 
  742     (bulk_mesh_pt->boundary_element_pt(b,e));
 
  745    int face_index = bulk_mesh_pt->face_index_at_boundary(b,e);
 
  748    NavierStokesTractionElement<ELEMENT>* flux_element_pt = 
 
  749     new  NavierStokesTractionElement<ELEMENT>(bulk_elem_pt,face_index);
 
  752    traction_mesh_pt->add_element_pt(flux_element_pt);
 
  764 template <
class ELEMENT>
 
  768  if (time_stepper_pt()->type()!=
"BDF")
 
  770    std::ostringstream error_stream;
 
  771    error_stream << 
"Timestepper has to be from the BDF family!\n" 
  772                 << 
"You have specified a timestepper from the " 
  773                 << time_stepper_pt()->type() << 
" family" << std::endl;
 
  775    throw OomphLibError(error_stream.str(),
 
  776                        OOMPH_CURRENT_FUNCTION,
 
  777                        OOMPH_EXCEPTION_LOCATION);
 
  781  bulk_mesh_pt()->node_update();
 
  784  unsigned num_nod = bulk_mesh_pt()->nnode();
 
  785  for (
unsigned n=0;n<num_nod;n++)
 
  789    x[0]=bulk_mesh_pt()->node_pt(n)->x(0);
 
  790    x[1]=bulk_mesh_pt()->node_pt(n)->x(1);
 
  793    bulk_mesh_pt()->node_pt(n)->set_value(0,6.0*(x[1]/Ly)*(1.0-(x[1]/Ly)));
 
  794    bulk_mesh_pt()->node_pt(n)->set_value(1,0.0);
 
  798  bulk_mesh_pt()->assign_initial_values_impulsive();
 
  811 int main(
int argc, 
char* argv[])
 
  815  CommandLineArgs::setup(argc,argv);
 
  818  unsigned coarsening_factor=1;
 
  819  if (CommandLineArgs::Argc>1)
 
  825  unsigned nup=20/coarsening_factor;
 
  826  unsigned ncollapsible=40/coarsening_factor;
 
  827  unsigned ndown=40/coarsening_factor;
 
  828  unsigned ny=16/coarsening_factor;
 
  832  double lcollapsible=10.0;
 
  843 #ifdef MACRO_ELEMENT_NODE_UPDATE 
  849   <MacroElementNodeUpdateElement<QTaylorHoodElement<2> > > 
 
  850   problem(nup, ncollapsible, ndown, ny, 
 
  851           lup, lcollapsible, ldown, ly);
 
  857   <MacroElementNodeUpdateElement<QCrouzeixRaviartElement<2> > > 
 
  858   problem(nup, ncollapsible, ndown, ny, 
 
  859           lup, lcollapsible, ldown, ly);
 
  869   <AlgebraicElement<QTaylorHoodElement<2> > > 
 
  870   problem(nup, ncollapsible, ndown, ny, 
 
  871           lup, lcollapsible, ldown, ly);
 
  877   <AlgebraicElement<QCrouzeixRaviartElement<2> > > 
 
  878   problem(nup, ncollapsible, ndown, ny, 
 
  879           lup, lcollapsible, ldown, ly);
 
  895  problem.time_pt()->time()=t_min;
 
  896  problem.initialise_dt(dt);
 
  899  problem.set_initial_condition();
 
  903  doc_info.set_directory(
"RESLT");
 
  908  sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
 
  909  trace_file.open(filename);
 
  912  problem.doc_solution(doc_info, trace_file);
 
  918  unsigned nstep = unsigned((t_max-t_min)/dt);
 
  919  if (CommandLineArgs::Argc>1)
 
  925  for (
unsigned istep=0;istep<nstep;istep++)
 
  928    problem.unsteady_newton_solve(dt);
 
  931    problem.doc_solution(doc_info, trace_file);
 
Mesh * Applied_fluid_traction_mesh_pt
Pointer to the "surface" mesh that applies the traction at the inflow.
 
double Ldown
x-length in the downstream part of the channel
 
Node * Left_node_pt
Pointer to the left control node.
 
Node * Right_node_pt
Pointer to right control node.
 
unsigned Nup
Number of elements in the x direction in the upstream part of the channel.
 
OneDLagrangianMesh< FSIHermiteBeamElement > * Wall_mesh_pt
Pointer to the "wall" mesh.
 
unsigned Ncollapsible
Number of elements in the x direction in the collapsible part of the channel.
 
void actions_after_newton_solve()
Update the problem after solve (empty)
 
unsigned Ny
Number of elements across the channel.
 
MacroElementNodeUpdateCollapsibleChannelMesh< ELEMENT > * bulk_mesh_pt()
Access function for the specific bulk (fluid) mesh.
 
unsigned Ndown
Number of elements in the x direction in the downstream part of the channel.
 
AlgebraicCollapsibleChannelMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
 
double Lup
x-length in the upstream part of the channel
 
AlgebraicCollapsibleChannelMesh< ELEMENT > * bulk_mesh_pt()
Access function for the specific bulk (fluid) mesh.
 
MacroElementNodeUpdateCollapsibleChannelMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
 
~FSICollapsibleChannelProblem()
Destructor (empty)
 
void actions_before_newton_convergence_check()
Update before checking Newton convergence: Update the nodal positions in the fluid mesh in response t...
 
void actions_before_newton_solve()
Update the problem specs before solve (empty)
 
Node * Wall_node_pt
Pointer to control node on the wall.
 
double Ly
Transverse length.
 
double Lcollapsible
x-length in the collapsible part of the channel
 
OneDLagrangianMesh< FSIHermiteBeamElement > * wall_mesh_pt()
Access function for the wall mesh.
 
void create_traction_elements(const unsigned &b, Mesh *const &bulk_mesh_pt, Mesh *const &traction_mesh_pt)
Create the prescribed traction elements on boundary b.
 
void set_initial_condition()
Apply initial conditions.
 
FSICollapsibleChannelProblem(const unsigned &nup, const unsigned &ncollapsible, const unsigned &ndown, const unsigned &ny, const double &lup, const double &lcollapsible, const double &ldown, const double &ly)
Constructor: The arguments are the number of elements and the lengths of the domain.
 
void doc_solution(DocInfo &doc_info, ofstream &trace_file)
Doc the solution.
 
////////////////////////////////////////////////////////////////// //////////////////////////////////...
 
////////////////////////////////////////////////////////////////// //////////////////////////////////...
 
int main(int argc, char *argv[])
Driver code for a collapsible channel problem with FSI. Presence of command line arguments indicates ...
 
Namespace to define the mapping [0,1] -> [0,1] that re-distributes nodal points across the channel wi...
 
double squash_fct(const double &s)
Mapping [0,1] -> [0,1] that re-distributes nodal points across the channel width.
 
double Delta
Boundary layer width.
 
double Fract_in_BL
Fraction of points in boundary layer.
 
Namespace for phyical parameters.
 
double P_ext
External pressure.
 
double ReSt
Womersley = Reynolds times Strouhal.
 
void prescribed_traction(const double &t, const Vector< double > &x, const Vector< double > &n, Vector< double > &traction)
Traction applied on the fluid at the left (inflow) boundary.
 
void load(const Vector< double > &xi, const Vector< double > &x, const Vector< double > &N, Vector< double > &load)
Load function: Apply a constant external pressure to the wall. Note: This is the load without the flu...
 
double Sigma0
2nd Piola Kirchhoff pre-stress. As in Jensen & Heil (2003) paper.
 
double Q
Fluid structure interaction parameter: Ratio of stresses used for non-dimensionalisation of fluid to ...
 
double Re
Reynolds number.
 
double P_up
Default pressure on the left boundary.
 
double H
Non-dimensional wall thickness. As in Jensen & Heil (2003) paper.
 
////////////////////////////////////////////////////////////////////// //////////////////////////////...