54 #ifndef Intrepid2_LegendreBasis_HVOL_PYR_h
55 #define Intrepid2_LegendreBasis_HVOL_PYR_h
57 #include <Kokkos_DynRankView.hpp>
59 #include <Intrepid2_config.h>
66 #include "Teuchos_RCP.hpp"
75 template<
class DeviceType,
class OutputScalar,
class PointScalar,
76 class OutputFieldType,
class InputPointsType>
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>>;
85 using TeamPolicy = Kokkos::TeamPolicy<ExecutionSpace>;
86 using TeamMember =
typename TeamPolicy::member_type;
90 OutputFieldType output_;
91 InputPointsType inputPoints_;
94 int numFields_, numPoints_;
96 size_t fad_size_output_;
98 static const int numVertices = 5;
99 static const int numMixedEdges = 4;
100 static const int numTriEdges = 4;
101 static const int numEdges = 8;
105 const int edge_start_[numEdges] = {0,1,2,3,0,1,2,3};
106 const int edge_end_[numEdges] = {1,2,3,0,4,4,4,4};
109 static const int numQuadFaces = 1;
110 static const int numTriFaces = 4;
113 const int tri_face_vertex_0[numTriFaces] = {0,1,3,0};
114 const int tri_face_vertex_1[numTriFaces] = {1,2,2,3};
115 const int tri_face_vertex_2[numTriFaces] = {4,4,4,4};
119 : opType_(opType), output_(output), inputPoints_(inputPoints),
120 polyOrder_(polyOrder),
121 fad_size_output_(getScalarDimensionForView(output))
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");
131 KOKKOS_INLINE_FUNCTION
132 void operator()(
const TeamMember & teamMember )
const
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;
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_);
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);
169 const auto & x = inputPoints_(pointOrdinal,0);
170 const auto & y = inputPoints_(pointOrdinal,1);
171 const auto & z = inputPoints_(pointOrdinal,2);
177 Kokkos::Array<PointScalar,3> coords;
178 transformToESEASPyramid<>(coords[0], coords[1], coords[2], x, y, z);
182 Array<PointScalar,5> lambda;
183 Array<Kokkos::Array<PointScalar,3>,5> lambdaGrad;
185 Array<Array<PointScalar,3>,2> mu;
186 Array<Array<Array<PointScalar,3>,3>,2> muGrad;
188 Array<Array<PointScalar,2>,3> nu;
189 Array<Array<Array<PointScalar,3>,2>,3> nuGrad;
191 affinePyramid(lambda, lambdaGrad, mu, muGrad, nu, nuGrad, coords);
199 ordinal_type fieldOrdinalOffset = 0;
200 auto & Pi = scratch1D_1;
201 auto & Pj = scratch1D_2;
202 auto & Pk = scratch1D_3;
204 Polynomials::shiftedScaledLegendreValues(Pi, polyOrder_, mu[1][0], mu[0][0] + mu[1][0]);
206 Polynomials::shiftedScaledLegendreValues(Pj, polyOrder_, mu[1][1], mu[0][1] + mu[1][1]);
208 Polynomials::shiftedScaledLegendreValues(Pk, polyOrder_, mu[1][2], mu[0][2] + mu[1][2]);
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];
216 for (
int k=0; k<=polyOrder_; k++)
218 for (
int j=0; j<=polyOrder_; j++)
220 for (
int i=0; i<=polyOrder_; i++)
222 output_(fieldOrdinalOffset,pointOrdinal) = Pk(k) * Pi(i) * Pj(j) * grad_weight;
223 fieldOrdinalOffset++;
240 INTREPID2_TEST_FOR_ABORT(
true,
241 ">>> ERROR: (Intrepid2::Hierarchical_HVOL_PYR_Functor) Computing of derivatives is not supported");
244 device_assert(
false);
251 size_t team_shmem_size (
int team_size)
const
258 const int numAlphaValues = std::max(polyOrder_-1, 1);
259 size_t shmem_size = 0;
260 if (fad_size_output_ > 0)
263 shmem_size += 9 * OutputScratchView::shmem_size(polyOrder_ + 1, fad_size_output_);
265 shmem_size += 3 * OutputScratchView2D::shmem_size(numAlphaValues, polyOrder_ + 1, fad_size_output_);
270 shmem_size += 9 * OutputScratchView::shmem_size(polyOrder_ + 1);
272 shmem_size += 3 * OutputScratchView2D::shmem_size(numAlphaValues, polyOrder_ + 1);
290 template<
typename DeviceType,
291 typename OutputScalar = double,
292 typename PointScalar =
double>
294 :
public Basis<DeviceType,OutputScalar,PointScalar>
310 EPointType pointType_;
319 polyOrder_(polyOrder),
320 pointType_(pointType)
322 INTREPID2_TEST_FOR_EXCEPTION(pointType!=POINTTYPE_DEFAULT,std::invalid_argument,
"PointType not supported");
325 this->
basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Pyramid<> >() );
330 const int degreeLength = 1;
334 int fieldOrdinalOffset = 0;
337 const int numVolumes = 1;
338 for (
int volumeOrdinal=0; volumeOrdinal<numVolumes; volumeOrdinal++)
341 for (
int k=0; k<=polyOrder_; k++)
343 for (
int j=0; j<=polyOrder_; j++)
345 for (
int i=0; i<=polyOrder_; i++)
347 const int max_ij = std::max(i,j);
348 const int max_ijk = std::max(max_ij,k);
351 fieldOrdinalOffset++;
357 INTREPID2_TEST_FOR_EXCEPTION(fieldOrdinalOffset != this->
basisCardinality_, std::invalid_argument,
"Internal error: basis enumeration is incorrect");
364 const ordinal_type tagSize = 4;
365 const ordinal_type posScDim = 0;
366 const ordinal_type posScOrd = 1;
367 const ordinal_type posDfOrd = 2;
370 const ordinal_type volumeDim = 3;
372 for (ordinal_type i=0;i<cardinality;++i) {
373 tagView(i*tagSize+0) = volumeDim;
374 tagView(i*tagSize+1) = 0;
375 tagView(i*tagSize+2) = i;
376 tagView(i*tagSize+3) = cardinality;
397 return "Intrepid2_LegendreBasis_HVOL_PYR";
430 const EOperator operatorType = OPERATOR_VALUE )
const override
432 auto numPoints = inputPoints.extent_int(0);
436 FunctorType functor(operatorType, outputValues, inputPoints, polyOrder_);
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;
443 auto policy = Kokkos::TeamPolicy<ExecutionSpace>(numPoints,teamSize,vectorSize);
444 Kokkos::parallel_for(
"Hierarchical_HVOL_PYR_Functor", policy, functor);
455 BasisPtr<DeviceType,OutputScalar,PointScalar>
458 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Input parameters out of bounds");
465 virtual BasisPtr<typename Kokkos::HostSpace::device_type, OutputScalar, PointScalar>
467 using HostDeviceType =
typename Kokkos::HostSpace::device_type;
469 return Teuchos::rcp(
new HostBasisType(polyOrder_, pointType_) );
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.
EBasis basisType_
Type of the basis.
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_
"true" 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.