module; #include #include export module mean_field:normalization.plan; export import :utils.blocks; export namespace mean_field::normalization { struct NormalizationPrescriptionTag { }; template concept NormalizationPrescription = std::derived_from< std::remove_cvref_t, NormalizationPrescriptionTag>; enum class CoordinateKind { value, residual }; enum class RieszTopology { identity, scalar_volume_l2, vector_volume_l2, scalar_boundary_l2, hybrid_scalar_volume_point_rows, global_scalar }; enum class PhysicalScaleKind { dimensionless, density, length, acceleration, inverse_time_squared, specific_energy, pressure, mass, force, angular_velocity, angular_momentum }; struct IdentityCoordinate final { }; /* * Honest compile-time method for a coordinate whose positive diagonal * factor is supplied at runtime by one exact normalization prescription. * Unlike IdentityCoordinate, this category makes no claim about the * numerical value of that factor. The owner type prevents one policy from * silently presenting another policy's runtime map as its own plan. */ template struct RuntimePreparedCoordinate final { using PrescriptionType = std::remove_cvref_t; }; template struct PhysicalRieszCoordinate final { static constexpr RieszTopology topology = Topology; static constexpr PhysicalScaleKind scale = Scale; }; struct UnsupportedPhysicalRieszCoordinate final { }; template struct PhysicalRieszBlockTraits { using Method = UnsupportedPhysicalRieszCoordinate; static constexpr bool registered = false; }; template struct CoordinateComponent final { using Blocks = BlockList; using Method = MethodType; static constexpr CoordinateKind kind = Kind; using ValueBlocks = std::conditional_t< Kind == CoordinateKind::value, BlockList, utils::blocks::type_list<>>; using ResidualBlocks = std::conditional_t< Kind == CoordinateKind::residual, BlockList, utils::blocks::type_list<>>; }; namespace detail { template struct IsTypeList : std::false_type { }; template struct IsTypeList> : std::true_type { }; template struct IsUniqueDerivedBlockList : std::false_type { }; template struct IsUniqueDerivedBlockList, Base> : std::bool_constant< (std::derived_from && ...) && utils::blocks::types_are_unique_v>> { }; template struct IsCoordinateMethod : std::false_type { }; template <> struct IsCoordinateMethod : std::true_type { }; template struct IsCoordinateMethod> : std::true_type { }; template struct IsCoordinateMethod> : std::true_type { }; template struct MethodSupportsBlock : std::false_type { }; template struct MethodSupportsBlock : std::bool_constant> { }; template struct MethodSupportsBlock, Block> : std::bool_constant> { }; template struct MethodSupportsBlock, Block> : std::bool_constant< PhysicalRieszBlockTraits::registered && std::same_as< typename PhysicalRieszBlockTraits::Method, PhysicalRieszCoordinate>> { }; template struct MethodSupportsEveryBlock : std::false_type { }; template struct MethodSupportsEveryBlock> : std::bool_constant<(MethodSupportsBlock::value && ...)> { }; template struct ComponentTraits { static constexpr bool valid = false; }; template struct ComponentTraits< Candidate, std::void_t< typename Candidate::Blocks, typename Candidate::Method, typename Candidate::ValueBlocks, typename Candidate::ResidualBlocks, decltype(Candidate::kind)>> { using Blocks = typename Candidate::Blocks; using Method = typename Candidate::Method; using ValueBlocks = typename Candidate::ValueBlocks; using ResidualBlocks = typename Candidate::ResidualBlocks; static constexpr bool hasValidKind = std::same_as, CoordinateKind>; static constexpr bool hasValidBlockList = [] { if constexpr (!hasValidKind || !IsTypeList::value) { return false; } else if constexpr (Candidate::kind == CoordinateKind::value) { return IsUniqueDerivedBlockList::value; } else if constexpr (Candidate::kind == CoordinateKind::residual) { return IsUniqueDerivedBlockList::value; } else { return false; } }(); static constexpr bool hasCoherentCoordinateLists = [] { if constexpr (!hasValidKind || !IsTypeList::value || !IsTypeList::value) { return false; } else if constexpr (Candidate::kind == CoordinateKind::value) { return std::same_as && std::same_as>; } else if constexpr (Candidate::kind == CoordinateKind::residual) { return std::same_as> && std::same_as; } else { return false; } }(); static constexpr bool valid = hasValidKind && IsTypeList::value && IsCoordinateMethod::value && hasValidBlockList && hasCoherentCoordinateLists && MethodSupportsEveryBlock::value; }; 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, Appended> { using Type = utils::blocks::type_list; }; template using AppendT = typename Append::Type; template using AppendUniqueT = std::conditional_t< utils::blocks::contains_type_v, 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< List, List, utils::blocks::type_list<>>::Type; template struct PlanTraits { static constexpr bool valid = false; }; } // namespace detail template concept NormalizationComponent = detail::ComponentTraits>::valid; template struct NormalizationPlan final { using ComponentTypes = utils::blocks::type_list; using ValueBlocks = detail::ConcatenateT; using ResidualBlocks = detail::ConcatenateT; }; namespace detail { template struct PlanTraits> { static constexpr bool valid = (ComponentTraits::valid && ...); }; template struct MakeIdentityPlan; template struct MakeIdentityPlan< utils::blocks::type_list, utils::blocks::type_list> { using Type = NormalizationPlan< CoordinateComponent, IdentityCoordinate>..., CoordinateComponent< CoordinateKind::residual, utils::blocks::type_list, IdentityCoordinate>...>; }; template < NormalizationPrescription Prescription, typename Values, typename Residuals> struct MakeRuntimePreparedPlan; template < NormalizationPrescription Prescription, typename... Values, typename... Residuals> struct MakeRuntimePreparedPlan< Prescription, utils::blocks::type_list, utils::blocks::type_list> { using Method = RuntimePreparedCoordinate; using Type = NormalizationPlan< CoordinateComponent< CoordinateKind::value, utils::blocks::type_list, Method>..., CoordinateComponent< CoordinateKind::residual, utils::blocks::type_list, Method>...>; }; } // namespace detail template concept NormalizationPlanType = detail::PlanTraits>::valid; template requires utils::blocks::block_form_is_valid_v
using IdentityNormalizationPlanFor = typename detail::MakeIdentityPlan< typename Form::value_blocks, typename Form::residual_blocks>::Type; template requires utils::blocks::block_form_is_valid_v using RuntimePreparedNormalizationPlanFor = typename detail::MakeRuntimePreparedPlan< std::remove_cvref_t, typename Form::value_blocks, typename Form::residual_blocks>::Type; template requires utils::blocks::block_form_is_valid_v struct NormalizationCoverage final { using DeclaredValueBlocks = typename Plan::ValueBlocks; using DeclaredResidualBlocks = typename Plan::ResidualBlocks; using MissingValueBlocks = detail::ListDifferenceT; using UnexpectedValueBlocks = detail::ListDifferenceT; using RepeatedValueBlocks = detail::RepeatedTypesT; using MissingResidualBlocks = detail::ListDifferenceT; using UnexpectedResidualBlocks = detail::ListDifferenceT; using RepeatedResidualBlocks = detail::RepeatedTypesT; static constexpr bool hasEveryValueBlock = MissingValueBlocks::size == 0; static constexpr bool hasOnlyValueBlocks = UnexpectedValueBlocks::size == 0; static constexpr bool hasUniqueValueOwners = RepeatedValueBlocks::size == 0; static constexpr bool hasEveryResidualBlock = MissingResidualBlocks::size == 0; static constexpr bool hasOnlyResidualBlocks = UnexpectedResidualBlocks::size == 0; static constexpr bool hasUniqueResidualOwners = RepeatedResidualBlocks::size == 0; static constexpr bool complete = hasEveryValueBlock && hasOnlyValueBlocks && hasUniqueValueOwners && hasEveryResidualBlock && hasOnlyResidualBlocks && hasUniqueResidualOwners; }; template concept CompleteNormalizationFor = utils::blocks::block_form_is_valid_v && NormalizationPlanType && NormalizationCoverage>::complete; } // namespace mean_field::normalization