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 
31 namespace Intrepid2 {
32 
33 namespace Impl {
34 namespace Debug {
35 
36 #ifdef HAVE_INTREPID2_DEBUG
37 template<typename subcellBasisType,
38 typename cellBasisType>
39 inline
40 void
41 check_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 
96 template<typename OutputViewType,
97 typename subcellBasisHostType,
98 typename cellBasisHostType>
99 inline
100 void
102 getCoeffMatrix_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 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 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...
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 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 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...