https://mooseframework.inl.gov
MeshInfo.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 
10 #include "MeshInfo.h"
11 #include "SubProblem.h"
12 #include "libmesh/system.h"
13 #include "libmesh/equation_systems.h"
14 #include "libmesh/parallel_sync.h"
15 
16 registerMooseObject("MooseApp", MeshInfo);
17 
20 {
22  params.addClassDescription(
23  "Report mesh information, such as the number of elements, nodes, and degrees of freedom.");
24 
25  MultiMooseEnum items(
26  "num_dofs num_dofs_nonlinear num_dofs_auxiliary num_elements num_nodes num_local_dofs "
27  "num_local_dofs_nonlinear num_local_dofs_auxiliary num_local_elements num_local_nodes "
28  "local_sidesets local_sideset_elems sidesets sideset_elems local_subdomains "
29  "local_subdomain_elems subdomains subdomain_elems");
30  params.addParam<MultiMooseEnum>(
31  "items",
32  items,
33  "The iteration information to output, if nothing is provided everything will be output.");
34 
35  return params;
36 }
37 
39  : GeneralReporter(parameters),
40  _items(getParam<MultiMooseEnum>("items")),
41  _num_dofs(declareHelper<unsigned int>("num_dofs", REPORTER_MODE_REPLICATED)),
42  _num_dofs_nl(declareHelper<unsigned int>("num_dofs_nonlinear", REPORTER_MODE_REPLICATED)),
43  _num_dofs_aux(declareHelper<unsigned int>("num_dofs_auxiliary", REPORTER_MODE_REPLICATED)),
44  _num_dofs_constrained(
45  declareHelper<unsigned int>("num_dofs_constrained", REPORTER_MODE_REPLICATED)),
46  _num_elem(declareHelper<unsigned int>("num_elements", REPORTER_MODE_REPLICATED)),
47  _num_node(declareHelper<unsigned int>("num_nodes", REPORTER_MODE_REPLICATED)),
48  _num_local_dofs(declareHelper<unsigned int>("num_local_dofs", REPORTER_MODE_DISTRIBUTED)),
49  _num_local_dofs_nl(
50  declareHelper<unsigned int>("num_dofs_local_nonlinear", REPORTER_MODE_DISTRIBUTED)),
51  _num_local_dofs_aux(
52  declareHelper<unsigned int>("num_dofs_local_auxiliary", REPORTER_MODE_DISTRIBUTED)),
53  _num_local_elem(declareHelper<unsigned int>("num_local_elements", REPORTER_MODE_DISTRIBUTED)),
54  _num_local_node(declareHelper<unsigned int>("num_local_nodes", REPORTER_MODE_DISTRIBUTED)),
55 
56  _local_sidesets(declareHelper<std::map<BoundaryID, SidesetInfo>>("local_sidesets",
58  _local_sideset_elems(declareHelper<std::map<BoundaryID, SidesetInfo>>(
59  "local_sideset_elems", REPORTER_MODE_DISTRIBUTED)),
60  _sidesets(declareHelper<std::map<BoundaryID, SidesetInfo>>("sidesets", REPORTER_MODE_ROOT)),
61  _sideset_elems(
62  declareHelper<std::map<BoundaryID, SidesetInfo>>("sideset_elems", REPORTER_MODE_ROOT)),
63 
64  _local_subdomains(declareHelper<std::map<SubdomainID, SubdomainInfo>>(
65  "local_subdomains", REPORTER_MODE_DISTRIBUTED)),
66  _local_subdomain_elems(declareHelper<std::map<SubdomainID, SubdomainInfo>>(
67  "local_subdomain_elems", REPORTER_MODE_DISTRIBUTED)),
68  _subdomains(
69  declareHelper<std::map<SubdomainID, SubdomainInfo>>("subdomains", REPORTER_MODE_ROOT)),
70  _subdomain_elems(
71  declareHelper<std::map<SubdomainID, SubdomainInfo>>("subdomain_elems", REPORTER_MODE_ROOT)),
72 
73  _equation_systems(_fe_problem.es()),
74  _nonlinear_system(_fe_problem.es().get_system("nl0")),
75  _aux_system(_fe_problem.es().get_system("aux0")),
76  _mesh(_fe_problem.mesh().getMesh())
77 {
78 }
79 
80 void
82 {
87  for (auto s : make_range(_equation_systems.n_systems()))
88  _num_dofs_constrained += _equation_systems.get_system(s).n_constrained_dofs();
89 
97 
100 }
101 
102 void
104 {
105  // Helper for adding the sideset names to a given map of sidesets
106  auto add_sideset_names = [&](std::map<BoundaryID, SidesetInfo> & sidesets)
107  {
108  for (auto & pair : sidesets)
109  pair.second.name = _mesh.get_boundary_info().get_sideset_name(pair.second.id);
110  };
111 
112  // Helper for sorting all of the sides in each sideset
113  auto sort_sides = [](std::map<BoundaryID, SidesetInfo> & sidesets)
114  {
115  for (auto & pair : sidesets)
116  std::sort(pair.second.sides.begin(), pair.second.sides.end());
117  };
118 
119  const bool include_all = !_items.isValid();
120 
121  if (include_all || _items.isValueSet("local_sidesets") ||
122  _items.isValueSet("local_sideset_elems") || _items.isValueSet("sideset_elems"))
123  {
124  _local_sidesets.clear();
125  _local_sideset_elems.clear();
126  _sideset_elems.clear();
127 
128  // Fill the local sideset information; all cases need it
129  std::map<BoundaryID, SidesetInfo> sidesets;
130  for (const auto & bnd_elem :
132  if (bnd_elem->_elem->processor_id() == processor_id())
133  {
134  auto & entry = sidesets[bnd_elem->_bnd_id];
135  entry.id = bnd_elem->_bnd_id;
136  entry.sides.emplace_back(bnd_elem->_elem->id(), bnd_elem->_side);
137  }
138 
139  // For local sidesets: copy over the local info, remove the sides, and add the names
140  if (include_all || _items.isValueSet("local_sidesets"))
141  {
142  // Copy over the local sideset info, remove the sides, and add the names
143  _local_sidesets = sidesets;
144  for (auto & pair : _local_sidesets)
145  pair.second.sides.clear();
146  add_sideset_names(_local_sidesets);
147  }
148 
149  // For local sideset elems: copy over the local info, and add the names
150  if (include_all || _items.isValueSet("local_sideset_elems"))
151  {
152  _local_sideset_elems = sidesets;
153  sort_sides(_local_sideset_elems);
154  add_sideset_names(_local_sideset_elems);
155  }
156 
157  // For the global sideset elems, we need to communicate all of the elems
158  if (include_all || _items.isValueSet("sideset_elems"))
159  {
160  // Set up a structure for sending each (id, elem id, side) tuple to root
161  std::map<processor_id_type,
162  std::vector<std::tuple<boundary_id_type, dof_id_type, unsigned int>>>
163  send_info;
164  auto & root_info = send_info[0];
165  for (const auto & pair : sidesets)
166  for (const auto & side : pair.second.sides)
167  root_info.emplace_back(pair.second.id, side.first, side.second);
168 
169  // Take the received information and insert it into _sideset_elems
170  auto accumulate_info =
171  [this](processor_id_type,
172  const std::vector<std::tuple<boundary_id_type, dof_id_type, unsigned int>> & info)
173  {
174  for (const auto & tuple : info)
175  {
176  const auto id = std::get<0>(tuple);
177  auto & entry = _sideset_elems[id];
178  entry.id = id;
179  entry.sides.emplace_back(std::get<1>(tuple), std::get<2>(tuple));
180  }
181  };
182 
183  // Push the information and insert it into _sideset_elems on root
184  Parallel::push_parallel_vector_data(comm(), send_info, accumulate_info);
185 
186  sort_sides(_sideset_elems);
187  add_sideset_names(_sideset_elems);
188  }
189  }
190 
191  // For global sideset information without elements, we can simplify communication.
192  // All we need are the boundary IDs from libMesh (may not be reduced, so take the union)
193  // and then add the names (global)
194  if (include_all || _items.isValueSet("sidesets"))
195  {
196  _sidesets.clear();
197 
198  auto boundary_ids = _mesh.get_boundary_info().get_boundary_ids();
199  comm().set_union(boundary_ids, 0);
200  if (processor_id() == 0)
201  {
202  for (const auto id : boundary_ids)
203  _sidesets[id].id = id;
204  add_sideset_names(_sidesets);
205  }
206  }
207 }
208 
209 void
210 to_json(nlohmann::json & json, const std::map<BoundaryID, MeshInfo::SidesetInfo> & sidesets)
211 {
212  for (const auto & pair : sidesets)
213  {
214  const MeshInfo::SidesetInfo & sideset_info = pair.second;
215 
216  nlohmann::json sideset_json;
217  sideset_json["id"] = sideset_info.id;
218  if (sideset_info.name.size())
219  sideset_json["name"] = sideset_info.name;
220  if (sideset_info.sides.size())
221  {
222  auto & sides_json = sideset_json["sides"];
223 
224  for (const std::pair<dof_id_type, unsigned int> & pair : sideset_info.sides)
225  {
226  nlohmann::json side_json;
227  side_json["elem_id"] = pair.first;
228  side_json["side"] = pair.second;
229  sides_json.push_back(side_json);
230  }
231  }
232 
233  json.push_back(sideset_json);
234  }
235 }
236 
237 void
238 dataStore(std::ostream & stream, MeshInfo::SidesetInfo & sideset_info, void * context)
239 {
240  storeHelper(stream, sideset_info.id, context);
241  storeHelper(stream, sideset_info.name, context);
242  storeHelper(stream, sideset_info.sides, context);
243 }
244 
245 void
246 dataLoad(std::istream & stream, MeshInfo::SidesetInfo & sideset_info, void * context)
247 {
248  loadHelper(stream, sideset_info.id, context);
249  loadHelper(stream, sideset_info.name, context);
250  loadHelper(stream, sideset_info.sides, context);
251 }
252 
253 void
255 {
256  // Helper for adding the subdomain names to a given map of subdomains
257  auto add_subdomain_names = [&](std::map<SubdomainID, SubdomainInfo> & subdomains)
258  {
259  for (auto & pair : subdomains)
260  pair.second.name = _mesh.subdomain_name(pair.second.id);
261  };
262 
263  // Helper for sorting all of the elems in each subdomain
264  auto sort_elems = [](std::map<SubdomainID, SubdomainInfo> & subdomains)
265  {
266  for (auto & pair : subdomains)
267  std::sort(pair.second.elems.begin(), pair.second.elems.end());
268  };
269 
270  const bool include_all = !_items.isValid();
271 
272  if (include_all || _items.isValueSet("local_subdomains") ||
273  _items.isValueSet("local_subdomain_elems") || _items.isValueSet("subdomain_elems"))
274  {
275  _local_subdomains.clear();
276  _local_subdomain_elems.clear();
277  _subdomain_elems.clear();
278 
279  // Fill the local subdomain information; all cases need it
280  std::map<SubdomainID, SubdomainInfo> subdomains;
281  for (const auto & elem : *_fe_problem.mesh().getActiveLocalElementRange())
282  {
283  auto & entry = subdomains[elem->subdomain_id()];
284  entry.id = elem->subdomain_id();
285  entry.elems.push_back(elem->id());
286  }
287 
288  // For local subdomains: copy over the local info, remove the elems, and add the names
289  if (include_all || _items.isValueSet("local_subdomains"))
290  {
291  _local_subdomains = subdomains;
292  for (auto & pair : _local_subdomains)
293  pair.second.elems.clear();
294  add_subdomain_names(_local_subdomains);
295  }
296 
297  // For local subdomain elems: copy over the local info, and add the names
298  if (include_all || _items.isValueSet("local_subdomain_elems"))
299  {
300  _local_subdomain_elems = subdomains;
301  sort_elems(_local_subdomain_elems);
302  add_subdomain_names(_local_subdomain_elems);
303  }
304 
305  // For the global subdomain elems, we need to communicate all of the elems
306  if (include_all || _items.isValueSet("subdomain_elems"))
307  {
308  // Set up a structure for sending each (id, elem id) to root
309  std::map<processor_id_type, std::vector<std::pair<subdomain_id_type, dof_id_type>>> send_info;
310  auto & root_info = send_info[0];
311  for (const auto & pair : subdomains)
312  for (const auto elem_id : pair.second.elems)
313  root_info.emplace_back(pair.second.id, elem_id);
314 
315  // Take the received information and insert it into _subdomain_elems
316  auto accumulate_info =
317  [this](processor_id_type,
318  const std::vector<std::pair<subdomain_id_type, dof_id_type>> & info)
319  {
320  for (const auto & subdomain_elem_pair : info)
321  {
322  auto & entry = _subdomain_elems[subdomain_elem_pair.first];
323  entry.id = subdomain_elem_pair.first;
324  entry.elems.emplace_back(subdomain_elem_pair.second);
325  }
326  };
327 
328  // Push the information and insert it into _subdomain_elems on root
329  Parallel::push_parallel_vector_data(comm(), send_info, accumulate_info);
330 
331  if (processor_id() == 0)
332  {
333  sort_elems(_subdomain_elems);
334  add_subdomain_names(_subdomain_elems);
335  }
336  }
337  }
338 
339  // For global subdomain information without elements, we can simplify communication.
340  // All we need are the subdomain IDs from libMesh and then add the names (global)
341  if (include_all || _items.isValueSet("subdomains"))
342  {
343  _subdomains.clear();
344 
345  std::set<subdomain_id_type> subdomain_ids;
346  _mesh.subdomain_ids(subdomain_ids);
347 
348  if (processor_id() == 0)
349  {
350  for (const auto id : subdomain_ids)
351  _subdomains[id].id = id;
352  add_subdomain_names(_subdomains);
353  }
354  }
355 }
356 
357 void
358 to_json(nlohmann::json & json, const std::map<SubdomainID, MeshInfo::SubdomainInfo> & subdomains)
359 {
360  for (const auto & pair : subdomains)
361  {
362  const MeshInfo::SubdomainInfo & subdomain_info = pair.second;
363 
364  nlohmann::json subdomain_json;
365  subdomain_json["id"] = subdomain_info.id;
366  if (subdomain_info.name.size())
367  subdomain_json["name"] = subdomain_info.name;
368  if (subdomain_info.elems.size())
369  {
370  auto & sides_json = subdomain_json["elems"];
371  for (const auto & id : subdomain_info.elems)
372  sides_json.push_back(id);
373  }
374 
375  json.push_back(subdomain_json);
376  }
377 }
378 
379 void
380 dataStore(std::ostream & stream, MeshInfo::SubdomainInfo & subdomain_info, void * context)
381 {
382  storeHelper(stream, subdomain_info.id, context);
383  storeHelper(stream, subdomain_info.name, context);
384  storeHelper(stream, subdomain_info.elems, context);
385 }
386 
387 void
388 dataLoad(std::istream & stream, MeshInfo::SubdomainInfo & subdomain_info, void * context)
389 {
390  loadHelper(stream, subdomain_info.id, context);
391  loadHelper(stream, subdomain_info.name, context);
392  loadHelper(stream, subdomain_info.elems, context);
393 }
virtual bnd_elem_iterator bndElemsEnd()
Definition: MooseMesh.C:1569
Helper struct for defining information about a single sideset.
Definition: MeshInfo.h:36
std::vector< dof_id_type > elems
Definition: MeshInfo.h:50
libMesh::ConstElemRange * getActiveLocalElementRange()
Return pointers to range objects for various types of ranges (local nodes, boundary elems...
Definition: MooseMesh.C:1238
std::string name
Definition: MeshInfo.h:39
std::string name
Definition: MeshInfo.h:49
unsigned int n_systems() const
static InputParameters validParams()
Definition: MeshInfo.C:19
unsigned int & _num_local_elem
Definition: MeshInfo.h:66
void possiblyAddSidesetInfo()
Possibly add to _local_sidesets, _local_sideset_elems, _sidesets, and _sideset_elems.
Definition: MeshInfo.C:103
const libMesh::MeshBase & _mesh
Definition: MeshInfo.h:90
unsigned int & _num_dofs_constrained
Definition: MeshInfo.h:60
MPI_Info info
Reporter object that has a single execution of the "execute" method for for each execute flag...
std::size_t n_dofs() const
const ReporterMode REPORTER_MODE_ROOT
virtual void execute() override
Execute method.
Definition: MeshInfo.C:81
virtual bool isValid() const override
IsValid.
std::map< SubdomainID, SubdomainInfo > & _subdomains
Definition: MeshInfo.h:74
MeshBase & mesh
unsigned int & _num_dofs_aux
Definition: MeshInfo.h:59
dof_id_type n_local_nodes() const
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::map< BoundaryID, SidesetInfo > & _sideset_elems
Definition: MeshInfo.h:71
const Parallel::Communicator & comm() const
virtual bnd_elem_iterator bndElemsBegin()
Return iterators to the beginning/end of the boundary elements list.
Definition: MooseMesh.C:1561
static InputParameters validParams()
dof_id_type n_local_dofs() const
const BoundaryInfo & get_boundary_info() const
const T_sys & get_system(std::string_view name) const
unsigned int & _num_local_dofs_aux
Definition: MeshInfo.h:65
unsigned int & _num_local_node
Definition: MeshInfo.h:67
dof_id_type n_local_elem() const
void to_json(nlohmann::json &json, const std::map< BoundaryID, MeshInfo::SidesetInfo > &sidesets)
Definition: MeshInfo.C:210
dof_id_type n_dofs() const
MeshInfo(const InputParameters &parameters)
Definition: MeshInfo.C:38
unsigned int & _num_dofs_nl
Definition: MeshInfo.h:58
Report mesh information, such as the number of elements, nodes, and degrees of freedom.
Definition: MeshInfo.h:24
void storeHelper(std::ostream &stream, P &data, void *context)
Scalar helper routine.
Definition: DataIO.h:893
uint8_t processor_id_type
const libMesh::EquationSystems & _equation_systems
Definition: MeshInfo.h:87
boundary_id_type BoundaryID
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
std::vector< std::pair< dof_id_type, unsigned int > > sides
Definition: MeshInfo.h:40
void subdomain_ids(std::set< subdomain_id_type > &ids, const bool global=true) const
std::string & subdomain_name(subdomain_id_type id)
void possiblyAddSubdomainInfo()
Possibly add to _local_subdomains, _local_subdomain_elems, _subdomains, and _subdomain_elems.
Definition: MeshInfo.C:254
std::map< BoundaryID, SidesetInfo > & _local_sidesets
Definition: MeshInfo.h:68
bool isValueSet(const std::string &value) const
Methods for seeing if a value is set in the MultiMooseEnum.
const ReporterMode REPORTER_MODE_DISTRIBUTED
unsigned int & _num_node
Definition: MeshInfo.h:62
Helper struct for defining information about a single subdomain.
Definition: MeshInfo.h:46
const std::set< boundary_id_type > & get_boundary_ids() const
const libMesh::System & _aux_system
Definition: MeshInfo.h:89
FEProblemBase & _fe_problem
Reference to the FEProblemBase for this user object.
Definition: UserObject.h:211
std::map< BoundaryID, SidesetInfo > & _sidesets
Definition: MeshInfo.h:70
if(!dmm->_nl) SETERRQ(PETSC_COMM_WORLD
void dataLoad(std::istream &stream, MeshInfo::SidesetInfo &sideset_info, void *context)
Definition: MeshInfo.C:246
const std::string & get_sideset_name(boundary_id_type id) const
std::map< SubdomainID, SubdomainInfo > & _local_subdomain_elems
Definition: MeshInfo.h:73
IntRange< T > make_range(T beg, T end)
virtual MooseMesh & mesh() override
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...
std::map< SubdomainID, SubdomainInfo > & _local_subdomains
Definition: MeshInfo.h:72
const ReporterMode REPORTER_MODE_REPLICATED
unsigned int & _num_local_dofs
Definition: MeshInfo.h:63
unsigned int & _num_dofs
Definition: MeshInfo.h:57
std::map< SubdomainID, SubdomainInfo > & _subdomain_elems
Definition: MeshInfo.h:75
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type...
const MultiMooseEnum & _items
Definition: MeshInfo.h:54
void dataStore(std::ostream &stream, MeshInfo::SidesetInfo &sideset_info, void *context)
Definition: MeshInfo.C:238
virtual dof_id_type n_elem() const=0
processor_id_type processor_id() const
unsigned int & _num_local_dofs_nl
Definition: MeshInfo.h:64
std::map< BoundaryID, SidesetInfo > & _local_sideset_elems
Definition: MeshInfo.h:69
void loadHelper(std::istream &stream, P &data, void *context)
Scalar helper routine.
Definition: DataIO.h:985
unsigned int & _num_elem
Definition: MeshInfo.h:61
const libMesh::System & _nonlinear_system
Definition: MeshInfo.h:88
void ErrorVector unsigned int
registerMooseObject("MooseApp", MeshInfo)
virtual dof_id_type n_nodes() const=0
void set_union(T &data, const unsigned int root_id) const