58 #ifndef __INTREPID2_ORIENTATIONTOOLS_DEF_COEFF_MATRIX_HDIV_HPP__ 
   59 #define __INTREPID2_ORIENTATIONTOOLS_DEF_COEFF_MATRIX_HDIV_HPP__ 
   62 #if defined (__clang__) && !defined (__INTEL_COMPILER) 
   63 #pragma clang system_header 
   68   template<
typename ExecSpaceType,
 
   69            typename outputValueType,
 
   70            typename pointValueType>
 
   71   class Basis_HDIV_TET_In_FEM;
 
   75     template<
typename OutputViewType,
 
   76              typename subcellBasisType,
 
   77              typename cellBasisType>
 
   82                         const subcellBasisType subcellBasis,
 
   83                         const cellBasisType cellBasis,
 
   84                         const ordinal_type subcellId,
 
   85                         const ordinal_type subcellOrt) {
 
   86       typedef typename OutputViewType::execution_space space_type;
 
   87       typedef typename OutputViewType::value_type value_type;
 
   91         Kokkos::Impl::is_space<space_type>::host_mirror_space::execution_space host_space_type;
 
   93       typedef Kokkos::DynRankView<value_type,host_space_type> DynRankViewHostType;
 
  100       const shards::CellTopology cellTopo = cellBasis.getBaseCellTopology();
 
  101       const shards::CellTopology subcellTopo = subcellBasis.getBaseCellTopology();
 
  103       const ordinal_type cellDim = cellTopo.getDimension();
 
  104       const ordinal_type subcellDim = subcellTopo.getDimension();
 
  106       INTREPID2_TEST_FOR_EXCEPTION( subcellDim >= cellDim,
 
  108                                     ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HDIV): " \
 
  109                                     "cellDim must be greater than subcellDim.");
 
  111       const auto subcellBaseKey = subcellTopo.getBaseKey();
 
  112       const auto cellBaseKey = cellTopo.getBaseKey();
 
  114       INTREPID2_TEST_FOR_EXCEPTION( subcellBaseKey != shards::Line<>::key &&
 
  115                                     subcellBaseKey != shards::Quadrilateral<>::key &&
 
  116                                     subcellBaseKey != shards::Triangle<>::key,
 
  118                                     ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HDIV): " \
 
  119                                     "subcellBasis must have line, quad, or triangle topology.");
 
  121       INTREPID2_TEST_FOR_EXCEPTION( cellBaseKey != shards::Quadrilateral<>::key &&
 
  122                                     cellBaseKey != shards::Triangle<>::key &&
 
  123                                     cellBaseKey != shards::Hexahedron<>::key &&
 
  124                                     cellBaseKey != shards::Tetrahedron<>::key,
 
  126                                     ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HDIV): " \
 
  127                                     "cellBasis must have quad, triangle, hexhedron or tetrahedron topology.");
 
  133         const bool isHDIV = cellBasis.getFunctionSpace() == FUNCTION_SPACE_HDIV;
 
  134         INTREPID2_TEST_FOR_EXCEPTION( !isHDIV,
 
  136                                       ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HDIV): " 
  137                                       "cellBasis is not HDIV.");
 
  139           const bool subcellBasisIsHGRAD = subcellBasis.getFunctionSpace() == FUNCTION_SPACE_HGRAD;
 
  140           const bool subcellBasisIsHVOL  = subcellBasis.getFunctionSpace() == FUNCTION_SPACE_HVOL;
 
  141           const bool cellIsTri  = cellBaseKey == shards::Triangle<>::key;
 
  142           const bool cellIsTet  = cellBaseKey == shards::Tetrahedron<>::key;
 
  143           const bool cellIsHex  = cellBaseKey == shards::Hexahedron<>::key;
 
  144           const bool cellIsQuad = cellBaseKey == shards::Quadrilateral<>::key;
 
  146           const std::string subcellBasisName(subcellBasis.getName());
 
  147           switch (subcellDim) {
 
  150             if (cellIsHex || cellIsQuad) {
 
  151               INTREPID2_TEST_FOR_EXCEPTION( !subcellBasisIsHGRAD,
 
  153                                           ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_DIV): "  
  154                                           "subcellBasis function space (1d) is not consistent to cellBasis, which should be open line hgrad, order -1.");
 
  155             } 
else if (cellIsTet || cellIsTri) {
 
  156               INTREPID2_TEST_FOR_EXCEPTION( !subcellBasisIsHVOL,
 
  158                                           ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_DIV): "  
  159                                           "subcellBasis function space (1d) is not consistent to cellBasis, which should be HVOL line, order -1.");
 
  164             if        (subcellBaseKey == shards::Quadrilateral<>::key) {
 
  166               INTREPID2_TEST_FOR_EXCEPTION( !subcellBasisIsHGRAD,
 
  168                                             ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HDIV): " 
  169                                             "subcellBasis function space is not compatible, which should be open line hgrad, order -1.");
 
  170             } 
