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"
34 constexpr
int MAX_FAD_DERIVATIVES_FOR_TESTS = 3;
37 #if defined(KOKKOS_ENABLE_CUDA)
38 using DefaultTestDeviceType = Kokkos::Device<Kokkos::Cuda,Kokkos::CudaSpace>;
39 #elif defined(KOKKOS_ENABLE_HIP)
40 using DefaultTestDeviceType = Kokkos::Device<Kokkos::HIP,Kokkos::HIPSpace>;
42 using DefaultTestDeviceType =
typename Kokkos::DefaultExecutionSpace::device_type;
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;
105 KOKKOS_INLINE_FUNCTION
double fromZeroOne(
double x_zero_one)
107 return x_zero_one * 2.0 - 1.0;
111 KOKKOS_INLINE_FUNCTION
double toZeroOne(
double x_minus_one_one)
113 return (x_minus_one_one + 1.0) / 2.0;
117 KOKKOS_INLINE_FUNCTION
double fromZeroOne_dx(
double dx_zero_one)
119 return dx_zero_one / 2.0;
123 KOKKOS_INLINE_FUNCTION
double toZeroOne_dx(
double dx_minus_one_one)
125 return dx_minus_one_one * 2.0;
128 template<
class DeviceViewType>
129 typename DeviceViewType::HostMirror getHostCopy(
const DeviceViewType &deviceView)
131 typename DeviceViewType::HostMirror hostView = Kokkos::create_mirror(deviceView);
132 Kokkos::deep_copy(hostView, deviceView);
136 template<
class BasisFamily>
137 inline Teuchos::RCP< Intrepid2::Basis<DefaultTestDeviceType,double,double> > getBasisUsingFamily(shards::CellTopology cellTopo, Intrepid2::EFunctionSpace fs,
138 int polyOrder_x,
int polyOrder_y=-1,
int polyOrder_z = -1)
140 using BasisPtr =
typename BasisFamily::BasisPtr;
143 using namespace Intrepid2;
145 if (cellTopo.getBaseKey() == shards::Line<>::key)
147 basis = getLineBasis<BasisFamily>(fs,polyOrder_x);
149 else if (cellTopo.getBaseKey() == shards::Quadrilateral<>::key)
151 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
152 basis = getQuadrilateralBasis<BasisFamily>(fs,polyOrder_x,polyOrder_y);
154 else if (cellTopo.getBaseKey() == shards::Triangle<>::key)
156 basis = getTriangleBasis<BasisFamily>(fs,polyOrder_x);
158 else if (cellTopo.getBaseKey() == shards::Hexahedron<>::key)
160 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
161 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_z < 0, std::invalid_argument,
"polyOrder_z must be specified");
162 basis = getHexahedronBasis<BasisFamily>(fs,polyOrder_x,polyOrder_y,polyOrder_z);
164 else if (cellTopo.getBaseKey() == shards::Tetrahedron<>::key)
166 basis = getTetrahedronBasis<BasisFamily>(fs, polyOrder_x);
168 else if (cellTopo.getBaseKey() == shards::Wedge<>::key)
170 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
171 basis = getWedgeBasis<BasisFamily>(fs,polyOrder_x,polyOrder_y);
173 else if (cellTopo.getBaseKey() == shards::Pyramid<>::key)
175 basis = getPyramidBasis<BasisFamily>(fs,polyOrder_x);
179 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported cell topology");
184 template<
bool defineVertexFunctions>
185 inline Teuchos::RCP< Intrepid2::Basis<DefaultTestDeviceType,double,double> > getHierarchicalBasis(shards::CellTopology cellTopo, Intrepid2::EFunctionSpace fs,
186 int polyOrder_x,
int polyOrder_y=-1,
int polyOrder_z = -1)
188 using DeviceType = DefaultTestDeviceType;
189 using Scalar = double;
190 using namespace Intrepid2;
200 return getBasisUsingFamily<BasisFamily>(cellTopo, fs, polyOrder_x, polyOrder_y, polyOrder_z);
203 template<
typename ValueType,
typename DeviceType,
class ... DimArgs>
204 inline ViewType<ValueType,DeviceType> getView(
const std::string &label, DimArgs... dims)
206 const bool allocateFadStorage = !(std::is_standard_layout<ValueType>::value && std::is_trivial<ValueType>::value);
207 if (!allocateFadStorage)
209 return ViewType<ValueType,DeviceType>(label,dims...);
213 return ViewType<ValueType,DeviceType>(label,dims...,MAX_FAD_DERIVATIVES_FOR_TESTS+1);
218 template<
typename ValueType,
class ... DimArgs>
219 inline FixedRankViewType<
typename RankExpander<ValueType,
sizeof...(DimArgs) >::value_type, DefaultTestDeviceType > getFixedRankView(
const std::string &label, DimArgs... dims)
221 const bool allocateFadStorage = !(std::is_standard_layout<ValueType>::value && std::is_trivial<ValueType>::value);
222 using value_type =
typename RankExpander<ValueType,
sizeof...(dims) >::value_type;
223 if (!allocateFadStorage)
225 return FixedRankViewType<value_type,DefaultTestDeviceType>(label,dims...);
229 return FixedRankViewType<value_type,DefaultTestDeviceType>(label,dims...,MAX_FAD_DERIVATIVES_FOR_TESTS+1);
239 template <
typename Po
intValueType,
typename DeviceType>
240 inline ViewType<PointValueType,DeviceType> getInputPointsView(shards::CellTopology &cellTopo,
int numPoints_1D)
242 if (cellTopo.getBaseKey() == shards::Wedge<>::key)
244 shards::CellTopology lineTopo = shards::CellTopology(shards::getCellTopologyData<shards::Line<> >() );
245 shards::CellTopology triTopo = shards::CellTopology(shards::getCellTopologyData<shards::Triangle<> >() );
247 const ordinal_type order = numPoints_1D - 1;
250 ordinal_type numPoints = numPoints_tri * numPoints_line;
251 ordinal_type spaceDim = cellTopo.getDimension();
253 ViewType<PointValueType,DeviceType> inputPointsTri = getView<PointValueType,DeviceType>(
"input points",numPoints_tri, 2);
254 ViewType<PointValueType,DeviceType> inputPointsLine = getView<PointValueType,DeviceType>(
"input points",numPoints_line,1);
258 ViewType<PointValueType,DeviceType> inputPoints = getView<PointValueType,DeviceType>(
"input points",numPoints,spaceDim);
260 using ExecutionSpace =
typename ViewType<PointValueType,DeviceType>::execution_space;
262 Kokkos::RangePolicy < ExecutionSpace > policy(0,numPoints_tri);
263 Kokkos::parallel_for( policy,
264 KOKKOS_LAMBDA (
const ordinal_type &triPointOrdinal )
266 ordinal_type pointOrdinal = triPointOrdinal * numPoints_line;
267 for (ordinal_type linePointOrdinal=0; linePointOrdinal<numPoints_line; linePointOrdinal++)
269 inputPoints(pointOrdinal,0) = inputPointsTri( triPointOrdinal,0);
270 inputPoints(pointOrdinal,1) = inputPointsTri( triPointOrdinal,1);
271 inputPoints(pointOrdinal,2) = inputPointsLine(linePointOrdinal,0);
281 const ordinal_type order = numPoints_1D - 1;
283 ordinal_type spaceDim = cellTopo.getDimension();
285 ViewType<PointValueType,DeviceType> inputPoints = getView<PointValueType,DeviceType>(
"input points",numPoints,spaceDim);
292 template<
typename OutputValueType,
typename DeviceType>
293 inline ViewType<OutputValueType,DeviceType> getOutputView(Intrepid2::EFunctionSpace fs, Intrepid2::EOperator op,
int basisCardinality,
int numPoints,
int spaceDim)
296 case Intrepid2::FUNCTION_SPACE_HGRAD:
298 case Intrepid2::OPERATOR_VALUE:
299 return getView<OutputValueType,DeviceType>(
"H^1 value output",basisCardinality,numPoints);
300 case Intrepid2::OPERATOR_GRAD:
301 return getView<OutputValueType,DeviceType>(
"H^1 derivative output",basisCardinality,numPoints,spaceDim);
302 case Intrepid2::OPERATOR_D1:
303 case Intrepid2::OPERATOR_D2:
304 case Intrepid2::OPERATOR_D3:
305 case Intrepid2::OPERATOR_D4:
306 case Intrepid2::OPERATOR_D5:
307 case Intrepid2::OPERATOR_D6:
308 case Intrepid2::OPERATOR_D7:
309 case Intrepid2::OPERATOR_D8:
310 case Intrepid2::OPERATOR_D9:
311 case Intrepid2::OPERATOR_D10:
313 const auto dkcard = getDkCardinality(op, spaceDim);
314 return getView<OutputValueType,DeviceType>(
"H^1 derivative output",basisCardinality,numPoints,dkcard);
317 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
319 case Intrepid2::FUNCTION_SPACE_HCURL:
321 case Intrepid2::OPERATOR_VALUE:
322 return getView<OutputValueType,DeviceType>(
"H(curl) value output",basisCardinality,numPoints,spaceDim);
323 case Intrepid2::OPERATOR_CURL:
325 return getView<OutputValueType,DeviceType>(
"H(curl) derivative output",basisCardinality,numPoints);
326 else if (spaceDim == 3)
327 return getView<OutputValueType,DeviceType>(
"H(curl) derivative output",basisCardinality,numPoints,spaceDim);
329 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
331 case Intrepid2::FUNCTION_SPACE_HDIV:
333 case Intrepid2::OPERATOR_VALUE:
334 return getView<OutputValueType,DeviceType>(
"H(div) value output",basisCardinality,numPoints,spaceDim);
335 case Intrepid2::OPERATOR_DIV:
336 return getView<OutputValueType,DeviceType>(
"H(div) derivative output",basisCardinality,numPoints);
338 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
341 case Intrepid2::FUNCTION_SPACE_HVOL:
343 case Intrepid2::OPERATOR_VALUE:
344 return getView<OutputValueType,DeviceType>(
"H(vol) value output",basisCardinality,numPoints);
345 case Intrepid2::OPERATOR_D1:
346 case Intrepid2::OPERATOR_D2:
347 case Intrepid2::OPERATOR_D3:
348 case Intrepid2::OPERATOR_D4:
349 case Intrepid2::OPERATOR_D5:
350 case Intrepid2::OPERATOR_D6:
351 case Intrepid2::OPERATOR_D7:
352 case Intrepid2::OPERATOR_D8:
353 case Intrepid2::OPERATOR_D9:
354 case Intrepid2::OPERATOR_D10:
356 const auto dkcard = getDkCardinality(op, spaceDim);
357 return getView<OutputValueType,DeviceType>(
"H(vol) derivative output",basisCardinality,numPoints,dkcard);
360 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
363 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
369 inline std::vector< std::vector<int> > getBasisTestCasesUpToDegree(
int spaceDim,
int minDegree,
int polyOrder_x,
int polyOrder_y=-1,
int polyOrder_z=-1)
371 std::vector<int> degrees(spaceDim);
372 degrees[0] = polyOrder_x;
373 if (spaceDim > 1) degrees[1] = polyOrder_y;
374 if (spaceDim > 2) degrees[2] = polyOrder_z;
376 int numCases = degrees[0];
377 for (
unsigned d=1; d<degrees.size(); d++)
379 INTREPID2_TEST_FOR_EXCEPTION(degrees[d] < minDegree, std::invalid_argument,
"Unsupported degree/minDegree combination");
380 numCases = numCases * (degrees[d] + 1 - minDegree);
382 std::vector< std::vector<int> > subBasisDegreeTestCases(numCases);
383 for (
int caseOrdinal=0; caseOrdinal<numCases; caseOrdinal++)
385 std::vector<int> subBasisDegrees(degrees.size());
386 int caseRemainder = caseOrdinal;
387 for (
int d=degrees.size()-1; d>=0; d--)
389 int subBasisDegree = caseRemainder % (degrees[d] + 1 - minDegree);
390 caseRemainder = caseRemainder / (degrees[d] + 1 - minDegree);
391 subBasisDegrees[d] = subBasisDegree + minDegree;
393 subBasisDegreeTestCases[caseOrdinal] = subBasisDegrees;
395 return subBasisDegreeTestCases;
399 template<
class Functor,
class Scalar,
int rank>
400 typename ViewType<Scalar,DefaultTestDeviceType>::HostMirror copyFunctorToHostView(
const Functor &deviceFunctor)
402 INTREPID2_TEST_FOR_EXCEPTION(rank != getFunctorRank(deviceFunctor), std::invalid_argument,
"functor rank must match the template argument");
404 using DeviceType = DefaultTestDeviceType;
405 ViewType<Scalar,DeviceType> view;
406 const std::string label =
"functor copy";
407 const auto &f = deviceFunctor;
411 view = getView<Scalar,DeviceType>(label);
414 view = getView<Scalar,DeviceType>(label, f.extent_int(0));
417 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1));
420 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2));
423 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2), f.extent_int(3));
426 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));
429 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));
432 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));
435 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported functor rank");
438 int entryCount = view.size();
440 using ExecutionSpace =
typename ViewType<Scalar,DeviceType>::execution_space;
445 Kokkos::RangePolicy < ExecutionSpace > policy(0,entryCount);
446 Kokkos::parallel_for( policy,
447 KOKKOS_LAMBDA (
const int &enumerationIndex )
449 ViewIteratorScalar vi(view);
450 FunctorIteratorScalar fi(f);
452 vi.setEnumerationIndex(enumerationIndex);
453 fi.setEnumerationIndex(enumerationIndex);
459 auto hostView = Kokkos::create_mirror_view(view);
460 Kokkos::deep_copy(hostView, view);
464 template<
class FunctorType,
typename Scalar,
int rank>
465 void printFunctor(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
467 auto functorHostCopy = copyFunctorToHostView<FunctorType, Scalar, rank>(functor);
469 std::string name = (functorName ==
"") ?
"Functor" : functorName;
471 out <<
"\n******** " << name <<
" (rank " << rank <<
") ********\n";
472 out <<
"dimensions: (";
473 for (
int r=0; r<rank; r++)
475 out << functor.extent_int(r);
476 if (r<rank-1) out <<
",";
482 bool moreEntries =
true;
485 Scalar value = vi.
get();
487 auto location = vi.getLocation();
488 out << functorName <<
"(";
489 for (ordinal_type i=0; i<rank; i++)
497 out <<
") " << value << std::endl;
499 moreEntries = (vi.increment() != -1);
504 template<
class FunctorType>
505 void printFunctor1(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
507 using Scalar =
typename std::remove_reference<decltype(functor(0))>::type;
508 printFunctor<FunctorType, Scalar, 1>(functor, out, functorName);
511 template<
class FunctorType>
512 void printFunctor2(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
514 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0))>::type>::type;
515 printFunctor<FunctorType, Scalar, 2>(functor, out, functorName);
518 template<
class FunctorType>
519 void printFunctor3(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
521 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0,0))>::type>::type;
522 printFunctor<FunctorType, Scalar, 3>(functor, out, functorName);
525 template<
class FunctorType>
526 void printFunctor4(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
528 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0,0,0))>::type>::type;
529 printFunctor<FunctorType, Scalar, 4>(functor, out, functorName);
532 template<
class FunctorType>
533 void printFunctor5(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
535 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0,0,0,0))>::type>::type;
536 printFunctor<FunctorType, Scalar, 5>(functor, out, functorName);
539 template<
class FunctorType>
540 void printFunctor6(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
542 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0,0,0,0,0))>::type>::type;
543 printFunctor<FunctorType, Scalar, 6>(functor, out, functorName);
546 template<
class FunctorType>
547 void printFunctor7(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
549 using Scalar =
typename std::remove_const<typename std::remove_reference<decltype(functor(0,0,0,0,0,0,0))>::type>::type;
550 printFunctor<FunctorType, Scalar, 7>(functor, out, functorName);
554 void printView(
const View &view, std::ostream &out,
const std::string &viewName =
"")
556 using Scalar =
typename View::value_type;
557 using HostView =
typename View::HostMirror;
560 auto hostView = getHostCopy(view);
562 HostViewIteratorScalar vi(hostView);
564 bool moreEntries = (vi.nextIncrementRank() != -1);
567 Scalar value = vi.
get();
569 auto location = vi.getLocation();
570 out << viewName <<
"(";
571 for (
unsigned i=0; i<getFunctorRank(view); i++)
574 if (i<getFunctorRank(view)-1)
579 out <<
") " << value << std::endl;
581 moreEntries = (vi.increment() != -1);
585 template <
class FunctorType1,
class FunctorType2,
int rank,
typename Scalar=
typename FunctorType1::value_type,
class ExecutionSpace =
typename FunctorType1::execution_space>
587 testFloatingEquality(
const FunctorType1 &functor1,
const FunctorType2 &functor2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
588 std::string functor1Name =
"Functor 1", std::string functor2Name =
"Functor 2")
590 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"testFloatingEquality() called on FunctorType1 or FunctorType2 that does not support the specified rank.\n");
594 template <
class FunctorType1,
class FunctorType2,
int rank,
typename Scalar=
typename FunctorType1::value_type,
class ExecutionSpace =
typename FunctorType1::execution_space>
596 testFloatingEquality(
const FunctorType1 &functor1,
const FunctorType2 &functor2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
597 std::string functor1Name =
"Functor 1", std::string functor2Name =
"Functor 2")
606 TEUCHOS_TEST_FOR_EXCEPTION(getFunctorRank(functor1) != rank, std::invalid_argument,
"functor1 and functor2 must agree in rank");
607 TEUCHOS_TEST_FOR_EXCEPTION(getFunctorRank(functor2) != rank, std::invalid_argument,
"functor1 and functor2 must agree in rank");
610 for (
unsigned i=0; i<getFunctorRank(functor1); i++)
612 TEUCHOS_TEST_FOR_EXCEPTION(functor1.extent_int(i) != functor2.extent_int(i), std::invalid_argument,
613 "functor1 and functor2 must agree in size in each dimension; functor1 has extent "
614 + std::to_string(functor1.extent_int(i)) +
" in dimension " + std::to_string(i)
615 +
"; functor2 has extent " + std::to_string(functor2.extent_int(i)) );
616 entryCount *= functor1.extent_int(i);
618 if (entryCount == 0)
return;
620 ViewType<bool,ExecutionSpace> valuesMatch = getView<bool,ExecutionSpace>(
"valuesMatch", entryCount);
622 Kokkos::RangePolicy < ExecutionSpace > policy(0,entryCount);
623 Kokkos::parallel_for( policy,
624 KOKKOS_LAMBDA (
const int &enumerationIndex )
626 Functor1IteratorScalar vi1(functor1);
627 Functor2IteratorScalar vi2(functor2);
629 vi1.setEnumerationIndex(enumerationIndex);
630 vi2.setEnumerationIndex(enumerationIndex);
632 const Scalar & value1 = vi1.
get();
633 const Scalar & value2 = vi2.
get();
635 bool errMeetsTol = errMeetsAbsAndRelTol(value1, value2, relTol, absTol);
636 valuesMatch(enumerationIndex) = errMeetsTol;
640 int failureCount = 0;
641 Kokkos::RangePolicy<ExecutionSpace > reducePolicy(0, entryCount);
642 Kokkos::parallel_reduce( reducePolicy,
643 KOKKOS_LAMBDA(
const int &enumerationIndex,
int &reducedValue )
645 reducedValue += valuesMatch(enumerationIndex) ? 0 : 1;
648 const bool allValuesMatch = (failureCount == 0);
649 success = success && allValuesMatch;
654 auto functor1CopyHost = copyFunctorToHostView<FunctorType1,Scalar,rank>(functor1);
655 auto functor2CopyHost = copyFunctorToHostView<FunctorType2,Scalar,rank>(functor2);
657 auto valuesMatchHost = getHostCopy(valuesMatch);
663 bool moreEntries =
true;
666 bool errMeetsTol = viMatch.get();
670 const Scalar value1 = vi1.
get();
671 const Scalar value2 = vi2.
get();
674 auto location = vi1.getLocation();
675 out <<
"At location (";
676 for (
unsigned i=0; i<getFunctorRank(functor1); i++)
679 if (i<getFunctorRank(functor1)-1)
684 out <<
") " << functor1Name <<
" value != " << functor2Name <<
" value (";
685 out << value1 <<
" != " << value2 <<
"); diff is " << std::abs(value1-value2) << std::endl;
688 moreEntries = (vi1.increment() != -1);
689 moreEntries = moreEntries && (vi2.increment() != -1);
690 moreEntries = moreEntries && (viMatch.increment() != -1);
695 template <
class ViewType,
class FunctorType>
696 void testFloatingEquality1(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
697 std::string view1Name =
"View", std::string view2Name =
"Functor")
699 testFloatingEquality<ViewType, FunctorType, 1>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
702 template <
class ViewType,
class FunctorType>
703 void testFloatingEquality2(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
704 std::string view1Name =
"View", std::string view2Name =
"Functor")
706 testFloatingEquality<ViewType, FunctorType, 2>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
709 template <
class ViewType,
class FunctorType>
710 void testFloatingEquality3(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
711 std::string view1Name =
"View", std::string view2Name =
"Functor")
713 testFloatingEquality<ViewType, FunctorType, 3>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
716 template <
class ViewType,
class FunctorType>
717 void testFloatingEquality4(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
718 std::string view1Name =
"View", std::string view2Name =
"Functor")
720 testFloatingEquality<ViewType, FunctorType, 4>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
723 template <
class ViewType,
class FunctorType>
724 void testFloatingEquality5(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
725 std::string view1Name =
"View", std::string view2Name =
"Functor")
727 testFloatingEquality<ViewType, FunctorType, 5>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
730 template <
class ViewType,
class FunctorType>
731 void testFloatingEquality6(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
732 std::string view1Name =
"View", std::string view2Name =
"Functor")
734 testFloatingEquality<ViewType, FunctorType, 6>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
737 template <
class ViewType,
class FunctorType>
738 void testFloatingEquality7(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
739 std::string view1Name =
"View", std::string view2Name =
"Functor")
741 testFloatingEquality<ViewType, FunctorType, 7>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
744 template <
class ViewType1,
class ViewType2>
745 void testViewFloatingEquality(
const ViewType1 &view1,
const ViewType2 &view2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
746 std::string view1Name =
"View 1", std::string view2Name =
"View 2")
749 TEUCHOS_TEST_FOR_EXCEPTION(view1.rank() != view2.rank(), std::invalid_argument,
"views must agree in rank");
750 for (
unsigned i=0; i<view1.rank(); i++)
752 TEUCHOS_TEST_FOR_EXCEPTION(view1.extent_int(i) != view2.extent_int(i), std::invalid_argument,
"views must agree in size in each dimension");
755 if (view1.size() == 0)
return;
757 const int rank = view1.rank();
760 case 0: testFloatingEquality<ViewType1, ViewType2, 0>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
761 case 1: testFloatingEquality<ViewType1, ViewType2, 1>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
762 case 2: testFloatingEquality<ViewType1, ViewType2, 2>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
763 case 3: testFloatingEquality<ViewType1, ViewType2, 3>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
764 case 4: testFloatingEquality<ViewType1, ViewType2, 4>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
765 case 5: testFloatingEquality<ViewType1, ViewType2, 5>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
766 case 6: testFloatingEquality<ViewType1, ViewType2, 6>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
767 case 7: testFloatingEquality<ViewType1, ViewType2, 7>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
768 default: INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported rank");
774 #ifdef HAVE_INTREPID2_SACADO
775 using Sacado_Fad_DFadType = Sacado::Fad::DFad<double>;
776 #define INTREPID2_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
778 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
780 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, Sacado_Fad_DFadType ) \
782 #define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
784 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, double, double ) \
786 TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, Sacado_Fad_DFadType, Sacado_Fad_DFadType ) \
789 #define INTREPID2_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
791 TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
793 #define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
795 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.