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  = (input.rank() == output.rank()) ?
 
  174                  Kokkos::subview(input,  cell, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL())
 
  175                : Kokkos::subview(input,        Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
 
  178       for (ordinal_type vertId=0;vertId<numVerts;++vertId) {
 
  179         const ordinal_type i = (
static_cast<size_type
>(vertId) < tagToOrdinal.extent(1) ? tagToOrdinal(0, vertId, 0) : -1);
 
  181           for (ordinal_type j=0;j<numPoints;++j)
 
  182             for (ordinal_type k=0;k<dimBasis;++k)
 
  183               out(i, j, k) = in(i, j, k);
 
  188         const ordinal_type ordIntr = (
static_cast<size_type
>(cellDim) < tagToOrdinal.extent(0) ? tagToOrdinal(cellDim, 0, 0) : -1);
 
  190           const ordinal_type ndofIntr = ordinalToTag(ordIntr, 3);
 
  191           for (ordinal_type i=0;i<ndofIntr;++i) {
 
  192             const ordinal_type ii = tagToOrdinal(cellDim, 0, i);
 
  193             for (ordinal_type j=0;j<numPoints;++j)
 
  194               for (ordinal_type k=0;k<dimBasis;++k)
 
  195                 out(ii, j, k) = in(ii, j, k);
 
  201       ordinal_type existEdgeDofs = 0;
 
  203         ordinal_type ortEdges[12];
 
  204         orts(cell).getEdgeOrientation(ortEdges, numEdges);
 
  207         for (ordinal_type edgeId=0;edgeId<numEdges;++edgeId) {
 
  208           const ordinal_type ordEdge = (1 < tagToOrdinal.extent(0) ? (
static_cast<size_type
>(edgeId) < tagToOrdinal.extent(1) ? tagToOrdinal(1, edgeId, 0) : -1) : -1);
 
  212             const ordinal_type ndofEdge = ordinalToTag(ordEdge, 3);
 
  213             const auto mat = Kokkos::subview(matData,
 
  214                                              edgeId, ortEdges[edgeId],
 
  215                                              Kokkos::ALL(), Kokkos::ALL());
 
  217             for (ordinal_type j=0;j<numPoints;++j)
 
  218               for (ordinal_type i=0;i<ndofEdge;++i) {
 
  219                 const ordinal_type ii = tagToOrdinal(1, edgeId, i);
 
  221                 for (ordinal_type k=0;k<dimBasis;++k) {
 
  222                   input_value_type temp = 0.0;
 
  223                   for (ordinal_type l=0;l<ndofEdge;++l) {
 
  224                     const ordinal_type ll = tagToOrdinal(1, edgeId, l);
 
  225                     temp += mat(i,l)*in(ll, j, k);
 
  227                   out(ii, j, k) = temp;
 
  236         ordinal_type ortFaces[12];
 
  237         orts(cell).getFaceOrientation(ortFaces, numFaces);
 
  240         for (ordinal_type faceId=0;faceId<numFaces;++faceId) {
 
  241           const ordinal_type ordFace = (2 < tagToOrdinal.extent(0) ? (
static_cast<size_type
>(faceId) < tagToOrdinal.extent(1) ? tagToOrdinal(2, faceId, 0) : -1) : -1);
 
  244             const ordinal_type ndofFace = ordinalToTag(ordFace, 3);
 
  245             const auto mat = Kokkos::subview(matData,
 
  246                                              numEdges*existEdgeDofs+faceId, ortFaces[faceId],
 
  247                                              Kokkos::ALL(), Kokkos::ALL());
 
  249             for (ordinal_type j=0;j<numPoints;++j)
 
  250               for (ordinal_type i=0;i<ndofFace;++i) {
 
  251                 const ordinal_type ii = tagToOrdinal(2, faceId, i);
 
  253                 for (ordinal_type k=0;k<dimBasis;++k) {
 
  254                   input_value_type temp = 0.0;
 
  255                   for (ordinal_type l=0;l<ndofFace;++l) {
 
  256                     const ordinal_type ll = tagToOrdinal(2, faceId, l);
 
  257                     temp += mat(i,l)*in(ll, j, k);
 
  259                   out(ii, j, k) = temp;
 
  268   template<
typename SpT>
 
  269   template<
typename outputValueType, 
class ...outputProperties,
 
  270            typename inputValueType,  
class ...inputProperties,
 
  271            typename ortValueType,    
class ...ortProperties,
 
  276                            const Kokkos::DynRankView<inputValueType, inputProperties...>  input,
 
  277                            const Kokkos::DynRankView<ortValueType,   ortProperties...>    orts,
 
  278                            const BasisType* basis ) {
 
  279 #ifdef HAVE_INTREPID2_DEBUG 
  281       if (input.rank() == output.rank())
 
  283         for (size_type i=0;i<input.rank();++i)
 
  284           INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i), std::invalid_argument,
 
  285                                         ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input and output dimension does not match.");
 
  287       else if (input.rank() == output.rank() - 1)
 
  289         for (size_type i=0;i<input.rank();++i)
 
  290           INTREPID2_TEST_FOR_EXCEPTION( input.extent(i) != output.extent(i+1), std::invalid_argument,
 
  291                                        ">>> ERROR (OrientationTools::modifyBasisByOrientation): Input dimensions must match output dimensions exactly, or else match all but the first dimension (in the case that input does not have a 'cell' dimension).");
 
  295         INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
 
  296                                      ">>> ERROR (OrientationTools::modifyBasisByOrientation): input and output ranks must either match, or input rank must be one less than that of output.")
 
  299       INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(output.extent(1)) != basis->getCardinality(), std::invalid_argument,
 
  300                                     ">>> ERROR (OrientationTools::modifyBasisByOrientation): Field dimension of input/output does not match to basis cardinality.");
 
  304     if (basis->requireOrientation()) {
 
  305       auto ordinalToTag = Kokkos::create_mirror_view(
typename SpT::memory_space(), basis->getAllDofTags());
 
  306       auto tagToOrdinal = Kokkos::create_mirror_view(
typename SpT::memory_space(), basis->getAllDofOrdinal());
 
  308       Kokkos::deep_copy(ordinalToTag, basis->getAllDofTags());
 
  309       Kokkos::deep_copy(tagToOrdinal, basis->getAllDofOrdinal());
 
  312         numCells  = output.extent(0),
 
  314         numPoints = output.extent(2),
 
  315         dimBasis  = output.extent(3); 
 
  318       const shards::CellTopology cellTopo = basis->getBaseCellTopology();
 
  321         cellDim = cellTopo.getDimension(),
 
  322         numVerts = cellTopo.getVertexCount()*ordinal_type(basis->getDofCount(0, 0) > 0),
 
  323         numEdges = cellTopo.getEdgeCount()*ordinal_type(basis->getDofCount(1, 0) > 0),
 
  324         numFaces = cellTopo.getFaceCount();
 
  326       const Kokkos::RangePolicy<SpT> policy(0, numCells);
 
  329          decltype(output),decltype(input),
 
  330          decltype(ordinalToTag),decltype(tagToOrdinal),
 
  331          decltype(matData)> FunctorType;
 
  332       Kokkos::parallel_for(policy,
 
  335                                        ordinalToTag, tagToOrdinal,
 
  337                                        cellDim, numVerts, numEdges, numFaces,
 
  338                                        numPoints, dimBasis));
 
  340       Kokkos::deep_copy(output, input);