feat(newton): first newton solver implementation

This commit is contained in:
2026-09-08 06:36:39 -04:00
parent 76818f2f82
commit b3c04d507a
98 changed files with 20397 additions and 11040 deletions

View File

@@ -6,6 +6,7 @@
#include <numbers>
#include <stdexcept>
#include <type_traits>
#include <utility>
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>
@@ -18,12 +19,12 @@ namespace material_surface_runtime_contract_test {
struct RegisteredAlternateEquationOfState final {
struct Parameters final { };
using ModelDefinition = mean_field::models::ConstitutiveLaw<
RegisteredAlternateEquationOfState,
"RegisteredAlternateMaterialSurfaceEquationOfState">;
using ModelDefinition = mean_field::models::
ConstitutiveLaw<RegisteredAlternateEquationOfState, "RegisteredAlternateMaterialSurfaceEquationOfState">;
using Relations = mean_field::eos::RelationCatalog<mean_field::eos::SpecificEnthalpyFromPressure>;
explicit RegisteredAlternateEquationOfState(Parameters) noexcept { }
explicit RegisteredAlternateEquationOfState(Parameters) noexcept {
}
[[nodiscard]] mean_field::dimensions::SpecificEnthalpyValue evaluate(
mean_field::eos::SpecificEnthalpyFromPressure,
@@ -40,7 +41,10 @@ namespace material_surface_runtime_contract_test {
using mfem::Operator::Operator;
void Mult(const mfem::Vector &, mfem::Vector &) const override;
void Mult(
const mfem::Vector &,
mfem::Vector &
) const override;
[[nodiscard]] const mean_field::operators::StellarEquilibriumLayout &GetLayout() const noexcept;
[[nodiscard]] mean_field::operators::PreparedStellarEquilibriumReport Prepare(
@@ -58,8 +62,7 @@ namespace material_surface_runtime_contract_test {
GetSurfaceConstraintOperator() const;
};
template <mean_field::model::StellarModelType Model>
class AlternateEquationOfStateRuntime final {
template <mean_field::model::StellarModelType Model> class AlternateEquationOfStateRuntime final {
public:
using Report = mean_field::operators::EmptySpecificationPreparationReport;
@@ -68,10 +71,17 @@ namespace material_surface_runtime_contract_test {
const mean_field::mapping::DomainMapper &,
AlternatePhysicalCore &,
const Model &
) noexcept { }
) noexcept {
}
template <typename StateView, typename Controls>
void ReadPhysicalControls(const StateView &, Controls &) noexcept { }
template <
typename StateView,
typename Controls>
void ReadPhysicalControls(
const StateView &,
Controls &
) noexcept {
}
template <typename StateView>
[[nodiscard]] Report PrepareAfterPhysical(
@@ -82,15 +92,18 @@ namespace material_surface_runtime_contract_test {
return {};
}
template <typename ResidualView>
void AddResidual(const ResidualView &) const noexcept { }
template <typename ResidualView> void AddResidual(const ResidualView &) const noexcept {
}
template <typename DirectionView, typename ActionView>
template <
typename DirectionView,
typename ActionView>
void AddJacobianAction(
const DirectionView &,
const ActionView &,
const AlternatePhysicalCore &
) const noexcept { }
) const noexcept {
}
[[nodiscard]] constexpr bool IsPrepared() const noexcept {
return true;
@@ -100,10 +113,9 @@ namespace material_surface_runtime_contract_test {
namespace mean_field::operators {
template <>
struct StellarEquilibriumCoreRuntime<
material_surface_runtime_contract_test::RegisteredAlternateEquationOfState> {
struct StellarEquilibriumCoreRuntime<material_surface_runtime_contract_test::RegisteredAlternateEquationOfState> {
static constexpr bool registered = true;
using CoreType = material_surface_runtime_contract_test::AlternatePhysicalCore;
using CoreType = material_surface_runtime_contract_test::AlternatePhysicalCore;
[[nodiscard]] static std::unique_ptr<CoreType> Make(
fem::FEM &,
@@ -134,7 +146,7 @@ namespace mean_field::preconditioning {
struct MaterialSurfaceEquationOfStateBackend<
material_surface_runtime_contract_test::RegisteredAlternateEquationOfState> {
static constexpr bool registered = true;
using CoreType = material_surface_runtime_contract_test::AlternatePhysicalCore;
using CoreType = material_surface_runtime_contract_test::AlternatePhysicalCore;
};
} // namespace mean_field::preconditioning
@@ -150,12 +162,12 @@ namespace {
mean_field::constraint::FixedCentralDensity>>;
using PolytropicProblem = mean_field::equilibrium::StellarEquilibriumProblem<PolytropicModel>;
using PolytropicMaterialSurfaceDescriptor = preconditioning::MaterialSurfaceDescriptorFor<PolytropicProblem>;
using RegisteredAlternateModel = mean_field::model::StellarModel<mean_field::models::SpecificationSet<
using RegisteredAlternateModel = mean_field::model::StellarModel<mean_field::models::SpecificationSet<
material_surface_runtime_contract_test::RegisteredAlternateEquationOfState,
mean_field::surface::Isobaric,
mean_field::integral::FixedTotalMass>>;
using RegisteredAlternateProblem = mean_field::equilibrium::StellarEquilibriumProblem<RegisteredAlternateModel>;
using MaterialSurfaceDiagonal = preconditioning::MaterialSurfaceBlock<
using MaterialSurfaceDiagonal = preconditioning::MaterialSurfaceBlock<
PolytropicMaterialSurfaceDescriptor,
backend::Diagonal,
backend::Diagonal,
@@ -174,10 +186,8 @@ namespace {
PolytropicMaterialSurfaceDescriptor,
preconditioning::ApproximateMaterialSurfaceLDU,
backend::FixedCycles>;
using RegisteredAlternateGravityComponent = preconditioning::GravityFieldBlock<
backend::Diagonal,
FixedCycleAMG,
preconditioning::GravityApproximateLDU>;
using RegisteredAlternateGravityComponent =
preconditioning::GravityFieldBlock<backend::Diagonal, FixedCycleAMG, preconditioning::GravityApproximateLDU>;
using RegisteredAlternateMaterialSurfaceDescriptor =
preconditioning::MaterialSurfaceDescriptorFor<RegisteredAlternateProblem>;
@@ -185,9 +195,8 @@ namespace {
struct DistinctPhysicalCore final { };
template <typename Problem>
concept CanMakeDefaultMaterialSurface = requires(const Problem &problem) {
preconditioning::materialSurfaceBlock(problem);
};
concept CanMakeDefaultMaterialSurface =
requires(const Problem &problem) { preconditioning::materialSurfaceBlock(problem); };
template <typename Problem>
concept CanPrepareDefaultMaterialSurface = requires(const Problem &problem) {
@@ -195,9 +204,8 @@ namespace {
};
template <typename Problem>
concept CanMakeDefaultStellarStructure = requires(const Problem &problem) {
preconditioning::stellarStructureBlock(problem);
};
concept CanMakeDefaultStellarStructure =
requires(const Problem &problem) { preconditioning::stellarStructureBlock(problem); };
class KnownCouplings final {
public:
@@ -315,41 +323,46 @@ TEST_CASE(
STATIC_CHECK(preconditioning::PreconditionerComponent<MaterialSurfaceDiagonal>);
STATIC_CHECK(preconditioning::PreconditionerComponent<MaterialSurfaceH1>);
STATIC_CHECK(preconditioning::MaterialSurfaceDescriptor<PolytropicMaterialSurfaceDescriptor>);
STATIC_CHECK(preconditioning::ImplementedMaterialSurfaceEquationOfState<
mean_field::eos::Polytrope>);
STATIC_CHECK(preconditioning::ImplementedMaterialSurfaceEquationOfState<mean_field::eos::Polytrope>);
STATIC_CHECK_FALSE(preconditioning::ImplementedMaterialSurfaceEquationOfState<int>);
STATIC_CHECK(preconditioning::ImplementedMaterialSurfaceDescriptor<PolytropicMaterialSurfaceDescriptor>);
STATIC_CHECK(
preconditioning::ExecutableMaterialSurfaceRuntimeFor<
mean_field::eos::Polytrope, mean_field::operators::PreparedStellarEquilibriumOperator>
);
STATIC_CHECK(
std::same_as<
typename preconditioning::MaterialSurfaceEquationOfStateBackend<mean_field::eos::Polytrope>::CoreType,
mean_field::operators::PreparedStellarEquilibriumOperator>
);
STATIC_CHECK(
preconditioning::MaterialSurfaceRuntimeFor<
PolytropicMaterialSurfaceDescriptor, mean_field::operators::PreparedStellarEquilibriumOperator>
);
STATIC_CHECK_FALSE(
preconditioning::ImplementedMaterialSurfaceEquationOfState<int>);
STATIC_CHECK(preconditioning::ImplementedMaterialSurfaceDescriptor<
PolytropicMaterialSurfaceDescriptor>);
STATIC_CHECK(preconditioning::ExecutableMaterialSurfaceRuntimeFor<
mean_field::eos::Polytrope,
mean_field::operators::PreparedStellarEquilibriumOperator>);
STATIC_CHECK(std::same_as<
typename preconditioning::MaterialSurfaceEquationOfStateBackend<
mean_field::eos::Polytrope>::CoreType,
mean_field::operators::PreparedStellarEquilibriumOperator>);
STATIC_CHECK(preconditioning::MaterialSurfaceRuntimeFor<
PolytropicMaterialSurfaceDescriptor,
mean_field::operators::PreparedStellarEquilibriumOperator>);
STATIC_CHECK_FALSE(preconditioning::MaterialSurfaceRuntimeFor<
PolytropicMaterialSurfaceDescriptor,
DistinctPhysicalCore>);
STATIC_CHECK(preconditioning::MaterialSurfaceDescriptor<
RegisteredAlternateMaterialSurfaceDescriptor>);
preconditioning::MaterialSurfaceRuntimeFor<PolytropicMaterialSurfaceDescriptor, DistinctPhysicalCore>
);
STATIC_CHECK(preconditioning::MaterialSurfaceDescriptor<RegisteredAlternateMaterialSurfaceDescriptor>);
STATIC_CHECK(mean_field::equilibrium::StellarEquilibriumModel<RegisteredAlternateModel>);
STATIC_CHECK(std::same_as<
typename RegisteredAlternateProblem::PhysicalCoreType,
material_surface_runtime_contract_test::AlternatePhysicalCore>);
STATIC_CHECK(preconditioning::ImplementedMaterialSurfaceEquationOfState<
material_surface_runtime_contract_test::RegisteredAlternateEquationOfState>);
STATIC_CHECK(preconditioning::ImplementedMaterialSurfaceDescriptor<
RegisteredAlternateMaterialSurfaceDescriptor>);
STATIC_CHECK_FALSE(preconditioning::ExecutableMaterialSurfaceRuntimeFor<
material_surface_runtime_contract_test::RegisteredAlternateEquationOfState,
material_surface_runtime_contract_test::AlternatePhysicalCore>);
STATIC_CHECK_FALSE(preconditioning::MaterialSurfaceRuntimeFor<
RegisteredAlternateMaterialSurfaceDescriptor,
material_surface_runtime_contract_test::AlternatePhysicalCore>);
STATIC_CHECK(
std::same_as<
typename RegisteredAlternateProblem::PhysicalCoreType,
material_surface_runtime_contract_test::AlternatePhysicalCore>
);
STATIC_CHECK(
preconditioning::ImplementedMaterialSurfaceEquationOfState<
material_surface_runtime_contract_test::RegisteredAlternateEquationOfState>
);
STATIC_CHECK(preconditioning::ImplementedMaterialSurfaceDescriptor<RegisteredAlternateMaterialSurfaceDescriptor>);
STATIC_CHECK_FALSE(
preconditioning::ExecutableMaterialSurfaceRuntimeFor<
material_surface_runtime_contract_test::RegisteredAlternateEquationOfState,
material_surface_runtime_contract_test::AlternatePhysicalCore>
);
STATIC_CHECK_FALSE(
preconditioning::MaterialSurfaceRuntimeFor<
RegisteredAlternateMaterialSurfaceDescriptor, material_surface_runtime_contract_test::AlternatePhysicalCore>
);
STATIC_CHECK(preconditioning::MaterialSurfacePreconditionerProblem<PolytropicProblem>);
STATIC_CHECK_FALSE(preconditioning::MaterialSurfacePreconditionerProblem<RegisteredAlternateProblem>);
STATIC_CHECK(CanMakeDefaultMaterialSurface<PolytropicProblem>);
@@ -357,10 +370,10 @@ TEST_CASE(
STATIC_CHECK(CanPrepareDefaultMaterialSurface<PolytropicProblem>);
STATIC_CHECK_FALSE(CanPrepareDefaultMaterialSurface<RegisteredAlternateProblem>);
STATIC_CHECK_FALSE(preconditioning::StellarStructurePreconditionerProblem<RegisteredAlternateProblem>);
STATIC_CHECK_FALSE(preconditioning::StellarStructurePreparableFor<
RegisteredAlternateProblem,
MaterialSurfaceDiagonal,
RegisteredAlternateGravityComponent>);
STATIC_CHECK_FALSE(
preconditioning::StellarStructurePreparableFor<
RegisteredAlternateProblem, MaterialSurfaceDiagonal, RegisteredAlternateGravityComponent>
);
STATIC_CHECK_FALSE(CanMakeDefaultStellarStructure<RegisteredAlternateProblem>);
STATIC_CHECK(
mean_field::material::CompiledThermodynamicEquations<typename PolytropicProblem::ThermodynamicEquationsType>
@@ -572,9 +585,10 @@ TEST_CASE(
const utils::Args arguments = test_utils::setup_args();
fem::FEM finiteElements = fem::setup_fem(arguments.mesh_file, arguments, 0);
REQUIRE(finiteElements.okay());
const mfem::ParFiniteElementSpace *surfaceDeformationSpace = finiteElements.surfaceDeformationFes.get();
constexpr double radius = utils::RADIUS;
constexpr double mass = utils::MASS;
constexpr double radius = utils::RADIUS;
constexpr double mass = utils::MASS;
const double polytropicConstant = 2.0 * utils::G * radius * radius / std::numbers::pi_v<double>;
const double centralDensity = std::numbers::pi_v<double> * mass / (4.0 * radius * radius * radius);
const auto stellarModel = model::StellarModel(
@@ -583,7 +597,7 @@ TEST_CASE(
integral::FixedTotalMass({.Mtotal = dimensions::MassValue{mass}}),
constraint::FixedCentralDensity({.RhoC = dimensions::DensityValue{centralDensity}})
);
auto problem = equilibrium::discretize(stellarModel, finiteElements);
auto problem = equilibrium::discretize(stellarModel, std::move(finiteElements));
auto projected = seed::makeProjectedEquilibriumState(problem, seed::LaneEmden({.radialSampleCount = 512}));
const auto rotation = zeroRotation();
problem.Prepare(projected.values, makeDependencies(), rotation);
@@ -711,7 +725,7 @@ TEST_CASE(
CHECK(surfaceFit.relativeGramDeterminant > 1.0e-12);
CHECK(surfaceFit.normalEquations.targetTarget > 0.0);
CHECK(frequencyAware.GetSurfaceInverse().Height() == physical.GetDomainDeformation().parameterCount());
CHECK(frequencyAware.GetSurfaceSurrogateMatrix().Height() == finiteElements.surfaceDeformationFes->GetTrueVSize());
CHECK(frequencyAware.GetSurfaceSurrogateMatrix().Height() == surfaceDeformationSpace->GetTrueVSize());
CHECK(frequencyAware.GetSurfaceBackend().GetStatistics().setups == 1);
CHECK(frequencyAware.GetStatistics().surfaceJacobianProbes == 4);
CHECK(frequencyAware.GetStatistics().surfaceH1Assemblies == 3);