feat(libmeanfield): variadic refactor
also added normaliztion operator
This commit is contained in:
@@ -292,7 +292,8 @@ export namespace mean_field::preconditioning {
|
||||
};
|
||||
|
||||
template <equilibrium::DiscretizedStellarEquilibriumProblem Problem, SpecificationBorderBlockType Block>
|
||||
requires EquilibriumCoordinateComponentFor<Block, typename std::remove_cvref_t<Problem>::FormType>
|
||||
requires EquilibriumCoordinateComponentFor<Block, typename std::remove_cvref_t<Problem>::FormType> &&
|
||||
SpecificationBorderPreparableFor<Problem, Block>
|
||||
class PreparedStellarPreconditioner final : public mfem::Solver {
|
||||
private:
|
||||
using ProblemType = std::remove_cvref_t<Problem>;
|
||||
@@ -324,6 +325,9 @@ export namespace mean_field::preconditioning {
|
||||
}
|
||||
}
|
||||
|
||||
PreparedStellarPreconditioner(ProblemType &&, BlockType) = delete;
|
||||
PreparedStellarPreconditioner(const ProblemType &&, BlockType) = delete;
|
||||
|
||||
PreparedStellarPreconditioner(const PreparedStellarPreconditioner &) = delete;
|
||||
PreparedStellarPreconditioner &operator=(const PreparedStellarPreconditioner &) = delete;
|
||||
PreparedStellarPreconditioner(PreparedStellarPreconditioner &&) = delete;
|
||||
@@ -367,6 +371,10 @@ export namespace mean_field::preconditioning {
|
||||
return m_grouped.GetBlock();
|
||||
}
|
||||
|
||||
[[nodiscard]] const ProblemType &GetProblem() const noexcept {
|
||||
return m_grouped.GetProblem();
|
||||
}
|
||||
|
||||
[[nodiscard]] const GroupedPreconditioner &GetGroupedPreconditioner() const noexcept {
|
||||
return m_grouped;
|
||||
}
|
||||
@@ -392,11 +400,26 @@ export namespace mean_field::preconditioning {
|
||||
SpecificationBorderBlockType Block>
|
||||
requires EquilibriumCoordinateComponentFor<
|
||||
Block,
|
||||
typename std::remove_cvref_t<Problem>::FormType>
|
||||
typename std::remove_cvref_t<Problem>::FormType> &&
|
||||
SpecificationBorderPreparableFor<Problem, Block>
|
||||
[[nodiscard]] auto prepare(
|
||||
const Problem &problem,
|
||||
Block block
|
||||
) {
|
||||
return PreparedStellarPreconditioner<Problem, Block>{problem, std::move(block)};
|
||||
}
|
||||
|
||||
template <typename Problem, SpecificationBorderBlockType Block>
|
||||
requires (!std::is_lvalue_reference_v<Problem>) &&
|
||||
equilibrium::DiscretizedStellarEquilibriumProblem<std::remove_cvref_t<Problem>> &&
|
||||
EquilibriumCoordinateComponentFor<
|
||||
Block,
|
||||
typename std::remove_cvref_t<Problem>::FormType> &&
|
||||
SpecificationBorderPreparableFor<std::remove_cvref_t<Problem>, Block>
|
||||
[[nodiscard]] auto prepare(
|
||||
Problem &&,
|
||||
Block
|
||||
) -> PreparedStellarPreconditioner<
|
||||
std::remove_cvref_t<Problem>,
|
||||
std::remove_cvref_t<Block>> = delete;
|
||||
} // namespace mean_field::preconditioning
|
||||
|
||||
@@ -231,10 +231,90 @@ export namespace mean_field::preconditioning {
|
||||
template <typename Candidate>
|
||||
concept MaterialSurfaceDescriptor = detail::IsMaterialSurfaceDescriptor<std::remove_cvref_t<Candidate>>::value;
|
||||
|
||||
/*
|
||||
* Capability boundary for EOS-specific material/surface surrogate
|
||||
* assembly. The current kernels remain polytropic, but selection no
|
||||
* longer embeds that closed-world type test in the descriptor concept.
|
||||
*/
|
||||
template <typename EquationOfState>
|
||||
struct MaterialSurfaceEquationOfStateBackend {
|
||||
static constexpr bool registered = false;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MaterialSurfaceEquationOfStateBackend<eos::Polytrope> {
|
||||
static constexpr bool registered = true;
|
||||
using CoreType = operators::PreparedStellarEquilibriumOperator;
|
||||
};
|
||||
|
||||
template <typename EquationOfState>
|
||||
concept ImplementedMaterialSurfaceEquationOfState = requires {
|
||||
{
|
||||
MaterialSurfaceEquationOfStateBackend<std::remove_cvref_t<EquationOfState>>::registered
|
||||
} -> std::convertible_to<bool>;
|
||||
requires MaterialSurfaceEquationOfStateBackend<
|
||||
std::remove_cvref_t<EquationOfState>>::registered;
|
||||
typename MaterialSurfaceEquationOfStateBackend<std::remove_cvref_t<EquationOfState>>::CoreType;
|
||||
};
|
||||
|
||||
/*
|
||||
* Registering an EOS-to-core association is intentionally not enough to
|
||||
* claim that the material/surface preconditioner can execute it. Every
|
||||
* implementation listed here must have matching prepared operators and
|
||||
* prepare(...) overloads below. A future backend should add its pair only
|
||||
* after those executable pieces exist; this keeps capability queries
|
||||
* truthful while the current kernels still consume the legacy physical
|
||||
* core directly.
|
||||
*/
|
||||
template <typename EquationOfState, typename PhysicalCore>
|
||||
struct MaterialSurfaceExecutableRuntime {
|
||||
static constexpr bool available = false;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MaterialSurfaceExecutableRuntime<eos::Polytrope, operators::PreparedStellarEquilibriumOperator> {
|
||||
static constexpr bool available = true;
|
||||
};
|
||||
|
||||
template <typename EquationOfState, typename PhysicalCore>
|
||||
concept ExecutableMaterialSurfaceRuntimeFor = requires {
|
||||
{
|
||||
MaterialSurfaceExecutableRuntime<
|
||||
std::remove_cvref_t<EquationOfState>,
|
||||
std::remove_cvref_t<PhysicalCore>>::available
|
||||
} -> std::convertible_to<bool>;
|
||||
requires MaterialSurfaceExecutableRuntime<
|
||||
std::remove_cvref_t<EquationOfState>,
|
||||
std::remove_cvref_t<PhysicalCore>>::available;
|
||||
};
|
||||
|
||||
template <typename Descriptor>
|
||||
concept ImplementedMaterialSurfaceDescriptor =
|
||||
MaterialSurfaceDescriptor<Descriptor> &&
|
||||
std::same_as<typename Descriptor::ThermodynamicEquations::EquationOfStateType, eos::Polytrope>;
|
||||
ImplementedMaterialSurfaceEquationOfState<
|
||||
typename Descriptor::ThermodynamicEquations::EquationOfStateType>;
|
||||
|
||||
template <typename Descriptor, typename PhysicalCore>
|
||||
concept MaterialSurfaceRuntimeFor =
|
||||
ImplementedMaterialSurfaceDescriptor<Descriptor> && requires {
|
||||
typename MaterialSurfaceEquationOfStateBackend<
|
||||
typename std::remove_cvref_t<Descriptor>::ThermodynamicEquations::EquationOfStateType>::CoreType;
|
||||
requires std::same_as<
|
||||
std::remove_cvref_t<PhysicalCore>,
|
||||
typename MaterialSurfaceEquationOfStateBackend<
|
||||
typename std::remove_cvref_t<Descriptor>::ThermodynamicEquations::EquationOfStateType>::CoreType>;
|
||||
requires ExecutableMaterialSurfaceRuntimeFor<
|
||||
typename std::remove_cvref_t<Descriptor>::ThermodynamicEquations::EquationOfStateType,
|
||||
PhysicalCore>;
|
||||
};
|
||||
|
||||
template <typename Candidate>
|
||||
concept MaterialSurfacePreconditionerProblem =
|
||||
equilibrium::DiscretizedStellarEquilibriumProblem<Candidate> && requires {
|
||||
requires MaterialSurfaceRuntimeFor<
|
||||
MaterialSurfaceDescriptorFor<std::remove_cvref_t<Candidate>>,
|
||||
typename std::remove_cvref_t<Candidate>::PhysicalCoreType>;
|
||||
};
|
||||
|
||||
using DensityMassDiagonalCharacteristics = OperatorCharacteristics<
|
||||
OperatorCategory::mass_like,
|
||||
@@ -605,7 +685,7 @@ export namespace mean_field::preconditioning {
|
||||
};
|
||||
|
||||
template <
|
||||
equilibrium::DiscretizedStellarEquilibriumProblem Problem,
|
||||
MaterialSurfacePreconditionerProblem Problem,
|
||||
backend::Registered MaterialBackend = backend::Diagonal,
|
||||
backend::Registered SurfaceBackend = backend::Diagonal,
|
||||
MaterialSurfaceFactorizationPolicy Policy = SurfaceThenMaterialTriangular>
|
||||
@@ -623,7 +703,7 @@ export namespace mean_field::preconditioning {
|
||||
}
|
||||
|
||||
template <
|
||||
equilibrium::DiscretizedStellarEquilibriumProblem Problem,
|
||||
MaterialSurfacePreconditionerProblem Problem,
|
||||
backend::Registered MaterialBackend,
|
||||
backend::Registered SurfaceBackend,
|
||||
MaterialSurfaceFactorizationPolicy Policy,
|
||||
@@ -688,7 +768,7 @@ export namespace mean_field::preconditioning {
|
||||
// direct coupling actions and does not pay for a full Jacobian
|
||||
// application.
|
||||
m_fullDirection = 0.0;
|
||||
const auto fullDirectionView = m_operation->GetRootManifest().directionView(m_fullDirection);
|
||||
const auto fullDirectionView = m_operation->GetRootManifest().stateView(m_fullDirection);
|
||||
mfem::Vector fullDensityDirection = fullDirectionView.block(utils::blocks::density_field.mass_term);
|
||||
mfem::Vector fullSurfaceDirection =
|
||||
fullDirectionView.block(utils::blocks::surface_deformation_field.parameters_term);
|
||||
@@ -699,10 +779,10 @@ export namespace mean_field::preconditioning {
|
||||
|
||||
m_operation->Mult(m_fullDirection, m_fullAction);
|
||||
const auto fullActionView = m_operation->GetRootManifest().residualView(m_fullAction);
|
||||
const mfem::Vector fullDensityAction = fullActionView.block(utils::blocks::density_field.mass_term);
|
||||
const mfem::Vector fullSurfaceAction =
|
||||
const auto fullDensityAction = fullActionView.block(utils::blocks::density_field.mass_term);
|
||||
const auto fullSurfaceAction =
|
||||
fullActionView.block(utils::blocks::surface_deformation_field.shape_equilibrium_term);
|
||||
const mfem::Vector fullEnthalpyAction = fullActionView.block(utils::blocks::enthalpy_field.specific_term);
|
||||
const auto fullEnthalpyAction = fullActionView.block(utils::blocks::enthalpy_field.specific_term);
|
||||
densityAction = fullDensityAction;
|
||||
surfaceAction = fullSurfaceAction;
|
||||
enthalpyAction = fullEnthalpyAction;
|
||||
@@ -1108,7 +1188,8 @@ export namespace mean_field::preconditioning {
|
||||
std::uint64_t surfaceH1Assemblies{0};
|
||||
};
|
||||
|
||||
template <ImplementedMaterialSurfaceDescriptor Descriptor, MaterialSurfaceFactorizationPolicy Policy>
|
||||
template <MaterialSurfaceDescriptor Descriptor, MaterialSurfaceFactorizationPolicy Policy>
|
||||
requires MaterialSurfaceRuntimeFor<Descriptor, operators::PreparedStellarEquilibriumOperator>
|
||||
class PreparedMaterialSurfaceBlock final : public mfem::Solver {
|
||||
public:
|
||||
using Block = MaterialSurfaceBlock<Descriptor, backend::Diagonal, backend::Diagonal, Policy>;
|
||||
@@ -1562,9 +1643,10 @@ export namespace mean_field::preconditioning {
|
||||
};
|
||||
|
||||
template <
|
||||
ImplementedMaterialSurfaceDescriptor Descriptor,
|
||||
MaterialSurfaceDescriptor Descriptor,
|
||||
MaterialSurfaceFactorizationPolicy Policy,
|
||||
backend::ApplicationMode Mode>
|
||||
requires MaterialSurfaceRuntimeFor<Descriptor, operators::PreparedStellarEquilibriumOperator>
|
||||
class PreparedH1MaterialSurfaceBlock final : public mfem::Solver {
|
||||
public:
|
||||
using SurfaceBackend = backend::HypreBoomerAMG<Mode>;
|
||||
@@ -2027,8 +2109,9 @@ export namespace mean_field::preconditioning {
|
||||
};
|
||||
|
||||
template <
|
||||
ImplementedMaterialSurfaceDescriptor Descriptor,
|
||||
MaterialSurfaceDescriptor Descriptor,
|
||||
MaterialSurfaceFactorizationPolicy Policy>
|
||||
requires MaterialSurfaceRuntimeFor<Descriptor, operators::PreparedStellarEquilibriumOperator>
|
||||
[[nodiscard]] auto prepare(
|
||||
const operators::PreparedStellarEquilibriumOperator &operation,
|
||||
MaterialSurfaceBlock<
|
||||
@@ -2042,26 +2125,26 @@ export namespace mean_field::preconditioning {
|
||||
|
||||
template <
|
||||
equilibrium::StellarEquilibriumModel Model,
|
||||
equilibrium::StellarDiscretizationType Discretization,
|
||||
MaterialSurfaceFactorizationPolicy Policy>
|
||||
requires MaterialSurfacePreconditionerProblem<
|
||||
equilibrium::StellarEquilibriumProblem<Model, Discretization>>
|
||||
[[nodiscard]] auto prepare(
|
||||
const equilibrium::StellarEquilibriumProblem<Model> &problem,
|
||||
const equilibrium::StellarEquilibriumProblem<Model, Discretization> &problem,
|
||||
MaterialSurfaceBlock<
|
||||
MaterialSurfaceDescriptorFor<equilibrium::StellarEquilibriumProblem<Model>>,
|
||||
MaterialSurfaceDescriptorFor<equilibrium::StellarEquilibriumProblem<Model, Discretization>>,
|
||||
backend::Diagonal,
|
||||
backend::Diagonal,
|
||||
Policy> block
|
||||
) {
|
||||
if constexpr (equilibrium::StellarEquilibriumProblem<Model>::hasFixedCentralDensity) {
|
||||
return prepare(problem.GetPreparedOperator().GetPhysicalOperator(), std::move(block));
|
||||
} else {
|
||||
return prepare(problem.GetPreparedOperator(), std::move(block));
|
||||
}
|
||||
return prepare(problem.GetPhysicalOperator(), std::move(block));
|
||||
}
|
||||
|
||||
template <
|
||||
ImplementedMaterialSurfaceDescriptor Descriptor,
|
||||
MaterialSurfaceDescriptor Descriptor,
|
||||
MaterialSurfaceFactorizationPolicy Policy,
|
||||
backend::ApplicationMode Mode>
|
||||
requires MaterialSurfaceRuntimeFor<Descriptor, operators::PreparedStellarEquilibriumOperator>
|
||||
[[nodiscard]] auto prepare(
|
||||
const operators::PreparedStellarEquilibriumOperator &operation,
|
||||
MaterialSurfaceBlock<
|
||||
@@ -2076,21 +2159,20 @@ export namespace mean_field::preconditioning {
|
||||
|
||||
template <
|
||||
equilibrium::StellarEquilibriumModel Model,
|
||||
equilibrium::StellarDiscretizationType Discretization,
|
||||
MaterialSurfaceFactorizationPolicy Policy,
|
||||
backend::ApplicationMode Mode>
|
||||
requires MaterialSurfacePreconditionerProblem<
|
||||
equilibrium::StellarEquilibriumProblem<Model, Discretization>>
|
||||
[[nodiscard]] auto prepare(
|
||||
const equilibrium::StellarEquilibriumProblem<Model> &problem,
|
||||
const equilibrium::StellarEquilibriumProblem<Model, Discretization> &problem,
|
||||
MaterialSurfaceBlock<
|
||||
MaterialSurfaceDescriptorFor<equilibrium::StellarEquilibriumProblem<Model>>,
|
||||
MaterialSurfaceDescriptorFor<equilibrium::StellarEquilibriumProblem<Model, Discretization>>,
|
||||
backend::Diagonal,
|
||||
backend::HypreBoomerAMG<Mode>,
|
||||
Policy,
|
||||
SurfaceH1MassStiffness> block
|
||||
) {
|
||||
if constexpr (equilibrium::StellarEquilibriumProblem<Model>::hasFixedCentralDensity) {
|
||||
return prepare(problem.GetPreparedOperator().GetPhysicalOperator(), std::move(block));
|
||||
} else {
|
||||
return prepare(problem.GetPreparedOperator(), std::move(block));
|
||||
}
|
||||
return prepare(problem.GetPhysicalOperator(), std::move(block));
|
||||
}
|
||||
} // namespace mean_field::preconditioning
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,7 @@ export namespace mean_field::preconditioning {
|
||||
operators::StellarEquilibriumDependencyStamp geometry;
|
||||
const void *equationOfStateIdentity{nullptr};
|
||||
operators::StellarEquilibriumDependencies linearization;
|
||||
std::uint64_t preparedOperatorGeneration{0};
|
||||
|
||||
constexpr bool operator==(const StellarPreconditionerLifecycleSnapshot &) const = default;
|
||||
};
|
||||
@@ -61,7 +62,8 @@ export namespace mean_field::preconditioning {
|
||||
.discretization = prepared.discretization != current.discretization,
|
||||
.geometry = prepared.geometry != current.geometry,
|
||||
.equationOfState = prepared.equationOfStateIdentity != current.equationOfStateIdentity,
|
||||
.linearization = prepared.linearization != current.linearization
|
||||
.linearization = prepared.linearization != current.linearization ||
|
||||
prepared.preparedOperatorGeneration != current.preparedOperatorGeneration
|
||||
};
|
||||
}
|
||||
|
||||
@@ -95,9 +97,11 @@ export namespace mean_field::preconditioning {
|
||||
static constexpr bool registered = false;
|
||||
};
|
||||
|
||||
template <equilibrium::StellarEquilibriumModel Model>
|
||||
struct StellarEquilibriumProblemTraits<equilibrium::StellarEquilibriumProblem<Model>> {
|
||||
using Problem = equilibrium::StellarEquilibriumProblem<Model>;
|
||||
template <
|
||||
equilibrium::StellarEquilibriumModel Model,
|
||||
equilibrium::StellarDiscretizationType Discretization>
|
||||
struct StellarEquilibriumProblemTraits<equilibrium::StellarEquilibriumProblem<Model, Discretization>> {
|
||||
using Problem = equilibrium::StellarEquilibriumProblem<Model, Discretization>;
|
||||
using Form = typename Problem::FormType;
|
||||
using JacobianForm = typename Problem::JacobianFormType;
|
||||
using Manifest = typename Problem::ManifestType;
|
||||
@@ -130,8 +134,9 @@ export namespace mean_field::preconditioning {
|
||||
.discretization = dependencies.discretization,
|
||||
.geometry = problem.GetGeometryDependency(),
|
||||
.equationOfStateIdentity =
|
||||
std::addressof(problem.GetStellarModel().template specification<eos::Polytrope>()),
|
||||
.linearization = dependencies
|
||||
std::addressof(problem.GetStellarModel().equationOfState()),
|
||||
.linearization = dependencies,
|
||||
.preparedOperatorGeneration = problem.GetPreparationGeneration()
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -139,6 +144,243 @@ export namespace mean_field::preconditioning {
|
||||
template <typename Candidate>
|
||||
concept StellarPreconditionerProblem = StellarEquilibriumProblemTraits<std::remove_cvref_t<Candidate>>::registered;
|
||||
|
||||
namespace detail {
|
||||
template <typename Block>
|
||||
struct IsGeneratedStellarValueBlock : std::false_type { };
|
||||
|
||||
template <typename Generated>
|
||||
struct IsGeneratedStellarValueBlock<utils::blocks::generated_value_block<Generated>>
|
||||
: std::true_type { };
|
||||
|
||||
template <typename Block>
|
||||
struct IsGeneratedStellarResidualBlock : std::false_type { };
|
||||
|
||||
template <typename Generated>
|
||||
struct IsGeneratedStellarResidualBlock<utils::blocks::generated_residual_block<Generated>>
|
||||
: std::true_type { };
|
||||
|
||||
template <typename Coupling>
|
||||
inline constexpr bool isPurePhysicalStellarCoupling =
|
||||
!IsGeneratedStellarValueBlock<
|
||||
std::remove_cvref_t<typename Coupling::Value>>::value &&
|
||||
!IsGeneratedStellarResidualBlock<
|
||||
std::remove_cvref_t<typename Coupling::Residual>>::value;
|
||||
|
||||
/* Pure structure contributions owned by a trusted backend are exact
|
||||
* (core, specification, coupling) capabilities. Future cores and new
|
||||
* edges start with no privilege: changing a built-in declaration must
|
||||
* be accompanied by an explicit preconditioner decision. Generated-
|
||||
* border terms remain the responsibility of specification-border
|
||||
* machinery. */
|
||||
template <typename PhysicalCore, typename Specification>
|
||||
struct StellarStructureBackendHandledCouplings {
|
||||
using Type = utils::blocks::type_list<>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StellarStructureBackendHandledCouplings<
|
||||
operators::PreparedStellarEquilibriumOperator,
|
||||
models::FixedTotalMass> {
|
||||
using Type = utils::blocks::type_list<
|
||||
operators::StellarEquilibriumJacobianCoupling<
|
||||
utils::blocks::enthalpy::specific::residual,
|
||||
utils::blocks::density::mass::value>,
|
||||
operators::StellarEquilibriumJacobianCoupling<
|
||||
utils::blocks::enthalpy::specific::residual,
|
||||
utils::blocks::surface_deformation::parameters::value>>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StellarStructureBackendHandledCouplings<
|
||||
operators::PreparedStellarEquilibriumOperator,
|
||||
models::FixedAngularMomentum> {
|
||||
using Type = utils::blocks::type_list<
|
||||
operators::StellarEquilibriumJacobianCoupling<
|
||||
utils::blocks::surface_deformation::shape_equilibrium::residual,
|
||||
utils::blocks::density::mass::value>,
|
||||
operators::StellarEquilibriumJacobianCoupling<
|
||||
utils::blocks::surface_deformation::shape_equilibrium::residual,
|
||||
utils::blocks::surface_deformation::parameters::value>,
|
||||
operators::StellarEquilibriumJacobianCoupling<
|
||||
utils::blocks::enthalpy::specific::residual,
|
||||
utils::blocks::density::mass::value>,
|
||||
operators::StellarEquilibriumJacobianCoupling<
|
||||
utils::blocks::enthalpy::specific::residual,
|
||||
utils::blocks::surface_deformation::parameters::value>>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StellarStructureBackendHandledCouplings<
|
||||
operators::PreparedStellarEquilibriumOperator,
|
||||
models::FixedCentralDensity> {
|
||||
using Type = utils::blocks::type_list<
|
||||
operators::StellarEquilibriumJacobianCoupling<
|
||||
utils::blocks::enthalpy::specific::residual,
|
||||
utils::blocks::enthalpy::specific::value>>;
|
||||
};
|
||||
|
||||
template <
|
||||
typename Coupling,
|
||||
typename Model,
|
||||
typename PhysicalCore,
|
||||
typename ModelSpecifications>
|
||||
struct EveryCouplingContributionHandled;
|
||||
|
||||
template <
|
||||
typename Coupling,
|
||||
model::StellarModelType Model,
|
||||
typename PhysicalCore,
|
||||
models::ModelSpecification... Specifications>
|
||||
struct EveryCouplingContributionHandled<
|
||||
Coupling,
|
||||
Model,
|
||||
PhysicalCore,
|
||||
models::detail::SpecificationSetStorage<Specifications...>> final {
|
||||
private:
|
||||
template <typename Specification>
|
||||
static constexpr bool handled =
|
||||
!utils::blocks::contains_type_v<
|
||||
Coupling,
|
||||
typename operators::StellarEquilibriumSpecificationCompilation<
|
||||
Specification>::JacobianCouplings> ||
|
||||
(operators::stellarEquilibriumBackendRuntimeAuthorized<
|
||||
Specification,
|
||||
Model> &&
|
||||
utils::blocks::contains_type_v<
|
||||
Coupling,
|
||||
typename StellarStructureBackendHandledCouplings<
|
||||
PhysicalCore,
|
||||
Specification>::Type>) ||
|
||||
operators::stellarEquilibriumSpecificationCouplingIsStructuralZero<
|
||||
Specification,
|
||||
Model,
|
||||
Coupling>;
|
||||
|
||||
public:
|
||||
static constexpr bool value =
|
||||
(handled<Specifications> && ...);
|
||||
};
|
||||
|
||||
template <
|
||||
typename Remaining,
|
||||
typename Model,
|
||||
typename PhysicalCore,
|
||||
typename ModelSpecifications,
|
||||
typename Unsupported>
|
||||
struct CollectUnsupportedStellarStructureCouplings;
|
||||
|
||||
template <
|
||||
typename Model,
|
||||
typename PhysicalCore,
|
||||
typename ModelSpecifications,
|
||||
typename Unsupported>
|
||||
struct CollectUnsupportedStellarStructureCouplings<
|
||||
utils::blocks::type_list<>,
|
||||
Model,
|
||||
PhysicalCore,
|
||||
ModelSpecifications,
|
||||
Unsupported> {
|
||||
using Type = Unsupported;
|
||||
};
|
||||
|
||||
template <
|
||||
typename Head,
|
||||
typename... Tail,
|
||||
typename Model,
|
||||
typename PhysicalCore,
|
||||
typename ModelSpecifications,
|
||||
typename... Unsupported>
|
||||
struct CollectUnsupportedStellarStructureCouplings<
|
||||
utils::blocks::type_list<Head, Tail...>,
|
||||
Model,
|
||||
PhysicalCore,
|
||||
ModelSpecifications,
|
||||
utils::blocks::type_list<Unsupported...>> {
|
||||
private:
|
||||
static constexpr bool supported =
|
||||
!isPurePhysicalStellarCoupling<Head> ||
|
||||
EveryCouplingContributionHandled<
|
||||
Head,
|
||||
Model,
|
||||
PhysicalCore,
|
||||
ModelSpecifications>::value;
|
||||
using Next = std::conditional_t<
|
||||
supported,
|
||||
utils::blocks::type_list<Unsupported...>,
|
||||
utils::blocks::type_list<Unsupported..., Head>>;
|
||||
|
||||
public:
|
||||
using Type = typename CollectUnsupportedStellarStructureCouplings<
|
||||
utils::blocks::type_list<Tail...>,
|
||||
Model,
|
||||
PhysicalCore,
|
||||
ModelSpecifications,
|
||||
Next>::Type;
|
||||
};
|
||||
|
||||
template <typename Candidate, typename = void>
|
||||
struct DefaultStellarStructurePhysicalTopologyAudit {
|
||||
using ContributionCouplings = utils::blocks::type_list<>;
|
||||
using UnsupportedCouplings = utils::blocks::type_list<>;
|
||||
|
||||
static constexpr bool supported = false;
|
||||
};
|
||||
|
||||
template <model::StellarModelType Model>
|
||||
requires(
|
||||
operators::StellarEquilibriumSystemCompilable<
|
||||
std::remove_cvref_t<Model>> &&
|
||||
operators::hasStellarEquilibriumCoreRuntime<
|
||||
std::remove_cvref_t<Model>>)
|
||||
struct DefaultStellarStructurePhysicalTopologyAudit<
|
||||
Model,
|
||||
std::void_t<
|
||||
typename operators::CompiledStellarEquilibriumSystem<
|
||||
std::remove_cvref_t<Model>>::ContributionJacobianCouplings,
|
||||
operators::StellarEquilibriumPhysicalCoreType<
|
||||
std::remove_cvref_t<Model>>>> {
|
||||
private:
|
||||
using Compilation = operators::CompiledStellarEquilibriumSystem<
|
||||
std::remove_cvref_t<Model>>;
|
||||
using PhysicalCore = operators::StellarEquilibriumPhysicalCoreType<
|
||||
std::remove_cvref_t<Model>>;
|
||||
public:
|
||||
using ContributionCouplings =
|
||||
typename Compilation::ContributionJacobianCouplings;
|
||||
using UnsupportedCouplings =
|
||||
typename CollectUnsupportedStellarStructureCouplings<
|
||||
ContributionCouplings,
|
||||
std::remove_cvref_t<Model>,
|
||||
PhysicalCore,
|
||||
typename std::remove_cvref_t<Model>::SpecificationTypes,
|
||||
utils::blocks::type_list<>>::Type;
|
||||
|
||||
static constexpr bool supported = UnsupportedCouplings::size == 0;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/* A generated-border edge is owned by specification-border machinery and
|
||||
* is deliberately ignored here. Every pure physical edge contributed by a
|
||||
* model must be owned by the selected numerical structure backend, or
|
||||
* every non-backend provider of that edge must prove StructuralZero. In
|
||||
* particular, merely overlapping an existing base-Jacobian edge is not
|
||||
* sufficient: a custom nonzero coefficient on that edge would otherwise
|
||||
* disappear silently from the default preconditioner. This audit is
|
||||
* detection-safe and therefore suitable for constraining factories. */
|
||||
template <typename Candidate>
|
||||
struct DefaultStellarStructurePhysicalTopologySupport
|
||||
: detail::DefaultStellarStructurePhysicalTopologyAudit<
|
||||
std::remove_cvref_t<Candidate>> { };
|
||||
|
||||
template <typename Candidate>
|
||||
inline constexpr bool defaultStellarStructurePhysicalTopologySupported =
|
||||
DefaultStellarStructurePhysicalTopologySupport<
|
||||
std::remove_cvref_t<Candidate>>::supported;
|
||||
|
||||
template <typename Candidate>
|
||||
concept DefaultStellarStructurePhysicalTopologySupportedFor =
|
||||
defaultStellarStructurePhysicalTopologySupported<Candidate>;
|
||||
|
||||
namespace backend {
|
||||
template <typename Component, typename Problem, typename Backend = typename Component::BackendType>
|
||||
class PreparedComponent;
|
||||
@@ -174,56 +416,17 @@ export namespace mean_field::preconditioning {
|
||||
} // namespace backend
|
||||
|
||||
namespace detail {
|
||||
using DensityIdentity =
|
||||
IdentityBlock<utils::blocks::density::mass::value, utils::blocks::density::mass::residual>;
|
||||
using SurfaceIdentity = IdentityBlock<
|
||||
utils::blocks::surface_deformation::parameters::value,
|
||||
utils::blocks::surface_deformation::shape_equilibrium::residual>;
|
||||
using GravityGradientIdentity =
|
||||
IdentityBlock<utils::blocks::gravity::gradient::value, utils::blocks::gravity::gradient::residual>;
|
||||
using GravityPotentialIdentity =
|
||||
IdentityBlock<utils::blocks::gravity::poisson::value, utils::blocks::gravity::poisson::residual>;
|
||||
using EnthalpyIdentity =
|
||||
IdentityBlock<utils::blocks::enthalpy::specific::value, utils::blocks::enthalpy::specific::residual>;
|
||||
using FixedMassIdentity = IdentityBlock<
|
||||
utils::blocks::fixed_total_mass::mass_normalization::value,
|
||||
utils::blocks::fixed_total_mass::mass_normalization::residual>;
|
||||
using FixedCentralDensityIdentity = IdentityBlock<
|
||||
utils::blocks::fixed_central_density::central_value::value,
|
||||
utils::blocks::fixed_central_density::central_value::residual>;
|
||||
|
||||
template <typename Form> struct IdentityPlanForForm;
|
||||
|
||||
template <> struct IdentityPlanForForm<utils::blocks::surface_deformed_stellar_equilibrium_form> {
|
||||
using Type = PreconditionerPlan<
|
||||
DensityIdentity,
|
||||
SurfaceIdentity,
|
||||
GravityGradientIdentity,
|
||||
GravityPotentialIdentity,
|
||||
EnthalpyIdentity,
|
||||
FixedMassIdentity>;
|
||||
template <typename... Values, typename... Residuals>
|
||||
struct IdentityPlanForForm<utils::blocks::block_form<
|
||||
utils::blocks::type_list<Values...>,
|
||||
utils::blocks::type_list<Residuals...>>> {
|
||||
static_assert(sizeof...(Values) == sizeof...(Residuals));
|
||||
using Type = PreconditionerPlan<IdentityBlock<Values, Residuals>...>;
|
||||
|
||||
[[nodiscard]] static constexpr Type Make() {
|
||||
return Type{DensityIdentity{}, SurfaceIdentity{}, GravityGradientIdentity{},
|
||||
GravityPotentialIdentity{}, EnthalpyIdentity{}, FixedMassIdentity{}};
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct IdentityPlanForForm<utils::blocks::central_density_bordered_stellar_equilibrium_form> {
|
||||
using Type = PreconditionerPlan<
|
||||
DensityIdentity,
|
||||
SurfaceIdentity,
|
||||
GravityGradientIdentity,
|
||||
GravityPotentialIdentity,
|
||||
EnthalpyIdentity,
|
||||
FixedMassIdentity,
|
||||
FixedCentralDensityIdentity>;
|
||||
|
||||
[[nodiscard]] static constexpr Type Make() {
|
||||
return Type{
|
||||
DensityIdentity{}, SurfaceIdentity{}, GravityGradientIdentity{}, GravityPotentialIdentity{},
|
||||
EnthalpyIdentity{}, FixedMassIdentity{}, FixedCentralDensityIdentity{}
|
||||
};
|
||||
return Type{IdentityBlock<Values, Residuals>{}...};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ export module mean_field:preconditioning.stellar_structure;
|
||||
|
||||
export import :preconditioning.gravity_field;
|
||||
export import :preconditioning.material_surface;
|
||||
export import :preconditioning.stellar_equilibrium;
|
||||
|
||||
export namespace mean_field::preconditioning {
|
||||
struct IndependentStellarSubsystems final { };
|
||||
@@ -626,28 +627,88 @@ export namespace mean_field::preconditioning {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Material/surface execution and stellar-structure execution are separate
|
||||
* capabilities. The latter also owns the physical cross-Jacobian and
|
||||
* gravity-context wiring, which currently target the legacy prepared core.
|
||||
* Add future cores here only together with matching cross-coupling and
|
||||
* preparation implementations.
|
||||
*/
|
||||
template <typename PhysicalCore>
|
||||
struct StellarStructureExecutableRuntime {
|
||||
static constexpr bool available = false;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StellarStructureExecutableRuntime<operators::PreparedStellarEquilibriumOperator> {
|
||||
static constexpr bool available = true;
|
||||
};
|
||||
|
||||
template <typename PhysicalCore>
|
||||
concept ExecutableStellarStructureRuntimeFor = requires {
|
||||
{
|
||||
StellarStructureExecutableRuntime<std::remove_cvref_t<PhysicalCore>>::available
|
||||
} -> std::convertible_to<bool>;
|
||||
requires StellarStructureExecutableRuntime<std::remove_cvref_t<PhysicalCore>>::available;
|
||||
};
|
||||
|
||||
template <typename Descriptor, typename PhysicalCore>
|
||||
concept StellarStructureRuntimeFor =
|
||||
MaterialSurfaceRuntimeFor<Descriptor, PhysicalCore> &&
|
||||
ExecutableStellarStructureRuntimeFor<PhysicalCore>;
|
||||
|
||||
template <typename Candidate>
|
||||
concept StellarStructurePreconditionerProblem =
|
||||
equilibrium::DiscretizedStellarEquilibriumProblem<Candidate> &&
|
||||
DefaultStellarStructurePhysicalTopologySupportedFor<
|
||||
typename std::remove_cvref_t<Candidate>::ModelType> &&
|
||||
requires {
|
||||
requires StellarStructureRuntimeFor<
|
||||
MaterialSurfaceDescriptorFor<std::remove_cvref_t<Candidate>>,
|
||||
typename std::remove_cvref_t<Candidate>::PhysicalCoreType>;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <equilibrium::StellarEquilibriumModel Model>
|
||||
[[nodiscard]] const operators::PreparedStellarEquilibriumOperator &
|
||||
physicalOperator(const equilibrium::StellarEquilibriumProblem<Model> &problem) {
|
||||
if constexpr (equilibrium::StellarEquilibriumProblem<Model>::hasFixedCentralDensity) {
|
||||
return problem.GetPreparedOperator().GetPhysicalOperator();
|
||||
} else {
|
||||
return problem.GetPreparedOperator();
|
||||
}
|
||||
template <StellarStructurePreconditionerProblem Problem>
|
||||
[[nodiscard]] const auto &physicalOperator(const Problem &problem) {
|
||||
return problem.GetPhysicalOperator();
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <typename Problem, typename MaterialComponent, typename GravityComponent>
|
||||
concept StellarStructurePreparableFor =
|
||||
StellarStructurePreconditionerProblem<std::remove_cvref_t<Problem>> &&
|
||||
PreconditionerComponent<std::remove_cvref_t<MaterialComponent>> &&
|
||||
PreconditionerComponent<std::remove_cvref_t<GravityComponent>> &&
|
||||
requires(
|
||||
const std::remove_cvref_t<Problem> &problem,
|
||||
std::remove_cvref_t<MaterialComponent> materialComponent,
|
||||
std::remove_cvref_t<GravityComponent> gravityComponent
|
||||
) {
|
||||
preconditioning::prepare(problem, std::move(materialComponent));
|
||||
preconditioning::prepare(
|
||||
problem.GetPhysicalOperator().GetHydrostaticOperator().GetFEM(),
|
||||
problem.GetPhysicalOperator().GetGravityContext().GetGeometryContext(),
|
||||
std::move(gravityComponent)
|
||||
);
|
||||
StellarStructureCrossJacobianOperator{problem.GetPhysicalOperator()};
|
||||
};
|
||||
|
||||
template <
|
||||
equilibrium::StellarEquilibriumModel Model,
|
||||
equilibrium::StellarDiscretizationType Discretization,
|
||||
typename MaterialComponent,
|
||||
backend::Registered GravityMassBackend,
|
||||
backend::ApplicationMode Mode,
|
||||
GravityFactorizationPolicy GravityPolicy,
|
||||
StellarStructureFactorizationPolicy StructurePolicy>
|
||||
requires StellarStructurePreparableFor<
|
||||
equilibrium::StellarEquilibriumProblem<Model, Discretization>,
|
||||
MaterialComponent,
|
||||
GravityFieldBlock<GravityMassBackend, backend::HypreBoomerAMG<Mode>, GravityPolicy>>
|
||||
class PreparedStellarStructureBlock final : public mfem::Solver {
|
||||
private:
|
||||
using Problem = equilibrium::StellarEquilibriumProblem<Model>;
|
||||
using Problem = equilibrium::StellarEquilibriumProblem<Model, Discretization>;
|
||||
using GravityComponent = GravityFieldBlock<GravityMassBackend, backend::HypreBoomerAMG<Mode>, GravityPolicy>;
|
||||
using Structure = StellarStructureBlock<
|
||||
MaterialComponent,
|
||||
@@ -769,7 +830,7 @@ export namespace mean_field::preconditioning {
|
||||
};
|
||||
|
||||
template <
|
||||
equilibrium::DiscretizedStellarEquilibriumProblem Problem,
|
||||
StellarStructurePreconditionerProblem Problem,
|
||||
typename MaterialComponent,
|
||||
backend::Registered GravityMassBackend,
|
||||
backend::ApplicationMode Mode,
|
||||
@@ -792,7 +853,7 @@ export namespace mean_field::preconditioning {
|
||||
};
|
||||
}
|
||||
|
||||
template <equilibrium::DiscretizedStellarEquilibriumProblem Problem>
|
||||
template <StellarStructurePreconditionerProblem Problem>
|
||||
[[nodiscard]] constexpr auto stellarStructureBlock(const Problem &problem) {
|
||||
using FixedAMG = backend::HypreBoomerAMG<backend::FixedCycles>;
|
||||
auto material = materialSurfaceBlock(problem);
|
||||
@@ -805,25 +866,30 @@ export namespace mean_field::preconditioning {
|
||||
|
||||
template <
|
||||
equilibrium::StellarEquilibriumModel Model,
|
||||
equilibrium::StellarDiscretizationType Discretization,
|
||||
typename MaterialComponent,
|
||||
backend::Registered GravityMassBackend,
|
||||
backend::ApplicationMode Mode,
|
||||
GravityFactorizationPolicy GravityPolicy,
|
||||
StellarStructureFactorizationPolicy StructurePolicy>
|
||||
requires StellarStructurePreparableFor<
|
||||
equilibrium::StellarEquilibriumProblem<Model, Discretization>,
|
||||
MaterialComponent,
|
||||
GravityFieldBlock<GravityMassBackend, backend::HypreBoomerAMG<Mode>, GravityPolicy>>
|
||||
[[nodiscard]] auto prepare(
|
||||
const equilibrium::StellarEquilibriumProblem<Model> &problem,
|
||||
const equilibrium::StellarEquilibriumProblem<Model, Discretization> &problem,
|
||||
StellarStructureBlock<
|
||||
MaterialComponent,
|
||||
GravityFieldBlock<
|
||||
GravityMassBackend,
|
||||
backend::HypreBoomerAMG<Mode>,
|
||||
GravityPolicy>,
|
||||
typename equilibrium::StellarEquilibriumProblem<Model>::FormType,
|
||||
typename equilibrium::StellarEquilibriumProblem<Model>::JacobianFormType,
|
||||
typename equilibrium::StellarEquilibriumProblem<Model, Discretization>::FormType,
|
||||
typename equilibrium::StellarEquilibriumProblem<Model, Discretization>::JacobianFormType,
|
||||
StructurePolicy> structure
|
||||
) {
|
||||
return PreparedStellarStructureBlock<
|
||||
Model, MaterialComponent, GravityMassBackend, Mode, GravityPolicy, StructurePolicy>{
|
||||
Model, Discretization, MaterialComponent, GravityMassBackend, Mode, GravityPolicy, StructurePolicy>{
|
||||
problem, std::move(structure)
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user