SpECTRE  v2024.09.29
Testing Framework

Classes, functions, macros, and instructions for developing tests. More...

Namespaces

namespace  ActionTesting
 Structures used for mocking the parallel components framework in order to test actions.
 
namespace  pypp
 Contains all functions for calling python from C++.
 
namespace  TestHelpers
 Collection of classes and functions useful for testing.
 
namespace  TestHelpers::domain::BoundaryConditions
 Helpers for boundary conditions.
 
namespace  TestHelpers::elliptic
 Helper functions to test elliptic first-order systems.
 
namespace  TestHelpers::AnalyticData
 Functions for testing analytic data.
 
namespace  TestHelpers::VerifyGrSolution
 Functions for testing GR analytic solutions.
 
namespace  TestHelpers::AnalyticSolutions
 Functions for testing analytic solutions.
 
namespace  TestHelpers::gr
 Make random GR variables which correct physical behavior, e.g. spatial metric will be positive definite.
 
namespace  TestHelpers::hydro
 Make random hydro variables which correct physical behavior, e.g. Lorentz factor will be greater or equal than one.
 

Classes

class  ActionTesting::MockRuntimeSystem< Metavariables >
 A class that mocks the infrastructure needed to run actions. It simulates message passing using the inbox infrastructure and handles most of the arguments to the apply method. This mocks the Charm++ runtime system as well as the layer built on top of it as part of SpECTRE. More...
 
class  UniformCustomDistribution< T >
 A uniform distribution function object which redirects appropriately to either the std::uniform_int_distribution or the std::uniform_real_distribution. This also provides a convenience constructor which takes a 2-element array for the bounds for either floating point or int distributions. More...
 
class  OrientationMapIterator< VolumeDim >
 An iterator for looping through all possible orientations of the n-dim cube. More...
 

Macros

#define INVOKE_TEST_FUNCTION(FUNCTION_NAME, TUPLE_ARGS, ...)
 Macro used to invoke a test function of multiple template arguments. More...
 
#define CHECK_FOR_DOUBLES_AND_DATAVECTORS(FUNCTION_NAME, ...)
 Macro used to test functions whose parameter can be a double or a DataVector. More...
 
#define CHECK_OP(a, op, b, c)
 Check a op b == c and also the op= version. More...
 
#define MAKE_GENERATOR(...)
 MAKE_GENERATOR(NAME [, SEED]) declares a variable of name NAME containing a generator of type std::mt19937. More...
 
#define CHECK_VARIABLES_APPROX(a, b)
 A wrapper around Catch's CHECK macro that checks approximate equality of each entry in each tag within a variables. More...
 
#define CHECK_VARIABLES_CUSTOM_APPROX(a, b, appx)
 Same as CHECK_VARIABLES_APPROX, but with a user-defined Approx. The third argument should be of type Approx. More...
 
#define SPECTRE_PARALLEL_REQUIRE(expr)
 A similar to Catch's REQUIRE statement, but can be used in tests that spawn several chares with possibly complex interaction between the chares. More...
 
#define SPECTRE_PARALLEL_REQUIRE_FALSE(expr)
 A similar to Catch's REQUIRE_FALSE statement, but can be used in tests that spawn several chares with possibly complex interaction between the chares. More...
 
#define CHECK_ITERABLE_APPROX(a, b)
 A wrapper around Catch's CHECK macro that checks approximate equality of entries in iterable containers. For maplike containers, keys are checked for strict equality and values are checked for approximate equality. More...
 
#define CHECK_ITERABLE_CUSTOM_APPROX(a, b, appx)
 Same as CHECK_ITERABLE_APPROX with user-defined Approx. The third argument should be of type Approx. More...
 
#define OUTPUT_TEST()
 Mark a test as checking the output with a regular expression. More...
 

Typedefs

using TestHelpers::VectorImpl::Bound = std::array< double, 2 >
 Type alias to be more expressive with distribution bounds in vector tests which call the generic math test below.
 

Enumerations

enum  TestHelpers::VectorImpl::TestKind { Normal , Strict , Inplace , GivenOrderOfArgumentsOnly }
 the set of test types that may be used for the math operations More...
 

Functions

template<typename T , typename Metavariables = NoSuchType>
TestHelpers::test_creation (const std::string &construction_string)
 Creates an instance of a given option-creatable type. More...
 
template<typename OptionTag , typename Metavariables = NoSuchType>
OptionTag::type TestHelpers::test_option_tag (const std::string &construction_string)
 Runs the option parser on a given tag. More...
 
template<typename BaseClass , typename DerivedClass >
std::unique_ptr< BaseClass > TestHelpers::test_factory_creation (const std::string &construction_string)
 Creates a class of a known derived type using a factory. More...
 
template<typename OptionTag , typename DerivedClass >
OptionTag::type TestHelpers::test_option_tag_factory_creation (const std::string &construction_string)
 A wrapper that allows testing an option tag without having to write a Metavariables class. Combines TestHelpers::test_factory_creation() and TestHelpers::test_option_tag(). More...
 
template<typename T >
serialize_and_deserialize (const T &t)
 Serializes and deserializes an object t of type T
 
template<typename T >
void serialize_and_deserialize (const gsl::not_null< T * > result, const T &t)
 Serializes and deserializes an object t of type T
 
template<typename T >
void test_serialization (const T &t)
 Tests the serialization of comparable types. More...
 
template<typename B , typename D , typename... Args>
void test_serialization_via_base (Args &&... args)
 Test the serialization of a derived class via a base class pointer. More...
 
template<typename T , typename U >
void check_cmp (const T &less, const U &greater)
 Function to test comparison operators. Pass values with less < greater.
 
template<typename Invocable , size_t VolumeDim>
std::invoke_result_t< const Invocable &, const std::array< double, VolumeDim > & > numerical_derivative (const Invocable &function, const std::array< double, VolumeDim > &x, const size_t direction, const double delta)
 Calculates the derivative of an Invocable at a point x - represented by an array of doubles - in the domain of map with a sixth-order finite difference method. More...
 
template<typename Exception , typename ThrowingFunctor >
void test_throw_exception (const ThrowingFunctor &func, const Exception &expected)
 Execute func and check that it throws an exception expected. More...
 
template<size_t NumSamples, typename Container , typename ValueType = typename Container::value_type>
std::array< ValueType, NumSamples > random_sample (const Container &container, const gsl::not_null< std::mt19937 * > generator)
 NumSamples unique random elements of the container More...
 
template<typename Container , typename ValueType = typename Container::value_type>
std::vector< ValueType > random_sample (const size_t number_of_samples, const Container &container, const gsl::not_null< std::mt19937 * > generator)
 Creates a new std::vector holding number_of_samples unique random elements of the container More...
 
template<typename DataType , size_t Dim, UpLo Ul, typename Fr = Frame::Inertial, Requires<(Ul==UpLo::Up)> = nullptr>
tnsr::I< DataType, Dim, Fr > make_random_vector_in_magnitude_range (const gsl::not_null< std::mt19937 * > nn_generator, const tnsr::ii< DataType, Dim, Fr > &metric, const double min_magnitude, const double max_magnitude)
 Construct a spatial vector in a given magnitude range. More...
 
template<typename DataType , size_t Dim, UpLo Ul, typename Fr = Frame::Inertial, typename T >
Tensor< DataType, Symmetry< 1 >, index_list< SpatialIndex< Dim, Ul, Fr > > > make_random_vector_in_magnitude_range_flat (const gsl::not_null< std::mt19937 * > nn_generator, const T &used_for_size, const double min_magnitude, const double max_magnitude)
 Construct a spatial vector in a given magnitude range. More...
 
template<typename T , typename UniformRandomBitGenerator , typename RandomNumberDistribution >
void fill_with_random_values (const gsl::not_null< T * > data, const gsl::not_null< UniformRandomBitGenerator * > generator, const gsl::not_null< RandomNumberDistribution * > distribution)
 Fill an existing data structure with random values.
 
template<typename T , typename UniformRandomBitGenerator , typename RandomNumberDistribution >
make_with_random_values (const gsl::not_null< UniformRandomBitGenerator * > generator, const gsl::not_null< RandomNumberDistribution * > distribution)
 Make a fixed-size data structure and fill with random values. More...
 
template<typename DataType >
tnsr::I< DataType, 1 > random_unit_normal (gsl::not_null< std::mt19937 * > generator, const tnsr::ii< DataType, 1 > &spatial_metric)
 Make a random unit normal vector at each element of DataType.
 
template<typename DataType >
void TestHelpers::tenex::test_evaluate_rank_0 (const DataType &data)
 Test that evaluating a right hand side tensor expression containing a single rank 0 tensor correctly assigns the data to the evaluated left hand side tensor. More...
 
template<typename DataType , typename TensorIndexTypeList , auto & TensorIndex>
void TestHelpers::tenex::test_evaluate_rank_1_impl ()
 Test that evaluating a right hand side tensor expression containing a single rank 1 tensor correctly assigns the data to the evaluated left hand side tensor. More...
 
template<typename DataType , template< size_t, UpLo, typename > class TensorIndexType, UpLo Valence, auto & TensorIndex>
void TestHelpers::tenex::test_evaluate_rank_1 ()
 Iterate testing of evaluating single rank 1 Tensors on multiple Frame types and dimensions. More...
 
template<typename DataType , typename RhsSymmetry , typename RhsTensorIndexTypeList , auto & TensorIndexA, auto & TensorIndexB>
void TestHelpers::tenex::test_evaluate_rank_2_impl ()
 Test that evaluating a right hand side tensor expression containing a single rank 2 tensor correctly assigns the data to the evaluated left hand side tensor. More...
 
template<typename DataType , template< size_t, UpLo, typename > class TensorIndexTypeA, template< size_t, UpLo, typename > class TensorIndexTypeB, UpLo ValenceA, UpLo ValenceB, auto & TensorIndexA, auto & TensorIndexB>
void TestHelpers::tenex::test_evaluate_rank_2_no_symmetry ()
 Iterate testing of evaluating single rank 2 Tensors on multiple Frame types and dimension combinations. More...
 
template<typename DataType , template< size_t, UpLo, typename > class TensorIndexType, UpLo Valence, auto & TensorIndexA, auto & TensorIndexB>
void TestHelpers::tenex::test_evaluate_rank_2_symmetric ()
 
template<typename DataType , typename RhsSymmetry , typename RhsTensorIndexTypeList , auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_impl ()
 Test that evaluating a right hand side tensor expression containing a single rank 3 tensor correctly assigns the data to the evaluated left hand side tensor. More...
 
template<typename DataType , template< size_t, UpLo, typename > class TensorIndexTypeA, template< size_t, UpLo, typename > class TensorIndexTypeB, template< size_t, UpLo, typename > class TensorIndexTypeC, UpLo ValenceA, UpLo ValenceB, UpLo ValenceC, auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_no_symmetry ()
 Iterate testing of evaluating single rank 3 Tensors on multiple Frame types and dimension combinations. More...
 
template<typename DataType , template< size_t, UpLo, typename > class TensorIndexTypeAB, template< size_t, UpLo, typename > class TensorIndexTypeC, UpLo ValenceAB, UpLo ValenceC, auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_ab_symmetry ()
 
template<typename DataType , template< size_t, UpLo, typename > class TensorIndexTypeAC, template< size_t, UpLo, typename > class TensorIndexTypeB, UpLo ValenceAC, UpLo ValenceB, auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_ac_symmetry ()
 
template<typename DataType , template< size_t, UpLo, typename > class TensorIndexTypeA, template< size_t, UpLo, typename > class TensorIndexTypeBC, UpLo ValenceA, UpLo ValenceBC, auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_bc_symmetry ()
 
template<typename DataType , template< size_t, UpLo, typename > class TensorIndexType, UpLo Valence, auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_abc_symmetry ()
 
template<typename DataType , typename RhsSymmetry , typename RhsTensorIndexTypeList , auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC, auto & TensorIndexD>
void TestHelpers::tenex::test_evaluate_rank_4 ()
 Test that evaluating a right hand side tensor expression containing a single rank 4 tensor correctly assigns the data to the evaluated left hand side tensor. More...
 
void TestHelpers::tenex::test_tensor_index_transformation_rank_0 ()
 Test that the transformation between two rank 0 tensors' generic indices and the subsequent transformed multi-index is correctly computed. More...
 
template<typename TensorIndex >
void TestHelpers::tenex::test_tensor_index_transformation_rank_1 (const TensorIndex &)
 Test that the transformation between two rank 1 tensors' generic indices and the subsequent transformed multi-indices are correctly computed. More...
 
template<typename TensorIndexA , typename TensorIndexB >
void TestHelpers::tenex::test_tensor_index_transformation_rank_2 (const TensorIndexA &, const TensorIndexB &)
 Test that the transformation between two rank 2 tensors' generic indices and the subsequent transformed multi-indices are correctly computed. More...
 
