MFEM v4.8.0
Finite element discretization library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
face_map_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_FACE_MAP_UTILS_HPP
13#define MFEM_FACE_MAP_UTILS_HPP
14
17#include <utility> // std::pair
18#include <vector>
19
20namespace mfem
21{
22
23namespace internal
24{
25
26/// Each face of a hexahedron is given by a level set x_i = l, where x_i is one
27/// of x, y, or z (corresponding to i=0, i=1, i=2), and l is either 0 or 1.
28/// Returns i and level.
29std::pair<int,int> GetFaceNormal3D(const int face_id);
30
31/// @brief Fills in the entries of the lexicographic face_map.
32///
33/// For use in FiniteElement::GetFaceMap.
34///
35/// n_face_dofs_per_component is the number of DOFs for each vector component
36/// on the face (there is only one vector component in all cases except for 3D
37/// Nedelec elements, where the face DOFs have two components to span the
38/// tangent space).
39///
40/// The DOFs for the i-th vector component begin at offsets[i] (i.e. the number
41/// of vector components is given by offsets.size()).
42///
43/// The DOFs for each vector component are arranged in a Cartesian grid defined
44/// by strides and n_dofs_per_dim.
45void FillFaceMap(const int n_face_dofs_per_component,
46 const std::vector<int> &offsets,
47 const std::vector<int> &strides,
48 const std::vector<int> &n_dofs_per_dim,
49 Array<int> &face_map);
50
51/// Return the face map for nodal tensor elements (H1, L2, and Bernstein basis).
52void GetTensorFaceMap(const int dim, const int order, const int face_id,
53 Array<int> &face_map);
54
55/// @brief Given a face DOF index in native (counter-clockwise) ordering, return
56/// the corresponding DOF index in lexicographic ordering (for a quadrilateral
57/// element).
58MFEM_HOST_DEVICE
59inline int ToLexOrdering2D(const int face_id, const int size1d, const int i)
60{
61 if (face_id==2 || face_id==3)
62 {
63 return size1d-1-i;
64 }
65 else
66 {
67 return i;
68 }
69}
70
71/// @brief Given a face DOF index on a shared face, ordered lexicographically
72/// relative to element the element (where the local face is face_id), and
73/// return the corresponding face DOF index ordered lexicographically relative
74/// to the face itself.
75MFEM_HOST_DEVICE
76inline int PermuteFace2D(const int face_id, const int orientation,
77 const int size1d, const int index)
78{
79 int new_index;
80 // Convert from element 1 lex ordering to native ordering
81 if (face_id == 2 || face_id == 3)
82 {
83 new_index = size1d-1-index;
84 }
85 else
86 {
87 new_index = index;
88 }
89 // Permute based on face orientations
90 if (orientation == 1)
91 {
92 new_index = size1d-1-new_index;
93 }
94 return new_index;
95}
96
97/// @brief Given a face DOF index on a shared face, ordered lexicographically
98/// relative to element 1, return the corresponding face DOF index ordered
99/// lexicographically relative to element 2.
100MFEM_HOST_DEVICE
101inline int PermuteFace2D(const int face_id1, const int face_id2,
102 const int orientation, const int size1d,
103 const int index)
104{
105 const int new_index = PermuteFace2D(face_id1, orientation, size1d, index);
106 return ToLexOrdering2D(face_id2, size1d, new_index);
107}
108
109/// @brief Given a face DOF index in native (counter-clockwise) ordering, return
110/// the corresponding DOF index in lexicographic ordering (for a hexahedral
111/// element).
112MFEM_HOST_DEVICE
113inline int ToLexOrdering3D(const int face_id, const int size1d, const int i,
114 const int j)
115{
116 if (face_id==2 || face_id==1 || face_id==5)
117 {
118 return i + j*size1d;
119 }
120 else if (face_id==3 || face_id==4)
121 {
122 return (size1d-1-i) + j*size1d;
123 }
124 else // face_id==0
125 {
126 return i + (size1d-1-j)*size1d;
127 }
128}
129
130/// @brief Given the index of a face DOF in lexicographic ordering relative the
131/// element (where the local face id is @a face_id), permute the index so that
132/// it is lexicographically ordered relative to the face itself.
133MFEM_HOST_DEVICE
134inline int PermuteFace3D(const int face_id, const int orientation,
135 const int size1d, const int index)
136{
137 int i=0, j=0, new_i=0, new_j=0;
138 i = index%size1d;
139 j = index/size1d;
140 // Convert from lex ordering
141 if (face_id==3 || face_id==4)
142 {
143 i = size1d-1-i;
144 }
145 else if (face_id==0)
146 {
147 j = size1d-1-j;
148 }
149 // Permute based on face orientations
150 switch (orientation)
151 {
152 case 0:
153 new_i = i;
154 new_j = j;
155 break;
156 case 1:
157 new_i = j;
158 new_j = i;
159 break;
160 case 2:
161 new_i = j;
162 new_j = (size1d-1-i);
163 break;
164 case 3:
165 new_i = (size1d-1-i);
166 new_j = j;
167 break;
168 case 4:
169 new_i = (size1d-1-i);
170 new_j = (size1d-1-j);
171 break;
172 case 5:
173 new_i = (size1d-1-j);
174 new_j = (size1d-1-i);
175 break;
176 case 6:
177 new_i = (size1d-1-j);
178 new_j = i;
179 break;
180 case 7:
181 new_i = i;
182 new_j = (size1d-1-j);
183 break;
184 }
185 return new_i + new_j*size1d;
186}
187
188/// @brief Given the index of a face DOF in lexicographic ordering relative
189/// element 1, permute the index so that it is lexicographically ordered
190/// relative to element 2.
191///
192/// The given face corresponds to local face index @a face_id1 relative to
193/// element 1, and @a face_id2 (with @a orientation) relative to element 2.
194MFEM_HOST_DEVICE
195inline int PermuteFace3D(const int face_id1, const int face_id2,
196 const int orientation,
197 const int size1d, const int index)
198{
199 const int new_index = PermuteFace3D(face_id1, orientation, size1d, index);
200 const int new_i = new_index%size1d;
201 const int new_j = new_index/size1d;
202 return ToLexOrdering3D(face_id2, size1d, new_i, new_j);
203}
204
205/// @brief Given a face DOF (or quadrature) index ordered lexicographically
206/// relative to element 1, return the associated (i, j) coordinates.
207///
208/// The returned coordinates will be relative to element 1 or element 2
209/// according to the value of side (side == 0 corresponds element 1).
210MFEM_HOST_DEVICE
211inline void FaceIdxToVolIdx2D(const int qi, const int nq, const int face_id0,
212 const int face_id1, const int side, int &i, int &j)
213{
214 // Note: in 2D, a consistently ordered mesh will always have the element 2
215 // face reversed relative to element 1, so orientation is determined entirely
216 // by side. (In 3D, separate orientation information is needed).
217 const int orientation = side;
218
219 const int face_id = (side == 0) ? face_id0 : face_id1;
220 const int edge_idx = (side == 0) ? qi : PermuteFace2D(face_id0, face_id1,
221 orientation, nq, qi);
222
223 const int level = (face_id == 0 || face_id == 3) ? 0 : (nq-1);
224 const bool x_axis = (face_id == 0 || face_id == 2);
225
226 i = x_axis ? edge_idx : level;
227 j = x_axis ? level : edge_idx;
228}
229
230/// @brief Given a face DOF (or quadrature) index ordered lexicographically
231/// relative to element 1, return the associated (i, j, k) coordinates.
232///
233/// The returned coordinates will be relative to element 1 or element 2
234/// according to the value of side (side == 0 corresponds element 1).
235MFEM_HOST_DEVICE
236inline void FaceIdxToVolIdx3D(const int index, const int size1d,
237 const int face_id0, const int face_id1,
238 const int side, const int orientation,
239 int& i, int& j, int& k)
240{
241 MFEM_VERIFY_KERNEL(face_id1 >= 0 || side == 0,
242 "Accessing second side but face_id1 is not valid.");
243
244 const int face_id = (side == 0) ? face_id0 : face_id1;
245 const int fidx = (side == 0) ? index
246 : PermuteFace3D(face_id0, face_id1, orientation, size1d, index);
247
248 const bool xy_plane = (face_id == 0 || face_id == 5);
249 const bool yz_plane = (face_id == 2 || face_id == 4);
250
251 const int level = (face_id == 0 || face_id == 1 || face_id == 4)
252 ? 0 : (size1d-1);
253
254 const int _i = fidx % size1d;
255 const int _j = fidx / size1d;
256
257 k = xy_plane ? level : _j;
258 j = yz_plane ? _i : xy_plane ? _j : level;
259 i = yz_plane ? level : _i;
260}
261
262} // namespace internal
263
264} // namespace mfem
265
266#endif
int dim
Definition ex24.cpp:53
int index(int i, int j, int nx, int ny)
Definition life.cpp:236