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

@@ -24,6 +24,7 @@ export namespace mean_field::preconditioning {
operators::StellarEquilibriumDependencyStamp geometry;
const void *equationOfStateIdentity{nullptr};
operators::StellarEquilibriumDependencies linearization;
std::uint64_t preparedOperatorGeneration{0};
constexpr bool operator==(const StellarPreconditionerLifecycleSnapshot &) const = default;
};
@@ -61,7 +62,8 @@ export namespace mean_field::preconditioning {
.discretization = prepared.discretization != current.discretization,
.geometry = prepared.geometry != current.geometry,
.equationOfState = prepared.equationOfStateIdentity != current.equationOfStateIdentity,
.linearization = prepared.linearization != current.linearization
.linearization = prepared.linearization != current.linearization ||
prepared.preparedOperatorGeneration != current.preparedOperatorGeneration
};
}
@@ -95,9 +97,11 @@ export namespace mean_field::preconditioning {
static constexpr bool registered = false;
};
template <equilibrium::StellarEquilibriumModel Model>
struct StellarEquilibriumProblemTraits<equilibrium::StellarEquilibriumProblem<Model>> {
using Problem = equilibrium::StellarEquilibriumProblem<Model>;
template <
equilibrium::StellarEquilibriumModel Model,
equilibrium::StellarDiscretizationType Discretization>
struct StellarEquilibriumProblemTraits<equilibrium::StellarEquilibriumProblem<Model, Discretization>> {
using Problem = equilibrium::StellarEquilibriumProblem<Model, Discretization>;
using Form = typename Problem::FormType;
using JacobianForm = typename Problem::JacobianFormType;
using Manifest = typename Problem::ManifestType;
@@ -130,8 +134,9 @@ export namespace mean_field::preconditioning {
.discretization = dependencies.discretization,
.geometry = problem.GetGeometryDependency(),
.equationOfStateIdentity =
std::addressof(problem.GetStellarModel().template specification<eos::Polytrope>()),
.linearization = dependencies
std::addressof(problem.GetStellarModel().equationOfState()),
.linearization = dependencies,
.preparedOperatorGeneration = problem.GetPreparationGeneration()
};
}
};
@@ -139,6 +144,243 @@ export namespace mean_field::preconditioning {
template <typename Candidate>
concept StellarPreconditionerProblem = StellarEquilibriumProblemTraits<std::remove_cvref_t<Candidate>>::registered;
namespace detail {
template <typename Block>
struct IsGeneratedStellarValueBlock : std::false_type { };
template <typename Generated>
struct IsGeneratedStellarValueBlock<utils::blocks::generated_value_block<Generated>>
: std::true_type { };
template <typename Block>
struct IsGeneratedStellarResidualBlock : std::false_type { };
template <typename Generated>
struct IsGeneratedStellarResidualBlock<utils::blocks::generated_residual_block<Generated>>
: std::true_type { };
template <typename Coupling>
inline constexpr bool isPurePhysicalStellarCoupling =
!IsGeneratedStellarValueBlock<
std::remove_cvref_t<typename Coupling::Value>>::value &&
!IsGeneratedStellarResidualBlock<
std::remove_cvref_t<typename Coupling::Residual>>::value;
/* Pure structure contributions owned by a trusted backend are exact
* (core, specification, coupling) capabilities. Future cores and new
* edges start with no privilege: changing a built-in declaration must
* be accompanied by an explicit preconditioner decision. Generated-
* border terms remain the responsibility of specification-border
* machinery. */
template <typename PhysicalCore, typename Specification>
struct StellarStructureBackendHandledCouplings {
using Type = utils::blocks::type_list<>;
};
template <>
struct StellarStructureBackendHandledCouplings<
operators::PreparedStellarEquilibriumOperator,
models::FixedTotalMass> {
using Type = utils::blocks::type_list<
operators::StellarEquilibriumJacobianCoupling<
utils::blocks::enthalpy::specific::residual,
utils::blocks::density::mass::value>,
operators::StellarEquilibriumJacobianCoupling<
utils::blocks::enthalpy::specific::residual,
utils::blocks::surface_deformation::parameters::value>>;
};
template <>
struct StellarStructureBackendHandledCouplings<
operators::PreparedStellarEquilibriumOperator,
models::FixedAngularMomentum> {
using Type = utils::blocks::type_list<
operators::StellarEquilibriumJacobianCoupling<
utils::blocks::surface_deformation::shape_equilibrium::residual,
utils::blocks::density::mass::value>,
operators::StellarEquilibriumJacobianCoupling<
utils::blocks::surface_deformation::shape_equilibrium::residual,
utils::blocks::surface_deformation::parameters::value>,
operators::StellarEquilibriumJacobianCoupling<
utils::blocks::enthalpy::specific::residual,
utils::blocks::density::mass::value>,
operators::StellarEquilibriumJacobianCoupling<
utils::blocks::enthalpy::specific::residual,
utils::blocks::surface_deformation::parameters::value>>;
};
template <>
struct StellarStructureBackendHandledCouplings<
operators::PreparedStellarEquilibriumOperator,
models::FixedCentralDensity> {
using Type = utils::blocks::type_list<
operators::StellarEquilibriumJacobianCoupling<
utils::blocks::enthalpy::specific::residual,
utils::blocks::enthalpy::specific::value>>;
};
template <
typename Coupling,
typename Model,
typename PhysicalCore,
typename ModelSpecifications>
struct EveryCouplingContributionHandled;
template <
typename Coupling,
model::StellarModelType Model,
typename PhysicalCore,
models::ModelSpecification... Specifications>
struct EveryCouplingContributionHandled<
Coupling,
Model,
PhysicalCore,
models::detail::SpecificationSetStorage<Specifications...>> final {
private:
template <typename Specification>
static constexpr bool handled =
!utils::blocks::contains_type_v<
Coupling,
typename operators::StellarEquilibriumSpecificationCompilation<
Specification>::JacobianCouplings> ||
(operators::stellarEquilibriumBackendRuntimeAuthorized<
Specification,
Model> &&
utils::blocks::contains_type_v<
Coupling,
typename StellarStructureBackendHandledCouplings<
PhysicalCore,
Specification>::Type>) ||
operators::stellarEquilibriumSpecificationCouplingIsStructuralZero<
Specification,
Model,
Coupling>;
public:
static constexpr bool value =
(handled<Specifications> && ...);
};
template <
typename Remaining,
typename Model,
typename PhysicalCore,
typename ModelSpecifications,
typename Unsupported>
struct CollectUnsupportedStellarStructureCouplings;
template <
typename Model,
typename PhysicalCore,
typename ModelSpecifications,
typename Unsupported>
struct CollectUnsupportedStellarStructureCouplings<
utils::blocks::type_list<>,
Model,
PhysicalCore,
ModelSpecifications,
Unsupported> {
using Type = Unsupported;
};
template <
typename Head,
typename... Tail,
typename Model,
typename PhysicalCore,
typename ModelSpecifications,
typename... Unsupported>
struct CollectUnsupportedStellarStructureCouplings<
utils::blocks::type_list<Head, Tail...>,
Model,
PhysicalCore,
ModelSpecifications,
utils::blocks::type_list<Unsupported...>> {
private:
static constexpr bool supported =
!isPurePhysicalStellarCoupling<Head> ||
EveryCouplingContributionHandled<
Head,
Model,
PhysicalCore,
ModelSpecifications>::value;
using Next = std::conditional_t<
supported,
utils::blocks::type_list<Unsupported...>,
utils::blocks::type_list<Unsupported..., Head>>;
public:
using Type = typename CollectUnsupportedStellarStructureCouplings<
utils::blocks::type_list<Tail...>,
Model,
PhysicalCore,
ModelSpecifications,
Next>::Type;
};
template <typename Candidate, typename = void>
struct DefaultStellarStructurePhysicalTopologyAudit {
using ContributionCouplings = utils::blocks::type_list<>;
using UnsupportedCouplings = utils::blocks::type_list<>;
static constexpr bool supported = false;
};
template <model::StellarModelType Model>
requires(
operators::StellarEquilibriumSystemCompilable<
std::remove_cvref_t<Model>> &&
operators::hasStellarEquilibriumCoreRuntime<
std::remove_cvref_t<Model>>)
struct DefaultStellarStructurePhysicalTopologyAudit<
Model,
std::void_t<
typename operators::CompiledStellarEquilibriumSystem<
std::remove_cvref_t<Model>>::ContributionJacobianCouplings,
operators::StellarEquilibriumPhysicalCoreType<
std::remove_cvref_t<Model>>>> {
private:
using Compilation = operators::CompiledStellarEquilibriumSystem<
std::remove_cvref_t<Model>>;
using PhysicalCore = operators::StellarEquilibriumPhysicalCoreType<
std::remove_cvref_t<Model>>;
public:
using ContributionCouplings =
typename Compilation::ContributionJacobianCouplings;
using UnsupportedCouplings =
typename CollectUnsupportedStellarStructureCouplings<
ContributionCouplings,
std::remove_cvref_t<Model>,
PhysicalCore,
typename std::remove_cvref_t<Model>::SpecificationTypes,
utils::blocks::type_list<>>::Type;
static constexpr bool supported = UnsupportedCouplings::size == 0;
};
} // namespace detail
/* A generated-border edge is owned by specification-border machinery and
* is deliberately ignored here. Every pure physical edge contributed by a
* model must be owned by the selected numerical structure backend, or
* every non-backend provider of that edge must prove StructuralZero. In
* particular, merely overlapping an existing base-Jacobian edge is not
* sufficient: a custom nonzero coefficient on that edge would otherwise
* disappear silently from the default preconditioner. This audit is
* detection-safe and therefore suitable for constraining factories. */
template <typename Candidate>
struct DefaultStellarStructurePhysicalTopologySupport
: detail::DefaultStellarStructurePhysicalTopologyAudit<
std::remove_cvref_t<Candidate>> { };
template <typename Candidate>
inline constexpr bool defaultStellarStructurePhysicalTopologySupported =
DefaultStellarStructurePhysicalTopologySupport<
std::remove_cvref_t<Candidate>>::supported;
template <typename Candidate>
concept DefaultStellarStructurePhysicalTopologySupportedFor =
defaultStellarStructurePhysicalTopologySupported<Candidate>;
namespace backend {
template <typename Component, typename Problem, typename Backend = typename Component::BackendType>
class PreparedComponent;
@@ -174,56 +416,17 @@ export namespace mean_field::preconditioning {
} // namespace backend
namespace detail {
using DensityIdentity =
IdentityBlock<utils::blocks::density::mass::value, utils::blocks::density::mass::residual>;
using SurfaceIdentity = IdentityBlock<
utils::blocks::surface_deformation::parameters::value,
utils::blocks::surface_deformation::shape_equilibrium::residual>;
using GravityGradientIdentity =
IdentityBlock<utils::blocks::gravity::gradient::value, utils::blocks::gravity::gradient::residual>;
using GravityPotentialIdentity =
IdentityBlock<utils::blocks::gravity::poisson::value, utils::blocks::gravity::poisson::residual>;
using EnthalpyIdentity =
IdentityBlock<utils::blocks::enthalpy::specific::value, utils::blocks::enthalpy::specific::residual>;
using FixedMassIdentity = IdentityBlock<
utils::blocks::fixed_total_mass::mass_normalization::value,
utils::blocks::fixed_total_mass::mass_normalization::residual>;
using FixedCentralDensityIdentity = IdentityBlock<
utils::blocks::fixed_central_density::central_value::value,
utils::blocks::fixed_central_density::central_value::residual>;
template <typename Form> struct IdentityPlanForForm;
template <> struct IdentityPlanForForm<utils::blocks::surface_deformed_stellar_equilibrium_form> {
using Type = PreconditionerPlan<
DensityIdentity,
SurfaceIdentity,
GravityGradientIdentity,
GravityPotentialIdentity,
EnthalpyIdentity,
FixedMassIdentity>;
template <typename... Values, typename... Residuals>
struct IdentityPlanForForm<utils::blocks::block_form<
utils::blocks::type_list<Values...>,
utils::blocks::type_list<Residuals...>>> {
static_assert(sizeof...(Values) == sizeof...(Residuals));
using Type = PreconditionerPlan<IdentityBlock<Values, Residuals>...>;
[[nodiscard]] static constexpr Type Make() {
return Type{DensityIdentity{}, SurfaceIdentity{}, GravityGradientIdentity{},
GravityPotentialIdentity{}, EnthalpyIdentity{}, FixedMassIdentity{}};
}
};
template <> struct IdentityPlanForForm<utils::blocks::central_density_bordered_stellar_equilibrium_form> {
using Type = PreconditionerPlan<
DensityIdentity,
SurfaceIdentity,
GravityGradientIdentity,
GravityPotentialIdentity,
EnthalpyIdentity,
FixedMassIdentity,
FixedCentralDensityIdentity>;
[[nodiscard]] static constexpr Type Make() {
return Type{
DensityIdentity{}, SurfaceIdentity{}, GravityGradientIdentity{}, GravityPotentialIdentity{},
EnthalpyIdentity{}, FixedMassIdentity{}, FixedCentralDensityIdentity{}
};
return Type{IdentityBlock<Values, Residuals>{}...};
}
};