template<typename TensorIndexA , typename TensorIndexB , typename TensorIndexC >
void TestHelpers::tenex::test_tensor_index_transformation_rank_3 (const TensorIndexA &, const TensorIndexB &, const TensorIndexC &)
 Test that the transformation between two rank 3 tensors' generic indices and the subsequent transformed multi-indices are correctly computed. More...
 
template<typename TensorIndexA , typename TensorIndexB , typename TensorIndexC , typename TensorIndexD >
void TestHelpers::tenex::test_tensor_index_transformation_rank_4 (const TensorIndexA &, const TensorIndexB &, const TensorIndexC &, const TensorIndexD &)
 Test that the transformation between two rank 4 tensors' generic indices and the subsequent transformed multi-indices are correctly computed. More...
 
void TestHelpers::tenex::test_tensor_index_transformation_with_time_indices ()
 Test that the transformation between two tensors generic indices and the subsequent transformed multi-indices are correctly computed when time indices are used with at least one of the tensors. More...
 
template<typename VectorType , typename ValueType >
void TestHelpers::VectorImpl::vector_test_construct_and_assign (tt::get_fundamental_type_t< ValueType > low=tt::get_fundamental_type_t< ValueType >{-100.0}, tt::get_fundamental_type_t< ValueType > high=tt::get_fundamental_type_t< ValueType >{100.0})
 test construction and assignment of a VectorType with a ValueType
 
template<typename VectorType , typename ValueType >
void TestHelpers::VectorImpl::vector_test_serialize (tt::get_fundamental_type_t< ValueType > low=tt::get_fundamental_type_t< ValueType >{-100.0}, tt::get_fundamental_type_t< ValueType > high=tt::get_fundamental_type_t< ValueType >{100.0})
 test the serialization of a VectorType constructed with a ValueType
 
template<typename VectorType , typename ValueType >
void TestHelpers::VectorImpl::vector_test_ref (tt::get_fundamental_type_t< ValueType > low=tt::get_fundamental_type_t< ValueType >{-100.0}, tt::get_fundamental_type_t< ValueType > high=tt::get_fundamental_type_t< ValueType >{100.0})
 test the construction and move of a reference VectorType constructed with a ValueType
 
template<typename VectorType , typename ValueType = typename VectorType::ElementType>
void TestHelpers::VectorImpl::vector_ref_test_size_error (RefSizeErrorTestKind test_kind, tt::get_fundamental_type_t< ValueType > low=tt::get_fundamental_type_t< ValueType >{-100.0}, tt::get_fundamental_type_t< ValueType > high=tt::get_fundamental_type_t< ValueType >{100.0})
 Test that assigning to a non-owning VectorType of the wrong size appropriately generates an error. More...
 
template<typename VectorType , typename ValueType >
void TestHelpers::VectorImpl::vector_test_math_after_move (tt::get_fundamental_type_t< ValueType > low=tt::get_fundamental_type_t< ValueType >{-100.0}, tt::get_fundamental_type_t< ValueType > high=tt::get_fundamental_type_t< ValueType >{100.0})
 tests a small sample of math functions after a move of a VectorType initialized with ValueType
 
template<TestKind Test, typename VectorType0 , typename... VectorTypes, typename... FunctionsAndArgumentBounds>
void TestHelpers::VectorImpl::test_functions_with_vector_arguments (const std::tuple< FunctionsAndArgumentBounds... > &tuple_of_functions_and_argument_bounds)
 General entry function for testing arbitrary math functions on vector types. More...
 
template<typename Map , typename SourceFrame , typename TargetFrame >
bool are_maps_equal (const Map &map, const domain::CoordinateMapBase< SourceFrame, TargetFrame, Map::dim > &map_base)
 Given a Map and a CoordinateMapBase, checks that the maps are equal by downcasting map_base and then comparing to map. Returns false if the downcast fails.
 
template<typename SourceFrame , typename TargetFrame , size_t VolumeDim>
void check_if_maps_are_equal (const domain::CoordinateMapBase< SourceFrame, TargetFrame, VolumeDim > &map_one, const domain::CoordinateMapBase< SourceFrame, TargetFrame, VolumeDim > &map_two, const double time=std::numeric_limits< double >::quiet_NaN(), const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time={}, Approx custom_approx=approx)
 Given two coordinate maps (but not their types), check that the maps are equal by evaluating them at a random set of points.
 
template<typename Map >
void check_if_map_is_identity (const Map &map)
 Given a coordinate map, check that this map is equal to the identity by evaluating the map at a random set of points.
 
template<typename Map , typename T >
void test_frame_velocity (const Map &map, const std::array< T, Map::dim > &test_point, const double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time, Approx local_approx=Approx::custom().epsilon(1e-10).scale(1.0))
 Given a Map map, checks that the frame velocity matches a sixth-order finite difference approximation.
 
template<typename Map , typename... Args>
void test_coordinate_map_implementation (const Map &map)
 Checks that the CoordinateMap map functions as expected when used as the template parameter to the CoordinateMap type.
 
template<typename Map , typename... Args>
void test_coordinate_map_argument_types (const Map &map, const std::array< double, Map::dim > &test_point, const Args &... args)
 Checks that the CoordinateMap map functions as expected when used with different argument types.
 
template<typename Map >
void test_suite_for_map_on_unit_cube (const Map &map)
 Given a Map map, tests the map functions, including map inverse, jacobian, and inverse jacobian, for a series of points. These points are chosen in a dim-dimensonal cube of side 2 centered at the origin. The map is expected to be valid on the boundaries of the cube.
 
template<typename Map >
void test_suite_for_map_on_sphere (const Map &map, const bool include_origin=true, const double radius_of_sphere=1.0)
 Given a Map map, tests the map functions, including map inverse, jacobian, and inverse jacobian, for a series of points. These points are chosen in a sphere of radius radius_of_sphere, and the map is expected to be valid on the boundary of that sphere as well as in its interior. The flag include_origin indicates whether to test the map at the origin. This test works only in 3 dimensions.
 
template<typename Map >
void test_suite_for_map_on_cylinder (const Map &map, const double inner_radius, const double outer_radius, const bool test_random_z_bdry_roundoff=false, const bool test_random_rho_bdry_roundoff=false)
 Given a Map map, tests the map functions, including map inverse, jacobian, and inverse jacobian, for a series of points. These points are chosen in a right cylinder with cylindrical radius 1 and z-axis extending from -1 to +1. The map is expected to be valid on the boundary of that cylinder as well as in its interior. This test works only in 3 dimensions.
 
std::array< OrientationMap< 3 >, 6 > all_wedge_directions ()
 Wedge OrientationMap in each of the six directions used in the Sphere domain creator.
 
template<typename System , typename BoundaryCorrection , size_t FaceDim, typename... VolumeTags, typename... RangeTags>
void TestHelpers::evolution::dg::test_boundary_correction_conservation (const gsl::not_null< std::mt19937 * > generator, const BoundaryCorrection &correction, const Mesh< FaceDim > &face_mesh, const tuples::TaggedTuple< VolumeTags... > &volume_data, const tuples::TaggedTuple< Tags::Range< RangeTags >... > &ranges, const ZeroOnSmoothSolution zero_on_smooth_solution=ZeroOnSmoothSolution::Yes, const double eps=1.0e-12)
 Checks that the boundary correction is conservative and that for smooth solutions the strong-form correction is zero. More...
 
template<typename System , typename ConversionClassList = tmpl::list<>, typename BoundaryCorrection , size_t FaceDim, typename... VolumeTags, typename... RangeTags>
void TestHelpers::evolution::dg::test_boundary_correction_with_python (const gsl::not_null< std::mt19937 * > generator, const std::string &python_module, const std::string &python_dg_package_data_function, const std::string &python_dg_boundary_terms_function, const BoundaryCorrection &correction, const Mesh< FaceDim > &face_mesh, const tuples::TaggedTuple< VolumeTags... > &volume_data, const tuples::TaggedTuple< Tags::Range< RangeTags >... > &ranges, const double epsilon=1.0e-12)
 Tests that the dg_package_data and dg_boundary_terms functions agree with the python implementation. More...
 
template<typename System , typename SolutionType , size_t Dim = System::volume_dim, typename... Maps, typename PackageFluxesArgs >
void FirstOrderEllipticSolutionsTestHelpers::verify_smooth_solution (const SolutionType &solution, const domain::CoordinateMap< Frame::ElementLogical, Frame::Inertial, Maps... > &coord_map, const double tolerance_offset, const double tolerance_scaling, PackageFluxesArgs &&package_fluxes_args)
 
template<typename System , typename SolutionType , size_t Dim = System::volume_dim, typename... Maps>
void FirstOrderEllipticSolutionsTestHelpers::verify_solution_with_power_law_convergence (const SolutionType &solution, const domain::CoordinateMap< Frame::ElementLogical, Frame::Inertial, Maps... > &coord_map, const double tolerance_offset, const double tolerance_pow)
 
template<typename Solution >
void verify_grmhd_solution (const Solution &solution, const Block< 3 > &block, const Mesh< 3 > &mesh, const double error_tolerance, const double time, const double delta_time)
 Determines if the given solution is a solution of the GRMHD equations. More...
 
template<typename DataType , size_t SpatialDim, typename Frame >
tnsr::ii< DataType, SpatialDim, Frame > TestHelpers::Schwarzschild::spatial_ricci (const tnsr::I< DataType, SpatialDim, Frame > &x, double mass)
 Schwarzschild (Kerr-Schild) spatial ricci tensor. More...
 
template<typename DataType , size_t SpatialDim, typename Frame >
tnsr::ii< DataType, SpatialDim, Frame > TestHelpers::Minkowski::extrinsic_curvature_sphere (const tnsr::I< DataType, SpatialDim, Frame > &x)
 Extrinsic curvature of 2D sphere in 3D flat space. More...
 
template<typename DataType >
Scalar< DataType > TestHelpers::Kerr::horizon_ricci_scalar (const Scalar< DataType > &horizon_radius, double mass, double dimensionless_spin_z)
 Kerr (Kerr-Schild) horizon ricci scalar (spin on z axis) More...
 
template<typename DataType >
Scalar< DataType > TestHelpers::Kerr::horizon_ricci_scalar (const Scalar< DataType > &horizon_radius_with_spin_on_z_axis, const ylm::Spherepack &ylm_with_spin_on_z_axis, const ylm::Spherepack &ylm, double mass, const std::array< double, 3 > &dimensionless_spin)
 Kerr (Kerr-Schild) horizon ricci scalar (generic spin) More...
 
template<typename ReturnType , typename T , typename UniformRandomBitGenerator , typename RandomNumberDistribution >
ReturnType make_with_random_values (const gsl::not_null< UniformRandomBitGenerator * > generator, const gsl::not_null< RandomNumberDistribution * > distribution, const T &used_for_size)
 Make a data structure and fill it with random values. More...
 
template<typename ReturnType , typename T , typename UniformRandomBitGenerator , typename RandomNumberDistribution >
ReturnType make_with_random_values (const gsl::not_null< UniformRandomBitGenerator * > generator, RandomNumberDistribution distribution, const T &used_for_size)
 Make a data structure and fill it with random values. More...
 
template<typename Map >
void test_jacobian (const Map &map, const std::array< double, Map::dim > &test_point)
 Given a Map map, checks that the jacobian gives expected results when compared to the numerical derivative in each direction.
 
template<typename Map >
void test_jacobian (const Map &map, const std::array< double, Map::dim > &test_point, const double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time, Approx local_approx=Approx::custom().epsilon(1e-10).scale(1.0))
 Given a Map map, checks that the jacobian gives expected results when compared to the numerical derivative in each direction.
 
template<typename Map >
void test_jacobian (const Map &map, const std::array< DataVector, Map::dim > &test_point)
 Given a Map map, checks that the jacobian gives expected results when compared to the numerical derivative in each direction.
 
template<typename Map >
void test_jacobian (const Map &map, const std::array< DataVector, Map::dim > &test_point, const double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time, Approx local_approx=Approx::custom().epsilon(1e-10).scale(1.0))
 Given a Map map, checks that the jacobian gives expected results when compared to the numerical derivative in each direction.
 
template<typename Map >
void test_inv_jacobian (const Map &map, const std::array< double, Map::dim > &test_point)
 Given a Map map, checks that the inverse jacobian and jacobian multiply together to produce the identity matrix.
 
template<typename Map >
void test_inv_jacobian (const Map &map, const std::array< double, Map::dim > &test_point, const double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time)
 Given a Map map, checks that the inverse jacobian and jacobian multiply together to produce the identity matrix.
 
template<typename Map >
void test_inv_jacobian (const Map &map, const std::array< DataVector, Map::dim > &test_point)
 Given a Map map, checks that the inverse jacobian and jacobian multiply together to produce the identity matrix.
 
template<typename Map >
void test_inv_jacobian (const Map &map, const std::array< DataVector, Map::dim > &test_point, const double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time)
 Given a Map map, checks that the inverse jacobian and jacobian multiply together to produce the identity matrix.
 
template<typename Map , typename T >
void test_inverse_map (const Map &map, const std::array< T, Map::dim > &test_point)
 Given a Map map, checks that the inverse map gives expected results.
 
