fsi_driven_cavity_problem.h
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-2022 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 // Generic oomph-lib includes
27 #include "generic.h"
28 #include "navier_stokes.h"
29 #include "beam.h"
30 
31 // The wall mesh
33 
34 //Include the fluid mesh
36 
37 
38 using namespace std;
39 using namespace oomph;
40 
41 
42 
46 
47 
48 //====start_of_underformed_wall============================================
52 //=========================================================================
53 class UndeformedWall : public GeomObject
54 {
55 
56 public:
57 
60  UndeformedWall(const double& x0, const double& h): GeomObject(1,2)
61  {
62  X0=x0;
63  H=h;
64  }
65 
66 
69  {
70  // Position Vector
71  r[0] = zeta[0]+X0;
72  r[1] = H;
73  }
74 
75 
79  void position(const unsigned& t, const Vector<double>& zeta,
80  Vector<double>& r) const
81  {
82  // Use the steady version
83  position(zeta,r);
84 
85  } // end of position
86 
87 
95  DenseMatrix<double> &drdzeta,
96  RankThreeTensor<double> &ddrdzeta) const
97  {
98  // Position vector
99  r[0] = zeta[0]+X0;
100  r[1] = H;
101 
102  // Tangent vector
103  drdzeta(0,0)=1.0;
104  drdzeta(0,1)=0.0;
105 
106  // Derivative of tangent vector
107  ddrdzeta(0,0,0)=0.0;
108  ddrdzeta(0,0,1)=0.0;
109 
110  } // end of d2position
111 
112  private :
113 
115  double X0;
116 
118  double H;
119 
120 }; //end_of_undeformed_wall
121 
122 
123 
124 
125 
126 
127 
128 //====start_of_physical_parameters=====================
130 //======================================================
132 {
134  double Re=100.0;
135 
137  double ReSt=100.0;
138 
140  double H=0.002;
141 
144  double Q=4.0e-5;
145 
148  double Lambda_sq=2.0;
149 
150 } // end of namespace
151 
152 
153 
154 
155 //====start_of_problem_class==========================================
157 //====================================================================
158 template <class ELEMENT>
159 class FSIDrivenCavityProblem : public virtual Problem
160 {
161 
162  public :
163 
167  FSIDrivenCavityProblem(const unsigned& nx,
168  const unsigned& ny,
169  const double& lx,
170  const double& ly,
171  const double& gap_fraction,
172  const double& period);
173 
176  {
177  // Mesh gets killed in general problem destructor
178  }
179 
180 
183  {
184  // Upcast from pointer to the Mesh base class to the specific
185  // element type that we're using here.
186  return dynamic_cast<
188  (Bulk_mesh_pt);
189  }
190 
191 
194  {
195  return Wall_mesh_pt;
196  } // end of access to wall mesh
197 
198 
201 
204 
207  {
208  // Oscillating lid
209  unsigned ibound=0;
210  unsigned num_nod=bulk_mesh_pt()->nboundary_node(ibound);
211  for (unsigned inod=0;inod<num_nod;inod++)
212  {
213  // Which node are we dealing with?
214  Node* node_pt=bulk_mesh_pt()->boundary_node_pt(ibound,inod);
215 
216  // Set velocity
217  double veloc=1.0-cos(2.0*MathematicalConstants::Pi*time_pt()->time()/T);
218 
219  // Apply no slip
220  node_pt->set_value(0,veloc);
221  }
222  }
223 
224 
229  {
230  Bulk_mesh_pt->node_update();
231  }
232 
234  void doc_solution(DocInfo& doc_info,ofstream& trace_file);
235 
236 
238  void set_initial_condition();
239 
240 protected :
241 
243  unsigned Nx;
244 
246  unsigned Ny;
247 
249  double Lx;
250 
252  double Ly;
253 
255  double T;
256 
259 
262 
265 
268 
271 
275 
276 };//end of problem class
277 
278 
279 
280 
281 //=====start_of_constructor======================================
283 //===============================================================
284 template <class ELEMENT>
286  const unsigned& nx,
287  const unsigned& ny,
288  const double& lx,
289  const double& ly,
290  const double& gap_fraction,
291  const double& period)
292 {
293 
294  // Store problem parameters
295  Nx=nx;
296  Ny=ny;
297  Lx=lx;
298  Ly=ly;
299 
300  // Period of lid oscillation
301  T=period;
302 
303 
304  // Allow for crappy initial guess
306  Max_residuals = 1.0e8;
307 
308  // Allocate the timestepper -- this constructs the Problem's
309  // time object with a sufficient amount of storage to store the
310  // previous timsteps.
311  BDF<2>* fluid_time_stepper_pt=new BDF<2>;
312  add_time_stepper_pt(fluid_time_stepper_pt);
313 
314  // Create the timestepper for the solid
315  Newmark<2>* solid_time_stepper_pt=new Newmark<2>;
316  //Steady<2>* solid_time_stepper_pt=new Steady<2>;
317  add_time_stepper_pt(solid_time_stepper_pt);
318 
319  // Geometric object that represents the undeformed wall:
320  // A straight line at height y=ly; starting at x=0.
321  UndeformedWall* undeformed_wall_pt=new UndeformedWall(0.0,ly);
322 
323  //Create the "wall" mesh with FSI Hermite elements
325  (nx,lx,undeformed_wall_pt,solid_time_stepper_pt);
326 
327 
328  // Build a geometric object (one Lagrangian, two Eulerian coordinates)
329  // from the wall mesh
330  Wall_geom_object_pt=
331  new MeshAsGeomObject(Wall_mesh_pt);
332 
333  //Build bulk (fluid) mesh
334  Bulk_mesh_pt = new AlgebraicFSIDrivenCavityMesh<ELEMENT>
335  (nx, ny, lx, ly, gap_fraction, Wall_geom_object_pt,fluid_time_stepper_pt);
336 
337 
338  // Add the sub meshes to the problem
339  add_sub_mesh(Bulk_mesh_pt);
340  add_sub_mesh(Wall_mesh_pt);
341 
342  // Combine all submeshes into a single Mesh
343  build_global_mesh();
344 
345 
346  // Complete build of fluid mesh
347  //-----------------------------
348 
349  // Loop over the elements to set up element-specific
350  // things that cannot be handled by constructor
351  unsigned n_element=Bulk_mesh_pt->nelement();
352  for(unsigned e=0;e<n_element;e++)
353  {
354  // Upcast from GeneralisedElement to the present element
355  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(Bulk_mesh_pt->element_pt(e));
356 
357  //Set the Reynolds number
358  el_pt->re_pt() = &Global_Physical_Variables::Re;
359 
360  // Set the Womersley number
361  el_pt->re_st_pt() = &Global_Physical_Variables::ReSt;
362 
363  } // end loop over elements
364 
365 
366 
367  // Apply boundary conditions for fluid
368  //------------------------------------
369 
370  // Pin the velocity on all boundaries apart from 1 and 5
371  // (the gaps above the driven lid)
372  for (unsigned ibound=0;ibound<6;ibound++)
373  {
374  if ((ibound!=1)&&(ibound!=5))
375  {
376  unsigned num_nod= bulk_mesh_pt()->nboundary_node(ibound);
377  for (unsigned inod=0;inod<num_nod;inod++)
378  {
379  for(unsigned i=0;i<2;i++)
380  {
381  bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(i);
382  }
383  }
384  }
385  }//end of pin_velocity
386 
387 
388  // Complete build of wall elements
389  //--------------------------------
390 
391  //Loop over the elements to set physical parameters etc.
392  n_element = wall_mesh_pt()->nelement();
393  for(unsigned e=0;e<n_element;e++)
394  {
395  // Upcast to the specific element type
396  FSIHermiteBeamElement *elem_pt =
397  dynamic_cast<FSIHermiteBeamElement*>(wall_mesh_pt()->element_pt(e));
398 
399  // Set physical parameters for each element:
400  elem_pt->h_pt() = &Global_Physical_Variables::H;
401 
402  // Function that specifies the load ratios
403  elem_pt->q_pt() = &Global_Physical_Variables::Q;
404 
405  // Set the undeformed shape for each element
406  elem_pt->undeformed_beam_pt() = undeformed_wall_pt;
407 
408  // The normal on the wall elements as computed by the FSIHermiteElements
409  // points away from the fluid rather than into the fluid (as assumed
410  // by default)
412 
413  // Timescale ratio for solid
415 
416  } // end of loop over elements
417 
418 
419  // Boundary conditions for wall mesh
420  //----------------------------------
421 
422  // Set the boundary conditions: Each end of the beam is fixed in space
423  // Loop over the boundaries (ends of the beam)
424  for(unsigned b=0;b<2;b++)
425  {
426  // Pin displacements in both x and y directions
427  wall_mesh_pt()->boundary_node_pt(b,0)->pin_position(0);
428  wall_mesh_pt()->boundary_node_pt(b,0)->pin_position(1);
429  }
430 
431 
432 
433 
434  //Choose control nodes
435  //---------------------
436 
437  // Left boundary
438  unsigned ibound=5;
439  unsigned num_nod= bulk_mesh_pt()->nboundary_node(ibound);
440  unsigned control_nod=num_nod/2;
441  Left_node_pt= bulk_mesh_pt()->boundary_node_pt(ibound, control_nod);
442 
443  // Right boundary
444  ibound=1;
445  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
446  control_nod=num_nod/2;
447  Right_node_pt= bulk_mesh_pt()->boundary_node_pt(ibound, control_nod);
448 
449 
450  // Set the pointer to the control node on the wall
451  num_nod= wall_mesh_pt()->nnode();
452  Wall_node_pt=wall_mesh_pt()->node_pt(nx/2);
453 
454 
455 
456 
457  // Setup FSI
458  //----------
459 
460  // The velocity of the fluid nodes on the wall (fluid mesh boundary 3)
461  // is set by the wall motion -- hence the no-slip condition must be
462  // re-applied whenever a node update is performed for these nodes.
463  // Such tasks may be performed automatically by the auxiliary node update
464  // function specified by a function pointer:
465  ibound=3;
466  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
467  for (unsigned inod=0;inod<num_nod;inod++)
468  {
469  static_cast<AlgebraicNode*>(
470  bulk_mesh_pt()->boundary_node_pt(ibound, inod))->
471  set_auxiliary_node_update_fct_pt(
473  }
474 
475 
476  // Work out which fluid dofs affect the residuals of the wall elements:
477  // We pass the boundary between the fluid and solid meshes and
478  // pointers to the meshes. The interaction boundary is boundary 3 of the
479  // 2D fluid mesh.
480  FSI_functions::setup_fluid_load_info_for_solid_elements<ELEMENT,2>
481  (this,3,Bulk_mesh_pt,Wall_mesh_pt);
482 
483  // Setup equation numbering scheme
484  cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
485 
486 
487 }//end of constructor
488 
489 
490 
491 
492 //====start_of_doc_solution===================================================
494 //============================================================================
495 template <class ELEMENT>
497  ofstream& trace_file)
498 {
499 
500  // Doc fsi
501  if (CommandLineArgs::Argc>1)
502  {
503  FSI_functions::doc_fsi<AlgebraicNode>(Bulk_mesh_pt,Wall_mesh_pt,doc_info);
504  }
505 
506  ofstream some_file;
507  char filename[100];
508 
509  // Number of plot points
510  unsigned npts;
511  npts=5;
512 
513  // Output fluid solution
514  sprintf(filename,"%s/soln%i.dat",doc_info.directory().c_str(),
515  doc_info.number());
516  some_file.open(filename);
517  bulk_mesh_pt()->output(some_file,npts);
518  some_file.close();
519 
520  // Document the wall shape
521  sprintf(filename,"%s/beam%i.dat",doc_info.directory().c_str(),
522  doc_info.number());
523  some_file.open(filename);
524  wall_mesh_pt()->output(some_file,npts);
525  some_file.close();
526 
527 
528  // Write trace file
529  trace_file << time_pt()->time() << " "
530  << Wall_node_pt->x(1) << " "
531  << Left_node_pt->value(0) << " "
532  << Right_node_pt->value(0) << " "
533  << std::endl;
534 
535 } // end_of_doc_solution
536 
537 
538 
539 
540 //====start_of_apply_initial_condition========================================
542 //============================================================================
543 template <class ELEMENT>
545 {
546  // Impulsive start for wall
547  wall_mesh_pt()->assign_initial_values_impulsive();
548 
549  // Update the mesh
550  bulk_mesh_pt()->node_update();
551 
552  // Loop over the nodes to set initial guess everywhere
553  unsigned num_nod = bulk_mesh_pt()->nnode();
554  for (unsigned n=0;n<num_nod;n++)
555  {
556  // Get nodal coordinates
557  Vector<double> x(2);
558  x[0]=bulk_mesh_pt()->node_pt(n)->x(0);
559  x[1]=bulk_mesh_pt()->node_pt(n)->x(1);
560 
561  // Assign initial condition: Zero flow
562  bulk_mesh_pt()->node_pt(n)->set_value(0,0.0);
563  bulk_mesh_pt()->node_pt(n)->set_value(1,0.0);
564  }
565 
566  // Assign initial values for an impulsive start
567  bulk_mesh_pt()->assign_initial_values_impulsive();
568 
569 
570 } // end of set_initial_condition
571 
572 
573 
574 
575 
576 
AnnoyingScalar cos(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:136
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Array< double, 1, 3 > e(1./3., 0.5, 2.)
MatrixXf H
Definition: HessenbergDecomposition_matrixH.cpp:4
MatrixXf Q
Definition: HouseholderQR_householderQ.cpp:1
Scalar * b
Definition: benchVecAdd.cpp:17
Problem class.
Definition: fsi_driven_cavity_problem.h:160
MeshAsGeomObject * Wall_geom_object_pt
Definition: fsi_driven_cavity_problem.h:274
OneDLagrangianMesh< FSIHermiteBeamElement > * Wall_mesh_pt
Pointer to the "wall" mesh.
Definition: fsi_driven_cavity_problem.h:261
unsigned Ny
Number of elements in the y direction.
Definition: fsi_driven_cavity_problem.h:246
Node * Wall_node_pt
Pointer to control node on the wall.
Definition: fsi_driven_cavity_problem.h:270
void actions_after_newton_solve()
Update the problem after solve (empty)
Definition: fsi_driven_cavity_problem.h:203
OneDLagrangianMesh< FSIHermiteBeamElement > * wall_mesh_pt()
Access function for the wall mesh.
Definition: fsi_driven_cavity_problem.h:193
double Lx
Width of domain.
Definition: fsi_driven_cavity_problem.h:249
double T
Period of oscillation.
Definition: fsi_driven_cavity_problem.h:255
double Ly
Height of domain.
Definition: fsi_driven_cavity_problem.h:252
~FSIDrivenCavityProblem()
Destructor.
Definition: fsi_driven_cavity_problem.h:175
Node * Left_node_pt
Pointer to the left control node.
Definition: fsi_driven_cavity_problem.h:264
AlgebraicFSIDrivenCavityMesh< ELEMENT > * bulk_mesh_pt()
Access function for the specific bulk (fluid) mesh.
Definition: fsi_driven_cavity_problem.h:182
void doc_solution(DocInfo &doc_info, ofstream &trace_file)
Doc the solution.
Definition: fsi_driven_cavity_problem.h:496
void actions_before_newton_solve()
Update the problem specs before solve (empty)
Definition: fsi_driven_cavity_problem.h:200
Node * Right_node_pt
Pointer to right control node.
Definition: fsi_driven_cavity_problem.h:267
void actions_before_newton_convergence_check()
Definition: fsi_driven_cavity_problem.h:228
void set_initial_condition()
Apply initial conditions.
Definition: fsi_driven_cavity_problem.h:544
FSIDrivenCavityProblem(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly, const double &gap_fraction, const double &period)
Constructor for the collapsible channel problem.
Definition: fsi_driven_cavity_problem.h:285
AlgebraicFSIDrivenCavityMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
Definition: fsi_driven_cavity_problem.h:258
unsigned Nx
Number of elements in the x direction.
Definition: fsi_driven_cavity_problem.h:243
void actions_before_implicit_timestep()
Update the velocity boundary condition on the moving lid.
Definition: fsi_driven_cavity_problem.h:206
Definition: fsi_chan_problem.h:156
void d2position(const Vector< double > &zeta, Vector< double > &r, DenseMatrix< double > &drdzeta, RankThreeTensor< double > &ddrdzeta) const
Definition: fsi_driven_cavity_problem.h:93
void position(const unsigned &t, const Vector< double > &zeta, Vector< double > &r) const
Definition: fsi_driven_cavity_problem.h:79
void position(const Vector< double > &zeta, Vector< double > &r) const
Position vector at Lagrangian coordinate zeta.
Definition: fsi_driven_cavity_problem.h:68
UndeformedWall(const double &x0, const double &h)
Definition: fsi_driven_cavity_problem.h:60
Definition: fsi_driven_cavity_mesh.template.h:161
Definition: algebraic_elements.h:55
void set_value(const unsigned &i, const double &value_)
Definition: nodes.h:271
Definition: oomph_utilities.h:499
std::string directory() const
Output directory.
Definition: oomph_utilities.h:524
unsigned & number()
Number used (e.g.) for labeling output files.
Definition: oomph_utilities.h:554
Definition: beam_elements.h:352
void set_normal_pointing_out_of_fluid()
Definition: beam_elements.h:384
double *& q_pt()
Definition: fsi.h:248
Definition: geom_objects.h:101
double *& h_pt()
Return a pointer to non-dim. wall thickness.
Definition: beam_elements.h:240
double *& lambda_sq_pt()
Return a pointer to timescale ratio (nondim density)
Definition: beam_elements.h:246
GeomObject *& undeformed_beam_pt()
Definition: beam_elements.h:253
Definition: mesh_as_geometric_object.h:93
Definition: nodes.h:906
Definition: problem.h:151
A Rank 3 Tensor class.
Definition: matrices.h:1370
double Pi
Definition: two_d_biharmonic.cc:235
EIGEN_STRONG_INLINE const Eigen::CwiseBinaryOp< Eigen::internal::scalar_zeta_op< typename DerivedX::Scalar >, const DerivedX, const DerivedQ > zeta(const Eigen::ArrayBase< DerivedX > &x, const Eigen::ArrayBase< DerivedQ > &q)
Definition: SpecialFunctionsArrayAPI.h:152
unsigned Nx
Number of elements in each direction (used by SimpleCubicMesh)
Definition: structured_cubic_point_source.cc:114
unsigned Ny
Definition: structured_cubic_point_source.cc:115
double Re
Reynolds number.
Definition: axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:61
double ReSt
Product of Reynolds and Strouhal numbers.
Definition: axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:64
double Ly
Length of domain in y direction.
Definition: periodic_load.cc:58
double Lx
Length of domain in x direction.
Definition: periodic_load.cc:55
Global variables.
Definition: TwenteMeshGluing.cpp:60
double ReSt
Womersley number.
Definition: rayleigh_instability.cc:56
double Q
Ratio of scales.
Definition: elastic_bretherton.cc:131
double Lambda_sq
Pseudo-solid mass density.
Definition: pressure_driven_torus.cc:62
double Re
Reynolds number.
Definition: fibre.cc:55
double H
Nondim thickness.
Definition: steady_ring.cc:50
Vector< double > x0(2, 0.0)
string filename
Definition: MergeRestartFiles.py:39
const double ly
Definition: ConstraintElementsUnitTest.cpp:34
const double lx
Definition: ConstraintElementsUnitTest.cpp:33
const unsigned nx
Definition: ConstraintElementsUnitTest.cpp:30
const unsigned ny
Definition: ConstraintElementsUnitTest.cpp:31
r
Definition: UniformPSDSelfTest.py:20
int Argc
Number of arguments + 1.
Definition: oomph_utilities.cc:407
void apply_no_slip_on_moving_wall(Node *node_pt)
Definition: fsi.cc:48
unsigned Max_newton_iterations
Maximum number of newton iterations.
Definition: elements.cc:1654
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
list x
Definition: plotDoE.py:28
t
Definition: plotPSD.py:36