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-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 flow past rectangular box -- meshed with triangle
27 
28 //Generic includes
29 #include "generic.h"
30 #include "navier_stokes.h"
31 
32 // The mesh
33 #include "meshes/triangle_mesh.h"
34 
35 using namespace std;
36 
37 using 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 //====================================================================
61 template<class ELEMENT>
62 class FlowPastBoxProblem : public Problem
63 {
64 
65 public:
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
148 private:
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 //========================================================================
163 template<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
174  Bulk_mesh_pt = new RefineableTriangleMesh<ELEMENT>(node_file_name,
175  element_file_name,
176  poly_file_name);
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,
188  element_file_name,
189  poly_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
225  el_pt->re_pt() = &Global_Physical_Variables::Re;
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 //========================================================================
238 template<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
278  el_pt->re_pt() = &Global_Physical_Variables::Re;
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 //========================================================================
292 template<class ELEMENT>
294 {
295  ofstream some_file;
296  char filename[100];
297 
298  // Number of plot points
299  unsigned npts;
300  npts=5;
301 
302  // Output solution
303  sprintf(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  sprintf(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 //=====================================================================
339 int 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";
351  error_message +=
352  "Must specify the following file names \n";
353  error_message +=
354  "filename.node then filename.ele then filename.poly\n";
355 
356  throw OomphLibError(error_message,
357  OOMPH_CURRENT_FUNCTION,
358  OOMPH_EXCEPTION_LOCATION);
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
372  DocInfo doc_info;
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
389  problem(node_file_name, element_file_name, poly_file_name);
390 #else
391  // Build the problem with TTaylorHoodElements
393  problem(node_file_name, element_file_name, poly_file_name);
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 
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
TriangleMesh< 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...
RefineableTriangleMesh< ELEMENT > * mesh_pt()
Access function for the specific mesh.
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.
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
int main(int argc, char *argv[])
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
Namespace for physical parameters.
////////////////////////////////////////////////////////////////////// //////////////////////////////...