template<typename Map , typename T >
void test_inverse_map (const Map &map, const std::array< T, Map::dim > &test_point, const double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time)
 Given a Map map, checks that the inverse map gives expected results.
 
template<class DampingFunctionType , class T , class... MemberArgs>
void TestHelpers::gh::ConstraintDamping::check (std::unique_ptr< DampingFunctionType > in_gh_damping_function, const std::string &python_function_prefix, const T &used_for_size, const std::array< std::pair< double, double >, 1 > &random_value_bounds, const std::vector< std::string > &function_of_time_names, const MemberArgs &... member_args)
 Test a DampingFunction by comparing to python functions. More...
 
template<class DampingFunctionType , class T , class... MemberArgs>
void TestHelpers::gh::ConstraintDamping::check (DampingFunctionType in_gh_damping_function, const std::string &python_function_prefix, const T &used_for_size, const std::array< std::pair< double, double >, 1 > &random_value_bounds, const std::vector< std::string > &function_of_time_names, const MemberArgs &... member_args)
 Test a DampingFunction by comparing to python functions. More...
 
template<typename System , typename SolutionType , typename... Maps, typename... FluxesArgs, typename... SourcesArgs>
void FirstOrderEllipticSolutionsTestHelpers::verify_solution (const SolutionType &solution, const Mesh< System::volume_dim > &mesh, const domain::CoordinateMap< Frame::ElementLogical, Frame::Inertial, Maps... > coord_map, const double tolerance, const std::tuple< FluxesArgs... > &fluxes_args, const std::tuple< SourcesArgs... > &sources_args=std::tuple<>{})
 Test that the solution numerically solves the System on the given grid for the given tolerance.
 
template<typename System , typename SolutionType , typename... Maps>
void FirstOrderEllipticSolutionsTestHelpers::verify_solution (const SolutionType &solution, const Mesh< System::volume_dim > &mesh, const domain::CoordinateMap< Frame::ElementLogical, Frame::Inertial, Maps... > coord_map, const double tolerance)
 Test that the solution numerically solves the System on the given grid for the given tolerance.
 
template<class EosType , class T , class... MemberArgs>
void TestHelpers::EquationsOfState::check (std::unique_ptr< EosType > in_eos, const std::string &python_file_name, const std::string &python_function_prefix, const T &used_for_size, const MemberArgs &... member_args)
 Test an equation of state by comparing to python functions. More...
 
template<class EosType , class T , class... MemberArgs>
void TestHelpers::EquationsOfState::check (EosType in_eos, const std::string &python_file_name, const std::string &python_function_prefix, const T &used_for_size, const MemberArgs &... member_args)
 Test an equation of state by comparing to python functions. More...
 
template<class MathFunctionType , class T , class... MemberArgs>
void TestHelpers::MathFunctions::check (std::unique_ptr< MathFunctionType > in_math_function, const std::string &python_function_prefix, const T &used_for_size, const std::array< std::pair< double, double >, 1 > random_value_bounds, const MemberArgs &... member_args)
 Test a MathFunction by comparing to python functions. More...
 
template<class MathFunctionType , class T , class... MemberArgs>
void TestHelpers::MathFunctions::check (MathFunctionType in_math_function, const std::string &python_function_prefix, const T &used_for_size, const std::array< std::pair< double, double >, 1 > random_value_bounds, const MemberArgs &... member_args)
 Test a MathFunction by comparing to python functions. More...
 

Detailed Description

Classes, functions, macros, and instructions for developing tests.

Details

SpECTRE uses the testing framework Catch. Catch supports a variety of different styles of tests including BDD and fixture tests. The file cmake/SpectreAddCatchTests.cmake parses the source files and adds the found tests to ctest with the correct properties specified by tags and attributes.

Usage

To run the tests, type ctest in the build directory. You can specify a regex to match the test name using ctest -R Unit.Blah, or run all tests with a certain tag using ctest -L tag.

Comparing double-precision results

To compare two floating-point numbers that may differ by round-off, use the helper object approx. This is an instance of Catch's comparison class Approx in which the relative tolerance for comparisons is set to roughly \(10^{-14}\) (i.e. std::numeric_limits<double>::epsilon()*100). When possible, we recommend using approx for fuzzy comparisons as follows:

Example

CHECK(sin(M_PI / 4.0) == approx(cos(M_PI / 4.0)));
T cos(T... args)
T sin(T... args)

For checks that need more control over the precision (e.g. an algorithm in which round-off errors accumulate to a higher level), we recommend using the approx helper with a one-time tolerance adjustment. A comment should explain the reason for the adjustment:

Example

// This check needs tolerance 1e-12 for X reason.
CHECK(1.0 == approx(1.0 + 5e-13).epsilon(1e-12));

For tests in which the same precision adjustment is re-used many times, a new helper object can be created from Catch's Approx with a custom precision:

Example

// The checks in this test need tolerance 1e-12 for X reason.
Approx my_approx = Approx::custom().epsilon(1e-12);
CHECK(1.0 == my_approx(1.0 + 5e-13));
CHECK(1.0 != my_approx(1.0 + 5e-12));

Note: We provide the approx object because Catch's Approx defaults to a very loose tolerance (std::numeric_limits<float>::epsilon()*100, or roughly \(10^{-5}\) relative error), and so is poorly-suited to checking many numerical algorithms that rely on double-precision accuracy. By providing a tighter tolerance with approx, we avoid having to redefine the tolerance in every test.

Attributes

Attributes allow you to modify properties of the test. Attributes are specified as follows:

// [[TimeOut, 10]]
// [[OutputRegex, The error message expected from the test]]
SPECTRE_TEST_CASE("Unit.Blah", "[Unit]") {

Available attributes are:

Attribute Description
TimeOut override the default timeout and set the timeout to N seconds. This should be set very sparingly since unit tests are designed to be short. If your test is too long you should consider testing smaller portions of the code if possible, or writing an integration test instead.
OutputRegex When testing failure modes the exact error message must be tested, not just that the test failed. Since the string passed is a regular expression you must escape any regex tokens. For example, to match some (word) and you must specify the string some \(word\) and. If your error message contains a newline, you can match it using the dot operator ., which matches any character.

Debugging Tests in GDB or LLDB

Several tests fail intentionally at the executable level to test error handling like ASSERT statements in the code. CTest is aware of which should fail and passes them. If you want to debug an individual test in a debugger you must specify the name of the test as the first argument to the test executable. For example, if you want to debug the "Unit.Gradient" test: Launch the debugger, for example if you're using LLDB then run lldb ./bin/Test_LinearOperators. Then run the test with run Unit.Gradient inside the debugger.

Details

SpECTRE uses the testing framework Catch. Catch supports a variety of different styles of tests including BDD and fixture tests. The file cmake/SpectreAddCatchTests.cmake parses the source files and adds the found tests to ctest with the correct properties specified by tags and attributes.

Usage

To run the tests, type ctest in the build directory. You can specify a regex to match the test name using ctest -R Unit.Blah, or run all tests with a certain tag using ctest -L tag.

Comparing double-precision results

To compare two floating-point numbers that may differ by round-off, use the helper object approx. This is an instance of Catch's comparison class Approx in which the relative tolerance for comparisons is set to roughly \(10^{-14}\) (i.e. std::numeric_limits<double>::epsilon()*100). When possible, we recommend using approx for fuzzy comparisons as follows:

Example

CHECK(sin(M_PI / 4.0) == approx(cos(M_PI / 4.0)));

For checks that need more control over the precision (e.g. an algorithm in which round-off errors accumulate to a higher level), we recommend using the approx helper with a one-time tolerance adjustment. A comment should explain the reason for the adjustment:

Example

// This check needs tolerance 1e-12 for X reason.
CHECK(1.0 == approx(1.0 + 5e-13).epsilon(1e-12));

For tests in which the same precision adjustment is re-used many times, a new helper object can be created from Catch's Approx with a custom precision:

Example

// The checks in this test need tolerance 1e-12 for X reason.
Approx my_approx = Approx::custom().epsilon(1e-12);
CHECK(1.0 == my_approx(1.0 + 5e-13));
CHECK(1.0 != my_approx(1.0 + 5e-12));

Note: We provide the approx object because Catch's Approx defaults to a very loose tolerance (std::numeric_limits<float>::epsilon()*100, or roughly \(10^{-5}\) relative error), and so is poorly-suited to checking many numerical algorithms that rely on double-precision accuracy. By providing a tighter tolerance with approx, we avoid having to redefine the tolerance in every test.

Attributes

Attributes allow you to modify properties of the test. Attributes are specified as follows:

// [[TimeOut, 10]]
// [[OutputRegex, The error message expected from the test]]
SPECTRE_TEST_CASE("Unit.Blah", "[Unit]") {

Available attributes are:

Attribute Description
TimeOut override the default timeout and set the timeout to N seconds. This should be set very sparingly since unit tests are designed to be short. If your test is too long you should consider testing smaller portions of the code if possible, or writing an integration test instead.
OutputRegex When testing failure modes the exact error message must be tested, not just that the test failed. Since the string passed is a regular expression you must escape any regex tokens. For example, to match some (word) and you must specify the string some \(word\) and. If your error message contains a newline, you can match it using the dot operator ., which matches any character.

Debugging Tests in GDB or LLDB

Several tests fail intentionally at the executable level to test error handling like ASSERT statements in the code. CTest is aware of which should fail and passes them. If you want to debug an individual test in a debugger you must specify the name of the test as the first argument to the test executable. For example, if you want to debug the "Unit.Gradient" test: Launch the debugger, for example if you're using LLDB then run lldb ./bin/Test_LinearOperators. Then run the test with run Unit.Gradient inside the debugger.

Macro Definition Documentation

◆ CHECK_FOR_DOUBLES_AND_DATAVECTORS

#define CHECK_FOR_DOUBLES_AND_DATAVECTORS (   FUNCTION_NAME,
  ... 
)
Value:
CHECK_FOR_DOUBLES(FUNCTION_NAME, __VA_ARGS__) \
CHECK_FOR_DATAVECTORS(FUNCTION_NAME, __VA_ARGS__)

Macro used to test functions whose parameter can be a double or a DataVector.

In testing multiple instances of a function template using random values, it often proves useful to write a wrapper around pypp::check_with_random_values. This way, one can easily loop over several values of one or multiple template parameters (e.g. when testing a function templated in the number of spacetime dimensions.) The template parameters of the wrapper will then correspond to the template parameters of the function, which will be used by pypp::check_with_random_values to invoke and test each instance. Each of these wrappers will generally need only one parameter, namely a variable used_for_size passed to pypp::check_with_random_values that can be a double, a DataVector, or both (provided that the function being tested is templated in the type of used_for_size.) Since this is applied in multiple test files, all of these files will share the same way to generate the required calls to the wrapper.

This macro, along with

CHECK_FOR_DOUBLES(FUNCTION_NAME, ...)
CHECK_FOR_DATAVECTORS(FUNCTION_NAME, ...)

allow to generate calls to multiple instances of a test function template in the same way as done by INVOKE_TEST_FUNCTION(FUNCTION_NAME, ARGS_TUPLE, ...) (to which these macros call), except that the tuple of arguments is not passed, as these macros will assume that a double d and/or a DataVector dv will be previously defined. Although any ds and dvs will work, one can (and it is recommended to) generate signaling NaN values for d and dv. This can be done by invoking one of the three provided macros: GENERATE_UNINIATILIZED_DOUBLE, GENERATE_UNINITIALIZED_DATAVECTOR, or GENERATE_UNINITIALIZED_DOUBLE_AND_DATAVECTOR. For example,

GENERATE_UNINITIALIZED_DATAVECTOR;
CHECK_FOR_DATAVECTORS(test_fluxes, (1, 2, 3))

will generate a test case for 1, 2 and 3 dimensions:

const DataVector dv(5);
test_fluxes<1>(dv);
test_fluxes<2>(dv);
test_fluxes<3>(dv);
Stores a collection of function values.
Definition: DataVector.hpp:48

Analogously, the wrapper

template <size_t Dim, IndexType TypeOfIndex, typename DataType>
test_ricci(const DataType& used_for_size) { ... }

can be invoked by writing

GENERATE_UNINITIALIZED_DOUBLE_AND_DATAVECTOR;
CHECK_FOR_DOUBLES_AND_DATAVECTORS(test_ricci, (1, 2, 3),
@ Spatial
The TensorIndexType is purely spatial.
@ Spacetime
The TensorIndexType is a spacetime index.
#define CHECK_FOR_DOUBLES_AND_DATAVECTORS(FUNCTION_NAME,...)
Macro used to test functions whose parameter can be a double or a DataVector.
Definition: CheckWithRandomValues.hpp:928

which will generate

const DataVector dv(5);
test_ricci<1, IndexType::Spatial>(d);
test_ricci<1, IndexType::Spacetime>(d);
test_ricci<2, IndexType::Spatial>(d);
test_ricci<2, IndexType::Spacetime>(d);
test_ricci<3, IndexType::Spatial>(d);
test_ricci<3, IndexType::Spacetime>(d);
test_ricci<1, IndexType::Spatial>(dv);
test_ricci<1, IndexType::Spacetime>(dv);
test_ricci<2, IndexType::Spatial>(dv);
test_ricci<2, IndexType::Spacetime>(dv);
test_ricci<3, IndexType::Spatial>(dv);
test_ricci<3, IndexType::Spacetime>(dv);

Note that it is not necessary to pass values for DataType, as they are deduced from used_for_size.

Note
The order of the macro-tuples of values must match the order of the template parameters of the function.
The function to be called must at least have one template argument, so passing an empty set of template parameters will not work.

◆ CHECK_ITERABLE_APPROX

#define CHECK_ITERABLE_APPROX (   a,
 
)
Value:
do { \
INFO(__FILE__ ":" + std::to_string(__LINE__) + ": " #a " == " #b); \
check_iterable_approx<std::common_type_t< \
std::decay_t<decltype(a)>, std::decay_t<decltype(b)>>>::apply(a, b); \
} while (false)
auto apply(F &&f, const ObservationBox< ComputeTagsList, DataBoxType > &observation_box, Args &&... args)
Apply the function object f using its nested argument_tags list of tags.
Definition: ObservationBox.hpp:238

A wrapper around Catch's CHECK macro that checks approximate equality of entries in iterable containers. For maplike containers, keys are checked for strict equality and values are checked for approximate equality.

◆ CHECK_ITERABLE_CUSTOM_APPROX

#define CHECK_ITERABLE_CUSTOM_APPROX (   a,
  b,
  appx 
)
Value:
do { \
INFO(__FILE__ ":" + std::to_string(__LINE__) + ": " #a " == " #b); \
check_iterable_approx<std::common_type_t< \
std::decay_t<decltype(a)>, std::decay_t<decltype(b)>>>::apply(a, b, \
appx); \
} while (false)

Same as CHECK_ITERABLE_APPROX with user-defined Approx. The third argument should be of type Approx.

◆ CHECK_OP

#define CHECK_OP (   a,
  op,
  b,
 
)
Value:
do { \
const auto& a_ = a; \
const auto& b_ = b; \
const auto& c_ = c; \
CHECK(a_ op b_ == c_); \
auto f = a_; \
CHECK((f op## = b_) == c_); \
CHECK(f == c_); \
} while (false)

Check a op b == c and also the op= version.

◆ CHECK_VARIABLES_APPROX

#define CHECK_VARIABLES_APPROX (   a,
 
)
Value:
do { \
INFO(__FILE__ ":" + std::to_string(__LINE__) + ": " #a " == " #b); \
check_variables_approx<std::common_type_t< \
std::decay_t<decltype(a)>, std::decay_t<decltype(b)>>>::apply(a, b); \
} while (false)

A wrapper around Catch's CHECK macro that checks approximate equality of each entry in each tag within a variables.

◆ CHECK_VARIABLES_CUSTOM_APPROX

#define CHECK_VARIABLES_CUSTOM_APPROX (   a,
  b,
  appx 
)
Value:
do { \
INFO(__FILE__ ":" + std::to_string(__LINE__) + ": " #a " == " #b); \
check_variables_approx<std::common_type_t< \
std::decay_t<decltype(a)>, std::decay_t<decltype(b)>>>::apply(a, b, \
appx); \
} while (false)

Same as CHECK_VARIABLES_APPROX, but with a user-defined Approx. The third argument should be of type Approx.

◆ INVOKE_TEST_FUNCTION

#define INVOKE_TEST_FUNCTION (   FUNCTION_NAME,
  TUPLE_ARGS,
  ... 
)
Value:
BOOST_PP_ASSERT_MSG(BOOST_PP_NOT(BOOST_VMD_IS_EMPTY(__VA_ARGS__)), \
"You cannot pass an empty set of template parameters " \
"to INVOKE_TEST_FUNCTION") \
BOOST_PP_TUPLE_ENUM( \
0, \
BOOST_PP_IF( \
BOOST_PP_EQUAL( \
BOOST_PP_TUPLE_SIZE(BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__)), \
1), \
(BOOST_PP_LIST_FOR_EACH( \
INVOKE_FUNCTION_WITH_SINGLE_TEMPLATE_PARAM, \
(FUNCTION_NAME, TUPLE_ARGS), \
BOOST_PP_TUPLE_TO_LIST( \
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__)))), \
(INVOKE_FUNCTION_WITH_MANY_TEMPLATE_PARAMS( \
BOOST_PP_TUPLE_PUSH_FRONT( \
BOOST_PP_LIST_TO_TUPLE(BOOST_PP_LIST_TRANSFORM( \
INVOKE_FUNCTION_WITH_MANY_TEMPLATE_PARAMS_TUPLE_TO_LIST, \
_, \
BOOST_PP_LIST_REST( \
BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)))), \
BOOST_PP_LIST_TRANSFORM( \
INVOKE_FUNCTION_TUPLE_PUSH_BACK, \
(FUNCTION_NAME, TUPLE_ARGS), \
BOOST_PP_TUPLE_TO_LIST( \
BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__))))))))

