64 #include "navier_stokes.h" 66 #include "constitutive.h" 70 #include "meshes/triangle_mesh.h" 73 using namespace oomph;
111 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
124 void doc_solution(DocInfo& doc_info);
130 this->delete_lagrange_multiplier_elements();
131 this->delete_fsi_traction_elements();
134 this->rebuild_global_mesh();
143 Fluid_mesh_pt->set_lagrangian_nodal_coordinates();
149 unsigned num_nod= Solid_mesh_pt->nboundary_node(ibound);
150 for (
unsigned inod=0;inod<num_nod;inod++)
154 SolidNode* nod_pt=Solid_mesh_pt->boundary_node_pt(ibound,inod);
157 for (
unsigned i=0;i<2;i++)
159 nod_pt->pin_position(i);
164 unsigned n_element = Solid_mesh_pt->nelement();
165 for(
unsigned i=0;i<n_element;i++)
168 SOLID_ELEMENT *el_pt =
169 dynamic_cast<SOLID_ELEMENT*
>(Solid_mesh_pt->element_pt(i));
172 el_pt->constitutive_law_pt() =
182 unsigned nbound=Fluid_mesh_pt->nboundary();
183 for(
unsigned ibound=0;ibound<nbound;ibound++)
185 unsigned num_nod=Fluid_mesh_pt->nboundary_node(ibound);
186 for (
unsigned inod=0;inod<num_nod;inod++)
192 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->pin(0);
194 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
200 for(
unsigned i=0;i<2;i++)
203 SolidNode* nod_pt=Fluid_mesh_pt->boundary_node_pt(ibound,inod);
204 nod_pt->pin_position(i);
212 n_element = Fluid_mesh_pt->nelement();
213 for(
unsigned e=0;e<n_element;e++)
216 FLUID_ELEMENT* el_pt =
217 dynamic_cast<FLUID_ELEMENT*
>(Fluid_mesh_pt->element_pt(e));
223 el_pt->constitutive_law_pt() =
230 const unsigned n_boundary = Fluid_mesh_pt->nboundary();
231 for (
unsigned ibound=0;ibound<n_boundary;ibound++)
233 const unsigned num_nod= Fluid_mesh_pt->nboundary_node(ibound);
234 for (
unsigned inod=0;inod<num_nod;inod++)
239 double y=Fluid_mesh_pt->boundary_node_pt(ibound,inod)->x(1);
240 double veloc = y*(1.0-y);
241 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,veloc);
242 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
247 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,0.0);
248 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
254 this->create_fsi_traction_elements();
255 this->create_lagrange_multiplier_elements();
258 this->rebuild_global_mesh();
266 for(
unsigned b=0;b<3;b++)
268 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
269 (
this,b,Fluid_mesh_pt,Traction_mesh_pt[b]);
278 double strain_energy = this->get_solid_strain_energy();
279 double dissipation = this->get_fluid_dissipation();
282 " " << dissipation <<
" " << strain_energy << std::endl;
292 for(
unsigned b=0;b<3;++b)
295 const unsigned n_element = Solid_mesh_pt->nboundary_element(b);
298 for(
unsigned e=0;e<n_element;e++)
301 SOLID_ELEMENT* bulk_elem_pt =
dynamic_cast<SOLID_ELEMENT*
>(
302 Solid_mesh_pt->boundary_element_pt(b,e));
305 int face_index = Solid_mesh_pt->face_index_at_boundary(b,e);
308 FSISolidTractionElement<SOLID_ELEMENT,2>* el_pt=
309 new FSISolidTractionElement<SOLID_ELEMENT,2>(bulk_elem_pt,face_index);
312 Traction_mesh_pt[b]->add_element_pt(el_pt);
315 el_pt->set_boundary_number_in_bulk_mesh(b);
327 for(
unsigned b=0;b<3;++b)
329 const unsigned n_element = Traction_mesh_pt[b]->nelement();
331 for(
unsigned e=0;e<n_element;e++)
333 delete Traction_mesh_pt[b]->element_pt(e);
336 Traction_mesh_pt[b]->flush_element_and_node_storage();
338 delete Solid_fsi_boundary_pt[b]; Solid_fsi_boundary_pt[b] = 0;
347 for(
unsigned b=0;b<3;b++)
350 Solid_fsi_boundary_pt[b] =
new MeshAsGeomObject(Traction_mesh_pt[b]);
353 unsigned n_element = Fluid_mesh_pt->nboundary_element(b);
356 for(
unsigned e=0;e<n_element;e++)
359 FLUID_ELEMENT* bulk_elem_pt =
dynamic_cast<FLUID_ELEMENT*
>(
360 Fluid_mesh_pt->boundary_element_pt(b,e));
363 int face_index = Fluid_mesh_pt->face_index_at_boundary(b,e);
366 ImposeDisplacementByLagrangeMultiplierElement<FLUID_ELEMENT>* el_pt =
367 new ImposeDisplacementByLagrangeMultiplierElement<FLUID_ELEMENT>(
368 bulk_elem_pt,face_index);
371 Lagrange_multiplier_mesh_pt[b]->add_element_pt(el_pt);
376 el_pt->set_boundary_shape_geom_object_pt(Solid_fsi_boundary_pt[b],b);
379 unsigned nnod=el_pt->nnode();
380 for (
unsigned j=0;j<nnod;j++)
382 Node* nod_pt = el_pt->node_pt(j);
386 unsigned n_bulk_value=el_pt->nbulk_value(j);
389 unsigned nval=nod_pt->nvalue();
391 if(nval > n_bulk_value + 2)
393 for (
unsigned j=n_bulk_value+2;j<nval;j++)
401 if((nod_pt->is_on_boundary(7)) || (nod_pt->is_on_boundary(3)))
403 for(
unsigned j=n_bulk_value;j<nval;j++)
419 for(
unsigned b=0;b<3;++b)
421 const unsigned n_element = Lagrange_multiplier_mesh_pt[b]->nelement();
423 for(
unsigned e=0;e<n_element;e++)
425 delete Lagrange_multiplier_mesh_pt[b]->element_pt(e);
428 Lagrange_multiplier_mesh_pt[b]->flush_element_and_node_storage();
437 double strain_energy=0.0;
438 const unsigned n_element = Solid_mesh_pt->nelement();
439 for(
unsigned e=0;e<n_element;e++)
442 SOLID_ELEMENT *el_pt =
443 dynamic_cast<SOLID_ELEMENT*
>(Solid_mesh_pt->element_pt(e));
445 double pot_en, kin_en;
446 el_pt->get_energy(pot_en,kin_en);
447 strain_energy += pot_en;
449 return strain_energy;
455 double dissipation=0.0;
456 const unsigned n_element = Fluid_mesh_pt->nelement();
457 for(
unsigned e=0;e<n_element;e++)
460 FLUID_ELEMENT *el_pt =
461 dynamic_cast<FLUID_ELEMENT*
>(Fluid_mesh_pt->element_pt(e));
463 dissipation += el_pt->dissipation();
499 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
504 double x_inlet = 0.0;
505 double channel_height = 1.0;
506 double channel_length = 4.0;
507 double x_leaflet = 1.0;
508 double leaflet_width = 0.2;
509 double leaflet_height = 0.5;
518 Vector<TriangleMeshCurveSection*> solid_boundary_segment_pt(4);
521 Vector<Vector<double> > bound_seg(2);
522 for(
unsigned i=0;i<2;i++) {bound_seg[i].resize(2);}
525 bound_seg[0][0]=x_leaflet - 0.5*leaflet_width;
527 bound_seg[1][0]=x_leaflet - 0.5*leaflet_width;
528 bound_seg[1][1]=leaflet_height;
531 unsigned bound_id = 0;
534 solid_boundary_segment_pt[0] =
new TriangleMeshPolyLine(bound_seg,bound_id);
537 bound_seg[0][0]=x_leaflet - 0.5*leaflet_width;
538 bound_seg[0][1]=leaflet_height;
539 bound_seg[1][0]=x_leaflet + 0.5*leaflet_width;
540 bound_seg[1][1]=leaflet_height;
546 solid_boundary_segment_pt[1] =
new TriangleMeshPolyLine(bound_seg,bound_id);
549 bound_seg[0][0]=x_leaflet + 0.5*leaflet_width;
550 bound_seg[0][1]=leaflet_height;
551 bound_seg[1][0]=x_leaflet + 0.5*leaflet_width;
558 solid_boundary_segment_pt[2] =
new TriangleMeshPolyLine(bound_seg,bound_id);
561 bound_seg[0][0]=x_leaflet + 0.5*leaflet_width;
563 bound_seg[1][0]=x_leaflet - 0.5*leaflet_width;
570 solid_boundary_segment_pt[3] =
new TriangleMeshPolyLine(bound_seg,bound_id);
573 Solid_outer_boundary_polyline_pt =
574 new TriangleMeshPolygon(solid_boundary_segment_pt);
583 double uniform_element_area= leaflet_width*leaflet_height/20.0;
585 TriangleMeshClosedCurve* solid_closed_curve_pt=
586 Solid_outer_boundary_polyline_pt;
590 TriangleMeshParameters triangle_mesh_parameters_solid(
591 solid_closed_curve_pt);
594 triangle_mesh_parameters_solid.element_area() =
595 uniform_element_area;
599 new RefineableSolidTriangleMesh<SOLID_ELEMENT>(
600 triangle_mesh_parameters_solid);
603 Z2ErrorEstimator* error_estimator_pt=
new Z2ErrorEstimator;
604 Solid_mesh_pt->spatial_error_estimator_pt()=error_estimator_pt;
607 Solid_mesh_pt->max_permitted_error()=0.0001;
608 Solid_mesh_pt->min_permitted_error()=0.001;
609 Solid_mesh_pt->max_element_size()=0.2;
610 Solid_mesh_pt->min_element_size()=0.001;
613 this->Solid_mesh_pt->output_boundaries(
"solid_boundaries.dat");
614 this->Solid_mesh_pt->output(
"solid_mesh.dat");
618 unsigned num_nod= Solid_mesh_pt->nboundary_node(ibound);
619 for (
unsigned inod=0;inod<num_nod;inod++)
623 SolidNode* nod_pt=Solid_mesh_pt->boundary_node_pt(ibound,inod);
626 for (
unsigned i=0;i<2;i++)
628 nod_pt->pin_position(i);
633 unsigned n_element = Solid_mesh_pt->nelement();
634 for(
unsigned i=0;i<n_element;i++)
637 SOLID_ELEMENT *el_pt =
638 dynamic_cast<SOLID_ELEMENT*
>(Solid_mesh_pt->element_pt(i));
641 el_pt->constitutive_law_pt() =
653 Vector<TriangleMeshCurveSection*> fluid_boundary_segment_pt(8);
656 for(
unsigned b=0;b<3;b++)
658 fluid_boundary_segment_pt[b] = solid_boundary_segment_pt[b];
663 bound_seg[0][0]=x_leaflet + 0.5*leaflet_width;
665 bound_seg[1][0]=x_inlet + channel_length;
672 fluid_boundary_segment_pt[3] =
new TriangleMeshPolyLine(bound_seg,bound_id);
675 bound_seg[0][0]=x_inlet + channel_length;
677 bound_seg[1][0]=x_inlet + channel_length;
678 bound_seg[1][1]=channel_height;
684 fluid_boundary_segment_pt[4] =
new TriangleMeshPolyLine(bound_seg,bound_id);
687 bound_seg[0][0]=x_inlet + channel_length;
688 bound_seg[0][1]=channel_height;
689 bound_seg[1][0]=x_inlet;
690 bound_seg[1][1]=channel_height;
696 fluid_boundary_segment_pt[5] =
new TriangleMeshPolyLine(bound_seg,bound_id);
699 bound_seg[0][0]=x_inlet;
700 bound_seg[0][1]=channel_height;
701 bound_seg[1][0]=x_inlet;
708 fluid_boundary_segment_pt[6] =
new TriangleMeshPolyLine(bound_seg,bound_id);
711 bound_seg[0][0]=x_inlet;
713 bound_seg[1][0]=x_leaflet - 0.5*leaflet_width;
720 fluid_boundary_segment_pt[7] =
new TriangleMeshPolyLine(bound_seg,bound_id);
723 Fluid_outer_boundary_polyline_pt =
724 new TriangleMeshPolygon(fluid_boundary_segment_pt);
733 uniform_element_area= channel_length*channel_height/40.0;;
735 TriangleMeshClosedCurve* fluid_closed_curve_pt=
736 Fluid_outer_boundary_polyline_pt;
740 TriangleMeshParameters triangle_mesh_parameters_fluid(
741 fluid_closed_curve_pt);
744 triangle_mesh_parameters_fluid.element_area() =
745 uniform_element_area;
749 new RefineableSolidTriangleMesh<FLUID_ELEMENT>(
750 triangle_mesh_parameters_fluid);
753 Z2ErrorEstimator* fluid_error_estimator_pt=
new Z2ErrorEstimator;
754 Fluid_mesh_pt->spatial_error_estimator_pt()=fluid_error_estimator_pt;
757 Fluid_mesh_pt->max_permitted_error()=0.0001;
758 Fluid_mesh_pt->min_permitted_error()=0.001;
759 Fluid_mesh_pt->max_element_size()=0.2;
760 Fluid_mesh_pt->min_element_size()=0.001;
763 this->Fluid_mesh_pt->output_boundaries(
"fluid_boundaries.dat");
764 this->Fluid_mesh_pt->output(
"fluid_mesh.dat");
771 unsigned nbound=Fluid_mesh_pt->nboundary();
772 for(
unsigned ibound=0;ibound<nbound;ibound++)
774 unsigned num_nod=Fluid_mesh_pt->nboundary_node(ibound);
775 for (
unsigned inod=0;inod<num_nod;inod++)
781 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->pin(0);
783 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
789 for(
unsigned i=0;i<2;i++)
792 SolidNode* nod_pt=Fluid_mesh_pt->boundary_node_pt(ibound,inod);
793 nod_pt->pin_position(i);
801 n_element = Fluid_mesh_pt->nelement();
802 for(
unsigned e=0;e<n_element;e++)
805 FLUID_ELEMENT* el_pt =
806 dynamic_cast<FLUID_ELEMENT*
>(Fluid_mesh_pt->element_pt(e));
812 el_pt->constitutive_law_pt() =
819 const unsigned n_boundary = Fluid_mesh_pt->nboundary();
820 for (
unsigned ibound=0;ibound<n_boundary;ibound++)
822 const unsigned num_nod= Fluid_mesh_pt->nboundary_node(ibound);
823 for (
unsigned inod=0;inod<num_nod;inod++)
828 double y=Fluid_mesh_pt->boundary_node_pt(ibound,inod)->x(1);
829 double veloc = y*(1.0-y);
830 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,veloc);
831 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
836 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,0.0);
837 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
847 Traction_mesh_pt.resize(3);
848 for(
unsigned m=0;m<3;m++) {Traction_mesh_pt[m] =
new SolidMesh;}
849 this->create_fsi_traction_elements();
852 Lagrange_multiplier_mesh_pt.resize(3);
853 Solid_fsi_boundary_pt.resize(3);
854 for(
unsigned m=0;m<3;m++) {Lagrange_multiplier_mesh_pt[m] =
new SolidMesh;}
855 this->create_lagrange_multiplier_elements();
858 add_sub_mesh(Fluid_mesh_pt);
859 add_sub_mesh(Solid_mesh_pt);
860 for(
unsigned m=0;m<3;m++)
862 add_sub_mesh(Traction_mesh_pt[m]);
863 add_sub_mesh(Lagrange_multiplier_mesh_pt[m]);
875 for(
unsigned b=0;b<3;b++)
877 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
878 (
this,b,Fluid_mesh_pt,Traction_mesh_pt[b]);
882 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
890 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
904 sprintf(filename,
"%s/solid_soln%i.dat",doc_info.directory().c_str(),
906 some_file.open(filename);
907 Solid_mesh_pt->output(some_file,npts);
911 sprintf(filename,
"%s/fluid_soln%i.dat",doc_info.directory().c_str(),
913 some_file.open(filename);
914 Fluid_mesh_pt->output(some_file,npts);
926 int main(
int argc,
char **argv)
930 CommandLineArgs::setup(argc,argv);
936 CommandLineArgs::specify_command_line_flag(
"--validation");
939 CommandLineArgs::parse_and_assign();
942 CommandLineArgs::doc_specified_flags();
947 doc_info.set_directory(
"RESLT");
950 std::ofstream trace(
"RESLT/trace.dat");
962 ProjectableTaylorHoodElement<
963 PseudoSolidNodeUpdateElement<TTaylorHoodElement<2>, TPVDElement<2,3> > >,
964 ProjectablePVDElement<TPVDElement<2,3> > > problem;
971 problem.newton_solve();
974 problem.doc_solution(doc_info);
979 problem.output_strain_and_dissipation(trace);
982 unsigned n_step = 10;
984 if (CommandLineArgs::command_line_flag_has_been_set(
"--validation"))
990 for(
unsigned i=0;i<n_step;i++)
993 problem.newton_solve(1);
997 problem.Fluid_mesh_pt->set_lagrangian_nodal_coordinates();
999 problem.doc_solution(doc_info);
1000 doc_info.number()++;
1004 problem.output_strain_and_dissipation(trace);
Vector< SolidMesh * > Lagrange_multiplier_mesh_pt
Vector of pointers to mesh of Lagrange multiplier elements.
void output_strain_and_dissipation(std::ostream &trace)
UnstructuredFSIProblem()
Constructor:
Vector< MeshAsGeomObject * > Solid_fsi_boundary_pt
double get_fluid_dissipation()
Calculate the fluid dissipation.
int main(int argc, char **argv)
Demonstrate how to solve an unstructured solid problem.
Vector< SolidMesh * > Traction_mesh_pt
Vectors of pointers to mesh of traction elements.
void create_fsi_traction_elements()
Create the traction element.
~UnstructuredFSIProblem()
Destructor (empty)
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
void doc_solution(DocInfo &doc_info)
Doc the solution.
Unstructured FSI problem.
double Re
Reynolds number.
TriangleMeshPolygon * Fluid_outer_boundary_polyline_pt
Triangle mesh polygon for outer boundary.
void actions_after_adapt()
Actions after adapt.
TriangleMeshPolygon * Solid_outer_boundary_polyline_pt
Triangle mesh polygon for outer boundary.
ConstitutiveLaw * Mesh_constitutive_law_pt
Pointer to constitutive law for the mesh.
void actions_before_adapt()
Actions before adapt.
void delete_lagrange_multiplier_elements()
Delete the traction elements.
RefineableSolidTriangleMesh< FLUID_ELEMENT > * Fluid_mesh_pt
Bulk fluid mesh.
double Mesh_Nu
Mesh poisson ratio.
void delete_fsi_traction_elements()
Delete the traction elements.
void create_lagrange_multiplier_elements()
RefineableSolidTriangleMesh< SOLID_ELEMENT > * Solid_mesh_pt
Bulk solid mesh.
double Nu
Poisson's ratio.
double get_solid_strain_energy()
Calculate the strain energy of the solid.