33 #include "navier_stokes.h"
36 #include "multi_physics.h"
39 #include "meshes/cylinder_with_flag_mesh.h"
40 #include "meshes/rectangular_quadmesh.h"
45 using namespace oomph;
110 const Vector<double> &xi,
133 0.5*(1.0-cos(MathematicalConstants::Pi*t/
Ramp_period));
184 else if (case_id==
"FSI2")
218 else if (case_id==
"FSI3")
252 else if (case_id==
"CSM1")
287 else if (case_id==
"CSM3")
325 std::cout <<
"Wrong case_id: " << case_id << std::endl;
337 oomph_info << std::endl;
338 oomph_info <<
"-------------------------------------------"
340 oomph_info <<
"Case: " << case_id << std::endl;
341 oomph_info <<
"Re = " <<
Re << std::endl;
342 oomph_info <<
"St = " <<
St << std::endl;
343 oomph_info <<
"ReSt = " <<
ReSt << std::endl;
344 oomph_info <<
"Q = " <<
Q << std::endl;
345 oomph_info <<
"Dt = " <<
Dt << std::endl;
346 oomph_info <<
"Ramp_period = " <<
Ramp_period << std::endl;
347 oomph_info <<
"Max_flux = " <<
Max_flux << std::endl;
348 oomph_info <<
"Density_ratio = " <<
Density_ratio << std::endl;
349 oomph_info <<
"Lambda_sq = " <<
Lambda_sq << std::endl;
350 oomph_info <<
"Gravity = " <<
Gravity << std::endl;
352 oomph_info <<
"-------------------------------------------"
353 << std::endl << std::endl;
369 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT >
376 TurekProblem(
const double &length,
const double &height);
380 {
return Fluid_mesh_pt;}
384 {
return Solid_mesh_pt;}
388 {
return Traction_mesh_pt[i];}
391 void actions_after_adapt();
394 void doc_solution(DocInfo& doc_info, ofstream& trace_file);
405 void actions_before_newton_convergence_check();
408 void actions_before_implicit_timestep();
413 void create_fsi_traction_elements();
445 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT >
448 const double &height) : Domain_height(height),
449 Domain_length(length)
454 Max_newton_iterations=20;
470 Newmark<2>* flag_time_stepper_pt=
new Newmark<2>;
471 add_time_stepper_pt(flag_time_stepper_pt);
475 Vector<double> origin(2);
484 double l_x=6.0-origin[0];
487 solid_mesh_pt() =
new ElasticRefineableRectangularQuadMesh<SOLID_ELEMENT>(
488 n_x,n_y,l_x,l_y,origin,flag_time_stepper_pt);
491 Z2ErrorEstimator* solid_error_estimator_pt=
new Z2ErrorEstimator;
492 solid_mesh_pt()->spatial_error_estimator_pt()=solid_error_estimator_pt;
496 FiniteElement* el_pt=
solid_mesh_pt()->finite_element_pt(n_x*n_y/2-1);
499 unsigned nnod=el_pt->nnode();
504 std::cout <<
"Coordinates of solid control point "
535 for (
unsigned bound=0;bound<3;bound++)
538 for(
unsigned e=0;e<n_face_element;e++)
541 FSISolidTractionElement<SOLID_ELEMENT,2>* elem_pt=
542 dynamic_cast<FSISolidTractionElement<SOLID_ELEMENT,2>*
>
546 elem_pt->set_boundary_number_in_bulk_mesh(bound);
563 MeshAsGeomObject* tip_flag_pt=
567 MeshAsGeomObject* top_flag_pt=
581 BDF<2>* fluid_time_stepper_pt=
new BDF<2>;
582 add_time_stepper_pt(fluid_time_stepper_pt);
586 new RefineableAlgebraicCylinderWithFlagMesh<FLUID_ELEMENT>
596 fluid_time_stepper_pt);
605 Z2ErrorEstimator* fluid_error_estimator_pt=
new Z2ErrorEstimator;
606 fluid_mesh_pt()->spatial_error_estimator_pt()=fluid_error_estimator_pt;
619 for (
unsigned i=0;i<3;i++)
636 unsigned n_side = mesh_pt()->nboundary_node(3);
639 for(
unsigned i=0;i<n_side;i++)
646 PVDEquationsBase<2>::pin_redundant_nodal_solid_pressures(
654 for(
unsigned ibound=0;ibound<num_bound;ibound++)
657 for (
unsigned inod=0;inod<num_nod;inod++)
673 RefineableNavierStokesEquations<2>::
674 pin_redundant_nodal_pressures(
fluid_mesh_pt()->element_pt());
686 for (
unsigned inod=0;inod<num_nod;inod++)
688 double ycoord =
Fluid_mesh_pt->boundary_node_pt(ibound,inod)->x(1);
690 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,uy);
691 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
700 for(
unsigned i=0;i<n_element;i++)
703 SOLID_ELEMENT *el_pt =
dynamic_cast<SOLID_ELEMENT*
>(
707 el_pt->constitutive_law_pt() =
724 for (
unsigned e=0;e<nelem;e++)
727 FLUID_ELEMENT* el_pt =
dynamic_cast<FLUID_ELEMENT*
>
754 for(
unsigned ibound=5;ibound<8;ibound++ )
757 for (
unsigned inod=0;inod<num_nod;inod++)
760 set_auxiliary_node_update_fct_pt(
761 FSI_functions::apply_no_slip_on_moving_wall);
769 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
772 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
775 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
784 GMRES<CRDoubleMatrix>* iterative_linear_solver_pt =
785 new GMRES<CRDoubleMatrix>;
788 iterative_linear_solver_pt->max_iter() = 100;
791 iterative_linear_solver_pt->tolerance() = 1.0e-10;
794 linear_solver_pt()=iterative_linear_solver_pt;
797 FSIPreconditioner* prec_pt=
new FSIPreconditioner(
this);
806 prec_pt->use_block_triangular_version_with_fluid_on_solid();
809 iterative_linear_solver_pt->preconditioner_pt()= prec_pt;
818 #ifdef OOMPH_HAS_HYPRE
820 #ifndef OOMPH_HAS_MPI
823 Preconditioner* P_matrix_preconditioner_pt =
new HyprePreconditioner;
825 HyprePreconditioner* P_hypre_solver_pt =
826 static_cast<HyprePreconditioner*
>(P_matrix_preconditioner_pt);
830 Hypre_default_settings::
831 set_defaults_for_2D_poisson_problem(P_hypre_solver_pt);
834 prec_pt->navier_stokes_preconditioner_pt()->
835 set_p_preconditioner(P_matrix_preconditioner_pt);
838 P_hypre_solver_pt->disable_doc_time();
844 cout << assign_eqn_numbers() << std::endl;
855 template <
class FLUID_ELEMENT,
class SOLID_ELEMENT>
859 fluid_mesh_pt()->node_update();
867 template <
class FLUID_ELEMENT,
class SOLID_ELEMENT>
872 double t=time_pt()->time();
879 unsigned num_nod= Fluid_mesh_pt->nboundary_node(ibound);
880 for (
unsigned inod=0;inod<num_nod;inod++)
882 double ycoord = Fluid_mesh_pt->boundary_node_pt(ibound,inod)->x(1);
883 double uy = ampl*6.0*ycoord/Domain_height*(1.0-ycoord/Domain_height);
884 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,uy);
885 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
894 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT >
898 RefineableNavierStokesEquations<2>::
899 unpin_all_pressure_dofs(fluid_mesh_pt()->element_pt());
902 RefineableNavierStokesEquations<2>::
903 pin_redundant_nodal_pressures(fluid_mesh_pt()->element_pt());
906 PVDEquationsBase<2>::
907 unpin_all_solid_pressure_dofs(solid_mesh_pt()->element_pt());
910 PVDEquationsBase<2>::pin_redundant_nodal_solid_pressures(
911 solid_mesh_pt()->element_pt());
921 for(
unsigned ibound=5;ibound<8;ibound++ )
923 unsigned num_nod= Fluid_mesh_pt->nboundary_node(ibound);
924 for (
unsigned inod=0;inod<num_nod;inod++)
926 Fluid_mesh_pt->boundary_node_pt(ibound, inod)->
927 set_auxiliary_node_update_fct_pt(
928 FSI_functions::apply_no_slip_on_moving_wall);
934 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
935 (
this,5,Fluid_mesh_pt,Traction_mesh_pt[0]);
937 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
938 (
this,6,Fluid_mesh_pt,Traction_mesh_pt[2]);
940 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
941 (
this,7,Fluid_mesh_pt,Traction_mesh_pt[1]);
952 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT >
957 std::set<SolidNode*> all_nodes;
960 for (
unsigned b=0;b<3;b++)
963 unsigned n_element = solid_mesh_pt()->nboundary_element(b);
966 for(
unsigned e=0;e<n_element;e++)
969 SOLID_ELEMENT* bulk_elem_pt =
dynamic_cast<SOLID_ELEMENT*
>(
970 solid_mesh_pt()->boundary_element_pt(b,e));
973 int face_index = solid_mesh_pt()->face_index_at_boundary(b,e);
976 Traction_mesh_pt[b]->add_element_pt(
977 new FSISolidTractionElement<SOLID_ELEMENT,2>(bulk_elem_pt,face_index));
982 unsigned nnod=solid_mesh_pt()->nboundary_node(b);
983 for (
unsigned j=0;j<nnod;j++)
985 all_nodes.insert(solid_mesh_pt()->boundary_node_pt(b,j));
990 Combined_traction_mesh_pt=
new SolidMesh(Traction_mesh_pt);
993 for (std::set<SolidNode*>::iterator it=all_nodes.begin();
994 it!=all_nodes.end();it++)
996 Combined_traction_mesh_pt->add_node_pt(*it);
1007 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT >
1009 DocInfo& doc_info, ofstream& trace_file)
1022 unsigned n_plot = 5;
1025 sprintf(filename,
"%s/solid_soln%i.dat",doc_info.directory().c_str(),
1027 some_file.open(filename);
1028 solid_mesh_pt()->output(some_file,n_plot);
1032 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
1034 some_file.open(filename);
1035 fluid_mesh_pt()->output(some_file,n_plot);
1040 sprintf(filename,
"%s/traction%i.dat",doc_info.directory().c_str(),
1042 some_file.open(filename);
1044 for(
unsigned i=0;i<3;i++)
1047 unsigned n_element = Traction_mesh_pt[i]->nelement();
1048 for(
unsigned e=0;e<n_element;e++)
1050 FSISolidTractionElement<SOLID_ELEMENT,2>* el_pt =
1051 dynamic_cast<FSISolidTractionElement<SOLID_ELEMENT,2>*
> (
1052 Traction_mesh_pt[i]->element_pt(e) );
1054 el_pt->output(some_file,5);
1062 trace_file << time_pt()->time() <<
" "
1063 << Solid_control_node_pt->x(0) <<
" "
1064 << Solid_control_node_pt->x(1) <<
" "
1065 << Fluid_control_node_pt->value(2) <<
" "
1069 cout <<
"Doced solution for step "
1070 << doc_info.number()
1071 << std::endl << std::endl << std::endl;
1083 CommandLineArgs::setup(argc,argv);
1086 string case_id=
"FSI1";
1087 if (CommandLineArgs::Argc==1)
1089 oomph_info <<
"No command line arguments; running self-test FSI1"
1092 else if (CommandLineArgs::Argc==2)
1094 case_id=CommandLineArgs::Argv[1];
1098 oomph_info <<
"Wrong number of command line arguments" << std::endl;
1099 oomph_info <<
"Enter none (for default) or one (namely the case id"
1101 oomph_info <<
"which should be one of: FSI1, FSI2, FSI3, CSM1"
1104 std::cout <<
"Running case " << case_id << std::endl;
1112 ofstream trace_file;
1113 doc_info.set_directory(
"RESLT");
1114 trace_file.open(
"RESLT/trace.dat");
1122 RefineableQPVDElement<2,3> > problem(length, height);
1125 unsigned nstep=4000;
1128 std::cout <<
"Reducing number of steps for FSI1 " << std::endl;
1132 if (CommandLineArgs::Argc==1)
1134 std::cout <<
"Reducing number of steps for validation " << std::endl;
1142 problem.initialise_dt(dt);
1145 problem.assign_initial_values_impulsive(dt);
1149 doc_info.number()++;
1156 unsigned max_adapt=1;
1158 for(
unsigned i=0;i<nstep;i++)
1161 problem.unsteady_newton_solve(dt,max_adapt,first);
1167 doc_info.number()++;
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
Vector< SolidMesh * > Traction_mesh_pt
Vector of pointers to mesh of FSI traction elements.
RefineableAlgebraicCylinderWithFlagMesh< FLUID_ELEMENT > * fluid_mesh_pt()
Access function for the fluid mesh.
RefineableAlgebraicCylinderWithFlagMesh< FLUID_ELEMENT > * Fluid_mesh_pt
Pointer to fluid mesh.
ElasticRefineableRectangularQuadMesh< SOLID_ELEMENT > * Solid_mesh_pt
Pointer to solid mesh.
double Domain_height
Overall height of domain.
void doc_solution(DocInfo &doc_info, ofstream &trace_file)
Doc the solution.
void actions_after_adapt()
Actions after adapt: Re-setup the fsi lookup scheme.
Node * Fluid_control_node_pt
Pointer to fluid control node.
void actions_before_implicit_timestep()
Update the time-dependent influx.
TurekProblem(const double &length, const double &height)
Constructor: Pass length and height of domain.
void actions_before_newton_solve()
Update function (empty)
ElasticRefineableRectangularQuadMesh< SOLID_ELEMENT > *& solid_mesh_pt()
Access function for the solid mesh.
SolidMesh *& traction_mesh_pt(const unsigned &i)
Access function for the i-th mesh of FSI traction elements.
void actions_before_newton_convergence_check()
Update the (dependent) fluid node positions following the update of the solid variables before perfor...
SolidMesh * Combined_traction_mesh_pt
Combined mesh of traction elements – only used for documentation.
void create_fsi_traction_elements()
Create FSI traction elements.
Node * Solid_control_node_pt
Pointer to solid control node.
void actions_after_newton_solve()
Update function (empty)
double Domain_length
Overall length of domain.
double Centre_x
x position of centre of cylinder
double Radius
Radius of cylinder.
double Max_flux
Max. flux.
void gravity(const double &time, const Vector< double > &xi, Vector< double > &b)
Non-dimensional gravity as body force.
double Nu
Poisson's ratio.
double Gravity
Non-dim gravity (default assignment for FSI1 test case)
double Lambda_sq
Timescale ratio for solid (dependent parameter assigned in set_parameters())
double Density_ratio
Density ratio (solid to fluid; default assignment for FSI1 test case)
double flux(const double &t)
Flux increases between Min_flux and Max_flux over period Ramp_period.
double Min_flux
Min. flux.
double Q
FSI parameter (default assignment for FSI1 test case)
double ReSt
Product of Reynolds and Strouhal numbers (default assignment for FSI1 test case)
string Case_ID
Default case ID.
void set_parameters(const string &case_id)
Set parameters for the various test cases.
double Re
Reynolds number (default assignment for FSI1 test case)
bool Ignore_fluid_loading
Ignore fluid (default assignment for FSI1 test case)
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
double St
Strouhal number (default assignment for FSI1 test case)
double Centre_y
y position of centre of cylinder
double Ramp_period
Period for ramping up in flux.
int main(int argc, char *argv[])
Driver.