https://mooseframework.inl.gov
SubdomainPerElementGenerator.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 "CastUniquePointer.h"
12 
13 #include "libmesh/elem.h"
14 
17  ElementSubdomainIDGenerator,
18  "05/18/2024 24:00",
20 
23 {
25 
26  params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
27  params.addRequiredParam<std::vector<SubdomainID>>("subdomain_ids",
28  "New subdomain IDs of all elements");
29  params.addParam<std::vector<dof_id_type>>("element_ids", "New element IDs of all elements");
30  params.addClassDescription(
31  "Allows the user to assign each element the subdomain ID of their choice");
32  return params;
33 }
34 
36  : MeshGenerator(parameters), _input(getMesh("input"))
37 {
38 }
39 
40 std::unique_ptr<MeshBase>
42 {
43  std::unique_ptr<MeshBase> mesh = std::move(_input);
44 
45  std::vector<SubdomainID> bids = getParam<std::vector<SubdomainID>>("subdomain_ids");
46 
47  // Generate a list of elements to which new subdomain IDs are to be assigned
48  std::vector<Elem *> elements;
49  if (isParamValid("element_ids"))
50  {
51  std::vector<dof_id_type> elemids = getParam<std::vector<dof_id_type>>("element_ids");
52  for (const auto & dof : elemids)
53  {
54  Elem * elem = mesh->query_elem_ptr(dof);
55  bool has_elem = elem;
56 
57  // If no processor sees this element, something must be wrong
58  // with the specified ID. If another processor sees this
59  // element but we don't, we'll insert NULL into our elements
60  // vector anyway so as to keep the indexing matching our bids
61  // vector.
62  this->comm().max(has_elem);
63  if (!has_elem)
64  mooseError("invalid element ID is in element_ids");
65  else
66  elements.push_back(elem);
67  }
68  }
69 
70  else
71  {
72  bool has_warned_remapping = false;
73 
74  // On a distributed mesh, iterating over all elements in
75  // increasing order is tricky. We have to consider element ids
76  // which aren't on a particular processor because they're remote,
77  // *and* elements which aren't on a particular processor because
78  // there's a hole in the current numbering.
79  //
80  // I don't see how to do this without a ton of communication,
81  // which is hopefully okay because it only happens at mesh setup,
82  // and because nobody who is here trying to use
83  // AssignElementSubdomainID to hand write every single element's
84  // subdomain ID will have a huge number of elements on their
85  // initial mesh.
86 
87  // Using plain max_elem_id() currently gives the same result on
88  // every processor, but that isn't guaranteed by the libMesh
89  // documentation, so let's be paranoid.
90  dof_id_type end_id = mesh->max_elem_id();
91  this->comm().max(end_id);
92 
93  for (dof_id_type e = 0; e != end_id; ++e)
94  {
95  // This is O(1) on ReplicatedMesh but O(log(N_elem)) on
96  // DistributedMesh. We can switch to more complicated but
97  // asymptotically faster code if my "nobody who is here ... will
98  // have a huge number of elements" claim turns out to be false.
99  Elem * elem = mesh->query_elem_ptr(e);
100  bool someone_has_elem = elem;
101  if (!mesh->is_replicated())
102  this->comm().max(someone_has_elem);
103 
104  if (elem && elem->id() != e && (!has_warned_remapping))
105  {
106  mooseWarning("AssignElementSubdomainID will ignore the element remapping");
107  has_warned_remapping = true;
108  }
109 
110  if (someone_has_elem)
111  elements.push_back(elem);
112  }
113  }
114 
115  if (bids.size() != elements.size())
116  mooseError(" Size of subdomain_ids is not consistent with the number of elements");
117 
118  // Assign new subdomain IDs and make sure elements in different types are not assigned with the
119  // same subdomain ID
120  std::map<ElemType, std::set<SubdomainID>> type2blocks;
121  for (dof_id_type e = 0; e < elements.size(); ++e)
122  {
123  // Get the element we need to assign, or skip it if we just have a
124  // nullptr placeholder indicating a remote element.
125  Elem * elem = elements[e];
126  if (!elem)
127  continue;
128 
129  ElemType type = elem->type();
130  SubdomainID newid = bids[e];
131 
132  bool has_type = false;
133  for (auto & it : type2blocks)
134  {
135  if (it.first == type)
136  {
137  has_type = true;
138  it.second.insert(newid);
139  }
140  else if (it.second.count(newid) > 0)
141  mooseError("trying to assign elements with different types with the same subdomain ID");
142  }
143 
144  if (!has_type)
145  {
146  std::set<SubdomainID> blocks;
147  blocks.insert(newid);
148  type2blocks.insert(std::make_pair(type, blocks));
149  }
150 
151  elem->subdomain_id() = newid;
152  }
153 
154  mesh->set_isnt_prepared();
155  return dynamic_pointer_cast<MeshBase>(mesh);
156 }
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
ElemType
char ** blocks
std::unique_ptr< MeshBase > & _input
mesh to modify
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const Parallel::Communicator & comm() const
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.
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
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...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
registerMooseObjectRenamed("MooseApp", ElementSubdomainIDGenerator, "05/18/2024 24:00", SubdomainPerElementGenerator)
registerMooseObject("MooseApp", SubdomainPerElementGenerator)
const std::string & type() const
Get the type of this class.
Definition: MooseBase.h:51
MeshGenerator for assigning subdomain IDs of all elements.
static InputParameters validParams()
Definition: MeshGenerator.C:23
void max(const T &r, T &o, Request &req) const
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
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...
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:32
uint8_t dof_id_type
SubdomainPerElementGenerator(const InputParameters &parameters)