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-2025 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
38using namespace std;
39
40using 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//====================================================================
83template<class ELEMENT>
85{
86
87public:
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
150private:
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//========================================================================
171template<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//========================================================================
262template<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 snprintf(filename, sizeof(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//=====================================================================
288int 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.
Driven cavity problem in quarter circle domain, templated by element type.
~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.
Vector< double > Gravity(2)
Gravity vector.
void zero_body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Zero functional body force.
double Re_invFr
Reynolds/Froude number.