Macro used to invoke a test function of multiple template arguments.

This macro allows to generate calls to multiple instances of a test function template, all of which will receive the same parameters. The first argument to this macro is the name of the function. The second argument is a macro-tuple containing the parameters passed to each instance, e.g. (x, y). The remaining arguments are macro-tuples of the values for each template parameter one wants to loop over, e.g. (1, 2, 3), (Frame::Inertial, Frame::Grid). For example, a function template

template <class Arg1, size_t Arg2, class Arg3>
my_function(const double var_1, const int& var_2) { ... }

can be invoked by writing

INVOKE_TEST_FUNCTION(my_function, (d, i), (a, b, c), (1, 2, 3), (A, B, C))
#define INVOKE_TEST_FUNCTION(FUNCTION_NAME, TUPLE_ARGS,...)
Macro used to invoke a test function of multiple template arguments.
Definition: CheckWithRandomValues.hpp:784

which will generate

my_function<a, 1, A>(d, i);
my_function<a, 1, B>(d, i);
my_function<a, 1, C>(d, i);
my_function<a, 2, A>(d, i);
my_function<a, 2, B>(d, i);
my_function<a, 2, C>(d, i);
my_function<a, 3, A>(d, i);
my_function<a, 3, B>(d, i);
my_function<a, 3, C>(d, i);
my_function<b, 1, A>(d, i);
my_function<b, 1, B>(d, i);
my_function<b, 1, C>(d, i);
my_function<b, 2, A>(d, i);
my_function<b, 2, B>(d, i);
my_function<b, 2, C>(d, i);
my_function<b, 3, A>(d, i);
my_function<b, 3, B>(d, i);
my_function<b, 3, C>(d, i);
my_function<c, 1, A>(d, i);
my_function<c, 1, B>(d, i);
my_function<c, 1, C>(d, i);
my_function<c, 2, A>(d, i);
my_function<c, 2, B>(d, i);
my_function<c, 2, C>(d, i);
my_function<c, 3, A>(d, i);
my_function<c, 3, B>(d, i);
my_function<c, 3, C>(d, i);
Note
The order of the macro-tuples of values must match the order of the template parameters of the function.
The function to be called must at least have one template argument, so passing an empty set of template parameters will not work.

◆ MAKE_GENERATOR

#define MAKE_GENERATOR (   ...)
Value:
std::mt19937 MAKE_GENERATOR_IMPL_FIRST_ARG(__VA_ARGS__, DUMMY_TOKEN); \
/* Capture everything because we don't know what passed seed uses */ \
INFO("Seed is: " << [&]() { \
const auto MAKE_GENERATOR_seed = (MAKE_GENERATOR_IMPL_SECOND_ARG( \
__VA_ARGS__, std::random_device{}(), DUMMY_TOKEN)); \
MAKE_GENERATOR_IMPL_FIRST_ARG(__VA_ARGS__, DUMMY_TOKEN) \
.seed(MAKE_GENERATOR_seed); \
return MakeString{} << MAKE_GENERATOR_seed << " from " __FILE__ ":" \
<< __LINE__; \
}());
Make a string by streaming into object.
Definition: MakeString.hpp:18

MAKE_GENERATOR(NAME [, SEED]) declares a variable of name NAME containing a generator of type std::mt19937.

Details

As the generator is made, INFO is called to make sure failed tests provide seed information. SEED is chosen randomly if not supplied, otherwise it must be a constant expression.

◆ OUTPUT_TEST

#define OUTPUT_TEST ( )
Value:
do { \
CHECK(true); \
} while (false)

Mark a test as checking the output with a regular expression.

Details

The OUTPUT_TEST() macro should be the first line in the SPECTRE_TEST_CASE. Catch requires at least one CHECK in each test to pass, so we add one in case nothing but the output is checked.

Example

// [[OutputRegex, -100 3000000000 1.0000000000000000000e\+00 \‍(0,4,8,-7\‍) test 1
// 2 3 abf a o e u Value 2]]
SPECTRE_TEST_CASE("Unit.Parallel.printf", "[Unit][Parallel]") {
// clang-tidy doesn't want c-style arrays, but here we are trying
// to test them explicitly.
const char c_string0[40] = {"test 1 2 3"}; // NOLINT
// clang-tidy doesn't want raw pointers, wants gsl::owner<>.
auto* c_string1 = new char[80]; // NOLINT
// clang-tidy: do not use pointer arithmetic
c_string1[0] = 'a'; // NOLINT
c_string1[1] = 'b'; // NOLINT
c_string1[2] = 'f'; // NOLINT
c_string1[3] = '\0'; // NOLINT
constexpr const char* const c_string2 = {"a o e u"};
Parallel::printf("%d %lld %s %s %s %s %s\n", -100, 3000000000, TestStream{},
c_string0, c_string1, c_string2, TestEnum::Value2);
// clang-tidy doesn't want delete on anything without gsl::owner<>.
delete[] c_string1; // NOLINT
test_fprintf();
}
void printf(const std::string &format, Args &&... args)
Print an atomic message to stdout with C printf usage.
Definition: Printf.hpp:125
#define OUTPUT_TEST()
Mark a test as checking the output with a regular expression.
Definition: TestingFramework.hpp:256

◆ SPECTRE_PARALLEL_REQUIRE

#define SPECTRE_PARALLEL_REQUIRE (   expr)
Value:
do { \
if (not(expr)) { \
ERROR("\nFailed comparison: " << #expr << "\nLine: " << __LINE__ \
<< "\nFile: " << __FILE__ << "\n"); \
} \
} while (false)

A similar to Catch's REQUIRE statement, but can be used in tests that spawn several chares with possibly complex interaction between the chares.

◆ SPECTRE_PARALLEL_REQUIRE_FALSE

#define SPECTRE_PARALLEL_REQUIRE_FALSE (   expr)
Value:
do { \
if ((expr)) { \
ERROR("\nFailed comparison: " << #expr << "\nLine: " << __LINE__ \
<< "\nFile: " << __FILE__ << "\n"); \
} \
} while (false)

A similar to Catch's REQUIRE_FALSE statement, but can be used in tests that spawn several chares with possibly complex interaction between the chares.

Enumeration Type Documentation

◆ TestKind

the set of test types that may be used for the math operations

Details

Three types of test are provided:

  • Normal is used to indicate those tests which should be performed over all combinations of the supplied vector type(s) and their value types. This is useful for e.g. +.
  • Strict is used to indicate those tests which should be performed over only sets of the vector type and compared to the same operation of the set of its value type. This is useful for e.g. atan2, which cannot take a DataVector and a double as arguments.
  • Inplace is used to indicate those tests which should be performed maintaining the type of the left-hand side of the operator and not including it in the combinations. Inplace operators such as += have a more restrictive condition on the type of the left hand side than do simply +. (e.g. double + complex<double> compiles, but double += complex<double> does not)
  • GivenOrderOfArgumentsOnly is used to indicate that the arguments given should not be taken in any combination apart from the given combination. This should be used for highly restrictive operations which are only supported for certain type combinations.

Function Documentation

◆ check() [1/6]

template<class DampingFunctionType , class T , class... MemberArgs>
void TestHelpers::gh::ConstraintDamping::check ( DampingFunctionType  in_gh_damping_function,
const std::string python_function_prefix,
const T &  used_for_size,
const std::array< std::pair< double, double >, 1 > &  random_value_bounds,
const std::vector< std::string > &  function_of_time_names,
const MemberArgs &...  member_args 
)

Test a DampingFunction by comparing to python functions.

The python functions must be added to TestFunctions.py in tests/Unit/Evolution/Systems/GeneralizedHarmonic/ConstraintDamping/Python. Each python function for a corresponding DampingFunction should begin with a prefix python_function_prefix. The prefix for each class of DampingFunction is arbitrary, but should generally be descriptive (e.g. 'gaussian_plus_constant') of the DampingFunction.