else if (subcellBaseKey == shards::Triangle<>::key) {
 
  172               INTREPID2_TEST_FOR_EXCEPTION( !subcellBasisIsHVOL,
 
  174                                             ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HDIV): " 
  175                                             "subcellBasis function space is not compatible, which should HVOL, order-1.");
 
  186       const ordinal_type numCellBasis = cellBasis.getCardinality();
 
  187       const ordinal_type numSubcellBasis = subcellBasis.getCardinality();
 
  189       const ordinal_type ordSubcell = cellBasis.getDofOrdinal(subcellDim, subcellId, 0);
 
  190       INTREPID2_TEST_FOR_EXCEPTION( ordSubcell == -1,
 
  192                                     ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HDIV): " \
 
  193                                     "Invalid subcellId returns -1 ordSubcell.");
 
  195       const ordinal_type ndofSubcell = cellBasis.getDofTag(ordSubcell)(3);
 
  198       DynRankViewHostType refPtsSubcell(
"refPtsSubcell", ndofSubcell, subcellDim);
 
  199       DynRankViewHostType subcellDofCoords(
"subcellDofCoords", numSubcellBasis, subcellDim);
 
  200       subcellBasis.getDofCoords(subcellDofCoords);
 
  201       for(ordinal_type i=0; i<ndofSubcell; ++i)
 
  202         for(ordinal_type d=0; d <subcellDim; ++d)
 
  203           refPtsSubcell(i,d) = subcellDofCoords(subcellBasis.getDofOrdinal(subcellDim, 0, i),d);
 
  206       DynRankViewHostType ortPtsSubcell(
"ortPtsSubcell", ndofSubcell, subcellDim);
 
  213       DynRankViewHostType refPtsCell(
"refPtsCell", ndofSubcell, cellDim);
 
  223       DynRankViewHostType refValues(
"refValues", numCellBasis, ndofSubcell, cellDim);
 
  224       cellBasis.getValues(refValues, refPtsCell, OPERATOR_VALUE);
 
  227       DynRankViewHostType ortJacobian(
"ortJacobian", subcellDim, subcellDim);
 
  229       auto ortJacobianDet = (subcellDim == 1) ? ortJacobian(0,0) :
 
  230                                  ortJacobian(0,0)*ortJacobian(1,1)-ortJacobian(1,0)*ortJacobian(0,1);
 
  235       DynRankViewHostType sideNormal(
"sideNormal", cellDim);
 
  238       if((cellBaseKey == shards::Triangle<>::key))
 
  239         for(ordinal_type i=0; i<cellDim; ++i)
 
  242       Kokkos::View<value_type**,Kokkos::LayoutLeft,host_space_type>
 
  243         refMat(
"refMat", ndofSubcell, ndofSubcell),
 
  244         ortMat(
"ortMat", ndofSubcell, ndofSubcell);
 
  245       DynRankViewHostType tmpValues(
"tmpValues", numCellBasis, ndofSubcell);
 
  246       for (ordinal_type i=0;i<ndofSubcell;++i) {
 
  247         const ordinal_type ii = cellBasis.getDofOrdinal(subcellDim, subcellId, i);
 
  248         for (ordinal_type j=0;j<ndofSubcell;++j)
 
  249           for (ordinal_type k=0;k<cellDim;++k) {
 
  250             refMat(i,j) += refValues(ii,j,k)*sideNormal(k)* ortJacobianDet;
 
  251             ortMat(i,j) = (i==j);  
 
  257         Teuchos::LAPACK<ordinal_type,value_type> lapack;
 
  258         ordinal_type info = 0;
 
  259         Kokkos::View<value_type**,Kokkos::LayoutLeft,host_space_type> pivVec(
"pivVec", ndofSubcell, 1);
 
  261         lapack.GESV(ndofSubcell, ndofSubcell,
 
  264                     (ordinal_type*)pivVec.data(),
 
  270           std::stringstream ss;
 
  271           ss << 
">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HDIV): " 
  272              << 
"LAPACK return with error code: " 
  274           INTREPID2_TEST_FOR_EXCEPTION( 
true, std::runtime_error, ss.str().c_str() );
 
  279           const double eps = threshold();
 
  280           for (ordinal_type i=0;i<ndofSubcell;++i)
 
  281             for (ordinal_type j=0;j<ndofSubcell;++j) {
 
  282               auto intOrtMat = std::round(ortMat(i,j));
 
  283               ortMat(i,j) = (std::abs(ortMat(i,j) - std::round(ortMat(i,j))) < eps) ? intOrtMat : ortMat(i,j);
 
  290         const Kokkos::pair<ordinal_type,ordinal_type> range(0, ndofSubcell);
 
  291         Kokkos::deep_copy(Kokkos::subview(output, range, range),
 
  292                           Kokkos::subview(ortMat, range, range));