Intrepid2
Intrepid2_LegendreBasis_HVOL_PYR.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Intrepid2 Package
5 // Copyright (2007) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Mauro Perego (mperego@sandia.gov) or
38 // Nate Roberts (nvrober@sandia.gov)
39 //
40 // ************************************************************************
41 // @HEADER
42 
54 #ifndef Intrepid2_LegendreBasis_HVOL_PYR_h
55 #define Intrepid2_LegendreBasis_HVOL_PYR_h
56 
57 #include <Kokkos_DynRankView.hpp>
58 
59 #include <Intrepid2_config.h>
60 
61 #include "Intrepid2_Basis.hpp"
64 #include "Intrepid2_Utils.hpp"
65 
66 #include "Teuchos_RCP.hpp"
67 
68 namespace Intrepid2
69 {
75  template<class DeviceType, class OutputScalar, class PointScalar,
76  class OutputFieldType, class InputPointsType>
78  {
79  using ExecutionSpace = typename DeviceType::execution_space;
80  using ScratchSpace = typename ExecutionSpace::scratch_memory_space;
81  using OutputScratchView = Kokkos::View<OutputScalar*,ScratchSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
82  using OutputScratchView2D = Kokkos::View<OutputScalar**,ScratchSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
83  using PointScratchView = Kokkos::View<PointScalar*, ScratchSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
84 
85  using TeamPolicy = Kokkos::TeamPolicy<ExecutionSpace>;
86  using TeamMember = typename TeamPolicy::member_type;
87 
88  EOperator opType_;
89 
90  OutputFieldType output_; // F,P
91  InputPointsType inputPoints_; // P,D
92 
93  int polyOrder_;
94  int numFields_, numPoints_;
95 
96  size_t fad_size_output_;
97 
98  static const int numVertices = 5;
99  static const int numMixedEdges = 4;
100  static const int numTriEdges = 4;
101  static const int numEdges = 8;
102  // the following ordering of the edges matches that used by ESEAS
103  // (it *looks* like this is what ESEAS uses; the basis comparison tests will clarify whether I've read their code correctly)
104  // see also PyramidEdgeNodeMap in Shards_BasicTopologies.hpp
105  const int edge_start_[numEdges] = {0,1,2,3,0,1,2,3}; // edge i is from edge_start_[i] to edge_end_[i]
106  const int edge_end_[numEdges] = {1,2,3,0,4,4,4,4}; // edge i is from edge_start_[i] to edge_end_[i]
107 
108  // quadrilateral face comes first
109  static const int numQuadFaces = 1;
110  static const int numTriFaces = 4;
111 
112  // face ordering matches ESEAS. (See BlendProjectPyraTF in ESEAS.)
113  const int tri_face_vertex_0[numTriFaces] = {0,1,3,0}; // faces are abc where 0 ≤ a < b < c ≤ 3
114  const int tri_face_vertex_1[numTriFaces] = {1,2,2,3};
115  const int tri_face_vertex_2[numTriFaces] = {4,4,4,4};
116 
117  Hierarchical_HVOL_PYR_Functor(EOperator opType, OutputFieldType output, InputPointsType inputPoints,
118  int polyOrder)
119  : opType_(opType), output_(output), inputPoints_(inputPoints),
120  polyOrder_(polyOrder),
121  fad_size_output_(getScalarDimensionForView(output))
122  {
123  numFields_ = output.extent_int(0);
124  numPoints_ = output.extent_int(1);
125  const auto & p = polyOrder;
126  const auto p_plus_one_cubed = (p+1) * (p+1) * (p+1);
127  INTREPID2_TEST_FOR_EXCEPTION(numPoints_ != inputPoints.extent_int(0), std::invalid_argument, "point counts need to match!");
128  INTREPID2_TEST_FOR_EXCEPTION(numFields_ != p_plus_one_cubed, std::invalid_argument, "output field size does not match basis cardinality");
129  }
130 
131  KOKKOS_INLINE_FUNCTION
132  void operator()( const TeamMember & teamMember ) const
133  {
134  auto pointOrdinal = teamMember.league_rank();
135  OutputScratchView scratch1D_1, scratch1D_2, scratch1D_3;
136  OutputScratchView scratch1D_4, scratch1D_5, scratch1D_6;
137  OutputScratchView scratch1D_7, scratch1D_8, scratch1D_9;
138  OutputScratchView2D scratch2D_1, scratch2D_2, scratch2D_3;
139  const int numAlphaValues = (polyOrder_-1 > 1) ? (polyOrder_-1) : 1; // make numAlphaValues at least 1 so we can avoid zero-extent allocations…
140  if (fad_size_output_ > 0) {
141  scratch1D_1 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
142  scratch1D_2 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
143  scratch1D_3 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
144  scratch1D_4 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
145  scratch1D_5 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
146  scratch1D_6 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
147  scratch1D_7 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
148  scratch1D_8 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
149  scratch1D_9 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
150  scratch2D_1 = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1, fad_size_output_);
151  scratch2D_2 = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1, fad_size_output_);
152  scratch2D_3 = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1, fad_size_output_);
153  }
154  else {
155  scratch1D_1 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
156  scratch1D_2 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
157  scratch1D_3 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
158  scratch1D_4 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
159  scratch1D_5 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
160  scratch1D_6 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
161  scratch1D_7 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
162  scratch1D_8 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
163  scratch1D_9 = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
164  scratch2D_1 = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1);
165  scratch2D_2 = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1);
166  scratch2D_3 = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1);
167  }
168 
169  const auto & x = inputPoints_(pointOrdinal,0);
170  const auto & y = inputPoints_(pointOrdinal,1);
171  const auto & z = inputPoints_(pointOrdinal,2);
172 
173  // Intrepid2 uses (-1,1)^2 for x,y
174  // ESEAS uses (0,1)^2
175  // (Can look at what we do on the HGRAD_LINE for reference; there's a similar difference for line topology.)
176 
177  Kokkos::Array<PointScalar,3> coords;
178  transformToESEASPyramid<>(coords[0], coords[1], coords[2], x, y, z); // map x,y coordinates from (-z,z)^2 to (0,z)^2
179 
180  // pyramid "affine" coordinates and gradients get stored in lambda, lambdaGrad:
181  using Kokkos::Array;
182  Array<PointScalar,5> lambda;
183  Array<Kokkos::Array<PointScalar,3>,5> lambdaGrad;
184 
185  Array<Array<PointScalar,3>,2> mu; // first index is subscript; second is superscript: 0 --> (\zeta, xi_1), 1 --> (\zeta, xi_2), 2 --> (\zeta)
186  Array<Array<Array<PointScalar,3>,3>,2> muGrad;
187 
188  Array<Array<PointScalar,2>,3> nu;
189  Array<Array<Array<PointScalar,3>,2>,3> nuGrad;
190 
191  affinePyramid(lambda, lambdaGrad, mu, muGrad, nu, nuGrad, coords);
192 
193  switch (opType_)
194  {
195  case OPERATOR_VALUE:
196  {
197  // interior functions
198  // rename scratch
199  ordinal_type fieldOrdinalOffset = 0;
200  auto & Pi = scratch1D_1;
201  auto & Pj = scratch1D_2;
202  auto & Pk = scratch1D_3;
203  // [P_i](mu_01^{\zeta,\xi_1})
204  Polynomials::shiftedScaledLegendreValues(Pi, polyOrder_, mu[1][0], mu[0][0] + mu[1][0]);
205  // [P_j](mu_01^{\zeta,\xi_2})
206  Polynomials::shiftedScaledLegendreValues(Pj, polyOrder_, mu[1][1], mu[0][1] + mu[1][1]);
207  // [P_k](mu_01^{\zeta})
208  Polynomials::shiftedScaledLegendreValues(Pk, polyOrder_, mu[1][2], mu[0][2] + mu[1][2]);
209  // (grad nu_1^{\zeta,\xi_1} x grad nu_1^{\zeta,\xi_2}) \cdot grad mu_1^zeta:
210  PointScalar grad_weight =
211  (nuGrad[1][0][1] * nuGrad[1][1][2] - nuGrad[1][0][2] * nuGrad[1][1][1]) * muGrad[1][2][0]
212  + (nuGrad[1][0][2] * nuGrad[1][1][0] - nuGrad[1][0][0] * nuGrad[1][1][2]) * muGrad[1][2][1]
213  + (nuGrad[1][0][0] * nuGrad[1][1][1] - nuGrad[1][0][1] * nuGrad[1][1][0]) * muGrad[1][2][2];
214 
215  // following the ESEAS ordering: k increments first
216  for (int k=0; k<=polyOrder_; k++)
217  {
218  for (int j=0; j<=polyOrder_; j++)
219  {
220  for (int i=0; i<=polyOrder_; i++)
221  {
222  output_(fieldOrdinalOffset,pointOrdinal) = Pk(k) * Pi(i) * Pj(j) * grad_weight;
223  fieldOrdinalOffset++;
224  }
225  }
226  }
227  } // end OPERATOR_VALUE
228  break;
229  case OPERATOR_GRAD:
230  case OPERATOR_D1:
231  case OPERATOR_D2:
232  case OPERATOR_D3:
233  case OPERATOR_D4:
234  case OPERATOR_D5:
235  case OPERATOR_D6:
236  case OPERATOR_D7:
237  case OPERATOR_D8:
238  case OPERATOR_D9:
239  case OPERATOR_D10:
240  INTREPID2_TEST_FOR_ABORT( true,
241  ">>> ERROR: (Intrepid2::Hierarchical_HVOL_PYR_Functor) Computing of derivatives is not supported");
242  default:
243  // unsupported operator type
244  device_assert(false);
245  }
246  }
247 
248  // Provide the shared memory capacity.
249  // This function takes the team_size as an argument,
250  // which allows team_size-dependent allocations.
251  size_t team_shmem_size (int team_size) const
252  {
253  // we use shared memory to create a fast buffer for basis computations
254  // for the (integrated) Legendre computations, we just need p+1 values stored. For interior functions on the pyramid, we have up to 3 scratch arrays with (integrated) Legendre values stored, for each of the 3 directions (i,j,k indices): a total of 9.
255  // for the (integrated) Jacobi computations, though, we want (p+1)*(# alpha values)
256  // alpha is either 2i or 2(i+j), where i=2,…,p or i+j=3,…,p. So there are at most (p-1) alpha values needed.
257  // We can have up to 3 of the (integrated) Jacobi values needed at once.
258  const int numAlphaValues = std::max(polyOrder_-1, 1); // make it at least 1 so we can avoid zero-extent ranks…
259  size_t shmem_size = 0;
260  if (fad_size_output_ > 0)
261  {
262  // Legendre:
263  shmem_size += 9 * OutputScratchView::shmem_size(polyOrder_ + 1, fad_size_output_);
264  // Jacobi:
265  shmem_size += 3 * OutputScratchView2D::shmem_size(numAlphaValues, polyOrder_ + 1, fad_size_output_);
266  }
267  else
268  {
269  // Legendre:
270  shmem_size += 9 * OutputScratchView::shmem_size(polyOrder_ + 1);
271  // Jacobi:
272  shmem_size += 3 * OutputScratchView2D::shmem_size(numAlphaValues, polyOrder_ + 1);
273  }
274 
275  return shmem_size;
276  }
277  };
278 
290  template<typename DeviceType,
291  typename OutputScalar = double,
292  typename PointScalar = double>
294  : public Basis<DeviceType,OutputScalar,PointScalar>
295  {
296  public:
298 
299  using typename BasisBase::OrdinalTypeArray1DHost;
300  using typename BasisBase::OrdinalTypeArray2DHost;
301 
302  using typename BasisBase::OutputViewType;
303  using typename BasisBase::PointViewType;
304  using typename BasisBase::ScalarViewType;
305 
306  using typename BasisBase::ExecutionSpace;
307 
308  protected:
309  int polyOrder_; // the maximum order of the polynomial
310  EPointType pointType_;
311  public:
317  LegendreBasis_HVOL_PYR(int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
318  :
319  polyOrder_(polyOrder),
320  pointType_(pointType)
321  {
322  INTREPID2_TEST_FOR_EXCEPTION(pointType!=POINTTYPE_DEFAULT,std::invalid_argument,"PointType not supported");
323  this->basisCardinality_ = (polyOrder + 1) * (polyOrder + 1) * (polyOrder + 1);
324  this->basisDegree_ = polyOrder;
325  this->basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Pyramid<> >() );
326  this->basisType_ = BASIS_FEM_HIERARCHICAL;
327  this->basisCoordinates_ = COORDINATES_CARTESIAN;
328  this->functionSpace_ = FUNCTION_SPACE_HVOL;
329 
330  const int degreeLength = 1;
331  this->fieldOrdinalPolynomialDegree_ = OrdinalTypeArray2DHost("Legendre H(vol) pyramid polynomial degree lookup", this->basisCardinality_, degreeLength);
332  this->fieldOrdinalH1PolynomialDegree_ = OrdinalTypeArray2DHost("Legendre H(vol) pyramid polynomial H^1 degree lookup", this->basisCardinality_, degreeLength);
333 
334  int fieldOrdinalOffset = 0;
335 
336  // **** interior functions **** //
337  const int numVolumes = 1; // interior
338  for (int volumeOrdinal=0; volumeOrdinal<numVolumes; volumeOrdinal++)
339  {
340  // following the ESEAS ordering: k increments first
341  for (int k=0; k<=polyOrder_; k++)
342  {
343  for (int j=0; j<=polyOrder_; j++)
344  {
345  for (int i=0; i<=polyOrder_; i++)
346  {
347  const int max_ij = std::max(i,j);
348  const int max_ijk = std::max(max_ij,k);
349  this->fieldOrdinalPolynomialDegree_ (fieldOrdinalOffset,0) = max_ijk; // L^2 degree
350  this->fieldOrdinalH1PolynomialDegree_(fieldOrdinalOffset,0) = max_ijk + 1; // H^1 degree
351  fieldOrdinalOffset++;
352  }
353  }
354  }
355  }
356 
357  INTREPID2_TEST_FOR_EXCEPTION(fieldOrdinalOffset != this->basisCardinality_, std::invalid_argument, "Internal error: basis enumeration is incorrect");
358 
359  // initialize tags
360  {
361  const auto & cardinality = this->basisCardinality_;
362 
363  // Basis-dependent initializations
364  const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
365  const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
366  const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
367  const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
368 
369  OrdinalTypeArray1DHost tagView("tag view", cardinality*tagSize);
370  const ordinal_type volumeDim = 3;
371 
372  for (ordinal_type i=0;i<cardinality;++i) {
373  tagView(i*tagSize+0) = volumeDim; // volume dimension
374  tagView(i*tagSize+1) = 0; // volume ordinal
375  tagView(i*tagSize+2) = i; // local dof id
376  tagView(i*tagSize+3) = cardinality; // total number of dofs on this volume
377  }
378 
379  // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
380  // tags are constructed on host
381  this->setOrdinalTagData(this->tagToOrdinal_,
382  this->ordinalToTag_,
383  tagView,
384  this->basisCardinality_,
385  tagSize,
386  posScDim,
387  posScOrd,
388  posDfOrd);
389  }
390  }
391 
396  const char* getName() const override {
397  return "Intrepid2_LegendreBasis_HVOL_PYR";
398  }
399 
402  virtual bool requireOrientation() const override {
403  return false;
404  }
405 
406  // since the getValues() below only overrides the FEM variant, we specify that
407  // we use the base class's getValues(), which implements the FVD variant by throwing an exception.
408  // (It's an error to use the FVD variant on this basis.)
409  using BasisBase::getValues;
410 
429  virtual void getValues( OutputViewType outputValues, const PointViewType inputPoints,
430  const EOperator operatorType = OPERATOR_VALUE ) const override
431  {
432  auto numPoints = inputPoints.extent_int(0);
433 
435 
436  FunctorType functor(operatorType, outputValues, inputPoints, polyOrder_);
437 
438  const int outputVectorSize = getVectorSizeForHierarchicalParallelism<OutputScalar>();
439  const int pointVectorSize = getVectorSizeForHierarchicalParallelism<PointScalar>();
440  const int vectorSize = std::max(outputVectorSize,pointVectorSize);
441  const int teamSize = 1; // because of the way the basis functions are computed, we don't have a second level of parallelism...
442 
443  auto policy = Kokkos::TeamPolicy<ExecutionSpace>(numPoints,teamSize,vectorSize);
444  Kokkos::parallel_for("Hierarchical_HVOL_PYR_Functor", policy, functor);
445  }
446 
455  BasisPtr<DeviceType,OutputScalar,PointScalar>
456  getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const override{
457  // no subcell ref basis for HVOL
458  INTREPID2_TEST_FOR_EXCEPTION(true,std::invalid_argument,"Input parameters out of bounds");
459  }
460 
465  virtual BasisPtr<typename Kokkos::HostSpace::device_type, OutputScalar, PointScalar>
466  getHostBasis() const override {
467  using HostDeviceType = typename Kokkos::HostSpace::device_type;
469  return Teuchos::rcp( new HostBasisType(polyOrder_, pointType_) );
470  }
471  };
472 } // end namespace Intrepid2
473 
474 // do ETI with default (double) type
476 
477 #endif /* Intrepid2_LegendreBasis_HVOL_PYR_h */
Functor for computing values for the LegendreBasis_HVOL_PYR class.
Kokkos::DynRankView< OutputValueType, Kokkos::LayoutStride, DeviceType > OutputViewType
View type for basis value output.
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
LegendreBasis_HVOL_PYR(int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Constructor.
virtual void getValues(const ExecutionSpace &, OutputViewType, const PointViewType, const EOperator=OPERATOR_VALUE) const
Evaluation of a FEM basis on a reference cell.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
Defines several coordinates and their gradients on the pyramid; maps from Intrepid2 (shards) pyramid ...
An abstract base class that defines interface for concrete basis implementations for Finite Element (...
Kokkos::DynRankView< scalarType, Kokkos::LayoutStride, DeviceType > ScalarViewType
View type for scalars.
Free functions, callable from device code, that implement various polynomials useful in basis definit...
EFunctionSpace functionSpace_
The function space in which the basis is defined.
ordinal_type basisDegree_
Degree of the largest complete polynomial space that can be represented by the basis.
Basis defining integrated Legendre basis on the line, a polynomial subspace of H(grad) on the line...
Header function for Intrepid2::Util class and other utility functions.
virtual BasisPtr< typename Kokkos::HostSpace::device_type, OutputScalar, PointScalar > getHostBasis() const override
Creates and returns a Basis object whose DeviceType template argument is Kokkos::HostSpace::device_ty...
Kokkos::View< ordinal_type **, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray2DHost
View type for 2d host array.
Kokkos::DynRankView< OutputValueType, Kokkos::LayoutStride, DeviceType > OutputViewType
View type for basis value output.
const char * getName() const override
Returns basis name.
ordinal_type basisCardinality_
Cardinality of the basis, i.e., the number of basis functions/degrees-of-freedom. ...
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
OrdinalTypeArray3DHost tagToOrdinal_
DoF tag to ordinal lookup table.
virtual void getValues(OutputViewType outputValues, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const override
Evaluation of a FEM basis on a reference cell.
OrdinalTypeArray2DHost ordinalToTag_
&quot;true&quot; if tagToOrdinal_ and ordinalToTag_ have been initialized
ECoordinates basisCoordinates_
The coordinate system for which the basis is defined.
shards::CellTopology basisCellTopology_
Base topology of the cells for which the basis is defined. See the Shards package for definition of b...
OrdinalTypeArray2DHost fieldOrdinalH1PolynomialDegree_
H^1 polynomial degree for each degree of freedom. Only defined for hierarchical bases right now...
OrdinalTypeArray2DHost fieldOrdinalPolynomialDegree_
Polynomial degree for each degree of freedom. Only defined for hierarchical bases right now...
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)
Fills ordinalToTag_ and tagToOrdinal_ by basis-specific tag data.
BasisPtr< DeviceType, OutputScalar, PointScalar > getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const override
returns the basis associated to a subCell.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
Header file for the abstract base class Intrepid2::Basis.
typename DeviceType::execution_space ExecutionSpace
(Kokkos) Execution space for basis.
virtual bool requireOrientation() const override
True if orientation is required.