feat(newton): first newton solver implementation
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
module;
|
||||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@@ -59,13 +59,14 @@ export namespace mean_field::seed {
|
||||
|
||||
/* 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;
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = true;
|
||||
template <typename Model> static constexpr bool supports = true;
|
||||
|
||||
template <typename Specification, typename Model>
|
||||
template <
|
||||
typename Specification,
|
||||
typename Model>
|
||||
static void validate(
|
||||
const Specification &,
|
||||
const Model &,
|
||||
@@ -74,7 +75,9 @@ export namespace mean_field::seed {
|
||||
) noexcept {
|
||||
}
|
||||
|
||||
template <typename Specification, typename Model>
|
||||
template <
|
||||
typename Specification,
|
||||
typename Model>
|
||||
static void initialize(
|
||||
const Specification &,
|
||||
const Model &,
|
||||
@@ -115,19 +118,17 @@ export namespace mean_field::seed {
|
||||
}
|
||||
|
||||
struct UnavailableRadialProjectionPhysics final {
|
||||
static constexpr bool registered = false;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
static constexpr bool registered = false;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = false;
|
||||
template <typename Model> static constexpr bool supports = false;
|
||||
};
|
||||
|
||||
struct FixedTotalMassRadialProjectionPhysics final {
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = true;
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = true;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = true;
|
||||
template <typename Model> static constexpr bool supports = true;
|
||||
|
||||
[[nodiscard]] static dimensions::MassValue targetMass(const models::FixedTotalMass &specification) {
|
||||
return specification.targetMass();
|
||||
@@ -164,10 +165,7 @@ export namespace mean_field::seed {
|
||||
static constexpr bool providesRadialMass = false;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = requires(
|
||||
const Model &model,
|
||||
const surface::Isobaric &condition
|
||||
) {
|
||||
static constexpr bool supports = requires(const Model &model, const surface::Isobaric &condition) {
|
||||
{
|
||||
eos::evaluate<dimensions::quantity::SpecificEnthalpy>(
|
||||
model.equationOfState(), condition.targetPressure()
|
||||
@@ -213,11 +211,10 @@ export namespace mean_field::seed {
|
||||
};
|
||||
|
||||
struct FixedCentralDensityRadialProjectionPhysics final {
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = true;
|
||||
template <typename Model> static constexpr bool supports = true;
|
||||
|
||||
template <typename Model>
|
||||
static void validate(
|
||||
@@ -246,11 +243,10 @@ export namespace mean_field::seed {
|
||||
};
|
||||
|
||||
struct FixedAngularMomentumRadialProjectionPhysics final {
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
static constexpr bool registered = true;
|
||||
static constexpr bool providesRadialMass = false;
|
||||
|
||||
template <typename Model>
|
||||
static constexpr bool supports = true;
|
||||
template <typename Model> static constexpr bool supports = true;
|
||||
|
||||
template <typename Model>
|
||||
static void validate(
|
||||
@@ -316,12 +312,12 @@ export namespace mean_field::seed {
|
||||
};
|
||||
|
||||
template <typename Candidate> struct UnwrapRadialProjectionPhysics {
|
||||
using Type = UnavailableRadialProjectionPhysics;
|
||||
using Type = UnavailableRadialProjectionPhysics;
|
||||
static constexpr bool valid = false;
|
||||
};
|
||||
|
||||
template <typename Physics> struct UnwrapRadialProjectionPhysics<projection::Use<Physics>> {
|
||||
using Type = Physics;
|
||||
using Type = Physics;
|
||||
static constexpr bool valid = true;
|
||||
};
|
||||
|
||||
@@ -358,7 +354,9 @@ export namespace mean_field::seed {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Specification, typename Model>
|
||||
template <
|
||||
typename Specification,
|
||||
typename Model>
|
||||
[[nodiscard]] consteval bool radialProjectionPhysicsIsComplete() {
|
||||
using Physics = typename SelectRadialProjectionPhysics<Specification>::Type;
|
||||
if constexpr (!radialProjectionPhysicsRegistered<Physics>()) {
|
||||
@@ -370,12 +368,9 @@ export namespace mean_field::seed {
|
||||
} 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,
|
||||
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);
|
||||
@@ -417,21 +412,24 @@ export namespace mean_field::seed {
|
||||
|
||||
static constexpr std::size_t radialMassProviderCount =
|
||||
(std::size_t{0} + ... +
|
||||
(radialProjectionPhysicsProvidesMass<
|
||||
typename SelectRadialProjectionPhysics<Specifications>::Type>()
|
||||
(radialProjectionPhysicsProvidesMass<typename SelectRadialProjectionPhysics<Specifications>::Type>()
|
||||
? std::size_t{1}
|
||||
: std::size_t{0}));
|
||||
static constexpr bool complete = radialMassProviderCount == 1 &&
|
||||
(radialProjectionPhysicsIsComplete<Specifications, ModelType>() && ...);
|
||||
static constexpr bool complete =
|
||||
radialMassProviderCount == 1 && (radialProjectionPhysicsIsComplete<Specifications, ModelType>() && ...);
|
||||
|
||||
[[nodiscard]] static dimensions::MassValue targetMass(const ModelType &model) requires complete {
|
||||
[[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>());
|
||||
}
|
||||
}(), ...);
|
||||
(
|
||||
[&] {
|
||||
using Physics = typename SelectRadialProjectionPhysics<Specifications>::Type;
|
||||
if constexpr (radialProjectionPhysicsProvidesMass<Physics>()) {
|
||||
result = Physics::targetMass(model.template specification<Specifications>());
|
||||
}
|
||||
}(),
|
||||
...);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -439,11 +437,15 @@ export namespace mean_field::seed {
|
||||
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);
|
||||
}(), ...);
|
||||
)
|
||||
requires complete
|
||||
{
|
||||
(
|
||||
[&] {
|
||||
using Physics = typename SelectRadialProjectionPhysics<Specifications>::Type;
|
||||
Physics::validate(model.template specification<Specifications>(), model, profile, options);
|
||||
}(),
|
||||
...);
|
||||
}
|
||||
|
||||
template <typename StateView>
|
||||
@@ -452,27 +454,32 @@ export namespace mean_field::seed {
|
||||
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{})
|
||||
);
|
||||
}
|
||||
}(), ...);
|
||||
)
|
||||
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{})
|
||||
);
|
||||
}
|
||||
}(),
|
||||
...);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -494,21 +501,25 @@ export namespace mean_field::seed {
|
||||
concept RadialProfileProjectableModel =
|
||||
model::StellarModelType<Candidate> && radialProjectionIsCompilable<std::remove_cvref_t<Candidate>>;
|
||||
|
||||
template <equilibrium::StellarEquilibriumModel Model, equilibrium::StellarDiscretizationType Discretization>
|
||||
template <
|
||||
equilibrium::StellarEquilibriumModel Model,
|
||||
equilibrium::StellarDiscretizationType Discretization>
|
||||
requires RadialProfileProjectableModel<Model>
|
||||
[[nodiscard]] ProjectedEquilibriumState<Model> projectRadialProfile(
|
||||
const equilibrium::StellarEquilibriumProblem<Model, Discretization> &problem,
|
||||
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>;
|
||||
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 dimensions::MassValue targetMass = Projection::targetMass(stellarModel);
|
||||
const detail::ProjectedRadialFields fields = detail::projectRadialFields(
|
||||
problem.GetDiscretization().finiteElementModel(), profile, targetMass, options
|
||||
equilibrium::detail::StellarEquilibriumProblemFactory::MutableFiniteElementModelForProjection(problem),
|
||||
profile, targetMass, options
|
||||
);
|
||||
|
||||
mfem::Vector values(problem.StateSize());
|
||||
@@ -563,11 +574,15 @@ export namespace mean_field::seed {
|
||||
equilibrium::StellarDiscretizationType Discretization,
|
||||
typename Strategy>
|
||||
requires RadialSeedStrategyFor<
|
||||
Strategy,
|
||||
typename equilibrium::StellarEquilibriumProblem<Model, Discretization>::ModelType> &&
|
||||
Strategy,
|
||||
typename equilibrium::StellarEquilibriumProblem<
|
||||
Model,
|
||||
Discretization>::ModelType> &&
|
||||
RadialProfileProjectableModel<Model>
|
||||
[[nodiscard]] ProjectedEquilibriumState<Model> makeProjectedEquilibriumState(
|
||||
const equilibrium::StellarEquilibriumProblem<Model, Discretization> &problem,
|
||||
equilibrium::StellarEquilibriumProblem<
|
||||
Model,
|
||||
Discretization> &problem,
|
||||
const Strategy &strategy,
|
||||
const StellarEquilibriumProjectionOptions &options = {}
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user