Intrepid2
Intrepid2_IntegratedLegendreBasis_HGRAD_TRI.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#ifndef Intrepid2_IntegratedLegendreBasis_HGRAD_TRI_h
16#define Intrepid2_IntegratedLegendreBasis_HGRAD_TRI_h
17
18#include <Kokkos_DynRankView.hpp>
19
20#include <Intrepid2_config.h>
21
22#include "Intrepid2_Basis.hpp"
25#include "Intrepid2_Utils.hpp"
26
27namespace Intrepid2
28{
34 template<class DeviceType, class OutputScalar, class PointScalar,
35 class OutputFieldType, class InputPointsType>
37 {
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>>;
42
43 using TeamPolicy = Kokkos::TeamPolicy<ExecutionSpace>;
44 using TeamMember = typename TeamPolicy::member_type;
45
46 EOperator opType_;
47
48 OutputFieldType output_; // F,P
49 InputPointsType inputPoints_; // P,D
50
51 int polyOrder_;
52 bool defineVertexFunctions_;
53 int numFields_, numPoints_;
54
55 size_t fad_size_output_;
56
57 static const int numVertices = 3;
58 static const int numEdges = 3;
59 const int edge_start_[numEdges] = {0,1,0}; // edge i is from edge_start_[i] to edge_end_[i]
60 const int edge_end_[numEdges] = {1,2,2}; // edge i is from edge_start_[i] to edge_end_[i]
61
62 Hierarchical_HGRAD_TRI_Functor(EOperator opType, OutputFieldType output, InputPointsType inputPoints,
63 int polyOrder, bool defineVertexFunctions)
64 : opType_(opType), output_(output), inputPoints_(inputPoints),
65 polyOrder_(polyOrder), defineVertexFunctions_(defineVertexFunctions),
66 fad_size_output_(getScalarDimensionForView(output))
67 {
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");
72 }
73
74 KOKKOS_INLINE_FUNCTION
75 void operator()( const TeamMember & teamMember ) const
76 {
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_);
84 }
85 else {
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);
90 }
91
92 const auto & x = inputPoints_(pointOrdinal,0);
93 const auto & y = inputPoints_(pointOrdinal,1);
94
95 // write as barycentric coordinates:
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.};
99
100 const int num1DEdgeFunctions = polyOrder_ - 1;
101
102 switch (opType_)
103 {
104 case OPERATOR_VALUE:
105 {
106 // vertex functions come first, according to vertex ordering: (0,0), (1,0), (0,1)
107 for (int vertexOrdinal=0; vertexOrdinal<numVertices; vertexOrdinal++)
108 {
109 output_(vertexOrdinal,pointOrdinal) = lambda[vertexOrdinal];
110 }
111 if (!defineVertexFunctions_)
112 {
113 // "DG" basis case
114 // here, we overwrite the first vertex function with 1:
115 output_(0,pointOrdinal) = 1.0;
116 }
117
118 // edge functions
119 int fieldOrdinalOffset = 3;
120 for (int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
121 {
122 const auto & s0 = lambda[edge_start_[edgeOrdinal]];
123 const auto & s1 = lambda[ edge_end_[edgeOrdinal]];
124
125 Polynomials::shiftedScaledIntegratedLegendreValues(edge_field_values_at_point, polyOrder_, PointScalar(s1), PointScalar(s0+s1));
126 for (int edgeFunctionOrdinal=0; edgeFunctionOrdinal<num1DEdgeFunctions; edgeFunctionOrdinal++)
127 {
128 // the first two integrated legendre functions are essentially the vertex functions; hence the +2 on on the RHS here:
129 output_(edgeFunctionOrdinal+fieldOrdinalOffset,pointOrdinal) = edge_field_values_at_point(edgeFunctionOrdinal+2);
130 }
131 fieldOrdinalOffset += num1DEdgeFunctions;
132 }
133
134 // face functions
135 {
136 // these functions multiply the edge functions from the 01 edge by integrated Jacobi functions, appropriately scaled
137 const double jacobiScaling = 1.0; // s0 + s1 + s2
138
139 const int max_ij_sum = polyOrder_;
140 const int min_i = 2;
141 const int min_j = 1;
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++)
144 {
145 for (int i=min_i; i<=ij_sum-min_j; i++)
146 {
147 const int j = ij_sum - i;
148 const int edgeBasisOrdinal = i+numVertices-2; // i+1: where the value of the edge function is stored in output_
149 const auto & edgeValue = output_(edgeBasisOrdinal,pointOrdinal);
150 const double alpha = i*2.0;
151
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++;
156 }
157 }
158 }
159 } // end OPERATOR_VALUE
160 break;
161 case OPERATOR_GRAD:
162 case OPERATOR_D1:
163 {
164 // vertex functions
165 if (defineVertexFunctions_)
166 {
167 // standard, "CG" basis case
168 // first vertex function is 1-x-y
169 output_(0,pointOrdinal,0) = -1.0;
170 output_(0,pointOrdinal,1) = -1.0;
171 }
172 else
173 {
174 // "DG" basis case
175 // here, the first "vertex" function is 1, so the derivative is 0:
176 output_(0,pointOrdinal,0) = 0.0;
177 output_(0,pointOrdinal,1) = 0.0;
178 }
179 // second vertex function is x
180 output_(1,pointOrdinal,0) = 1.0;
181 output_(1,pointOrdinal,1) = 0.0;
182 // third vertex function is y
183 output_(2,pointOrdinal,0) = 0.0;
184 output_(2,pointOrdinal,1) = 1.0;
185
186 // edge functions
187 int fieldOrdinalOffset = 3;
188 /*
189 Per Fuentes et al. (see Appendix E.1, E.2), the edge functions, defined for i ≥ 2, are
190 [L_i](s0,s1) = L_i(s1; s0+s1)
191 and have gradients:
192 grad [L_i](s0,s1) = [P_{i-1}](s0,s1) grad s1 + [R_{i-1}](s0,s1) grad (s0 + s1)
193 where
194 [R_{i-1}](s0,s1) = R_{i-1}(s1; s0+s1) = d/dt L_{i}(s0; s0+s1)
195 The P_i we have implemented in shiftedScaledLegendreValues, while d/dt L_{i+1} is
196 implemented in shiftedScaledIntegratedLegendreValues_dt.
197 */
198 // rename the scratch memory to match our usage here:
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++)
202 {
203 const auto & s0 = lambda[edge_start_[edgeOrdinal]];
204 const auto & s1 = lambda[ edge_end_[edgeOrdinal]];
205
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]];
210
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++)
214 {
215 // the first two (integrated) Legendre functions are essentially the vertex functions; hence the +2 here:
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);
219 }
220 fieldOrdinalOffset += num1DEdgeFunctions;
221 }
222
223 /*
224 Fuentes et al give the face functions as phi_{ij}, with gradient:
225 grad phi_{ij}(s0,s1,s2) = [L^{2i}_j](s0+s1,s2) grad [L_i](s0,s1) + [L_i](s0,s1) grad [L^{2i}_j](s0+s1,s2)
226 where:
227 - grad [L_i](s0,s1) is the edge function gradient we computed above
228 - [L_i](s0,s1) is the edge function which we have implemented above (in OPERATOR_VALUE)
229 - L^{2i}_j is a Jacobi polynomial with:
230 [L^{2i}_j](s0,s1) = L^{2i}_j(s1;s0+s1)
231 and the gradient for j ≥ 1 is
232 grad [L^{2i}_j](s0,s1) = [P^{2i}_{j-1}](s0,s1) grad s1 + [R^{2i}_{j-1}(s0,s1)] grad (s0 + s1)
233 Here,
234 [P^{2i}_{j-1}](s0,s1) = P^{2i}_{j-1}(s1,s0+s1)
235 and
236 [R^{2i}_{j-1}(s0,s1)] = d/dt L^{2i}_j(s1,s0+s1)
237 We have implemented P^{alpha}_{j} as shiftedScaledJacobiValues,
238 and d/dt L^{alpha}_{j} as shiftedScaledIntegratedJacobiValues_dt.
239 */
240 // rename the scratch memory to match our usage here:
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;
245 {
246 // face functions multiply the edge functions from the 01 edge by integrated Jacobi functions, appropriately scaled
247 const double jacobiScaling = 1.0; // s0 + s1 + s2
248
249 const int max_ij_sum = polyOrder_;
250 const int min_i = 2;
251 const int min_j = 1;
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++)
254 {
255 for (int i=min_i; i<=ij_sum-min_j; i++)
256 {
257 const int j = ij_sum - i;
258 // the edge function here is for edge 01, in the first set of edge functions.
259 const int edgeBasisOrdinal = i+numVertices-2; // i+1: where the value of the edge function is stored in output_
260 const auto & grad_L_i_dx = output_(edgeBasisOrdinal,pointOrdinal,0);
261 const auto & grad_L_i_dy = output_(edgeBasisOrdinal,pointOrdinal,1);
262
263 const double alpha = i*2.0;
264
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);
269
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];
276
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));
279
280 output_(fieldOrdinalOffset,pointOrdinal,0) = basisValue_dx;
281 output_(fieldOrdinalOffset,pointOrdinal,1) = basisValue_dy;
282 fieldOrdinalOffset++;
283 }
284 }
285 }
286 }
287 break;
288 case OPERATOR_D2:
289 case OPERATOR_D3:
290 case OPERATOR_D4:
291 case OPERATOR_D5:
292 case OPERATOR_D6:
293 case OPERATOR_D7:
294 case OPERATOR_D8:
295 case OPERATOR_D9:
296 case OPERATOR_D10:
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");
299 default:
300 // unsupported operator type
301 device_assert(false);
302 }
303 }
304
305 // Provide the shared memory capacity.
306 // This function takes the team_size as an argument,
307 // which allows team_size-dependent allocations.
308 size_t team_shmem_size (int team_size) const
309 {
310 // we will use shared memory to create a fast buffer for basis computations
311 size_t shmem_size = 0;
312 if (fad_size_output_ > 0)
313 shmem_size += 4 * OutputScratchView::shmem_size(polyOrder_ + 1, fad_size_output_);
314 else
315 shmem_size += 4 * OutputScratchView::shmem_size(polyOrder_ + 1);
316
317 return shmem_size;
318 }
319 };
320
337 template<typename DeviceType,
338 typename OutputScalar = double,
339 typename PointScalar = double,
340 bool defineVertexFunctions = true> // if defineVertexFunctions is true, first three basis functions are 1-x-y, x, and y. Otherwise, they are 1, x, and y.
342 : public Basis<DeviceType,OutputScalar,PointScalar>
343 {
344 public:
347
350
351 using typename BasisBase::OutputViewType;
352 using typename BasisBase::PointViewType;
353 using typename BasisBase::ScalarViewType;
354
355 using typename BasisBase::ExecutionSpace;
356
357 protected:
358 int polyOrder_; // the maximum order of the polynomial
359 EPointType pointType_;
360 public:
371 IntegratedLegendreBasis_HGRAD_TRI(int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
372 :
373 polyOrder_(polyOrder),
374 pointType_(pointType)
375 {
376 INTREPID2_TEST_FOR_EXCEPTION(pointType!=POINTTYPE_DEFAULT,std::invalid_argument,"PointType not supported");
377
378 this->basisCardinality_ = ((polyOrder+2) * (polyOrder+1)) / 2;
379 this->basisDegree_ = polyOrder;
380 this->basisCellTopologyKey_ = shards::Triangle<>::key;
381 this->basisType_ = BASIS_FEM_HIERARCHICAL;
382 this->basisCoordinates_ = COORDINATES_CARTESIAN;
383 this->functionSpace_ = FUNCTION_SPACE_HGRAD;
384
385 const int degreeLength = 1;
386 this->fieldOrdinalPolynomialDegree_ = OrdinalTypeArray2DHost("Integrated Legendre H(grad) triangle polynomial degree lookup", this->basisCardinality_, degreeLength);
387 this->fieldOrdinalH1PolynomialDegree_ = OrdinalTypeArray2DHost("Integrated Legendre H(grad) triangle polynomial degree lookup", this->basisCardinality_, degreeLength);
388
389 int fieldOrdinalOffset = 0;
390 // **** vertex functions **** //
391 const int numVertices = this->getBaseCellTopology().getVertexCount();
392 const int numFunctionsPerVertex = 1;
393 const int numVertexFunctions = numVertices * numFunctionsPerVertex;
394 for (int i=0; i<numVertexFunctions; i++)
395 {
396 // for H(grad) on triangle, if defineVertexFunctions is false, first three basis members are linear
397 // if not, then the only difference is that the first member is constant
398 this->fieldOrdinalPolynomialDegree_ (i,0) = 1;
399 this->fieldOrdinalH1PolynomialDegree_(i,0) = 1;
400 }
401 if (!defineVertexFunctions)
402 {
403 this->fieldOrdinalPolynomialDegree_ (0,0) = 0;
404 this->fieldOrdinalH1PolynomialDegree_(0,0) = 0;
405 }
406 fieldOrdinalOffset += numVertexFunctions;
407
408 // **** edge functions **** //
409 const int numFunctionsPerEdge = polyOrder - 1; // bubble functions: all but the vertices
410 const int numEdges = this->getBaseCellTopology().getEdgeCount();
411 for (int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
412 {
413 for (int i=0; i<numFunctionsPerEdge; i++)
414 {
415 this->fieldOrdinalPolynomialDegree_(i+fieldOrdinalOffset,0) = i+2; // vertex functions are 1st order; edge functions start at order 2
416 this->fieldOrdinalH1PolynomialDegree_(i+fieldOrdinalOffset,0) = i+2; // vertex functions are 1st order; edge functions start at order 2
417 }
418 fieldOrdinalOffset += numFunctionsPerEdge;
419 }
420
421 // **** face functions **** //
422 const int max_ij_sum = polyOrder;
423 const int min_i = 2;
424 const int min_j = 1;
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++)
427 {
428 for (int i=min_i; i<=ij_sum-min_j; i++)
429 {
430 const int j = ij_sum - i;
431 this->fieldOrdinalPolynomialDegree_(fieldOrdinalOffset,0) = i+j;
432 this->fieldOrdinalH1PolynomialDegree_(fieldOrdinalOffset,0) = i+j;
433 fieldOrdinalOffset++;
434 }
435 }
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");
439
440 // initialize tags
441 {
442 const auto & cardinality = this->basisCardinality_;
443
444 // Basis-dependent initializations
445 const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
446 const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
447 const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
448 const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
449
450 OrdinalTypeArray1DHost tagView("tag view", cardinality*tagSize);
451 const int vertexDim = 0, edgeDim = 1, faceDim = 2;
452
453 if (defineVertexFunctions) {
454 {
455 int tagNumber = 0;
456 for (int vertexOrdinal=0; vertexOrdinal<numVertices; vertexOrdinal++)
457 {
458 for (int functionOrdinal=0; functionOrdinal<numFunctionsPerVertex; functionOrdinal++)
459 {
460 tagView(tagNumber*tagSize+0) = vertexDim; // vertex dimension
461 tagView(tagNumber*tagSize+1) = vertexOrdinal; // vertex id
462 tagView(tagNumber*tagSize+2) = functionOrdinal; // local dof id
463 tagView(tagNumber*tagSize+3) = numFunctionsPerVertex; // total number of dofs in this vertex
464 tagNumber++;
465 }
466 }
467 for (int edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++)
468 {
469 for (int functionOrdinal=0; functionOrdinal<numFunctionsPerEdge; functionOrdinal++)
470 {
471 tagView(tagNumber*tagSize+0) = edgeDim; // edge dimension
472 tagView(tagNumber*tagSize+1) = edgeOrdinal; // edge id
473 tagView(tagNumber*tagSize+2) = functionOrdinal; // local dof id
474 tagView(tagNumber*tagSize+3) = numFunctionsPerEdge; // total number of dofs on this edge
475 tagNumber++;
476 }
477 }
478 for (int faceOrdinal=0; faceOrdinal<numFaces; faceOrdinal++)
479 {
480 for (int functionOrdinal=0; functionOrdinal<numFunctionsPerFace; functionOrdinal++)
481 {
482 tagView(tagNumber*tagSize+0) = faceDim; // face dimension
483 tagView(tagNumber*tagSize+1) = faceOrdinal; // face id
484 tagView(tagNumber*tagSize+2) = functionOrdinal; // local dof id
485 tagView(tagNumber*tagSize+3) = numFunctionsPerFace; // total number of dofs on this face
486 tagNumber++;
487 }
488 }
489 }
490 } else {
491 for (ordinal_type i=0;i<cardinality;++i) {
492 tagView(i*tagSize+0) = faceDim; // face dimension
493 tagView(i*tagSize+1) = 0; // face id
494 tagView(i*tagSize+2) = i; // local dof id
495 tagView(i*tagSize+3) = cardinality; // total number of dofs on this face
496 }
497 }
498
499 // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
500 // tags are constructed on host
502 this->ordinalToTag_,
503 tagView,
504 this->basisCardinality_,
505 tagSize,
506 posScDim,
507 posScOrd,
508 posDfOrd);
509 }
510 }
511
516 const char* getName() const override {
517 return "Intrepid2_IntegratedLegendreBasis_HGRAD_TRI";
518 }
519
522 virtual bool requireOrientation() const override {
523 return (this->getDegree() > 2);
524 }
525
526 // since the getValues() below only overrides the FEM variant, we specify that
527 // we use the base class's getValues(), which implements the FVD variant by throwing an exception.
528 // (It's an error to use the FVD variant on this basis.)
530
549 virtual void getValues( OutputViewType outputValues, const PointViewType inputPoints,
550 const EOperator operatorType = OPERATOR_VALUE ) const override
551 {
552 auto numPoints = inputPoints.extent_int(0);
553
555
556 FunctorType functor(operatorType, outputValues, inputPoints, polyOrder_, defineVertexFunctions);
557
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; // because of the way the basis functions are computed, we don't have a second level of parallelism...
562
563 auto policy = Kokkos::TeamPolicy<ExecutionSpace>(numPoints,teamSize,vectorSize);
564 Kokkos::parallel_for("Hierarchical_HGRAD_TRI_Functor", policy, functor);
565 }
566
576 getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const override{
577 if(subCellDim == 1) {
578 return Teuchos::rcp(new
580 (this->basisDegree_));
581 }
582 INTREPID2_TEST_FOR_EXCEPTION(true,std::invalid_argument,"Input parameters out of bounds");
583 }
584
590 getHostBasis() const override {
591 using HostDeviceType = typename Kokkos::HostSpace::device_type;
593 return Teuchos::rcp( new HostBasisType(polyOrder_, pointType_) );
594 }
595 };
596} // end namespace Intrepid2
597
598#endif /* Intrepid2_IntegratedLegendreBasis_HGRAD_TRI_h */
Header file for the abstract base class Intrepid2::Basis.
Teuchos::RCP< Basis< DeviceType, OutputType, PointType > > BasisPtr
Basis Pointer.
KOKKOS_INLINE_FUNCTION void device_assert(bool val)
H(grad) basis on the line based on integrated Legendre polynomials.
Free functions, callable from device code, that implement various polynomials useful in basis definit...
Header function for Intrepid2::Util class and other utility functions.
KOKKOS_INLINE_FUNCTION constexpr unsigned getScalarDimensionForView(const ViewType &view)
Returns the size of the Scalar dimension for the View. This is 0 for non-AD types....
An abstract base class that defines interface for concrete basis implementations for Finite Element (...
ECoordinates basisCoordinates_
The coordinate system for which the basis is defined.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
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.
Kokkos::DynRankView< OutputValueType, Kokkos::LayoutStride, DeviceType > OutputViewType
View type for basis value output.
EBasis basisType_
Type of the basis.
ordinal_type basisDegree_
Degree of the largest complete polynomial space that can be represented by the basis.
ordinal_type getDegree() const
Returns the degree of the basis.
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< scalarType, Kokkos::LayoutStride, DeviceType > ScalarViewType
View type for scalars.
OrdinalTypeArray2DHost ordinalToTag_
"true" if tagToOrdinal_ and ordinalToTag_ have been initialized
OrdinalTypeArray2DHost fieldOrdinalH1PolynomialDegree_
H^1 polynomial degree for each degree of freedom. Only defined for hierarchical bases right now....
Kokkos::View< ordinal_type **, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray2DHost
View type for 2d host array.
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.
shards::CellTopology getBaseCellTopology() const
Returns the base cell topology for which the basis is defined. See Shards documentation https://trili...
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...
typename DeviceType::execution_space ExecutionSpace
(Kokkos) Execution space for basis.
OrdinalTypeArray2DHost fieldOrdinalPolynomialDegree_
Polynomial degree for each degree of freedom. Only defined for hierarchical bases right now....
EFunctionSpace functionSpace_
The function space in which the basis is defined.
Basis defining integrated Legendre basis on the line, a polynomial subspace of H(grad) on the line.
Basis defining integrated Legendre basis on the line, a polynomial subspace of H(grad) on the line: e...
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
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...
virtual void getValues(OutputViewType outputValues, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const override
Evaluation of a FEM basis on a reference cell.
virtual bool requireOrientation() const override
True if orientation is required.
Kokkos::View< ordinal_type **, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray2DHost
View type for 2d host array.
BasisPtr< DeviceType, OutputScalar, PointScalar > getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const override
returns the basis associated to a subCell.
IntegratedLegendreBasis_HGRAD_TRI(int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Constructor.
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
Functor for computing values for the IntegratedLegendreBasis_HGRAD_TRI class.