15 #ifndef Intrepid2_IntegratedLegendreBasis_HGRAD_TET_h
16 #define Intrepid2_IntegratedLegendreBasis_HGRAD_TET_h
18 #include <Kokkos_DynRankView.hpp>
20 #include <Intrepid2_config.h>
35 template<
class DeviceType,
class OutputScalar,
class PointScalar,
36 class OutputFieldType,
class InputPointsType>
39 using ExecutionSpace =
typename DeviceType::execution_space;
40 using ScratchSpace =
typename ExecutionSpace::scratch_memory_space;
41 using OutputScratchView = Kokkos::View<OutputScalar*,ScratchSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
42 using OutputScratchView2D = Kokkos::View<OutputScalar**,ScratchSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
43 using PointScratchView = Kokkos::View<PointScalar*, ScratchSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
45 using TeamPolicy = Kokkos::TeamPolicy<ExecutionSpace>;
46 using TeamMember =
typename TeamPolicy::member_type;
50 OutputFieldType output_;
51 InputPointsType inputPoints_;
54 bool defineVertexFunctions_;
55 int numFields_, numPoints_;
57 size_t fad_size_output_;
59 static const int numVertices = 4;
60 static const int numEdges = 6;
62 const int edge_start_[numEdges] = {0,1,0,0,1,2};
63 const int edge_end_[numEdges] = {1,2,2,3,3,3};
65 static const int numFaces = 4;
66 const int face_vertex_0[numFaces] = {0,0,1,0};
67 const int face_vertex_1[numFaces] = {1,1,2,2};
68 const int face_vertex_2[numFaces] = {2,3,3,3};
72 const int face_ordinal_of_first_edge[numFaces] = {0,0,1,2};
75 int polyOrder,
bool defineVertexFunctions)
76 : opType_(opType), output_(output), inputPoints_(inputPoints),
77 polyOrder_(polyOrder), defineVertexFunctions_(defineVertexFunctions),
78 fad_size_output_(getScalarDimensionForView(output))
80 numFields_ = output.extent_int(0);
81 numPoints_ = output.extent_int(1);
82 INTREPID2_TEST_FOR_EXCEPTION(numPoints_ != inputPoints.extent_int(0), std::invalid_argument,
"point counts need to match!");
83 INTREPID2_TEST_FOR_EXCEPTION(numFields_ != (polyOrder_+1)*(polyOrder_+2)*(polyOrder_+3)/6, std::invalid_argument,
"output field size does not match basis cardinality");
86 KOKKOS_INLINE_FUNCTION
87 void operator()(
const TeamMember & teamMember )
const
89 const int numFaceBasisFunctionsPerFace = (polyOrder_-2) * (polyOrder_-1) / 2;
90 const int numInteriorBasisFunctions = (polyOrder_-3) * (polyOrder_-2) * (polyOrder_-1) / 6;
92 auto pointOrdinal = teamMember.league_rank();
93 OutputScratchView legendre_values1_at_point, legendre_values2_at_point;
94 OutputScratchView2D jacobi_values1_at_point, jacobi_values2_at_point, jacobi_values3_at_point;
95 const int numAlphaValues = (polyOrder_-1 > 1) ? (polyOrder_-1) : 1;
96 if (fad_size_output_ > 0) {
97 legendre_values1_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
98 legendre_values2_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1, fad_size_output_);
99 jacobi_values1_at_point = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1, fad_size_output_);
100 jacobi_values2_at_point = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1, fad_size_output_);
101 jacobi_values3_at_point = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1, fad_size_output_);
104 legendre_values1_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
105 legendre_values2_at_point = OutputScratchView(teamMember.team_shmem(), polyOrder_ + 1);
106 jacobi_values1_at_point = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1);
107 jacobi_values2_at_point = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1);
108 jacobi_values3_at_point = OutputScratchView2D(teamMember.team_shmem(), numAlphaValues, polyOrder_ + 1);
111 const auto & x = inputPoints_(pointOrdinal,0);
112 const auto & y = inputPoints_(pointOrdinal,1);
113 const auto & z = inputPoints_(pointOrdinal,2);
116 const PointScalar lambda[numVertices] = {1. - x - y - z, x, y, z};
117 const PointScalar lambda_dx[numVertices] = {-1., 1., 0., 0.};
118 const PointScalar lambda_dy[numVertices] = {-1., 0., 1., 0.};
119 const PointScalar lambda_dz[numVertices] = {-1., 0., 0., 1.};
121 const int num1DEdgeFunctions = polyOrder_ - 1;
128 for (
int vertexOrdinal=0; vertexOrdinal<numVertices; vertexOrdinal++)
130 output_(vertexOrdinal,pointOrdinal) = lambda[vertexOrdinal];
132 if (!defineVertexFunctions_)
136 output_(0,pointOrdinal) = 1.0;
140 int fieldOrdinalOffset = numVertices;
141 for (
int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
143 const auto & s0 = lambda[edge_start_[edgeOrdinal]];
144 const auto & s1 = lambda[ edge_end_[edgeOrdinal]];
146 Polynomials::shiftedScaledIntegratedLegendreValues(legendre_values1_at_point, polyOrder_, PointScalar(s1), PointScalar(s0+s1));
147 for (
int edgeFunctionOrdinal=0; edgeFunctionOrdinal<num1DEdgeFunctions; edgeFunctionOrdinal++)
150 output_(edgeFunctionOrdinal+fieldOrdinalOffset,pointOrdinal) = legendre_values1_at_point(edgeFunctionOrdinal+2);
152 fieldOrdinalOffset += num1DEdgeFunctions;
158 for (
int faceOrdinal=0; faceOrdinal<numFaces; faceOrdinal++)
160 const auto & s0 = lambda[face_vertex_0[faceOrdinal]];
161 const auto & s1 = lambda[face_vertex_1[faceOrdinal]];
162 const auto & s2 = lambda[face_vertex_2[faceOrdinal]];
163 const PointScalar jacobiScaling = s0 + s1 + s2;
166 for (
int n=2; n<=polyOrder_; n++)
168 const double alpha = n*2;
169 const int alphaOrdinal = n-2;
170 using Kokkos::subview;
172 auto jacobi_alpha = subview(jacobi_values1_at_point, alphaOrdinal, ALL);
173 Polynomials::shiftedScaledIntegratedJacobiValues(jacobi_alpha, alpha, polyOrder_-2, s2, jacobiScaling);
176 const int edgeOrdinal = face_ordinal_of_first_edge[faceOrdinal];
177 int localFaceBasisOrdinal = 0;
178 for (
int totalPolyOrder=3; totalPolyOrder<=polyOrder_; totalPolyOrder++)
180 for (
int i=2; i<totalPolyOrder; i++)
182 const int edgeBasisOrdinal = edgeOrdinal*num1DEdgeFunctions + i-2 + numVertices;
183 const auto & edgeValue = output_(edgeBasisOrdinal,pointOrdinal);
184 const int alphaOrdinal = i-2;
186 const int j = totalPolyOrder - i;
187 const auto & jacobiValue = jacobi_values1_at_point(alphaOrdinal,j);
188 const int fieldOrdinal = fieldOrdinalOffset + localFaceBasisOrdinal;
189 output_(fieldOrdinal,pointOrdinal) = edgeValue * jacobiValue;
191 localFaceBasisOrdinal++;
194 fieldOrdinalOffset += numFaceBasisFunctionsPerFace;
198 for (
int n=3; n<=polyOrder_; n++)
200 const double alpha = n*2;
201 const double jacobiScaling = 1.0;
202 const int alphaOrdinal = n-3;
203 using Kokkos::subview;
205 auto jacobi_alpha = subview(jacobi_values1_at_point, alphaOrdinal, ALL);
206 Polynomials::shiftedScaledIntegratedJacobiValues(jacobi_alpha, alpha, polyOrder_-3, lambda[3], jacobiScaling);
211 const int min_ij = min_i + min_j;
212 const int min_ijk = min_ij + min_k;
213 int localInteriorBasisOrdinal = 0;
214 for (
int totalPolyOrder_ijk=min_ijk; totalPolyOrder_ijk <= polyOrder_; totalPolyOrder_ijk++)
216 int localFaceBasisOrdinal = 0;
217 for (
int totalPolyOrder_ij=min_ij; totalPolyOrder_ij <= totalPolyOrder_ijk-min_j; totalPolyOrder_ij++)
219 for (
int i=2; i <= totalPolyOrder_ij-min_j; i++)
221 const int j = totalPolyOrder_ij - i;
222 const int k = totalPolyOrder_ijk - totalPolyOrder_ij;
223 const int faceBasisOrdinal = numEdges*num1DEdgeFunctions + numVertices + localFaceBasisOrdinal;
224 const auto & faceValue = output_(faceBasisOrdinal,pointOrdinal);
225 const int alphaOrdinal = (i+j)-3;
226 localFaceBasisOrdinal++;
228 const int fieldOrdinal = fieldOrdinalOffset + localInteriorBasisOrdinal;
229 const auto & jacobiValue = jacobi_values1_at_point(alphaOrdinal,k);
230 output_(fieldOrdinal,pointOrdinal) = faceValue * jacobiValue;
231 localInteriorBasisOrdinal++;
235 fieldOrdinalOffset += numInteriorBasisFunctions;
242 if (defineVertexFunctions_)
246 output_(0,pointOrdinal,0) = -1.0;
247 output_(0,pointOrdinal,1) = -1.0;
248 output_(0,pointOrdinal,2) = -1.0;
254 output_(0,pointOrdinal,0) = 0.0;
255 output_(0,pointOrdinal,1) = 0.0;
256 output_(0,pointOrdinal,2) = 0.0;
259 output_(1,pointOrdinal,0) = 1.0;
260 output_(1,pointOrdinal,1) = 0.0;
261 output_(1,pointOrdinal,2) = 0.0;
263 output_(2,pointOrdinal,0) = 0.0;
264 output_(2,pointOrdinal,1) = 1.0;
265 output_(2,pointOrdinal,2) = 0.0;
267 output_(3,pointOrdinal,0) = 0.0;
268 output_(3,pointOrdinal,1) = 0.0;
269 output_(3,pointOrdinal,2) = 1.0;
272 int fieldOrdinalOffset = numVertices;
284 auto & P_i_minus_1 = legendre_values1_at_point;
285 auto & L_i_dt = legendre_values2_at_point;
286 for (
int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
288 const auto & s0 = lambda[edge_start_[edgeOrdinal]];
289 const auto & s1 = lambda[ edge_end_[edgeOrdinal]];
291 const auto & s0_dx = lambda_dx[edge_start_[edgeOrdinal]];
292 const auto & s0_dy = lambda_dy[edge_start_[edgeOrdinal]];
293 const auto & s0_dz = lambda_dz[edge_start_[edgeOrdinal]];
294 const auto & s1_dx = lambda_dx[ edge_end_[edgeOrdinal]];
295 const auto & s1_dy = lambda_dy[ edge_end_[edgeOrdinal]];
296 const auto & s1_dz = lambda_dz[ edge_end_[edgeOrdinal]];
298 Polynomials::shiftedScaledLegendreValues (P_i_minus_1, polyOrder_-1, PointScalar(s1), PointScalar(s0+s1));
299 Polynomials::shiftedScaledIntegratedLegendreValues_dt(L_i_dt, polyOrder_, PointScalar(s1), PointScalar(s0+s1));
300 for (
int edgeFunctionOrdinal=0; edgeFunctionOrdinal<num1DEdgeFunctions; edgeFunctionOrdinal++)
303 const int i = edgeFunctionOrdinal+2;
304 output_(edgeFunctionOrdinal+fieldOrdinalOffset,pointOrdinal,0) = P_i_minus_1(i-1) * s1_dx + L_i_dt(i) * (s1_dx + s0_dx);
305 output_(edgeFunctionOrdinal+fieldOrdinalOffset,pointOrdinal,1) = P_i_minus_1(i-1) * s1_dy + L_i_dt(i) * (s1_dy + s0_dy);
306 output_(edgeFunctionOrdinal+fieldOrdinalOffset,pointOrdinal,2) = P_i_minus_1(i-1) * s1_dz + L_i_dt(i) * (s1_dz + s0_dz);
308 fieldOrdinalOffset += num1DEdgeFunctions;
329 auto & L_i = legendre_values2_at_point;
330 auto & L_2i_j_dt = jacobi_values1_at_point;
331 auto & L_2i_j = jacobi_values2_at_point;
332 auto & P_2i_j_minus_1 = jacobi_values3_at_point;
334 for (
int faceOrdinal=0; faceOrdinal<numFaces; faceOrdinal++)
336 const auto & s0 = lambda[face_vertex_0[faceOrdinal]];
337 const auto & s1 = lambda[face_vertex_1[faceOrdinal]];
338 const auto & s2 = lambda[face_vertex_2[faceOrdinal]];
339 Polynomials::shiftedScaledIntegratedLegendreValues(L_i, polyOrder_, s1, s0+s1);
341 const PointScalar jacobiScaling = s0 + s1 + s2;
344 for (
int n=2; n<=polyOrder_; n++)
346 const double alpha = n*2;
347 const int alphaOrdinal = n-2;
348 using Kokkos::subview;
350 auto L_2i_j_dt_alpha = subview(L_2i_j_dt, alphaOrdinal, ALL);
351 auto L_2i_j_alpha = subview(L_2i_j, alphaOrdinal, ALL);
352 auto P_2i_j_minus_1_alpha = subview(P_2i_j_minus_1, alphaOrdinal, ALL);
353 Polynomials::shiftedScaledIntegratedJacobiValues_dt(L_2i_j_dt_alpha, alpha, polyOrder_-2, s2, jacobiScaling);
354 Polynomials::shiftedScaledIntegratedJacobiValues (L_2i_j_alpha, alpha, polyOrder_-2, s2, jacobiScaling);
355 Polynomials::shiftedScaledJacobiValues(P_2i_j_minus_1_alpha, alpha, polyOrder_-1, s2, jacobiScaling);
358 const int edgeOrdinal = face_ordinal_of_first_edge[faceOrdinal];
359 int localFaceOrdinal = 0;
360 for (
int totalPolyOrder=3; totalPolyOrder<=polyOrder_; totalPolyOrder++)
362 for (
int i=2; i<totalPolyOrder; i++)
364 const int edgeBasisOrdinal = edgeOrdinal*num1DEdgeFunctions + i-2 + numVertices;
365 const auto & grad_L_i_dx = output_(edgeBasisOrdinal,pointOrdinal,0);
366 const auto & grad_L_i_dy = output_(edgeBasisOrdinal,pointOrdinal,1);
367 const auto & grad_L_i_dz = output_(edgeBasisOrdinal,pointOrdinal,2);
369 const int alphaOrdinal = i-2;
371 const auto & s0_dx = lambda_dx[face_vertex_0[faceOrdinal]];
372 const auto & s0_dy = lambda_dy[face_vertex_0[faceOrdinal]];
373 const auto & s0_dz = lambda_dz[face_vertex_0[faceOrdinal]];
374 const auto & s1_dx = lambda_dx[face_vertex_1[faceOrdinal]];
375 const auto & s1_dy = lambda_dy[face_vertex_1[faceOrdinal]];
376 const auto & s1_dz = lambda_dz[face_vertex_1[faceOrdinal]];
377 const auto & s2_dx = lambda_dx[face_vertex_2[faceOrdinal]];
378 const auto & s2_dy = lambda_dy[face_vertex_2[faceOrdinal]];
379 const auto & s2_dz = lambda_dz[face_vertex_2[faceOrdinal]];
381 int j = totalPolyOrder - i;
384 auto & l_2i_j = L_2i_j(alphaOrdinal,j);
386 auto & l_2i_j_dt = L_2i_j_dt(alphaOrdinal,j);
387 auto & p_2i_j_minus_1 = P_2i_j_minus_1(alphaOrdinal,j-1);
389 const OutputScalar basisValue_dx = l_2i_j * grad_L_i_dx + l_i * (p_2i_j_minus_1 * s2_dx + l_2i_j_dt * (s0_dx + s1_dx + s2_dx));
390 const OutputScalar basisValue_dy = l_2i_j * grad_L_i_dy + l_i * (p_2i_j_minus_1 * s2_dy + l_2i_j_dt * (s0_dy + s1_dy + s2_dy));
391 const OutputScalar basisValue_dz = l_2i_j * grad_L_i_dz + l_i * (p_2i_j_minus_1 * s2_dz + l_2i_j_dt * (s0_dz + s1_dz + s2_dz));
393 const int fieldOrdinal = fieldOrdinalOffset + localFaceOrdinal;
395 output_(fieldOrdinal,pointOrdinal,0) = basisValue_dx;
396 output_(fieldOrdinal,pointOrdinal,1) = basisValue_dy;
397 output_(fieldOrdinal,pointOrdinal,2) = basisValue_dz;
402 fieldOrdinalOffset += numFaceBasisFunctionsPerFace;
421 auto & L_alpha = jacobi_values1_at_point;
422 auto & P_alpha = jacobi_values2_at_point;
426 const auto & s0 = lambda[0];
427 const auto & s1 = lambda[1];
428 const auto & s2 = lambda[2];
430 Polynomials::shiftedScaledIntegratedLegendreValues(legendre_values1_at_point, polyOrder_, PointScalar(s1), PointScalar(s0+s1));
433 const PointScalar jacobiScaling = s0 + s1 + s2;
434 for (
int n=2; n<=polyOrder_; n++)
436 const double alpha = n*2;
437 const int alphaOrdinal = n-2;
438 using Kokkos::subview;
440 auto jacobi_alpha = subview(jacobi_values3_at_point, alphaOrdinal, ALL);
441 Polynomials::shiftedScaledIntegratedJacobiValues(jacobi_alpha, alpha, polyOrder_-2, s2, jacobiScaling);
446 for (
int n=3; n<=polyOrder_; n++)
448 const double alpha = n*2;
449 const double jacobiScaling = 1.0;
450 const int alphaOrdinal = n-3;
451 using Kokkos::subview;
455 auto L = subview(L_alpha, alphaOrdinal, ALL);
456 auto P = subview(P_alpha, alphaOrdinal, ALL);
457 Polynomials::shiftedScaledIntegratedJacobiValues(L, alpha, polyOrder_-3, lambda[3], jacobiScaling);
458 Polynomials::shiftedScaledJacobiValues (P, alpha, polyOrder_-3, lambda[3], jacobiScaling);
464 const int min_ij = min_i + min_j;
465 const int min_ijk = min_ij + min_k;
466 int localInteriorBasisOrdinal = 0;
467 for (
int totalPolyOrder_ijk=min_ijk; totalPolyOrder_ijk <= polyOrder_; totalPolyOrder_ijk++)
469 int localFaceBasisOrdinal = 0;
470 for (
int totalPolyOrder_ij=min_ij; totalPolyOrder_ij <= totalPolyOrder_ijk-min_j; totalPolyOrder_ij++)
472 for (
int i=2; i <= totalPolyOrder_ij-min_j; i++)
474 const int j = totalPolyOrder_ij - i;
475 const int k = totalPolyOrder_ijk - totalPolyOrder_ij;
477 const int faceBasisOrdinal = numEdges*num1DEdgeFunctions + numVertices + localFaceBasisOrdinal;
479 const auto & faceValue_dx = output_(faceBasisOrdinal,pointOrdinal,0);
480 const auto & faceValue_dy = output_(faceBasisOrdinal,pointOrdinal,1);
481 const auto & faceValue_dz = output_(faceBasisOrdinal,pointOrdinal,2);
484 OutputScalar faceValue;
486 const auto & edgeValue = legendre_values1_at_point(i);
487 const int alphaOrdinal = i-2;
488 const auto & jacobiValue = jacobi_values3_at_point(alphaOrdinal,j);
489 faceValue = edgeValue * jacobiValue;
491 localFaceBasisOrdinal++;
493 const int alphaOrdinal = (i+j)-3;
495 const int fieldOrdinal = fieldOrdinalOffset + localInteriorBasisOrdinal;
496 const auto & integratedJacobiValue = L_alpha(alphaOrdinal,k);
497 const auto & jacobiValue = P_alpha(alphaOrdinal,k-1);
498 output_(fieldOrdinal,pointOrdinal,0) = integratedJacobiValue * faceValue_dx + faceValue * jacobiValue * lambda_dx[3];
499 output_(fieldOrdinal,pointOrdinal,1) = integratedJacobiValue * faceValue_dy + faceValue * jacobiValue * lambda_dy[3];
500 output_(fieldOrdinal,pointOrdinal,2) = integratedJacobiValue * faceValue_dz + faceValue * jacobiValue * lambda_dz[3];
502 localInteriorBasisOrdinal++;
506 fieldOrdinalOffset += numInteriorBasisFunctions;
518 INTREPID2_TEST_FOR_ABORT(
true,
519 ">>> ERROR: (Intrepid2::Basis_HGRAD_TET_Cn_FEM_ORTH::OrthPolynomialTri) Computing of second and higher-order derivatives is not currently supported");
522 device_assert(
false);
529 size_t team_shmem_size (
int team_size)
const
536 const int numAlphaValues = std::max(polyOrder_-1, 1);
537 size_t shmem_size = 0;
538 if (fad_size_output_ > 0)
541 shmem_size += 2 * OutputScratchView::shmem_size(polyOrder_ + 1, fad_size_output_);
543 shmem_size += 3 * OutputScratchView2D::shmem_size(numAlphaValues, polyOrder_ + 1, fad_size_output_);
548 shmem_size += 2 * OutputScratchView::shmem_size(polyOrder_ + 1);
550 shmem_size += 3 * OutputScratchView2D::shmem_size(numAlphaValues, polyOrder_ + 1);
574 template<
typename DeviceType,
575 typename OutputScalar = double,
576 typename PointScalar = double,
577 bool defineVertexFunctions =
true>
579 :
public Basis<DeviceType,OutputScalar,PointScalar>
595 EPointType pointType_;
609 polyOrder_(polyOrder),
610 pointType_(pointType)
612 INTREPID2_TEST_FOR_EXCEPTION(pointType!=POINTTYPE_DEFAULT,std::invalid_argument,
"PointType not supported");
620 const int degreeLength = 1;
624 int fieldOrdinalOffset = 0;
627 const int numFunctionsPerVertex = 1;
628 const int numVertexFunctions = numVertices * numFunctionsPerVertex;
629 for (
int i=0; i<numVertexFunctions; i++)
636 if (!defineVertexFunctions)
641 fieldOrdinalOffset += numVertexFunctions;
644 const int numFunctionsPerEdge = polyOrder - 1;
646 for (
int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
648 for (
int i=0; i<numFunctionsPerEdge; i++)
653 fieldOrdinalOffset += numFunctionsPerEdge;
657 const int numFunctionsPerFace = ((polyOrder-1)*(polyOrder-2))/2;
658 const int numFaces = 4;
659 for (
int faceOrdinal=0; faceOrdinal<numFaces; faceOrdinal++)
661 for (
int totalPolyOrder=3; totalPolyOrder<=polyOrder_; totalPolyOrder++)
663 const int totalFaceDofs = (totalPolyOrder-2)*(totalPolyOrder-1)/2;
664 const int totalFaceDofsPrevious = (totalPolyOrder-3)*(totalPolyOrder-2)/2;
665 const int faceDofsForPolyOrder = totalFaceDofs - totalFaceDofsPrevious;
666 for (
int i=0; i<faceDofsForPolyOrder; i++)
670 fieldOrdinalOffset++;
676 const int numFunctionsPerVolume = ((polyOrder-1)*(polyOrder-2)*(polyOrder-3))/6;
677 const int numVolumes = 1;
678 for (
int volumeOrdinal=0; volumeOrdinal<numVolumes; volumeOrdinal++)
680 for (
int totalPolyOrder=4; totalPolyOrder<=polyOrder_; totalPolyOrder++)
682 const int totalInteriorDofs = (totalPolyOrder-3)*(totalPolyOrder-2)*(totalPolyOrder-1)/6;
683 const int totalInteriorDofsPrevious = (totalPolyOrder-4)*(totalPolyOrder-3)*(totalPolyOrder-2)/6;
684 const int interiorDofsForPolyOrder = totalInteriorDofs - totalInteriorDofsPrevious;
686 for (
int i=0; i<interiorDofsForPolyOrder; i++)
690 fieldOrdinalOffset++;
695 INTREPID2_TEST_FOR_EXCEPTION(fieldOrdinalOffset != this->
basisCardinality_, std::invalid_argument,
"Internal error: basis enumeration is incorrect");
702 const int intrepid2FaceOrdinals[4] {3,0,1,2};
707 const ordinal_type tagSize = 4;
708 const ordinal_type posScDim = 0;
709 const ordinal_type posScOrd = 1;
710 const ordinal_type posDfOrd = 2;
713 const int vertexDim = 0, edgeDim = 1, faceDim = 2, volumeDim = 3;
715 if (defineVertexFunctions) {
718 for (
int vertexOrdinal=0; vertexOrdinal<numVertices; vertexOrdinal++)
720 for (
int functionOrdinal=0; functionOrdinal<numFunctionsPerVertex; functionOrdinal++)
722 tagView(tagNumber*tagSize+0) = vertexDim;
723 tagView(tagNumber*tagSize+1) = vertexOrdinal;
724 tagView(tagNumber*tagSize+2) = functionOrdinal;
725 tagView(tagNumber*tagSize+3) = numFunctionsPerVertex;
729 for (
int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
731 for (
int functionOrdinal=0; functionOrdinal<numFunctionsPerEdge; functionOrdinal++)
733 tagView(tagNumber*tagSize+0) = edgeDim;
734 tagView(tagNumber*tagSize+1) = edgeOrdinal;
735 tagView(tagNumber*tagSize+2) = functionOrdinal;
736 tagView(tagNumber*tagSize+3) = numFunctionsPerEdge;
740 for (
int faceOrdinalESEAS=0; faceOrdinalESEAS<numFaces; faceOrdinalESEAS++)
742 int faceOrdinalIntrepid2 = intrepid2FaceOrdinals[faceOrdinalESEAS];
743 for (
int functionOrdinal=0; functionOrdinal<numFunctionsPerFace; functionOrdinal++)
745 tagView(tagNumber*tagSize+0) = faceDim;
746 tagView(tagNumber*tagSize+1) = faceOrdinalIntrepid2;
747 tagView(tagNumber*tagSize+2) = functionOrdinal;
748 tagView(tagNumber*tagSize+3) = numFunctionsPerFace;
752 for (
int volumeOrdinal=0; volumeOrdinal<numVolumes; volumeOrdinal++)
754 for (
int functionOrdinal=0; functionOrdinal<numFunctionsPerVolume; functionOrdinal++)
756 tagView(tagNumber*tagSize+0) = volumeDim;
757 tagView(tagNumber*tagSize+1) = volumeOrdinal;
758 tagView(tagNumber*tagSize+2) = functionOrdinal;
759 tagView(tagNumber*tagSize+3) = numFunctionsPerVolume;
763 INTREPID2_TEST_FOR_EXCEPTION(tagNumber != this->
basisCardinality_, std::invalid_argument,
"Internal error: basis tag enumeration is incorrect");
766 for (ordinal_type i=0;i<cardinality;++i) {
767 tagView(i*tagSize+0) = volumeDim;
768 tagView(i*tagSize+1) = 0;
769 tagView(i*tagSize+2) = i;
770 tagView(i*tagSize+3) = cardinality;
792 return "Intrepid2_IntegratedLegendreBasis_HGRAD_TET";
825 const EOperator operatorType = OPERATOR_VALUE )
const override
827 auto numPoints = inputPoints.extent_int(0);
831 FunctorType functor(operatorType, outputValues, inputPoints, polyOrder_, defineVertexFunctions);
833 const int outputVectorSize = getVectorSizeForHierarchicalParallelism<OutputScalar>();
834 const int pointVectorSize = getVectorSizeForHierarchicalParallelism<PointScalar>();
835 const int vectorSize = std::max(outputVectorSize,pointVectorSize);
836 const int teamSize = 1;
838 auto policy = Kokkos::TeamPolicy<ExecutionSpace>(numPoints,teamSize,vectorSize);
839 Kokkos::parallel_for(
"Hierarchical_HGRAD_TET_Functor", policy, functor);
850 BasisPtr<DeviceType,OutputScalar,PointScalar>
852 if(subCellDim == 1) {
853 return Teuchos::rcp(
new
856 }
else if(subCellDim == 2) {
857 return Teuchos::rcp(
new
861 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Input parameters out of bounds");
868 virtual BasisPtr<typename Kokkos::HostSpace::device_type, OutputScalar, PointScalar>
870 using HostDeviceType =
typename Kokkos::HostSpace::device_type;
872 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.
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.
Basis defining integrated Legendre basis on the line, a polynomial subspace of H(grad) on the line...
IntegratedLegendreBasis_HGRAD_TET(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...
BasisPtr< DeviceType, OutputScalar, PointScalar > getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const override
returns the basis associated to a subCell.
Kokkos::DynRankView< scalarType, Kokkos::LayoutStride, DeviceType > ScalarViewType
View type for scalars.
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...
Free functions, callable from device code, that implement various polynomials useful in basis definit...
Kokkos::DynRankView< OutputValueType, Kokkos::LayoutStride, DeviceType > OutputViewType
View type for basis value output.
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.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
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.
Basis defining integrated Legendre basis on the line, a polynomial subspace of H(grad) on the line: e...
Basis defining integrated Legendre basis on the line, a polynomial subspace of H(grad) on the line...
Functor for computing values for the IntegratedLegendreBasis_HGRAD_TET class.
ordinal_type basisCardinality_
Cardinality of the basis, i.e., the number of basis functions/degrees-of-freedom. ...
virtual bool requireOrientation() const override
True if orientation is required.
H(grad) basis on the triangle based on integrated Legendre polynomials.
OrdinalTypeArray3DHost tagToOrdinal_
DoF tag to ordinal lookup table.
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
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.
const char * getName() const override
Returns basis name.
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.
virtual void getValues(OutputViewType outputValues, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const override
Evaluation of a FEM basis on a reference cell.
Header file for the abstract base class Intrepid2::Basis.
typename DeviceType::execution_space ExecutionSpace
(Kokkos) Execution space for basis.