#include #include #include import mean_field; import test_helpers; namespace { namespace blocks = mean_field::utils::blocks; namespace preconditioning = mean_field::preconditioning; using Form = blocks::surface_deformed_stellar_equilibrium_form; using JacobianForm = blocks::surface_deformed_stellar_equilibrium_jacobian_form; using CentralForm = blocks::central_density_bordered_stellar_equilibrium_form; using CentralJacobianForm = blocks::central_density_bordered_stellar_equilibrium_jacobian_form; using DensityIdentity = preconditioning::IdentityBlock; using SurfaceIdentity = preconditioning::IdentityBlock< blocks::surface_deformation::parameters::value, blocks::surface_deformation::shape_equilibrium::residual>; using GravityGradientIdentity = preconditioning::IdentityBlock; using GravityPotentialIdentity = preconditioning::IdentityBlock; using EnthalpyIdentity = preconditioning::IdentityBlock; using MassIdentity = preconditioning::IdentityBlock< blocks::fixed_total_mass::mass_normalization::value, blocks::fixed_total_mass::mass_normalization::residual>; using CentralDensityIdentity = preconditioning::IdentityBlock< blocks::fixed_central_density::central_value::value, blocks::fixed_central_density::central_value::residual>; using IdentityPlan = preconditioning::PreconditionerPlan< DensityIdentity, SurfaceIdentity, GravityGradientIdentity, GravityPotentialIdentity, EnthalpyIdentity, MassIdentity>; using CentralIdentityPlan = preconditioning::PreconditionerPlan< DensityIdentity, SurfaceIdentity, GravityGradientIdentity, GravityPotentialIdentity, EnthalpyIdentity, MassIdentity, CentralDensityIdentity>; using IncompleteCentralPlan = IdentityPlan; struct AlternateDensityIdentity final : preconditioning::ComponentDeclaration< blocks::type_list, blocks::type_list, blocks::type_list<>, preconditioning::IdentityOperatorCharacteristics, preconditioning::backend::Identity> { }; using DuplicateOwnershipPlan = preconditioning::PreconditionerPlan< DensityIdentity, SurfaceIdentity, GravityGradientIdentity, GravityPotentialIdentity, EnthalpyIdentity, MassIdentity, CentralDensityIdentity, AlternateDensityIdentity>; using ExplicitOverlapPlan = preconditioning::OverlappingPreconditionerPlan< DensityIdentity, SurfaceIdentity, GravityGradientIdentity, GravityPotentialIdentity, EnthalpyIdentity, MassIdentity, CentralDensityIdentity, AlternateDensityIdentity>; struct ExtraCorrection final : blocks::value_block_base { }; struct ExtraResidual final : blocks::residual_block_base { }; using ExtraIdentity = preconditioning::IdentityBlock; using UnexpectedOwnershipPlan = preconditioning::PreconditionerPlan< DensityIdentity, SurfaceIdentity, GravityGradientIdentity, GravityPotentialIdentity, EnthalpyIdentity, MassIdentity, ExtraIdentity>; using CoupledGravity = preconditioning::ComponentDeclaration< blocks::type_list, blocks::type_list, blocks::type_list< preconditioning::Coupling, preconditioning::Coupling, preconditioning::Coupling>, preconditioning::IdentityOperatorCharacteristics, preconditioning::backend::Identity>; using ValidCoupledPlan = preconditioning:: PreconditionerPlan; using InvalidGravityCoupling = preconditioning::ComponentDeclaration< blocks::type_list, blocks::type_list, blocks::type_list>, preconditioning::IdentityOperatorCharacteristics, preconditioning::backend::Identity>; using InvalidCoupledPlan = preconditioning:: PreconditionerPlan; using IncompatibleBackendComponent = preconditioning::ComponentDeclaration< blocks::type_list, blocks::type_list, blocks::type_list<>, preconditioning::OperatorCharacteristics< preconditioning::OperatorCategory::elliptic_like, preconditioning::OperatorValueStructure::vector, preconditioning::OperatorSymmetry::symmetric, preconditioning::OperatorDefiniteness::positive_definite, preconditioning::OperatorRepresentation::assembled_sparse, preconditioning::OperatorDistribution::distributed_true_dof, preconditioning::OperatorFESpace::h_div>, preconditioning::backend::HypreBoomerAMG<>>; struct IncoherentPlanDeclaration final { using ComponentTypes = blocks::type_list; using CorrectionBlocks = blocks::type_list; using ResidualBlocks = blocks::type_list; using RequiredCouplings = blocks::type_list<>; }; } // namespace TEST_CASE( "Preconditioning Backends Advertise Compile-Time Operator Compatibility", tags::preconditioning_type_contract ) { using ScalarElliptic = preconditioning::OperatorCharacteristics< preconditioning::OperatorCategory::elliptic_like, preconditioning::OperatorValueStructure::scalar, preconditioning::OperatorSymmetry::symmetric, preconditioning::OperatorDefiniteness::positive_definite, preconditioning::OperatorRepresentation::assembled_sparse, preconditioning::OperatorDistribution::distributed_true_dof, preconditioning::OperatorFESpace::h1>; using VectorElliptic = preconditioning::OperatorCharacteristics< preconditioning::OperatorCategory::elliptic_like, preconditioning::OperatorValueStructure::vector, preconditioning::OperatorSymmetry::symmetric, preconditioning::OperatorDefiniteness::positive_definite, preconditioning::OperatorRepresentation::assembled_sparse, preconditioning::OperatorDistribution::distributed_true_dof, preconditioning::OperatorFESpace::h_div>; using LocalDenseBorder = preconditioning::OperatorCharacteristics< preconditioning::OperatorCategory::dense_border, preconditioning::OperatorValueStructure::block, preconditioning::OperatorSymmetry::nonsymmetric, preconditioning::OperatorDefiniteness::indefinite, preconditioning::OperatorRepresentation::assembled_dense, preconditioning::OperatorDistribution::local>; using FixedAMG = preconditioning::backend::HypreBoomerAMG; STATIC_CHECK(preconditioning::backend::Registered); STATIC_CHECK(preconditioning::backend::Compatible); STATIC_CHECK_FALSE(preconditioning::backend::Compatible); STATIC_CHECK(preconditioning::backend::Compatible); STATIC_CHECK_FALSE(preconditioning::PreconditionerComponent); STATIC_CHECK( preconditioning::backend::applicationContract == preconditioning::ApplicationContract::stationary_linear ); } TEST_CASE( "Preconditioner Plans Prove Complete Unique Ownership Of Every Equilibrium Block", tags::preconditioning_type_contract ) { STATIC_CHECK(preconditioning::PreconditionerComponent); STATIC_CHECK(preconditioning::PreconditionerPlanType); STATIC_CHECK_FALSE(preconditioning::PreconditionerPlanType); STATIC_CHECK(preconditioning::CompletePreconditionerFor); STATIC_CHECK(preconditioning::CompatiblePreconditionerFor); STATIC_CHECK(preconditioning::CompletePreconditionerFor); STATIC_CHECK(preconditioning::CompatiblePreconditionerFor); STATIC_CHECK(preconditioning::StationaryLinearPreconditionerPlan); } TEST_CASE( "Preconditioner Coverage Reports Missing Generated Borders And Rejects Accidental Overlap", tags::preconditioning_type_contract ) { using IncompleteCoverage = preconditioning::PreconditionerCoverage; using DuplicateCoverage = preconditioning::PreconditionerCoverage; STATIC_CHECK_FALSE(preconditioning::CompletePreconditionerFor); STATIC_CHECK(IncompleteCoverage::MissingCorrectionBlocks::size == 1); STATIC_CHECK(IncompleteCoverage::MissingResidualBlocks::size == 1); STATIC_CHECK( blocks::contains_type_v< blocks::fixed_central_density::central_value::value, IncompleteCoverage::MissingCorrectionBlocks> ); STATIC_CHECK( blocks::contains_type_v< blocks::fixed_central_density::central_value::residual, IncompleteCoverage::MissingResidualBlocks> ); STATIC_CHECK_FALSE(preconditioning::CompletePreconditionerFor); STATIC_CHECK(DuplicateCoverage::RepeatedCorrectionBlocks::size == 1); STATIC_CHECK(DuplicateCoverage::RepeatedResidualBlocks::size == 1); STATIC_CHECK(preconditioning::CompletePreconditionerFor); } TEST_CASE( "Preconditioner Coverage Rejects Blocks Outside The Compiled Stellar Form", tags::preconditioning_type_contract ) { using Coverage = preconditioning::PreconditionerCoverage; STATIC_CHECK_FALSE(preconditioning::CompletePreconditionerFor); STATIC_CHECK(Coverage::UnexpectedCorrectionBlocks::size == 1); STATIC_CHECK(Coverage::UnexpectedResidualBlocks::size == 1); STATIC_CHECK(blocks::contains_type_v); STATIC_CHECK(blocks::contains_type_v); } TEST_CASE( "Preconditioner Component Dependencies Must Exist In The Compiled Jacobian Graph", tags::preconditioning_type_contract ) { STATIC_CHECK(preconditioning::PreconditionerComponent); STATIC_CHECK(preconditioning::CompletePreconditionerFor); STATIC_CHECK(preconditioning::CompatiblePreconditionerFor); STATIC_CHECK(preconditioning::CompletePreconditionerFor); STATIC_CHECK_FALSE(preconditioning::requiredCouplingsExist); STATIC_CHECK_FALSE(preconditioning::CompatiblePreconditionerFor); }