elastic_two_layer_interface_axisym.cc
Go to the documentation of this file.
1 //LIC// ====================================================================
2 //LIC// This file forms part of oomph-lib, the object-oriented,
3 //LIC// multi-physics finite-element library, available
4 //LIC// at http://www.oomph-lib.org.
5 //LIC//
6 //LIC// Copyright (C) 2006-2023 Matthias Heil and Andrew Hazel
7 //LIC//
8 //LIC// This library is free software; you can redistribute it and/or
9 //LIC// modify it under the terms of the GNU Lesser General Public
10 //LIC// License as published by the Free Software Foundation; either
11 //LIC// version 2.1 of the License, or (at your option) any later version.
12 //LIC//
13 //LIC// This library is distributed in the hope that it will be useful,
14 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 //LIC// Lesser General Public License for more details.
17 //LIC//
18 //LIC// You should have received a copy of the GNU Lesser General Public
19 //LIC// License along with this library; if not, write to the Free Software
20 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 //LIC// 02110-1301 USA.
22 //LIC//
23 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 //LIC//
25 //LIC//====================================================================
26 // Driver for an adaptive axisymmetric two fluid interface problem,
27 // where the mesh is deformed using a pseudo-solid node-update strategy
28 
29 // Generic oomph-lib header
30 #include "generic.h"
31 
32 // Axisymmetric Navier-Stokes headers
33 #include "axisym_navier_stokes.h"
34 #include "navier_stokes.h"
35 
36 // Interface headers
37 #include "fluid_interface.h"
38 
39 // Constitutive law headers
40 #include "constitutive.h"
41 
42 // Solid headers
43 #include "solid.h"
44 
45 // Bessel function headers
46 #include "oomph_crbond_bessel.h"
47 
48 // The mesh
49 #include "meshes/rectangular_quadmesh.h"
50 
51 using namespace std;
52 
53 using namespace oomph;
54 
55 
56 //==start_of_namespace====================================================
57 /// Namespace for physical parameters
58 //========================================================================
60 {
61 
62  /// Reynolds number
63  double Re = 5.0;
64 
65  /// Strouhal number
66  double St = 1.0;
67 
68  /// Womersley number (Reynolds x Strouhal)
69  double ReSt = 5.0;
70 
71  /// Product of Reynolds number and inverse of Froude number
72  double ReInvFr = 5.0;
73 
74  /// Ratio of viscosity in upper fluid to viscosity in lower
75  /// fluid. Reynolds number etc. is based on viscosity in lower fluid.
76  double Viscosity_Ratio = 0.1;
77 
78  /// Ratio of density in upper fluid to density in lower
79  /// fluid. Reynolds number etc. is based on density in lower fluid.
80  double Density_Ratio = 0.5;
81 
82  /// Capillary number
83  double Ca = 0.01;
84 
85  /// Direction of gravity
86  Vector<double> G(3);
87 
88  /// Pseudo-solid Poisson ratio
89  double Nu = 0.1;
90 
91 } // End of namespace
92 
93 
94 /// ///////////////////////////////////////////////////////////////////////
95 /// ///////////////////////////////////////////////////////////////////////
96 /// ///////////////////////////////////////////////////////////////////////
97 
98 
99 //==start_of_specific_mesh_class==========================================
100 /// Two layer mesh which employs a pseudo-solid node-update strategy.
101 /// This class is essentially a wrapper to an
102 /// ElasticRefineableRectangularQuadMesh, with an additional boundary
103 /// to represent the interface between the two fluid layers.
104 //========================================================================
105 template <class ELEMENT>
107  public virtual ElasticRefineableRectangularQuadMesh<ELEMENT>
108 {
109 
110 public:
111 
112  /// Constructor: Pass number of elements in x-direction, number of
113  /// elements in y-direction in bottom and top layer, respectively,
114  /// axial length and height of top and bottom layers, and pointer
115  /// to timestepper (defaults to Steady timestepper)
116  ElasticRefineableTwoLayerMesh(const unsigned &nx,
117  const unsigned &ny1,
118  const unsigned &ny2,
119  const double &lx,
120  const double &h1,
121  const double &h2,
122  TimeStepper* time_stepper_pt=
123  &Mesh::Default_TimeStepper)
124  : RectangularQuadMesh<ELEMENT>(nx,ny1+ny2,lx,h1+h2,
125  false,time_stepper_pt),
126  ElasticRectangularQuadMesh<ELEMENT>(nx,ny1+ny2,lx,h1+h2,
127  false,time_stepper_pt),
128  ElasticRefineableRectangularQuadMesh<ELEMENT>(nx,ny1+ny2,lx,h1+h2,
129  false,time_stepper_pt)
130  {
131  // ----------------------------------------------------
132  // Convert all nodes on the interface to boundary nodes
133  // ----------------------------------------------------
134 
135  // Set the number of boundaries to 5
136  this->set_nboundary(5);
137 
138  // Loop over horizontal elements
139  for(unsigned e=0;e<nx;e++)
140  {
141  // Get pointer to element in lower fluid adjacent to interface
142  FiniteElement* el_pt = this->finite_element_pt(nx*(ny1-1)+e);
143 
144  // Determine number of nodes in this element
145  const unsigned n_node = el_pt->nnode();
146 
147  // The last three nodes in this element are those on the interface.
148  // Loop over these nodes and convert them to boundary nodes.
149  for(unsigned n=0;n<3;n++)
150  {
151  Node* nod_pt = el_pt->node_pt(n_node-3+n);
152  this->convert_to_boundary_node(nod_pt);
153  this->add_boundary_node(4,nod_pt);
154  }
155  } // End of loop over horizontal elements
156 
157  // Set up the boundary element information
158  this->setup_boundary_element_info();
159  }
160 
161 }; // End of specific mesh class
162 
163 
164 /// ///////////////////////////////////////////////////////////////////////
165 /// ///////////////////////////////////////////////////////////////////////
166 /// ///////////////////////////////////////////////////////////////////////
167 
168 
169 //==start_of_problem_class================================================
170 /// Axisymmetric two fluid interface problem in a rectangular domain
171 //========================================================================
172 template <class ELEMENT, class TIMESTEPPER>
173 class InterfaceProblem : public Problem
174 {
175 
176 public:
177 
178  /// Constructor
180 
181  /// Destructor (empty)
183 
184  /// Set initial conditions
185  void set_initial_condition();
186 
187  /// Set boundary conditions
188  void set_boundary_conditions();
189 
190  /// Document the solution
191  void doc_solution(DocInfo &doc_info);
192 
193  /// Do unsteady run up to maximum time t_max with given timestep dt
194  void unsteady_run(const double &t_max, const double &dt);
195 
196 private:
197 
198  /// No actions required before solve step
200 
201  /// No actions required after solve step
203 
204  /// Actions before the timestep: For maximum stability, reset
205  /// the current nodal positions to be the "stress-free" ones.
207  {
208  Bulk_mesh_pt->set_lagrangian_nodal_coordinates();
209  }
210 
211  /// Strip off the interface elements before adapting the bulk mesh
212  void actions_before_adapt();
213 
214  /// Rebuild the mesh of interface elements after adapting the bulk mesh
215  void actions_after_adapt();
216 
217  /// Create the 1d interface elements
218  void create_interface_elements();
219 
220  /// Delete the 1d interface elements
221  void delete_interface_elements();
222 
223  /// Deform the mesh/free surface to a prescribed function
224  void deform_free_surface(const double &epsilon, const double &k);
225 
226  /// Fix pressure in element e at pressure dof pdof and set to pvalue
227  void fix_pressure(const unsigned &e,
228  const unsigned &pdof,
229  const double &pvalue)
230  {
231  // Fix the pressure at that element
232  dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e))->
233  fix_pressure(pdof,pvalue);
234  }
235 
236  /// Pointer to the (specific) "bulk" mesh
238 
239  /// Pointer to the "surface" mesh
241 
242  // Pointer to the constitutive law used to determine the mesh deformation
243  ConstitutiveLaw* Constitutive_law_pt;
244 
245  /// Width of domain
246  double Lr;
247 
248  /// Trace file
249  ofstream Trace_file;
250 
251 }; // End of problem class
252 
253 
254 
255 //==start_of_constructor==================================================
256 /// Constructor for axisymmetric two fluid interface problem
257 //========================================================================
258 template <class ELEMENT, class TIMESTEPPER>
261 {
262  // Allocate the timestepper (this constructs the time object as well)
263  add_time_stepper_pt(new TIMESTEPPER);
264 
265  // Define number of elements in r direction
266  const unsigned n_r = 3;
267 
268  // Define number of elements in z direction in lower fluid (fluid 1)
269  const unsigned n_z1 = 3;
270 
271  // Define number of elements in z direction in upper fluid (fluid 2)
272  const unsigned n_z2 = 3;
273 
274  // Define width of domain and store as class member data
275  const double l_r = 1.0;
276  this->Lr = l_r;
277 
278  // Define height of lower fluid layer
279  const double h1 = 1.0;
280 
281  // Define height of upper fluid layer
282  const double h2 = 1.0;
283 
284  // Build and assign the "bulk" mesh
285  Bulk_mesh_pt = new ElasticRefineableTwoLayerMesh<ELEMENT>
286  (n_r,n_z1,n_z2,l_r,h1,h2,time_stepper_pt());
287 
288  // Create and set the error estimator for spatial adaptivity
289  Bulk_mesh_pt->spatial_error_estimator_pt() = new Z2ErrorEstimator;
290 
291  // Set the maximum refinement level for the mesh to 4
292  Bulk_mesh_pt->max_refinement_level() = 4;
293 
294  // Create the "surface" mesh that will contain only the interface
295  // elements. The constructor just creates the mesh without giving
296  // it any elements, nodes, etc.
297  Surface_mesh_pt = new Mesh;
298 
299  // Create interface elements at the boundary between the two fluids,
300  // and add them to the surface mesh
301  create_interface_elements();
302 
303  // Add the two sub meshes to the problem
304  add_sub_mesh(Bulk_mesh_pt);
305  add_sub_mesh(Surface_mesh_pt);
306 
307  // Combine all sub-meshes into a single mesh
308  build_global_mesh();
309 
310  // --------------------------------------------
311  // Set the boundary conditions for this problem
312  // --------------------------------------------
313 
314  // All nodes are free by default -- just pin the ones that have
315  // Dirichlet conditions here
316 
317  // Determine number of mesh boundaries
318  const unsigned n_boundary = Bulk_mesh_pt->nboundary();
319 
320  // Loop over mesh boundaries
321  for(unsigned b=0;b<n_boundary;b++)
322  {
323  // Determine number of nodes on boundary b
324  const unsigned n_node = Bulk_mesh_pt->nboundary_node(b);
325 
326  // Loop over nodes on boundary b
327  for(unsigned n=0;n<n_node;n++)
328  {
329  // Fluid boundary conditions:
330  // --------------------------
331 
332  // Pin radial and azimuthal velocities (no slip/penetration)
333  // on all boundaries other than the interface (b=4)
334  if(b!=4)
335  {
336  Bulk_mesh_pt->boundary_node_pt(b,n)->pin(0);
337  Bulk_mesh_pt->boundary_node_pt(b,n)->pin(2);
338  }
339 
340  // Pin axial velocity on top (b=2) and bottom (b=0) boundaries
341  // (no penetration). Because we have a slippery outer wall we do
342  // NOT pin the axial velocity on this boundary (b=1); similarly,
343  // we do not pin the axial velocity on the symmetry boundary (b=3).
344  if(b==0 || b==2) { Bulk_mesh_pt->boundary_node_pt(b,n)->pin(1); }
345 
346  // Solid boundary conditions:
347  // --------------------------
348 
349  // Pin vertical displacement on solid boundaries
350  if(b==0 || b==2) { Bulk_mesh_pt->boundary_node_pt(b,n)->pin_position(1); }
351 
352  } // End of loop over nodes on boundary b
353  } // End of loop over mesh boundaries
354 
355  // Loop over all nodes in mesh
356  const unsigned n_node = Bulk_mesh_pt->nnode();
357  for(unsigned n=0;n<n_node;n++)
358  {
359  // Pin horizontal displacement of all nodes
360  Bulk_mesh_pt->node_pt(n)->pin_position(0);
361 
362  // Pin all azimuthal velocities throughout the bulk of the domain
363  Bulk_mesh_pt->node_pt(n)->pin(2);
364  }
365 
366  // Define a constitutive law for the solid equations: generalised Hookean
367  Constitutive_law_pt = new GeneralisedHookean(&Global_Physical_Variables::Nu);
368 
369  // ----------------------------------------------------------------
370  // Complete the problem setup to make the elements fully functional
371  // ----------------------------------------------------------------
372 
373  // Compute number of bulk elements in lower/upper fluids
374  const unsigned n_lower = n_r*n_z1;
375  const unsigned n_upper = n_r*n_z2;
376 
377  // Loop over bulk elements in lower fluid
378  for(unsigned e=0;e<n_lower;e++)
379  {
380  // Upcast from GeneralisedElement to the present element
381  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(Bulk_mesh_pt->element_pt(e));
382 
383  // Set the Reynolds number
384  el_pt->re_pt() = &Global_Physical_Variables::Re;
385 
386  // Set the Womersley number
387  el_pt->re_st_pt() = &Global_Physical_Variables::ReSt;
388 
389  // Set the product of the Reynolds number and the inverse of the
390  // Froude number
391  el_pt->re_invfr_pt() = &Global_Physical_Variables::ReInvFr;
392 
393  // Set the direction of gravity
394  el_pt->g_pt() = &Global_Physical_Variables::G;
395 
396  // Set the constitutive law
397  el_pt->constitutive_law_pt() = Constitutive_law_pt;
398 
399  } // End of loop over bulk elements in lower fluid
400 
401  // Loop over bulk elements in upper fluid
402  for(unsigned e=n_lower;e<(n_lower+n_upper);e++)
403  {
404  // Upcast from GeneralisedElement to the present element
405  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(Bulk_mesh_pt->element_pt(e));
406 
407  // Set the Reynolds number
408  el_pt->re_pt() = &Global_Physical_Variables::Re;
409 
410  // Set the Womersley number
411  el_pt->re_st_pt() = &Global_Physical_Variables::ReSt;
412 
413  // Set the product of the Reynolds number and the inverse of the
414  // Froude number
415  el_pt->re_invfr_pt() = &Global_Physical_Variables::ReInvFr;
416 
417  // Set the direction of gravity
418  el_pt->g_pt() = &Global_Physical_Variables::G;
419 
420  // Set the viscosity ratio
421  el_pt->viscosity_ratio_pt() = &Global_Physical_Variables::Viscosity_Ratio;
422 
423  // Set the density ratio
424  el_pt->density_ratio_pt() = &Global_Physical_Variables::Density_Ratio;
425 
426  // Set the constitutive law
427  el_pt->constitutive_law_pt() = Constitutive_law_pt;
428 
429  } // End of loop over bulk elements in upper fluid
430 
431  // Set the pressure in the first element at 'node' 0 to 0.0
432  fix_pressure(0,0,0.0);
433 
434  // Pin the redundant solid pressures (if any)
435  PVDEquationsBase<2>::pin_redundant_nodal_solid_pressures(
436  Bulk_mesh_pt->element_pt());
437 
438  // Apply the boundary conditions
439  set_boundary_conditions();
440 
441  // Set up equation numbering scheme
442  cout << "Number of equations: " << assign_eqn_numbers() << std::endl;
443 
444 } // End of constructor
445 
446 
447 
448 //==start_of_set_initial_condition========================================
449 /// Set initial conditions: Set all nodal velocities to zero and
450 /// initialise the previous velocities and nodal positions to correspond
451 /// to an impulsive start
452 //========================================================================
453 template <class ELEMENT, class TIMESTEPPER>
455 {
456  // Determine number of nodes in mesh
457  const unsigned n_node = Bulk_mesh_pt->nnode();
458 
459  // Loop over all nodes in mesh
460  for(unsigned n=0;n<n_node;n++)
461  {
462  // Loop over the three velocity components
463  for(unsigned i=0;i<3;i++)
464  {
465  // Set velocity component i of node n to zero
466  Bulk_mesh_pt->node_pt(n)->set_value(i,0.0);
467  }
468  }
469 
470  // Initialise the previous velocity values and nodal positions
471  // for timestepping corresponding to an impulsive start
472  assign_initial_values_impulsive();
473 
474 } // End of set_initial_condition
475 
476 
477 
478 //==start_of_set_boundary_conditions======================================
479 /// Set boundary conditions: Set all velocity components to zero
480 /// on the top and bottom (solid) walls and the radial and azimuthal
481 /// components only to zero on the side boundaries
482 //========================================================================
483 template <class ELEMENT, class TIMESTEPPER>
485 {
486  // Determine number of mesh boundaries
487  const unsigned n_boundary = Bulk_mesh_pt->nboundary();
488 
489  // Loop over mesh boundaries
490  for(unsigned b=0;b<n_boundary;b++)
491  {
492  // Determine number of nodes on boundary b
493  const unsigned n_node = Bulk_mesh_pt->nboundary_node(b);
494 
495  // Loop over nodes on boundary b
496  for(unsigned n=0;n<n_node;n++)
497  {
498  // Set radial component of the velocity to zero on all boundaries
499  // other than the interface (b=4)
500  if(b!=4) { Bulk_mesh_pt->boundary_node_pt(b,n)->set_value(0,0.0); }
501 
502  // Set azimuthal component of the velocity to zero on all boundaries
503  // other than the interface (b=4)
504  if(b!=4) { Bulk_mesh_pt->boundary_node_pt(b,n)->set_value(2,0.0); }
505 
506  // Set axial component of the velocity to zero on solid boundaries
507  if(b==0 || b==2)
508  {
509  Bulk_mesh_pt->boundary_node_pt(b,n)->set_value(1,0.0);
510  }
511  }
512  }
513 } // End of set_boundary_conditions
514 
515 
516 
517 //==start_of_actions_before_adapt=========================================
518 /// Strip off the interface elements before adapting the bulk mesh
519 //========================================================================
520 template<class ELEMENT, class TIMESTEPPER>
522 {
523  // Delete the interface elements and wipe the surface mesh
524  delete_interface_elements();
525 
526  // Rebuild the Problem's global mesh from its various sub-meshes
527  rebuild_global_mesh();
528 
529 } // End of actions_before_adapt
530 
531 
532 
533 //==start_of_actions_after_adapt==========================================
534 /// Rebuild the mesh of interface elements after adapting the bulk mesh
535 //========================================================================
536 template<class ELEMENT, class TIMESTEPPER>
538 {
539  // Create the interface elements
540  this->create_interface_elements();
541 
542  // Rebuild the Problem's global mesh from its various sub-meshes
543  rebuild_global_mesh();
544 
545  // Pin horizontal displacement of all nodes
546  const unsigned n_node = Bulk_mesh_pt->nnode();
547  for(unsigned n=0;n<n_node;n++) { Bulk_mesh_pt->node_pt(n)->pin_position(0); }
548 
549  // Unpin all fluid pressure dofs
550  RefineableAxisymmetricNavierStokesEquations::
551  unpin_all_pressure_dofs(Bulk_mesh_pt->element_pt());
552 
553  // Pin redudant fluid pressure dofs
554  RefineableAxisymmetricNavierStokesEquations::
555  pin_redundant_nodal_pressures(Bulk_mesh_pt->element_pt());
556 
557  // Now set the pressure in the first element at 'node' 0 to 0.0
558  fix_pressure(0,0,0.0);
559 
560  // Pin the redundant solid pressures (if any)
561  PVDEquationsBase<2>::pin_redundant_nodal_solid_pressures(
562  Bulk_mesh_pt->element_pt());
563 
564  // Reset the boundary conditions
565  set_boundary_conditions();
566 
567 } // End of actions_after_adapt
568 
569 
570 
571 //==start_of_create_interface_elements====================================
572 /// Create interface elements between the two fluids in the mesh
573 /// pointed to by Bulk_mesh_pt and add the elements to the Mesh object
574 /// pointed to by Surface_mesh_pt.
575 //========================================================================
576 template <class ELEMENT, class TIMESTEPPER>
578 {
579  // Determine number of bulk elements adjacent to interface (boundary 4)
580  const unsigned n_element = this->Bulk_mesh_pt->nboundary_element(4);
581 
582  // Loop over those elements adjacent to the interface
583  for(unsigned e=0;e<n_element;e++)
584  {
585  // Get pointer to the bulk element that is adjacent to the interface
586  ELEMENT* bulk_elem_pt = dynamic_cast<ELEMENT*>(
587  this->Bulk_mesh_pt->boundary_element_pt(4,e));
588 
589  // We only want to attach interface elements to the bulk elements
590  // which are BELOW the interface, and so we filter out those above by
591  // referring to the viscosity_ratio_pt
592  if(bulk_elem_pt->viscosity_ratio_pt()
594  {
595  // Find index of the face of element e that corresponds to the interface
596  const int face_index = this->Bulk_mesh_pt->face_index_at_boundary(4,e);
597 
598  // Create the interface element
599  FiniteElement* interface_element_element_pt =
600  new ElasticAxisymmetricFluidInterfaceElement<ELEMENT>(bulk_elem_pt,
601  face_index);
602 
603  // Add the interface element to the surface mesh
604  this->Surface_mesh_pt->add_element_pt(interface_element_element_pt);
605  }
606  }
607 
608  // --------------------------------------------------------
609  // Complete the setup to make the elements fully functional
610  // --------------------------------------------------------
611 
612  // Determine number of 1D interface elements in mesh
613  const unsigned n_interface_element = this->Surface_mesh_pt->nelement();
614 
615  // Loop over the interface elements
616  for(unsigned e=0;e<n_interface_element;e++)
617  {
618  // Upcast from GeneralisedElement to the present element
619  ElasticAxisymmetricFluidInterfaceElement<ELEMENT>* el_pt =
620  dynamic_cast<ElasticAxisymmetricFluidInterfaceElement<ELEMENT>*>
621  (Surface_mesh_pt->element_pt(e));
622 
623  // Set the Strouhal number
624  el_pt->st_pt() = &Global_Physical_Variables::St;
625 
626  // Set the Capillary number
627  el_pt->ca_pt() = &Global_Physical_Variables::Ca;
628 
629  } // End of loop over interface elements
630 
631 } // End of create_interface_elements()
632 
633 
634 
635 //==start_of_delete_interface_elements====================================
636 /// Delete the interface elements and wipe the surface mesh
637 //========================================================================
638 template <class ELEMENT, class TIMESTEPPER>
640 {
641  // Determine number of interface elements
642  const unsigned n_interface_element = Surface_mesh_pt->nelement();
643 
644  // Loop over interface elements and delete
645  for(unsigned e=0;e<n_interface_element;e++)
646  {
647  delete Surface_mesh_pt->element_pt(e);
648  }
649 
650  // Wipe the mesh
651  Surface_mesh_pt->flush_element_and_node_storage();
652 
653 } // End of delete_interface_elements
654 
655 
656 
657 //==start_of_deform_free_surface==========================================
658 /// Deform the mesh/free surface to a prescribed function
659 //========================================================================
660 template <class ELEMENT, class TIMESTEPPER>
662 deform_free_surface(const double &epsilon,const double &k)
663 {
664  // Initialise Bessel functions (only need the first!)
665  double j0, j1, y0, y1, j0p, j1p, y0p, y1p;
666 
667  // Determine number of nodes in the "bulk" mesh
668  const unsigned n_node = Bulk_mesh_pt->nnode();
669 
670  // Loop over all nodes in mesh
671  for(unsigned n=0;n<n_node;n++)
672  {
673  // Determine eulerian position of node
674  const double current_r_pos = Bulk_mesh_pt->node_pt(n)->x(0);
675  const double current_z_pos = Bulk_mesh_pt->node_pt(n)->x(1);
676 
677  // Compute Bessel functions
678  CRBond_Bessel::bessjy01a(k*current_r_pos,j0,j1,y0,y1,j0p,j1p,y0p,y1p);
679 
680  // Determine new vertical position of node
681  const double new_z_pos = current_z_pos
682  + (1.0-fabs(1.0-current_z_pos))*epsilon*j0;
683 
684  // Set new position
685  Bulk_mesh_pt->node_pt(n)->x(1) = new_z_pos;
686  }
687 } // End of deform_free_surface
688 
689 
690 
691 //==start_of_doc_solution=================================================
692 /// Doc the solution
693 //========================================================================
694 template <class ELEMENT, class TIMESTEPPER>
696 {
697 
698  // Output the time
699  cout << "Time is now " << time_pt()->time() << std::endl;
700 
701  // Upcast from GeneralisedElement to the present element
702  ElasticAxisymmetricFluidInterfaceElement<ELEMENT>* el_pt =
703  dynamic_cast<ElasticAxisymmetricFluidInterfaceElement<ELEMENT>*>
704  (Surface_mesh_pt->element_pt(0));
705 
706  // Document time and vertical position of left hand side of interface
707  // in trace file
708  Trace_file << time_pt()->time() << " "
709  << el_pt->node_pt(0)->x(1) << std::endl;
710 
711  ofstream some_file;
712  char filename[100];
713 
714  // Set number of plot points (in each coordinate direction)
715  const unsigned npts = 5;
716 
717  // Open solution output file
718  sprintf(filename,"%s/soln%i.dat",
719  doc_info.directory().c_str(),doc_info.number());
720  some_file.open(filename);
721 
722  // Output solution to file
723  Bulk_mesh_pt->output(some_file,npts);
724 
725  // Close solution output file
726  some_file.close();
727 
728  // Open interface solution output file
729  sprintf(filename,"%s/interface_soln%i.dat",
730  doc_info.directory().c_str(),doc_info.number());
731  some_file.open(filename);
732 
733  // Output solution to file
734  Surface_mesh_pt->output(some_file,npts);
735 
736  // Close solution output file
737  some_file.close();
738 
739 } // End of doc_solution
740 
741 
742 
743 //==start_of_unsteady_run=================================================
744 /// Perform run up to specified time t_max with given timestep dt
745 //========================================================================
746 template <class ELEMENT, class TIMESTEPPER>
748 unsteady_run(const double &t_max, const double &dt)
749 {
750 
751  // Set value of epsilon
752  const double epsilon = 0.1;
753 
754  // Set value of k in Bessel function J_0(kr)
755  const double k_bessel = 3.8317;
756 
757  // Deform the mesh/free surface
758  deform_free_surface(epsilon,k_bessel);
759 
760  // Initialise DocInfo object
761  DocInfo doc_info;
762 
763  // Set output directory
764  doc_info.set_directory("RESLT");
765 
766  // Initialise counter for solutions
767  doc_info.number()=0;
768 
769  // Open trace file
770  char filename[100];
771  sprintf(filename,"%s/trace.dat",doc_info.directory().c_str());
772  Trace_file.open(filename);
773 
774  // Initialise trace file
775  Trace_file << "time, interface height" << std::endl;
776 
777  // Initialise timestep
778  initialise_dt(dt);
779 
780  // Set initial condition
781  set_initial_condition();
782 
783  // Maximum number of spatial adaptations per timestep
784  unsigned max_adapt = 2;
785 
786  // Call refine_uniformly twice
787  for(unsigned i=0;i<2;i++) { refine_uniformly(); }
788 
789  // Doc initial solution
790  doc_solution(doc_info);
791 
792  // Increment counter for solutions
793  doc_info.number()++;
794 
795  // Determine number of timesteps
796  const unsigned n_timestep = unsigned(t_max/dt);
797 
798  // Are we on the first timestep? At this point, yes!
799  bool first_timestep = true;
800 
801  // Timestepping loop
802  for(unsigned t=1;t<=n_timestep;t++)
803  {
804  // Output current timestep to screen
805  cout << "\nTimestep " << t << " of " << n_timestep << std::endl;
806 
807  // Take one fixed timestep with spatial adaptivity
808  unsteady_newton_solve(dt,max_adapt,first_timestep);
809 
810  // No longer on first timestep, so set first_timestep flag to false
811  first_timestep = false;
812 
813  // Reset maximum number of adaptations for all future timesteps
814  max_adapt = 1;
815 
816  // Doc solution
817  doc_solution(doc_info);
818 
819  // Increment counter for solutions
820  doc_info.number()++;
821 
822  } // End of timestepping loop
823 
824 } // End of unsteady_run
825 
826 
827 /// ///////////////////////////////////////////////////////////////////////
828 /// ///////////////////////////////////////////////////////////////////////
829 /// ///////////////////////////////////////////////////////////////////////
830 
831 
832 //==start_of_main=========================================================
833 /// Driver code for axisymmetric two fluid interface problem
834 //========================================================================
835 int main(int argc, char* argv[])
836 {
837  // Store command line arguments
838  CommandLineArgs::setup(argc,argv);
839 
840  // -----------------------------------------------------------------
841  // Define possible command line arguments and parse the ones that
842  // were actually specified
843  // -----------------------------------------------------------------
844 
845  // Are we performing a validation run?
846  CommandLineArgs::specify_command_line_flag("--validation");
847 
848  // Parse command line
849  CommandLineArgs::parse_and_assign();
850 
851  // Doc what has actually been specified on the command line
852  CommandLineArgs::doc_specified_flags();
853 
854  // Check that definition of Womersley number is consistent with those
855  // of the Reynolds and Strouhal numbers
858  {
859  std::ostringstream error_stream;
860  error_stream << "Definition of Global_Physical_Variables::ReSt is "
861  << "inconsistant with those\n"
862  << "of Global_Physical_Variables::Re and "
863  << "Global_Physical_Variables::St." << std::endl;
864  throw OomphLibError(error_stream.str(),
865  OOMPH_CURRENT_FUNCTION,OOMPH_EXCEPTION_LOCATION);
866  }
867 
868  /// Maximum time
869  double t_max = 1.2;
870 
871  /// Duration of timestep
872  const double dt = 0.005;
873 
874  // If we are doing validation run, use smaller number of timesteps
875  if(CommandLineArgs::command_line_flag_has_been_set("--validation"))
876  {
877  t_max = 0.01;
878  }
879 
880  // Set direction of gravity (vertically downwards)
884 
885  // Set up the elastic test problem with AxisymmetricQCrouzeixRaviartElements,
886  // using the BDF<2> timestepper
887  InterfaceProblem<RefineablePseudoSolidNodeUpdateElement<
888  RefineableAxisymmetricQCrouzeixRaviartElement,
889  RefineableQPVDElement<2,3> >,BDF<2> > problem;
890 
891  // Run the unsteady simulation
892  problem.unsteady_run(t_max,dt);
893 
894 } // End of main
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
ElasticRefineableTwoLayerMesh(const unsigned &nx, const unsigned &ny1, const unsigned &ny2, const double &lx, const double &h1, const double &h2, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass number of elements in x-direction, number of elements in y-direction in bottom and ...
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
Mesh * Surface_mesh_pt
Pointer to the "surface" mesh.
void set_initial_condition()
Set initial conditions.
void actions_after_adapt()
Rebuild the mesh of interface elements after adapting the bulk mesh.
void doc_solution(DocInfo &doc_info)
Document the solution.
void set_boundary_conditions()
Set boundary conditions.
void actions_before_adapt()
Strip off the interface elements before adapting the bulk mesh.
void create_interface_elements()
Create the 1d interface elements.
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 deform_free_surface(const double &epsilon, const double &k)
Deform the mesh/free surface to a prescribed function.
void delete_interface_elements()
Delete the 1d interface elements.
ElasticRefineableTwoLayerMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the (specific) "bulk" mesh.
void actions_before_newton_solve()
No actions required before solve step.
void unsteady_run(const double &t_max, const double &dt)
Do unsteady run up to maximum time t_max with given timestep dt.
void actions_before_implicit_timestep()
Actions before the timestep: For maximum stability, reset the current nodal positions to be the "stre...
void actions_after_newton_solve()
No actions required after solve step.
int main(int argc, char *argv[])
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
Namespace for physical parameters.
double ReSt
Womersley number (Reynolds x Strouhal)
double Nu
Pseudo-solid Poisson ratio.
double Density_Ratio
Ratio of density in upper fluid to density in lower fluid. Reynolds number etc. is based on density i...
double ReInvFr
Product of Reynolds number and inverse of Froude number.
double Viscosity_Ratio
Ratio of viscosity in upper fluid to viscosity in lower fluid. Reynolds number etc....
Vector< double > G(3)
Direction of gravity.