60 #include "navier_stokes.h"
62 #include "constitutive.h"
66 #include "meshes/triangle_mesh.h"
69 using namespace oomph;
107 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
120 void doc_solution(DocInfo& doc_info);
126 this->delete_lagrange_multiplier_elements();
127 this->delete_fsi_traction_elements();
130 this->rebuild_global_mesh();
139 Fluid_mesh_pt->set_lagrangian_nodal_coordinates();
145 unsigned num_nod= Solid_mesh_pt->nboundary_node(ibound);
146 for (
unsigned inod=0;inod<num_nod;inod++)
150 SolidNode* nod_pt=Solid_mesh_pt->boundary_node_pt(ibound,inod);
153 for (
unsigned i=0;i<2;i++)
155 nod_pt->pin_position(i);
160 unsigned n_element = Solid_mesh_pt->nelement();
161 for(
unsigned i=0;i<n_element;i++)
164 SOLID_ELEMENT *el_pt =
165 dynamic_cast<SOLID_ELEMENT*
>(Solid_mesh_pt->element_pt(i));
168 el_pt->constitutive_law_pt() =
178 unsigned nbound=Fluid_mesh_pt->nboundary();
179 for(
unsigned ibound=0;ibound<nbound;ibound++)
181 unsigned num_nod=Fluid_mesh_pt->nboundary_node(ibound);
182 for (
unsigned inod=0;inod<num_nod;inod++)
188 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->pin(0);
190 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
196 for(
unsigned i=0;i<2;i++)
199 SolidNode* nod_pt=Fluid_mesh_pt->boundary_node_pt(ibound,inod);
200 nod_pt->pin_position(i);
208 n_element = Fluid_mesh_pt->nelement();
209 for(
unsigned e=0;e<n_element;e++)
212 FLUID_ELEMENT* el_pt =
213 dynamic_cast<FLUID_ELEMENT*
>(Fluid_mesh_pt->element_pt(e));
219 el_pt->constitutive_law_pt() =
226 const unsigned n_boundary = Fluid_mesh_pt->nboundary();
227 for (
unsigned ibound=0;ibound<n_boundary;ibound++)
229 const unsigned num_nod= Fluid_mesh_pt->nboundary_node(ibound);
230 for (
unsigned inod=0;inod<num_nod;inod++)
235 double y=Fluid_mesh_pt->boundary_node_pt(ibound,inod)->x(1);
236 double veloc = y*(1.0-y);
237 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,veloc);
238 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
243 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,0.0);
244 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
250 this->create_fsi_traction_elements();
251 this->create_lagrange_multiplier_elements();
254 this->rebuild_global_mesh();
262 for(
unsigned b=0;b<3;b++)
264 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
265 (
this,b,Fluid_mesh_pt,Traction_mesh_pt[b]);
274 double strain_energy = this->get_solid_strain_energy();
275 double dissipation = this->get_fluid_dissipation();
278 " " << dissipation <<
" " << strain_energy << std::endl;
288 for(
unsigned b=0;b<3;++b)
291 const unsigned n_element = Solid_mesh_pt->nboundary_element(b);
294 for(
unsigned e=0;e<n_element;e++)
297 SOLID_ELEMENT* bulk_elem_pt =
dynamic_cast<SOLID_ELEMENT*
>(
298 Solid_mesh_pt->boundary_element_pt(b,e));
301 int face_index = Solid_mesh_pt->face_index_at_boundary(b,e);
304 FSISolidTractionElement<SOLID_ELEMENT,2>* el_pt=
305 new FSISolidTractionElement<SOLID_ELEMENT,2>(bulk_elem_pt,face_index);
308 Traction_mesh_pt[b]->add_element_pt(el_pt);
311 el_pt->set_boundary_number_in_bulk_mesh(b);
323 for(
unsigned b=0;b<3;++b)
325 const unsigned n_element = Traction_mesh_pt[b]->nelement();
327 for(
unsigned e=0;e<n_element;e++)
329 delete Traction_mesh_pt[b]->element_pt(e);
332 Traction_mesh_pt[b]->flush_element_and_node_storage();
334 delete Solid_fsi_boundary_pt[b]; Solid_fsi_boundary_pt[b] = 0;
343 for(
unsigned b=0;b<3;b++)
346 Solid_fsi_boundary_pt[b] =
new MeshAsGeomObject(Traction_mesh_pt[b]);
349 unsigned n_element = Fluid_mesh_pt->nboundary_element(b);
352 for(
unsigned e=0;e<n_element;e++)
355 FLUID_ELEMENT* bulk_elem_pt =
dynamic_cast<FLUID_ELEMENT*
>(
356 Fluid_mesh_pt->boundary_element_pt(b,e));
359 int face_index = Fluid_mesh_pt->face_index_at_boundary(b,e);
362 ImposeDisplacementByLagrangeMultiplierElement<FLUID_ELEMENT>* el_pt =
363 new ImposeDisplacementByLagrangeMultiplierElement<FLUID_ELEMENT>(
364 bulk_elem_pt,face_index);
367 Lagrange_multiplier_mesh_pt[b]->add_element_pt(el_pt);
372 el_pt->set_boundary_shape_geom_object_pt(Solid_fsi_boundary_pt[b],b);
375 unsigned nnod=el_pt->nnode();
376 for (
unsigned j=0;j<nnod;j++)
378 Node* nod_pt = el_pt->node_pt(j);
382 unsigned n_bulk_value=el_pt->nbulk_value(j);
385 unsigned nval=nod_pt->nvalue();
387 if(nval > n_bulk_value + 2)
389 for (
unsigned j=n_bulk_value+2;j<nval;j++)
397 if((nod_pt->is_on_boundary(7)) || (nod_pt->is_on_boundary(3)))
399 for(
unsigned j=n_bulk_value;j<nval;j++)
415 for(
unsigned b=0;b<3;++b)
417 const unsigned n_element = Lagrange_multiplier_mesh_pt[b]->nelement();
419 for(
unsigned e=0;e<n_element;e++)
421 delete Lagrange_multiplier_mesh_pt[b]->element_pt(e);
424 Lagrange_multiplier_mesh_pt[b]->flush_element_and_node_storage();
433 double strain_energy=0.0;
434 const unsigned n_element = Solid_mesh_pt->nelement();
435 for(
unsigned e=0;e<n_element;e++)
438 SOLID_ELEMENT *el_pt =
439 dynamic_cast<SOLID_ELEMENT*
>(Solid_mesh_pt->element_pt(e));
441 double pot_en, kin_en;
442 el_pt->get_energy(pot_en,kin_en);
443 strain_energy += pot_en;
445 return strain_energy;
451 double dissipation=0.0;
452 const unsigned n_element = Fluid_mesh_pt->nelement();
453 for(
unsigned e=0;e<n_element;e++)
456 FLUID_ELEMENT *el_pt =
457 dynamic_cast<FLUID_ELEMENT*
>(Fluid_mesh_pt->element_pt(e));
459 dissipation += el_pt->dissipation();
495 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
500 double x_inlet = 0.0;
501 double channel_height = 1.0;
502 double channel_length = 4.0;
503 double x_leaflet = 1.0;
504 double leaflet_width = 0.2;
505 double leaflet_height = 0.5;
514 Vector<TriangleMeshCurveSection*> solid_boundary_segment_pt(4);
517 Vector<Vector<double> > bound_seg(2);
518 for(
unsigned i=0;i<2;i++) {bound_seg[i].resize(2);}
521 bound_seg[0][0]=x_leaflet - 0.5*leaflet_width;
523 bound_seg[1][0]=x_leaflet - 0.5*leaflet_width;
524 bound_seg[1][1]=leaflet_height;
527 unsigned bound_id = 0;
530 solid_boundary_segment_pt[0] =
new TriangleMeshPolyLine(bound_seg,bound_id);
533 bound_seg[0][0]=x_leaflet - 0.5*leaflet_width;
534 bound_seg[0][1]=leaflet_height;
535 bound_seg[1][0]=x_leaflet + 0.5*leaflet_width;
536 bound_seg[1][1]=leaflet_height;
542 solid_boundary_segment_pt[1] =
new TriangleMeshPolyLine(bound_seg,bound_id);
545 bound_seg[0][0]=x_leaflet + 0.5*leaflet_width;
546 bound_seg[0][1]=leaflet_height;
547 bound_seg[1][0]=x_leaflet + 0.5*leaflet_width;
554 solid_boundary_segment_pt[2] =
new TriangleMeshPolyLine(bound_seg,bound_id);
557 bound_seg[0][0]=x_leaflet + 0.5*leaflet_width;
559 bound_seg[1][0]=x_leaflet - 0.5*leaflet_width;
566 solid_boundary_segment_pt[3] =
new TriangleMeshPolyLine(bound_seg,bound_id);
569 Solid_outer_boundary_polyline_pt =
570 new TriangleMeshPolygon(solid_boundary_segment_pt);
579 double uniform_element_area= leaflet_width*leaflet_height/20.0;
581 TriangleMeshClosedCurve* solid_closed_curve_pt=
582 Solid_outer_boundary_polyline_pt;
586 TriangleMeshParameters triangle_mesh_parameters_solid(
587 solid_closed_curve_pt);
590 triangle_mesh_parameters_solid.element_area() =
591 uniform_element_area;
595 new RefineableSolidTriangleMesh<SOLID_ELEMENT>(
596 triangle_mesh_parameters_solid);
599 Z2ErrorEstimator* error_estimator_pt=
new Z2ErrorEstimator;
600 Solid_mesh_pt->spatial_error_estimator_pt()=error_estimator_pt;
603 Solid_mesh_pt->max_permitted_error()=0.0001;
604 Solid_mesh_pt->min_permitted_error()=0.001;
605 Solid_mesh_pt->max_element_size()=0.2;
606 Solid_mesh_pt->min_element_size()=0.001;
609 this->Solid_mesh_pt->output_boundaries(
"solid_boundaries.dat");
610 this->Solid_mesh_pt->output(
"solid_mesh.dat");
614 unsigned num_nod= Solid_mesh_pt->nboundary_node(ibound);
615 for (
unsigned inod=0;inod<num_nod;inod++)
619 SolidNode* nod_pt=Solid_mesh_pt->boundary_node_pt(ibound,inod);
622 for (
unsigned i=0;i<2;i++)
624 nod_pt->pin_position(i);
629 unsigned n_element = Solid_mesh_pt->nelement();
630 for(
unsigned i=0;i<n_element;i++)
633 SOLID_ELEMENT *el_pt =
634 dynamic_cast<SOLID_ELEMENT*
>(Solid_mesh_pt->element_pt(i));
637 el_pt->constitutive_law_pt() =
649 Vector<TriangleMeshCurveSection*> fluid_boundary_segment_pt(8);
652 for(
unsigned b=0;b<3;b++)
654 fluid_boundary_segment_pt[b] = solid_boundary_segment_pt[b];
659 bound_seg[0][0]=x_leaflet + 0.5*leaflet_width;
661 bound_seg[1][0]=x_inlet + channel_length;
668 fluid_boundary_segment_pt[3] =
new TriangleMeshPolyLine(bound_seg,bound_id);
671 bound_seg[0][0]=x_inlet + channel_length;
673 bound_seg[1][0]=x_inlet + channel_length;
674 bound_seg[1][1]=channel_height;
680 fluid_boundary_segment_pt[4] =
new TriangleMeshPolyLine(bound_seg,bound_id);
683 bound_seg[0][0]=x_inlet + channel_length;
684 bound_seg[0][1]=channel_height;
685 bound_seg[1][0]=x_inlet;
686 bound_seg[1][1]=channel_height;
692 fluid_boundary_segment_pt[5] =
new TriangleMeshPolyLine(bound_seg,bound_id);
695 bound_seg[0][0]=x_inlet;
696 bound_seg[0][1]=channel_height;
697 bound_seg[1][0]=x_inlet;
704 fluid_boundary_segment_pt[6] =
new TriangleMeshPolyLine(bound_seg,bound_id);
707 bound_seg[0][0]=x_inlet;
709 bound_seg[1][0]=x_leaflet - 0.5*leaflet_width;
716 fluid_boundary_segment_pt[7] =
new TriangleMeshPolyLine(bound_seg,bound_id);
719 Fluid_outer_boundary_polyline_pt =
720 new TriangleMeshPolygon(fluid_boundary_segment_pt);
729 uniform_element_area= channel_length*channel_height/40.0;;
731 TriangleMeshClosedCurve* fluid_closed_curve_pt=
732 Fluid_outer_boundary_polyline_pt;
736 TriangleMeshParameters triangle_mesh_parameters_fluid(
737 fluid_closed_curve_pt);
740 triangle_mesh_parameters_fluid.element_area() =
741 uniform_element_area;
745 new RefineableSolidTriangleMesh<FLUID_ELEMENT>(
746 triangle_mesh_parameters_fluid);
749 Z2ErrorEstimator* fluid_error_estimator_pt=
new Z2ErrorEstimator;
750 Fluid_mesh_pt->spatial_error_estimator_pt()=fluid_error_estimator_pt;
753 Fluid_mesh_pt->max_permitted_error()=0.0001;
754 Fluid_mesh_pt->min_permitted_error()=0.001;
755 Fluid_mesh_pt->max_element_size()=0.2;
756 Fluid_mesh_pt->min_element_size()=0.001;
759 this->Fluid_mesh_pt->output_boundaries(
"fluid_boundaries.dat");
760 this->Fluid_mesh_pt->output(
"fluid_mesh.dat");
767 unsigned nbound=Fluid_mesh_pt->nboundary();
768 for(
unsigned ibound=0;ibound<nbound;ibound++)
770 unsigned num_nod=Fluid_mesh_pt->nboundary_node(ibound);
771 for (
unsigned inod=0;inod<num_nod;inod++)
777 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->pin(0);
779 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
785 for(
unsigned i=0;i<2;i++)
788 SolidNode* nod_pt=Fluid_mesh_pt->boundary_node_pt(ibound,inod);
789 nod_pt->pin_position(i);
797 n_element = Fluid_mesh_pt->nelement();
798 for(
unsigned e=0;e<n_element;e++)
801 FLUID_ELEMENT* el_pt =
802 dynamic_cast<FLUID_ELEMENT*
>(Fluid_mesh_pt->element_pt(e));
808 el_pt->constitutive_law_pt() =
815 const unsigned n_boundary = Fluid_mesh_pt->nboundary();
816 for (
unsigned ibound=0;ibound<n_boundary;ibound++)
818 const unsigned num_nod= Fluid_mesh_pt->nboundary_node(ibound);
819 for (
unsigned inod=0;inod<num_nod;inod++)
824 double y=Fluid_mesh_pt->boundary_node_pt(ibound,inod)->x(1);
825 double veloc = y*(1.0-y);
826 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,veloc);
827 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
832 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(0,0.0);
833 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->set_value(1,0.0);
843 Traction_mesh_pt.resize(3);
844 for(
unsigned m=0;m<3;m++) {Traction_mesh_pt[m] =
new SolidMesh;}
845 this->create_fsi_traction_elements();
848 Lagrange_multiplier_mesh_pt.resize(3);
849 Solid_fsi_boundary_pt.resize(3);
850 for(
unsigned m=0;m<3;m++) {Lagrange_multiplier_mesh_pt[m] =
new SolidMesh;}
851 this->create_lagrange_multiplier_elements();
854 add_sub_mesh(Fluid_mesh_pt);
855 add_sub_mesh(Solid_mesh_pt);
856 for(
unsigned m=0;m<3;m++)
858 add_sub_mesh(Traction_mesh_pt[m]);
859 add_sub_mesh(Lagrange_multiplier_mesh_pt[m]);
871 for(
unsigned b=0;b<3;b++)
873 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
874 (
this,b,Fluid_mesh_pt,Traction_mesh_pt[b]);
878 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
886 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
900 sprintf(filename,
"%s/solid_soln%i.dat",doc_info.directory().c_str(),
902 some_file.open(filename);
903 Solid_mesh_pt->output(some_file,npts);
907 sprintf(filename,
"%s/fluid_soln%i.dat",doc_info.directory().c_str(),
909 some_file.open(filename);
910 Fluid_mesh_pt->output(some_file,npts);
922 int main(
int argc,
char **argv)
926 CommandLineArgs::setup(argc,argv);
932 CommandLineArgs::specify_command_line_flag(
"--validation");
935 CommandLineArgs::parse_and_assign();
938 CommandLineArgs::doc_specified_flags();
943 doc_info.set_directory(
"RESLT");
946 std::ofstream trace(
"RESLT/trace.dat");
958 ProjectableTaylorHoodElement<
959 PseudoSolidNodeUpdateElement<TTaylorHoodElement<2>, TPVDElement<2,3> > >,
960 ProjectablePVDElement<TPVDElement<2,3> > > problem;
967 problem.newton_solve();
970 problem.doc_solution(doc_info);
975 problem.output_strain_and_dissipation(trace);
978 unsigned n_step = 10;
980 if (CommandLineArgs::command_line_flag_has_been_set(
"--validation"))
986 for(
unsigned i=0;i<n_step;i++)
989 problem.newton_solve(1);
993 problem.Fluid_mesh_pt->set_lagrangian_nodal_coordinates();
995 problem.doc_solution(doc_info);
1000 problem.output_strain_and_dissipation(trace);
Unstructured FSI problem.
void doc_solution(DocInfo &doc_info)
Doc the solution.
Vector< MeshAsGeomObject * > Solid_fsi_boundary_pt
Vector< SolidMesh * > Lagrange_multiplier_mesh_pt
Vector of pointers to mesh of Lagrange multiplier elements.
RefineableSolidTriangleMesh< SOLID_ELEMENT > * Solid_mesh_pt
Bulk solid mesh.
void actions_before_adapt()
Actions before adapt.
double get_solid_strain_energy()
Calculate the strain energy of the solid.
UnstructuredFSIProblem()
Constructor:
void create_lagrange_multiplier_elements()
Create the multipliers that add lagrange multipliers to the fluid elements that apply the solid displ...
void create_fsi_traction_elements()
Create the traction element.
void delete_fsi_traction_elements()
Delete the traction elements.
RefineableSolidTriangleMesh< FLUID_ELEMENT > * Fluid_mesh_pt
Bulk fluid mesh.
~UnstructuredFSIProblem()
Destructor (empty)
void output_strain_and_dissipation(std::ostream &trace)
Output function to compute the strain energy in the solid and the dissipation in the fluid and write ...
Vector< SolidMesh * > Traction_mesh_pt
Vectors of pointers to mesh of traction elements.
void delete_lagrange_multiplier_elements()
Delete the traction elements.
TriangleMeshPolygon * Fluid_outer_boundary_polyline_pt
Triangle mesh polygon for outer boundary.
void actions_after_adapt()
Actions after adapt.
double get_fluid_dissipation()
Calculate the fluid dissipation.
TriangleMeshPolygon * Solid_outer_boundary_polyline_pt
Triangle mesh polygon for outer boundary.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
double Mesh_Nu
Mesh poisson ratio.
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
double Nu
Poisson's ratio.
ConstitutiveLaw * Mesh_constitutive_law_pt
Pointer to constitutive law for the mesh.
double Re
Reynolds number.
int main(int argc, char **argv)
Demonstrate how to solve an unstructured solid problem.