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.