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,8 @@ module;
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <type_traits>
#include <utility>
@@ -13,46 +15,126 @@ export import :deformation.domain_deformation;
export import :equilibrium.stellar_discretization;
export import :material.thermodynamic_equations;
export import :model.typed_stellar;
export import :operators.prepared_central_density_stellar_equilibrium;
export import :normalization.operators;
export import :operators.prepared_variadic_stellar_equilibrium;
export import :surface.compiler;
export namespace mean_field::equilibrium {
namespace detail {
template <
model::StellarModelType Model,
bool SymbolicallyCompilable = operators::StellarEquilibriumSystemCompilable<Model>>
struct StellarSurfaceCompilationAudit {
static constexpr bool complete = false;
};
template <model::StellarModelType Model>
struct StellarSurfaceCompilationAudit<Model, true> {
private:
using ModelType = std::remove_cvref_t<Model>;
using EquationOfState = typename ModelType::EquationOfStateType;
using Form = operators::CompiledStellarEquilibriumForm<ModelType>;
using AvailableEquations = material::StellarEquilibriumThermodynamicEquations;
static constexpr bool thermodynamicsCompilable =
material::ThermodynamicEquationsCompilable<EquationOfState, Form, AvailableEquations>;
public:
static constexpr bool complete = [] {
if constexpr (!thermodynamicsCompilable) {
return false;
} else {
using ThermodynamicEquations =
material::CompiledThermodynamicEquationsT<EquationOfState, Form, AvailableEquations>;
using Formulation = typename ThermodynamicEquations::PressureSurfaceFormulation;
using CompiledSurface =
surface::CompiledPressureSurfaceConstraintT<Formulation, EquationOfState>;
return requires(const ModelType &model) {
{
surface::compilePressureSurfaceConstraint<Formulation>(
model.surfaceCondition(),
model.equationOfState()
)
} -> std::same_as<CompiledSurface>;
};
}
}();
};
} // namespace detail
template <model::StellarModelType Model>
inline constexpr bool hasStellarEquilibriumSurfaceCompilation =
detail::StellarSurfaceCompilationAudit<std::remove_cvref_t<Model>>::complete;
template <typename Candidate>
concept StellarEquilibriumModel = model::StellarModelType<Candidate> && requires {
requires std::remove_cvref_t<Candidate>::template containsSpecification<eos::Polytrope>;
requires std::remove_cvref_t<Candidate>::template containsSpecification<surface::Isobaric>;
typename std::remove_cvref_t<Candidate>::EquationOfStateType;
requires(
std::remove_cvref_t<Candidate>::template specificationRoleCount<
models::SpecificationRole::boundary_condition> == 1
);
requires std::remove_cvref_t<Candidate>::template containsSpecification<models::FixedTotalMass>;
requires std::remove_cvref_t<Candidate>::specificationCount ==
3 + static_cast<std::size_t>(
std::remove_cvref_t<Candidate>::template containsSpecification<models::FixedCentralDensity>
);
requires operators::StellarEquilibriumSystemCompilable<std::remove_cvref_t<Candidate>>;
requires hasStellarEquilibriumSurfaceCompilation<std::remove_cvref_t<Candidate>>;
requires operators::CompilableRootManifestFor<
std::remove_cvref_t<Candidate>,
operators::CompiledStellarEquilibriumForm<std::remove_cvref_t<Candidate>>>;
requires operators::hasStellarEquilibriumCoreRuntime<std::remove_cvref_t<Candidate>>;
requires operators::hasCompleteStellarEquilibriumRuntime<std::remove_cvref_t<Candidate>>;
requires operators::stellarEquilibriumRotationProviderCount<std::remove_cvref_t<Candidate>> <= 1;
};
template <StellarEquilibriumModel Model> class StellarEquilibriumProblem final {
namespace detail {
template <typename Model, typename Discretization, typename = void>
struct StellarEquilibriumModelDiscretizationStructureAudit : std::false_type { };
template <typename Model, typename Discretization>
requires StellarEquilibriumModel<std::remove_cvref_t<Model>> &&
StellarDiscretizationType<std::remove_cvref_t<Discretization>>
struct StellarEquilibriumModelDiscretizationStructureAudit<
Model,
Discretization,
std::void_t<
typename std::remove_cvref_t<Discretization>::NormalizationPrescriptionType,
typename std::remove_cvref_t<Model>::SpecificationTypes,
operators::CompiledStellarEquilibriumForm<std::remove_cvref_t<Model>>,
operators::StellarEquilibriumPhysicalCoreType<std::remove_cvref_t<Model>>>>
: std::bool_constant<normalization::StellarNormalizationRuntimeAvailableFor<
typename std::remove_cvref_t<Discretization>::NormalizationPrescriptionType,
operators::CompiledStellarEquilibriumForm<std::remove_cvref_t<Model>>,
operators::StellarEquilibriumPhysicalCoreType<std::remove_cvref_t<Model>>,
typename std::remove_cvref_t<Model>::SpecificationTypes>> { };
struct StellarEquilibriumProblemFactory;
} // namespace detail
template <
StellarEquilibriumModel Model,
StellarDiscretizationType Discretization = StellarDiscretization>
requires detail::StellarEquilibriumModelDiscretizationStructureAudit<
std::remove_cvref_t<Model>,
std::remove_cvref_t<Discretization>>::value
class StellarEquilibriumProblem final {
public:
using ModelType = std::remove_cvref_t<Model>;
using DiscretizationType = std::remove_cvref_t<Discretization>;
using NormalizationPrescriptionType = typename DiscretizationType::NormalizationPrescriptionType;
static constexpr bool hasFixedCentralDensity =
ModelType::template containsSpecification<models::FixedCentralDensity>;
static constexpr bool hasFixedAngularMomentum =
ModelType::template containsSpecification<models::FixedAngularMomentum>;
static constexpr std::size_t generatedRotationProviderCount =
operators::stellarEquilibriumRotationProviderCount<ModelType>;
static constexpr bool symbolicallySquare = ModelType::symbolicallySquare;
using PreparedOperatorType = std::conditional_t<
hasFixedCentralDensity,
operators::PreparedCentralDensityStellarEquilibriumOperator,
operators::PreparedStellarEquilibriumOperator>;
using FormType = std::conditional_t<
hasFixedCentralDensity,
operators::CentralDensityStellarEquilibriumForm,
utils::blocks::surface_deformed_stellar_equilibrium_form>;
using JacobianFormType = std::conditional_t<
hasFixedCentralDensity,
operators::CentralDensityStellarEquilibriumJacobianForm,
utils::blocks::surface_deformed_stellar_equilibrium_jacobian_form>;
using ManifestType = std::conditional_t<
hasFixedCentralDensity,
operators::CentralDensityStellarEquilibriumSystemManifest,
operators::StellarEquilibriumSystemManifest>;
using EquationOfStateType = eos::Polytrope;
using PreparedOperatorType = operators::PreparedVariadicStellarEquilibriumOperator<ModelType>;
using PhysicalCoreType = typename PreparedOperatorType::PhysicalCoreType;
using FormType = operators::CompiledStellarEquilibriumForm<ModelType>;
using JacobianFormType = operators::CompiledStellarEquilibriumJacobianForm<ModelType>;
using ManifestType = operators::EquilibriumSystemManifest<ModelType, FormType, JacobianFormType>;
using EquationOfStateType = model::EquationOfStateType<ModelType>;
using SurfaceConditionType = model::SurfaceConditionType<ModelType>;
using AvailableThermodynamicEquations = material::StellarEquilibriumThermodynamicEquations;
using ThermodynamicEquationsType =
material::CompiledThermodynamicEquationsT<EquationOfStateType, FormType, AvailableThermodynamicEquations>;
@@ -60,44 +142,22 @@ export namespace mean_field::equilibrium {
typename ThermodynamicEquationsType::PressureSurfaceFormulation,
EquationOfStateType>;
StellarEquilibriumProblem(
ModelType stellarModel,
const StellarDiscretization discretization
)
requires(!hasFixedCentralDensity)
: m_stellarModel(std::move(stellarModel)),
m_discretization(discretization),
m_compiledSurfaceConstraint(CompileSurfaceConstraint(m_stellarModel)),
m_preparedOperator(
m_discretization.finiteElementModel(),
m_discretization.domainMapper(),
m_stellarModel.template specification<eos::Polytrope>(),
models::compileConstraint(m_stellarModel.template specification<models::FixedTotalMass>()),
operators::PressureSurfaceConstraintView{m_compiledSurfaceConstraint},
CompileDefaultDomainDeformation(m_discretization.finiteElementModel())
) {
VerifyProblem();
}
private:
friend struct detail::StellarEquilibriumProblemFactory;
StellarEquilibriumProblem(
ModelType stellarModel,
const StellarDiscretization discretization
DiscretizationType discretization
)
requires hasFixedCentralDensity
: m_stellarModel(std::move(stellarModel)),
m_discretization(discretization),
m_compiledSurfaceConstraint(CompileSurfaceConstraint(m_stellarModel)),
: m_stellarModel(std::make_shared<ModelType>(std::move(stellarModel))),
m_discretization(std::move(discretization)),
m_compiledSurfaceConstraint(CompileSurfaceConstraint(*m_stellarModel)),
m_preparedOperator(
m_discretization.finiteElementModel(),
m_discretization.domainMapper(),
m_stellarModel.template specification<eos::Polytrope>(),
models::compileConstraint(m_stellarModel.template specification<models::FixedTotalMass>()),
m_stellarModel,
operators::PressureSurfaceConstraintView{m_compiledSurfaceConstraint},
CompileDefaultDomainDeformation(m_discretization.finiteElementModel()),
models::compileConstraint(
m_stellarModel.template specification<models::FixedCentralDensity>(),
m_stellarModel.template specification<eos::Polytrope>()
)
CompileDefaultDomainDeformation(m_discretization.finiteElementModel())
) {
VerifyProblem();
}
@@ -107,14 +167,19 @@ export namespace mean_field::equilibrium {
StellarEquilibriumProblem(StellarEquilibriumProblem &&) = delete;
StellarEquilibriumProblem &operator=(StellarEquilibriumProblem &&) = delete;
public:
[[nodiscard]] const ModelType &GetStellarModel() const noexcept {
return m_stellarModel;
return *m_stellarModel;
}
[[nodiscard]] const StellarDiscretization &GetDiscretization() const noexcept {
[[nodiscard]] const DiscretizationType &GetDiscretization() const noexcept {
return m_discretization;
}
[[nodiscard]] const NormalizationPrescriptionType &GetNormalizationPrescription() const noexcept {
return m_discretization.normalizationPrescription();
}
[[nodiscard]] const CompiledSurfaceConstraintType &GetCompiledSurfaceConstraint() const noexcept {
return m_compiledSurfaceConstraint;
}
@@ -127,6 +192,10 @@ export namespace mean_field::equilibrium {
return m_preparedOperator;
}
[[nodiscard]] const PhysicalCoreType &GetPhysicalOperator() const noexcept {
return m_preparedOperator.GetPhysicalOperator();
}
[[nodiscard]] const auto &GetManifest() const noexcept {
return m_preparedOperator.GetRootManifest();
}
@@ -135,28 +204,20 @@ export namespace mean_field::equilibrium {
return m_preparedOperator.IsPrepared();
}
[[nodiscard]] std::uint64_t GetPreparationGeneration() const noexcept {
return m_preparationGeneration;
}
[[nodiscard]] const operators::StellarEquilibriumDependencies &GetLinearizationDependencies() const {
if constexpr (hasFixedCentralDensity) {
return m_preparedOperator.GetPhysicalOperator().GetDependencies();
} else {
return m_preparedOperator.GetDependencies();
}
return GetPhysicalOperator().GetDependencies();
}
[[nodiscard]] const operators::StellarEquilibriumDependencyStamp &GetGeometryDependency() const {
if constexpr (hasFixedCentralDensity) {
return m_preparedOperator.GetPhysicalOperator().GetGeneratedDisplacementDependency();
} else {
return m_preparedOperator.GetGeneratedDisplacementDependency();
}
return GetPhysicalOperator().GetGeneratedDisplacementDependency();
}
[[nodiscard]] const field::FieldBoundaryDofMap &GetPressureSurfaceRows() const noexcept {
if constexpr (hasFixedCentralDensity) {
return m_preparedOperator.GetPhysicalOperator().GetSurfaceConstraintOperator().GetSurfaceRows();
} else {
return m_preparedOperator.GetSurfaceConstraintOperator().GetSurfaceRows();
}
return GetPhysicalOperator().GetSurfaceConstraintOperator().GetSurfaceRows();
}
[[nodiscard]] int StateSize() const noexcept {
@@ -175,8 +236,19 @@ export namespace mean_field::equilibrium {
const mfem::Vector &state,
const operators::StellarEquilibriumDependencies &dependencies,
const physics::RigidRotation &rotation
) {
return m_preparedOperator.Prepare(state, dependencies, rotation);
) requires(generatedRotationProviderCount == 0) {
auto report = m_preparedOperator.Prepare(state, dependencies, rotation);
++m_preparationGeneration;
return report;
}
[[nodiscard]] auto Prepare(
const mfem::Vector &state,
const operators::StellarEquilibriumDependencies &dependencies
) requires(generatedRotationProviderCount == 1) {
auto report = m_preparedOperator.Prepare(state, dependencies);
++m_preparationGeneration;
return report;
}
void BuildResidual(mfem::Vector &residual) const {
@@ -194,8 +266,8 @@ export namespace mean_field::equilibrium {
[[nodiscard]] static CompiledSurfaceConstraintType CompileSurfaceConstraint(const ModelType &stellarModel) {
return surface::compilePressureSurfaceConstraint<
typename ThermodynamicEquationsType::PressureSurfaceFormulation>(
stellarModel.template specification<surface::Isobaric>(),
stellarModel.template specification<EquationOfStateType>()
stellarModel.surfaceCondition(),
stellarModel.equationOfState()
);
}
@@ -224,34 +296,112 @@ export namespace mean_field::equilibrium {
MFEM_VERIFY(m_discretization.isCurrent(), "The stellar equilibrium problem has a stale discretization.");
}
ModelType m_stellarModel;
StellarDiscretization m_discretization;
std::shared_ptr<const ModelType> m_stellarModel;
DiscretizationType m_discretization;
CompiledSurfaceConstraintType m_compiledSurfaceConstraint;
PreparedOperatorType m_preparedOperator;
std::uint64_t m_preparationGeneration{0};
};
template <StellarEquilibriumModel Model>
template <typename Candidate> struct IsStellarEquilibriumProblem : std::false_type { };
template <StellarEquilibriumModel Model, StellarDiscretizationType Discretization>
requires detail::StellarEquilibriumModelDiscretizationStructureAudit<
std::remove_cvref_t<Model>,
std::remove_cvref_t<Discretization>>::value
struct IsStellarEquilibriumProblem<StellarEquilibriumProblem<Model, Discretization>> : std::true_type { };
template <typename Candidate>
concept DiscretizedStellarEquilibriumProblem = IsStellarEquilibriumProblem<std::remove_cvref_t<Candidate>>::value;
namespace detail {
template <
typename Model,
typename Discretization,
bool StructurallyCompatible =
StellarEquilibriumModelDiscretizationStructureAudit<
std::remove_cvref_t<Model>,
std::remove_cvref_t<Discretization>>::value>
struct StellarEquilibriumModelDiscretizationOperationAudit : std::false_type { };
template <typename Model, typename Discretization>
struct StellarEquilibriumModelDiscretizationOperationAudit<
Model,
Discretization,
true> {
private:
using ModelType = std::remove_cvref_t<Model>;
using DiscretizationType = std::remove_cvref_t<Discretization>;
using Problem = StellarEquilibriumProblem<ModelType, DiscretizationType>;
using Prescription = typename DiscretizationType::NormalizationPrescriptionType;
public:
static constexpr bool value = [] {
if constexpr (
std::same_as<Prescription, normalization::Unnormalized> ||
normalization::PhysicalRieszDiagonalPrescription<Prescription>) {
return true;
} else {
return normalization::RuntimePreparedNormalizationOperation<Problem>;
}
}();
};
} // namespace detail
/*
* A model and a discretization are separate compile-time choices. Their
* pairing is valid only when the normalization plan covers the inferred
* form, the selected physical runtime supports it, and a third-party
* runtime policy provides its exact preparation operation. Keeping this
* as a detection-safe public factory boundary rejects incomplete policies
* at discretize(), before a solver-facing problem can be constructed.
*/
template <typename Model, typename Discretization>
concept StellarEquilibriumModelDiscretizationCompatible =
detail::StellarEquilibriumModelDiscretizationOperationAudit<
std::remove_cvref_t<Model>,
std::remove_cvref_t<Discretization>>::value;
namespace detail {
/* The structurally formed problem type is needed to probe the ADL
* operation without a recursive concept. Its constructor remains
* private, and this factory is the single construction authority after
* the complete public compatibility contract has succeeded. */
struct StellarEquilibriumProblemFactory final {
template <StellarEquilibriumModel Model, StellarDiscretizationType Discretization>
requires StellarEquilibriumModelDiscretizationCompatible<Model, Discretization>
[[nodiscard]] static auto Create(
Model &&stellarModel,
Discretization discretization
) {
using ModelType = std::remove_cvref_t<Model>;
using DiscretizationType = std::remove_cvref_t<Discretization>;
return StellarEquilibriumProblem<ModelType, DiscretizationType>{
std::forward<Model>(stellarModel),
std::move(discretization)
};
}
};
} // namespace detail
template <StellarEquilibriumModel Model, StellarDiscretizationType Discretization>
requires StellarEquilibriumModelDiscretizationCompatible<Model, Discretization>
[[nodiscard]] auto discretize(
Model &&stellarModel,
const StellarDiscretization discretization
Discretization discretization
) {
using ModelType = std::remove_cvref_t<Model>;
return StellarEquilibriumProblem<ModelType>{std::forward<Model>(stellarModel), discretization};
return detail::StellarEquilibriumProblemFactory::Create(
std::forward<Model>(stellarModel),
std::move(discretization)
);
}
template <StellarEquilibriumModel Model>
requires StellarEquilibriumModelDiscretizationCompatible<Model, StellarDiscretization>
[[nodiscard]] auto discretize(
Model &&stellarModel,
fem::FEM &finiteElementModel
) {
return discretize(std::forward<Model>(stellarModel), StellarDiscretization{finiteElementModel});
}
template <typename Candidate> struct IsStellarEquilibriumProblem : std::false_type { };
template <StellarEquilibriumModel Model>
struct IsStellarEquilibriumProblem<StellarEquilibriumProblem<Model>> : std::true_type { };
template <typename Candidate>
concept DiscretizedStellarEquilibriumProblem = IsStellarEquilibriumProblem<std::remove_cvref_t<Candidate>>::value;
} // namespace mean_field::equilibrium