32 #include "navier_stokes.h"
34 #include "constitutive.h"
35 #include "fluid_interface.h"
38 #include "meshes/triangle_mesh.h"
41 using namespace oomph;
52 public virtual PseudoSolidNodeUpdateElement<TCrouzeixRaviartElement<2>,
53 TPVDBubbleEnrichedElement<2,3> >
65 TPVDBubbleEnrichedElement<2,3> >()
76 std::string txt=
"VARIABLES=";
103 const unsigned &nplot)
110 Vector<double> s(el_dim);
113 Vector<double> dudt(el_dim);
116 Vector<double> mesh_veloc(el_dim,0.0);
119 outfile << tecplot_zone_string(nplot);
122 unsigned n_node = nnode();
126 DShape dpsifdx(n_node,el_dim);
129 unsigned num_plot_points=nplot_points(nplot);
130 for (
unsigned iplot=0;iplot<num_plot_points;iplot++)
134 get_s_plot(iplot,nplot,s);
137 dshape_eulerian(s,psif,dpsifdx);
140 Vector<double> mesh_veloc(el_dim);
141 Vector<double> dudt(el_dim);
142 Vector<double> dudt_ALE(el_dim);
143 DenseMatrix<double> interpolated_dudx(el_dim,el_dim);
146 for(
unsigned i=0;i<el_dim;i++)
151 for(
unsigned j=0;j<el_dim;j++)
153 interpolated_dudx(i,j) = 0.0;
160 for(
unsigned i=0;i<el_dim;i++)
163 unsigned u_nodal_index = u_index_nst(i);
165 for(
unsigned l=0;l<n_node;l++)
167 dudt[i]+=du_dt_nst(l,u_nodal_index)*psif[l];
168 mesh_veloc[i]+=dnodal_position_dt(l,i)*psif[l];
171 for(
unsigned j=0;j<el_dim;j++)
173 interpolated_dudx(i,j) += nodal_value(l,u_nodal_index)*
181 for(
unsigned i=0;i<el_dim;i++)
184 for (
unsigned k=0;k<el_dim;k++)
186 dudt_ALE[i]-=mesh_veloc[k]*interpolated_dudx(i,k);
192 for(
unsigned i=0;i<el_dim;i++)
194 outfile << interpolated_x(s,i) <<
" ";
198 for(
unsigned i=0;i<el_dim;i++)
200 outfile << interpolated_u_nst(s,i) <<
" ";
204 outfile << interpolated_p_nst(s) <<
" ";
207 for(
unsigned i=0;i<el_dim;i++)
209 outfile << dudt_ALE[i] <<
" ";
213 for(
unsigned i=0;i<el_dim;i++)
215 outfile << mesh_veloc[i] <<
" ";
219 unsigned n_prev=node_pt(0)->position_time_stepper_pt()->ntstorage();
220 for (
unsigned t=1;t<n_prev;t++)
222 for(
unsigned i=0;i<el_dim;i++)
224 outfile << interpolated_x(t,s,i) <<
" ";
229 n_prev=node_pt(0)->time_stepper_pt()->ntstorage();
230 for (
unsigned t=1;t<n_prev;t++)
232 for(
unsigned i=0;i<el_dim;i++)
234 outfile << interpolated_u_nst(t,s,i) <<
" ";
238 outfile << Error <<
" "
239 << size() << std::endl;
243 write_tecplot_zone_footer(outfile,nplot);
255 :
public virtual SolidTElement<1,3>
269 :
public virtual SolidPointElement
350 template<
class ELEMENT>
363 delete this->time_stepper_pt(0);
366 unsigned n=Outer_boundary_polyline_pt->npolyline();
367 for (
unsigned j=0;j<n;j++)
369 delete Outer_boundary_polyline_pt->polyline_pt(j);
371 delete Outer_boundary_polyline_pt;
374 delete_free_surface_elements();
375 delete Free_surface_mesh_pt;
378 delete Fluid_mesh_pt->spatial_error_estimator_pt();
381 delete Fluid_mesh_pt;
384 delete Drop_pressure_data_pt;
396 delete_free_surface_elements();
399 this->rebuild_global_mesh();
408 create_free_surface_elements();
411 this->rebuild_global_mesh();
416 complete_problem_setup();
430 Fluid_mesh_pt->set_lagrangian_nodal_coordinates();
434 void complete_problem_setup();
437 void doc_solution(
const std::string& comment=
"");
440 void compute_error_estimate(
double& max_err,
447 const unsigned n_node = Fluid_mesh_pt->nnode();
450 for(
unsigned n=0;n<n_node;n++)
453 for(
unsigned i=0;i<2;i++)
456 Fluid_mesh_pt->node_pt(n)->set_value(i,0.0);
462 assign_initial_values_impulsive();
473 const unsigned n_node = Fluid_mesh_pt->nnode();
476 for(
unsigned n=0;n<n_node;n++)
479 const double current_x_pos = Fluid_mesh_pt->node_pt(n)->x(0);
480 const double current_y_pos = Fluid_mesh_pt->node_pt(n)->x(1);
483 const double new_y_pos = current_y_pos
484 + (1.0-fabs(1.0-current_y_pos))*epsilon
488 Fluid_mesh_pt->node_pt(n)->x(1) = new_y_pos;
496 const unsigned &pdof,
497 const double &pvalue)
500 dynamic_cast<ELEMENT*
>(Fluid_mesh_pt->element_pt(e))->
501 fix_pressure(pdof,pvalue);
509 void create_free_surface_elements();
515 unsigned n_element = Free_surface_mesh_pt->nelement();
518 for(
unsigned e=0;e<n_element;e++)
521 delete Free_surface_mesh_pt->element_pt(e);
526 Free_surface_mesh_pt->flush_element_and_node_storage();
560 Inflow_boundary_id=0,
561 Upper_wall_boundary_id=1,
562 Outflow_boundary_id=2,
563 Bottom_wall_boundary_id=3,
564 Interface_boundary_id=4,
574 template<
class ELEMENT>
583 this->add_time_stepper_pt(
new BDF<2>);
589 Vector<TriangleMeshCurveSection*> boundary_polyline_pt(4);
593 Vector<Vector<double> > vertex_coord(3);
594 for(
unsigned i=0;i<3;i++)
596 vertex_coord[i].resize(2);
603 vertex_coord[0][0]=0.0;
604 vertex_coord[0][1]=0.0;
605 vertex_coord[1][0]=0.0;
606 vertex_coord[1][1]= h;
607 vertex_coord[2][0]=0.0;
608 vertex_coord[2][1]= H;
611 boundary_polyline_pt[0] =
new TriangleMeshPolyLine(vertex_coord,
615 vertex_coord[0][0]=0.0;
616 vertex_coord[0][1]=H;
618 vertex_coord[1][1]=H;
620 vertex_coord[2][1]=H;
623 boundary_polyline_pt[1] =
new TriangleMeshPolyLine(vertex_coord,
624 Upper_wall_boundary_id);
628 vertex_coord[0][1]=H;
630 vertex_coord[1][1]=h;
632 vertex_coord[2][1]=0.0;
635 boundary_polyline_pt[2] =
new TriangleMeshPolyLine(vertex_coord,
636 Outflow_boundary_id);
640 vertex_coord[0][1]=0.0;
642 vertex_coord[1][1]=0.0;
643 vertex_coord[2][0]=0.0;
644 vertex_coord[2][1]=0.0;
647 boundary_polyline_pt[3] =
new TriangleMeshPolyLine(vertex_coord,
648 Bottom_wall_boundary_id);
651 Outer_boundary_polyline_pt =
new TriangleMeshPolygon(boundary_polyline_pt);
654 Vector<TriangleMeshOpenCurve *> interface_pt(1);
656 vertex_coord[0][0]=0.0;
657 vertex_coord[0][1]=h;
659 vertex_coord[1][1]=h;
661 vertex_coord[2][1]=h;
664 TriangleMeshPolyLine* interface_polyline_pt =
665 new TriangleMeshPolyLine(vertex_coord,
666 Interface_boundary_id);
670 interface_polyline_pt->connect_initial_vertex_to_polyline(
671 dynamic_cast<TriangleMeshPolyLine*
>(boundary_polyline_pt[0]),1);
675 interface_polyline_pt->connect_final_vertex_to_polyline(
676 dynamic_cast<TriangleMeshPolyLine*
>(boundary_polyline_pt[2]),1);
678 Vector<TriangleMeshCurveSection*> interface_curve_pt(1);
679 interface_curve_pt[0] = interface_polyline_pt;
681 interface_pt[0] =
new TriangleMeshOpenCurve(interface_curve_pt);
689 TriangleMeshClosedCurve* outer_closed_curve_pt=Outer_boundary_polyline_pt;
691 unsigned n_internal_closed_boundaries = 0;
692 Vector<TriangleMeshClosedCurve *>
693 inner_boundaries_pt(n_internal_closed_boundaries);
696 double uniform_element_area=0.01;
700 TriangleMeshParameters triangle_mesh_parameters(
701 outer_closed_curve_pt);
704 triangle_mesh_parameters.internal_closed_curve_pt() = inner_boundaries_pt;
707 triangle_mesh_parameters.internal_open_curves_pt() = interface_pt;
710 triangle_mesh_parameters.element_area() =
711 uniform_element_area;
713 Vector<double> lower_region(2);
718 triangle_mesh_parameters.add_region_coordinates(1, lower_region);
722 new RefineableSolidTriangleMesh<ELEMENT>(
723 triangle_mesh_parameters, this->time_stepper_pt());
726 Z2ErrorEstimator* error_estimator_pt=
new Z2ErrorEstimator;
727 Fluid_mesh_pt->spatial_error_estimator_pt()=error_estimator_pt;
730 Fluid_mesh_pt->max_permitted_error()=0.005;
731 Fluid_mesh_pt->min_permitted_error()=0.001;
732 Fluid_mesh_pt->max_element_size()=0.2;
733 Fluid_mesh_pt->min_element_size()=0.001;
736 if (CommandLineArgs::command_line_flag_has_been_set(
"--validation"))
738 Fluid_mesh_pt->min_element_size()=0.01;
742 this->Fluid_mesh_pt->output_boundaries(
"boundaries.dat");
743 this->Fluid_mesh_pt->output(
"mesh.dat");
746 complete_problem_setup();
749 Free_surface_mesh_pt=
new Mesh;
750 create_free_surface_elements();
756 this->add_sub_mesh(Fluid_mesh_pt);
759 this->add_sub_mesh(this->Free_surface_mesh_pt);
762 this->build_global_mesh();
765 cout <<
"Number of equations: " << this->assign_eqn_numbers() << std::endl;
774 template<
class ELEMENT>
779 unsigned nb=Fluid_mesh_pt->nboundary();
780 for(
unsigned b=4;b<nb;b++)
784 unsigned n_element = Fluid_mesh_pt->nboundary_element_in_region(b,0);
787 for(
unsigned e=0;e<n_element;e++)
791 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
792 Fluid_mesh_pt->boundary_element_in_region_pt(b,0,e));
795 int face_index = Fluid_mesh_pt->face_index_at_boundary_in_region(b,0,e);
798 ElasticLineFluidInterfaceElement<ELEMENT>* el_pt =
799 new ElasticLineFluidInterfaceElement<ELEMENT>(
800 bulk_elem_pt,face_index);
803 Free_surface_mesh_pt->add_element_pt(el_pt);
806 el_pt->set_boundary_number_in_bulk_mesh(b);
824 template<
class ELEMENT>
830 unsigned nbound=Fluid_mesh_pt->nboundary();
831 for(
unsigned ibound=0;ibound<nbound;ibound++)
833 unsigned num_nod=Fluid_mesh_pt->nboundary_node(ibound);
834 for (
unsigned inod=0;inod<num_nod;inod++)
837 Node* nod_pt=Fluid_mesh_pt->boundary_node_pt(ibound,inod);
840 if((ibound==1) || (ibound==3))
847 if((ibound==0) || (ibound==2)) {nod_pt->pin(0);}
850 SolidNode* solid_node_pt =
dynamic_cast<SolidNode*
>(nod_pt);
851 solid_node_pt->pin_position(0);
854 if((ibound==1) || (ibound==3))
856 solid_node_pt->pin_position(1);
860 solid_node_pt->unpin_position(1);
870 unsigned n_element = Fluid_mesh_pt->nelement();
871 for(
unsigned e=0;e<n_element;e++)
874 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(Fluid_mesh_pt->element_pt(e));
895 n_element = Fluid_mesh_pt->nregion_element(1);
896 for(
unsigned e=0;e<n_element;e++)
900 dynamic_cast<ELEMENT*
>(Fluid_mesh_pt->region_element_pt(1,e));
916 nbound=this->Fluid_mesh_pt->nboundary();
917 for(
unsigned ibound=0;ibound<nbound;++ibound)
920 unsigned num_nod=this->Fluid_mesh_pt->nboundary_node(ibound);
921 for (
unsigned inod=0;inod<num_nod;inod++)
924 Node* nod_pt=this->Fluid_mesh_pt->boundary_node_pt(ibound,inod);
927 unsigned n_prev=nod_pt->time_stepper_pt()->nprev_values();
931 if((ibound==1) || (ibound==3))
934 for (
unsigned t=0;t<=n_prev;t++)
936 nod_pt->set_value(t,0,0.0);
937 nod_pt->set_value(t,1,0.0);
940 nod_pt->x(t,0)=nod_pt->x(0,0);
941 nod_pt->x(t,1)=nod_pt->x(0,1);
946 if((ibound==0) || (ibound==2))
948 for (
unsigned t=0;t<=n_prev;t++)
950 nod_pt->set_value(t,0,0.0);
952 nod_pt->x(t,0)=nod_pt->x(0,0);
959 fix_pressure(0,0,0.0);
968 template<
class ELEMENT>
973 cout <<
"Time is now " << time_pt()->time() << std::endl;
975 double min_x_coordinate = 2.0;
976 unsigned min_boundary_node = 0;
978 unsigned n_bound = Fluid_mesh_pt->nboundary_node(4);
979 for(
unsigned n=0;n<n_bound;++n)
981 Node* nod_pt = Fluid_mesh_pt->boundary_node_pt(4,n);
982 if(nod_pt->x(0) < min_x_coordinate)
984 min_x_coordinate = nod_pt->x(0);
985 min_boundary_node = n;
992 << time_pt()->time() <<
" "
993 << Fluid_mesh_pt->boundary_node_pt(4,min_boundary_node)->x(1) << std::endl;
999 const unsigned npts = 5;
1002 sprintf(filename,
"%s/soln%i.dat",
1005 some_file.open(filename);
1008 Fluid_mesh_pt->output(some_file,npts);
1014 sprintf(filename,
"%s/interface_soln%i.dat",
1017 some_file.open(filename);
1020 Free_surface_mesh_pt->output(some_file,npts);
1032 template<
class ELEMENT>
1037 ErrorEstimator* err_est_pt=Fluid_mesh_pt->spatial_error_estimator_pt();
1040 unsigned nel=Fluid_mesh_pt->nelement();
1041 Vector<double> elemental_error(nel);
1046 Mesh* fluid_mesh_pt=
dynamic_cast<Mesh*
>(Fluid_mesh_pt);
1047 err_est_pt->get_element_errors(fluid_mesh_pt,
1053 for (
unsigned e=0;e<nel;e++)
1056 set_error(elemental_error[e]);
1058 max_err=std::max(max_err,elemental_error[e]);
1059 min_err=std::min(min_err,elemental_error[e]);
1072 CommandLineArgs::setup(argc,argv);
1078 CommandLineArgs::specify_command_line_flag(
"--validation");
1081 CommandLineArgs::parse_and_assign();
1084 CommandLineArgs::doc_specified_flags();
1098 const double epsilon = 0.1;
1101 const unsigned n_periods = 1;
1103 const double dt = 0.0025;
1108 problem.deform_interface(epsilon,n_periods);
1119 problem.initialise_dt(dt);
1122 problem.set_initial_condition();
1125 unsigned max_adapt = 2;
1128 problem.doc_solution();
1131 const unsigned n_timestep = unsigned(t_max/dt);
1134 bool first_timestep =
true;
1137 for(
unsigned t=1;t<=n_timestep;t++)
1140 cout <<
"\nTimestep " << t <<
" of " << n_timestep << std::endl;
1143 problem.unsteady_newton_solve(dt,max_adapt,first_timestep);
1146 first_timestep =
false;
1152 problem.doc_solution();
Problem class to simulate viscous drop propagating along 2D channel.
ELEMENT * Hijacked_element_pt
Pointer to hijacked element.
void doc_solution(const std::string &comment="")
Doc the solution.
Mesh * Free_surface_mesh_pt
Pointers to mesh of free surface elements.
void delete_free_surface_elements()
Delete free surface elements.
void actions_after_adapt()
Actions after adapt: Rebuild the mesh of free surface elements.
~TwoLayerInterfaceProblem()
Destructor.
void fix_pressure(const unsigned &e, const unsigned &pdof, const double &pvalue)
Fix pressure in element e at pressure dof pdof and set to pvalue.
void compute_error_estimate(double &max_err, double &min_err)
Compute the error estimates and assign to elements for plotting.
void actions_before_adapt()
Actions before adapt: Wipe the mesh of free surface elements.
void create_free_surface_elements()
Create free surface elements.
void complete_problem_setup()
Set boundary conditions and complete the build of all elements.
void actions_before_newton_solve()
Update the problem specs before solve.
void actions_after_newton_solve()
Update the after solve (empty)
TwoLayerInterfaceProblem()
Constructor.
void set_initial_condition()
Set the initial conditions.
Vector< TriangleMeshPolygon * > Drop_polygon_pt
Vector storing pointer to the drop polygons.
RefineableSolidTriangleMesh< ELEMENT > * Fluid_mesh_pt
Pointer to Fluid_mesh.
void deform_interface(const double &epsilon, const unsigned &n_periods)
Function to deform the interface.
bool Use_volume_constraint
Bool to indicate if volume constraint is applied (only for steady run)
TriangleMeshPolygon * Outer_boundary_polyline_pt
Triangle mesh polygon for outer boundary.
Data * Drop_pressure_data_pt
Pointer to a global drop pressure datum.
double Initial_value_for_drop_pressure
Backed up drop pressure between adaptations.
Overload CrouzeixRaviart element to modify output.
void set_error(const double &error)
Set error value for post-processing.
MyCrouzeixRaviartElement()
Constructor initialise error.
double Error
Storage for elemental error estimate – used for post-processing.
void output(std::ostream &outfile, const unsigned &nplot)
Overload output function.
std::string variable_identifier()
Return variable identifier.
//////////////////////////////////////////////////////// ////////////////////////////////////////////...
double ReSt
Womersley number (Reynolds x Strouhal)
DocInfo Doc_info
Doc info.
ofstream Norm_file
File to document the norm of the solution (for validation purposes – triangle doesn't give fully repr...
ofstream Trace_file
Trace file.
double Length
Length of the channel.
Vector< double > G(2)
Direction of gravity.
double Density_Ratio
Ratio of density in upper fluid to density in lower fluid. Reynolds number etc. is based on density i...
double St
Strouhal number.
ConstitutiveLaw * Constitutive_law_pt
Constitutive law used to determine the mesh deformation.
double ReInvFr
Product of Reynolds number and inverse of Froude number.
double Nu
Pseudo-solid Poisson ratio.
double Viscosity_Ratio
Ratio of viscosity in upper fluid to viscosity in lower fluid. Reynolds number etc....
double Re
Reynolds number.
double Ca
Capillary number.
int main(int argc, char **argv)
Driver code for moving block problem.