37 #include "navier_stokes.h"
39 #include "constitutive.h"
40 #include "rigid_body.h"
43 #include "meshes/triangle_mesh.h"
51 using namespace oomph;
95 double null(
const double &t) {
return 0.0;}
103 return atan((b/a)*tan((a*b*t)/(b*b + a*a)));
113 double chi =
angle(t);
116 return (a*a*sin(chi)*sin(chi) + b*b*cos(chi)*cos(chi))/(a*a + b*b);
126 double chi =
angle(t);
130 return 2.0*(a*a - b*b)*(sin(chi)*cos(chi))*chi_dot/(a*a + b*b);
150 double Centre_x, Centre_y,
A,
B;
157 const double &a,
const double &b)
158 : GeomObject(1,2), Centre_x(centre_x), Centre_y(centre_y),
A(a),
B(b)
166 void position(
const Vector<double> &xi, Vector<double> &r)
const
168 r[0] = Centre_x +
A*cos(xi[0]);
169 r[1] = Centre_y +
B*sin(xi[0]);
174 const Vector<double> &xi, Vector<double> &r)
const
176 return position(xi,r);
192 template<
class ELEMENT>
207 this->set_boundary_velocity();
211 void actions_before_adapt();
214 void actions_after_adapt();
221 Fluid_mesh_pt->node_update();
227 void complete_problem_setup();
230 void set_boundary_velocity();
235 void solve_for_consistent_nodal_positions();
238 void doc_solution(
const bool& project=
false);
241 void output_exact_solution(std::ofstream &output_file);
247 void create_lagrange_multiplier_elements();
251 void delete_lagrange_multiplier_elements();
255 void create_drag_elements();
259 void delete_drag_elements();
262 void pin_rigid_body();
265 void unpin_rigid_body();
304 template<
class ELEMENT>
309 this->Doc_info.set_directory(
"RESLT");
312 this->Norm_file.open(
"RESLT/norm.dat");
315 this->Cog_file.open(
"RESLT/cog_trace.dat");
318 this->Cog_exact_file.open(
"RESLT/cog_exact_trace.dat");
323 this->add_time_stepper_pt(
new BDF<2>);
326 this->add_time_stepper_pt(
new Newmark<2>);
335 Vector<TriangleMeshCurveSection*> boundary_segment_pt(4);
338 double half_length = 5.0;
339 double half_height = 2.5;
342 Vector<Vector<double> > bound_seg(2);
343 for(
unsigned i=0;i<2;i++) {bound_seg[i].resize(2);}
346 bound_seg[0][0]=-half_length;
347 bound_seg[0][1]=-half_height;
348 bound_seg[1][0]=-half_length;
349 bound_seg[1][1]=half_height;
352 unsigned bound_id = 0;
355 boundary_segment_pt[0] =
new TriangleMeshPolyLine(bound_seg,bound_id);
358 bound_seg[0][0]=-half_length;
359 bound_seg[0][1]=half_height;
360 bound_seg[1][0]=half_length;
361 bound_seg[1][1]=half_height;
367 boundary_segment_pt[1] =
new TriangleMeshPolyLine(bound_seg,bound_id);
370 bound_seg[0][0]=half_length;
371 bound_seg[0][1]=half_height;
372 bound_seg[1][0]=half_length;
373 bound_seg[1][1]=-half_height;
379 boundary_segment_pt[2] =
new TriangleMeshPolyLine(bound_seg,bound_id);
382 bound_seg[0][0]=half_length;
383 bound_seg[0][1]=-half_height;
384 bound_seg[1][0]=-half_length;
385 bound_seg[1][1]=-half_height;
391 boundary_segment_pt[3] =
new TriangleMeshPolyLine(bound_seg,bound_id);
394 Outer_boundary_polygon_pt =
new TriangleMeshPolygon(boundary_segment_pt);
400 Rigid_body_pt.resize(1);
401 Vector<TriangleMeshClosedCurve*> hole_pt(1);
405 double x_center = 0.0;
406 double y_center = 0.0;
410 Rigid_body_pt[0] =
new ImmersedRigidBodyElement(temp_hole_pt,
411 this->time_stepper_pt(1));
414 Vector<TriangleMeshCurveSection*> curvilinear_boundary_pt(2);
417 double zeta_start=0.0;
418 double zeta_end=MathematicalConstants::Pi;
420 unsigned boundary_id=4;
421 curvilinear_boundary_pt[0]=
new TriangleMeshCurviLine(
422 Rigid_body_pt[0],zeta_start,zeta_end,nsegment,boundary_id);
425 zeta_start=MathematicalConstants::Pi;
426 zeta_end=2.0*MathematicalConstants::Pi;
429 curvilinear_boundary_pt[1]=
new TriangleMeshCurviLine(
430 Rigid_body_pt[0],zeta_start,zeta_end,
431 nsegment,boundary_id);
434 Vector<double> hole_coords(2);
437 Vector<TriangleMeshClosedCurve*> curvilinear_hole_pt(1);
439 new TriangleMeshClosedCurve(
440 curvilinear_boundary_pt,hole_coords);
447 TriangleMeshClosedCurve* closed_curve_pt=Outer_boundary_polygon_pt;
449 double uniform_element_area=1.0;
453 TriangleMeshParameters triangle_mesh_parameters(
457 triangle_mesh_parameters.internal_closed_curve_pt() =
461 triangle_mesh_parameters.element_area() =
462 uniform_element_area;
466 new RefineableSolidTriangleMesh<ELEMENT>(
467 triangle_mesh_parameters, this->time_stepper_pt());
470 Z2ErrorEstimator* error_estimator_pt=
new Z2ErrorEstimator;
471 Fluid_mesh_pt->spatial_error_estimator_pt()=error_estimator_pt;
474 Fluid_mesh_pt->max_permitted_error()=0.005;
475 Fluid_mesh_pt->min_permitted_error()=0.001;
476 Fluid_mesh_pt->max_element_size()=1.0;
477 Fluid_mesh_pt->min_element_size()=0.001;
480 if (CommandLineArgs::command_line_flag_has_been_set(
"--validation"))
482 Fluid_mesh_pt->min_element_size()=0.01;
488 complete_problem_setup();
491 ImmersedRigidBodyElement* rigid_element1_pt =
492 dynamic_cast<ImmersedRigidBodyElement*
>(Rigid_body_pt[0]);
493 rigid_element1_pt->initial_centre_of_mass(0) = x_center;
494 rigid_element1_pt->initial_centre_of_mass(1) = y_center;
495 rigid_element1_pt->mass_shape() = MathematicalConstants::Pi*
A*
B;
496 rigid_element1_pt->moment_of_inertia_shape() =
497 0.25*MathematicalConstants::Pi*
A*
B*(
A*
A +
B*
B);
503 rigid_element1_pt->pin_centre_of_mass_coordinate(0);
504 rigid_element1_pt->pin_centre_of_mass_coordinate(1);
507 Rigid_body_mesh_pt =
new Mesh;
508 Rigid_body_mesh_pt->add_element_pt(rigid_element1_pt);
511 Drag_mesh_pt.resize(1);
512 for(
unsigned m=0;m<1;m++) {Drag_mesh_pt[m] =
new Mesh;}
513 this->create_drag_elements();
516 rigid_element1_pt->set_drag_mesh(Drag_mesh_pt[0]);
524 Lagrange_multiplier_mesh_pt=
new SolidMesh;
525 create_lagrange_multiplier_elements();
532 this->add_sub_mesh(Fluid_mesh_pt);
535 this->add_sub_mesh(this->Lagrange_multiplier_mesh_pt);
537 this->add_sub_mesh(this->Rigid_body_mesh_pt);
540 this->build_global_mesh();
543 cout <<
"Number of equations: " << this->assign_eqn_numbers() << std::endl;
551 template<
class ELEMENT>
556 delete this->time_stepper_pt(0);
559 delete this->time_stepper_pt(1);
562 unsigned n=Outer_boundary_polygon_pt->npolyline();
563 for (
unsigned j=0;j<n;j++)
565 delete Outer_boundary_polygon_pt->polyline_pt(j);
567 delete Outer_boundary_polygon_pt;
570 dynamic_cast<ImmersedRigidBodyElement*
>(Rigid_body_pt[0])->
574 delete_lagrange_multiplier_elements();
575 delete Lagrange_multiplier_mesh_pt;
578 delete Fluid_mesh_pt->spatial_error_estimator_pt();
581 delete Fluid_mesh_pt;
587 this->Cog_exact_file.close();
588 this->Cog_file.close();
589 this->Norm_file.close();
596 template<
class ELEMENT>
600 dynamic_cast<ImmersedRigidBodyElement*
>(Rigid_body_pt[0])->
604 delete_drag_elements();
607 delete_lagrange_multiplier_elements();
610 this->rebuild_global_mesh();
617 template<
class ELEMENT>
622 Fluid_mesh_pt->set_lagrangian_nodal_coordinates();
625 create_lagrange_multiplier_elements();
628 create_drag_elements();
631 dynamic_cast<ImmersedRigidBodyElement*
>(Rigid_body_pt[0])->
632 set_drag_mesh(this->Drag_mesh_pt[0]);
635 this->rebuild_global_mesh();
640 complete_problem_setup();
643 bool doc_projection=
true;
644 doc_solution(doc_projection);
653 template<
class ELEMENT>
659 unsigned nbound=Fluid_mesh_pt->nboundary();
660 for(
unsigned ibound=0;ibound<nbound;ibound++)
662 unsigned num_nod=Fluid_mesh_pt->nboundary_node(ibound);
663 for (
unsigned inod=0;inod<num_nod;inod++)
666 Node*
const nod_pt=Fluid_mesh_pt->boundary_node_pt(ibound,inod);
670 if((ibound!=0) && (ibound!=2)) {nod_pt->pin(0);}
677 SolidNode*
const solid_node_pt =
dynamic_cast<SolidNode*
>(nod_pt);
682 solid_node_pt->pin_position(0);
683 solid_node_pt->pin_position(1);
689 solid_node_pt->unpin_position(0);
690 solid_node_pt->unpin_position(1);
699 nod_pt->set_auxiliary_node_update_fct_pt(
700 FSI_functions::apply_no_slip_on_moving_wall);
706 unsigned n_element = Fluid_mesh_pt->nelement();
707 for(
unsigned e=0;e<n_element;e++)
710 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(Fluid_mesh_pt->element_pt(e));
727 this->set_boundary_velocity();
735 template<
class ELEMENT>
740 for(
unsigned ibound=0;ibound<4;ibound++)
744 if((ibound==0) || (ibound==2))
746 unsigned num_nod=this->Fluid_mesh_pt->nboundary_node(ibound);
747 for (
unsigned inod=0;inod<num_nod;inod++)
750 Node*
const nod_pt=this->Fluid_mesh_pt->boundary_node_pt(ibound,inod);
753 unsigned n_prev=nod_pt->time_stepper_pt()->nprev_values();
756 for(
unsigned t=0;t<=n_prev;t++)
758 nod_pt->set_value(t,1,0.0);
766 unsigned num_nod=this->Fluid_mesh_pt->nboundary_node(ibound);
767 for (
unsigned inod=0;inod<num_nod;inod++)
770 Node* nod_pt=this->Fluid_mesh_pt->boundary_node_pt(ibound,inod);
773 unsigned n_prev=nod_pt->time_stepper_pt()->nprev_values();
776 double y = nod_pt->x(1);
778 for(
unsigned t=0;t<=n_prev;t++)
781 double time_ = this->time_pt()->time(t);
788 double e1 = exp(-delta);
789 double a1 = 1.0 - (1.0 + delta + 0.5*delta*delta)*e1;
790 double b1 = (3.0 + 3.0*delta + delta*delta)*e1 - 3.0;
791 double c1 = 3.0 - (3.0 + 2.0*delta + 0.5*delta*delta)*e1;
793 if((time_ >= 0.0) & (time_ <= 1.0))
795 ramp = a1*time_*time_*time_
800 else if (time_ > 1.0)
802 ramp = 1.0 - exp(-delta*time_);
805 nod_pt->set_value(t,0,-y*ramp);
810 for (
unsigned t=0;t<=n_prev;t++)
812 nod_pt->set_value(t,1,0.0);
823 template<
class ELEMENT>
826 unsigned n_rigid_body = Rigid_body_pt.size();
827 for(
unsigned i=0;i<n_rigid_body;++i)
829 unsigned n_geom_data = Rigid_body_pt[i]->ngeom_data();
830 for(
unsigned j=0;j<n_geom_data;j++)
832 Rigid_body_pt[i]->geom_data_pt(j)->pin_all();
841 template<
class ELEMENT>
844 unsigned n_rigid_body = Rigid_body_pt.size();
845 for(
unsigned i=0;i<n_rigid_body;++i)
847 unsigned n_geom_data = Rigid_body_pt[i]->ngeom_data();
848 for(
unsigned j=0;j<n_geom_data;j++)
850 Rigid_body_pt[i]->geom_data_pt(j)->unpin_all();
862 template<
class ELEMENT>
867 this->pin_rigid_body();
870 this->assign_eqn_numbers();
873 this->steady_newton_solve();
876 this->unpin_rigid_body();
879 ImmersedRigidBodyElement* rigid_element1_pt =
880 dynamic_cast<ImmersedRigidBodyElement*
>(Rigid_body_pt[0]);
881 rigid_element1_pt->pin_centre_of_mass_coordinate(0);
882 rigid_element1_pt->pin_centre_of_mass_coordinate(1);
885 this->assign_eqn_numbers();
896 template<
class ELEMENT>
904 unsigned n_boundary = Fluid_mesh_pt->nboundary();
907 for(
unsigned b=0;b<n_boundary;b++)
910 GeomObject* boundary_geom_obj_pt =
911 Fluid_mesh_pt->boundary_geom_object_pt(b);
914 if(boundary_geom_obj_pt!=0)
917 unsigned n_element = Fluid_mesh_pt->nboundary_element(b);
920 for(
unsigned e=0;e<n_element;e++)
924 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
925 Fluid_mesh_pt->boundary_element_pt(b,e));
928 int face_index = Fluid_mesh_pt->face_index_at_boundary(b,e);
933 ImposeDisplacementByLagrangeMultiplierElement<ELEMENT>* el_pt =
934 new ImposeDisplacementByLagrangeMultiplierElement<ELEMENT>(
935 bulk_elem_pt,face_index,b);
938 Lagrange_multiplier_mesh_pt->add_element_pt(el_pt);
943 el_pt->set_boundary_shape_geom_object_pt(
944 boundary_geom_obj_pt,b);
947 unsigned nnod=el_pt->nnode();
948 for(
unsigned j=0;j<nnod;j++)
950 Node* nod_pt = el_pt->node_pt(j);
954 unsigned n_bulk_value=el_pt->nbulk_value(j);
958 unsigned nval=nod_pt->nvalue();
961 for (
unsigned i=0;i<2;i++)
964 nod_pt->pin(n_bulk_value+2+i);
979 template<
class ELEMENT>
984 unsigned n_element = Lagrange_multiplier_mesh_pt->nelement();
987 for(
unsigned e=0;e<n_element;e++)
990 delete Lagrange_multiplier_mesh_pt->element_pt(e);
994 Lagrange_multiplier_mesh_pt->flush_element_and_node_storage();
1005 template<
class ELEMENT>
1013 unsigned n_rigid = Rigid_body_pt.size();
1016 unsigned n_boundary = Fluid_mesh_pt->nboundary();
1019 for(
unsigned r=0;r<n_rigid;r++)
1022 ImmersedRigidBodyElement* rigid_el_pt =
1023 dynamic_cast<ImmersedRigidBodyElement*
>(this->Rigid_body_pt[r]);
1026 for(
unsigned b=0;b<n_boundary;b++)
1029 if(
dynamic_cast<ImmersedRigidBodyElement*
>
1030 (Fluid_mesh_pt->boundary_geom_object_pt(b)) == rigid_el_pt)
1033 unsigned n_element = Fluid_mesh_pt->nboundary_element(b);
1036 for(
unsigned e=0;e<n_element;e++)
1040 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
1041 Fluid_mesh_pt->boundary_element_pt(b,e));
1044 int face_index = Fluid_mesh_pt->face_index_at_boundary(b,e);
1049 NavierStokesSurfaceDragTorqueElement<ELEMENT>* el_pt =
1050 new NavierStokesSurfaceDragTorqueElement<ELEMENT>(
1051 bulk_elem_pt,face_index);
1054 Drag_mesh_pt[r]->add_element_pt(el_pt);
1058 for(
unsigned i=0;i<2;i++)
1059 {el_pt->centre_of_rotation(i) =
1060 rigid_el_pt->initial_centre_of_mass(i);}
1065 el_pt->set_translation_and_rotation(rigid_el_pt->geom_data_pt(0));
1078 template<
class ELEMENT>
1081 unsigned n_bodies = Drag_mesh_pt.size();
1082 for(
unsigned n=0;n<n_bodies;n++)
1085 unsigned n_element = Drag_mesh_pt[n]->nelement();
1088 for(
unsigned e=0;e<n_element;e++)
1091 delete Drag_mesh_pt[n]->element_pt(e);
1095 Drag_mesh_pt[n]->flush_element_and_node_storage();
1105 template<
class ELEMENT>
1107 const bool& project)
1110 oomph_info <<
"Docing step: " << this->Doc_info.number()
1124 sprintf(filename,
"%s/soln%i.dat",
1125 this->Doc_info.directory().c_str(),
1126 this->Doc_info.number());
1130 sprintf(filename,
"%s/proj%i.dat",
1131 this->Doc_info.directory().c_str(),
1132 this->Doc_info.number()-1);
1136 double square_of_l2_norm=0.0;
1137 unsigned nel=Fluid_mesh_pt->nelement();
1138 for (
unsigned e=0;e<nel;e++)
1141 dynamic_cast<ELEMENT*
>(this->Fluid_mesh_pt->element_pt(e))->
1142 square_of_l2_norm();
1145 std::cout <<
"Checking " << sqrt(square_of_l2_norm) <<
"\n";
1146 this->Norm_file << sqrt(square_of_l2_norm) <<
"\n";
1148 some_file.open(filename);
1149 some_file << dynamic_cast<ELEMENT*>(this->Fluid_mesh_pt->element_pt(0))
1150 ->variable_identifier();
1151 this->Fluid_mesh_pt->output(some_file,npts);
1158 sprintf(filename,
"%s/int%i.dat",
1159 this->Doc_info.directory().c_str(),
1160 this->Doc_info.number());
1161 some_file.open(filename);
1162 this->Lagrange_multiplier_mesh_pt->output(some_file);
1166 this->Doc_info.number()++;
1169 dynamic_cast<ImmersedRigidBodyElement*
>(this->Rigid_body_pt[0])->
1170 output_centre_of_gravity(this->Cog_file);
1173 this->output_exact_solution(this->Cog_exact_file);
1181 template<
class ELEMENT>
1186 double time = this->time();
1201 CommandLineArgs::setup(argc,argv);
1207 CommandLineArgs::specify_command_line_flag(
"--validation");
1210 CommandLineArgs::parse_and_assign();
1213 CommandLineArgs::doc_specified_flags();
1217 ProjectableTaylorHoodElement<MyTaylorHoodElement> > problem;
1225 problem.initialise_dt(dt);
1228 problem.assign_initial_values_impulsive();
1231 problem.doc_solution();
1235 for (
unsigned i=0;i<nstep;i++)
1238 problem.unsteady_newton_solve(dt);
1239 problem.doc_solution();
1243 unsigned ncycle=200;
1244 if (CommandLineArgs::command_line_flag_has_been_set(
"--validation"))
1247 oomph_info <<
"Only doing one cycle during validation\n";
1250 for (
unsigned j=0;j<ncycle;j++)
1256 for (
unsigned i=0;i<nstep;i++)
1259 problem.unsteady_newton_solve(dt);
1260 problem.doc_solution();
//////////////////////////////////////////////////////// ////////////////////////////////////////////...
void position(const unsigned &t, const Vector< double > &xi, Vector< double > &r) const
~GeneralEllipse()
Empty Destructor.
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.
void position(const Vector< double > &xi, Vector< double > &r) const
Return the position of the ellipse boundary as a function of the angle xi[0].
//////////////////////////////////////////////////////// ////////////////////////////////////////////...
void pin_rigid_body()
Pin the degrees of freedom associated with the solid bodies.
void doc_solution(const bool &project=false)
Doc the solution.
RefineableSolidTriangleMesh< ELEMENT > * Fluid_mesh_pt
Pointer to Fluid_mesh.
void create_drag_elements()
Create elements that calculate the drag and torque on the boundaries.
DocInfo Doc_info
Internal DocInfo object.
void output_exact_solution(std::ofstream &output_file)
Output the exact solution.
void solve_for_consistent_nodal_positions()
Function that solves a simplified problem to ensure that the positions of the boundary nodes are init...
Mesh * Rigid_body_mesh_pt
Mesh of the generalised elements for the rigid bodies.
void actions_before_implicit_timestep()
Reset the boundary conditions when timestepping.
void create_lagrange_multiplier_elements()
Create elements that enforce prescribed boundary motion for the pseudo-solid fluid mesh by Lagrange m...
ofstream Cog_exact_file
File to document the exact motion of the centre of gravity.
void complete_problem_setup()
Set boundary condition, assign auxiliary node update fct. Complete the build of all elements,...
void unpin_rigid_body()
Unpin the degrees of freedom associated with the solid bodies.
void delete_lagrange_multiplier_elements()
Delete elements that impose the prescribed boundary displacement and wipe the associated mesh.
UnstructuredImmersedEllipseProblem()
Constructor.
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.
~UnstructuredImmersedEllipseProblem()
Destructor.
Vector< Mesh * > Drag_mesh_pt
Mesh of drag elements.
void actions_before_adapt()
Wipe the meshes of Lagrange multiplier and drag elements.
Vector< GeomObject * > Rigid_body_pt
Storage for the geom object.
void actions_after_adapt()
Rebuild the meshes of Lagrange multiplier and drag elements.
void set_boundary_velocity()
Set the boundary velocity.
ofstream Cog_file
File to document the motion of the centre of gravity.
SolidMesh * Lagrange_multiplier_mesh_pt
Pointers to mesh of Lagrange multiplier elements.
TriangleMeshPolygon * Outer_boundary_polygon_pt
Triangle mesh polygon for outer boundary.
void actions_before_newton_convergence_check()
Re-apply the no slip condition (imposed indirectly via dependent velocities)
int main(int argc, char **argv)
Driver code for immersed ellipse problem.
Exact solution for the rotation of an ellipse in unbounded shear flow as computed by Jeffery (1922)
double velocity(const double &t)
Angular velocity as function of time t.
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)
Namespace for Problem Parameters.
double Lambda_sq
Pseudo-solid (mesh) "density" Set to zero because we don't want inertia in the node update!
double A
Initial axis of the elliptical solid in x-direction.
double Density_ratio
Density ratio (Solid density / Fluid density)
double St
Strouhal number.
ConstitutiveLaw * Constitutive_law_pt
Constitutive law used to determine the mesh deformation.
double Nu
Pseudo-solid (mesh) Poisson ratio.
double B
Initial axis of the elliptical solid in y-direction (N.B. 2B = 1 is the reference length scale)
double Re
Reynolds number.