36 #include "navier_stokes.h"
37 #include "fluid_interface.h"
38 #include "constitutive.h"
42 #include "meshes/single_layer_spine_mesh.h"
47 using namespace oomph;
63 Vector<double> &normal)
76 template<
class ELEMENT>
91 void parameter_study(
const string& dir_name);
97 void create_volume_constraint_elements();
100 void doc_solution(DocInfo& doc_info);
146 template<
class ELEMENT>
151 Angle(0.5*MathematicalConstants::Pi)
165 double half_width=0.5;
169 new SingleLayerSpineMesh<SpineElement<ELEMENT> >(nx,nh,half_width,1.0);
180 unsigned n_boundary_element =
Bulk_mesh_pt->nboundary_element(2);
181 for(
unsigned e=0;e<n_boundary_element;e++)
184 FiniteElement *interface_element_pt =
185 new SpineLineFluidInterfaceElement<SpineElement<ELEMENT> >(
190 this->Surface_mesh_pt->add_element_pt(interface_element_pt);
193 unsigned n_node = interface_element_pt->nnode();
196 if(interface_element_pt->node_pt(n_node-1)->is_on_boundary(1))
199 FiniteElement* point_element_pt =
200 dynamic_cast<SpineLineFluidInterfaceElement<
201 SpineElement<ELEMENT>
>*>(interface_element_pt)
202 ->make_bounding_element(1);
230 Bulk_mesh_pt->element_pt(0))->hijack_internal_value(0,0);
249 dynamic_cast<ELEMENT*
>(
Bulk_mesh_pt->element_pt(0))->fix_pressure(0,0.0);
259 for(
unsigned e=0;e<n_interface;e++)
262 SpineLineFluidInterfaceElement<SpineElement<ELEMENT> >*el_pt=
263 dynamic_cast<SpineLineFluidInterfaceElement<SpineElement<ELEMENT>
>*>
267 el_pt->ca_pt() = &
Ca;
280 for (
unsigned b=0;b<n_bound;b++)
285 unsigned n_boundary_node =
Bulk_mesh_pt->nboundary_node(b);
287 for(
unsigned n=0;n<n_boundary_node;n++)
300 FluidInterfaceBoundingElement *contact_angle_element_pt
301 =
dynamic_cast<FluidInterfaceBoundingElement*
>(
304 contact_angle_element_pt->set_contact_angle(&
Angle);
305 contact_angle_element_pt->ca_pt() = &
Ca;
306 contact_angle_element_pt->wall_unit_normal_fct_pt()
317 this->build_global_mesh();
320 cout <<
"Number of unknowns: " << assign_eqn_numbers() << std::endl;
329 template<
class ELEMENT>
333 unsigned n_element = Volume_constraint_mesh_pt->nelement();
334 for(
unsigned e=0;e<n_element;e++)
335 {
delete Volume_constraint_mesh_pt->element_pt(e);}
337 Volume_constraint_mesh_pt->flush_element_and_node_storage();
339 delete Volume_constraint_mesh_pt;
342 if(Traded_pressure_data_pt!=External_pressure_data_pt)
343 {
delete Traded_pressure_data_pt;}
345 delete External_pressure_data_pt;
348 n_element = Point_mesh_pt->nelement();
349 for(
unsigned e=0;e<n_element;e++)
350 {
delete Point_mesh_pt->element_pt(e);}
352 Point_mesh_pt->flush_element_and_node_storage();
354 delete Point_mesh_pt;
357 n_element = Surface_mesh_pt->nelement();
358 for(
unsigned e=0;e<n_element;e++)
359 {
delete Surface_mesh_pt->element_pt(e);}
361 Surface_mesh_pt->flush_element_and_node_storage();
363 delete Surface_mesh_pt;
373 template<
class ELEMENT>
377 Volume_constraint_mesh_pt =
new Mesh;
378 VolumeConstraintElement* vol_constraint_element =
379 new VolumeConstraintElement(&Volume,Traded_pressure_data_pt,0);
380 Volume_constraint_mesh_pt->add_element_pt(vol_constraint_element);
383 for(
unsigned b=0;b<4;b++)
386 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
389 for(
unsigned e=0;e<n_element;e++)
393 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
394 Bulk_mesh_pt->boundary_element_pt(b,e));
397 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
400 SpineLineVolumeConstraintBoundingElement<ELEMENT>* el_pt =
401 new SpineLineVolumeConstraintBoundingElement<ELEMENT>(
402 bulk_elem_pt,face_index);
405 el_pt->set_volume_constraint_element(vol_constraint_element);
408 Volume_constraint_mesh_pt->add_element_pt(el_pt);
418 template<
class ELEMENT>
424 doc_info.set_directory(dir_name);
430 sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
431 Trace_file.open(filename);
432 Trace_file <<
"VARIABLES=\"<greek>a</greek><sub>prescribed</sub>\",";
433 Trace_file <<
"\"h<sub>left</sub>\",\"h<sub>right</sub>\",";
434 Trace_file <<
"\"p<sub>fluid</sub>-p<sub>ext</sub>\",";
435 Trace_file <<
"\"<greek>D</greek>p<sub>exact</sub>\"";
436 Trace_file << std::endl;
439 for(
unsigned i=0;i<6;i++)
442 steady_newton_solve();
445 doc_solution(doc_info);
451 Angle -= 5.0*MathematicalConstants::Pi/180.0;
462 template<
class ELEMENT>
474 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
476 some_file.open(filename);
477 Bulk_mesh_pt->output(some_file,npts);
478 Surface_mesh_pt->output(some_file,npts);
483 unsigned nspine=Bulk_mesh_pt->nspine();
486 Trace_file << Angle*180.0/MathematicalConstants::Pi;
487 Trace_file <<
" " << Bulk_mesh_pt->spine_pt(0)->height();
488 Trace_file <<
" " << Bulk_mesh_pt->spine_pt(nspine-1)->height();
490 <<
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(0))
491 ->p_nst(0)- External_pressure_data_pt->value(0);
492 Trace_file <<
" " << -2.0*cos(Angle)/Ca;
493 Trace_file << std::endl;
503 template<
class ELEMENT>
583 template<
class ELEMENT>
588 Angle(0.5*MathematicalConstants::Pi)
602 double half_width=0.5;
605 Bulk_mesh_pt =
new ElasticRectangularQuadMesh<ELEMENT>(nx,nh,half_width,1.0);
628 Bulk_mesh_pt->element_pt(0))->hijack_internal_value(0,0);
647 dynamic_cast<ELEMENT*
>(
Bulk_mesh_pt->element_pt(0))->fix_pressure(0,0.0);
656 for(
unsigned e=0;e<n_bulk;e++)
671 for (
unsigned b=0;b<n_bound;b++)
676 unsigned n_boundary_node =
Bulk_mesh_pt->nboundary_node(b);
678 for(
unsigned n=0;n<n_boundary_node;n++)
690 for (
unsigned b=0;b<n_bound;b++)
695 unsigned n_boundary_node =
Bulk_mesh_pt->nboundary_node(b);
697 for(
unsigned n=0;n<n_boundary_node;n++)
702 static_cast<SolidNode*
>(
Bulk_mesh_pt->boundary_node_pt(b,n))
708 static_cast<SolidNode*
>(
Bulk_mesh_pt->boundary_node_pt(b,n))
718 for(
unsigned n=0;n<n_node;n++)
720 static_cast<SolidNode*
>(
Bulk_mesh_pt->node_pt(n))->pin_position(0);
741 this->build_global_mesh();
744 cout <<
"Number of unknowns: " << assign_eqn_numbers() << std::endl;
753 template<
class ELEMENT>
757 delete Free_surface_bounding_mesh_pt->element_pt(0);
758 Free_surface_bounding_mesh_pt->flush_element_and_node_storage();
759 delete Free_surface_bounding_mesh_pt;
761 delete Volume_constraint_mesh_pt;
763 unsigned n_element = Volume_computation_mesh_pt->nelement();
764 for(
unsigned e=0;e<n_element;e++)
765 {
delete Volume_computation_mesh_pt->element_pt(e);}
767 Volume_computation_mesh_pt->flush_element_and_node_storage();
769 delete Volume_computation_mesh_pt;
771 n_element = Free_surface_mesh_pt->nelement();
772 for(
unsigned e=0;e<n_element;e++)
773 {
delete Free_surface_mesh_pt->element_pt(e);}
775 Free_surface_mesh_pt->flush_element_and_node_storage();
777 delete Free_surface_mesh_pt;
780 delete Constitutive_law_pt;
783 if(Traded_pressure_data_pt!=External_pressure_data_pt)
784 {
delete Traded_pressure_data_pt;}
786 delete External_pressure_data_pt;
794 template<
class ELEMENT>
798 Free_surface_mesh_pt =
new Mesh;
804 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
807 for(
unsigned e=0;e<n_element;e++)
811 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
812 Bulk_mesh_pt->boundary_element_pt(b,e));
815 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
818 ElasticLineFluidInterfaceElement<ELEMENT>* el_pt =
819 new ElasticLineFluidInterfaceElement<ELEMENT>(
820 bulk_elem_pt,face_index);
823 Free_surface_mesh_pt->add_element_pt(el_pt);
826 el_pt->set_boundary_number_in_bulk_mesh(b);
829 el_pt->ca_pt() = &Ca;
832 el_pt->set_external_pressure_data(External_pressure_data_pt);
841 template<
class ELEMENT>
845 Volume_constraint_mesh_pt =
new Mesh;
846 VolumeConstraintElement* vol_constraint_element =
847 new VolumeConstraintElement(&Volume,Traded_pressure_data_pt,0);
848 Volume_constraint_mesh_pt->add_element_pt(vol_constraint_element);
851 Volume_computation_mesh_pt =
new Mesh;
854 for(
unsigned b=0;b<4;b++)
857 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
860 for(
unsigned e=0;e<n_element;e++)
864 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
865 Bulk_mesh_pt->boundary_element_pt(b,e));
868 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
871 ElasticLineVolumeConstraintBoundingElement<ELEMENT>* el_pt =
872 new ElasticLineVolumeConstraintBoundingElement<ELEMENT>(
873 bulk_elem_pt,face_index);
876 el_pt->set_volume_constraint_element(vol_constraint_element);
879 Volume_computation_mesh_pt->add_element_pt(el_pt);
887 template<
class ELEMENT>
890 Free_surface_bounding_mesh_pt =
new Mesh;
894 unsigned n_free_surface = Free_surface_mesh_pt->nelement();
898 FluidInterfaceBoundingElement* el_pt =
899 dynamic_cast<ElasticLineFluidInterfaceElement<ELEMENT>*
>
900 (Free_surface_mesh_pt->element_pt(n_free_surface-1))->
901 make_bounding_element(1);
904 el_pt->set_contact_angle(&Angle);
907 el_pt->ca_pt() = &Ca;
910 el_pt->wall_unit_normal_fct_pt()
914 Free_surface_bounding_mesh_pt->add_element_pt(el_pt);
924 template<
class ELEMENT>
929 doc_info.set_directory(dir_name);
934 sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
935 Trace_file.open(filename);
936 Trace_file <<
"VARIABLES=\"<greek>a</greek><sub>prescribed</sub>\",";
937 Trace_file <<
"\"h<sub>left</sub>\",\"h<sub>right</sub>\",";
938 Trace_file <<
"\"p<sub>fluid</sub>-p<sub>ext</sub>\",";
939 Trace_file <<
"\"<greek>D</greek>p<sub>exact</sub>\"";
940 Trace_file << std::endl;
943 for(
unsigned i=0;i<6;i++)
946 steady_newton_solve();
949 doc_solution(doc_info);
955 Angle -= 5.0*MathematicalConstants::Pi/180.0;
966 template<
class ELEMENT>
977 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
979 some_file.open(filename);
980 Bulk_mesh_pt->output(some_file,npts);
985 unsigned ninterface=Free_surface_mesh_pt->nelement();
987 unsigned np = Free_surface_mesh_pt->finite_element_pt(ninterface-1)->nnode();
992 Trace_file << Angle*180.0/MathematicalConstants::Pi;
993 Trace_file <<
" " << Free_surface_mesh_pt->finite_element_pt(0)
996 << Free_surface_mesh_pt->finite_element_pt(ninterface-1)
997 ->node_pt(np-1)->x(1);
999 <<
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(0))->p_nst(0)-
1000 External_pressure_data_pt->value(0);
1001 Trace_file <<
" " << -2.0*cos(Angle)/Ca;
1002 Trace_file << std::endl;
1017 for (
unsigned i=0;i<2;i++)
1020 bool hijack_internal=
false;
1021 if (i==1) hijack_internal=
true;
1025 string dir_name=
"RESLT_hijacked_external";
1026 if (i==1) dir_name=
"RESLT_hijacked_internal";
1036 for (
unsigned i=0;i<2;i++)
1038 bool hijack_internal=
false;
1039 if (i==1) hijack_internal=
true;
1042 PseudoSolidNodeUpdateElement<QCrouzeixRaviartElement<2>,
1043 QPVDElementWithPressure<2> > > > problem(hijack_internal);
1045 string dir_name=
"RESLT_elastic_hijacked_external";
1046 if (i==1) dir_name=
"RESLT_elastic_hijacked_internal";
1049 problem.parameter_study(dir_name);
A Problem class that solves the Navier–Stokes equations + free surface in a 2D geometry using a spine...
Mesh * Volume_constraint_mesh_pt
The volume constraint mesh.
Data * Traded_pressure_data_pt
Data that is traded for the volume constraint.
Mesh * Surface_mesh_pt
The mesh for the interface elements.
Data * External_pressure_data_pt
Data object whose single value stores the external pressure.
ofstream Trace_file
Trace file.
void parameter_study()
Peform a parameter study: Solve problem for a range of contact angles.
SingleLayerSpineMesh< SpineElement< ELEMENT > > * Bulk_mesh_pt
The bulk mesh of fluid elements.
double Pext
The external pressure.
double Angle
The contact angle.
void doc_solution(DocInfo &doc_info)
Doc the solution.
void create_volume_constraint_elements()
Create the volume constraint elements.
CapProblem(const bool &hijack_internal)
Constructor: Pass boolean flag to indicate if the volume constraint is applied by hijacking an intern...
double Volume
The volume of the fluid.
void actions_before_newton_convergence_check()
Update the spine mesh after every Newton step.
Mesh * Point_mesh_pt
The mesh for the element at the contact point.
~CapProblem()
Destructor. Make sure to clean up all allocated memory, so that multiple instances of the problem don...
double Ca
The Capillary number.
void parameter_study(const string &dir_name)
Perform a parameter study: Solve problem for a range of contact angles Pass name of output directory ...
A class that solves the Navier–Stokes equations to compute the shape of a static interface in a recta...
void create_volume_constraint_elements()
Create the volume constraint elements.
Mesh * Volume_computation_mesh_pt
Storage for the elements that compute the enclosed volume.
void doc_solution(DocInfo &doc_info)
Doc the solution.
double Volume
The prescribed volume of the fluid.
PseudoSolidCapProblem(const bool &hijack_internal)
Constructor: Boolean flag indicates if volume constraint is applied by hijacking internal or external...
Data * External_pressure_data_pt
Data object whose single value stores the external pressure.
double Angle
The contact angle.
Data * Traded_pressure_data_pt
Mesh * Volume_constraint_mesh_pt
Storage for the volume constraint.
Mesh * Bulk_mesh_pt
Storage for the bulk mesh.
ofstream Trace_file
Trace file.
void create_contact_angle_element()
Create the contact angle element.
ConstitutiveLaw * Constitutive_law_pt
Constitutive law used to determine the mesh deformation.
Mesh * Free_surface_bounding_mesh_pt
Storage for the element bounding the free surface.
void create_free_surface_elements()
Create the free surface elements.
Mesh * Free_surface_mesh_pt
Storage for the free surface mesh.
double Ca
The Capillary number.
void parameter_study(const string &dir_name)
Peform a parameter study: Solve problem for a range of contact angles Pass name of output directory a...
~PseudoSolidCapProblem()
Destructor: clean up memory allocated by the object.
double Pext
The external pressure.
Namespace for phyical parameters.
void wall_unit_normal_fct(const Vector< double > &x, Vector< double > &normal)
Function that specifies the wall unit normal.
double Nu
Pseudo-solid Poisson ratio.
Vector< double > Wall_normal
Direction of the wall normal vector.
int main()
Main driver: Build problem and initiate parameter study.