https://mooseframework.inl.gov
ManifoldSubdomainGenerator.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
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 "CastUniquePointer.h"
13 #include "MooseMeshUtils.h"
14 #include "TriangleManifold.h"
15 
16 #include "libmesh/mesh_serializer.h"
17 #include "libmesh/elem.h"
18 
19 #include <set>
20 
22 
25 {
26  // This interface intentionally mirrors other point-sampling subdomain tagging generators.
27  MooseEnum location("INSIDE OUTSIDE", "INSIDE");
28 
30  params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify.");
31  params.addRequiredParam<MeshGeneratorName>("manifold", "The mesh defining a closed manifold.");
32  params.addRequiredParam<subdomain_id_type>("block_id", "Subdomain id to assign.");
33  params.addParam<SubdomainName>("block_name", "Optional subdomain name to assign.");
34  params.addParam<MooseEnum>(
35  "location", location, "Control whether the manifold interior or exterior is tagged.");
36  params.addParam<std::vector<SubdomainName>>("restricted_subdomains",
37  "Only reset subdomain ID for given subdomains.");
38  params.addRangeCheckedParam<Real>(
39  "surface_tolerance",
40  1e-10,
41  "surface_tolerance>0",
42  "Absolute geometric tolerance used for manifold validation and near-surface classification. "
43  "Choose this relative to the STL length scale and expected coordinate noise.");
44  params.addClassDescription(
45  "Changes the subdomain ID of elements whose vertex-average point lies inside or outside a "
46  "closed manifold defined by surface mesh.");
47  return params;
48 }
49 
51  : MeshGenerator(parameters),
52  _input(getMesh("input")),
53  _manifold(getMesh("manifold")),
54  _location(parameters.get<MooseEnum>("location")),
55  _block_id(parameters.get<subdomain_id_type>("block_id")),
56  _has_restriction(isParamValid("restricted_subdomains")),
57  _surface_tolerance(getParam<Real>("surface_tolerance"))
58 {
59 #if LIBMESH_DOF_ID_BYTES != 8
61  "moose", 32898, "ManifoldSubdomainGenerator currently only works with 64-bit DoF IDs");
62 #endif
63 }
64 
65 std::unique_ptr<MeshBase>
67 {
68  std::unique_ptr<MeshBase> mesh = std::move(_input);
69  std::unique_ptr<MeshBase> manifold_mesh = std::move(_manifold);
70 
71  // The manifold describes a volume boundary, so the target mesh must also be volumetric.
72  if (mesh->mesh_dimension() != 3)
73  paramError("input", "Only 3D meshes are supported.");
74 
75  // Make sure the mesh is prepared
76  if (!manifold_mesh->is_prepared())
77  manifold_mesh->prepare_for_use();
78  // Must be serialized, for now
79  libMesh::MeshSerializer serial_manifold(*manifold_mesh);
80  // The manifold must also be 2D
81  if (*(manifold_mesh->elem_dimensions().begin()) != 2 ||
82  *(manifold_mesh->elem_dimensions().rbegin()) != 2)
83  paramError("manifold", "Only 2D meshes are supported.");
84 
85  std::set<SubdomainID> restricted_ids;
86  if (_has_restriction)
87  {
88  // Resolve user block names to ids once before the element loop.
89  const auto & names = getParam<std::vector<SubdomainName>>("restricted_subdomains");
90  for (const auto & name : names)
91  {
93  paramError("restricted_subdomains", "The block '", name, "' was not found in the mesh");
94 
95  restricted_ids.insert(MooseMeshUtils::getSubdomainID(name, *mesh));
96  }
97  }
98 
99  if (MooseMeshUtils::hasSubdomainID(*mesh, _block_id) && mesh->processor_id() == 0)
100  mooseInfo("The requested block_id ",
101  _block_id,
102  " already exists on the input mesh. Elements outside the closed manifold that are "
103  "already assigned to this block will remain unchanged.");
104 
105  // Build the classifier up front so the per-element loop only performs point-in-manifold queries.
106  TriangleManifold manifold(*manifold_mesh, _surface_tolerance);
107 
108  // On distributed meshes, only locally owned active elements are modified on each rank.
109  // TODO: This could technically be over local elements, but changing subdomains asynchronously
110  // causes issues in downstream mesh generators like BlockDeletionGenerator.
111  for (const auto & elem : mesh->active_element_ptr_range())
112  {
113  if (_has_restriction && restricted_ids.count(elem->subdomain_id()) == 0)
114  continue;
115 
116  // This generator intentionally samples at the vertex average instead of the true geometric
117  // centroid, matching the inexpensive behavior of other subdomain tagging generators.
118  const bool contains = manifold.contains(elem->vertex_average());
119  if ((contains && _location == "INSIDE") || (!contains && _location == "OUTSIDE"))
120  elem->subdomain_id() = _block_id;
121  }
122 
123  // Preserve the optional user-facing subdomain name for the assigned id.
124  if (isParamValid("block_name"))
125  mesh->subdomain_name(_block_id) = getParam<SubdomainName>("block_name");
126 
127  // Mark derived mesh data as stale because element subdomain assignments have changed.
128  mesh->unset_has_cached_elem_data();
129  return dynamic_pointer_cast<MeshBase>(mesh);
130 }
void mooseInfo(Args &&... args) const
Definition: MooseBase.h:344
const Real _surface_tolerance
Absolute tolerance used by the manifold classifier; choose relative to geometry scale/noise.
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
const MooseEnum _location
Whether to tag the interior or exterior of the STL manifold.
MeshGenerator for defining a subdomain based on whether element vertex averages lie within a closed m...
MeshBase & mesh
const subdomain_id_type _block_id
Target subdomain identifier to assign.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
void mooseDocumentedError(const std::string &repo_name, const unsigned int issue_num, Args &&... args) const
Definition: MooseBase.h:287
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.
ManifoldSubdomainGenerator(const InputParameters &parameters)
Construct the mesh generator from user input.
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...
registerMooseObject("MooseApp", ManifoldSubdomainGenerator)
SubdomainID getSubdomainID(const SubdomainName &subdomain_name, const MeshBase &mesh)
Gets the subdomain ID associated with the given SubdomainName.
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)
Whether a particular subdomain ID exists in the mesh.
std::unique_ptr< MeshBase > & _input
Input mesh to modify in place.
static InputParameters validParams()
Declare the input parameters for STL-based subdomain assignment.
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
bool contains(std::string_view superstring, std::string_view substring)
const bool _has_restriction
Whether retagging is limited to a subset of existing subdomains.
static InputParameters validParams()
Definition: MeshGenerator.C:23
bool hasSubdomainName(const MeshBase &input_mesh, const SubdomainName &name)
Whether a particular subdomain name exists in the mesh.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::unique_ptr< MeshBase > & _manifold
Surface mesh that defines the closed manifold.
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
Utility for querying point containment against a closed triangulated surface mesh.
std::unique_ptr< MeshBase > generate() override
Apply STL-based subdomain tagging using element vertex averages as the query points.
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:33
const Elem & get(const ElemType type_in)
bool contains(const Point &point) const