41 #include "navier_stokes.h"
43 #include "fluid_interface.h"
44 #include "meshes/simple_rectangular_quadmesh.h"
48 using namespace oomph;
66 Vector<double>
G(2,0.0);
85 Vector<double> &normal)
92 Vector<double> &normal)
97 unsigned n_dim = normal.size();
98 for(
unsigned i=0;i<n_dim;++i) {normal[i] *= -1.0;}
107 const Vector<double> &n,
108 Vector<double> &traction)
110 traction[0] =
ReInvFr*
G[1]*(1.0 - x[1]);
116 const Vector<double> &n,
117 Vector<double> &traction)
119 traction[0] = -
ReInvFr*
G[1]*(1.0 - x[1]);
137 template<
class ELEMENT,
class INTERFACE_ELEMENT>
162 const double &length) :
163 Output_prefix(
"Unset") { }
169 void timestep(
const double &dt,
const unsigned &n_tsteps);
176 double time = this->time_pt()->time();
179 double epsilon = 0.01;
181 unsigned n_node = this->Bulk_mesh_pt->nboundary_node(0);
182 for(
unsigned n=0;n<n_node;n++)
184 Node* nod_pt = this->Bulk_mesh_pt->boundary_node_pt(0,n);
186 double value = sin(arg)*epsilon*time*exp(-time);
187 nod_pt->set_value(1,value);
196 Traction_mesh_pt =
new Mesh;
201 unsigned n_boundary_element = Bulk_mesh_pt->nboundary_element(b);
203 for(
unsigned e=0;e<n_boundary_element;e++)
205 NavierStokesTractionElement<ELEMENT> *surface_element_pt =
206 new NavierStokesTractionElement<ELEMENT>
207 (Bulk_mesh_pt->boundary_element_pt(b,e),
208 Bulk_mesh_pt->face_index_at_boundary(b,e));
210 Traction_mesh_pt->add_element_pt(surface_element_pt);
212 surface_element_pt->traction_fct_pt() =
221 unsigned n_boundary_element = Bulk_mesh_pt->nboundary_element(b);
223 for(
unsigned e=0;e<n_boundary_element;e++)
225 NavierStokesTractionElement<ELEMENT> *surface_element_pt =
226 new NavierStokesTractionElement<ELEMENT>
227 (Bulk_mesh_pt->boundary_element_pt(b,e),
228 Bulk_mesh_pt->face_index_at_boundary(b,e));
230 Traction_mesh_pt->add_element_pt(surface_element_pt);
232 surface_element_pt->traction_fct_pt() =
242 Surface_mesh_pt =
new Mesh;
243 Point_mesh_pt =
new Mesh;
247 unsigned n_boundary_element = Bulk_mesh_pt->nboundary_element(b);
249 for(
unsigned e=0;e<n_boundary_element;e++)
251 INTERFACE_ELEMENT *surface_element_pt =
252 new INTERFACE_ELEMENT
253 (Bulk_mesh_pt->boundary_element_pt(b,e),
254 Bulk_mesh_pt->face_index_at_boundary(b,e));
256 Surface_mesh_pt->add_element_pt(surface_element_pt);
258 surface_element_pt->ca_pt() =
266 FluidInterfaceBoundingElement* point_element_pt =
267 surface_element_pt->make_bounding_element(-1);
269 Point_mesh_pt->add_element_pt(point_element_pt);
273 point_element_pt->wall_unit_normal_fct_pt() =
276 point_element_pt->set_contact_angle(
283 if(e==n_boundary_element-1)
285 FluidInterfaceBoundingElement* point_element_pt =
286 surface_element_pt->make_bounding_element(1);
288 Point_mesh_pt->add_element_pt(point_element_pt);
292 point_element_pt->wall_unit_normal_fct_pt() =
306 unsigned n_element = Bulk_mesh_pt->nelement();
308 for(
unsigned e=0;e<n_element;e++)
311 ELEMENT *temp_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
314 temp_pt->re_pt() = &
Re;
316 temp_pt->re_st_pt() = &
Re;
318 temp_pt->re_invfr_pt() = &
ReInvFr;
320 temp_pt->g_pt() = &
G;
327 bool elastic =
false;
328 if(
dynamic_cast<SolidNode*
>(Bulk_mesh_pt->node_pt(0))) {elastic=
true;}
331 unsigned n_node = Bulk_mesh_pt->nboundary_node(0);
332 for(
unsigned j=0;j<n_node;j++)
335 Bulk_mesh_pt->boundary_node_pt(0,j)->pin(0);
336 Bulk_mesh_pt->boundary_node_pt(0,j)->pin(1);
342 static_cast<SolidNode*
>(Bulk_mesh_pt->boundary_node_pt(0,j))
344 static_cast<SolidNode*
>(Bulk_mesh_pt->boundary_node_pt(0,j))
351 n_node = Bulk_mesh_pt->nboundary_node(3);
352 for(
unsigned j=0;j<n_node;j++)
354 Bulk_mesh_pt->boundary_node_pt(3,j)->pin(1);
359 static_cast<SolidNode*
>(Bulk_mesh_pt->boundary_node_pt(3,j))
366 n_node = Bulk_mesh_pt->nboundary_node(1);
367 for(
unsigned j=0;j<n_node;j++)
369 Bulk_mesh_pt->boundary_node_pt(1,j)->pin(1);
374 static_cast<SolidNode*
>(Bulk_mesh_pt->boundary_node_pt(1,j))
381 std::cout << assign_eqn_numbers() <<
" in the main problem" << std::endl;
389 this->Point_mesh_pt->flush_node_storage();
391 delete this->Point_mesh_pt;
393 this->Surface_mesh_pt->flush_node_storage();
394 delete this->Surface_mesh_pt;
396 this->Traction_mesh_pt->flush_node_storage();
397 delete this->Traction_mesh_pt;
399 delete this->Bulk_mesh_pt;
401 delete this->time_stepper_pt();
410 template<
class ELEMENT,
class INTERFACE_ELEMENT>
418 unsigned n_node = Bulk_mesh_pt->nnode();
419 for(
unsigned n=0;n<n_node;n++)
421 double y = Bulk_mesh_pt->node_pt(n)->x(1);
423 Bulk_mesh_pt->node_pt(n)->set_value(0,0.5*
ReInvFr*sin(
Alpha)*(2.0*y - y*y));
428 steady_newton_solve();
431 std::string filename = Output_prefix;;
432 filename.append(
"_output.dat");
433 ofstream file(filename.c_str());
434 Bulk_mesh_pt->output(file,5);
442 template<
class ELEMENT,
class INTERFACE_ELEMENT>
444 timestep(
const double &dt,
const unsigned &n_tsteps)
450 std::string filename = Output_prefix;
451 filename.append(
"_time_trace.dat");
452 ofstream trace(filename.c_str());
459 trace << time_pt()->time() <<
" "
460 << Bulk_mesh_pt->boundary_node_pt(2,0)->value(1)
463 boundary_node_pt(2, Bulk_mesh_pt->nboundary_node(2)-1)->x(1)
468 for(
unsigned t=1;t<=n_tsteps;t++)
473 cout <<
"--------------TIMESTEP " << t<<
" ------------------" << std::endl;
476 unsteady_newton_solve(dt);
482 std::ostringstream filename;
483 filename << Output_prefix <<
"_step" <<
Re <<
"_" << t <<
".dat";
484 file.open(filename.str().c_str());
485 Bulk_mesh_pt->output(file,5);
494 std::ostringstream filename;
495 filename << Output_prefix <<
"_interface_" <<
Re <<
"_" << t <<
".dat";
496 file.open(filename.str().c_str());
497 Surface_mesh_pt->output(file,5);
503 trace << time_pt()->time() <<
" "
504 << Bulk_mesh_pt->boundary_node_pt(2,0)->x(1) <<
" "
507 boundary_node_pt(2,Bulk_mesh_pt->nboundary_node(2)-1)->x(1) <<
" "
521 template <
class ELEMENT>
523 public SimpleRectangularQuadMesh<ELEMENT>,
528 const double &lx,
const double &ly,
529 TimeStepper* time_stepper_pt) :
530 SimpleRectangularQuadMesh<ELEMENT>
531 (nx,ny,lx,ly,time_stepper_pt), SpineMesh()
534 unsigned n_p =
dynamic_cast<ELEMENT*
>(finite_element_pt(0))->nnode_1d();
536 Spine_pt.reserve((n_p-1)*nx + 1);
539 Spine* new_spine_pt=0;
542 for(
unsigned long j=0;j<nx;j++)
546 unsigned n_pmax = n_p-1;
548 if(j==nx-1) {n_pmax = n_p;}
551 for(
unsigned l2=0;l2<n_pmax;l2++)
554 new_spine_pt=
new Spine(1.0);
555 Spine_pt.push_back(new_spine_pt);
558 SpineNode* nod_pt=element_node_pt(j,l2);
560 nod_pt->spine_pt() = new_spine_pt;
562 nod_pt->fraction() = 0.0;
564 nod_pt->spine_mesh_pt() =
this;
568 for(
unsigned long i=0;i<ny;i++)
571 for(
unsigned l1=1;l1<n_p;l1++)
574 SpineNode* nod_pt=element_node_pt(i*nx+j,l1*n_p+l2);
576 nod_pt->spine_pt() = new_spine_pt;
578 nod_pt->fraction()=(double(i)+double(l1)/double(n_p-1))/
double(ny);
580 nod_pt->spine_mesh_pt() =
this;
593 double W = spine_node_pt->fraction();
595 double H = spine_node_pt->h();
597 spine_node_pt->x(1) = W*H;
606 template<
class ELEMENT,
class TIMESTEPPER>
614 const double &length):
619 this->Output_prefix =
"spine";
622 this->add_time_stepper_pt(
new TIMESTEPPER);
626 nx,ny,length,1.0,this->time_stepper_pt());
629 this->make_traction_elements();
631 this->make_free_surface_elements();
634 this->add_sub_mesh(this->Bulk_mesh_pt);
635 this->add_sub_mesh(this->Traction_mesh_pt);
636 this->add_sub_mesh(this->Surface_mesh_pt);
637 this->add_sub_mesh(this->Point_mesh_pt);
639 this->build_global_mesh();
642 this->complete_build();
650 {this->Bulk_mesh_pt->node_update();}
663 template <
class ELEMENT>
665 public SimpleRectangularQuadMesh<ELEMENT>,
671 const double &lx,
const double &ly,
672 TimeStepper* time_stepper_pt) :
673 SimpleRectangularQuadMesh<ELEMENT>(nx,ny,lx,ly,time_stepper_pt), SolidMesh()
676 set_lagrangian_nodal_coordinates();
686 template<
class ELEMENT,
class TIMESTEPPER>
693 const double &length) :
698 this->Output_prefix =
"elastic";
701 this->add_time_stepper_pt(
new TIMESTEPPER);
705 nx,ny,length,1.0,this->time_stepper_pt());
708 unsigned n_element = this->Bulk_mesh_pt->nelement();
710 for(
unsigned e=0;e<n_element;e++)
713 ELEMENT *temp_pt =
dynamic_cast<ELEMENT*
>(
714 this->Bulk_mesh_pt->element_pt(e));
716 temp_pt->constitutive_law_pt() =
721 this->make_traction_elements();
723 this->make_free_surface_elements();
726 this->add_sub_mesh(this->Bulk_mesh_pt);
727 this->add_sub_mesh(this->Traction_mesh_pt);
728 this->add_sub_mesh(this->Surface_mesh_pt);
729 this->add_sub_mesh(this->Point_mesh_pt);
731 this->build_global_mesh();
734 this->complete_build();
742 unsigned n_node = this->Bulk_mesh_pt->nnode();
743 for(
unsigned n=0;n<n_node;n++)
747 static_cast<SolidNode*
>(this->Bulk_mesh_pt->node_pt(n));
748 for(
unsigned j=0;j<2;j++) {temp_pt->xi(j) = temp_pt->x(j);}
756 int main(
int argc,
char **argv)
764 #define FLUID_ELEMENT QCrouzeixRaviartElement<2>
766 #define FLUID_ELEMENT QTaylorHoodElement<2>
794 problem.assign_initial_values_impulsive(dt);
805 PseudoSolidNodeUpdateElement<FLUID_ELEMENT,QPVDElement<2,3> >, BDF<2> >
809 problem.solve_steady();
814 problem.assign_initial_values_impulsive(dt);
817 problem.timestep(dt,2);
Create an Elastic mesh for the problem.
ElasticInclinedPlaneMesh(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly, TimeStepper *time_stepper_pt)
ElasticInclinedPlaneProblem(const unsigned &nx, const unsigned &ny, const double &length)
void actions_after_implicit_timestep()
Update Lagrangian positions after each timestep (updated-lagrangian approach)
Generic problem class that will form the base class for both spine and elastic mesh-updates of the pr...
void solve_steady()
Solve the steady problem.
Mesh * Bulk_mesh_pt
Bulk fluid mesh.
void make_traction_elements()
Function to add the traction boundary elements to boundaries 3(inlet) and 1(outlet) of the mesh.
InclinedPlaneProblem(const unsigned &nx, const unsigned &ny, const double &length)
Generic Constructor (empty)
std::string Output_prefix
Prefix for output files.
void timestep(const double &dt, const unsigned &n_tsteps)
Take n_tsteps timesteps of size dt.
void make_free_surface_elements()
Mesh * Traction_mesh_pt
Mesh for the traction elements that are added at inlet and outlet.
Mesh * Surface_mesh_pt
Mesh for the free surface elements.
~InclinedPlaneProblem()
Generic desructor to clean up the memory allocated in the problem.
Mesh * Point_mesh_pt
Mesh for the point elements at each end of the free surface.
void complete_build()
Complete the build of the problem setting all standard parameters and boundary conditions.
void actions_before_implicit_timestep()
Actions before the timestep (update the time-dependent boundary conditions)
Create a spine mesh for the problem.
virtual void spine_node_update(SpineNode *spine_node_pt)
General node update function implements pure virtual function defined in SpineMesh base class and per...
SpineInclinedPlaneMesh(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly, TimeStepper *time_stepper_pt)
SpineInclinedPlaneProblem(const unsigned &nx, const unsigned &ny, const double &length)
void actions_before_newton_convergence_check()
Spine heights/lengths are unknowns in the problem so their values get corrected during each Newton st...
int main(int argc, char **argv)
double Inlet_Angle
The contact angle that is imposed at the inlet (pi)
ConstitutiveLaw * Constitutive_law_pt
Constitutive law used to determine the mesh deformation.
double Nu
Pseudo-solid Poisson ratio.
Vector< double > Wall_normal
Direction of the wall normal vector (at the inlet)
void wall_unit_normal_outlet_fct(const Vector< double > &x, Vector< double > &normal)
Function that specified the wall unit normal at the outlet.
double Ca
The Capillary number.
double Length
The length of the domain to fit the desired number of waves.
double K
Set the wavenumber.
void wall_unit_normal_inlet_fct(const Vector< double > &x, Vector< double > &normal)
Function that specifies the wall unit normal at the inlet.
double Alpha
Angle of incline of the slope (45 degrees)
double ReInvFr
The product of Reynolds number and inverse Froude number is set to two in this problem,...
Vector< double > G(2, 0.0)
The Vector direction of gravity, set in main()
void hydrostatic_pressure_outlet(const double &time, const Vector< double > &x, const Vector< double > &n, Vector< double > &traction)
Function that prescribes the hydrostatic pressure field at the outlet.
double Re
Reynolds number, based on the average velocity within the fluid film.
double N_wave
Set the number of waves desired in the domain.
void hydrostatic_pressure_inlet(const double &time, const Vector< double > &x, const Vector< double > &n, Vector< double > &traction)
Function that prescribes hydrostatic pressure field at the inlet.