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

Generated on Tue Dec 19 2017 12:47:28 for GRINS-0.8.0 by  doxygen 1.8.9.1