15 #ifndef Intrepid2_IntegratedLegendreBasis_HGRAD_TRI_h
16 #define Intrepid2_IntegratedLegendreBasis_HGRAD_TRI_h
18 #include <Kokkos_DynRankView.hpp>
20 #include <Intrepid2_config.h>
34 template<
class DeviceType,
class OutputScalar,
class PointScalar,
35 class OutputFieldType,
class InputPointsType>
38 using ExecutionSpace =
typename DeviceType::execution_space;
39 using ScratchSpace =
typename ExecutionSpace::scratch_memory_space;
40 using OutputScratchView = Kokkos::View<OutputScalar*,ScratchSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
41 using PointScratchView = Kokkos::View<PointScalar*, ScratchSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
43 using TeamPolicy = Kokkos::TeamPolicy<ExecutionSpace>;
44 using TeamMember =
typename TeamPolicy::member_type;
48 OutputFieldType output_;
49 InputPointsType inputPoints_;
52 bool defineVertexFunctions_;
53 int numFields_, numPoints_;
55 size_t fad_size_output_;
57 static const int numVertices = 3;
58 static const int numEdges = 3;
59 const int edge_start_[numEdges] = {0,1,0};
60 const int edge_end_[numEdges] = {1,2,2};
63 int polyOrder,
bool defineVertexFunctions)
64 : opType_(opType), output_(output), inputPoints_(inputPoints),
65 polyOrder_(polyOrder), defineVertexFunctions_(defineVertexFunctions),
66 fad_size_output_(getScalarDimensionForView(output))
68 numFields_ = output.extent_int(0);
69 numPoints_ = output.extent_int(1);
70 INTREPID2_TEST_FOR_EXCEPTION(numPoints_ != inputPoints.extent_int(0), std::invalid_argument,
"point counts need to match!");
71 INTREPID2_TEST_FOR_EXCEPTION(numFields_ != (polyOrder_+1)*(polyOrder_+2)/2, std::invalid_argument,
"output field size does not match basis cardinality");
74 KOKKOS_INLINE_FUNCTION
75 void operator()(
const TeamMember & teamMember )
const
77 auto pointOrdinal = teamMember.league_rank();
78 OutputScratchView edge_field_values_at_point, jacobi_values_at_point, other_values_at_point, other_values2_at_point;
79 if (fad_size_output_ > 0) {
80 edge_field_values_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
81 jacobi_values_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
82 other_values_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
83 other_values2_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
86 edge_field_values_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
87 jacobi_values_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
88 other_values_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
89 other_values2_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
92 const auto & x = inputPoints_(pointOrdinal,0);
93 const auto & y = inputPoints_(pointOrdinal,1);
96 const PointScalar lambda[3] = {1. - x - y, x, y};
97 const PointScalar lambda_dx[3] = {-1., 1., 0.};
98 const PointScalar lambda_dy[3] = {-1., 0., 1.};
100 const int num1DEdgeFunctions = polyOrder_ - 1;
107 for (
int vertexOrdinal=0; vertexOrdinal<numVertices; vertexOrdinal++)
109 output_(vertexOrdinal,pointOrdinal) = lambda[vertexOrdinal];
111 if (!defineVertexFunctions_)
115 output_(0,pointOrdinal) = 1.0;
119 int fieldOrdinalOffset = 3;
120 for (
int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
122 const auto & s0 = lambda[edge_start_[edgeOrdinal]];
123 const auto & s1 = lambda[ edge_end_[edgeOrdinal]];
125 Polynomials::shiftedScaledIntegratedLegendreValues(edge_field_values_at_point, polyOrder_, PointScalar(s1), PointScalar(s0+s1));
126 for (
int edgeFunctionOrdinal=0; edgeFunctionOrdinal<num1DEdgeFunctions; edgeFunctionOrdinal++)
129 output_(edgeFunctionOrdinal+fieldOrdinalOffset,pointOrdinal) = edge_field_values_at_point(edgeFunctionOrdinal+2);
131 fieldOrdinalOffset += num1DEdgeFunctions;
137 const double jacobiScaling = 1.0;
139 const int max_ij_sum = polyOrder_;
142 const int min_ij_sum = min_i + min_j;
143 for (
int ij_sum = min_ij_sum; ij_sum <= max_ij_sum; ij_sum++)
145 for (
int i=min_i; i<=ij_sum-min_j; i++)
147 const int j = ij_sum - i;
148 const int edgeBasisOrdinal = i+numVertices-2;
149 const auto & edgeValue = output_(edgeBasisOrdinal,pointOrdinal);
150 const double alpha = i*2.0;
152 Polynomials::shiftedScaledIntegratedJacobiValues(jacobi_values_at_point, alpha, polyOrder_-2, lambda[2], jacobiScaling);
153 const auto & jacobiValue = jacobi_values_at_point(j);
154 output_(fieldOrdinalOffset,pointOrdinal) = edgeValue * jacobiValue;
155 fieldOrdinalOffset++;
165 if (defineVertexFunctions_)
169 output_(0,pointOrdinal,0) = -1.0;
170 output_(0,pointOrdinal,1) = -1.0;
176 output_(0,pointOrdinal,0) = 0.0;
177 output_(0,pointOrdinal,1) = 0.0;
180 output_(1,pointOrdinal,0) = 1.0;
181 output_(1,pointOrdinal,1) = 0.0;
183 output_(2,pointOrdinal,0) = 0.0;
184 output_(2,pointOrdinal,1) = 1.0;
187 int fieldOrdinalOffset = 3;
199 auto & P_i_minus_1 = edge_field_values_at_point;
200 auto & L_i_dt = jacobi_values_at_point;
201 for (
int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
203 const auto & s0 = lambda[edge_start_[edgeOrdinal]];
204 const auto & s1 = lambda[ edge_end_[edgeOrdinal]];
206 const auto & s0_dx = lambda_dx[edge_start_[edgeOrdinal]];
207 const auto & s0_dy = lambda_dy[edge_start_[edgeOrdinal]];
208 const auto & s1_dx = lambda_dx[ edge_end_[edgeOrdinal]];
209 const auto & s1_dy = lambda_dy[ edge_end_[edgeOrdinal]];
211 Polynomials::shiftedScaledLegendreValues (P_i_minus_1, polyOrder_-1, PointScalar(s1), PointScalar(s0+s1));
212 Polynomials::shiftedScaledIntegratedLegendreValues_dt(L_i_dt, polyOrder_, PointScalar(s1), PointScalar(s0+s1));
213 for (
int edgeFunctionOrdinal=0; edgeFunctionOrdinal<num1DEdgeFunctions; edgeFunctionOrdinal++)
216 const int i = edgeFunctionOrdinal+2;
217 output_(edgeFunctionOrdinal+fieldOrdinalOffset,pointOrdinal,0) = P_i_minus_1(i-1) * s1_dx + L_i_dt(i) * (s1_dx + s0_dx);
218 output_(edgeFunctionOrdinal+fieldOrdinalOffset,pointOrdinal,1) = P_i_minus_1(i-1) * s1_dy + L_i_dt(i) * (s1_dy + s0_dy);
220 fieldOrdinalOffset += num1DEdgeFunctions;
241 auto & P_2i_j_minus_1 = edge_field_values_at_point;
242 auto & L_2i_j_dt = jacobi_values_at_point;
243 auto & L_i = other_values_at_point;
244 auto & L_2i_j = other_values2_at_point;
247 const double jacobiScaling = 1.0;
249 const int max_ij_sum = polyOrder_;
252 const int min_ij_sum = min_i + min_j;
253 for (
int ij_sum = min_ij_sum; ij_sum <= max_ij_sum; ij_sum++)
255 for (
int i=min_i; i<=ij_sum-min_j; i++)
257 const int j = ij_sum - i;
259 const int edgeBasisOrdinal = i+numVertices-2;
260 const auto & grad_L_i_dx = output_(edgeBasisOrdinal,pointOrdinal,0);
261 const auto & grad_L_i_dy = output_(edgeBasisOrdinal,pointOrdinal,1);
263 const double alpha = i*2.0;
265 Polynomials::shiftedScaledIntegratedLegendreValues (L_i, polyOrder_, lambda[1], lambda[0]+lambda[1]);
266 Polynomials::shiftedScaledIntegratedJacobiValues_dt(L_2i_j_dt, alpha, polyOrder_, lambda[2], jacobiScaling);
267 Polynomials::shiftedScaledIntegratedJacobiValues ( L_2i_j, alpha, polyOrder_, lambda[2], jacobiScaling);
268 Polynomials::shiftedScaledJacobiValues(P_2i_j_minus_1, alpha, polyOrder_-1, lambda[2], jacobiScaling);
270 const auto & s0_dx = lambda_dx[0];
271 const auto & s0_dy = lambda_dy[0];
272 const auto & s1_dx = lambda_dx[1];
273 const auto & s1_dy = lambda_dy[1];
274 const auto & s2_dx = lambda_dx[2];
275 const auto & s2_dy = lambda_dy[2];
277 const OutputScalar basisValue_dx = L_2i_j(j) * grad_L_i_dx + L_i(i) * (P_2i_j_minus_1(j-1) * s2_dx + L_2i_j_dt(j) * (s0_dx + s1_dx + s2_dx));
278 const OutputScalar basisValue_dy = L_2i_j(j) * grad_L_i_dy + L_i(i) * (P_2i_j_minus_1(j-1) * s2_dy + L_2i_j_dt(j) * (s0_dy + s1_dy + s2_dy));
280 output_(fieldOrdinalOffset,pointOrdinal,0) = basisValue_dx;
281 output_(fieldOrdinalOffset,pointOrdinal,1) = basisValue_dy;
282 fieldOrdinalOffset++;
297 INTREPID2_TEST_FOR_ABORT(
true,
298 ">>> ERROR: (Intrepid2::Basis_HGRAD_TRI_Cn_FEM_ORTH::OrthPolynomialTri) Computing of second and higher-order derivatives is not currently supported");
301 device_assert(
false);
308 size_t team_shmem_size (
int team_size)
const
311 size_t shmem_size = 0;
312 if (fad_size_output_ > 0)
313 shmem_size += 4 * OutputScratchView::shmem_size(polyOrder_ + 1, fad_size_output_);
315 shmem_size += 4 * OutputScratchView::shmem_size(polyOrder_ + 1);
337 template<
typename DeviceType,
338 typename OutputScalar = double,
339 typename PointScalar = double,
340 bool defineVertexFunctions =
true>
342 :
public Basis<DeviceType,OutputScalar,PointScalar>
359 EPointType pointType_;
373 polyOrder_(polyOrder),
374 pointType_(pointType)
376 INTREPID2_TEST_FOR_EXCEPTION(pointType!=POINTTYPE_DEFAULT,std::invalid_argument,
"PointType not supported");
385 const int degreeLength = 1;
389 int fieldOrdinalOffset = 0;
392 const int numFunctionsPerVertex = 1;
393 const int numVertexFunctions = numVertices * numFunctionsPerVertex;
394 for (
int i=0; i<numVertexFunctions; i++)
401 if (!defineVertexFunctions)
406 fieldOrdinalOffset += numVertexFunctions;
409 const int numFunctionsPerEdge = polyOrder - 1;
411 for (
int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
413 for (
int i=0; i<numFunctionsPerEdge; i++)
418 fieldOrdinalOffset += numFunctionsPerEdge;
422 const int max_ij_sum = polyOrder;
425 const int min_ij_sum = min_i + min_j;
426 for (
int ij_sum = min_ij_sum; ij_sum <= max_ij_sum; ij_sum++)
428 for (
int i=min_i; i<=ij_sum-min_j; i++)
430 const int j = ij_sum - i;
433 fieldOrdinalOffset++;
436 const int numFaces = 1;
437 const int numFunctionsPerFace = ((polyOrder-1)*(polyOrder-2))/2;
438 INTREPID2_TEST_FOR_EXCEPTION(fieldOrdinalOffset != this->
basisCardinality_, std::invalid_argument,
"Internal error: basis enumeration is incorrect");
445 const ordinal_type tagSize = 4;
446 const ordinal_type posScDim = 0;
447 const ordinal_type posScOrd = 1;
448 const ordinal_type posDfOrd = 2;
451 const int vertexDim = 0, edgeDim = 1, faceDim = 2;
453 if (defineVertexFunctions) {
456 for (
int vertexOrdinal=0; vertexOrdinal<numVertices; vertexOrdinal++)
458 for (
int functionOrdinal=0; functionOrdinal<numFunctionsPerVertex; functionOrdinal++)
460 tagView(tagNumber*tagSize+0) = vertexDim;
461 tagView(tagNumber*tagSize+1) = vertexOrdinal;
462 tagView(tagNumber*tagSize+2) = functionOrdinal;
463 tagView(tagNumber*tagSize+3) = numFunctionsPerVertex;
467 for (
int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
469 for (
int functionOrdinal=0; functionOrdinal<numFunctionsPerEdge; functionOrdinal++)
471 tagView(tagNumber*tagSize+0) = edgeDim;
472 tagView(tagNumber*tagSize+1) = edgeOrdinal;
473 tagView(tagNumber*tagSize+2) = functionOrdinal;
474 tagView(tagNumber*tagSize+3) = numFunctionsPerEdge;
478 for (
int faceOrdinal=0; faceOrdinal<numFaces; faceOrdinal++)
480 for (
int functionOrdinal=0; functionOrdinal<numFunctionsPerFace; functionOrdinal++)
482 tagView(tagNumber*tagSize+0) = faceDim;
483 tagView(tagNumber*tagSize+1) = faceOrdinal;
484 tagView(tagNumber*tagSize+2) = functionOrdinal;
485 tagView(tagNumber*tagSize+3) = numFunctionsPerFace;
491 for (ordinal_type i=0;i<cardinality;++i) {
492 tagView(i*tagSize+0) = faceDim;
493 tagView(i*tagSize+1) = 0;
494 tagView(i*tagSize+2) = i;
495 tagView(i*tagSize+3) = cardinality;
517 return "Intrepid2_IntegratedLegendreBasis_HGRAD_TRI";
550 const EOperator operatorType = OPERATOR_VALUE )
const override
552 auto numPoints = inputPoints.extent_int(0);
556 FunctorType functor(operatorType, outputValues, inputPoints, polyOrder_, defineVertexFunctions);
558 const int outputVectorSize = getVectorSizeForHierarchicalParallelism<OutputScalar>();
559 const int pointVectorSize = getVectorSizeForHierarchicalParallelism<PointScalar>();
560 const int vectorSize = std::max(outputVectorSize,pointVectorSize);
561 const int teamSize = 1;
563 auto policy = Kokkos::TeamPolicy<ExecutionSpace>(numPoints,teamSize,vectorSize);
564 Kokkos::parallel_for(
"Hierarchical_HGRAD_TRI_Functor", policy, functor);
575 BasisPtr<DeviceType,OutputScalar,PointScalar>
577 if(subCellDim == 1) {
578 return Teuchos::rcp(
new
582 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Input parameters out of bounds");
589 virtual BasisPtr<typename Kokkos::HostSpace::device_type, OutputScalar, PointScalar>
591 using HostDeviceType =
typename Kokkos::HostSpace::device_type;
593 return Teuchos::rcp(
new HostBasisType(polyOrder_, pointType_) );
H(grad) basis on the line based on integrated Legendre polynomials.
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
virtual bool requireOrientation() const override
True if orientation is required.
const char * getName() const override
Returns basis name.
unsigned basisCellTopologyKey_
Identifier of the base topology of the cells for which the basis is defined. See the Shards package f...
EBasis basisType_
Type of the basis.
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
IntegratedLegendreBasis_HGRAD_TRI(int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Constructor.
An abstract base class that defines interface for concrete basis implementations for Finite Element (...
shards::CellTopology getBaseCellTopology() const
Returns the base cell topology for which the basis is defined. See Shards documentation https://trili...
virtual void getValues(OutputViewType outputValues, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const override
Evaluation of a FEM basis on a reference cell.
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.
virtual KOKKOS_INLINE_FUNCTION void getValues(OutputViewType, const PointViewType, const EOperator, const typename Kokkos::TeamPolicy< ExecutionSpace >::member_type &teamMember, const typename ExecutionSpace::scratch_memory_space &scratchStorage, const ordinal_type subcellDim=-1, const ordinal_type subcellOrdinal=-1) const
Team-level evaluation of basis functions on a reference cell.
Header function for Intrepid2::Util class and other utility functions.
BasisPtr< DeviceType, OutputScalar, PointScalar > getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const override
returns the basis associated to a subCell.
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.
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...
Basis defining integrated Legendre basis on the line, a polynomial subspace of H(grad) on the line: e...
Functor for computing values for the IntegratedLegendreBasis_HGRAD_TRI class.
Basis defining integrated Legendre basis on the line, a polynomial subspace of H(grad) on the line...
ordinal_type basisCardinality_
Cardinality of the basis, i.e., the number of basis functions/degrees-of-freedom. ...
OrdinalTypeArray3DHost tagToOrdinal_
DoF tag to ordinal lookup table.
Kokkos::DynRankView< OutputValueType, Kokkos::LayoutStride, DeviceType > OutputViewType
View type for basis value output.
OrdinalTypeArray2DHost ordinalToTag_
"true" if tagToOrdinal_ and ordinalToTag_ have been initialized
ordinal_type getDegree() const
Returns the degree of the basis.
ECoordinates basisCoordinates_
The coordinate system for which the basis is defined.
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.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
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.