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"
71#if defined(KOKKOS_ENABLE_CUDA)
73#elif defined(KOKKOS_ENABLE_HIP)
74 using DefaultTestDeviceType = Kokkos::Device<Kokkos::Experimental::HIP,Kokkos::Experimental::HIPSpace>;
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)
183 else if (cellTopo.getBaseKey() == shards::Quadrilateral<>::key)
185 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
188 else if (cellTopo.getBaseKey() == shards::Triangle<>::key)
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");
198 else if (cellTopo.getBaseKey() == shards::Tetrahedron<>::key)
202 else if (cellTopo.getBaseKey() == shards::Wedge<>::key)
204 INTREPID2_TEST_FOR_EXCEPTION(polyOrder_y < 0, std::invalid_argument,
"polyOrder_y must be specified");
207 else if (cellTopo.getBaseKey() == shards::Pyramid<>::key)
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)
223 using Scalar = double;
224 using namespace Intrepid2;
226 using LineBasisGrad = Intrepid2::IntegratedLegendreBasis_HGRAD_LINE<DeviceType, Scalar, Scalar, defineVertexFunctions, true>;
227 using LineBasisVol = Intrepid2::LegendreBasis_HVOL_LINE< DeviceType, Scalar, Scalar>;
228 using TriangleBasisFamily = Intrepid2::HierarchicalTriangleBasisFamily<DeviceType, Scalar, Scalar, defineVertexFunctions>;
229 using TetrahedronBasisFamily = Intrepid2::HierarchicalTetrahedronBasisFamily<DeviceType, Scalar, Scalar, defineVertexFunctions>;
230 using PyramidBasisFamily = Intrepid2::HierarchicalPyramidBasisFamily<DeviceType, Scalar, Scalar, defineVertexFunctions>;
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...);
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...);
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:
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:
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>
436 INTREPID2_TEST_FOR_EXCEPTION(rank !=
getFunctorRank(deviceFunctor), std::invalid_argument,
"functor rank must match the template argument");
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 =
"")
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 <<
",";
514 ViewIterator<
decltype(functorHostCopy),Scalar> vi(functorHostCopy);
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;
592 using HostViewIteratorScalar = Intrepid2::ViewIterator<HostView, Scalar>;
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 <<
"(";
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>
620 typename std::enable_if< !(supports_rank<FunctorType1,rank>::value && supports_rank<FunctorType2,rank>::value),
void >::type
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>
629 typename std::enable_if< (supports_rank<FunctorType1,rank>::value && supports_rank<FunctorType2,rank>::value),
void >::type
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")
633 static_assert( supports_rank<FunctorType1,rank>::value,
"Functor1 must support the specified rank through operator().");
634 static_assert( supports_rank<FunctorType2,rank>::value,
"Functor2 must support the specified rank through operator().");
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");
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;
691 auto valuesMatchHost = getHostCopy(valuesMatch);
693 FunctorIterator<
decltype(functor1CopyHost),Scalar,rank> vi1(functor1CopyHost);
694 FunctorIterator<
decltype(functor2CopyHost),Scalar,rank> vi2(functor2CopyHost);
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 (";
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
809using Sacado_Fad_DFadType = Sacado::Fad::DFad<double>;
810#define INTREPID2_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
812TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
814TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, Sacado_Fad_DFadType ) \
816#define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
818TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, double, double ) \
820TEUCHOS_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) \
825TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( GROUP_NAME, TEST_NAME, double ) \
827#define INTREPID2_OUTPUTSCALAR_POINTSCALAR_TEST_INSTANT(GROUP_NAME, TEST_NAME) \
829TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( GROUP_NAME, TEST_NAME, double, double ) \
Header file for the abstract base class Intrepid2::Basis.
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.
Teuchos::RCP< Basis< DeviceType, OutputType, PointType > > BasisPtr
Basis Pointer.
Stateless class representing a family of basis functions, templated on H(vol) and H(grad) on the line...
static BasisFamily::BasisPtr getWedgeBasis(Intrepid2::EFunctionSpace fs, int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Factory method for isotropic wedge bases in the given family.
static BasisFamily::BasisPtr getHexahedronBasis(Intrepid2::EFunctionSpace fs, int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Factory method for isotropic bases on the hexahedron in the given family.
static BasisFamily::BasisPtr getQuadrilateralBasis(Intrepid2::EFunctionSpace fs, int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Factory method for isotropic quadrilateral bases in the given family.
static BasisFamily::BasisPtr getTetrahedronBasis(Intrepid2::EFunctionSpace fs, int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Factory method for isotropic tetrahedron bases in the given family.
static BasisFamily::BasisPtr getTriangleBasis(Intrepid2::EFunctionSpace fs, int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Factory method for isotropic triangle bases in the given family.
static BasisFamily::BasisPtr getPyramidBasis(Intrepid2::EFunctionSpace fs, ordinal_type polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Factory method for pyramid bases in the given family.
static BasisFamily::BasisPtr getLineBasis(Intrepid2::EFunctionSpace fs, int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Factory method for line bases in the given family.
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< Scalar, DefaultTestDeviceType >::HostMirror copyFunctorToHostView(const Functor &deviceFunctor)
Copy the values for the specified functor.
typename Kokkos::DefaultExecutionSpace::device_type DefaultTestDeviceType
Default Kokkos::Device to use for tests; depends on platform.
ViewType< PointValueType, DeviceType > getInputPointsView(shards::CellTopology &cellTopo, int numPoints_1D)
Returns a DynRankView containing regularly-spaced points on the specified cell topology.
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...
A helper class that allows iteration over some part of a Kokkos View, while allowing the calling code...
Helper to get Scalar[*+] where the number of *'s matches the given rank.