Intrepid2
Intrepid2_HGRAD_HEX_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_HEX_CN_FEMDEF_HPP__
17#define __INTREPID2_HGRAD_HEX_CN_FEMDEF_HPP__
18
19namespace Intrepid2 {
20
21 // -------------------------------------------------------------------------------------
22 namespace Impl {
23
24 template<EOperator opType>
25 template<typename OutputViewType,
26 typename inputViewType,
27 typename workViewType,
28 typename vinvViewType>
29 KOKKOS_INLINE_FUNCTION
30 void
32 getValues( OutputViewType output,
33 const inputViewType input,
34 workViewType work,
35 const vinvViewType vinv,
36 const ordinal_type operatorDn ) {
37 ordinal_type opDn = operatorDn;
38
39 const ordinal_type cardLine = vinv.extent(0);
40 const ordinal_type npts = input.extent(0);
41
42 typedef Kokkos::pair<ordinal_type,ordinal_type> range_type;
43 const auto input_x = Kokkos::subview(input, Kokkos::ALL(), range_type(0,1));
44 const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2));
45 const auto input_z = Kokkos::subview(input, Kokkos::ALL(), range_type(2,3));
46
47 const ordinal_type dim_s = get_dimension_scalar(input);
48 auto ptr0 = work.data();
49 auto ptr1 = work.data()+cardLine*npts*dim_s;
50 auto ptr2 = work.data()+2*cardLine*npts*dim_s;
51 auto ptr3 = work.data()+3*cardLine*npts*dim_s;
52
53 typedef typename Kokkos::DynRankView<typename inputViewType::value_type, typename workViewType::memory_space> viewType;
54
55 switch (opType) {
56 case OPERATOR_VALUE: {
57 viewType work_line = createMatchingUnmanagedView<viewType>(input, ptr0, cardLine, npts);
58 viewType output_x = createMatchingUnmanagedView<viewType>(input, ptr1, cardLine, npts);
59 viewType output_y = createMatchingUnmanagedView<viewType>(input, ptr2, cardLine, npts);
60 viewType output_z = createMatchingUnmanagedView<viewType>(input, ptr3, cardLine, npts);
61
62 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
63 getValues(output_x, input_x, work_line, vinv);
64
65 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
66 getValues(output_y, input_y, work_line, vinv);
67
68 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
69 getValues(output_z, input_z, work_line, vinv);
70
71 // tensor product
72 ordinal_type idx = 0;
73 for (ordinal_type k=0;k<cardLine;++k) // z
74 for (ordinal_type j=0;j<cardLine;++j) // y
75 for (ordinal_type i=0;i<cardLine;++i,++idx) // x
76 for (ordinal_type l=0;l<npts;++l)
77 output.access(idx,l) = output_x.access(i,l)*output_y.access(j,l)*output_z.access(k,l);
78 break;
79 }
80 case OPERATOR_GRAD:
81 case OPERATOR_D1:
82 case OPERATOR_D2:
83 case OPERATOR_D3:
84 case OPERATOR_D4:
85 case OPERATOR_D5:
86 case OPERATOR_D6:
87 case OPERATOR_D7:
88 case OPERATOR_D8:
89 case OPERATOR_D9:
90 case OPERATOR_D10:
91 opDn = getOperatorOrder(opType);
92 case OPERATOR_Dn: {
93 const ordinal_type dkcard = opDn + 1;
94
95 ordinal_type d = 0;
96 for (ordinal_type l1=0;l1<dkcard;++l1)
97 for (ordinal_type l0=0;l0<(l1+1);++l0) {
98 const ordinal_type mult_x = (opDn - l1);
99 const ordinal_type mult_y = l1 - l0;
100 const ordinal_type mult_z = l0;
101
102 //std::cout << " l0, l1 = " << l0 << " " << l1 << std::endl;
103 //std::cout << " x , y , z = " << mult_x << " " << mult_y << " " << mult_z << std::endl;
104
105 if (mult_x < 0) {
106 // pass
107 } else {
108 viewType work_line = createMatchingUnmanagedView<viewType>(input, ptr0, cardLine, npts);
109 decltype(work_line) output_x, output_y, output_z;
110
111 if (mult_x) {
112 output_x = createMatchingUnmanagedView<viewType>(input, ptr1, cardLine, npts, 1);
113 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
114 getValues(output_x, input_x, work_line, vinv, mult_x);
115 } else {
116 output_x = createMatchingUnmanagedView<viewType>(input, ptr1, cardLine, npts);
117 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
118 getValues(output_x, input_x, work_line, vinv);
119 }
120
121 if (mult_y) {
122 output_y = createMatchingUnmanagedView<viewType>(input, ptr2, cardLine, npts, 1);
123 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
124 getValues(output_y, input_y, work_line, vinv, mult_y);
125 } else {
126 output_y = createMatchingUnmanagedView<viewType>(input, ptr2, cardLine, npts);
127 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
128 getValues(output_y, input_y, work_line, vinv);
129 }
130
131 if (mult_z) {
132 output_z = createMatchingUnmanagedView<viewType>(input, ptr3, cardLine, npts, 1);
133 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
134 getValues(output_z, input_z, work_line, vinv, mult_z);
135 } else {
136 output_z = createMatchingUnmanagedView<viewType>(input, ptr3, cardLine, npts);
137 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
138 getValues(output_z, input_z, work_line, vinv);
139 }
140
141 // tensor product (extra dimension of ouput x,y and z are ignored)
142 ordinal_type idx = 0;
143 for (ordinal_type k=0;k<cardLine;++k) // z
144 for (ordinal_type j=0;j<cardLine;++j) // y
145 for (ordinal_type i=0;i<cardLine;++i,++idx) // x
146 for (ordinal_type l=0;l<npts;++l)
147 output.access(idx,l,d) = output_x.access(i,l,0)*output_y.access(j,l,0)*output_z.access(k,l,0);
148 ++d;
149 }
150 }
151 break;
152 }
153 default: {
154 INTREPID2_TEST_FOR_ABORT( true ,
155 ">>> ERROR (Basis_HGRAD_HEX_Cn_FEM): Operator type not implemented");
156 break;
157 }
158 }
159 }
160
161 template<typename DT, ordinal_type numPtsPerEval,
162 typename outputValueValueType, class ...outputValueProperties,
163 typename inputPointValueType, class ...inputPointProperties,
164 typename vinvValueType, class ...vinvProperties>
165 void
166 Basis_HGRAD_HEX_Cn_FEM::
167 getValues( const typename DT::execution_space& space,
168 Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
169 const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
170 const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinv,
171 const EOperator operatorType ) {
172 typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
173 typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
174 typedef Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvViewType;
175 typedef typename ExecSpace<typename inputPointViewType::execution_space,typename DT::execution_space>::ExecSpaceType ExecSpaceType;
176
177 // loopSize corresponds to cardinality
178 const auto loopSizeTmp1 = (inputPoints.extent(0)/numPtsPerEval);
179 const auto loopSizeTmp2 = (inputPoints.extent(0)%numPtsPerEval != 0);
180 const auto loopSize = loopSizeTmp1 + loopSizeTmp2;
181 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(space, 0, loopSize);
182
183 const ordinal_type cardinality = outputValues.extent(0);
184 const ordinal_type cardLine = std::cbrt(cardinality);
185 const ordinal_type workSize = 4*cardLine;
186
187 auto work = createMatchingDynRankView(inputPoints, "Basis_HGRAD_HEX_Cn_FEM::getValues::work", workSize, inputPoints.extent(0));
188
189 switch (operatorType) {
190 case OPERATOR_VALUE: {
191 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,decltype(work),
192 OPERATOR_VALUE,numPtsPerEval> FunctorType;
193 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
194 break;
195 }
196 case OPERATOR_CURL: {
197 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,decltype(work),
198 OPERATOR_CURL,numPtsPerEval> FunctorType;
199 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
200 break;
201 }
202 case OPERATOR_GRAD:
203 case OPERATOR_D1:
204 case OPERATOR_D2:
205 case OPERATOR_D3:
206 case OPERATOR_D4:
207 case OPERATOR_D5:
208 case OPERATOR_D6:
209 case OPERATOR_D7:
210 case OPERATOR_D8:
211 case OPERATOR_D9:
212 case OPERATOR_D10: {
213 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,decltype(work),
214 OPERATOR_Dn,numPtsPerEval> FunctorType;
215 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work,
216 getOperatorOrder(operatorType)) );
217 break;
218 }
219 default: {
220 INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument,
221 ">>> ERROR (Basis_HGRAD_HEX_Cn_FEM): Operator type not implemented" );
222 // break; commented out since exception is thrown
223 }
224 }
225 }
226 }
227
228 // -------------------------------------------------------------------------------------
229 template<typename DT, typename OT, typename PT>
231 Basis_HGRAD_HEX_Cn_FEM( const ordinal_type order,
232 const EPointType pointType ) {
233
234 // this should be in host
235 Basis_HGRAD_LINE_Cn_FEM<DT,OT,PT> lineBasis( order, pointType );
236 const auto cardLine = lineBasis.getCardinality();
237
238 this->vinv_ = Kokkos::DynRankView<typename ScalarViewType::value_type,DT>("Hgrad::HEX::Cn::vinv", cardLine, cardLine);
239 lineBasis.getVandermondeInverse(this->vinv_);
240
241 const ordinal_type spaceDim = 3;
242 this->basisCardinality_ = cardLine*cardLine*cardLine;
243 this->basisDegree_ = order;
244 this->basisCellTopologyKey_ = shards::Hexahedron<8>::key;
245 this->basisType_ = BASIS_FEM_LAGRANGIAN;
246 this->basisCoordinates_ = COORDINATES_CARTESIAN;
247 this->functionSpace_ = FUNCTION_SPACE_HGRAD;
248 pointType_ = pointType;
249
250 // initialize tags
251 {
252 // Basis-dependent initializations
253 const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
254 const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
255 const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
256 const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
257
258 // 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.
259 // 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.)
260 INTREPID2_TEST_FOR_EXCEPTION( order > Parameters::MaxOrder, std::invalid_argument, "polynomial order exceeds the max supported by this class");
261
262 // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
263 constexpr ordinal_type maxCardLine = Parameters::MaxOrder + 1;
264 ordinal_type tags[maxCardLine*maxCardLine*maxCardLine][4];
265
266 const ordinal_type vert[2][2][2] = { { {0,1}, {3,2} },
267 { {4,5}, {7,6} } }; //[z][y][x]
268
269 const ordinal_type edge_x[2][2] = { {0, 4}, {2, 6} };
270 const ordinal_type edge_y[2][2] = { {3, 7}, {1, 5} };
271 const ordinal_type edge_z[2][2] = { {8,11}, {9,10} };
272
273 const ordinal_type face_yz[2] = {3, 1};
274 const ordinal_type face_xz[2] = {0, 2};
275 const ordinal_type face_xy[2] = {4, 5};
276
277 {
278 ordinal_type idx = 0;
279 for (auto k=0;k<cardLine;++k) { // z
280 const auto tag_z = lineBasis.getDofTag(k);
281 for (ordinal_type j=0;j<cardLine;++j) { // y
282 const auto tag_y = lineBasis.getDofTag(j);
283 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
284 const auto tag_x = lineBasis.getDofTag(i);
285
286 if (tag_x(0) == 0 && tag_y(0) == 0 && tag_z(0) == 0) {
287 // vertices
288 tags[idx][0] = 0; // vertex dof
289 tags[idx][1] = vert[tag_z(1)][tag_y(1)][tag_x(1)]; // vertex id
290 tags[idx][2] = 0; // local dof id
291 tags[idx][3] = 1; // total number of dofs in this vertex
292 } else if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 0) {
293 // edge, x edge, y vert, z vert,
294 tags[idx][0] = 1; // edge dof
295 tags[idx][1] = edge_x[tag_y(1)][tag_z(1)]; // edge id
296 tags[idx][2] = tag_x(2); // local dof id
297 tags[idx][3] = tag_x(3); // total number of dofs in this edge
298 } else if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 0) {
299 // edge, x vert, y edge, z vert,
300 tags[idx][0] = 1; // edge dof
301 tags[idx][1] = edge_y[tag_x(1)][tag_z(1)]; // edge id
302 tags[idx][2] = tag_y(2); // local dof id
303 tags[idx][3] = tag_y(3); // total number of dofs in this edge
304 } else if (tag_x(0) == 0 && tag_y(0) == 0 && tag_z(0) == 1) {
305 // edge, x vert, y vert, z edge,
306 tags[idx][0] = 1; // edge dof
307 tags[idx][1] = edge_z[tag_x(1)][tag_y(1)]; // edge id
308 tags[idx][2] = tag_z(2); // local dof id
309 tags[idx][3] = tag_z(3); // total number of dofs in this edge
310 } else if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 1) {
311 // face, x vert, y edge, z edge
312 tags[idx][0] = 2; // face dof
313 tags[idx][1] = face_yz[tag_x(1)]; // face id
314 tags[idx][2] = tag_y(2) + tag_y(3)*tag_z(2); // local dof id
315 tags[idx][3] = tag_y(3)*tag_z(3); // total number of dofs in this vertex
316 } else if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 1) {
317 // face, x edge, y vert, z edge
318 tags[idx][0] = 2; // face dof
319 tags[idx][1] = face_xz[tag_y(1)]; // face id
320 tags[idx][2] = tag_x(2) + tag_x(3)*tag_z(2); // local dof id
321 tags[idx][3] = tag_x(3)*tag_z(3); // total number of dofs in this vertex
322 } else if (tag_x(0) == 1 && tag_y(0) == 1 && tag_z(0) == 0) {
323 // face, x edge, y edge, z vert
324 tags[idx][0] = 2; // face dof
325 tags[idx][1] = face_xy[tag_z(1)]; // face id
326 tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2); // local dof id
327 tags[idx][3] = tag_x(3)*tag_y(3); // total number of dofs in this vertex
328 } else {
329 // interior
330 tags[idx][0] = 3; // interior dof
331 tags[idx][1] = 0;
332 tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2); // local dof id
333 tags[idx][3] = tag_x(3)*tag_y(3)*tag_z(3); // total number of dofs in this vertex
334 }
335 }
336 }
337 }
338 }
339
340 OrdinalTypeArray1DHost tagView(&tags[0][0], this->basisCardinality_*4);
341
342 // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
343 // tags are constructed on host
345 this->ordinalToTag_,
346 tagView,
347 this->basisCardinality_,
348 tagSize,
349 posScDim,
350 posScOrd,
351 posDfOrd);
352 }
353
354 // dofCoords on host and create its mirror view to device
355 Kokkos::DynRankView<typename ScalarViewType::value_type,typename DT::execution_space::array_layout,Kokkos::HostSpace>
356 dofCoordsHost("dofCoordsHost", this->basisCardinality_, spaceDim);
357
358 Kokkos::DynRankView<typename ScalarViewType::value_type,DT>
359 dofCoordsLine("dofCoordsLine", cardLine, 1);
360
361 lineBasis.getDofCoords(dofCoordsLine);
362 auto dofCoordsLineHost = Kokkos::create_mirror_view(dofCoordsLine);
363 Kokkos::deep_copy(dofCoordsLineHost, dofCoordsLine);
364 {
365 ordinal_type idx = 0;
366 for (auto k=0;k<cardLine;++k) { // z
367 for (ordinal_type j=0;j<cardLine;++j) { // y
368 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
369 dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
370 dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
371 dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
372 }
373 }
374 }
375 }
376
377 this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoordsHost);
378 Kokkos::deep_copy(this->dofCoords_, dofCoordsHost);
379 }
380
381 template<typename DT, typename OT, typename PT>
382 void
383 Basis_HGRAD_HEX_Cn_FEM<DT,OT,PT>::getScratchSpaceSize(
384 ordinal_type& perTeamSpaceSize,
385 ordinal_type& perThreadSpaceSize,
386 const PointViewType inputPoints,
387 const EOperator operatorType) const {
388 (void) operatorType; //avoid warning for unused variable
389 perTeamSpaceSize = 0;
390 perThreadSpaceSize = 4*this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType);
391 }
392
393 template<typename DT, typename OT, typename PT>
394 KOKKOS_INLINE_FUNCTION
395 void
396 Basis_HGRAD_HEX_Cn_FEM<DT,OT,PT>::getValues(
397 OutputViewType outputValues,
398 const PointViewType inputPoints,
399 const EOperator operatorType,
400 const typename Kokkos::TeamPolicy<typename DT::execution_space>::member_type& team_member,
401 const typename DT::execution_space::scratch_memory_space & scratchStorage,
402 const ordinal_type subcellDim,
403 const ordinal_type subcellOrdinal) const {
404
405 INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)),
406 ">>> ERROR: (Intrepid2::Basis_HGRAD_HEX_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet.");
407
408 const int numPoints = inputPoints.extent(0);
409 using ScalarType = typename ScalarTraits<typename PointViewType::value_type>::scalar_type;
410 using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits<Kokkos::Unmanaged> >;
411 ordinal_type sizePerPoint = 4*this->vinv_.extent(0)*get_dimension_scalar(inputPoints);
412 WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size());
413 using range_type = Kokkos::pair<ordinal_type,ordinal_type>;
414
415 switch(operatorType) {
416 case OPERATOR_VALUE:
417 Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=, &vinv_ = this->vinv_] (ordinal_type& pt) {
418 auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() );
419 const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() );
420 WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
421 Impl::Basis_HGRAD_HEX_Cn_FEM::Serial<OPERATOR_VALUE>::getValues( output, input, work, vinv_ );
422 });
423 break;
424 case OPERATOR_GRAD:
425 Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=, &vinv_ = this->vinv_] (ordinal_type& pt) {
426 auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() );
427 const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() );
428 WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
429 Impl::Basis_HGRAD_HEX_Cn_FEM::Serial<OPERATOR_GRAD>::getValues( output, input, work, vinv_ );
430 });
431 break;
432 default: {
433 INTREPID2_TEST_FOR_ABORT( true,
434 ">>> ERROR (Basis_HGRAD_TET_Cn_FEM): getValues not implemented for this operator");
435 }
436 }
437 }
438}// namespace Intrepid2
439
440#endif
KOKKOS_INLINE_FUNCTION ordinal_type getOperatorOrder(const EOperator operatorType)
Returns order of an operator.
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...
DeduceDynRankView< InViewType >::type createMatchingDynRankView(const InViewType &view, const CtorProp &prop, const Dims... dims)
Creates and returns a view that matches the value_type of the provided view The output view type is d...
Basis_HGRAD_HEX_Cn_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.
Kokkos::DynRankView< typename ScalarViewType::value_type, DeviceType > vinv_
inverse of Generalized Vandermonde matrix (isotropic order)
EPointType pointType_
type of lattice used for creating the DoF coordinates
Implementation of the locally H(grad)-compatible FEM basis of variable order on the [-1,...
virtual void getDofCoords(ScalarViewType dofCoords) const override
Returns spatial locations (coordinates) of degrees of freedom on the reference cell.
const OrdinalTypeArrayStride1DHost getDofTag(const ordinal_type dofOrd) const
DoF ordinal to DoF tag lookup.
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)
ordinal_type getCardinality() const
Returns cardinality of the basis.
Kokkos::DynRankView< scalarType, DeviceType > dofCoords_
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
static constexpr ordinal_type MaxOrder
The maximum reconstruction order.