2410 lines
102 KiB
C++
2410 lines
102 KiB
C++
#include <concepts>
|
|
#include <memory>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
#include <catch2/catch_test_macros.hpp>
|
|
#include <mfem.hpp>
|
|
|
|
import mean_field;
|
|
|
|
namespace stellar_runtime_contract_test {
|
|
template <mean_field::model::StellarModelType Model>
|
|
class PreparedMissingRieszScalarConstraint;
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
class PreparedSecondRotationController;
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
class PreparedRawNestedProtocolConstraint;
|
|
|
|
struct NonDefaultRuntimeReport final {
|
|
NonDefaultRuntimeReport() = delete;
|
|
explicit constexpr NonDefaultRuntimeReport(const bool changed) noexcept
|
|
: m_changed(changed) {}
|
|
|
|
[[nodiscard]] constexpr bool DidAnyWork() const noexcept { return m_changed; }
|
|
|
|
private:
|
|
bool m_changed;
|
|
};
|
|
|
|
struct NonAssignableRuntimeReport final {
|
|
constexpr NonAssignableRuntimeReport() noexcept = default;
|
|
NonAssignableRuntimeReport(const NonAssignableRuntimeReport &) = default;
|
|
NonAssignableRuntimeReport(NonAssignableRuntimeReport &&) = default;
|
|
NonAssignableRuntimeReport &operator=(const NonAssignableRuntimeReport &) =
|
|
delete;
|
|
NonAssignableRuntimeReport &operator=(NonAssignableRuntimeReport &&) =
|
|
delete;
|
|
|
|
[[nodiscard]] constexpr bool DidAnyWork() const noexcept { return false; }
|
|
};
|
|
|
|
/* Deliberately carries no framework-specific work-reporting method. A
|
|
* third-party report is storage for its author's diagnostics, not an input to
|
|
* residual-cache correctness. */
|
|
struct OpaqueRuntimeReport final {
|
|
bool prepared{true};
|
|
};
|
|
|
|
template <mean_field::model::StellarModelType Model, typename ReportType>
|
|
class PreparedReportContractRuntime final {
|
|
public:
|
|
using Report = ReportType;
|
|
|
|
template <mean_field::models::ModelSpecification Specification>
|
|
explicit PreparedReportContractRuntime(const Specification &) noexcept {}
|
|
|
|
template <typename StateView>
|
|
[[nodiscard]] Report PrepareAfterPhysical(const StateView &) noexcept {
|
|
if constexpr (std::default_initializable<Report>) {
|
|
return {};
|
|
} else {
|
|
return Report{false};
|
|
}
|
|
}
|
|
|
|
template <typename Equation, typename Row>
|
|
[[nodiscard]] mean_field::stellar::StructuralZero AddResidual(
|
|
Equation,
|
|
Row &) const noexcept {
|
|
return mean_field::stellar::structuralZero;
|
|
}
|
|
|
|
template <typename Equation, typename State, typename Direction, typename Row>
|
|
[[nodiscard]] mean_field::stellar::StructuralZero AddJacobianAction(
|
|
mean_field::stellar::Derivative<Equation, State>,
|
|
const Direction &,
|
|
Row &) const noexcept {
|
|
return mean_field::stellar::zeroDerivative;
|
|
}
|
|
|
|
[[nodiscard]] constexpr bool IsPrepared() const noexcept { return true; }
|
|
};
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
using PreparedNonDefaultReportRuntime =
|
|
PreparedReportContractRuntime<Model, NonDefaultRuntimeReport>;
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
using PreparedNonAssignableReportRuntime =
|
|
PreparedReportContractRuntime<Model, NonAssignableRuntimeReport>;
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
using PreparedOpaqueReportRuntime =
|
|
PreparedReportContractRuntime<Model, OpaqueRuntimeReport>;
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
using PreparedAmbiguousRegistrationRuntime = PreparedReportContractRuntime<
|
|
Model, mean_field::operators::EmptySpecificationPreparationReport>;
|
|
|
|
struct NonDefaultReportConstraint final {
|
|
struct Parameters final {
|
|
mean_field::dimensions::SpecificEnthalpyValue target;
|
|
};
|
|
|
|
using ScalarDescription = mean_field::stellar::ScalarConstraint<
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
"runtime.non_default.value", "lambda_nd",
|
|
"runtime.non_default.residual", "R_nd">;
|
|
using ModelDefinition = mean_field::constraint::ScalarPhaseCondition<
|
|
NonDefaultReportConstraint, "NonDefaultReportConstraint",
|
|
mean_field::stellar::Reads<
|
|
mean_field::stellar::state::SpecificEnthalpy>,
|
|
mean_field::stellar::Changes<
|
|
mean_field::stellar::equation::HydrostaticBalance>,
|
|
ScalarDescription>;
|
|
using EquilibriumPhysics = mean_field::operators::SpecificationEquilibriumPhysics<
|
|
PreparedNonDefaultReportRuntime>;
|
|
|
|
explicit constexpr NonDefaultReportConstraint(Parameters parameters) noexcept
|
|
: m_target(parameters.target) {}
|
|
[[nodiscard]] constexpr auto target() const noexcept { return m_target; }
|
|
|
|
private:
|
|
mean_field::dimensions::SpecificEnthalpyValue m_target;
|
|
};
|
|
|
|
struct NonAssignableReportConstraint final {
|
|
struct Parameters final {
|
|
mean_field::dimensions::SpecificEnthalpyValue target;
|
|
};
|
|
|
|
using ScalarDescription = mean_field::stellar::ScalarConstraint<
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
"runtime.non_assignable.value", "lambda_na",
|
|
"runtime.non_assignable.residual", "R_na">;
|
|
using ModelDefinition = mean_field::constraint::ScalarPhaseCondition<
|
|
NonAssignableReportConstraint, "NonAssignableReportConstraint",
|
|
mean_field::stellar::Reads<
|
|
mean_field::stellar::state::SpecificEnthalpy>,
|
|
mean_field::stellar::Changes<
|
|
mean_field::stellar::equation::HydrostaticBalance>,
|
|
ScalarDescription>;
|
|
using EquilibriumPhysics = mean_field::operators::SpecificationEquilibriumPhysics<
|
|
PreparedNonAssignableReportRuntime>;
|
|
|
|
explicit constexpr NonAssignableReportConstraint(Parameters parameters) noexcept
|
|
: m_target(parameters.target) {}
|
|
[[nodiscard]] constexpr auto target() const noexcept { return m_target; }
|
|
|
|
private:
|
|
mean_field::dimensions::SpecificEnthalpyValue m_target;
|
|
};
|
|
|
|
struct OpaqueReportConstraint final {
|
|
struct Parameters final {
|
|
mean_field::dimensions::SpecificEnthalpyValue target;
|
|
};
|
|
|
|
using ScalarDescription = mean_field::stellar::ScalarConstraint<
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
"runtime.opaque.value", "lambda_opaque",
|
|
"runtime.opaque.residual", "R_opaque">;
|
|
using ModelDefinition = mean_field::constraint::ScalarPhaseCondition<
|
|
OpaqueReportConstraint, "OpaqueReportConstraint",
|
|
mean_field::stellar::Reads<
|
|
mean_field::stellar::state::SpecificEnthalpy>,
|
|
mean_field::stellar::Changes<
|
|
mean_field::stellar::equation::HydrostaticBalance>,
|
|
ScalarDescription>;
|
|
using EquilibriumPhysics =
|
|
mean_field::operators::SpecificationEquilibriumPhysics<
|
|
PreparedOpaqueReportRuntime>;
|
|
|
|
explicit constexpr OpaqueReportConstraint(Parameters parameters) noexcept
|
|
: m_target(parameters.target) {}
|
|
[[nodiscard]] constexpr auto target() const noexcept { return m_target; }
|
|
|
|
private:
|
|
mean_field::dimensions::SpecificEnthalpyValue m_target;
|
|
};
|
|
|
|
/* This fixture implements the former nested protocol verbatim. It is a
|
|
* physics-facing declaration, so raw backend access must not make it an
|
|
* executable contribution. */
|
|
struct RawNestedProtocolConstraint final {
|
|
struct Parameters final {
|
|
mean_field::dimensions::SpecificEnthalpyValue target;
|
|
};
|
|
|
|
using ScalarDescription = mean_field::stellar::ScalarConstraint<
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
"runtime.raw.value", "lambda_raw",
|
|
"runtime.raw.residual", "R_raw">;
|
|
using ModelDefinition = mean_field::constraint::ScalarPhaseCondition<
|
|
RawNestedProtocolConstraint, "RawNestedProtocolConstraint",
|
|
mean_field::stellar::Reads<
|
|
mean_field::stellar::state::SpecificEnthalpy>,
|
|
mean_field::stellar::Changes<
|
|
mean_field::stellar::equation::HydrostaticBalance>,
|
|
ScalarDescription>;
|
|
using EquilibriumPhysics =
|
|
mean_field::operators::SpecificationEquilibriumPhysics<
|
|
PreparedRawNestedProtocolConstraint>;
|
|
|
|
explicit constexpr RawNestedProtocolConstraint(Parameters parameters) noexcept
|
|
: m_target(parameters.target) {}
|
|
[[nodiscard]] constexpr auto target() const noexcept { return m_target; }
|
|
|
|
private:
|
|
mean_field::dimensions::SpecificEnthalpyValue m_target;
|
|
};
|
|
|
|
struct AmbiguousRuntimeRegistrationConstraint final {
|
|
struct Parameters final {
|
|
mean_field::dimensions::SpecificEnthalpyValue target;
|
|
};
|
|
|
|
using ScalarDescription = mean_field::stellar::ScalarConstraint<
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
"runtime.ambiguous.value", "lambda_ar",
|
|
"runtime.ambiguous.residual", "R_ar">;
|
|
using ModelDefinition = mean_field::constraint::ScalarPhaseCondition<
|
|
AmbiguousRuntimeRegistrationConstraint,
|
|
"AmbiguousRuntimeRegistrationConstraint",
|
|
mean_field::stellar::Reads<
|
|
mean_field::stellar::state::SpecificEnthalpy>,
|
|
mean_field::stellar::Changes<
|
|
mean_field::stellar::equation::HydrostaticBalance>,
|
|
ScalarDescription>;
|
|
using EquilibriumPhysics = mean_field::operators::SpecificationEquilibriumPhysics<
|
|
PreparedAmbiguousRegistrationRuntime>;
|
|
|
|
explicit constexpr AmbiguousRuntimeRegistrationConstraint(
|
|
Parameters parameters) noexcept
|
|
: m_target(parameters.target) {}
|
|
[[nodiscard]] constexpr auto target() const noexcept { return m_target; }
|
|
|
|
private:
|
|
mean_field::dimensions::SpecificEnthalpyValue m_target;
|
|
};
|
|
|
|
/* A complete aggregate backend candidate with no nested provider. Its raw
|
|
* registration is deliberately not authorized by the built-in concrete core,
|
|
* so the runtime capability must reject it at exactly that boundary. */
|
|
struct UnauthorizedAggregateConstraint final {
|
|
struct Parameters final {
|
|
mean_field::dimensions::SpecificEnthalpyValue target;
|
|
};
|
|
|
|
using ScalarDescription = mean_field::stellar::ScalarConstraint<
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
mean_field::dimensions::quantity::SpecificEnthalpy,
|
|
"runtime.unauthorized.value", "lambda_unauthorized",
|
|
"runtime.unauthorized.residual", "R_unauthorized">;
|
|
using ModelDefinition = mean_field::constraint::ScalarPhaseCondition<
|
|
UnauthorizedAggregateConstraint,
|
|
"UnauthorizedAggregateConstraint",
|
|
mean_field::stellar::Reads<
|
|
mean_field::stellar::state::SpecificEnthalpy>,
|
|
mean_field::stellar::Changes<
|
|
mean_field::stellar::equation::HydrostaticBalance>,
|
|
ScalarDescription>;
|
|
|
|
explicit constexpr UnauthorizedAggregateConstraint(
|
|
Parameters parameters) noexcept
|
|
: m_target(parameters.target) {}
|
|
|
|
[[nodiscard]] constexpr auto target() const noexcept { return m_target; }
|
|
|
|
private:
|
|
mean_field::dimensions::SpecificEnthalpyValue m_target;
|
|
};
|
|
|
|
struct RegisteredWithoutMakeEquationOfState final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = mean_field::models::ConstitutiveLaw<
|
|
RegisteredWithoutMakeEquationOfState,
|
|
"RegisteredWithoutMakeEquationOfState">;
|
|
|
|
explicit RegisteredWithoutMakeEquationOfState(Parameters) noexcept {}
|
|
};
|
|
|
|
struct IncompleteSurfaceRuntime final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = mean_field::surface::BoundaryCondition<
|
|
IncompleteSurfaceRuntime, "IncompleteSurfaceRuntime">;
|
|
|
|
explicit IncompleteSurfaceRuntime(Parameters) noexcept {}
|
|
};
|
|
|
|
/*
|
|
* This constraint is executable and has complete diagnostic metadata, but it
|
|
* deliberately omits its generated-coordinate Physical Riesz declaration.
|
|
* It isolates model/discretization compatibility from every other runtime
|
|
* capability in the rejection-boundary tests below.
|
|
*/
|
|
struct MissingRieszScalarConstraint final {
|
|
struct Parameters final {
|
|
mean_field::dimensions::MassValue target;
|
|
};
|
|
|
|
using TargetValue = mean_field::dimensions::MassValue;
|
|
using ModelDefinition = mean_field::integral::FixedIntegralWithMultiplier<
|
|
MissingRieszScalarConstraint, "MissingRieszScalarConstraint",
|
|
mean_field::models::DependsOn<
|
|
mean_field::models::stellar::state::Density>,
|
|
mean_field::models::Affects<
|
|
mean_field::models::stellar::equation::HydrostaticBalance>,
|
|
mean_field::models::UnavailableGeneratedNormalization,
|
|
mean_field::models::GeneratedManifest<
|
|
"missing_riesz.multiplier", "lambda_mr",
|
|
"missing_riesz.residual", "R_mr", "mass", "mass">>;
|
|
using EquilibriumPhysics =
|
|
mean_field::operators::SpecificationEquilibriumPhysics<
|
|
PreparedMissingRieszScalarConstraint>;
|
|
|
|
explicit MissingRieszScalarConstraint(Parameters parameters) noexcept
|
|
: m_target(parameters.target) {}
|
|
|
|
[[nodiscard]] TargetValue target() const noexcept { return m_target; }
|
|
|
|
private:
|
|
TargetValue m_target;
|
|
};
|
|
|
|
/* A second, independently inferred rotation source. Its numerical runtime is
|
|
* otherwise complete; pairing it with FixedAngularMomentum must fail solely
|
|
* because a physical model cannot have two owners for the generated rotation
|
|
* control. */
|
|
struct SecondRotationController final {
|
|
struct Parameters final {
|
|
mean_field::dimensions::SpecificEnthalpyValue target;
|
|
};
|
|
|
|
using TargetValue = mean_field::dimensions::SpecificEnthalpyValue;
|
|
using ModelDefinition = mean_field::constraint::PhaseCondition<
|
|
SecondRotationController, "SecondRotationController",
|
|
mean_field::models::DependsOn<
|
|
mean_field::models::stellar::state::SpecificEnthalpy>,
|
|
mean_field::models::Affects<
|
|
mean_field::models::stellar::equation::HydrostaticBalance>,
|
|
mean_field::models::GlobalScalarNormalization<
|
|
mean_field::models::PhysicalScaleLaw::specific_energy,
|
|
mean_field::models::PhysicalScaleLaw::specific_energy>,
|
|
mean_field::models::GeneratedManifest<
|
|
"second_rotation.control", "omega_2",
|
|
"second_rotation.residual", "R_omega_2",
|
|
"specific_enthalpy", "specific_enthalpy">>;
|
|
using EquilibriumPhysics =
|
|
mean_field::operators::SpecificationEquilibriumPhysics<
|
|
PreparedSecondRotationController,
|
|
1>;
|
|
|
|
explicit SecondRotationController(Parameters parameters) noexcept
|
|
: m_target(parameters.target) {}
|
|
|
|
[[nodiscard]] TargetValue target() const noexcept { return m_target; }
|
|
|
|
private:
|
|
TargetValue m_target;
|
|
};
|
|
|
|
struct AlternateCoreEquationOfState final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = mean_field::models::ConstitutiveLaw<
|
|
AlternateCoreEquationOfState, "AlternateCoreEquationOfState">;
|
|
using Relations = mean_field::eos::RelationCatalog<
|
|
mean_field::eos::SpecificEnthalpyFromPressure>;
|
|
|
|
explicit AlternateCoreEquationOfState(Parameters) noexcept {}
|
|
|
|
[[nodiscard]] mean_field::dimensions::SpecificEnthalpyValue evaluate(
|
|
mean_field::eos::SpecificEnthalpyFromPressure,
|
|
mean_field::dimensions::PressureValue) const;
|
|
};
|
|
|
|
struct WrongOwnerEquationOfState final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = mean_field::models::ConstitutiveLaw<
|
|
WrongOwnerEquationOfState, "WrongOwnerEquationOfState">;
|
|
|
|
explicit WrongOwnerEquationOfState(Parameters) noexcept {}
|
|
};
|
|
|
|
/*
|
|
* A deliberately tiny alternate core. No MFEM stellar assembly is needed:
|
|
* this type exists to prove that the extension protocol is structural and
|
|
* does not name the Polytrope implementation.
|
|
*/
|
|
class AlternatePhysicalCore : public mfem::Operator {
|
|
public:
|
|
using BackendSpecifications = mean_field::models::ModelTypeList<
|
|
AlternateCoreEquationOfState,
|
|
WrongOwnerEquationOfState,
|
|
mean_field::surface::Isobaric,
|
|
mean_field::models::FixedTotalMass,
|
|
mean_field::models::FixedAngularMomentum,
|
|
AmbiguousRuntimeRegistrationConstraint>;
|
|
|
|
using mfem::Operator::Operator;
|
|
|
|
void Mult(const mfem::Vector &, mfem::Vector &) const override;
|
|
|
|
[[nodiscard]] const mean_field::operators::StellarEquilibriumLayout &
|
|
GetLayout() const noexcept;
|
|
|
|
[[nodiscard]] mean_field::operators::PreparedStellarEquilibriumReport Prepare(
|
|
const mfem::Vector &,
|
|
const mean_field::operators::StellarEquilibriumDependencies &,
|
|
const mean_field::physics::RigidRotation &);
|
|
|
|
void BuildResidual(mfem::Vector &) const;
|
|
[[nodiscard]] bool IsPrepared() const noexcept;
|
|
[[nodiscard]] mean_field::operators::RootConstraintReport
|
|
GetFixedMassReport() const;
|
|
[[nodiscard]] const mean_field::operators::StellarEquilibriumDependencies &
|
|
GetDependencies() const;
|
|
[[nodiscard]] const mean_field::operators::StellarEquilibriumDependencyStamp &
|
|
GetGeneratedDisplacementDependency() const;
|
|
[[nodiscard]] const mean_field::operators::PreparedPressureSurfaceConstraint &
|
|
GetSurfaceConstraintOperator() const;
|
|
};
|
|
|
|
class PhysicalRieszGravityContext final {
|
|
public:
|
|
[[nodiscard]] const mean_field::field::FieldDofMap &GetDensityMap() const
|
|
noexcept;
|
|
[[nodiscard]] const mean_field::field::FieldDofMap &
|
|
GetGravityGradientMap() const noexcept;
|
|
[[nodiscard]] const mean_field::field::FieldDofMap &
|
|
GetGravityPotentialMap() const noexcept;
|
|
};
|
|
|
|
class PhysicalRieszHydrostaticOperator final {
|
|
public:
|
|
[[nodiscard]] const mean_field::field::FieldDofMap &GetEnthalpyMap() const
|
|
noexcept;
|
|
};
|
|
|
|
class PhysicalRieszDomainDeformation final {
|
|
public:
|
|
[[nodiscard]] int parameterCount() const noexcept;
|
|
};
|
|
|
|
/*
|
|
* Declaration-only opt-in mock: the normalization capability is structural,
|
|
* so none of the heavyweight MFEM physical assembly needs to be constructed
|
|
* to prove that a distinct core can satisfy it.
|
|
*/
|
|
class PhysicalRieszCapableCore final : public AlternatePhysicalCore {
|
|
public:
|
|
using AlternatePhysicalCore::AlternatePhysicalCore;
|
|
|
|
[[nodiscard]] const PhysicalRieszGravityContext &GetGravityContext() const
|
|
noexcept;
|
|
[[nodiscard]] const PhysicalRieszHydrostaticOperator &
|
|
GetHydrostaticOperator() const noexcept;
|
|
[[nodiscard]] const PhysicalRieszDomainDeformation &GetDomainDeformation()
|
|
const noexcept;
|
|
};
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
class AlternateEquationOfStateRuntime final {
|
|
public:
|
|
using Report = mean_field::operators::EmptySpecificationPreparationReport;
|
|
|
|
AlternateEquationOfStateRuntime(
|
|
mean_field::fem::FEM &, const mean_field::mapping::DomainMapper &,
|
|
AlternatePhysicalCore &, const Model &) noexcept {}
|
|
|
|
template <typename StateView, typename Controls>
|
|
void ReadPhysicalControls(const StateView &, Controls &) noexcept {}
|
|
|
|
template <typename StateView>
|
|
[[nodiscard]] Report PrepareAfterPhysical(
|
|
const StateView &,
|
|
const mean_field::operators::StellarEquilibriumDependencies &,
|
|
const AlternatePhysicalCore &) noexcept {
|
|
return {};
|
|
}
|
|
|
|
template <typename ResidualView>
|
|
void AddResidual(const ResidualView &) const noexcept {}
|
|
|
|
template <typename DirectionView, typename ActionView>
|
|
void AddJacobianAction(const DirectionView &, const ActionView &,
|
|
const AlternatePhysicalCore &) const noexcept {}
|
|
|
|
[[nodiscard]] bool IsPrepared() const noexcept { return true; }
|
|
};
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
class IncompletePreparedSurfaceRuntime final {
|
|
public:
|
|
struct Report final {
|
|
[[nodiscard]] constexpr bool DidAnyWork() const noexcept { return false; }
|
|
};
|
|
|
|
IncompletePreparedSurfaceRuntime(
|
|
mean_field::fem::FEM &, const mean_field::mapping::DomainMapper &,
|
|
mean_field::operators::PreparedStellarEquilibriumOperator &,
|
|
const Model &) noexcept {}
|
|
|
|
// Intentionally omits the preparation and operator-action interface.
|
|
};
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
class PreparedMissingRieszScalarConstraint final {
|
|
public:
|
|
using Report = mean_field::operators::EmptySpecificationPreparationReport;
|
|
|
|
explicit PreparedMissingRieszScalarConstraint(
|
|
const MissingRieszScalarConstraint &) noexcept {}
|
|
|
|
template <typename StateView>
|
|
[[nodiscard]] Report PrepareAfterPhysical(const StateView &) noexcept {
|
|
return {};
|
|
}
|
|
|
|
template <typename Equation, typename Row>
|
|
[[nodiscard]] mean_field::stellar::StructuralZero AddResidual(
|
|
Equation,
|
|
Row &) const noexcept {
|
|
return mean_field::stellar::structuralZero;
|
|
}
|
|
|
|
template <typename Equation, typename State, typename Direction, typename Row>
|
|
[[nodiscard]] mean_field::stellar::StructuralZero AddJacobianAction(
|
|
mean_field::stellar::Derivative<Equation, State>,
|
|
const Direction &,
|
|
Row &) const noexcept {
|
|
return mean_field::stellar::zeroDerivative;
|
|
}
|
|
|
|
[[nodiscard]] constexpr bool IsPrepared() const noexcept { return true; }
|
|
};
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
class PreparedSecondRotationController final {
|
|
public:
|
|
using Report = mean_field::operators::EmptySpecificationPreparationReport;
|
|
|
|
explicit PreparedSecondRotationController(
|
|
const SecondRotationController &) noexcept {}
|
|
|
|
template <typename StateView>
|
|
[[nodiscard]] mean_field::physics::RigidRotation
|
|
GenerateRotation(const StateView &) const {
|
|
mfem::Vector angularVelocity(3);
|
|
mfem::Vector center(3);
|
|
angularVelocity = 0.0;
|
|
center = 0.0;
|
|
return {angularVelocity, center};
|
|
}
|
|
|
|
template <typename StateView>
|
|
[[nodiscard]] Report PrepareAfterPhysical(const StateView &) noexcept {
|
|
return {};
|
|
}
|
|
|
|
template <typename Equation, typename Row>
|
|
[[nodiscard]] mean_field::stellar::StructuralZero AddResidual(
|
|
Equation,
|
|
Row &) const noexcept {
|
|
return mean_field::stellar::structuralZero;
|
|
}
|
|
|
|
template <typename Equation, typename State, typename Direction, typename Row>
|
|
[[nodiscard]] mean_field::stellar::StructuralZero AddJacobianAction(
|
|
mean_field::stellar::Derivative<Equation, State>,
|
|
const Direction &,
|
|
Row &) const noexcept {
|
|
return mean_field::stellar::zeroDerivative;
|
|
}
|
|
|
|
[[nodiscard]] constexpr bool IsPrepared() const noexcept { return true; }
|
|
};
|
|
|
|
template <mean_field::model::StellarModelType Model>
|
|
class PreparedRawNestedProtocolConstraint final {
|
|
public:
|
|
using Report = OpaqueRuntimeReport;
|
|
|
|
template <mean_field::operators::PreparedStellarEquilibriumPhysicalCore Core>
|
|
PreparedRawNestedProtocolConstraint(
|
|
mean_field::fem::FEM &, const mean_field::mapping::DomainMapper &,
|
|
Core &, const Model &) noexcept {}
|
|
|
|
template <typename StateView, typename Controls>
|
|
void ReadPhysicalControls(const StateView &, Controls &) noexcept {}
|
|
|
|
template <typename StateView,
|
|
mean_field::operators::PreparedStellarEquilibriumPhysicalCore Core>
|
|
[[nodiscard]] Report PrepareAfterPhysical(
|
|
const StateView &,
|
|
const mean_field::operators::StellarEquilibriumDependencies &,
|
|
const Core &) noexcept {
|
|
return {};
|
|
}
|
|
|
|
template <typename ResidualView>
|
|
void AddResidual(const ResidualView &) const noexcept {}
|
|
|
|
template <typename DirectionView, typename ActionView,
|
|
mean_field::operators::PreparedStellarEquilibriumPhysicalCore Core>
|
|
void AddJacobianAction(const DirectionView &, const ActionView &,
|
|
const Core &) const noexcept {}
|
|
|
|
[[nodiscard]] constexpr bool IsPrepared() const noexcept { return true; }
|
|
};
|
|
} // namespace stellar_runtime_contract_test
|
|
|
|
namespace mean_field::operators {
|
|
template <>
|
|
struct StellarEquilibriumCoreRuntime<
|
|
stellar_runtime_contract_test::RegisteredWithoutMakeEquationOfState> {
|
|
static constexpr bool registered = true;
|
|
// Intentionally no Make(). Capability follows the callable interface.
|
|
};
|
|
|
|
|
|
template <>
|
|
struct StellarEquilibriumCoreRuntime<
|
|
stellar_runtime_contract_test::AlternateCoreEquationOfState> {
|
|
static constexpr bool registered = true;
|
|
using CoreType = stellar_runtime_contract_test::AlternatePhysicalCore;
|
|
|
|
[[nodiscard]] static std::unique_ptr<CoreType> Make(
|
|
fem::FEM &, const mapping::DomainMapper &,
|
|
const stellar_runtime_contract_test::AlternateCoreEquationOfState &,
|
|
const models::CompiledFixedMass &, PressureSurfaceConstraintView,
|
|
deformation::PreparedDomainDeformationRuntime);
|
|
|
|
[[nodiscard]] static int SurfaceEquationCount(const CoreType &) noexcept;
|
|
};
|
|
|
|
template <>
|
|
struct StellarEquilibriumRuntimeContribution<
|
|
stellar_runtime_contract_test::AlternateCoreEquationOfState>
|
|
: PreparedStellarEquilibriumContribution<
|
|
stellar_runtime_contract_test::AlternateEquationOfStateRuntime> {};
|
|
|
|
template <>
|
|
struct StellarEquilibriumCoreRuntime<
|
|
stellar_runtime_contract_test::WrongOwnerEquationOfState> {
|
|
static constexpr bool registered = true;
|
|
using CoreType = stellar_runtime_contract_test::AlternatePhysicalCore;
|
|
|
|
// Intentionally owns the Polytrope core instead of the advertised type.
|
|
[[nodiscard]] static std::unique_ptr<PreparedStellarEquilibriumOperator> Make(
|
|
fem::FEM &, const mapping::DomainMapper &,
|
|
const stellar_runtime_contract_test::WrongOwnerEquationOfState &,
|
|
const models::CompiledFixedMass &, PressureSurfaceConstraintView,
|
|
deformation::PreparedDomainDeformationRuntime);
|
|
|
|
[[nodiscard]] static int SurfaceEquationCount(const CoreType &) noexcept;
|
|
};
|
|
|
|
template <>
|
|
struct StellarEquilibriumRuntimeContribution<
|
|
stellar_runtime_contract_test::WrongOwnerEquationOfState>
|
|
: PreparedStellarEquilibriumContribution<
|
|
stellar_runtime_contract_test::AlternateEquationOfStateRuntime> {};
|
|
|
|
template <>
|
|
struct StellarEquilibriumRuntimeContribution<
|
|
stellar_runtime_contract_test::IncompleteSurfaceRuntime>
|
|
: PreparedStellarEquilibriumContribution<
|
|
stellar_runtime_contract_test::IncompletePreparedSurfaceRuntime> {};
|
|
|
|
template <>
|
|
struct StellarEquilibriumRuntimeContribution<
|
|
stellar_runtime_contract_test::UnauthorizedAggregateConstraint>
|
|
: PreparedStellarEquilibriumContribution<
|
|
stellar_runtime_contract_test::
|
|
PreparedRawNestedProtocolConstraint> {};
|
|
|
|
/* Deliberately duplicates the constraint's nested package. Whether that is an
|
|
* ambiguity depends on the selected core's own privileged allow-list. */
|
|
template <>
|
|
struct StellarEquilibriumRuntimeContribution<
|
|
stellar_runtime_contract_test::AmbiguousRuntimeRegistrationConstraint>
|
|
: PreparedStellarEquilibriumContribution<
|
|
stellar_runtime_contract_test::
|
|
AlternateEquationOfStateRuntime> {};
|
|
|
|
} // namespace mean_field::operators
|
|
|
|
namespace {
|
|
using namespace mean_field;
|
|
|
|
using BaseModel = model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass>>;
|
|
|
|
using CentralDensityModel = model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
models::FixedCentralDensity>>;
|
|
|
|
using AngularMomentumModel = model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
models::FixedAngularMomentum>>;
|
|
|
|
using AngularCentralDensityModel =
|
|
model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
models::FixedAngularMomentum, models::FixedCentralDensity>>;
|
|
|
|
using DensityValue = utils::blocks::density::mass::value;
|
|
using SurfaceValue = utils::blocks::surface_deformation::parameters::value;
|
|
using GravityGradientValue = utils::blocks::gravity::gradient::value;
|
|
using GravityPotentialValue = utils::blocks::gravity::poisson::value;
|
|
using EnthalpyValue = utils::blocks::enthalpy::specific::value;
|
|
using MassValue =
|
|
utils::blocks::fixed_total_mass::mass_normalization::value;
|
|
using AngularVelocityValue =
|
|
utils::blocks::fixed_angular_momentum::angular_velocity::value;
|
|
using CentralDensityValue =
|
|
utils::blocks::fixed_central_density::central_value::value;
|
|
|
|
using GravityGradientResidual = utils::blocks::gravity::gradient::residual;
|
|
using GravityPotentialResidual = utils::blocks::gravity::poisson::residual;
|
|
using DensityResidual = utils::blocks::density::mass::residual;
|
|
using SurfaceResidual =
|
|
utils::blocks::surface_deformation::shape_equilibrium::residual;
|
|
using EnthalpyResidual = utils::blocks::enthalpy::specific::residual;
|
|
using MassResidual =
|
|
utils::blocks::fixed_total_mass::mass_normalization::residual;
|
|
using AngularMomentumResidual =
|
|
utils::blocks::fixed_angular_momentum::angular_velocity::residual;
|
|
using CentralDensityResidual =
|
|
utils::blocks::fixed_central_density::central_value::residual;
|
|
|
|
using ExpectedAngularMomentumForm = utils::blocks::block_form<
|
|
utils::blocks::type_list<DensityValue, SurfaceValue, GravityGradientValue,
|
|
GravityPotentialValue, EnthalpyValue, MassValue,
|
|
AngularVelocityValue>,
|
|
utils::blocks::type_list<
|
|
GravityGradientResidual, GravityPotentialResidual, DensityResidual,
|
|
SurfaceResidual, EnthalpyResidual, MassResidual,
|
|
AngularMomentumResidual>>;
|
|
|
|
using ExpectedAngularMomentumJacobian = utils::blocks::type_list<
|
|
utils::blocks::block_row<GravityGradientResidual, GravityGradientValue,
|
|
GravityPotentialValue, SurfaceValue>,
|
|
utils::blocks::block_row<GravityPotentialResidual, GravityGradientValue,
|
|
DensityValue, SurfaceValue>,
|
|
utils::blocks::block_row<DensityResidual, DensityValue, EnthalpyValue,
|
|
SurfaceValue>,
|
|
utils::blocks::block_row<SurfaceResidual, DensityValue, SurfaceValue,
|
|
GravityGradientValue, EnthalpyValue,
|
|
AngularVelocityValue>,
|
|
utils::blocks::block_row<EnthalpyResidual, EnthalpyValue,
|
|
GravityPotentialValue, SurfaceValue, DensityValue,
|
|
MassValue, AngularVelocityValue>,
|
|
utils::blocks::block_row<MassResidual, DensityValue, SurfaceValue>,
|
|
utils::blocks::block_row<AngularMomentumResidual, DensityValue,
|
|
SurfaceValue, AngularVelocityValue>>;
|
|
|
|
using ExpectedAngularCentralDensityForm = utils::blocks::block_form<
|
|
utils::blocks::type_list<DensityValue, SurfaceValue, GravityGradientValue,
|
|
GravityPotentialValue, EnthalpyValue, MassValue,
|
|
AngularVelocityValue, CentralDensityValue>,
|
|
utils::blocks::type_list<
|
|
GravityGradientResidual, GravityPotentialResidual, DensityResidual,
|
|
SurfaceResidual, EnthalpyResidual, MassResidual,
|
|
AngularMomentumResidual, CentralDensityResidual>>;
|
|
|
|
using ExpectedAngularCentralDensityJacobian = utils::blocks::type_list<
|
|
utils::blocks::block_row<GravityGradientResidual, GravityGradientValue,
|
|
GravityPotentialValue, SurfaceValue>,
|
|
utils::blocks::block_row<GravityPotentialResidual, GravityGradientValue,
|
|
DensityValue, SurfaceValue>,
|
|
utils::blocks::block_row<DensityResidual, DensityValue, EnthalpyValue,
|
|
SurfaceValue>,
|
|
utils::blocks::block_row<SurfaceResidual, DensityValue, SurfaceValue,
|
|
GravityGradientValue, EnthalpyValue,
|
|
AngularVelocityValue>,
|
|
utils::blocks::block_row<EnthalpyResidual, EnthalpyValue,
|
|
GravityPotentialValue, SurfaceValue, DensityValue,
|
|
MassValue, AngularVelocityValue,
|
|
CentralDensityValue>,
|
|
utils::blocks::block_row<MassResidual, DensityValue, SurfaceValue>,
|
|
utils::blocks::block_row<AngularMomentumResidual, DensityValue,
|
|
SurfaceValue, AngularVelocityValue>,
|
|
utils::blocks::block_row<CentralDensityResidual, EnthalpyValue>>;
|
|
|
|
using MissingMassModel = model::StellarModel<
|
|
models::SpecificationSet<eos::Polytrope, surface::Isobaric>>;
|
|
|
|
using RegisteredWithoutMakeModel = model::StellarModel<models::SpecificationSet<
|
|
stellar_runtime_contract_test::RegisteredWithoutMakeEquationOfState,
|
|
surface::Isobaric, models::FixedTotalMass>>;
|
|
|
|
using AlternateCoreModel = model::StellarModel<models::SpecificationSet<
|
|
stellar_runtime_contract_test::AlternateCoreEquationOfState,
|
|
surface::Isobaric, models::FixedTotalMass>>;
|
|
|
|
using AlternateCoreAngularMomentumModel =
|
|
model::StellarModel<models::SpecificationSet<
|
|
stellar_runtime_contract_test::AlternateCoreEquationOfState,
|
|
surface::Isobaric, models::FixedTotalMass,
|
|
models::FixedAngularMomentum>>;
|
|
|
|
using MissingRieszModel = model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
stellar_runtime_contract_test::MissingRieszScalarConstraint>>;
|
|
|
|
using TwoRotationProvidersModel =
|
|
model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
models::FixedAngularMomentum,
|
|
stellar_runtime_contract_test::SecondRotationController>>;
|
|
|
|
using NonDefaultReportModel = model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
stellar_runtime_contract_test::NonDefaultReportConstraint>>;
|
|
|
|
using NonAssignableReportModel = model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
stellar_runtime_contract_test::NonAssignableReportConstraint>>;
|
|
|
|
using OpaqueReportModel = model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
stellar_runtime_contract_test::OpaqueReportConstraint>>;
|
|
|
|
using RawNestedProtocolModel = model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
stellar_runtime_contract_test::RawNestedProtocolConstraint>>;
|
|
|
|
/*
|
|
* Focused fixtures for the exact physics-provider contract. Every class is
|
|
* constructible from the same valid specification, so a failed provider
|
|
* concept below can only come from its residual/Jacobian overload set.
|
|
*
|
|
* RawNestedProtocolConstraint declares one owned constraint row, one changed
|
|
* physical row, one read physical state, and one owned generated coordinate.
|
|
* The compiler therefore requires exactly two residual providers and three
|
|
* derivative providers.
|
|
*/
|
|
class CompleteExplicitZeroProvider final {
|
|
public:
|
|
explicit CompleteExplicitZeroProvider(
|
|
const stellar_runtime_contract_test::RawNestedProtocolConstraint &)
|
|
noexcept {}
|
|
|
|
template <typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddResidual(
|
|
stellar::equation::OwnConstraint, Row &) const noexcept {
|
|
return stellar::structuralZero;
|
|
}
|
|
|
|
template <typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddResidual(
|
|
stellar::equation::HydrostaticBalance, Row &) const noexcept {
|
|
return stellar::structuralZero;
|
|
}
|
|
|
|
template <typename Direction, typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddJacobianAction(
|
|
stellar::Derivative<stellar::equation::OwnConstraint,
|
|
stellar::state::SpecificEnthalpy>,
|
|
const Direction &, Row &) const noexcept {
|
|
return stellar::zeroDerivative;
|
|
}
|
|
|
|
template <typename Direction, typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddJacobianAction(
|
|
stellar::Derivative<stellar::equation::HydrostaticBalance,
|
|
stellar::state::SpecificEnthalpy>,
|
|
const Direction &, Row &) const noexcept {
|
|
return stellar::zeroDerivative;
|
|
}
|
|
|
|
template <typename Direction, typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddJacobianAction(
|
|
stellar::Derivative<stellar::equation::HydrostaticBalance,
|
|
stellar::state::OwnGeneratedCoordinate>,
|
|
const Direction &, Row &) const noexcept {
|
|
return stellar::zeroDerivative;
|
|
}
|
|
};
|
|
|
|
class MissingHydrostaticResidualProvider final {
|
|
public:
|
|
explicit MissingHydrostaticResidualProvider(
|
|
const stellar_runtime_contract_test::RawNestedProtocolConstraint &)
|
|
noexcept {}
|
|
|
|
template <typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddResidual(
|
|
stellar::equation::OwnConstraint, Row &) const noexcept {
|
|
return stellar::structuralZero;
|
|
}
|
|
|
|
template <typename Direction, typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddJacobianAction(
|
|
stellar::Derivative<stellar::equation::OwnConstraint,
|
|
stellar::state::SpecificEnthalpy>,
|
|
const Direction &, Row &) const noexcept {
|
|
return stellar::zeroDerivative;
|
|
}
|
|
|
|
template <typename Direction, typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddJacobianAction(
|
|
stellar::Derivative<stellar::equation::HydrostaticBalance,
|
|
stellar::state::SpecificEnthalpy>,
|
|
const Direction &, Row &) const noexcept {
|
|
return stellar::zeroDerivative;
|
|
}
|
|
|
|
template <typename Direction, typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddJacobianAction(
|
|
stellar::Derivative<stellar::equation::HydrostaticBalance,
|
|
stellar::state::OwnGeneratedCoordinate>,
|
|
const Direction &, Row &) const noexcept {
|
|
return stellar::zeroDerivative;
|
|
}
|
|
};
|
|
|
|
class MissingGeneratedControlDerivativeProvider final {
|
|
public:
|
|
explicit MissingGeneratedControlDerivativeProvider(
|
|
const stellar_runtime_contract_test::RawNestedProtocolConstraint &)
|
|
noexcept {}
|
|
|
|
template <typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddResidual(
|
|
stellar::equation::OwnConstraint, Row &) const noexcept {
|
|
return stellar::structuralZero;
|
|
}
|
|
|
|
template <typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddResidual(
|
|
stellar::equation::HydrostaticBalance, Row &) const noexcept {
|
|
return stellar::structuralZero;
|
|
}
|
|
|
|
template <typename Direction, typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddJacobianAction(
|
|
stellar::Derivative<stellar::equation::OwnConstraint,
|
|
stellar::state::SpecificEnthalpy>,
|
|
const Direction &, Row &) const noexcept {
|
|
return stellar::zeroDerivative;
|
|
}
|
|
|
|
template <typename Direction, typename Row>
|
|
[[nodiscard]] stellar::StructuralZero AddJacobianAction(
|
|
stellar::Derivative<stellar::equation::HydrostaticBalance,
|
|
stellar::state::SpecificEnthalpy>,
|
|
const Direction &, Row &) const noexcept {
|
|
return stellar::zeroDerivative;
|
|
}
|
|
};
|
|
|
|
/* The pre-refactor imperative shape can be constructed, but neither callback
|
|
* identifies a compiler-enumerated equation/state pair or returns the token
|
|
* required to prove that the pair was handled. */
|
|
class LegacyBroadEmptyProvider final {
|
|
public:
|
|
explicit LegacyBroadEmptyProvider(
|
|
const stellar_runtime_contract_test::RawNestedProtocolConstraint &)
|
|
noexcept {}
|
|
|
|
template <typename ResidualView>
|
|
void AddResidual(const ResidualView &) const noexcept {}
|
|
|
|
template <typename DirectionView, typename ActionView, typename Core>
|
|
void AddJacobianAction(const DirectionView &, const ActionView &,
|
|
const Core &) const noexcept {}
|
|
};
|
|
|
|
template <typename Physics, typename Equation>
|
|
concept HasExactProviderResidual = requires(
|
|
const Physics &physics,
|
|
operators::StellarEquilibriumContributionRow<
|
|
stellar_runtime_contract_test::RawNestedProtocolConstraint,
|
|
RawNestedProtocolModel,
|
|
Equation> &row) {
|
|
{ physics.AddResidual(Equation{}, row) } -> stellar::ContributionResult;
|
|
};
|
|
|
|
template <typename Physics, typename Equation, typename State>
|
|
concept HasExactProviderDerivative = requires(
|
|
const Physics &physics,
|
|
const operators::StellarEquilibriumContributionDirection<
|
|
stellar_runtime_contract_test::RawNestedProtocolConstraint,
|
|
RawNestedProtocolModel,
|
|
State> &direction,
|
|
operators::StellarEquilibriumContributionRow<
|
|
stellar_runtime_contract_test::RawNestedProtocolConstraint,
|
|
RawNestedProtocolModel,
|
|
Equation> &row) {
|
|
{
|
|
physics.AddJacobianAction(stellar::Derivative<Equation, State>{},
|
|
direction, row)
|
|
} -> stellar::ContributionResult;
|
|
};
|
|
|
|
using AmbiguousRuntimeRegistrationModel =
|
|
model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
stellar_runtime_contract_test::AmbiguousRuntimeRegistrationConstraint>>;
|
|
|
|
using UnauthorizedAggregateModel =
|
|
model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope,
|
|
surface::Isobaric,
|
|
models::FixedTotalMass,
|
|
stellar_runtime_contract_test::UnauthorizedAggregateConstraint>>;
|
|
|
|
using AuthorizedAmbiguousRuntimeRegistrationModel =
|
|
model::StellarModel<models::SpecificationSet<
|
|
stellar_runtime_contract_test::AlternateCoreEquationOfState,
|
|
surface::Isobaric,
|
|
models::FixedTotalMass,
|
|
stellar_runtime_contract_test::AmbiguousRuntimeRegistrationConstraint>>;
|
|
|
|
using PhysicalRieszDiscretization = equilibrium::StellarDiscretizationFor<
|
|
normalization::PhysicalRieszDiagonal<>>;
|
|
using BaseProblem = equilibrium::StellarEquilibriumProblem<BaseModel>;
|
|
using BasePhysicalRieszProblem = equilibrium::StellarEquilibriumProblem<
|
|
BaseModel, PhysicalRieszDiscretization>;
|
|
using AlternateCoreProblem =
|
|
equilibrium::StellarEquilibriumProblem<AlternateCoreModel>;
|
|
using MissingRieszUnnormalizedProblem =
|
|
equilibrium::StellarEquilibriumProblem<MissingRieszModel>;
|
|
|
|
using WrongOwnerModel = model::StellarModel<models::SpecificationSet<
|
|
stellar_runtime_contract_test::WrongOwnerEquationOfState,
|
|
surface::Isobaric, models::FixedTotalMass>>;
|
|
|
|
using IncompleteSurfaceRuntimeModel =
|
|
model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope,
|
|
stellar_runtime_contract_test::IncompleteSurfaceRuntime,
|
|
models::FixedTotalMass>>;
|
|
|
|
using CarrierlessManifestForm = utils::blocks::block_form<
|
|
utils::blocks::type_list<
|
|
utils::blocks::fixed_total_mass::mass_normalization::value>,
|
|
utils::blocks::type_list<
|
|
utils::blocks::fixed_total_mass::mass_normalization::residual>>;
|
|
|
|
struct UnsupportedCentralDensityEquationOfState final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = models::ConstitutiveLaw<
|
|
UnsupportedCentralDensityEquationOfState,
|
|
"UnsupportedCentralDensityEquationOfState">;
|
|
|
|
explicit UnsupportedCentralDensityEquationOfState(Parameters) noexcept {}
|
|
};
|
|
|
|
using UnsupportedCentralDensityModel = model::StellarModel<
|
|
models::SpecificationSet<UnsupportedCentralDensityEquationOfState,
|
|
surface::Isobaric, models::FixedTotalMass,
|
|
models::FixedCentralDensity>>;
|
|
|
|
struct EarlierMultiplier final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = models::FixedIntegralWithMultiplier<
|
|
EarlierMultiplier, "AardvarkMultiplier",
|
|
models::DependsOn<utils::blocks::density::mass::value>,
|
|
models::Affects<utils::blocks::enthalpy::specific::residual>>;
|
|
|
|
explicit EarlierMultiplier(Parameters) noexcept {}
|
|
};
|
|
|
|
using EarlierMultiplierValue = utils::blocks::generated_value_block<
|
|
models::MultiplierFor<EarlierMultiplier>>;
|
|
using EarlierMultiplierModel = model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
EarlierMultiplier>>;
|
|
|
|
struct FullPhysicsStateReader final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = models::FixedIntegralWithPhysicalCoordinate<
|
|
FullPhysicsStateReader,
|
|
"FullPhysicsStateReader",
|
|
models::DependsOn<
|
|
models::stellar::state::Density,
|
|
models::stellar::state::SurfaceShape,
|
|
models::stellar::state::GravityGradient,
|
|
models::stellar::state::GravitationalPotential,
|
|
models::stellar::state::SpecificEnthalpy>,
|
|
models::Affects<models::stellar::equation::HydrostaticBalance>>;
|
|
|
|
explicit FullPhysicsStateReader(Parameters) noexcept {}
|
|
};
|
|
|
|
using FullPhysicsStateReaderModel = model::StellarModel<
|
|
models::SpecificationSet<
|
|
eos::Polytrope,
|
|
surface::Isobaric,
|
|
models::FixedTotalMass,
|
|
FullPhysicsStateReader>>;
|
|
|
|
struct CrossAlpha;
|
|
struct CrossBeta;
|
|
|
|
using CrossAlphaValue = utils::blocks::generated_value_block<
|
|
models::PhysicalCoordinateFor<CrossAlpha>>;
|
|
using CrossAlphaResidual =
|
|
utils::blocks::generated_residual_block<models::ResidualFor<CrossAlpha>>;
|
|
using CrossBetaValue = utils::blocks::generated_value_block<
|
|
models::PhysicalCoordinateFor<CrossBeta>>;
|
|
using CrossBetaResidual =
|
|
utils::blocks::generated_residual_block<models::ResidualFor<CrossBeta>>;
|
|
|
|
struct CrossAlphaTerm final {
|
|
using value = CrossAlphaValue;
|
|
using residual = CrossAlphaResidual;
|
|
};
|
|
|
|
struct CrossBetaTerm final {
|
|
using value = CrossBetaValue;
|
|
using residual = CrossBetaResidual;
|
|
};
|
|
|
|
inline constexpr CrossAlphaTerm crossAlphaTerm{};
|
|
inline constexpr CrossBetaTerm crossBetaTerm{};
|
|
|
|
struct NoOpJacobianCallback final {
|
|
template <typename DirectionView, typename ActionView>
|
|
void operator()(DirectionView &, ActionView &) const noexcept {}
|
|
};
|
|
|
|
struct OneArgumentJacobianCallback final {
|
|
template <typename DirectionView>
|
|
void operator()(DirectionView &) const noexcept {}
|
|
};
|
|
|
|
struct NonVoidJacobianCallback final {
|
|
template <typename DirectionView, typename ActionView>
|
|
[[nodiscard]] int operator()(DirectionView &, ActionView &) const noexcept {
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
template <
|
|
typename JacobianView,
|
|
typename ResidualTerm,
|
|
typename ValueTerm,
|
|
typename Callback = NoOpJacobianCallback>
|
|
concept CanBindDeclaredJacobianCallback = requires(
|
|
const JacobianView &jacobian,
|
|
const ResidualTerm &residual,
|
|
const ValueTerm &value,
|
|
Callback callback
|
|
) {
|
|
jacobian.add(residual, value, std::move(callback));
|
|
};
|
|
|
|
template <typename JacobianView, typename ResidualTerm, typename ValueTerm>
|
|
concept CanAddRawJacobianContribution = requires(
|
|
const JacobianView &jacobian,
|
|
const ResidualTerm &residual,
|
|
const ValueTerm &value
|
|
) {
|
|
jacobian.add(residual, value, 1.0);
|
|
};
|
|
|
|
template <typename JacobianView, typename ResidualTerm, typename ValueTerm>
|
|
concept CanAddRawJacobianEntry = requires(
|
|
const JacobianView &jacobian,
|
|
const ResidualTerm &residual,
|
|
const ValueTerm &value
|
|
) {
|
|
jacobian.addEntry(residual, value, 0, 1.0);
|
|
};
|
|
|
|
/*
|
|
* Alpha is canonicalized before Beta, yet both of Alpha's edges name a
|
|
* block contributed by Beta. A sequential compiler loses Alpha's affected
|
|
* edge because Beta's residual row does not exist yet.
|
|
*/
|
|
struct CrossAlpha final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = models::FixedIntegralWithPhysicalCoordinate<
|
|
CrossAlpha, "CompilerCrossAlpha", models::DependsOn<CrossBetaValue>,
|
|
models::Affects<CrossBetaResidual>>;
|
|
|
|
explicit CrossAlpha(Parameters) noexcept {}
|
|
};
|
|
|
|
struct CrossBeta final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = models::FixedIntegralWithPhysicalCoordinate<
|
|
CrossBeta, "CompilerCrossBeta",
|
|
models::DependsOn<utils::blocks::density::mass::value>,
|
|
models::Affects<
|
|
utils::blocks::surface_deformation::shape_equilibrium::residual>>;
|
|
|
|
explicit CrossBeta(Parameters) noexcept {}
|
|
};
|
|
|
|
using CrossModel = model::StellarModel<
|
|
models::SpecificationSet<eos::Polytrope, surface::Isobaric,
|
|
models::FixedTotalMass, CrossAlpha, CrossBeta>>;
|
|
|
|
using PermutedCrossModel = model::StellarModel<
|
|
models::SpecificationSet<CrossBeta, models::FixedTotalMass,
|
|
surface::Isobaric, CrossAlpha, eos::Polytrope>>;
|
|
|
|
struct MalformedDeclaration final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = models::FixedIntegralWithPhysicalCoordinate<
|
|
MalformedDeclaration, "MalformedCompilerDeclaration",
|
|
models::DependsOn<int>,
|
|
models::Affects<utils::blocks::enthalpy::specific::residual>>;
|
|
|
|
explicit MalformedDeclaration(Parameters) noexcept {}
|
|
};
|
|
|
|
using MalformedModel = model::StellarModel<
|
|
models::SpecificationSet<eos::Polytrope, surface::Isobaric,
|
|
models::FixedTotalMass,
|
|
MalformedDeclaration>>;
|
|
|
|
struct UnmappedStellarState final {};
|
|
|
|
struct UnmappedPhysicsDependency final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = models::FixedIntegralWithPhysicalCoordinate<
|
|
UnmappedPhysicsDependency, "UnmappedPhysicsDependency",
|
|
models::DependsOn<UnmappedStellarState>,
|
|
models::Affects<models::stellar::equation::HydrostaticBalance>>;
|
|
|
|
explicit UnmappedPhysicsDependency(Parameters) noexcept {}
|
|
};
|
|
|
|
using UnmappedPhysicsModel = model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
UnmappedPhysicsDependency>>;
|
|
|
|
struct UnmappedStellarEquation final {};
|
|
|
|
struct UnmappedPhysicsEffect final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = models::FixedIntegralWithPhysicalCoordinate<
|
|
UnmappedPhysicsEffect, "UnmappedPhysicsEffect",
|
|
models::DependsOn<models::stellar::state::Density>,
|
|
models::Affects<UnmappedStellarEquation>>;
|
|
|
|
explicit UnmappedPhysicsEffect(Parameters) noexcept {}
|
|
};
|
|
|
|
using UnmappedPhysicsEffectModel =
|
|
model::StellarModel<models::SpecificationSet<
|
|
eos::Polytrope, surface::Isobaric, models::FixedTotalMass,
|
|
UnmappedPhysicsEffect>>;
|
|
|
|
struct ForeignValueBlock final : utils::blocks::value_block_base {};
|
|
|
|
struct OrphanEndpoint final {
|
|
struct Parameters final {};
|
|
|
|
using ModelDefinition = models::FixedIntegralWithPhysicalCoordinate<
|
|
OrphanEndpoint, "OrphanCompilerEndpoint",
|
|
models::DependsOn<ForeignValueBlock>,
|
|
models::Affects<utils::blocks::enthalpy::specific::residual>>;
|
|
|
|
explicit OrphanEndpoint(Parameters) noexcept {}
|
|
};
|
|
|
|
using OrphanEndpointModel = model::StellarModel<
|
|
models::SpecificationSet<eos::Polytrope, OrphanEndpoint>>;
|
|
|
|
template <typename Candidate>
|
|
concept HasCompiledStellarEquilibriumSystem = requires {
|
|
typename operators::CompiledStellarEquilibriumSystem<Candidate>;
|
|
};
|
|
|
|
template <typename Candidate>
|
|
concept HasPreparedVariadicStellarEquilibriumOperator = requires {
|
|
typename operators::PreparedVariadicStellarEquilibriumOperator<Candidate>;
|
|
};
|
|
|
|
template <typename Problem>
|
|
concept HasNormalizedStellarEquilibriumOperator = requires {
|
|
typename normalization::NormalizedStellarEquilibriumOperator<Problem>;
|
|
};
|
|
|
|
template <typename Problem>
|
|
concept CanMakeNormalizedStellarEquilibriumOperator =
|
|
requires(Problem &problem) {
|
|
normalization::makeNormalizedStellarEquilibriumOperator(problem);
|
|
};
|
|
|
|
template <typename Problem>
|
|
concept CanMakeDefaultStellarPreconditioner =
|
|
requires(const Problem &problem) {
|
|
preconditioning::makePreconditioner(problem);
|
|
};
|
|
|
|
template <typename Model, typename Discretization>
|
|
concept HasStellarEquilibriumProblem = requires {
|
|
typename equilibrium::StellarEquilibriumProblem<Model, Discretization>;
|
|
};
|
|
|
|
template <typename Model, typename Discretization>
|
|
concept CanDiscretizeStellarModel =
|
|
requires(Model &&model, Discretization discretization) {
|
|
equilibrium::discretize(std::move(model), std::move(discretization));
|
|
};
|
|
|
|
template <typename View, typename Term>
|
|
concept CanAccessContributionBlock =
|
|
requires(const View &view, const Term &term) { view.block(term); };
|
|
|
|
template <typename View, typename Term>
|
|
concept CanAddContributionBlock =
|
|
requires(const View &view, const Term &term) { view.add(term, 0.0); };
|
|
|
|
template <typename View, typename Term>
|
|
concept CanAddContributionVectorAndEntry = requires(
|
|
const View &view,
|
|
const Term &term,
|
|
const mfem::Vector &contribution
|
|
) {
|
|
view.add(term, contribution);
|
|
view.addEntry(term, 0, 0.0);
|
|
};
|
|
|
|
template <typename View>
|
|
concept HasPhysicsDensity = requires(const View &view) { view.density(); };
|
|
|
|
template <typename View>
|
|
concept HasPhysicsSurfaceShape =
|
|
requires(const View &view) { view.surfaceShape(); };
|
|
|
|
template <typename View>
|
|
concept HasPhysicsGravityGradient =
|
|
requires(const View &view) { view.gravityGradient(); };
|
|
|
|
template <typename View>
|
|
concept HasPhysicsGravitationalPotential =
|
|
requires(const View &view) { view.gravitationalPotential(); };
|
|
|
|
template <typename View>
|
|
concept HasPhysicsSpecificEnthalpy =
|
|
requires(const View &view) { view.specificEnthalpy(); };
|
|
|
|
template <typename View>
|
|
concept HasPhysicsGeneratedCoordinate =
|
|
requires(const View &view) { view.generatedCoordinate(); };
|
|
|
|
template <typename View>
|
|
concept ExposesUnrestrictedRootVector =
|
|
requires(const View &view) { view.vector(); };
|
|
|
|
template <
|
|
typename ExpectedSourceTerm,
|
|
typename OtherSourceTerm,
|
|
typename ExpectedResidualTerm,
|
|
typename OtherResidualTerm,
|
|
bool NamesOwnGeneratedCoordinate>
|
|
struct ExactPairAuditCallback final {
|
|
template <typename DirectionView, typename ActionView>
|
|
requires CanAccessContributionBlock<DirectionView, ExpectedSourceTerm> &&
|
|
(!CanAccessContributionBlock<DirectionView, OtherSourceTerm>) &&
|
|
(HasPhysicsGeneratedCoordinate<DirectionView> ==
|
|
NamesOwnGeneratedCoordinate) &&
|
|
(!HasPhysicsDensity<DirectionView>) &&
|
|
(!HasPhysicsSpecificEnthalpy<DirectionView>) &&
|
|
CanAddContributionBlock<ActionView, ExpectedResidualTerm> &&
|
|
CanAddContributionVectorAndEntry<
|
|
ActionView,
|
|
ExpectedResidualTerm> &&
|
|
(!CanAddContributionBlock<ActionView, OtherResidualTerm>) &&
|
|
(!ExposesUnrestrictedRootVector<DirectionView>) &&
|
|
(!ExposesUnrestrictedRootVector<ActionView>)
|
|
void operator()(DirectionView &, ActionView &) const noexcept {}
|
|
};
|
|
|
|
struct RequiresCrossProductDirectionCallback final {
|
|
template <typename DirectionView, typename ActionView>
|
|
requires CanAccessContributionBlock<DirectionView, CrossAlphaTerm> &&
|
|
CanAccessContributionBlock<DirectionView, CrossBetaTerm>
|
|
void operator()(DirectionView &, ActionView &) const noexcept {}
|
|
};
|
|
|
|
struct RequiresCrossProductActionCallback final {
|
|
template <typename DirectionView, typename ActionView>
|
|
requires CanAddContributionBlock<ActionView, CrossAlphaTerm> &&
|
|
CanAddContributionBlock<ActionView, CrossBetaTerm>
|
|
void operator()(DirectionView &, ActionView &) const noexcept {}
|
|
};
|
|
} // namespace
|
|
|
|
TEST_CASE("Two-Pass Stellar Compiler Preserves Established Physical Forms",
|
|
"[stellar-equilibrium][compiler][type-contract]") {
|
|
using namespace mean_field;
|
|
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<BaseModel>);
|
|
STATIC_CHECK(BaseModel::hasCompleteEquilibriumDeclaration);
|
|
STATIC_CHECK(
|
|
operators::CompiledStellarEquilibriumSystem<BaseModel>::compilationClass ==
|
|
models::EquilibriumSystemCompilation::complete_equilibrium_system);
|
|
STATIC_CHECK(operators::hasStellarEquilibriumCoreRuntime<BaseModel>);
|
|
STATIC_CHECK(operators::hasCompleteStellarEquilibriumRuntime<BaseModel>);
|
|
STATIC_CHECK(equilibrium::hasStellarEquilibriumSurfaceCompilation<BaseModel>);
|
|
STATIC_CHECK(
|
|
operators::StellarEquilibriumSystemCompilable<CentralDensityModel>);
|
|
STATIC_CHECK(
|
|
operators::StellarEquilibriumSystemCompilable<AngularMomentumModel>);
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<
|
|
AngularCentralDensityModel>);
|
|
STATIC_CHECK(
|
|
(std::same_as<operators::CompiledStellarEquilibriumForm<BaseModel>,
|
|
utils::blocks::surface_deformed_stellar_equilibrium_form>));
|
|
STATIC_CHECK(
|
|
(std::same_as<
|
|
operators::CompiledStellarEquilibriumJacobianForm<BaseModel>,
|
|
utils::blocks::surface_deformed_stellar_equilibrium_jacobian_form>));
|
|
STATIC_CHECK(
|
|
(std::same_as<
|
|
operators::CompiledStellarEquilibriumForm<CentralDensityModel>,
|
|
utils::blocks::central_density_bordered_stellar_equilibrium_form>));
|
|
STATIC_CHECK(
|
|
(std::same_as<
|
|
operators::CompiledStellarEquilibriumJacobianForm<
|
|
CentralDensityModel>,
|
|
utils::blocks::
|
|
central_density_bordered_stellar_equilibrium_jacobian_form>));
|
|
STATIC_CHECK((std::same_as<
|
|
operators::CompiledStellarEquilibriumForm<
|
|
AngularMomentumModel>,
|
|
ExpectedAngularMomentumForm>));
|
|
STATIC_CHECK((std::same_as<
|
|
operators::CompiledStellarEquilibriumJacobianForm<
|
|
AngularMomentumModel>,
|
|
ExpectedAngularMomentumJacobian>));
|
|
STATIC_CHECK((std::same_as<
|
|
operators::CompiledStellarEquilibriumForm<
|
|
AngularCentralDensityModel>,
|
|
ExpectedAngularCentralDensityForm>));
|
|
STATIC_CHECK((std::same_as<
|
|
operators::CompiledStellarEquilibriumJacobianForm<
|
|
AngularCentralDensityModel>,
|
|
ExpectedAngularCentralDensityJacobian>));
|
|
}
|
|
|
|
TEST_CASE("Runtime Contributions See Only Their Declared Physics Blocks",
|
|
"[stellar-equilibrium][runtime][sparsity][type-contract]") {
|
|
using namespace mean_field;
|
|
using AngularState =
|
|
operators::StellarEquilibriumContributionStateView<
|
|
models::FixedAngularMomentum, AngularMomentumModel>;
|
|
using AngularResidual =
|
|
operators::StellarEquilibriumContributionResidualView<
|
|
models::FixedAngularMomentum, AngularMomentumModel>;
|
|
using CentralState =
|
|
operators::StellarEquilibriumContributionStateView<
|
|
models::FixedCentralDensity, CentralDensityModel>;
|
|
using CentralResidual =
|
|
operators::StellarEquilibriumContributionResidualView<
|
|
models::FixedCentralDensity, CentralDensityModel>;
|
|
using FullPhysicsState =
|
|
operators::StellarEquilibriumContributionStateView<
|
|
FullPhysicsStateReader,
|
|
FullPhysicsStateReaderModel>;
|
|
|
|
STATIC_CHECK(CanAccessContributionBlock<
|
|
AngularState,
|
|
decltype(utils::blocks::density_field.mass_term)>);
|
|
STATIC_CHECK(CanAccessContributionBlock<
|
|
AngularState,
|
|
decltype(utils::blocks::surface_deformation_field.parameters_term)>);
|
|
STATIC_CHECK(CanAccessContributionBlock<
|
|
AngularState,
|
|
decltype(utils::blocks::fixed_angular_momentum_constraint
|
|
.angular_velocity_term)>);
|
|
STATIC_CHECK_FALSE(CanAccessContributionBlock<
|
|
AngularState,
|
|
decltype(utils::blocks::gravity_field.poisson_term)>);
|
|
STATIC_CHECK(HasPhysicsDensity<AngularState>);
|
|
STATIC_CHECK(HasPhysicsSurfaceShape<AngularState>);
|
|
STATIC_CHECK(HasPhysicsGeneratedCoordinate<AngularState>);
|
|
STATIC_CHECK_FALSE(HasPhysicsGravityGradient<AngularState>);
|
|
STATIC_CHECK_FALSE(HasPhysicsGravitationalPotential<AngularState>);
|
|
STATIC_CHECK_FALSE(HasPhysicsSpecificEnthalpy<AngularState>);
|
|
|
|
STATIC_CHECK(CanAddContributionBlock<
|
|
AngularResidual,
|
|
decltype(utils::blocks::fixed_angular_momentum_constraint
|
|
.angular_velocity_term)>);
|
|
STATIC_CHECK(CanAddContributionBlock<
|
|
AngularResidual,
|
|
decltype(utils::blocks::surface_deformation_field
|
|
.shape_equilibrium_term)>);
|
|
STATIC_CHECK(CanAddContributionBlock<
|
|
AngularResidual,
|
|
decltype(utils::blocks::enthalpy_field.specific_term)>);
|
|
STATIC_CHECK_FALSE(CanAddContributionBlock<
|
|
AngularResidual,
|
|
decltype(utils::blocks::density_field.mass_term)>);
|
|
|
|
STATIC_CHECK(CanAccessContributionBlock<
|
|
CentralState,
|
|
decltype(utils::blocks::enthalpy_field.specific_term)>);
|
|
STATIC_CHECK(CanAccessContributionBlock<
|
|
CentralState,
|
|
decltype(utils::blocks::fixed_central_density_phase
|
|
.central_value_term)>);
|
|
STATIC_CHECK_FALSE(CanAccessContributionBlock<
|
|
CentralState,
|
|
decltype(utils::blocks::density_field.mass_term)>);
|
|
STATIC_CHECK(HasPhysicsSpecificEnthalpy<CentralState>);
|
|
STATIC_CHECK(HasPhysicsGeneratedCoordinate<CentralState>);
|
|
STATIC_CHECK_FALSE(HasPhysicsDensity<CentralState>);
|
|
STATIC_CHECK_FALSE(HasPhysicsSurfaceShape<CentralState>);
|
|
|
|
// The astronomer-facing names span the complete current barotropic core
|
|
// and the specification's inferred scalar without exposing backend block
|
|
// types. Each accessor remains absent unless its dependency was declared.
|
|
STATIC_CHECK(HasPhysicsDensity<FullPhysicsState>);
|
|
STATIC_CHECK(HasPhysicsSurfaceShape<FullPhysicsState>);
|
|
STATIC_CHECK(HasPhysicsGravityGradient<FullPhysicsState>);
|
|
STATIC_CHECK(HasPhysicsGravitationalPotential<FullPhysicsState>);
|
|
STATIC_CHECK(HasPhysicsSpecificEnthalpy<FullPhysicsState>);
|
|
STATIC_CHECK(HasPhysicsGeneratedCoordinate<FullPhysicsState>);
|
|
STATIC_CHECK(CanAddContributionBlock<
|
|
CentralResidual,
|
|
decltype(utils::blocks::enthalpy_field.specific_term)>);
|
|
STATIC_CHECK(CanAddContributionBlock<
|
|
CentralResidual,
|
|
decltype(utils::blocks::fixed_central_density_phase
|
|
.central_value_term)>);
|
|
|
|
// Residual access is additive-only: declared rows are writable through add,
|
|
// but no specification can obtain a mutable block and overwrite an earlier
|
|
// contribution. There is also no escape hatch to the full root vector.
|
|
STATIC_CHECK_FALSE(CanAccessContributionBlock<
|
|
AngularResidual,
|
|
decltype(utils::blocks::enthalpy_field.specific_term)>);
|
|
STATIC_CHECK_FALSE(CanAccessContributionBlock<
|
|
CentralResidual,
|
|
decltype(utils::blocks::enthalpy_field.specific_term)>);
|
|
STATIC_CHECK_FALSE(ExposesUnrestrictedRootVector<AngularState>);
|
|
STATIC_CHECK_FALSE(ExposesUnrestrictedRootVector<AngularResidual>);
|
|
STATIC_CHECK_FALSE(ExposesUnrestrictedRootVector<CentralState>);
|
|
STATIC_CHECK_FALSE(ExposesUnrestrictedRootVector<CentralResidual>);
|
|
}
|
|
|
|
TEST_CASE("Built-In Physics Declarations Are The Compiler's Single Source",
|
|
"[stellar-equilibrium][compiler][metadata][physics-api]") {
|
|
using namespace mean_field;
|
|
using EmptyBlocks = utils::blocks::type_list<>;
|
|
using PolytropeCompilation =
|
|
operators::StellarEquilibriumSpecificationCompilation<eos::Polytrope>;
|
|
using IsobaricCompilation =
|
|
operators::StellarEquilibriumSpecificationCompilation<surface::Isobaric>;
|
|
using MassContribution =
|
|
models::SpecificationContribution<models::FixedTotalMass>;
|
|
using AngularContribution =
|
|
models::SpecificationContribution<models::FixedAngularMomentum>;
|
|
using CentralContribution =
|
|
models::SpecificationContribution<models::FixedCentralDensity>;
|
|
|
|
STATIC_CHECK((std::same_as<
|
|
typename MassContribution::DependsOn,
|
|
models::DependsOn<models::stellar::state::Density,
|
|
models::stellar::state::SurfaceShape>>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename MassContribution::Affects,
|
|
models::Affects<
|
|
models::stellar::equation::HydrostaticBalance>>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename AngularContribution::DependsOn,
|
|
models::DependsOn<
|
|
models::stellar::state::Density,
|
|
models::stellar::state::SurfaceShape,
|
|
models::stellar::state::OwnGeneratedCoordinate>>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename AngularContribution::Affects,
|
|
models::Affects<
|
|
models::stellar::equation::SurfaceShapeBalance,
|
|
models::stellar::equation::HydrostaticBalance>>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename CentralContribution::DependsOn,
|
|
models::DependsOn<
|
|
models::stellar::state::SpecificEnthalpy>>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename CentralContribution::Affects,
|
|
models::Affects<
|
|
models::stellar::equation::HydrostaticBalance>>));
|
|
|
|
using MassCompilation =
|
|
operators::StellarEquilibriumSpecificationCompilation<
|
|
models::FixedTotalMass>;
|
|
using AngularCompilation =
|
|
operators::StellarEquilibriumSpecificationCompilation<
|
|
models::FixedAngularMomentum>;
|
|
using CentralCompilation =
|
|
operators::StellarEquilibriumSpecificationCompilation<
|
|
models::FixedCentralDensity>;
|
|
|
|
STATIC_CHECK(
|
|
operators::stellarEquilibriumSpecificationCompilationComplete<
|
|
eos::Polytrope>);
|
|
STATIC_CHECK(
|
|
operators::stellarEquilibriumSpecificationCompilationComplete<
|
|
surface::Isobaric>);
|
|
STATIC_CHECK((std::same_as<
|
|
typename PolytropeCompilation::GeneratedValueBlocks,
|
|
EmptyBlocks>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename PolytropeCompilation::GeneratedResidualBlocks,
|
|
EmptyBlocks>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename IsobaricCompilation::GeneratedValueBlocks,
|
|
EmptyBlocks>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename IsobaricCompilation::GeneratedResidualBlocks,
|
|
EmptyBlocks>));
|
|
STATIC_CHECK((std::same_as<typename MassCompilation::DependsOnValueBlocks,
|
|
utils::blocks::type_list<DensityValue,
|
|
SurfaceValue>>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename MassCompilation::AffectedResidualBlocks,
|
|
utils::blocks::type_list<EnthalpyResidual>>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename AngularCompilation::DependsOnValueBlocks,
|
|
utils::blocks::type_list<DensityValue, SurfaceValue,
|
|
AngularVelocityValue>>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename AngularCompilation::AffectedResidualBlocks,
|
|
utils::blocks::type_list<SurfaceResidual,
|
|
EnthalpyResidual>>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename CentralCompilation::DependsOnValueBlocks,
|
|
utils::blocks::type_list<EnthalpyValue>>));
|
|
STATIC_CHECK((std::same_as<
|
|
typename CentralCompilation::AffectedResidualBlocks,
|
|
utils::blocks::type_list<EnthalpyResidual>>));
|
|
|
|
const auto descriptors =
|
|
AngularCentralDensityModel::runtimeSpecificationDescriptors();
|
|
REQUIRE(descriptors.size() == 5);
|
|
CHECK(descriptors[2].specification.name == "FixedTotalMass");
|
|
CHECK(descriptors[3].specification.name == "FixedAngularMomentum");
|
|
CHECK(descriptors[4].specification.name == "FixedCentralDensity");
|
|
CHECK(descriptors[2].hasDeclarativeDefinition);
|
|
CHECK(descriptors[3].hasDeclarativeDefinition);
|
|
CHECK(descriptors[4].hasDeclarativeDefinition);
|
|
}
|
|
|
|
TEST_CASE("Fixed Total Mass Exposes Its Generated Blocks And Incident Edges",
|
|
"[stellar-equilibrium][compiler][metadata]") {
|
|
using namespace mean_field;
|
|
using Compilation = operators::StellarEquilibriumSpecificationCompilation<
|
|
models::FixedTotalMass>;
|
|
using MassValue = utils::blocks::fixed_total_mass::mass_normalization::value;
|
|
using MassResidual =
|
|
utils::blocks::fixed_total_mass::mass_normalization::residual;
|
|
|
|
STATIC_CHECK(operators::stellarEquilibriumSpecificationCompilationComplete<
|
|
models::FixedTotalMass>);
|
|
STATIC_CHECK((std::same_as<typename Compilation::GeneratedValueBlocks,
|
|
utils::blocks::type_list<MassValue>>));
|
|
STATIC_CHECK((std::same_as<typename Compilation::GeneratedCorrectionBlocks,
|
|
utils::blocks::type_list<MassValue>>));
|
|
STATIC_CHECK((std::same_as<typename Compilation::GeneratedResidualBlocks,
|
|
utils::blocks::type_list<MassResidual>>));
|
|
STATIC_CHECK(utils::blocks::contains_type_v<
|
|
operators::EquilibriumJacobianCoupling<
|
|
MassResidual, utils::blocks::density::mass::value>,
|
|
typename Compilation::IncidentJacobianCouplings>);
|
|
STATIC_CHECK(utils::blocks::contains_type_v<
|
|
operators::EquilibriumJacobianCoupling<
|
|
utils::blocks::enthalpy::specific::residual, MassValue>,
|
|
typename Compilation::IncidentJacobianCouplings>);
|
|
}
|
|
|
|
TEST_CASE("Core Coordinates Are Identified By Type Rather Than Pack Position",
|
|
"[stellar-equilibrium][compiler][ordering]") {
|
|
using namespace mean_field;
|
|
using Form =
|
|
operators::CompiledStellarEquilibriumForm<EarlierMultiplierModel>;
|
|
using MassValue =
|
|
utils::blocks::fixed_total_mass::mass_normalization::value;
|
|
|
|
STATIC_CHECK(
|
|
operators::StellarEquilibriumSystemCompilable<EarlierMultiplierModel>);
|
|
STATIC_CHECK(utils::blocks::type_index_v<
|
|
EarlierMultiplierValue, typename Form::value_blocks> == 5);
|
|
STATIC_CHECK(utils::blocks::type_index_v<
|
|
MassValue, typename Form::value_blocks> == 6);
|
|
STATIC_CHECK(utils::blocks::has_jacobian_coupling_v<
|
|
utils::blocks::enthalpy::specific::residual,
|
|
EarlierMultiplierValue,
|
|
operators::CompiledStellarEquilibriumJacobianForm<
|
|
EarlierMultiplierModel>>);
|
|
}
|
|
|
|
TEST_CASE("Two-Pass Compiler Resolves Couplings Across Independently Declared "
|
|
"Constraints",
|
|
"[stellar-equilibrium][compiler][variadic][order-independence]") {
|
|
using namespace mean_field;
|
|
using System = operators::CompiledStellarEquilibriumSystem<CrossModel>;
|
|
using Form = typename System::FormType;
|
|
using Jacobian = typename System::JacobianType;
|
|
|
|
STATIC_CHECK(models::ModelSpecification<CrossAlpha>);
|
|
STATIC_CHECK(models::ModelSpecification<CrossBeta>);
|
|
STATIC_CHECK((std::same_as<CrossModel, PermutedCrossModel>));
|
|
STATIC_CHECK(operators::stellarEquilibriumSpecificationCompilationComplete<
|
|
CrossAlpha>);
|
|
STATIC_CHECK(
|
|
operators::stellarEquilibriumSpecificationCompilationComplete<CrossBeta>);
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<CrossModel>);
|
|
STATIC_CHECK(Form::value_block_count == 8);
|
|
STATIC_CHECK(Form::residual_block_count == 8);
|
|
STATIC_CHECK(utils::blocks::valid_jacobian_form<Form, Jacobian>);
|
|
|
|
// Both endpoints are introduced by different declarations. In particular,
|
|
// R_B does not exist when a one-pass compiler visits Alpha.
|
|
STATIC_CHECK(
|
|
utils::blocks::has_jacobian_coupling_v<CrossBetaResidual, CrossAlphaValue,
|
|
Jacobian>);
|
|
STATIC_CHECK(
|
|
utils::blocks::has_jacobian_coupling_v<CrossAlphaResidual, CrossBetaValue,
|
|
Jacobian>);
|
|
STATIC_CHECK(
|
|
utils::blocks::has_jacobian_coupling_v<
|
|
CrossBetaResidual, utils::blocks::density::mass::value, Jacobian>);
|
|
STATIC_CHECK(utils::blocks::has_jacobian_coupling_v<
|
|
utils::blocks::surface_deformation::shape_equilibrium::residual,
|
|
CrossBetaValue, Jacobian>);
|
|
|
|
// Changes are conservatively state dependent on every declared Read. This
|
|
// is the Hessian-like block required by nonlinear constrained systems.
|
|
STATIC_CHECK(utils::blocks::has_jacobian_coupling_v<
|
|
CrossBetaResidual, CrossBetaValue, Jacobian>);
|
|
|
|
STATIC_CHECK(utils::blocks::contains_type_v<
|
|
operators::EquilibriumJacobianCoupling<CrossBetaResidual,
|
|
CrossAlphaValue>,
|
|
typename System::ContributionJacobianCouplings>);
|
|
STATIC_CHECK((std::same_as<
|
|
typename System::GeneratedCorrectionBlocks,
|
|
utils::blocks::type_list<
|
|
utils::blocks::fixed_total_mass::mass_normalization::value,
|
|
CrossAlphaValue, CrossBetaValue>>));
|
|
|
|
using CrossAlphaJacobian =
|
|
operators::StellarEquilibriumContributionJacobianView<
|
|
CrossAlpha,
|
|
CrossModel>;
|
|
using AlphaResidualFromBetaValue = ExactPairAuditCallback<
|
|
CrossBetaTerm,
|
|
CrossAlphaTerm,
|
|
CrossAlphaTerm,
|
|
CrossBetaTerm,
|
|
false>;
|
|
using BetaResidualFromAlphaValue = ExactPairAuditCallback<
|
|
CrossAlphaTerm,
|
|
CrossBetaTerm,
|
|
CrossBetaTerm,
|
|
CrossAlphaTerm,
|
|
true>;
|
|
using BetaResidualFromBetaValue = ExactPairAuditCallback<
|
|
CrossBetaTerm,
|
|
CrossAlphaTerm,
|
|
CrossBetaTerm,
|
|
CrossAlphaTerm,
|
|
false>;
|
|
|
|
STATIC_CHECK(CanBindDeclaredJacobianCallback<
|
|
CrossAlphaJacobian,
|
|
CrossAlphaTerm,
|
|
CrossBetaTerm,
|
|
AlphaResidualFromBetaValue>);
|
|
STATIC_CHECK(CanBindDeclaredJacobianCallback<
|
|
CrossAlphaJacobian,
|
|
CrossBetaTerm,
|
|
CrossAlphaTerm,
|
|
BetaResidualFromAlphaValue>);
|
|
STATIC_CHECK(CanBindDeclaredJacobianCallback<
|
|
CrossAlphaJacobian,
|
|
CrossBetaTerm,
|
|
CrossBetaTerm,
|
|
BetaResidualFromBetaValue>);
|
|
|
|
// Alpha's residual does not read Alpha's coordinate. Although that row and
|
|
// column are independently present in other callbacks, their undeclared
|
|
// diagonal cannot bind a callback. Raw scalar writes and malformed callback
|
|
// protocols are rejected too: all numeric accumulation happens through the
|
|
// one-row action supplied to a valid callback.
|
|
STATIC_CHECK_FALSE(CanBindDeclaredJacobianCallback<
|
|
CrossAlphaJacobian,
|
|
CrossAlphaTerm,
|
|
CrossAlphaTerm>);
|
|
STATIC_CHECK_FALSE(CanAddRawJacobianContribution<
|
|
CrossAlphaJacobian,
|
|
CrossAlphaTerm,
|
|
CrossBetaTerm>);
|
|
STATIC_CHECK_FALSE(CanAddRawJacobianEntry<
|
|
CrossAlphaJacobian,
|
|
CrossAlphaTerm,
|
|
CrossBetaTerm>);
|
|
STATIC_CHECK_FALSE(CanBindDeclaredJacobianCallback<
|
|
CrossAlphaJacobian,
|
|
CrossAlphaTerm,
|
|
CrossBetaTerm,
|
|
OneArgumentJacobianCallback>);
|
|
STATIC_CHECK_FALSE(CanBindDeclaredJacobianCallback<
|
|
CrossAlphaJacobian,
|
|
CrossAlphaTerm,
|
|
CrossBetaTerm,
|
|
NonVoidJacobianCallback>);
|
|
STATIC_CHECK_FALSE(CanBindDeclaredJacobianCallback<
|
|
CrossAlphaJacobian,
|
|
CrossAlphaTerm,
|
|
CrossBetaTerm,
|
|
RequiresCrossProductDirectionCallback>);
|
|
STATIC_CHECK_FALSE(CanBindDeclaredJacobianCallback<
|
|
CrossAlphaJacobian,
|
|
CrossAlphaTerm,
|
|
CrossBetaTerm,
|
|
RequiresCrossProductActionCallback>);
|
|
STATIC_CHECK_FALSE(CanBindDeclaredJacobianCallback<
|
|
CrossAlphaJacobian,
|
|
int,
|
|
CrossBetaTerm>);
|
|
}
|
|
|
|
TEST_CASE("Exact Physics Providers Must Cover Every Compiler-Inferred Pair",
|
|
"[stellar-equilibrium][compiler][physics-provider][contracts]") {
|
|
using Specification =
|
|
stellar_runtime_contract_test::RawNestedProtocolConstraint;
|
|
using Model = RawNestedProtocolModel;
|
|
using Topology =
|
|
operators::StellarEquilibriumContributionTopology<Specification, Model>;
|
|
|
|
STATIC_CHECK(Topology::ResidualEquations::size == 2);
|
|
STATIC_CHECK(Topology::Derivatives::size == 3);
|
|
|
|
STATIC_CHECK((std::constructible_from<CompleteExplicitZeroProvider,
|
|
const Specification &>));
|
|
STATIC_CHECK((HasExactProviderResidual<
|
|
CompleteExplicitZeroProvider,
|
|
stellar::equation::OwnConstraint>));
|
|
STATIC_CHECK((HasExactProviderResidual<
|
|
CompleteExplicitZeroProvider,
|
|
stellar::equation::HydrostaticBalance>));
|
|
STATIC_CHECK((HasExactProviderDerivative<
|
|
CompleteExplicitZeroProvider,
|
|
stellar::equation::OwnConstraint,
|
|
stellar::state::SpecificEnthalpy>));
|
|
STATIC_CHECK((HasExactProviderDerivative<
|
|
CompleteExplicitZeroProvider,
|
|
stellar::equation::HydrostaticBalance,
|
|
stellar::state::SpecificEnthalpy>));
|
|
STATIC_CHECK((HasExactProviderDerivative<
|
|
CompleteExplicitZeroProvider,
|
|
stellar::equation::HydrostaticBalance,
|
|
stellar::state::OwnGeneratedCoordinate>));
|
|
STATIC_CHECK((operators::CompleteStellarEquilibriumPhysicsProvider<
|
|
CompleteExplicitZeroProvider, Specification, Model>));
|
|
|
|
// This provider has the valid constructor and all three inferred
|
|
// derivatives. Omitting only the changed physical residual rejects it.
|
|
STATIC_CHECK((std::constructible_from<MissingHydrostaticResidualProvider,
|
|
const Specification &>));
|
|
STATIC_CHECK((HasExactProviderResidual<
|
|
MissingHydrostaticResidualProvider,
|
|
stellar::equation::OwnConstraint>));
|
|
STATIC_CHECK_FALSE((HasExactProviderResidual<
|
|
MissingHydrostaticResidualProvider,
|
|
stellar::equation::HydrostaticBalance>));
|
|
STATIC_CHECK((HasExactProviderDerivative<
|
|
MissingHydrostaticResidualProvider,
|
|
stellar::equation::OwnConstraint,
|
|
stellar::state::SpecificEnthalpy>));
|
|
STATIC_CHECK((HasExactProviderDerivative<
|
|
MissingHydrostaticResidualProvider,
|
|
stellar::equation::HydrostaticBalance,
|
|
stellar::state::SpecificEnthalpy>));
|
|
STATIC_CHECK((HasExactProviderDerivative<
|
|
MissingHydrostaticResidualProvider,
|
|
stellar::equation::HydrostaticBalance,
|
|
stellar::state::OwnGeneratedCoordinate>));
|
|
STATIC_CHECK_FALSE((operators::CompleteStellarEquilibriumPhysicsProvider<
|
|
MissingHydrostaticResidualProvider,
|
|
Specification,
|
|
Model>));
|
|
|
|
// This provider has the valid constructor and both inferred residuals.
|
|
// Omitting only d(hydrostatic)/d(owned coordinate) rejects it.
|
|
STATIC_CHECK((std::constructible_from<
|
|
MissingGeneratedControlDerivativeProvider,
|
|
const Specification &>));
|
|
STATIC_CHECK((HasExactProviderResidual<
|
|
MissingGeneratedControlDerivativeProvider,
|
|
stellar::equation::OwnConstraint>));
|
|
STATIC_CHECK((HasExactProviderResidual<
|
|
MissingGeneratedControlDerivativeProvider,
|
|
stellar::equation::HydrostaticBalance>));
|
|
STATIC_CHECK((HasExactProviderDerivative<
|
|
MissingGeneratedControlDerivativeProvider,
|
|
stellar::equation::OwnConstraint,
|
|
stellar::state::SpecificEnthalpy>));
|
|
STATIC_CHECK((HasExactProviderDerivative<
|
|
MissingGeneratedControlDerivativeProvider,
|
|
stellar::equation::HydrostaticBalance,
|
|
stellar::state::SpecificEnthalpy>));
|
|
STATIC_CHECK_FALSE((HasExactProviderDerivative<
|
|
MissingGeneratedControlDerivativeProvider,
|
|
stellar::equation::HydrostaticBalance,
|
|
stellar::state::OwnGeneratedCoordinate>));
|
|
STATIC_CHECK_FALSE((operators::CompleteStellarEquilibriumPhysicsProvider<
|
|
MissingGeneratedControlDerivativeProvider,
|
|
Specification,
|
|
Model>));
|
|
|
|
// Construction alone does not grandfather in the former broad/imperative
|
|
// callbacks. They provide neither an equation-tagged residual result nor
|
|
// a derivative-tagged Jacobian result.
|
|
STATIC_CHECK((std::constructible_from<LegacyBroadEmptyProvider,
|
|
const Specification &>));
|
|
STATIC_CHECK_FALSE((HasExactProviderResidual<
|
|
LegacyBroadEmptyProvider,
|
|
stellar::equation::OwnConstraint>));
|
|
STATIC_CHECK_FALSE((HasExactProviderDerivative<
|
|
LegacyBroadEmptyProvider,
|
|
stellar::equation::OwnConstraint,
|
|
stellar::state::SpecificEnthalpy>));
|
|
STATIC_CHECK_FALSE((operators::CompleteStellarEquilibriumPhysicsProvider<
|
|
LegacyBroadEmptyProvider, Specification, Model>));
|
|
}
|
|
|
|
TEST_CASE("Compiler Capability Queries Reject Invalid Declarations Without "
|
|
"Hard Errors",
|
|
"[stellar-equilibrium][compiler][sfinae]") {
|
|
using namespace mean_field;
|
|
|
|
STATIC_CHECK_FALSE(
|
|
operators::stellarEquilibriumSpecificationCompilationComplete<int>);
|
|
STATIC_CHECK_FALSE(
|
|
operators::stellarEquilibriumSpecificationCompilationComplete<
|
|
MalformedDeclaration>);
|
|
STATIC_CHECK_FALSE(
|
|
operators::StellarEquilibriumSystemCompilable<MalformedModel>);
|
|
STATIC_CHECK_FALSE(HasCompiledStellarEquilibriumSystem<MalformedModel>);
|
|
STATIC_CHECK(models::ModelSpecification<UnmappedPhysicsDependency>);
|
|
// A valid declaration is not a claim that the numerical compiler knows how
|
|
// to map every name it contains.
|
|
STATIC_CHECK(UnmappedPhysicsModel::hasCompleteEquilibriumDeclaration);
|
|
STATIC_CHECK_FALSE(
|
|
operators::stellarEquilibriumSpecificationCompilationComplete<
|
|
UnmappedPhysicsDependency>);
|
|
STATIC_CHECK_FALSE(
|
|
operators::StellarEquilibriumSystemCompilable<UnmappedPhysicsModel>);
|
|
STATIC_CHECK_FALSE(
|
|
HasCompiledStellarEquilibriumSystem<UnmappedPhysicsModel>);
|
|
STATIC_CHECK(models::ModelSpecification<UnmappedPhysicsEffect>);
|
|
STATIC_CHECK_FALSE(
|
|
operators::stellarEquilibriumSpecificationCompilationComplete<
|
|
UnmappedPhysicsEffect>);
|
|
STATIC_CHECK_FALSE(operators::StellarEquilibriumSystemCompilable<
|
|
UnmappedPhysicsEffectModel>);
|
|
STATIC_CHECK_FALSE(
|
|
HasCompiledStellarEquilibriumSystem<UnmappedPhysicsEffectModel>);
|
|
STATIC_CHECK_FALSE(operators::StellarEquilibriumSystemCompilable<int>);
|
|
STATIC_CHECK_FALSE(HasCompiledStellarEquilibriumSystem<int>);
|
|
STATIC_CHECK(operators::StellarEquilibriumBackendSpecificationList<
|
|
models::ModelTypeList<eos::Polytrope, surface::Isobaric>>);
|
|
STATIC_CHECK(operators::StellarEquilibriumBackendSpecificationList<
|
|
models::ModelTypeList<>>);
|
|
STATIC_CHECK_FALSE(operators::StellarEquilibriumBackendSpecificationList<
|
|
models::ModelTypeList<int>>);
|
|
STATIC_CHECK_FALSE(operators::StellarEquilibriumBackendSpecificationList<
|
|
models::ModelTypeList<eos::Polytrope, eos::Polytrope>>);
|
|
STATIC_CHECK_FALSE(
|
|
operators::StellarEquilibriumBackendSpecificationList<int>);
|
|
STATIC_CHECK_FALSE(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
int, int>);
|
|
STATIC_CHECK(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
eos::Polytrope, BaseModel>);
|
|
STATIC_CHECK(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
models::FixedTotalMass, BaseModel>);
|
|
|
|
STATIC_CHECK(operators::StellarEquilibriumCoreRuntime<
|
|
stellar_runtime_contract_test::
|
|
RegisteredWithoutMakeEquationOfState>::registered);
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<
|
|
RegisteredWithoutMakeModel>);
|
|
STATIC_CHECK_FALSE(operators::hasStellarEquilibriumCoreRuntime<
|
|
RegisteredWithoutMakeModel>);
|
|
|
|
STATIC_CHECK(operators::PreparedStellarEquilibriumPhysicalCore<
|
|
stellar_runtime_contract_test::AlternatePhysicalCore>);
|
|
STATIC_CHECK(operators::hasStellarEquilibriumCoreRuntime<
|
|
AlternateCoreModel>);
|
|
STATIC_CHECK((std::same_as<
|
|
operators::StellarEquilibriumPhysicalCoreType<
|
|
AlternateCoreModel>,
|
|
stellar_runtime_contract_test::AlternatePhysicalCore>));
|
|
STATIC_CHECK(operators::hasCompleteStellarEquilibriumRuntime<
|
|
AlternateCoreModel>);
|
|
STATIC_CHECK(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
stellar_runtime_contract_test::AlternateCoreEquationOfState,
|
|
AlternateCoreModel>);
|
|
STATIC_CHECK(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
surface::Isobaric, AlternateCoreModel>);
|
|
STATIC_CHECK(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
models::FixedTotalMass, AlternateCoreModel>);
|
|
STATIC_CHECK(
|
|
HasPreparedVariadicStellarEquilibriumOperator<AlternateCoreModel>);
|
|
|
|
// Core support and constraint support are separate contracts. This tiny
|
|
// core supports the common outer root, but does not advertise the physical
|
|
// facilities required by FixedAngularMomentum.
|
|
STATIC_CHECK(operators::hasStellarEquilibriumCoreRuntime<
|
|
AlternateCoreAngularMomentumModel>);
|
|
STATIC_CHECK(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
models::FixedAngularMomentum,
|
|
AlternateCoreAngularMomentumModel>);
|
|
STATIC_CHECK_FALSE(operators::hasCompleteStellarEquilibriumRuntime<
|
|
AlternateCoreAngularMomentumModel>);
|
|
STATIC_CHECK_FALSE(HasPreparedVariadicStellarEquilibriumOperator<
|
|
AlternateCoreAngularMomentumModel>);
|
|
|
|
// The pack fold also rejects ambiguous physical-control ownership. Both
|
|
// contributions are independently executable, but exactly one runtime may
|
|
// generate the rotation used by the shared physical core.
|
|
STATIC_CHECK_FALSE(
|
|
operators::StellarEquilibriumRuntimeContribution<
|
|
stellar_runtime_contract_test::SecondRotationController>::registered);
|
|
STATIC_CHECK(operators::StellarEquilibriumPhysicsAvailableFor<
|
|
stellar_runtime_contract_test::SecondRotationController,
|
|
TwoRotationProvidersModel>);
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<
|
|
TwoRotationProvidersModel>);
|
|
STATIC_CHECK(operators::hasStellarEquilibriumCoreRuntime<
|
|
TwoRotationProvidersModel>);
|
|
STATIC_CHECK(operators::hasCompleteStellarEquilibriumRuntime<
|
|
TwoRotationProvidersModel>);
|
|
STATIC_CHECK(HasPreparedVariadicStellarEquilibriumOperator<
|
|
TwoRotationProvidersModel>);
|
|
STATIC_CHECK_FALSE(equilibrium::StellarEquilibriumModel<
|
|
TwoRotationProvidersModel>);
|
|
STATIC_CHECK(operators::stellarEquilibriumRotationProviderCount<
|
|
TwoRotationProvidersModel> == 2);
|
|
using AmbiguousRotationRoot =
|
|
operators::PreparedVariadicStellarEquilibriumOperator<
|
|
TwoRotationProvidersModel>;
|
|
STATIC_CHECK_FALSE(std::constructible_from<
|
|
AmbiguousRotationRoot, fem::FEM &,
|
|
const mapping::DomainMapper &,
|
|
std::shared_ptr<const TwoRotationProvidersModel>,
|
|
operators::PressureSurfaceConstraintView,
|
|
deformation::PreparedDomainDeformationRuntime>);
|
|
|
|
// Report storage is part of the real runtime protocol: preparation creates
|
|
// the complete report tuple and assigns each per-specification result into
|
|
// it. Capability queries must reject both failures without reaching a hard
|
|
// error inside PreparedVariadicStellarEquilibriumOperator::Prepare().
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<
|
|
NonDefaultReportModel>);
|
|
STATIC_CHECK_FALSE(operators::StellarEquilibriumPhysicsAvailableFor<
|
|
stellar_runtime_contract_test::NonDefaultReportConstraint,
|
|
NonDefaultReportModel>);
|
|
STATIC_CHECK_FALSE(operators::hasCompleteStellarEquilibriumRuntime<
|
|
NonDefaultReportModel>);
|
|
STATIC_CHECK_FALSE(equilibrium::StellarEquilibriumModel<
|
|
NonDefaultReportModel>);
|
|
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<
|
|
NonAssignableReportModel>);
|
|
STATIC_CHECK_FALSE(operators::StellarEquilibriumPhysicsAvailableFor<
|
|
stellar_runtime_contract_test::
|
|
NonAssignableReportConstraint,
|
|
NonAssignableReportModel>);
|
|
STATIC_CHECK_FALSE(operators::hasCompleteStellarEquilibriumRuntime<
|
|
NonAssignableReportModel>);
|
|
STATIC_CHECK_FALSE(equilibrium::StellarEquilibriumModel<
|
|
NonAssignableReportModel>);
|
|
|
|
// Reports are deliberately opaque to the framework. Default construction
|
|
// and assignment are sufficient for tuple storage; no DidAnyWork member is
|
|
// required to keep the residual correct.
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<
|
|
OpaqueReportModel>);
|
|
STATIC_CHECK(operators::StellarEquilibriumPhysicsAvailableFor<
|
|
stellar_runtime_contract_test::OpaqueReportConstraint,
|
|
OpaqueReportModel>);
|
|
STATIC_CHECK(operators::hasCompleteStellarEquilibriumRuntime<
|
|
OpaqueReportModel>);
|
|
STATIC_CHECK(equilibrium::StellarEquilibriumModel<OpaqueReportModel>);
|
|
|
|
// A nested declaration is the restricted physics-author path. Merely
|
|
// implementing the former raw FEM/model/core/dependency protocol must not
|
|
// recover the privileged backend access reserved for explicit registry
|
|
// specializations.
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<
|
|
RawNestedProtocolModel>);
|
|
STATIC_CHECK_FALSE(std::constructible_from<
|
|
stellar_runtime_contract_test::
|
|
PreparedRawNestedProtocolConstraint<
|
|
RawNestedProtocolModel>,
|
|
const stellar_runtime_contract_test::
|
|
RawNestedProtocolConstraint &>);
|
|
STATIC_CHECK_FALSE(operators::StellarEquilibriumPhysicsAvailableFor<
|
|
stellar_runtime_contract_test::RawNestedProtocolConstraint,
|
|
RawNestedProtocolModel>);
|
|
STATIC_CHECK_FALSE(operators::hasCompleteStellarEquilibriumRuntime<
|
|
RawNestedProtocolModel>);
|
|
STATIC_CHECK_FALSE(equilibrium::StellarEquilibriumModel<
|
|
RawNestedProtocolModel>);
|
|
|
|
// Even a structurally complete aggregate runtime cannot select itself for
|
|
// an existing core. Symbolic compilation and core availability remain
|
|
// independently true, isolating authorization as the failed rung.
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<
|
|
UnauthorizedAggregateModel>);
|
|
STATIC_CHECK(operators::hasStellarEquilibriumCoreRuntime<
|
|
UnauthorizedAggregateModel>);
|
|
STATIC_CHECK(operators::StellarEquilibriumRuntimeContribution<
|
|
stellar_runtime_contract_test::
|
|
UnauthorizedAggregateConstraint>::registered);
|
|
STATIC_CHECK_FALSE(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
stellar_runtime_contract_test::
|
|
UnauthorizedAggregateConstraint,
|
|
UnauthorizedAggregateModel>);
|
|
STATIC_CHECK_FALSE(operators::StellarEquilibriumPhysicsAvailableFor<
|
|
stellar_runtime_contract_test::
|
|
UnauthorizedAggregateConstraint,
|
|
UnauthorizedAggregateModel>);
|
|
STATIC_CHECK_FALSE(operators::hasCompleteStellarEquilibriumRuntime<
|
|
UnauthorizedAggregateModel>);
|
|
STATIC_CHECK_FALSE(equilibrium::StellarEquilibriumModel<
|
|
UnauthorizedAggregateModel>);
|
|
|
|
// A raw registry specialization cannot grant itself privileged access to
|
|
// the built-in core and cannot shadow a valid restricted nested package.
|
|
STATIC_CHECK(operators::StellarEquilibriumRuntimeContribution<
|
|
stellar_runtime_contract_test::
|
|
AmbiguousRuntimeRegistrationConstraint>::registered);
|
|
STATIC_CHECK_FALSE(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
stellar_runtime_contract_test::
|
|
AmbiguousRuntimeRegistrationConstraint,
|
|
AmbiguousRuntimeRegistrationModel>);
|
|
STATIC_CHECK(operators::StellarEquilibriumPhysicsAvailableFor<
|
|
stellar_runtime_contract_test::
|
|
AmbiguousRuntimeRegistrationConstraint,
|
|
AmbiguousRuntimeRegistrationModel>);
|
|
STATIC_CHECK(operators::hasCompleteStellarEquilibriumRuntime<
|
|
AmbiguousRuntimeRegistrationModel>);
|
|
STATIC_CHECK(equilibrium::StellarEquilibriumModel<
|
|
AmbiguousRuntimeRegistrationModel>);
|
|
|
|
// A core owner can deliberately authorize an aggregate backend candidate.
|
|
// If that exact model then also supplies nested physics, the two valid
|
|
// providers are genuinely ambiguous and are rejected.
|
|
STATIC_CHECK(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
stellar_runtime_contract_test::
|
|
AmbiguousRuntimeRegistrationConstraint,
|
|
AuthorizedAmbiguousRuntimeRegistrationModel>);
|
|
STATIC_CHECK_FALSE(operators::StellarEquilibriumPhysicsAvailableFor<
|
|
stellar_runtime_contract_test::
|
|
AmbiguousRuntimeRegistrationConstraint,
|
|
AuthorizedAmbiguousRuntimeRegistrationModel>);
|
|
STATIC_CHECK_FALSE(operators::hasCompleteStellarEquilibriumRuntime<
|
|
AuthorizedAmbiguousRuntimeRegistrationModel>);
|
|
STATIC_CHECK_FALSE(equilibrium::StellarEquilibriumModel<
|
|
AuthorizedAmbiguousRuntimeRegistrationModel>);
|
|
|
|
// A registration bit and a plausible core type are insufficient: the
|
|
// factory must return ownership of the advertised concrete core.
|
|
STATIC_CHECK_FALSE(
|
|
operators::hasStellarEquilibriumCoreRuntime<WrongOwnerModel>);
|
|
STATIC_CHECK_FALSE(operators::hasCompleteStellarEquilibriumRuntime<
|
|
WrongOwnerModel>);
|
|
|
|
STATIC_CHECK(operators::StellarEquilibriumRuntimeContribution<
|
|
stellar_runtime_contract_test::
|
|
IncompleteSurfaceRuntime>::registered);
|
|
STATIC_CHECK_FALSE(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
|
stellar_runtime_contract_test::IncompleteSurfaceRuntime,
|
|
IncompleteSurfaceRuntimeModel>);
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<
|
|
IncompleteSurfaceRuntimeModel>);
|
|
STATIC_CHECK(operators::hasStellarEquilibriumCoreRuntime<
|
|
IncompleteSurfaceRuntimeModel>);
|
|
STATIC_CHECK_FALSE(operators::hasCompleteStellarEquilibriumRuntime<
|
|
IncompleteSurfaceRuntimeModel>);
|
|
STATIC_CHECK_FALSE(equilibrium::hasStellarEquilibriumSurfaceCompilation<
|
|
IncompleteSurfaceRuntimeModel>);
|
|
STATIC_CHECK_FALSE(equilibrium::StellarEquilibriumModel<
|
|
IncompleteSurfaceRuntimeModel>);
|
|
|
|
STATIC_CHECK_FALSE(
|
|
operators::hasCompatibleStellarEquilibriumPhysicalRoot<MissingMassModel>);
|
|
STATIC_CHECK_FALSE(
|
|
HasPreparedVariadicStellarEquilibriumOperator<MissingMassModel>);
|
|
|
|
STATIC_CHECK_FALSE(operators::CompilableRootManifestFor<
|
|
CentralDensityModel,
|
|
utils::blocks::surface_deformed_stellar_equilibrium_form>);
|
|
STATIC_CHECK_FALSE(operators::CompilableRootManifestFor<
|
|
BaseModel, CarrierlessManifestForm>);
|
|
STATIC_CHECK_FALSE(operators::CompilableRootManifestFor<
|
|
UnsupportedCentralDensityModel,
|
|
operators::CompiledStellarEquilibriumForm<
|
|
UnsupportedCentralDensityModel>>);
|
|
|
|
// This declaration is internally well formed, but its dependency is not
|
|
// supplied by the final model. Completeness is therefore contextual.
|
|
STATIC_CHECK(operators::stellarEquilibriumSpecificationCompilationComplete<
|
|
OrphanEndpoint>);
|
|
STATIC_CHECK_FALSE(
|
|
operators::StellarEquilibriumSystemCompilable<OrphanEndpointModel>);
|
|
STATIC_CHECK_FALSE(HasCompiledStellarEquilibriumSystem<OrphanEndpointModel>);
|
|
}
|
|
|
|
TEST_CASE("Direct Variadic Root Construction Requires Shared Model Ownership",
|
|
"[stellar-equilibrium][runtime][lifetime][type-contract]") {
|
|
using namespace mean_field;
|
|
using Operator =
|
|
operators::PreparedVariadicStellarEquilibriumOperator<BaseModel>;
|
|
|
|
STATIC_CHECK_FALSE(std::constructible_from<
|
|
Operator, fem::FEM &, const mapping::DomainMapper &,
|
|
const BaseModel &,
|
|
operators::PressureSurfaceConstraintView,
|
|
deformation::PreparedDomainDeformationRuntime>);
|
|
STATIC_CHECK(std::constructible_from<
|
|
Operator, fem::FEM &, const mapping::DomainMapper &,
|
|
std::shared_ptr<const BaseModel>,
|
|
operators::PressureSurfaceConstraintView,
|
|
deformation::PreparedDomainDeformationRuntime>);
|
|
}
|
|
|
|
TEST_CASE("Physical Riesz Runtime Capability Follows The Selected Core",
|
|
"[normalization][stellar-equilibrium][type-contract]") {
|
|
using namespace mean_field;
|
|
using AlternateForm =
|
|
operators::CompiledStellarEquilibriumForm<AlternateCoreModel>;
|
|
using AlternateSpecifications = AlternateCoreModel::SpecificationTypes;
|
|
|
|
STATIC_CHECK(normalization::PhysicalRieszStellarEquilibriumCore<
|
|
operators::PreparedStellarEquilibriumOperator>);
|
|
STATIC_CHECK_FALSE(normalization::PhysicalRieszStellarEquilibriumCore<
|
|
stellar_runtime_contract_test::AlternatePhysicalCore>);
|
|
STATIC_CHECK(normalization::PhysicalRieszStellarEquilibriumCore<
|
|
stellar_runtime_contract_test::PhysicalRieszCapableCore>);
|
|
STATIC_CHECK(normalization::StellarNormalizationRuntimeAvailableFor<
|
|
normalization::Unnormalized,
|
|
AlternateForm,
|
|
stellar_runtime_contract_test::AlternatePhysicalCore,
|
|
AlternateSpecifications>);
|
|
STATIC_CHECK_FALSE(normalization::StellarNormalizationRuntimeAvailableFor<
|
|
normalization::PhysicalRieszDiagonal<>,
|
|
AlternateForm,
|
|
stellar_runtime_contract_test::AlternatePhysicalCore,
|
|
AlternateSpecifications>);
|
|
STATIC_CHECK(normalization::StellarNormalizationRuntimeAvailableFor<
|
|
normalization::PhysicalRieszDiagonal<>,
|
|
AlternateForm,
|
|
stellar_runtime_contract_test::PhysicalRieszCapableCore,
|
|
AlternateSpecifications>);
|
|
STATIC_CHECK_FALSE(normalization::StellarNormalizationRuntimeAvailableFor<
|
|
int, int, int, int>);
|
|
|
|
// Runtime normalization is selected by the discretization type. A lean
|
|
// alternate core remains fully usable without scaling, while the Physical
|
|
// Riesz pairing is rejected at the public capability boundary rather than
|
|
// failing in the normalized operator's constructor body.
|
|
STATIC_CHECK(equilibrium::StellarEquilibriumModel<AlternateCoreModel>);
|
|
STATIC_CHECK(equilibrium::StellarEquilibriumModelDiscretizationCompatible<
|
|
AlternateCoreModel, equilibrium::StellarDiscretization>);
|
|
STATIC_CHECK_FALSE(equilibrium::StellarEquilibriumModelDiscretizationCompatible<
|
|
AlternateCoreModel, PhysicalRieszDiscretization>);
|
|
STATIC_CHECK_FALSE(HasStellarEquilibriumProblem<
|
|
AlternateCoreModel, PhysicalRieszDiscretization>);
|
|
STATIC_CHECK_FALSE(CanDiscretizeStellarModel<
|
|
AlternateCoreModel, PhysicalRieszDiscretization>);
|
|
STATIC_CHECK(normalization::NormalizableStellarEquilibriumProblem<
|
|
BaseProblem>);
|
|
STATIC_CHECK(normalization::PhysicalRieszStellarEquilibriumProblem<
|
|
BasePhysicalRieszProblem>);
|
|
STATIC_CHECK(normalization::NormalizableStellarEquilibriumProblem<
|
|
BasePhysicalRieszProblem>);
|
|
STATIC_CHECK(normalization::NormalizableStellarEquilibriumProblem<
|
|
AlternateCoreProblem>);
|
|
STATIC_CHECK_FALSE(normalization::PhysicalRieszStellarEquilibriumProblem<int>);
|
|
STATIC_CHECK_FALSE(normalization::NormalizableStellarEquilibriumProblem<int>);
|
|
|
|
STATIC_CHECK(HasNormalizedStellarEquilibriumOperator<BaseProblem>);
|
|
STATIC_CHECK(HasNormalizedStellarEquilibriumOperator<
|
|
BasePhysicalRieszProblem>);
|
|
STATIC_CHECK(HasNormalizedStellarEquilibriumOperator<AlternateCoreProblem>);
|
|
STATIC_CHECK(CanMakeNormalizedStellarEquilibriumOperator<BaseProblem>);
|
|
STATIC_CHECK(CanMakeNormalizedStellarEquilibriumOperator<
|
|
AlternateCoreProblem>);
|
|
STATIC_CHECK_FALSE(CanMakeNormalizedStellarEquilibriumOperator<int>);
|
|
}
|
|
|
|
TEST_CASE("Model And Discretization Compatibility Rejects Missing Riesz "
|
|
"Metadata Without Instantiating A Problem",
|
|
"[normalization][stellar-equilibrium][type-contract][sfinae]") {
|
|
using namespace mean_field;
|
|
using MissingRieszForm =
|
|
operators::CompiledStellarEquilibriumForm<MissingRieszModel>;
|
|
using MissingConstraint =
|
|
stellar_runtime_contract_test::MissingRieszScalarConstraint;
|
|
|
|
// Every non-normalization rung is complete for this model.
|
|
STATIC_CHECK(equilibrium::StellarEquilibriumModel<MissingRieszModel>);
|
|
STATIC_CHECK(operators::StellarEquilibriumSystemCompilable<
|
|
MissingRieszModel>);
|
|
STATIC_CHECK(operators::hasCompleteStellarEquilibriumRuntime<
|
|
MissingRieszModel>);
|
|
STATIC_CHECK(operators::CompilableRootManifestFor<MissingRieszModel,
|
|
MissingRieszForm>);
|
|
STATIC_CHECK(models::CompleteGeneratedManifestFor<MissingConstraint>);
|
|
|
|
// Identity normalization covers the generated pair without physical scale
|
|
// metadata. Physical Riesz correctly requires that missing declaration.
|
|
STATIC_CHECK_FALSE(models::CompleteGeneratedNormalizationFor<
|
|
MissingConstraint>);
|
|
STATIC_CHECK_FALSE(normalization::CompleteGeneratedPhysicalRieszNormalizationFor<
|
|
MissingConstraint>);
|
|
STATIC_CHECK_FALSE(
|
|
normalization::CompleteGeneratedPhysicalRieszRuntimeNormalizationFor<
|
|
MissingConstraint>);
|
|
STATIC_CHECK(
|
|
normalization::CompleteGeneratedPhysicalRieszRuntimeNormalizationFor<
|
|
models::FixedTotalMass>);
|
|
STATIC_CHECK(normalization::CompilableNormalizationFor<
|
|
normalization::Unnormalized, MissingRieszForm>);
|
|
STATIC_CHECK_FALSE(normalization::CompilableNormalizationFor<
|
|
normalization::PhysicalRieszDiagonal<>,
|
|
MissingRieszForm>);
|
|
STATIC_CHECK_FALSE(normalization::CompleteStellarNormalizationFor<
|
|
MissingRieszModel, MissingRieszForm>);
|
|
|
|
STATIC_CHECK(equilibrium::StellarEquilibriumModelDiscretizationCompatible<
|
|
MissingRieszModel, equilibrium::StellarDiscretization>);
|
|
STATIC_CHECK_FALSE(
|
|
equilibrium::StellarEquilibriumModelDiscretizationCompatible<
|
|
MissingRieszModel, PhysicalRieszDiscretization>);
|
|
STATIC_CHECK_FALSE(
|
|
equilibrium::StellarEquilibriumModelDiscretizationCompatible<int, int>);
|
|
|
|
STATIC_CHECK(HasStellarEquilibriumProblem<
|
|
MissingRieszModel, equilibrium::StellarDiscretization>);
|
|
STATIC_CHECK_FALSE(HasStellarEquilibriumProblem<
|
|
MissingRieszModel, PhysicalRieszDiscretization>);
|
|
STATIC_CHECK_FALSE(HasStellarEquilibriumProblem<int, int>);
|
|
STATIC_CHECK(CanDiscretizeStellarModel<
|
|
MissingRieszModel, equilibrium::StellarDiscretization>);
|
|
STATIC_CHECK_FALSE(CanDiscretizeStellarModel<
|
|
MissingRieszModel, PhysicalRieszDiscretization>);
|
|
|
|
STATIC_CHECK(equilibrium::DiscretizedStellarEquilibriumProblem<
|
|
MissingRieszUnnormalizedProblem>);
|
|
STATIC_CHECK(normalization::NormalizableStellarEquilibriumProblem<
|
|
MissingRieszUnnormalizedProblem>);
|
|
}
|
|
|
|
TEST_CASE("Restricted Equilibrium Physics Automatically Supplies The Default "
|
|
"Constraint Border",
|
|
"[preconditioning][stellar-equilibrium][type-contract][sfinae]") {
|
|
using namespace mean_field;
|
|
|
|
// The ordinary nested provider is the single source of numerical formulas.
|
|
// Border-incident edges are projected from it automatically, while the
|
|
// custom pure-structure edge is explicitly proven to be StructuralZero.
|
|
STATIC_CHECK(equilibrium::StellarEquilibriumModel<MissingRieszModel>);
|
|
STATIC_CHECK(operators::hasCompleteStellarEquilibriumRuntime<
|
|
MissingRieszModel>);
|
|
STATIC_CHECK(equilibrium::DiscretizedStellarEquilibriumProblem<
|
|
MissingRieszUnnormalizedProblem>);
|
|
STATIC_CHECK(preconditioning::CompleteSpecificationBorderActionsFor<
|
|
MissingRieszUnnormalizedProblem>);
|
|
STATIC_CHECK(
|
|
preconditioning::DefaultStellarPreconditionerAvailableFor<
|
|
MissingRieszUnnormalizedProblem>);
|
|
STATIC_CHECK(CanMakeDefaultStellarPreconditioner<
|
|
MissingRieszUnnormalizedProblem>);
|
|
}
|