30 #include "navier_stokes.h"
31 #include "multi_physics.h"
32 #include "constitutive.h"
36 #include "meshes/channel_with_leaflet_mesh.h"
37 #include "meshes/one_d_lagrangian_mesh.h"
40 using namespace oomph;
54 template <
class ELEMENT>
56 public virtual ELEMENT
67 return 2*ELEMENT::dim();
84 std::list<std::pair<unsigned long,unsigned> >& dof_lookup_list)
const
87 std::pair<unsigned,unsigned> dof_lookup;
90 const unsigned n_node = this->nnode();
93 const unsigned n_position_type = ELEMENT::nnodal_position_type();
94 const unsigned nodal_dim = ELEMENT::nodal_dimension();
100 for(
unsigned n=0;n<n_node;n++)
103 if (this->node_pt(n)->nvalue() != this->required_nvalue(n))
105 offset = ELEMENT::dim();
109 for(
unsigned k=0;k<n_position_type;k++)
112 for(
unsigned i=0;i<nodal_dim;i++)
115 local_unknown = ELEMENT::position_local_eqn(n,k,i);
118 if (local_unknown >= 0)
122 dof_lookup.first = this->eqn_number(local_unknown);
123 dof_lookup.second = offset+i;
126 dof_lookup_list.push_front(dof_lookup);
139 template<
class ELEMENT>
141 public virtual FaceGeometry<ELEMENT>
155 #ifdef OOMPH_HAS_HYPRE
167 HyprePreconditioner* hypre_preconditioner_pt
168 =
new HyprePreconditioner;
169 hypre_preconditioner_pt->set_amg_iterations(2);
170 hypre_preconditioner_pt->amg_using_simple_smoothing();
171 hypre_preconditioner_pt->amg_simple_smoother() = 0;
172 hypre_preconditioner_pt->hypre_method() = HyprePreconditioner::BoomerAMG;
173 hypre_preconditioner_pt->amg_strength() = 0.25;
174 hypre_preconditioner_pt->amg_coarsening() = 3;
175 hypre_preconditioner_pt->amg_damping() = 2.0/3.0;
176 return hypre_preconditioner_pt;
284 void position(
const Vector<double>& zeta, Vector<double>& r)
const
295 void position(
const unsigned& t,
const Vector<double>& zeta,
296 Vector<double>& r)
const
310 DenseMatrix<double> &drdzeta,
311 RankThreeTensor<double> &ddrdzeta)
const
346 template<
class ELEMENT>
359 delete Lagrange_multiplier_mesh_pt;
361 delete Bulk_time_stepper_pt;
362 delete Wall_time_stepper_pt;
363 delete Wall_geom_object_pt;
364 delete Undeformed_wall_pt;
365 delete Constitutive_law_pt;
376 Bulk_mesh_pt->set_lagrangian_nodal_coordinates();
383 unsigned nnod=Bulk_mesh_pt->nnode();
384 for (
unsigned j=0;j<nnod;j++)
386 Bulk_mesh_pt->node_pt(j)->perform_auxiliary_node_update_fct();
395 double t=time_pt()->time();
402 unsigned num_nod= Bulk_mesh_pt->nboundary_node(ibound);
403 for (
unsigned inod=0;inod<num_nod;inod++)
405 double ycoord = Bulk_mesh_pt->boundary_node_pt(ibound,inod)->x(1);
408 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,uy);
409 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
414 void set_iterative_solver();
417 void doc_solution(DocInfo& doc_info);
421 void create_lagrange_multiplier_elements();
425 void delete_lagrange_multiplier_elements();
430 oomph_info <<
"\n\n=================================================\n";
439 oomph_info <<
"t : " << time_pt()->time()
441 oomph_info <<
"tip x : "
442 << tip_node_pt()->x(0) << std::endl;
443 oomph_info <<
"tip y : "
444 << tip_node_pt()->x(1) << std::endl;
445 oomph_info <<
"=================================================\n\n";
453 unsigned n_el_wall=Wall_mesh_pt->nelement();
454 return Wall_mesh_pt->finite_element_pt(n_el_wall-1)->node_pt(1);
488 template <
class ELEMENT>
490 (
const unsigned& mesh_multiplier)
494 Bulk_time_stepper_pt=
new BDF<2>;
495 add_time_stepper_pt(Bulk_time_stepper_pt);
496 Wall_time_stepper_pt=
new Newmark<2>;
497 add_time_stepper_pt(Wall_time_stepper_pt);
507 Wall_mesh_pt =
new OneDLagrangianMesh<FSIHermiteBeamElement>
509 Undeformed_wall_pt,Wall_time_stepper_pt);
516 Wall_geom_object_pt=
new MeshAsGeomObject(Wall_mesh_pt);
519 Bulk_mesh_pt =
new PseudoElasticChannelWithLeafletMesh<ELEMENT>(
529 Bulk_time_stepper_pt);
536 Lagrange_multiplier_mesh_pt=
new SolidMesh;
537 create_lagrange_multiplier_elements();
542 add_sub_mesh(Bulk_mesh_pt);
543 add_sub_mesh(Lagrange_multiplier_mesh_pt);
544 add_sub_mesh(Wall_mesh_pt);
553 unsigned num_bound = Bulk_mesh_pt->nboundary();
554 for(
unsigned ibound=0;ibound<num_bound;ibound++)
556 unsigned num_nod= Bulk_mesh_pt->nboundary_node(ibound);
557 for (
unsigned inod=0;inod<num_nod;inod++)
559 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
564 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->pin(0);
571 for (
unsigned ibound=0;ibound<7;ibound++)
573 if (ibound==0||ibound==1||ibound==2||ibound==3||ibound==6)
575 unsigned num_nod=Bulk_mesh_pt->nboundary_node(ibound);
576 for (
unsigned inod=0;inod<num_nod;inod++)
578 for(
unsigned i=0;i<2;i++)
580 if (!( (ibound==2)&&(i==0) ))
582 dynamic_cast<SolidNode*
>(Bulk_mesh_pt->
583 boundary_node_pt(ibound, inod))
595 unsigned num_nod= Bulk_mesh_pt->nboundary_node(ibound);
596 for (
unsigned inod=0;inod<num_nod;inod++)
598 double ycoord = Bulk_mesh_pt->boundary_node_pt(ibound,inod)->x(1);
601 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,uy);
602 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
612 Wall_mesh_pt->boundary_node_pt(b,0)->pin_position(0);
613 Wall_mesh_pt->boundary_node_pt(b,0)->pin_position(1);
616 Wall_mesh_pt->boundary_node_pt(b,0)->pin_position(1,0);
627 unsigned n_element = Bulk_mesh_pt->nelement();
628 for(
unsigned e=0;e<n_element;e++)
631 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
640 el_pt->constitutive_law_pt() = Constitutive_law_pt;
651 n_element = Wall_mesh_pt->nelement();
652 for(
unsigned e=0;e<n_element;e++)
655 FSIHermiteBeamElement *elem_pt =
656 dynamic_cast<FSIHermiteBeamElement*
>(Wall_mesh_pt->element_pt(e));
665 elem_pt->undeformed_beam_pt() = Undeformed_wall_pt;
671 elem_pt->enable_fluid_loading_on_both_sides();
677 elem_pt->set_normal_pointing_out_of_fluid();
689 for(
unsigned ibound=4;ibound<6;ibound++ )
691 unsigned num_nod= Bulk_mesh_pt->nboundary_node(ibound);
692 for (
unsigned inod=0;inod<num_nod;inod++)
694 Bulk_mesh_pt->boundary_node_pt(ibound, inod)->
695 set_auxiliary_node_update_fct_pt(
696 FSI_functions::apply_no_slip_on_moving_wall);
710 FSI_functions::setup_fluid_load_info_for_solid_elements<ELEMENT,2>
719 FSI_functions::setup_fluid_load_info_for_solid_elements<ELEMENT,2>
720 (
this,5,Bulk_mesh_pt,Wall_mesh_pt,face);
724 oomph_info <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
732 template<
class ELEMENT>
736 IterativeLinearSolver* solver_pt=0;
739 #ifdef OOMPH_HAS_TRILINOS
742 solver_pt =
new TrilinosAztecOOSolver;
745 dynamic_cast<TrilinosAztecOOSolver*
>(solver_pt)->solver_type()
746 = TrilinosAztecOOSolver::GMRES;
751 solver_pt =
new GMRES<CRDoubleMatrix>;
756 linear_solver_pt() = solver_pt;
760 PseudoElasticFSIPreconditioner* prec_pt=
761 new PseudoElasticFSIPreconditioner(dim,
this);
764 solver_pt->preconditioner_pt() = prec_pt;
769 prec_pt->set_fluid_and_pseudo_elastic_mesh_pt(Bulk_mesh_pt);
770 prec_pt->set_solid_mesh_pt(Wall_mesh_pt);
771 prec_pt->set_lagrange_multiplier_mesh_pt(Lagrange_multiplier_mesh_pt);
776 if (!CommandLineArgs::command_line_flag_has_been_set(
"--suppress_lsc"))
778 oomph_info <<
"Enabling LSC preconditioner\n";
779 prec_pt->enable_navier_stokes_schur_complement_preconditioner();
783 prec_pt->disable_navier_stokes_schur_complement_preconditioner();
784 oomph_info <<
"Not using LSC preconditioner\n";
790 if (CommandLineArgs::command_line_flag_has_been_set(
"--superlu_for_blocks"))
792 oomph_info <<
"Use SuperLU for block solves\n";
796 oomph_info <<
"Use optimal block solves\n";
799 NavierStokesSchurComplementPreconditioner* ns_prec_pt =
800 prec_pt->navier_stokes_schur_complement_preconditioner_pt();
806 BlockTriangularPreconditioner<CRDoubleMatrix>*
807 f_prec_pt =
new BlockTriangularPreconditioner<CRDoubleMatrix>;
810 ns_prec_pt->set_f_preconditioner(f_prec_pt);
812 #ifdef OOMPH_HAS_HYPRE
815 f_prec_pt->set_subsidiary_preconditioner_function
823 HyprePreconditioner* p_prec_pt =
new HyprePreconditioner;
824 p_prec_pt->disable_doc_time();
825 Hypre_default_settings::set_defaults_for_2D_poisson_problem(p_prec_pt);
826 ns_prec_pt->set_p_preconditioner(p_prec_pt);
834 prec_pt->pseudo_elastic_preconditioner_pt()->elastic_preconditioner_type()
835 = PseudoElasticPreconditioner::Block_upper_triangular_preconditioner;
837 #ifdef OOMPH_HAS_HYPRE
840 prec_pt->pseudo_elastic_preconditioner_pt()->
841 set_elastic_subsidiary_preconditioner(
842 Pseudo_Elastic_Preconditioner_Subsidiary_Operator_Helper::
843 get_elastic_preconditioner_hypre);
847 #ifdef OOMPH_HAS_TRILINOS
851 prec_pt->pseudo_elastic_preconditioner_pt()->
852 set_lagrange_multiplier_subsidiary_preconditioner
853 (Pseudo_Elastic_Preconditioner_Subsidiary_Operator_Helper::
854 get_lagrange_multiplier_preconditioner);
866 template<
class ELEMENT>
871 for (
unsigned b=4;b<=5;b++)
874 unsigned n_bulk_element = Bulk_mesh_pt->nboundary_element(b);
877 for(
unsigned e=0;e<n_bulk_element;e++)
880 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
881 Bulk_mesh_pt->boundary_element_pt(b,e));
884 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
887 ImposeDisplacementByLagrangeMultiplierElement<ELEMENT> *el_pt =
888 new ImposeDisplacementByLagrangeMultiplierElement<ELEMENT>(
889 bulk_elem_pt,face_index);
892 Lagrange_multiplier_mesh_pt->add_element_pt(el_pt);
897 el_pt->set_boundary_shape_geom_object_pt(Wall_geom_object_pt,b);
903 unsigned n_element=Lagrange_multiplier_mesh_pt->nelement();
904 for(
unsigned i=0;i<n_element;i++)
907 ImposeDisplacementByLagrangeMultiplierElement<ELEMENT> *el_pt =
908 dynamic_cast<ImposeDisplacementByLagrangeMultiplierElement<ELEMENT>*
>
909 (Lagrange_multiplier_mesh_pt->element_pt(i));
912 unsigned nnod=el_pt->nnode();
913 for (
unsigned j=0;j<nnod;j++)
915 Node* nod_pt = el_pt->node_pt(j);
918 if ((nod_pt->is_on_boundary(0))||(nod_pt->is_on_boundary(6)))
922 unsigned n_bulk_value=el_pt->nbulk_value(j);
925 unsigned nval=nod_pt->nvalue();
926 for (
unsigned k=n_bulk_value;k<nval;k++)
941 template<
class ELEMENT>
946 unsigned n_element = Lagrange_multiplier_mesh_pt->nelement();
949 for(
unsigned e=0;e<n_element;e++)
952 delete Lagrange_multiplier_mesh_pt->element_pt(e);
956 Lagrange_multiplier_mesh_pt->flush_element_and_node_storage();
965 template<
class ELEMENT>
976 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
978 some_file.open(filename);
979 Bulk_mesh_pt->output(some_file,npts);
983 sprintf(filename,
"%s/wall_soln%i.dat",doc_info.directory().c_str(),
985 some_file.open(filename);
986 Wall_mesh_pt->output(some_file,npts);
995 sprintf(filename,
"%s/bulk_boundary_elements_front_%i.dat",
996 doc_info.directory().c_str(),
998 some_file.open(filename);
999 unsigned nel= Bulk_mesh_pt->nboundary_element(bound);
1000 for (
unsigned e=0;e<nel;e++)
1002 dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->boundary_element_pt(bound,e))
1003 ->output(some_file,npts);
1011 sprintf(filename,
"%s/bulk_boundary_elements_back_%i.dat",
1012 doc_info.directory().c_str(),
1014 some_file.open(filename);
1015 nel= Bulk_mesh_pt->nboundary_element(bound);
1016 for (
unsigned e=0;e<nel;e++)
1018 dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->boundary_element_pt(bound,e))
1019 ->output(some_file,npts);
1025 sprintf(filename,
"%s/wall_normal_%i.dat",
1026 doc_info.directory().c_str(),
1028 some_file.open(filename);
1029 nel=Wall_mesh_pt->nelement();
1030 Vector<double> s(1);
1031 Vector<double> x(2);
1032 Vector<double> xi(1);
1033 Vector<double> N(2);
1034 for (
unsigned e=0;e<nel;e++)
1037 FSIHermiteBeamElement* el_pt=
1038 dynamic_cast<FSIHermiteBeamElement*
>(Wall_mesh_pt->element_pt(e));
1041 for (
unsigned i=0;i<npts;i++)
1043 s[0]=-1.0+2.0*double(i)/double(npts-1);
1046 el_pt->interpolated_x(s,x);
1049 el_pt->get_normal(s,N);
1052 el_pt->interpolated_xi(s,xi);
1054 some_file << x[0] <<
" " << x[1] <<
" "
1055 << N[0] <<
" " << N[1] <<
" "
1056 << xi[0] << std::endl;
1070 #ifdef OOMPH_HAS_MPI
1071 MPI_Helpers::init(argc,argv);
1075 oomph_info.output_modifier_pt() = &default_output_modifier;
1078 CommandLineArgs::setup(argc,argv);
1082 unsigned mesh_multiplier = 2;
1083 CommandLineArgs::specify_command_line_flag(
"--mesh_multiplier",
1087 CommandLineArgs::specify_command_line_flag(
"--suppress_lsc");
1090 CommandLineArgs::specify_command_line_flag(
"--use_direct_solver");
1093 CommandLineArgs::specify_command_line_flag(
"--superlu_for_blocks");
1096 CommandLineArgs::specify_command_line_flag(
"--validate");
1099 CommandLineArgs::parse_and_assign();
1102 CommandLineArgs::doc_specified_flags();
1106 <QTaylorHoodElement<2>,
1110 <QTaylorHoodElement<2>,
1119 doc_info.set_directory(
"RESLT");
1123 std::ofstream output_stream;
1124 char filename[1000];
1125 #ifdef OOMPH_HAS_MPI
1126 sprintf(filename,
"%s/OUTPUT_STEADY.%i",doc_info.directory().c_str(),
1127 MPI_Helpers::communicator_pt()->my_rank());
1129 sprintf(filename,
"%s/OUTPUT_STEADY.%i",doc_info.directory().c_str(),0);
1132 output_stream.open(filename);
1133 oomph_info.stream_pt() = &output_stream;
1134 OomphLibWarning::set_stream_pt(&output_stream);
1135 OomphLibError::set_stream_pt(&output_stream);
1139 problem_pt->doc_solution(doc_info);
1140 doc_info.number()++;
1143 if (!CommandLineArgs::command_line_flag_has_been_set(
"--use_direct_solver"))
1145 problem_pt->set_iterative_solver();
1158 problem_pt->steady_newton_solve();
1159 problem_pt->doc_parameters();
1162 problem_pt->doc_solution(doc_info);
1163 doc_info.number()++;
1169 problem_pt->steady_newton_solve();
1170 problem_pt->doc_parameters();
1171 problem_pt->doc_solution(doc_info);
1172 doc_info.number()++;
1178 output_stream.close();
1179 #ifdef OOMPH_HAS_MPI
1180 sprintf(filename,
"%s/OUTPUT_UNSTEADY.%i",doc_info.directory().c_str(),
1181 MPI_Helpers::communicator_pt()->my_rank());
1183 sprintf(filename,
"%s/OUTPUT_UNSTEADY.%i",doc_info.directory().c_str(),0);
1185 output_stream.open(filename);
1186 oomph_info.stream_pt() = &output_stream;
1187 OomphLibWarning::set_stream_pt(&output_stream);
1188 OomphLibError::set_stream_pt(&output_stream);
1192 unsigned n_period=1;
1194 unsigned nstep=unsigned(
double(n_period)
1197 if (CommandLineArgs::command_line_flag_has_been_set(
"--validate"))
1201 for (
unsigned r = 0; r < nstep; r++)
1204 problem_pt->doc_parameters();
1205 problem_pt->doc_solution(doc_info);
1206 doc_info.number()++;
1213 oomph_info <<
"Done\n";
1215 #ifdef OOMPH_HAS_MPI
1216 MPI_Helpers::finalize();
///////////////////////////////////////////////////////////////////////// ///////////////////////////...
Node * tip_node_pt()
Helper fct; returns the node at the tip of the wall mesh.
void doc_parameters()
Doc parameters.
MeshAsGeomObject * Wall_geom_object_pt
Geometric object for the leaflet (to apply lagrange mult)
PseudoElasticChannelWithLeafletMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the fluid mesh.
~FSIChannelWithLeafletProblem()
Destructor empty.
ConstitutiveLaw * Constitutive_law_pt
Constitutive law used to determine the mesh deformation.
FSIChannelWithLeafletProblem(const unsigned &mesh_multiplier)
Constructor: Pass multiplier for uniform mesh refinement.
void actions_before_newton_solve()
Actions before Newton solve: Reset the pseudo-elastic undeformed configuration.
void set_iterative_solver()
Set iterative solver.
OneDLagrangianMesh< FSIHermiteBeamElement > * Wall_mesh_pt
Pointer to the "wall" mesh.
void create_lagrange_multiplier_elements()
Create elements that enforce prescribed boundary motion by Lagrange multipliers.
SolidMesh * Lagrange_multiplier_mesh_pt
Pointers to mesh of Lagrange multiplier elements.
void actions_after_newton_solve()
Actions after solve (empty)
BDF< 2 > * Bulk_time_stepper_pt
Bulk timestepper.
void actions_before_implicit_timestep()
Actions before implicit timestep: Update the inflow velocity.
Newmark< 2 > * Wall_time_stepper_pt
Wall time stepper pt.
UndeformedLeaflet * Undeformed_wall_pt
Geom object for the leaflet.
void doc_solution(DocInfo &doc_info)
Doc the solution.
void delete_lagrange_multiplier_elements()
Delete elements that enforce prescribed boundary motion by Lagrange multipliers.
void actions_before_newton_convergence_check()
Update no slip before Newton convergence check.
Pseudo-Elastic Solid element class to overload the Block Preconditioner methods ndof_types() and get_...
unsigned ndof_types() const
Return the number of DOF types associated with this element.
PseudoElasticBulkElement()
default constructor
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...
int main(int argc, char **argv)
Driver code.
////////////////////////////////////////////////////////////////// //////////////////////////////////...
double Fluid_length_right
length of fluid mesh to right of leaflet
double Nu
Pseudo-solid Poisson ratio.
double Lambda_sq
Pseudo-solid mass density.
double flux(const double &t)
Flux: Pulsatile flow.
double Leaflet_height
height of leaflet
unsigned Mesh_ny1
Num elements in fluid mesh in y dirn adjacent to leaflet.
double Q
Fluid structure interaction parameter: Ratio of stresses used for non-dimensionalisation of fluid to ...
double ReSt
Womersley number: Product of Reynolds and Strouhal numbers.
unsigned Mesh_nright
Num elements to right of leaflet in coarse mesh.
double Leaflet_x0
x-position of root of leaflet
unsigned Mesh_nleft
Num elements to left of leaflet in coarse mesh.
double Re
Reynolds number.
unsigned Mesh_ny2
Num elements in fluid mesh in y dirn above leaflet.
double Dt
Timestep for simulation: 40 steps per period.
double H
Non-dimensional wall thickness.
double U_perturbation
Max. flux.
double Fluid_length_left
length of fluid mesh to left of leaflet
double Fluid_height
height of fluid mesh
double T
Period for fluctuations in flux.
double Lambda_sq_beam
Beam mass density.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
Preconditioner * set_hypre_preconditioner()
Create instance of Hypre preconditioner with settings that are appropriate for serial solution of Nav...
////////////////////////////////////////////////////////////////// //////////////////////////////////...