The input parameter function_of_time_name is the name of the FunctionOfTime that will be included in the FunctionsOfTime passed to the DampingFunction's call operator. For time-dependent DampingFunctions, this parameter must be consistent with the FunctionOfTime name that the call operator of in_gh_damping_function expects. For time-independent DampingFunctions, function_of_time_name will be ignored.

If a DampingFunction class has member variables set by its constructor, then these member variables must be passed in as the last arguments to the check function`. Each python function must take these same arguments as the trailing arguments.

◆ check() [2/6]

template<class EosType , class T , class... MemberArgs>
void TestHelpers::EquationsOfState::check ( EosType  in_eos,
const std::string python_file_name,
const std::string python_function_prefix,
const T &  used_for_size,
const MemberArgs &...  member_args 
)

Test an equation of state by comparing to python functions.

The python functions must be added to tests/Unit/PointwiseFunctions/Hydro/EquationsOfState/TestFunctions.py. The prefix for each class of equation of state is arbitrary, but should generally be something like "polytropic" for polytropic fluids.

The python_function_prefix argument passed to check must be PREFIX. If an EoS class has member variables (these must be doubles currently) that are used to compute the quantities, such as the polytropic constant and polytropic exponent for a fluid, then they must be passed in as the last arguments to the check function`. Each python function must take these same arguments as the trailing arguments.

◆ check() [3/6]

template<class MathFunctionType , class T , class... MemberArgs>
void TestHelpers::MathFunctions::check ( MathFunctionType  in_math_function,
const std::string python_function_prefix,
const T &  used_for_size,
const std::array< std::pair< double, double >, 1 >  random_value_bounds,
const MemberArgs &...  member_args 
)

Test a MathFunction by comparing to python functions.

The python functions must be added to tests/Unit/PointwiseFunctions/MathFunctions/Python/TestFunctions.py. The prefix for each class of MathFunction is arbitrary, but should generally be descriptive (e.g. 'gaussian', 'sinusoid', 'pow_x') of the MathFunction.

The python_function_prefix argument passed to check must be PREFIX. If a MathFunction class has member variables set by its constructor, then these member variables must be passed in as the last arguments to the check function`. Each python function must take these same arguments as the trailing arguments.

◆ check() [4/6]

template<class DampingFunctionType , class T , class... MemberArgs>
void TestHelpers::gh::ConstraintDamping::check ( std::unique_ptr< DampingFunctionType >  in_gh_damping_function,
const std::string python_function_prefix,
const T &  used_for_size,
const std::array< std::pair< double, double >, 1 > &  random_value_bounds,
const std::vector< std::string > &  function_of_time_names,
const MemberArgs &...  member_args 
)

Test a DampingFunction by comparing to python functions.

The python functions must be added to TestFunctions.py in tests/Unit/Evolution/Systems/GeneralizedHarmonic/ConstraintDamping/Python. Each python function for a corresponding DampingFunction should begin with a prefix python_function_prefix. The prefix for each class of DampingFunction is arbitrary, but should generally be descriptive (e.g. 'gaussian_plus_constant') of the DampingFunction.

The input parameter function_of_time_name is the name of the FunctionOfTime that will be included in the FunctionsOfTime passed to the DampingFunction's call operator. For time-dependent DampingFunctions, this parameter must be consistent with the FunctionOfTime name that the call operator of in_gh_damping_function expects. For time-independent DampingFunctions, function_of_time_name will be ignored.

If a DampingFunction class has member variables set by its constructor, then these member variables must be passed in as the last arguments to the check function`. Each python function must take these same arguments as the trailing arguments.

◆ check() [5/6]

template<class EosType , class T , class... MemberArgs>
void TestHelpers::EquationsOfState::check ( std::unique_ptr< EosType >  in_eos,
const std::string python_file_name,
const std::string python_function_prefix,
const T &  used_for_size,
const MemberArgs &...  member_args 
)

Test an equation of state by comparing to python functions.

The python functions must be added to tests/Unit/PointwiseFunctions/Hydro/EquationsOfState/TestFunctions.py. The prefix for each class of equation of state is arbitrary, but should generally be something like "polytropic" for polytropic fluids.

The python_function_prefix argument passed to check must be PREFIX. If an EoS class has member variables (these must be doubles currently) that are used to compute the quantities, such as the polytropic constant and polytropic exponent for a fluid, then they must be passed in as the last arguments to the check function`. Each python function must take these same arguments as the trailing arguments.

◆ check() [6/6]

template<class MathFunctionType , class T , class... MemberArgs>
void TestHelpers::MathFunctions::check ( std::unique_ptr< MathFunctionType >  in_math_function,
const std::string python_function_prefix,
const T &  used_for_size,
const std::array< std::pair< double, double >, 1 >  random_value_bounds,
const MemberArgs &...  member_args 
)

Test a MathFunction by comparing to python functions.

The python functions must be added to tests/Unit/PointwiseFunctions/MathFunctions/Python/TestFunctions.py. The prefix for each class of MathFunction is arbitrary, but should generally be descriptive (e.g. 'gaussian', 'sinusoid', 'pow_x') of the MathFunction.

The python_function_prefix argument passed to check must be PREFIX. If a MathFunction class has member variables set by its constructor, then these member variables must be passed in as the last arguments to the check function`. Each python function must take these same arguments as the trailing arguments.

◆ extrinsic_curvature_sphere()

template<typename DataType , size_t SpatialDim, typename Frame >
tnsr::ii< DataType, SpatialDim, Frame > TestHelpers::Minkowski::extrinsic_curvature_sphere ( const tnsr::I< DataType, SpatialDim, Frame > &  x)

Extrinsic curvature of 2D sphere in 3D flat space.

Details

Computes \(K_{ij} = \frac{1}{r}\left(\delta_{ij} - \frac{x_i x_j}{r}\right),\) where \(r = x_i x_j \delta^{ij}\) and \(x_i\) is the position vector in Cartesian coordinates.

◆ horizon_ricci_scalar() [1/2]

template<typename DataType >
Scalar< DataType > TestHelpers::Kerr::horizon_ricci_scalar ( const Scalar< DataType > &  horizon_radius,
double  mass,
double  dimensionless_spin_z 
)

Kerr (Kerr-Schild) horizon ricci scalar (spin on z axis)

Details

Computes the 2-dimensional Ricci scalar \(R\) on the horizon of a Kerr-Schild black hole with spin in the z direction in terms of mass mass and dimensionless spin dimensionless_spin_z.

◆ horizon_ricci_scalar() [2/2]

template<typename DataType >
Scalar< DataType > TestHelpers::Kerr::horizon_ricci_scalar ( const Scalar< DataType > &  horizon_radius_with_spin_on_z_axis,
const ylm::Spherepack ylm_with_spin_on_z_axis,
const ylm::Spherepack ylm,
double  mass,
const std::array< double, 3 > &  dimensionless_spin 
)

Kerr (Kerr-Schild) horizon ricci scalar (generic spin)

Details

Computes the 2-dimensional Ricci scalar \(R\) on the horizon of a Kerr-Schild black hole with generic spin in terms of mass mass and dimensionless spin dimensionless_spin.

◆ make_random_vector_in_magnitude_range()

template<typename DataType , size_t Dim, UpLo Ul, typename Fr = Frame::Inertial, Requires<(Ul==UpLo::Up)> = nullptr>
tnsr::I< DataType, Dim, Fr > make_random_vector_in_magnitude_range ( const gsl::not_null< std::mt19937 * >  nn_generator,
const tnsr::ii< DataType, Dim, Fr > &  metric,
const double  min_magnitude,
const double  max_magnitude 
)

Construct a spatial vector in a given magnitude range.

The magnitude is computed with respect to the given metric, where the metric is assumed to have positive signature.

◆ make_random_vector_in_magnitude_range_flat()

template<typename DataType , size_t Dim, UpLo Ul, typename Fr = Frame::Inertial, typename T >
Tensor< DataType, Symmetry< 1 >, index_list< SpatialIndex< Dim, Ul, Fr > > > make_random_vector_in_magnitude_range_flat ( const gsl::not_null< std::mt19937 * >  nn_generator,
const T &  used_for_size,
const double  min_magnitude,
const double  max_magnitude 
)

Construct a spatial vector in a given magnitude range.

The magnitude is computed with respect to the flat space Euclidian metric.

◆ make_with_random_values() [1/3]

template<typename T , typename UniformRandomBitGenerator , typename RandomNumberDistribution >
T make_with_random_values ( const gsl::not_null< UniformRandomBitGenerator * >  generator,
const gsl::not_null< RandomNumberDistribution * >  distribution 
)

Make a fixed-size data structure and fill with random values.

Details

Given a template argument type T, create an object of the same type, fills it with random values, and returns the result. Acts as a convenience function to avoid users needing to put in constructors with signaling_NaN()s or max()s themselves when making with random values. Used as make_with_random_values<Type>(make_not_null(&gen),make_not_null(&dist))

◆ make_with_random_values() [2/3]

template<typename ReturnType , typename T , typename UniformRandomBitGenerator , typename RandomNumberDistribution >
ReturnType make_with_random_values ( const gsl::not_null< UniformRandomBitGenerator * >  generator,
const gsl::not_null< RandomNumberDistribution * >  distribution,
const T &  used_for_size 
)

Make a data structure and fill it with random values.

Details

Given an object of type T, create an object of type ReturnType whose elements are initialized to random values using the given random number generator and random number distribution.

Requires: the type ReturnType to be creatable using make_with_value<ReturnType>(T)

◆ make_with_random_values() [3/3]

template<typename ReturnType , typename T , typename UniformRandomBitGenerator , typename RandomNumberDistribution >
ReturnType make_with_random_values ( const gsl::not_null< UniformRandomBitGenerator * >  generator,
RandomNumberDistribution  distribution,
const T &  used_for_size 
)

Make a data structure and fill it with random values.

Details

Given an object of type T, create an object of type ReturnType whose elements are initialized to random values using the given random number generator and random number distribution.

Requires: the type ReturnType to be creatable using make_with_value<ReturnType>(T)

◆ numerical_derivative()

template<typename Invocable , size_t VolumeDim>
std::invoke_result_t< const Invocable &, const std::array< double, VolumeDim > & > numerical_derivative ( const Invocable &  function,
const std::array< double, VolumeDim > &  x,
const size_t  direction,
const double  delta 
)

Calculates the derivative of an Invocable at a point x - represented by an array of doubles - in the domain of map with a sixth-order finite difference method.

Details

Intended for use with CoordinateMaps taking the domain {xi,eta,zeta} to the range {x,y,z}. This function calculates the derivative along the direction given by direction with a step size of h.

Requires: direction be between 0 and VolumeDim

◆ random_sample() [1/2]

template<size_t NumSamples, typename Container , typename ValueType = typename Container::value_type>
std::array< ValueType, NumSamples > random_sample ( const Container &  container,
const gsl::not_null< std::mt19937 * >  generator 
)

NumSamples unique random elements of the container

This function is useful to iterate over a random subset of a container, like this:

