#pragma once #include #include #include #include #include "plateau_preconditioner_benchmark.hpp" // Include after import mean_field. These owning recipes belong to the // experiment driver; the public physics-facing solver factory stays unchanged. namespace experiment::plateau_diagnostics { template concept NewtonBenchmarkPolicy = (std::same_as && RefinedGravity) || (std::same_as && !RefinedGravity); template requires NewtonBenchmarkPolicy class NewtonBenchmarkPreconditioner final : public mean_field::preconditioning::StellarPreconditionerPrescriptionTag { public: explicit NewtonBenchmarkPreconditioner(mean_field::preconditioning::GravityConsistentSchurLDU gravity) : m_gravity(gravity) { if (gravity.correctionSweeps < 0 || !std::isfinite(gravity.relaxation) || gravity.relaxation <= 0.0) throw std::invalid_argument("Newton benchmark gravity controls must be finite and valid."); } [[nodiscard]] mean_field::preconditioning::GravityConsistentSchurLDU GravityPolicy() const noexcept { return m_gravity; } private: // A recipe can outlive command-line parsing. Keep numeric controls by // value; prepared objects acquire their problem binding only via ADL. mean_field::preconditioning::GravityConsistentSchurLDU m_gravity; }; template < class Policy, bool RefinedGravity, mean_field::preconditioning::DefaultStellarPreconditionerAvailableFor Problem> requires NewtonBenchmarkPolicy< Policy, RefinedGravity> [[nodiscard]] auto prepareStellarPreconditioner( NewtonBenchmarkPreconditioner< Policy, RefinedGravity> prescription, const Problem &problem ) { PreconditionerBenchmarkOptions options; options.schurCorrectionSweeps = prescription.GravityPolicy().correctionSweeps; options.schurRelaxation = prescription.GravityPolicy().relaxation; // Returning the benchmark's concrete prepared type lets the existing // context own refreshes and rebuilt scalar-border completion unchanged. return preconditioner_benchmark_detail::Prepare(problem, options); } using GravitySchurNewtonPreconditioner = NewtonBenchmarkPreconditioner; using StellarLDUNewtonPreconditioner = NewtonBenchmarkPreconditioner; static_assert(mean_field::preconditioning::StellarPreconditionerPrescription); static_assert(mean_field::preconditioning::StellarPreconditionerPrescription); static_assert(std::is_trivially_copyable_v); static_assert(std::is_trivially_copyable_v); } // namespace experiment::plateau_diagnostics