48 #ifndef __INTREPID2_ORIENTATIONTOOLS_DEF_MODIFY_BASIS_HPP__ 
   49 #define __INTREPID2_ORIENTATIONTOOLS_DEF_MODIFY_BASIS_HPP__ 
   52 #if defined (__clang__) && !defined (__INTEL_COMPILER) 
   53 #pragma clang system_header 
   58   template<
typename SpT>
 
   59   template<
typename ptViewType>
 
   60   KOKKOS_INLINE_FUNCTION
 
   63 #ifdef HAVE_INTREPID2_DEBUG 
   64     INTREPID2_TEST_FOR_ABORT( pts.rank() != 2,  
 
   65                               ">>> ERROR (Intrepid::OrientationTools::isLeftHandedCell): " \
 
   66                               "Point array is supposed to have rank 2.");
 
   68     typedef typename ptViewType::value_type value_type;
 
   70     const auto dim = pts.extent(1);
 
   75       const value_type v[2][2] = { { pts(1,0) - pts(0,0), pts(1,1) - pts(0,1) },
 
   76                                    { pts(2,0) - pts(0,0), pts(2,1) - pts(0,1) } };
 
   78       det = (v[0][0]*v[1][1] - v[1][0]*v[0][1]);
 
   83       const value_type v[3][3] = { { pts(1,0) - pts(0,0), pts(1,1) - pts(0,1), pts(1,2) - pts(0,2) },
 
   84                                    { pts(2,0) - pts(0,0), pts(2,1) - pts(0,1), pts(2,2) - pts(0,2) },
 
   85                                    { pts(3,0) - pts(0,0), pts(3,1) - pts(0,1), pts(3,2) - pts(0,2) } };
 
   87       det = (v[0][0] * v[1][1] * v[2][2] +
 
   88              v[0][1] * v[1][2] * v[2][0] +
 
   89              v[0][2] * v[1][0] * v[2][1] -
 
   90              v[0][2] * v[1][1] * v[2][0] -
 
   91              v[0][0] * v[1][2] * v[2][1] -
 
   92              v[0][1] * v[1][0] * v[2][2]);
 
   96       INTREPID2_TEST_FOR_ABORT( 
true,
 
   97                                 ">>> ERROR (Intrepid::Orientation::isLeftHandedCell): " \
 
   98                                 "Dimension of points must be 2 or 3");
 
  104   template<
typename SpT>
 
  105   template<
typename elemOrtValueType, 
class ...elemOrtProperties,
 
  106            typename elemNodeValueType, 
