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

@@ -7,13 +7,13 @@
import mean_field;
namespace {
namespace blocks = mean_field::utils::blocks;
namespace blocks = mean_field::utils::blocks;
namespace normalization = mean_field::normalization;
using PhysicalForm = blocks::surface_deformed_stellar_equilibrium_form;
using PhaseForm = blocks::central_density_bordered_stellar_equilibrium_form;
using PhysicalPlan = normalization::PhysicalRieszNormalizationPlanFor<PhysicalForm>;
using PhasePlan = normalization::PhysicalRieszNormalizationPlanFor<PhaseForm>;
using PhysicalForm = blocks::surface_deformed_stellar_equilibrium_form;
using PhaseForm = blocks::central_density_bordered_stellar_equilibrium_form;
using PhysicalPlan = normalization::PhysicalRieszNormalizationPlanFor<PhysicalForm>;
using PhasePlan = normalization::PhysicalRieszNormalizationPlanFor<PhaseForm>;
struct ValueA final : blocks::value_block_base { };
struct ValueB final : blocks::value_block_base { };
@@ -22,9 +22,7 @@ namespace {
struct ForeignValue final : blocks::value_block_base { };
struct ForeignResidual final : blocks::residual_block_base { };
using SmallForm = blocks::block_form<
blocks::type_list<ValueA, ValueB>,
blocks::type_list<ResidualA, ResidualB>>;
using SmallForm = blocks::block_form<blocks::type_list<ValueA, ValueB>, blocks::type_list<ResidualA, ResidualB>>;
using ValueAIdentity = normalization::CoordinateComponent<
normalization::CoordinateKind::value,
blocks::type_list<ValueA>,
@@ -50,21 +48,11 @@ namespace {
blocks::type_list<ForeignResidual>,
normalization::IdentityCoordinate>;
using CompleteSmallPlan = normalization::NormalizationPlan<
ValueAIdentity,
ValueBIdentity,
ResidualAIdentity,
ResidualBIdentity>;
using MissingSmallPlan = normalization::NormalizationPlan<
ValueAIdentity,
ResidualAIdentity,
ResidualBIdentity>;
using DuplicateSmallPlan = normalization::NormalizationPlan<
ValueAIdentity,
ValueAIdentity,
ValueBIdentity,
ResidualAIdentity,
ResidualBIdentity>;
using CompleteSmallPlan =
normalization::NormalizationPlan<ValueAIdentity, ValueBIdentity, ResidualAIdentity, ResidualBIdentity>;
using MissingSmallPlan = normalization::NormalizationPlan<ValueAIdentity, ResidualAIdentity, ResidualBIdentity>;
using DuplicateSmallPlan = normalization::
NormalizationPlan<ValueAIdentity, ValueAIdentity, ValueBIdentity, ResidualAIdentity, ResidualBIdentity>;
using ForeignSmallPlan = normalization::NormalizationPlan<
ValueAIdentity,
ValueBIdentity,
@@ -79,11 +67,11 @@ namespace {
};
struct IncoherentComponent final {
using Blocks = blocks::type_list<ValueA>;
using Method = normalization::IdentityCoordinate;
using ValueBlocks = blocks::type_list<ValueB>;
using ResidualBlocks = blocks::type_list<>;
static constexpr auto kind = normalization::CoordinateKind::value;
using Blocks = blocks::type_list<ValueA>;
using Method = normalization::IdentityCoordinate;
using ValueBlocks = blocks::type_list<ValueB>;
using ResidualBlocks = blocks::type_list<>;
static constexpr auto kind = normalization::CoordinateKind::value;
};
using WrongDensityTopology = normalization::CoordinateComponent<
@@ -95,40 +83,34 @@ namespace {
struct FutureInvariantValue final : blocks::value_block_base { };
struct FutureInvariantResidual final : blocks::residual_block_base { };
using UnregisteredFutureForm = blocks::block_form<
blocks::type_list<FutureInvariantValue>,
blocks::type_list<FutureInvariantResidual>>;
using UnregisteredFutureForm =
blocks::block_form<blocks::type_list<FutureInvariantValue>, blocks::type_list<FutureInvariantResidual>>;
using BaseModel = mean_field::model::StellarModel<mean_field::models::SpecificationSet<
using BaseModel = mean_field::model::StellarModel<mean_field::models::SpecificationSet<
mean_field::eos::Polytrope,
mean_field::surface::Isobaric,
mean_field::integral::FixedTotalMass>>;
using RieszPolicy = normalization::PhysicalRieszDiagonal<>;
using RieszPolicy = normalization::PhysicalRieszDiagonal<>;
using RieszDiscretization = mean_field::equilibrium::StellarDiscretizationFor<RieszPolicy>;
using BaselineProblem = mean_field::equilibrium::StellarEquilibriumProblem<BaseModel>;
using RieszProblem = mean_field::equilibrium::StellarEquilibriumProblem<BaseModel, RieszDiscretization>;
using AngularModel = mean_field::model::StellarModel<mean_field::models::SpecificationSet<
using BaselineProblem = mean_field::equilibrium::StellarEquilibriumProblem<BaseModel>;
using RieszProblem = mean_field::equilibrium::StellarEquilibriumProblem<BaseModel, RieszDiscretization>;
using AngularModel = mean_field::model::StellarModel<mean_field::models::SpecificationSet<
mean_field::eos::Polytrope,
mean_field::surface::Isobaric,
mean_field::integral::FixedTotalMass,
mean_field::integral::FixedAngularMomentum>>;
using AngularForm = mean_field::operators::CompiledStellarEquilibriumForm<AngularModel>;
using AngularForm = mean_field::operators::CompiledStellarEquilibriumForm<AngularModel>;
template <typename Mapper>
concept CanMakeRieszDiscretization = requires(
mean_field::fem::FEM &finiteElements,
Mapper &&mapper,
RieszPolicy policy
) {
mean_field::equilibrium::makeStellarDiscretization(
finiteElements,
std::forward<Mapper>(mapper),
policy
);
template <typename FiniteElements>
concept CanMakeRieszDiscretization = requires(FiniteElements &&finiteElements, RieszPolicy policy) {
mean_field::equilibrium::makeStellarDiscretization(std::forward<FiniteElements>(finiteElements), policy);
};
} // namespace
TEST_CASE("Normalization Plans Prove Exact Ownership Of Every Compiled Coordinate", "[normalization][type]") {
TEST_CASE(
"Normalization Plans Prove Exact Ownership Of Every Compiled Coordinate",
"[normalization][type]"
) {
STATIC_CHECK(normalization::NormalizationPlanType<PhysicalPlan>);
STATIC_CHECK(normalization::CompleteNormalizationFor<PhysicalPlan, PhysicalForm>);
STATIC_CHECK(normalization::CompleteNormalizationFor<PhasePlan, PhaseForm>);
@@ -136,17 +118,19 @@ TEST_CASE("Normalization Plans Prove Exact Ownership Of Every Compiled Coordinat
STATIC_CHECK(normalization::CompilableNormalizationFor<RieszPolicy, PhysicalForm>);
STATIC_CHECK(normalization::CompilableNormalizationFor<RieszPolicy, PhaseForm>);
STATIC_CHECK(normalization::CompilableNormalizationFor<RieszPolicy, AngularForm>);
STATIC_CHECK(normalization::StellarSpecificationNormalizationContribution<
mean_field::integral::FixedAngularMomentum>::registered);
STATIC_CHECK(
normalization::StellarSpecificationNormalizationContribution<
mean_field::integral::FixedAngularMomentum>::registered
);
STATIC_CHECK(normalization::CompleteNormalizationFor<CompleteSmallPlan, SmallForm>);
STATIC_CHECK_FALSE(normalization::CompleteNormalizationFor<MissingSmallPlan, SmallForm>);
STATIC_CHECK_FALSE(normalization::CompleteNormalizationFor<DuplicateSmallPlan, SmallForm>);
STATIC_CHECK_FALSE(normalization::CompleteNormalizationFor<ForeignSmallPlan, SmallForm>);
using Missing = normalization::NormalizationCoverage<SmallForm, MissingSmallPlan>;
using Missing = normalization::NormalizationCoverage<SmallForm, MissingSmallPlan>;
using Duplicate = normalization::NormalizationCoverage<SmallForm, DuplicateSmallPlan>;
using Foreign = normalization::NormalizationCoverage<SmallForm, ForeignSmallPlan>;
using Foreign = normalization::NormalizationCoverage<SmallForm, ForeignSmallPlan>;
STATIC_CHECK(Missing::MissingValueBlocks::size == 1);
STATIC_CHECK(blocks::contains_type_v<ValueB, typename Missing::MissingValueBlocks>);
STATIC_CHECK(Duplicate::RepeatedValueBlocks::size == 1);
@@ -155,72 +139,54 @@ TEST_CASE("Normalization Plans Prove Exact Ownership Of Every Compiled Coordinat
STATIC_CHECK(Foreign::UnexpectedResidualBlocks::size == 1);
}
TEST_CASE("Physical Riesz Methods Reject Incompatible Or Unregistered Field Topologies", "[normalization][type]") {
TEST_CASE(
"Physical Riesz Methods Reject Incompatible Or Unregistered Field Topologies",
"[normalization][type]"
) {
STATIC_CHECK_FALSE(normalization::NormalizationComponent<MalformedComponent>);
STATIC_CHECK_FALSE(normalization::NormalizationComponent<IncoherentComponent>);
STATIC_CHECK_FALSE(normalization::NormalizationComponent<WrongDensityTopology>);
STATIC_CHECK_FALSE(normalization::CompilableNormalizationFor<RieszPolicy, UnregisteredFutureForm>);
STATIC_CHECK(normalization::CompilableNormalizationFor<normalization::Unnormalized, UnregisteredFutureForm>);
using Density = normalization::PhysicalRieszBlockTraits<blocks::density::mass::value>;
using Gravity = normalization::PhysicalRieszBlockTraits<blocks::gravity::gradient::value>;
using Surface = normalization::PhysicalRieszBlockTraits<blocks::surface_deformation::parameters::value>;
using Density = normalization::PhysicalRieszBlockTraits<blocks::density::mass::value>;
using Gravity = normalization::PhysicalRieszBlockTraits<blocks::gravity::gradient::value>;
using Surface = normalization::PhysicalRieszBlockTraits<blocks::surface_deformation::parameters::value>;
using EnthalpyResidual = normalization::PhysicalRieszBlockTraits<blocks::enthalpy::specific::residual>;
using MassResidual = normalization::PhysicalRieszBlockTraits<
blocks::fixed_total_mass::mass_normalization::residual>;
using MassResidual =
normalization::PhysicalRieszBlockTraits<blocks::fixed_total_mass::mass_normalization::residual>;
STATIC_CHECK(Density::Method::topology == normalization::RieszTopology::scalar_volume_l2);
STATIC_CHECK(Gravity::Method::topology == normalization::RieszTopology::vector_volume_l2);
STATIC_CHECK(Surface::Method::topology == normalization::RieszTopology::scalar_boundary_l2);
STATIC_CHECK(
EnthalpyResidual::Method::topology == normalization::RieszTopology::hybrid_scalar_volume_point_rows
);
STATIC_CHECK(EnthalpyResidual::Method::topology == normalization::RieszTopology::hybrid_scalar_volume_point_rows);
STATIC_CHECK(MassResidual::Method::topology == normalization::RieszTopology::global_scalar);
STATIC_CHECK(MassResidual::Method::scale == normalization::PhysicalScaleKind::mass);
}
TEST_CASE("Normalization Is Part Of The Compile-Time Discretization And Problem Type", "[normalization][type]") {
TEST_CASE(
"Normalization Is Part Of The Compile-Time Discretization And Problem Type",
"[normalization][type]"
) {
STATIC_CHECK(mean_field::equilibrium::StellarDiscretizationType<RieszDiscretization>);
STATIC_CHECK_FALSE(std::same_as<RieszDiscretization, mean_field::equilibrium::StellarDiscretization>);
STATIC_CHECK_FALSE(std::same_as<RieszProblem, BaselineProblem>);
STATIC_CHECK(std::same_as<typename BaselineProblem::NormalizationPrescriptionType, normalization::Unnormalized>);
STATIC_CHECK(std::same_as<typename RieszProblem::NormalizationPrescriptionType, RieszPolicy>);
STATIC_CHECK(mean_field::equilibrium::DiscretizedStellarEquilibriumProblem<RieszProblem>);
STATIC_CHECK(std::constructible_from<
RieszDiscretization,
mean_field::fem::FEM &,
const mean_field::mapping::DomainMapper &,
RieszPolicy>);
STATIC_CHECK_FALSE(std::constructible_from<
RieszDiscretization,
mean_field::fem::FEM &,
mean_field::mapping::DomainMapper &&,
RieszPolicy>);
STATIC_CHECK_FALSE(std::constructible_from<
RieszDiscretization,
mean_field::fem::FEM &,
const mean_field::mapping::DomainMapper &&,
RieszPolicy>);
STATIC_CHECK(std::constructible_from<
mean_field::equilibrium::StellarDiscretization,
mean_field::fem::FEM &,
const mean_field::mapping::DomainMapper &>);
STATIC_CHECK_FALSE(std::constructible_from<
mean_field::equilibrium::StellarDiscretization,
mean_field::fem::FEM &,
mean_field::mapping::DomainMapper &&>);
STATIC_CHECK_FALSE(std::constructible_from<
mean_field::equilibrium::StellarDiscretization,
mean_field::fem::FEM &,
const mean_field::mapping::DomainMapper &&>);
STATIC_CHECK(CanMakeRieszDiscretization<
mean_field::mapping::DomainMapper &>);
STATIC_CHECK_FALSE(CanMakeRieszDiscretization<
mean_field::mapping::DomainMapper>);
STATIC_CHECK_FALSE(CanMakeRieszDiscretization<
const mean_field::mapping::DomainMapper>);
STATIC_CHECK(std::constructible_from<RieszDiscretization, mean_field::fem::FEM &&, RieszPolicy>);
STATIC_CHECK_FALSE(std::constructible_from<RieszDiscretization, mean_field::fem::FEM &, RieszPolicy>);
STATIC_CHECK_FALSE(std::constructible_from<RieszDiscretization, const mean_field::fem::FEM &, RieszPolicy>);
STATIC_CHECK(std::constructible_from<mean_field::equilibrium::StellarDiscretization, mean_field::fem::FEM &&>);
STATIC_CHECK_FALSE(std::constructible_from<mean_field::equilibrium::StellarDiscretization, mean_field::fem::FEM &>);
STATIC_CHECK_FALSE(
std::constructible_from<mean_field::equilibrium::StellarDiscretization, const mean_field::fem::FEM &>
);
STATIC_CHECK(CanMakeRieszDiscretization<mean_field::fem::FEM>);
STATIC_CHECK_FALSE(CanMakeRieszDiscretization<mean_field::fem::FEM &>);
STATIC_CHECK_FALSE(CanMakeRieszDiscretization<const mean_field::fem::FEM &>);
using SmallLayout = blocks::form_layout<SmallForm>;
using SmallLayout = blocks::form_layout<SmallForm>;
using SmallBuilder = normalization::DiagonalNormalizationBuilder<SmallForm>;
STATIC_CHECK(std::constructible_from<SmallBuilder, const SmallLayout &>);
STATIC_CHECK_FALSE(std::constructible_from<SmallBuilder, SmallLayout &&>);