circular_driven_cavity.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 adaptive 2D quarter circle driven cavity. Solved with black
27 // box adaptation, using Taylor Hood and Crouzeix Raviart elements.
28 
29 // Generic oomph-lib header
30 #include "generic.h"
31 
32 // Navier Stokes headers
33 #include "navier_stokes.h"
34 
35 // The mesh
36 #include "meshes/quarter_circle_sector_mesh.h"
37 
38 using namespace std;
39 
40 using namespace oomph;
41 
42 
43 //==start_of_namespace===================================================
44 /// Namespace for physical parameters
45 //=======================================================================
47 {
48  /// Reynolds number
49  double Re=100;
50 
51  /// Reynolds/Froude number
52  double Re_invFr=100;
53 
54  /// Gravity vector
55  Vector<double> Gravity(2);
56 
57  /// Functional body force
58  void body_force(const double& time, const Vector<double>& x,
59  Vector<double>& result)
60  {
61  result[0]=0.0;
62  result[1]=-Re_invFr;
63  }
64 
65  /// Zero functional body force
66  void zero_body_force(const double& time, const Vector<double>& x,
67  Vector<double>& result)
68  {
69  result[0]=0.0;
70  result[1]=0.0;
71  }
72 
73 } // end_of_namespace
74 
75 /// ///////////////////////////////////////////////////////////////////
76 /// ///////////////////////////////////////////////////////////////////
77 /// ///////////////////////////////////////////////////////////////////
78 
79 //==start_of_problem_class============================================
80 /// Driven cavity problem in quarter circle domain, templated
81 /// by element type.
82 //====================================================================
83 template<class ELEMENT>
84 class QuarterCircleDrivenCavityProblem : public Problem
85 {
86 
87 public:
88 
89  /// Constructor
91  NavierStokesEquations<2>::NavierStokesBodyForceFctPt body_force_fct_pt);
92 
93  /// Destructor: Empty
95 
96  /// Update the after solve (empty)
98 
99  /// Update the problem specs before solve.
100  /// (Re-)set velocity boundary conditions just to be on the safe side...
102  {
103  // Setup tangential flow along boundary 0:
104  unsigned ibound=0;
105  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
106  for (unsigned inod=0;inod<num_nod;inod++)
107  {
108  // Tangential flow
109  unsigned i=0;
110  mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,1.0);
111  // No penetration
112  i=1;
113  mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,0.0);
114  }
115 
116  // Overwrite with no flow along all other boundaries
117  unsigned num_bound = mesh_pt()->nboundary();
118  for(unsigned ibound=1;ibound<num_bound;ibound++)
119  {
120  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
121  for (unsigned inod=0;inod<num_nod;inod++)
122  {
123  for (unsigned i=0;i<2;i++)
124  {
125  mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,0.0);
126  }
127  }
128  }
129  } // end_of_actions_before_newton_solve
130 
131 
132  /// After adaptation: Unpin pressure and pin redudant pressure dofs.
134  {
135  // Unpin all pressure dofs
136  RefineableNavierStokesEquations<2>::
137  unpin_all_pressure_dofs(mesh_pt()->element_pt());
138 
139  // Pin redundant pressure dofs
140  RefineableNavierStokesEquations<2>::
141  pin_redundant_nodal_pressures(mesh_pt()->element_pt());
142 
143  // Now pin the first pressure dof in the first element and set it to 0.0
144  fix_pressure(0,0,0.0);
145  } // end_of_actions_after_adapt
146 
147  /// Doc the solution
148  void doc_solution(DocInfo& doc_info);
149 
150 private:
151 
152  /// Pointer to body force function
153  NavierStokesEquations<2>::NavierStokesBodyForceFctPt Body_force_fct_pt;
154 
155  /// Fix pressure in element e at pressure dof pdof and set to pvalue
156  void fix_pressure(const unsigned &e, const unsigned &pdof,
157  const double &pvalue)
158  {
159  //Cast to proper element and fix pressure
160  dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e))->
161  fix_pressure(pdof,pvalue);
162  } // end_of_fix_pressure
163 
164 }; // end_of_problem_class
165 
166 
167 
168 //==start_of_constructor==================================================
169 /// Constructor for driven cavity problem in quarter circle domain
170 //========================================================================
171 template<class ELEMENT>
173  NavierStokesEquations<2>::NavierStokesBodyForceFctPt body_force_fct_pt) :
174  Body_force_fct_pt(body_force_fct_pt)
175 {
176 
177  // Build geometric object that parametrises the curved boundary
178  // of the domain
179 
180  // Half axes for ellipse
181  double a_ellipse=1.0;
182  double b_ellipse=1.0;
183 
184  // Setup elliptical ring
185  GeomObject* Wall_pt=new Ellipse(a_ellipse,b_ellipse);
186 
187  // End points for wall
188  double xi_lo=0.0;
189  double xi_hi=2.0*atan(1.0);
190 
191  //Now create the mesh
192  double fract_mid=0.5;
193  Problem::mesh_pt() = new
194  RefineableQuarterCircleSectorMesh<ELEMENT>(
195  Wall_pt,xi_lo,fract_mid,xi_hi);
196 
197  // Set error estimator
198  Z2ErrorEstimator* error_estimator_pt=new Z2ErrorEstimator;
199  dynamic_cast<RefineableQuarterCircleSectorMesh<ELEMENT>*>(
200  mesh_pt())->spatial_error_estimator_pt()=error_estimator_pt;
201 
202  // Set the boundary conditions for this problem: All nodes are
203  // free by default -- just pin the ones that have Dirichlet conditions
204  // here: All boundaries are Dirichlet boundaries.
205  unsigned num_bound = mesh_pt()->nboundary();
206  for(unsigned ibound=0;ibound<num_bound;ibound++)
207  {
208  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
209  for (unsigned inod=0;inod<num_nod;inod++)
210  {
211  // Loop over values (u and v velocities)
212  for (unsigned i=0;i<2;i++)
213  {
214  mesh_pt()->boundary_node_pt(ibound,inod)->pin(i);
215  }
216  }
217  } // end loop over boundaries
218 
219  //Find number of elements in mesh
220  unsigned n_element = mesh_pt()->nelement();
221 
222  // Loop over the elements to set up element-specific
223  // things that cannot be handled by constructor: Pass pointer to Reynolds
224  // number
225  for(unsigned e=0;e<n_element;e++)
226  {
227  // Upcast from GeneralisedElement to the present element
228  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e));
229 
230  //Set the Reynolds number, etc
231  el_pt->re_pt() = &Global_Physical_Variables::Re;
232  //Set the Re/Fr
233  el_pt->re_invfr_pt() = &Global_Physical_Variables::Re_invFr;
234  //Set Gravity vector
235  el_pt->g_pt() = &Global_Physical_Variables::Gravity;
236  //set body force function
237  el_pt->body_force_fct_pt() = Body_force_fct_pt;
238 
239  } // end loop over elements
240 
241  // Initial refinement level
242  refine_uniformly();
243  refine_uniformly();
244 
245  // Pin redudant pressure dofs
246  RefineableNavierStokesEquations<2>::
247  pin_redundant_nodal_pressures(mesh_pt()->element_pt());
248 
249  // Now pin the first pressure dof in the first element and set it to 0.0
250  fix_pressure(0,0,0.0);
251 
252  // Setup equation numbering scheme
253  cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
254 
255 } // end_of_constructor
256 
257 
258 
259 //==start_of_doc_solution=================================================
260 /// Doc the solution
261 //========================================================================
262 template<class ELEMENT>
264 {
265 
266  ofstream some_file;
267  char filename[100];
268 
269  // Number of plot points
270  unsigned npts=5;
271 
272 
273  // Output solution
274  sprintf(filename,"%s/soln%i.dat",doc_info.directory().c_str(),
275  doc_info.number());
276  some_file.open(filename);
277  mesh_pt()->output(some_file,npts);
278  some_file.close();
279 
280 } // end_of_doc_solution
281 
282 
283 
284 
285 //==start_of_main======================================================
286 /// Driver for QuarterCircleDrivenCavityProblem test problem
287 //=====================================================================
288 int main()
289 {
290 
291  // Set output directory and initialise count
292  DocInfo doc_info;
293  doc_info.set_directory("RESLT");
294 
295  // Set max. number of black-box adaptation
296  unsigned max_adapt=3;
297 
298  // Solve problem 1 with Taylor-Hood elements
299  //--------------------------------------------
300  {
301  // Set up downwards-Gravity vector
304 
305  // Set up Gamma vector for stress-divergence form
306  NavierStokesEquations<2>::Gamma[0]=1;
307  NavierStokesEquations<2>::Gamma[1]=1;
308 
309  // Build problem with Gravity vector in stress divergence form,
310  // using zero body force function
313 
314  // Solve the problem with automatic adaptation
315  problem.newton_solve(max_adapt);
316 
317  // Step number
318  doc_info.number()=0;
319 
320  // Output solution
321  problem.doc_solution(doc_info);
322 
323  } // end of problem 1
324 
325 
326 
327  // Solve problem 2 with Taylor Hood elements
328  //--------------------------------------------
329  {
330  // Set up zero-Gravity vector
333 
334  // Set up Gamma vector for simplified form
335  NavierStokesEquations<2>::Gamma[0]=0;
336  NavierStokesEquations<2>::Gamma[1]=0;
337 
338  // Build problem with body force function and simplified form,
339  // using body force function
342 
343  // Solve the problem with automatic adaptation
344  problem.newton_solve(max_adapt);
345 
346  // Step number
347  doc_info.number()=1;
348 
349  // Output solution
350  problem.doc_solution(doc_info);
351 
352  } // end of problem 2
353 
354 } // end_of_main
355 
356 
int main()
Driver for QuarterCircleDrivenCavityProblem test problem.
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
~QuarterCircleDrivenCavityProblem()
Destructor: Empty.
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 doc_solution(DocInfo &doc_info)
Doc the solution.
void actions_after_adapt()
After adaptation: Unpin pressure and pin redudant pressure dofs.
NavierStokesEquations< 2 >::NavierStokesBodyForceFctPt Body_force_fct_pt
Pointer to body force function.
void actions_before_newton_solve()
Update the problem specs before solve. (Re-)set velocity boundary conditions just to be on the safe s...
void actions_after_newton_solve()
Update the after solve (empty)
QuarterCircleDrivenCavityProblem(NavierStokesEquations< 2 >::NavierStokesBodyForceFctPt body_force_fct_pt)
Constructor.
Namespace for physical parameters.
void body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Functional body force.
void zero_body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Zero functional body force.
double Re_invFr
Reynolds/Froude number.
Vector< double > Gravity(2)
Gravity vector.