14 #include "libmesh/partitioner.h" 26 params.
addClassDescription(
"Break all element-element interfaces in the specified subdomains.");
27 params.
addRequiredParam<MeshGeneratorName>(
"input",
"The mesh we want to modify");
28 params.
addParam<std::vector<SubdomainID>>(
"subdomains",
"The list of subdomain IDs to explode.");
30 "interface_name",
"The boundary name containing all broken element-element interfaces.");
36 _input(getMesh(
"input")),
38 _interface_name(getParam<BoundaryName>(
"interface_name"))
42 std::unique_ptr<MeshBase>
45 std::unique_ptr<MeshBase>
mesh = std::move(
_input);
50 paramError(
"subdomains",
"The block ID '",
id,
"' was not found in the mesh");
52 BoundaryInfo & boundary_info =
mesh->get_boundary_info();
54 paramError(
"interface_name",
"The specified interface name already exits in the mesh.");
62 Partitioner::set_node_processor_ids(*
mesh);
69 std::unique_ptr<MeshBase> & mesh,
const std::vector<SubdomainID> & subdomains)
const 72 for (
const auto & elem :
mesh->active_element_ptr_range())
75 if (std::find(subdomains.begin(), subdomains.end(), elem->subdomain_id()) == subdomains.end())
78 std::set<const Elem *> neighbors;
79 elem->find_point_neighbors(neighbors);
85 bool should_duplicate =
true;
86 for (
auto neighbor : neighbors)
87 if (neighbor->contains_point(elem->node_ref(n)) &&
88 std::find(subdomains.begin(), subdomains.end(), neighbor->subdomain_id()) ==
91 should_duplicate =
false;
96 node_to_elem_map[elem->node_id(n)].insert(elem->id());
100 return node_to_elem_map;
107 for (
const auto & [node_id, connected_elem_ids] : node_to_elem_map)
108 for (
auto & connected_elem_id : connected_elem_ids)
109 if (connected_elem_id != *connected_elem_ids.begin())
116 const Node * node)
const 118 std::unique_ptr<Node> new_node = Node::build(*node, Node::invalid_id);
119 new_node->processor_id() = elem->processor_id();
120 Node * added_node =
mesh->add_node(std::move(new_node));
121 for (
const auto j : elem->node_index_range())
122 if (elem->node_id(j) == node->id())
124 elem->set_node(j, added_node);
129 BoundaryInfo & boundary_info =
mesh->get_boundary_info();
130 std::vector<boundary_id_type> node_boundary_ids;
131 boundary_info.boundary_ids(node, node_boundary_ids);
132 boundary_info.add_node(added_node, node_boundary_ids);
139 BoundaryInfo & boundary_info =
mesh.get_boundary_info();
140 const auto & existing_boundary_ids = boundary_info.get_boundary_ids();
142 existing_boundary_ids.empty() ? 0 : *existing_boundary_ids.rbegin() + 1;
145 std::set<std::pair<dof_id_type, unsigned int>> sides_to_add;
147 for (
const auto & node_to_elems : node_to_elem_map)
148 for (
const auto & elem_id_i : node_to_elems.second)
150 Elem * elem_i =
mesh.elem_ptr(elem_id_i);
151 for (
const auto & elem_id_j : node_to_elems.second)
153 Elem * elem_j =
mesh.elem_ptr(elem_id_j);
154 if (elem_i != elem_j && elem_id_i < elem_id_j && elem_i->has_neighbor(elem_j))
155 sides_to_add.insert(std::make_pair(elem_id_i, elem_i->which_neighbor_am_i(elem_j)));
159 for (
const auto & [elem_id, side] : sides_to_add)
160 boundary_info.add_side(elem_id, side, interface_id);
std::map< const dof_id_type, std::set< dof_id_type > > NodeToElemMapType
NodeToElemMapType buildSubdomainRestrictedNodeToElemMap(std::unique_ptr< MeshBase > &mesh, const std::vector< SubdomainID > &subdomains) const
const BoundaryID INVALID_BOUNDARY_ID
static InputParameters validParams()
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.
registerMooseObject("MooseApp", BreakMeshByElementGenerator)
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)
Whether a particular subdomain ID exists in the mesh.
std::unique_ptr< MeshBase > & _input
The mesh to modify.
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
static InputParameters validParams()
registerMooseObjectRenamed("MooseApp", ExplodeMeshGenerator, "05/18/2024 24:00", BreakMeshByElementGenerator)
void duplicateNode(std::unique_ptr< MeshBase > &mesh, Elem *elem, const Node *node) const
const BoundaryName _interface_name
IntRange< T > make_range(T beg, T end)
void duplicateNodes(std::unique_ptr< MeshBase > &mesh, const NodeToElemMapType &node_to_elem_map) const
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
BreakMeshByElementGenerator(const InputParameters ¶meters)
const std::vector< SubdomainID > & _subdomains
MeshGenerators are objects that can modify or add to an existing mesh.
void createInterface(MeshBase &mesh, const NodeToElemMapType &node_to_elem_map) const