49 #ifndef Intrepid2_TestUtils_h
50 #define Intrepid2_TestUtils_h
52 #include "Kokkos_Core.hpp"
53 #include "Kokkos_DynRankView.hpp"
63 #include "Teuchos_UnitTestHarness.hpp"
68 constexpr
int MAX_FAD_DERIVATIVES_FOR_TESTS = 3;
71 #if defined(KOKKOS_ENABLE_CUDA)
72 using DefaultTestDeviceType = Kokkos::Device<Kokkos::Cuda,Kokkos::CudaSpace>;
73 #elif defined(KOKKOS_ENABLE_HIP)
74 using DefaultTestDeviceType = Kokkos::Device<Kokkos::HIP,Kokkos::HIPSpace>;
76 using DefaultTestDeviceType =
typename Kokkos::DefaultExecutionSpace::device_type;
80 template <
class Scalar>
81 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType
84 using ST = Teuchos::ScalarTraits<Scalar>;
85 return ST::magnitude(Teuchos::RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber());
89 template <
class Scalar1,
class Scalar2>
90 KOKKOS_INLINE_FUNCTION
92 relErrMeetsTol(
const Scalar1 &s1,
const Scalar2 &s2,
const typename Teuchos::ScalarTraits<
typename std::common_type<Scalar1,Scalar2>::type >::magnitudeType &smallNumber,
const double &tol )
94 using Scalar =
typename std::common_type<Scalar1,Scalar2>::type;
95 const Scalar s1Abs = fabs(s1);
96 const Scalar s2Abs = fabs(s2);
97 const Scalar maxAbs = (s1Abs > s2Abs) ? s1Abs : s2Abs;
98 const Scalar relErr = fabs( s1 - s2 ) / ( smallNumber + maxAbs );
102 template <
class Scalar1,
class Scalar2>
103 KOKKOS_INLINE_FUNCTION
105 errMeetsAbsAndRelTol(
const Scalar1 &s1,
const Scalar2 &s2,
const double &relTol,
const double &absTol )
107 return fabs( s1 - s2 ) <= absTol + fabs(s1) * relTol;
110 static const double TEST_TOLERANCE_TIGHT = 1.e2 * std::numeric_limits<double>::epsilon();
113 template<
typename ScalarType,
typename DeviceType>
114 using ViewType = Kokkos::DynRankView<ScalarType,DeviceType>;
116 template<
typename ScalarType,
typename DeviceType>
117 using FixedRankViewType = Kokkos::View<ScalarType,DeviceType>;
119 template<
typename ScalarType>
120 KOKKOS_INLINE_FUNCTION
bool valuesAreSmall(
const ScalarType &a,
const ScalarType &b,
const double &epsilon)
123 return (abs(a) < epsilon) && (abs(b) < epsilon);
126 inline bool approximatelyEqual(
double a,
double b,
double epsilon)
128 const double larger_magnitude = (std::abs(a) < std::abs(b) ? std::abs(b) : std::abs(a));
129 return std::abs(a - b) <= larger_magnitude * epsilon;
132 inline bool essentiallyEqual(
double a,
double b,
double epsilon)
134 const double smaller_magnitude = (std::abs(a) > std::abs(b) ? std::abs(b) : std::abs(a));
135 return std::abs(a - b) <= smaller_magnitude * epsilon;
139 KOKKOS_INLINE_FUNCTION
double fromZeroOne(
double x_zero_one)
141 return x_zero_one * 2.0 - 1.0;
145 KOKKOS_INLINE_FUNCTION
double toZeroOne(
double x_minus_one_one)
147 return (x_minus_one_one + 1.0) / 2.0;
151 KOKKOS_INLINE_FUNCTION
double fromZeroOne_dx(
double dx_zero_one)
153 return dx_zero_one / 2.0;
157 KOKKOS_INLINE_FUNCTION
double toZeroOne_dx(
double dx_minus_one_one)
159 return dx_minus_one_one * 2.0;
162 template<
class DeviceViewType>
163 typename DeviceViewType::HostMirror getHostCopy(
const DeviceViewType &deviceView)
165 typename DeviceViewType::HostMirror hostView = Kokkos::create_mirror(deviceView);
166 Kokkos::deep_copy(hostView, deviceView);
170 template<
class BasisFamily>
171 inline Teuchos::RCP< Intrepid2::Basis<DefaultTestDeviceType,double,double> > getBasisUsingFamily(shards::CellTopology cellTopo, Intrepid2::EFunctionSpace fs,
172 int polyOrder_x,
int polyOrder_y=-1,
int polyOrder_z = -1)
174 using BasisPtr =
typename BasisFamily::BasisPtr;
177 using namespace Intrepid2;
179 if (cellTopo.getBaseKey() == shards::Line<>::key)
181 basis = getLineBasis<BasisFamily>(fs,polyOrder_x);
183 else if (cellTopo.getBaseKey() == shards::Quadrilateral<>::key)
185 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
186 basis = getQuadrilateralBasis<BasisFamily>(fs,polyOrder_x,polyOrder_y);
188 else if (cellTopo.getBaseKey() == shards::Triangle<>::key)
190 basis = getTriangleBasis<BasisFamily>(fs,polyOrder_x);
192 else if (cellTopo.getBaseKey() == shards::Hexahedron<>::key)
194 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
195 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_z < 0, std::invalid_argument,
"polyOrder_z must be specified");
196 basis = getHexahedronBasis<BasisFamily>(fs,polyOrder_x,polyOrder_y,polyOrder_z);
198 else if (cellTopo.getBaseKey() == shards::Tetrahedron<>::key)
200 basis = getTetrahedronBasis<BasisFamily>(fs, polyOrder_x);
202 else if (cellTopo.getBaseKey() == shards::Wedge<>::key)
204 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
205 basis = getWedgeBasis<BasisFamily>(fs,polyOrder_x,polyOrder_y);
207 else if (cellTopo.getBaseKey() == shards::Pyramid<>::key)
209 basis = getPyramidBasis<BasisFamily>(fs,polyOrder_x);
213 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported cell topology");
218 template<
bool defineVertexFunctions>
219 inline Teuchos::RCP< Intrepid2::Basis<DefaultTestDeviceType,double,double> > getHierarchicalBasis(shards::CellTopology cellTopo, Intrepid2::EFunctionSpace fs,
220 int polyOrder_x,
int polyOrder_y=-1,
int polyOrder_z = -1)
222 using DeviceType = DefaultTestDeviceType;
223 using Scalar = double;
224 using namespace Intrepid2;
234 return getBasisUsingFamily<BasisFamily>(cellTopo, fs, polyOrder_x, polyOrder_y, polyOrder_z);
237 template<
typename ValueType,
typename DeviceType,
class ... DimArgs>
238 inline ViewType<ValueType,DeviceType> getView(
const std::string &label, DimArgs... dims)
240 const bool allocateFadStorage = !std::is_pod<ValueType>::value;
241 if (!allocateFadStorage)
243 return ViewType<ValueType,DeviceType>(label,dims...);
247 return ViewType<ValueType,DeviceType>(label,dims...,MAX_FAD_DERIVATIVES_FOR_TESTS+1);
252 template<
typename ValueType,
class ... DimArgs>
253 inline FixedRankViewType<
typename RankExpander<ValueType,
sizeof...(DimArgs) >::value_type, DefaultTestDeviceType > getFixedRankView(
const std::string &label, DimArgs... dims)
255 const bool allocateFadStorage = !std::is_pod<ValueType>::value;
256 using value_type =
typename RankExpander<ValueType,
sizeof...(dims) >::value_type;
257 if (!allocateFadStorage)
259 return FixedRankViewType<value_type,DefaultTestDeviceType>(label,dims...);
263 return FixedRankViewType<value_type,DefaultTestDeviceType>(label,dims...,MAX_FAD_DERIVATIVES_FOR_TESTS+1);
273 template <
typename Po
intValueType,
typename DeviceType>
274 inline ViewType<PointValueType,DeviceType> getInputPointsView(shards::CellTopology &cellTopo,
int numPoints_1D)
276 if (cellTopo.getBaseKey() == shards::Wedge<>::key)
278 shards::CellTopology lineTopo = shards::CellTopology(shards::getCellTopologyData<shards::Line<> >() );
279 shards::CellTopology triTopo = shards::CellTopology(shards::getCellTopologyData<shards::Triangle<> >() );
281 const ordinal_type order = numPoints_1D - 1;
284 ordinal_type numPoints = numPoints_tri * numPoints_line;
285 ordinal_type spaceDim = cellTopo.getDimension();
287 ViewType<PointValueType,DeviceType> inputPointsTri = getView<PointValueType,DeviceType>(
"input points",numPoints_tri, 2);
288 ViewType<PointValueType,DeviceType> inputPointsLine = getView<PointValueType,DeviceType>(
"input points",numPoints_line,1);
292 ViewType<PointValueType,DeviceType> inputPoints = getView<PointValueType,DeviceType>(
"input points",numPoints,spaceDim);
294 using ExecutionSpace =
typename ViewType<PointValueType,DeviceType>::execution_space;
296 Kokkos::RangePolicy < ExecutionSpace > policy(0,numPoints_tri);
297 Kokkos::parallel_for( policy,
298 KOKKOS_LAMBDA (
const ordinal_type &triPointOrdinal )
300 ordinal_type pointOrdinal = triPointOrdinal * numPoints_line;
301 for (ordinal_type linePointOrdinal=0; linePointOrdinal<numPoints_line; linePointOrdinal++)
303 inputPoints(pointOrdinal,0) = inputPointsTri( triPointOrdinal,0);
304 inputPoints(pointOrdinal,1) = inputPointsTri( triPointOrdinal,1);
305 inputPoints(pointOrdinal,2) = inputPointsLine(linePointOrdinal,0);
315 const ordinal_type order = numPoints_1D - 1;
317 ordinal_type spaceDim = cellTopo.getDimension();
319 ViewType<PointValueType,DeviceType> inputPoints = getView<PointValueType,DeviceType>(
"input points",numPoints,spaceDim);
326 template<
typename OutputValueType,
typename DeviceType>
327 inline ViewType<OutputValueType,DeviceType> getOutputView(Intrepid2::EFunctionSpace fs, Intrepid2::EOperator op,
int basisCardinality,
int numPoints,
int spaceDim)
330 case Intrepid2::FUNCTION_SPACE_HGRAD:
332 case Intrepid2::OPERATOR_VALUE:
333 return getView<OutputValueType,DeviceType>(
"H^1 value output",basisCardinality,numPoints);
334 case Intrepid2::OPERATOR_GRAD:
335 return getView<OutputValueType,DeviceType>(
"H^1 derivative output",basisCardinality,numPoints,spaceDim);
336 case Intrepid2::OPERATOR_D1:
337 case Intrepid2::OPERATOR_D2:
338 case Intrepid2::OPERATOR_D3:
339 case Intrepid2::OPERATOR_D4:
340 case Intrepid2::OPERATOR_D5:
341 case Intrepid2::OPERATOR_D6:
342 case Intrepid2::OPERATOR_D7:
343 case Intrepid2::OPERATOR_D8:
344 case Intrepid2::OPERATOR_D9:
345 case Intrepid2::OPERATOR_D10:
347 const auto dkcard = getDkCardinality(op, spaceDim);
348 return getView<OutputValueType,DeviceType>(
"H^1 derivative output",basisCardinality,numPoints,dkcard);
351 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
353 case Intrepid2::FUNCTION_SPACE_HCURL:
355 case Intrepid2::OPERATOR_VALUE:
356 return getView<OutputValueType,DeviceType>(
"H(curl) value output",basisCardinality,numPoints,spaceDim);
357 case Intrepid2::OPERATOR_CURL:
359 return getView<OutputValueType,DeviceType>(
"H(curl) derivative output",basisCardinality,numPoints);
360 else if (spaceDim == 3)
361 return getView<OutputValueType,DeviceType>(
"H(curl) derivative output",basisCardinality,numPoints,spaceDim);
363 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
365 case Intrepid2::FUNCTION_SPACE_HDIV:
367 case Intrepid2::OPERATOR_VALUE:
368 return getView<OutputValueType,DeviceType>(
"H(div) value output",basisCardinality,numPoints,spaceDim);
369 case Intrepid2::OPERATOR_DIV:
370 return getView<OutputValueType,DeviceType>(
"H(div) derivative output",basisCardinality,numPoints);
372 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
375 case Intrepid2::FUNCTION_SPACE_HVOL:
377 case Intrepid2::OPERATOR_VALUE:
378 return getView<OutputValueType,DeviceType>(
"H(vol) value output",basisCardinality,numPoints);
379 case Intrepid2::OPERATOR_D1:
380 case Intrepid2::OPERATOR_D2:
381 case Intrepid2::OPERATOR_D3:
382 case Intrepid2::OPERATOR_D4:
383 case Intrepid2::OPERATOR_D5:
384 case Intrepid2::OPERATOR_D6:
385 case Intrepid2::OPERATOR_D7:
386 case Intrepid2::OPERATOR_D8:
387 case Intrepid2::OPERATOR_D9:
388 case Intrepid2::OPERATOR_D10:
390 const auto dkcard = getDkCardinality(op, spaceDim);
391 return getView<OutputValueType,DeviceType>(
"H(vol) derivative output",basisCardinality,numPoints,dkcard);
394 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
397 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
403 inline std::vector< std::vector<int> > getBasisTestCasesUpToDegree(
int spaceDim,
int minDegree,
int polyOrder_x,
int polyOrder_y=-1,
int polyOrder_z=-1)
405 std::vector<int> degrees(spaceDim);
406 degrees[0] = polyOrder_x;
407 if (spaceDim > 1) degrees[1] = polyOrder_y;
408 if (spaceDim > 2) degrees[2] = polyOrder_z;
410 int numCases = degrees[0];
411 for (
unsigned d=1; d<degrees.size(); d++)
413 INTREPID2_TEST_FOR_EXCEPTION(degrees[d] < minDegree, std::invalid_argument,
"Unsupported degree/minDegree combination");
414 numCases = numCases * (degrees[d] + 1 - minDegree);
416 std::vector< std::vector<int> > subBasisDegreeTestCases(numCases);
417 for (
int caseOrdinal=0; caseOrdinal<numCases; caseOrdinal++)
419 std::vector<int> subBasisDegrees(degrees.size());
420 int caseRemainder = caseOrdinal;
421 for (
int d=degrees.size()-1; d>=0; d--)
423 int subBasisDegree = caseRemainder % (degrees[d] + 1 - minDegree);
424 caseRemainder = caseRemainder / (degrees[d] + 1 - minDegree);
425 subBasisDegrees[d] = subBasisDegree + minDegree;
427 subBasisDegreeTestCases[caseOrdinal] = subBasisDegrees;
429 return subBasisDegreeTestCases;
433 template<
class Functor,
class Scalar,
int rank>
434 typename ViewType<Scalar,DefaultTestDeviceType>::HostMirror copyFunctorToHostView(
const Functor &deviceFunctor)
436 INTREPID2_TEST_FOR_EXCEPTION(rank != getFunctorRank(deviceFunctor), std::invalid_argument,
"functor rank must match the template argument");
438 using DeviceType = DefaultTestDeviceType;
439 ViewType<Scalar,DeviceType> view;
440 const std::string label =
"functor copy";
441 const auto &f = deviceFunctor;
445 view = getView<Scalar,DeviceType>(label);
448 view = getView<Scalar,DeviceType>(label, f.extent_int(0));
451 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1));
454 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2));
457 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2), f.extent_int(3));
460 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));
463 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));
466 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));
469 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported functor rank");
472 int entryCount = view.size();
474 using ExecutionSpace =
typename ViewType<Scalar,DeviceType>::execution_space;
479 Kokkos::RangePolicy < ExecutionSpace > policy(0,entryCount);
480 Kokkos::parallel_for( policy,
481 KOKKOS_LAMBDA (
const int &enumerationIndex )
483 ViewIteratorScalar vi(view);
484 FunctorIteratorScalar fi(f);
486 vi.setEnumerationIndex(enumerationIndex);
487 fi.setEnumerationIndex(enumerationIndex);
493 auto hostView = Kokkos::create_mirror_view(view);
494 Kokkos::deep_copy(hostView, view);
498 template<
class FunctorType,
typename Scalar,
int rank>
499 void printFunctor(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
501 auto functorHostCopy = copyFunctorToHostView<FunctorType, Scalar, rank>(functor);
503 std::string name = (functorName ==
"") ?
"Functor" : functorName;
505 out <<
"\n******** " << name <<
" (rank " << rank <<
") ********\n";
506 out <<
"dimensions: (";
507 for (
int r=0; r<rank; r++)
509 out << functor.extent_int(r);
510 if (r<rank-1) out <<
",";
516 bool moreEntries =
true;
519 Scalar value = vi.
get();
521 auto location = vi.getLocation();
522 out << functorName <<
"(";
523 for (ordinal_type i=0; i<rank; i++)
531 out <<
") " << value << std::endl;
533 moreEntries = (vi.increment() != -1);
538 template<
class FunctorType>
539 void printFunctor1(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
541 using Scalar =
typename std::remove_reference<decltype(functor(0))>::type;
542 printFunctor<FunctorType, Scalar, 1>(functor, out, functorName);
545 template<
class FunctorType>
546 void printFunctor2(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
548 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0))>::type>::type;
549 printFunctor<FunctorType, Scalar, 2>(functor, out, functorName);
552 template<
class FunctorType>
553 void printFunctor3(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
555 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0,0))>::type>::type;
556 printFunctor<FunctorType, Scalar, 3>(functor, out, functorName);
559 template<
class FunctorType>
560 void printFunctor4(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
562 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0,0,0))>::type>::type;
563 printFunctor<FunctorType, Scalar, 4>(functor, out, functorName);
566 template<
class FunctorType>
567 void printFunctor5(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
569 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0,0,0,0))>::type>::type;
570 printFunctor<FunctorType, Scalar, 5>(functor, out, functorName);
573 template<
class FunctorType>
574 void printFunctor6(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
576 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0,0,0,0,0))>::type>::type;
577 printFunctor<FunctorType, Scalar, 6>(functor, out, functorName);
580 template<
class FunctorType>
581 void printFunctor7(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
583 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0,0,0,0,0,0))>::type>::type;
584 printFunctor<FunctorType, Scalar, 7>(functor, out, functorName);
588 void printView(
const View &view, std::ostream &out,
const std::string &viewName =
"")
590 using Scalar =
typename View::value_type;
591 using HostView =
typename View::HostMirror;
594 auto hostView = getHostCopy(view);
596 HostViewIteratorScalar vi(hostView);
598 bool moreEntries = (vi.nextIncrementRank() != -1);
601 Scalar value = vi.
get();
603 auto location = vi.getLocation();
604 out << viewName <<
"(";
605 for (
unsigned i=0; i<getFunctorRank(view); i++)
608 if (i<getFunctorRank(view)-1)
613 out <<
") " << value << std::endl;
615 moreEntries = (vi.increment() != -1);
619 template <
class FunctorType1,
class FunctorType2,
int rank,
typename Scalar=
typename FunctorType1::value_type,
class ExecutionSpace =
typename FunctorType1::execution_space>
621 testFloatingEquality(
const FunctorType1 &functor1,
const FunctorType2 &functor2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
622 std::string functor1Name =
"Functor 1", std::string functor2Name =
"Functor 2")
624 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"testFloatingEquality() called on FunctorType1 or FunctorType2 that does not support the specified rank.\n");
628 template <
class FunctorType1,
class FunctorType2,
int rank,
typename Scalar=
typename FunctorType1::value_type,
class ExecutionSpace =
typename FunctorType1::execution_space>
630 testFloatingEquality(
const FunctorType1 &functor1,
const FunctorType2 &functor2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
631 std::string functor1Name =
"Functor 1", std::string functor2Name =
"Functor 2")
640 TEUCHOS_TEST_FOR_EXCEPTION(getFunctorRank(functor1) != rank, std::invalid_argument,
"functor1 and functor2 must agree in rank");
641 TEUCHOS_TEST_FOR_EXCEPTION(getFunctorRank(functor2) != rank, std::invalid_argument,
"functor1 and functor2 must agree in rank");
644 for (
unsigned i=0; i<getFunctorRank(functor1); i++)
646 TEUCHOS_TEST_FOR_EXCEPTION(functor1.extent_int(i) != functor2.extent_int(i), std::invalid_argument,
647 "functor1 and functor2 must agree in size in each dimension; functor1 has extent "
648 + std::to_string(functor1.extent_int(i)) +
" in dimension " + std::to_string(i)
649 +
"; functor2 has extent " + std::to_string(functor2.extent_int(i)) );
650 entryCount *= functor1.extent_int(i);
652 if (entryCount == 0)
return;
654 ViewType<bool,ExecutionSpace> valuesMatch = getView<bool,ExecutionSpace>(
"valuesMatch", entryCount);
656 Kokkos::RangePolicy < ExecutionSpace > policy(0,entryCount);
657 Kokkos::parallel_for( policy,
658 KOKKOS_LAMBDA (
const int &enumerationIndex )
660 Functor1IteratorScalar vi1(functor1);
661 Functor2IteratorScalar vi2(functor2);
663 vi1.setEnumerationIndex(enumerationIndex);
664 vi2.setEnumerationIndex(enumerationIndex);
666 const Scalar & value1 = vi1.
get();
667 const Scalar & value2 = vi2.
get();
669 bool errMeetsTol = errMeetsAbsAndRelTol(value1, value2, relTol, absTol);
670 valuesMatch(enumerationIndex) = errMeetsTol;
674 int failureCount = 0;
675 Kokkos::RangePolicy<ExecutionSpace > reducePolicy(0, entryCount);
676 Kokkos::parallel_reduce( reducePolicy,
677 KOKKOS_LAMBDA(
const int &enumerationIndex,
int &reducedValue )
679 reducedValue += valuesMatch(enumerationIndex) ? 0 : 1;
682 const bool allValuesMatch = (failureCount == 0);
683 success = success && allValuesMatch;
688 auto functor1CopyHost = copyFunctorToHostView<FunctorType1,Scalar,rank>(functor1);
689 auto functor2CopyHost = copyFunctorToHostView<FunctorType2,Scalar,rank>(functor2);
691 auto valuesMatchHost = getHostCopy(valuesMatch);
697 bool moreEntries =
true;
700 bool errMeetsTol = viMatch.get();
704 const Scalar value1 = vi1.
get();
705 const Scalar value2 = vi2.
get();
708 auto location = vi1.getLocation();
709 out <<
"At location (";
710 for (
unsigned i=0; i<getFunctorRank(functor1); i++)
713 if (i<getFunctorRank(functor1)-1)
718 out <<
") " << functor1Name <<
" value != " << functor2Name <<
" value (";
719 out << value1 <<
" != " << value2 <<
"); diff is " << std::abs(value1-value2) << std::endl;
722 moreEntries = (vi1.increment() != -1);
723 moreEntries = moreEntries && (vi2.increment() != -1);
724 moreEntries = moreEntries && (viMatch.increment() != -1);
729 template <
class ViewType,
class FunctorType>
730 void testFloatingEquality1(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
731 std::string view1Name =
"View", std::string view2Name =
"Functor")
733 testFloatingEquality<ViewType, FunctorType, 1>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
736 template <
class ViewType,
class FunctorType>
737 void testFloatingEquality2(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
738 std::string view1Name =
"View", std::string view2Name =
"Functor")
740 testFloatingEquality<ViewType, FunctorType, 2>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
743 template <
class ViewType,
class FunctorType>
744 void testFloatingEquality3(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
745 std::string view1Name =
"View", std::string view2Name =
"Functor")
747 testFloatingEquality<ViewType, FunctorType, 3>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
750 template <
class ViewType,
class FunctorType>
751 void testFloatingEquality4(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
752 std::string view1Name =
"View", std::string view2Name =
"Functor")
754 testFloatingEquality<ViewType, FunctorType, 4>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
757 template <
class ViewType,
class FunctorType>
758 void testFloatingEquality5(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
759 std::string view1Name =
"View", std::string view2Name =
"Functor")
761 testFloatingEquality<ViewType, FunctorType, 5>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
764 template <
class ViewType,
class FunctorType>
765 void testFloatingEquality6(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
766 std::string view1Name =
"View", std::string view2Name =
"Functor")
768 testFloatingEquality<ViewType, FunctorType, 6>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
771 template <
class ViewType,
class FunctorType>
772 void testFloatingEquality7(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
773 std::string view1Name =
"View", std::string view2Name =
"Functor")
775 testFloatingEquality<ViewType, FunctorType, 7>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
778 template <
class ViewType1,
class ViewType2>
779 void testViewFloatingEquality(
const ViewType1 &view1,
const ViewType2 &view2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
780 std::string view1Name =
"View 1", std::string view2Name =
"View 2")
783 TEUCHOS_TEST_FOR_EXCEPTION(view1.rank() != view2.rank(), std::invalid_argument,
"views must agree in rank");
784 for (
unsigned i=0; i<view1.rank(); i++)
786 TEUCHOS_TEST_FOR_EXCEPTION(view1.extent_int(i) != view2.extent_int(i), std::invalid_argument,
"views must agree in size in each dimension");
789 if (view1.size() == 0)
return;
791 const int rank = view1.rank();
794 case 0: testFloatingEquality<ViewType1, ViewType2, 0>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
795 case 1: testFloatingEquality<ViewType1, ViewType2, 1>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
796 case 2: testFloatingEquality<ViewType1, ViewType2, 2>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
797 case 3: testFloatingEquality<ViewType1, ViewType2, 3>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
798 case 4: testFloatingEquality<ViewType1, ViewType2, 4>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
799 case 5: testFloatingEquality<ViewType1, ViewType2, 5>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
800 case 6: testFloatingEquality<ViewType1, ViewType2, 6>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
801 case 7: testFloatingEquality<ViewType1, ViewType2, 7>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
802 default: INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported rank");
808 #ifdef HAVE_INTREPID2_SACADO
809 using Sacado_Fad_DFadType = Sacado::Fad::DFad<double>;
810 #define INTREPID2_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
812 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
814 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, Sacado_Fad_DFadType ) \
816 #define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
818 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, double, double ) \
820 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, Sacado_Fad_DFadType, Sacado_Fad_DFadType ) \
823 #define INTREPID2_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
825 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
827 #define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
829 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, double, double ) \
Stateless classes that act as factories for two families of hierarchical bases. HierarchicalBasisFami...
Stateless class representing a family of basis functions, templated on H(vol) and H(grad) on the line...
KOKKOS_INLINE_FUNCTION ScalarType get()
SFINAE helper to detect whether a type supports a rank-integral-argument operator().
Header function for Intrepid2::Util class and other utility functions.
Helper to get Scalar[*+] where the number of *'s matches the given rank.
Basis defining Legendre basis on the line, a polynomial subspace of L^2 (a.k.a. H(vol)) on the line...
Basis defining integrated Legendre basis on the line, a polynomial subspace of H(grad) on the line...
essentially, a read-only variant of ViewIterator, for a general functor (extent_int() and rank() supp...
Defines the Intrepid2::FunctorIterator class, as well as the Intrepid2::functor_returns_ref SFINAE he...
A family of basis functions, constructed from H(vol) and H(grad) bases on the line.
Header file to include all Sacado headers that are required if using Intrepid2 with Sacado types...
A helper class that allows iteration over some part of a Kokkos View, while allowing the calling code...
Header file for the abstract base class Intrepid2::Basis.