adaptive_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 rectangular 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/rectangular_quadmesh.h"
37
38using namespace std;
39
40using namespace oomph;
41
42//==start_of_namespace===================================================
43/// Namespace for physical parameters
44//=======================================================================
46{
47 /// Reynolds number
48 double Re=100;
49} // end_of_namespace
50
51
52
53//==start_of_problem_class============================================
54/// Driven cavity problem in rectangular domain, templated
55/// by element type.
56//====================================================================
57template<class ELEMENT>
58class RefineableDrivenCavityProblem : public Problem
59{
60
61public:
62
63 /// Constructor
65
66 /// Destructor: Empty
68
69 /// Update the after solve (empty)
71
72 /// Update the problem specs before solve.
73 /// (Re-)set velocity boundary conditions just to be on the safe side...
75 {
76 // Setup tangential flow along boundary 0:
77 unsigned ibound=0;
78 unsigned num_nod= mesh_pt()->nboundary_node(ibound);
79 for (unsigned inod=0;inod<num_nod;inod++)
80 {
81 // Tangential flow
82 unsigned i=0;
83 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,1.0);
84 // No penetration
85 i=1;
86 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,0.0);
87 }
88
89 // Overwrite with no flow along all other boundaries
90 unsigned num_bound = mesh_pt()->nboundary();
91 for(unsigned ibound=1;ibound<num_bound;ibound++)
92 {
93 unsigned num_nod= mesh_pt()->nboundary_node(ibound);
94 for (unsigned inod=0;inod<num_nod;inod++)
95 {
96 for (unsigned i=0;i<2;i++)
97 {
98 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,0.0);
99 }
100 }
101 }
102 } // end_of_actions_before_newton_solve
103
104
105 /// After adaptation: Unpin pressure and pin redudant pressure dofs.
107 {
108 // Unpin all pressure dofs
109 RefineableNavierStokesEquations<2>::
110 unpin_all_pressure_dofs(mesh_pt()->element_pt());
111
112 // Pin redundant pressure dofs
113 RefineableNavierStokesEquations<2>::
114 pin_redundant_nodal_pressures(mesh_pt()->element_pt());
115
116 // Now set the first pressure dof in the first element to 0.0
117 fix_pressure(0,0,0.0);
118 } // end_of_actions_after_adapt
119
120 /// Doc the solution
121 void doc_solution(DocInfo& doc_info);
122
123
124private:
125
126 /// Fix pressure in element e at pressure dof pdof and set to pvalue
127 void fix_pressure(const unsigned &e, const unsigned &pdof,
128 const double &pvalue)
129 {
130 //Cast to proper element and fix pressure
131 dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e))->
132 fix_pressure(pdof,pvalue);
133 } // end_of_fix_pressure
134
135}; // end_of_problem_class
136
137
138
139//==start_of_constructor==================================================
140/// Constructor for RefineableDrivenCavity problem
141///
142//========================================================================
143template<class ELEMENT>
145{
146
147 // Setup mesh
148
149 // # of elements in x-direction
150 unsigned n_x=10;
151
152 // # of elements in y-direction
153 unsigned n_y=10;
154
155 // Domain length in x-direction
156 double l_x=1.0;
157
158 // Domain length in y-direction
159 double l_y=1.0;
160
161 // Build and assign mesh
162 Problem::mesh_pt() =
163 new RefineableRectangularQuadMesh<ELEMENT>(n_x,n_y,l_x,l_y);
164
165 // Set error estimator
166 Z2ErrorEstimator* error_estimator_pt=new Z2ErrorEstimator;
167 dynamic_cast<RefineableRectangularQuadMesh<ELEMENT>*>(mesh_pt())->
168 spatial_error_estimator_pt()=error_estimator_pt;
169
170 // Set the boundary conditions for this problem: All nodes are
171 // free by default -- just pin the ones that have Dirichlet conditions
172 // here: All boundaries are Dirichlet boundaries.
173 unsigned num_bound = mesh_pt()->nboundary();
174 for(unsigned ibound=0;ibound<num_bound;ibound++)
175 {
176 unsigned num_nod= mesh_pt()->nboundary_node(ibound);
177 for (unsigned inod=0;inod<num_nod;inod++)
178 {
179 // Loop over values (u and v velocities)
180 for (unsigned i=0;i<2;i++)
181 {
182 mesh_pt()->boundary_node_pt(ibound,inod)->pin(i);
183 }
184 }
185 } // end loop over boundaries
186
187 //Find number of elements in mesh
188 unsigned n_element = mesh_pt()->nelement();
189
190 // Loop over the elements to set up element-specific
191 // things that cannot be handled by constructor: Pass pointer to Reynolds
192 // number
193 for(unsigned e=0;e<n_element;e++)
194 {
195 // Upcast from GeneralisedElement to the present element
196 ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e));
197 //Set the Reynolds number, etc
198 el_pt->re_pt() = &Global_Physical_Variables::Re;
199 } // end loop over elements
200
201 // Pin redudant pressure dofs
202 RefineableNavierStokesEquations<2>::
203 pin_redundant_nodal_pressures(mesh_pt()->element_pt());
204
205 // Now set the first pressure dof in the first element to 0.0
206 fix_pressure(0,0,0.0);
207
208 // Setup equation numbering scheme
209 cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
210
211} // end_of_constructor
212
213
214
215//==start_of_doc_solution=================================================
216/// Doc the solution
217//========================================================================
218template<class ELEMENT>
220{
221
222 ofstream some_file;
223 char filename[100];
224
225 // Number of plot points
226 unsigned npts=5;
227
228
229 // Output solution
230 snprintf(filename, sizeof(filename), "%s/soln%i.dat",doc_info.directory().c_str(),
231 doc_info.number());
232 some_file.open(filename);
233 mesh_pt()->output(some_file,npts);
234 some_file.close();
235
236} // end_of_doc_solution
237
238
239
240
241//==start_of_main======================================================
242/// Driver for RefineableDrivenCavity test problem
243//=====================================================================
244int main()
245{
246
247 // Set output directory
248 DocInfo doc_info;
249 doc_info.set_directory("RESLT");
250
251
252 // Set max. number of black-box adaptation
253 unsigned max_adapt=3;
254
255 // Solve problem with Taylor Hood elements
256 //---------------------------------------
257 {
258 //Build problem
260
261 // Solve the problem with automatic adaptation
262 problem.newton_solve(max_adapt);
263
264 // Step number
265 doc_info.number()=0;
266
267 //Output solution
268 problem.doc_solution(doc_info);
269 } // end of Taylor Hood elements
270
271
272 // Solve problem with Crouzeix Raviart elements
273 //--------------------------------------------
274 {
275 // Build problem
277
278 // Solve the problem with automatic adaptation
279 problem.newton_solve(max_adapt);
280
281 // Step number
282 doc_info.number()=1;
283
284 //Output solution
285 problem.doc_solution(doc_info);
286 } // end of Crouzeix Raviart elements
287
288
289} // end_of_main
290
291
292
293
294
295
296
297
298
299
300
int main()
Driver for RefineableDrivenCavity test problem.
Driven cavity problem in rectangular domain, templated by element type.
void doc_solution(DocInfo &doc_info)
Doc the solution.
void actions_after_newton_solve()
Update the after solve (empty)
~RefineableDrivenCavityProblem()
Destructor: Empty.
void actions_after_adapt()
After adaptation: Unpin pressure and pin redudant pressure dofs.
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.