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