34 #include "navier_stokes.h" 35 #include "multi_physics.h" 36 #include "constitutive.h" 40 #include "meshes/channel_with_leaflet_mesh.h" 41 #include "meshes/one_d_lagrangian_mesh.h" 44 using namespace oomph;
58 template <
class ELEMENT>
60 public virtual ELEMENT
71 return 2*ELEMENT::dim();
88 std::list<std::pair<unsigned long,unsigned> >& dof_lookup_list)
const 91 std::pair<unsigned,unsigned> dof_lookup;
94 const unsigned n_node = this->nnode();
97 const unsigned n_position_type = ELEMENT::nnodal_position_type();
98 const unsigned nodal_dim = ELEMENT::nodal_dimension();
104 for(
unsigned n=0;n<n_node;n++)
107 if (this->node_pt(n)->nvalue() != this->required_nvalue(n))
109 offset = ELEMENT::dim();
113 for(
unsigned k=0;k<n_position_type;k++)
116 for(
unsigned i=0;i<nodal_dim;i++)
119 local_unknown = ELEMENT::position_local_eqn(n,k,i);
122 if (local_unknown >= 0)
126 dof_lookup.first = this->eqn_number(local_unknown);
127 dof_lookup.second = offset+i;
130 dof_lookup_list.push_front(dof_lookup);
143 template<
class ELEMENT>
145 public virtual FaceGeometry<ELEMENT>
159 #ifdef OOMPH_HAS_HYPRE 171 HyprePreconditioner* hypre_preconditioner_pt
172 =
new HyprePreconditioner;
173 hypre_preconditioner_pt->set_amg_iterations(2);
174 hypre_preconditioner_pt->amg_using_simple_smoothing();
175 hypre_preconditioner_pt->amg_simple_smoother() = 0;
176 hypre_preconditioner_pt->hypre_method() = HyprePreconditioner::BoomerAMG;
177 hypre_preconditioner_pt->amg_strength() = 0.25;
178 hypre_preconditioner_pt->amg_coarsening() = 3;
179 hypre_preconditioner_pt->amg_damping() = 2.0/3.0;
180 return hypre_preconditioner_pt;
250 return U_base+U_perturbation*cos(2.0*MathematicalConstants::Pi*t/T);
288 void position(
const Vector<double>& zeta, Vector<double>& r)
const 299 void position(
const unsigned& t,
const Vector<double>& zeta,
300 Vector<double>& r)
const 314 DenseMatrix<double> &drdzeta,
315 RankThreeTensor<double> &ddrdzeta)
const 350 template<
class ELEMENT>
363 delete Lagrange_multiplier_mesh_pt;
365 delete Bulk_time_stepper_pt;
366 delete Wall_time_stepper_pt;
367 delete Wall_geom_object_pt;
368 delete Undeformed_wall_pt;
369 delete Constitutive_law_pt;
380 Bulk_mesh_pt->set_lagrangian_nodal_coordinates();
387 unsigned nnod=Bulk_mesh_pt->nnode();
388 for (
unsigned j=0;j<nnod;j++)
390 Bulk_mesh_pt->node_pt(j)->perform_auxiliary_node_update_fct();
399 double t=time_pt()->time();
406 unsigned num_nod= Bulk_mesh_pt->nboundary_node(ibound);
407 for (
unsigned inod=0;inod<num_nod;inod++)
409 double ycoord = Bulk_mesh_pt->boundary_node_pt(ibound,inod)->x(1);
412 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,uy);
413 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
418 void set_iterative_solver();
421 void doc_solution(DocInfo& doc_info);
425 void create_lagrange_multiplier_elements();
429 void delete_lagrange_multiplier_elements();
434 oomph_info <<
"\n\n=================================================\n";
443 oomph_info <<
"t : " << time_pt()->time()
445 oomph_info <<
"tip x : " 446 << tip_node_pt()->x(0) << std::endl;
447 oomph_info <<
"tip y : " 448 << tip_node_pt()->x(1) << std::endl;
449 oomph_info <<
"=================================================\n\n";
457 unsigned n_el_wall=Wall_mesh_pt->nelement();
458 return Wall_mesh_pt->finite_element_pt(n_el_wall-1)->node_pt(1);
492 template <
class ELEMENT>
494 (
const unsigned& mesh_multiplier)
498 Bulk_time_stepper_pt=
new BDF<2>;
499 add_time_stepper_pt(Bulk_time_stepper_pt);
500 Wall_time_stepper_pt=
new Newmark<2>;
501 add_time_stepper_pt(Wall_time_stepper_pt);
511 Wall_mesh_pt =
new OneDLagrangianMesh<FSIHermiteBeamElement>
513 Undeformed_wall_pt,Wall_time_stepper_pt);
520 Wall_geom_object_pt=
new MeshAsGeomObject(Wall_mesh_pt);
523 Bulk_mesh_pt =
new PseudoElasticChannelWithLeafletMesh<ELEMENT>(
533 Bulk_time_stepper_pt);
540 Lagrange_multiplier_mesh_pt=
new SolidMesh;
541 create_lagrange_multiplier_elements();
546 add_sub_mesh(Bulk_mesh_pt);
547 add_sub_mesh(Lagrange_multiplier_mesh_pt);
548 add_sub_mesh(Wall_mesh_pt);
557 unsigned num_bound = Bulk_mesh_pt->nboundary();
558 for(
unsigned ibound=0;ibound<num_bound;ibound++)
560 unsigned num_nod= Bulk_mesh_pt->nboundary_node(ibound);
561 for (
unsigned inod=0;inod<num_nod;inod++)
563 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
568 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->pin(0);
575 for (
unsigned ibound=0;ibound<7;ibound++)
577 if (ibound==0||ibound==1||ibound==2||ibound==3||ibound==6)
579 unsigned num_nod=Bulk_mesh_pt->nboundary_node(ibound);
580 for (
unsigned inod=0;inod<num_nod;inod++)
582 for(
unsigned i=0;i<2;i++)
584 if (!( (ibound==2)&&(i==0) ))
586 dynamic_cast<SolidNode*
>(Bulk_mesh_pt->
587 boundary_node_pt(ibound, inod))
599 unsigned num_nod= Bulk_mesh_pt->nboundary_node(ibound);
600 for (
unsigned inod=0;inod<num_nod;inod++)
602 double ycoord = Bulk_mesh_pt->boundary_node_pt(ibound,inod)->x(1);
603 double uy = 4.0*ycoord/Global_Parameters::Fluid_height*
605 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,uy);
606 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
616 Wall_mesh_pt->boundary_node_pt(b,0)->pin_position(0);
617 Wall_mesh_pt->boundary_node_pt(b,0)->pin_position(1);
620 Wall_mesh_pt->boundary_node_pt(b,0)->pin_position(1,0);
631 unsigned n_element = Bulk_mesh_pt->nelement();
632 for(
unsigned e=0;e<n_element;e++)
635 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
644 el_pt->constitutive_law_pt() = Constitutive_law_pt;
655 n_element = Wall_mesh_pt->nelement();
656 for(
unsigned e=0;e<n_element;e++)
659 FSIHermiteBeamElement *elem_pt =
660 dynamic_cast<FSIHermiteBeamElement*
>(Wall_mesh_pt->element_pt(e));
669 elem_pt->undeformed_beam_pt() = Undeformed_wall_pt;
675 elem_pt->enable_fluid_loading_on_both_sides();
681 elem_pt->set_normal_pointing_out_of_fluid();
693 for(
unsigned ibound=4;ibound<6;ibound++ )
695 unsigned num_nod= Bulk_mesh_pt->nboundary_node(ibound);
696 for (
unsigned inod=0;inod<num_nod;inod++)
698 Bulk_mesh_pt->boundary_node_pt(ibound, inod)->
699 set_auxiliary_node_update_fct_pt(
700 FSI_functions::apply_no_slip_on_moving_wall);
714 FSI_functions::setup_fluid_load_info_for_solid_elements<ELEMENT,2>
723 FSI_functions::setup_fluid_load_info_for_solid_elements<ELEMENT,2>
724 (
this,5,Bulk_mesh_pt,Wall_mesh_pt,face);
728 oomph_info <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
736 template<
class ELEMENT>
740 IterativeLinearSolver* solver_pt=0;
743 #ifdef OOMPH_HAS_TRILINOS 746 solver_pt =
new TrilinosAztecOOSolver;
749 dynamic_cast<TrilinosAztecOOSolver*
>(solver_pt)->solver_type()
750 = TrilinosAztecOOSolver::GMRES;
755 solver_pt =
new GMRES<CRDoubleMatrix>;
760 linear_solver_pt() = solver_pt;
764 PseudoElasticFSIPreconditioner* prec_pt=
765 new PseudoElasticFSIPreconditioner(dim,
this);
768 solver_pt->preconditioner_pt() = prec_pt;
773 prec_pt->set_fluid_and_pseudo_elastic_mesh_pt(Bulk_mesh_pt);
774 prec_pt->set_solid_mesh_pt(Wall_mesh_pt);
775 prec_pt->set_lagrange_multiplier_mesh_pt(Lagrange_multiplier_mesh_pt);
780 if (!CommandLineArgs::command_line_flag_has_been_set(
"--suppress_lsc"))
782 oomph_info <<
"Enabling LSC preconditioner\n";
783 prec_pt->enable_navier_stokes_schur_complement_preconditioner();
787 prec_pt->disable_navier_stokes_schur_complement_preconditioner();
788 oomph_info <<
"Not using LSC preconditioner\n";
794 if (CommandLineArgs::command_line_flag_has_been_set(
"--superlu_for_blocks"))
796 oomph_info <<
"Use SuperLU for block solves\n";
800 oomph_info <<
"Use optimal block solves\n";
803 NavierStokesSchurComplementPreconditioner* ns_prec_pt =
804 prec_pt->navier_stokes_schur_complement_preconditioner_pt();
810 BlockTriangularPreconditioner<CRDoubleMatrix>*
811 f_prec_pt =
new BlockTriangularPreconditioner<CRDoubleMatrix>;
814 ns_prec_pt->set_f_preconditioner(f_prec_pt);
816 #ifdef OOMPH_HAS_HYPRE 819 f_prec_pt->set_subsidiary_preconditioner_function
827 HyprePreconditioner* p_prec_pt =
new HyprePreconditioner;
828 p_prec_pt->disable_doc_time();
829 Hypre_default_settings::set_defaults_for_2D_poisson_problem(p_prec_pt);
830 ns_prec_pt->set_p_preconditioner(p_prec_pt);
838 prec_pt->pseudo_elastic_preconditioner_pt()->elastic_preconditioner_type()
839 = PseudoElasticPreconditioner::Block_upper_triangular_preconditioner;
841 #ifdef OOMPH_HAS_HYPRE 844 prec_pt->pseudo_elastic_preconditioner_pt()->
845 set_elastic_subsidiary_preconditioner(
846 Pseudo_Elastic_Preconditioner_Subsidiary_Operator_Helper::
847 get_elastic_preconditioner_hypre);
851 #ifdef OOMPH_HAS_TRILINOS 855 prec_pt->pseudo_elastic_preconditioner_pt()->
856 set_lagrange_multiplier_subsidiary_preconditioner
857 (Pseudo_Elastic_Preconditioner_Subsidiary_Operator_Helper::
858 get_lagrange_multiplier_preconditioner);
870 template<
class ELEMENT>
875 for (
unsigned b=4;b<=5;b++)
878 unsigned n_bulk_element = Bulk_mesh_pt->nboundary_element(b);
881 for(
unsigned e=0;e<n_bulk_element;e++)
884 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
885 Bulk_mesh_pt->boundary_element_pt(b,e));
888 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
891 ImposeDisplacementByLagrangeMultiplierElement<ELEMENT> *el_pt =
892 new ImposeDisplacementByLagrangeMultiplierElement<ELEMENT>(
893 bulk_elem_pt,face_index);
896 Lagrange_multiplier_mesh_pt->add_element_pt(el_pt);
901 el_pt->set_boundary_shape_geom_object_pt(Wall_geom_object_pt,b);
907 unsigned n_element=Lagrange_multiplier_mesh_pt->nelement();
908 for(
unsigned i=0;i<n_element;i++)
911 ImposeDisplacementByLagrangeMultiplierElement<ELEMENT> *el_pt =
912 dynamic_cast<ImposeDisplacementByLagrangeMultiplierElement<ELEMENT>*
> 913 (Lagrange_multiplier_mesh_pt->element_pt(i));
916 unsigned nnod=el_pt->nnode();
917 for (
unsigned j=0;j<nnod;j++)
919 Node* nod_pt = el_pt->node_pt(j);
922 if ((nod_pt->is_on_boundary(0))||(nod_pt->is_on_boundary(6)))
926 unsigned n_bulk_value=el_pt->nbulk_value(j);
929 unsigned nval=nod_pt->nvalue();
930 for (
unsigned k=n_bulk_value;k<nval;k++)
945 template<
class ELEMENT>
950 unsigned n_element = Lagrange_multiplier_mesh_pt->nelement();
953 for(
unsigned e=0;e<n_element;e++)
956 delete Lagrange_multiplier_mesh_pt->element_pt(e);
960 Lagrange_multiplier_mesh_pt->flush_element_and_node_storage();
969 template<
class ELEMENT>
980 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
982 some_file.open(filename);
983 Bulk_mesh_pt->output(some_file,npts);
987 sprintf(filename,
"%s/wall_soln%i.dat",doc_info.directory().c_str(),
989 some_file.open(filename);
990 Wall_mesh_pt->output(some_file,npts);
999 sprintf(filename,
"%s/bulk_boundary_elements_front_%i.dat",
1000 doc_info.directory().c_str(),
1002 some_file.open(filename);
1003 unsigned nel= Bulk_mesh_pt->nboundary_element(bound);
1004 for (
unsigned e=0;e<nel;e++)
1006 dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->boundary_element_pt(bound,e))
1007 ->output(some_file,npts);
1015 sprintf(filename,
"%s/bulk_boundary_elements_back_%i.dat",
1016 doc_info.directory().c_str(),
1018 some_file.open(filename);
1019 nel= Bulk_mesh_pt->nboundary_element(bound);
1020 for (
unsigned e=0;e<nel;e++)
1022 dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->boundary_element_pt(bound,e))
1023 ->output(some_file,npts);
1029 sprintf(filename,
"%s/wall_normal_%i.dat",
1030 doc_info.directory().c_str(),
1032 some_file.open(filename);
1033 nel=Wall_mesh_pt->nelement();
1034 Vector<double> s(1);
1035 Vector<double> x(2);
1036 Vector<double> xi(1);
1037 Vector<double> N(2);
1038 for (
unsigned e=0;e<nel;e++)
1041 FSIHermiteBeamElement* el_pt=
1042 dynamic_cast<FSIHermiteBeamElement*
>(Wall_mesh_pt->element_pt(e));
1045 for (
unsigned i=0;i<npts;i++)
1047 s[0]=-1.0+2.0*double(i)/double(npts-1);
1050 el_pt->interpolated_x(s,x);
1053 el_pt->get_normal(s,N);
1056 el_pt->interpolated_xi(s,xi);
1058 some_file << x[0] <<
" " << x[1] <<
" " 1059 << N[0] <<
" " << N[1] <<
" " 1060 << xi[0] << std::endl;
1074 #ifdef OOMPH_HAS_MPI 1075 MPI_Helpers::init(argc,argv);
1079 oomph_info.output_modifier_pt() = &default_output_modifier;
1082 CommandLineArgs::setup(argc,argv);
1086 unsigned mesh_multiplier = 2;
1087 CommandLineArgs::specify_command_line_flag(
"--mesh_multiplier",
1091 CommandLineArgs::specify_command_line_flag(
"--suppress_lsc");
1094 CommandLineArgs::specify_command_line_flag(
"--use_direct_solver");
1097 CommandLineArgs::specify_command_line_flag(
"--superlu_for_blocks");
1100 CommandLineArgs::specify_command_line_flag(
"--validate");
1103 CommandLineArgs::parse_and_assign();
1106 CommandLineArgs::doc_specified_flags();
1110 <QTaylorHoodElement<2>,
1114 <QTaylorHoodElement<2>,
1123 doc_info.set_directory(
"RESLT");
1127 std::ofstream output_stream;
1128 char filename[1000];
1129 #ifdef OOMPH_HAS_MPI 1130 sprintf(filename,
"%s/OUTPUT_STEADY.%i",doc_info.directory().c_str(),
1131 MPI_Helpers::communicator_pt()->my_rank());
1133 sprintf(filename,
"%s/OUTPUT_STEADY.%i",doc_info.directory().c_str(),0);
1136 output_stream.open(filename);
1137 oomph_info.stream_pt() = &output_stream;
1138 OomphLibWarning::set_stream_pt(&output_stream);
1139 OomphLibError::set_stream_pt(&output_stream);
1143 problem_pt->doc_solution(doc_info);
1144 doc_info.number()++;
1147 if (!CommandLineArgs::command_line_flag_has_been_set(
"--use_direct_solver"))
1149 problem_pt->set_iterative_solver();
1162 problem_pt->steady_newton_solve();
1163 problem_pt->doc_parameters();
1166 problem_pt->doc_solution(doc_info);
1167 doc_info.number()++;
1173 problem_pt->steady_newton_solve();
1174 problem_pt->doc_parameters();
1175 problem_pt->doc_solution(doc_info);
1176 doc_info.number()++;
1182 output_stream.close();
1183 #ifdef OOMPH_HAS_MPI 1184 sprintf(filename,
"%s/OUTPUT_UNSTEADY.%i",doc_info.directory().c_str(),
1185 MPI_Helpers::communicator_pt()->my_rank());
1187 sprintf(filename,
"%s/OUTPUT_UNSTEADY.%i",doc_info.directory().c_str(),0);
1189 output_stream.open(filename);
1190 oomph_info.stream_pt() = &output_stream;
1191 OomphLibWarning::set_stream_pt(&output_stream);
1192 OomphLibError::set_stream_pt(&output_stream);
1196 unsigned n_period=1;
1198 unsigned nstep=unsigned(
double(n_period)
1201 if (CommandLineArgs::command_line_flag_has_been_set(
"--validate"))
1205 for (
unsigned r = 0; r < nstep; r++)
1208 problem_pt->doc_parameters();
1209 problem_pt->doc_solution(doc_info);
1210 doc_info.number()++;
1217 oomph_info <<
"Done\n";
1219 #ifdef OOMPH_HAS_MPI 1220 MPI_Helpers::finalize();
Newmark< 2 > * Wall_time_stepper_pt
Wall time stepper pt.
void set_iterative_solver()
Set iterative solver.
double Q
Fluid structure interaction parameter: Ratio of stresses used for non-dimensionalisation of fluid to ...
FSIChannelWithLeafletProblem(const unsigned &mesh_multiplier)
Constructor: Pass multiplier for uniform mesh refinement.
Preconditioner * set_hypre_preconditioner()
Create instance of Hypre preconditioner with settings that are appropriate for serial solution of Nav...
void actions_before_implicit_timestep()
Actions before implicit timestep: Update the inflow velocity.
int main(int argc, char **argv)
Driver code.
void delete_lagrange_multiplier_elements()
double Fluid_length_right
length of fluid mesh to right of leaflet
double Leaflet_height
height of leaflet
~FSIChannelWithLeafletProblem()
Destructor empty.
void doc_solution(DocInfo &doc_info)
Doc the solution.
void create_lagrange_multiplier_elements()
Create elements that enforce prescribed boundary motion by Lagrange multipliers.
double flux(const double &t)
Flux: Pulsatile flow.
MeshAsGeomObject * Wall_geom_object_pt
Geometric object for the leaflet (to apply lagrange mult)
void actions_before_newton_solve()
Actions before Newton solve: Reset the pseudo-elastic undeformed configuration.
SolidMesh * Lagrange_multiplier_mesh_pt
Pointers to mesh of Lagrange multiplier elements.
double Leaflet_x0
x-position of root of leaflet
PseudoElasticBulkElement()
default constructor
double Lambda_sq_beam
Beam mass density.
double Fluid_length_left
length of fluid mesh to left of leaflet
unsigned Mesh_ny2
Num elements in fluid mesh in y dirn above leaflet.
void actions_before_newton_convergence_check()
Update no slip before Newton convergence check.
unsigned Mesh_nleft
Num elements to left of leaflet in coarse mesh.
PseudoElasticChannelWithLeafletMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the fluid mesh.
double Lambda_sq
Pseudo-solid mass density.
Node * tip_node_pt()
Helper fct; returns the node at the tip of the wall mesh.
void actions_after_newton_solve()
Actions after solve (empty)
double Fluid_height
height of fluid mesh
void doc_parameters()
Doc parameters.
double U_perturbation
Max. flux.
BDF< 2 > * Bulk_time_stepper_pt
Bulk timestepper.
double Nu
Pseudo-solid Poisson ratio.
double ReSt
Womersley number: Product of Reynolds and Strouhal numbers.
void get_dof_numbers_for_unknowns(std::list< std::pair< unsigned long, unsigned > > &dof_lookup_list) const
Create a list of pairs for all unknowns in this element, so that the first entry in each pair contain...
Namespace for Navier Stokes LSC Preconditioner.
ConstitutiveLaw * Constitutive_law_pt
Constitutive law used to determine the mesh deformation.
unsigned ndof_types() const
Return the number of DOF types associated with this element.
double H
Non-dimensional wall thickness.
unsigned Mesh_ny1
Num elements in fluid mesh in y dirn adjacent to leaflet.
OneDLagrangianMesh< FSIHermiteBeamElement > * Wall_mesh_pt
Pointer to the "wall" mesh.
UndeformedLeaflet * Undeformed_wall_pt
Geom object for the leaflet.
double Re
Reynolds number.
double Dt
Timestep for simulation: 40 steps per period.
unsigned Mesh_nright
Num elements to right of leaflet in coarse mesh.
double T
Period for fluctuations in flux.