https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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.");
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
65std::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;
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->set_subdomain_name(_block_id, getParam<SubdomainName>("block_name"), true);
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}
registerMooseObject("MooseApp", ManifoldSubdomainGenerator)
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
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 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...
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 addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
MeshGenerator for defining a subdomain based on whether element vertex averages lie within a closed m...
std::unique_ptr< MeshBase > generate() override
Apply STL-based subdomain tagging using element vertex averages as the query points.
const bool _has_restriction
Whether retagging is limited to a subset of existing subdomains.
const subdomain_id_type _block_id
Target subdomain identifier to assign.
static InputParameters validParams()
Declare the input parameters for STL-based subdomain assignment.
ManifoldSubdomainGenerator(const InputParameters &parameters)
Construct the mesh generator from user input.
const MooseEnum _location
Whether to tag the interior or exterior of the STL manifold.
std::unique_ptr< MeshBase > & _manifold
Surface mesh that defines the closed manifold.
const Real _surface_tolerance
Absolute tolerance used by the manifold classifier; choose relative to geometry scale/noise.
std::unique_ptr< MeshBase > & _input
Input mesh to modify in place.
MeshGenerators are objects that can modify or add to an existing mesh.
static InputParameters validParams()
void mooseDocumentedError(const std::string &repo_name, const unsigned int issue_num, Args &&... args) const
Definition MooseBase.h:277
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
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:457
void mooseInfo(Args &&... args) const
Definition MooseBase.h:334
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
Utility for querying point containment against a closed triangulated surface mesh.
bool contains(const Point &point) const
MeshBase & mesh
bool hasSubdomainName(const MeshBase &input_mesh, const SubdomainName &name)
Whether a particular subdomain name exists in the mesh.
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)
Whether a particular subdomain ID exists in the mesh.
SubdomainID getSubdomainID(const SubdomainName &subdomain_name, const MeshBase &mesh)
Gets the subdomain ID associated with the given SubdomainName.