feat(preconditioner): major work on preconditioner system
first preconditioner MVP
This commit is contained in:
116
tests/user-api/stellar_equilibrium.cpp
Normal file
116
tests/user-api/stellar_equilibrium.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
import mean_field;
|
||||
import test_helpers;
|
||||
|
||||
namespace {
|
||||
[[nodiscard]] mean_field::fem::FEM makeFiniteElements() {
|
||||
const mean_field::utils::Args arguments = test_utils::setup_args();
|
||||
return mean_field::fem::setup_fem(arguments.mesh_file, arguments, 0);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE(
|
||||
"Simple User API Builds A Stellar Model With Its Default Preconditioner",
|
||||
"[user-api][simple]"
|
||||
) {
|
||||
using namespace mean_field;
|
||||
|
||||
auto finiteElements = makeFiniteElements();
|
||||
REQUIRE(finiteElements.okay());
|
||||
|
||||
auto model = model::StellarModel(
|
||||
eos::Polytrope({.n = 1.0, .K = 0.25}), surface::Isobaric({.Psurf = dimensions::PressureValue{0.0}}),
|
||||
integral::FixedTotalMass({.Mtotal = dimensions::MassValue{1.0}})
|
||||
);
|
||||
|
||||
auto problem = equilibrium::discretize(model, finiteElements);
|
||||
auto preconditioner = preconditioning::makePreconditioner(problem);
|
||||
const auto &gravity = preconditioner.structureComponent().gravityComponent();
|
||||
|
||||
STATIC_CHECK(preconditioning::PreconditionerComponent<decltype(preconditioner)>);
|
||||
STATIC_CHECK(
|
||||
std::same_as<
|
||||
typename std::remove_cvref_t<decltype(gravity)>::MassBackend, preconditioning::backend::MatrixFreeChebyshev>
|
||||
);
|
||||
CHECK(problem.StateSize() == problem.EquationSize());
|
||||
CHECK(decltype(preconditioner)::borderValueArity == 1);
|
||||
CHECK(gravity.massInverseBackend().order == 5);
|
||||
CHECK(gravity.potentialSchurBackend().application.cycles == 3);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Intermediate User API Selects A Coupled Stellar Factorization",
|
||||
"[user-api][intermediate]"
|
||||
) {
|
||||
using namespace mean_field;
|
||||
|
||||
auto finiteElements = makeFiniteElements();
|
||||
REQUIRE(finiteElements.okay());
|
||||
|
||||
auto model = model::StellarModel(
|
||||
eos::Polytrope({.n = 3.0, .K = 0.25}), surface::Isobaric({.Psurf = dimensions::PressureValue{0.0}}),
|
||||
integral::FixedTotalMass({.Mtotal = dimensions::MassValue{1.0}}),
|
||||
constraint::FixedCentralDensity({.RhoC = dimensions::DensityValue{1.0}})
|
||||
);
|
||||
auto problem = equilibrium::discretize(model, finiteElements);
|
||||
|
||||
auto material = preconditioning::materialSurfaceBlock(problem);
|
||||
auto gravity = preconditioning::GravityFieldBlock(
|
||||
preconditioning::backend::Diagonal{},
|
||||
preconditioning::backend::HypreBoomerAMG(preconditioning::backend::FixedCycles{.cycles = 2}),
|
||||
preconditioning::GravityApproximateLDU{}
|
||||
);
|
||||
auto structure = preconditioning::stellarStructureBlock(
|
||||
problem, material, gravity, preconditioning::ApproximateStellarBlockLDU{}
|
||||
);
|
||||
auto preconditioner = preconditioning::specificationBorderBlock(problem, structure);
|
||||
|
||||
STATIC_CHECK(preconditioning::PreconditionerComponent<decltype(preconditioner)>);
|
||||
STATIC_CHECK(preconditioning::backend::ArnoldiAdmissible<typename decltype(preconditioner)::BackendType>);
|
||||
CHECK(decltype(preconditioner)::borderValueArity == 2);
|
||||
}
|
||||
|
||||
TEST_CASE(
|
||||
"Advanced User API Composes Explicit Blocks Backends And Application Modes",
|
||||
"[user-api][advanced]"
|
||||
) {
|
||||
using namespace mean_field;
|
||||
|
||||
auto finiteElements = makeFiniteElements();
|
||||
REQUIRE(finiteElements.okay());
|
||||
|
||||
auto model = model::StellarModel(
|
||||
eos::Polytrope({.n = 3.0, .K = 0.25}), surface::Isobaric({.Psurf = dimensions::PressureValue{0.0}}),
|
||||
integral::FixedTotalMass({.Mtotal = dimensions::MassValue{1.0}}),
|
||||
constraint::FixedCentralDensity({.RhoC = dimensions::DensityValue{1.0}})
|
||||
);
|
||||
auto problem = equilibrium::discretize(model, finiteElements);
|
||||
|
||||
auto material = preconditioning::materialSurfaceBlock(
|
||||
problem, preconditioning::backend::Diagonal{}, preconditioning::backend::Diagonal{},
|
||||
preconditioning::MaterialThenSurfaceTriangular{}, {.relativeFloor = 1.0e-10, .absoluteFloor = 1.0e-13}
|
||||
);
|
||||
auto gravity = preconditioning::GravityFieldBlock(
|
||||
preconditioning::backend::Diagonal{},
|
||||
preconditioning::backend::HypreBoomerAMG(
|
||||
preconditioning::backend::SolveToTolerance{.relativeTolerance = 1.0e-8, .maximumCycles = 20}
|
||||
),
|
||||
preconditioning::GravityUpperTriangular{}
|
||||
);
|
||||
auto structure = preconditioning::stellarStructureBlock(
|
||||
problem, material, gravity, preconditioning::MaterialThenGravityTriangular{}
|
||||
);
|
||||
auto preconditioner =
|
||||
preconditioning::specificationBorderBlock(problem, structure, preconditioning::backend::DenseDirect{});
|
||||
|
||||
STATIC_CHECK(preconditioning::PreconditionerComponent<decltype(preconditioner)>);
|
||||
STATIC_CHECK_FALSE(preconditioning::backend::ArnoldiAdmissible<typename decltype(preconditioner)::BackendType>);
|
||||
CHECK(preconditioner.structureComponent().materialSurfaceComponent().diagonalOptions().relativeFloor == 1.0e-10);
|
||||
CHECK(
|
||||
preconditioner.structureComponent().gravityComponent().potentialSchurBackend().application.maximumCycles == 20
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user