62 #ifndef __INTREPID2_ORIENTATIONTOOLS_DEF_COEFF_MATRIX_HCURL_HPP__
63 #define __INTREPID2_ORIENTATIONTOOLS_DEF_COEFF_MATRIX_HCURL_HPP__
70 #if defined (__clang__) && !defined (__INTEL_COMPILER)
71 #pragma clang system_header
80 #ifdef HAVE_INTREPID2_DEBUG
81 template<
typename subcellBasisType,
82 typename cellBasisType>
85 check_getCoeffMatrix_HCURL(
const subcellBasisType& subcellBasis,
86 const cellBasisType& cellBasis,
87 const ordinal_type subcellId,
88 const ordinal_type subcellOrt) {
89 const shards::CellTopology cellTopo = cellBasis.getBaseCellTopology();
90 const shards::CellTopology subcellTopo = subcellBasis.getBaseCellTopology();
92 const ordinal_type cellDim = cellTopo.getDimension();
93 const ordinal_type subcellDim = subcellTopo.getDimension();
97 INTREPID2_TEST_FOR_EXCEPTION( subcellDim > cellDim,
99 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " \
100 "cellDim cannot be smaller than subcellDim.");
102 const auto subcellBaseKey = subcellTopo.getBaseKey();
103 const auto cellBaseKey = cellTopo.getBaseKey();
105 INTREPID2_TEST_FOR_EXCEPTION( subcellBaseKey != shards::Line<>::key &&
106 subcellBaseKey != shards::Quadrilateral<>::key &&
107 subcellBaseKey != shards::Triangle<>::key,
109 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " \
110 "subcellBasis must have line, quad, or triangle topology.");
112 INTREPID2_TEST_FOR_EXCEPTION( cellBaseKey != shards::Quadrilateral<>::key &&
113 cellBaseKey != shards::Triangle<>::key &&
114 cellBaseKey != shards::Hexahedron<>::key &&
115 cellBaseKey != shards::Wedge<>::key &&
116 cellBaseKey != shards::Tetrahedron<>::key,
118 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " \
119 "cellBasis must have quad, triangle, hexhedron or tetrahedron topology.");
125 const bool cellBasisIsHCURL = cellBasis.getFunctionSpace() == FUNCTION_SPACE_HCURL;
128 if (cellBasisIsHCURL) {
129 const bool subcellBasisIsHGRAD = subcellBasis.getFunctionSpace() == FUNCTION_SPACE_HGRAD;
130 const bool subcellBasisIsHVOL = subcellBasis.getFunctionSpace() == FUNCTION_SPACE_HVOL;
131 const bool subcellBasisIsHCURL = subcellBasis.getFunctionSpace() == FUNCTION_SPACE_HCURL;
132 const bool cellIsTri = cellBaseKey == shards::Triangle<>::key;
133 const bool cellIsTet = cellBaseKey == shards::Tetrahedron<>::key;
134 const bool cellIsHex = cellBaseKey == shards::Hexahedron<>::key;
135 const bool cellIsQuad = cellBaseKey == shards::Quadrilateral<>::key;
139 switch (subcellDim) {
142 if (cellIsHex || cellIsQuad) {
143 INTREPID2_TEST_FOR_EXCEPTION( !(subcellBasisIsHGRAD||subcellBasisIsHVOL),
145 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): "
146 "subcellBasis function space (1d) is not consistent to cellBasis.");
147 }
else if (cellIsTet || cellIsTri) {
148 INTREPID2_TEST_FOR_EXCEPTION( !subcellBasisIsHVOL,
150 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): "
151 "subcellBasis function space (1d) is not consistent to cellBasis.");
156 INTREPID2_TEST_FOR_EXCEPTION( !subcellBasisIsHCURL,
158 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): "
159 "subcellBasis function space (2d) is not consistent to cellBasis.");
169 template<
typename OutputViewType,
170 typename subcellBasisHostType,
171 typename cellBasisHostType>
176 const subcellBasisHostType& subcellBasis,
177 const cellBasisHostType& cellBasis,
178 const ordinal_type subcellId,
179 const ordinal_type subcellOrt,
180 const bool inverse) {
182 #ifdef HAVE_INTREPID2_DEBUG
183 Debug::check_getCoeffMatrix_HCURL(subcellBasis,cellBasis,subcellId,subcellOrt);
186 using value_type =
typename OutputViewType::non_const_value_type;
187 using host_device_type =
typename Kokkos::HostSpace::device_type;
193 const shards::CellTopology cellTopo = cellBasis.getBaseCellTopology();
194 const shards::CellTopology subcellTopo = subcellBasis.getBaseCellTopology();
195 const ordinal_type cellDim = cellTopo.getDimension();
196 const ordinal_type subcellDim = subcellTopo.getDimension();
197 const auto subcellBaseKey = subcellTopo.getBaseKey();
198 const ordinal_type numCellBasis = cellBasis.getCardinality();
199 const ordinal_type numSubcellBasis = subcellBasis.getCardinality();
200 const ordinal_type ndofSubcell = cellBasis.getDofCount(subcellDim,subcellId);
207 Kokkos::DynRankView<value_type,host_device_type> subcellTangents(
"subcellTangents", numSubcellBasis, subcellDim);
208 auto degree = subcellBasis.getDegree();
209 BasisPtr<host_device_type, value_type, value_type> basisPtr;
210 if(subcellBaseKey == shards::Line<>::key) {
212 basisPtr->getDofCoeffs(Kokkos::subview(subcellTangents, Kokkos::ALL(),0));
213 }
else if (subcellBaseKey == shards::Triangle<>::key) {
215 basisPtr->getDofCoeffs(subcellTangents);
216 }
else if (subcellBaseKey == shards::Quadrilateral<>::key) {
218 basisPtr->getDofCoeffs(subcellTangents);
222 Kokkos::DynRankView<value_type,host_device_type> subcellDofCoords(
"subcellDofCoords", basisPtr->getCardinality(), subcellDim);
223 basisPtr->getDofCoords(subcellDofCoords);
224 INTREPID2_TEST_FOR_EXCEPTION( basisPtr->getDofCount(subcellDim,0) != ndofSubcell,
226 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): " \
227 "the number of basisPtr internal DoFs should equate those of the subcell");
230 Kokkos::DynRankView<value_type,host_device_type> refPtsSubcell(
"refPtsSubcell", ndofSubcell, subcellDim);
231 Kokkos::DynRankView<value_type,host_device_type> refSubcellTangents(
"subcellTangents", ndofSubcell, subcellDim);
232 auto tagToOrdinal = basisPtr->getAllDofOrdinal();
233 for (ordinal_type i=0;i<ndofSubcell;++i) {
234 ordinal_type isc = tagToOrdinal(subcellDim, 0, i);
235 for(ordinal_type d=0; d <subcellDim; ++d){
236 refPtsSubcell(i,d) = subcellDofCoords(isc,d);
237 for(ordinal_type k=0; k <subcellDim; ++k)
238 refSubcellTangents(i,d) = subcellTangents(isc,d);
247 Kokkos::DynRankView<value_type,host_device_type> subCellValues(
"subCellValues", numSubcellBasis, ndofSubcell, subcellDim);
249 auto lineValues = Kokkos::subview(subCellValues, Kokkos::ALL(), Kokkos::ALL(), 0);
250 subcellBasis.getValues(lineValues, refPtsSubcell, OPERATOR_VALUE);
252 subcellBasis.getValues(subCellValues, refPtsSubcell, OPERATOR_VALUE);
259 Kokkos::DynRankView<value_type,host_device_type> refPtsCell(
"refPtsCell", ndofSubcell, cellDim);
260 Kokkos::DynRankView<value_type,host_device_type> trJacobianF(
"trJacobianF", subcellDim, cellDim );
262 if(cellDim == subcellDim) {
267 Kokkos::DynRankView<value_type,host_device_type> jac(
"data", subcellDim, subcellDim);
269 for(ordinal_type d=0; d<subcellDim; ++d)
270 for(ordinal_type j=0; j<cellDim; ++j) {
271 trJacobianF(j,d) = jac(d,j);
284 Kokkos::DynRankView<value_type,host_device_type> cellBasisValues(
"cellBasisValues", numCellBasis, ndofSubcell, cellDim);
285 cellBasis.getValues(cellBasisValues, refPtsCell, OPERATOR_VALUE);
294 Kokkos::DynRankView<value_type,Kokkos::LayoutLeft,host_device_type>
295 PsiMat(
"PsiMat", ndofSubcell, ndofSubcell),
296 PhiMat(
"PhiMat", ndofSubcell, ndofSubcell),
300 auto cellTagToOrdinal = cellBasis.getAllDofOrdinal();
301 auto subcellTagToOrdinal = subcellBasis.getAllDofOrdinal();
303 for (ordinal_type i=0;i<ndofSubcell;++i) {
304 const ordinal_type ic = cellTagToOrdinal(subcellDim, subcellId, i);
305 for (ordinal_type j=0;j<ndofSubcell;++j) {
306 const ordinal_type isc = subcellTagToOrdinal(subcellDim, 0, i);
307 value_type refEntry = 0, ortEntry =0;
308 for (ordinal_type k=0;k<subcellDim;++k) {
309 ortEntry += subCellValues(isc,j,k)*refSubcellTangents(j,k);
310 for (ordinal_type d=0; d<cellDim; ++d)
311 refEntry += cellBasisValues(ic,j,d)*trJacobianF(k,d)*refSubcellTangents(j,k);
313 PsiMat(j,i) = refEntry;
314 PhiMat(j,i) = ortEntry;
318 RefMat = inverse ? PhiMat : PsiMat;
319 OrtMat = inverse ? PsiMat : PhiMat;
323 Teuchos::LAPACK<ordinal_type,value_type> lapack;
324 ordinal_type info = 0;
338 Kokkos::DynRankView<ordinal_type,host_device_type> pivVec(
"pivVec", ndofSubcell);
339 lapack.GESV(ndofSubcell, ndofSubcell,
348 std::stringstream ss;
349 ss <<
">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HCURL): "
350 <<
"LAPACK return with error code: "
352 INTREPID2_TEST_FOR_EXCEPTION(
true, std::runtime_error, ss.str().c_str() );
358 const double eps = tolerence();
359 for (ordinal_type i=0;i<ndofSubcell;++i) {
360 auto intmatii = std::round(OrtMat(i,i));
361 OrtMat(i,i) = (std::abs(OrtMat(i,i) - intmatii) < eps) ? intmatii : OrtMat(i,i);
362 for (ordinal_type j=i+1;j<ndofSubcell;++j) {
363 auto matij = OrtMat(i,j);
365 auto intmatji = std::round(OrtMat(j,i));
366 OrtMat(i,j) = (std::abs(OrtMat(j,i) - intmatji) < eps) ? intmatji : OrtMat(j,i);
368 auto intmatij = std::round(matij);
369 OrtMat(j,i) = (std::abs(matij - intmatij) < eps) ? intmatij : matij;
395 const Kokkos::pair<ordinal_type,ordinal_type> range(0, ndofSubcell);
396 auto suboutput = Kokkos::subview(output, range, range);
397 auto tmp = Kokkos::create_mirror_view_and_copy(
typename OutputViewType::device_type::memory_space(), OrtMat);
398 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.