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
96#ifdef HAVE_INTREPID2_DEBUG
97 for(ordinal_type i=0;i<numVerts-1;++i)
98 for(ordinal_type j=i+1;j<numVerts;++j)
99 INTREPID2_TEST_FOR_ABORT( ( subCellVerts[i] == subCellVerts[j] ),
100 ">>> ERROR (Intrepid::Orientation::getOrientation): " \
101 "Invalid subCellVerts, some vertex ids are repeated");
102#endif
103
104 ordinal_type rotation = 0; // find smallest vertex id
105 for (ordinal_type i=1;i<numVerts;++i)
106 rotation = (subCellVerts[i] < subCellVerts[rotation]) ? i : rotation;
107
108 switch (numVerts) {
109 case 2: {// edge
110 ort = rotation;
111 break;
112 }
113 case 3: {
114 const ordinal_type axes[][2] = { {1,2}, {2,0}, {0,1} };
115 const ordinal_type flip = (subCellVerts[axes[rotation][0]] > subCellVerts[axes[rotation][1]]);
116
117 ort = flip*3 + rotation;
118 break;
119 }
120 case 4: {
121 const ordinal_type axes[][2] = { {1,3}, {2,0}, {3,1}, {0,2} };
122 const ordinal_type flip = (subCellVerts[axes[rotation][0]] > subCellVerts[axes[rotation][1]]);
123
124 ort = flip*4 + rotation;
125 break;
126 }
127 default: {
128 INTREPID2_TEST_FOR_ABORT( true,
129 ">>> ERROR (Intrepid::Orientation::getOrientation): " \
130 "Invalid numVerts (2 (edge),3 (triangle) and 4 (quadrilateral) are allowed)");
131 break;
132 }
133 }
134 return ort;
135 }
136
137 template<typename cellVertViewType>
138 inline
140 Orientation::getOrientation(const shards::CellTopology cellTopo,
141 const cellVertViewType cellVertices,
142 bool isSide) {
143 static_assert(Kokkos::Impl::MemorySpaceAccess
144 <Kokkos::HostSpace,typename cellVertViewType::device_type::memory_space>::accessible,
145 "host space cannot access cellVertViewType");
146
147 Orientation ort;
148 auto dim = cellTopo.getDimension();
149 const ordinal_type nedge = (isSide && dim==1) ? 1 : cellTopo.getEdgeCount();
150
151 if (nedge > 0) {
152 typename cellVertViewType::non_const_value_type vertsSubCell[2];
153 ordinal_type orts[12], nvertSubCell;
154 for (ordinal_type i=0;i<nedge;++i) {
155 Orientation::getCellVertexMap(vertsSubCell,
156 nvertSubCell,
157 cellTopo,
158 cellVertices,
159 1, i);
160 orts[i] = Orientation::getOrientation(vertsSubCell, nvertSubCell);
161 }
162 ort.setEdgeOrientation(nedge, orts);
163 }
164 const ordinal_type nface = (isSide && dim==2) ? 1 : cellTopo.getFaceCount();
165 if (nface > 0) {
166 typename cellVertViewType::non_const_value_type vertsSubCell[4];
167 ordinal_type orts[6], nvertSubCell;
168 for (ordinal_type i=0;i<nface;++i) {
169 Orientation::getCellVertexMap(vertsSubCell,
170 nvertSubCell,
171 cellTopo,
172 cellVertices,
173 2, i);
174 orts[i] = Orientation::getOrientation(vertsSubCell, nvertSubCell);
175 }
176 ort.setFaceOrientation(nface, orts);
177 }
178 return ort;
179 }
180
181 inline
182 ordinal_type
183 Orientation::getEdgeOrdinalOfFace(const ordinal_type subsubcellOrd,
184 const ordinal_type subcellOrd,
185 const shards::CellTopology cellTopo) {
186 ordinal_type r_val = -1;
187
188 const auto cellBaseKey = cellTopo.getBaseKey();
189 if (cellBaseKey == shards::Hexahedron<>::key) {
190 INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 6) &&
191 !(subsubcellOrd < 4),
192 std::logic_error,
193 "subcell and subsubcell information are not correct" );
194 const int quad_to_hex_edges[6][4] = { { 0, 9, 4, 8 },
195 { 1,10, 5, 9 },
196 { 2,11, 6,10 },
197 { 8, 7,11, 3 },
198 { 3, 2, 1, 0 },
199 { 4, 5, 6, 7 } };
200 r_val = quad_to_hex_edges[subcellOrd][subsubcellOrd];
201 } else if (cellBaseKey == shards::Tetrahedron<>::key) {
202 INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 4) &&
203 !(subsubcellOrd < 3),
204 std::logic_error,
205 "subcell and subsubcell information are not correct" );
206 const ordinal_type tri_to_tet_edges[4][3] = { { 0, 4, 3 },
207 { 1, 5, 4 },
208 { 3, 5, 2 },
209 { 2, 1, 0 } };
210 r_val = tri_to_tet_edges[subcellOrd][subsubcellOrd];
211 } else {
212 INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
213 "cellTopo is not supported: try TET and HEX" );
214 }
215 return r_val;
216 }
217
218 KOKKOS_INLINE_FUNCTION
220 : _edgeOrt(0), _faceOrt(0) {}
221
222 KOKKOS_INLINE_FUNCTION
223 bool
225 return (_edgeOrt == 0 && _faceOrt == 0);
226 }
227
228 KOKKOS_INLINE_FUNCTION
229 void
230 Orientation::setEdgeOrientation(const ordinal_type numEdge, const ordinal_type edgeOrt[]) {
231#ifdef HAVE_INTREPID2_DEBUG
232 INTREPID2_TEST_FOR_ABORT( !((numEdge == 1) || (3 <= numEdge && numEdge <= 12 )),
233 ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): " \
234 "Invalid numEdge");
235#endif
236 _edgeOrt = 0;
237 for (ordinal_type i=0;i<numEdge;++i)
238 _edgeOrt |= (edgeOrt[i] & 1) << i;
239 }
240
241 KOKKOS_INLINE_FUNCTION
242 void
243 Orientation::getEdgeOrientation(ordinal_type *edgeOrt, const ordinal_type numEdge) const {
244#ifdef HAVE_INTREPID2_DEBUG
245 INTREPID2_TEST_FOR_ABORT( !((numEdge == 1) || (3 <= numEdge && numEdge <= 12 )),
246 ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): " \
247 "Invalid numEdge");
248#endif
249 for (ordinal_type i=0;i<numEdge;++i)
250 edgeOrt[i] = (_edgeOrt & (1 << i)) >> i;
251 }
252
253 KOKKOS_INLINE_FUNCTION
254 void
255 Orientation::setFaceOrientation(const ordinal_type numFace, const ordinal_type faceOrt[]) {
256#ifdef HAVE_INTREPID2_DEBUG
257 INTREPID2_TEST_FOR_ABORT( !((numFace == 1) || (4 <= numFace && numFace <= 6 )),
258 ">>> ERROR (Intrepid::Orientation::setFaceOrientation): "
259 "Invalid numFace");
260#endif
261 _faceOrt = 0;
262 for (ordinal_type i=0;i<numFace;++i) {
263 const ordinal_type s = i*3;
264 _faceOrt |= (faceOrt[i] & 7) << s;
265 }
266 }
267
268 KOKKOS_INLINE_FUNCTION
269 void
270 Orientation::getFaceOrientation(ordinal_type *faceOrt, const ordinal_type numFace) const {
271#ifdef HAVE_INTREPID2_DEBUG
272 INTREPID2_TEST_FOR_ABORT( !((numFace == 1) || (4 <= numFace && numFace <= 6 )),
273 ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): "
274 "Invalid numFace");
275#endif
276 for (ordinal_type i=0;i<numFace;++i) {
277 const ordinal_type s = i*3;
278 faceOrt[i] = (_faceOrt & (7 << s)) >> s;
279 }
280 }
281
282 inline std::string Orientation::to_string() const {
283 return "Orientation{ face: " + std::to_string(_faceOrt) + "; edge: " + std::to_string(_edgeOrt) + " }";
284 }
285}
286
287#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