feat(libmeanfield): variadic refactor
also added normaliztion operator
This commit is contained in:
@@ -0,0 +1,815 @@
|
||||
module;
|
||||
|
||||
#include <concepts>
|
||||
#include <type_traits>
|
||||
|
||||
export module mean_field:operators.stellar_equilibrium_compiler;
|
||||
|
||||
export import :model.compiled_fixed_angular_momentum;
|
||||
export import :model.compiled_fixed_central_density;
|
||||
export import :model.typed_stellar;
|
||||
export import :utils.blocks;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
/*
|
||||
* A coupling is the symbolic statement that one Jacobian block may be
|
||||
* nonzero. Specifications contribute these statements independently of
|
||||
* the final row and column layout.
|
||||
*/
|
||||
template <typename ResidualBlock, typename ValueBlock>
|
||||
struct StellarEquilibriumJacobianCoupling final {
|
||||
using Residual = ResidualBlock;
|
||||
using Value = ValueBlock;
|
||||
|
||||
using ResidualBlockType = ResidualBlock;
|
||||
using ValueBlockType = ValueBlock;
|
||||
};
|
||||
|
||||
template <typename ResidualBlock, typename ValueBlock>
|
||||
using EquilibriumJacobianCoupling =
|
||||
StellarEquilibriumJacobianCoupling<ResidualBlock, ValueBlock>;
|
||||
|
||||
namespace detail {
|
||||
template <typename... Lists> struct ConcatenateBlockLists;
|
||||
|
||||
template <> struct ConcatenateBlockLists<> {
|
||||
using Type = utils::blocks::type_list<>;
|
||||
};
|
||||
|
||||
template <typename... Types>
|
||||
struct ConcatenateBlockLists<utils::blocks::type_list<Types...>> {
|
||||
using Type = utils::blocks::type_list<Types...>;
|
||||
};
|
||||
|
||||
template <typename... First, typename... Second, typename... Remaining>
|
||||
struct ConcatenateBlockLists<utils::blocks::type_list<First...>,
|
||||
utils::blocks::type_list<Second...>,
|
||||
Remaining...> {
|
||||
using Type = typename ConcatenateBlockLists<
|
||||
utils::blocks::type_list<First..., Second...>, Remaining...>::Type;
|
||||
};
|
||||
|
||||
template <typename... Lists>
|
||||
using ConcatenateBlockListsT = typename ConcatenateBlockLists<Lists...>::Type;
|
||||
|
||||
template <typename List, typename Type> struct AppendUniqueBlockType;
|
||||
|
||||
template <typename... Types, typename Type>
|
||||
struct AppendUniqueBlockType<utils::blocks::type_list<Types...>, Type> {
|
||||
using TypeValue = std::conditional_t<
|
||||
utils::blocks::contains_type_v<Type, utils::blocks::type_list<Types...>>,
|
||||
utils::blocks::type_list<Types...>,
|
||||
utils::blocks::type_list<Types..., Type>>;
|
||||
};
|
||||
|
||||
template <typename Accumulated, typename Remaining> struct UniqueBlockListImpl;
|
||||
|
||||
template <typename Accumulated>
|
||||
struct UniqueBlockListImpl<Accumulated, utils::blocks::type_list<>> {
|
||||
using Type = Accumulated;
|
||||
};
|
||||
|
||||
template <typename Accumulated, typename Head, typename... Tail>
|
||||
struct UniqueBlockListImpl<Accumulated,
|
||||
utils::blocks::type_list<Head, Tail...>> {
|
||||
using Type = typename UniqueBlockListImpl<
|
||||
typename AppendUniqueBlockType<Accumulated, Head>::TypeValue,
|
||||
utils::blocks::type_list<Tail...>>::Type;
|
||||
};
|
||||
|
||||
template <typename List>
|
||||
using UniqueBlockListT =
|
||||
typename UniqueBlockListImpl<utils::blocks::type_list<>, List>::Type;
|
||||
|
||||
template <typename... Lists>
|
||||
using UniqueConcatenateBlockListsT =
|
||||
UniqueBlockListT<ConcatenateBlockListsT<Lists...>>;
|
||||
|
||||
template <typename Candidate> struct IsValueBlockList : std::false_type {};
|
||||
|
||||
template <typename... Blocks>
|
||||
struct IsValueBlockList<utils::blocks::type_list<Blocks...>>
|
||||
: std::bool_constant<
|
||||
(std::derived_from<Blocks, utils::blocks::value_block_base> && ...) &&
|
||||
utils::blocks::types_are_unique_v<
|
||||
utils::blocks::type_list<Blocks...>>> {};
|
||||
|
||||
template <typename Candidate> struct IsResidualBlockList : std::false_type {};
|
||||
|
||||
template <typename... Blocks>
|
||||
struct IsResidualBlockList<utils::blocks::type_list<Blocks...>>
|
||||
: std::bool_constant<
|
||||
(std::derived_from<Blocks, utils::blocks::residual_block_base> &&
|
||||
...) &&
|
||||
utils::blocks::types_are_unique_v<
|
||||
utils::blocks::type_list<Blocks...>>> {};
|
||||
|
||||
template <typename GeneratedValues> struct GeneratedValueBlocksFor;
|
||||
|
||||
template <typename... GeneratedValues>
|
||||
struct GeneratedValueBlocksFor<models::ModelTypeList<GeneratedValues...>> {
|
||||
using Type = utils::blocks::type_list<
|
||||
utils::blocks::generated_value_block<GeneratedValues>...>;
|
||||
};
|
||||
|
||||
template <typename GeneratedResiduals> struct GeneratedResidualBlocksFor;
|
||||
|
||||
template <typename... GeneratedResiduals>
|
||||
struct GeneratedResidualBlocksFor<
|
||||
models::ModelTypeList<GeneratedResiduals...>> {
|
||||
using Type = utils::blocks::type_list<
|
||||
utils::blocks::generated_residual_block<GeneratedResiduals>...>;
|
||||
};
|
||||
|
||||
/*
|
||||
* One translation boundary turns physics-facing stellar names into backend
|
||||
* blocks. Existing backend block types pass through unchanged, which keeps
|
||||
* the advanced extension API open without making built-in physics declarations
|
||||
* depend on utils.blocks.
|
||||
*/
|
||||
template <typename DeclaredDependency>
|
||||
struct UnmappedStellarDependency final {};
|
||||
|
||||
template <typename Blocks, typename DeclaredDependency>
|
||||
struct SingleGeneratedBlock {
|
||||
using Type = UnmappedStellarDependency<DeclaredDependency>;
|
||||
static constexpr bool available = false;
|
||||
};
|
||||
|
||||
template <typename Block, typename DeclaredDependency>
|
||||
struct SingleGeneratedBlock<utils::blocks::type_list<Block>,
|
||||
DeclaredDependency> {
|
||||
using Type = Block;
|
||||
static constexpr bool available = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification, typename Dependency>
|
||||
struct StellarDependencyBlock {
|
||||
using Type = UnmappedStellarDependency<Dependency>;
|
||||
static constexpr bool mapped = false;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification, typename Block>
|
||||
requires(std::derived_from<Block, utils::blocks::value_block_base> ||
|
||||
std::derived_from<Block, utils::blocks::residual_block_base>)
|
||||
struct StellarDependencyBlock<Specification, Block> {
|
||||
using Type = Block;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<Specification, models::stellar::state::Density> {
|
||||
using Type = utils::blocks::density::mass::value;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<Specification,
|
||||
models::stellar::state::SurfaceShape> {
|
||||
using Type = utils::blocks::surface_deformation::parameters::value;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<Specification,
|
||||
models::stellar::state::GravityGradient> {
|
||||
using Type = utils::blocks::gravity::gradient::value;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<
|
||||
Specification, models::stellar::state::GravitationalPotential> {
|
||||
using Type = utils::blocks::gravity::poisson::value;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<Specification,
|
||||
models::stellar::state::SpecificEnthalpy> {
|
||||
using Type = utils::blocks::enthalpy::specific::value;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<
|
||||
Specification, models::stellar::state::OwnGeneratedCoordinate> {
|
||||
private:
|
||||
using GeneratedBlocks = typename GeneratedValueBlocksFor<
|
||||
typename models::SpecificationContribution<
|
||||
Specification>::GeneratedValues>::Type;
|
||||
using Selection = SingleGeneratedBlock<
|
||||
GeneratedBlocks, models::stellar::state::OwnGeneratedCoordinate>;
|
||||
|
||||
public:
|
||||
using Type = typename Selection::Type;
|
||||
static constexpr bool mapped = Selection::available;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification,
|
||||
models::ModelSpecification Owner>
|
||||
struct StellarDependencyBlock<
|
||||
Specification, models::stellar::state::GeneratedCoordinateOf<Owner>> {
|
||||
private:
|
||||
using GeneratedBlocks = typename GeneratedValueBlocksFor<
|
||||
typename models::SpecificationContribution<Owner>::GeneratedValues>::Type;
|
||||
using Dependency = models::stellar::state::GeneratedCoordinateOf<Owner>;
|
||||
using Selection = SingleGeneratedBlock<GeneratedBlocks, Dependency>;
|
||||
|
||||
public:
|
||||
using Type = typename Selection::Type;
|
||||
static constexpr bool mapped = Selection::available;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<
|
||||
Specification, models::stellar::equation::GravityGradientDefinition> {
|
||||
using Type = utils::blocks::gravity::gradient::residual;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<Specification,
|
||||
models::stellar::equation::PoissonEquation> {
|
||||
using Type = utils::blocks::gravity::poisson::residual;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<Specification,
|
||||
models::stellar::equation::DensityClosure> {
|
||||
using Type = utils::blocks::density::mass::residual;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<
|
||||
Specification, models::stellar::equation::SurfaceShapeBalance> {
|
||||
using Type =
|
||||
utils::blocks::surface_deformation::shape_equilibrium::residual;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<
|
||||
Specification, models::stellar::equation::HydrostaticBalance> {
|
||||
using Type = utils::blocks::enthalpy::specific::residual;
|
||||
static constexpr bool mapped = true;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarDependencyBlock<Specification,
|
||||
models::stellar::equation::OwnConstraint> {
|
||||
private:
|
||||
using GeneratedBlocks = typename GeneratedResidualBlocksFor<
|
||||
typename models::SpecificationContribution<
|
||||
Specification>::GeneratedResiduals>::Type;
|
||||
using Selection = SingleGeneratedBlock<
|
||||
GeneratedBlocks, models::stellar::equation::OwnConstraint>;
|
||||
|
||||
public:
|
||||
using Type = typename Selection::Type;
|
||||
static constexpr bool mapped = Selection::available;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification,
|
||||
models::ModelSpecification Owner>
|
||||
struct StellarDependencyBlock<
|
||||
Specification, models::stellar::equation::ConstraintOf<Owner>> {
|
||||
private:
|
||||
using GeneratedBlocks = typename GeneratedResidualBlocksFor<
|
||||
typename models::SpecificationContribution<Owner>::GeneratedResiduals>::Type;
|
||||
using Dependency = models::stellar::equation::ConstraintOf<Owner>;
|
||||
using Selection = SingleGeneratedBlock<GeneratedBlocks, Dependency>;
|
||||
|
||||
public:
|
||||
using Type = typename Selection::Type;
|
||||
static constexpr bool mapped = Selection::available;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification, typename Dependencies>
|
||||
struct CompileStellarDependencies {
|
||||
using Type = utils::blocks::type_list<
|
||||
UnmappedStellarDependency<Dependencies>>;
|
||||
static constexpr bool complete = false;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification, typename... Dependencies>
|
||||
struct CompileStellarDependencies<Specification,
|
||||
models::ModelTypeList<Dependencies...>> {
|
||||
using Type = utils::blocks::type_list<
|
||||
typename StellarDependencyBlock<Specification, Dependencies>::Type...>;
|
||||
static constexpr bool complete =
|
||||
(StellarDependencyBlock<Specification, Dependencies>::mapped && ...);
|
||||
};
|
||||
|
||||
template <typename Residual, typename Values> struct CoupleResidualToValues;
|
||||
|
||||
template <typename Residual, typename... Values>
|
||||
struct CoupleResidualToValues<Residual, utils::blocks::type_list<Values...>> {
|
||||
using Type = utils::blocks::type_list<
|
||||
StellarEquilibriumJacobianCoupling<Residual, Values>...>;
|
||||
};
|
||||
|
||||
template <typename Residuals, typename Values>
|
||||
struct CartesianJacobianCouplings;
|
||||
|
||||
template <typename... Residuals, typename Values>
|
||||
struct CartesianJacobianCouplings<utils::blocks::type_list<Residuals...>,
|
||||
Values> {
|
||||
using Type = ConcatenateBlockListsT<
|
||||
typename CoupleResidualToValues<Residuals, Values>::Type...>;
|
||||
};
|
||||
|
||||
template <typename Candidate> struct IsJacobianCoupling : std::false_type {};
|
||||
|
||||
template <typename Residual, typename Value>
|
||||
struct IsJacobianCoupling<StellarEquilibriumJacobianCoupling<Residual, Value>>
|
||||
: std::bool_constant<
|
||||
std::derived_from<Residual, utils::blocks::residual_block_base> &&
|
||||
std::derived_from<Value, utils::blocks::value_block_base>> {};
|
||||
|
||||
template <typename Candidate>
|
||||
struct IsJacobianCouplingList : std::false_type {};
|
||||
|
||||
template <typename... Couplings>
|
||||
struct IsJacobianCouplingList<utils::blocks::type_list<Couplings...>>
|
||||
: std::bool_constant<(IsJacobianCoupling<Couplings>::value && ...) &&
|
||||
utils::blocks::types_are_unique_v<
|
||||
utils::blocks::type_list<Couplings...>>> {};
|
||||
|
||||
template <typename Candidate> struct IsGeneratedValueBlock : std::false_type {};
|
||||
|
||||
template <typename Owner>
|
||||
struct IsGeneratedValueBlock<utils::blocks::generated_value_block<Owner>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename Candidate>
|
||||
struct IsGeneratedResidualBlock : std::false_type {};
|
||||
|
||||
template <typename Owner>
|
||||
struct IsGeneratedResidualBlock<utils::blocks::generated_residual_block<Owner>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename Coupling>
|
||||
inline constexpr bool isGeneratedBorderIncidentCoupling =
|
||||
IsGeneratedValueBlock<typename Coupling::Value>::value ||
|
||||
IsGeneratedResidualBlock<typename Coupling::Residual>::value;
|
||||
|
||||
template <typename Couplings> struct GeneratedBorderIncidentCouplings;
|
||||
|
||||
template <>
|
||||
struct GeneratedBorderIncidentCouplings<utils::blocks::type_list<>> {
|
||||
using Type = utils::blocks::type_list<>;
|
||||
};
|
||||
|
||||
template <typename Head, typename... Tail>
|
||||
struct GeneratedBorderIncidentCouplings<
|
||||
utils::blocks::type_list<Head, Tail...>> {
|
||||
private:
|
||||
using Remaining = typename GeneratedBorderIncidentCouplings<
|
||||
utils::blocks::type_list<Tail...>>::Type;
|
||||
|
||||
public:
|
||||
using Type = std::conditional_t<
|
||||
isGeneratedBorderIncidentCoupling<Head>,
|
||||
ConcatenateBlockListsT<utils::blocks::type_list<Head>, Remaining>,
|
||||
Remaining>;
|
||||
};
|
||||
|
||||
template <bool Registered, typename GeneratedValues,
|
||||
typename GeneratedResiduals, typename DependsOn, typename Affects>
|
||||
struct DeclarativeStellarEquilibriumSpecificationCompilation {
|
||||
using GeneratedValueBlocks = GeneratedValues;
|
||||
using GeneratedResidualBlocks = GeneratedResiduals;
|
||||
using DependsOnValueBlocks = DependsOn;
|
||||
using AffectedResidualBlocks = Affects;
|
||||
|
||||
/*
|
||||
* Preserve the two physical meanings in the declaration instead of
|
||||
* flattening their endpoints into independent unions:
|
||||
*
|
||||
* constraint equation <- everything named in Reads
|
||||
* changed equations <- Reads plus the generated coordinate
|
||||
*
|
||||
* The second group deliberately includes Affects x Reads. Nonlinear
|
||||
* constraints and multiplier forces generally contribute Hessian-like
|
||||
* state derivatives there. Linear contributions simply assemble zero on
|
||||
* those structurally permitted edges.
|
||||
*/
|
||||
using ConstraintInputValueBlocks = DependsOnValueBlocks;
|
||||
using ConstraintOutputResidualBlocks = GeneratedResidualBlocks;
|
||||
using ChangedEquationInputValueBlocks = UniqueConcatenateBlockListsT<
|
||||
DependsOnValueBlocks, GeneratedValueBlocks>;
|
||||
using ChangedEquationOutputResidualBlocks = AffectedResidualBlocks;
|
||||
|
||||
using ConstraintJacobianCouplings =
|
||||
typename CartesianJacobianCouplings<GeneratedResidualBlocks,
|
||||
DependsOnValueBlocks>::Type;
|
||||
using ChangedEquationJacobianCouplings =
|
||||
typename CartesianJacobianCouplings<AffectedResidualBlocks,
|
||||
ChangedEquationInputValueBlocks>::Type;
|
||||
|
||||
// Compatibility names retained for backend code that distinguishes the
|
||||
// generated row from the generated-coordinate column.
|
||||
using GeneratedRowJacobianCouplings = ConstraintJacobianCouplings;
|
||||
using AffectedRowJacobianCouplings =
|
||||
typename CartesianJacobianCouplings<AffectedResidualBlocks,
|
||||
GeneratedValueBlocks>::Type;
|
||||
using AffectedStateJacobianCouplings =
|
||||
typename CartesianJacobianCouplings<AffectedResidualBlocks,
|
||||
DependsOnValueBlocks>::Type;
|
||||
|
||||
using JacobianCouplings = UniqueConcatenateBlockListsT<
|
||||
ConstraintJacobianCouplings, ChangedEquationJacobianCouplings>;
|
||||
using IncidentJacobianCouplings =
|
||||
typename GeneratedBorderIncidentCouplings<JacobianCouplings>::Type;
|
||||
|
||||
// Correction is the Newton-facing name for a value coordinate.
|
||||
using GeneratedCorrectionBlocks = GeneratedValueBlocks;
|
||||
|
||||
static constexpr bool registered = Registered;
|
||||
static constexpr bool complete =
|
||||
registered && IsValueBlockList<GeneratedValueBlocks>::value &&
|
||||
IsResidualBlockList<GeneratedResidualBlocks>::value &&
|
||||
IsValueBlockList<DependsOnValueBlocks>::value &&
|
||||
IsResidualBlockList<AffectedResidualBlocks>::value &&
|
||||
IsJacobianCouplingList<JacobianCouplings>::value &&
|
||||
(GeneratedValueBlocks::size == GeneratedResidualBlocks::size) &&
|
||||
((GeneratedValueBlocks::size == 0 && DependsOnValueBlocks::size == 0 &&
|
||||
AffectedResidualBlocks::size == 0) ||
|
||||
(GeneratedValueBlocks::size > 0 && DependsOnValueBlocks::size > 0 &&
|
||||
AffectedResidualBlocks::size > 0));
|
||||
};
|
||||
|
||||
using EmptySpecificationCompilation =
|
||||
DeclarativeStellarEquilibriumSpecificationCompilation<
|
||||
false, utils::blocks::type_list<>, utils::blocks::type_list<>,
|
||||
utils::blocks::type_list<>, utils::blocks::type_list<>>;
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct SelfDescribingSpecificationCompilationInputs {
|
||||
using Contribution = models::SpecificationContribution<Specification>;
|
||||
using DependsOn =
|
||||
CompileStellarDependencies<Specification, typename Contribution::DependsOn>;
|
||||
using Affects =
|
||||
CompileStellarDependencies<Specification, typename Contribution::Affects>;
|
||||
|
||||
using GeneratedValueBlocks = typename GeneratedValueBlocksFor<
|
||||
typename Contribution::GeneratedValues>::Type;
|
||||
using GeneratedResidualBlocks = typename GeneratedResidualBlocksFor<
|
||||
typename Contribution::GeneratedResiduals>::Type;
|
||||
using DependsOnValueBlocks = typename DependsOn::Type;
|
||||
using AffectedResidualBlocks = typename Affects::Type;
|
||||
|
||||
static constexpr bool registered =
|
||||
Contribution::hasDeclarativeDefinition && DependsOn::complete &&
|
||||
Affects::complete;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct SelfDescribingSpecificationCompilation
|
||||
: DeclarativeStellarEquilibriumSpecificationCompilation<
|
||||
SelfDescribingSpecificationCompilationInputs<Specification>::registered,
|
||||
typename SelfDescribingSpecificationCompilationInputs<
|
||||
Specification>::GeneratedValueBlocks,
|
||||
typename SelfDescribingSpecificationCompilationInputs<
|
||||
Specification>::GeneratedResidualBlocks,
|
||||
typename SelfDescribingSpecificationCompilationInputs<
|
||||
Specification>::DependsOnValueBlocks,
|
||||
typename SelfDescribingSpecificationCompilationInputs<
|
||||
Specification>::AffectedResidualBlocks> {};
|
||||
} // namespace detail
|
||||
|
||||
/*
|
||||
* Public, inspectable per-specification compilation metadata. The primary
|
||||
* is deliberately well formed and incomplete, so testing an arbitrary type
|
||||
* in a requires-expression never triggers a diagnostic.
|
||||
*/
|
||||
template <typename Specification>
|
||||
struct StellarEquilibriumSpecificationCompilation
|
||||
: detail::EmptySpecificationCompilation {};
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
struct StellarEquilibriumSpecificationCompilation<Specification>
|
||||
: detail::SelfDescribingSpecificationCompilation<Specification> {};
|
||||
|
||||
namespace detail {
|
||||
template <typename Specification, typename = void>
|
||||
struct SpecificationCompilationIsComplete : std::false_type {};
|
||||
|
||||
template <typename Specification>
|
||||
struct SpecificationCompilationIsComplete<
|
||||
Specification,
|
||||
std::void_t<typename StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::GeneratedValueBlocks,
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::GeneratedResidualBlocks,
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::DependsOnValueBlocks,
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::AffectedResidualBlocks,
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::JacobianCouplings,
|
||||
std::bool_constant<StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::registered>,
|
||||
std::bool_constant<StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::complete>>>
|
||||
: std::bool_constant<
|
||||
StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::registered &&
|
||||
StellarEquilibriumSpecificationCompilation<Specification>::complete &&
|
||||
IsValueBlockList<typename StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::GeneratedValueBlocks>::value &&
|
||||
IsResidualBlockList<
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::GeneratedResidualBlocks>::value &&
|
||||
IsValueBlockList<typename StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::DependsOnValueBlocks>::value &&
|
||||
IsResidualBlockList<
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::AffectedResidualBlocks>::value &&
|
||||
IsJacobianCouplingList<
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::JacobianCouplings>::value> {};
|
||||
} // namespace detail
|
||||
|
||||
template <typename Candidate>
|
||||
inline constexpr bool stellarEquilibriumSpecificationCompilationComplete =
|
||||
detail::SpecificationCompilationIsComplete<
|
||||
std::remove_cvref_t<Candidate>>::value;
|
||||
|
||||
template <typename Candidate>
|
||||
concept StellarEquilibriumSpecificationCompilable =
|
||||
stellarEquilibriumSpecificationCompilationComplete<Candidate>;
|
||||
|
||||
namespace detail {
|
||||
/*
|
||||
* This five-by-five physical core is independent of global constraints.
|
||||
* Even FixedTotalMass is compiled as a contribution, keeping C and R_M
|
||||
* visible in that specification's metadata.
|
||||
*/
|
||||
using StellarPhysicsValueBlocks = utils::blocks::type_list<
|
||||
utils::blocks::density::mass::value,
|
||||
utils::blocks::surface_deformation::parameters::value,
|
||||
utils::blocks::gravity::gradient::value,
|
||||
utils::blocks::gravity::poisson::value,
|
||||
utils::blocks::enthalpy::specific::value>;
|
||||
|
||||
using StellarPhysicsResidualBlocks = utils::blocks::type_list<
|
||||
utils::blocks::gravity::gradient::residual,
|
||||
utils::blocks::gravity::poisson::residual,
|
||||
utils::blocks::density::mass::residual,
|
||||
utils::blocks::surface_deformation::shape_equilibrium::residual,
|
||||
utils::blocks::enthalpy::specific::residual>;
|
||||
|
||||
using StellarPhysicsJacobianRows = utils::blocks::type_list<
|
||||
utils::blocks::block_row<
|
||||
utils::blocks::gravity::gradient::residual,
|
||||
utils::blocks::gravity::gradient::value,
|
||||
utils::blocks::gravity::poisson::value,
|
||||
utils::blocks::surface_deformation::parameters::value>,
|
||||
utils::blocks::block_row<
|
||||
utils::blocks::gravity::poisson::residual,
|
||||
utils::blocks::gravity::gradient::value,
|
||||
utils::blocks::density::mass::value,
|
||||
utils::blocks::surface_deformation::parameters::value>,
|
||||
utils::blocks::block_row<
|
||||
utils::blocks::density::mass::residual,
|
||||
utils::blocks::density::mass::value,
|
||||
utils::blocks::enthalpy::specific::value,
|
||||
utils::blocks::surface_deformation::parameters::value>,
|
||||
utils::blocks::block_row<
|
||||
utils::blocks::surface_deformation::shape_equilibrium::residual,
|
||||
utils::blocks::density::mass::value,
|
||||
utils::blocks::surface_deformation::parameters::value,
|
||||
utils::blocks::gravity::gradient::value,
|
||||
utils::blocks::enthalpy::specific::value>,
|
||||
utils::blocks::block_row<
|
||||
utils::blocks::enthalpy::specific::residual,
|
||||
utils::blocks::enthalpy::specific::value,
|
||||
utils::blocks::gravity::poisson::value,
|
||||
utils::blocks::surface_deformation::parameters::value>>;
|
||||
|
||||
template <typename Row> struct JacobianRowCouplings;
|
||||
|
||||
template <typename Residual, typename... Values>
|
||||
struct JacobianRowCouplings<utils::blocks::block_row<Residual, Values...>> {
|
||||
using Type = utils::blocks::type_list<
|
||||
StellarEquilibriumJacobianCoupling<Residual, Values>...>;
|
||||
};
|
||||
|
||||
template <typename Rows> struct FlattenJacobianRows;
|
||||
|
||||
template <typename... Rows>
|
||||
struct FlattenJacobianRows<utils::blocks::type_list<Rows...>> {
|
||||
using Type =
|
||||
ConcatenateBlockListsT<typename JacobianRowCouplings<Rows>::Type...>;
|
||||
};
|
||||
|
||||
using StellarPhysicsJacobianCouplings =
|
||||
typename FlattenJacobianRows<StellarPhysicsJacobianRows>::Type;
|
||||
|
||||
template <typename SpecificationSet>
|
||||
struct SpecificationSetCompilationsAreComplete;
|
||||
|
||||
template <models::ModelSpecification... Specifications>
|
||||
struct SpecificationSetCompilationsAreComplete<
|
||||
models::detail::SpecificationSetStorage<Specifications...>>
|
||||
: std::bool_constant<(
|
||||
stellarEquilibriumSpecificationCompilationComplete<Specifications> &&
|
||||
...)> {};
|
||||
|
||||
template <typename SpecificationSet, bool Complete>
|
||||
struct CollectStellarEquilibriumContributionsImpl {
|
||||
using GeneratedValueBlocks = utils::blocks::type_list<>;
|
||||
using GeneratedResidualBlocks = utils::blocks::type_list<>;
|
||||
using ContributionJacobianCouplings = utils::blocks::type_list<>;
|
||||
using IncidentJacobianCouplings = ContributionJacobianCouplings;
|
||||
|
||||
static constexpr bool complete = false;
|
||||
};
|
||||
|
||||
template <models::ModelSpecification... Specifications>
|
||||
struct CollectStellarEquilibriumContributionsImpl<
|
||||
models::detail::SpecificationSetStorage<Specifications...>, true> {
|
||||
using GeneratedValueBlocks = ConcatenateBlockListsT<
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specifications>::GeneratedValueBlocks...>;
|
||||
using GeneratedResidualBlocks = ConcatenateBlockListsT<
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specifications>::GeneratedResidualBlocks...>;
|
||||
using ContributionJacobianCouplings = UniqueConcatenateBlockListsT<
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specifications>::JacobianCouplings...>;
|
||||
using IncidentJacobianCouplings = UniqueConcatenateBlockListsT<
|
||||
typename StellarEquilibriumSpecificationCompilation<
|
||||
Specifications>::IncidentJacobianCouplings...>;
|
||||
|
||||
static constexpr bool complete = true;
|
||||
};
|
||||
|
||||
template <typename SpecificationSet>
|
||||
using CollectStellarEquilibriumContributions =
|
||||
CollectStellarEquilibriumContributionsImpl<
|
||||
SpecificationSet,
|
||||
SpecificationSetCompilationsAreComplete<SpecificationSet>::value>;
|
||||
|
||||
template <typename Residual, typename Couplings> struct ValuesCoupledToResidual;
|
||||
|
||||
template <typename Residual>
|
||||
struct ValuesCoupledToResidual<Residual, utils::blocks::type_list<>> {
|
||||
using Type = utils::blocks::type_list<>;
|
||||
};
|
||||
|
||||
template <typename Residual, typename HeadResidual, typename HeadValue,
|
||||
typename... Tail>
|
||||
struct ValuesCoupledToResidual<
|
||||
Residual,
|
||||
utils::blocks::type_list<
|
||||
StellarEquilibriumJacobianCoupling<HeadResidual, HeadValue>, Tail...>> {
|
||||
private:
|
||||
using Remaining =
|
||||
typename ValuesCoupledToResidual<Residual,
|
||||
utils::blocks::type_list<Tail...>>::Type;
|
||||
|
||||
public:
|
||||
using Type = std::conditional_t<
|
||||
std::same_as<Residual, HeadResidual>,
|
||||
ConcatenateBlockListsT<utils::blocks::type_list<HeadValue>, Remaining>,
|
||||
Remaining>;
|
||||
};
|
||||
|
||||
template <typename Residual, typename Values> struct MakeJacobianRow;
|
||||
|
||||
template <typename Residual, typename... Values>
|
||||
struct MakeJacobianRow<Residual, utils::blocks::type_list<Values...>> {
|
||||
using Type = utils::blocks::block_row<Residual, Values...>;
|
||||
};
|
||||
|
||||
template <typename Residuals, typename Couplings> struct SynthesizeJacobianRows;
|
||||
|
||||
template <typename... Residuals, typename Couplings>
|
||||
struct SynthesizeJacobianRows<utils::blocks::type_list<Residuals...>,
|
||||
Couplings> {
|
||||
using Type = utils::blocks::type_list<typename MakeJacobianRow<
|
||||
Residuals,
|
||||
typename ValuesCoupledToResidual<Residuals, Couplings>::Type>::Type...>;
|
||||
};
|
||||
|
||||
template <typename Couplings, typename ValueBlocks, typename ResidualBlocks>
|
||||
struct CouplingEndpointsBelongToForm : std::false_type {};
|
||||
|
||||
template <typename ValueBlocks, typename ResidualBlocks, typename... Couplings>
|
||||
struct CouplingEndpointsBelongToForm<utils::blocks::type_list<Couplings...>,
|
||||
ValueBlocks, ResidualBlocks>
|
||||
: std::bool_constant<((utils::blocks::contains_type_v<
|
||||
typename Couplings::Value, ValueBlocks> &&
|
||||
utils::blocks::contains_type_v<
|
||||
typename Couplings::Residual, ResidualBlocks>) &&
|
||||
...)> {};
|
||||
|
||||
template <typename Candidate> struct CompileStellarEquilibriumSystem {
|
||||
using GeneratedValueBlocks = utils::blocks::type_list<>;
|
||||
using GeneratedCorrectionBlocks = GeneratedValueBlocks;
|
||||
using GeneratedResidualBlocks = utils::blocks::type_list<>;
|
||||
using BaseJacobianCouplings = utils::blocks::type_list<>;
|
||||
using ContributionJacobianCouplings = utils::blocks::type_list<>;
|
||||
using IncidentJacobianCouplings = ContributionJacobianCouplings;
|
||||
using JacobianCouplings = utils::blocks::type_list<>;
|
||||
|
||||
static constexpr bool compilable = false;
|
||||
};
|
||||
|
||||
template <model::StellarModelType Model>
|
||||
struct CompileStellarEquilibriumSystem<Model> {
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
using Contributions = CollectStellarEquilibriumContributions<
|
||||
typename ModelType::SpecificationTypes>;
|
||||
|
||||
using GeneratedValueBlocks = typename Contributions::GeneratedValueBlocks;
|
||||
using GeneratedCorrectionBlocks = GeneratedValueBlocks;
|
||||
using GeneratedResidualBlocks =
|
||||
typename Contributions::GeneratedResidualBlocks;
|
||||
|
||||
using ValueBlocks =
|
||||
ConcatenateBlockListsT<StellarPhysicsValueBlocks, GeneratedValueBlocks>;
|
||||
using ResidualBlocks = ConcatenateBlockListsT<StellarPhysicsResidualBlocks,
|
||||
GeneratedResidualBlocks>;
|
||||
using FormType = utils::blocks::block_form<ValueBlocks, ResidualBlocks>;
|
||||
|
||||
using BaseJacobianCouplings = StellarPhysicsJacobianCouplings;
|
||||
using ContributionJacobianCouplings =
|
||||
typename Contributions::ContributionJacobianCouplings;
|
||||
using IncidentJacobianCouplings = ContributionJacobianCouplings;
|
||||
using JacobianCouplings =
|
||||
UniqueConcatenateBlockListsT<BaseJacobianCouplings,
|
||||
ContributionJacobianCouplings>;
|
||||
|
||||
// Pass two: materialize rows only after all contributed blocks are
|
||||
// present in the final form.
|
||||
using JacobianType =
|
||||
typename SynthesizeJacobianRows<ResidualBlocks, JacobianCouplings>::Type;
|
||||
|
||||
static constexpr bool compilable =
|
||||
Contributions::complete &&
|
||||
utils::blocks::block_form_is_valid_v<FormType> &&
|
||||
IsJacobianCouplingList<JacobianCouplings>::value &&
|
||||
CouplingEndpointsBelongToForm<JacobianCouplings, ValueBlocks,
|
||||
ResidualBlocks>::value &&
|
||||
utils::blocks::jacobian_form_is_valid_v<FormType, JacobianType>;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <typename Candidate>
|
||||
inline constexpr bool stellarEquilibriumSystemIsCompilable =
|
||||
detail::CompileStellarEquilibriumSystem<
|
||||
std::remove_cvref_t<Candidate>>::compilable;
|
||||
|
||||
/*
|
||||
* This compiler proves the symbolic block topology only. Keep the explicit
|
||||
* name available to extension authors and tests so that success here is not
|
||||
* mistaken for an assembled numerical runtime. The established spelling is
|
||||
* retained below as a compatibility alias.
|
||||
*/
|
||||
template <typename Candidate>
|
||||
inline constexpr bool stellarEquilibriumIsSymbolicallyCompilable =
|
||||
stellarEquilibriumSystemIsCompilable<Candidate>;
|
||||
|
||||
template <typename Candidate>
|
||||
concept StellarEquilibriumSymbolicallyCompilable =
|
||||
stellarEquilibriumIsSymbolicallyCompilable<Candidate>;
|
||||
|
||||
template <typename Candidate>
|
||||
concept StellarEquilibriumSystemCompilable =
|
||||
StellarEquilibriumSymbolicallyCompilable<Candidate>;
|
||||
|
||||
template <model::StellarModelType Model>
|
||||
requires StellarEquilibriumSystemCompilable<Model>
|
||||
struct CompiledStellarEquilibriumSystem final
|
||||
: detail::CompileStellarEquilibriumSystem<std::remove_cvref_t<Model>> {
|
||||
using Base =
|
||||
detail::CompileStellarEquilibriumSystem<std::remove_cvref_t<Model>>;
|
||||
|
||||
using FormType = typename Base::FormType;
|
||||
using JacobianType = typename Base::JacobianType;
|
||||
|
||||
// This classification is exposed only after the complete compiler concept
|
||||
// has succeeded; model declarations intentionally do not predict it.
|
||||
static constexpr models::EquilibriumSystemCompilation compilationClass =
|
||||
models::EquilibriumSystemCompilation::complete_equilibrium_system;
|
||||
|
||||
static_assert(utils::blocks::block_form_is_valid_v<FormType>);
|
||||
static_assert(utils::blocks::valid_jacobian_form<FormType, JacobianType>);
|
||||
};
|
||||
|
||||
template <model::StellarModelType Model>
|
||||
requires StellarEquilibriumSystemCompilable<Model>
|
||||
using CompiledStellarEquilibriumForm =
|
||||
typename CompiledStellarEquilibriumSystem<Model>::FormType;
|
||||
|
||||
template <model::StellarModelType Model>
|
||||
requires StellarEquilibriumSystemCompilable<Model>
|
||||
using CompiledStellarEquilibriumJacobianForm =
|
||||
typename CompiledStellarEquilibriumSystem<Model>::JacobianType;
|
||||
} // namespace mean_field::operators
|
||||
Reference in New Issue
Block a user