15#ifndef Intrepid2_TestUtils_h
16#define Intrepid2_TestUtils_h
18#include "Kokkos_Core.hpp"
19#include "Kokkos_DynRankView.hpp"
29#include "Teuchos_UnitTestHarness.hpp"
37#if defined(KOKKOS_ENABLE_CUDA)
39#elif defined(KOKKOS_ENABLE_HIP)
46 template <
class Scalar>
47 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType
50 using ST = Teuchos::ScalarTraits<Scalar>;
51 return ST::magnitude(Teuchos::RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber());
55 template <
class Scalar1,
class Scalar2>
56 KOKKOS_INLINE_FUNCTION
58 relErrMeetsTol(
const Scalar1 &s1,
const Scalar2 &s2,
const typename Teuchos::ScalarTraits<
typename std::common_type<Scalar1,Scalar2>::type >::magnitudeType &smallNumber,
const double &tol )
60 using Scalar =
typename std::common_type<Scalar1,Scalar2>::type;
61 const Scalar s1Abs = fabs(s1);
62 const Scalar s2Abs = fabs(s2);
63 const Scalar maxAbs = (s1Abs > s2Abs) ? s1Abs : s2Abs;
64 const Scalar relErr = fabs( s1 - s2 ) / (
smallNumber + maxAbs );
68 template <
class Scalar1,
class Scalar2>
69 KOKKOS_INLINE_FUNCTION
71 errMeetsAbsAndRelTol(
const Scalar1 &s1,
const Scalar2 &s2,
const double &relTol,
const double &absTol )
73 return fabs( s1 - s2 ) <= absTol + fabs(s1) * relTol;
76 static const double TEST_TOLERANCE_TIGHT = 1.e2 * std::numeric_limits<double>::epsilon();
79 template<
typename ScalarType,
typename DeviceType>
80 using ViewType = Kokkos::DynRankView<ScalarType,DeviceType>;
82 template<
typename ScalarType,
typename DeviceType>
83 using FixedRankViewType = Kokkos::View<ScalarType,DeviceType>;
85 template<
typename ScalarType>
86 KOKKOS_INLINE_FUNCTION
bool valuesAreSmall(
const ScalarType &a,
const ScalarType &b,
const double &epsilon)
89 return (abs(a) < epsilon) && (abs(b) < epsilon);
92 inline bool approximatelyEqual(
double a,
double b,
double epsilon)
94 const double larger_magnitude = (std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a));
95 return std::abs(a - b) <= larger_magnitude * epsilon;
98 inline bool essentiallyEqual(
double a,
double b,
double epsilon)
100 const double smaller_magnitude = (std::abs(a) > std::abs(b) ? std::abs(b) : std::abs(a));
101 return std::abs(a - b) <= smaller_magnitude * epsilon;
113 template<
typename ScalarType>
114 typename ScalarTraits<ScalarType>::scalar_type
116 if constexpr (!std::is_same<typename ScalarTraits<ScalarType>::scalar_type, ScalarType>::value) {
117 auto norm1 = std::abs(value.val());
118 for (
int i = 0; i < value.size(); ++i)
119 norm1 = std::max(norm1, std::abs(value.fastAccessDx(i)));
122 return std::abs(value);
126 KOKKOS_INLINE_FUNCTION
double fromZeroOne(
double x_zero_one)
128 return x_zero_one * 2.0 - 1.0;
132 KOKKOS_INLINE_FUNCTION
double toZeroOne(
double x_minus_one_one)
134 return (x_minus_one_one + 1.0) / 2.0;
138 KOKKOS_INLINE_FUNCTION
double fromZeroOne_dx(
double dx_zero_one)
140 return dx_zero_one / 2.0;
144 KOKKOS_INLINE_FUNCTION
double toZeroOne_dx(
double dx_minus_one_one)
146 return dx_minus_one_one * 2.0;
149 template<
class DeviceViewType>
150 typename DeviceViewType::host_mirror_type getHostCopy(
const DeviceViewType &deviceView)
152 typename DeviceViewType::host_mirror_type hostView = Kokkos::create_mirror(deviceView);
153 Kokkos::deep_copy(hostView, deviceView);
157 template<
class BasisFamily>
158 inline Teuchos::RCP< Intrepid2::Basis<DefaultTestDeviceType,double,double> > getBasisUsingFamily(shards::CellTopology cellTopo, Intrepid2::EFunctionSpace fs,
159 int polyOrder_x,
int polyOrder_y=-1,
int polyOrder_z = -1)
161 using BasisPtr =
typename BasisFamily::BasisPtr;
164 using namespace Intrepid2;
166 if (cellTopo.getBaseKey() == shards::Line<>::key)
168 basis = getLineBasis<BasisFamily>(fs,polyOrder_x);
170 else if (cellTopo.getBaseKey() == shards::Quadrilateral<>::key)
172 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
173 basis = getQuadrilateralBasis<BasisFamily>(fs,polyOrder_x,polyOrder_y);
175 else if (cellTopo.getBaseKey() == shards::Triangle<>::key)
177 basis = getTriangleBasis<BasisFamily>(fs,polyOrder_x);
179 else if (cellTopo.getBaseKey() == shards::Hexahedron<>::key)
181 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
182 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_z < 0, std::invalid_argument,
"polyOrder_z must be specified");
183 basis = getHexahedronBasis<BasisFamily>(fs,polyOrder_x,polyOrder_y,polyOrder_z);
185 else if (cellTopo.getBaseKey() == shards::Tetrahedron<>::key)
187 basis = getTetrahedronBasis<BasisFamily>(fs, polyOrder_x);
189 else if (cellTopo.getBaseKey() == shards::Wedge<>::key)
191 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
192 basis = getWedgeBasis<BasisFamily>(fs,polyOrder_x,polyOrder_y);
194 else if (cellTopo.getBaseKey() == shards::Pyramid<>::key)
196 basis = getPyramidBasis<BasisFamily>(fs,polyOrder_x);
200 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported cell topology");
205 template<
bool defineVertexFunctions>
206 inline Teuchos::RCP< Intrepid2::Basis<DefaultTestDeviceType,double,double> > getHierarchicalBasis(shards::CellTopology cellTopo, Intrepid2::EFunctionSpace fs,
207 int polyOrder_x,
int polyOrder_y=-1,
int polyOrder_z = -1)
210 using Scalar = double;
211 using namespace Intrepid2;
221 return getBasisUsingFamily<BasisFamily>(cellTopo, fs, polyOrder_x, polyOrder_y, polyOrder_z);
224 template<
typename ValueType,
typename DeviceType,
class ... DimArgs>
225 inline ViewType<ValueType,DeviceType> getView(
const std::string &label, DimArgs... dims)
227 const bool allocateFadStorage = !(std::is_standard_layout<ValueType>::value && std::is_trivial<ValueType>::value);
228 if (!allocateFadStorage)
230 return ViewType<ValueType,DeviceType>(label,dims...);
234 return ViewType<ValueType,DeviceType>(label,dims...,MAX_FAD_DERIVATIVES_FOR_TESTS+1);
239 template<
typename ValueType,
class ... DimArgs>
240 inline FixedRankViewType<
typename RankExpander<ValueType,
sizeof...(DimArgs) >::value_type,
DefaultTestDeviceType > getFixedRankView(
const std::string &label, DimArgs... dims)
242 const bool allocateFadStorage = !(std::is_standard_layout<ValueType>::value && std::is_trivial<ValueType>::value);
243 using value_type =
typename RankExpander<ValueType,
sizeof...(dims) >::value_type;
244 if (!allocateFadStorage)
246 return FixedRankViewType<value_type,DefaultTestDeviceType>(label,dims...);
250 return FixedRankViewType<value_type,DefaultTestDeviceType>(label,dims...,MAX_FAD_DERIVATIVES_FOR_TESTS+1);
260 template <
typename Po
intValueType,
typename DeviceType>
261 inline ViewType<PointValueType,DeviceType>
getInputPointsView(shards::CellTopology &cellTopo,
int numPoints_1D)
263 if (cellTopo.getBaseKey() == shards::Wedge<>::key)
265 shards::CellTopology lineTopo = shards::CellTopology(shards::getCellTopologyData<shards::Line<> >() );
266 shards::CellTopology triTopo = shards::CellTopology(shards::getCellTopologyData<shards::Triangle<> >() );
268 const ordinal_type order = numPoints_1D - 1;
271 ordinal_type numPoints = numPoints_tri * numPoints_line;
272 ordinal_type spaceDim = cellTopo.getDimension();
274 ViewType<PointValueType,DeviceType> inputPointsTri = getView<PointValueType,DeviceType>(
"input points",numPoints_tri, 2);
275 ViewType<PointValueType,DeviceType> inputPointsLine = getView<PointValueType,DeviceType>(
"input points",numPoints_line,1);
279 ViewType<PointValueType,DeviceType> inputPoints = getView<PointValueType,DeviceType>(
"input points",numPoints,spaceDim);
281 using ExecutionSpace =
typename ViewType<PointValueType,DeviceType>::execution_space;
283 Kokkos::RangePolicy < ExecutionSpace > policy(0,numPoints_tri);
284 Kokkos::parallel_for( policy,
285 KOKKOS_LAMBDA (
const ordinal_type &triPointOrdinal )
287 ordinal_type pointOrdinal = triPointOrdinal * numPoints_line;
288 for (ordinal_type linePointOrdinal=0; linePointOrdinal<numPoints_line; linePointOrdinal++)
290 inputPoints(pointOrdinal,0) = inputPointsTri( triPointOrdinal,0);
291 inputPoints(pointOrdinal,1) = inputPointsTri( triPointOrdinal,1);
292 inputPoints(pointOrdinal,2) = inputPointsLine(linePointOrdinal,0);
302 const ordinal_type order = numPoints_1D - 1;
304 ordinal_type spaceDim = cellTopo.getDimension();
306 ViewType<PointValueType,DeviceType> inputPoints = getView<PointValueType,DeviceType>(
"input points",numPoints,spaceDim);
313 template<
typename OutputValueType,
typename DeviceType>
314 inline ViewType<OutputValueType,DeviceType> getOutputView(Intrepid2::EFunctionSpace fs, Intrepid2::EOperator op,
int basisCardinality,
int numPoints,
int spaceDim)
317 case Intrepid2::FUNCTION_SPACE_HGRAD:
319 case Intrepid2::OPERATOR_VALUE:
320 return getView<OutputValueType,DeviceType>(
"H^1 value output",basisCardinality,numPoints);
321 case Intrepid2::OPERATOR_GRAD:
322 return getView<OutputValueType,DeviceType>(
"H^1 derivative output",basisCardinality,numPoints,spaceDim);
323 case Intrepid2::OPERATOR_D1:
324 case Intrepid2::OPERATOR_D2:
325 case Intrepid2::OPERATOR_D3:
326 case Intrepid2::OPERATOR_D4:
327 case Intrepid2::OPERATOR_D5:
328 case Intrepid2::OPERATOR_D6:
329 case Intrepid2::OPERATOR_D7:
330 case Intrepid2::OPERATOR_D8:
331 case Intrepid2::OPERATOR_D9:
332 case Intrepid2::OPERATOR_D10:
334 const auto dkcard = getDkCardinality(op, spaceDim);
335 return getView<OutputValueType,DeviceType>(
"H^1 derivative output",basisCardinality,numPoints,dkcard);
338 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
340 case Intrepid2::FUNCTION_SPACE_HCURL:
342 case Intrepid2::OPERATOR_VALUE:
343 return getView<OutputValueType,DeviceType>(
"H(curl) value output",basisCardinality,numPoints,spaceDim);
344 case Intrepid2::OPERATOR_CURL:
346 return getView<OutputValueType,DeviceType>(
"H(curl) derivative output",basisCardinality,numPoints);
347 else if (spaceDim == 3)
348 return getView<OutputValueType,DeviceType>(
"H(curl) derivative output",basisCardinality,numPoints,spaceDim);
351 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
353 case Intrepid2::FUNCTION_SPACE_HDIV:
355 case Intrepid2::OPERATOR_VALUE:
356 return getView<OutputValueType,DeviceType>(
"H(div) value output",basisCardinality,numPoints,spaceDim);
357 case Intrepid2::OPERATOR_DIV:
358 return getView<OutputValueType,DeviceType>(
"H(div) derivative output",basisCardinality,numPoints);
360 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
363 case Intrepid2::FUNCTION_SPACE_HVOL:
365 case Intrepid2::OPERATOR_VALUE:
366 return getView<OutputValueType,DeviceType>(
"H(vol) value output",basisCardinality,numPoints);
367 case Intrepid2::OPERATOR_D1:
368 case Intrepid2::OPERATOR_D2:
369 case Intrepid2::OPERATOR_D3:
370 case Intrepid2::OPERATOR_D4:
371 case Intrepid2::OPERATOR_D5:
372 case Intrepid2::OPERATOR_D6:
373 case Intrepid2::OPERATOR_D7:
374 case Intrepid2::OPERATOR_D8:
375 case Intrepid2::OPERATOR_D9:
376 case Intrepid2::OPERATOR_D10:
379 return getView<OutputValueType,DeviceType>(
"H(vol) derivative output",basisCardinality,numPoints,dkcard);
382 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
385 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
391 inline std::vector< std::vector<int> > getBasisTestCasesUpToDegree(
int spaceDim,
int minDegree,
int polyOrder_x,
int polyOrder_y=-1,
int polyOrder_z=-1)
393 std::vector<int> degrees(spaceDim);
394 degrees[0] = polyOrder_x;
395 if (spaceDim > 1) degrees[1] = polyOrder_y;
396 if (spaceDim > 2) degrees[2] = polyOrder_z;
398 int numCases = degrees[0];
399 for (
unsigned d=1; d<degrees.size(); d++)
401 INTREPID2_TEST_FOR_EXCEPTION(degrees[d] < minDegree, std::invalid_argument,
"Unsupported degree/minDegree combination");
402 numCases = numCases * (degrees[d] + 1 - minDegree);
404 std::vector< std::vector<int> > subBasisDegreeTestCases(numCases);
405 for (
int caseOrdinal=0; caseOrdinal<numCases; caseOrdinal++)
407 std::vector<int> subBasisDegrees(degrees.size());
408 int caseRemainder = caseOrdinal;
409 for (
int d=degrees.size()-1; d>=0; d--)
411 int subBasisDegree = caseRemainder % (degrees[d] + 1 - minDegree);
412 caseRemainder = caseRemainder / (degrees[d] + 1 - minDegree);
413 subBasisDegrees[d] = subBasisDegree + minDegree;
415 subBasisDegreeTestCases[caseOrdinal] = subBasisDegrees;
417 return subBasisDegreeTestCases;
421 template<
class Functor,
class Scalar,
int rank>
422 typename ViewType<Scalar,DefaultTestDeviceType>::host_mirror_type
copyFunctorToHostView(
const Functor &deviceFunctor)
424 INTREPID2_TEST_FOR_EXCEPTION(rank !=
getFunctorRank(deviceFunctor), std::invalid_argument,
"functor rank must match the template argument");
427 ViewType<Scalar,DeviceType> view;
428 const std::string label =
"functor copy";
429 const auto &f = deviceFunctor;
433 view = getView<Scalar,DeviceType>(label);
436 view = getView<Scalar,DeviceType>(label, f.extent_int(0));
439 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1));
442 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2));
445 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2), f.extent_int(3));
448 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2), f.extent_int(3), f.extent_int(4));
451 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2), f.extent_int(3), f.extent_int(4), f.extent_int(5));
454 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2), f.extent_int(3), f.extent_int(4), f.extent_int(5), f.extent_int(6));
457 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported functor rank");
460 int entryCount = view.size();
462 using ExecutionSpace =
typename ViewType<Scalar,DeviceType>::execution_space;
467 Kokkos::RangePolicy < ExecutionSpace > policy(0,entryCount);
468 Kokkos::parallel_for( policy,
469 KOKKOS_LAMBDA (
const int &enumerationIndex )
471 ViewIteratorScalar vi(view);
472 FunctorIteratorScalar fi(f);
474 vi.setEnumerationIndex(enumerationIndex);
475 fi.setEnumerationIndex(enumerationIndex);
481 auto hostView = Kokkos::create_mirror_view(view);
482 Kokkos::deep_copy(hostView, view);
486 template<
class FunctorType,
typename Scalar,
int rank>
487 void printFunctor(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
489 auto functorHostCopy = copyFunctorToHostView<FunctorType, Scalar, rank>(functor);
491 std::string name = (functorName ==
"") ?
"Functor" : functorName;
493 out <<
"\n******** " << name <<
" (rank " << rank <<
") ********\n";
494 out <<
"dimensions: (";
495 for (
int r=0; r<rank; r++)
497 out << functor.extent_int(r);
498 if (r<rank-1) out <<
",";
502 ViewIterator<
decltype(functorHostCopy),Scalar> vi(functorHostCopy);
504 bool moreEntries =
true;
507 Scalar value = vi.get();
509 auto location = vi.getLocation();
510 out << functorName <<
"(";
511 for (ordinal_type i=0; i<rank; i++)
519 out <<
") " << value << std::endl;
521 moreEntries = (vi.increment() != -1);
526 template<
class FunctorType>
527 void printFunctor1(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
529 using Scalar =
typename std::remove_reference<
decltype(functor(0))>::type;
530 printFunctor<FunctorType, Scalar, 1>(functor, out, functorName);
533 template<
class FunctorType>
534 void printFunctor2(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
536 using Scalar =
typename std::remove_const<
typename std::remove_reference<
decltype(functor(0,0))>::type>::type;
537 printFunctor<FunctorType, Scalar, 2>(functor, out, functorName);
540 template<
class FunctorType>
541 void printFunctor3(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
543 using Scalar =
typename std::remove_const<
typename std::remove_reference<
decltype(functor(0,0,0))>::type>::type;
544 printFunctor<FunctorType, Scalar, 3>(functor, out, functorName);
547 template<
class FunctorType>
548 void printFunctor4(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
550 using Scalar =
typename std::remove_const<
typename std::remove_reference<
decltype(functor(0,0,0,0))>::type>::type;
551 printFunctor<FunctorType, Scalar, 4>(functor, out, functorName);
554 template<
class FunctorType>
555 void printFunctor5(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
557 using Scalar =
typename std::remove_const<
typename std::remove_reference<
decltype(functor(0,0,0,0,0))>::type>::type;
558 printFunctor<FunctorType, Scalar, 5>(functor, out, functorName);
561 template<
class FunctorType>
562 void printFunctor6(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
564 using Scalar =
typename std::remove_const<
typename std::remove_reference<
decltype(functor(0,0,0,0,0,0))>::type>::type;
565 printFunctor<FunctorType, Scalar, 6>(functor, out, functorName);
568 template<
class FunctorType>
569 void printFunctor7(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
571 using Scalar =
typename std::remove_const<
typename std::remove_reference<
decltype(functor(0,0,0,0,0,0,0))>::type>::type;
572 printFunctor<FunctorType, Scalar, 7>(functor, out, functorName);
576 void printView(
const View &view, std::ostream &out,
const std::string &viewName =
"")
578 using Scalar =
typename View::value_type;
579 using HostView =
typename View::host_mirror_type;
582 auto hostView = getHostCopy(view);
584 HostViewIteratorScalar vi(hostView);
586 bool moreEntries = (vi.nextIncrementRank() != -1);
589 Scalar value = vi.get();
591 auto location = vi.getLocation();
592 out << viewName <<
"(";
601 out <<
") " << value << std::endl;
603 moreEntries = (vi.increment() != -1);
607 template <
class FunctorType1,
class FunctorType2,
int rank,
typename Scalar=
typename FunctorType1::value_type,
class ExecutionSpace =
typename FunctorType1::execution_space>
609 testFloatingEquality(
const FunctorType1 &functor1,
const FunctorType2 &functor2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
610 std::string functor1Name =
"Functor 1", std::string functor2Name =
"Functor 2")
612 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"testFloatingEquality() called on FunctorType1 or FunctorType2 that does not support the specified rank.\n");
616 template <
class FunctorType1,
class FunctorType2,
int rank,
typename Scalar=
typename FunctorType1::value_type,
class ExecutionSpace =
typename FunctorType1::execution_space>
618 testFloatingEquality(
const FunctorType1 &functor1,
const FunctorType2 &functor2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
619 std::string functor1Name =
"Functor 1", std::string functor2Name =
"Functor 2")
628 TEUCHOS_TEST_FOR_EXCEPTION(
getFunctorRank(functor1) != rank, std::invalid_argument,
"functor1 and functor2 must agree in rank");
629 TEUCHOS_TEST_FOR_EXCEPTION(
getFunctorRank(functor2) != rank, std::invalid_argument,
"functor1 and functor2 must agree in rank");
634 TEUCHOS_TEST_FOR_EXCEPTION(functor1.extent_int(i) != functor2.extent_int(i), std::invalid_argument,
635 "functor1 and functor2 must agree in size in each dimension; functor1 has extent "
636 + std::to_string(functor1.extent_int(i)) +
" in dimension " + std::to_string(i)
637 +
"; functor2 has extent " + std::to_string(functor2.extent_int(i)) );
638 entryCount *= functor1.extent_int(i);
640 if (entryCount == 0)
return;
642 ViewType<bool,ExecutionSpace> valuesMatch = getView<bool,ExecutionSpace>(
"valuesMatch", entryCount);
644 Kokkos::RangePolicy < ExecutionSpace > policy(0,entryCount);
645 Kokkos::parallel_for( policy,
646 KOKKOS_LAMBDA (
const int &enumerationIndex )
648 Functor1IteratorScalar vi1(functor1);
649 Functor2IteratorScalar vi2(functor2);
651 vi1.setEnumerationIndex(enumerationIndex);
652 vi2.setEnumerationIndex(enumerationIndex);
654 const Scalar & value1 = vi1.get();
655 const Scalar & value2 = vi2.get();
657 bool errMeetsTol = errMeetsAbsAndRelTol(value1, value2, relTol, absTol);
658 valuesMatch(enumerationIndex) = errMeetsTol;
662 int failureCount = 0;
663 Kokkos::RangePolicy<ExecutionSpace > reducePolicy(0, entryCount);
664 Kokkos::parallel_reduce( reducePolicy,
665 KOKKOS_LAMBDA(
const int &enumerationIndex,
int &reducedValue )
667 reducedValue += valuesMatch(enumerationIndex) ? 0 : 1;
670 const bool allValuesMatch = (failureCount == 0);
671 success = success && allValuesMatch;
676 auto functor1CopyHost = copyFunctorToHostView<FunctorType1,Scalar,rank>(functor1);
677 auto functor2CopyHost = copyFunctorToHostView<FunctorType2,Scalar,rank>(functor2);
679 auto valuesMatchHost = getHostCopy(valuesMatch);
681 FunctorIterator<
decltype(functor1CopyHost),Scalar,rank> vi1(functor1CopyHost);
682 FunctorIterator<
decltype(functor2CopyHost),Scalar,rank> vi2(functor2CopyHost);
685 bool moreEntries =
true;
688 bool errMeetsTol = viMatch.get();
692 const Scalar value1 = vi1.get();
693 const Scalar value2 = vi2.get();
696 auto location = vi1.getLocation();
697 out <<
"At location (";
706 out <<
") " << functor1Name <<
" value != " << functor2Name <<
" value (";
707 out << value1 <<
" != " << value2 <<
"); diff is " << std::abs(value1-value2) << std::endl;
710 moreEntries = (vi1.increment() != -1);
711 moreEntries = moreEntries && (vi2.increment() != -1);
712 moreEntries = moreEntries && (viMatch.increment() != -1);
717 template <
class ViewType,
class FunctorType>
718 void testFloatingEquality1(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
719 std::string view1Name =
"View", std::string view2Name =
"Functor")
721 testFloatingEquality<ViewType, FunctorType, 1>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
724 template <
class ViewType,
class FunctorType>
725 void testFloatingEquality2(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
726 std::string view1Name =
"View", std::string view2Name =
"Functor")
728 testFloatingEquality<ViewType, FunctorType, 2>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
731 template <
class ViewType,
class FunctorType>
732 void testFloatingEquality3(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
733 std::string view1Name =
"View", std::string view2Name =
"Functor")
735 testFloatingEquality<ViewType, FunctorType, 3>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
738 template <
class ViewType,
class FunctorType>
739 void testFloatingEquality4(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
740 std::string view1Name =
"View", std::string view2Name =
"Functor")
742 testFloatingEquality<ViewType, FunctorType, 4>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
745 template <
class ViewType,
class FunctorType>
746 void testFloatingEquality5(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
747 std::string view1Name =
"View", std::string view2Name =
"Functor")
749 testFloatingEquality<ViewType, FunctorType, 5>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
752 template <
class ViewType,
class FunctorType>
753 void testFloatingEquality6(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
754 std::string view1Name =
"View", std::string view2Name =
"Functor")
756 testFloatingEquality<ViewType, FunctorType, 6>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
759 template <
class ViewType,
class FunctorType>
760 void testFloatingEquality7(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
761 std::string view1Name =
"View", std::string view2Name =
"Functor")
763 testFloatingEquality<ViewType, FunctorType, 7>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
766 template <
class ViewType1,
class ViewType2>
767 void testViewFloatingEquality(
const ViewType1 &view1,
const ViewType2 &view2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
768 std::string view1Name =
"View 1", std::string view2Name =
"View 2")
771 TEUCHOS_TEST_FOR_EXCEPTION(view1.rank() != view2.rank(), std::invalid_argument,
"views must agree in rank");
772 for (
unsigned i=0; i<view1.rank(); i++)
774 TEUCHOS_TEST_FOR_EXCEPTION(view1.extent_int(i) != view2.extent_int(i), std::invalid_argument,
"views must agree in size in each dimension");
777 if (view1.size() == 0)
return;
779 const int rank = view1.rank();
782 case 0: testFloatingEquality<ViewType1, ViewType2, 0>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
783 case 1: testFloatingEquality<ViewType1, ViewType2, 1>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
784 case 2: testFloatingEquality<ViewType1, ViewType2, 2>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
785 case 3: testFloatingEquality<ViewType1, ViewType2, 3>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
786 case 4: testFloatingEquality<ViewType1, ViewType2, 4>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
787 case 5: testFloatingEquality<ViewType1, ViewType2, 5>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
788 case 6: testFloatingEquality<ViewType1, ViewType2, 6>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
789 case 7: testFloatingEquality<ViewType1, ViewType2, 7>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
790 default: INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported rank");
796#ifdef HAVE_INTREPID2_SACADO
797using Sacado_Fad_DFadType = Sacado::Fad::DFad<double>;
798#define INTREPID2_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
800TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
802TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, Sacado_Fad_DFadType ) \
804#define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
806TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, double, double ) \
808TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, Sacado_Fad_DFadType, Sacado_Fad_DFadType ) \
811#define INTREPID2_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
813TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
815#define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
817TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, double, double ) \
Header file for the abstract base class Intrepid2::Basis.
Teuchos::RCP< Basis< DeviceType, OutputType, PointType > > BasisPtr
Basis Pointer.
KOKKOS_INLINE_FUNCTION ordinal_type getDkCardinality(const EOperator operatorType, const ordinal_type spaceDim)
Returns cardinality of Dk, i.e., the number of all derivatives of order k.
Stateless class representing a family of basis functions, templated on H(vol) and H(grad) on the line...
Defines the Intrepid2::FunctorIterator class, as well as the Intrepid2::functor_returns_ref SFINAE he...
Stateless classes that act as factories for two families of hierarchical bases. HierarchicalBasisFami...
Header file to include all Sacado headers that are required if using Intrepid2 with Sacado types.
ViewType< PointValueType, DeviceType > getInputPointsView(shards::CellTopology &cellTopo, int numPoints_1D)
Returns a DynRankView containing regularly-spaced points on the specified cell topology.
ScalarTraits< ScalarType >::scalar_type computeMaxNorm(const ScalarType &value)
Compute the norm 1 of a scalar value or Sacado Fad type.
typename Kokkos::DefaultExecutionSpace::device_type DefaultTestDeviceType
Default Kokkos::Device to use for tests; depends on platform.
ViewType< Scalar, DefaultTestDeviceType >::host_mirror_type copyFunctorToHostView(const Functor &deviceFunctor)
Copy the values for the specified functor.
constexpr int MAX_FAD_DERIVATIVES_FOR_TESTS
Maximum number of derivatives to track for Fad types in tests.
const Teuchos::ScalarTraits< Scalar >::magnitudeType smallNumber()
Use Teuchos small number determination on host; pass this to Intrepid2::relErr() on device.
KOKKOS_INLINE_FUNCTION bool relErrMeetsTol(const Scalar1 &s1, const Scalar2 &s2, const typename Teuchos::ScalarTraits< typename std::common_type< Scalar1, Scalar2 >::type >::magnitudeType &smallNumber, const double &tol)
Adapted from Teuchos::relErr(); for use in code that may be executed on device.
Header function for Intrepid2::Util class and other utility functions.
enable_if_t< has_rank_method< Functor >::value, unsigned > KOKKOS_INLINE_FUNCTION getFunctorRank(const Functor &functor)
A family of basis functions, constructed from H(vol) and H(grad) bases on the line.
essentially, a read-only variant of ViewIterator, for a general functor (extent_int() and rank() supp...
Basis defining integrated Legendre basis on the line, a polynomial subspace of H(grad) on the line.
Basis defining Legendre basis on the line, a polynomial subspace of L^2 (a.k.a. H(vol)) on the line.
A helper class that allows iteration over some part of a Kokkos View, while allowing the calling code...
SFINAE helper to detect whether a type supports a rank-integral-argument operator().
Helper to get Scalar[*+] where the number of *'s matches the given rank.