29 #ifndef __INTREPID2_ORIENTATIONTOOLS_DEF_COEFF_MATRIX_HCURL_HPP__ 
   30 #define __INTREPID2_ORIENTATIONTOOLS_DEF_COEFF_MATRIX_HCURL_HPP__ 
   37 #if defined (__clang__) && !defined (__INTEL_COMPILER) 
   38 #pragma clang system_header 
   47 #ifdef HAVE_INTREPID2_DEBUG 
   48 template<
typename subcellBasisType,
 
   49 typename cellBasisType>
 
   52 check_getCoeffMatrix_HCURL(
const subcellBasisType& subcellBasis,
 
   53     const cellBasisType& cellBasis,
 
   54     const ordinal_type subcellId,
 
   55     const ordinal_type subcellOrt) {
 
   56   const shards::CellTopology cellTopo = cellBasis.getBaseCellTopology();
 
   57   const shards::CellTopology subcellTopo = subcellBasis.getBaseCellTopology();
 
   59   const ordinal_type cellDim = cellTopo.getDimension();
 
   60   const ordinal_type subcellDim = subcellTopo.getDimension();
 
   64   INTREPID2_TEST_FOR_EXCEPTION( subcellDim > cellDim,
 
   66       ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " \
 
   67       "cellDim cannot be smaller than subcellDim.");
 
   69   const auto subcellBaseKey = subcellTopo.getBaseKey();
 
   70   const auto cellBaseKey = cellTopo.getBaseKey();
 
   72   INTREPID2_TEST_FOR_EXCEPTION( subcellBaseKey != shards::Line<>::key &&
 
   73       subcellBaseKey != shards::Quadrilateral<>::key &&
 
   74       subcellBaseKey != shards::Triangle<>::key,
 
   76       ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " \
 
   77       "subcellBasis must have line, quad, or triangle topology.");
 
   79   INTREPID2_TEST_FOR_EXCEPTION( cellBaseKey != shards::Quadrilateral<>::key &&
 
   80       cellBaseKey != shards::Triangle<>::key &&
 
   81       cellBaseKey != shards::Hexahedron<>::key &&
 
   82       cellBaseKey != shards::Wedge<>::key &&
 
   83       cellBaseKey != shards::Tetrahedron<>::key,
 
   85       ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " \
 
   86       "cellBasis must have quad, triangle, hexhedron or tetrahedron topology.");
 
   92     const bool cellBasisIsHCURL = cellBasis.getFunctionSpace() == FUNCTION_SPACE_HCURL;
 
   95     if (cellBasisIsHCURL) {
 
   96       const bool subcellBasisIsHGRAD = subcellBasis.getFunctionSpace() == FUNCTION_SPACE_HGRAD;
 
   97       const bool subcellBasisIsHVOL  = subcellBasis.getFunctionSpace() == FUNCTION_SPACE_HVOL;
 
   98       const bool subcellBasisIsHCURL = subcellBasis.getFunctionSpace() == FUNCTION_SPACE_HCURL;
 
   99       const bool cellIsTri  = cellBaseKey == shards::Triangle<>::key;
 
  100       const bool cellIsTet  = cellBaseKey == shards::Tetrahedron<>::key;
 
  101       const bool cellIsHex  = cellBaseKey == shards::Hexahedron<>::key;
 
  102       const bool cellIsQuad = cellBaseKey == shards::Quadrilateral<>::key;
 
  106       switch (subcellDim) {
 
  109         if (cellIsHex || cellIsQuad) {
 
  110           INTREPID2_TEST_FOR_EXCEPTION( !(subcellBasisIsHGRAD||subcellBasisIsHVOL),
 
  112               ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " 
  113               "subcellBasis function space (1d) is not consistent to cellBasis.");
 
  114         } 
else if (cellIsTet || cellIsTri) {
 
  115           INTREPID2_TEST_FOR_EXCEPTION( !subcellBasisIsHVOL,
 
  117               ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " 
  118               "subcellBasis function space (1d) is not consistent to cellBasis.");
 
  123         INTREPID2_TEST_FOR_EXCEPTION( !subcellBasisIsHCURL,
 
  125             ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " 
  126             "subcellBasis function space (2d) is not consistent to cellBasis.");
 
  136 template<
typename OutputViewType,
 
  137 typename subcellBasisHostType,
 
  138 typename cellBasisHostType>
 
  143     const subcellBasisHostType& subcellBasis,
 
  144     const cellBasisHostType& cellBasis,
 
  145     const ordinal_type subcellId,
 
  146     const ordinal_type subcellOrt,
 
  147     const bool inverse) {
 
  149 #ifdef HAVE_INTREPID2_DEBUG 
  150   Debug::check_getCoeffMatrix_HCURL(subcellBasis,cellBasis,subcellId,subcellOrt);
 
  153   using value_type = 
typename OutputViewType::non_const_value_type;
 
  154   using host_device_type = 
typename Kokkos::HostSpace::device_type;
 
  160   const shards::CellTopology cellTopo = cellBasis.getBaseCellTopology();
 
  161   const shards::CellTopology subcellTopo = subcellBasis.getBaseCellTopology();
 
  162   const ordinal_type cellDim = cellTopo.getDimension();
 
  163   const ordinal_type subcellDim = subcellTopo.getDimension();
 
  164   const auto subcellBaseKey = subcellTopo.getBaseKey();
 
  165   const ordinal_type numCellBasis = cellBasis.getCardinality();
 
  166   const ordinal_type numSubcellBasis = subcellBasis.getCardinality();
 
  167   const ordinal_type ndofSubcell = cellBasis.getDofCount(subcellDim,subcellId);
 
  174   Kokkos::DynRankView<value_type,host_device_type> subcellTangents(
"subcellTangents", numSubcellBasis, subcellDim);
 
  175   auto degree = subcellBasis.getDegree();
 
  176   BasisPtr<host_device_type, value_type, value_type> basisPtr;
 
  177   if(subcellBaseKey == shards::Line<>::key) {
 
  179     basisPtr->getDofCoeffs(Kokkos::subview(subcellTangents, Kokkos::ALL(),0));
 
  180   } 
else if (subcellBaseKey == shards::Triangle<>::key) {
 
  182     basisPtr->getDofCoeffs(subcellTangents);
 
  183   } 
else if (subcellBaseKey == shards::Quadrilateral<>::key) {
 
  185     basisPtr->getDofCoeffs(subcellTangents);
 
  189   Kokkos::DynRankView<value_type,host_device_type> subcellDofCoords(
"subcellDofCoords", basisPtr->getCardinality(), subcellDim);
 
  190   basisPtr->getDofCoords(subcellDofCoords);
 
  191   INTREPID2_TEST_FOR_EXCEPTION( basisPtr->getDofCount(subcellDim,0) != ndofSubcell,
 
  193       ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " \
 
  194       "the number of basisPtr internal DoFs should equate those of the subcell");
 
  197   Kokkos::DynRankView<value_type,host_device_type> refPtsSubcell(
"refPtsSubcell", ndofSubcell, subcellDim);
 
  198   Kokkos::DynRankView<value_type,host_device_type> refSubcellTangents(
"subcellTangents", ndofSubcell, subcellDim);
 
  199   auto tagToOrdinal = basisPtr->getAllDofOrdinal();
 
  200   for (ordinal_type i=0;i<ndofSubcell;++i) {
 
  201     ordinal_type isc = tagToOrdinal(subcellDim, 0, i);
 
  202     for(ordinal_type d=0; d <subcellDim; ++d){
 
  203       refPtsSubcell(i,d) = subcellDofCoords(isc,d);
 
  204       for(ordinal_type k=0; k <subcellDim; ++k)
 
  205         refSubcellTangents(i,d) = subcellTangents(isc,d);
 
  214   Kokkos::DynRankView<value_type,host_device_type> subCellValues(
"subCellValues", numSubcellBasis, ndofSubcell, subcellDim);
 
  216     auto lineValues = Kokkos::subview(subCellValues, Kokkos::ALL(), Kokkos::ALL(), 0);
 
  217     subcellBasis.getValues(lineValues, refPtsSubcell, OPERATOR_VALUE);
 
  219     subcellBasis.getValues(subCellValues, refPtsSubcell, OPERATOR_VALUE);
 
  226   Kokkos::DynRankView<value_type,host_device_type> refPtsCell(
"refPtsCell", ndofSubcell, cellDim);
 
  227   Kokkos::DynRankView<value_type,host_device_type> trJacobianF(
"trJacobianF", subcellDim, cellDim );
 
  229   if(cellDim == subcellDim) {
 
  234     Kokkos::DynRankView<value_type,host_device_type> jac(
"data", subcellDim, subcellDim);
 
  236     for(ordinal_type d=0; d<subcellDim; ++d)
 
  237       for(ordinal_type j=0; j<cellDim; ++j) {
 
  238         trJacobianF(j,d) = jac(d,j);
 
  251   Kokkos::DynRankView<value_type,host_device_type> cellBasisValues(
"cellBasisValues", numCellBasis, ndofSubcell, cellDim);
 
  252   cellBasis.getValues(cellBasisValues, refPtsCell, OPERATOR_VALUE);
 
  261   Kokkos::DynRankView<value_type,Kokkos::LayoutLeft,host_device_type> 
 
  262     PsiMat(
"PsiMat", ndofSubcell, ndofSubcell),
 
  263     PhiMat(
"PhiMat", ndofSubcell, ndofSubcell),
 
  267   auto cellTagToOrdinal = cellBasis.getAllDofOrdinal();
 
  268   auto subcellTagToOrdinal = subcellBasis.getAllDofOrdinal();
 
  270   for (ordinal_type i=0;i<ndofSubcell;++i) {
 
  271     const ordinal_type ic = cellTagToOrdinal(subcellDim, subcellId, i);
 
  272     for (ordinal_type j=0;j<ndofSubcell;++j) {
 
  273       const ordinal_type isc = subcellTagToOrdinal(subcellDim, 0, i);
 
  274       value_type refEntry = 0, ortEntry =0;
 
  275       for (ordinal_type k=0;k<subcellDim;++k) {
 
  276         ortEntry += subCellValues(isc,j,k)*refSubcellTangents(j,k);
 
  277         for (ordinal_type d=0; d<cellDim; ++d)
 
  278           refEntry +=  cellBasisValues(ic,j,d)*trJacobianF(k,d)*refSubcellTangents(j,k);
 
  280       PsiMat(j,i) = refEntry;
 
  281       PhiMat(j,i) = ortEntry;
 
  285   RefMat = inverse ? PhiMat : PsiMat;
 
  286   OrtMat = inverse ? PsiMat : PhiMat;
 
  290     Teuchos::LAPACK<ordinal_type,value_type> lapack;
 
  291     ordinal_type info = 0;
 
  305     Kokkos::DynRankView<ordinal_type,host_device_type> pivVec(
"pivVec", ndofSubcell);
 
  306     lapack.GESV(ndofSubcell, ndofSubcell,
 
  315       std::stringstream ss;
 
  316       ss << 
">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " 
  317           << 
"LAPACK return with error code: " 
  319       INTREPID2_TEST_FOR_EXCEPTION( 
true, std::runtime_error, ss.str().c_str() );
 
  325       const double eps = tolerence();
 
  326       for (ordinal_type i=0;i<ndofSubcell;++i) {
 
  327         auto intmatii = std::round(OrtMat(i,i));
 
  328         OrtMat(i,i) = (std::abs(OrtMat(i,i) - intmatii) < eps) ? intmatii : OrtMat(i,i);
 
  329         for (ordinal_type j=i+1;j<ndofSubcell;++j) {
 
  330           auto matij = OrtMat(i,j);
 
  332           auto intmatji = std::round(OrtMat(j,i));
 
  333           OrtMat(i,j) = (std::abs(OrtMat(j,i) - intmatji) < eps) ? intmatji : OrtMat(j,i);
 
  335           auto intmatij = std::round(matij);
 
  336           OrtMat(j,i) = (std::abs(matij - intmatij) < eps) ? intmatij : matij;
 
  362     const Kokkos::pair<ordinal_type,ordinal_type> range(0, ndofSubcell);
 
  363     auto suboutput = Kokkos::subview(output, range, range);
 
  364     auto tmp = Kokkos::create_mirror_view_and_copy(
typename OutputViewType::device_type::memory_space(), OrtMat);
 
  365     Kokkos::deep_copy(suboutput, tmp);
 
Implementation of the default H(curl)-compatible FEM basis on Quadrilateral cell. ...
 
static ConstViewType get(const ordinal_type subcellDim, const unsigned parentCellKey)
Returns a Kokkos view with the coefficients of the parametrization maps for the edges or faces of a r...
 
Header file for the Intrepid2::Basis_HVOL_LINE_Cn_FEM class. 
 
Header file for the Intrepid2::Basis_HCURL_QUAD_In_FEM class. 
 
Implementation of the locally HVOL-compatible FEM basis of variable order on the [-1,1] reference line cell, using Lagrange polynomials. 
 
Implementation of the default H(curl)-compatible Nedelec (first kind) basis of arbitrary degree on Tr...
 
Header file for the Intrepid2::Basis_HCURL_TRI_In_FEM class.