www.mooseframework.org
LowerDBlockFromSideset.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 
10 #include "LowerDBlockFromSideset.h"
11 #include "InputParameters.h"
12 #include "MooseTypes.h"
13 #include "MooseMesh.h"
14 
15 #include "libmesh/distributed_mesh.h"
16 #include "libmesh/elem.h"
17 
18 #include <set>
19 
21 
22 template <>
25 {
27  params.addRequiredParam<SubdomainID>("new_block_id", "The lower dimensional block id to create");
28  params.addParam<SubdomainName>("new_block_name",
29  "The lower dimensional block name to create (optional)");
30  params.addRequiredParam<std::vector<BoundaryID>>(
31  "sidesets", "The sidesets from which to create the new block");
32 
33  params.addClassDescription("Adds lower dimensional elements on the specified sidesets.");
34  return params;
35 }
36 
38  : MeshModifier(parameters),
39  _new_block_id(getParam<SubdomainID>("new_block_id")),
40  _sidesets(getParam<std::vector<BoundaryID>>("sidesets"))
41 {
42 }
43 
44 // Used to temporarily store information about which lower-dimensional
45 // sides to add and what subdomain id to use for the added sides.
46 struct ElemSideDouble
47 {
48  ElemSideDouble(Elem * elem_in, unsigned short int side_in) : elem(elem_in), side(side_in) {}
49 
50  Elem * elem;
51  unsigned short int side;
52 };
53 
54 void
56 {
57  MeshBase & mesh = _mesh_ptr->getMesh();
58  bool distributed = dynamic_cast<DistributedMesh *>(&mesh);
59  if (distributed)
61 
62  auto side_list = mesh.get_boundary_info().build_side_list();
63  std::sort(side_list.begin(),
64  side_list.end(),
65  [](std::tuple<dof_id_type, unsigned short int, boundary_id_type> a,
66  std::tuple<dof_id_type, unsigned short int, boundary_id_type> b) {
67  auto a_elem_id = std::get<0>(a);
68  auto b_elem_id = std::get<0>(b);
69  if (a_elem_id == b_elem_id)
70  {
71  auto a_side_id = std::get<1>(a);
72  auto b_side_id = std::get<1>(b);
73  if (a_side_id == b_side_id)
74  return std::get<2>(a) < std::get<2>(b);
75  else
76  return a_side_id < b_side_id;
77  }
78  else
79  return a_elem_id < b_elem_id;
80  });
81 
82  std::set<BoundaryID> sidesets(_sidesets.begin(), _sidesets.end());
83  std::vector<ElemSideDouble> element_sides_on_boundary;
84  for (const auto & triple : side_list)
85  if (sidesets.count(std::get<2>(triple)))
86  element_sides_on_boundary.push_back(
87  ElemSideDouble(mesh.elem_ptr(std::get<0>(triple)), std::get<1>(triple)));
88 
89  dof_id_type max_elem_id = mesh.max_elem_id();
90  mesh.comm().max(max_elem_id);
91  auto max_elems_to_add = element_sides_on_boundary.size();
92  mesh.comm().max(max_elems_to_add);
93 
94  for (MooseIndex(element_sides_on_boundary) i = 0; i < element_sides_on_boundary.size(); ++i)
95  {
96  Elem * elem = element_sides_on_boundary[i].elem;
97  if (distributed && elem->processor_id() != processor_id())
98  continue;
99 
100  unsigned int side = element_sides_on_boundary[i].side;
101 
102  // Build a non-proxy element from this side.
103  std::unique_ptr<Elem> side_elem(elem->build_side_ptr(side, /*proxy=*/false));
104 
105  // The side will be added with the same processor id as the parent.
106  side_elem->processor_id() = elem->processor_id();
107 
108  // Add subdomain ID
109  side_elem->subdomain_id() = _new_block_id;
110 
111  // Also assign the side's interior parent, so it is always
112  // easy to figure out the Elem we came from.
113  side_elem->set_interior_parent(elem);
114 
115  // Add id for distributed
116  if (distributed)
117  side_elem->set_id(max_elem_id + processor_id() * max_elems_to_add + i);
118 
119  // Finally, add the lower-dimensional element to the Mesh.
120  mesh.add_elem(side_elem.release());
121  };
122 
123  // Assign block name, if provided
124  if (isParamValid("new_block_name"))
125  mesh.subdomain_name(_new_block_id) = getParam<SubdomainName>("new_block_name");
126 }
InputParameters validParams< LowerDBlockFromSideset >()
void needsPrepareForUse()
If this method is called, we will call libMesh&#39;s prepare_for_use method when we call Moose&#39;s prepare ...
Definition: MooseMesh.C:2310
const SubdomainID _new_block_id
The subdomain ID of the new lower dimensional block.
MeshModifiers are objects that can modify or add to an existing mesh.
Definition: MeshModifier.h:25
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::vector< BoundaryID > _sidesets
The sidesets on which to create the lower dimensional elements.
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...
MooseMesh * _mesh_ptr
Pointer to the mesh.
Definition: MeshModifier.h:68
Creates lower-dimensional elements on the specified sidesets.
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:2567
boundary_id_type BoundaryID
subdomain_id_type SubdomainID
ElemSideDouble(Elem *elem_in, unsigned short int side_in)
virtual void modify() override
Pure virtual modify function MUST be overridden by children classes.
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 option parameter and a documentation string to the InputParameters object...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseObject.h:89
registerMooseObject("MooseApp", LowerDBlockFromSideset)
InputParameters validParams< MeshModifier >()
Definition: MeshModifier.C:15
LowerDBlockFromSideset(const InputParameters &parameters)