Intrepid2
Intrepid2_OrientationDef.hpp
Go to the documentation of this file.
1// @HEADER
2// ************************************************************************
3//
4// Intrepid2 Package
5// Copyright (2007) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Kyungjoo Kim (kyukim@sandia.gov), or
38// Mauro Perego (mperego@sandia.gov)
39//
40// ************************************************************************
41// @HEADER
42
43
48#ifndef __INTREPID2_ORIENTATION_DEF_HPP__
49#define __INTREPID2_ORIENTATION_DEF_HPP__
50
51// disable clang warnings
52#if defined (__clang__) && !defined (__INTEL_COMPILER)
53#pragma clang system_header
54#endif
55
56namespace Intrepid2 {
57
58 // ------------------------------------------------------------------------------------
59 // Orientation
60 //
61 //
62 template<typename cellVertViewType>
63 inline
64 void
65 Orientation::getCellVertexMap(typename cellVertViewType::non_const_value_type *subCellVerts,
66 ordinal_type &numVerts,
67 const shards::CellTopology cellTopo,
68 const cellVertViewType cellVertices,
69 const ordinal_type subCellDim,
70 const ordinal_type subCellOrd) {
71 static_assert(Kokkos::Impl::MemorySpaceAccess
72 <Kokkos::HostSpace,typename cellVertViewType::device_type::memory_space>::accessible,
73 "host space cannot access cellVertViewType");
74 switch (subCellDim) {
75 case 0: {
76 numVerts = 1;
77 subCellVerts[0] = cellVertices(subCellOrd);
78 break;
79 }
80 default: {
81 numVerts = cellTopo.getVertexCount(subCellDim, subCellOrd);
82 for (ordinal_type i=0;i<numVerts;++i)
83 subCellVerts[i] = cellVertices(cellTopo.getNodeMap(subCellDim, subCellOrd, i));
84 break;
85 }
86 }
87 }
88
89 template<typename subCellVertType>
90 inline
91 ordinal_type
92 Orientation::getOrientation(const subCellVertType subCellVerts[],
93 const ordinal_type numVerts) {
94 ordinal_type ort = 0;
95 switch (numVerts) {
96 case 2: {// edge
97#ifdef HAVE_INTREPID2_DEBUG
98 INTREPID2_TEST_FOR_ABORT( ( subCellVerts[0] == subCellVerts[1] ),
99 ">>> ERROR (Intrepid::Orientation::getOrientation): " \
100 "Invalid subCellVerts, same vertex ids are repeated");
101#endif
102 ort = (subCellVerts[0] > subCellVerts[1]);
103 break;
104 }
105 case 3: {
106#ifdef HAVE_INTREPID2_DEBUG
107 INTREPID2_TEST_FOR_ABORT( ( subCellVerts[0] == subCellVerts[1] ||
108 subCellVerts[0] == subCellVerts[2] ||
109 subCellVerts[1] == subCellVerts[2] ),
110 ">>> ERROR (Intrepid::Orientation::getOrientation): " \
111 "Invalid subCellVerts, same vertex ids are repeated");
112#endif
113 ordinal_type rotation = 0; // find smallest vertex id
114 for (ordinal_type i=1;i<3;++i)
115 rotation = ( subCellVerts[i] < subCellVerts[rotation] ? i : rotation );
116
117 const ordinal_type axes[][2] = { {1,2}, {2,0}, {0,1} };
118 const ordinal_type flip = (subCellVerts[axes[rotation][0]] > subCellVerts[axes[rotation][1]]);
119
120 ort = flip*3 + rotation;
121 break;
122 }
123 case 4: {
124#ifdef HAVE_INTREPID2_DEBUG
125 INTREPID2_TEST_FOR_ABORT( ( subCellVerts[0] == subCellVerts[1] ||
126 subCellVerts[0] == subCellVerts[2] ||
127 subCellVerts[0] == subCellVerts[3] ||
128 subCellVerts[1] == subCellVerts[2] ||
129 subCellVerts[1] == subCellVerts[3] ||
130 subCellVerts[2] == subCellVerts[3] ),
131 ">>> ERROR (Intrepid::Orientation::getOrientation): " \
132 "Invalid subCellVerts, same vertex ids are repeated");
133#endif
134 ordinal_type rotation = 0; // find smallest vertex id
135 for (ordinal_type i=1;i<4;++i)
136 rotation = ( subCellVerts[i] < subCellVerts[rotation] ? i : rotation );
137
138 const ordinal_type axes[][2] = { {1,3}, {2,0}, {3,1}, {0,2} };
139 const ordinal_type flip = (subCellVerts[axes[rotation][0]] > subCellVerts[axes[rotation][1]]);
140
141 ort = flip*4 + rotation;
142 break;
143 }
144 default: {
145 INTREPID2_TEST_FOR_ABORT( true,
146 ">>> ERROR (Intrepid::Orientation::getOrientation): " \
147 "Invalid numVerts (2 (edge),3 (triangle) and 4 (quadrilateral) are allowed)");
148 break;
149 }
150 }
151 return ort;
152 }
153
154 template<typename cellVertViewType>
155 inline
156 Orientation
157 Orientation::getOrientation(const shards::CellTopology cellTopo,
158 const cellVertViewType cellVertices,
159 bool isSide) {
160 static_assert(Kokkos::Impl::MemorySpaceAccess
161 <Kokkos::HostSpace,typename cellVertViewType::device_type::memory_space>::accessible,
162 "host space cannot access cellVertViewType");
163
164 Orientation ort;
165 auto dim = cellTopo.getDimension();
166 const ordinal_type nedge = (isSide && dim==1) ? 1 : cellTopo.getEdgeCount();
167
168 if (nedge > 0) {
169 typename cellVertViewType::non_const_value_type vertsSubCell[2];
170 ordinal_type orts[12], nvertSubCell;
171 for (ordinal_type i=0;i<nedge;++i) {
172 Orientation::getCellVertexMap(vertsSubCell,
173 nvertSubCell,
174 cellTopo,
175 cellVertices,
176 1, i);
177 orts[i] = Orientation::getOrientation(vertsSubCell, nvertSubCell);
178 }
179 ort.setEdgeOrientation(nedge, orts);
180 }
181 const ordinal_type nface = (isSide && dim==2) ? 1 : cellTopo.getFaceCount();
182 if (nface > 0) {
183 typename cellVertViewType::non_const_value_type vertsSubCell[4];
184 ordinal_type orts[6], nvertSubCell;
185 for (ordinal_type i=0;i<nface;++i) {
186 Orientation::getCellVertexMap(vertsSubCell,
187 nvertSubCell,
188 cellTopo,
189 cellVertices,
190 2, i);
191 orts[i] = Orientation::getOrientation(vertsSubCell, nvertSubCell);
192 }
193 ort.setFaceOrientation(nface, orts);
194 }
195 return ort;
196 }
197
198 inline
199 ordinal_type
200 Orientation::getEdgeOrdinalOfFace(const ordinal_type subsubcellOrd,
201 const ordinal_type subcellOrd,
202 const shards::CellTopology cellTopo) {
203 ordinal_type r_val = -1;
204
205 const auto cellBaseKey = cellTopo.getBaseKey();
206 if (cellBaseKey == shards::Hexahedron<>::key) {
207 INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 6) &&
208 !(subsubcellOrd < 4),
209 std::logic_error,
210 "subcell and subsubcell information are not correct" );
211 const int quad_to_hex_edges[6][4] = { { 0, 9, 4, 8 },
212 { 1,10, 5, 9 },
213 { 2,11, 6,10 },
214 { 8, 7,11, 3 },
215 { 3, 2, 1, 0 },
216 { 4, 5, 6, 7 } };
217 r_val = quad_to_hex_edges[subcellOrd][subsubcellOrd];
218 } else if (cellBaseKey == shards::Tetrahedron<>::key) {
219 INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 4) &&
220 !(subsubcellOrd < 3),
221 std::logic_error,
222 "subcell and subsubcell information are not correct" );
223 const ordinal_type tri_to_tet_edges[4][3] = { { 0, 4, 3 },
224 { 1, 5, 4 },
225 { 3, 5, 2 },
226 { 2, 1, 0 } };
227 r_val = tri_to_tet_edges[subcellOrd][subsubcellOrd];
228 } else {
229 INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
230 "cellTopo is not supported: try TET and HEX" );
231 }
232 return r_val;
233 }
234
235 KOKKOS_INLINE_FUNCTION
237 : _edgeOrt(0), _faceOrt(0) {}
238
239 KOKKOS_INLINE_FUNCTION
240 bool
242 return (_edgeOrt == 0 && _faceOrt == 0);
243 }
244
245 KOKKOS_INLINE_FUNCTION
246 void
247 Orientation::setEdgeOrientation(const ordinal_type numEdge, const ordinal_type edgeOrt[]) {
248#ifdef HAVE_INTREPID2_DEBUG
249 INTREPID2_TEST_FOR_ABORT( !((numEdge == 1) || (3 <= numEdge && numEdge <= 12 )),
250 ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): " \
251 "Invalid numEdge");
252#endif
253 _edgeOrt = 0;
254 for (ordinal_type i=0;i<numEdge;++i)
255 _edgeOrt |= (edgeOrt[i] & 1) << i;
256 }
257
258 KOKKOS_INLINE_FUNCTION
259 void
260 Orientation::getEdgeOrientation(ordinal_type *edgeOrt, const ordinal_type numEdge) const {
261#ifdef HAVE_INTREPID2_DEBUG
262 INTREPID2_TEST_FOR_ABORT( !((numEdge == 1) || (3 <= numEdge && numEdge <= 12 )),
263 ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): " \
264 "Invalid numEdge");
265#endif
266 for (ordinal_type i=0;i<numEdge;++i)
267 edgeOrt[i] = (_edgeOrt & (1 << i)) >> i;
268 }
269
270 KOKKOS_INLINE_FUNCTION
271 void
272 Orientation::setFaceOrientation(const ordinal_type numFace, const ordinal_type faceOrt[]) {
273#ifdef HAVE_INTREPID2_DEBUG
274 INTREPID2_TEST_FOR_ABORT( !((numFace == 1) || (4 <= numFace && numFace <= 6 )),
275 ">>> ERROR (Intrepid::Orientation::setFaceOrientation): "
276 "Invalid numFace");
277#endif
278 _faceOrt = 0;
279 for (ordinal_type i=0;i<numFace;++i) {
280 const ordinal_type s = i*3;
281 _faceOrt |= (faceOrt[i] & 7) << s;
282 }
283 }
284
285 KOKKOS_INLINE_FUNCTION
286 void
287 Orientation::getFaceOrientation(ordinal_type *faceOrt, const ordinal_type numFace) const {
288#ifdef HAVE_INTREPID2_DEBUG
289 INTREPID2_TEST_FOR_ABORT( !((numFace == 1) || (4 <= numFace && numFace <= 6 )),
290 ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): "
291 "Invalid numFace");
292#endif
293 for (ordinal_type i=0;i<numFace;++i) {
294 const ordinal_type s = i*3;
295 faceOrt[i] = (_faceOrt & (7 << s)) >> s;
296 }
297 }
298
299 inline std::string Orientation::to_string() const {
300 return "Orientation{ face: " + std::to_string(_faceOrt) + "; edge: " + std::to_string(_edgeOrt) + " }";
301 }
302}
303
304#endif
Orientation encoding and decoding.
KOKKOS_INLINE_FUNCTION void getFaceOrientation(ordinal_type *faceOrt, const ordinal_type numFace) const
KOKKOS_INLINE_FUNCTION void setFaceOrientation(const ordinal_type numFace, const ordinal_type faceOrt[])
KOKKOS_INLINE_FUNCTION void getEdgeOrientation(ordinal_type *edgeOrt, const ordinal_type numEdge) const
KOKKOS_INLINE_FUNCTION Orientation()
static ordinal_type getEdgeOrdinalOfFace(const ordinal_type subsubcellOrd, const ordinal_type subcellOrd, const shards::CellTopology cellTopo)
KOKKOS_INLINE_FUNCTION void setEdgeOrientation(const ordinal_type numEdge, const ordinal_type edgeOrt[])
KOKKOS_INLINE_FUNCTION bool isAlignedToReference() const