for (const auto& [halves, orientation, with_equiangular_map,
with_adapted_equiangular_map, radial_distribution] :
random_sample<5>(
halves_array, all_wedge_directions(), make_array(true, false),
make_array(true, false),
make_array(CoordinateMaps::Distribution::Linear,
CoordinateMaps::Distribution::Linear,
CoordinateMaps::Distribution::Linear,
CoordinateMaps::Distribution::Logarithmic,
CoordinateMaps::Distribution::Inverse)),
make_not_null(&gen))) {
std::array< OrientationMap< 3 >, 6 > all_wedge_directions()
Wedge OrientationMap in each of the six directions used in the Sphere domain creator.
Definition: TestMapHelpers.hpp:871
void cartesian_product(OutputIterator result, std::pair< InputIterator, InputIterator >... dimensions)
Fill the result iterator with the Cartesian product of a sequence of iterators.
Definition: CartesianProduct.hpp:49
constexpr std::array< T, Size > make_array(Args &&... args)
Create a std::array<T, Size>{{T(args...), T(args...), ...}}
Definition: MakeArray.hpp:65
Note
This implementation copies the random elements into a std::array that can be iterated over. This can be changed if we need to support noncopyable types.

◆ random_sample() [2/2]

template<typename Container , typename ValueType = typename Container::value_type>
std::vector< ValueType > random_sample ( const size_t  number_of_samples,
const Container &  container,
const gsl::not_null< std::mt19937 * >  generator 
)

Creates a new std::vector holding number_of_samples unique random elements of the container

Note
If container has fewer elements than number_of_samples, this function returns a std::vector of all elements in container

◆ spatial_ricci()

template<typename DataType , size_t SpatialDim, typename Frame >
tnsr::ii< DataType, SpatialDim, Frame > TestHelpers::Schwarzschild::spatial_ricci ( const tnsr::I< DataType, SpatialDim, Frame > &  x,
double  mass 
)

Schwarzschild (Kerr-Schild) spatial ricci tensor.

Details

Computes \(R_{ij} = M \frac{r^2(4M+r)\delta_{ij}-(8M+3r)x_i x_j} {r^4(2M+r^2)},\) where \(r = x_i x_j \delta^{ij}\), \(x_i\) is the position vector in Cartesian coordinates, and M is the mass.

◆ test_boundary_correction_conservation()

template<typename System , typename BoundaryCorrection , size_t FaceDim, typename... VolumeTags, typename... RangeTags>
void TestHelpers::evolution::dg::test_boundary_correction_conservation ( const gsl::not_null< std::mt19937 * >  generator,
const BoundaryCorrection &  correction,
const Mesh< FaceDim > &  face_mesh,
const tuples::TaggedTuple< VolumeTags... > &  volume_data,
const tuples::TaggedTuple< Tags::Range< RangeTags >... > &  ranges,
const ZeroOnSmoothSolution  zero_on_smooth_solution = ZeroOnSmoothSolution::Yes,
const double  eps = 1.0e-12 
)

Checks that the boundary correction is conservative and that for smooth solutions the strong-form correction is zero.

By default, each input tensor for dg_package_data is randomly generated from the interval [-1,1) (except the metric, which for systems with a metric is generated to be close to flat space). The argument ranges is a TaggedTuple of TestHelpers::evolution::dg::Tags::Range<tag> that enables the caller to pick a custom interval for generating the input tag. This is useful, for example, for tensors that need positive values. Each tag in ranges must be an argument of dg_package_data.

◆ test_boundary_correction_with_python()

template<typename System , typename ConversionClassList = tmpl::list<>, typename BoundaryCorrection , size_t FaceDim, typename... VolumeTags, typename... RangeTags>
void TestHelpers::evolution::dg::test_boundary_correction_with_python ( const gsl::not_null< std::mt19937 * >  generator,
const std::string python_module,
const std::string python_dg_package_data_function,
const std::string python_dg_boundary_terms_function,
const BoundaryCorrection &  correction,
const Mesh< FaceDim > &  face_mesh,
const tuples::TaggedTuple< VolumeTags... > &  volume_data,
const tuples::TaggedTuple< Tags::Range< RangeTags >... > &  ranges,
const double  epsilon = 1.0e-12 
)

Tests that the dg_package_data and dg_boundary_terms functions agree with the python implementation.

The variables are filled with random numbers between zero and one before being passed to the implementations. If in the future we need support for negative numbers we can add the ability to specify a single range for all random numbers or each individually.

Please note the following:

  • The pypp::SetupLocalPythonEnvironment must be created before the test_boundary_correction_with_python can be called.
  • The dg_formulation is passed as a bool use_strong_form to the python functions since we don't want to rely on python bindings for the enum.
  • You can convert custom types using the ConversionClassList template parameter, which is then passed to pypp::call(). This allows you to, e.g., convert an equation of state into an array locally in a test file.
  • There must be one python function to compute the packaged data for each tag in dg_package_field_tags
  • There must be one python function to compute the boundary correction for each tag in System::variables_tag
  • The arguments to the python functions for computing the packaged data are the same as the arguments for the C++ dg_package_data function, excluding the gsl::not_null arguments.
  • The arguments to the python functions for computing the boundary corrections are the same as the arguments for the C++ dg_boundary_terms function, excluding the gsl::not_null arguments.
  • By default, each input tensor for dg_package_data is randomly generated from the interval [-1,1) (except the metric, which for systems with a metric is generated to be close to flat space). The argument ranges is a TaggedTuple of TestHelpers::evolution::dg::Tags::Range<tag> that enables the caller to pick a custom interval for generating the input tag. This is useful, for example, for tensors that need positive values. Each tag in ranges must be an argument of dg_package_data.

◆ test_creation()

template<typename T , typename Metavariables = NoSuchType>
T TestHelpers::test_creation ( const std::string construction_string)

Creates an instance of a given option-creatable type.

This is a wrapper around Options::Parser constructing a single, specified type T from the supplied string. If necessary, metavariables can be supplied as the second template argument.

A class can be explicitly created through a factory by passing std::unique_ptr<BaseClass> as the type. This will require metavariables to be passed. For testing basic factory creation, the simpler TestHelpers::test_factory_creation() can be used instead.

struct ClassWithoutMetavariables {
struct SizeT {
using type = size_t;
static constexpr Options::String help = {"SizeT help"};
};
using options = tmpl::list<SizeT>;
static constexpr Options::String help = {"Help"};
explicit ClassWithoutMetavariables(const size_t in_value) : value(in_value) {}
ClassWithoutMetavariables() = default;
size_t value{0};
};
constexpr T & value(T &t)
Returns t.value() if t is a std::optional otherwise returns t.
Definition: OptionalHelpers.hpp:32
const char *const String
The string used in option structs.
Definition: String.hpp:8
CHECK(
TestHelpers::test_creation<ClassWithoutMetavariables>("SizeT: 7").value ==
7);
See also
TestHelpers::test_option_tag()

◆ test_evaluate_rank_0()

template<typename DataType >
void TestHelpers::tenex::test_evaluate_rank_0 ( const DataType &  data)

Test that evaluating a right hand side tensor expression containing a single rank 0 tensor correctly assigns the data to the evaluated left hand side tensor.

Parameters
datathe data being stored in the Tensors

◆ test_evaluate_rank_1()

template<typename DataType , template< size_t, UpLo, typename > class TensorIndexType, UpLo Valence, auto & TensorIndex>
void TestHelpers::tenex::test_evaluate_rank_1 ( )

Iterate testing of evaluating single rank 1 Tensors on multiple Frame types and dimensions.

Template Parameters
DataTypethe type of data being stored in the Tensors
TensorIndexTypethe Tensors' TensorIndexType
Valencethe valence of the Tensors' index
TensorIndexthe TensorIndex used in the the TensorExpression, e.g. ti::a

◆ test_evaluate_rank_1_impl()

template<typename DataType , typename TensorIndexTypeList , auto & TensorIndex>
void TestHelpers::tenex::test_evaluate_rank_1_impl ( )

Test that evaluating a right hand side tensor expression containing a single rank 1 tensor correctly assigns the data to the evaluated left hand side tensor.

Template Parameters
DataTypethe type of data being stored in the Tensors
TensorIndexTypeListthe Tensors' typelist containing their TensorIndexType
TensorIndexthe TensorIndex used in the the TensorExpression, e.g. ti::a

◆ test_evaluate_rank_2_impl()

template<typename DataType , typename RhsSymmetry , typename RhsTensorIndexTypeList , auto & TensorIndexA, auto & TensorIndexB>
void TestHelpers::tenex::test_evaluate_rank_2_impl ( )

Test that evaluating a right hand side tensor expression containing a single rank 2 tensor correctly assigns the data to the evaluated left hand side tensor.

Details

TensorIndexA and TensorIndexB can be any type of TensorIndex and are not necessarily ti::a and ti::b. The "A" and "B" suffixes just denote the ordering of the generic indices of the RHS tensor expression. In the RHS tensor expression, it means TensorIndexA is the first index used and TensorIndexB is the second index used.

If we consider the RHS tensor's generic indices to be (a, b), then this test checks that the data in the evaluated LHS tensor is correct according to the index orders of the LHS and RHS. The two possible cases that are checked are when the LHS tensor is evaluated with index order (a, b) and when it is evaluated with the index order (b, a).

Template Parameters
DataTypethe type of data being stored in the Tensors
RhsSymmetrythe Symmetry of the RHS Tensor
RhsTensorIndexTypeListthe RHS Tensor's typelist of TensorIndexTypes
TensorIndexAthe first TensorIndex used on the RHS of the TensorExpression, e.g. ti::a
TensorIndexBthe second TensorIndex used on the RHS of the TensorExpression, e.g. ti::B

◆ test_evaluate_rank_2_no_symmetry()

template<typename DataType , template< size_t, UpLo, typename > class TensorIndexTypeA, template< size_t, UpLo, typename > class TensorIndexTypeB, UpLo ValenceA, UpLo ValenceB, auto & TensorIndexA, auto & TensorIndexB>
void TestHelpers::tenex::test_evaluate_rank_2_no_symmetry ( )

Iterate testing of evaluating single rank 2 Tensors on multiple Frame types and dimension combinations.

We test nonsymmetric indices and symmetric indices across two functions to ensure that the code works correctly with symmetries. This function tests one of the following symmetries:

  • <2, 1> (test_evaluate_rank_2_no_symmetry)
  • <1, 1> (test_evaluate_rank_2_symmetric)

Details

TensorIndexA and TensorIndexB can be any type of TensorIndex and are not necessarily ti::a and ti::b. The "A" and "B" suffixes just denote the ordering of the generic indices of the RHS tensor expression. In the RHS tensor expression, it means TensorIndexA is the first index used and TensorIndexB is the second index used.

Note: test_evaluate_rank_2_symmetric has fewer template parameters due to the two indices having a shared TensorIndexType and and valence

Template Parameters
DataTypethe type of data being stored in the Tensors
TensorIndexTypeAthe TensorIndexType of the first index of the RHS Tensor
TensorIndexTypeBthe TensorIndexType of the second index of the RHS Tensor
ValenceAthe valence of the first index used on the RHS of the TensorExpression
ValenceBthe valence of the second index used on the RHS of the TensorExpression
TensorIndexAthe first TensorIndex used on the RHS of the TensorExpression, e.g. ti::a
TensorIndexBthe second TensorIndex used on the RHS of the TensorExpression, e.g. ti::B

◆ test_evaluate_rank_2_symmetric()

template<typename DataType , template< size_t, UpLo, typename > class TensorIndexType, UpLo Valence, auto & TensorIndexA, auto & TensorIndexB>
void TestHelpers::tenex::test_evaluate_rank_2_symmetric ( )

Iterate testing of evaluating single rank 2 Tensors on multiple Frame types and dimension combinations.

We test nonsymmetric indices and symmetric indices across two functions to ensure that the code works correctly with symmetries. This function tests one of the following symmetries:

  • <2, 1> (test_evaluate_rank_2_no_symmetry)
  • <1, 1> (test_evaluate_rank_2_symmetric)

Details

TensorIndexA and TensorIndexB can be any type of TensorIndex and are not necessarily ti::a and ti::b. The "A" and "B" suffixes just denote the ordering of the generic indices of the RHS tensor expression. In the RHS tensor expression, it means TensorIndexA is the first index used and TensorIndexB is the second index used.

Note: test_evaluate_rank_2_symmetric has fewer template parameters due to the two indices having a shared TensorIndexType and and valence

Template Parameters
DataTypethe type of data being stored in the Tensors
TensorIndexTypeAthe TensorIndexType of the first index of the RHS Tensor
TensorIndexTypeBthe TensorIndexType of the second index of the RHS Tensor
ValenceAthe valence of the first index used on the RHS of the TensorExpression
ValenceBthe valence of the second index used on the RHS of the TensorExpression
TensorIndexAthe first TensorIndex used on the RHS of the TensorExpression, e.g. ti::a
TensorIndexBthe second TensorIndex used on the RHS of the TensorExpression, e.g. ti::B

◆ test_evaluate_rank_3_ab_symmetry()

template<typename DataType , template< size_t, UpLo, typename > class TensorIndexTypeAB, template< size_t, UpLo, typename > class TensorIndexTypeC, UpLo ValenceAB, UpLo ValenceC, auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_ab_symmetry ( )

Iterate testing of evaluating single rank 3 Tensors on multiple Frame types and dimension combinations.

We test various different symmetries across several functions to ensure that the code works correctly with symmetries. This function tests one of the following symmetries:

  • <3, 2, 1> (test_evaluate_rank_3_no_symmetry)
  • <2, 2, 1> (test_evaluate_rank_3_ab_symmetry)
  • <2, 1, 2> (test_evaluate_rank_3_ac_symmetry)
  • <2, 1, 1> (test_evaluate_rank_3_bc_symmetry)
  • <1, 1, 1> (test_evaluate_rank_3_abc_symmetry)

Details

TensorIndexA, TensorIndexB, and TensorIndexC can be any type of TensorIndex and are not necessarily ti::a, ti::b, and ti::c. The "A", "B", and "C" suffixes just denote the ordering of the generic indices of the RHS tensor expression. In the RHS tensor expression, it means TensorIndexA is the first index used, TensorIndexB is the second index used, and TensorIndexC is the third index used.

Note: the functions dealing with symmetric indices have fewer template parameters due to the indices having a shared TensorIndexType and valence

Template Parameters
DataTypethe type of data being stored in the Tensors
TensorIndexTypeAthe TensorIndexType of the first index of the RHS Tensor
TensorIndexTypeBthe TensorIndexType of the second index of the RHS Tensor
TensorIndexTypeCthe TensorIndexType of the third index of the RHS Tensor
ValenceAthe valence of the first index used on the RHS of the TensorExpression
ValenceBthe valence of the second index used on the RHS of the TensorExpression
ValenceCthe valence of the third index used on the RHS of the TensorExpression
TensorIndexAthe first TensorIndex used on the RHS of the TensorExpression, e.g. ti::a
TensorIndexBthe second TensorIndex used on the RHS of the TensorExpression, e.g. ti::B
TensorIndexCthe third TensorIndex used on the RHS of the TensorExpression, e.g. ti::c

◆ test_evaluate_rank_3_abc_symmetry()

template<typename DataType , template< size_t, UpLo, typename > class TensorIndexType, UpLo Valence, auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_abc_symmetry ( )

Iterate testing of evaluating single rank 3 Tensors on multiple Frame types and dimension combinations.

We test various different symmetries across several functions to ensure that the code works correctly with symmetries. This function tests one of the following symmetries:

  • <3, 2, 1> (test_evaluate_rank_3_no_symmetry)
  • <2, 2, 1> (test_evaluate_rank_3_ab_symmetry)
  • <2, 1, 2> (test_evaluate_rank_3_ac_symmetry)
  • <2, 1, 1> (test_evaluate_rank_3_bc_symmetry)
  • <1, 1, 1> (test_evaluate_rank_3_abc_symmetry)

Details

TensorIndexA, TensorIndexB, and TensorIndexC can be any type of TensorIndex and are not necessarily ti::a, ti::b, and ti::c. The "A", "B", and "C" suffixes just denote the ordering of the generic indices of the RHS tensor expression. In the RHS tensor expression, it means TensorIndexA is the first index used, TensorIndexB is the second index used, and TensorIndexC is the third index used.

Note: the functions dealing with symmetric indices have fewer template parameters due to the indices having a shared TensorIndexType and valence

Template Parameters
DataTypethe type of data being stored in the Tensors
TensorIndexTypeAthe TensorIndexType of the first index of the RHS Tensor
TensorIndexTypeBthe TensorIndexType of the second index of the RHS Tensor
TensorIndexTypeCthe TensorIndexType of the third index of the RHS Tensor
ValenceAthe valence of the first index used on the RHS of the TensorExpression
ValenceBthe valence of the second index used on the RHS of the TensorExpression
ValenceCthe valence of the third index used on the RHS of the TensorExpression
TensorIndexAthe first TensorIndex used on the RHS of the TensorExpression, e.g. ti::a
TensorIndexBthe second TensorIndex used on the RHS of the TensorExpression, e.g. ti::B
TensorIndexCthe third TensorIndex used on the RHS of the TensorExpression, e.g. ti::c

◆ test_evaluate_rank_3_ac_symmetry()

template<typename DataType , template< size_t, UpLo, typename > class TensorIndexTypeAC, template< size_t, UpLo, typename > class TensorIndexTypeB, UpLo ValenceAC, UpLo ValenceB, auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_ac_symmetry ( )

Iterate testing of evaluating single rank 3 Tensors on multiple Frame types and dimension combinations.

We test various different symmetries across several functions to ensure that the code works correctly with symmetries. This function tests one of the following symmetries:

  • <3, 2, 1> (test_evaluate_rank_3_no_symmetry)
  • <2, 2, 1> (test_evaluate_rank_3_ab_symmetry)
  • <2, 1, 2> (test_evaluate_rank_3_ac_symmetry)
  • <2, 1, 1> (test_evaluate_rank_3_bc_symmetry)
  • <1, 1, 1> (test_evaluate_rank_3_abc_symmetry)

Details

TensorIndexA, TensorIndexB, and TensorIndexC can be any type of TensorIndex and are not necessarily ti::a, ti::b, and ti::c. The "A", "B", and "C" suffixes just denote the ordering of the generic indices of the RHS tensor expression. In the RHS tensor expression, it means TensorIndexA is the first index used, TensorIndexB is the second index used, and TensorIndexC is the third index used.

Note: the functions dealing with symmetric indices have fewer template parameters due to the indices having a shared TensorIndexType and valence

Template Parameters
DataTypethe type of data being stored in the Tensors
TensorIndexTypeAthe TensorIndexType of the first index of the RHS Tensor
TensorIndexTypeBthe TensorIndexType of the second index of the RHS Tensor
TensorIndexTypeCthe TensorIndexType of the third index of the RHS Tensor
ValenceAthe valence of the first index used on the RHS of the TensorExpression
ValenceBthe valence of the second index used on the RHS of the TensorExpression
ValenceCthe valence of the third index used on the RHS of the TensorExpression
TensorIndexAthe first TensorIndex used on the RHS of the TensorExpression, e.g. ti::a
TensorIndexBthe second TensorIndex used on the RHS of the TensorExpression, e.g. ti::B
TensorIndexCthe third TensorIndex used on the RHS of the TensorExpression, e.g. ti::c

◆ test_evaluate_rank_3_bc_symmetry()

template<typename DataType , template< size_t, UpLo, typename > class TensorIndexTypeA, template< size_t, UpLo, typename > class TensorIndexTypeBC, UpLo ValenceA, UpLo ValenceBC, auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_bc_symmetry ( )

Iterate testing of evaluating single rank 3 Tensors on multiple Frame types and dimension combinations.

We test various different symmetries across several functions to ensure that the code works correctly with symmetries. This function tests one of the following symmetries:

  • <3, 2, 1> (test_evaluate_rank_3_no_symmetry)
  • <2, 2, 1> (test_evaluate_rank_3_ab_symmetry)
  • <2, 1, 2> (test_evaluate_rank_3_ac_symmetry)
  • <2, 1, 1> (test_evaluate_rank_3_bc_symmetry)
  • <1, 1, 1> (test_evaluate_rank_3_abc_symmetry)

Details

TensorIndexA, TensorIndexB, and TensorIndexC can be any type of TensorIndex and are not necessarily ti::a, ti::b, and ti::c. The "A", "B", and "C" suffixes just denote the ordering of the generic indices of the RHS tensor expression. In the RHS tensor expression, it means TensorIndexA is the first index used, TensorIndexB is the second index used, and TensorIndexC is the third index used.

Note: the functions dealing with symmetric indices have fewer template parameters due to the indices having a shared TensorIndexType and valence

Template Parameters
DataTypethe type of data being stored in the Tensors
TensorIndexTypeAthe TensorIndexType of the first index of the RHS Tensor
TensorIndexTypeBthe TensorIndexType of the second index of the RHS Tensor
TensorIndexTypeCthe TensorIndexType of the third index of the RHS Tensor
ValenceAthe valence of the first index used on the RHS of the TensorExpression
ValenceBthe valence of the second index used on the RHS of the TensorExpression
ValenceCthe valence of the third index used on the RHS of the TensorExpression
TensorIndexAthe first TensorIndex used on the RHS of the TensorExpression, e.g. ti::a
TensorIndexBthe second TensorIndex used on the RHS of the TensorExpression, e.g. ti::B
TensorIndexCthe third TensorIndex used on the RHS of the TensorExpression, e.g. ti::c

◆ test_evaluate_rank_3_impl()

template<typename DataType , typename RhsSymmetry , typename RhsTensorIndexTypeList , auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_impl ( )

Test that evaluating a right hand side tensor expression containing a single rank 3 tensor correctly assigns the data to the evaluated left hand side tensor.

Details

TensorIndexA, TensorIndexB, and TensorIndexC can be any type of TensorIndex and are not necessarily ti::a, ti::b, and ti::c. The "A", "B", and "C" suffixes just denote the ordering of the generic indices of the RHS tensor expression. In the RHS tensor expression, it means TensorIndexA is the first index used, TensorIndexB is the second index used, and TensorIndexC is the third index used.

If we consider the RHS tensor's generic indices to be (a, b, c), then this test checks that the data in the evaluated LHS tensor is correct according to the index orders of the LHS and RHS. The possible cases that are checked are when the LHS tensor is evaluated with index orders: (a, b, c), (a, c, b), (b, a, c), (b, c, a), (c, a, b), and (c, b, a).

Template Parameters
DataTypethe type of data being stored in the Tensors
RhsSymmetrythe Symmetry of the RHS Tensor
RhsTensorIndexTypeListthe RHS Tensor's typelist of TensorIndexTypes
TensorIndexAthe first TensorIndex used on the RHS of the TensorExpression, e.g. ti::a
TensorIndexBthe second TensorIndex used on the RHS of the TensorExpression, e.g. ti::B
TensorIndexCthe third TensorIndex used on the RHS of the TensorExpression, e.g. ti::c

◆ test_evaluate_rank_3_no_symmetry()

template<typename DataType , template< size_t, UpLo, typename > class TensorIndexTypeA, template< size_t, UpLo, typename > class TensorIndexTypeB, template< size_t, UpLo, typename > class TensorIndexTypeC, UpLo ValenceA, UpLo ValenceB, UpLo ValenceC, auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC>
void TestHelpers::tenex::test_evaluate_rank_3_no_symmetry ( )

Iterate testing of evaluating single rank 3 Tensors on multiple Frame types and dimension combinations.

We test various different symmetries across several functions to ensure that the code works correctly with symmetries. This function tests one of the following symmetries:

  • <3, 2, 1> (test_evaluate_rank_3_no_symmetry)
  • <2, 2, 1> (test_evaluate_rank_3_ab_symmetry)
  • <2, 1, 2> (test_evaluate_rank_3_ac_symmetry)
  • <2, 1, 1> (test_evaluate_rank_3_bc_symmetry)
  • <1, 1, 1> (test_evaluate_rank_3_abc_symmetry)

Details

TensorIndexA, TensorIndexB, and TensorIndexC can be any type of TensorIndex and are not necessarily ti::a, ti::b, and ti::c. The "A", "B", and "C" suffixes just denote the ordering of the generic indices of the RHS tensor expression. In the RHS tensor expression, it means TensorIndexA is the first index used, TensorIndexB is the second index used, and TensorIndexC is the third index used.

Note: the functions dealing with symmetric indices have fewer template parameters due to the indices having a shared TensorIndexType and valence

Template Parameters
DataTypethe type of data being stored in the Tensors
TensorIndexTypeAthe TensorIndexType of the first index of the RHS Tensor
TensorIndexTypeBthe TensorIndexType of the second index of the RHS Tensor
TensorIndexTypeCthe TensorIndexType of the third index of the RHS Tensor
ValenceAthe valence of the first index used on the RHS of the TensorExpression
ValenceBthe valence of the second index used on the RHS of the TensorExpression
ValenceCthe valence of the third index used on the RHS of the TensorExpression
TensorIndexAthe first TensorIndex used on the RHS of the TensorExpression, e.g. ti::a
TensorIndexBthe second TensorIndex used on the RHS of the TensorExpression, e.g. ti::B
TensorIndexCthe third TensorIndex used on the RHS of the TensorExpression, e.g. ti::c

◆ test_evaluate_rank_4()

template<typename DataType , typename RhsSymmetry , typename RhsTensorIndexTypeList , auto & TensorIndexA, auto & TensorIndexB, auto & TensorIndexC, auto & TensorIndexD>
void TestHelpers::tenex::test_evaluate_rank_4 ( )

Test that evaluating a right hand side tensor expression containing a single rank 4 tensor correctly assigns the data to the evaluated left hand side tensor.

Details

TensorIndexA, TensorIndexB, TensorIndexC, and TensorIndexD can be any type of TensorIndex and are not necessarily ti::a, ti::b, ti::c, and ti::d. The "A", "B", "C", and "D" suffixes just denote the ordering of the generic indices of the RHS tensor expression. In the RHS tensor expression, it means TensorIndexA is the first index used, TensorIndexB is the second index used, TensorIndexC is the third index used, and TensorIndexD is the fourth index used.

If we consider the RHS tensor's generic indices to be (a, b, c, d), then this test checks that the data in the evaluated LHS tensor is correct according to the index orders of the LHS and RHS. The possible cases that are checked are when the LHS tensor is evaluated with index orders of all 24 permutations of (a, b, c, d), e.g. (a, b, d, c), (a, c, b, d), ...

Template Parameters
DataTypethe type of data being stored in the Tensors
RhsSymmetrythe Symmetry of the RHS Tensor
RhsTensorIndexTypeListthe RHS Tensor's typelist of TensorIndexTypes
TensorIndexAthe first TensorIndex used on the RHS of the TensorExpression, e.g. ti::a
TensorIndexBthe second TensorIndex used on the RHS of the TensorExpression, e.g. ti::B
TensorIndexCthe third TensorIndex used on the RHS of the TensorExpression, e.g. ti::c
TensorIndexDthe fourth TensorIndex used on the RHS of the TensorExpression, e.g. ti::D

◆ test_factory_creation()

template<typename BaseClass , typename DerivedClass >
std::unique_ptr< BaseClass > TestHelpers::test_factory_creation ( const std::string construction_string)

Creates a class of a known derived type using a factory.

This is a shorthand for creating a DerivedClass through a BaseClass factory, saving the caller from having to explicitly write metavariables with the appropriate factory_classes alias. The name of the type should be supplied as the first line of the passed string, just as for normal use of a factory.

If multiple factory creatable types must be handled or if metavariables must be passed for some other reason, then the more general TestHelpers::test_creation() must be used instead.

CHECK(TestHelpers::test_factory_creation<BaseClass, DerivedClass>(
"DerivedClass:\n"
" SizeT: 5")
->get_value() == 5);

◆ test_functions_with_vector_arguments()

template<TestKind Test, typename VectorType0 , typename... VectorTypes, typename... FunctionsAndArgumentBounds>
void TestHelpers::VectorImpl::test_functions_with_vector_arguments ( const std::tuple< FunctionsAndArgumentBounds... > &  tuple_of_functions_and_argument_bounds)

General entry function for testing arbitrary math functions on vector types.

Details

This utility tests all combinations of the operator on the type arguments, and all combinations of reference or constant reference wrappers on all arguments. In certain test cases (see below), it also tests using the vector type's value_types in the operators as well (e.g. DataVector + double). This is very useful for quickly generating a lot of tests, but the number of tests scales exponentially in the number of arguments. Therefore, functions with many arguments can be time-consuming to run. 4-or-more-argument functions should be used only if completely necessary and with caution. Any number of vector types may be specified, and tests are run on all unique combinations of the provided. For instance, if only one type is provided, the tests will be run only on combinations of that single type and its value_type.

Parameters
tuple_of_functions_and_argument_boundsA tuple of tuples, in which the inner tuple contains first a function object followed by a tuple of 2-element arrays equal to the number of arguments, which represent the bounds for the random generation of the respective arguments. This system is provided for robust testing of operators like /, where the left-hand side has a different valid set of values than the right-hand-side.
Template Parameters
Testfrom the TestKind enum, determines whether the tests will be:
  • TestKind::Normal: executed on all combinations of arguments and value types
  • TestKind::Strict: executed on all combinations of arguments, for only the vector types
  • TestKind::Inplace: executed on all combinations of arguments after the first, so first is always the 'left hand side' of the operator. In this case, at least two VectorTypes must be specified, where the first is used only for the left-hand side.
  • TestKind::GivenOrderOfArgumentsOnly: executed on only the combination of arguments provided, in the order provided. In this case, the number of provided types in typename VectorType0, typename... VectorTypes must precisely match the number of arguments taken by the function.
VectorType0The first vector type for which combinations are tested. The first is accepted as a separate template argument for appropriately handling Inplace tests.
VectorTypesThe remaining types for which combinations are tested. Any number of types may be passed in, and the test will check the appropriate combinations of the vector types and (depending on the Test) the respective value_types.

◆ test_option_tag()

template<typename OptionTag , typename Metavariables = NoSuchType>
OptionTag::type TestHelpers::test_option_tag ( const std::string construction_string)

Runs the option parser on a given tag.

Runs the option parser with the supplied input on a given tag. The tag name and any groups are handled by this function and should not be supplied in the argument string. If necessary, metavariables can be supplied as the second template argument.

struct ClassWithoutMetavariables {
struct SizeT {
using type = size_t;
static constexpr Options::String help = {"SizeT help"};
};
using options = tmpl::list<SizeT>;
static constexpr Options::String help = {"Help"};
explicit ClassWithoutMetavariables(const size_t in_value) : value(in_value) {}
ClassWithoutMetavariables() = default;
size_t value{0};
};
struct ExampleTag {
using type = ClassWithoutMetavariables;
static constexpr Options::String help = {"help"};
using group = OptionGroup1;
};
CHECK(TestHelpers::test_option_tag<ExampleTag>("SizeT: 7").value == 7);
See also
TestHelpers::test_creation()

◆ test_option_tag_factory_creation()

template<typename OptionTag , typename DerivedClass >
OptionTag::type TestHelpers::test_option_tag_factory_creation ( const std::string construction_string)

A wrapper that allows testing an option tag without having to write a Metavariables class. Combines TestHelpers::test_factory_creation() and TestHelpers::test_option_tag().

Note
Assumes that the option tag holds a std::unique_ptr<BaseClass>.
namespace OptionTags {
struct BaseClass {
static constexpr Options::String help = "Halp";
};
} // namespace OptionTags
CHECK(TestHelpers::test_option_tag_factory_creation<OptionTags::BaseClass,
DerivedClass>(
"DerivedClass:\n"
" SizeT: 5")
->get_value() == 5);
OptionTag::type test_option_tag_factory_creation(const std::string &construction_string)
A wrapper that allows testing an option tag without having to write a Metavariables class....
Definition: TestCreation.hpp:152

◆ test_serialization()

template<typename T >
void test_serialization ( const T &  t)

Tests the serialization of comparable types.

Example

{
INFO("tuple");
um["aaa"] = 1.589;
um["bbb"] = -10.7392;
auto test_tuple = std::make_tuple<int, double, std::string,
2, 0.57, "blah", std::move(um));
test_serialization(test_tuple);
}
void test_serialization(const T &t)
Tests the serialization of comparable types.
Definition: TestHelpers.hpp:68

