Intrepid2
Intrepid2_OrientationToolsDefCoeffMatrix_HGRAD.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Intrepid2 Package
4//
5// Copyright 2007 NTESS and the Intrepid2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10
23#ifndef __INTREPID2_ORIENTATIONTOOLS_DEF_COEFF_MATRIX_HGRAD_HPP__
24#define __INTREPID2_ORIENTATIONTOOLS_DEF_COEFF_MATRIX_HGRAD_HPP__
25
26// disable clang warnings
27#if defined (__clang__) && !defined (__INTEL_COMPILER)
28#pragma clang system_header
29#endif
30
31namespace Intrepid2 {
32
33namespace Impl {
34namespace Debug {
35
36#ifdef HAVE_INTREPID2_DEBUG
37template<typename subcellBasisType,
38typename cellBasisType>
39inline
40void
41check_getCoeffMatrix_HGRAD(const subcellBasisType& subcellBasis,
42 const cellBasisType& cellBasis,
43 const ordinal_type subcellId,
44 const ordinal_type subcellOrt) {
45
46 // populate points on a subcell and map to subcell
47 const shards::CellTopology cellTopo = cellBasis.getBaseCellTopology();
48 const shards::CellTopology subcellTopo = subcellBasis.getBaseCellTopology();
49
50 const ordinal_type cellDim = cellTopo.getDimension();
51 const ordinal_type subcellDim = subcellTopo.getDimension();
52
53 INTREPID2_TEST_FOR_EXCEPTION( subcellDim > cellDim,
54 std::logic_error,
55 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HGRAD): " \
56 "cellDim cannot be smaller than subcellDim.");
57
58 INTREPID2_TEST_FOR_EXCEPTION( subcellDim > 2,
59 std::logic_error,
60 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HGRAD): " \
61 "subCellDim cannot be larger than 2.");
62
63 const auto subcellBaseKey = subcellTopo.getBaseKey();
64
65 INTREPID2_TEST_FOR_EXCEPTION( subcellBaseKey != shards::Line<>::key &&
66 subcellBaseKey != shards::Quadrilateral<>::key &&
67 subcellBaseKey != shards::Triangle<>::key,
68 std::logic_error,
69 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HGRAD): " \
70 "subcellBasis must have line, quad, or triangle topology.");
71
72
73 //
74 // Function space
75 //
76
77 {
78 const bool cellBasisIsHGRAD = cellBasis.getFunctionSpace() == FUNCTION_SPACE_HGRAD;
79 const bool subcellBasisIsHGRAD = subcellBasis.getFunctionSpace() == FUNCTION_SPACE_HGRAD;
80 if (cellBasisIsHGRAD) {
81 INTREPID2_TEST_FOR_EXCEPTION( !subcellBasisIsHGRAD,
82 std::logic_error,
83 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HGRAD): " \
84 "subcellBasis function space is not consistent to cellBasis.");
85 }
86
87 INTREPID2_TEST_FOR_EXCEPTION( subcellBasis.getDegree() != cellBasis.getDegree(),
88 std::logic_error,
89 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HGRAD): " \
90 "subcellBasis has a different polynomial degree from cellBasis' degree.");
91 }
92}
93#endif
94} // Debug namespace
95
96template<typename OutputViewType,
97typename subcellBasisHostType,
98typename cellBasisHostType>
99inline
100void
102getCoeffMatrix_HGRAD(OutputViewType &output,
103 const subcellBasisHostType& subcellBasis,
104 const cellBasisHostType& cellBasis,
105 const ordinal_type subcellId,
106 const ordinal_type subcellOrt,
107 const bool inverse) {
108
109#ifdef HAVE_INTREPID2_DEBUG
110 Debug::check_getCoeffMatrix_HGRAD(subcellBasis,cellBasis,subcellId,subcellOrt);
111#endif
112
113 using host_device_type = typename Kokkos::HostSpace::device_type;
114 using value_type = typename OutputViewType::non_const_value_type;
115
116 //
117 // Topology
118 //
119
120 const shards::CellTopology cellTopo = cellBasis.getBaseCellTopology();
121 const shards::CellTopology subcellTopo = subcellBasis.getBaseCellTopology();
122 const ordinal_type cellDim = cellTopo.getDimension();
123 const ordinal_type subcellDim = subcellTopo.getDimension();
124 const auto subcellBaseKey = subcellTopo.getBaseKey();
125 const ordinal_type numCellBasis = cellBasis.getCardinality();
126 const ordinal_type numSubcellBasis = subcellBasis.getCardinality();
127 const ordinal_type ndofSubcell = cellBasis.getDofCount(subcellDim,subcellId);
128
129 //
130 // Reference points
131 //
132
133 // Reference points \xi_j on the subcell
134 Kokkos::DynRankView<value_type,host_device_type> refPtsSubcell("refPtsSubcell", ndofSubcell, subcellDim);
135 auto latticeSize=PointTools::getLatticeSize(subcellTopo, subcellBasis.getDegree(), 1);
136
137 INTREPID2_TEST_FOR_EXCEPTION( latticeSize != ndofSubcell,
138 std::logic_error,
139 ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HGRAD): " \
140 "Lattice size should be equal to the number of subcell internal DoFs");
141 PointTools::getLattice(refPtsSubcell, subcellTopo, subcellBasis.getDegree(), 1, POINTTYPE_WARPBLEND);
142
143 // map the points into the parent, cell accounting for orientation
144 Kokkos::DynRankView<value_type,host_device_type> refPtsCell("refPtsCell", ndofSubcell, cellDim);
145 // refPtsCell = F_s (\eta_o (refPtsSubcell))
146 if(cellDim == subcellDim) //the cell is a side of dimension 1 or 2.
147 mapToModifiedReference(refPtsCell,refPtsSubcell,subcellBaseKey,subcellOrt);
148 else {
149 auto subcellParam = Intrepid2::RefSubcellParametrization<host_device_type>::get(subcellDim, cellTopo.getKey());
150 mapSubcellCoordsToRefCell(refPtsCell,refPtsSubcell, subcellParam, subcellBaseKey, subcellId, subcellOrt);
151 }
152
153 //
154 // Bases evaluation on the reference points
155 //
156
157 // cellBasisValues = \psi_k(F_s (\eta_o (\xi_j)))
158 Kokkos::DynRankView<value_type,host_device_type> cellBasisValues("cellBasisValues", numCellBasis, ndofSubcell);
159
160 // subcellBasisValues = \phi_i (\xi_j)
161 Kokkos::DynRankView<value_type,host_device_type> subcellBasisValues("subcellBasisValues", numSubcellBasis, ndofSubcell);
162
163 cellBasis.getValues(cellBasisValues, refPtsCell, OPERATOR_VALUE);
164 subcellBasis.getValues(subcellBasisValues, refPtsSubcell, OPERATOR_VALUE);
165
166 //
167 // Compute Psi_jk = \psi_k(F_s (\eta_o (\xi_j))) and Phi_ji = \phi_i (\xi_j),
168 // and solve
169 // Psi A^T = Phi
170 //
171
172 // construct Psi and Phi matrices. LAPACK wants left layout
173 Kokkos::DynRankView<value_type,Kokkos::LayoutLeft,host_device_type>
174 PsiMat("PsiMat", ndofSubcell, ndofSubcell),
175 PhiMat("PhiMat", ndofSubcell, ndofSubcell),
176 RefMat,
177 OrtMat;
178
179 auto cellTagToOrdinal = cellBasis.getAllDofOrdinal();
180 auto subcellTagToOrdinal = subcellBasis.getAllDofOrdinal();
181
182 for (ordinal_type i=0;i<ndofSubcell;++i) {
183 const ordinal_type ic = cellTagToOrdinal(subcellDim, subcellId, i);
184 const ordinal_type isc = subcellTagToOrdinal(subcellDim, 0, i);
185 for (ordinal_type j=0;j<ndofSubcell;++j) {
186 PsiMat(j, i) = cellBasisValues(ic,j);
187 PhiMat(j, i) = subcellBasisValues(isc,j);
188 }
189 }
190
191 RefMat = inverse ? PhiMat : PsiMat;
192 OrtMat = inverse ? PsiMat : PhiMat;
193
194 // Solve the system
195 {
196 Teuchos::LAPACK<ordinal_type,value_type> lapack;
197 ordinal_type info = 0;
198
199 Kokkos::DynRankView<ordinal_type,Kokkos::LayoutLeft,host_device_type> pivVec("pivVec", ndofSubcell);
200 lapack.GESV(ndofSubcell, ndofSubcell,
201 RefMat.data(),
202 RefMat.stride(1),
203 pivVec.data(),
204 OrtMat.data(),
205 OrtMat.stride(1),
206 &info);
207
208 if (info) {
209 std::stringstream ss;
210 ss << ">>> ERROR (Intrepid::OrientationTools::getCoeffMatrix_HGRAD): "
211 << "LAPACK return with error code: "
212 << info;
213 INTREPID2_TEST_FOR_EXCEPTION( true, std::runtime_error, ss.str().c_str() );
214 }
215
216 //After solving the system w/ LAPACK, Phi contains A^T
217
218 // transpose B and clean up numerical noise (for permutation matrices)
219 const double eps = tolerence();
220 for (ordinal_type i=0;i<ndofSubcell;++i) {
221 auto intmatii = std::round(OrtMat(i,i));
222 OrtMat(i,i) = (std::abs(OrtMat(i,i) - intmatii) < eps) ? intmatii : OrtMat(i,i);
223 for (ordinal_type j=i+1;j<ndofSubcell;++j) {
224 auto matij = OrtMat(i,j);
225
226 auto intmatji = std::round(OrtMat(j,i));
227 OrtMat(i,j) = (std::abs(OrtMat(j,i) - intmatji) < eps) ? intmatji : OrtMat(j,i);
228
229 auto intmatij = std::round(matij);
230 OrtMat(j,i) = (std::abs(matij - intmatij) < eps) ? intmatij : matij;
231 }
232 }
233
234 }
235
236 // Print A Matrix
237 /*
238 {
239 std::cout << "|";
240 for (ordinal_type i=0;i<ndofSubcell;++i) {
241 for (ordinal_type j=0;j<ndofSubcell;++j) {
242 std::cout << OrtMat(i,j) << " ";
243 }
244 std::cout << "| ";
245 }
246 std::cout <<std::endl;
247 }
248 */
249
250 {
251 // move the data to original device memory
252 const Kokkos::pair<ordinal_type,ordinal_type> range(0, ndofSubcell);
253 auto suboutput = Kokkos::subview(output, range, range);
254 auto tmp = Kokkos::create_mirror_view_and_copy(typename OutputViewType::device_type::memory_space(), OrtMat);
255 Kokkos::deep_copy(suboutput, tmp);
256 }
257}
258}
259
260}
261#endif
static void getCoeffMatrix_HGRAD(OutputViewType &output, const subcellBasisHostType &subcellBasis, const cellBasisHostType &cellBasis, const ordinal_type subcellId, const ordinal_type subcellOrt, const bool inverse=false)
Compute orientation matrix for HGRAD basis for a given subcell and its reference basis.
static void mapToModifiedReference(outPointViewType outPoints, const refPointViewType refPoints, const shards::CellTopology cellTopo, const ordinal_type cellOrt=0)
Computes modified parameterization maps of 1- and 2-subcells with orientation.
static KOKKOS_INLINE_FUNCTION void mapSubcellCoordsToRefCell(coordsViewType cellCoords, const subcellCoordsViewType subCellCoords, const ParamViewType subcellParametrization, const unsigned subcellTopoKey, const ordinal_type subCellOrd, const ordinal_type ort)
Maps points defined on the subCell manifold into the parent Cell accounting for orientation.
static ordinal_type getLatticeSize(const shards::CellTopology cellType, const ordinal_type order, const ordinal_type offset=0)
Computes the number of points in a lattice of a given order on a simplex (currently disabled for othe...
static void getLattice(Kokkos::DynRankView< pointValueType, pointProperties... > points, const shards::CellTopology cellType, const ordinal_type order, const ordinal_type offset=0, const EPointType pointType=POINTTYPE_EQUISPACED)
Computes a lattice of points of a given order on a reference simplex, quadrilateral or hexahedron (cu...
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...