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);
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:
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>::host_mirror_type
copyFunctorToHostView(
const Functor &deviceFunctor)
402 INTREPID2_TEST_FOR_EXCEPTION(rank !=
getFunctorRank(deviceFunctor), std::invalid_argument,
"functor rank must match the template argument");
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 <<
",";
480 ViewIterator<
decltype(functorHostCopy),Scalar> vi(functorHostCopy);
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::host_mirror_type;
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 <<
"(";
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");
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);
659 FunctorIterator<
decltype(functor1CopyHost),Scalar,rank> vi1(functor1CopyHost);
660 FunctorIterator<
decltype(functor2CopyHost),Scalar,rank> vi2(functor2CopyHost);
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 (";
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
775using Sacado_Fad_DFadType = Sacado::Fad::DFad<double>;
776#define INTREPID2_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
778TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
780TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, Sacado_Fad_DFadType ) \
782#define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
784TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, double, double ) \
786TEUCHOS_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) \
791TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
793#define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
795TEUCHOS_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.