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;