https://mooseframework.inl.gov
SurfaceSubdomainsDelaunayRemesher.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 
12 #include "MooseMeshUtils.h"
13 #include "CastUniquePointer.h"
14 
15 #include "libmesh/boundary_info.h"
16 #include "libmesh/mesh_triangle_holes.h"
17 #include "libmesh/mesh_modification.h"
18 #include "libmesh/parallel_algebra.h"
19 #include "libmesh/poly2tri_triangulator.h"
20 #include "libmesh/unstructured_mesh.h"
21 
22 #include "libmesh/mesh_base.h"
23 #include "libmesh/replicated_mesh.h"
24 
26 
29 {
32  params.renameParameterGroup("Parsed expression advanced", "Level set shape parsed expression");
33 
34  params.addClassDescription(
35  "Mesh generator that re-meshes a 2D surface mesh given as one or more subdomains into "
36  "a 2D surface mesh using Delaunay triangulation.");
37 
38  // Definition of the region to re-mesh
39  params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
40  params.addParam<std::vector<std::vector<SubdomainName>>>(
41  "subdomain_names", {}, "The surface mesh subdomains to be re-meshed");
42  params.addParam<std::vector<SubdomainName>>(
43  "exclude_subdomain_names", {}, "The surface mesh subdomains that should not be re-meshed");
44 
45  // Surface re-meshing parameters
46  params.addRangeCheckedParam<Real>(
47  "max_edge_length",
48  "max_edge_length>0",
49  "Maximum length of an edge in the 1D meshes around each subdomain. Only a single value is "
50  "currently allowed as the boundary refinement must be consistent between all subdomains.");
51  // NOTE: we could make this a per-included-subdomain parameter, we would just need to identify
52  // interfaces between each subdomain and use the minimum (or average or maximum, just needs to
53  // be consistent) edge length on those interfaces.
54  params.addParam<std::vector<unsigned int>>(
55  "interpolate_boundaries",
56  {1},
57  "Ratio of points to add to the boundaries. Can be set to a single value for all groups at "
58  "once, or specified individually. A single value is recommended as the boundary refinement "
59  "must be consistent between all subdomains.");
60  params.addParam<std::vector<Real>>(
61  "desired_areas",
62  {0},
63  "Target element size when triangulating projection of the subdomain group. Can be set to a "
64  "single value for all groups at once, or specified individually. Default of 0 means no "
65  "constraint.");
66  params.addParamNamesToGroup("max_edge_length interpolate_boundaries desired_areas",
67  "Delaunay triangulation");
68 
69  // Parameters for stitching meshes at the end
70  params.addParam<bool>("avoid_merging_subdomains",
71  false,
72  "Whether to prevent merging subdomains by offsetting ids. The first mesh "
73  "in the input will keep the same subdomains ids, the others will have "
74  "offsets. All subdomain names will remain valid");
75  params.addParam<bool>("clear_stitching_boundaries",
76  true,
77  "Whether to clear the boundaries between the subdomains being stitched "
78  "together after they were re-meshed with triangles");
79  MooseEnum algorithm("BINARY EXHAUSTIVE", "BINARY");
80  params.addParam<MooseEnum>(
81  "stitching_algorithm",
82  algorithm,
83  "Control the use of binary search for the nodes of the stitched surfaces.");
84  params.addParam<bool>(
85  "verbose_stitching", false, "Whether mesh stitching should have verbose output.");
86  params.addParamNamesToGroup(
87  "avoid_merging_subdomains clear_stitching_boundaries stitching_algorithm verbose_stitching",
88  "Stitching triangularized meshes");
89 
90  return params;
91 }
92 
94  const InputParameters & parameters)
95  : SurfaceDelaunayGeneratorBase(parameters),
96  LevelSetMeshingHelper(parameters),
97  _input(getMesh("input")),
98  _subdomain_names(getParam<std::vector<std::vector<SubdomainName>>>("subdomain_names")),
99  _interpolate_boundaries(getParam<std::vector<unsigned int>>("interpolate_boundaries")),
100  _desired_areas(getParam<std::vector<Real>>("desired_areas"))
101 {
102  if (isParamSetByUser("subdomain_names") && isParamSetByUser("exclude_subdomain_names"))
103  paramError("exclude_subdomain_names",
104  "Excluding subdomain names is only to be set when 'subdomain_names' is not set");
105 }
106 
107 std::unique_ptr<MeshBase>
109 {
110  std::unique_ptr<MeshBase> mesh_3d = std::move(_input);
111 
112  // Select subdomain names if it has not been selected by the user
113  // We form 1 group per subdomain by default (easiest to mesh)
114  if (_subdomain_names.empty() || _subdomain_names[0].empty())
115  {
116  if (_subdomain_names.size())
117  _subdomain_names.erase(_subdomain_names.begin());
118 
119  // Get all subdomains from the mesh
120  std::set<subdomain_id_type> sub_ids;
121  mesh_3d->subdomain_ids(sub_ids);
122 
123  // Copy only the ones that are not excluded
124  const auto & excluded = getParam<std::vector<SubdomainName>>("exclude_subdomain_names");
125  for (const auto & sub_id : sub_ids)
126  {
127  const auto & sn = mesh_3d->subdomain_name(sub_id) == "" ? std::to_string(sub_id)
128  : mesh_3d->subdomain_name(sub_id);
129  if (excluded.empty() || std::find(excluded.begin(), excluded.end(), sn) == excluded.end())
130  _subdomain_names.push_back({sn});
131  }
132  }
133  _num_groups = _subdomain_names.size();
134  if (_interpolate_boundaries.size() == 1)
136  if (_desired_areas.size() == 1)
138  if (_interpolate_boundaries.size() != _num_groups)
139  paramError("interpolate_boundaries",
140  "Should be the same size as 'subdomain_names' or of size 1");
141  if (_desired_areas.size() != _num_groups)
142  paramError("desired_areas", "Should be the same size as 'subdomain_names' or of size 1");
143 
144  // Re-create surface meshes from each of the subdomains
145  std::vector<std::unique_ptr<UnstructuredMesh>> remeshed_2d;
146 
147  for (const auto i : make_range(_num_groups))
148  {
149  auto mesh_2d = buildReplicatedMesh();
151 
152  // Mesh the subdomains by groups
153  // TODO: holes for each subdomain are not currently supported
154  std::vector<std::unique_ptr<UnstructuredMesh>> no_holes = {};
155  auto new_mesh = General2DDelaunay(*mesh_2d, /*holes*/ no_holes, i);
156 
157  // Keep the remeshed subdomains 2D meshes
158  remeshed_2d.push_back(std::move(new_mesh));
159  }
160 
161  // TODO: can we gain efficiency by using different boundary ids for each stitch?
162  const auto primary_bcid = 1;
163  // Prevent deleting a legitimate ID if we start conserving boundary IDs from the input mesh
164  // to the output mesh
165  const auto starting_stitching_id = MooseMeshUtils::getNextFreeBoundaryID(*mesh_3d);
166  auto paired_bcid = starting_stitching_id;
167  const auto verbose_stitching = getParam<bool>("verbose_stitching");
168  const auto use_binary_search = getParam<MooseEnum>("stitching_algorithm") == "BINARY";
169 
170  // Stitch all the parts to the first one
171  std::unique_ptr<UnstructuredMesh> full_mesh;
172  full_mesh = std::move(remeshed_2d[0]);
173 
174  // Build a subdomain map
175  auto & main_subdomain_map = full_mesh->set_subdomain_name_map();
176 
177  for (auto remesh_i : index_range(remeshed_2d))
178  {
179  if (remesh_i == 0)
180  continue;
181 
182  UnstructuredMesh & remeshed = dynamic_cast<UnstructuredMesh &>(*remeshed_2d[remesh_i]);
183 
184  // NOTE: we cannot use MeshedHole because the meshes are no longer in the XY plane
185  // Potential optimization: instead of using the full mesh outer boundary for stitching
186  // use what is done in the XYDelaunayGenerator and re-build only the boundary near the
187  // mesh that we are stitching
188  // Potential optimization: we could keep the external boundaries from the triangulation phase
189 
190  // Create the boundary outside the remeshed mesh
191  bool rem_has_external_bdy = false;
192  MooseMeshUtils::addExternalBoundary(remeshed, paired_bcid, rem_has_external_bdy);
193  mooseAssert(rem_has_external_bdy, "Subdomain mesh should have an external boundary");
194 
195  // We need to re-create the boundary outside the parent mesh because we are clearing
196  // it on every stitch
197  bool base_has_external_bdy = false;
198  MooseMeshUtils::addExternalBoundary(*full_mesh, primary_bcid, base_has_external_bdy);
199  if (!base_has_external_bdy)
200  mooseWarning(
201  "Full mesh should have an external boundary. This could occur if the surface mesh is "
202  "disconnected in several parts and a part's surface mesh has just been fully remeshed");
203 
204  // Retrieve subdomain name map from the mesh to be stitched and insert it into the main
205  // subdomain map
206  const auto & increment_subdomain_map = remeshed.get_subdomain_name_map();
207  main_subdomain_map.insert(increment_subdomain_map.begin(), increment_subdomain_map.end());
208 
209  full_mesh->stitch_meshes(remeshed,
210  primary_bcid,
211  paired_bcid,
212  TOLERANCE,
213  /*clear_stitched_bcids*/ getParam<bool>("clear_stitching_boundaries"),
214  verbose_stitching,
215  use_binary_search,
216  /*enforce_all_nodes_match_on_boundaries*/ false,
217  /*merge_boundary_nodes_all_or_nothing*/ false,
218  /*remap_subdomain_ids*/ !getParam<bool>("avoid_merging_subdomains"));
219 
220  // If we want to keep track of the stitching boundaries
221  paired_bcid++;
222  // TODO: when implementing hole meshes, we might want to also stitch the hole meshes
223  }
224 
225  // We do not need the 3D mesh anymore
226  mesh_3d->clear();
227  // The stitching boundary should be removed by the stitcher, but this does not hurt
228  if (getParam<bool>("clear_stitching_boundaries"))
229  for (const auto bcid : make_range(starting_stitching_id, paired_bcid))
230  full_mesh->get_boundary_info().remove_id(bcid);
231  // Mesh is not prepared after stitching (TODO: fix this)
232  full_mesh->unset_is_prepared();
233 
234  return full_mesh;
235 }
236 
237 std::unique_ptr<UnstructuredMesh>
239  UnstructuredMesh & mesh_2d,
240  std::vector<std::unique_ptr<UnstructuredMesh>> & hole_meshes_2d,
241  unsigned int group_i)
242 {
243  if (_verbose)
244  {
245  if (!mesh_2d.preparation().has_cached_elem_data)
246  mesh_2d.cache_elem_data();
247  _console << "Re-meshing mesh\n " << mesh_2d << std::endl;
248  _console << "with subdomains " << Moose::stringify(mesh_2d.get_subdomain_name_map())
249  << std::endl;
250  if (hole_meshes_2d.size())
251  _console << "With " << hole_meshes_2d.size() << " holes:" << std::endl;
252  for (const auto & hole_m : hole_meshes_2d)
253  {
254  if (!hole_m->preparation().has_cached_elem_data)
255  hole_m->cache_elem_data();
256  _console << "Hole subdomains " << Moose::stringify(hole_m->get_subdomain_name_map())
257  << std::endl;
258  _console << *hole_m << std::endl;
259  }
260  }
261  // If a level set is provided, we need to check if the nodes in the original 2D mesh match the
262  // level set
263  if (_func_level_set)
264  {
265  for (const auto & node : mesh_2d.node_ptr_range())
266  {
268  {
269  paramError("level_set",
270  "The level set function does not match the nodes in the given boundary of the "
271  "input mesh. Level set evaluates at: " +
272  std::to_string(levelSetEvaluator(*node)) + " at node: " + node->get_info());
273  }
274  }
275  }
276 
277  // Create the external boundary of the 2D mesh
278  // Easier to work with a TRI3 mesh
279  // all_tri() also prepares the mesh for use
280  mesh_2d.prepare_for_use();
281  bool has_external_side = false;
282  MeshTools::Modification::all_tri(mesh_2d);
283  const auto mesh_2d_ext_bdry = MooseMeshUtils::getNextFreeBoundaryID(mesh_2d);
284  for (const auto elem : mesh_2d.active_element_ptr_range())
285  for (const auto i_side : elem->side_index_range())
286  if (elem->neighbor_ptr(i_side) == nullptr)
287  {
288  mesh_2d.get_boundary_info().add_side(elem, i_side, mesh_2d_ext_bdry);
289  has_external_side = true;
290  }
291 
292  // Create a clone of the 2D mesh to be used for the 1D mesh generation
293  auto mesh_2d_dummy = mesh_2d.clone();
294  // Generate a new 1D block based on the external boundary
295  const auto new_block_id_1d = MooseMeshUtils::getNextFreeSubdomainID(*mesh_2d_dummy);
296 
297  if (has_external_side)
299  {std::to_string(mesh_2d_ext_bdry)},
300  new_block_id_1d,
301  SubdomainName(),
302  type());
303 
304  // Create a 1D mesh from the 1D block
305  auto mesh_1d = buildMeshBaseObject();
306  if (has_external_side)
307  MooseMeshUtils::convertBlockToMesh(*mesh_2d_dummy, *mesh_1d, {std::to_string(new_block_id_1d)});
308  mesh_2d_dummy->clear();
309 
310  // Add more nodes in the 1D mesh
311  // We need to do this BEFORE the mesh is projected to avoid distortion in the node distances
312  // The distortion is not the same for each subdomain, so we would end up with a non-conformal mesh
313  if (isParamValid("max_edge_length"))
314  {
315  // We need to extract the points in the order of the boundary. This utility will build the
316  // boundary as a loop
317  // Add the nodeset from the sideset
318  // NOTE: this is redoing the 1D mesh from the boundary
319  mesh_2d.get_boundary_info().build_node_list_from_side_list({mesh_2d_ext_bdry});
320  const auto boundary_1d = MooseMeshUtils::buildLoopBoundaryOf2DMesh(mesh_2d, mesh_2d_ext_bdry);
321  // Extract the points
322  std::vector<Point> mesh_1d_points;
323  mesh_1d_points.reserve(boundary_1d->n_nodes());
324  for (const auto & node : boundary_1d->node_ptr_range())
325  mesh_1d_points.push_back(*node);
326 
327  // Re-create the 1D mesh with a polyline with a maximum edge length
328  mesh_1d->clear();
329  // we add a tiny offset to avoid roundoff differences
331  *mesh_1d, mesh_1d_points, true, "", "", getParam<Real>("max_edge_length") + 1e-8);
332  }
333 
334  // Find centroid of the 2D mesh
335  const Point centroid = MooseMeshUtils::meshCentroidCalculator(mesh_2d);
336  // calculate an average normal vector of the 2D mesh
337  const Point mesh_norm = meshNormal2D(mesh_2d);
338  // Check the deviation of the mesh normal vector from the global average normal vector
339  if (meshNormalDeviation2D(mesh_2d, mesh_norm) > _max_angle_deviation)
340  paramError("subdomain_names",
341  "The normal vector of some elements in the 2D mesh deviates too much from the "
342  "global average normal vector. The maximum deviation found / allowed is " +
343  std::to_string(meshNormalDeviation2D(mesh_2d, mesh_norm)) + " / " +
344  std::to_string(_max_angle_deviation) +
345  ". Consider dividing the boundary into several parts to "
346  "reduce the angle deviation.");
347 
348  // Move both 2d and 1d meshes to the centroid of the 2D mesh
349  MeshTools::Modification::translate(*mesh_1d, -centroid(0), -centroid(1), -centroid(2));
350  MeshTools::Modification::translate(mesh_2d, -centroid(0), -centroid(1), -centroid(2));
351 
352  // Calculate the Euler angles to rotate the meshes so that the 2D mesh is close to the XY plane
353  // (i.e., the normal vector of the 2D mesh is aligned with the Z axis)
354  const Real theta = std::acos(mesh_norm(2)) / M_PI * 180.0;
355  const Real phi =
356  (MooseUtils::absoluteFuzzyLessThan(mesh_norm(2), 1.0) ? std::atan2(mesh_norm(1), mesh_norm(0))
357  : 0.0) /
358  M_PI * 180.0;
359  MeshTools::Modification::rotate(*mesh_1d, 90.0 - phi, theta, 0.0);
360  MeshTools::Modification::rotate(mesh_2d, 90.0 - phi, theta, 0.0);
361 
362  // Clone the 2D mesh to be used for reverse projection later
363  auto mesh_2d_xyz = dynamic_pointer_cast<MeshBase>(mesh_2d.clone());
364 
365  // Project the 2D mesh to the XY plane so that XYDelaunay can be used
366  for (const auto & node : mesh_2d.node_ptr_range())
367  (*node)(2) = 0;
368  // Project the 1D mesh to the XY plane as well
369  for (const auto & node : mesh_1d->node_ptr_range())
370  (*node)(2) = 0;
371 
372  // Finally, triangulation
373  std::unique_ptr<UnstructuredMesh> mesh =
374  dynamic_pointer_cast<UnstructuredMesh>(std::move(mesh_1d));
375 
376  Poly2TriTriangulator poly2tri(*mesh);
377  poly2tri.triangulation_type() = TriangulatorInterface::PSLG;
378 
379  poly2tri.set_interpolate_boundary_points(_interpolate_boundaries[group_i]);
380  poly2tri.set_verify_hole_boundaries(false);
381  poly2tri.desired_area() = _desired_areas[group_i];
382  poly2tri.minimum_angle() = 0; // Not yet supported
383  poly2tri.smooth_after_generating() = false;
384  // Future TODO: correct the area function based on the local normal vector
386  poly2tri.set_auto_area_function(this->comm(),
391  poly2tri.triangulate();
392 
393  // Reverse the projection based on the original 2D mesh
394  for (const auto & node : mesh->node_ptr_range())
395  {
396  bool node_mod = false;
397  // Try to find the element in mesh_2d that contains the new node
398  for (const auto & elem : mesh_2d.active_element_ptr_range())
399  {
400  if (elem->contains_point(Point((*node)(0), (*node)(1), 0.0)))
401  {
402  // Element id
403  const auto elem_id = elem->id();
404  // element in xyz_in_xyz
405  const Elem & elem_xyz = *mesh_2d_xyz->elem_ptr(elem_id);
406 
407  const Point elem_normal = elemNormal(elem_xyz);
408  const auto & elem_p = mesh_2d_xyz->elem_ptr(elem_id)->point(0);
409 
410  // if the x and y values of the node is the same as the elem_p's first node, we can just
411  // move it to that node's position
412  if (MooseUtils::absoluteFuzzyEqual((*node)(0), elem_p(0)) &&
413  MooseUtils::absoluteFuzzyEqual((*node)(1), elem_p(1)))
414  {
415  (*node)(2) = elem_p(2);
416  node_mod = true;
417  break;
418  }
419  // Otherwise, we need to find a position inside the 2D element
420  // It has the same x and y coordinates as the node in the projected mesh;
421  (*node)(2) = elem_p(2) - (((*node)(0) - elem_p(0)) * elem_normal(0) +
422  ((*node)(1) - elem_p(1)) * elem_normal(1)) /
423  elem_normal(2);
424  node_mod = true;
425  break;
426  }
427  }
428  if (!node_mod)
429  mooseError("Node not found in mesh_in_xy");
430  }
431 
432  // Rotate the mesh back
433  MeshTools::Modification::rotate(*mesh, 0.0, -theta, phi - 90.0);
434  // Translate the mesh back
435  MeshTools::Modification::translate(*mesh, centroid(0), centroid(1), centroid(2));
436 
437  // Correct the nodes based on the level set function
438  if (_func_level_set)
439  {
440  for (const auto & node : mesh->node_ptr_range())
441  {
442  unsigned int iter_ct = 0;
443  while (iter_ct < _max_level_set_correction_iterations &&
445  {
446  levelSetCorrection(*node);
447  ++iter_ct;
448  }
449  }
450  }
451  // Give the old subdomain to all elements
452  const auto common_id = mesh_2d.get_mesh_subdomains().begin();
453  for (auto & elem : mesh->active_element_ptr_range())
454  elem->subdomain_id() = *common_id;
455 
456  // Pass the subdomain names
457  mesh->set_subdomain_name_map() = mesh_2d.get_subdomain_name_map();
458  // Remove the boundaries, they get re-added (with a known ID) when stitching the pieces together
459  mesh->get_boundary_info().remove_id(mesh_2d_ext_bdry);
460  // Elements have changed, neighbors, ids etc
461  mesh->unset_is_prepared();
462 
463  return mesh;
464 }
void buildPolyLineMesh(MeshBase &mesh, const std::vector< Point > &points, const bool loop, const BoundaryName &start_boundary, const BoundaryName &end_boundary, const std::vector< unsigned int > &nums_edges_between_points)
Generates meshes from edges connecting a list of points.
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
Definition: EigenADReal.h:50
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
Real meshNormalDeviation2D(const MeshBase &mesh, const Point &global_norm)
Calculate the maximum deviation of the normal vectors in a given mesh from a global average normal ve...
std::unique_ptr< ReplicatedMesh > buildReplicatedMesh(unsigned int dim=libMesh::invalid_uint)
Build a replicated mesh.
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition: MooseBase.h:467
void convertBlockToMesh(MeshBase &source_mesh, MeshBase &target_mesh, const std::vector< SubdomainName > &target_blocks)
Convert a list of blocks in a given mesh to a standalone new mesh.
static constexpr Real TOLERANCE
Base class for Delaunay mesh generators applied to a surface.
virtual std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
MeshBase & mesh
std::unique_ptr< UnstructuredMesh > General2DDelaunay(UnstructuredMesh &mesh_2d, std::vector< std::unique_ptr< UnstructuredMesh >> &hole_meshes_2d, unsigned int group_i)
Generate a 2D mesh using Delaunay triangulation based on the input 2D surface mesh and the 2D hole me...
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const Parallel::Communicator & comm() const
Point meshNormal2D(const MeshBase &mesh)
Calculate the average normal vector of a 2D mesh based on the normal vectors of its elements using th...
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
Helper class to define, parameterize and create a level set function used in meshing, often to correct the position of nodes on a surface.
unsigned int _num_groups
Number of groups of subdomains, also number of times we will call the Delaunay generator.
std::unique_ptr< ReplicatedMesh > buildLoopBoundaryOf2DMesh(const MeshBase &input_mesh, const boundary_id_type boundary_id)
Build a loop mesh of edges from the contiguous 2D boundary of 2D input mesh Note: The lower-dimension...
void renameParameterGroup(const std::string &old_name, const std::string &new_name)
This method renames a parameter group.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
static InputParameters validParams()
void mooseWarning(Args &&... args) const
const bool _use_auto_area_func
Whether to use automatic desired area function.
registerMooseObject("MooseApp", SurfaceSubdomainsDelaunayRemesher)
const bool _verbose
Whether the generator should be verbose.
std::vector< Real > _desired_areas
Target areas for the triangulation for each group of surface subdomains.
const std::string & type() const
Get the type of this class.
Definition: MooseBase.h:93
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
const unsigned int _auto_area_function_num_points
Maximum number of points to use for the inverse distance interpolation for automatic area function...
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
SymFunctionPtr _func_level_set
function parser object describing the level set
void levelSetCorrection(Node &node)
Correct the position of a node based on the level set function.
SurfaceSubdomainsDelaunayRemesher(const InputParameters &parameters)
Real levelSetEvaluator(const Point &point)
Evaluate the level set function at a given point.
const Real _auto_area_func_default_size_dist
Background size&#39;s effective distance for automatic desired area function.
std::vector< std::vector< SubdomainName > > _subdomain_names
The subdomains to be converted to a 2D mesh.
void createSubdomainFromSidesets(MeshBase &mesh, std::vector< BoundaryName > boundary_names, const SubdomainID new_subdomain_id, const SubdomainName new_subdomain_name, const std::string type_name)
Create a new subdomain by generating new side elements from a list of sidesets in a given mesh...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Real _max_angle_deviation
Max angle deviation from the global average normal vector in the input mesh.
std::vector< unsigned int > _interpolate_boundaries
Number of points added to boundaries around each group of surface subdomains.
const Real _auto_area_function_power
Power of the polynomial used in the inverse distance interpolation for automatic area function...
const unsigned int _max_level_set_correction_iterations
Maximum number of iterations to correct the nodes based on the level set function.
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:281
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:209
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
Point meshCentroidCalculator(const MeshBase &mesh)
Calculates the centroid of a MeshBase.
std::unique_ptr< MeshBase > buildMeshBaseObject(unsigned int dim=libMesh::invalid_uint)
Build a MeshBase object whose underlying type will be determined by the Mesh input file block...
const Real _auto_area_func_default_size
Background size for automatic desired area function.
SubdomainID getNextFreeSubdomainID(MeshBase &input_mesh)
Checks input mesh and returns max(block ID) + 1, which represents a block ID that is not currently in...
BoundaryID getNextFreeBoundaryID(MeshBase &input_mesh)
Checks input mesh and returns the largest boundary ID in the mesh plus one, which is a boundary ID in...
std::unique_ptr< MeshBase > & _input
The input mesh name.
Class to remesh surface subdomains using a triangle mesh inside the subdomain boundaries.
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition: MooseBase.h:215
void ErrorVector unsigned int
auto index_range(const T &sizable)
Point elemNormal(const Elem &elem)
Calculate the normal vector of a 2D element based the first three vertices.
void addExternalBoundary(MeshBase &mesh, const BoundaryID extern_bid, bool &has_external_bid)
Adds a sideset for the external boundary of the mesh (e.g.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...