feat(libmeanfield): variadic refactor

also added normaliztion operator
This commit is contained in:
2026-09-06 10:15:00 -04:00
parent 71423d543f
commit 76818f2f82
63 changed files with 28794 additions and 1119 deletions

View File

@@ -2,6 +2,7 @@
#include <type_traits>
#include <catch2/catch_test_macros.hpp>
#include <mfem.hpp>
import mean_field;
import test_helpers;
@@ -11,6 +12,25 @@ namespace {
const mean_field::utils::Args arguments = test_utils::setup_args();
return mean_field::fem::setup_fem(arguments.mesh_file, arguments, 0);
}
template <typename Problem>
concept PreparesWithGeneratedRotation = requires(
Problem &problem,
const mfem::Vector &state,
const mean_field::operators::StellarEquilibriumDependencies &dependencies
) {
problem.Prepare(state, dependencies);
};
template <typename Problem>
concept PreparesWithPrescribedRotation = requires(
Problem &problem,
const mfem::Vector &state,
const mean_field::operators::StellarEquilibriumDependencies &dependencies,
const mean_field::physics::RigidRotation &rotation
) {
problem.Prepare(state, dependencies, rotation);
};
} // namespace
TEST_CASE(
@@ -42,6 +62,49 @@ TEST_CASE(
CHECK(gravity.potentialSchurBackend().application.cycles == 3);
}
TEST_CASE(
"Fixed Angular Momentum User API Generates Rotation And Its Composable Solver Border",
"[user-api][fixed-angular-momentum][type]"
) {
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}}),
integral::FixedAngularMomentum({
.Jtotal = dimensions::AngularMomentumValue{0.2},
.axis = {0.0, 0.0, 2.0}
})
);
auto problem = equilibrium::discretize(model, finiteElements);
auto preconditioner = preconditioning::makePreconditioner(problem);
using Problem = std::remove_cvref_t<decltype(problem)>;
using Preconditioner = std::remove_cvref_t<decltype(preconditioner)>;
STATIC_CHECK(Problem::hasFixedAngularMomentum);
STATIC_CHECK_FALSE(Problem::hasFixedCentralDensity);
STATIC_CHECK(PreparesWithGeneratedRotation<Problem>);
STATIC_CHECK_FALSE(PreparesWithPrescribedRotation<Problem>);
STATIC_CHECK(Problem::FormType::value_block_count == 7);
STATIC_CHECK(Problem::FormType::residual_block_count == 7);
STATIC_CHECK(preconditioning::PreconditionerComponent<Preconditioner>);
STATIC_CHECK(Preconditioner::borderValueArity == 2);
STATIC_CHECK(Preconditioner::borderResidualArity == 2);
CHECK(problem.StateSize() == problem.EquationSize());
CHECK(problem.StateSize() == problem.GetPhysicalOperator().Width() + 1);
REQUIRE(problem.GetManifest().constraints().size() == 3);
CHECK(problem.GetManifest().template specification<models::FixedAngularMomentum>().stableId ==
"FixedAngularMomentum");
CHECK(problem.GetManifest().valueBlocks().back().symbol == "Omega");
CHECK(problem.GetManifest().residualBlocks().back().symbol == "R_J");
}
TEST_CASE(
"Intermediate User API Selects A Coupled Stellar Factorization",
"[user-api][intermediate]"