◆ test_serialization_via_base()

template<typename B , typename D , typename... Args>
void test_serialization_via_base ( Args &&...  args)

Test the serialization of a derived class via a base class pointer.

Example

{
INFO("unique_ptr.abstract_base");
test_serialization_via_base<Test_Classes::Base,
Test_Classes::DerivedInPupStlCpp11>(
std::vector<double>{-1, 12.3, -7, 8});
}
void test_serialization_via_base(Args &&... args)
Test the serialization of a derived class via a base class pointer.
Definition: TestHelpers.hpp:83
Template Parameters
Bthe base class
Dthe derived class
Argsdeduced from args
Parameters
argsarguments passed to a constructor of the derived class

◆ test_tensor_index_transformation_rank_0()

void TestHelpers::tenex::test_tensor_index_transformation_rank_0 ( )
inline

Test that the transformation between two rank 0 tensors' generic indices and the subsequent transformed multi-index is correctly computed.

Details

The functions tested are:

◆ test_tensor_index_transformation_rank_1()

template<typename TensorIndex >
void TestHelpers::tenex::test_tensor_index_transformation_rank_1 ( const TensorIndex )

Test that the transformation between two rank 1 tensors' generic indices and the subsequent transformed multi-indices are correctly computed.

Details

The functions tested are:

