module; #include #include #include #include export module mean_field:preconditioning.stellar_recipe; export import :preconditioning.equilibrium_coordinates; export namespace mean_field::preconditioning { /* * A stellar-preconditioner prescription is an unbound, owning value. It * may therefore be created before a problem exists and safely moved into * the eventual user-owned solve context. A prepared inverse is deliberately a * separate, problem-bound object with a stable address. */ struct StellarPreconditionerPrescriptionTag { }; template concept StellarPreconditionerPrescription = std::derived_from, StellarPreconditionerPrescriptionTag> && std::move_constructible>; struct DefaultStellarPreconditioner final : StellarPreconditionerPrescriptionTag { }; /* * This overload is the user-facing, problem-independent factory. The * existing makePreconditioner(problem) overload remains the low-level * factory for the typed, unprepared block assembled below. */ [[nodiscard]] constexpr DefaultStellarPreconditioner makePreconditioner() noexcept { return {}; } template concept PreparedStellarInverseFor = equilibrium::DiscretizedStellarEquilibriumProblem> && std::derived_from, mfem::Solver> && std::destructible> && requires(std::remove_cvref_t &prepared, const std::remove_cvref_t &constantPrepared) { { constantPrepared.GetProblem() } -> std::same_as &>; { constantPrepared.IsCurrent() } -> std::same_as; prepared.Refresh(); }; /* * Built-in preparation is intentionally policy-first. The same spelling * can be supplied beside a third-party prescription and found by ADL, * without adding that prescription to a central registry or switch. * Preparation requires an already-prepared problem because the current * physical inverse assembles state-dependent numerical data. */ template [[nodiscard]] auto prepareStellarPreconditioner( DefaultStellarPreconditioner, const Problem &problem ) { return preconditioning::prepare(problem, preconditioning::makePreconditioner(problem)); } template concept StellarPreconditionerRuntimeAvailableFor = StellarPreconditionerPrescription && equilibrium::DiscretizedStellarEquilibriumProblem> && requires(std::remove_cvref_t prescription, const std::remove_cvref_t &problem) { requires std::same_as< decltype(prepareStellarPreconditioner(std::move(prescription), problem)), std::remove_cvref_t>; { prepareStellarPreconditioner(std::move(prescription), problem) } -> PreparedStellarInverseFor>; }; template requires StellarPreconditionerRuntimeAvailableFor using PreparedStellarInverseType = std::remove_cvref_t &&>(), std::declval &>() ))>; } // namespace mean_field::preconditioning