MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
submesh_utils.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_SUBMESH_UTILS
13#define MFEM_SUBMESH_UTILS
14
15#include <type_traits>
16#include <unordered_map>
17#include "submesh.hpp"
18#include "../../fem/fespace.hpp"
19
20namespace mfem
21{
22class NCSubMesh;
23class ParNCSubMesh;
24
25namespace SubMeshUtils
26{
27
28/**
29 * @brief Convenience object to create unique indices.
30 */
32{
33 int counter = 0;
34 std::unordered_map<int, int> idx;
35
36 /**
37 * @brief Returns the unique index from an index set.
38 *
39 * @param i index
40 * @param new_index indicates if the index is new or was already present in
41 * the set.
42 */
43 int Get(int i, bool &new_index);
44};
45
46/**
47 * @brief Given a Mesh @a parent and another Mesh @a mesh using the list of
48 * attributes in @a attributes, this function adds matching elements with those
49 * attributes from @a parent to @a mesh.
50 *
51 * It also returns a tuple containing first the parent vertex ids (mapping from
52 * mesh vertex ids (index of the array), to the parent vertex ids) and second
53 * the parent element ids (mapping from submesh element ids (index of the
54 * array), to the parent element ids)
55 *
56 * @note Works with ParMesh.
57 *
58 * @param parent The Mesh where the elements are "extracted" from.
59 * @param mesh The Mesh where the elements are extracted to.
60 * @param attributes The attributes of the desired elements.
61 * @param from_boundary Indication if the desired elements come from the
62 * boundary of the parent.
63 */
64std::tuple< Array<int>, Array<int> >
65AddElementsToMesh(const Mesh& parent,
66 Mesh& mesh, const Array<int> &attributes,
67 bool from_boundary = false);
68
69/**
70 * @brief Given two meshes that have a parent to SubMesh relationship create a
71 * face map, using a SubMesh to parent Mesh element id map.
72 *
73 * @param parent The parent Mesh.
74 * @param mesh The Mesh to match its parents faces.
75 * @param parent_element_ids The Mesh element to parent element id map.
76 */
77Array<int> BuildFaceMap(const Mesh& parent, const Mesh& mesh,
78 const Array<int> &parent_element_ids);
79
80/**
81 * @brief Build the vdof to vdof mapping between two FiniteElementSpace objects.
82 *
83 * Given two FiniteElementSpace objects and the map parent_element_ids, which
84 * maps the element ids of the subfes to elements on the parentfes (or boundary
85 * elements depending on the type of transfer, volume or surface), create a vdof
86 * to vdof map.
87 *
88 * This map is entirely serial and has no knowledge about parallel groups.
89 *
90 * @param[in] subfes
91 * @param[in] parentfes
92 * @param[in] from
93 * @param[in] parent_element_ids
94 * @param[out] vdof_to_vdof_map
95 */
96void BuildVdofToVdofMap(const FiniteElementSpace& subfes,
97 const FiniteElementSpace& parentfes,
98 const SubMesh::From& from,
99 const Array<int>& parent_element_ids,
100 Array<int>& vdof_to_vdof_map);
101
102/**
103 * @brief Identify the root parent of a given SubMesh.
104 *
105 * @tparam T The type of the input object which has to fulfill the
106 * SubMesh::GetParent() interface.
107 */
108template <class T>
109auto GetRootParent(const T &m) -> decltype(std::declval<T>().GetParent())
110{
111 auto parent = m.GetParent();
112 while (true)
113 {
114 const T* next = dynamic_cast<const T*>(parent);
115 if (next == nullptr) { return parent; }
116 else { parent = next->GetParent(); }
117 }
118}
119
120/**
121 * @brief Add boundary elements to the SubMesh.
122 * @details An attempt to call this function for anything other than SubMesh or
123 * ParSubMesh will result in a linker error as the template is only explicitly
124 * instantiated for those types.
125 * @param mesh The SubMesh to add boundary elements to.
126 * @param lface_to_boundary_attribute Map from local faces in the submesh to
127 * boundary attributes. Only necessary for interior boundary attributes of
128 * volume submeshes, where the face owning the attribute might be on a
129 * neighboring rank.
130 * @tparam SubMeshT The SubMesh type, options SubMesh and ParSubMesh.
131 */
132template <typename SubMeshT>
133void AddBoundaryElements(SubMeshT &mesh,
134 const std::unordered_map<int,int> &lface_to_boundary_attribute = {});
135
136/**
137 * @brief Construct a nonconformal mesh (serial or parallel) for a surface
138 * submesh, from an existing nonconformal volume mesh (serial or parallel).
139 * @details This function is only instantiated for NCSubMesh and ParNCSubMesh
140 * Attempting to use it with other classes will result in a linker error.
141 * @tparam NCSubMeshT The NCSubMesh type
142 * @param[out] submesh The surface submesh to be filled.
143 * @param attributes The set of attributes defining the submesh.
144 */
145template<typename NCSubMeshT>
146void ConstructFaceTree(NCSubMeshT &submesh, const Array<int> &attributes);
147
148/**
149 * @brief Construct a nonconformal mesh (serial or parallel) for a volume
150 * submesh, from an existing nonconformal volume mesh (serial or parallel).
151 * @details This function is only instantiated for NCSubMesh and ParNCSubMesh
152 * Attempting to use it with other classes will result in a linker error.
153 * @tparam NCSubMeshT The NCSubMesh type
154 * @param[out] submesh The volume submesh to be filled from parent.
155 * @param attributes The set of attributes defining the submesh.
156 */
157template <typename NCSubMeshT>
158void ConstructVolumeTree(NCSubMeshT &submesh, const Array<int> &attributes);
159
160/**
161 * @brief Helper for checking if an object's attributes match a list
162 *
163 * @tparam T Object Type
164 * @param el Instance of T, requires method `GetAttribute()`
165 * @param attributes Set of attributes to match against
166 * @return true The attribute of el is contained within attributes
167 * @return false
168 */
169template <typename T>
170bool HasAttribute(const T &el, const Array<int> &attributes)
171{
172 for (int a = 0; a < attributes.Size(); a++)
173 {
174 if (el.GetAttribute() == attributes[a])
175 {
176 return true;
177 }
178 }
179 return false;
180}
181
182/**
183 * @brief Forwarding dispatch to HasAttribute for backwards compatibility
184 *
185 * @param el Instance of T, requires method `GetAttribute()`
186 * @param attributes Set of attributes to match against
187 * @return true The attribute of el is contained within attributes
188 * @return false
189 */
190MFEM_DEPRECATED inline bool ElementHasAttribute(const Element &el,
191 const Array<int> &attributes)
192{
193 return HasAttribute(el,attributes);
194}
195
196/**
197 * @brief Apply permutation to a container type
198 *
199 * @tparam T1 Container type 1
200 * @tparam T2 Container type 2
201 * @tparam T3 Container type 3
202 * @param indices Set of indices that define the permutation
203 * @param t1 First collection to be permuted
204 * @param t2 Second collection to be permuted
205 * @param t3 Third collection to be permuted
206 */
207template <typename T1, typename T2, typename T3>
208void Permute(const Array<int>& indices, T1& t1, T2& t2, T3& t3)
209{
210 Permute(Array<int>(indices), t1, t2, t3);
211}
212
213/**
214 * @brief Apply permutation to a container type
215 * @details Sorts the indices variable in the process, thereby destroying the
216 * permutation.
217 *
218 * @tparam T1 Container type 1
219 * @tparam T2 Container type 2
220 * @tparam T3 Container type 3
221 * @param indices Set of indices that define the permutation
222 * @param t1 First collection to be permuted
223 * @param t2 Second collection to be permuted
224 * @param t3 Third collection to be permuted
225 */
226template <typename T1, typename T2, typename T3>
227void Permute(Array<int>&& indices, T1& t1, T2& t2, T3& t3)
228{
229 /*
230 TODO: In c++17 can replace this with a parameter pack expansion technique to
231 operate on arbitrary collections of reference accessible containers of
232 arbitrary type.
233 template <typename ...T> void Permute(Array<int>&&indices, T&... t)
234 {
235 for (int i = 0; i < indices.Size(); i++)
236 {
237 auto current = i;
238 while (i != indices[current])
239 {
240 auto next = indices[current];
241 // Lambda allows iteration over expansion in c++17
242 // https://stackoverflow.com/a/60136761
243 ([&]{std::swap(t[current], t[next]);} (), ...);
244 current = next;
245 }
246 indices[current] = current;
247 }
248 }
249 */
250
251 for (int i = 0; i < indices.Size(); i++)
252 {
253 auto current = i;
254 while (i != indices[current])
255 {
256 auto next = indices[current];
257 std::swap(t1[current], t1[next]);
258 std::swap(t2[current], t2[next]);
259 std::swap(t3[current], t3[next]);
260 indices[current] = current;
261 current = next;
262 }
263 indices[current] = current;
264 }
265}
266
267
268} // namespace SubMeshUtils
269} // namespace mfem
270
271#endif
int Size() const
Return the logical size of the array.
Definition array.hpp:147
Abstract data type element.
Definition element.hpp:29
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:244
Mesh data type.
Definition mesh.hpp:64
From
Indicator from which part of the parent Mesh the SubMesh is created.
Definition submesh.hpp:49
real_t a
Definition lissajous.cpp:41
std::tuple< Array< int >, Array< int > > AddElementsToMesh(const Mesh &parent, Mesh &mesh, const Array< int > &attributes, bool from_boundary)
Given a Mesh parent and another Mesh mesh using the list of attributes in attributes,...
void ConstructFaceTree(NCSubMeshT &submesh, const Array< int > &attributes)
Construct a nonconformal mesh (serial or parallel) for a surface submesh, from an existing nonconform...
void BuildVdofToVdofMap(const FiniteElementSpace &subfes, const FiniteElementSpace &parentfes, const SubMesh::From &from, const Array< int > &parent_element_ids, Array< int > &vdof_to_vdof_map)
Build the vdof to vdof mapping between two FiniteElementSpace objects.
bool HasAttribute(const T &el, const Array< int > &attributes)
Helper for checking if an object's attributes match a list.
bool ElementHasAttribute(const ElementT &el, const Array< int > &attributes)
void Permute(const Array< int > &indices, T1 &t1, T2 &t2, T3 &t3)
Apply permutation to a container type.
void ConstructVolumeTree(NCSubMeshT &submesh, const Array< int > &attributes)
Construct a nonconformal mesh (serial or parallel) for a volume submesh, from an existing nonconforma...
auto GetRootParent(const T &m) -> decltype(std::declval< T >().GetParent())
Identify the root parent of a given SubMesh.
Array< int > BuildFaceMap(const Mesh &pm, const Mesh &sm, const Array< int > &parent_element_ids)
Given two meshes that have a parent to SubMesh relationship create a face map, using a SubMesh to par...
void AddBoundaryElements(SubMeshT &mesh, const std::unordered_map< int, int > &lface_to_boundary_attribute)
Add boundary elements to the SubMesh.
Convenience object to create unique indices.
std::unordered_map< int, int > idx
int Get(int i, bool &new_index)
Returns the unique index from an index set.