https://mooseframework.inl.gov
Loading...
Searching...
No Matches
CoarseMeshExtraElementIDGenerator.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#include "MooseMeshUtils.h"
12
13#include "libmesh/enum_point_locator_type.h"
14#include "libmesh/elem.h"
15#include "libmesh/mesh_serializer.h"
16
17using namespace libMesh;
18
20
23{
25 params.addRequiredParam<MeshGeneratorName>(
26 "input", "Name of an existing mesh generator to which we assign coarse element IDs");
27 params.addRequiredParam<MeshGeneratorName>(
28 "coarse_mesh", "Name of an existing mesh generator as the coarse mesh");
29 params.addRequiredParam<std::string>(
30 "extra_element_id_name", "Name for the extra element ID that is added to the input mesh");
31 params.addParam<std::string>(
32 "coarse_mesh_extra_element_id",
33 "Name for the extra element ID that is copied from the coarse mesh (default to element ID)");
34 params.addParam<std::vector<SubdomainName>>(
35 "subdomains", std::vector<SubdomainName>(), "Subdomains to apply extra element IDs to.");
36 params.addParam<bool>("enforce_mesh_embedding",
37 false,
38 "True to error out when the input mesh is not embedded in the coarse mesh");
39
40 params.addClassDescription("Assign coarse element IDs for elements on a "
41 "mesh based on a coarse mesh.");
42 return params;
43}
44
46 : MeshGenerator(params),
47 _input(getMesh("input")),
48 _coarse_mesh(getMesh("coarse_mesh")),
49 _coarse_id_name(getParam<std::string>("extra_element_id_name")),
50 _using_coarse_element_id(isParamValid("coarse_mesh_extra_element_id")),
51 _embedding_necessary(getParam<bool>("enforce_mesh_embedding"))
52{
53}
54
55std::unique_ptr<MeshBase>
57{
58 std::unique_ptr<MeshBase> mesh = std::move(_input);
59
60 unsigned int coarse_id;
61 const bool already_has_id = mesh->has_elem_integer(_coarse_id_name);
62 if (!already_has_id)
64 else
66
67 // Get the requested subdomain IDs
68 std::set<SubdomainID> included_subdomains;
69 std::set<SubdomainName> bad_subdomains;
70 for (const auto & snm : getParam<std::vector<SubdomainName>>("subdomains"))
71 {
72 auto sid = MooseMeshUtils::getSubdomainID(snm, *mesh);
74 bad_subdomains.insert(snm);
75 else
76 included_subdomains.insert(sid);
77 }
78 if (!bad_subdomains.empty())
79 paramError("subdomains",
80 "The requested subdomains do not exist on the fine mesh: ",
81 Moose::stringify(bad_subdomains));
82
83 // If we are not going through the entire mesh and the ID already exists, we need to offset the
84 // assigned ID so that we don't copy ones that are already there
85 dof_id_type id_offset = 0;
86 if (already_has_id && !included_subdomains.empty())
87 {
88 for (auto & elem : mesh->active_element_ptr_range())
89 {
90 dof_id_type elem_id = elem->get_extra_integer(coarse_id);
91 if (elem_id != DofObject::invalid_id && elem_id > id_offset)
92 id_offset = elem_id;
93 }
94 id_offset++;
95 }
96
97 std::unique_ptr<MeshBase> coarse_mesh = std::move(_coarse_mesh);
98
99 bool using_subdomain_id = false;
100 unsigned int id_for_assignment = 0;
102 {
103 const auto & id_name = getParam<std::string>("coarse_mesh_extra_element_id");
104 if (id_name == "subdomain_id")
105 using_subdomain_id = true;
106 else
107 {
108 using_subdomain_id = false;
109 if (!coarse_mesh->has_elem_integer(id_name))
110 paramError("coarse_mesh_extra_element_id",
111 "The extra element ID does not exist on the coarse mesh");
112 else
113 id_for_assignment = coarse_mesh->get_elem_integer_index(id_name);
114 }
115 }
116
117 // a relative tolerance on checking if fine mesh is embedded in the coarse mesh
118 Real aeps = 0.01;
119
120 // The coarse mesh is serialized for distributed mesh to avoid boundary issues.
121 // As it is coarse this should be cheap. This will be a null operation for a replicated mesh.
122 MeshSerializer tm(*coarse_mesh);
123
124 // build a point_locator on coarse mesh
125 std::unique_ptr<PointLocatorBase> point_locator =
127 point_locator->enable_out_of_mesh_mode();
128
129 // loop through fine mesh elements and get element's centroid
130 auto elem_range = included_subdomains.empty()
131 ? mesh->active_element_ptr_range()
132 : mesh->active_subdomain_set_elements_ptr_range(included_subdomains);
133 for (auto & elem : elem_range)
134 {
135 // Get the centroid of the fine elem
136 Point centroid = elem->true_centroid();
137
138 // Find coarse elem
139 const Elem * coarse_elem = (*point_locator)(centroid);
140 if (!coarse_elem)
141 mooseError("Could not find a coarse element containing a fine element with centroid ",
142 centroid);
143
144 // get id from the coarse element
145 dof_id_type elem_id;
147 {
148 if (using_subdomain_id)
149 elem_id = coarse_elem->subdomain_id();
150 else
151 elem_id = coarse_elem->get_extra_integer(id_for_assignment);
152 }
153 else
154 elem_id = coarse_elem->id();
155 elem_id += id_offset;
156
157 // Check if the fine elem is nested in the coarse element
158 for (unsigned int n = 0; n < elem->n_nodes(); n++)
159 {
160 // Get the node: we need to manually move it towards the centroid to
161 // ensure that nothing weird happes due to round-off
162 Point current_node = elem->point(n);
163 current_node.add_scaled(current_node, -aeps);
164 current_node.add_scaled(centroid, aeps);
165
166 // Get the element this node is in and check if it is the same
167 // as the coarse elem; however check if node_elem is valid as it
168 // might not be in case the sub element it outside the coarse domain
169 const Elem * node_elem = (*point_locator)(current_node);
170 if (!node_elem)
171 mooseError("Could not find a coarse element containing a node of fine element at ",
172 elem->point(n));
173
174 // get another id from the coarse element with this node
175 dof_id_type node_elem_id;
177 {
178 if (using_subdomain_id)
179 node_elem_id = node_elem->subdomain_id();
180 else
181 node_elem_id = node_elem->get_extra_integer(id_for_assignment);
182 }
183 else
184 node_elem_id = node_elem->id();
185
186 if (node_elem_id != elem_id)
189 "Input mesh is not nested in the coarse mesh in CoarseMeshExtraElementIDGenerator.");
190 }
191
192 elem->set_extra_integer(coarse_id, elem_id);
193 }
194
195 return mesh;
196}
registerMooseObject("ReactorApp", CoarseMeshExtraElementIDGenerator)
const std::string & _coarse_id_name
coarse element ID name
std::unique_ptr< MeshBase > & _input
input mesh for adding element IDs
virtual std::unique_ptr< MeshBase > generate() override
const bool & _embedding_necessary
whether the input mesh must be embedded in the coarse mesh
CoarseMeshExtraElementIDGenerator(const InputParameters &parameters)
std::unique_ptr< MeshBase > & _coarse_mesh
name of the coarse mesh file
const bool _using_coarse_element_id
whether or not using the coarse element ID for the extra element ID assignment
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
static InputParameters validParams()
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
dof_id_type get_extra_integer(const unsigned int index) const
static constexpr dof_id_type invalid_id
dof_id_type id() const
subdomain_id_type subdomain_id() const
virtual SimpleRange< element_iterator > active_subdomain_set_elements_ptr_range(std::set< subdomain_id_type > ss)=0
unsigned int get_elem_integer_index(std::string_view name) const
unsigned int add_elem_integer(std::string name, bool allocate_data=true, dof_id_type default_value=DofObject::invalid_id)
bool has_elem_integer(std::string_view name) const
static std::unique_ptr< PointLocatorBase > build(PointLocatorType t, const MeshBase &mesh, const PointLocatorBase *master=nullptr)
void add_scaled(const TypeVector< T2 > &, const Real &)
MeshBase & mesh
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)
SubdomainID getSubdomainID(const SubdomainName &subdomain_name, const MeshBase &mesh)
std::string stringify(const T &t)
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
uint8_t dof_id_type
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real