34 #include "navier_stokes.h" 36 #include "constitutive.h" 39 #include "meshes/triangle_mesh.h" 42 using namespace oomph;
60 const Vector<double> &xi,
79 dynamic_cast<BoundaryNodeBase*>(nod_pt)!=0)&&
82 ( (nod_pt->x(0)>1.6)&&(nod_pt->x(0)<4.75)&&
84 (nod_pt->x(1)>0.1125)&&(nod_pt->x(1)<2.8) ) ||
86 ( (nod_pt->x(1)<0.3)&&
88 ( ( (nod_pt->x(0)>3.0)&&(nod_pt->x(0)<3.1) ) ||
89 ( (nod_pt->x(0)<4.6)&&(nod_pt->x(0)>4.5) ) )
115 template<
class ELEMENT>
117 public virtual SolidMesh
124 const std::string& element_file_name,
125 const std::string& poly_file_name,
126 TimeStepper* time_stepper_pt=
127 &Mesh::Default_TimeStepper) :
128 TriangleMesh<ELEMENT>(node_file_name,element_file_name,
129 poly_file_name, time_stepper_pt)
132 set_lagrangian_nodal_coordinates();
137 unsigned n_node=this->nnode();
138 for (
unsigned j=0;j<n_node;j++)
140 Node* nod_pt=this->node_pt(j);
143 if (nod_pt->x(1)<0.15)
145 this->remove_boundary_node(0,nod_pt);
146 this->add_boundary_node(1,nod_pt);
152 this->remove_boundary_node(0,nod_pt);
153 this->add_boundary_node(2,nod_pt);
158 TriangleMesh<ELEMENT>::setup_boundary_element_info();
161 this->
template setup_boundary_coordinates<ELEMENT>(1);
162 this->
template setup_boundary_coordinates<ELEMENT>(2);
181 template<
class ELEMENT>
183 public virtual SolidMesh
190 const std::string& element_file_name,
191 const std::string& poly_file_name,
192 TimeStepper* time_stepper_pt=
193 &Mesh::Default_TimeStepper) :
194 TriangleMesh<ELEMENT>(node_file_name,element_file_name,
195 poly_file_name, time_stepper_pt)
198 set_lagrangian_nodal_coordinates();
201 this->set_nboundary(4);
203 unsigned n_node=this->nnode();
204 for (
unsigned j=0;j<n_node;j++)
206 Node* nod_pt=this->node_pt(j);
209 if (nod_pt->x(0)<0.226)
211 this->remove_boundary_node(0,nod_pt);
212 this->add_boundary_node(1,nod_pt);
215 if (nod_pt->x(1)<0.2) this->add_boundary_node(0,nod_pt);
216 if (nod_pt->x(1)>4.06) this->add_boundary_node(0,nod_pt);
220 if (nod_pt->x(0)>8.28)
222 this->remove_boundary_node(0,nod_pt);
223 this->add_boundary_node(2,nod_pt);
226 if (nod_pt->x(1)<0.2) this->add_boundary_node(0,nod_pt);
227 if (nod_pt->x(1)>4.06) this->add_boundary_node(0,nod_pt);
234 this->remove_boundary_node(0,nod_pt);
235 this->add_boundary_node(3,nod_pt);
238 if (nod_pt->x(1)<0.2) this->add_boundary_node(0,nod_pt);
241 TriangleMesh<ELEMENT>::setup_boundary_element_info();
250 ofstream some_file(
"RESLT/boundary_generation_test.dat");
253 this->
template setup_boundary_coordinates<ELEMENT>(1);
254 this->
template setup_boundary_coordinates<ELEMENT>(2);
255 this->
template setup_boundary_coordinates<ELEMENT>(3,some_file);
276 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
291 return Fluid_mesh_pt;
297 return Solid_mesh_pt;
301 void doc_solution(DocInfo& doc_info);
306 void create_fsi_traction_elements();
310 void create_lagrange_multiplier_elements();
313 void doc_solid_boundary_coordinates();
338 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
346 string fluid_node_file_name=
"fluid.fig.1.node";
347 string fluid_element_file_name=
"fluid.fig.1.ele";
348 string fluid_poly_file_name=
"fluid.fig.1.poly";
350 fluid_element_file_name,
351 fluid_poly_file_name);
354 std::ofstream pseudo_solid_bc_file(
"pinned_pseudo_solid_nodes.dat");
359 unsigned nbound=Fluid_mesh_pt->nboundary();
360 for(
unsigned ibound=0;ibound<nbound;ibound++)
362 unsigned num_nod=Fluid_mesh_pt->nboundary_node(ibound);
363 for (
unsigned inod=0;inod<num_nod;inod++)
369 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->pin(0);
371 Fluid_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
375 if ((ibound==0)||(ibound==1)||(ibound==2))
377 for(
unsigned i=0;i<2;i++)
380 SolidNode* nod_pt=Fluid_mesh_pt->boundary_node_pt(ibound,inod);
381 nod_pt->pin_position(i);
384 pseudo_solid_bc_file << nod_pt->x(i) <<
" ";
386 pseudo_solid_bc_file << std::endl;
392 pseudo_solid_bc_file.close();
396 unsigned n_element = Fluid_mesh_pt->nelement();
397 for(
unsigned e=0;e<n_element;e++)
400 FLUID_ELEMENT* el_pt =
401 dynamic_cast<FLUID_ELEMENT*
>(Fluid_mesh_pt->element_pt(e));
407 el_pt->constitutive_law_pt() =
418 double y_min=fluid_mesh_pt()->boundary_node_pt(ibound,0)->x(1);;
422 unsigned num_nod= fluid_mesh_pt()->nboundary_node(ibound);
423 for (
unsigned inod=1;inod<num_nod;inod++)
425 double y=fluid_mesh_pt()->boundary_node_pt(ibound,inod)->x(1);
435 double y_mid=0.5*(y_min+y_max);
438 const unsigned n_boundary = fluid_mesh_pt()->nboundary();
439 for (
unsigned ibound=0;ibound<n_boundary;ibound++)
441 const unsigned num_nod= fluid_mesh_pt()->nboundary_node(ibound);
442 for (
unsigned inod=0;inod<num_nod;inod++)
447 double y=fluid_mesh_pt()->boundary_node_pt(ibound,inod)->x(1);
448 double veloc=1.5/(y_max-y_min)*
449 (y-y_min)*(y_max-y)/((y_mid-y_min)*(y_max-y_mid));
450 fluid_mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,veloc);
451 fluid_mesh_pt()->boundary_node_pt(ibound,inod)->set_value(1,0.0);
456 fluid_mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,0.0);
457 fluid_mesh_pt()->boundary_node_pt(ibound,inod)->set_value(1,0.0);
467 string solid_node_file_name=
"solid.fig.1.node";
468 string solid_element_file_name=
"solid.fig.1.ele";
469 string solid_poly_file_name=
"solid.fig.1.poly";
471 solid_element_file_name,
472 solid_poly_file_name);
476 n_element = Solid_mesh_pt->nelement();
477 for(
unsigned i=0;i<n_element;i++)
480 SOLID_ELEMENT *el_pt =
481 dynamic_cast<SOLID_ELEMENT*
>(Solid_mesh_pt->element_pt(i));
484 el_pt->constitutive_law_pt() =
493 num_nod=Solid_mesh_pt->nboundary_node(ibound);
494 for (
unsigned inod=0;inod<num_nod;inod++)
496 Solid_mesh_pt->boundary_node_pt(ibound,inod)->pin_position(0);
497 Solid_mesh_pt->boundary_node_pt(ibound,inod)->pin_position(1);
505 Traction_mesh_pt=
new SolidMesh;
508 create_fsi_traction_elements();
515 Lagrange_multiplier_mesh_pt=
new SolidMesh;
516 create_lagrange_multiplier_elements();
523 add_sub_mesh(Fluid_mesh_pt);
524 add_sub_mesh(Solid_mesh_pt);
525 add_sub_mesh(Traction_mesh_pt);
526 add_sub_mesh(Lagrange_multiplier_mesh_pt);
538 Multi_domain_functions::Doc_boundary_coordinate_file.open(
539 "fluid_boundary_test.dat");
545 FSI_functions::setup_fluid_load_info_for_solid_elements<FLUID_ELEMENT,2>
546 (
this,3,Fluid_mesh_pt,Traction_mesh_pt);
549 Multi_domain_functions::Doc_boundary_coordinate_file.close();
552 doc_solid_boundary_coordinates();
555 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
565 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
571 std::ofstream the_file(
"solid_boundary_test.dat");
574 double zeta_min= 1.0e40;
575 double zeta_max=-1.0e40;
578 unsigned n_face_element = Traction_mesh_pt->nelement();
579 for(
unsigned e=0;e<n_face_element;e++)
582 FSISolidTractionElement<SOLID_ELEMENT,2>* el_pt=
583 dynamic_cast<FSISolidTractionElement<SOLID_ELEMENT,2>*
> 584 (Traction_mesh_pt->element_pt(e));
588 Vector<double> zeta(1);
591 the_file << el_pt->tecplot_zone_string(n_plot);
594 unsigned num_plot_points=el_pt->nplot_points(n_plot);
595 for (
unsigned iplot=0;iplot<num_plot_points;iplot++)
598 el_pt->get_s_plot(iplot,n_plot,s);
599 el_pt->interpolated_zeta(s,zeta);
600 el_pt->interpolated_x(s,x);
601 for (
unsigned i=0;i<2;i++)
603 the_file << x[i] <<
" ";
605 the_file << zeta[0] <<
" ";
608 if (zeta[0]<zeta_min) zeta_min=zeta[0];
609 if (zeta[0]>zeta_max) zeta_max=zeta[0];
611 the_file << std::endl;
620 the_file.open(
"fsi_geom_object.dat");
621 unsigned nplot=10000;
622 Vector<double> zeta(1);
624 for (
unsigned i=0;i<nplot;i++)
626 zeta[0]=zeta_min+(zeta_max-zeta_min)*
double(i)/double(nplot-1);
627 Solid_fsi_boundary_pt->position(zeta,r);
628 the_file << r[0] <<
" " << r[1] << std::endl;
640 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
648 unsigned n_element = solid_mesh_pt()->nboundary_element(b);
651 for(
unsigned e=0;e<n_element;e++)
654 SOLID_ELEMENT* bulk_elem_pt =
dynamic_cast<SOLID_ELEMENT*
>(
655 solid_mesh_pt()->boundary_element_pt(b,e));
658 int face_index = solid_mesh_pt()->face_index_at_boundary(b,e);
661 FSISolidTractionElement<SOLID_ELEMENT,2>* el_pt=
662 new FSISolidTractionElement<SOLID_ELEMENT,2>(bulk_elem_pt,face_index);
665 Traction_mesh_pt->add_element_pt(el_pt);
668 el_pt->set_boundary_number_in_bulk_mesh(b);
682 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
688 Solid_fsi_boundary_pt=
696 unsigned n_element = Fluid_mesh_pt->nboundary_element(b);
699 for(
unsigned e=0;e<n_element;e++)
702 FLUID_ELEMENT* bulk_elem_pt =
dynamic_cast<FLUID_ELEMENT*
>(
703 Fluid_mesh_pt->boundary_element_pt(b,e));
706 int face_index = Fluid_mesh_pt->face_index_at_boundary(b,e);
709 ImposeDisplacementByLagrangeMultiplierElement<FLUID_ELEMENT>* el_pt =
710 new ImposeDisplacementByLagrangeMultiplierElement<FLUID_ELEMENT>(
711 bulk_elem_pt,face_index);
714 Lagrange_multiplier_mesh_pt->add_element_pt(el_pt);
719 el_pt->set_boundary_shape_geom_object_pt(Solid_fsi_boundary_pt,b);
722 unsigned nnod=el_pt->nnode();
723 for (
unsigned j=0;j<nnod;j++)
725 Node* nod_pt = el_pt->node_pt(j);
728 if (nod_pt->is_on_boundary(0))
732 unsigned n_bulk_value=el_pt->nbulk_value(j);
735 unsigned nval=nod_pt->nvalue();
736 for (
unsigned j=n_bulk_value;j<nval;j++)
750 template<
class FLUID_ELEMENT,
class SOLID_ELEMENT>
762 sprintf(filename,
"%s/fluid_soln%i.dat",doc_info.directory().c_str(),
764 some_file.open(filename);
765 Fluid_mesh_pt->output(some_file,npts);
770 sprintf(filename,
"%s/solid_soln%i.dat",doc_info.directory().c_str(),
772 some_file.open(filename);
773 Solid_mesh_pt->output(some_file,npts);
796 doc_info.set_directory(
"RESLT");
804 PseudoSolidNodeUpdateElement<TTaylorHoodElement<2>, TPVDElement<2,3> >,
805 TPVDElement<2,3> > problem;
808 problem.
fluid_mesh_pt()->output_boundaries(
"RESLT/fluid_boundaries.dat");
809 problem.solid_mesh_pt()->output_boundaries(
"RESLT/solid_boundaries.dat");
812 problem.doc_solution(doc_info);
817 double q_increment=1.0e-6;
820 problem.newton_solve();
823 problem.doc_solution(doc_info);
831 for (
unsigned i=0;i<nstep;i++)
834 problem.newton_solve();
837 problem.doc_solution(doc_info);
FluidTriangleMesh(const std::string &node_file_name, const std::string &element_file_name, const std::string &poly_file_name, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor.
SolidMesh * Traction_mesh_pt
Vector of pointers to mesh of FSI traction elements.
UnstructuredFSIProblem()
Constructor.
MySolidTriangleMesh< SOLID_ELEMENT > * Solid_mesh_pt
Solid mesh.
FluidTriangleMesh< FLUID_ELEMENT > *& fluid_mesh_pt()
Access function for the fluid mesh.
Triangle-based mesh upgraded to become a solid mesh.
virtual ~MySolidTriangleMesh()
Empty Destructor.
void create_fsi_traction_elements()
Create FSI traction elements.
int main()
Driver for unstructured fsi problem.
~UnstructuredFSIProblem()
Destructor (empty)
virtual ~FluidTriangleMesh()
Empty Destructor.
void doc_solution(DocInfo &doc_info)
Doc the solution.
double Gravity
Non-dim gravity.
SolidMesh * Lagrange_multiplier_mesh_pt
Pointers to mesh of Lagrange multiplier elements.
Unstructured FSI Problem.
Namespace for physical parameters.
FluidTriangleMesh< FLUID_ELEMENT > * Fluid_mesh_pt
Fluid mesh.
double Nu
Pseudo-solid Poisson ratio.
void gravity(const double &time, const Vector< double > &xi, Vector< double > &b)
Non-dimensional gravity as body force.
void create_lagrange_multiplier_elements()
Create elements that enforce prescribed boundary motion for the pseudo-solid fluid mesh by Lagrange m...
ConstitutiveLaw * Constitutive_law_pt
Constitutive law for the solid (and pseudo-solid) mechanics.
double Re
Reynolds number.
bool is_on_fsi_boundary(Node *nod_pt)
Boolean to identify if node is on fsi boundary.
Triangle-based mesh upgraded to become a pseudo-solid mesh.
MySolidTriangleMesh(const std::string &node_file_name, const std::string &element_file_name, const std::string &poly_file_name, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor:
MySolidTriangleMesh< SOLID_ELEMENT > *& solid_mesh_pt()
Access function for the solid mesh.
void doc_solid_boundary_coordinates()
Sanity check: Doc boundary coordinates from solid side.
MeshAsGeomObject * Solid_fsi_boundary_pt
GeomObject incarnation of fsi boundary in solid mesh.