module; #include #include #include #include export module mean_field:preconditioning.plan; export import :preconditioning.backend; export import :utils.blocks; export namespace mean_field::preconditioning { template struct Coupling final { using Residual = ResidualBlock; using Correction = CorrectionBlock; }; template < typename CorrectionBlockList, typename ResidualBlockList, typename RequiredCouplingList, typename Characteristics, typename Backend, typename PreparationRequirements = typename backend::Traits>::PreparationDependencies> struct ComponentDeclaration { using CorrectionBlocks = CorrectionBlockList; using ResidualBlocks = ResidualBlockList; using RequiredCouplings = RequiredCouplingList; using OperatorDescription = Characteristics; using BackendType = Backend; using PreparationDependencies = PreparationRequirements; }; template requires std::derived_from && std::derived_from struct IdentityBlock final { using CorrectionBlocks = utils::blocks::type_list; using ResidualBlocks = utils::blocks::type_list; using RequiredCouplings = utils::blocks::type_list<>; using OperatorDescription = IdentityOperatorCharacteristics; using BackendType = backend::Identity; using PreparationDependencies = NoPreparationDependencies; }; namespace detail { template struct IsTypeList : std::false_type { }; template struct IsTypeList> : std::true_type { }; template inline constexpr bool isTypeList = IsTypeList>::value; template struct IsUniqueDerivedBlockList : std::false_type { }; template struct IsUniqueDerivedBlockList, Base> : std::bool_constant< (std::derived_from && ...) && utils::blocks::types_are_unique_v>> { }; template struct IsCoupling : std::false_type { }; template struct IsCoupling> : std::bool_constant< std::derived_from && std::derived_from> { }; template struct IsCouplingList : std::false_type { }; template struct IsCouplingList> : std::bool_constant< (IsCoupling::value && ...) && utils::blocks::types_are_unique_v>> { }; template struct ComponentTraits { static constexpr bool valid = false; }; template struct ComponentTraits< Candidate, std::void_t< typename Candidate::CorrectionBlocks, typename Candidate::ResidualBlocks, typename Candidate::RequiredCouplings, typename Candidate::OperatorDescription, typename Candidate::BackendType, typename Candidate::PreparationDependencies>> { using CorrectionBlocks = typename Candidate::CorrectionBlocks; using ResidualBlocks = typename Candidate::ResidualBlocks; using RequiredCouplings = typename Candidate::RequiredCouplings; using OperatorDescription = typename Candidate::OperatorDescription; using BackendType = typename Candidate::BackendType; using PreparationDependencies = typename Candidate::PreparationDependencies; using BackendPreparationDependencies = typename backend::Traits::PreparationDependencies; static constexpr bool valid = IsUniqueDerivedBlockList::value && IsUniqueDerivedBlockList::value && IsCouplingList::value && OperatorCharacteristicsType && backend::Registered && backend::isCompatible && PreparationDependenciesType && ((PreparationDependencies::mask & BackendPreparationDependencies::mask) == BackendPreparationDependencies::mask); }; template struct Concatenate; template <> struct Concatenate<> { using Type = utils::blocks::type_list<>; }; template struct Concatenate> { using Type = utils::blocks::type_list; }; template struct Concatenate, utils::blocks::type_list, Remaining...> { using Type = typename Concatenate, Remaining...>::Type; }; template using ConcatenateT = typename Concatenate::Type; template struct Append; template struct Append, Type> { using Result = utils::blocks::type_list; }; template using AppendT = typename Append::Result; template using AppendUniqueT = std::conditional_t, List, AppendT>; template struct ListDifference; template struct ListDifference, Excluded> { using Type = utils::blocks::type_list<>; }; template struct ListDifference, Excluded> { private: using Remaining = typename ListDifference, Excluded>::Type; public: using Type = std::conditional_t< utils::blocks::contains_type_v, Remaining, ConcatenateT, Remaining>>; }; template using ListDifferenceT = typename ListDifference::Type; template struct CollectRepeatedTypes; template struct CollectRepeatedTypes, Original, Repeated> { using Type = Repeated; }; template struct CollectRepeatedTypes, Original, Repeated> { private: using Next = std::conditional_t< (utils::blocks::type_count_v > 1), AppendUniqueT, Repeated>; public: using Type = typename CollectRepeatedTypes, Original, Next>::Type; }; template using RepeatedTypesT = typename CollectRepeatedTypes>::Type; template class PlanStorage { public: using ComponentTypes = utils::blocks::type_list; using CorrectionBlocks = ConcatenateT::CorrectionBlocks...>; using ResidualBlocks = ConcatenateT::ResidualBlocks...>; using RequiredCouplings = ConcatenateT::RequiredCouplings...>; static constexpr bool allowsOverlappingOwnership = AllowsOverlap; static constexpr bool stationaryLinear = ((backend::applicationContract::BackendType> == ApplicationContract::stationary_linear) && ...); constexpr explicit PlanStorage(Components... components) : m_components(std::move(components)...) { } template [[nodiscard]] constexpr const Component &component() const noexcept { return std::get(m_components); } [[nodiscard]] constexpr const std::tuple &components() const noexcept { return m_components; } private: std::tuple m_components; }; template < bool ComponentsAreValid, typename DeclaredCorrectionBlocks, typename DeclaredResidualBlocks, typename DeclaredCouplings, typename... Components> struct CoherentPlanDeclaration : std::false_type { }; template < typename DeclaredCorrectionBlocks, typename DeclaredResidualBlocks, typename DeclaredCouplings, typename... Components> struct CoherentPlanDeclaration< true, DeclaredCorrectionBlocks, DeclaredResidualBlocks, DeclaredCouplings, Components...> : std::bool_constant< std::same_as< DeclaredCorrectionBlocks, ConcatenateT::CorrectionBlocks...>> && std::same_as< DeclaredResidualBlocks, ConcatenateT::ResidualBlocks...>> && std::same_as< DeclaredCouplings, ConcatenateT::RequiredCouplings...>>> { }; template < typename ComponentList, typename DeclaredCorrectionBlocks, typename DeclaredResidualBlocks, typename DeclaredCouplings> struct PlanDeclarationIsCoherent : std::false_type { }; template < typename... Components, typename DeclaredCorrectionBlocks, typename DeclaredResidualBlocks, typename DeclaredCouplings> struct PlanDeclarationIsCoherent< utils::blocks::type_list, DeclaredCorrectionBlocks, DeclaredResidualBlocks, DeclaredCouplings> : CoherentPlanDeclaration< (ComponentTraits::valid && ...), DeclaredCorrectionBlocks, DeclaredResidualBlocks, DeclaredCouplings, Components...> { }; template struct PlanTraits { static constexpr bool valid = false; }; template struct PlanTraits< Candidate, std::void_t< typename Candidate::ComponentTypes, typename Candidate::CorrectionBlocks, typename Candidate::ResidualBlocks, typename Candidate::RequiredCouplings>> { static constexpr bool valid = isTypeList && isTypeList && isTypeList && isTypeList && PlanDeclarationIsCoherent< typename Candidate::ComponentTypes, typename Candidate::CorrectionBlocks, typename Candidate::ResidualBlocks, typename Candidate::RequiredCouplings>::value; }; template struct CouplingsExistInJacobian; template struct CouplingsExistInJacobian, JacobianForm> : std::true_type { }; template struct CouplingsExistInJacobian< utils::blocks::type_list, Remaining...>, JacobianForm> : std::bool_constant< utils::blocks::has_jacobian_coupling_v && CouplingsExistInJacobian, JacobianForm>::value> { }; template >::valid> struct RequiredCouplingsExist : std::false_type { }; template struct RequiredCouplingsExist : CouplingsExistInJacobian::RequiredCouplings, JacobianForm> { }; } // namespace detail template concept PreconditionerComponent = detail::ComponentTraits>::valid; template class PreconditionerPlan final : public detail::PlanStorage { using Base = detail::PlanStorage; public: using Base::Base; }; template PreconditionerPlan(Components...) -> PreconditionerPlan; template class OverlappingPreconditionerPlan final : public detail::PlanStorage { using Base = detail::PlanStorage; public: using Base::Base; }; template OverlappingPreconditionerPlan(Components...) -> OverlappingPreconditionerPlan; template concept PreconditionerPlanType = detail::PlanTraits>::valid; template requires utils::blocks::block_form_is_valid_v
&& PreconditionerPlanType struct PreconditionerCoverage final { using DeclaredCorrectionBlocks = typename Plan::CorrectionBlocks; using DeclaredResidualBlocks = typename Plan::ResidualBlocks; using MissingCorrectionBlocks = detail::ListDifferenceT; using UnexpectedCorrectionBlocks = detail::ListDifferenceT; using RepeatedCorrectionBlocks = detail::RepeatedTypesT; using MissingResidualBlocks = detail::ListDifferenceT; using UnexpectedResidualBlocks = detail::ListDifferenceT; using RepeatedResidualBlocks = detail::RepeatedTypesT; static constexpr bool hasEveryCorrectionBlock = MissingCorrectionBlocks::size == 0; static constexpr bool hasOnlyCorrectionBlocks = UnexpectedCorrectionBlocks::size == 0; static constexpr bool hasUniqueCorrectionOwners = Plan::allowsOverlappingOwnership || RepeatedCorrectionBlocks::size == 0; static constexpr bool hasEveryResidualBlock = MissingResidualBlocks::size == 0; static constexpr bool hasOnlyResidualBlocks = UnexpectedResidualBlocks::size == 0; static constexpr bool hasUniqueResidualOwners = Plan::allowsOverlappingOwnership || RepeatedResidualBlocks::size == 0; static constexpr bool complete = hasEveryCorrectionBlock && hasOnlyCorrectionBlocks && hasUniqueCorrectionOwners && hasEveryResidualBlock && hasOnlyResidualBlocks && hasUniqueResidualOwners; }; template concept CompletePreconditionerFor = utils::blocks::block_form_is_valid_v && PreconditionerPlanType && PreconditionerCoverage>::complete; template inline constexpr bool requiredCouplingsExist = detail::RequiredCouplingsExist::value; template concept CompatiblePreconditionerFor = CompletePreconditionerFor && utils::blocks::valid_jacobian_form && requiredCouplingsExist; template concept StationaryLinearPreconditionerPlan = PreconditionerPlanType && std::remove_cvref_t::stationaryLinear; } // namespace mean_field::preconditioning