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;
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::host_mirror_type getHostCopy(
const DeviceViewType &deviceView)
131 typename DeviceViewType::host_mirror_type 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)
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);
330 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
332 case Intrepid2::FUNCTION_SPACE_HDIV:
334 case Intrepid2::OPERATOR_VALUE:
335 return getView<OutputValueType,DeviceType>(
"H(div) value output",basisCardinality,numPoints,spaceDim);
336 case Intrepid2::OPERATOR_DIV:
337 return getView<OutputValueType,DeviceType>(
"H(div) derivative output",basisCardinality,numPoints);
339 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
342 case Intrepid2::FUNCTION_SPACE_HVOL:
344 case Intrepid2::OPERATOR_VALUE:
345 return getView<OutputValueType,DeviceType>(
"H(vol) value output",basisCardinality,numPoints);
346 case Intrepid2::OPERATOR_D1:
347 case Intrepid2::OPERATOR_D2:
348 case Intrepid2::OPERATOR_D3:
349 case Intrepid2::OPERATOR_D4:
350 case Intrepid2::OPERATOR_D5:
351 case Intrepid2::OPERATOR_D6:
352 case Intrepid2::OPERATOR_D7:
353 case Intrepid2::OPERATOR_D8:
354 case Intrepid2::OPERATOR_D9:
355 case Intrepid2::OPERATOR_D10:
358 return getView<OutputValueType,DeviceType>(
"H(vol) derivative output",basisCardinality,numPoints,dkcard);
361 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
364 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported op/fs combination");
370 inline std::vector< std::vector<int> > getBasisTestCasesUpToDegree(
int spaceDim,
int minDegree,
int polyOrder_x,
int polyOrder_y=-1,
int polyOrder_z=-1)
372 std::vector<int> degrees(spaceDim);
373 degrees[0] = polyOrder_x;
374 if (spaceDim > 1) degrees[1] = polyOrder_y;
375 if (spaceDim > 2) degrees[2] = polyOrder_z;
377 int numCases = degrees[0];
378 for (
unsigned d=1; d<degrees.size(); d++)
380 INTREPID2_TEST_FOR_EXCEPTION(degrees[d] < minDegree, std::invalid_argument,
"Unsupported degree/minDegree combination");
381 numCases = numCases * (degrees[d] + 1 - minDegree);
383 std::vector< std::vector<int> > subBasisDegreeTestCases(numCases);
384 for (
int caseOrdinal=0; caseOrdinal<numCases; caseOrdinal++)
386 std::vector<int> subBasisDegrees(degrees.size());
387 int caseRemainder = caseOrdinal;
388 for (
int d=degrees.size()-1; d>=0; d--)
390 int subBasisDegree = caseRemainder % (degrees[d] + 1 - minDegree);
391 caseRemainder = caseRemainder / (degrees[d] + 1 - minDegree);
392 subBasisDegrees[d] = subBasisDegree + minDegree;
394 subBasisDegreeTestCases[caseOrdinal] = subBasisDegrees;
396 return subBasisDegreeTestCases;
400 template<
class Functor,
class Scalar,
int rank>
401 typename ViewType<Scalar,DefaultTestDeviceType>::host_mirror_type
copyFunctorToHostView(
const Functor &deviceFunctor)
403 INTREPID2_TEST_FOR_EXCEPTION(rank !=
getFunctorRank(deviceFunctor), std::invalid_argument,
"functor rank must match the template argument");
406 ViewType<Scalar,DeviceType> view;
407 const std::string label =
"functor copy";
408 const auto &f = deviceFunctor;
412 view = getView<Scalar,DeviceType>(label);
415 view = getView<Scalar,DeviceType>(label, f.extent_int(0));
418 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1));
421 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2));
424 view = getView<Scalar,DeviceType>(label, f.extent_int(0), f.extent_int(1), f.extent_int(2), f.extent_int(3));
427 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));
430 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));
433 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));
436 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported functor rank");
439 int entryCount = view.size();
441 using ExecutionSpace =
typename ViewType<Scalar,DeviceType>::execution_space;
446 Kokkos::RangePolicy < ExecutionSpace > policy(0,entryCount);
447 Kokkos::parallel_for( policy,
448 KOKKOS_LAMBDA (
const int &enumerationIndex )
450 ViewIteratorScalar vi(view);
451 FunctorIteratorScalar fi(f);
453 vi.setEnumerationIndex(enumerationIndex);
454 fi.setEnumerationIndex(enumerationIndex);
460 auto hostView = Kokkos::create_mirror_view(view);
461 Kokkos::deep_copy(hostView, view);
465 template<
class FunctorType,
typename Scalar,
int rank>
466 void printFunctor(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
468 auto functorHostCopy = copyFunctorToHostView<FunctorType, Scalar, rank>(functor);
470 std::string name = (functorName ==
"") ?
"Functor" : functorName;
472 out <<
"\n******** " << name <<
" (rank " << rank <<
") ********\n";
473 out <<
"dimensions: (";
474 for (
int r=0; r<rank; r++)
476 out << functor.extent_int(r);
477 if (r<rank-1) out <<
",";
481 ViewIterator<
decltype(functorHostCopy),Scalar> vi(functorHostCopy);
483 bool moreEntries =
true;
486 Scalar value = vi.get();
488 auto location = vi.getLocation();
489 out << functorName <<
"(";
490 for (ordinal_type i=0; i<rank; i++)
498 out <<
") " << value << std::endl;
500 moreEntries = (vi.increment() != -1);
505 template<
class FunctorType>
506 void printFunctor1(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
508 using Scalar =
typename std::remove_reference<
decltype(functor(0))>::type;
509 printFunctor<FunctorType, Scalar, 1>(functor, out, functorName);
512 template<
class FunctorType>
513 void printFunctor2(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
515 using Scalar =
typename std::remove_const<
typename std::remove_reference<
decltype(functor(0,0))>::type>::type;
516 printFunctor<FunctorType, Scalar, 2>(functor, out, functorName);
519 template<
class FunctorType>
520 void printFunctor3(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
522 using Scalar =
typename std::remove_const<
typename std::remove_reference<
decltype(functor(0,0,0))>::type>::type;
523 printFunctor<FunctorType, Scalar, 3>(functor, out, functorName);
526 template<
class FunctorType>
527 void printFunctor4(
const FunctorType &functor, std::ostream &out,
const std::string &functorName =
"")
529 using Scalar =
typename std::remove_const<
typename std::remove_reference<
decltype(functor(0,0,0,0))>::type>::type;
530 printFunctor<FunctorType, Scalar, 4>(functor, out, functorName);
533 template<
class FunctorType>
534 void printFunctor5(
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,0,0,0))>::type>::type;
537 printFunctor<FunctorType, Scalar, 5>(functor, out, functorName);
540 template<
class FunctorType>
541 void printFunctor6(
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,0,0,0))>::type>::type;
544 printFunctor<FunctorType, Scalar, 6>(functor, out, functorName);
547 template<
class FunctorType>
548 void printFunctor7(
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,0,0,0))>::type>::type;
551 printFunctor<FunctorType, Scalar, 7>(functor, out, functorName);
555 void printView(
const View &view, std::ostream &out,
const std::string &viewName =
"")
557 using Scalar =
typename View::value_type;
558 using HostView =
typename View::host_mirror_type;
561 auto hostView = getHostCopy(view);
563 HostViewIteratorScalar vi(hostView);
565 bool moreEntries = (vi.nextIncrementRank() != -1);
568 Scalar value = vi.get();
570 auto location = vi.getLocation();
571 out << viewName <<
"(";
580 out <<
") " << value << std::endl;
582 moreEntries = (vi.increment() != -1);
586 template <
class FunctorType1,
class FunctorType2,
int rank,
typename Scalar=
typename FunctorType1::value_type,
class ExecutionSpace =
typename FunctorType1::execution_space>
588 testFloatingEquality(
const FunctorType1 &functor1,
const FunctorType2 &functor2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
589 std::string functor1Name =
"Functor 1", std::string functor2Name =
"Functor 2")
591 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"testFloatingEquality() called on FunctorType1 or FunctorType2 that does not support the specified rank.\n");
595 template <
class FunctorType1,
class FunctorType2,
int rank,
typename Scalar=
typename FunctorType1::value_type,
class ExecutionSpace =
typename FunctorType1::execution_space>
597 testFloatingEquality(
const FunctorType1 &functor1,
const FunctorType2 &functor2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
598 std::string functor1Name =
"Functor 1", std::string functor2Name =
"Functor 2")
607 TEUCHOS_TEST_FOR_EXCEPTION(
getFunctorRank(functor1) != rank, std::invalid_argument,
"functor1 and functor2 must agree in rank");
608 TEUCHOS_TEST_FOR_EXCEPTION(
getFunctorRank(functor2) != rank, std::invalid_argument,
"functor1 and functor2 must agree in rank");
613 TEUCHOS_TEST_FOR_EXCEPTION(functor1.extent_int(i) != functor2.extent_int(i), std::invalid_argument,
614 "functor1 and functor2 must agree in size in each dimension; functor1 has extent "
615 + std::to_string(functor1.extent_int(i)) +
" in dimension " + std::to_string(i)
616 +
"; functor2 has extent " + std::to_string(functor2.extent_int(i)) );
617 entryCount *= functor1.extent_int(i);
619 if (entryCount == 0)
return;
621 ViewType<bool,ExecutionSpace> valuesMatch = getView<bool,ExecutionSpace>(
"valuesMatch", entryCount);
623 Kokkos::RangePolicy < ExecutionSpace > policy(0,entryCount);
624 Kokkos::parallel_for( policy,
625 KOKKOS_LAMBDA (
const int &enumerationIndex )
627 Functor1IteratorScalar vi1(functor1);
628 Functor2IteratorScalar vi2(functor2);
630 vi1.setEnumerationIndex(enumerationIndex);
631 vi2.setEnumerationIndex(enumerationIndex);
633 const Scalar & value1 = vi1.get();
634 const Scalar & value2 = vi2.get();
636 bool errMeetsTol = errMeetsAbsAndRelTol(value1, value2, relTol, absTol);
637 valuesMatch(enumerationIndex) = errMeetsTol;
641 int failureCount = 0;
642 Kokkos::RangePolicy<ExecutionSpace > reducePolicy(0, entryCount);
643 Kokkos::parallel_reduce( reducePolicy,
644 KOKKOS_LAMBDA(
const int &enumerationIndex,
int &reducedValue )
646 reducedValue += valuesMatch(enumerationIndex) ? 0 : 1;
649 const bool allValuesMatch = (failureCount == 0);
650 success = success && allValuesMatch;
655 auto functor1CopyHost = copyFunctorToHostView<FunctorType1,Scalar,rank>(functor1);
656 auto functor2CopyHost = copyFunctorToHostView<FunctorType2,Scalar,rank>(functor2);
658 auto valuesMatchHost = getHostCopy(valuesMatch);
660 FunctorIterator<
decltype(functor1CopyHost),Scalar,rank> vi1(functor1CopyHost);
661 FunctorIterator<
decltype(functor2CopyHost),Scalar,rank> vi2(functor2CopyHost);
664 bool moreEntries =
true;
667 bool errMeetsTol = viMatch.get();
671 const Scalar value1 = vi1.get();
672 const Scalar value2 = vi2.get();
675 auto location = vi1.getLocation();
676 out <<
"At location (";
685 out <<
") " << functor1Name <<
" value != " << functor2Name <<
" value (";
686 out << value1 <<
" != " << value2 <<
"); diff is " << std::abs(value1-value2) << std::endl;
689 moreEntries = (vi1.increment() != -1);
690 moreEntries = moreEntries && (vi2.increment() != -1);
691 moreEntries = moreEntries && (viMatch.increment() != -1);
696 template <
class ViewType,
class FunctorType>
697 void testFloatingEquality1(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
698 std::string view1Name =
"View", std::string view2Name =
"Functor")
700 testFloatingEquality<ViewType, FunctorType, 1>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
703 template <
class ViewType,
class FunctorType>
704 void testFloatingEquality2(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
705 std::string view1Name =
"View", std::string view2Name =
"Functor")
707 testFloatingEquality<ViewType, FunctorType, 2>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
710 template <
class ViewType,
class FunctorType>
711 void testFloatingEquality3(
const ViewType &view,
const FunctorType &functor,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
712 std::string view1Name =
"View", std::string view2Name =
"Functor")
714 testFloatingEquality<ViewType, FunctorType, 3>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
717 template <
class ViewType,
class FunctorType>
718 void testFloatingEquality4(
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, 4>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
724 template <
class ViewType,
class FunctorType>
725 void testFloatingEquality5(
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, 5>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
731 template <
class ViewType,
class FunctorType>
732 void testFloatingEquality6(
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, 6>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
738 template <
class ViewType,
class FunctorType>
739 void testFloatingEquality7(
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, 7>(view, functor, relTol, absTol, out, success, view1Name, view2Name);
745 template <
class ViewType1,
class ViewType2>
746 void testViewFloatingEquality(
const ViewType1 &view1,
const ViewType2 &view2,
double relTol,
double absTol, Teuchos::FancyOStream &out,
bool &success,
747 std::string view1Name =
"View 1", std::string view2Name =
"View 2")
750 TEUCHOS_TEST_FOR_EXCEPTION(view1.rank() != view2.rank(), std::invalid_argument,
"views must agree in rank");
751 for (
unsigned i=0; i<view1.rank(); i++)
753 TEUCHOS_TEST_FOR_EXCEPTION(view1.extent_int(i) != view2.extent_int(i), std::invalid_argument,
"views must agree in size in each dimension");
756 if (view1.size() == 0)
return;
758 const int rank = view1.rank();
761 case 0: testFloatingEquality<ViewType1, ViewType2, 0>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
762 case 1: testFloatingEquality<ViewType1, ViewType2, 1>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
763 case 2: testFloatingEquality<ViewType1, ViewType2, 2>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
764 case 3: testFloatingEquality<ViewType1, ViewType2, 3>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
765 case 4: testFloatingEquality<ViewType1, ViewType2, 4>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
766 case 5: testFloatingEquality<ViewType1, ViewType2, 5>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
767 case 6: testFloatingEquality<ViewType1, ViewType2, 6>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
768 case 7: testFloatingEquality<ViewType1, ViewType2, 7>(view1, view2, relTol, absTol, out, success, view1Name, view2Name);
break;
769 default: INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported rank");
775#ifdef HAVE_INTREPID2_SACADO
776using Sacado_Fad_DFadType = Sacado::Fad::DFad<double>;
777#define INTREPID2_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
779TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
781TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, Sacado_Fad_DFadType ) \
783#define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
785TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, double, double ) \
787TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, Sacado_Fad_DFadType, Sacado_Fad_DFadType ) \
790#define INTREPID2_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
792TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
794#define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
796TEUCHOS_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.
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.