Intrepid2
Intrepid2_HGRAD_TET_Cn_FEMDef.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
15
16#ifndef __INTREPID2_HGRAD_TET_CN_FEM_DEF_HPP__
17#define __INTREPID2_HGRAD_TET_CN_FEM_DEF_HPP__
18
21
22namespace Intrepid2 {
23
24// -------------------------------------------------------------------------------------
25namespace Impl {
26
27template<EOperator OpType>
28template<typename OutputViewType,
29typename InputViewType,
30typename WorkViewType,
31typename VinvViewType>
32KOKKOS_INLINE_FUNCTION
33void
35getValues( OutputViewType output,
36 const InputViewType input,
37 WorkViewType work,
38 const VinvViewType vinv,
39 const ordinal_type order ) {
40
41 constexpr ordinal_type spaceDim = 3;
42 const ordinal_type
43 card = vinv.extent(0),
44 npts = input.extent(0);
45
46 typedef typename Kokkos::DynRankView<typename InputViewType::value_type, typename WorkViewType::memory_space> ViewType;
47 auto ptr = work.data();
48
49 switch (OpType) {
50 case OPERATOR_VALUE: {
51 const ViewType phis = createMatchingUnmanagedView<ViewType>(input, ptr, card, npts);
52 ViewType dummyView;
53
54 Impl::Basis_HGRAD_TET_Cn_FEM_ORTH::
55 Serial<OpType>::getValues(phis, input, dummyView, order);
56
57 for (ordinal_type i=0;i<card;++i)
58 for (ordinal_type j=0;j<npts;++j) {
59 output.access(i,j) = 0.0;
60 for (ordinal_type k=0;k<card;++k)
61 output.access(i,j) += vinv(k,i)*phis.access(k,j);
62 }
63 break;
64 }
65 case OPERATOR_GRAD:
66 case OPERATOR_D1: {
67 const ViewType phis = createMatchingUnmanagedView<ViewType>(input, ptr,card, npts, spaceDim);
68 ptr += card*npts*spaceDim*get_dimension_scalar(input);
69 const ViewType workView = createMatchingUnmanagedView<ViewType>(input, ptr, card, npts, spaceDim+1);
70 Impl::Basis_HGRAD_TET_Cn_FEM_ORTH::
71 Serial<OpType>::getValues(phis, input, workView, order);
72
73 // loop order interchanged to workaround nvcc compiler issues with sems-cuda/11.4.2
74 // nvcc error : 'ptxas' died due to signal 11 (Invalid memory reference)
75 for (ordinal_type j=0;j<npts;++j)
76 for (ordinal_type k=0;k<spaceDim;++k)
77 for (ordinal_type i=0;i<card;++i)
78 {
79 output.access(i,j,k) = 0.0;
80 for (ordinal_type l=0;l<card;++l)
81 output.access(i,j,k) += vinv(l,i)*phis.access(l,j,k);
82 }
83 break;
84 }
85 case OPERATOR_D2:
86 case OPERATOR_D3:
87 case OPERATOR_D4:
88 case OPERATOR_D5:
89 case OPERATOR_D6:
90 case OPERATOR_D7:
91 case OPERATOR_D8:
92 case OPERATOR_D9:
93 case OPERATOR_D10: {
94 const ordinal_type dkcard = getDkCardinality<OpType,spaceDim>(); //(orDn + 1);
95 const ViewType phis = createMatchingUnmanagedView<ViewType>(input, ptr, card, npts, dkcard);
96 ViewType dummyView;
97
98 Impl::Basis_HGRAD_TET_Cn_FEM_ORTH::
99 Serial<OpType>::getValues(phis, input, dummyView, order);
100
101 for (ordinal_type i=0;i<card;++i)
102 for (ordinal_type j=0;j<npts;++j)
103 for (ordinal_type k=0;k<dkcard;++k) {
104 output.access(i,j,k) = 0.0;
105 for (ordinal_type l=0;l<card;++l)
106 output.access(i,j,k) += vinv(l,i)*phis.access(l,j,k);
107 }
108 break;
109 }
110 default: {
111 INTREPID2_TEST_FOR_ABORT( true,
112 ">>> ERROR (Basis_HGRAD_TET_Cn_FEM): Operator type not implemented");
113 }
114 }
115}
116
117template<typename DT, ordinal_type numPtsPerEval,
118typename outputValueValueType, class ...outputValueProperties,
119typename inputPointValueType, class ...inputPointProperties,
120typename vinvValueType, class ...vinvProperties>
121void
122Basis_HGRAD_TET_Cn_FEM::
123getValues(
124 const typename DT::execution_space& space,
125 Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
126 const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
127 const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinv,
128 const ordinal_type order,
129 const EOperator operatorType) {
130 typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
131 typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
132 typedef Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvViewType;
133 typedef typename ExecSpace<typename inputPointViewType::execution_space,typename DT::execution_space>::ExecSpaceType ExecSpaceType;
134
135 // loopSize corresponds to cardinality
136 const auto loopSizeTmp1 = (inputPoints.extent(0)/numPtsPerEval);
137 const auto loopSizeTmp2 = (inputPoints.extent(0)%numPtsPerEval != 0);
138 const auto loopSize = loopSizeTmp1 + loopSizeTmp2;
139 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(space, 0, loopSize);
140
141 const ordinal_type cardinality = outputValues.extent(0);
142 const ordinal_type spaceDim = 3;
143
144 typedef typename DeduceDynRankView<inputPointViewType>::type workViewType;
145
146 switch (operatorType) {
147 case OPERATOR_VALUE: {
148 workViewType work = createMatchingView<workViewType>(inputPoints, "Basis_HGRAD_TET_Cn_FEM::getValues::work", cardinality, inputPoints.extent(0));
149 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
150 OPERATOR_VALUE,numPtsPerEval> FunctorType;
151 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work, order) );
152 break;
153 }
154 case OPERATOR_GRAD:
155 case OPERATOR_D1: {
156 workViewType work = createMatchingView<workViewType>(inputPoints, "Basis_HGRAD_TET_Cn_FEM::getValues::work", cardinality*(2*spaceDim+1), inputPoints.extent(0));
157 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
158 OPERATOR_D1,numPtsPerEval> FunctorType;
159 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work, order) );
160 break;
161 }
162 case OPERATOR_D2: {
163 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
164 OPERATOR_D2,numPtsPerEval> FunctorType;
165 workViewType work = createMatchingView<workViewType>(inputPoints, "Basis_HGRAD_TET_Cn_FEM::getValues::work", cardinality*outputValues.extent(2), inputPoints.extent(0));
166 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work, order) );
167 break;
168 }
169 default: {
170 INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument,
171 ">>> ERROR (Basis_HGRAD_TET_Cn_FEM): Operator type not implemented" );
172 }
173 }
174}
175}
176
177// -------------------------------------------------------------------------------------
178template<typename DT, typename OT, typename PT>
180Basis_HGRAD_TET_Cn_FEM( const ordinal_type order,
181 const EPointType pointType ) {
182 constexpr ordinal_type spaceDim = 3;
183
185 this->basisDegree_ = order; // small n
186 this->basisCellTopologyKey_ = shards::Tetrahedron<4>::key;
187 this->basisType_ = BASIS_FEM_LAGRANGIAN;
188 this->basisCoordinates_ = COORDINATES_CARTESIAN;
189 this->functionSpace_ = FUNCTION_SPACE_HGRAD;
190 pointType_ = (pointType == POINTTYPE_DEFAULT) ? POINTTYPE_EQUISPACED : pointType;
191
192 const ordinal_type card = this->basisCardinality_;
193
194 // points are computed in the host and will be copied
195 Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
196 dofCoords("Hgrad::Tet::Cn::dofCoords", card, spaceDim);
197
198 // Note: the only reason why equispaced can't support higher order than Parameters::MaxOrder appears to be the fact that the tags below get stored into a fixed-length array.
199 // TODO: relax the maximum order requirement by setting up tags in a different container, perhaps directly into an OrdinalTypeArray1DHost (tagView, below). (As of this writing (1/25/22), looks like other nodal bases do this in a similar way -- those should be fixed at the same time; maybe search for Parameters::MaxOrder.)
200 INTREPID2_TEST_FOR_EXCEPTION( order > Parameters::MaxOrder, std::invalid_argument, "polynomial order exceeds the max supported by this class");
201
202 // Basis-dependent initializations
203 constexpr ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
204 constexpr ordinal_type maxCard = Intrepid2::getPnCardinality<spaceDim, Parameters::MaxOrder>();
205 ordinal_type tags[maxCard][tagSize];
206
207 // construct lattice
208
209 shards::CellTopology cellTopo(shards::getCellTopologyData<shards::Tetrahedron<4> >() );
210 const ordinal_type numEdges = cellTopo.getEdgeCount();
211 const ordinal_type numFaces = cellTopo.getFaceCount();
212
213 shards::CellTopology edgeTopo(shards::getCellTopologyData<shards::Line<2> >() );
214 shards::CellTopology faceTopo(shards::getCellTopologyData<shards::Triangle<3> >() );
215
216 const int numVertexes = PointTools::getLatticeSize( cellTopo ,
217 1 ,
218 0 );
219
220 const int numPtsPerEdge = PointTools::getLatticeSize( edgeTopo ,
221 order ,
222 1 );
223
224 const int numPtsPerFace = PointTools::getLatticeSize( faceTopo ,
225 order ,
226 1 );
227
228 const int numPtsPerCell = PointTools::getLatticeSize( cellTopo ,
229 order ,
230 1 );
231
232 Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> vertexes("Hcurl::Tet::In::vertexes", numVertexes , spaceDim );
233 Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> linePts("Hcurl::Tet::In::linePts", numPtsPerEdge , 1 );
234 Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> triPts("Hcurl::Tet::In::triPts", numPtsPerFace , 2 );
235
236 // construct lattice
237 const ordinal_type offset = 1;
238
239
240 PointTools::getLattice( vertexes,
241 cellTopo ,
242 1, 0,
243 this->pointType_ );
244
245 PointTools::getLattice( linePts,
246 edgeTopo,
247 order, offset,
248 this->pointType_ );
249
251 faceTopo,
252 order, offset,
253 this->pointType_ );
254
255 // holds the image of the line points
256 Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> edgePts("Hcurl::Tet::In::edgePts", numPtsPerEdge , spaceDim );
257 Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> facePts("Hcurl::Tet::In::facePts", numPtsPerFace , spaceDim );
258
259 for (ordinal_type i=0;i<numVertexes;i++) {
260 auto i_card=i;
261 for(ordinal_type k=0; k<spaceDim; ++k)
262 dofCoords(i_card,k) = vertexes(i,k);
263 tags[i_card][0] = 0; // vertex dof
264 tags[i_card][1] = i; // vertex id
265 tags[i_card][2] = 0; // local dof id
266 tags[i_card][3] = 1; // total vert dof
267 }
268
269
270 // these are tangents scaled by the appropriate edge lengths.
271 for (ordinal_type i=0;i<numEdges;i++) { // loop over edges
273 linePts ,
274 1 ,
275 i ,
276 cellTopo );
277
278
279 // loop over points (rows of V2)
280 for (ordinal_type j=0;j<numPtsPerEdge;j++) {
281
282 const ordinal_type i_card = numVertexes + numPtsPerEdge*i+j;
283
284 //save dof coordinates and coefficients
285 for(ordinal_type k=0; k<spaceDim; ++k)
286 dofCoords(i_card,k) = edgePts(j,k);
287
288 tags[i_card][0] = 1; // edge dof
289 tags[i_card][1] = i; // edge id
290 tags[i_card][2] = j; // local dof id
291 tags[i_card][3] = numPtsPerEdge; // total edge dof
292
293 }
294 }
295
296 if(numPtsPerFace >0) {//handle faces if needed (order >1)
297
298 for (ordinal_type i=0;i<numFaces;i++) { // loop over faces
299
301 triPts ,
302 2 ,
303 i ,
304 cellTopo );
305 for (ordinal_type j=0;j<numPtsPerFace;j++) {
306
307 const ordinal_type i_card = numVertexes+numEdges*numPtsPerEdge+numPtsPerFace*i+j;
308
309 //save dof coordinates
310 for(ordinal_type k=0; k<spaceDim; ++k)
311 dofCoords(i_card,k) = facePts(j,k);
312
313 tags[i_card][0] = 2; // face dof
314 tags[i_card][1] = i; // face id
315 tags[i_card][2] = j; // local face id
316 tags[i_card][3] = numPtsPerFace; // total face dof
317 }
318 }
319 }
320
321
322 // internal dof, if needed
323 if (numPtsPerCell > 0) {
324 Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
325 cellPoints( "Hcurl::Tet::In::cellPoints", numPtsPerCell , spaceDim );
326 PointTools::getLattice( cellPoints ,
327 cellTopo ,
328 order,
329 1 ,
330 this->pointType_ );
331
332 // copy values into right positions of V2
333 for (ordinal_type j=0;j<numPtsPerCell;j++) {
334
335 const ordinal_type i_card = numVertexes+numEdges*numPtsPerEdge+numFaces*numPtsPerFace+j;
336
337 //save dof coordinates
338 for(ordinal_type dim=0; dim<spaceDim; ++dim)
339 dofCoords(i_card,dim) = cellPoints(j,dim);
340
341 tags[i_card][0] = spaceDim; // elem dof
342 tags[i_card][1] = 0; // elem id
343 tags[i_card][2] = j; // local dof id
344 tags[i_card][3] = numPtsPerCell; // total vert dof
345 }
346 }
347
348 this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoords);
349 Kokkos::deep_copy(this->dofCoords_, dofCoords);
350
351 // form Vandermonde matrix. Actually, this is the transpose of the VDM,
352 // so we transpose on copy below.
353 const ordinal_type lwork = card*card;
354 Kokkos::DynRankView<scalarType,Kokkos::LayoutLeft,Kokkos::HostSpace>
355 vmat("Hgrad::Tet::Cn::vmat", card, card),
356 work("Hgrad::Tet::Cn::work", lwork),
357 ipiv("Hgrad::Tet::Cn::ipiv", card);
358
359 Impl::Basis_HGRAD_TET_Cn_FEM_ORTH::getValues<Kokkos::HostSpace::execution_space,Parameters::MaxNumPtsPerBasisEval>(typename Kokkos::HostSpace::execution_space{},
360 vmat,
361 dofCoords,
362 order,
363 OPERATOR_VALUE);
364
365 ordinal_type info = 0;
366 Teuchos::LAPACK<ordinal_type,scalarType> lapack;
367
368 lapack.GETRF(card, card,
369 vmat.data(), vmat.stride(1),
370 (ordinal_type*)ipiv.data(),
371 &info);
372
373 INTREPID2_TEST_FOR_EXCEPTION( info != 0,
374 std::runtime_error ,
375 ">>> ERROR: (Intrepid2::Basis_HGRAD_TET_Cn_FEM) lapack.GETRF returns nonzero info." );
376
377 lapack.GETRI(card,
378 vmat.data(), vmat.stride(1),
379 (ordinal_type*)ipiv.data(),
380 work.data(), lwork,
381 &info);
382
383 INTREPID2_TEST_FOR_EXCEPTION( info != 0,
384 std::runtime_error ,
385 ">>> ERROR: (Intrepid2::Basis_HGRAD_TET_Cn_FEM) lapack.GETRI returns nonzero info." );
386
387 // create host mirror
388 Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
389 vinv("Hgrad::Line::Cn::vinv", card, card);
390
391 for (ordinal_type i=0;i<card;++i)
392 for (ordinal_type j=0;j<card;++j)
393 vinv(i,j) = vmat(j,i);
394
395 this->vinv_ = Kokkos::create_mirror_view(typename DT::memory_space(), vinv);
396 Kokkos::deep_copy(this->vinv_ , vinv);
397
398 // initialize tags
399 {
400 // Basis-dependent initializations
401 const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
402 const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
403 const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
404
405 OrdinalTypeArray1DHost tagView(&tags[0][0], card*tagSize);
406
407 // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
408 // tags are constructed on host
410 this->ordinalToTag_,
411 tagView,
412 this->basisCardinality_,
413 tagSize,
414 posScDim,
415 posScOrd,
416 posDfOrd);
417 }
418}
419
420 template<typename DT, typename OT, typename PT>
421 void
422 Basis_HGRAD_TET_Cn_FEM<DT,OT,PT>::getScratchSpaceSize(
423 ordinal_type& perTeamSpaceSize,
424 ordinal_type& perThreadSpaceSize,
425 const PointViewType inputPoints,
426 const EOperator operatorType) const {
427 perTeamSpaceSize = 0;
428 perThreadSpaceSize = getWorkSizePerPoint(operatorType)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType);
429 }
430
431 template<typename DT, typename OT, typename PT>
432 KOKKOS_INLINE_FUNCTION
433 void
434 Basis_HGRAD_TET_Cn_FEM<DT,OT,PT>::getValues(
435 OutputViewType outputValues,
436 const PointViewType inputPoints,
437 const EOperator operatorType,
438 const typename Kokkos::TeamPolicy<typename DT::execution_space>::member_type& team_member,
439 const typename DT::execution_space::scratch_memory_space & scratchStorage,
440 const ordinal_type subcellDim,
441 const ordinal_type subcellOrdinal) const {
442
443 INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)),
444 ">>> ERROR: (Intrepid2::Basis_HGRAD_TET_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet.");
445
446 const int numPoints = inputPoints.extent(0);
447 using ScalarType = typename ScalarTraits<typename PointViewType::value_type>::scalar_type;
448 using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits<Kokkos::Unmanaged> >;
449 constexpr ordinal_type spaceDim = 3;
450 auto sizePerPoint = (operatorType==OPERATOR_VALUE) ?
451 this->vinv_.extent(0)*get_dimension_scalar(inputPoints) :
452 (2*spaceDim+1)*this->vinv_.extent(0)*get_dimension_scalar(inputPoints);
453 WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size());
454 using range_type = Kokkos::pair<ordinal_type,ordinal_type>;
455 switch(operatorType) {
456 case OPERATOR_VALUE:
457 Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=, &vinv_ = this->vinv_, basisDegree_ = this->basisDegree_] (ordinal_type& pt) {
458 auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() );
459 const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() );
460 WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
461 Impl::Basis_HGRAD_TET_Cn_FEM::Serial<OPERATOR_VALUE>::getValues( output, input, work, vinv_, basisDegree_);
462 });
463 break;
464 case OPERATOR_GRAD:
465 Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=, &vinv_ = this->vinv_, basisDegree_ = this->basisDegree_] (ordinal_type& pt) {
466 auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() );
467 const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() );
468 WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
469 Impl::Basis_HGRAD_TET_Cn_FEM::Serial<OPERATOR_GRAD>::getValues( output, input, work, vinv_, basisDegree_);
470 });
471 break;
472 default: {
473 INTREPID2_TEST_FOR_ABORT( true,
474 ">>> ERROR (Basis_HGRAD_TET_Cn_FEM): getValues not implemented for this operator");
475 }
476 }
477 }
478
479} // namespace Intrepid2
480#endif
KOKKOS_INLINE_FUNCTION ordinal_type getPnCardinality(ordinal_type n)
Returns cardinality of Polynomials of order n (P^n).
Header file for the Intrepid2::Basis_HGRAD_TET_Cn_FEM class.
Header file for the Intrepid2::Basis_HGRAD_TET_Cn_FEM_ORTH class.
KOKKOS_INLINE_FUNCTION std::enable_if< std::is_pointer_v< CtorProp > &&!std::is_convertible_v< CtorProp, constchar * >, OutViewType >::type createMatchingUnmanagedView(const InViewType &view, const CtorProp &data, const Dims... dims)
Creates an unmanaged view that matches the value_type of the provided view The type of the output vie...
Kokkos::DynRankView< scalarType, DeviceType > vinv_
inverse of Generalized Vandermonde matrix, whose columns store the expansion coefficients of the noda...
EPointType pointType_
type of lattice used for creating the DoF coordinates
Basis_HGRAD_TET_Cn_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.
void setOrdinalTagData(OrdinalTypeView3D &tagToOrdinal, OrdinalTypeView2D &ordinalToTag, const OrdinalTypeView1D tags, const ordinal_type basisCard, const ordinal_type tagSize, const ordinal_type posScDim, const ordinal_type posScOrd, const ordinal_type posDfOrd)
Kokkos::DynRankView< scalarType, DeviceType > dofCoords_
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
static void mapToReferenceSubcell(refSubcellViewType refSubcellPoints, const paramPointViewType paramPoints, const ordinal_type subcellDim, const ordinal_type subcellOrd, const shards::CellTopology parentCell)
Computes parameterization maps of 1- and 2-subcells of reference cells.
static constexpr ordinal_type MaxOrder
The maximum reconstruction order.
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...