class ...elemNodeProperties>
 
  109   getOrientation(      Kokkos::DynRankView<elemOrtValueType,elemOrtProperties...> elemOrts,
 
  110                  const Kokkos::DynRankView<elemNodeValueType,elemNodeProperties...> elemNodes,
 
  111                  const shards::CellTopology cellTopo) {
 
  113     typedef typename Kokkos::Impl::is_space<SpT>::host_mirror_space::execution_space host_space_type;
 
  114     auto elemOrtsHost = Kokkos::create_mirror_view(
typename host_space_type::memory_space(), elemOrts);
 
  115     auto elemNodesHost = Kokkos::create_mirror_view_and_copy(
typename host_space_type::memory_space(), elemNodes);
 
  117     const ordinal_type numCells = elemNodes.extent(0);
 
  118     for (
auto cell=0;cell<numCells;++cell) {
 
  119       const auto nodes = Kokkos::subview(elemNodesHost, cell, Kokkos::ALL());
 
  120       elemOrtsHost(cell) = Orientation::getOrientation(cellTopo, nodes);
 
  123     Kokkos::deep_copy(elemOrts, elemOrtsHost);
 
  126   template<
typename ortViewType,
 
  127            typename OutputViewType,
 
  128            typename inputViewType,
 
  129            typename o2tViewType,
 
  130            typename t2oViewType,
 
  131            typename dataViewType>
 
  134     OutputViewType output;
 
  136     o2tViewType ordinalToTag;
 
  137     t2oViewType tagToOrdinal;
 
  139     const dataViewType matData;
 
  140     const ordinal_type cellDim, numVerts, numEdges, numFaces, numPoints, dimBasis;
 
  143                                OutputViewType output_,
 
  144                                inputViewType input_,
 
  145                                o2tViewType ordinalToTag_,
 
  146                                t2oViewType tagToOrdinal_,
 
  147                                const dataViewType matData_,
 
  148                                const ordinal_type cellDim_,
 
  149                                const ordinal_type numVerts_,
 
  150                                const ordinal_type numEdges_,
 
  151                                const ordinal_type numFaces_,
 
  152                                const ordinal_type numPoints_,
 
  153                                const ordinal_type dimBasis_)
 
  157       ordinalToTag(ordinalToTag_),
 
  158       tagToOrdinal(tagToOrdinal_),
 
  164       numPoints(numPoints_),
 
  168     KOKKOS_INLINE_FUNCTION
 
  169     void operator()(
const ordinal_type cell)
 const {
 
  170       typedef typename inputViewType::non_const_value_type input_value_type;
 
  172       auto out = Kokkos::subview(output, cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
 
  173       auto in  = Kokkos::subview(input,  cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
 
  176       for (ordinal_type vertId=0;vertId<numVerts;++vertId) {
 
  177         const ordinal_type i = (
static_cast<size_type
>(vertId) < tagToOrdinal.extent(1) ? tagToOrdinal(0, vertId, 0) : -1);
 
  179           for (ordinal_type j=0;j<numPoints;++j)
 
  180             for (ordinal_type k=0;k<dimBasis;++k)
 
  181               out(i, j, k) = in(i, j, k);
 
  186         const ordinal_type ordIntr = (
static_cast<size_type
>(cellDim) < tagToOrdinal.extent(0) ? tagToOrdinal(cellDim, 0, 0) : -1);
 
  188           const ordinal_type ndofIntr = ordinalToTag(ordIntr, 3);
 
  189           for (ordinal_type i=0;i<ndofIntr;++i) {
 
  190             const ordinal_type ii = tagToOrdinal(cellDim, 0, i);
 
  191             for (ordinal_type j=0;j<numPoints;++j)
 
  192               for (ordinal_type k=0;k<dimBasis;++k)
 
  193                 out(ii, j, k) = in(ii, j, k);
 
  199       ordinal_type existEdgeDofs = 0;
 
  201         ordinal_type ortEdges[12];
 
  202         orts(cell).getEdgeOrientation(ortEdges, numEdges);
 
  205         for (ordinal_type edgeId=0;edgeId<numEdges;++edgeId) {
 
  206           const ordinal_type ordEdge = (1 < tagToOrdinal.extent(0) ? (
static_cast<size_type
>(edgeId) < tagToOrdinal.extent(1) ? tagToOrdinal(1, edgeId, 0) : -1) : -1);
 
  210             const ordinal_type ndofEdge = ordinalToTag(ordEdge, 3);
 
  211             const auto mat = Kokkos::subview(matData,
 
  212                                              edgeId, ortEdges[edgeId],
 
  213                                              Kokkos::ALL(), Kokkos::ALL());
 
  215             for (ordinal_type j=0;j<numPoints;++j)
 
  216               for (ordinal_type i=0;i<ndofEdge;++i) {
 
  217                 const ordinal_type ii = tagToOrdinal(1, edgeId, i);
 
  219                 for (ordinal_type k=0;k<dimBasis;++k) {
 
  220                   input_value_type temp = 0.0;
 
  221                   for (ordinal_type l=0;l<ndofEdge;++l) {
 
  222                     const ordinal_type ll = tagToOrdinal(1, edgeId, l);
 
  223                     temp += mat(i,l)*in(ll, j, k);
 
  225                   out(ii, j, k) = temp;
 
  234         ordinal_type ortFaces[12];
 
  235         orts(cell).getFaceOrientation(ortFaces, numFaces);
 
  238         for (ordinal_type faceId=0;faceId<numFaces;++faceId) {
 
  239           const ordinal_type ordFace = (2 < tagToOrdinal.extent(0) ? (
static_cast<size_type
>(faceId) < tagToOrdinal.extent(1) ? tagToOrdinal(2, faceId, 0) : -1) : -1);
 
  242             const ordinal_type ndofFace = ordinalToTag(ordFace, 3);
 
  243             const auto mat = Kokkos::subview(matData,
 
  244                                              numEdges*existEdgeDofs+faceId, ortFaces[faceId],
 
  245                                              Kokkos::ALL(), Kokkos::ALL());
 
  247             for (ordinal_type j=0;j<numPoints;++j)
 
  248               for (ordinal_type i=0;i<ndofFace;++i) {
 
  249                 const ordinal_type ii = tagToOrdinal(2, faceId, i);
 
  251                 for (ordinal_type k=0;k<dimBasis;++k) {
 
  252                   input_value_type temp = 0.0;
 
  253                   for (ordinal_type l=0;l<ndofFace;++l) {
 
  254                     const ordinal_type ll = tagToOrdinal(2, faceId, l);
 
  255                     temp += mat(i,l)*in(ll, j, k);
 
  257                   out(ii, j, k) = temp;
 
  266   template<
typename SpT>
 
  267   template<
typename outputValueType, 
class ...outputProperties,
 
  268            typename inputValueType,  
class ...inputProperties,
 
  269            typename ortValueType,    
class ...ortProperties,
 
  270            typename BasisPtrType>
 
  274                            const Kokkos::DynRankView<inputValueType, inputProperties...>  input,
 
  275                            const Kokkos::DynRankView<ortValueType,   ortProperties...>    orts,
 
  276                            const BasisPtrType basis ) {
 
  277 #ifdef HAVE_INTREPID2_DEBUG 
  279       INTREPID2_TEST_FOR_EXCEPTION( input.rank() != output.rank(), std::invalid_argument,
 
  280                                     ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input and output rank are not 3.");
 
  281       for (size_type i=0;i<input.rank();++i)
 
  282         INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i), std::invalid_argument,
 
  283                                       ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input and output dimension does not match.");
 
  285       INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(input.extent(1)) != basis->getCardinality(), std::invalid_argument,
 
  286                                     ">>> ERROR (OrientationTools::modifyBasisByOrientation): Field dimension of input/output does not match to basis cardinality.");
 
  290     if (basis->requireOrientation()) {
 
  291       auto ordinalToTag = Kokkos::create_mirror_view(
typename SpT::memory_space(), basis->getAllDofTags());
 
  292       auto tagToOrdinal = Kokkos::create_mirror_view(
typename SpT::memory_space(), basis->getAllDofOrdinal());
 
  294       Kokkos::deep_copy(ordinalToTag, basis->getAllDofTags());
 
  295       Kokkos::deep_copy(tagToOrdinal, basis->getAllDofOrdinal());
 
  298         numCells  = output.extent(0),
 
  300         numPoints = output.extent(2),
 
  301         dimBasis  = output.extent(3); 
 
  304       const shards::CellTopology cellTopo = basis->getBaseCellTopology();
 
  307         cellDim = cellTopo.getDimension(),
 
  308         numVerts = cellTopo.getVertexCount()*ordinal_type(basis->getDofCount(0, 0) > 0),
 
  309         numEdges = cellTopo.getEdgeCount()*ordinal_type(basis->getDofCount(1, 0) > 0),
 
  310         numFaces = cellTopo.getFaceCount();
 
  312       const Kokkos::RangePolicy<SpT> policy(0, numCells);
 
  315          decltype(output),decltype(input),
 
  316          decltype(ordinalToTag),decltype(tagToOrdinal),
 
  317          decltype(matData)> FunctorType;
 
  318       Kokkos::parallel_for(policy,
 
  321                                        ordinalToTag, tagToOrdinal,
 
  323                                        cellDim, numVerts, numEdges, numFaces,
 
  324                                        numPoints, dimBasis));
 
  326       Kokkos::deep_copy(output, input);