Intrepid2
Intrepid2_PointToolsDef.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_POINTTOOLS_DEF_HPP__
16#define __INTREPID2_POINTTOOLS_DEF_HPP__
17
18#if defined(_MSC_VER) || defined(_WIN32) && defined(__ICL)
19// M_PI, M_SQRT2, etc. are hidden in MSVC by #ifdef _USE_MATH_DEFINES
20 #ifndef _USE_MATH_DEFINES
21 #define _USE_MATH_DEFINES
22 #endif
23 #include <math.h>
24#endif
25
26namespace Intrepid2 {
27
28// -----------------------------------------------------------------------------------------
29// Front interface
30// -----------------------------------------------------------------------------------------
31
32inline
33ordinal_type
35getLatticeSize( const shards::CellTopology cellType,
36 const ordinal_type order,
37 const ordinal_type offset ) {
38#ifdef HAVE_INTREPID2_DEBUG
39 INTREPID2_TEST_FOR_EXCEPTION( order < 0 || offset < 0,
40 std::invalid_argument ,
41 ">>> ERROR (PointTools::getLatticeSize): order and offset must be positive values." );
42#endif
43 ordinal_type r_val = 0;
44 switch (cellType.getBaseKey()) {
45 case shards::Tetrahedron<>::key: {
46 const auto effectiveOrder = order - 4 * offset;
47 r_val = (effectiveOrder < 0 ? 0 :(effectiveOrder+1)*(effectiveOrder+2)*(effectiveOrder+3)/6);
48 break;
49 }
50 case shards::Triangle<>::key: {
51 const auto effectiveOrder = order - 3 * offset;
52 r_val = (effectiveOrder < 0 ? 0 : (effectiveOrder+1)*(effectiveOrder+2)/2);
53 break;
54 }
55 case shards::Line<>::key: {
56 const auto effectiveOrder = order - 2 * offset;
57 r_val = (effectiveOrder < 0 ? 0 : (effectiveOrder+1));
58 break;
59 }
60 case shards::Quadrilateral<>::key: {
61 const auto effectiveOrder = order - 2 * offset;
62 r_val = std::pow(effectiveOrder < 0 ? 0 : (effectiveOrder+1),2);
63 break;
64 }
65 case shards::Hexahedron<>::key: {
66 const auto effectiveOrder = order - 2 * offset;
67 r_val = std::pow(effectiveOrder < 0 ? 0 : (effectiveOrder+1),3);
68 break;
69 }
70 case shards::Pyramid<>::key: {
71 const auto effectiveOrder = order - 2 * offset;
72 r_val = (effectiveOrder < 0 ? 0 : (effectiveOrder+1)*(effectiveOrder+2)*(2*effectiveOrder+3)/6);
73 break;
74 }
75 default: {
76 INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument ,
77 ">>> ERROR (Intrepid2::PointTools::getLatticeSize): the specified cell type is not supported." );
78 }
79 }
80 return r_val;
81}
82
83template<typename pointValueType, class ...pointProperties>
84void
86getLattice( Kokkos::DynRankView<pointValueType,pointProperties...> points,
87 const shards::CellTopology cell,
88 const ordinal_type order,
89 const ordinal_type offset,
90 const EPointType pointType ) {
91#ifdef HAVE_INTREPID2_DEBUG
92 INTREPID2_TEST_FOR_EXCEPTION( points.rank() != 2,
93 std::invalid_argument ,
94 ">>> ERROR (PointTools::getLattice): points rank must be 2." );
95 INTREPID2_TEST_FOR_EXCEPTION( order < 0 || offset < 0,
96 std::invalid_argument ,
97 ">>> ERROR (PointTools::getLattice): order and offset must be positive values." );
98
99 const size_type latticeSize = getLatticeSize( cell, order, offset );
100 const size_type spaceDim = cell.getDimension();
101
102 INTREPID2_TEST_FOR_EXCEPTION( points.extent(0) != latticeSize ||
103 points.extent(1) != spaceDim,
104 std::invalid_argument ,
105 ">>> ERROR (PointTools::getLattice): dimension does not match to lattice size." );
106#endif
107
108 switch (cell.getBaseKey()) {
109 case shards::Tetrahedron<>::key: getLatticeTetrahedron( points, order, offset, pointType ); break;
110 case shards::Pyramid<>::key: getLatticePyramid ( points, order, offset, pointType ); break;
111 case shards::Triangle<>::key: getLatticeTriangle ( points, order, offset, pointType ); break;
112 case shards::Line<>::key: getLatticeLine ( points, order, offset, pointType ); break;
113 case shards::Quadrilateral<>::key: {
114 auto hostPoints = Kokkos::create_mirror_view(points);
115 shards::CellTopology line(shards::getCellTopologyData<shards::Line<2> >());
116 const ordinal_type numPoints = getLatticeSize( line, order, offset );
117 auto linePoints = getMatchingViewWithLabel(hostPoints, "linePoints", numPoints, 1);
118 getLatticeLine( linePoints, order, offset, pointType );
119 ordinal_type idx=0;
120 for (ordinal_type j=0; j<numPoints; ++j) {
121 for (ordinal_type i=0; i<numPoints; ++i, ++idx) {
122 hostPoints(idx,0) = linePoints(i,0);
123 hostPoints(idx,1) = linePoints(j,0);
124 }
125 }
126 Kokkos::deep_copy(points,hostPoints);
127 }
128 break;
129 case shards::Hexahedron<>::key: {
130 auto hostPoints = Kokkos::create_mirror_view(points);
131 shards::CellTopology line(shards::getCellTopologyData<shards::Line<2> >());
132 const ordinal_type numPoints = getLatticeSize( line, order, offset );
133 auto linePoints = getMatchingViewWithLabel(hostPoints, "linePoints", numPoints, 1);
134 getLatticeLine( linePoints, order, offset, pointType );
135 ordinal_type idx=0;
136 for (ordinal_type k=0; k<numPoints; ++k) {
137 for (ordinal_type j=0; j<numPoints; ++j) {
138 for (ordinal_type i=0; i<numPoints; ++i, ++idx) {
139 hostPoints(idx,0) = linePoints(i,0);
140 hostPoints(idx,1) = linePoints(j,0);
141 hostPoints(idx,2) = linePoints(k,0);
142 }
143 }
144 }
145 Kokkos::deep_copy(points,hostPoints);
146 }
147 break;
148 default: {
149 INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument ,
150 ">>> ERROR (Intrepid2::PointTools::getLattice): the specified cell type is not supported." );
151 }
152 }
153}
154
155template<typename pointValueType, class ...pointProperties>
156void
158getGaussPoints( Kokkos::DynRankView<pointValueType,pointProperties...> points,
159 const ordinal_type order ) {
160#ifdef HAVE_INTREPID2_DEBUG
161 INTREPID2_TEST_FOR_EXCEPTION( points.rank() != 2,
162 std::invalid_argument ,
163 ">>> ERROR (PointTools::getGaussPoints): points rank must be 1." );
164 INTREPID2_TEST_FOR_EXCEPTION( order < 0,
165 std::invalid_argument ,
166 ">>> ERROR (PointTools::getGaussPoints): order must be positive value." );
167#endif
168 const ordinal_type np = order + 1;
169 const double alpha = 0.0, beta = 0.0;
170
171 // until view and dynrankview inter-operatible, we use views in a consistent way
172 Kokkos::View<pointValueType*,Kokkos::HostSpace>
173 zHost("PointTools::getGaussPoints::z", np),
174 wHost("PointTools::getGaussPoints::w", np);
175
176 // sequential means that the code is decorated with KOKKOS_INLINE_FUNCTION
177 // and it does not invoke parallel for inside (cheap operation), which means
178 // that gpu memory is not accessible unless this is called inside of functor.
179 Polylib::Serial::Cubature<POLYTYPE_GAUSS>::getValues(zHost, wHost, np, alpha, beta);
180
181 typedef Kokkos::pair<ordinal_type,ordinal_type> range_type;
182 auto pts = Kokkos::subview( points, range_type(0,np), 0 );
183 // should be fixed after view and dynrankview are inter-operatible
184 auto z = Kokkos::DynRankView<pointValueType,Kokkos::HostSpace>(zHost.data(), np);
185 Kokkos::deep_copy(pts, z);
186}
187
188// -----------------------------------------------------------------------------------------
189// Internal implementation
190// -----------------------------------------------------------------------------------------
191
192template<typename pointValueType, class ...pointProperties>
193void
195getLatticeLine( Kokkos::DynRankView<pointValueType,pointProperties...> points,
196 const ordinal_type order,
197 const ordinal_type offset,
198 const EPointType pointType ) {
199 switch (pointType) {
200 case POINTTYPE_EQUISPACED: getEquispacedLatticeLine( points, order, offset ); break;
201 case POINTTYPE_WARPBLEND: getWarpBlendLatticeLine( points, order, offset ); break;
202 default: {
203 INTREPID2_TEST_FOR_EXCEPTION( true ,
204 std::invalid_argument ,
205 ">>> ERROR (PointTools::getLattice): invalid EPointType." );
206 }
207 }
208}
209
210template<typename pointValueType, class ...pointProperties>
211void
213getLatticeTriangle( Kokkos::DynRankView<pointValueType,pointProperties...> points,
214 const ordinal_type order,
215 const ordinal_type offset,
216 const EPointType pointType ) {
217 switch (pointType) {
218 case POINTTYPE_EQUISPACED: getEquispacedLatticeTriangle( points, order, offset ); break;
219 case POINTTYPE_WARPBLEND: getWarpBlendLatticeTriangle ( points, order, offset ); break;
220 default: {
221 INTREPID2_TEST_FOR_EXCEPTION( true ,
222 std::invalid_argument ,
223 ">>> ERROR (PointTools::getLattice): invalid EPointType." );
224 }
225 }
226}
227
228template<typename pointValueType, class ...pointProperties>
229void
231getLatticeTetrahedron( Kokkos::DynRankView<pointValueType,pointProperties...> points,
232 const ordinal_type order,
233 const ordinal_type offset,
234 const EPointType pointType ) {
235 switch (pointType) {
236 case POINTTYPE_EQUISPACED: getEquispacedLatticeTetrahedron( points, order, offset ); break;
237 case POINTTYPE_WARPBLEND: getWarpBlendLatticeTetrahedron ( points, order, offset ); break;
238 default: {
239 INTREPID2_TEST_FOR_EXCEPTION( true ,
240 std::invalid_argument ,
241 ">>> ERROR (PointTools::getLattice): invalid EPointType." );
242 }
243 }
244}
245
246template<typename pointValueType, class ...pointProperties>
247void
249getLatticePyramid( Kokkos::DynRankView<pointValueType,pointProperties...> points,
250 const ordinal_type order,
251 const ordinal_type offset,
252 const EPointType pointType )
253{
254 switch (pointType) {
255 case POINTTYPE_EQUISPACED: getEquispacedLatticePyramid( points, order, offset ); break;
256 default: {
257 INTREPID2_TEST_FOR_EXCEPTION( true ,
258 std::invalid_argument ,
259 ">>> ERROR (PointTools::getLattice): invalid EPointType." );
260 }
261 }
262}
263
264// -----------------------------------------------------------------------------------------
265
266template<typename pointValueType, class ...pointProperties>
267void
269getEquispacedLatticeLine( Kokkos::DynRankView<pointValueType,pointProperties...> points,
270 const ordinal_type order,
271 const ordinal_type offset ) {
272 auto pointsHost = Kokkos::create_mirror_view(points);
273
274 if (order == 0)
275 pointsHost(0,0) = 0.0;
276 else {
277 const pointValueType h = 2.0 / order;
278 const ordinal_type ibeg = offset, iend = order-offset+1;
279 for (ordinal_type i=ibeg;i<iend;++i)
280 pointsHost(i-ibeg, 0) = -1.0 + h * (pointValueType) i;
281 }
282
283 Kokkos::deep_copy(points, pointsHost);
284}
285
286template<typename pointValueType, class ...pointProperties>
287void
289getWarpBlendLatticeLine( Kokkos::DynRankView<pointValueType,pointProperties...> points,
290 const ordinal_type order,
291 const ordinal_type offset ) {
292 // order is order of polynomial degree. The Gauss-Lobatto points are accurate
293 // up to degree 2*i-1
294 const ordinal_type np = order + 1;
295 const double alpha = 0.0, beta = 0.0;
296 const ordinal_type s = np - 2*offset;
297
298 if (s > 0) {
299 // until view and dynrankview inter-operatible, we use views in a consistent way
300 Kokkos::View<pointValueType*,Kokkos::HostSpace>
301 zHost("PointTools::getGaussPoints::z", np),
302 wHost("PointTools::getGaussPoints::w", np);
303
304 // sequential means that the code is decorated with KOKKOS_INLINE_FUNCTION
305 // and it does not invoke parallel for inside (cheap operation), which means
306 // that gpu memory is not accessible unless this is called inside of functor.
308
309 typedef Kokkos::pair<ordinal_type,ordinal_type> range_type;
310 auto pts = Kokkos::subview( points, range_type(0, s), 0 );
311
312 // this should be fixed after view and dynrankview is interoperatable
313 auto z = Kokkos::DynRankView<pointValueType,Kokkos::HostSpace>(zHost.data() + offset, np-offset);
314
315 const auto common_range = range_type(0, std::min(pts.extent(0), z.extent(0)));
316 Kokkos::deep_copy(Kokkos::subview(pts, common_range),
317 Kokkos::subview(z, common_range));
318 }
319}
320
321template<typename pointValueType, class ...pointProperties>
322void
324getEquispacedLatticeTriangle( Kokkos::DynRankView<pointValueType,pointProperties...> points,
325 const ordinal_type order,
326 const ordinal_type offset ) {
327 TEUCHOS_TEST_FOR_EXCEPTION( order <= 0 ,
328 std::invalid_argument ,
329 ">>> ERROR (Intrepid2::PointTools::getEquispacedLatticeTriangle): order must be positive" );
330
331 auto pointsHost = Kokkos::create_mirror_view(points);
332
333 const pointValueType h = 1.0 / order;
334 ordinal_type cur = 0;
335
336 for (ordinal_type i=offset;i<=order-offset;i++) {
337 for (ordinal_type j=offset;j<=order-i-offset;j++) {
338 pointsHost(cur,0) = j * h ;
339 pointsHost(cur,1) = i * h;
340 cur++;
341 }
342 }
343 Kokkos::deep_copy(points, pointsHost);
344}
345
346template<typename pointValueType, class ...pointProperties>
347void
349getEquispacedLatticeTetrahedron( Kokkos::DynRankView<pointValueType,pointProperties...> points,
350 const ordinal_type order ,
351 const ordinal_type offset ) {
352 TEUCHOS_TEST_FOR_EXCEPTION( (order <= 0) ,
353 std::invalid_argument ,
354 ">>> ERROR (Intrepid2::PointTools::getEquispacedLatticeTetrahedron): order must be positive" );
355
356 auto pointsHost = Kokkos::create_mirror_view(points);
357
358 const pointValueType h = 1.0 / order;
359 ordinal_type cur = 0;
360
361 for (ordinal_type i=offset;i<=order-offset;i++) {
362 for (ordinal_type j=offset;j<=order-i-offset;j++) {
363 for (ordinal_type k=offset;k<=order-i-j-offset;k++) {
364 pointsHost(cur,0) = k * h;
365 pointsHost(cur,1) = j * h;
366 pointsHost(cur,2) = i * h;
367 cur++;
368 }
369 }
370 }
371 Kokkos::deep_copy(points, pointsHost);
372}
373
374template<typename pointValueType, class ...pointProperties>
375void
377getEquispacedLatticePyramid( Kokkos::DynRankView<pointValueType,pointProperties...> points,
378 const ordinal_type order ,
379 const ordinal_type offset ) {
380 TEUCHOS_TEST_FOR_EXCEPTION( (order <= 0) ,
381 std::invalid_argument ,
382 ">>> ERROR (Intrepid2::PointTools::getEquispacedLatticePyramid): order must be positive" );
383
384 auto pointsHost = Kokkos::create_mirror_view(points);
385
386 const pointValueType h = 1.0 / order;
387 ordinal_type cur = 0;
388
389 for (ordinal_type i=offset;i<=order-offset;i++) { // z dimension (goes from 0 to 1)
390 pointValueType z = i * h;
391 for (ordinal_type j=offset;j<=order-i-offset;j++) { // y (goes from -(1-z) to 1-z)
392 for (ordinal_type k=offset;k<=order-i-offset;k++) { // x (goes from -(1-z) to 1-z)
393 pointsHost(cur,0) = 2. * k * h - (1.-z);
394 pointsHost(cur,1) = 2. * j * h - (1.-z);
395 pointsHost(cur,2) = z;
396 cur++;
397 }
398 }
399 }
400 Kokkos::deep_copy(points, pointsHost);
401}
402
403template<typename pointValueType, class ...pointProperties>
404void
406warpFactor( Kokkos::DynRankView<pointValueType,pointProperties...> warp,
407 const ordinal_type order,
408 const Kokkos::DynRankView<pointValueType,pointProperties...> xnodes ,
409 const Kokkos::DynRankView<pointValueType,pointProperties...> xout
410 )
411 {
412 TEUCHOS_TEST_FOR_EXCEPTION( ( warp.extent(0) != xout.extent(0) ) ,
413 std::invalid_argument ,
414 ">>> ERROR (PointTools::warpFactor): xout and warp must be same size." );
415
416 Kokkos::deep_copy(warp, pointValueType(0.0));
417
418 ordinal_type xout_dim0 = xout.extent(0);
419 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> d("d", xout_dim0 );
420
421 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> xeq_("xeq", order + 1 ,1);
422 PointTools::getEquispacedLatticeLine( xeq_ , order , 0 );
423 const auto xeq = Kokkos::subview(xeq_, Kokkos::ALL(),0);
424
425 TEUCHOS_TEST_FOR_EXCEPTION( ( xeq.extent(0) != xnodes.extent(0) ) ,
426 std::invalid_argument ,
427 ">>> ERROR (PointTools::warpFactor): xeq and xnodes must be same size." );
428
429
430 for (ordinal_type i=0;i<=order;i++) {
431
432 Kokkos::deep_copy(d, xnodes(i,0) - xeq(i));
433
434 for (ordinal_type j=1;j<order;j++) {
435 if (i != j) {
436 for (ordinal_type k=0;k<xout_dim0;k++) {
437 d(k) = d(k) * ( (xout(k)-xeq(j)) / (xeq(i)-xeq(j)) );
438 }
439 }
440 }
441
442 // deflate end roots
443 if ( i != 0 ) {
444 for (ordinal_type k=0;k<xout_dim0;k++) {
445 d(k) = -d(k) / (xeq(i) - xeq(0));
446 }
447 }
448
449 if (i != order ) {
450 for (ordinal_type k=0;k<xout_dim0;k++) {
451 d(k) = d(k) / (xeq(i) - xeq(order));
452 }
453 }
454
455 for (ordinal_type k=0;k<xout_dim0;k++) {
456 warp(k) += d(k);
457 }
458
459 }
460 }
461
462template<typename pointValueType, class ...pointProperties>
463void
465getWarpBlendLatticeTriangle( Kokkos::DynRankView<pointValueType,pointProperties...> points,
466 const ordinal_type order ,
467 const ordinal_type offset)
468 {
469 /* get Gauss-Lobatto points */
470
471 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> gaussX("gaussX", order + 1 , 1 );
472
473 PointTools::getWarpBlendLatticeLine( gaussX , order , 0 );
474 //auto gaussX = Kokkos::subdynrankview(gaussX_, Kokkos::ALL(),0);
475
476 // gaussX.resize(gaussX.extent(0));
477
478 pointValueType alpopt[] = {0.0000,0.0000,1.4152,0.1001,0.2751,0.9800,1.0999,
479 1.2832,1.3648, 1.4773, 1.4959, 1.5743, 1.5770, 1.6223, 1.6258};
480
481 pointValueType alpha;
482
483 if (order >= 1 && order < 16) {
484 alpha = alpopt[order-1];
485 }
486 else {
487 alpha = 5.0 / 3.0;
488 }
489
490 const ordinal_type p = order; /* switch to Warburton's notation */
491 ordinal_type N = (p+1)*(p+2)/2;
492
493 /* equidistributed nodes on equilateral triangle */
494 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> L1("L1", N );
495 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> L2("L2", N );
496 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> L3("L3", N );
497 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> X("X", N);
498 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> Y("Y", N);
499
500 ordinal_type sk = 0;
501 for (ordinal_type n=1;n<=p+1;n++) {
502 for (ordinal_type m=1;m<=p+2-n;m++) {
503 L1(sk) = (n-1) / (pointValueType)p;
504 L3(sk) = (m-1) / (pointValueType)p;
505 L2(sk) = 1.0 - L1(sk) - L3(sk);
506 sk++;
507 }
508 }
509
510 for (ordinal_type n=0;n<N;n++) {
511 X(n) = -L2(n) + L3(n);
512 Y(n) = (-L2(n) - L3(n) + 2*L1(n))/1.7320508075688772;
513 }
514
515 /* get blending function for each node at each edge */
516 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> blend1("blend1", N);
517 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> blend2("blend2", N);
518 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> blend3("blend3", N);
519
520 for (ordinal_type n=0;n<N;n++) {
521 blend1(n) = 4.0 * L2(n) * L3(n);
522 blend2(n) = 4.0 * L1(n) * L3(n);
523 blend3(n) = 4.0 * L1(n) * L2(n);
524 }
525
526 /* get difference of each barycentric coordinate */
527 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> L3mL2("L3mL2", N);
528 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> L1mL3("L1mL3", N);
529 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> L2mL1("L2mL1", N);
530
531 for (ordinal_type k=0;k<N;k++) {
532 L3mL2(k) = L3(k)-L2(k);
533 L1mL3(k) = L1(k)-L3(k);
534 L2mL1(k) = L2(k)-L1(k);
535 }
536
537 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> warpfactor1("warpfactor1", N);
538 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> warpfactor2("warpfactor2", N);
539 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> warpfactor3("warpfactor3", N);
540
541 warpFactor( warpfactor1, order , gaussX , L3mL2 );
542 warpFactor( warpfactor2, order , gaussX , L1mL3 );
543 warpFactor( warpfactor3, order , gaussX , L2mL1 );
544
545 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> warp1("warp1", N);
546 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> warp2("warp2", N);
547 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> warp3("warp3", N);
548
549 for (ordinal_type k=0;k<N;k++) {
550 warp1(k) = blend1(k) * warpfactor1(k) *
551 ( 1.0 + alpha * alpha * L1(k) * L1(k) );
552 warp2(k) = blend2(k) * warpfactor2(k) *
553 ( 1.0 + alpha * alpha * L2(k) * L2(k) );
554 warp3(k) = blend3(k) * warpfactor3(k) *
555 ( 1.0 + alpha * alpha * L3(k) * L3(k) );
556 }
557
558 for (ordinal_type k=0;k<N;k++) {
559 X(k) += 1.0 * warp1(k) + cos( 2.0 * M_PI / 3.0 ) * warp2(k) + cos(4*M_PI/3.0) * warp3(k);
560 Y(k) += 0.0 * warp1(k) + sin( 2.0 * M_PI / 3.0 ) * warp2(k) + sin( 4*M_PI/3.0) * warp3(k);
561 }
562
563 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> warXY("warXY", 1, N,2);
564
565 for (ordinal_type k=0;k<N;k++) {
566 warXY(0, k,0) = X(k);
567 warXY(0, k,1) = Y(k);
568 }
569
570
571 // finally, convert the warp-blend points to the correct triangle
572 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> warburtonVerts("warburtonVerts", 1,3,2);
573 warburtonVerts(0,0,0) = -1.0;
574 warburtonVerts(0,0,1) = -1.0/std::sqrt(3.0);
575 warburtonVerts(0,1,0) = 1.0;
576 warburtonVerts(0,1,1) = -1.0/std::sqrt(3.0);
577 warburtonVerts(0,2,0) = 0.0;
578 warburtonVerts(0,2,1) = 2.0/std::sqrt(3.0);
579
580 Kokkos::DynRankView<pointValueType, Kokkos::DefaultHostExecutionSpace> refPts("refPts", 1, N,2);
581
583 warXY ,
584 warburtonVerts ,
585 shards::getCellTopologyData< shards::Triangle<3> >()
586 );
587
588
589 auto pointsHost = Kokkos::create_mirror_view(points);
590 // now write from refPts into points, taking care of offset
591 ordinal_type noffcur = 0; // index into refPts
592 ordinal_type offcur = 0; // index ordinal_type points
593 for (ordinal_type i=0;i<=order;i++) {
594 for (ordinal_type j=0;j<=order-i;j++) {
595 if ( (i >= offset) && (i <= order-offset) &&
596 (j >= offset) && (j <= order-i-offset) ) {
597 pointsHost(offcur,0) = refPts(0, noffcur,0);
598 pointsHost(offcur,1) = refPts(0, noffcur,1);
599 offcur++;
600 }
601 noffcur++;
602 }
603 }
604
605 Kokkos::deep_copy(points, pointsHost);
606
607 }
608
609
610template<typename pointValueType, class ...pointProperties>
611void
613warpShiftFace3D( Kokkos::DynRankView<pointValueType,pointProperties...> dxy,
614 const ordinal_type order ,
615 const pointValueType pval ,
616 const Kokkos::DynRankView<pointValueType,pointProperties...> /* L1 */,
617 const Kokkos::DynRankView<pointValueType,pointProperties...> L2,
618 const Kokkos::DynRankView<pointValueType,pointProperties...> L3,
619 const Kokkos::DynRankView<pointValueType,pointProperties...> L4
620 )
621 {
622 evalshift(dxy,order,pval,L2,L3,L4);
623 return;
624 }
625
626template<typename pointValueType, class ...pointProperties>
627void
629evalshift( Kokkos::DynRankView<pointValueType,pointProperties...> dxy,
630 const ordinal_type order ,
631 const pointValueType pval ,
632 const Kokkos::DynRankView<pointValueType,pointProperties...> L1 ,
633 const Kokkos::DynRankView<pointValueType,pointProperties...> L2 ,
634 const Kokkos::DynRankView<pointValueType,pointProperties...> L3
635 )
636 {
637 // get Gauss-Lobatto-nodes
638 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> gaussX("gaussX",order+1,1);
639 PointTools::getWarpBlendLatticeLine( gaussX , order , 0 );
640 //gaussX.resize(order+1);
641 const ordinal_type N = L1.extent(0);
642
643 // Warburton code reverses them
644 for (ordinal_type k=0;k<=order;k++) {
645 gaussX(k,0) *= -1.0;
646 }
647
648 // blending function at each node for each edge
649 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> blend1("blend1",N);
650 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> blend2("blend2",N);
651 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> blend3("blend3",N);
652
653 for (ordinal_type i=0;i<N;i++) {
654 blend1(i) = L2(i) * L3(i);
655 blend2(i) = L1(i) * L3(i);
656 blend3(i) = L1(i) * L2(i);
657 }
658
659 // amount of warp for each node for each edge
660 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> warpfactor1("warpfactor1",N);
661 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> warpfactor2("warpfactor2",N);
662 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> warpfactor3("warpfactor3",N);
663
664 // differences of barycentric coordinates
665 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> L3mL2("L3mL2",N);
666 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> L1mL3("L1mL3",N);
667 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> L2mL1("L2mL1",N);
668
669 for (ordinal_type k=0;k<N;k++) {
670 L3mL2(k) = L3(k)-L2(k);
671 L1mL3(k) = L1(k)-L3(k);
672 L2mL1(k) = L2(k)-L1(k);
673 }
674
675 evalwarp( warpfactor1 , order , gaussX , L3mL2 );
676 evalwarp( warpfactor2 , order , gaussX , L1mL3 );
677 evalwarp( warpfactor3 , order , gaussX , L2mL1 );
678
679 for (ordinal_type k=0;k<N;k++) {
680 warpfactor1(k) *= 4.0;
681 warpfactor2(k) *= 4.0;
682 warpfactor3(k) *= 4.0;
683 }
684
685 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> warp1("warp1",N);
686 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> warp2("warp2",N);
687 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> warp3("warp3",N);
688
689 for (ordinal_type k=0;k<N;k++) {
690 warp1(k) = blend1(k) * warpfactor1(k) *
691 ( 1.0 + pval * pval * L1(k) * L1(k) );
692 warp2(k) = blend2(k) * warpfactor2(k) *
693 ( 1.0 + pval * pval * L2(k) * L2(k) );
694 warp3(k) = blend3(k) * warpfactor3(k) *
695 ( 1.0 + pval * pval * L3(k) * L3(k) );
696 }
697
698 for (ordinal_type k=0;k<N;k++) {
699 dxy(k,0) = 1.0 * warp1(k) + cos( 2.0 * M_PI / 3.0 ) * warp2(k) + cos( 4.0*M_PI/3.0 ) * warp3(k);
700 dxy(k,1) = 0.0 * warp1(k) + sin( 2.0 * M_PI / 3.0 ) * warp2(k) + sin( 4.0*M_PI/3.0 ) * warp3(k);
701 }
702 }
703
704 /* one-d edge warping function */
705template<typename pointValueType, class ...pointProperties>
706void
708evalwarp(Kokkos::DynRankView<pointValueType,pointProperties...> warp ,
709 const ordinal_type order ,
710 const Kokkos::DynRankView<pointValueType,pointProperties...> xnodes,
711 const Kokkos::DynRankView<pointValueType,pointProperties...> xout )
712 {
713 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> xeq("xeq",order+1);
714
715 ordinal_type xout_dim0 = xout.extent(0);
716 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> d("d",xout_dim0);
717
718 //Kokkos::deep_copy(d, 0.0);
719
720 for (ordinal_type i=0;i<=order;i++) {
721 xeq(i) = -1.0 + 2.0 * ( order - i ) / order;
722 }
723
724 for (ordinal_type i=0;i<=order;i++) {
725 Kokkos::deep_copy(d, xnodes(i,0) - xeq(i));
726 for (ordinal_type j=1;j<order;j++) {
727 if (i!=j) {
728 for (ordinal_type k=0;k<xout_dim0;k++) {
729 d(k) = d(k) * (xout(k)-xeq(j))/(xeq(i)-xeq(j));
730 }
731 }
732 }
733 if (i!=0) {
734 for (ordinal_type k=0;k<xout_dim0;k++) {
735 d(k) = -d(k)/(xeq(i)-xeq(0));
736 }
737 }
738 if (i!=order) {
739 for (ordinal_type k=0;k<xout_dim0;k++) {
740 d(k) = d(k)/(xeq(i)-xeq(order));
741 }
742 }
743
744 for (ordinal_type k=0;k<xout_dim0;k++) {
745 warp(k) += d(k);
746 }
747 }
748 }
749
750
751template<typename pointValueType, class ...pointProperties>
752void
754getWarpBlendLatticeTetrahedron(Kokkos::DynRankView<pointValueType,pointProperties...> points,
755 const ordinal_type order ,
756 const ordinal_type offset )
757 {
758 pointValueType alphastore[] = { 0,0,0,0.1002, 1.1332,1.5608,1.3413,1.2577,1.1603,
759 1.10153,0.6080,0.4523,0.8856,0.8717,0.9655};
760 pointValueType alpha;
761
762 if (order <= 15) {
763 alpha = alphastore[std::max(order-1,0)];
764 }
765 else {
766 alpha = 1.0;
767 }
768
769 const ordinal_type N = (order+1)*(order+2)*(order+3)/6;
770 pointValueType tol = 1.e-10;
771
772 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> shift("shift",N,3);
773 Kokkos::deep_copy(shift,0.0);
774
775 /* create 3d equidistributed nodes on Warburton tet */
776 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> equipoints("equipoints", N,3);
777 ordinal_type sk = 0;
778 for (ordinal_type n=0;n<=order;n++) {
779 for (ordinal_type m=0;m<=order-n;m++) {
780 for (ordinal_type q=0;q<=order-n-m;q++) {
781 equipoints(sk,0) = -1.0 + (q * 2.0 ) / order;
782 equipoints(sk,1) = -1.0 + (m * 2.0 ) / order;
783 equipoints(sk,2) = -1.0 + (n * 2.0 ) / order;
784 sk++;
785 }
786 }
787 }
788
789
790 /* construct barycentric coordinates for equispaced lattice */
791 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> L1("L1",N);
792 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> L2("L2",N);
793 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> L3("L3",N);
794 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> L4("L4",N);
795 for (ordinal_type i=0;i<N;i++) {
796 L1(i) = (1.0 + equipoints(i,2)) / 2.0;
797 L2(i) = (1.0 + equipoints(i,1)) / 2.0;
798 L3(i) = -(1.0 + equipoints(i,0) + equipoints(i,1) + equipoints(i,2)) / 2.0;
799 L4(i) = (1.0 + equipoints(i,0)) / 2.0;
800 }
801
802
803 /* vertices of Warburton tet */
804 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> warVerts_("warVerts",1,4,3);
805 auto warVerts = Kokkos::subview(warVerts_,0,Kokkos::ALL(),Kokkos::ALL());
806 warVerts(0,0) = -1.0;
807 warVerts(0,1) = -1.0/sqrt(3.0);
808 warVerts(0,2) = -1.0/sqrt(6.0);
809 warVerts(1,0) = 1.0;
810 warVerts(1,1) = -1.0/sqrt(3.0);
811 warVerts(1,2) = -1.0/sqrt(6.0);
812 warVerts(2,0) = 0.0;
813 warVerts(2,1) = 2.0 / sqrt(3.0);
814 warVerts(2,2) = -1.0/sqrt(6.0);
815 warVerts(3,0) = 0.0;
816 warVerts(3,1) = 0.0;
817 warVerts(3,2) = 3.0 / sqrt(6.0);
818
819
820 /* tangents to faces */
821 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> t1("t1",4,3);
822 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> t2("t2",4,3);
823 for (ordinal_type i=0;i<3;i++) {
824 t1(0,i) = warVerts(1,i) - warVerts(0,i);
825 t1(1,i) = warVerts(1,i) - warVerts(0,i);
826 t1(2,i) = warVerts(2,i) - warVerts(1,i);
827 t1(3,i) = warVerts(2,i) - warVerts(0,i);
828 t2(0,i) = warVerts(2,i) - 0.5 * ( warVerts(0,i) + warVerts(1,i) );
829 t2(1,i) = warVerts(3,i) - 0.5 * ( warVerts(0,i) + warVerts(1,i) );
830 t2(2,i) = warVerts(3,i) - 0.5 * ( warVerts(1,i) + warVerts(2,i) );
831 t2(3,i) = warVerts(3,i) - 0.5 * ( warVerts(0,i) + warVerts(2,i) );
832 }
833
834 /* normalize tangents */
835 for (ordinal_type n=0;n<4;n++) {
836 /* Compute norm of t1(n) and t2(n) */
837 pointValueType normt1n = 0.0;
838 pointValueType normt2n = 0.0;
839 for (ordinal_type i=0;i<3;i++) {
840 normt1n += (t1(n,i) * t1(n,i));
841 normt2n += (t2(n,i) * t2(n,i));
842 }
843 normt1n = sqrt(normt1n);
844 normt2n = sqrt(normt2n);
845 /* normalize each tangent now */
846 for (ordinal_type i=0;i<3;i++) {
847 t1(n,i) /= normt1n;
848 t2(n,i) /= normt2n;
849 }
850 }
851
852 /* undeformed coordinates */
853 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> XYZ("XYZ",N,3);
854 for (ordinal_type i=0;i<N;i++) {
855 for (ordinal_type j=0;j<3;j++) {
856 XYZ(i,j) = L3(i)*warVerts(0,j) + L4(i)*warVerts(1,j) + L2(i)*warVerts(2,j) + L1(i)*warVerts(3,j);
857 }
858 }
859
860 for (ordinal_type face=1;face<=4;face++) {
861 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> La, Lb, Lc, Ld;
862 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> warp("warp",N,2);
863 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> blend("blend",N);
864 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> denom("denom",N);
865 switch (face) {
866 case 1:
867 La = L1; Lb = L2; Lc = L3; Ld = L4; break;
868 case 2:
869 La = L2; Lb = L1; Lc = L3; Ld = L4; break;
870 case 3:
871 La = L3; Lb = L1; Lc = L4; Ld = L2; break;
872 case 4:
873 La = L4; Lb = L1; Lc = L3; Ld = L2; break;
874 }
875
876 /* get warp tangential to face */
877 warpShiftFace3D(warp,order,alpha,La,Lb,Lc,Ld);
878
879 for (ordinal_type k=0;k<N;k++) {
880 blend(k) = Lb(k) * Lc(k) * Ld(k);
881 }
882
883 for (ordinal_type k=0;k<N;k++) {
884 denom(k) = (Lb(k) + 0.5 * La(k)) * (Lc(k) + 0.5*La(k)) * (Ld(k) + 0.5 * La(k));
885 }
886
887 for (ordinal_type k=0;k<N;k++) {
888 if (denom(k) > tol) {
889 blend(k) *= ( 1.0 + alpha * alpha * La(k) * La(k) ) / denom(k);
890 }
891 }
892
893
894 // compute warp and blend
895 for (ordinal_type k=0;k<N;k++) {
896 for (ordinal_type j=0;j<3;j++) {
897 shift(k,j) = shift(k,j) + blend(k) * warp(k,0) * t1(face-1,j)
898 + blend(k) * warp(k,1) * t2(face-1,j);
899 }
900 }
901
902 for (ordinal_type k=0;k<N;k++) {
903 if (La(k) < tol && ( Lb(k) < tol || Lc(k) < tol || Ld(k) < tol )) {
904 for (ordinal_type j=0;j<3;j++) {
905 shift(k,j) = warp(k,0) * t1(face-1,j) + warp(k,1) * t2(face-1,j);
906 }
907 }
908 }
909
910 }
911
912 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> updatedPoints("updatedPoints",1,N,3);
913 for (ordinal_type k=0;k<N;k++) {
914 for (ordinal_type j=0;j<3;j++) {
915 updatedPoints(0,k,j) = XYZ(k,j) + shift(k,j);
916 }
917 }
918
919 //warVerts.resize( 1 , 4 , 3 );
920
921 // now we convert to Pavel's reference triangle!
922 Kokkos::DynRankView<pointValueType,Kokkos::DefaultHostExecutionSpace> refPts("refPts",1,N,3);
924 warVerts_ ,
925 shards::getCellTopologyData<shards::Tetrahedron<4> >()
926 );
927
928 auto pointsHost = Kokkos::create_mirror_view(points);
929 // now write from refPts into points, taking offset into account
930 ordinal_type noffcur = 0;
931 ordinal_type offcur = 0;
932 for (ordinal_type i=0;i<=order;i++) {
933 for (ordinal_type j=0;j<=order-i;j++) {
934 for (ordinal_type k=0;k<=order-i-j;k++) {
935 if ( (i >= offset) && (i <= order-offset) &&
936 (j >= offset) && (j <= order-i-offset) &&
937 (k >= offset) && (k <= order-i-j-offset) ) {
938 pointsHost(offcur,0) = refPts(0,noffcur,0);
939 pointsHost(offcur,1) = refPts(0,noffcur,1);
940 pointsHost(offcur,2) = refPts(0,noffcur,2);
941 offcur++;
942 }
943 noffcur++;
944 }
945 }
946 }
947
948 Kokkos::deep_copy(points, pointsHost);
949 }
950
951
952} // face Intrepid
953#endif
Kokkos::DynRankView< typename ViewType::value_type, typename DeduceLayout< ViewType >::result_layout, typename ViewType::device_type > getMatchingViewWithLabel(const ViewType &view, const std::string &label, DimArgs... dims)
Creates and returns a view that matches the provided view in Kokkos Layout.
static void mapToReferenceFrame(Kokkos::DynRankView< refPointValueType, refPointProperties... > refPoints, const Kokkos::DynRankView< physPointValueType, physPointProperties... > physPoints, const Kokkos::DynRankView< worksetCellValueType, worksetCellProperties... > worksetCell, const shards::CellTopology cellTopo)
Computes , the inverse of the reference-to-physical frame map using a default initial guess.
static void getWarpBlendLatticeLine(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0)
Returns the Gauss-Lobatto points of a given order on the reference line [-1,1]. The output array is (...
static void getEquispacedLatticeTriangle(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0)
Computes an equispaced lattice of a given order on the reference triangle. The output array is (P,...
static void evalshift(Kokkos::DynRankView< pointValueType, pointProperties... > dxy, const ordinal_type order, const pointValueType pval, const Kokkos::DynRankView< pointValueType, pointProperties... > L1, const Kokkos::DynRankView< pointValueType, pointProperties... > L2, const Kokkos::DynRankView< pointValueType, pointProperties... > L3)
Used internally to evaluate the point shift for warp-blend points on faces of tets.
static void getLatticePyramid(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0, const EPointType pointType=POINTTYPE_EQUISPACED)
Computes a lattice of points of a given order on a reference pyramid. The output array is (P,...
static void getLatticeTetrahedron(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0, const EPointType pointType=POINTTYPE_EQUISPACED)
Computes a lattice of points of a given order on a reference tetrahedron. The output array is (P,...
static void warpFactor(Kokkos::DynRankView< pointValueType, pointProperties... > warp, const ordinal_type order, const Kokkos::DynRankView< pointValueType, pointProperties... > xnodes, const Kokkos::DynRankView< pointValueType, pointProperties... > xout)
interpolates Warburton's warp function on the line
static ordinal_type getLatticeSize(const shards::CellTopology cellType, const ordinal_type order, const ordinal_type offset=0)
Computes the number of points in a lattice of a given order on a simplex (currently disabled for othe...
static void getWarpBlendLatticeTetrahedron(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0)
Returns Warburton's warp-blend points of a given order on the reference tetrahedron....
static void getLatticeTriangle(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0, const EPointType pointType=POINTTYPE_EQUISPACED)
Computes a lattice of points of a given order on a reference triangle. The output array is (P,...
static void evalwarp(Kokkos::DynRankView< pointValueType, pointProperties... > warp, const ordinal_type order, const Kokkos::DynRankView< pointValueType, pointProperties... > xnodes, const Kokkos::DynRankView< pointValueType, pointProperties... > xout)
Used internally to compute the warp on edges of a triangle in warp-blend points.
static void getGaussPoints(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order)
static void getLatticeLine(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0, const EPointType pointType=POINTTYPE_EQUISPACED)
Computes a lattice of points of a given order on a reference line. The output array is (P,...
static void getWarpBlendLatticeTriangle(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0)
Returns Warburton's warp-blend points of a given order on the reference triangle. The output array is...
static void getEquispacedLatticeTetrahedron(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0)
Computes an equispaced lattice of a given order on the reference tetrahedron. The output array is (P,...
static void getEquispacedLatticePyramid(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0)
Computes an equispaced lattice of a given order on the reference pyramid. The output array is (P,...
static void warpShiftFace3D(Kokkos::DynRankView< pointValueType, pointProperties... > dxy, const ordinal_type order, const pointValueType pval, const Kokkos::DynRankView< pointValueType, pointProperties... > L1, const Kokkos::DynRankView< pointValueType, pointProperties... > L2, const Kokkos::DynRankView< pointValueType, pointProperties... > L3, const Kokkos::DynRankView< pointValueType, pointProperties... > L4)
This is used internally to compute the tetrahedral warp-blend points one each face.
static void getLattice(Kokkos::DynRankView< pointValueType, pointProperties... > points, const shards::CellTopology cellType, const ordinal_type order, const ordinal_type offset=0, const EPointType pointType=POINTTYPE_EQUISPACED)
Computes a lattice of points of a given order on a reference simplex, quadrilateral or hexahedron (cu...
static void getEquispacedLatticeLine(Kokkos::DynRankView< pointValueType, pointProperties... > points, const ordinal_type order, const ordinal_type offset=0)
Computes an equispaced lattice of a given order on the reference line [-1,1]. The output array is (P,...
Gauss-Jacobi/Gauss-Radau-Jacobi/Gauss-Lobatto zeros and weights.