feat(newton): first newton solver implementation

This commit is contained in:
2026-09-08 06:36:39 -04:00
parent 76818f2f82
commit b3c04d507a
98 changed files with 20397 additions and 11040 deletions

View File

@@ -57,11 +57,9 @@ export namespace mean_field::models {
static constexpr std::size_t size = sizeof...(Types);
};
template <typename... ValueBlocks>
using DependsOn = ModelTypeList<ValueBlocks...>;
template <typename... ValueBlocks> using DependsOn = ModelTypeList<ValueBlocks...>;
template <typename... ResidualBlocks>
using Affects = ModelTypeList<ResidualBlocks...>;
template <typename... ResidualBlocks> using Affects = ModelTypeList<ResidualBlocks...>;
/*
* Physics vocabulary for declaring how a stellar specification couples to
@@ -83,8 +81,7 @@ export namespace mean_field::models {
* the physics-facing spelling for coupled global constraints: an
* extension names the constraint it reads, never its solver block.
*/
template <typename Specification>
struct GeneratedCoordinateOf final {
template <typename Specification> struct GeneratedCoordinateOf final {
using SpecificationType = Specification;
};
@@ -108,8 +105,7 @@ export namespace mean_field::models {
struct OwnConstraint final { };
/* The scalar constraint equation owned by another specification. */
template <typename Specification>
struct ConstraintOf final {
template <typename Specification> struct ConstraintOf final {
using SpecificationType = Specification;
};
} // namespace equation
@@ -119,8 +115,7 @@ export namespace mean_field::models {
* Runtime providers consume this vocabulary without learning backend
* row and column block types.
*/
template <typename Equation, typename State>
struct Derivative final {
template <typename Equation, typename State> struct Derivative final {
using EquationType = Equation;
using StateType = State;
};
@@ -220,11 +215,7 @@ export namespace mean_field::models {
concept PhysicalScaleRepresentedQuantity =
dimensions::PhysicalQuantityType<Quantity> &&
physicalScaleForQuantity<Quantity> != PhysicalScaleLaw::unavailable &&
requires {
typename std::bool_constant<
!static_cast<std::string_view>(
Quantity::identifier).empty()>;
};
requires { typename std::bool_constant<!static_cast<std::string_view>(Quantity::identifier).empty()>; };
namespace detail {
template <typename Candidate> [[nodiscard]] consteval bool declaredCoordinateNormalizationIsAvailable() {
@@ -270,8 +261,7 @@ export namespace mean_field::models {
case SpecificationRole::boundary_condition:
return kind == GeneratedStateKind::none;
case SpecificationRole::invariant:
return kind == GeneratedStateKind::multiplier ||
kind == GeneratedStateKind::physical_coordinate;
return kind == GeneratedStateKind::multiplier || kind == GeneratedStateKind::physical_coordinate;
case SpecificationRole::phase_condition:
case SpecificationRole::gauge_choice:
return kind == GeneratedStateKind::solver_border;
@@ -304,11 +294,12 @@ export namespace mean_field::models {
using UnavailableCoordinateNormalization =
CoordinateNormalization<RieszTopology::unavailable, PhysicalScaleLaw::unavailable>;
template <typename ValueNormalization = UnavailableCoordinateNormalization,
typename ResidualNormalization = UnavailableCoordinateNormalization>
template <
typename ValueNormalization = UnavailableCoordinateNormalization,
typename ResidualNormalization = UnavailableCoordinateNormalization>
struct GeneratedNormalization final {
using Value = ValueNormalization;
using Residual = ResidualNormalization;
using Value = ValueNormalization;
using Residual = ResidualNormalization;
static constexpr bool available = detail::declaredCoordinateNormalizationIsAvailable<Value>() &&
detail::declaredCoordinateNormalizationIsAvailable<Residual>();
@@ -321,8 +312,13 @@ export namespace mean_field::models {
CoordinateNormalization<RieszTopology::global_scalar, ValueScale>,
CoordinateNormalization<RieszTopology::global_scalar, ResidualScale>>;
template <FixedString ValueStableId = "", FixedString ValueSymbol = "", FixedString ResidualStableId = "",
FixedString ResidualSymbol = "", FixedString TargetUnits = "", FixedString ResidualUnits = "">
template <
FixedString ValueStableId = "",
FixedString ValueSymbol = "",
FixedString ResidualStableId = "",
FixedString ResidualSymbol = "",
FixedString TargetUnits = "",
FixedString ResidualUnits = "">
struct GeneratedManifest final {
private:
inline static constexpr auto valueStableIdStorage = ValueStableId;
@@ -366,21 +362,19 @@ export namespace mean_field::models {
FixedString ResidualStableId,
FixedString ResidualSymbol>
struct DimensionalScalarConstraint final {
using TargetQuantity = TargetQuantityT;
using GeneratedCoordinateQuantity = GeneratedCoordinateQuantityT;
using ConstraintResidualQuantity = ConstraintResidualQuantityT;
using TargetValue = dimensions::QuantityValue<TargetQuantity>;
static constexpr PhysicalScaleLaw targetScale =
physicalScaleForQuantity<TargetQuantity>;
using TargetQuantity = TargetQuantityT;
using GeneratedCoordinateQuantity = GeneratedCoordinateQuantityT;
using ConstraintResidualQuantity = ConstraintResidualQuantityT;
using TargetValue = dimensions::QuantityValue<TargetQuantity>;
static constexpr PhysicalScaleLaw targetScale = physicalScaleForQuantity<TargetQuantity>;
struct Normalization final {
using TargetQuantity = TargetQuantityT;
using GeneratedCoordinateQuantity = GeneratedCoordinateQuantityT;
using ConstraintResidualQuantity = ConstraintResidualQuantityT;
using TargetValue = dimensions::QuantityValue<TargetQuantity>;
static constexpr PhysicalScaleLaw targetScale =
physicalScaleForQuantity<TargetQuantity>;
using Value = CoordinateNormalization<
using TargetQuantity = TargetQuantityT;
using GeneratedCoordinateQuantity = GeneratedCoordinateQuantityT;
using ConstraintResidualQuantity = ConstraintResidualQuantityT;
using TargetValue = dimensions::QuantityValue<TargetQuantity>;
static constexpr PhysicalScaleLaw targetScale = physicalScaleForQuantity<TargetQuantity>;
using Value = CoordinateNormalization<
RieszTopology::global_scalar,
physicalScaleForQuantity<GeneratedCoordinateQuantity>>;
using Residual = CoordinateNormalization<
@@ -408,20 +402,23 @@ export namespace mean_field::models {
static constexpr std::string_view residualSymbol = residualSymbolStorage.view();
static constexpr std::string_view targetUnits = TargetQuantity::identifier;
static constexpr std::string_view residualUnits = ConstraintResidualQuantity::identifier;
static constexpr bool available =
!valueStableId.empty() && !valueSymbol.empty() &&
!residualStableId.empty() && !residualSymbol.empty() &&
!targetUnits.empty() && !residualUnits.empty();
static constexpr bool available = !valueStableId.empty() && !valueSymbol.empty() &&
!residualStableId.empty() && !residualSymbol.empty() &&
!targetUnits.empty() && !residualUnits.empty();
};
static constexpr bool dimensionallyTyped = true;
};
template <typename Specification, FixedString StableName, SpecificationRole Role,
GeneratedStateKind StateKind = GeneratedStateKind::none, typename DependsOnBlocks = ModelTypeList<>,
typename AffectedResidualBlocks = ModelTypeList<>,
typename NormalizationDefinition = UnavailableGeneratedNormalization,
typename ManifestDefinition = UnavailableGeneratedManifest>
template <
typename Specification,
FixedString StableName,
SpecificationRole Role,
GeneratedStateKind StateKind = GeneratedStateKind::none,
typename DependsOnBlocks = ModelTypeList<>,
typename AffectedResidualBlocks = ModelTypeList<>,
typename NormalizationDefinition = UnavailableGeneratedNormalization,
typename ManifestDefinition = UnavailableGeneratedManifest>
struct ModelDefinition final {
using SpecificationType = Specification;
using DependsOn = DependsOnBlocks;
@@ -447,26 +444,56 @@ export namespace mean_field::models {
template <typename Specification, FixedString Name>
using BoundaryCondition = ModelDefinition<Specification, Name, SpecificationRole::boundary_condition>;
template <typename Specification, FixedString Name, typename DependsOn = ModelTypeList<>,
typename Affects = ModelTypeList<>, typename Normalization = UnavailableGeneratedNormalization,
typename Manifest = UnavailableGeneratedManifest>
using FixedIntegralWithMultiplier =
ModelDefinition<Specification, Name, SpecificationRole::invariant, GeneratedStateKind::multiplier, DependsOn,
Affects, Normalization, Manifest>;
template <
typename Specification,
FixedString Name,
typename DependsOn = ModelTypeList<>,
typename Affects = ModelTypeList<>,
typename Normalization = UnavailableGeneratedNormalization,
typename Manifest = UnavailableGeneratedManifest>
using FixedIntegralWithMultiplier = ModelDefinition<
Specification,
Name,
SpecificationRole::invariant,
GeneratedStateKind::multiplier,
DependsOn,
Affects,
Normalization,
Manifest>;
template <typename Specification, FixedString Name, typename DependsOn = ModelTypeList<>,
typename Affects = ModelTypeList<>, typename Normalization = UnavailableGeneratedNormalization,
typename Manifest = UnavailableGeneratedManifest>
using FixedIntegralWithPhysicalCoordinate =
ModelDefinition<Specification, Name, SpecificationRole::invariant, GeneratedStateKind::physical_coordinate,
DependsOn, Affects, Normalization, Manifest>;
template <
typename Specification,
FixedString Name,
typename DependsOn = ModelTypeList<>,
typename Affects = ModelTypeList<>,
typename Normalization = UnavailableGeneratedNormalization,
typename Manifest = UnavailableGeneratedManifest>
using FixedIntegralWithPhysicalCoordinate = ModelDefinition<
Specification,
Name,
SpecificationRole::invariant,
GeneratedStateKind::physical_coordinate,
DependsOn,
Affects,
Normalization,
Manifest>;
template <typename Specification, FixedString Name, typename DependsOn = ModelTypeList<>,
typename Affects = ModelTypeList<>, typename Normalization = UnavailableGeneratedNormalization,
typename Manifest = UnavailableGeneratedManifest>
using PhaseCondition =
ModelDefinition<Specification, Name, SpecificationRole::phase_condition, GeneratedStateKind::solver_border,
DependsOn, Affects, Normalization, Manifest>;
template <
typename Specification,
FixedString Name,
typename DependsOn = ModelTypeList<>,
typename Affects = ModelTypeList<>,
typename Normalization = UnavailableGeneratedNormalization,
typename Manifest = UnavailableGeneratedManifest>
using PhaseCondition = ModelDefinition<
Specification,
Name,
SpecificationRole::phase_condition,
GeneratedStateKind::solver_border,
DependsOn,
Affects,
Normalization,
Manifest>;
struct SpecificationKey final {
SpecificationRole role;
@@ -510,35 +537,42 @@ export namespace mean_field::models {
};
namespace detail {
template <typename Candidate> struct IsModelTypeList : std::false_type {};
template <typename Candidate> struct IsModelTypeList : std::false_type { };
template <typename... Types> struct IsModelTypeList<ModelTypeList<Types...>> : std::true_type {};
template <typename... Types> struct IsModelTypeList<ModelTypeList<Types...>> : std::true_type { };
template <typename Candidate> struct IsModelDefinition : std::false_type {};
template <typename Candidate> struct IsModelDefinition : std::false_type { };
template <typename Specification, FixedString StableName, SpecificationRole Role, GeneratedStateKind StateKind,
typename DependsOn, typename Affects, typename Normalization, typename Manifest>
template <
typename Specification,
FixedString StableName,
SpecificationRole Role,
GeneratedStateKind StateKind,
typename DependsOn,
typename Affects,
typename Normalization,
typename Manifest>
struct IsModelDefinition<
ModelDefinition<Specification, StableName, Role, StateKind, DependsOn, Affects, Normalization, Manifest>>
: std::bool_constant<(StableName.view().size() > 0) &&
CompatibleSpecificationRoleAndGeneratedState<Role, StateKind> &&
IsModelTypeList<DependsOn>::value &&
IsModelTypeList<Affects>::value>{};
: std::bool_constant<
(StableName.view().size() > 0) && CompatibleSpecificationRoleAndGeneratedState<Role, StateKind> &&
IsModelTypeList<DependsOn>::value && IsModelTypeList<Affects>::value> { };
template <typename Definition, typename Candidate, bool = IsModelDefinition<Definition>::value>
struct DefinitionDescribesCandidate : std::false_type {};
struct DefinitionDescribesCandidate : std::false_type { };
template <typename Definition, typename Candidate>
struct DefinitionDescribesCandidate<Definition, Candidate, true>
: std::bool_constant<std::same_as<typename Definition::SpecificationType, Candidate>> {};
: std::bool_constant<std::same_as<typename Definition::SpecificationType, Candidate>> { };
template <typename Candidate, typename = void> struct SpecificationDefinitionFor {
static constexpr bool available = false;
};
template <typename Candidate>
struct SpecificationDefinitionFor<Candidate,
std::void_t<typename std::remove_cvref_t<Candidate>::ModelDefinition>> {
struct SpecificationDefinitionFor<
Candidate,
std::void_t<typename std::remove_cvref_t<Candidate>::ModelDefinition>> {
using Type = typename std::remove_cvref_t<Candidate>::ModelDefinition;
static constexpr bool available = DefinitionDescribesCandidate<Type, std::remove_cvref_t<Candidate>>::value;
};
@@ -570,7 +604,7 @@ export namespace mean_field::models {
template <typename Candidate>
requires detail::SpecificationDefinitionFor<std::remove_cvref_t<Candidate>>::available
struct SpecificationTraits<Candidate> {
using Definition = ModelDefinitionForT<Candidate>;
using Definition = ModelDefinitionForT<Candidate>;
static constexpr std::string_view name = Definition::name;
static constexpr SpecificationRole role = Definition::role;
@@ -604,7 +638,8 @@ export namespace mean_field::models {
"R_M">;
using TargetValue = typename ScalarDescription::TargetValue;
using ModelDefinition = FixedIntegralWithMultiplier<
FixedTotalMass, "FixedTotalMass",
FixedTotalMass,
"FixedTotalMass",
DependsOn<stellar::state::Density, stellar::state::SurfaceShape>,
Affects<stellar::equation::HydrostaticBalance>,
typename ScalarDescription::Normalization,
@@ -615,9 +650,13 @@ export namespace mean_field::models {
explicit FixedTotalMass(const TargetValue targetMass) : m_targetMass(targetMass) {
if (!std::isfinite(targetMass.value()) || targetMass.value() <= 0.0) {
throw std::invalid_argument(std::format("The fixed total mass must be finite and positive. "
"Instead M = {} was provided.",
targetMass.value()));
throw std::invalid_argument(
std::format(
"The fixed total mass must be finite and positive. "
"Instead M = {} was provided.",
targetMass.value()
)
);
}
}
@@ -651,29 +690,35 @@ export namespace mean_field::models {
"R_J">;
using TargetValue = typename ScalarDescription::TargetValue;
using ModelDefinition = FixedIntegralWithPhysicalCoordinate<
FixedAngularMomentum, "FixedAngularMomentum",
DependsOn<
stellar::state::Density,
stellar::state::SurfaceShape,
stellar::state::OwnGeneratedCoordinate>,
FixedAngularMomentum,
"FixedAngularMomentum",
DependsOn<stellar::state::Density, stellar::state::SurfaceShape, stellar::state::OwnGeneratedCoordinate>,
Affects<stellar::equation::SurfaceShapeBalance, stellar::equation::HydrostaticBalance>,
typename ScalarDescription::Normalization,
typename ScalarDescription::Manifest>;
explicit FixedAngularMomentum(const Parameters parameters)
: m_targetAngularMomentum(parameters.Jtotal), m_axis(parameters.axis), m_center(parameters.center) {
: m_targetAngularMomentum(parameters.Jtotal),
m_axis(parameters.axis),
m_center(parameters.center) {
if (!std::isfinite(m_targetAngularMomentum.value()) || m_targetAngularMomentum.value() < 0.0) {
throw std::invalid_argument(std::format("The fixed total angular momentum must be finite and "
"nonnegative. Instead J = {} was "
"provided.",
m_targetAngularMomentum.value()));
throw std::invalid_argument(
std::format(
"The fixed total angular momentum must be finite and "
"nonnegative. Instead J = {} was "
"provided.",
m_targetAngularMomentum.value()
)
);
}
double axisNormSquared = 0.0;
for (std::size_t component = 0; component < m_axis.size(); ++component) {
if (!std::isfinite(m_axis[component]) || !std::isfinite(m_center[component])) {
throw std::invalid_argument("A fixed-angular-momentum rotation axis and center must contain "
"only finite values.");
throw std::invalid_argument(
"A fixed-angular-momentum rotation axis and center must contain "
"only finite values."
);
}
axisNormSquared += m_axis[component] * m_axis[component];
}
@@ -698,11 +743,17 @@ export namespace mean_field::models {
return m_targetAngularMomentum;
}
[[nodiscard]] const std::array<double, 3> &axis() const noexcept {
[[nodiscard]] const std::array<
double,
3> &
axis() const noexcept {
return m_axis;
}
[[nodiscard]] const std::array<double, 3> &center() const noexcept {
[[nodiscard]] const std::array<
double,
3> &
center() const noexcept {
return m_center;
}
@@ -728,7 +779,8 @@ export namespace mean_field::models {
"R_rho_c">;
using TargetValue = typename ScalarDescription::TargetValue;
using ModelDefinition = PhaseCondition<
FixedCentralDensity, "FixedCentralDensity",
FixedCentralDensity,
"FixedCentralDensity",
DependsOn<stellar::state::SpecificEnthalpy>,
Affects<stellar::equation::HydrostaticBalance>,
typename ScalarDescription::Normalization,
@@ -739,9 +791,13 @@ export namespace mean_field::models {
explicit FixedCentralDensity(const TargetValue targetDensity) : m_targetDensity(targetDensity) {
if (!std::isfinite(targetDensity.value()) || targetDensity.value() <= 0.0) {
throw std::invalid_argument(std::format("The fixed central density must be finite and positive. "
"Instead rho_c = {} was provided.",
targetDensity.value()));
throw std::invalid_argument(
std::format(
"The fixed central density must be finite and positive. "
"Instead rho_c = {} was provided.",
targetDensity.value()
)
);
}
}
@@ -761,19 +817,19 @@ export namespace mean_field::models {
template <typename Query, typename... Types>
struct ModelTypeListContains<Query, ModelTypeList<Types...>>
: std::bool_constant<(std::same_as<Query, Types> || ...)> {};
: std::bool_constant<(std::same_as<Query, Types> || ...)> { };
template <typename Query, typename List>
inline constexpr bool modelTypeListContains = ModelTypeListContains<Query, List>::value;
template <typename Specification> struct ResidualFor final {
using SpecificationType = Specification;
using SpecificationType = Specification;
static constexpr std::size_t scalarArity = 1;
};
template <typename Specification> struct MultiplierFor final {
using SpecificationType = Specification;
using SpecificationType = Specification;
static constexpr std::size_t scalarArity = 1;
};
@@ -781,13 +837,13 @@ export namespace mean_field::models {
// A generated state variable that participates directly in the physical
// equations, rather than serving only as a Lagrange multiplier or border.
template <typename Specification> struct PhysicalCoordinateFor final {
using SpecificationType = Specification;
using SpecificationType = Specification;
static constexpr std::size_t scalarArity = 1;
};
template <typename Specification> struct BorderFor final {
using SpecificationType = Specification;
using SpecificationType = Specification;
static constexpr std::size_t scalarArity = 1;
};
@@ -881,15 +937,15 @@ export namespace mean_field::models {
static constexpr std::size_t generatedValueArity = Definition::generatedValueArity;
static constexpr std::size_t generatedResidualArity = Definition::generatedResidualArity;
static constexpr bool isDefined = Definition::structurallyAvailable;
static constexpr bool hasDeclarativeDefinition = Definition::structurallyAvailable;
static constexpr bool hasDeclarativeDefinition = Definition::structurallyAvailable;
};
namespace detail {
template <ModelSpecification Specification>
[[nodiscard]] consteval bool generatedScalarDimensionsAreCoherent() {
using Contribution = SpecificationContribution<Specification>;
using Contribution = SpecificationContribution<Specification>;
using Normalization = typename Contribution::Normalization;
using Manifest = typename Contribution::Manifest;
using Manifest = typename Contribution::Manifest;
if constexpr (Contribution::generatedValueArity == 0) {
return true;
@@ -899,9 +955,7 @@ export namespace mean_field::models {
typename Normalization::GeneratedCoordinateQuantity;
typename Normalization::ConstraintResidualQuantity;
typename Normalization::TargetValue;
{
Normalization::targetScale
} -> std::convertible_to<PhysicalScaleLaw>;
{ Normalization::targetScale } -> std::convertible_to<PhysicalScaleLaw>;
};
constexpr bool manifestIsTyped = requires {
typename Manifest::TargetQuantity;
@@ -918,72 +972,53 @@ export namespace mean_field::models {
} else if constexpr (!normalizationIsTyped || !manifestIsTyped) {
return false;
} else {
using TargetQuantity = typename Normalization::TargetQuantity;
using GeneratedCoordinateQuantity =
typename Normalization::GeneratedCoordinateQuantity;
using ConstraintResidualQuantity =
typename Normalization::ConstraintResidualQuantity;
using ValueNormalization = typename Normalization::Value;
using ResidualNormalization = typename Normalization::Residual;
using TargetQuantity = typename Normalization::TargetQuantity;
using GeneratedCoordinateQuantity = typename Normalization::GeneratedCoordinateQuantity;
using ConstraintResidualQuantity = typename Normalization::ConstraintResidualQuantity;
using ValueNormalization = typename Normalization::Value;
using ResidualNormalization = typename Normalization::Residual;
if constexpr (
!PhysicalScaleRepresentedQuantity<TargetQuantity> ||
!PhysicalScaleRepresentedQuantity<GeneratedCoordinateQuantity> ||
!PhysicalScaleRepresentedQuantity<ConstraintResidualQuantity>) {
!PhysicalScaleRepresentedQuantity<ConstraintResidualQuantity>
) {
return false;
} else if constexpr (!requires {
typename std::integral_constant<
PhysicalScaleLaw,
static_cast<PhysicalScaleLaw>(
Normalization::targetScale)>;
typename std::integral_constant<
PhysicalScaleLaw,
static_cast<PhysicalScaleLaw>(
ValueNormalization::scale)>;
typename std::integral_constant<
PhysicalScaleLaw,
static_cast<PhysicalScaleLaw>(
ResidualNormalization::scale)>;
typename std::bool_constant<
static_cast<std::string_view>(
Manifest::targetUnits) ==
TargetQuantity::identifier>;
typename std::bool_constant<
static_cast<std::string_view>(
Manifest::residualUnits) ==
ConstraintResidualQuantity::identifier>;
}) {
} else if constexpr (
!requires {
typename std::integral_constant<
PhysicalScaleLaw, static_cast<PhysicalScaleLaw>(Normalization::targetScale)>;
typename std::integral_constant<
PhysicalScaleLaw, static_cast<PhysicalScaleLaw>(ValueNormalization::scale)>;
typename std::integral_constant<
PhysicalScaleLaw, static_cast<PhysicalScaleLaw>(ResidualNormalization::scale)>;
typename std::bool_constant<
static_cast<std::string_view>(Manifest::targetUnits) == TargetQuantity::identifier>;
typename std::bool_constant<
static_cast<std::string_view>(Manifest::residualUnits) ==
ConstraintResidualQuantity::identifier>;
}
) {
return false;
} else if constexpr (!requires(const Specification &specification) {
specification.target();
}) {
} else if constexpr (!requires(const Specification &specification) { specification.target(); }) {
return false;
} else {
return
std::same_as<
typename Normalization::TargetValue,
dimensions::QuantityValue<TargetQuantity>> &&
Normalization::targetScale ==
physicalScaleForQuantity<TargetQuantity> &&
std::same_as<TargetQuantity, typename Manifest::TargetQuantity> &&
std::same_as<
GeneratedCoordinateQuantity,
typename Manifest::GeneratedCoordinateQuantity> &&
std::same_as<
ConstraintResidualQuantity,
typename Manifest::ConstraintResidualQuantity> &&
ValueNormalization::scale ==
physicalScaleForQuantity<GeneratedCoordinateQuantity> &&
ResidualNormalization::scale ==
physicalScaleForQuantity<ConstraintResidualQuantity> &&
static_cast<std::string_view>(Manifest::targetUnits) ==
TargetQuantity::identifier &&
static_cast<std::string_view>(Manifest::residualUnits) ==
ConstraintResidualQuantity::identifier &&
std::same_as<
std::remove_cvref_t<decltype(
std::declval<const Specification &>().target())>,
typename Normalization::TargetValue>;
return std::same_as<
typename Normalization::TargetValue, dimensions::QuantityValue<TargetQuantity>> &&
Normalization::targetScale == physicalScaleForQuantity<TargetQuantity> &&
std::same_as<TargetQuantity, typename Manifest::TargetQuantity> &&
std::same_as<
GeneratedCoordinateQuantity, typename Manifest::GeneratedCoordinateQuantity> &&
std::same_as<
ConstraintResidualQuantity, typename Manifest::ConstraintResidualQuantity> &&
ValueNormalization::scale == physicalScaleForQuantity<GeneratedCoordinateQuantity> &&
ResidualNormalization::scale == physicalScaleForQuantity<ConstraintResidualQuantity> &&
static_cast<std::string_view>(Manifest::targetUnits) == TargetQuantity::identifier &&
static_cast<std::string_view>(Manifest::residualUnits) ==
ConstraintResidualQuantity::identifier &&
std::same_as<
std::remove_cvref_t<decltype(std::declval<const Specification &>().target())>,
typename Normalization::TargetValue>;
}
}
}
@@ -993,20 +1028,17 @@ export namespace mean_field::models {
template <typename Specification>
concept CompleteGeneratedScalarDimensionsFor =
ModelSpecification<Specification> &&
detail::generatedScalarDimensionsAreCoherent<
std::remove_cvref_t<Specification>>();
detail::generatedScalarDimensionsAreCoherent<std::remove_cvref_t<Specification>>();
template <typename Specification>
concept CompleteGeneratedNormalizationFor =
ModelSpecification<Specification> &&
CompleteGeneratedScalarDimensionsFor<Specification> &&
ModelSpecification<Specification> && CompleteGeneratedScalarDimensionsFor<Specification> &&
(SpecificationContribution<std::remove_cvref_t<Specification>>::generatedValueArity == 0 ||
SpecificationContribution<std::remove_cvref_t<Specification>>::Normalization::available);
template <typename Specification>
concept CompleteGeneratedManifestFor =
ModelSpecification<Specification> &&
CompleteGeneratedScalarDimensionsFor<Specification> &&
ModelSpecification<Specification> && CompleteGeneratedScalarDimensionsFor<Specification> &&
(SpecificationContribution<std::remove_cvref_t<Specification>>::generatedValueArity == 0 ||
SpecificationContribution<std::remove_cvref_t<Specification>>::Manifest::available);
@@ -1035,7 +1067,7 @@ export namespace mean_field::models {
};
template <SpecificationRole Role, typename SpecificationSet> struct SpecificationsForRole {
using Type = ModelTypeList<>;
using Type = ModelTypeList<>;
static constexpr bool available = false;
static constexpr std::size_t count = 0;
@@ -1043,9 +1075,10 @@ export namespace mean_field::models {
template <SpecificationRole Role, ModelSpecification... Specifications>
struct SpecificationsForRole<Role, SpecificationSetStorage<Specifications...>> {
using Type = typename ConcatenateModelTypeLists<
std::conditional_t<SpecificationTraits<Specifications>::role == Role, ModelTypeList<Specifications>,
ModelTypeList<>>...>::Type;
using Type = typename ConcatenateModelTypeLists<std::conditional_t<
SpecificationTraits<Specifications>::role == Role,
ModelTypeList<Specifications>,
ModelTypeList<>>...>::Type;
static constexpr bool available = true;
static constexpr std::size_t count = Type::size;
@@ -1077,9 +1110,10 @@ export namespace mean_field::models {
};
public:
using Type = std::conditional_t<(SpecificationTraits<Specification>::key < SpecificationTraits<Head>::key),
SpecificationSetStorage<Specification, Head, Tail...>,
typename PrependSpecification<Head, InsertedTail>::Type>;
using Type = std::conditional_t<
(SpecificationTraits<Specification>::key < SpecificationTraits<Head>::key),
SpecificationSetStorage<Specification, Head, Tail...>,
typename PrependSpecification<Head, InsertedTail>::Type>;
};
template <typename Set, ModelSpecification... Specifications> struct CanonicalizeSpecifications;
@@ -1098,21 +1132,26 @@ export namespace mean_field::models {
using CanonicalSpecificationSet =
typename CanonicalizeSpecifications<SpecificationSetStorage<>, Specifications...>::Type;
template <ModelSpecification Head, ModelSpecification... Tail> consteval bool specificationKeyIsUnique() {
template <
ModelSpecification Head,
ModelSpecification... Tail>
consteval bool specificationKeyIsUnique() {
constexpr auto headKey = SpecificationTraits<Head>::key;
return ((headKey.role != SpecificationTraits<Tail>::key.role ||
headKey.stableName != SpecificationTraits<Tail>::key.stableName) &&
...);
return (
(headKey.role != SpecificationTraits<Tail>::key.role ||
headKey.stableName != SpecificationTraits<Tail>::key.stableName) &&
...
);
}
template <ModelSpecification... Specifications> struct SpecificationKeysAreUnique;
template <> struct SpecificationKeysAreUnique<> : std::true_type {};
template <> struct SpecificationKeysAreUnique<> : std::true_type { };
template <ModelSpecification Head, ModelSpecification... Tail>
struct SpecificationKeysAreUnique<Head, Tail...>
: std::bool_constant<specificationKeyIsUnique<Head, Tail...>() &&
SpecificationKeysAreUnique<Tail...>::value> {};
: std::bool_constant<
specificationKeyIsUnique<Head, Tail...>() && SpecificationKeysAreUnique<Tail...>::value> { };
template <SpecificationRole Role, ModelSpecification... Specifications>
inline constexpr std::size_t specificationRoleCount =
@@ -1122,7 +1161,7 @@ export namespace mean_field::models {
template <typename... Types>
struct ModelTypeListScalarArity<ModelTypeList<Types...>>
: std::integral_constant<std::size_t, (std::size_t{0} + ... + Types::scalarArity)> {};
: std::integral_constant<std::size_t, (std::size_t{0} + ... + Types::scalarArity)> { };
template <typename Query, typename... Types>
inline constexpr bool isOneOf = (std::same_as<Query, Types> || ...);
@@ -1136,9 +1175,10 @@ export namespace mean_field::models {
template <ModelSpecification... CanonicalSpecifications, typename... Arguments>
struct ArgumentsMatchCanonicalSpecifications<SpecificationSetStorage<CanonicalSpecifications...>, Arguments...>
: std::bool_constant<sizeof...(CanonicalSpecifications) == sizeof...(Arguments) &&
(isOneOf<std::remove_cvref_t<Arguments>, CanonicalSpecifications...> && ...) &&
((typeCount<CanonicalSpecifications, Arguments...> == 1) && ...)> {};
: std::bool_constant<
sizeof...(CanonicalSpecifications) == sizeof...(Arguments) &&
(isOneOf<std::remove_cvref_t<Arguments>, CanonicalSpecifications...> && ...) &&
((typeCount<CanonicalSpecifications, Arguments...> == 1) && ...)> { };
} // namespace detail
template <typename... Specifications>
@@ -1150,12 +1190,12 @@ export namespace mean_field::models {
concept ValidModelSpecificationPack =
(ResolvedModelSpecification<std::remove_cvref_t<Specifications>> && ...) &&
specificationKeysAreUnique<std::remove_cvref_t<Specifications>...> &&
detail::specificationRoleCount<SpecificationRole::constitutive_law,
std::remove_cvref_t<Specifications>...> == 1;
detail::specificationRoleCount<SpecificationRole::constitutive_law, std::remove_cvref_t<Specifications>...> ==
1;
template <typename... Specifications>
requires(ModelSpecification<std::remove_cvref_t<Specifications>> && ...) &&
specificationKeysAreUnique<std::remove_cvref_t<Specifications>...>
specificationKeysAreUnique<std::remove_cvref_t<Specifications>...>
using SpecificationSet = detail::CanonicalSpecificationSet<std::remove_cvref_t<Specifications>...>;
template <SpecificationRole Role, typename SpecificationSet>
@@ -1203,12 +1243,13 @@ export namespace mean_field::models {
[[nodiscard]] consteval SpecificationDescriptor specificationDescriptor() {
using Contribution = SpecificationContribution<Specification>;
return {.name = SpecificationTraits<Specification>::name,
.role = SpecificationTraits<Specification>::role,
.key = SpecificationTraits<Specification>::key,
.generatedValueArity = detail::ModelTypeListScalarArity<typename Contribution::GeneratedValues>::value,
.generatedResidualArity =
detail::ModelTypeListScalarArity<typename Contribution::GeneratedResiduals>::value};
return {
.name = SpecificationTraits<Specification>::name,
.role = SpecificationTraits<Specification>::role,
.key = SpecificationTraits<Specification>::key,
.generatedValueArity = detail::ModelTypeListScalarArity<typename Contribution::GeneratedValues>::value,
.generatedResidualArity = detail::ModelTypeListScalarArity<typename Contribution::GeneratedResiduals>::value
};
}
namespace detail {
@@ -1231,14 +1272,12 @@ export namespace mean_field::models {
std::tuple<ArgumentTypes...> &&arguments,
CanonicalArgumentsTag
)
: m_specifications(
std::get<Specifications>(std::move(arguments))...
) {
: m_specifications(std::get<Specifications>(std::move(arguments))...) {
}
public:
using SpecificationTypes = SpecificationSetStorage<Specifications...>;
using OperatorSignature = SpecificationOperatorSignature<SpecificationTypes>;
using SpecificationTypes = SpecificationSetStorage<Specifications...>;
using OperatorSignature = SpecificationOperatorSignature<SpecificationTypes>;
static constexpr bool symbolicallySquare = OperatorSignature::symbolicallySquare;
@@ -1249,22 +1288,27 @@ export namespace mean_field::models {
symbolicallySquare && (SpecificationContribution<Specifications>::hasDeclarativeDefinition && ...);
template <typename... Arguments>
requires ArgumentsMatchCanonicalSpecifications<SpecificationTypes, Arguments...>::value &&
requires ArgumentsMatchCanonicalSpecifications<
SpecificationTypes,
Arguments...>::value &&
std::constructible_from<
std::tuple<std::remove_cvref_t<Arguments>...>,
Arguments...> &&
(std::constructible_from<Specifications, Specifications &&> && ...)
(std::constructible_from<
Specifications,
Specifications &&> &&
...)
explicit SpecifiedModel(Arguments &&...arguments)
: SpecifiedModel(
std::tuple<std::remove_cvref_t<Arguments>...>{
std::forward<Arguments>(arguments)...
},
std::tuple<std::remove_cvref_t<Arguments>...>{std::forward<Arguments>(arguments)...},
CanonicalArgumentsTag{}
) {
}
template <ModelSpecification Specification>
requires isOneOf<Specification, Specifications...>
requires isOneOf<
Specification,
Specifications...>
[[nodiscard]] const Specification &specification() const noexcept {
return std::get<Specification>(m_specifications);
}
@@ -1282,10 +1326,11 @@ export namespace mean_field::models {
runtimeDescriptors = [] {
std::array<RuntimeSpecificationDescriptor, sizeof...(Specifications)> descriptors{};
std::size_t index = 0;
((descriptors[index] = {.specification = specificationDescriptor<Specifications>(),
.canonicalIndex = index,
.hasDeclarativeDefinition =
SpecificationContribution<Specifications>::hasDeclarativeDefinition},
((descriptors[index] =
{.specification = specificationDescriptor<Specifications>(),
.canonicalIndex = index,
.hasDeclarativeDefinition =
SpecificationContribution<Specifications>::hasDeclarativeDefinition},
++index),
...);
return descriptors;
@@ -1346,27 +1391,23 @@ export namespace mean_field::stellar {
} // namespace state
namespace equation {
using GravityGradientDefinition = models::stellar::equation::GravityGradientDefinition;
using PoissonEquation = models::stellar::equation::PoissonEquation;
using DensityClosure = models::stellar::equation::DensityClosure;
using SurfaceShapeBalance = models::stellar::equation::SurfaceShapeBalance;
using HydrostaticBalance = models::stellar::equation::HydrostaticBalance;
using OwnConstraint = models::stellar::equation::OwnConstraint;
using GravityGradientDefinition = models::stellar::equation::GravityGradientDefinition;
using PoissonEquation = models::stellar::equation::PoissonEquation;
using DensityClosure = models::stellar::equation::DensityClosure;
using SurfaceShapeBalance = models::stellar::equation::SurfaceShapeBalance;
using HydrostaticBalance = models::stellar::equation::HydrostaticBalance;
using OwnConstraint = models::stellar::equation::OwnConstraint;
template <typename Specification>
using ConstraintOf = models::stellar::equation::ConstraintOf<Specification>;
template <typename Specification> using ConstraintOf = models::stellar::equation::ConstraintOf<Specification>;
} // namespace equation
template <typename Equation, typename State>
using Derivative = models::stellar::Derivative<Equation, State>;
template <typename Equation, typename State> using Derivative = models::stellar::Derivative<Equation, State>;
template <typename... Quantities>
using Reads = models::DependsOn<Quantities...>;
template <typename... Quantities> using Reads = models::DependsOn<Quantities...>;
template <typename... Equations>
using Changes = models::Affects<Equations...>;
template <typename... Equations> using Changes = models::Affects<Equations...>;
using PhysicalScale = models::PhysicalScaleLaw;
using PhysicalScale = models::PhysicalScaleLaw;
template <
models::PhysicalScaleRepresentedQuantity TargetQuantity,
@@ -1393,10 +1434,8 @@ export namespace mean_field::stellar {
typename std::remove_cvref_t<Candidate>::GeneratedCoordinateQuantity;
typename std::remove_cvref_t<Candidate>::ConstraintResidualQuantity;
typename std::remove_cvref_t<Candidate>::TargetValue;
requires models::GeneratedNormalizationDefinition<
typename std::remove_cvref_t<Candidate>::Normalization>;
requires models::GeneratedManifestDefinition<
typename std::remove_cvref_t<Candidate>::Manifest>;
requires models::GeneratedNormalizationDefinition<typename std::remove_cvref_t<Candidate>::Normalization>;
requires models::GeneratedManifestDefinition<typename std::remove_cvref_t<Candidate>::Manifest>;
requires std::remove_cvref_t<Candidate>::Normalization::available;
requires std::remove_cvref_t<Candidate>::Manifest::available;
requires std::remove_cvref_t<Candidate>::dimensionallyTyped;
@@ -1407,31 +1446,43 @@ export namespace mean_field::integral {
using FixedTotalMass = models::FixedTotalMass;
using FixedAngularMomentum = models::FixedAngularMomentum;
template <typename Specification, models::FixedString Name, typename DependsOn = models::ModelTypeList<>,
typename Affects = models::ModelTypeList<>,
typename Normalization = models::UnavailableGeneratedNormalization,
typename Manifest = models::UnavailableGeneratedManifest>
template <
typename Specification,
models::FixedString Name,
typename DependsOn = models::ModelTypeList<>,
typename Affects = models::ModelTypeList<>,
typename Normalization = models::UnavailableGeneratedNormalization,
typename Manifest = models::UnavailableGeneratedManifest>
using FixedIntegralWithMultiplier =
models::FixedIntegralWithMultiplier<Specification, Name, DependsOn, Affects, Normalization, Manifest>;
template <typename Specification, models::FixedString Name, typename DependsOn = models::ModelTypeList<>,
typename Affects = models::ModelTypeList<>,
typename Normalization = models::UnavailableGeneratedNormalization,
typename Manifest = models::UnavailableGeneratedManifest>
template <
typename Specification,
models::FixedString Name,
typename DependsOn = models::ModelTypeList<>,
typename Affects = models::ModelTypeList<>,
typename Normalization = models::UnavailableGeneratedNormalization,
typename Manifest = models::UnavailableGeneratedManifest>
using FixedWithMultiplier =
FixedIntegralWithMultiplier<Specification, Name, DependsOn, Affects, Normalization, Manifest>;
template <typename Specification, models::FixedString Name, typename DependsOn = models::ModelTypeList<>,
typename Affects = models::ModelTypeList<>,
typename Normalization = models::UnavailableGeneratedNormalization,
typename Manifest = models::UnavailableGeneratedManifest>
template <
typename Specification,
models::FixedString Name,
typename DependsOn = models::ModelTypeList<>,
typename Affects = models::ModelTypeList<>,
typename Normalization = models::UnavailableGeneratedNormalization,
typename Manifest = models::UnavailableGeneratedManifest>
using FixedIntegralWithPhysicalCoordinate =
models::FixedIntegralWithPhysicalCoordinate<Specification, Name, DependsOn, Affects, Normalization, Manifest>;
template <typename Specification, models::FixedString Name, typename DependsOn = models::ModelTypeList<>,
typename Affects = models::ModelTypeList<>,
typename Normalization = models::UnavailableGeneratedNormalization,
typename Manifest = models::UnavailableGeneratedManifest>
template <
typename Specification,
models::FixedString Name,
typename DependsOn = models::ModelTypeList<>,
typename Affects = models::ModelTypeList<>,
typename Normalization = models::UnavailableGeneratedNormalization,
typename Manifest = models::UnavailableGeneratedManifest>
using FixedWithPhysicalCoordinate =
FixedIntegralWithPhysicalCoordinate<Specification, Name, DependsOn, Affects, Normalization, Manifest>;
@@ -1467,10 +1518,13 @@ export namespace mean_field::integral {
export namespace mean_field::constraint {
using FixedCentralDensity = models::FixedCentralDensity;
template <typename Specification, models::FixedString Name, typename DependsOn = models::ModelTypeList<>,
typename Affects = models::ModelTypeList<>,
typename Normalization = models::UnavailableGeneratedNormalization,
typename Manifest = models::UnavailableGeneratedManifest>
template <
typename Specification,
models::FixedString Name,
typename DependsOn = models::ModelTypeList<>,
typename Affects = models::ModelTypeList<>,
typename Normalization = models::UnavailableGeneratedNormalization,
typename Manifest = models::UnavailableGeneratedManifest>
using PhaseCondition = models::PhaseCondition<Specification, Name, DependsOn, Affects, Normalization, Manifest>;
template <