GRINS-0.6.0
mesh_builder.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // GRINS - General Reacting Incompressible Navier-Stokes
5 //
6 // Copyright (C) 2014-2015 Paul T. Bauman, Roy H. Stogner
7 // Copyright (C) 2010-2013 The PECOS Development Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the Version 2.1 GNU Lesser General
11 // Public License as published by the Free Software Foundation.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc. 51 Franklin Street, Fifth Floor,
21 // Boston, MA 02110-1301 USA
22 //
23 //-----------------------------------------------------------------------el-
24 
25 
26 // C++
27 #include <iostream>
28 
29 // This class
30 #include "grins/grins_enums.h"
31 #include "grins/mesh_builder.h"
32 
33 // libMesh
34 #include "libmesh/string_to_enum.h"
35 #include "libmesh/mesh_generation.h"
36 #include "libmesh/mesh_modification.h"
37 #include "libmesh/mesh_refinement.h"
38 #include "libmesh/parallel_mesh.h"
39 #include "libmesh/parsed_function.h"
40 #include "libmesh/serial_mesh.h"
41 
42 
43 namespace GRINS
44 {
45 
47  {
48  return;
49  }
50 
52  {
53  return;
54  }
55 
56  std::tr1::shared_ptr<libMesh::UnstructuredMesh> MeshBuilder::build
57  (const GetPot& input,
58  const libMesh::Parallel::Communicator &comm)
59  {
60  // First check if the user has both old and new versions of mesh input
61  if( input.have_section("mesh-options/") &&
62  input.have_section("Mesh/") )
63  {
64  libmesh_error_msg("Error: Detected illegal simulataneous use of [mesh-options] and [Mesh] in input!");
65  }
66 
67  // User needs to tell us if we are generating or reading a mesh
68  // We infer this by checking and seeing if the use has a Mesh/Read
69  // or a Mesh/Generation section
70  if( !input.have_variable("mesh-options/mesh_option") &&
71  !input.have_section("Mesh/Read/") &&
72  !input.have_section("Mesh/Generation/") )
73  {
74  libmesh_error_msg("ERROR: Must specify either Mesh/Read or Mesh/Generation in input.");
75  }
76 
77  // But you can't have it both ways
78  if( input.have_section("Mesh/Read/") && input.have_section("Mesh/Generation/") )
79  {
80  libmesh_error_msg("ERROR: Can only specify one of Mesh/Read and Mesh/Generation");
81  }
82 
83  // Are we generating the mesh or are we reading one in from a file?
84  std::string mesh_build_type = "NULL";
85  if( input.have_section("Mesh/Read/") )
86  mesh_build_type = "read";
87 
88  else if( input.have_section("Mesh/Generation/") )
89  mesh_build_type = "generate";
90 
91  this->deprecated_option<std::string>( input, "mesh-options/mesh_option", "Mesh/Read or Mesh/Generation", "DIE!", mesh_build_type);
92 
93  // Make sure the user gave a valid option
95  if( mesh_build_type != std::string("generate") &&
96  mesh_build_type != std::string("read") &&
97  mesh_build_type != std::string("read_mesh_from_file") &&
98  mesh_build_type != std::string("create_1D_mesh") &&
99  mesh_build_type != std::string("create_2D_mesh") &&
100  mesh_build_type != std::string("create_3D_mesh") )
101  {
102  std::string error = "ERROR: Invalid value of "+mesh_build_type+" for Mesh/type.\n";
103  error += " Valid values are: generate\n";
104  error += " read\n";
105  libmesh_error_msg(error);
106  }
107 
108  // Create UnstructuredMesh object (defaults to dimension 1).
109  libMesh::UnstructuredMesh* mesh;
110 
111  // Were we specifically asked to use a ParallelMesh or SerialMesh?
112  {
113  std::string mesh_class = input("Mesh/class", "default");
114 
115  this->deprecated_option<std::string>( input, "mesh-options/mesh_class", "Mesh/class", "default", mesh_class);
116 
117  if (mesh_class == "parallel")
118  mesh = new libMesh::ParallelMesh(comm);
119  else if (mesh_class == "serial")
120  mesh = new libMesh::SerialMesh(comm);
121  else if (mesh_class == "default")
122  mesh = new libMesh::Mesh(comm);
123  else
124  {
125  std::string error = "ERROR: Invalid class "+mesh_class+" input for Mesh/class.\n";
126  error += " Valid choices are: serial, parallel.\n";
127  libmesh_error_msg(error);
128  }
129  }
130 
131  // Read mesh from file
132  if(mesh_build_type =="read_mesh_from_file" /* This is deprecated */ ||
133  mesh_build_type == "read" )
134  {
135  // Make sure the user set the filename to read
136  if( !input.have_variable("mesh-options/mesh_filename") /* This is deprecated */ &&
137  !input.have_variable("Mesh/Read/filename") )
138  {
139  libmesh_error_msg("ERROR: Must specify Mesh/Read/filename for reading mesh.");
140  }
141 
142  std::string mesh_filename = input("Mesh/Read/filename", "DIE!");
143 
144  this->deprecated_option<std::string>( input, "mesh-options/mesh_filename", "Mesh/Read/filename", "DIE!", mesh_filename);
145 
146  // According to Roy Stogner, the only read format
147  // that won't properly reset the dimension is gmsh.
149  mesh->read(mesh_filename);
150  }
151 
152  // Generate the mesh using built-in libMesh functions
153  else if(mesh_build_type=="create_1D_mesh" /* This is deprecated */ ||
154  mesh_build_type=="create_2D_mesh" /* This is deprecated */ ||
155  mesh_build_type=="create_3D_mesh" /* This is deprecated */ ||
156  mesh_build_type=="generate")
157  {
158  this->generate_mesh(mesh_build_type,input,mesh);
159  }
160 
161  else
162  {
163  // Shouldn't have gotten here
164  libmesh_error();
165  }
166 
167  /* Only do the mesh refinement here if we don't have a restart file.
168  Otherwise, we need to wait until we've read in the restart file.
169  That is done in Simulation::check_for_restart */
170  if( !input.have_variable("restart-options/restart_file") )
171  {
172  this->do_mesh_refinement_from_input( input, comm, *mesh );
173  }
174 
175  return std::tr1::shared_ptr<libMesh::UnstructuredMesh>(mesh);
176  }
177 
178  void MeshBuilder::generate_mesh( const std::string& mesh_build_type, const GetPot& input,
179  libMesh::UnstructuredMesh* mesh )
180  {
181  unsigned int dimension = input("Mesh/Generation/dimension",0);
182 
183  if( !input.have_variable("mesh-options/mesh_option") /* Deprecated */ &&
184  !input.have_variable("Mesh/Generation/dimension") )
185  {
186  libmesh_error_msg("ERROR: Must specify Mesh/Generation/dimension for generating mesh.");
187  }
188 
189  /* Remove these once suport for mesh-options/mesh_option is removed */
190  if( mesh_build_type == "create_1D_mesh" /* This is deprecated */ )
191  dimension = 1;
192 
193  if( mesh_build_type=="create_2D_mesh" /* This is deprecated */ )
194  dimension = 2;
195 
196  if( mesh_build_type=="create_3D_mesh" /* This is deprecated */ )
197  dimension = 3;
198 
199  // Set the mesh dimension
200  mesh->set_mesh_dimension(dimension);
201 
202  /* Now look for spatial extent of the grid that the user wants to generate. */
203 
204  libMesh::Real x_min = input("Mesh/Generation/x_min", 0.0);
205  this->deprecated_option( input, "mesh-options/domain_x1_min", "Mesh/Generation/x_min", 0.0, x_min );
206 
207  libMesh::Real x_max = input("Mesh/Generation/x_max", 1.0);
208  this->deprecated_option( input, "mesh-options/domain_x1_max", "Mesh/Generation/x_max", 1.0, x_max );
209 
210 
211  /* We only check the y_{min,max} input if dimension is > 1 so that GetPot
212  UFO detection will give us an error if we have this in the input file
213  and are only using a 1D grid. */
214  libMesh::Real y_min = 0.0;
215  libMesh::Real y_max = 0.0;
216 
217  if( dimension > 1 )
218  {
219  y_min = input("Mesh/Generation/y_min", 0.0);
220  this->deprecated_option( input, "mesh-options/domain_x2_min", "Mesh/Generation/y_min", 0.0, y_min );
221 
222  y_max = input("Mesh/Generation/y_max", 1.0);
223  this->deprecated_option( input, "mesh-options/domain_x2_max", "Mesh/Generation/y_max", 1.0, y_max );
224  }
225 
226  /* We only check the z_{min,max} input if dimension is > 2 so that GetPot
227  UFO detection will give us an error if we have this in the input file
228  and are only using a 1D or 2D grid. */
229  libMesh::Real z_min = 0.0;
230  libMesh::Real z_max = 0.0;
231 
232  if( dimension > 2 )
233  {
234  z_min = input("Mesh/Generation/z_min", 0.0);
235  this->deprecated_option( input, "mesh-options/domain_x3_min", "Mesh/Generation/z_min", 0.0, z_min );
236 
237  z_max = input("Mesh/Generation/z_max", 1.0);
238  this->deprecated_option( input, "mesh-options/domain_x3_max", "Mesh/Generation/z_max", 1.0, z_max );
239  }
240 
241  /* Now check for the number of elements in each direction */
242 
243  // Make sure user gave us info about how many elements to use
244  if( !input.have_variable("mesh-options/mesh_nx1") /* Deprecated */ &&
245  !input.have_variable("Mesh/Generation/n_elems_x") )
246  {
247  libmesh_error_msg("ERROR: Must supply Mesh/Generation/n_elems_x for mesh generation.");
248  }
249 
250  unsigned int n_elems_x = input("Mesh/Generation/n_elems_x", 0);
251  this->deprecated_option<unsigned int>( input, "mesh-options/mesh_nx1", "Mesh/Generation/n_elems_x", 0, n_elems_x );
252 
253  /* We only check n_elems_y input if dimension is > 1 so that GetPot
254  UFO detection will give us an error if we have this in the input file
255  and are only using a 1D grid. */
256  unsigned int n_elems_y = 0;
257  if( dimension > 1 )
258  {
259  if( !input.have_variable("mesh-options/mesh_nx2") /* Deprecated */ &&
260  !input.have_variable("Mesh/Generation/n_elems_y") )
261  {
262  libmesh_error_msg("ERROR: Must supply Mesh/Generation/n_elems_y for mesh generation.");
263  }
264 
265  n_elems_y = input("Mesh/Generation/n_elems_y", 0);
266  this->deprecated_option<unsigned int>( input, "mesh-options/mesh_nx2", "Mesh/Generation/n_elems_y", 0, n_elems_y );
267  }
268 
269  /* We only check n_elems_z input if dimension is > 2 so that GetPot
270  UFO detection will give us an error if we have this in the input file
271  and are only using a 1D or 2D grid. */
272  unsigned int n_elems_z = 0;
273  if( dimension > 2 )
274  {
275  if( !input.have_variable("mesh-options/mesh_nx3") /* Deprecated */ &&
276  !input.have_variable("Mesh/Generation/n_elems_z") )
277  {
278  libmesh_error_msg("ERROR: Must supply Mesh/Generation/n_elems_z for mesh generation.");
279  }
280 
281  n_elems_z = input("Mesh/Generation/n_elems_z", 0);
282  this->deprecated_option<unsigned int>( input, "mesh-options/mesh_nx3", "Mesh/Generation/n_elems_z", 0, n_elems_z );
283  }
284 
285  /* Now grab the element_type the user wants for the mesh. */
286 
287  std::string element_type = input("Mesh/Generation/element_type", "default");
288  this->deprecated_option<std::string>( input, "mesh-options/element_type", "Mesh/Generation/element_type", "default", element_type );
289 
290  /* Now generate the mesh. */
291  if( dimension == 1 )
292  {
293  if(element_type=="default")
294  {
295  element_type = "EDGE3";
296  }
297 
298  GRINSEnums::ElemType element_enum_type =
299  libMesh::Utility::string_to_enum<GRINSEnums::ElemType>(element_type);
300 
301  libMesh::MeshTools::Generation::build_line(*mesh,
302  n_elems_x,
303  x_min,
304  x_max,
305  element_enum_type);
306  }
307 
308  else if( dimension == 2 )
309  {
310  if(element_type=="default")
311  {
312  element_type = "TRI6";
313  }
314 
315  GRINSEnums::ElemType element_enum_type =
316  libMesh::Utility::string_to_enum<GRINSEnums::ElemType>(element_type);
317 
318  libMesh::MeshTools::Generation::build_square(*mesh,
319  n_elems_x,
320  n_elems_y,
321  x_min,
322  x_max,
323  y_min,
324  y_max,
325  element_enum_type);
326  }
327 
328  else if( dimension == 3 )
329  {
330  if(element_type=="default")
331  {
332  element_type = "TET10";
333  }
334 
335  GRINSEnums::ElemType element_enum_type =
336  libMesh::Utility::string_to_enum<GRINSEnums::ElemType>(element_type);
337 
338  libMesh::MeshTools::Generation::build_cube(*mesh,
339  n_elems_x,
340  n_elems_y,
341  n_elems_z,
342  x_min,
343  x_max,
344  y_min,
345  y_max,
346  z_min,
347  z_max,
348  element_enum_type);
349  }
350 
351  else
352  {
353  // This shouldn't have happened
354  libmesh_error();
355  }
356 
357  return;
358  }
359 
361  const libMesh::Parallel::Communicator &comm,
362  libMesh::UnstructuredMesh& mesh ) const
363  {
364  std::string redistribution_function_string =
365  input("Mesh/Redistribution/function", std::string("0"));
366  this->deprecated_option<std::string>( input, "mesh-options/redistribute", "Mesh/Redistribution/function", "0", redistribution_function_string );
367 
368  if (redistribution_function_string != "0")
369  {
370  libMesh::ParsedFunction<libMesh::Real>
371  redistribution_function(redistribution_function_string);
372 
373  libMesh::MeshTools::Modification::redistribute
374  (mesh, redistribution_function);
375 
376  // Redistribution can create distortions *within* second-order
377  // elements, which can then be magnified by refinement. Let's
378  // undistort everything by converting to first order and back
379  // if necessary.
380 
381  // FIXME - this only works for meshes with uniform geometry
382  // order equal to FIRST or (full-order) SECOND.
383 
384  const libMesh::Elem *elem = *mesh.elements_begin();
385 
386  if (elem->default_order() != libMesh::FIRST)
387  {
388  mesh.all_first_order();
389  mesh.all_second_order();
390  }
391  }
392 
393  int uniformly_refine = input("Mesh/Refinement/uniformly_refine", 0);
394  this->deprecated_option( input, "mesh-options/uniformly_refine", "Mesh/Refinement/uniformly_refine", 0, uniformly_refine );
395 
396  if( uniformly_refine > 0 )
397  {
398  libMesh::MeshRefinement(mesh).uniformly_refine(uniformly_refine);
399  }
400 
401  std::string h_refinement_function_string =
402  input("Mesh/Refinement/locally_h_refine", std::string("0"));
403  this->deprecated_option<std::string>( input, "mesh-options/locally_h_refine", "Mesh/Refinement/locally_h_refine", "0", h_refinement_function_string );
404 
405  if (h_refinement_function_string != "0")
406  {
407  libMesh::ParsedFunction<libMesh::Real>
408  h_refinement_function(h_refinement_function_string);
409 
410  libMesh::MeshRefinement mesh_refinement(mesh);
411 
412  libMesh::dof_id_type found_refinements = 0;
413  do {
414  found_refinements = 0;
415  unsigned int max_level_refining = 0;
416 
417  libMesh::MeshBase::element_iterator elem_it =
418  mesh.active_elements_begin();
419  libMesh::MeshBase::element_iterator elem_end =
420  mesh.active_elements_end();
421  for (; elem_it != elem_end; ++elem_it)
422  {
423  libMesh::Elem *elem = *elem_it;
424 
425  const libMesh::Real refinement_val =
426  h_refinement_function(elem->centroid());
427 
428  const unsigned int n_refinements = refinement_val > 0 ?
429  refinement_val : 0;
430 
431  if (elem->level() - uniformly_refine < n_refinements)
432  {
433  elem->set_refinement_flag(libMesh::Elem::REFINE);
434  found_refinements++;
435  max_level_refining = std::max(max_level_refining,
436  elem->level());
437  }
438  }
439 
440  comm.max(found_refinements);
441  comm.max(max_level_refining);
442 
443  if (found_refinements)
444  {
445  std::cout << "Found up to " << found_refinements <<
446  " elements to refine on each processor," << std::endl;
447  std::cout << "with max level " << max_level_refining << std::endl;
448  mesh_refinement.refine_and_coarsen_elements();
449 
450  if( input.have_variable("restart-options/restart_file") )
451  {
452  std::cout << "Warning: it is known that locally_h_refine is broken when restarting." << std::endl
453  << " and multiple refinement passes are done. We are forcibly" << std::endl
454  << " limiting the refinement to one pass until this issue is resolved." << std::endl;
455  break;
456  }
457  }
458 
459  } while(found_refinements);
460 
461  }
462 
463  return;
464  }
465 
466 } // namespace GRINS
MeshBuilder()
This Object handles building a libMesh::UnstructuredMesh subclass.
Definition: mesh_builder.C:46
GRINS namespace.
std::tr1::shared_ptr< libMesh::UnstructuredMesh > build(const GetPot &input, const libMesh::Parallel::Communicator &comm LIBMESH_CAN_DEFAULT_TO_COMMWORLD)
Builds the libMesh::Mesh according to input options.
Definition: mesh_builder.C:57
void generate_mesh(const std::string &mesh_build_type, const GetPot &input, libMesh::UnstructuredMesh *mesh)
Definition: mesh_builder.C:178
void do_mesh_refinement_from_input(const GetPot &input, const libMesh::Parallel::Communicator &comm, libMesh::UnstructuredMesh &mesh) const
Refine the mesh based on user input parameters.
Definition: mesh_builder.C:360
void deprecated_option(const GetPot &input, const std::string &old_option, const std::string &new_option, const T &default_value, T &option_value) const
Helper function for displaying deprecated warnings.
Definition: mesh_builder.h:85

Generated on Mon Jun 22 2015 21:32:20 for GRINS-0.6.0 by  doxygen 1.8.9.1