elastic_two_layer_interface.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 two-dimensional 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// Navier-Stokes headers
33#include "navier_stokes.h"
34
35// Interface headers
36#include "fluid_interface.h"
37
38// Constitutive law headers
39#include "constitutive.h"
40
41// Solid headers
42#include "solid.h"
43
44// The mesh
45#include "meshes/rectangular_quadmesh.h"
46
47using namespace std;
48
49using namespace oomph;
50
51
52//==start_of_namespace====================================================
53/// Namespace for physical parameters
54//========================================================================
56{
57
58 /// Reynolds number
59 double Re = 5.0;
60
61 /// Strouhal number
62 double St = 1.0;
63
64 /// Womersley number (Reynolds x Strouhal)
65 double ReSt = 5.0;
66
67 /// Product of Reynolds number and inverse of Froude number
68 double ReInvFr = 5.0;
69
70 /// Ratio of viscosity in upper fluid to viscosity in lower
71 /// fluid. Reynolds number etc. is based on viscosity in lower fluid.
72 double Viscosity_Ratio = 0.1;
73
74 /// Ratio of density in upper fluid to density in lower
75 /// fluid. Reynolds number etc. is based on density in lower fluid.
76 double Density_Ratio = 0.5;
77
78 /// Capillary number
79 double Ca = 0.01;
80
81 /// Direction of gravity
82 Vector<double> G(2);
83
84 /// Pseudo-solid Poisson ratio
85 double Nu = 0.1;
86
87} // End of namespace
88
89
90/// ///////////////////////////////////////////////////////////////////////
91/// ///////////////////////////////////////////////////////////////////////
92/// ///////////////////////////////////////////////////////////////////////
93
94
95//==start_of_specific_mesh_class==========================================
96/// Two layer mesh which employs a pseudo-solid node-update strategy.
97/// This class is essentially a wrapper to an
98/// ElasticRefineableRectangularQuadMesh, with an additional boundary
99/// to represent the interface between the two fluid layers.
100//========================================================================
101template <class ELEMENT>
103 public virtual ElasticRefineableRectangularQuadMesh<ELEMENT>
104{
105
106public:
107
108 /// Constructor: Pass number of elements in x-direction, number of
109 /// elements in y-direction in bottom and top layer, respectively,
110 /// axial length and height of top and bottom layers, a boolean
111 /// flag to make the mesh periodic in the x-direction, and pointer
112 /// to timestepper (defaults to Steady timestepper)
113 ElasticRefineableTwoLayerMesh(const unsigned &nx,
114 const unsigned &ny1,
115 const unsigned &ny2,
116 const double &lx,
117 const double &h1,
118 const double &h2,
119 const bool& periodic_in_x,
120 TimeStepper* time_stepper_pt=
121 &Mesh::Default_TimeStepper)
122 : RectangularQuadMesh<ELEMENT>(nx,ny1+ny2,lx,h1+h2,
123 periodic_in_x,time_stepper_pt),
124 ElasticRectangularQuadMesh<ELEMENT>(nx,ny1+ny2,lx,h1+h2,
125 periodic_in_x,time_stepper_pt),
126 ElasticRefineableRectangularQuadMesh<ELEMENT>(nx,ny1+ny2,lx,h1+h2,
127 periodic_in_x,
128 time_stepper_pt)
129 {
130 // ----------------------------------------------------
131 // Convert all nodes on the interface to boundary nodes
132 // ----------------------------------------------------
133
134 // Set the number of boundaries to 5
135 this->set_nboundary(5);
136
137 // Loop over horizontal elements
138 for(unsigned e=0;e<nx;e++)
139 {
140 // Get pointer to element in lower fluid adjacent to interface
141 FiniteElement* el_pt = this->finite_element_pt(nx*(ny1-1)+e);
142
143 // Determine number of nodes in this element
144 const unsigned n_node = el_pt->nnode();
145
146 // The last three nodes in this element are those on the interface.
147 // Loop over these nodes and convert them to boundary nodes.
148 for(unsigned n=0;n<3;n++)
149 {
150 Node* nod_pt = el_pt->node_pt(n_node-3+n);
151 this->convert_to_boundary_node(nod_pt);
152 this->add_boundary_node(4,nod_pt);
153 }
154 } // End of loop over horizontal elements
155
156 // Set up the boundary element information
157 this->setup_boundary_element_info();
158 }
159
160}; // End of specific mesh class
161
162
163/// ///////////////////////////////////////////////////////////////////////
164/// ///////////////////////////////////////////////////////////////////////
165/// ///////////////////////////////////////////////////////////////////////
166
167
168//==start_of_problem_class================================================
169/// Two fluid interface problem in a rectangular domain which is
170/// periodic in the x direction
171//========================================================================
172template <class ELEMENT, class TIMESTEPPER>
173class InterfaceProblem : public Problem
174{
175
176public:
177
178 /// Constructor
180
181 /// Destructor (empty)
183
184 /// Set initial conditions
186
187 /// 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
196private:
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
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
219
220 /// Delete the 1d interface elements
222
223 /// Deform the mesh/free surface to a prescribed function
224 void deform_free_surface(const double &epsilon, const unsigned &n_periods);
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 Lx;
247
248 /// Trace file
249 ofstream Trace_file;
250
251}; // End of problem class
252
253
254
255//==start_of_constructor==================================================
256/// Constructor for two fluid interface problem
257//========================================================================
258template <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 x direction
266 const unsigned n_x = 3;
267
268 // Define number of elements in y direction in lower fluid (fluid 1)
269 const unsigned n_y1 = 3;
270
271 // Define number of elements in y direction in upper fluid (fluid 2)
272 const unsigned n_y2 = 3;
273
274 // Define width of domain and store as class member data
275 const double l_x = 1.0;
276 this->Lx = l_x;
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 (the "true" boolean flag tells
285 // the mesh constructor that the domain is periodic in x)
288
289 // Create and set the error estimator for spatial adaptivity
290 Bulk_mesh_pt->spatial_error_estimator_pt() = new Z2ErrorEstimator;
291
292 // Set the maximum refinement level for the mesh to 4
293 Bulk_mesh_pt->max_refinement_level() = 4;
294
295 // Create the "surface" mesh that will contain only the interface
296 // elements. The constructor just creates the mesh without giving
297 // it any elements, nodes, etc.
298 Surface_mesh_pt = new Mesh;
299
300 // Create interface elements at the boundary between the two fluids,
301 // and add them to the surface mesh
302 create_interface_elements();
303
304 // Add the two sub meshes to the problem
305 add_sub_mesh(Bulk_mesh_pt);
306 add_sub_mesh(Surface_mesh_pt);
307
308 // Combine all sub-meshes into a single mesh
310
311 // --------------------------------------------
312 // Set the boundary conditions for this problem
313 // --------------------------------------------
314
315 // All values are free by default -- just pin the ones that have
316 // Dirichlet conditions here
317
318 // Determine number of mesh boundaries
319 const unsigned n_boundary = Bulk_mesh_pt->nboundary();
320
321 // Loop over mesh boundaries
322 for(unsigned b=0;b<n_boundary;b++)
323 {
324 // Determine number of nodes on boundary b
325 const unsigned n_node = Bulk_mesh_pt->nboundary_node(b);
326
327 // Loop over nodes on boundary b
328 for(unsigned n=0;n<n_node;n++)
329 {
330 // Fluid boundary conditions:
331 // --------------------------
332
333 // Pin x-component of velocity (no slip/penetration)
334 // on all boundaries other than the interface (b=4)
335 if(b!=4) { Bulk_mesh_pt->boundary_node_pt(b,n)->pin(0); }
336
337 // Pin y-component of velocity on both solid boundaries (no penetration)
338 if(b==0 || b==2) { Bulk_mesh_pt->boundary_node_pt(b,n)->pin(1); }
339
340 // Solid boundary conditions:
341 // --------------------------
342
343 // Pin vertical mesh position on both solid boundaries (no penetration)
344 if(b==0 || b==2) { Bulk_mesh_pt->boundary_node_pt(b,n)->pin_position(1); }
345
346 } // End of loop over nodes on boundary b
347 } // End of loop over mesh boundaries
348
349 // Pin horizontal position of all nodes
350 const unsigned n_node = Bulk_mesh_pt->nnode();
351 for(unsigned n=0;n<n_node;n++) { Bulk_mesh_pt->node_pt(n)->pin_position(0); }
352
353 // Define a constitutive law for the solid equations: generalised Hookean
354 Constitutive_law_pt = new GeneralisedHookean(&Global_Physical_Variables::Nu);
355
356 // ----------------------------------------------------------------
357 // Complete the problem setup to make the elements fully functional
358 // ----------------------------------------------------------------
359
360 // Compute number of bulk elements in lower/upper fluids
361 const unsigned n_lower = n_x*n_y1;
362 const unsigned n_upper = n_x*n_y2;
363
364 // Loop over bulk elements in lower fluid
365 for(unsigned e=0;e<n_lower;e++)
366 {
367 // Upcast from GeneralisedElement to the present element
368 ELEMENT *el_pt = dynamic_cast<ELEMENT*>(Bulk_mesh_pt->element_pt(e));
369
370 // Set the Reynolds number
372
373 // Set the Womersley number
375
376 // Set the product of the Reynolds number and the inverse of the
377 // Froude number
379
380 // Set the direction of gravity
382
383 // Set the constitutive law
384 el_pt->constitutive_law_pt() = Constitutive_law_pt;
385
386 } // End of loop over bulk elements in lower fluid
387
388 // Loop over bulk elements in upper fluid
389 for(unsigned e=n_lower;e<(n_lower+n_upper);e++)
390 {
391 // Upcast from GeneralisedElement to the present element
392 ELEMENT *el_pt = dynamic_cast<ELEMENT*>(Bulk_mesh_pt->element_pt(e));
393
394 // Set the Reynolds number
396
397 // Set the Womersley number
399
400 // Set the product of the Reynolds number and the inverse of the
401 // Froude number
403
404 // Set the viscosity ratio
405 el_pt->viscosity_ratio_pt() = &Global_Physical_Variables::Viscosity_Ratio;
406
407 // Set the density ratio
408 el_pt->density_ratio_pt() = &Global_Physical_Variables::Density_Ratio;
409
410 // Set the direction of gravity
412
413 // Set the constitutive law
414 el_pt->constitutive_law_pt() = Constitutive_law_pt;
415
416 } // End of loop over bulk elements in upper fluid
417
418 // Set the pressure in the first element at 'node' 0 to 0.0
419 fix_pressure(0,0,0.0);
420
421 // Apply the boundary conditions
422 set_boundary_conditions();
423
424 // Set up equation numbering scheme
425 cout << "Number of equations: " << assign_eqn_numbers() << std::endl;
426
427} // End of constructor
428
429
430
431//==start_of_set_initial_condition========================================
432/// Set initial conditions: Set all nodal velocities to zero and
433/// initialise the previous velocities and nodal positions to correspond
434/// to an impulsive start
435//========================================================================
436template <class ELEMENT, class TIMESTEPPER>
438{
439 // Determine number of nodes in mesh
440 const unsigned n_node = mesh_pt()->nnode();
441
442 // Loop over all nodes in mesh
443 for(unsigned n=0;n<n_node;n++)
444 {
445 // Loop over the two velocity components
446 for(unsigned i=0;i<2;i++)
447 {
448 // Set velocity component i of node n to zero
449 mesh_pt()->node_pt(n)->set_value(i,0.0);
450 }
451 }
452
453 // Initialise the previous velocity values and nodal positions
454 // for timestepping corresponding to an impulsive start
456
457} // End of set_initial_condition
458
459
460
461//==start_of_set_boundary_conditions======================================
462/// Set boundary conditions: Set both velocity components
463/// to zero on the top and bottom (solid) walls and the horizontal
464/// component only to zero on the side (periodic) boundaries
465//========================================================================
466template <class ELEMENT, class TIMESTEPPER>
468{
469 // Determine number of mesh boundaries
470 const unsigned n_boundary = Bulk_mesh_pt->nboundary();
471
472 // Loop over mesh boundaries
473 for(unsigned b=0;b<n_boundary;b++)
474 {
475 // Determine number of nodes on boundary b
476 const unsigned n_node = Bulk_mesh_pt->nboundary_node(b);
477
478 // Loop over nodes on boundary b
479 for(unsigned n=0;n<n_node;n++)
480 {
481 // Set x-component of the velocity to zero on all boundaries
482 // other than the interface (b=4)
483 if(b!=4) { Bulk_mesh_pt->boundary_node_pt(b,n)->set_value(0,0.0); }
484
485 // Set y-component of the velocity to zero on both solid
486 // boundaries (top and bottom)
487 if(b==0 || b==2)
488 {
489 Bulk_mesh_pt->boundary_node_pt(b,n)->set_value(1,0.0);
490 }
491 } // End of loop over nodes on boundary b
492 } // End of loop over mesh boundaries
493
494} // End of set_boundary_conditions
495
496
497
498//==start_of_actions_before_adapt=========================================
499/// Strip off the interface elements before adapting the bulk mesh
500//========================================================================
501template<class ELEMENT, class TIMESTEPPER>
503{
504 // Delete the interface elements and wipe the surface mesh
505 delete_interface_elements();
506
507 // Rebuild the Problem's global mesh from its various sub-meshes
509
510} // End of actions_before_adapt
511
512
513
514//==start_of_actions_after_adapt==========================================
515/// Rebuild the mesh of interface elements after adapting the bulk mesh
516//========================================================================
517template<class ELEMENT, class TIMESTEPPER>
519{
520 // Create the interface elements
521 this->create_interface_elements();
522
523 // Rebuild the Problem's global mesh from its various sub-meshes
525
526 // Pin horizontal displacement of all nodes
527 const unsigned n_node = Bulk_mesh_pt->nnode();
528 for(unsigned n=0;n<n_node;n++) { Bulk_mesh_pt->node_pt(n)->pin_position(0); }
529
530 // Unpin all fluid pressure dofs
532 unpin_all_pressure_dofs(Bulk_mesh_pt->element_pt());
533
534 // Pin redudant fluid pressure dofs
536 pin_redundant_nodal_pressures(Bulk_mesh_pt->element_pt());
537
538 // Now set the pressure in the first element at 'node' 0 to 0.0
539 fix_pressure(0,0,0.0);
540
541 // Pin the redundant solid pressures (if any)
543 Bulk_mesh_pt->element_pt());
544
545 // Reset the boundary conditions
546 set_boundary_conditions();
547
548} // End of actions_after_adapt
549
550
551
552//==start_of_create_interface_elements====================================
553/// Create interface elements between the two fluids in the mesh
554/// pointed to by Bulk_mesh_pt and add the elements to the Mesh object
555/// pointed to by Surface_mesh_pt.
556//========================================================================
557template <class ELEMENT, class TIMESTEPPER>
559{
560 // Determine number of bulk elements adjacent to interface (boundary 4)
561 const unsigned n_element = this->Bulk_mesh_pt->nboundary_element(4);
562
563 // Loop over those elements adjacent to the interface
564 for(unsigned e=0;e<n_element;e++)
565 {
566 // Get pointer to the bulk element that is adjacent to the interface
567 ELEMENT* bulk_elem_pt = dynamic_cast<ELEMENT*>(
568 this->Bulk_mesh_pt->boundary_element_pt(4,e));
569
570 // We only want to attach interface elements to the bulk elements
571 // which are BELOW the interface, and so we filter out those above by
572 // referring to the viscosity_ratio_pt
573 if(bulk_elem_pt->viscosity_ratio_pt()
575 {
576 // Find index of the face of element e that corresponds to the interface
577 const int face_index = this->Bulk_mesh_pt->face_index_at_boundary(4,e);
578
579 // Create the interface element
582
583 // Add the interface element to the surface mesh
584 this->Surface_mesh_pt->add_element_pt(interface_element_element_pt);
585 }
586 }
587
588 // --------------------------------------------------------
589 // Complete the setup to make the elements fully functional
590 // --------------------------------------------------------
591
592 // Determine number of 1D interface elements in mesh
593 const unsigned n_interface_element = this->Surface_mesh_pt->nelement();
594
595 // Loop over the interface elements
596 for(unsigned e=0;e<n_interface_element;e++)
597 {
598 // Upcast from GeneralisedElement to the present element
601 (Surface_mesh_pt->element_pt(e));
602
603 // Set the Strouhal number
605
606 // Set the Capillary number
608
609 } // End of loop over interface elements
610
611} // End of create_interface_elements
612
613
614
615//==start_of_delete_interface_elements====================================
616/// Delete the interface elements and wipe the surface mesh
617//========================================================================
618template <class ELEMENT, class TIMESTEPPER>
620{
621 // Determine number of interface elements
622 const unsigned n_interface_element = Surface_mesh_pt->nelement();
623
624 // Loop over interface elements and delete
625 for(unsigned e=0;e<n_interface_element;e++)
626 {
627 delete Surface_mesh_pt->element_pt(e);
628 }
629
630 // Wipe the mesh
631 Surface_mesh_pt->flush_element_and_node_storage();
632
633} // End of delete_interface_elements
634
635
636
637//==start_of_deform_free_surface==========================================
638/// Deform the mesh/free surface to a prescribed function
639//========================================================================
640template <class ELEMENT, class TIMESTEPPER>
642deform_free_surface(const double &epsilon,const unsigned &n_periods)
643{
644 // Determine number of nodes in the "bulk" mesh
645 const unsigned n_node = Bulk_mesh_pt->nnode();
646
647 // Loop over all nodes in mesh
648 for(unsigned n=0;n<n_node;n++)
649 {
650 // Determine eulerian position of node
651 const double current_x_pos = Bulk_mesh_pt->node_pt(n)->x(0);
652 const double current_y_pos = Bulk_mesh_pt->node_pt(n)->x(1);
653
654 // Determine new vertical position of node
655 const double new_y_pos = current_y_pos
656 + (1.0-fabs(1.0-current_y_pos))*epsilon
658
659 // Set new position
660 Bulk_mesh_pt->node_pt(n)->x(1) = new_y_pos;
661 }
662} // End of deform_free_surface
663
664
665
666//==start_of_doc_solution=================================================
667/// Doc the solution
668//========================================================================
669template <class ELEMENT, class TIMESTEPPER>
671{
672
673 // Output the time
674 cout << "Time is now " << time_pt()->time() << std::endl;
675
676 // Upcast from GeneralisedElement to the present element
679 (Surface_mesh_pt->element_pt(0));
680
681 // Document time and vertical position of left hand side of interface
682 // in trace file
683 Trace_file << time_pt()->time() << " "
684 << el_pt->node_pt(0)->x(1) << std::endl;
685
687 char filename[100];
688
689 // Set number of plot points (in each coordinate direction)
690 const unsigned npts = 5;
691
692 // Open solution output file
693 sprintf(filename,"%s/soln%i.dat",
694 doc_info.directory().c_str(),doc_info.number());
695 some_file.open(filename);
696
697 // Output solution to file
698 Bulk_mesh_pt->output(some_file,npts);
699
700 // Close solution output file
701 some_file.close();
702
703 // Open interface solution output file
704 sprintf(filename,"%s/interface_soln%i.dat",
705 doc_info.directory().c_str(),doc_info.number());
706 some_file.open(filename);
707
708 // Output solution to file
709 Surface_mesh_pt->output(some_file,npts);
710
711 // Close solution output file
712 some_file.close();
713
714} // End of doc_solution
715
716
717
718//==start_of_unsteady_run=================================================
719/// Perform run up to specified time t_max with given timestep dt
720//========================================================================
721template <class ELEMENT, class TIMESTEPPER>
723unsteady_run(const double &t_max, const double &dt)
724{
725
726 // Set value of epsilon
727 const double epsilon = 0.1;
728
729 // Set number of periods for cosine term
730 const unsigned n_periods = 1;
731
732 // Deform the mesh/free surface
733 deform_free_surface(epsilon,n_periods);
734
735 // Initialise DocInfo object
737
738 // Set output directory
739 doc_info.set_directory("RESLT");
740
741 // Initialise counter for solutions
742 doc_info.number()=0;
743
744 // Open trace file
745 char filename[100];
746 sprintf(filename,"%s/trace.dat",doc_info.directory().c_str());
747 Trace_file.open(filename);
748
749 // Initialise trace file
750 Trace_file << "time, interface height" << std::endl;
751
752 // Initialise timestep
754
755 // Set initial condition
756 set_initial_condition();
757
758 // Maximum number of spatial adaptations per timestep
759 unsigned max_adapt = 2;
760
761 // Call refine_uniformly twice
762 for(unsigned i=0;i<2;i++) { refine_uniformly(); }
763
764 // Doc initial solution
765 doc_solution(doc_info);
766
767 // Increment counter for solutions
768 doc_info.number()++;
769
770 // Determine number of timesteps
771 const unsigned n_timestep = unsigned(t_max/dt);
772
773 // Are we on the first timestep? At this point, yes!
774 bool first_timestep = true;
775
776 // Timestepping loop
777 for(unsigned t=1;t<=n_timestep;t++)
778 {
779 // Output current timestep to screen
780 cout << "\nTimestep " << t << " of " << n_timestep << std::endl;
781
782 // Take one fixed timestep with spatial adaptivity
784
785 // No longer on first timestep, so set first_timestep flag to false
786 first_timestep = false;
787
788 // Reset maximum number of adaptations for all future timesteps
789 max_adapt = 1;
790
791 // Doc solution
792 doc_solution(doc_info);
793
794 // Increment counter for solutions
795 doc_info.number()++;
796
797 } // End of timestepping loop
798
799} // End of unsteady_run
800
801
802/// ///////////////////////////////////////////////////////////////////////
803/// ///////////////////////////////////////////////////////////////////////
804/// ///////////////////////////////////////////////////////////////////////
805
806
807//==start_of_main=========================================================
808/// Driver code for two-dimensional two fluid interface problem
809//========================================================================
810int main(int argc, char* argv[])
811{
812 // Store command line arguments
814
815 // -----------------------------------------------------------------
816 // Define possible command line arguments and parse the ones that
817 // were actually specified
818 // -----------------------------------------------------------------
819
820 // Are we performing a validation run?
822
823 // Parse command line
825
826 // Doc what has actually been specified on the command line
828
829 // Check that definition of Womersley number is consistent with those
830 // of the Reynolds and Strouhal numbers
833 {
834 std::ostringstream error_stream;
835 error_stream << "Definition of Global_Physical_Variables::ReSt is "
836 << "inconsistant with those\n"
837 << "of Global_Physical_Variables::Re and "
838 << "Global_Physical_Variables::St." << std::endl;
839 throw OomphLibError(error_stream.str(),
841 }
842
843 /// Maximum time
844 double t_max = 0.6;
845
846 /// Duration of timestep
847 const double dt = 0.0025;
848
849 // If we are doing validation run, use smaller number of timesteps
851 {
852 t_max = 0.005;
853 }
854
855 // Set direction of gravity (vertically downwards)
858
859 // Set up the elastic test problem with QCrouzeixRaviartElements,
860 // using the BDF<2> timestepper
863 problem;
864
865 // Run the unsteady simulation
866 problem.unsteady_run(t_max,dt);
867
868} // End of main
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
ElasticRefineableTwoLayerMesh(const unsigned &nx, const unsigned &ny1, const unsigned &ny2, const double &lx, const double &h1, const double &h2, const bool &periodic_in_x, 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 deform_free_surface(const double &epsilon, const unsigned &n_periods)
Deform the mesh/free surface to a prescribed function.
void doc_solution(DocInfo &doc_info)
Document the solution.
ConstitutiveLaw * Constitutive_law_pt
void set_boundary_conditions()
Set boundary conditions.
~InterfaceProblem()
Destructor (empty)
void actions_before_adapt()
Strip off the interface elements before adapting the bulk mesh.
void create_interface_elements()
Create the 1d interface elements.
double Lx
Width of domain.
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 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)
Vector< double > G(2)
Direction of gravity.
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....