feat(libmeanfield): variadic refactor
also added normaliztion operator
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
module;
|
||||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <concepts>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
@@ -25,6 +27,65 @@ export namespace mean_field::seed {
|
||||
mfem::Vector values;
|
||||
};
|
||||
|
||||
/*
|
||||
* The public radial-projection extension boundary deliberately speaks in
|
||||
* physical state names. A specification author supplies one small rule
|
||||
* and opts in with
|
||||
*
|
||||
* using RadialProjection = seed::projection::Use<MyProjectionPhysics>;
|
||||
*
|
||||
* There is no registry ordinal and no model-combination specialization.
|
||||
*/
|
||||
struct RadialProjectionScales final {
|
||||
dimensions::MassValue targetMass;
|
||||
dimensions::LengthValue stellarRadius;
|
||||
double bernoulliConstant;
|
||||
double sphericalMomentOfInertia;
|
||||
const mfem::Array<int> *surfaceCarrierRows;
|
||||
};
|
||||
|
||||
struct RadialProjectionState final {
|
||||
mfem::Vector density;
|
||||
mfem::Vector surfaceShape;
|
||||
mfem::Vector gravityGradient;
|
||||
mfem::Vector gravityPotential;
|
||||
mfem::Vector specificEnthalpy;
|
||||
};
|
||||
|
||||
namespace projection {
|
||||
template <typename Physics> struct Use final {
|
||||
using PhysicsType = Physics;
|
||||
};
|
||||
|
||||
/* An explicit opt-in for a specification that leaves a radial seed unchanged. */
|
||||
struct NoStateChange {
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = true;
|
||||
|
||||
template <typename Specification, typename Model>
|
||||
static void validate(
|
||||
const Specification &,
|
||||
const Model &,
|
||||
const RadialProfile &,
|
||||
const StellarEquilibriumProjectionOptions &
|
||||
) noexcept {
|
||||
}
|
||||
|
||||
template <typename Specification, typename Model>
|
||||
static void initialize(
|
||||
const Specification &,
|
||||
const Model &,
|
||||
const RadialProjectionScales &,
|
||||
RadialProjectionState &,
|
||||
mfem::Vector
|
||||
) noexcept {
|
||||
}
|
||||
};
|
||||
} // namespace projection
|
||||
|
||||
namespace detail {
|
||||
struct ProjectedRadialFields final {
|
||||
mfem::Vector density;
|
||||
@@ -32,13 +93,13 @@ export namespace mean_field::seed {
|
||||
mfem::Vector gravityPotential;
|
||||
mfem::Vector specificEnthalpy;
|
||||
double bernoulliConstant;
|
||||
double sphericalMomentOfInertia;
|
||||
};
|
||||
|
||||
[[nodiscard]] ProjectedRadialFields projectRadialFields(
|
||||
const equilibrium::StellarDiscretization &discretization,
|
||||
fem::FEM &finiteElementModel,
|
||||
const RadialProfile &profile,
|
||||
dimensions::MassValue targetMass,
|
||||
dimensions::PressureValue targetSurfacePressure,
|
||||
const StellarEquilibriumProjectionOptions &options
|
||||
);
|
||||
|
||||
@@ -52,18 +113,402 @@ export namespace mean_field::seed {
|
||||
}
|
||||
destination = source;
|
||||
}
|
||||
|
||||
struct UnavailableRadialProjectionPhysics final {
|
||||
static constexpr bool registered = false;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = false;
|
||||
};
|
||||
|
||||
struct FixedTotalMassRadialProjectionPhysics final {
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = true;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = true;
|
||||
|
||||
[[nodiscard]] static dimensions::MassValue targetMass(const models::FixedTotalMass &specification) {
|
||||
return specification.targetMass();
|
||||
}
|
||||
|
||||
template <typename Model>
|
||||
static void validate(
|
||||
const models::FixedTotalMass &,
|
||||
const Model &,
|
||||
const RadialProfile &,
|
||||
const StellarEquilibriumProjectionOptions &
|
||||
) noexcept {
|
||||
}
|
||||
|
||||
template <typename Model>
|
||||
static void initialize(
|
||||
const models::FixedTotalMass &,
|
||||
const Model &,
|
||||
const RadialProjectionScales &scales,
|
||||
RadialProjectionState &,
|
||||
mfem::Vector coordinate
|
||||
) {
|
||||
if (coordinate.Size() != 1) {
|
||||
throw std::invalid_argument(
|
||||
"A fixed-total-mass radial projection requires exactly one generated multiplier."
|
||||
);
|
||||
}
|
||||
coordinate(0) = scales.bernoulliConstant;
|
||||
}
|
||||
};
|
||||
|
||||
struct IsobaricRadialProjectionPhysics final {
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = requires(
|
||||
const Model &model,
|
||||
const surface::Isobaric &condition
|
||||
) {
|
||||
{
|
||||
eos::evaluate<dimensions::quantity::SpecificEnthalpy>(
|
||||
model.equationOfState(), condition.targetPressure()
|
||||
)
|
||||
} -> std::same_as<dimensions::SpecificEnthalpyValue>;
|
||||
};
|
||||
|
||||
template <typename Model>
|
||||
static void validate(
|
||||
const surface::Isobaric &condition,
|
||||
const Model &,
|
||||
const RadialProfile &,
|
||||
const StellarEquilibriumProjectionOptions &
|
||||
) {
|
||||
if (condition.targetPressure().value() != 0.0) {
|
||||
throw std::invalid_argument("A Lane-Emden radial seed requires a zero-pressure isobaric surface.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Model>
|
||||
static void initialize(
|
||||
const surface::Isobaric &condition,
|
||||
const Model &model,
|
||||
const RadialProjectionScales &scales,
|
||||
RadialProjectionState &state,
|
||||
mfem::Vector coordinate
|
||||
) {
|
||||
if (coordinate.Size() != 0) {
|
||||
throw std::logic_error("An isobaric surface must not generate a radial-seed coordinate.");
|
||||
}
|
||||
if (scales.surfaceCarrierRows == nullptr) {
|
||||
throw std::logic_error("An isobaric radial projection requires compiled surface-carrier rows.");
|
||||
}
|
||||
|
||||
const dimensions::SpecificEnthalpyValue requiredSurfaceEnthalpy =
|
||||
eos::evaluate<dimensions::quantity::SpecificEnthalpy>(
|
||||
model.equationOfState(), condition.targetPressure()
|
||||
);
|
||||
for (const int surfaceRow : *scales.surfaceCarrierRows) {
|
||||
state.specificEnthalpy(surfaceRow) = requiredSurfaceEnthalpy.value();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FixedCentralDensityRadialProjectionPhysics final {
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = true;
|
||||
|
||||
template <typename Model>
|
||||
static void validate(
|
||||
const models::FixedCentralDensity &,
|
||||
const Model &,
|
||||
const RadialProfile &,
|
||||
const StellarEquilibriumProjectionOptions &
|
||||
) noexcept {
|
||||
}
|
||||
|
||||
template <typename Model>
|
||||
static void initialize(
|
||||
const models::FixedCentralDensity &,
|
||||
const Model &,
|
||||
const RadialProjectionScales &,
|
||||
RadialProjectionState &,
|
||||
mfem::Vector coordinate
|
||||
) {
|
||||
if (coordinate.Size() != 1) {
|
||||
throw std::invalid_argument(
|
||||
"A fixed-central-density radial projection requires exactly one generated phase coordinate."
|
||||
);
|
||||
}
|
||||
coordinate(0) = 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
struct FixedAngularMomentumRadialProjectionPhysics final {
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = true;
|
||||
|
||||
template <typename Model>
|
||||
static void validate(
|
||||
const models::FixedAngularMomentum &,
|
||||
const Model &,
|
||||
const RadialProfile &,
|
||||
const StellarEquilibriumProjectionOptions &
|
||||
) noexcept {
|
||||
}
|
||||
|
||||
template <typename Model>
|
||||
static void initialize(
|
||||
const models::FixedAngularMomentum &constraint,
|
||||
const Model &,
|
||||
const RadialProjectionScales &scales,
|
||||
RadialProjectionState &,
|
||||
mfem::Vector coordinate
|
||||
) {
|
||||
if (coordinate.Size() != 1) {
|
||||
throw std::logic_error(
|
||||
"A fixed-angular-momentum radial projection requires one angular-velocity coordinate."
|
||||
);
|
||||
}
|
||||
|
||||
double centerSquared = 0.0;
|
||||
double centerAlongAxis = 0.0;
|
||||
for (std::size_t component = 0; component < constraint.center().size(); ++component) {
|
||||
centerSquared += constraint.center()[component] * constraint.center()[component];
|
||||
centerAlongAxis += constraint.center()[component] * constraint.axis()[component];
|
||||
}
|
||||
const double parallelAxisCorrection =
|
||||
scales.targetMass.value() * (centerSquared - centerAlongAxis * centerAlongAxis);
|
||||
const double momentOfInertia = scales.sphericalMomentOfInertia + parallelAxisCorrection;
|
||||
if (!std::isfinite(momentOfInertia) || momentOfInertia <= 0.0) {
|
||||
throw std::runtime_error("The radial seed has no finite, positive axial moment of inertia.");
|
||||
}
|
||||
coordinate(0) = constraint.targetAngularMomentum().value() / momentOfInertia;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Specification> struct BuiltinRadialProjectionPhysics {
|
||||
using Type = UnavailableRadialProjectionPhysics;
|
||||
};
|
||||
|
||||
template <> struct BuiltinRadialProjectionPhysics<eos::Polytrope> {
|
||||
using Type = projection::NoStateChange;
|
||||
};
|
||||
|
||||
template <> struct BuiltinRadialProjectionPhysics<surface::Isobaric> {
|
||||
using Type = IsobaricRadialProjectionPhysics;
|
||||
};
|
||||
|
||||
template <> struct BuiltinRadialProjectionPhysics<models::FixedTotalMass> {
|
||||
using Type = FixedTotalMassRadialProjectionPhysics;
|
||||
};
|
||||
|
||||
template <> struct BuiltinRadialProjectionPhysics<models::FixedCentralDensity> {
|
||||
using Type = FixedCentralDensityRadialProjectionPhysics;
|
||||
};
|
||||
|
||||
template <> struct BuiltinRadialProjectionPhysics<models::FixedAngularMomentum> {
|
||||
using Type = FixedAngularMomentumRadialProjectionPhysics;
|
||||
};
|
||||
|
||||
template <typename Candidate> struct UnwrapRadialProjectionPhysics {
|
||||
using Type = UnavailableRadialProjectionPhysics;
|
||||
static constexpr bool valid = false;
|
||||
};
|
||||
|
||||
template <typename Physics> struct UnwrapRadialProjectionPhysics<projection::Use<Physics>> {
|
||||
using Type = Physics;
|
||||
static constexpr bool valid = true;
|
||||
};
|
||||
|
||||
template <typename Specification, typename = void> struct SelectRadialProjectionPhysics {
|
||||
using Type = typename BuiltinRadialProjectionPhysics<Specification>::Type;
|
||||
};
|
||||
|
||||
template <typename Specification>
|
||||
struct SelectRadialProjectionPhysics<Specification, std::void_t<typename Specification::RadialProjection>> {
|
||||
private:
|
||||
using Wrapped = UnwrapRadialProjectionPhysics<typename Specification::RadialProjection>;
|
||||
|
||||
public:
|
||||
using Type = std::conditional_t<Wrapped::valid, typename Wrapped::Type, UnavailableRadialProjectionPhysics>;
|
||||
};
|
||||
|
||||
template <typename Physics> [[nodiscard]] consteval bool radialProjectionPhysicsRegistered() {
|
||||
if constexpr (requires {
|
||||
{ Physics::registered } -> std::convertible_to<bool>;
|
||||
}) {
|
||||
return static_cast<bool>(Physics::registered);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Physics> [[nodiscard]] consteval bool radialProjectionPhysicsProvidesMass() {
|
||||
if constexpr (requires {
|
||||
{ Physics::providesRadialMass } -> std::convertible_to<bool>;
|
||||
}) {
|
||||
return static_cast<bool>(Physics::providesRadialMass);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Specification, typename Model>
|
||||
[[nodiscard]] consteval bool radialProjectionPhysicsIsComplete() {
|
||||
using Physics = typename SelectRadialProjectionPhysics<Specification>::Type;
|
||||
if constexpr (!radialProjectionPhysicsRegistered<Physics>()) {
|
||||
return false;
|
||||
} else if constexpr (!requires {
|
||||
{ Physics::template supports<Model> } -> std::convertible_to<bool>;
|
||||
}) {
|
||||
return false;
|
||||
} else if constexpr (!static_cast<bool>(Physics::template supports<Model>)) {
|
||||
return false;
|
||||
} else if constexpr (!requires(
|
||||
const Specification &specification,
|
||||
const Model &model,
|
||||
const RadialProfile &profile,
|
||||
const StellarEquilibriumProjectionOptions &options,
|
||||
const RadialProjectionScales &scales,
|
||||
RadialProjectionState &state,
|
||||
mfem::Vector coordinate
|
||||
) {
|
||||
Physics::validate(specification, model, profile, options);
|
||||
Physics::initialize(specification, model, scales, state, coordinate);
|
||||
}) {
|
||||
return false;
|
||||
} else if constexpr (radialProjectionPhysicsProvidesMass<Physics>()) {
|
||||
return requires(const Specification &specification) {
|
||||
{ Physics::targetMass(specification) } -> std::same_as<dimensions::MassValue>;
|
||||
};
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template <models::ModelSpecification Specification, models::GeneratedStateKind Kind>
|
||||
struct RadialProjectionCoordinateTerm;
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct RadialProjectionCoordinateTerm<Specification, models::GeneratedStateKind::multiplier> final {
|
||||
using value = utils::blocks::generated_value_block<models::MultiplierFor<Specification>>;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct RadialProjectionCoordinateTerm<Specification, models::GeneratedStateKind::physical_coordinate> final {
|
||||
using value = utils::blocks::generated_value_block<models::PhysicalCoordinateFor<Specification>>;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct RadialProjectionCoordinateTerm<Specification, models::GeneratedStateKind::solver_border> final {
|
||||
using value = utils::blocks::generated_value_block<models::BorderFor<Specification>>;
|
||||
};
|
||||
|
||||
template <typename Model, typename SpecificationSet> struct CompileRadialProjection;
|
||||
|
||||
template <model::StellarModelType Model, models::ModelSpecification... Specifications>
|
||||
struct CompileRadialProjection<Model, models::detail::SpecificationSetStorage<Specifications...>> {
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
|
||||
static constexpr std::size_t radialMassProviderCount =
|
||||
(std::size_t{0} + ... +
|
||||
(radialProjectionPhysicsProvidesMass<
|
||||
typename SelectRadialProjectionPhysics<Specifications>::Type>()
|
||||
? std::size_t{1}
|
||||
: std::size_t{0}));
|
||||
static constexpr bool complete = radialMassProviderCount == 1 &&
|
||||
(radialProjectionPhysicsIsComplete<Specifications, ModelType>() && ...);
|
||||
|
||||
[[nodiscard]] static dimensions::MassValue targetMass(const ModelType &model) requires complete {
|
||||
dimensions::MassValue result{0.0};
|
||||
([&] {
|
||||
using Physics = typename SelectRadialProjectionPhysics<Specifications>::Type;
|
||||
if constexpr (radialProjectionPhysicsProvidesMass<Physics>()) {
|
||||
result = Physics::targetMass(model.template specification<Specifications>());
|
||||
}
|
||||
}(), ...);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void validate(
|
||||
const ModelType &model,
|
||||
const RadialProfile &profile,
|
||||
const StellarEquilibriumProjectionOptions &options
|
||||
) requires complete {
|
||||
([&] {
|
||||
using Physics = typename SelectRadialProjectionPhysics<Specifications>::Type;
|
||||
Physics::validate(model.template specification<Specifications>(), model, profile, options);
|
||||
}(), ...);
|
||||
}
|
||||
|
||||
template <typename StateView>
|
||||
static void initialize(
|
||||
const ModelType &model,
|
||||
const RadialProjectionScales &scales,
|
||||
RadialProjectionState &state,
|
||||
const StateView &stateView
|
||||
) requires complete {
|
||||
([&] {
|
||||
using Contribution = models::SpecificationContribution<Specifications>;
|
||||
using Physics = typename SelectRadialProjectionPhysics<Specifications>::Type;
|
||||
if constexpr (Contribution::generatedValueArity == 0) {
|
||||
Physics::initialize(
|
||||
model.template specification<Specifications>(), model, scales, state, mfem::Vector{}
|
||||
);
|
||||
} else {
|
||||
static_assert(
|
||||
Contribution::generatedValueArity == 1,
|
||||
"Radial projection currently requires each specification contribution to generate at "
|
||||
"most one scalar coordinate."
|
||||
);
|
||||
using Term = RadialProjectionCoordinateTerm<Specifications, Contribution::generatedStateKind>;
|
||||
Physics::initialize(
|
||||
model.template specification<Specifications>(), model, scales, state,
|
||||
stateView.block(Term{})
|
||||
);
|
||||
}
|
||||
}(), ...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Candidate, bool = model::StellarModelType<Candidate>>
|
||||
struct RadialProjectionCompilationAudit {
|
||||
static constexpr bool complete = false;
|
||||
};
|
||||
|
||||
template <typename Candidate>
|
||||
struct RadialProjectionCompilationAudit<Candidate, true>
|
||||
: CompileRadialProjection<Candidate, typename Candidate::SpecificationTypes> { };
|
||||
} // namespace detail
|
||||
|
||||
template <equilibrium::StellarEquilibriumModel Model>
|
||||
template <typename Candidate>
|
||||
inline constexpr bool radialProjectionIsCompilable =
|
||||
detail::RadialProjectionCompilationAudit<std::remove_cvref_t<Candidate>>::complete;
|
||||
|
||||
template <typename Candidate>
|
||||
concept RadialProfileProjectableModel =
|
||||
model::StellarModelType<Candidate> && radialProjectionIsCompilable<std::remove_cvref_t<Candidate>>;
|
||||
|
||||
template <equilibrium::StellarEquilibriumModel Model, equilibrium::StellarDiscretizationType Discretization>
|
||||
requires RadialProfileProjectableModel<Model>
|
||||
[[nodiscard]] ProjectedEquilibriumState<Model> projectRadialProfile(
|
||||
const equilibrium::StellarEquilibriumProblem<Model> &problem,
|
||||
const equilibrium::StellarEquilibriumProblem<Model, Discretization> &problem,
|
||||
const RadialProfile &profile,
|
||||
const StellarEquilibriumProjectionOptions &options = {}
|
||||
) {
|
||||
using Projection = detail::CompileRadialProjection<
|
||||
std::remove_cvref_t<Model>,
|
||||
typename std::remove_cvref_t<Model>::SpecificationTypes>;
|
||||
const auto &stellarModel = problem.GetStellarModel();
|
||||
Projection::validate(stellarModel, profile, options);
|
||||
const dimensions::MassValue targetMass = Projection::targetMass(stellarModel);
|
||||
const detail::ProjectedRadialFields fields = detail::projectRadialFields(
|
||||
problem.GetDiscretization(), profile,
|
||||
problem.GetStellarModel().template specification<models::FixedTotalMass>().targetMass(),
|
||||
problem.GetStellarModel().template specification<surface::Isobaric>().targetPressure(), options
|
||||
problem.GetDiscretization().finiteElementModel(), profile, targetMass, options
|
||||
);
|
||||
|
||||
mfem::Vector values(problem.StateSize());
|
||||
@@ -89,45 +534,40 @@ export namespace mean_field::seed {
|
||||
);
|
||||
|
||||
/*
|
||||
* Projection of a continuous spherical profile onto a faceted
|
||||
* reference mesh generally leaves a small trace error on the physical
|
||||
* surface. The pressure condition replaces these carrier rows in the
|
||||
* compiled equilibrium problem, so impose its required carrier value
|
||||
* exactly after bulk projection instead of treating that geometric
|
||||
* mismatch as part of the initial residual.
|
||||
* Each specification now initializes only its inferred contribution.
|
||||
* In particular, the surface rule imposes the exact carrier trace and
|
||||
* generated constraints obtain their coordinate by type, not by a
|
||||
* hard-coded whole-model layout.
|
||||
*/
|
||||
mfem::Vector enthalpy = stateView.block(utils::blocks::enthalpy_field.specific_term);
|
||||
const dimensions::SpecificEnthalpyValue requiredSurfaceEnthalpy =
|
||||
eos::evaluate<dimensions::quantity::SpecificEnthalpy>(
|
||||
problem.GetStellarModel().template specification<eos::Polytrope>(),
|
||||
problem.GetStellarModel().template specification<surface::Isobaric>().targetPressure()
|
||||
);
|
||||
for (const int surfaceRow : problem.GetPressureSurfaceRows().reduced_dofs()) {
|
||||
enthalpy(surfaceRow) = requiredSurfaceEnthalpy.value();
|
||||
}
|
||||
|
||||
mfem::Vector fixedMassCoordinate =
|
||||
stateView.block(utils::blocks::fixed_total_mass_constraint.mass_normalization_term);
|
||||
if (fixedMassCoordinate.Size() != 1) {
|
||||
throw std::invalid_argument("FixedTotalMass must generate exactly one equilibrium-state coordinate.");
|
||||
}
|
||||
fixedMassCoordinate(0) = fields.bernoulliConstant;
|
||||
|
||||
if constexpr (std::remove_cvref_t<Model>::template containsSpecification<models::FixedCentralDensity>) {
|
||||
stateView.block(utils::blocks::fixed_central_density_phase.central_value_term) = 0.0;
|
||||
}
|
||||
RadialProjectionState projectedState{
|
||||
.density = stateView.block(utils::blocks::density_field.mass_term),
|
||||
.surfaceShape = stateView.block(utils::blocks::surface_deformation_field.parameters_term),
|
||||
.gravityGradient = stateView.block(utils::blocks::gravity_field.gradient_term),
|
||||
.gravityPotential = stateView.block(utils::blocks::gravity_field.poisson_term),
|
||||
.specificEnthalpy = stateView.block(utils::blocks::enthalpy_field.specific_term)
|
||||
};
|
||||
const RadialProjectionScales scales{
|
||||
.targetMass = targetMass,
|
||||
.stellarRadius = profile.stellarRadius,
|
||||
.bernoulliConstant = fields.bernoulliConstant,
|
||||
.sphericalMomentOfInertia = fields.sphericalMomentOfInertia,
|
||||
.surfaceCarrierRows = &problem.GetPressureSurfaceRows().reduced_dofs()
|
||||
};
|
||||
Projection::initialize(stellarModel, scales, projectedState, stateView);
|
||||
|
||||
return {.values = std::move(values)};
|
||||
}
|
||||
|
||||
template <
|
||||
equilibrium::StellarEquilibriumModel Model,
|
||||
equilibrium::StellarDiscretizationType Discretization,
|
||||
typename Strategy>
|
||||
requires RadialSeedStrategyFor<
|
||||
Strategy,
|
||||
typename equilibrium::StellarEquilibriumProblem<Model>::ModelType>
|
||||
typename equilibrium::StellarEquilibriumProblem<Model, Discretization>::ModelType> &&
|
||||
RadialProfileProjectableModel<Model>
|
||||
[[nodiscard]] ProjectedEquilibriumState<Model> makeProjectedEquilibriumState(
|
||||
const equilibrium::StellarEquilibriumProblem<Model> &problem,
|
||||
const equilibrium::StellarEquilibriumProblem<Model, Discretization> &problem,
|
||||
const Strategy &strategy,
|
||||
const StellarEquilibriumProjectionOptions &options = {}
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user