module; #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 :model.typed_stellar; export import :operators.prepared_central_density_stellar_equilibrium; export import :surface.compiler; export namespace mean_field::equilibrium { template concept StellarEquilibriumModel = model::StellarModelType && requires { requires std::remove_cvref_t::template containsSpecification; requires std::remove_cvref_t::template containsSpecification; requires std::remove_cvref_t::template containsSpecification; requires std::remove_cvref_t::specificationCount == 3 + static_cast( std::remove_cvref_t::template containsSpecification ); }; template class StellarEquilibriumProblem final { public: using ModelType = std::remove_cvref_t; static constexpr bool hasFixedCentralDensity = ModelType::template containsSpecification; static constexpr bool symbolicallySquare = ModelType::symbolicallySquare; using PreparedOperatorType = std::conditional_t< hasFixedCentralDensity, operators::PreparedCentralDensityStellarEquilibriumOperator, operators::PreparedStellarEquilibriumOperator>; using CompiledSurfaceConstraintType = surface::CompiledPressureSurfaceConstraintT; 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(), models::compileConstraint(m_stellarModel.template specification()), operators::PressureSurfaceConstraintView{m_compiledSurfaceConstraint}, CompileDefaultDomainDeformation(m_discretization.finiteElementModel()) ) { VerifyProblem(); } 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(), models::compileConstraint(m_stellarModel.template specification()), operators::PressureSurfaceConstraintView{m_compiledSurfaceConstraint}, CompileDefaultDomainDeformation(m_discretization.finiteElementModel()), models::compileConstraint( m_stellarModel.template specification(), m_stellarModel.template specification() ) ) { VerifyProblem(); } StellarEquilibriumProblem(const StellarEquilibriumProblem &) = delete; StellarEquilibriumProblem &operator=(const StellarEquilibriumProblem &) = delete; StellarEquilibriumProblem(StellarEquilibriumProblem &&) = delete; StellarEquilibriumProblem &operator=(StellarEquilibriumProblem &&) = delete; [[nodiscard]] const ModelType &GetStellarModel() const noexcept { return m_stellarModel; } [[nodiscard]] const StellarDiscretization &GetDiscretization() const noexcept { return m_discretization; } [[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 auto &GetManifest() const noexcept { return m_preparedOperator.GetRootManifest(); } [[nodiscard]] const field::FieldBoundaryDofMap &GetPressureSurfaceRows() const noexcept { if constexpr (hasFixedCentralDensity) { return m_preparedOperator.GetPhysicalOperator().GetSurfaceConstraintOperator().GetSurfaceRows(); } else { return m_preparedOperator.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 ) { return m_preparedOperator.Prepare(state, dependencies, rotation); } 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( stellarModel.template specification(), stellarModel.template specification() ); } [[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."); } ModelType m_stellarModel; StellarDiscretization m_discretization; CompiledSurfaceConstraintType m_compiledSurfaceConstraint; PreparedOperatorType m_preparedOperator; }; template [[nodiscard]] auto discretize( Model &&stellarModel, const StellarDiscretization discretization ) { using ModelType = std::remove_cvref_t; return StellarEquilibriumProblem{std::forward(stellarModel), discretization}; } template [[nodiscard]] auto discretize( Model &&stellarModel, fem::FEM &finiteElementModel ) { return discretize(std::forward(stellarModel), StellarDiscretization{finiteElementModel}); } } // namespace mean_field::equilibrium