MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
submesh.cpp
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#include "submesh.hpp"
13#include "submesh_utils.hpp"
15#include "../ncmesh.hpp"
16#include "ncsubmesh.hpp"
17
18namespace mfem
19{
20
22 const Array<int> &domain_attributes)
23{
24 return SubMesh(parent, From::Domain, domain_attributes);
25}
26
28 const Array<int> &boundary_attributes)
29{
30 return SubMesh(parent, From::Boundary, boundary_attributes);
31}
32
33SubMesh::SubMesh(const Mesh &parent, From from,
34 const Array<int> &attributes) : parent_(&parent), from_(from),
35 attributes_(attributes)
36{
37 if (from == From::Domain)
38 {
39 InitMesh(parent.Dimension(), parent.SpaceDimension(), 0, 0, 0);
40
41 std::tie(parent_vertex_ids_,
42 parent_element_ids_) = SubMeshUtils::AddElementsToMesh(parent, *this,
43 attributes_);
44 }
45 else if (from == From::Boundary)
46 {
47 InitMesh(parent.Dimension() - 1, parent.SpaceDimension(), 0, 0, 0);
48
49 std::tie(parent_vertex_ids_,
50 parent_element_ids_) = SubMeshUtils::AddElementsToMesh(parent, *this,
51 attributes_, true);
52 }
53
54 parent_to_submesh_vertex_ids_.SetSize(parent.GetNV());
55 parent_to_submesh_vertex_ids_ = -1;
56 for (int i = 0; i < parent_vertex_ids_.Size(); i++)
57 {
58 parent_to_submesh_vertex_ids_[parent_vertex_ids_[i]] = i;
59 }
60
61 parent_to_submesh_element_ids_.SetSize(from == From::Boundary ? parent.GetNBE()
62 : parent.GetNE());
63 parent_to_submesh_element_ids_ = -1;
64 for (int i = 0; i < parent_element_ids_.Size(); i++)
65 {
66 parent_to_submesh_element_ids_[parent_element_ids_[i]] = i;
67 }
68
69 FinalizeTopology(false);
70
71 if (parent.Nonconforming())
72 {
73 ncmesh = new NCSubMesh(*this, *parent.ncmesh, from, attributes);
74 ncsubmesh_ = dynamic_cast<NCSubMesh*>(ncmesh);
75 InitFromNCMesh(*ncsubmesh_);
76 ncsubmesh_->OnMeshUpdated(this);
77
78 // Update the submesh to parent vertex mapping, ncsubmesh_ reordered the
79 // vertices so the map to parent is no longer valid.
80 parent_to_submesh_vertex_ids_ = -1;
81 for (int i = 0; i < parent_vertex_ids_.Size(); i++)
82 {
83 // vertex -> node -> parent node -> parent vertex
84 auto node = ncsubmesh_->vertex_nodeId[i];
85 auto parent_node = ncsubmesh_->parent_node_ids_[node];
86 auto parent_vertex = parent.ncmesh->GetNodeVertex(parent_node);
87 parent_vertex_ids_[i] = parent_vertex;
88 parent_to_submesh_vertex_ids_[parent_vertex] = i;
89 }
92 }
93
94 DSTable v2v(parent_->GetNV());
95 parent_->GetVertexToVertexTable(v2v);
96 for (int i = 0; i < NumOfEdges; i++)
97 {
98 Array<int> lv;
99 GetEdgeVertices(i, lv);
100
101 // Find vertices/edge in parent mesh
102 int parent_edge_id = v2v(parent_vertex_ids_[lv[0]],
103 parent_vertex_ids_[lv[1]]);
104 parent_edge_ids_.Append(parent_edge_id);
105 }
106
107 parent_to_submesh_edge_ids_.SetSize(parent.GetNEdges());
108 parent_to_submesh_edge_ids_ = -1;
109 for (int i = 0; i < parent_edge_ids_.Size(); i++)
110 {
111 parent_to_submesh_edge_ids_[parent_edge_ids_[i]] = i;
112 }
113
114 if (Dim == 3)
115 {
116 parent_face_ids_ = SubMeshUtils::BuildFaceMap(parent, *this,
117 parent_element_ids_);
118
119 parent_to_submesh_face_ids_.SetSize(parent.GetNFaces());
120 parent_to_submesh_face_ids_ = -1;
121 for (int i = 0; i < parent_face_ids_.Size(); i++)
122 {
123 parent_to_submesh_face_ids_[parent_face_ids_[i]] = i;
124 }
125
126 parent_face_ori_.SetSize(NumOfFaces);
127 for (int i = 0; i < NumOfFaces; i++)
128 {
129 Array<int> sub_vert;
130 GetFaceVertices(i, sub_vert);
131
132 Array<int> sub_par_vert(sub_vert.Size());
133 for (int j = 0; j < sub_vert.Size(); j++)
134 {
135 sub_par_vert[j] = parent_vertex_ids_[sub_vert[j]];
136 }
137
138 Array<int> par_vert;
139 parent.GetFaceVertices(parent_face_ids_[i], par_vert);
140 if (par_vert.Size() == 3)
141 {
142 parent_face_ori_[i] = GetTriOrientation(par_vert, sub_par_vert);
143 }
144 else
145 {
146 parent_face_ori_[i] = GetQuadOrientation(par_vert, sub_par_vert);
147 }
148 }
149 }
150 else if (Dim == 2)
151 {
152 if (from == From::Domain)
153 {
154 parent_edge_ids_ = SubMeshUtils::BuildFaceMap(parent, *this,
155 parent_element_ids_);
156
157 parent_to_submesh_edge_ids_.SetSize(parent.GetNEdges());
158 parent_to_submesh_edge_ids_ = -1;
159 for (int i = 0; i < parent_edge_ids_.Size(); i++)
160 {
161 parent_to_submesh_edge_ids_[parent_edge_ids_[i]] = i;
162 }
163
164 Array<int> parent_face_to_be = parent.GetFaceToBdrElMap();
165 int max_bdr_attr = parent.bdr_attributes.Size() ?
166 parent.bdr_attributes.Max() : 1;
167
168 for (int i = 0; i < NumOfBdrElements; i++)
169 {
170 int pbeid = parent_face_to_be[parent_edge_ids_[GetBdrElementFaceIndex(i)]];
171 if (pbeid != -1)
172 {
173 int attr = parent.GetBdrElement(pbeid)->GetAttribute();
174 GetBdrElement(i)->SetAttribute(attr);
175 }
176 else
177 {
178 // This case happens when a domain is extracted, but the root
179 // parent mesh didn't have a boundary element on the surface that
180 // defined it's boundary. It still creates a valid mesh, so we
181 // allow it.
182 GetBdrElement(i)->SetAttribute(max_bdr_attr + 1);
183 }
184 }
185 }
186
187 parent_face_ori_.SetSize(NumOfElements);
188
189 for (int i = 0; i < NumOfElements; i++)
190 {
191 Array<int> sub_vert;
192 GetElementVertices(i, sub_vert);
193
194 Array<int> sub_par_vert(sub_vert.Size());
195 for (int j = 0; j < sub_vert.Size(); j++)
196 {
197 sub_par_vert[j] = parent_vertex_ids_[sub_vert[j]];
198 }
199
200 Array<int> par_vert;
201 int be_ori = 0;
202 if (from == From::Boundary)
203 {
204 parent.GetBdrElementVertices(parent_element_ids_[i], par_vert);
205
206 int f = -1;
207 parent.GetBdrElementFace(parent_element_ids_[i], &f, &be_ori);
208 }
209 else
210 {
211 parent.GetElementVertices(parent_element_ids_[i], par_vert);
212 }
213
214 if (par_vert.Size() == 3)
215 {
216 int se_ori = GetTriOrientation(par_vert, sub_par_vert);
217 parent_face_ori_[i] = ComposeTriOrientations(be_ori, se_ori);
218 }
219 else
220 {
221 parent_face_ori_[i] = GetQuadOrientation(par_vert, sub_par_vert);
222 }
223 }
224 }
225
227
228 if (Dim > 1)
229 {
230 delete el_to_edge;
231 el_to_edge = new Table;
233 }
234 if (Dim > 2)
235 {
237 }
238
239 // If the parent Mesh has nodes and therefore is defined on a higher order
240 // geometry, we define this SubMesh as a curved Mesh and transfer the
241 // GridFunction from the parent Mesh to the SubMesh.
242 const GridFunction *parent_nodes = parent.GetNodes();
243 if (parent_nodes)
244 {
245 const FiniteElementSpace *parent_fes = parent_nodes->FESpace();
246
248 parent_fes->FEColl()->GetOrder(),
249 parent_fes->IsDGSpace(),
250 spaceDim,
251 parent_fes->GetOrdering());
252
253 Transfer(*parent.GetNodes(), *GetNodes());
254 }
255
257 Finalize();
258}
259
261{
262 CreateTransferMap(src, dst).Transfer(src, dst);
263}
264
266 const GridFunction &dst)
267{
268 return TransferMap(src, dst);
269}
270
271} // namespace mfem
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:68
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:758
int Size() const
Return the logical size of the array.
Definition array.hpp:147
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:830
void SetAttribute(const int attr)
Set element's attribute.
Definition element.hpp:61
int GetAttribute() const
Return element's attribute.
Definition element.hpp:58
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
Mesh data type.
Definition mesh.hpp:64
int GetElementToEdgeTable(Table &)
Definition mesh.cpp:7741
int GetNEdges() const
Return the number of edges.
Definition mesh.hpp:1288
void GetBdrElementFace(int i, int *f, int *o) const
Definition mesh.cpp:7565
void InitMesh(int Dim_, int spaceDim_, int NVert, int NElem, int NBdrElem)
Begin construction of a mesh.
Definition mesh.cpp:1850
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:290
static int GetQuadOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
Definition mesh.cpp:6815
int NumOfBdrElements
Definition mesh.hpp:79
void GetBdrElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of boundary element i.
Definition mesh.hpp:1512
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
Definition mesh.hpp:1508
Array< int > GetFaceToBdrElMap() const
Definition mesh.cpp:1517
void GenerateNCFaceInfo()
Definition mesh.cpp:8059
int Dim
Definition mesh.hpp:76
bool Nonconforming() const
Return a bool indicating whether this mesh is nonconforming.
Definition mesh.hpp:2367
int GetBdrElementFaceIndex(int be_idx) const
Return the local face (codimension-1) index for the given boundary element index.
Definition mesh.hpp:1588
void InitFromNCMesh(const NCMesh &ncmesh)
Initialize vertices/elements/boundary/tables from a nonconforming mesh.
Definition mesh.cpp:10658
static int GetTriOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
Definition mesh.cpp:6726
int GetNFaces() const
Return the number of faces in a 3D mesh.
Definition mesh.hpp:1291
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
Definition mesh.cpp:3362
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1282
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
Definition mesh.hpp:1354
Table * el_to_edge
Definition mesh.hpp:235
STable3D * GetElementToFaceTable(int ret_ftbl=0)
Definition mesh.cpp:8180
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Definition mesh.hpp:1219
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:9294
static int ComposeTriOrientations(int ori_a_b, int ori_b_c)
Definition mesh.cpp:6786
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
Definition mesh.hpp:1279
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
Definition mesh.cpp:7351
int NumOfElements
Definition mesh.hpp:79
void GetFaceVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of face i.
Definition mesh.hpp:1526
int NumOfFaces
Definition mesh.hpp:80
int spaceDim
Definition mesh.hpp:77
int GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1285
virtual void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
Definition mesh.cpp:3468
NCMesh * ncmesh
Optional nonconforming mesh extension.
Definition mesh.hpp:299
GridFunction * GetNodes()
Return a pointer to the internal node GridFunction (may be NULL).
Definition mesh.hpp:2229
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Set the curvature of the mesh nodes using the given polynomial degree.
Definition mesh.cpp:6484
void GetVertexToVertexTable(DSTable &) const
Definition mesh.cpp:7716
int NumOfEdges
Definition mesh.hpp:80
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition mesh.hpp:288
virtual void SetAttributes()
Determine the sets of unique attribute values in domain and boundary elements.
Definition mesh.cpp:1819
void OnMeshUpdated(Mesh *mesh)
Definition ncmesh.cpp:2885
int GetNodeVertex(int node)
Given a node index, return the vertex index associated.
Definition ncmesh.hpp:505
Array< int > vertex_nodeId
vertex-index to node-id map, see UpdateVertices
Definition ncmesh.hpp:725
Subdomain representation of a topological parent in another Mesh.
Definition submesh.hpp:44
static SubMesh CreateFromBoundary(const Mesh &parent, const Array< int > &boundary_attributes)
Create a surface SubMesh from its parent.
Definition submesh.cpp:27
static void Transfer(const GridFunction &src, GridFunction &dst)
Transfer the dofs of a GridFunction.
Definition submesh.cpp:260
static SubMesh CreateFromDomain(const Mesh &parent, const Array< int > &domain_attributes)
Create a domain SubMesh from its parent.
Definition submesh.cpp:21
friend class NCSubMesh
Definition submesh.hpp:45
static TransferMap CreateTransferMap(const GridFunction &src, const GridFunction &dst)
Create a Transfer Map object.
Definition submesh.cpp:265
SubMesh()=delete
TransferMap represents a mapping of degrees of freedom from a source GridFunction to a destination Gr...
void Transfer(const GridFunction &src, GridFunction &dst) const
Transfer the source GridFunction to the destination GridFunction.
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,...
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.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30