circular_driven_cavity2.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 QuarterCircleDrivenCavityProblem2 : 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 1:
104  unsigned ibound=1;
105  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
106  for (unsigned inod=0;inod<num_nod;inod++)
107  {
108  // get coordinates
109  double x=mesh_pt()->boundary_node_pt(ibound,inod)->x(0);
110  double y=mesh_pt()->boundary_node_pt(ibound,inod)->x(1);
111  // find Lagrangian coordinate (the angle)
112  double zeta=0.0;
113  if (x!=0.0)
114  {
115  zeta=atan(y/x);
116  }
117  // Tangential flow u0
118  unsigned i=0;
119  mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,-sin(zeta));
120  // Tangential flow u1
121  i=1;
122  mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,cos(zeta));
123  }
124 
125  // Overwrite with no flow along all boundaries
126  unsigned num_bound = mesh_pt()->nboundary();
127  for(unsigned ibound=0;ibound<num_bound;ibound++)
128  {
129  if (ibound!=1)
130  {
131  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
132  for (unsigned inod=0;inod<num_nod;inod++)
133  {
134  for (unsigned i=0;i<2;i++)
135  {
136  mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,0.0);
137  }
138  }
139  }
140  }
141 
142  } // end_of_actions_before_newton_solve
143 
144 
145  /// After adaptation: Unpin pressure and pin redudant pressure dofs.
147  {
148  // Unpin all pressure dofs
149  RefineableNavierStokesEquations<2>::
150  unpin_all_pressure_dofs(mesh_pt()->element_pt());
151 
152  // Pin redundant pressure dofs
153  RefineableNavierStokesEquations<2>::
154  pin_redundant_nodal_pressures(mesh_pt()->element_pt());
155 
156  // Now pin the first pressure dof in the first element and set it to 0.0
157  fix_pressure(0,0,0.0);
158  } // end_of_actions_after_adapt
159 
160  /// Doc the solution
161  void doc_solution(DocInfo& doc_info);
162 
163 private:
164 
165  /// Pointer to body force function
166  NavierStokesEquations<2>::NavierStokesBodyForceFctPt Body_force_fct_pt;
167 
168  /// Fix pressure in element e at pressure dof pdof and set to pvalue
169  void fix_pressure(const unsigned &e, const unsigned &pdof,
170  const double &pvalue)
171  {
172  //Cast to proper element and fix pressure
173  dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e))->
174  fix_pressure(pdof,pvalue);
175  } // end_of_fix_pressure
176 
177 }; // end_of_problem_class
178 
179 
180 
181 //==start_of_constructor==================================================
182 /// Constructor for driven cavity problem in quarter circle domain
183 //========================================================================
184 template<class ELEMENT>
186  NavierStokesEquations<2>::NavierStokesBodyForceFctPt body_force_fct_pt) :
187  Body_force_fct_pt(body_force_fct_pt)
188 {
189 
190  // Build geometric object that parametrises the curved boundary
191  // of the domain
192 
193  // Half axes for ellipse
194  double a_ellipse=1.0;
195  double b_ellipse=1.0;
196 
197  // Setup elliptical ring
198  GeomObject* Wall_pt=new Ellipse(a_ellipse,b_ellipse);
199 
200  // End points for wall
201  double xi_lo=0.0;
202  double xi_hi=2.0*atan(1.0);
203 
204  //Now create the mesh
205  double fract_mid=0.5;
206  Problem::mesh_pt() = new
207  RefineableQuarterCircleSectorMesh<ELEMENT>(
208  Wall_pt,xi_lo,fract_mid,xi_hi);
209 
210  // Set error estimator
211  Z2ErrorEstimator* error_estimator_pt=new Z2ErrorEstimator;
212  dynamic_cast<RefineableQuarterCircleSectorMesh<ELEMENT>*>(
213  mesh_pt())->spatial_error_estimator_pt()=error_estimator_pt;
214 
215  // Set the boundary conditions for this problem: All nodes are
216  // free by default -- just pin the ones that have Dirichlet conditions
217  // here: All boundaries are Dirichlet boundaries.
218  unsigned num_bound = mesh_pt()->nboundary();
219  for(unsigned ibound=0;ibound<num_bound;ibound++)
220  {
221  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
222  for (unsigned inod=0;inod<num_nod;inod++)
223  {
224  // Loop over values (u and v velocities)
225  for (unsigned i=0;i<2;i++)
226  {
227  mesh_pt()->boundary_node_pt(ibound,inod)->pin(i);
228  }
229  }
230  } // end loop over boundaries
231 
232  //Find number of elements in mesh
233  unsigned n_element = mesh_pt()->nelement();
234 
235  // Loop over the elements to set up element-specific
236  // things that cannot be handled by constructor: Pass pointer to Reynolds
237  // number
238  for(unsigned e=0;e<n_element;e++)
239  {
240  // Upcast from GeneralisedElement to the present element
241  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e));
242 
243  //Set the Reynolds number, etc
244  el_pt->re_pt() = &Global_Physical_Variables2::Re;
245  //Set the Re/Fr
246  el_pt->re_invfr_pt() = &Global_Physical_Variables2::Re_invFr;
247  //Set Gravity vector
248  el_pt->g_pt() = &Global_Physical_Variables2::Gravity;
249  //set body force function
250  el_pt->body_force_fct_pt() = Body_force_fct_pt;
251 
252  } // end loop over elements
253 
254  // Initial refinement level
255  refine_uniformly();
256  refine_uniformly();
257 
258  // Pin redudant pressure dofs
259  RefineableNavierStokesEquations<2>::
260  pin_redundant_nodal_pressures(mesh_pt()->element_pt());
261 
262  // Now pin the first pressure dof in the first element and set it to 0.0
263  fix_pressure(0,0,0.0);
264 
265  // Setup equation numbering scheme
266  cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
267 
268 } // end_of_constructor
269 
270 
271 
272 //==start_of_doc_solution=================================================
273 /// Doc the solution
274 //========================================================================
275 template<class ELEMENT>
277 {
278 
279  ofstream some_file;
280  char filename[100];
281 
282  // Number of plot points
283  unsigned npts=5;
284 
285 
286  // Output solution
287  sprintf(filename,"%s/soln%i.dat",doc_info.directory().c_str(),
288  doc_info.number());
289  some_file.open(filename);
290  mesh_pt()->output(some_file,npts);
291  some_file.close();
292 
293 } // end_of_doc_solution
294 
295 
296 
297 
298 //==start_of_main======================================================
299 /// Driver for QuarterCircleDrivenCavityProblem2 test problem
300 //=====================================================================
301 int main()
302 {
303 
304  // Set output directory and initialise count
305  DocInfo doc_info;
306  doc_info.set_directory("RESLT2");
307 
308  // Set max. number of black-box adaptation
309  unsigned max_adapt=3;
310 
311  // Solve problem 1 with Taylor-Hood elements
312  //--------------------------------------------
313  {
314  // Set up downwards-Gravity vector
317 
318  // Set up Gamma vector for stress-divergence form
319  NavierStokesEquations<2>::Gamma[0]=1;
320  NavierStokesEquations<2>::Gamma[1]=1;
321 
322  // Build problem with Gravity vector in stress divergence form,
323  // using zero body force function
326 
327  // Solve the problem with automatic adaptation
328  problem.newton_solve(max_adapt);
329 
330  // Step number
331  doc_info.number()=0;
332 
333  // Output solution
334  problem.doc_solution(doc_info);
335 
336  } // end of problem 1
337 
338 
339 
340  // Solve problem 2 with Taylor Hood elements
341  //--------------------------------------------
342  {
343  // Set up zero-Gravity vector
346 
347  // Set up Gamma vector for simplified form
348  NavierStokesEquations<2>::Gamma[0]=0;
349  NavierStokesEquations<2>::Gamma[1]=0;
350 
351  // Build problem with body force function and simplified form,
352  // using body force function
355 
356  // Solve the problem with automatic adaptation
357  problem.newton_solve(max_adapt);
358 
359  // Step number
360  doc_info.number()=1;
361 
362  // Output solution
363  problem.doc_solution(doc_info);
364 
365  } // end of problem 2
366 
367 } // end_of_main
368 
369 
int main()
Driver for QuarterCircleDrivenCavityProblem2 test problem.
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
void actions_after_newton_solve()
Update the after solve (empty)
QuarterCircleDrivenCavityProblem2(NavierStokesEquations< 2 >::NavierStokesBodyForceFctPt body_force_fct_pt)
Constructor.
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 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 actions_before_newton_solve()
Update the problem specs before solve. (Re-)set velocity boundary conditions just to be on the safe s...
~QuarterCircleDrivenCavityProblem2()
Destructor: Empty.
Namespace for physical parameters.
double Re_invFr
Reynolds/Froude number.
Vector< double > Gravity(2)
Gravity vector.
void zero_body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Zero functional body force.
void body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Functional body force.