module; #include #include #include #include #include #include #include export module mean_field:operators.stellar_equilibrium_problem; export import :deformation.domain_deformation; export import :equilibrium.stellar_discretization; export import :material.thermodynamic_equations; export import :model.typed_stellar; 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> struct StellarSurfaceCompilationAudit { static constexpr bool complete = false; }; template struct StellarSurfaceCompilationAudit { private: using ModelType = std::remove_cvref_t; using EquationOfState = typename ModelType::EquationOfStateType; using Form = operators::CompiledStellarEquilibriumForm; using AvailableEquations = material::StellarEquilibriumThermodynamicEquations; static constexpr bool thermodynamicsCompilable = material::ThermodynamicEquationsCompilable; public: static constexpr bool complete = [] { if constexpr (!thermodynamicsCompilable) { return false; } else { using ThermodynamicEquations = material::CompiledThermodynamicEquationsT; using Formulation = typename ThermodynamicEquations::PressureSurfaceFormulation; using CompiledSurface = surface::CompiledPressureSurfaceConstraintT; return requires(const ModelType &model) { { surface::compilePressureSurfaceConstraint( model.surfaceCondition(), model.equationOfState() ) } -> std::same_as; }; } }(); }; } // namespace detail template inline constexpr bool hasStellarEquilibriumSurfaceCompilation = detail::StellarSurfaceCompilationAudit>::complete; template concept StellarEquilibriumModel = model::StellarModelType && requires { typename std::remove_cvref_t::EquationOfStateType; requires( std::remove_cvref_t::template specificationRoleCount< models::SpecificationRole::boundary_condition> == 1 ); requires std::remove_cvref_t::template containsSpecification; requires operators::StellarEquilibriumSystemCompilable>; requires hasStellarEquilibriumSurfaceCompilation>; requires operators::CompilableRootManifestFor< std::remove_cvref_t, operators::CompiledStellarEquilibriumForm>>; requires operators::hasStellarEquilibriumCoreRuntime>; requires operators::hasCompleteStellarEquilibriumRuntime>; requires operators::stellarEquilibriumRotationProviderCount> <= 1; }; namespace detail { template struct StellarEquilibriumModelDiscretizationStructureAudit : std::false_type { }; template requires StellarEquilibriumModel> && StellarDiscretizationType> struct StellarEquilibriumModelDiscretizationStructureAudit< Model, Discretization, std::void_t< typename std::remove_cvref_t::NormalizationPrescriptionType, typename std::remove_cvref_t::SpecificationTypes, operators::CompiledStellarEquilibriumForm>, operators::StellarEquilibriumPhysicalCoreType>>> : std::bool_constant::NormalizationPrescriptionType, operators::CompiledStellarEquilibriumForm>, operators::StellarEquilibriumPhysicalCoreType>, typename std::remove_cvref_t::SpecificationTypes>> { }; struct StellarEquilibriumProblemFactory; } // namespace detail template < StellarEquilibriumModel Model, StellarDiscretizationType Discretization = StellarDiscretization> requires detail::StellarEquilibriumModelDiscretizationStructureAudit< std::remove_cvref_t, std::remove_cvref_t>::value class StellarEquilibriumProblem final { public: using ModelType = std::remove_cvref_t; using DiscretizationType = std::remove_cvref_t; using NormalizationPrescriptionType = typename DiscretizationType::NormalizationPrescriptionType; static constexpr bool hasFixedCentralDensity = ModelType::template containsSpecification; static constexpr bool hasFixedAngularMomentum = ModelType::template containsSpecification; static constexpr std::size_t generatedRotationProviderCount = operators::stellarEquilibriumRotationProviderCount; static constexpr bool symbolicallySquare = ModelType::symbolicallySquare; using PreparedOperatorType = operators::PreparedVariadicStellarEquilibriumOperator; using PhysicalCoreType = typename PreparedOperatorType::PhysicalCoreType; using FormType = operators::CompiledStellarEquilibriumForm; using JacobianFormType = operators::CompiledStellarEquilibriumJacobianForm; using ManifestType = operators::EquilibriumSystemManifest; using EquationOfStateType = model::EquationOfStateType; using SurfaceConditionType = model::SurfaceConditionType; using AvailableThermodynamicEquations = material::StellarEquilibriumThermodynamicEquations; using ThermodynamicEquationsType = material::CompiledThermodynamicEquationsT; using CompiledSurfaceConstraintType = surface::CompiledPressureSurfaceConstraintT< typename ThermodynamicEquationsType::PressureSurfaceFormulation, EquationOfStateType>; private: friend struct detail::StellarEquilibriumProblemFactory; StellarEquilibriumProblem( ModelType stellarModel, DiscretizationType discretization ) : m_stellarModel(std::make_shared(std::move(stellarModel))), m_discretization(std::move(discretization)), m_compiledSurfaceConstraint(CompileSurfaceConstraint(*m_stellarModel)), m_preparedOperator( m_discretization.finiteElementModel(), m_discretization.domainMapper(), m_stellarModel, operators::PressureSurfaceConstraintView{m_compiledSurfaceConstraint}, CompileDefaultDomainDeformation(m_discretization.finiteElementModel()) ) { VerifyProblem(); } StellarEquilibriumProblem(const StellarEquilibriumProblem &) = delete; StellarEquilibriumProblem &operator=(const StellarEquilibriumProblem &) = delete; StellarEquilibriumProblem(StellarEquilibriumProblem &&) = delete; StellarEquilibriumProblem &operator=(StellarEquilibriumProblem &&) = delete; public: [[nodiscard]] const ModelType &GetStellarModel() const noexcept { return *m_stellarModel; } [[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; } [[nodiscard]] PreparedOperatorType &GetPreparedOperator() noexcept { return m_preparedOperator; } [[nodiscard]] const PreparedOperatorType &GetPreparedOperator() const noexcept { return m_preparedOperator; } [[nodiscard]] const PhysicalCoreType &GetPhysicalOperator() const noexcept { return m_preparedOperator.GetPhysicalOperator(); } [[nodiscard]] const auto &GetManifest() const noexcept { return m_preparedOperator.GetRootManifest(); } [[nodiscard]] bool IsPrepared() const noexcept { return m_preparedOperator.IsPrepared(); } [[nodiscard]] std::uint64_t GetPreparationGeneration() const noexcept { return m_preparationGeneration; } [[nodiscard]] const operators::StellarEquilibriumDependencies &GetLinearizationDependencies() const { return GetPhysicalOperator().GetDependencies(); } [[nodiscard]] const operators::StellarEquilibriumDependencyStamp &GetGeometryDependency() const { return GetPhysicalOperator().GetGeneratedDisplacementDependency(); } [[nodiscard]] const field::FieldBoundaryDofMap &GetPressureSurfaceRows() const noexcept { return GetPhysicalOperator().GetSurfaceConstraintOperator().GetSurfaceRows(); } [[nodiscard]] int StateSize() const noexcept { return m_preparedOperator.Width(); } [[nodiscard]] int EquationSize() const noexcept { return m_preparedOperator.Height(); } [[nodiscard]] const mfem::Operator &GetLinearizationOperator() const noexcept { return m_preparedOperator; } [[nodiscard]] auto Prepare( const mfem::Vector &state, const operators::StellarEquilibriumDependencies &dependencies, const physics::RigidRotation &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 { m_preparedOperator.BuildResidual(residual); } void ApplyLinearization( const mfem::Vector &direction, mfem::Vector &action ) const { m_preparedOperator.Mult(direction, action); } private: [[nodiscard]] static CompiledSurfaceConstraintType CompileSurfaceConstraint(const ModelType &stellarModel) { return surface::compilePressureSurfaceConstraint< typename ThermodynamicEquationsType::PressureSurfaceFormulation>( stellarModel.surfaceCondition(), stellarModel.equationOfState() ); } [[nodiscard]] static deformation::PreparedDomainDeformationRuntime CompileDefaultDomainDeformation(fem::FEM &finiteElementModel) { MFEM_VERIFY( finiteElementModel.mesh != nullptr, "Default stellar domain-deformation compilation requires a physical mesh." ); mfem::Vector referenceCenter(finiteElementModel.mesh->SpaceDimension()); referenceCenter = 0.0; return deformation::PreparedDomainDeformationRuntime{deformation::compileDomainDeformation( deformation::NodalRadialSurface{std::move(referenceCenter)}, deformation::PowerLawRadialInteriorExtension{}, deformation::FixedInfinityRadialVacuumExtension{}, finiteElementModel )}; } void VerifyProblem() const { MFEM_VERIFY(symbolicallySquare, "A stellar equilibrium problem must be symbolically square."); MFEM_VERIFY( StateSize() == EquationSize(), "The discretized stellar equilibrium problem has unequal state and equation dimensions." ); MFEM_VERIFY(m_discretization.isCurrent(), "The stellar equilibrium problem has a stale discretization."); } std::shared_ptr m_stellarModel; DiscretizationType m_discretization; CompiledSurfaceConstraintType m_compiledSurfaceConstraint; PreparedOperatorType m_preparedOperator; std::uint64_t m_preparationGeneration{0}; }; template struct IsStellarEquilibriumProblem : std::false_type { }; template requires detail::StellarEquilibriumModelDiscretizationStructureAudit< std::remove_cvref_t, std::remove_cvref_t>::value struct IsStellarEquilibriumProblem> : std::true_type { }; template concept DiscretizedStellarEquilibriumProblem = IsStellarEquilibriumProblem>::value; namespace detail { template < typename Model, typename Discretization, bool StructurallyCompatible = StellarEquilibriumModelDiscretizationStructureAudit< std::remove_cvref_t, std::remove_cvref_t>::value> struct StellarEquilibriumModelDiscretizationOperationAudit : std::false_type { }; template struct StellarEquilibriumModelDiscretizationOperationAudit< Model, Discretization, true> { private: using ModelType = std::remove_cvref_t; using DiscretizationType = std::remove_cvref_t; using Problem = StellarEquilibriumProblem; using Prescription = typename DiscretizationType::NormalizationPrescriptionType; public: static constexpr bool value = [] { if constexpr ( std::same_as || normalization::PhysicalRieszDiagonalPrescription) { return true; } else { return normalization::RuntimePreparedNormalizationOperation; } }(); }; } // 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 concept StellarEquilibriumModelDiscretizationCompatible = detail::StellarEquilibriumModelDiscretizationOperationAudit< std::remove_cvref_t, std::remove_cvref_t>::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 requires StellarEquilibriumModelDiscretizationCompatible [[nodiscard]] static auto Create( Model &&stellarModel, Discretization discretization ) { using ModelType = std::remove_cvref_t; using DiscretizationType = std::remove_cvref_t; return StellarEquilibriumProblem{ std::forward(stellarModel), std::move(discretization) }; } }; } // namespace detail template requires StellarEquilibriumModelDiscretizationCompatible [[nodiscard]] auto discretize( Model &&stellarModel, Discretization discretization ) { return detail::StellarEquilibriumProblemFactory::Create( std::forward(stellarModel), std::move(discretization) ); } template requires StellarEquilibriumModelDiscretizationCompatible [[nodiscard]] auto discretize( Model &&stellarModel, fem::FEM &finiteElementModel ) { return discretize(std::forward(stellarModel), StellarDiscretization{finiteElementModel}); } } // namespace mean_field::equilibrium