#pragma once #include #include #include "serif/eos/models/polytropic.hpp" #include "serif/equations/angular_momentum.hpp" #include "serif/equations/barotropic_density.hpp" #include "serif/equations/mass_normalization.hpp" #include "serif/equations/primal_gravity.hpp" #include "serif/equations/surface_potential.hpp" #include "serif/geometry/surface/isobaric.hpp" #include "serif/model/eos_reference.hpp" #include "serif/model/stellar_model.hpp" #include "serif/model/specifications/fixed_total_mass.hpp" #include "serif/model/specifications/fixed_angular_momentum.hpp" #include "serif/utils/error/errors.hpp" namespace serif::examples { /** @brief Solve density mechanics, primal gravity and the isobar shape at fixed mass, EOS and angular momentum. */ [[nodiscard]] inline auto make_polytropic_model(double n = 1.0, double K = 2.0 / std::numbers::pi, double mass = 1.0, double angular_momentum = 0.0, double G = 1.0, double surface_pressure = 0.0) { const auto equations = [G, surface_pressure](const auto& physics) { const auto eos = model::borrow_eos(physics.equation_of_state()); const double index = physics.equation_of_state().polytropic_index(); const auto& rotation = physics.template specification(); // Resolve physical compatibility with the deferred equation definition, without restricting the EOS itself. utils::errors::serif_ensure( !(index == 3.0 && rotation.target().value() == 0.0 && surface_pressure == 0.0), "Fixed K and M do not determine a unique nonrotating n=3 vacuum equilibrium: compatible mass leaves radius free, and incompatible mass has no solution."); return model::EquilibriumEquations{ .interior_equations = serif::equations::EquationRegistry{ serif::equations::BarotropicDensityBalance{eos, dimensions::PressureValue{surface_pressure}, rotation.axis(), rotation.center()}, serif::equations::PrimalPoissonBalance{4.0 * std::numbers::pi * G}, serif::equations::MassNormalization{physics.template specification().target().value()}, serif::equations::AngularMomentumConstraint{rotation.target().value(), rotation.axis(), rotation.center()} }, .shape_force = serif::equations::SurfacePotentialBalance{rotation.axis(), rotation.center()}, .surface_condition = geometry::surface::Isobaric{dimensions::PressureValue{surface_pressure}} }; }; return model::make_stellar_model(eos::models::Polytrope{n, K}, equations, model::FixedTotalMass{dimensions::MassValue{mass}}, model::FixedAngularMomentum{dimensions::AngularMomentumValue{angular_momentum}}); } }