2391 lines
105 KiB
C++
2391 lines
105 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>);
|
|
}
|