mesh_from_triangle_navier_stokes.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 flow past rectangular box -- meshed with triangle
27
28//Generic includes
29#include "generic.h"
30#include "navier_stokes.h"
31
32// The mesh
34
35using namespace std;
36
37using namespace oomph;
38
39//==start_of_namespace==============================
40/// Namespace for physical parameters
41//==================================================
43{
44
45 /// Reynolds number
46 double Re=10.0;
47
48} // end_of_namespace
49
50
51
52////////////////////////////////////////////////////////////////////////
53////////////////////////////////////////////////////////////////////////
54////////////////////////////////////////////////////////////////////////
55
56
57
58//==start_of_problem_class============================================
59/// Flow past a box in a channel
60//====================================================================
61template<class ELEMENT>
62class FlowPastBoxProblem : public Problem
63{
64
65public:
66
67
68 /// Constructor: Pass filenames for mesh
69 FlowPastBoxProblem(const string& node_file_name,
70 const string& element_file_name,
71 const string& poly_file_name);
72
73 /// Destructor (empty)
75
76 /// Update the after solve (empty)
78
79 /// Update the problem specs before solve.
80 /// Re-set velocity boundary conditions just to be on the safe side...
82 {
83 // Find max. and min y-coordinate at inflow
84 double y_min=1.0e20;
85 double y_max=-1.0e20;
86 unsigned ibound=0;
87 unsigned num_nod= mesh_pt()->nboundary_node(ibound);
88 for (unsigned inod=0;inod<num_nod;inod++)
89 {
90 double y=mesh_pt()->boundary_node_pt(ibound,inod)->x(1);
91 if (y>y_max)
92 {
93 y_max=y;
94 }
95 if (y<y_min)
96 {
97 y_min=y;
98 }
99 }
100
101 // Loop over all boundaries
102 for (unsigned ibound=0;ibound<mesh_pt()->nboundary();ibound++)
103 {
104 unsigned num_nod= mesh_pt()->nboundary_node(ibound);
105 for (unsigned inod=0;inod<num_nod;inod++)
106 {
107 // Parabolic horizontal flow at inflow
108 if (ibound==0)
109 {
110 double y=mesh_pt()->boundary_node_pt(ibound,inod)->x(1);
111 double veloc=(y-y_min)*(y_max-y);
112 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,veloc);
113 }
114 // Zero horizontal flow elsewhere (either as IC or otherwise)
115 else
116 {
117 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,0.0);
118 }
119 // Zero vertical flow on all boundaries
120 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(1,0.0);
121 }
122 }
123 } // end_of_actions_before_newton_solve
124
125#ifdef ADAPT
126 // Perform actions after mesh adaptation
127 void actions_after_adapt();
128#endif
129
130#ifdef ADAPT
131 /// Access function for the specific mesh
133 {
134 return dynamic_cast<RefineableTriangleMesh<ELEMENT>*>(Problem::mesh_pt());
135 }
136#else
137 /// Access function for the specific mesh
139 {
140 return dynamic_cast<TriangleMesh<ELEMENT>*>(Problem::mesh_pt());
141 }
142#endif
143
144 /// Doc the solution
145 void doc_solution(DocInfo& doc_info);
146
147#ifdef ADAPT
148private:
149 /// Pointer to the bulk mesh
151
152 /// Error estimator
153 Z2ErrorEstimator* error_estimator_pt;
154
155#endif
156
157}; // end_of_problem_class
158
159
160//==start_of_constructor==================================================
161/// Constructor for FlowPastBox problem. Pass filenames for mesh
162//========================================================================
163template<class ELEMENT>
165 const string& node_file_name,
166 const string& element_file_name,
167 const string& poly_file_name)
168{
169
170 Problem::Max_residuals=1000.0;
171
172#ifdef ADAPT
173 //Create mesh
177
178 // Set error estimator for bulk mesh
179 Z2ErrorEstimator* error_estimator_pt=new Z2ErrorEstimator;
180 Bulk_mesh_pt->spatial_error_estimator_pt() = error_estimator_pt;
181
182 // Set the problem mesh pointer to the bulk mesh
183 Problem::mesh_pt() = Bulk_mesh_pt;
184
185#else
186 //Create mesh
187 Problem::mesh_pt() = new TriangleMesh<ELEMENT>(node_file_name,
190#endif
191
192 // Set the boundary conditions for this problem: All nodes are
193 // free by default -- just pin the ones that have Dirichlet conditions
194 // here.
195 unsigned num_bound = mesh_pt()->nboundary();
196 for(unsigned ibound=0;ibound<num_bound;ibound++)
197 {
198 unsigned num_nod= mesh_pt()->nboundary_node(ibound);
199 for (unsigned inod=0;inod<num_nod;inod++)
200 {
201 // Pin horizontal velocity everywhere apart from pure outflow
202 if ((ibound!=2))
203 {
204 mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
205 }
206
207 // Pin vertical velocity everywhere
208 mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
209 }
210 } // end loop over boundaries
211
212 // Complete the build of all elements so they are fully functional
213
214 //Find number of elements in mesh
215 unsigned n_element = mesh_pt()->nelement();
216
217 // Loop over the elements to set up element-specific
218 // things that cannot be handled by constructor
219 for(unsigned e=0;e<n_element;e++)
220 {
221 // Upcast from GeneralisedElement to the present element
222 ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e));
223
224 //Set the Reynolds number
226 } // end loop over elements
227
228
229 // Setup equation numbering scheme
230 cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
231
232} // end_of_constructor
233
234#ifdef ADAPT
235//========================================================================
236// Perform actions after mesh adaptation
237//========================================================================
238template<class ELEMENT>
240{
241
242 // Pin the nodes and make all the element fully functional since the
243 // mesh adaptation generated a new mesh
244
245 // Set the boundary conditions for this problem: All nodes are
246 // free by default -- just pin the ones that have Dirichlet conditions
247 // here.
248 unsigned num_bound = mesh_pt()->nboundary();
249 for(unsigned ibound=0;ibound<num_bound;ibound++)
250 {
251 unsigned num_nod= mesh_pt()->nboundary_node(ibound);
252 for (unsigned inod=0;inod<num_nod;inod++)
253 {
254 // Pin horizontal velocity everywhere apart from pure outflow
255 if ((ibound!=2))
256 {
257 mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
258 }
259
260 // Pin vertical velocity everywhere
261 mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
262 }
263 } // end loop over boundaries
264
265 // Complete the build of all elements so they are fully functional
266
267 //Find number of elements in mesh
268 unsigned n_element = mesh_pt()->nelement();
269
270 // Loop over the elements to set up element-specific
271 // things that cannot be handled by constructor
272 for(unsigned e=0;e<n_element;e++)
273 {
274 // Upcast from GeneralisedElement to the present element
275 ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e));
276
277 //Set the Reynolds number
279 } // end loop over elements
280
281
282 // Setup equation numbering scheme
283 cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
284
285}
286#endif
287
288
289//==start_of_doc_solution=================================================
290/// Doc the solution
291//========================================================================
292template<class ELEMENT>
294{
296 char filename[100];
297
298 // Number of plot points
299 unsigned npts;
300 npts=5;
301
302 // Output solution
303 snprintf(filename, sizeof(filename), "%s/soln%i.dat",doc_info.directory().c_str(),
304 doc_info.number());
305 some_file.open(filename);
306 mesh_pt()->output(some_file,npts);
307 some_file.close();
308
309 // Get norm of solution
310 snprintf(filename, sizeof(filename), "%s/norm%i.dat",doc_info.directory().c_str(),
311 doc_info.number());
312 some_file.open(filename);
313 double norm_soln=0.0;
314 mesh_pt()->compute_norm(norm_soln);
315 some_file << sqrt(norm_soln) << std::endl;
316 cout << "Norm of computed solution: " << sqrt(norm_soln) << endl;
317 some_file.close();
318
319
320} // end_of_doc_solution
321
322
323
324
325
326////////////////////////////////////////////////////////////////////////
327////////////////////////////////////////////////////////////////////////
328////////////////////////////////////////////////////////////////////////
329
330
331
332
333
334
335
336//==start_of_main======================================================
337/// Driver for FlowPastBox test problem
338//=====================================================================
339int main(int argc, char* argv[])
340{
341
342// Store command line arguments
343 CommandLineArgs::setup(argc,argv);
344
345
346 // Check number of command line arguments: Need exactly two.
347 if (argc!=4)
348 {
349 std::string error_message =
350 "Wrong number of command line arguments.\n";
352 "Must specify the following file names \n";
353 error_message +=
354 "filename.node then filename.ele then filename.poly\n";
355
359 }
360
361
362 // Convert arguments to strings that specify the input file names
363 string node_file_name(argv[1]);
364 string element_file_name(argv[2]);
365 string poly_file_name(argv[3]);
366
367
368 // Set up doc info
369 // ---------------
370
371 // Label for output
373
374 // Set output directory
375 doc_info.set_directory("RESLT");
376
377 // Step number
378 doc_info.number()=0;
379
380#ifdef ADAPT
381 const unsigned max_adapt = 3;
382#endif
383
384// Doing TTaylorHoodElements
385 {
386#ifdef ADAPT
387 // Build the problem with TTaylorHoodElements
390#else
391 // Build the problem with TTaylorHoodElements
394#endif
395 // Output boundaries
396 problem.mesh_pt()->output_boundaries("RESLT/boundaries.dat");
397
398 // Outpt the solution
399 problem.doc_solution(doc_info);
400
401 // Step number
402 doc_info.number()++;
403
404#ifdef ADAPT
405 // Solve the problem
406 problem.newton_solve(max_adapt);
407#else
408 // Solve the problem
409 problem.newton_solve();
410#endif
411
412 // Outpt the solution
413 problem.doc_solution(doc_info);
414
415 // Step number
416 doc_info.number()++;
417
418 } // end of QTaylorHoodElements
419
420
421} // end_of_main
422
423
424
425
426
427
428
429
430
431
Flow past a box in a channel.
RefineableTriangleMesh< ELEMENT > * mesh_pt()
Access function for the specific mesh.
Z2ErrorEstimator * error_estimator_pt
Error estimator.
void actions_after_newton_solve()
Update the after solve (empty)
RefineableTriangleMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the bulk mesh.
void actions_before_newton_solve()
Update the problem specs before solve. Re-set velocity boundary conditions just to be on the safe sid...
FlowPastBoxProblem(const string &node_file_name, const string &element_file_name, const string &poly_file_name)
Constructor: Pass filenames for mesh.
void doc_solution(DocInfo &doc_info)
Doc the solution.
TriangleMesh< ELEMENT > * mesh_pt()
Access function for the specific mesh.
Unstructured refineable Triangle Mesh.
Triangle mesh build with the help of the scaffold mesh coming from the triangle mesh generator Triang...
int main(int argc, char *argv[])
Driver for FlowPastBox test problem.
Namespace for physical parameters.