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