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
18
21{
23 params.addRequiredParam<MeshGeneratorName>(
24 "input", "Name of an existing mesh generator to which we assign coarse element IDs");
25 params.addRequiredParam<MeshGeneratorName>(
26 "coarse_mesh", "Name of an existing mesh generator as the coarse mesh");
27 params.addRequiredParam<std::string>(
28 "extra_element_id_name", "Name for the extra element ID that is added to the input mesh");
29 params.addParam<std::string>(
30 "coarse_mesh_extra_element_id",
31 "Name for the extra element ID that is copied from the coarse mesh (default to element ID)");
32 params.addParam<std::vector<SubdomainName>>(
33 "subdomains", std::vector<SubdomainName>(), "Subdomains to apply extra element IDs to.");
34 params.addParam<bool>("enforce_mesh_embedding",
35 false,
36 "True to error out when the input mesh is not embedded in the coarse mesh");
37
38 params.addClassDescription("Assign coarse element IDs for elements on a "
39 "mesh based on a coarse mesh.");
40 return params;
41}
42
44 : MeshGenerator(params),
45 _input(getMesh("input")),
46 _coarse_mesh(getMesh("coarse_mesh")),
47 _coarse_id_name(getParam<std::string>("extra_element_id_name")),
48 _using_coarse_element_id(isParamValid("coarse_mesh_extra_element_id")),
49 _embedding_necessary(getParam<bool>("enforce_mesh_embedding"))
50{
51}
52
53std::unique_ptr<MeshBase>
55{
56 std::unique_ptr<MeshBase> mesh = std::move(_input);
57
58 unsigned int coarse_id;
59 const bool already_has_id = mesh->has_elem_integer(_coarse_id_name);
60 if (!already_has_id)
61 coarse_id = mesh->add_elem_integer(_coarse_id_name);
62 else
63 coarse_id = mesh->get_elem_integer_index(_coarse_id_name);
64
65 // Get the requested subdomain IDs
66 std::set<SubdomainID> included_subdomains;
67 std::set<SubdomainName> bad_subdomains;
68 for (const auto & snm : getParam<std::vector<SubdomainName>>("subdomains"))
69 {
70 auto sid = MooseMeshUtils::getSubdomainID(snm, *mesh);
72 bad_subdomains.insert(snm);
73 else
74 included_subdomains.insert(sid);
75 }
76 if (!bad_subdomains.empty())
77 paramError("subdomains",
78 "The requested subdomains do not exist on the fine mesh: ",
79 Moose::stringify(bad_subdomains));
80
81 // If we are not going through the entire mesh and the ID already exists, we need to offset the
82 // assigned ID so that we don't copy ones that are already there
83 dof_id_type id_offset = 0;
84 if (already_has_id && !included_subdomains.empty())
85 {
86 for (auto & elem : mesh->active_element_ptr_range())
87 {
88 dof_id_type elem_id = elem->get_extra_integer(coarse_id);
89 if (elem_id != DofObject::invalid_id && elem_id > id_offset)
90 id_offset = elem_id;
91 }
92 id_offset++;
93 }
94
95 std::unique_ptr<MeshBase> coarse_mesh = std::move(_coarse_mesh);
96
97 bool using_subdomain_id = false;
98 unsigned int id_for_assignment = 0;
100 {
101 const auto & id_name = getParam<std::string>("coarse_mesh_extra_element_id");
102 if (id_name == "subdomain_id")
103 using_subdomain_id = true;
104 else
105 {
106 using_subdomain_id = false;
107 if (!coarse_mesh->has_elem_integer(id_name))
108 paramError("coarse_mesh_extra_element_id",
109 "The extra element ID does not exist on the coarse mesh");
110 else
111 id_for_assignment = coarse_mesh->get_elem_integer_index(id_name);
112 }
113 }
114
115 // a relative tolerance on checking if fine mesh is embedded in the coarse mesh
116 Real aeps = 0.01;
117
118 // The coarse mesh is serialized for distributed mesh to avoid boundary issues.
119 // As it is coarse this should be cheap. This will be a null operation for a replicated mesh.
120 MeshSerializer tm(*coarse_mesh);
121
122 // build a point_locator on coarse mesh
123 std::unique_ptr<PointLocatorBase> point_locator =
124 PointLocatorBase::build(TREE_ELEMENTS, *coarse_mesh);
125 point_locator->enable_out_of_mesh_mode();
126
127 // loop through fine mesh elements and get element's centroid
128 auto elem_range = included_subdomains.empty()
129 ? mesh->active_element_ptr_range()
130 : mesh->active_subdomain_set_elements_ptr_range(included_subdomains);
131 for (auto & elem : elem_range)
132 {
133 // Get the centroid of the fine elem
134 Point centroid = elem->true_centroid();
135
136 // Find coarse elem
137 const Elem * coarse_elem = (*point_locator)(centroid);
138 if (!coarse_elem)
139 mooseError("Could not find a coarse element containing a fine element with centroid ",
140 centroid);
141
142 // get id from the coarse element
143 dof_id_type elem_id;
145 {
146 if (using_subdomain_id)
147 elem_id = coarse_elem->subdomain_id();
148 else
149 elem_id = coarse_elem->get_extra_integer(id_for_assignment);
150 }
151 else
152 elem_id = coarse_elem->id();
153 elem_id += id_offset;
154
155 // Check if the fine elem is nested in the coarse element
156 for (unsigned int n = 0; n < elem->n_nodes(); n++)
157 {
158 // Get the node: we need to manually move it towards the centroid to
159 // ensure that nothing weird happes due to round-off
160 Point current_node = elem->point(n);
161 current_node.add_scaled(current_node, -aeps);
162 current_node.add_scaled(centroid, aeps);
163
164 // Get the element this node is in and check if it is the same
165 // as the coarse elem; however check if node_elem is valid as it
166 // might not be in case the sub element it outside the coarse domain
167 const Elem * node_elem = (*point_locator)(current_node);
168 if (!node_elem)
169 mooseError("Could not find a coarse element containing a node of fine element at ",
170 elem->point(n));
171
172 // get another id from the coarse element with this node
173 dof_id_type node_elem_id;
175 {
176 if (using_subdomain_id)
177 node_elem_id = node_elem->subdomain_id();
178 else
179 node_elem_id = node_elem->get_extra_integer(id_for_assignment);
180 }
181 else
182 node_elem_id = node_elem->id();
183
184 if (node_elem_id != elem_id)
187 "Input mesh is not nested in the coarse mesh in CoarseMeshExtraElementIDGenerator.");
188 }
189
190 elem->set_extra_integer(coarse_id, elem_id);
191 }
192
193 return mesh;
194}
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
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)