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>>(
30 std::vector<SubdomainID>(),
31 "The list of subdomain IDs to explode. Leave unset to explode all subdomains.");
35 "The boundary name containing all broken element-element interfaces.");
40 "Whether to add no interface boundary, a 1-sided boundary (facing from lower to higher " 41 "element id), or a 2-sided boundary");
47 _input(getMesh(
"input")),
49 _interface_name(getParam<BoundaryName>(
"interface_name")),
50 _interface_sides(getParam<unsigned
int>(
"interface_sides"))
54 std::unique_ptr<MeshBase>
57 std::unique_ptr<MeshBase>
mesh = std::move(
_input);
59 if (!
mesh->is_prepared())
60 mesh->prepare_for_use();
65 paramError(
"subdomains",
"The block ID '",
id,
"' was not found in the mesh");
67 BoundaryInfo & boundary_info =
mesh->get_boundary_info();
70 paramError(
"interface_name",
"The specified interface name already exists in the mesh.");
78 Partitioner::set_node_processor_ids(*
mesh);
82 boundary_info.regenerate_id_sets();
89 std::unique_ptr<MeshBase> & mesh,
const std::vector<SubdomainID> & subdomains)
const 92 for (
const auto & elem :
mesh->active_element_ptr_range())
95 if (!subdomains.empty() &&
96 std::find(subdomains.begin(), subdomains.end(), elem->subdomain_id()) == subdomains.end())
99 std::set<const Elem *> neighbors;
100 elem->find_point_neighbors(neighbors);
106 bool should_duplicate =
true;
107 if (!subdomains.empty())
108 for (
auto neighbor : neighbors)
109 if (neighbor->contains_point(elem->node_ref(n)) &&
110 std::find(subdomains.begin(), subdomains.end(), neighbor->subdomain_id()) ==
113 should_duplicate =
false;
117 if (should_duplicate)
118 node_to_elem_map[elem->node_id(n)].insert(elem->id());
122 return node_to_elem_map;
129 for (
const auto & [node_id, connected_elem_ids] : node_to_elem_map)
130 for (
auto & connected_elem_id : connected_elem_ids)
131 if (connected_elem_id != *connected_elem_ids.begin())
138 const Node * node)
const 140 std::unique_ptr<Node> new_node = Node::build(*node, Node::invalid_id);
141 new_node->processor_id() = elem->processor_id();
142 Node * added_node =
mesh->add_node(std::move(new_node));
143 for (
const auto j : elem->node_index_range())
144 if (elem->node_id(j) == node->id())
146 elem->set_node(j, added_node);
151 BoundaryInfo & boundary_info =
mesh->get_boundary_info();
152 std::vector<boundary_id_type> node_boundary_ids;
153 boundary_info.boundary_ids(node, node_boundary_ids);
154 boundary_info.add_node(added_node, node_boundary_ids);
161 std::set<std::pair<dof_id_type, unsigned int>> sides_breaking;
163 for (
const auto & node_to_elems : node_to_elem_map)
164 for (
const auto & elem_id_i : node_to_elems.second)
166 Elem * elem_i =
mesh.elem_ptr(elem_id_i);
167 for (
const auto & elem_id_j : node_to_elems.second)
169 Elem * elem_j =
mesh.elem_ptr(elem_id_j);
170 if (elem_i != elem_j && elem_i->has_neighbor(elem_j))
171 sides_breaking.insert(std::make_pair(elem_id_i, elem_i->which_neighbor_am_i(elem_j)));
177 BoundaryInfo & boundary_info =
mesh.get_boundary_info();
179 const auto & existing_boundary_ids = boundary_info.get_boundary_ids();
181 existing_boundary_ids.empty() ? 0 : *existing_boundary_ids.rbegin() + 1;
184 for (
const auto & [elem_id, side] : sides_breaking)
186 boundary_info.add_side(elem_id, side, interface_id);
190 for (
const auto & [elem_id, side] : sides_breaking)
191 mesh.elem_ref(elem_id).set_neighbor(side,
nullptr);
std::map< const dof_id_type, std::set< dof_id_type > > NodeToElemMapType
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
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 ...
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.
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 unsigned int _interface_sides
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 ErrorVector unsigned int
void createInterface(MeshBase &mesh, const NodeToElemMapType &node_to_elem_map) const