Template Parameters
TensorIndexthe first generic tensor index, e.g. type of ti::a

◆ test_tensor_index_transformation_rank_2()

template<typename TensorIndexA , typename TensorIndexB >
void TestHelpers::tenex::test_tensor_index_transformation_rank_2 ( const TensorIndexA &  ,
const TensorIndexB &   
)

Test that the transformation between two rank 2 tensors' generic indices and the subsequent transformed multi-indices are correctly computed.

Details

The functions tested are:

If we consider the first tensor's generic indices to be (a, b), the possible orderings of the second tensor's generic indices are: (a, b) and (b, a). For each of these cases, this test checks that for each multi-index with the first generic index ordering, the equivalent multi-index with the second ordering is correctly computed.

Template Parameters
TensorIndexAthe first generic tensor index, e.g. type of ti::a
TensorIndexBthe second generic tensor index, e.g. type of ti::B

◆ test_tensor_index_transformation_rank_3()

template<typename TensorIndexA , typename TensorIndexB , typename TensorIndexC >
void TestHelpers::tenex::test_tensor_index_transformation_rank_3 ( const TensorIndexA &  ,
const TensorIndexB &  ,
const TensorIndexC &   
)

Test that the transformation between two rank 3 tensors' generic indices and the subsequent transformed multi-indices are correctly computed.

Details

The functions tested are:

If we consider the first tensor's generic indices to be (a, b, c), the possible orderings of the second tensor's generic indices are: (a, b, c), (a, c, b), (b, a, c), (b, c, a), (c, a, b), and (c, b, a). For each of these cases, this test checks that for each multi-index with the first generic index ordering, the equivalent multi-index with the second ordering is correctly computed.

Template Parameters
TensorIndexAthe first generic tensor index, e.g. type of ti::a
TensorIndexBthe second generic tensor index, e.g. type of ti::B
TensorIndexCthe third generic tensor index, e.g. type of ti::c

◆ test_tensor_index_transformation_rank_4()

template<typename TensorIndexA , typename TensorIndexB , typename TensorIndexC , typename TensorIndexD >
void TestHelpers::tenex::test_tensor_index_transformation_rank_4 ( const TensorIndexA &  ,
const TensorIndexB &  ,
const TensorIndexC &  ,
const TensorIndexD &   
)

Test that the transformation between two rank 4 tensors' generic indices and the subsequent transformed multi-indices are correctly computed.

Details

The functions tested are:

If we consider the first tensor's generic indices to be (a, b, c, d), there are 24 permutations that are possible orderings of the second tensor's generic indices, such as: (a, b, c, d), (a, b, d, c), (a, c, b, d), etc. For each of these cases, this test checks that for each multi-index with the first generic index ordering, the equivalent multi-index with the second ordering is correctly computed.

Template Parameters
TensorIndexAthe first generic tensor index, e.g. type of ti::a
TensorIndexBthe second generic tensor index, e.g. type of ti::B
TensorIndexCthe third generic tensor index, e.g. type of ti::c
TensorIndexDthe fourth generic tensor index, e.g. type of ti::D

◆ test_tensor_index_transformation_with_time_indices()

void TestHelpers::tenex::test_tensor_index_transformation_with_time_indices ( )
inline

Test that the transformation between two tensors generic indices and the subsequent transformed multi-indices are correctly computed when time indices are used with at least one of the tensors.

Details

The functions tested are:

◆ test_throw_exception()

template<typename Exception , typename ThrowingFunctor >
void test_throw_exception ( const ThrowingFunctor &  func,
const Exception &  expected 
)

Execute func and check that it throws an exception expected.

Note
The .what() strings of the thrown and expected exceptions are compared for a partial match only: the expected.what() string must be contained in (or equal to) the .what() string of the thrown exception.

◆ vector_ref_test_size_error()

template<typename VectorType , typename ValueType = typename VectorType::ElementType>
void TestHelpers::VectorImpl::vector_ref_test_size_error ( RefSizeErrorTestKind  test_kind,
tt::get_fundamental_type_t< ValueType >  low = tt::get_fundamental_type_t<ValueType>{-100.0},
tt::get_fundamental_type_t< ValueType >  high = tt::get_fundamental_type_t<ValueType>{100.0} 
)

Test that assigning to a non-owning VectorType of the wrong size appropriately generates an error.

Details

a calling function should be in a CHECK_THROWS_WITH() inside a #ifdef SPECTRE_DEBUG block, and check for the string "Must copy/move/assign into same size". Three types of tests are provided and one must be provided as the first function argument:

  • RefSizeErrorTestKind::Copy: Checks that copy-assigning to a non-owning VectorType from a VectorType with the wrong size generates an error.
  • RefSizeErrorTestKind::ExpressionAssign: Checks that assigning to a non-owning VectorType from an expression with alias ResultType of VectorType with the wrong size generates an error
  • RefSizeErrorTestKind::Move: Checks that move-assigning to a non-owning VectorType from a VectorType with the wrong size generates an error.

◆ verify_grmhd_solution()

template<typename Solution >
void verify_grmhd_solution ( const Solution &  solution,
const Block< 3 > &  block,
const Mesh< 3 > &  mesh,
const double  error_tolerance,
const double  time,
const double  delta_time 
)

Determines if the given solution is a solution of the GRMHD equations.

Uses numerical derivatives to compute the solution, on the given mesh of the root Element of the given block at the given time using a sixth-order derivative in time for the given delta_time. The maximum residual of the GRMHD equations must be zero within error_tolerance

◆ verify_smooth_solution()

template<typename System , typename SolutionType , size_t Dim = System::volume_dim, typename... Maps, typename PackageFluxesArgs >
void FirstOrderEllipticSolutionsTestHelpers::verify_smooth_solution ( const SolutionType &  solution,
const domain::CoordinateMap< Frame::ElementLogical, Frame::Inertial, Maps... > &  coord_map,
const double  tolerance_offset,
const double  tolerance_scaling,
PackageFluxesArgs &&  package_fluxes_args 
)

Test that the solution numerically solves the System on the given grid and that the discretization error decreases as expected for a smooth function.

Details

We expect exponential convergence for a smooth solution, so the tolerance is computed as

\begin{equation} C_1 \exp{\left(-C_2 * N_\mathrm{points}\right)} \end{equation}

where \(C_1\) is the tolerance_offset, \(C_2\) is the tolerance_scaling and \(N_\mathrm{points}\) is the number of grid points per dimension.

◆ verify_solution_with_power_law_convergence()

template<typename System , typename SolutionType , size_t Dim = System::volume_dim, typename... Maps>
void FirstOrderEllipticSolutionsTestHelpers::verify_solution_with_power_law_convergence ( const SolutionType &  solution,
const domain::CoordinateMap< Frame::ElementLogical, Frame::Inertial, Maps... > &  coord_map,
const double  tolerance_offset,
const double  tolerance_pow 
)

Test that the solution numerically solves the System on the given grid and that the discretization error decreases as a power law.

Details

The tolerance is computed as

\begin{equation} C \left(N_\mathrm{points}\right)^{-p} \end{equation}

where \(C\) is the tolerance_offset, \(p\) is the tolerance_pow and \(N_\mathrm{points}\) is the number of grid points per dimension.