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