The test suite is extensive. Note that LLMs were used to aid in the development of the test suite. All LLM generated code was manually reviewed.
88 lines
4.2 KiB
C++
88 lines
4.2 KiB
C++
#include <array>
|
|
#include <limits>
|
|
|
|
#include <catch2/catch_approx.hpp>
|
|
#include <catch2/catch_test_macros.hpp>
|
|
#include <catch2/matchers/catch_matchers_string.hpp>
|
|
|
|
#include "serif/solver/normalization/diagonal.hpp"
|
|
#include "serif/solver/normalization/point_rows.hpp"
|
|
|
|
namespace
|
|
{
|
|
namespace normalization = serif::solver::normalization;
|
|
}
|
|
|
|
// Ported from MeanField tests/normalization/physical_riesz.cpp, without assuming matching pressure and enthalpy scales.
|
|
TEST_CASE("Replaced residual rows use point metrics and independent physical units", "[normalization][unit][math]")
|
|
{
|
|
const std::array metric{4.0, 0.0, 16.0, 0.0};
|
|
const std::array point_rows{1, 3};
|
|
const auto enthalpy = normalization::make_point_replaced_residual_factors(metric, 5.0, point_rows, 5.0);
|
|
REQUIRE(enthalpy);
|
|
CHECK((*enthalpy)[0] == Catch::Approx(1.0 / 10.0));
|
|
CHECK((*enthalpy)[1] == Catch::Approx(1.0 / 5.0));
|
|
CHECK((*enthalpy)[2] == Catch::Approx(1.0 / 20.0));
|
|
CHECK((*enthalpy)[3] == Catch::Approx(1.0 / 5.0));
|
|
|
|
const auto pressure = normalization::make_point_replaced_residual_factors(metric, 5.0, point_rows, 7.0);
|
|
REQUIRE(pressure);
|
|
CHECK((*pressure)[0] == (*enthalpy)[0]);
|
|
CHECK((*pressure)[2] == (*enthalpy)[2]);
|
|
CHECK((*pressure)[1] == Catch::Approx(1.0 / 7.0));
|
|
CHECK((*pressure)[3] == Catch::Approx(1.0 / 7.0));
|
|
}
|
|
|
|
TEST_CASE("Point normalization rejects duplicate and out-of-range physical row selections", "[normalization][unit][validation]")
|
|
{
|
|
const std::array metric{4.0, 9.0};
|
|
const auto duplicate = normalization::make_point_replaced_residual_factors(metric, 1.0, std::array{1, 1}, 1.0);
|
|
REQUIRE_FALSE(duplicate);
|
|
CHECK_THAT(duplicate.error(), Catch::Matchers::ContainsSubstring("INVALID_ARGUMENT"));
|
|
for (const int row : {-1, 2})
|
|
{
|
|
const auto outside = normalization::make_point_replaced_residual_factors(metric, 1.0, std::array{row}, 1.0);
|
|
REQUIRE_FALSE(outside);
|
|
CHECK_THAT(outside.error(), Catch::Matchers::ContainsSubstring("OUT_OF_RANGE_ERROR"));
|
|
}
|
|
CHECK_FALSE(normalization::make_point_replaced_residual_factors({}, 1.0, std::array{0}, 1.0));
|
|
}
|
|
|
|
TEST_CASE("Only replaced residual rows may have unusable volume metrics", "[normalization][unit][validation]")
|
|
{
|
|
for (const double invalid : {0.0, -1.0, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::infinity()})
|
|
{
|
|
const std::array metric{4.0, invalid};
|
|
const auto replaced = normalization::make_point_replaced_residual_factors(metric, 2.0, std::array{1}, 5.0);
|
|
REQUIRE(replaced);
|
|
CHECK((*replaced)[0] == Catch::Approx(0.25));
|
|
CHECK((*replaced)[1] == Catch::Approx(0.2));
|
|
CHECK_FALSE(normalization::make_point_replaced_residual_factors(metric, 2.0, {}, 5.0));
|
|
CHECK_FALSE(normalization::make_point_replaced_residual_factors(metric, invalid, std::array{1}, 5.0));
|
|
CHECK_FALSE(normalization::make_point_replaced_residual_factors(metric, 2.0, std::array{1}, invalid));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Point row composition validates factors only in the representations actually used", "[normalization][unit][math]")
|
|
{
|
|
const auto extreme_bulk = normalization::make_point_replaced_residual_factors(std::array{1.0e300, 0.0}, 1.0e-310, std::array{1}, 2.0);
|
|
REQUIRE(extreme_bulk);
|
|
CHECK((*extreme_bulk)[0] == Catch::Approx(1.0e160).epsilon(1.0e-12));
|
|
CHECK((*extreme_bulk)[1] == 0.5);
|
|
|
|
const auto no_points = normalization::make_point_replaced_residual_factors(std::array{4.0}, 2.0, {}, 1.0e-310);
|
|
REQUIRE(no_points);
|
|
CHECK(no_points->front() == 0.25);
|
|
CHECK_FALSE(normalization::make_point_replaced_residual_factors(std::array{4.0}, 2.0, std::array{0}, 1.0e-310));
|
|
|
|
const auto no_bulk = normalization::make_point_replaced_residual_factors(std::array{0.0}, 1.0e-310, std::array{0}, 2.0);
|
|
REQUIRE(no_bulk);
|
|
CHECK(no_bulk->front() == 0.5);
|
|
const auto empty = normalization::make_point_replaced_residual_factors({}, 1.0e-310, {}, 1.0e-310);
|
|
REQUIRE(empty);
|
|
CHECK(empty->empty());
|
|
const auto empty_factors = normalization::make_riesz_factors(serif::discretization::blocks::RepresentedValueKind::residual, {}, 1.0e-310);
|
|
REQUIRE(empty_factors);
|
|
CHECK(empty_factors->empty());
|
|
}
|