41 #include "navier_stokes.h" 43 #include "constitutive.h" 44 #include "rigid_body.h" 47 #include "meshes/triangle_mesh.h" 55 using namespace oomph;
99 double null(
const double &t) {
return 0.0;}
107 return atan((b/a)*tan((a*b*t)/(b*b + a*a)));
117 double chi =
angle(t);
120 return (a*a*sin(chi)*sin(chi) + b*b*cos(chi)*cos(chi))/(a*a + b*b);
130 double chi =
angle(t);
134 return 2.0*(a*a - b*b)*(sin(chi)*cos(chi))*chi_dot/(a*a + b*b);
161 const double &a,
const double &b)
162 : GeomObject(1,2), Centre_x(centre_x), Centre_y(centre_y), A(a), B(b)
170 void position(
const Vector<double> &xi, Vector<double> &r)
const 172 r[0] = Centre_x + A*cos(xi[0]);
173 r[1] = Centre_y + B*sin(xi[0]);
178 const Vector<double> &xi, Vector<double> &r)
const 180 return position(xi,r);
196 template<
class ELEMENT>
211 this->set_boundary_velocity();
215 void actions_before_adapt();
218 void actions_after_adapt();
225 Fluid_mesh_pt->node_update();
231 void complete_problem_setup();
234 void set_boundary_velocity();
239 void solve_for_consistent_nodal_positions();
242 void doc_solution(
const bool& project=
false);
245 void output_exact_solution(std::ofstream &output_file);
251 void create_lagrange_multiplier_elements();
255 void delete_lagrange_multiplier_elements();
259 void create_drag_elements();
263 void delete_drag_elements();
266 void pin_rigid_body();
269 void unpin_rigid_body();
308 template<
class ELEMENT>
313 this->Doc_info.set_directory(
"RESLT");
316 this->Norm_file.open(
"RESLT/norm.dat");
319 this->Cog_file.open(
"RESLT/cog_trace.dat");
322 this->Cog_exact_file.open(
"RESLT/cog_exact_trace.dat");
327 this->add_time_stepper_pt(
new BDF<2>);
330 this->add_time_stepper_pt(
new Newmark<2>);
339 Vector<TriangleMeshCurveSection*> boundary_segment_pt(4);
342 double half_length = 5.0;
343 double half_height = 2.5;
346 Vector<Vector<double> > bound_seg(2);
347 for(
unsigned i=0;i<2;i++) {bound_seg[i].resize(2);}
350 bound_seg[0][0]=-half_length;
351 bound_seg[0][1]=-half_height;
352 bound_seg[1][0]=-half_length;
353 bound_seg[1][1]=half_height;
356 unsigned bound_id = 0;
359 boundary_segment_pt[0] =
new TriangleMeshPolyLine(bound_seg,bound_id);
362 bound_seg[0][0]=-half_length;
363 bound_seg[0][1]=half_height;
364 bound_seg[1][0]=half_length;
365 bound_seg[1][1]=half_height;
371 boundary_segment_pt[1] =
new TriangleMeshPolyLine(bound_seg,bound_id);
374 bound_seg[0][0]=half_length;
375 bound_seg[0][1]=half_height;
376 bound_seg[1][0]=half_length;
377 bound_seg[1][1]=-half_height;
383 boundary_segment_pt[2] =
new TriangleMeshPolyLine(bound_seg,bound_id);
386 bound_seg[0][0]=half_length;
387 bound_seg[0][1]=-half_height;
388 bound_seg[1][0]=-half_length;
389 bound_seg[1][1]=-half_height;
395 boundary_segment_pt[3] =
new TriangleMeshPolyLine(bound_seg,bound_id);
398 Outer_boundary_polygon_pt =
new TriangleMeshPolygon(boundary_segment_pt);
404 Rigid_body_pt.resize(1);
405 Vector<TriangleMeshClosedCurve*> hole_pt(1);
409 double x_center = 0.0;
410 double y_center = 0.0;
413 GeomObject* temp_hole_pt =
new GeneralEllipse(x_center,y_center,A,B);
414 Rigid_body_pt[0] =
new ImmersedRigidBodyElement(temp_hole_pt,
415 this->time_stepper_pt(1));
418 Vector<TriangleMeshCurveSection*> curvilinear_boundary_pt(2);
421 double zeta_start=0.0;
422 double zeta_end=MathematicalConstants::Pi;
424 unsigned boundary_id=4;
425 curvilinear_boundary_pt[0]=
new TriangleMeshCurviLine(
426 Rigid_body_pt[0],zeta_start,zeta_end,nsegment,boundary_id);
429 zeta_start=MathematicalConstants::Pi;
430 zeta_end=2.0*MathematicalConstants::Pi;
433 curvilinear_boundary_pt[1]=
new TriangleMeshCurviLine(
434 Rigid_body_pt[0],zeta_start,zeta_end,
435 nsegment,boundary_id);
438 Vector<double> hole_coords(2);
441 Vector<TriangleMeshClosedCurve*> curvilinear_hole_pt(1);
443 new TriangleMeshClosedCurve(
444 curvilinear_boundary_pt,hole_coords);
451 TriangleMeshClosedCurve* closed_curve_pt=Outer_boundary_polygon_pt;
453 double uniform_element_area=1.0;
457 TriangleMeshParameters triangle_mesh_parameters(
461 triangle_mesh_parameters.internal_closed_curve_pt() =
465 triangle_mesh_parameters.element_area() =
466 uniform_element_area;
470 new RefineableSolidTriangleMesh<ELEMENT>(
471 triangle_mesh_parameters, this->time_stepper_pt());
474 Z2ErrorEstimator* error_estimator_pt=
new Z2ErrorEstimator;
475 Fluid_mesh_pt->spatial_error_estimator_pt()=error_estimator_pt;
478 Fluid_mesh_pt->max_permitted_error()=0.005;
479 Fluid_mesh_pt->min_permitted_error()=0.001;
480 Fluid_mesh_pt->max_element_size()=1.0;
481 Fluid_mesh_pt->min_element_size()=0.001;
484 if (CommandLineArgs::command_line_flag_has_been_set(
"--validation"))
486 Fluid_mesh_pt->min_element_size()=0.01;
492 complete_problem_setup();
495 ImmersedRigidBodyElement* rigid_element1_pt =
496 dynamic_cast<ImmersedRigidBodyElement*
>(Rigid_body_pt[0]);
497 rigid_element1_pt->initial_centre_of_mass(0) = x_center;
498 rigid_element1_pt->initial_centre_of_mass(1) = y_center;
499 rigid_element1_pt->mass_shape() = MathematicalConstants::Pi*A*
B;
500 rigid_element1_pt->moment_of_inertia_shape() =
501 0.25*MathematicalConstants::Pi*A*B*(A*A + B*
B);
507 rigid_element1_pt->pin_centre_of_mass_coordinate(0);
508 rigid_element1_pt->pin_centre_of_mass_coordinate(1);
511 Rigid_body_mesh_pt =
new Mesh;
512 Rigid_body_mesh_pt->add_element_pt(rigid_element1_pt);
515 Drag_mesh_pt.resize(1);
516 for(
unsigned m=0;m<1;m++) {Drag_mesh_pt[m] =
new Mesh;}
517 this->create_drag_elements();
520 rigid_element1_pt->set_drag_mesh(Drag_mesh_pt[0]);
528 Lagrange_multiplier_mesh_pt=
new SolidMesh;
529 create_lagrange_multiplier_elements();
536 this->add_sub_mesh(Fluid_mesh_pt);
539 this->add_sub_mesh(this->Lagrange_multiplier_mesh_pt);
541 this->add_sub_mesh(this->Rigid_body_mesh_pt);
544 this->build_global_mesh();
547 cout <<
"Number of equations: " << this->assign_eqn_numbers() << std::endl;
555 template<
class ELEMENT>
560 delete this->time_stepper_pt(0);
563 delete this->time_stepper_pt(1);
566 unsigned n=Outer_boundary_polygon_pt->npolyline();
567 for (
unsigned j=0;j<n;j++)
569 delete Outer_boundary_polygon_pt->polyline_pt(j);
571 delete Outer_boundary_polygon_pt;
574 dynamic_cast<ImmersedRigidBodyElement*
>(Rigid_body_pt[0])->
578 delete_lagrange_multiplier_elements();
579 delete Lagrange_multiplier_mesh_pt;
582 delete Fluid_mesh_pt->spatial_error_estimator_pt();
585 delete Fluid_mesh_pt;
591 this->Cog_exact_file.close();
592 this->Cog_file.close();
593 this->Norm_file.close();
600 template<
class ELEMENT>
604 dynamic_cast<ImmersedRigidBodyElement*
>(Rigid_body_pt[0])->
608 delete_drag_elements();
611 delete_lagrange_multiplier_elements();
614 this->rebuild_global_mesh();
621 template<
class ELEMENT>
626 Fluid_mesh_pt->set_lagrangian_nodal_coordinates();
629 create_lagrange_multiplier_elements();
632 create_drag_elements();
635 dynamic_cast<ImmersedRigidBodyElement*
>(Rigid_body_pt[0])->
636 set_drag_mesh(this->Drag_mesh_pt[0]);
639 this->rebuild_global_mesh();
644 complete_problem_setup();
647 bool doc_projection=
true;
648 doc_solution(doc_projection);
657 template<
class ELEMENT>
663 unsigned nbound=Fluid_mesh_pt->nboundary();
664 for(
unsigned ibound=0;ibound<nbound;ibound++)
666 unsigned num_nod=Fluid_mesh_pt->nboundary_node(ibound);
667 for (
unsigned inod=0;inod<num_nod;inod++)
670 Node*
const nod_pt=Fluid_mesh_pt->boundary_node_pt(ibound,inod);
674 if((ibound!=0) && (ibound!=2)) {nod_pt->pin(0);}
681 SolidNode*
const solid_node_pt =
dynamic_cast<SolidNode*
>(nod_pt);
686 solid_node_pt->pin_position(0);
687 solid_node_pt->pin_position(1);
693 solid_node_pt->unpin_position(0);
694 solid_node_pt->unpin_position(1);
703 nod_pt->set_auxiliary_node_update_fct_pt(
704 FSI_functions::apply_no_slip_on_moving_wall);
710 unsigned n_element = Fluid_mesh_pt->nelement();
711 for(
unsigned e=0;e<n_element;e++)
714 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(Fluid_mesh_pt->element_pt(e));
731 this->set_boundary_velocity();
739 template<
class ELEMENT>
744 for(
unsigned ibound=0;ibound<4;ibound++)
748 if((ibound==0) || (ibound==2))
750 unsigned num_nod=this->Fluid_mesh_pt->nboundary_node(ibound);
751 for (
unsigned inod=0;inod<num_nod;inod++)
754 Node*
const nod_pt=this->Fluid_mesh_pt->boundary_node_pt(ibound,inod);
757 unsigned n_prev=nod_pt->time_stepper_pt()->nprev_values();
760 for(
unsigned t=0;t<=n_prev;t++)
762 nod_pt->set_value(t,1,0.0);
770 unsigned num_nod=this->Fluid_mesh_pt->nboundary_node(ibound);
771 for (
unsigned inod=0;inod<num_nod;inod++)
774 Node* nod_pt=this->Fluid_mesh_pt->boundary_node_pt(ibound,inod);
777 unsigned n_prev=nod_pt->time_stepper_pt()->nprev_values();
780 double y = nod_pt->x(1);
782 for(
unsigned t=0;t<=n_prev;t++)
785 double time_ = this->time_pt()->time(t);
792 double e1 = exp(-delta);
793 double a1 = 1.0 - (1.0 + delta + 0.5*delta*delta)*e1;
794 double b1 = (3.0 + 3.0*delta + delta*delta)*e1 - 3.0;
795 double c1 = 3.0 - (3.0 + 2.0*delta + 0.5*delta*delta)*e1;
797 if((time_ >= 0.0) & (time_ <= 1.0))
799 ramp = a1*time_*time_*time_
804 else if (time_ > 1.0)
806 ramp = 1.0 - exp(-delta*time_);
809 nod_pt->set_value(t,0,-y*ramp);
814 for (
unsigned t=0;t<=n_prev;t++)
816 nod_pt->set_value(t,1,0.0);
827 template<
class ELEMENT>
830 unsigned n_rigid_body = Rigid_body_pt.size();
831 for(
unsigned i=0;i<n_rigid_body;++i)
833 unsigned n_geom_data = Rigid_body_pt[i]->ngeom_data();
834 for(
unsigned j=0;j<n_geom_data;j++)
836 Rigid_body_pt[i]->geom_data_pt(j)->pin_all();
845 template<
class ELEMENT>
848 unsigned n_rigid_body = Rigid_body_pt.size();
849 for(
unsigned i=0;i<n_rigid_body;++i)
851 unsigned n_geom_data = Rigid_body_pt[i]->ngeom_data();
852 for(
unsigned j=0;j<n_geom_data;j++)
854 Rigid_body_pt[i]->geom_data_pt(j)->unpin_all();
866 template<
class ELEMENT>
871 this->pin_rigid_body();
874 this->assign_eqn_numbers();
877 this->steady_newton_solve();
880 this->unpin_rigid_body();
883 ImmersedRigidBodyElement* rigid_element1_pt =
884 dynamic_cast<ImmersedRigidBodyElement*
>(Rigid_body_pt[0]);
885 rigid_element1_pt->pin_centre_of_mass_coordinate(0);
886 rigid_element1_pt->pin_centre_of_mass_coordinate(1);
889 this->assign_eqn_numbers();
900 template<
class ELEMENT>
908 unsigned n_boundary = Fluid_mesh_pt->nboundary();
911 for(
unsigned b=0;b<n_boundary;b++)
914 GeomObject* boundary_geom_obj_pt =
915 Fluid_mesh_pt->boundary_geom_object_pt(b);
918 if(boundary_geom_obj_pt!=0)
921 unsigned n_element = Fluid_mesh_pt->nboundary_element(b);
924 for(
unsigned e=0;e<n_element;e++)
928 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
929 Fluid_mesh_pt->boundary_element_pt(b,e));
932 int face_index = Fluid_mesh_pt->face_index_at_boundary(b,e);
937 ImposeDisplacementByLagrangeMultiplierElement<ELEMENT>* el_pt =
938 new ImposeDisplacementByLagrangeMultiplierElement<ELEMENT>(
939 bulk_elem_pt,face_index,b);
942 Lagrange_multiplier_mesh_pt->add_element_pt(el_pt);
947 el_pt->set_boundary_shape_geom_object_pt(
948 boundary_geom_obj_pt,b);
951 unsigned nnod=el_pt->nnode();
952 for(
unsigned j=0;j<nnod;j++)
954 Node* nod_pt = el_pt->node_pt(j);
958 unsigned n_bulk_value=el_pt->nbulk_value(j);
962 unsigned nval=nod_pt->nvalue();
965 for (
unsigned i=0;i<2;i++)
968 nod_pt->pin(n_bulk_value+2+i);
983 template<
class ELEMENT>
988 unsigned n_element = Lagrange_multiplier_mesh_pt->nelement();
991 for(
unsigned e=0;e<n_element;e++)
994 delete Lagrange_multiplier_mesh_pt->element_pt(e);
998 Lagrange_multiplier_mesh_pt->flush_element_and_node_storage();
1009 template<
class ELEMENT>
1017 unsigned n_rigid = Rigid_body_pt.size();
1020 unsigned n_boundary = Fluid_mesh_pt->nboundary();
1023 for(
unsigned r=0;r<n_rigid;r++)
1026 ImmersedRigidBodyElement* rigid_el_pt =
1027 dynamic_cast<ImmersedRigidBodyElement*
>(this->Rigid_body_pt[r]);
1030 for(
unsigned b=0;b<n_boundary;b++)
1033 if(dynamic_cast<ImmersedRigidBodyElement*>
1034 (Fluid_mesh_pt->boundary_geom_object_pt(b)) == rigid_el_pt)
1037 unsigned n_element = Fluid_mesh_pt->nboundary_element(b);
1040 for(
unsigned e=0;e<n_element;e++)
1044 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
1045 Fluid_mesh_pt->boundary_element_pt(b,e));
1048 int face_index = Fluid_mesh_pt->face_index_at_boundary(b,e);
1053 NavierStokesSurfaceDragTorqueElement<ELEMENT>* el_pt =
1054 new NavierStokesSurfaceDragTorqueElement<ELEMENT>(
1055 bulk_elem_pt,face_index);
1058 Drag_mesh_pt[r]->add_element_pt(el_pt);
1062 for(
unsigned i=0;i<2;i++)
1063 {el_pt->centre_of_rotation(i) =
1064 rigid_el_pt->initial_centre_of_mass(i);}
1069 el_pt->set_translation_and_rotation(rigid_el_pt->geom_data_pt(0));
1082 template<
class ELEMENT>
1085 unsigned n_bodies = Drag_mesh_pt.size();
1086 for(
unsigned n=0;n<n_bodies;n++)
1089 unsigned n_element = Drag_mesh_pt[n]->nelement();
1092 for(
unsigned e=0;e<n_element;e++)
1095 delete Drag_mesh_pt[n]->element_pt(e);
1099 Drag_mesh_pt[n]->flush_element_and_node_storage();
1109 template<
class ELEMENT>
1111 const bool& project)
1114 oomph_info <<
"Docing step: " << this->Doc_info.number()
1128 sprintf(filename,
"%s/soln%i.dat",
1129 this->Doc_info.directory().c_str(),
1130 this->Doc_info.number());
1134 sprintf(filename,
"%s/proj%i.dat",
1135 this->Doc_info.directory().c_str(),
1136 this->Doc_info.number()-1);
1140 double square_of_l2_norm=0.0;
1141 unsigned nel=Fluid_mesh_pt->nelement();
1142 for (
unsigned e=0;e<nel;e++)
1145 dynamic_cast<ELEMENT*
>(this->Fluid_mesh_pt->element_pt(e))->
1146 square_of_l2_norm();
1149 std::cout <<
"Checking " << sqrt(square_of_l2_norm) <<
"\n";
1150 this->Norm_file << sqrt(square_of_l2_norm) <<
"\n";
1152 some_file.open(filename);
1153 some_file << dynamic_cast<ELEMENT*>(this->Fluid_mesh_pt->element_pt(0))
1154 ->variable_identifier();
1155 this->Fluid_mesh_pt->output(some_file,npts);
1162 sprintf(filename,
"%s/int%i.dat",
1163 this->Doc_info.directory().c_str(),
1164 this->Doc_info.number());
1165 some_file.open(filename);
1166 this->Lagrange_multiplier_mesh_pt->output(some_file);
1170 this->Doc_info.number()++;
1173 dynamic_cast<ImmersedRigidBodyElement*
>(this->Rigid_body_pt[0])->
1174 output_centre_of_gravity(this->Cog_file);
1177 this->output_exact_solution(this->Cog_exact_file);
1185 template<
class ELEMENT>
1190 double time = this->time();
1205 CommandLineArgs::setup(argc,argv);
1211 CommandLineArgs::specify_command_line_flag(
"--validation");
1214 CommandLineArgs::parse_and_assign();
1217 CommandLineArgs::doc_specified_flags();
1221 ProjectableTaylorHoodElement<MyTaylorHoodElement> > problem;
1229 problem.initialise_dt(dt);
1232 problem.assign_initial_values_impulsive();
1235 problem.doc_solution();
1239 for (
unsigned i=0;i<nstep;i++)
1242 problem.unsteady_newton_solve(dt);
1243 problem.doc_solution();
1247 unsigned ncycle=200;
1248 if (CommandLineArgs::command_line_flag_has_been_set(
"--validation"))
1251 oomph_info <<
"Only doing one cycle during validation\n";
1254 for (
unsigned j=0;j<ncycle;j++)
1260 for (
unsigned i=0;i<nstep;i++)
1263 problem.unsteady_newton_solve(dt);
1264 problem.doc_solution();
Mesh * Rigid_body_mesh_pt
Mesh of the generalised elements for the rigid bodies.
SolidMesh * Lagrange_multiplier_mesh_pt
Pointers to mesh of Lagrange multiplier elements.
GeneralEllipse(const double ¢re_x, const double ¢re_y, const double &a, const double &b)
Simple Constructor that transfers appropriate geometric parameters into internal data.
double velocity(const double &t)
Angular velocity as function of time t.
void position(const Vector< double > &xi, Vector< double > &r) const
~UnstructuredImmersedEllipseProblem()
Destructor.
double A
Initial axis of the elliptical solid in x-direction.
void output_exact_solution(std::ofstream &output_file)
Output the exact solution.
void unpin_rigid_body()
Unpin the degrees of freedom associated with the solid bodies.
void set_boundary_velocity()
Set the boundary velocity.
ofstream Norm_file
File to document the norm of the solution (for validation purposes)
void delete_drag_elements()
Delete elements that calculate the drag and torque on the boundaries.
void position(const unsigned &t, const Vector< double > &xi, Vector< double > &r) const
void pin_rigid_body()
Pin the degrees of freedom associated with the solid bodies.
ConstitutiveLaw * Constitutive_law_pt
Constitutive law used to determine the mesh deformation.
Vector< Mesh * > Drag_mesh_pt
Mesh of drag elements.
void actions_before_adapt()
Wipe the meshes of Lagrange multiplier and drag elements.
A geometric object for an ellipse with initial centre of mass at (centre_x, centre_y) with axis in th...
void create_lagrange_multiplier_elements()
Create elements that enforce prescribed boundary motion for the pseudo-solid fluid mesh by Lagrange m...
void doc_solution(const bool &project=false)
Doc the solution.
DocInfo Doc_info
Internal DocInfo object.
ofstream Cog_exact_file
File to document the exact motion of the centre of gravity.
double Lambda_sq
Pseudo-solid (mesh) "density" Set to zero because we don't want inertia in the node update! ...
double null(const double &t)
Null function.
void complete_problem_setup()
Set boundary condition, assign auxiliary node update fct. Complete the build of all elements...
void actions_before_implicit_timestep()
Reset the boundary conditions when timestepping.
double St
Strouhal number.
void actions_after_adapt()
Rebuild the meshes of Lagrange multiplier and drag elements.
double Nu
Pseudo-solid (mesh) Poisson ratio.
void actions_before_newton_convergence_check()
Re-apply the no slip condition (imposed indirectly via enslaved velocities)
void solve_for_consistent_nodal_positions()
Function that solves a simplified problem to ensure that the positions of the boundary nodes are init...
double Density_ratio
Density ratio (Solid density / Fluid density)
RefineableSolidTriangleMesh< ELEMENT > * Fluid_mesh_pt
Pointer to Fluid_mesh.
double angle(const double &t)
Angular position as a function of time t.
double acceleration(const double &t)
Angular acceleration as a function of time t (should always be zero)
void delete_lagrange_multiplier_elements()
Delete elements that impose the prescribed boundary displacement and wipe the associated mesh...
Vector< GeomObject * > Rigid_body_pt
Storage for the geom object.
double Re
Reynolds number.
UnstructuredImmersedEllipseProblem()
Constructor.
Namespace for Problem Parameters.
int main(int argc, char **argv)
Driver code for immersed ellipse problem.
void create_drag_elements()
Create elements that calculate the drag and torque on the boundaries.
~GeneralEllipse()
Empty Destructor.
ofstream Cog_file
File to document the motion of the centre of gravity.
TriangleMeshPolygon * Outer_boundary_polygon_pt
Triangle mesh polygon for outer boundary.