https://mooseframework.inl.gov
MooseMeshUtils.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 // MOOSE includes
11 #include "MooseMeshUtils.h"
12 
13 #include "libmesh/elem.h"
14 #include "libmesh/boundary_info.h"
15 #include "libmesh/parallel.h"
16 #include "libmesh/parallel_algebra.h"
17 #include "libmesh/utility.h"
18 
19 using namespace libMesh;
20 
21 namespace MooseMeshUtils
22 {
23 
24 void
26 {
27  // We check if we have the same boundary name with different IDs. If we do, we assign the
28  // first ID to every occurrence.
29  const auto & side_bd_name_map = mesh.get_boundary_info().get_sideset_name_map();
30  const auto & node_bd_name_map = mesh.get_boundary_info().get_nodeset_name_map();
31  std::map<boundary_id_type, boundary_id_type> same_name_ids;
32 
33  auto populate_map = [](const std::map<boundary_id_type, std::string> & map,
34  std::map<boundary_id_type, boundary_id_type> & same_ids)
35  {
36  for (const auto & pair_outer : map)
37  for (const auto & pair_inner : map)
38  // The last condition is needed to make sure we only store one combination
39  if (pair_outer.second == pair_inner.second && pair_outer.first != pair_inner.first &&
40  same_ids.find(pair_inner.first) == same_ids.end())
41  same_ids[pair_outer.first] = pair_inner.first;
42  };
43 
44  populate_map(side_bd_name_map, same_name_ids);
45  populate_map(node_bd_name_map, same_name_ids);
46 
47  for (const auto & [id1, id2] : same_name_ids)
49 }
50 
51 void
53  const boundary_id_type old_id,
54  const boundary_id_type new_id,
55  bool delete_prev)
56 {
57  // Get a reference to our BoundaryInfo object, we will use it several times below...
58  BoundaryInfo & boundary_info = mesh.get_boundary_info();
59 
60  // Container to catch ids passed back from BoundaryInfo
61  std::vector<boundary_id_type> old_ids;
62 
63  // Only level-0 elements store BCs. Loop over them.
64  for (auto & elem : as_range(mesh.level_elements_begin(0), mesh.level_elements_end(0)))
65  {
66  unsigned int n_sides = elem->n_sides();
67  for (const auto s : make_range(n_sides))
68  {
69  boundary_info.boundary_ids(elem, s, old_ids);
70  if (std::find(old_ids.begin(), old_ids.end(), old_id) != old_ids.end())
71  {
72  std::vector<boundary_id_type> new_ids(old_ids);
73  std::replace(new_ids.begin(), new_ids.end(), old_id, new_id);
74  if (delete_prev)
75  {
76  boundary_info.remove_side(elem, s);
77  boundary_info.add_side(elem, s, new_ids);
78  }
79  else
80  boundary_info.add_side(elem, s, new_ids);
81  }
82  }
83  }
84 
85  // Remove any remaining references to the old ID from the
86  // BoundaryInfo object. This prevents things like empty sidesets
87  // from showing up when printing information, etc.
88  if (delete_prev)
89  boundary_info.remove_id(old_id);
90 
91  // global information may now be out of sync
93 }
94 
95 std::vector<boundary_id_type>
96 getBoundaryIDs(const MeshBase & mesh,
97  const std::vector<BoundaryName> & boundary_name,
98  bool generate_unknown)
99 {
100  return getBoundaryIDs(
101  mesh, boundary_name, generate_unknown, mesh.get_boundary_info().get_boundary_ids());
102 }
103 
104 std::vector<boundary_id_type>
106  const std::vector<BoundaryName> & boundary_name,
107  bool generate_unknown,
108  const std::set<BoundaryID> & mesh_boundary_ids)
109 {
110  const BoundaryInfo & boundary_info = mesh.get_boundary_info();
111  const std::map<BoundaryID, std::string> & sideset_map = boundary_info.get_sideset_name_map();
112  const std::map<BoundaryID, std::string> & nodeset_map = boundary_info.get_nodeset_name_map();
113 
114  BoundaryID max_boundary_local_id = 0;
115  /* It is required to generate a new ID for a given name. It is used often in mesh modifiers such
116  * as SideSetsBetweenSubdomains. Then we need to check the current boundary ids since they are
117  * changing during "mesh modify()", and figure out the right max boundary ID. Most of mesh
118  * modifiers are running in serial, and we won't involve a global communication.
119  */
120  if (generate_unknown)
121  {
124  max_boundary_local_id = bids.empty() ? 0 : *(bids.rbegin());
125  /* We should not hit this often */
126  if (!mesh.is_prepared() && !mesh.is_serial())
127  mesh.comm().max(max_boundary_local_id);
128  }
129 
130  BoundaryID max_boundary_id = mesh_boundary_ids.empty() ? 0 : *(mesh_boundary_ids.rbegin());
131 
132  max_boundary_id =
133  max_boundary_id > max_boundary_local_id ? max_boundary_id : max_boundary_local_id;
134 
135  std::vector<BoundaryID> ids(boundary_name.size());
136  for (const auto i : index_range(boundary_name))
137  {
138  if (boundary_name[i] == "ANY_BOUNDARY_ID")
139  {
140  ids.assign(mesh_boundary_ids.begin(), mesh_boundary_ids.end());
141  if (i)
142  mooseWarning("You passed \"ANY_BOUNDARY_ID\" in addition to other boundary_names. This "
143  "may be a logic error.");
144  break;
145  }
146 
147  if (boundary_name[i].empty() && !generate_unknown)
148  mooseError("Incoming boundary name is empty and we are not generating unknown boundary IDs. "
149  "This is invalid.");
150 
151  BoundaryID id;
152 
153  if (boundary_name[i].empty() || !MooseUtils::isDigits(boundary_name[i]))
154  {
160  if (generate_unknown &&
161  !MooseUtils::doesMapContainValue(sideset_map, std::string(boundary_name[i])) &&
162  !MooseUtils::doesMapContainValue(nodeset_map, std::string(boundary_name[i])))
163  id = ++max_boundary_id;
164  else
165  id = boundary_info.get_id_by_name(boundary_name[i]);
166  }
167  else
168  id = getIDFromName<BoundaryName, BoundaryID>(boundary_name[i]);
169 
170  ids[i] = id;
171  }
172 
173  return ids;
174 }
175 
176 std::set<BoundaryID>
178  const std::vector<BoundaryName> & boundary_name,
179  bool generate_unknown)
180 {
181  auto boundaries = getBoundaryIDs(mesh, boundary_name, generate_unknown);
182  return std::set<BoundaryID>(boundaries.begin(), boundaries.end());
183 }
184 
185 std::vector<subdomain_id_type>
186 getSubdomainIDs(const MeshBase & mesh, const std::vector<SubdomainName> & subdomain_names)
187 {
188  std::vector<SubdomainID> ids(subdomain_names.size());
189 
190  for (const auto i : index_range(subdomain_names))
191  ids[i] = MooseMeshUtils::getSubdomainID(subdomain_names[i], mesh);
192 
193  return ids;
194 }
195 
196 std::set<subdomain_id_type>
197 getSubdomainIDs(const MeshBase & mesh, const std::set<SubdomainName> & subdomain_names)
198 {
199  std::set<SubdomainID> ids;
200  for (const auto & name : subdomain_names)
202  return ids;
203 }
204 
206 getBoundaryID(const BoundaryName & boundary_name, const MeshBase & mesh)
207 {
209  if (boundary_name.empty())
210  return id;
211 
212  if (!MooseUtils::isDigits(boundary_name))
213  id = mesh.get_boundary_info().get_id_by_name(boundary_name);
214  else
215  id = getIDFromName<BoundaryName, BoundaryID>(boundary_name);
216 
217  return id;
218 }
219 
221 getSubdomainID(const SubdomainName & subdomain_name, const MeshBase & mesh)
222 {
223  if (subdomain_name == "ANY_BLOCK_ID")
224  mooseError("getSubdomainID() does not work with \"ANY_BLOCK_ID\"");
225 
227  if (subdomain_name.empty())
228  return id;
229 
230  if (!MooseUtils::isDigits(subdomain_name))
231  id = mesh.get_id_by_name(subdomain_name);
232  else
233  id = getIDFromName<SubdomainName, SubdomainID>(subdomain_name);
234 
235  return id;
236 }
237 
238 void
240 {
241  for (const auto & elem : mesh.element_ptr_range())
242  if (elem->subdomain_id() == old_id)
243  elem->subdomain_id() = new_id;
244 
245  // global cached information may now be out of sync
247 }
248 
249 Point
251 {
252  Point centroid_pt = Point(0.0, 0.0, 0.0);
253  Real vol_tmp = 0.0;
254  for (const auto & elem :
255  as_range(mesh.active_local_elements_begin(), mesh.active_local_elements_end()))
256  {
257  Real elem_vol = elem->volume();
258  centroid_pt += (elem->true_centroid()) * elem_vol;
259  vol_tmp += elem_vol;
260  }
261  mesh.comm().sum(centroid_pt);
262  mesh.comm().sum(vol_tmp);
263  centroid_pt /= vol_tmp;
264  return centroid_pt;
265 }
266 
267 std::unordered_map<dof_id_type, dof_id_type>
269  const std::set<SubdomainID> & block_ids,
270  std::vector<ExtraElementIDName> extra_ids)
271 {
272  // check block restriction
273  const bool block_restricted = !block_ids.empty();
274  // get element id name of interest in recursive parsing algorithm
275  ExtraElementIDName id_name = extra_ids.back();
276  extra_ids.pop_back();
277  const auto id_index = mesh.get_elem_integer_index(id_name);
278 
279  // create base parsed id set
280  if (extra_ids.empty())
281  {
282  // get set of extra id values;
283  std::vector<dof_id_type> ids;
284  {
285  std::set<dof_id_type> ids_set;
286  for (const auto & elem : mesh.active_element_ptr_range())
287  {
288  if (block_restricted && block_ids.find(elem->subdomain_id()) == block_ids.end())
289  continue;
290  const auto id = elem->get_extra_integer(id_index);
291  ids_set.insert(id);
292  }
293  mesh.comm().set_union(ids_set);
294  ids.assign(ids_set.begin(), ids_set.end());
295  }
296 
297  // determine new extra id values;
298  std::unordered_map<dof_id_type, dof_id_type> parsed_ids;
299  for (auto & elem : mesh.active_element_ptr_range())
300  {
301  if (block_restricted && block_ids.find(elem->subdomain_id()) == block_ids.end())
302  continue;
303  parsed_ids[elem->id()] = std::distance(
304  ids.begin(), std::lower_bound(ids.begin(), ids.end(), elem->get_extra_integer(id_index)));
305  }
306  return parsed_ids;
307  }
308 
309  // if extra_ids is not empty, recursively call getExtraIDUniqueCombinationMap
310  const auto base_parsed_ids =
312  // parsing extra ids based on ref_parsed_ids
313  std::vector<std::pair<dof_id_type, dof_id_type>> unique_ids;
314  {
315  std::set<std::pair<dof_id_type, dof_id_type>> unique_ids_set;
316  for (const auto & elem : mesh.active_element_ptr_range())
317  {
318  if (block_restricted && block_ids.find(elem->subdomain_id()) == block_ids.end())
319  continue;
320  const dof_id_type id1 = libmesh_map_find(base_parsed_ids, elem->id());
321  const dof_id_type id2 = elem->get_extra_integer(id_index);
322  const std::pair<dof_id_type, dof_id_type> ids = std::make_pair(id1, id2);
323  unique_ids_set.insert(ids);
324  }
325  mesh.comm().set_union(unique_ids_set);
326  unique_ids.assign(unique_ids_set.begin(), unique_ids_set.end());
327  }
328 
329  std::unordered_map<dof_id_type, dof_id_type> parsed_ids;
330 
331  for (const auto & elem : mesh.active_element_ptr_range())
332  {
333  if (block_restricted && block_ids.find(elem->subdomain_id()) == block_ids.end())
334  continue;
335  const dof_id_type id1 = libmesh_map_find(base_parsed_ids, elem->id());
336  const dof_id_type id2 = elem->get_extra_integer(id_index);
337  const dof_id_type new_id = std::distance(
338  unique_ids.begin(),
339  std::lower_bound(unique_ids.begin(), unique_ids.end(), std::make_pair(id1, id2)));
340  parsed_ids[elem->id()] = new_id;
341  }
342 
343  return parsed_ids;
344 }
345 
346 bool
347 isCoPlanar(const std::vector<Point> vec_pts, const Point plane_nvec, const Point fixed_pt)
348 {
349  for (const auto & pt : vec_pts)
350  if (!MooseUtils::absoluteFuzzyEqual((pt - fixed_pt) * plane_nvec, 0.0))
351  return false;
352  return true;
353 }
354 
355 bool
356 isCoPlanar(const std::vector<Point> vec_pts, const Point plane_nvec)
357 {
358  return isCoPlanar(vec_pts, plane_nvec, vec_pts.front());
359 }
360 
361 bool
362 isCoPlanar(const std::vector<Point> vec_pts)
363 {
364  // Assuming that overlapped Points are allowed, the Points that are overlapped with vec_pts[0] are
365  // removed before further calculation.
366  std::vector<Point> vec_pts_nonzero{vec_pts[0]};
367  for (const auto i : index_range(vec_pts))
368  if (!MooseUtils::absoluteFuzzyEqual((vec_pts[i] - vec_pts[0]).norm(), 0.0))
369  vec_pts_nonzero.push_back(vec_pts[i]);
370  // 3 or fewer points are always coplanar
371  if (vec_pts_nonzero.size() <= 3)
372  return true;
373  else
374  {
375  for (const auto i : make_range(vec_pts_nonzero.size() - 1))
376  {
377  const Point tmp_pt = (vec_pts_nonzero[i] - vec_pts_nonzero[0])
378  .cross(vec_pts_nonzero[i + 1] - vec_pts_nonzero[0]);
379  // if the three points are not collinear, use cross product as the normal vector of the plane
380  if (!MooseUtils::absoluteFuzzyEqual(tmp_pt.norm(), 0.0))
381  return isCoPlanar(vec_pts_nonzero, tmp_pt.unit());
382  }
383  }
384  // If all the points are collinear, they are also coplanar
385  return true;
386 }
387 
390 {
391  // Call this to get most up to date block id information
392  input_mesh.cache_elem_data();
393 
394  std::set<SubdomainID> preexisting_subdomain_ids;
395  input_mesh.subdomain_ids(preexisting_subdomain_ids);
396  if (preexisting_subdomain_ids.empty())
397  return 0;
398  else
399  {
400  const auto highest_subdomain_id =
401  *std::max_element(preexisting_subdomain_ids.begin(), preexisting_subdomain_ids.end());
402  mooseAssert(highest_subdomain_id < std::numeric_limits<SubdomainID>::max(),
403  "A SubdomainID with max possible value was found");
404  return highest_subdomain_id + 1;
405  }
406 }
407 
410 {
411  auto boundary_ids = input_mesh.get_boundary_info().get_boundary_ids();
412  if (boundary_ids.empty())
413  return 0;
414  return (*boundary_ids.rbegin() + 1);
415 }
416 
417 bool
418 hasSubdomainID(const MeshBase & input_mesh, const SubdomainID & id)
419 {
420  std::set<SubdomainID> mesh_blocks;
421  input_mesh.subdomain_ids(mesh_blocks);
422 
423  // On a distributed mesh we may have sideset IDs that only exist on
424  // other processors
425  if (!input_mesh.is_replicated())
426  input_mesh.comm().set_union(mesh_blocks);
427 
428  return mesh_blocks.count(id) && (id != Moose::INVALID_BLOCK_ID);
429 }
430 
431 bool
432 hasSubdomainName(const MeshBase & input_mesh, const SubdomainName & name)
433 {
434  const auto id = getSubdomainID(name, input_mesh);
435  return hasSubdomainID(input_mesh, id);
436 }
437 
438 bool
439 hasBoundaryID(const MeshBase & input_mesh, const BoundaryID id)
440 {
441  const BoundaryInfo & boundary_info = input_mesh.get_boundary_info();
442  std::set<boundary_id_type> boundary_ids = boundary_info.get_boundary_ids();
443 
444  // On a distributed mesh we may have boundary IDs that only exist on
445  // other processors
446  if (!input_mesh.is_replicated())
447  input_mesh.comm().set_union(boundary_ids);
448 
449  return boundary_ids.count(id) && (id != Moose::INVALID_BOUNDARY_ID);
450 }
451 
452 bool
453 hasBoundaryName(const MeshBase & input_mesh, const BoundaryName & name)
454 {
455  const auto id = getBoundaryID(name, input_mesh);
456  return hasBoundaryID(input_mesh, id);
457 }
458 
459 void
460 makeOrderedNodeList(std::vector<std::pair<dof_id_type, dof_id_type>> & node_assm,
461  std::vector<dof_id_type> & elem_id_list,
462  std::vector<dof_id_type> & midpoint_node_list,
463  std::vector<dof_id_type> & ordered_node_list,
464  std::vector<dof_id_type> & ordered_elem_id_list)
465 {
466  // a flag to indicate if the ordered_node_list has been reversed
467  bool is_flipped = false;
468  // Start from the first element, try to find a chain of nodes
469  mooseAssert(node_assm.size(), "Node list must not be empty");
470  ordered_node_list.push_back(node_assm.front().first);
471  if (midpoint_node_list.front() != DofObject::invalid_id)
472  ordered_node_list.push_back(midpoint_node_list.front());
473  ordered_node_list.push_back(node_assm.front().second);
474  ordered_elem_id_list.push_back(elem_id_list.front());
475  // Remove the element that has just been added to ordered_node_list
476  node_assm.erase(node_assm.begin());
477  midpoint_node_list.erase(midpoint_node_list.begin());
478  elem_id_list.erase(elem_id_list.begin());
479  const unsigned int node_assm_size_0 = node_assm.size();
480  for (unsigned int i = 0; i < node_assm_size_0; i++)
481  {
482  // Find nodes to expand the chain
483  dof_id_type end_node_id = ordered_node_list.back();
484  auto isMatch1 = [end_node_id](std::pair<dof_id_type, dof_id_type> old_id_pair)
485  { return old_id_pair.first == end_node_id; };
486  auto isMatch2 = [end_node_id](std::pair<dof_id_type, dof_id_type> old_id_pair)
487  { return old_id_pair.second == end_node_id; };
488  auto result = std::find_if(node_assm.begin(), node_assm.end(), isMatch1);
489  bool match_first;
490  if (result == node_assm.end())
491  {
492  match_first = false;
493  result = std::find_if(node_assm.begin(), node_assm.end(), isMatch2);
494  }
495  else
496  {
497  match_first = true;
498  }
499  // If found, add the node to boundary_ordered_node_list
500  if (result != node_assm.end())
501  {
502  const auto elem_index = std::distance(node_assm.begin(), result);
503  if (midpoint_node_list[elem_index] != DofObject::invalid_id)
504  ordered_node_list.push_back(midpoint_node_list[elem_index]);
505  ordered_node_list.push_back(match_first ? (*result).second : (*result).first);
506  node_assm.erase(result);
507  midpoint_node_list.erase(midpoint_node_list.begin() + elem_index);
508  ordered_elem_id_list.push_back(elem_id_list[elem_index]);
509  elem_id_list.erase(elem_id_list.begin() + elem_index);
510  }
511  // If there are still elements in node_assm and result ==
512  // node_assm.end(), this means the curve is not a loop, the
513  // ordered_node_list is flipped and try the other direction that has not
514  // been examined yet.
515  else
516  {
517  if (is_flipped)
518  // Flipped twice; this means the node list has at least two segments.
519  throw MooseException("The node list provided has more than one segments.");
520 
521  // mark the first flip event.
522  is_flipped = true;
523  std::reverse(ordered_node_list.begin(), ordered_node_list.end());
524  std::reverse(midpoint_node_list.begin(), midpoint_node_list.end());
525  std::reverse(ordered_elem_id_list.begin(), ordered_elem_id_list.end());
526  // As this iteration is wasted, set the iterator backward
527  i--;
528  }
529  }
530 }
531 
532 void
533 makeOrderedNodeList(std::vector<std::pair<dof_id_type, dof_id_type>> & node_assm,
534  std::vector<dof_id_type> & elem_id_list,
535  std::vector<dof_id_type> & ordered_node_list,
536  std::vector<dof_id_type> & ordered_elem_id_list)
537 {
538  std::vector<dof_id_type> dummy_midpoint_node_list(node_assm.size(), DofObject::invalid_id);
540  node_assm, elem_id_list, dummy_midpoint_node_list, ordered_node_list, ordered_elem_id_list);
541 }
542 
543 void
544 swapNodesInElem(Elem & elem, const unsigned int nd1, const unsigned int nd2)
545 {
546  Node * n_temp = elem.node_ptr(nd1);
547  elem.set_node(nd1, elem.node_ptr(nd2));
548  elem.set_node(nd2, n_temp);
549 }
550 
551 void
553  const std::string & class_name,
554  const unsigned int num_sections,
555  const unsigned int num_integers,
556  const std::vector<std::vector<std::vector<dof_id_type>>> & elem_integers_swaps,
557  std::vector<std::unordered_map<dof_id_type, dof_id_type>> & elem_integers_swap_pairs)
558 {
559  elem_integers_swap_pairs.reserve(num_sections * num_integers);
560  for (const auto i : make_range(num_integers))
561  {
562  const auto & elem_integer_swaps = elem_integers_swaps[i];
563  std::vector<std::unordered_map<dof_id_type, dof_id_type>> elem_integer_swap_pairs;
564  try
565  {
567  "elem_integers_swaps",
568  elem_integer_swaps,
569  elem_integer_swap_pairs,
570  i * num_sections);
571  }
572  catch (const MooseException & e)
573  {
574  throw MooseException(e.what());
575  }
576 
577  elem_integers_swap_pairs.insert(elem_integers_swap_pairs.end(),
578  elem_integer_swap_pairs.begin(),
579  elem_integer_swap_pairs.end());
580  }
581 }
582 
583 std::unique_ptr<ReplicatedMesh>
584 buildBoundaryMesh(const ReplicatedMesh & input_mesh, const boundary_id_type boundary_id)
585 {
586  auto poly_mesh = std::make_unique<ReplicatedMesh>(input_mesh.comm());
587 
588  auto side_list = input_mesh.get_boundary_info().build_side_list();
589 
590  std::unordered_map<dof_id_type, dof_id_type> old_new_node_map;
591  for (const auto & bside : side_list)
592  {
593  if (std::get<2>(bside) != boundary_id)
594  continue;
595 
596  const Elem * elem = input_mesh.elem_ptr(std::get<0>(bside));
597  const auto side = std::get<1>(bside);
598  auto side_elem = elem->build_side_ptr(side);
599  auto copy = side_elem->build(side_elem->type());
600 
601  for (const auto i : side_elem->node_index_range())
602  {
603  auto & n = side_elem->node_ref(i);
604 
605  if (old_new_node_map.count(n.id()))
606  copy->set_node(i, poly_mesh->node_ptr(old_new_node_map[n.id()]));
607  else
608  {
609  Node * node = poly_mesh->add_point(side_elem->point(i));
610  copy->set_node(i, node);
611  old_new_node_map[n.id()] = node->id();
612  }
613  }
614  poly_mesh->add_elem(copy.release());
615  }
616  poly_mesh->skip_partitioning(true);
617  poly_mesh->prepare_for_use();
618  if (poly_mesh->n_elem() == 0)
619  mooseError("The input mesh does not have a boundary with id ", boundary_id);
620 
621  return poly_mesh;
622 }
623 }
void swapNodesInElem(Elem &elem, const unsigned int nd1, const unsigned int nd2)
std::string name(const ElemQuality q)
void remove_id(boundary_id_type id, bool global=false)
bool is_prepared() const
void makeOrderedNodeList(std::vector< std::pair< dof_id_type, dof_id_type >> &node_assm, std::vector< dof_id_type > &elem_id_list, std::vector< dof_id_type > &midpoint_node_list, std::vector< dof_id_type > &ordered_node_list, std::vector< dof_id_type > &ordered_elem_id_list)
Convert a list of sides in the form of a vector of pairs of node ids into a list of ordered nodes bas...
std::unordered_map< dof_id_type, dof_id_type > getExtraIDUniqueCombinationMap(const MeshBase &mesh, const std::set< SubdomainID > &block_ids, std::vector< ExtraElementIDName > extra_ids)
virtual Node *& set_node(const unsigned int i)
std::set< BoundaryID > getBoundaryIDSet(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown)
Gets the boundary IDs into a set with their names.
virtual const char * what() const
Get out the error message.
std::unique_ptr< ReplicatedMesh > buildBoundaryMesh(const ReplicatedMesh &input_mesh, const boundary_id_type boundary_id)
auto norm() const -> decltype(std::norm(Real()))
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
Definition: MooseUtils.h:380
bool hasBoundaryName(const MeshBase &input_mesh, const BoundaryName &name)
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
const BoundaryID INVALID_BOUNDARY_ID
Definition: MooseTypes.C:22
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition: MooseError.h:336
bool doesMapContainValue(const std::map< T1, T2 > &the_map, const T2 &value)
This routine is a simple helper function for searching a map by values instead of keys...
Definition: MooseUtils.h:356
void set_isnt_prepared()
const std::map< boundary_id_type, std::string > & get_sideset_name_map() const
MeshBase & mesh
const Parallel::Communicator & comm() const
bool hasBoundaryID(const MeshBase &input_mesh, const BoundaryID id)
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
std::vector< subdomain_id_type > getSubdomainIDs(const libMesh::MeshBase &mesh, const std::vector< SubdomainName > &subdomain_name)
Get the associated subdomainIDs for the subdomain names that are passed in.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
const BoundaryInfo & get_boundary_info() const
void renumber_id(boundary_id_type old_id, boundary_id_type new_id)
SubdomainID getSubdomainID(const SubdomainName &subdomain_name, const MeshBase &mesh)
Gets the subdomain ID associated with the given SubdomainName.
auto max(const L &left, const R &right)
subdomain_id_type get_id_by_name(std::string_view name) const
void build_side_list(std::vector< dof_id_type > &element_id_list, std::vector< unsigned short int > &side_list, std::vector< boundary_id_type > &bc_id_list) const
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)
const SubdomainID INVALID_BLOCK_ID
Definition: MooseTypes.C:20
boundary_id_type get_id_by_name(std::string_view name) const
BoundaryID getBoundaryID(const BoundaryName &boundary_name, const MeshBase &mesh)
virtual const Elem * elem_ptr(const dof_id_type i) const override final
unsigned int get_elem_integer_index(std::string_view name) const
virtual bool is_serial() const
TypeVector< Real > unit() const
const std::map< boundary_id_type, std::string > & get_nodeset_name_map() const
int8_t boundary_id_type
dof_id_type id() const
boundary_id_type BoundaryID
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
void subdomain_ids(std::set< subdomain_id_type > &ids, const bool global=true) const
static const dof_id_type invalid_id
void idSwapParametersProcessor(const std::string &class_name, const std::string &id_name, const std::vector< std::vector< T >> &id_swaps, std::vector< std::unordered_map< T, T >> &id_swap_pairs, const unsigned int row_index_shift=0)
Reprocess the swap related input parameters to make pairs out of them to ease further processing...
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.
void changeBoundaryId(MeshBase &mesh, const boundary_id_type old_id, const boundary_id_type new_id, bool delete_prev)
auto norm(const T &a) -> decltype(std::abs(a))
bool hasSubdomainName(const MeshBase &input_mesh, const SubdomainName &name)
bool isCoPlanar(const std::vector< Point > vec_pts)
const std::set< boundary_id_type > & get_boundary_ids() const
void changeSubdomainId(MeshBase &mesh, const subdomain_id_type old_id, const subdomain_id_type new_id)
void remove_side(const Elem *elem, const unsigned short int side)
Provides a way for users to bail out of the current solve.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void max(const T &r, T &o, Request &req) const
const Node * node_ptr(const unsigned int i) const
virtual bool is_replicated() const
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
const std::set< boundary_id_type > & get_global_boundary_ids() const
IntRange< T > make_range(T beg, T end)
void extraElemIntegerSwapParametersProcessor(const std::string &class_name, const unsigned int num_sections, const unsigned int num_integers, const std::vector< std::vector< std::vector< dof_id_type >>> &elem_integers_swaps, std::vector< std::unordered_map< dof_id_type, dof_id_type >> &elem_integers_swap_pairs)
Reprocess the elem_integers_swaps into maps so they are easier to use.
Point meshCentroidCalculator(const MeshBase &mesh)
void mergeBoundaryIDsWithSameName(MeshBase &mesh)
SubdomainID getNextFreeSubdomainID(MeshBase &input_mesh)
bool isDigits(const std::string &str)
Courtesy https://stackoverflow.com/a/8889045 and https://en.cppreference.com/w/cpp/string/byte/isdigi...
Definition: MooseUtils.h:1208
BoundaryID getNextFreeBoundaryID(MeshBase &input_mesh)
auto index_range(const T &sizable)
uint8_t dof_id_type
void set_union(T &data, const unsigned int root_id) const