48 #ifndef __INTREPID2_ORIENTATION_DEF_HPP__
49 #define __INTREPID2_ORIENTATION_DEF_HPP__
52 #if defined (__clang__) && !defined (__INTEL_COMPILER)
53 #pragma clang system_header
62 template<
typename elemNodeViewType>
65 Orientation::getElementNodeMap(
typename elemNodeViewType::non_const_value_type *subCellVerts,
66 ordinal_type &numVerts,
67 const shards::CellTopology cellTopo,
68 const elemNodeViewType elemNodes,
69 const ordinal_type subCellDim,
70 const ordinal_type subCellOrd) {
74 subCellVerts[0] = elemNodes(subCellOrd);
78 numVerts = cellTopo.getVertexCount(subCellDim, subCellOrd);
79 for (ordinal_type i=0;i<numVerts;++i)
80 subCellVerts[i] = elemNodes(cellTopo.getNodeMap(subCellDim, subCellOrd, i));
86 template<
typename subCellVertType>
89 Orientation::getOrientation(
const subCellVertType subCellVerts[],
90 const ordinal_type numVerts) {
94 #ifdef HAVE_INTREPID2_DEBUG
95 INTREPID2_TEST_FOR_ABORT( ( subCellVerts[0] == subCellVerts[1] ),
96 ">>> ERROR (Intrepid::Orientation::getOrientation): " \
97 "Invalid subCellVerts, same vertex ids are repeated");
99 ort = (subCellVerts[0] > subCellVerts[1]);
103 #ifdef HAVE_INTREPID2_DEBUG
104 INTREPID2_TEST_FOR_ABORT( ( subCellVerts[0] == subCellVerts[1] ||
105 subCellVerts[0] == subCellVerts[2] ||
106 subCellVerts[1] == subCellVerts[2] ),
107 ">>> ERROR (Intrepid::Orientation::getOrientation): " \
108 "Invalid subCellVerts, same vertex ids are repeated");
110 ordinal_type rotation = 0;
111 for (ordinal_type i=1;i<3;++i)
112 rotation = ( subCellVerts[i] < subCellVerts[rotation] ? i : rotation );
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]]);
117 ort = flip*3 + rotation;
121 #ifdef HAVE_INTREPID2_DEBUG
122 INTREPID2_TEST_FOR_ABORT( ( subCellVerts[0] == subCellVerts[1] ||
123 subCellVerts[0] == subCellVerts[2] ||
124 subCellVerts[0] == subCellVerts[3] ||
125 subCellVerts[1] == subCellVerts[2] ||
126 subCellVerts[1] == subCellVerts[3] ||
127 subCellVerts[2] == subCellVerts[3] ),
128 ">>> ERROR (Intrepid::Orientation::getGlobalVertexNodes): " \
129 "Invalid subCellVerts, same vertex ids are repeated");
131 ordinal_type rotation = 0;
132 for (ordinal_type i=1;i<4;++i)
133 rotation = ( subCellVerts[i] < subCellVerts[rotation] ? i : rotation );
135 const ordinal_type axes[][2] = { {1,3}, {2,0}, {3,1}, {0,2} };
136 const ordinal_type flip = (subCellVerts[axes[rotation][0]] > subCellVerts[axes[rotation][1]]);
138 ort = flip*4 + rotation;
142 INTREPID2_TEST_FOR_ABORT(
true,
143 ">>> ERROR (Intrepid::Orientation::getOrientation): " \
144 "Invalid numVerts (2 (edge),3 (triangle) and 4 (quadrilateral) are allowed)");
151 template<
typename elemNodeViewType>
154 Orientation::getOrientation(
const shards::CellTopology cellTopo,
155 const elemNodeViewType elemNodes) {
157 const ordinal_type nedge = cellTopo.getEdgeCount();
160 typename elemNodeViewType::non_const_value_type vertsSubCell[2];
161 ordinal_type orts[12], nvertSubCell;
162 for (ordinal_type i=0;i<nedge;++i) {
163 Orientation::getElementNodeMap(vertsSubCell,
168 orts[i] = Orientation::getOrientation(vertsSubCell, nvertSubCell);
170 ort.setEdgeOrientation(nedge, orts);
172 const ordinal_type nface = cellTopo.getFaceCount();
174 typename elemNodeViewType::non_const_value_type vertsSubCell[4];
175 ordinal_type orts[6], nvertSubCell;
176 for (ordinal_type i=0;i<nface;++i) {
177 Orientation::getElementNodeMap(vertsSubCell,
182 orts[i] = Orientation::getOrientation(vertsSubCell, nvertSubCell);
184 ort.setFaceOrientation(nface, orts);
191 Orientation::getEdgeOrdinalOfFace(
const ordinal_type subsubcellOrd,
192 const ordinal_type subcellOrd,
193 const shards::CellTopology cellTopo) {
194 ordinal_type r_val = -1;
196 const auto cellBaseKey = cellTopo.getBaseKey();
197 if (cellBaseKey == shards::Hexahedron<>::key) {
198 INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 6) &&
199 !(subsubcellOrd < 4),
201 "subcell and subsubcell information are not correct" );
202 const int quad_to_hex_edges[6][4] = { { 0, 9, 4, 8 },
208 r_val = quad_to_hex_edges[subcellOrd][subsubcellOrd];
209 }
else if (cellBaseKey == shards::Tetrahedron<>::key) {
210 INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 4) &&
211 !(subsubcellOrd < 3),
213 "subcell and subsubcell information are not correct" );
214 const ordinal_type tri_to_tet_edges[4][3] = { { 0, 4, 3 },
218 r_val = tri_to_tet_edges[subcellOrd][subsubcellOrd];
220 INTREPID2_TEST_FOR_EXCEPTION(
true, std::logic_error,
221 "cellTopo is not supported: try TET and HEX" );
226 template<
typename refTanType>
229 Orientation::getReferenceEdgeTangent(
const refTanType &tanE,
230 const ordinal_type subcellOrd,
231 const shards::CellTopology cellTopo,
232 const ordinal_type ort,
233 const bool is_normalize) {
234 const auto cellBaseKey = cellTopo.getBaseKey();
235 INTREPID2_TEST_FOR_EXCEPTION( !(cellBaseKey == shards::Hexahedron<>::key && subcellOrd < 12) &&
236 !(cellBaseKey == shards::Tetrahedron<>::key && subcellOrd < 6) &&
237 !(cellBaseKey == shards::Quadrilateral<>::key && subcellOrd < 4) &&
238 !(cellBaseKey == shards::Triangle<>::key && subcellOrd < 3),
240 "subcell information are not correct" );
241 const ordinal_type i[2][2] = { { 0, 1 },
243 const unsigned int v[2] = { cellTopo.getNodeMap(1, subcellOrd, 0),
244 cellTopo.getNodeMap(1, subcellOrd, 1) };
246 auto normalize = [&](
double *vv, ordinal_type iend) {
248 for (ordinal_type ii=0;ii<iend;++ii)
249 norm += vv[ii]*vv[ii];
250 norm = std::sqrt(norm);
251 for (ordinal_type ii=0;ii<iend;++ii)
255 auto assign_tangent = [&](refTanType t,
double *vv, ordinal_type iend) {
256 for (ordinal_type ii=0;ii<iend;++ii)
261 const int cell_dim = cellTopo.getDimension();
262 if (cellBaseKey == shards::Hexahedron<>::key) {
263 const double hex_verts[8][3] = { { -1.0, -1.0, -1.0 },
271 { -1.0, 1.0, 1.0 } };
272 for (ordinal_type k=0;k<3;++k) {
273 const ordinal_type *ii = &i[ort][0];
274 t[k] = hex_verts[v[ii[1]]][k] - hex_verts[v[ii[0]]][k];
276 }
else if (cellBaseKey == shards::Tetrahedron<>::key) {
277 const double tet_verts[4][3] = { { 0.0, 0.0, 0.0 },
281 for (ordinal_type k=0;k<3;++k) {
282 const ordinal_type *ii = &i[ort][0];
283 t[k] = tet_verts[v[ii[1]]][k] - tet_verts[v[ii[0]]][k];
285 }
else if (cellBaseKey == shards::Quadrilateral<>::key) {
286 const double quad_verts[8][3] = { { -1.0, -1.0 },
290 for (ordinal_type k=0;k<2;++k) {
291 const ordinal_type *ii = &i[ort][0];
292 t[k] = quad_verts[v[ii[1]]][k] - quad_verts[v[ii[0]]][k];
294 }
else if (cellBaseKey == shards::Triangle<>::key) {
295 const double tri_verts[4][3] = { { 0.0, 0.0 },
298 for (ordinal_type k=0;k<2;++k) {
299 const ordinal_type *ii = &i[ort][0];
300 t[k] = tri_verts[v[ii[1]]][k] - tri_verts[v[ii[0]]][k];
303 INTREPID2_TEST_FOR_EXCEPTION(
true, std::logic_error,
304 "cellTopo is not supported: try TET and HEX" );
307 if (is_normalize) normalize(t, cell_dim);
308 assign_tangent(tanE, t, cell_dim);
311 template<
typename refTanType>
314 Orientation::getReferenceFaceTangents(
const refTanType &tanU,
315 const refTanType &tanV,
316 const ordinal_type subcellOrd,
317 const shards::CellTopology cellTopo,
318 const ordinal_type ort,
319 const bool is_normalize) {
320 const auto cellBaseKey = cellTopo.getBaseKey();
322 auto normalize = [&](
double *v, ordinal_type iend) {
324 for (ordinal_type i=0;i<iend;++i)
326 norm = std::sqrt(norm);
327 for (ordinal_type i=0;i<iend;++i)
331 auto assign_tangent = [&](refTanType t,
double *v, ordinal_type iend) {
332 for (ordinal_type i=0;i<iend;++i)
337 if (cellBaseKey == shards::Hexahedron<>::key) {
338 INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 6),
340 "subcell information are not correct" );
341 const double hex_verts[8][3] = { { -1.0, -1.0, -1.0 },
349 { -1.0, 1.0, 1.0 } };
350 const unsigned int v[4] = { cellTopo.getNodeMap(2, subcellOrd, 0),
351 cellTopo.getNodeMap(2, subcellOrd, 1),
352 cellTopo.getNodeMap(2, subcellOrd, 2),
353 cellTopo.getNodeMap(2, subcellOrd, 3) };
354 const ordinal_type i[8][4] = { { 0, 1, 2, 3 },
363 for (ordinal_type k=0;k<3;++k) {
364 const ordinal_type *ii = &i[ort][0];
366 tu[k] = hex_verts[v[ii[1]]][k] - hex_verts[v[ii[0]]][k];
367 tv[k] = hex_verts[v[ii[3]]][k] - hex_verts[v[ii[0]]][k];
370 }
else if (cellBaseKey == shards::Tetrahedron<>::key) {
371 INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 4),
373 "subcell information are not correct" );
374 const double tet_verts[4][3] = { { 0.0, 0.0, 0.0 },
378 const unsigned int v[4] = { cellTopo.getNodeMap(2, subcellOrd, 0),
379 cellTopo.getNodeMap(2, subcellOrd, 1),
380 cellTopo.getNodeMap(2, subcellOrd, 2) };
381 const ordinal_type i[6][3] = { { 0, 1, 2 },
388 for (ordinal_type k=0;k<3;++k) {
389 const ordinal_type *ii = &i[ort][0];
391 tu[k] = tet_verts[v[ii[1]]][k] - tet_verts[v[ii[0]]][k];
392 tv[k] = tet_verts[v[ii[2]]][k] - tet_verts[v[ii[0]]][k];
396 INTREPID2_TEST_FOR_EXCEPTION(
true, std::logic_error,
397 "cellTopo is not supported: try TET and HEX" );
405 assign_tangent(tanU, tu, 3);
406 assign_tangent(tanV, tv, 3);
409 template<
typename refNormalType>
412 Orientation::getReferenceFaceNormal(
const refNormalType &normalV,
413 const ordinal_type subcellOrd,
414 const shards::CellTopology cellTopo,
415 const ordinal_type ort,
416 const bool is_normalize) {
417 const auto cellBaseKey = cellTopo.getBaseKey();
419 auto normalize = [&](
double *v, ordinal_type iend) {
421 for (ordinal_type i=0;i<iend;++i)
423 norm = std::sqrt(norm);
424 for (ordinal_type i=0;i<iend;++i)
428 auto assign_normal = [&](refNormalType n,
double *v, ordinal_type iend) {
429 for (ordinal_type i=0;i<iend;++i)
434 Kokkos::View<double*,Kokkos::HostSpace> tanU(&buf[0][0], 3);
435 Kokkos::View<double*,Kokkos::HostSpace> tanV(&buf[1][0], 3);
437 getReferenceFaceTangents(tanU, tanV,
445 v[0] = tanU(1)*tanV(2) - tanU(2)*tanV(1);
446 v[1] = tanU(2)*tanV(0) - tanU(0)*tanV(2);
447 v[2] = tanU(0)*tanV(1) - tanU(1)*tanV(0);
449 if (is_normalize) normalize(v, 3);
450 assign_normal(normalV, v, 3);
453 KOKKOS_INLINE_FUNCTION
454 Orientation::Orientation()
455 : _edgeOrt(0), _faceOrt(0) {}
457 KOKKOS_INLINE_FUNCTION
459 Orientation::isAlignedToReference()
const {
460 return (_edgeOrt == 0 && _faceOrt == 0);
463 KOKKOS_INLINE_FUNCTION
465 Orientation::setEdgeOrientation(
const ordinal_type numEdge,
const ordinal_type edgeOrt[]) {
466 #ifdef HAVE_INTREPID2_DEBUG
467 INTREPID2_TEST_FOR_ABORT( !( 3 <= numEdge && numEdge <= 12 ),
468 ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): " \
469 "Invalid numEdge (3--12)");
472 for (ordinal_type i=0;i<numEdge;++i)
473 _edgeOrt |= (edgeOrt[i] & 1) << i;
476 KOKKOS_INLINE_FUNCTION
478 Orientation::getEdgeOrientation(ordinal_type *edgeOrt,
const ordinal_type numEdge)
const {
479 #ifdef HAVE_INTREPID2_DEBUG
480 INTREPID2_TEST_FOR_ABORT( !( 3 <= numEdge && numEdge <= 12 ),
481 ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): " \
482 "Invalid numEdge (3--12)");
484 for (ordinal_type i=0;i<numEdge;++i)
485 edgeOrt[i] = (_edgeOrt & (1 << i)) >> i;
488 KOKKOS_INLINE_FUNCTION
490 Orientation::setFaceOrientation(
const ordinal_type numFace,
const ordinal_type faceOrt[]) {
491 #ifdef HAVE_INTREPID2_DEBUG
492 INTREPID2_TEST_FOR_ABORT( !( 4 <= numFace && numFace <= 6 ),
493 ">>> ERROR (Intrepid::Orientation::setFaceOrientation): "
494 "Invalid numFace (4--6)");
497 for (ordinal_type i=0;i<numFace;++i) {
498 const ordinal_type s = i*3;
499 _faceOrt |= (faceOrt[i] & 7) << s;
503 KOKKOS_INLINE_FUNCTION
505 Orientation::getFaceOrientation(ordinal_type *faceOrt,
const ordinal_type numFace)
const {
506 #ifdef HAVE_INTREPID2_DEBUG
507 INTREPID2_TEST_FOR_ABORT( !( 4 <= numFace && numFace <= 6 ),
508 ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): "
509 "Invalid numFace (4--6)");
511 for (ordinal_type i=0;i<numFace;++i) {
512 const ordinal_type s = i*3;
513 faceOrt[i] = (_faceOrt & (7 << s)) >> s;