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-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 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
163private:
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//========================================================================
184template<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
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//========================================================================
275template<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 snprintf(filename, sizeof(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//=====================================================================
301int 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.
Driven cavity problem in quarter circle domain, templated by element type.
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...
Namespace for physical parameters.
double Re_invFr
Reynolds/Froude number.
void zero_body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Zero functional body force.
Vector< double > Gravity(2)
Gravity vector.
void body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Functional body force.