https://mooseframework.inl.gov
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 
17 using 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 
55 std::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 =
126  PointLocatorBase::build(TREE_ELEMENTS, *coarse_mesh);
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)
188  mooseError(
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 }
void add_scaled(const TypeVector< T2 > &, const Real &)
T & getMesh(MooseMesh &mesh)
function to cast mesh
Definition: SCM.h:35
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const bool & _embedding_necessary
whether the input mesh must be embedded in the coarse mesh
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
MeshBase & mesh
std::unique_ptr< MeshBase > & _input
input mesh for adding element IDs
const bool _using_coarse_element_id
whether or not using the coarse element ID for the extra element ID assignment
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
TREE_ELEMENTS
void addRequiredParam(const std::string &name, const std::string &doc_string)
SubdomainID getSubdomainID(const SubdomainName &subdomain_name, const MeshBase &mesh)
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)
unsigned int get_elem_integer_index(std::string_view name) const
dof_id_type id() const
registerMooseObject("ReactorApp", CoarseMeshExtraElementIDGenerator)
const T & getParam(const std::string &name) const
void paramError(const std::string &param, Args... args) const
static InputParameters validParams()
std::unique_ptr< MeshBase > & _coarse_mesh
name of the coarse mesh file
std::string stringify(const T &t)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
subdomain_id_type subdomain_id() const
void mooseError(Args &&... args) const
virtual SimpleRange< element_iterator > active_subdomain_set_elements_ptr_range(std::set< subdomain_id_type > ss)=0
void addClassDescription(const std::string &doc_string)
const std::string & _coarse_id_name
coarse element ID name
CoarseMeshExtraElementIDGenerator(const InputParameters &parameters)
virtual std::unique_ptr< MeshBase > generate() override
dof_id_type get_extra_integer(const unsigned int index) const
uint8_t dof_id_type