34 #include "navier_stokes.h" 38 #include "meshes/one_d_lagrangian_mesh.h" 41 #include "meshes/collapsible_channel_mesh.h" 45 using namespace oomph;
67 if (s<0.5*Fract_in_BL)
71 else if (s>1.0-0.5*Fract_in_BL)
73 y=2.0*Delta/Fract_in_BL*s+1.0-2.0*Delta/
Fract_in_BL;
77 y=(1.0-2.0*
Delta)/(1.0-Fract_in_BL)*s+
115 void position(
const Vector<double>& zeta, Vector<double>& r)
const 126 void position(
const unsigned& t,
const Vector<double>& zeta,
127 Vector<double>& r)
const 142 DenseMatrix<double> &drdzeta,
143 RankThreeTensor<double> &ddrdzeta)
const 191 const Vector<double>& x,
192 const Vector<double>& n,
193 Vector<double>& traction)
213 void load(
const Vector<double>& xi,
const Vector<double>& x,
214 const Vector<double>& N, Vector<double>&
load)
216 for(
unsigned i=0;i<2;i++)
218 load[i] = -P_ext*N[i];
236 template <
class ELEMENT>
245 const unsigned& ncollapsible,
246 const unsigned& ndown,
249 const double& lcollapsible,
257 #ifdef MACRO_ELEMENT_NODE_UPDATE 303 Bulk_mesh_pt->node_update();
307 void doc_solution(DocInfo& doc_info,ofstream& trace_file);
310 void set_initial_condition();
315 void create_traction_elements(
const unsigned &b,
316 Mesh*
const &bulk_mesh_pt,
317 Mesh*
const &traction_mesh_pt);
344 #ifdef MACRO_ELEMENT_NODE_UPDATE 381 template <
class ELEMENT>
384 const unsigned& ncollapsible,
385 const unsigned& ndown,
388 const double& lcollapsible,
394 Ncollapsible=ncollapsible;
398 Lcollapsible=lcollapsible;
404 Problem::Max_residuals=1000.0;
409 add_time_stepper_pt(
new BDF<2>);
418 (Ncollapsible,Lcollapsible,undeformed_wall_pt);
424 MeshAsGeomObject* wall_geom_object_pt=
425 new MeshAsGeomObject(Wall_mesh_pt);
428 #ifdef MACRO_ELEMENT_NODE_UPDATE 433 (nup, ncollapsible, ndown, ny,
434 lup, lcollapsible, ldown, ly,
442 Bulk_mesh_pt->node_update();
449 (nup, ncollapsible, ndown, ny,
450 lup, lcollapsible, ldown, ly,
461 Applied_fluid_traction_mesh_pt =
new Mesh;
465 create_traction_elements(5,Bulk_mesh_pt,Applied_fluid_traction_mesh_pt);
468 add_sub_mesh(Bulk_mesh_pt);
469 add_sub_mesh(Applied_fluid_traction_mesh_pt);
470 add_sub_mesh(Wall_mesh_pt);
481 unsigned n_element=Bulk_mesh_pt->nelement();
482 for(
unsigned e=0;e<n_element;e++)
485 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
503 unsigned num_nod= bulk_mesh_pt()->nboundary_node(ibound);
504 for (
unsigned inod=0;inod<num_nod;inod++)
506 for(
unsigned i=0;i<2;i++)
508 bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(i);
513 for(ibound=2;ibound<5;ibound++)
515 num_nod= bulk_mesh_pt()->nboundary_node(ibound);
516 for (
unsigned inod=0;inod<num_nod;inod++)
518 for(
unsigned i=0;i<2;i++)
520 bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(i);
527 num_nod= bulk_mesh_pt()->nboundary_node(ibound);
528 for (
unsigned inod=0;inod<num_nod;inod++)
530 bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(1);
536 num_nod= bulk_mesh_pt()->nboundary_node(ibound);
537 for (
unsigned inod=0;inod<num_nod;inod++)
539 bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(1);
548 unsigned n_el=Applied_fluid_traction_mesh_pt->nelement();
549 for(
unsigned e=0;e<n_el;e++)
552 NavierStokesTractionElement<ELEMENT> *el_pt =
553 dynamic_cast< NavierStokesTractionElement<ELEMENT>*
>(
554 Applied_fluid_traction_mesh_pt->element_pt(e));
567 n_element = wall_mesh_pt()->nelement();
568 for(
unsigned e=0;e<n_element;e++)
571 FSIHermiteBeamElement *elem_pt =
572 dynamic_cast<FSIHermiteBeamElement*
>(wall_mesh_pt()->element_pt(e));
585 elem_pt->undeformed_beam_pt() = undeformed_wall_pt;
591 elem_pt->set_normal_pointing_out_of_fluid();
602 for(
unsigned b=0;b<2;b++)
605 wall_mesh_pt()->boundary_node_pt(b,0)->pin_position(0);
606 wall_mesh_pt()->boundary_node_pt(b,0)->pin_position(1);
617 num_nod= bulk_mesh_pt()->nboundary_node(ibound);
618 unsigned control_nod=num_nod/2;
619 Left_node_pt= bulk_mesh_pt()->boundary_node_pt(ibound, control_nod);
623 num_nod= bulk_mesh_pt()->nboundary_node(ibound);
624 control_nod=num_nod/2;
625 Right_node_pt= bulk_mesh_pt()->boundary_node_pt(ibound, control_nod);
629 Wall_node_pt=wall_mesh_pt()->node_pt(Ncollapsible/2);
643 num_nod= bulk_mesh_pt()->nboundary_node(ibound);
644 for (
unsigned inod=0;inod<num_nod;inod++)
646 bulk_mesh_pt()->boundary_node_pt(ibound, inod)->
647 set_auxiliary_node_update_fct_pt(
648 FSI_functions::apply_no_slip_on_moving_wall);
656 FSI_functions::setup_fluid_load_info_for_solid_elements<ELEMENT,2>
657 (
this,3,Bulk_mesh_pt,Wall_mesh_pt);
660 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
671 template <
class ELEMENT>
673 ofstream& trace_file)
677 #ifdef MACRO_ELEMENT_NODE_UPDATE 680 if (CommandLineArgs::Argc>1)
682 FSI_functions::doc_fsi<MacroElementNodeUpdateNode>(Bulk_mesh_pt,Wall_mesh_pt,doc_info);
688 if (CommandLineArgs::Argc>1)
690 FSI_functions::doc_fsi<AlgebraicNode>(Bulk_mesh_pt,Wall_mesh_pt,doc_info);
703 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
705 some_file.open(filename);
706 bulk_mesh_pt()->output(some_file,npts);
710 sprintf(filename,
"%s/beam%i.dat",doc_info.directory().c_str(),
712 some_file.open(filename);
713 wall_mesh_pt()->output(some_file,npts);
718 trace_file << time_pt()->time() <<
" " 719 << Wall_node_pt->x(1) <<
" " 720 << Left_node_pt->value(0) <<
" " 721 << Right_node_pt->value(0) <<
" " 733 template <
class ELEMENT>
735 const unsigned &b, Mesh*
const &bulk_mesh_pt, Mesh*
const &traction_mesh_pt)
739 unsigned n_element = bulk_mesh_pt->nboundary_element(b);
742 for(
unsigned e=0;e<n_element;e++)
745 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
> 746 (bulk_mesh_pt->boundary_element_pt(b,e));
749 int face_index = bulk_mesh_pt->face_index_at_boundary(b,e);
752 NavierStokesTractionElement<ELEMENT>* flux_element_pt =
753 new NavierStokesTractionElement<ELEMENT>(bulk_elem_pt,face_index);
756 traction_mesh_pt->add_element_pt(flux_element_pt);
768 template <
class ELEMENT>
772 if (time_stepper_pt()->type()!=
"BDF")
774 std::ostringstream error_stream;
775 error_stream <<
"Timestepper has to be from the BDF family!\n" 776 <<
"You have specified a timestepper from the " 777 << time_stepper_pt()->type() <<
" family" << std::endl;
779 throw OomphLibError(error_stream.str(),
780 OOMPH_CURRENT_FUNCTION,
781 OOMPH_EXCEPTION_LOCATION);
785 bulk_mesh_pt()->node_update();
788 unsigned num_nod = bulk_mesh_pt()->nnode();
789 for (
unsigned n=0;n<num_nod;n++)
793 x[0]=bulk_mesh_pt()->node_pt(n)->x(0);
794 x[1]=bulk_mesh_pt()->node_pt(n)->x(1);
797 bulk_mesh_pt()->node_pt(n)->set_value(0,6.0*(x[1]/Ly)*(1.0-(x[1]/Ly)));
798 bulk_mesh_pt()->node_pt(n)->set_value(1,0.0);
802 bulk_mesh_pt()->assign_initial_values_impulsive();
815 int main(
int argc,
char* argv[])
819 CommandLineArgs::setup(argc,argv);
822 unsigned coarsening_factor=1;
823 if (CommandLineArgs::Argc>1)
829 unsigned nup=20/coarsening_factor;
830 unsigned ncollapsible=40/coarsening_factor;
831 unsigned ndown=40/coarsening_factor;
832 unsigned ny=16/coarsening_factor;
836 double lcollapsible=10.0;
847 #ifdef MACRO_ELEMENT_NODE_UPDATE 853 <MacroElementNodeUpdateElement<QTaylorHoodElement<2> > >
854 problem(nup, ncollapsible, ndown, ny,
855 lup, lcollapsible, ldown, ly);
861 <MacroElementNodeUpdateElement<QCrouzeixRaviartElement<2> > >
862 problem(nup, ncollapsible, ndown, ny,
863 lup, lcollapsible, ldown, ly);
873 <AlgebraicElement<QTaylorHoodElement<2> > >
874 problem(nup, ncollapsible, ndown, ny,
875 lup, lcollapsible, ldown, ly);
881 <AlgebraicElement<QCrouzeixRaviartElement<2> > >
882 problem(nup, ncollapsible, ndown, ny,
883 lup, lcollapsible, ldown, ly);
899 problem.time_pt()->time()=t_min;
900 problem.initialise_dt(dt);
903 problem.set_initial_condition();
907 doc_info.set_directory(
"RESLT");
912 sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
913 trace_file.open(filename);
916 problem.doc_solution(doc_info, trace_file);
922 unsigned nstep = unsigned((t_max-t_min)/dt);
923 if (CommandLineArgs::Argc>1)
929 for (
unsigned istep=0;istep<nstep;istep++)
932 problem.unsteady_newton_solve(dt);
935 problem.doc_solution(doc_info, trace_file);
void actions_before_newton_convergence_check()
Update before checking Newton convergence: Update the nodal positions in the fluid mesh in response t...
OneDLagrangianMesh< FSIHermiteBeamElement > * wall_mesh_pt()
Access function for the wall mesh.
void actions_before_newton_solve()
Update the problem specs before solve (empty)
~FSICollapsibleChannelProblem()
Destructor (empty)
MacroElementNodeUpdateCollapsibleChannelMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
AlgebraicCollapsibleChannelMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
double Ly
Transverse length.
void set_initial_condition()
Apply initial conditions.
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...
Node * Wall_node_pt
Pointer to control node on the wall.
AlgebraicCollapsibleChannelMesh< ELEMENT > * bulk_mesh_pt()
Access function for the specific bulk (fluid) mesh.
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 ...
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.
double P_up
Default pressure on the left boundary.
double Lcollapsible
x-length in the collapsible part of the channel
double ReSt
Womersley = Reynolds times Strouhal.
MacroElementNodeUpdateCollapsibleChannelMesh< ELEMENT > * bulk_mesh_pt()
Access function for the specific bulk (fluid) mesh.
void doc_solution(DocInfo &doc_info, ofstream &trace_file)
Doc the solution.
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.
unsigned Ncollapsible
Number of elements in the x direction in the collapsible part of the channel.
double Delta
Boundary layer width.
double Re
Reynolds number.
void actions_after_newton_solve()
Update the problem after solve (empty)
Mesh * Applied_fluid_traction_mesh_pt
Pointer to the "surface" mesh that applies the traction at the inflow.
Node * Left_node_pt
Pointer to the left control node.
double Fract_in_BL
Fraction of points in boundary layer.
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 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.
Collapsible channel mesh with algebraic node update.
int main(int argc, char *argv[])
Namespace for phyical parameters.
double H
Non-dimensional wall thickness. As in Jensen & Heil (2003) paper.
double Ldown
x-length in the downstream part of the channel
double Lup
x-length in the upstream part of the channel
virtual CollapsibleChannelDomain::BLSquashFctPt & bl_squash_fct_pt()
Function pointer for function that squashes the mesh near the walls. Default trivial mapping (the ide...
double squash_fct(const double &s)
Mapping [0,1] -> [0,1] that re-distributes nodal points across the channel width. ...
double P_ext
External pressure.
unsigned Ndown
Number of elements in the x direction in the downstream part of the channel.
unsigned Ny
Number of elements across the channel.
OneDLagrangianMesh< FSIHermiteBeamElement > * Wall_mesh_pt
Pointer to the "wall" mesh.