feat(newton): first newton solver implementation

This commit is contained in:
2026-09-08 06:36:39 -04:00
parent 76818f2f82
commit b3c04d507a
98 changed files with 20397 additions and 11040 deletions

View File

@@ -39,7 +39,7 @@ export namespace mean_field::normalization {
}
mfem::Vector state(stateSize);
mfem::Vector residual(residualSize);
state = 1.0;
state = 1.0;
residual = 1.0;
return {std::move(state), std::move(residual)};
}
@@ -126,7 +126,7 @@ export namespace mean_field::normalization {
}
for (int index = 0; index < input.Size(); ++index) {
const double value = input(index);
output(index) = inverse ? value / factors(index) : factors(index) * value;
output(index) = inverse ? value / factors(index) : factors(index) * value;
}
}
@@ -156,22 +156,19 @@ export namespace mean_field::normalization {
* the policy and is found by ADL, so adding a normalization family does
* not edit a library registry or switch. */
template <typename Problem>
concept RuntimePreparedNormalizationOperation =
requires(const std::remove_cvref_t<Problem> &problem) {
typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType;
typename std::remove_cvref_t<Problem>::FormType;
requires RuntimePreparedNormalizationFor<
typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType,
typename std::remove_cvref_t<Problem>::FormType>;
{
problem.GetNormalizationPrescription()
} -> std::same_as<const typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType &>;
{
prepareStellarNormalization(
problem.GetNormalizationPrescription(),
problem)
} -> std::same_as<DiagonalNormalization>;
};
concept RuntimePreparedNormalizationOperation = requires(const std::remove_cvref_t<Problem> &problem) {
typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType;
typename std::remove_cvref_t<Problem>::FormType;
requires RuntimePreparedNormalizationFor<
typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType,
typename std::remove_cvref_t<Problem>::FormType>;
{
problem.GetNormalizationPrescription()
} -> std::same_as<const typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType &>;
{
prepareStellarNormalization(problem.GetNormalizationPrescription(), problem)
} -> std::same_as<DiagonalNormalization>;
};
template <typename Form>
requires utils::blocks::block_form_is_valid_v<Form>
@@ -183,16 +180,14 @@ export namespace mean_field::normalization {
m_residualFactors(layout.residual_offsets().Last()) {
}
explicit DiagonalNormalizationBuilder(
utils::blocks::form_layout<Form> &&
) = delete;
explicit DiagonalNormalizationBuilder(utils::blocks::form_layout<Form> &&) = delete;
explicit DiagonalNormalizationBuilder(
const utils::blocks::form_layout<Form> &&
) = delete;
explicit DiagonalNormalizationBuilder(const utils::blocks::form_layout<Form> &&) = delete;
template <typename Block>
requires utils::blocks::contains_type_v<Block, typename Form::value_blocks>
requires utils::blocks::contains_type_v<
Block,
typename Form::value_blocks>
void SetValueBlock(
const double physicalScale,
const mfem::Vector &primalGramDiagonal
@@ -200,18 +195,17 @@ export namespace mean_field::normalization {
constexpr int block = utils::blocks::type_index_v<Block, typename Form::value_blocks>;
RequireUnassigned(m_valueAssigned[block], "value");
AssignBlock(
m_stateFactors,
m_layout->value_offsets()[block],
m_layout->value_offsets()[block + 1] - m_layout->value_offsets()[block],
physicalScale,
primalGramDiagonal,
false
m_stateFactors, m_layout->value_offsets()[block],
m_layout->value_offsets()[block + 1] - m_layout->value_offsets()[block], physicalScale,
primalGramDiagonal, false
);
m_valueAssigned[block] = true;
}
template <typename Block>
requires utils::blocks::contains_type_v<Block, typename Form::residual_blocks>
requires utils::blocks::contains_type_v<
Block,
typename Form::residual_blocks>
void SetResidualBlock(
const double physicalScale,
const mfem::Vector &primalGramDiagonal
@@ -219,25 +213,26 @@ export namespace mean_field::normalization {
constexpr int block = utils::blocks::type_index_v<Block, typename Form::residual_blocks>;
RequireUnassigned(m_residualAssigned[block], "residual");
AssignBlock(
m_residualFactors,
m_layout->residual_offsets()[block],
m_layout->residual_offsets()[block + 1] - m_layout->residual_offsets()[block],
physicalScale,
primalGramDiagonal,
true
m_residualFactors, m_layout->residual_offsets()[block],
m_layout->residual_offsets()[block + 1] - m_layout->residual_offsets()[block], physicalScale,
primalGramDiagonal, true
);
m_residualAssigned[block] = true;
}
template <typename Block>
requires utils::blocks::contains_type_v<Block, typename Form::value_blocks>
requires utils::blocks::contains_type_v<
Block,
typename Form::value_blocks>
void SetValueGlobal(const double physicalScale) {
constexpr int block = utils::blocks::type_index_v<Block, typename Form::value_blocks>;
SetConstantMetricValueBlock<Block>(physicalScale, BlockSize(m_layout->value_offsets(), block));
}
template <typename Block>
requires utils::blocks::contains_type_v<Block, typename Form::residual_blocks>
requires utils::blocks::contains_type_v<
Block,
typename Form::residual_blocks>
void SetResidualGlobal(const double physicalScale) {
constexpr int block = utils::blocks::type_index_v<Block, typename Form::residual_blocks>;
mfem::Vector metric(BlockSize(m_layout->residual_offsets(), block));
@@ -246,7 +241,9 @@ export namespace mean_field::normalization {
}
template <typename Block>
requires utils::blocks::contains_type_v<Block, typename Form::residual_blocks>
requires utils::blocks::contains_type_v<
Block,
typename Form::residual_blocks>
void SetHybridResidualBlock(
const double physicalScale,
const mfem::Vector &bulkPrimalGramDiagonal,
@@ -254,7 +251,7 @@ export namespace mean_field::normalization {
const double pointMetric = 1.0
) {
constexpr int block = utils::blocks::type_index_v<Block, typename Form::residual_blocks>;
const int size = BlockSize(m_layout->residual_offsets(), block);
const int size = BlockSize(m_layout->residual_offsets(), block);
if (bulkPrimalGramDiagonal.Size() != size) {
throw std::invalid_argument("The hybrid residual Gram diagonal has the wrong size.");
}
@@ -273,9 +270,7 @@ export namespace mean_field::normalization {
mfem::Vector metric(size);
for (int row = 0; row < size; ++row) {
metric(row) = isPointRow[static_cast<std::size_t>(row)]
? pointMetric
: bulkPrimalGramDiagonal(row);
metric(row) = isPointRow[static_cast<std::size_t>(row)] ? pointMetric : bulkPrimalGramDiagonal(row);
}
SetResidualBlock<Block>(physicalScale, metric);
}
@@ -345,9 +340,7 @@ export namespace mean_field::normalization {
const double metric = primalGramDiagonal(index);
ValidateMetric(metric);
const double rieszFactor = std::sqrt(metric);
const double factor = dual
? 1.0 / (physicalScale * rieszFactor)
: rieszFactor / physicalScale;
const double factor = dual ? 1.0 / (physicalScale * rieszFactor) : rieszFactor / physicalScale;
if (!std::isfinite(factor) || factor <= 0.0) {
throw std::overflow_error("A normalization factor is not finite and positive.");
}
@@ -368,7 +361,10 @@ export namespace mean_field::normalization {
const mfem::Operator &physicalJacobian,
const DiagonalNormalization &normalization
)
: mfem::Operator(normalization.ResidualSize(), normalization.StateSize()),
: mfem::Operator(
normalization.ResidualSize(),
normalization.StateSize()
),
m_physicalJacobian(&physicalJacobian),
m_normalization(&normalization),
m_physicalDirection(normalization.StateSize()),
@@ -421,7 +417,10 @@ export namespace mean_field::normalization {
const mfem::Operator &physicalInverse,
const DiagonalNormalization &normalization
)
: mfem::Operator(normalization.StateSize(), normalization.ResidualSize()),
: mfem::Operator(
normalization.StateSize(),
normalization.ResidualSize()
),
m_physicalInverse(&physicalInverse),
m_normalization(&normalization),
m_physicalResidual(normalization.ResidualSize()),
@@ -548,7 +547,7 @@ export namespace mean_field::normalization {
const mfem::Operator &,
const mfem::Operator &,
const DiagonalNormalization &&
) = delete;
) = delete;
ScaledPreconditioner(const ScaledPreconditioner &) = delete;
ScaledPreconditioner &operator=(const ScaledPreconditioner &) = delete;
@@ -557,9 +556,7 @@ export namespace mean_field::normalization {
void SetOperator(const mfem::Operator &normalizedJacobian) override {
if (normalizedJacobian.Width() != Width() || normalizedJacobian.Height() != Height()) {
throw std::invalid_argument(
"The scaled preconditioner received an incompatible normalized Jacobian."
);
throw std::invalid_argument("The scaled preconditioner received an incompatible normalized Jacobian.");
}
if (&normalizedJacobian != m_expectedNormalizedJacobian) {
throw std::invalid_argument(

View File

@@ -27,10 +27,10 @@ export namespace mean_field::normalization {
template <
RieszGeometryPolicy GeometryPolicy = ReferenceGeometry,
ReferenceScalePolicy ScalePolicy = FixedMassBranchReference>
ReferenceScalePolicy ScalePolicy = FixedMassBranchReference>
class PhysicalRieszDiagonal final : public NormalizationPrescriptionTag {
public:
using Geometry = GeometryPolicy;
using Geometry = GeometryPolicy;
using ScaleSource = ScalePolicy;
explicit PhysicalRieszDiagonal(
@@ -62,8 +62,13 @@ export namespace mean_field::normalization {
double m_gravitationalConstant;
};
PhysicalRieszDiagonal(dimensions::LengthValue, double = 1.0)
-> PhysicalRieszDiagonal<ReferenceGeometry, FixedMassBranchReference>;
PhysicalRieszDiagonal(
dimensions::LengthValue,
double = 1.0
)
-> PhysicalRieszDiagonal<
ReferenceGeometry,
FixedMassBranchReference>;
template <typename Candidate> struct IsPhysicalRieszDiagonal : std::false_type { };
@@ -71,8 +76,7 @@ export namespace mean_field::normalization {
struct IsPhysicalRieszDiagonal<PhysicalRieszDiagonal<Geometry, ScaleSource>> : std::true_type { };
template <typename Candidate>
concept PhysicalRieszDiagonalPrescription =
IsPhysicalRieszDiagonal<std::remove_cvref_t<Candidate>>::value;
concept PhysicalRieszDiagonalPrescription = IsPhysicalRieszDiagonal<std::remove_cvref_t<Candidate>>::value;
struct StellarCharacteristicScales final {
dimensions::MassValue mass;
@@ -93,7 +97,7 @@ export namespace mean_field::normalization {
const dimensions::LengthValue radius,
const double gravitationalConstant = 1.0
) {
const double massValue = mass.value();
const double massValue = mass.value();
const double radiusValue = radius.value();
if (!std::isfinite(massValue) || massValue <= 0.0) {
throw std::invalid_argument("Characteristic stellar scales require a finite, positive mass.");
@@ -107,28 +111,19 @@ export namespace mean_field::normalization {
);
}
const double radiusSquared = radiusValue * radiusValue;
const double radiusCubed = radiusSquared * radiusValue;
const double density = massValue / radiusCubed;
const double acceleration = gravitationalConstant * massValue / radiusSquared;
const double radiusSquared = radiusValue * radiusValue;
const double radiusCubed = radiusSquared * radiusValue;
const double density = massValue / radiusCubed;
const double acceleration = gravitationalConstant * massValue / radiusSquared;
const double inverseTimeSquared = gravitationalConstant * massValue / radiusCubed;
const double specificEnergy = gravitationalConstant * massValue / radiusValue;
const double pressure = gravitationalConstant * massValue * massValue /
(radiusSquared * radiusSquared);
const double specificEnergy = gravitationalConstant * massValue / radiusValue;
const double pressure = gravitationalConstant * massValue * massValue / (radiusSquared * radiusSquared);
const double angularVelocity = std::sqrt(inverseTimeSquared);
const double angularMomentum = massValue * std::sqrt(gravitationalConstant * massValue * radiusValue);
const double force = gravitationalConstant * massValue * massValue / radiusSquared;
const double force = gravitationalConstant * massValue * massValue / radiusSquared;
const double derived[] = {
density,
acceleration,
inverseTimeSquared,
specificEnergy,
pressure,
angularVelocity,
angularMomentum,
force
};
const double derived[] = {density, acceleration, inverseTimeSquared, specificEnergy,
pressure, angularVelocity, angularMomentum, force};
for (const double value : derived) {
if (!std::isfinite(value) || value <= 0.0) {
throw std::overflow_error("A derived characteristic stellar scale is not finite and positive.");
@@ -136,36 +131,38 @@ export namespace mean_field::normalization {
}
return {
.mass = mass,
.radius = radius,
.mass = mass,
.radius = radius,
.gravitationalConstant = gravitationalConstant,
.density = density,
.acceleration = acceleration,
.inverseTimeSquared = inverseTimeSquared,
.specificEnergy = specificEnergy,
.pressure = pressure,
.angularVelocity = angularVelocity,
.angularMomentum = angularMomentum,
.force = force
.density = density,
.acceleration = acceleration,
.inverseTimeSquared = inverseTimeSquared,
.specificEnergy = specificEnergy,
.pressure = pressure,
.angularVelocity = angularVelocity,
.angularMomentum = angularMomentum,
.force = force
};
}
template <RieszGeometryPolicy Geometry, ReferenceScalePolicy ScaleSource, typename Model>
template <
RieszGeometryPolicy Geometry,
ReferenceScalePolicy ScaleSource,
typename Model>
requires requires(const Model &model) {
{
model.template specification<models::FixedTotalMass>()
} -> std::same_as<const models::FixedTotalMass &>;
{ model.template specification<models::FixedTotalMass>() } -> std::same_as<const models::FixedTotalMass &>;
{
model.template specification<models::FixedTotalMass>().targetMass()
} -> std::same_as<dimensions::MassValue>;
}
[[nodiscard]] StellarCharacteristicScales deriveStellarCharacteristicScales(
const PhysicalRieszDiagonal<Geometry, ScaleSource> &prescription,
const PhysicalRieszDiagonal<
Geometry,
ScaleSource> &prescription,
const Model &model
) {
return deriveStellarCharacteristicScales(
model.template specification<models::FixedTotalMass>().targetMass(),
prescription.referenceRadius(),
model.template specification<models::FixedTotalMass>().targetMass(), prescription.referenceRadius(),
prescription.gravitationalConstant()
);
}
@@ -179,14 +176,14 @@ export namespace mean_field::normalization {
* normalization plan used by the discretization.
*/
template <models::RieszTopology Topology> struct DeclaredRieszTopology {
static constexpr bool available = false;
static constexpr bool available = false;
static constexpr RieszTopology value = RieszTopology::identity;
};
#define MEAN_FIELD_DECLARED_RIESZ_TOPOLOGY(Name) \
template <> struct DeclaredRieszTopology<models::RieszTopology::Name> { \
static constexpr bool available = true; \
static constexpr RieszTopology value = RieszTopology::Name; \
#define MEAN_FIELD_DECLARED_RIESZ_TOPOLOGY(Name) \
template <> struct DeclaredRieszTopology<models::RieszTopology::Name> { \
static constexpr bool available = true; \
static constexpr RieszTopology value = RieszTopology::Name; \
}
MEAN_FIELD_DECLARED_RIESZ_TOPOLOGY(identity);
@@ -199,14 +196,14 @@ export namespace mean_field::normalization {
#undef MEAN_FIELD_DECLARED_RIESZ_TOPOLOGY
template <models::PhysicalScaleLaw Scale> struct DeclaredPhysicalScale {
static constexpr bool available = false;
static constexpr bool available = false;
static constexpr PhysicalScaleKind value = PhysicalScaleKind::dimensionless;
};
#define MEAN_FIELD_DECLARED_PHYSICAL_SCALE(Name) \
template <> struct DeclaredPhysicalScale<models::PhysicalScaleLaw::Name> { \
static constexpr bool available = true; \
static constexpr PhysicalScaleKind value = PhysicalScaleKind::Name; \
#define MEAN_FIELD_DECLARED_PHYSICAL_SCALE(Name) \
template <> struct DeclaredPhysicalScale<models::PhysicalScaleLaw::Name> { \
static constexpr bool available = true; \
static constexpr PhysicalScaleKind value = PhysicalScaleKind::Name; \
}
MEAN_FIELD_DECLARED_PHYSICAL_SCALE(dimensionless);
@@ -223,9 +220,8 @@ export namespace mean_field::normalization {
#undef MEAN_FIELD_DECLARED_PHYSICAL_SCALE
template <typename Declaration, typename = void>
struct CompileDeclaredPhysicalRieszCoordinate {
using Method = UnsupportedPhysicalRieszCoordinate;
template <typename Declaration, typename = void> struct CompileDeclaredPhysicalRieszCoordinate {
using Method = UnsupportedPhysicalRieszCoordinate;
static constexpr bool registered = false;
};
@@ -246,11 +242,11 @@ export namespace mean_field::normalization {
static constexpr models::PhysicalScaleLaw declaredScale =
static_cast<models::PhysicalScaleLaw>(Declaration::scale);
using Topology = DeclaredRieszTopology<declaredTopology>;
using Scale = DeclaredPhysicalScale<declaredScale>;
using Scale = DeclaredPhysicalScale<declaredScale>;
public:
static constexpr bool registered = static_cast<bool>(Declaration::available) &&
Topology::available && Scale::available;
static constexpr bool registered =
static_cast<bool>(Declaration::available) && Topology::available && Scale::available;
using Method = std::conditional_t<
registered,
PhysicalRieszCoordinate<Topology::value, Scale::value>,
@@ -259,7 +255,7 @@ export namespace mean_field::normalization {
template <typename Generated, CoordinateKind Kind, typename = void>
struct DeclaredGeneratedPhysicalRieszCoordinate {
using Method = UnsupportedPhysicalRieszCoordinate;
using Method = UnsupportedPhysicalRieszCoordinate;
static constexpr bool registered = false;
};
@@ -271,9 +267,8 @@ export namespace mean_field::normalization {
typename Generated::SpecificationType,
typename models::SpecificationContribution<
typename Generated::SpecificationType>::Normalization::Value>>
: CompileDeclaredPhysicalRieszCoordinate<
typename models::SpecificationContribution<
typename Generated::SpecificationType>::Normalization::Value> { };
: CompileDeclaredPhysicalRieszCoordinate<typename models::SpecificationContribution<
typename Generated::SpecificationType>::Normalization::Value> { };
template <typename Generated>
struct DeclaredGeneratedPhysicalRieszCoordinate<
@@ -283,12 +278,10 @@ export namespace mean_field::normalization {
typename Generated::SpecificationType,
typename models::SpecificationContribution<
typename Generated::SpecificationType>::Normalization::Residual>>
: CompileDeclaredPhysicalRieszCoordinate<
typename models::SpecificationContribution<
typename Generated::SpecificationType>::Normalization::Residual> { };
: CompileDeclaredPhysicalRieszCoordinate<typename models::SpecificationContribution<
typename Generated::SpecificationType>::Normalization::Residual> { };
template <typename GeneratedValues, typename GeneratedResiduals>
struct GeneratedPhysicalRieszCoverage {
template <typename GeneratedValues, typename GeneratedResiduals> struct GeneratedPhysicalRieszCoverage {
static constexpr bool complete = false;
};
@@ -297,16 +290,12 @@ export namespace mean_field::normalization {
models::ModelTypeList<GeneratedValues...>,
models::ModelTypeList<GeneratedResiduals...>> {
static constexpr bool complete =
(DeclaredGeneratedPhysicalRieszCoordinate<
GeneratedValues,
CoordinateKind::value>::registered && ...) &&
(DeclaredGeneratedPhysicalRieszCoordinate<
GeneratedResiduals,
CoordinateKind::residual>::registered && ...);
(DeclaredGeneratedPhysicalRieszCoordinate<GeneratedValues, CoordinateKind::value>::registered && ...) &&
(DeclaredGeneratedPhysicalRieszCoordinate<GeneratedResiduals, CoordinateKind::residual>::registered &&
...);
};
template <typename Specification, typename = void>
struct SpecificationPhysicalRieszCoverage {
template <typename Specification, typename = void> struct SpecificationPhysicalRieszCoverage {
static constexpr bool complete = false;
};
@@ -355,29 +344,17 @@ export namespace mean_field::normalization {
* adapter can consult the same authority without importing one another.
*/
template <typename Candidate>
concept PhysicalRieszCoreRuntime =
requires(const std::remove_cvref_t<Candidate> &core) {
{
core.GetGravityContext().GetDensityMap()
} -> std::same_as<const field::FieldDofMap &>;
{
core.GetGravityContext().GetGravityGradientMap()
} -> std::same_as<const field::FieldDofMap &>;
{
core.GetGravityContext().GetGravityPotentialMap()
} -> std::same_as<const field::FieldDofMap &>;
{
core.GetHydrostaticOperator().GetEnthalpyMap()
} -> std::same_as<const field::FieldDofMap &>;
{
core.GetDomainDeformation().parameterCount()
} -> std::same_as<int>;
};
concept PhysicalRieszCoreRuntime = requires(const std::remove_cvref_t<Candidate> &core) {
{ core.GetGravityContext().GetDensityMap() } -> std::same_as<const field::FieldDofMap &>;
{ core.GetGravityContext().GetGravityGradientMap() } -> std::same_as<const field::FieldDofMap &>;
{ core.GetGravityContext().GetGravityPotentialMap() } -> std::same_as<const field::FieldDofMap &>;
{ core.GetHydrostaticOperator().GetEnthalpyMap() } -> std::same_as<const field::FieldDofMap &>;
{ core.GetDomainDeformation().parameterCount() } -> std::same_as<int>;
};
namespace detail {
template <typename Generated, CoordinateKind Kind>
using GeneratedPhysicalRieszMethod =
typename DeclaredGeneratedPhysicalRieszCoordinate<Generated, Kind>::Method;
using GeneratedPhysicalRieszMethod = typename DeclaredGeneratedPhysicalRieszCoordinate<Generated, Kind>::Method;
template <typename Generated, CoordinateKind Kind, typename = void>
struct GeneratedPhysicalRieszRuntimeCoordinate : std::false_type { };
@@ -389,8 +366,7 @@ export namespace mean_field::normalization {
std::void_t<decltype(GeneratedPhysicalRieszMethod<Generated, Kind>::topology)>>
: std::bool_constant<
DeclaredGeneratedPhysicalRieszCoordinate<Generated, Kind>::registered &&
GeneratedPhysicalRieszMethod<Generated, Kind>::topology ==
RieszTopology::global_scalar> { };
GeneratedPhysicalRieszMethod<Generated, Kind>::topology == RieszTopology::global_scalar> { };
template <typename Specification, typename = void>
struct SpecificationPhysicalRieszRuntimeCoverage : std::false_type { };
@@ -420,21 +396,18 @@ export namespace mean_field::normalization {
struct SpecificationSetPhysicalRieszRuntimeCoverage : std::false_type { };
template <models::ModelSpecification... Specifications>
struct SpecificationSetPhysicalRieszRuntimeCoverage<
models::detail::SpecificationSetStorage<Specifications...>>
: std::bool_constant<
(SpecificationPhysicalRieszRuntimeCoverage<Specifications>::value && ...)> { };
struct SpecificationSetPhysicalRieszRuntimeCoverage<models::detail::SpecificationSetStorage<Specifications...>>
: std::bool_constant<(SpecificationPhysicalRieszRuntimeCoverage<Specifications>::value && ...)> { };
} // namespace detail
template <typename Specification>
concept CompleteGeneratedPhysicalRieszRuntimeNormalizationFor =
detail::SpecificationPhysicalRieszRuntimeCoverage<
std::remove_cvref_t<Specification>>::value;
detail::SpecificationPhysicalRieszRuntimeCoverage<std::remove_cvref_t<Specification>>::value;
#define MEAN_FIELD_PHYSICAL_RIESZ_TRAIT(BlockType, TopologyValue, ScaleValue) \
template <> struct PhysicalRieszBlockTraits<BlockType> { \
using Method = PhysicalRieszCoordinate<RieszTopology::TopologyValue, PhysicalScaleKind::ScaleValue>; \
static constexpr bool registered = true; \
#define MEAN_FIELD_PHYSICAL_RIESZ_TRAIT(BlockType, TopologyValue, ScaleValue) \
template <> struct PhysicalRieszBlockTraits<BlockType> { \
using Method = PhysicalRieszCoordinate<RieszTopology::TopologyValue, PhysicalScaleKind::ScaleValue>; \
static constexpr bool registered = true; \
}
MEAN_FIELD_PHYSICAL_RIESZ_TRAIT(
@@ -490,12 +463,9 @@ export namespace mean_field::normalization {
);
#undef MEAN_FIELD_PHYSICAL_RIESZ_TRAIT
template <typename Block>
[[nodiscard]] double physicalScale(
const StellarCharacteristicScales &scales
) {
template <typename Block> [[nodiscard]] double physicalScale(const StellarCharacteristicScales &scales) {
static_assert(PhysicalRieszBlockTraits<Block>::registered, "The block has no Physical Riesz normalization.");
using Method = typename PhysicalRieszBlockTraits<Block>::Method;
using Method = typename PhysicalRieszBlockTraits<Block>::Method;
constexpr PhysicalScaleKind scale = Method::scale;
if constexpr (scale == PhysicalScaleKind::dimensionless) {
return 1.0;
@@ -527,9 +497,7 @@ export namespace mean_field::normalization {
template <typename Values, typename Residuals> struct MakePhysicalRieszPlan;
template <typename... Values, typename... Residuals>
struct MakePhysicalRieszPlan<
utils::blocks::type_list<Values...>,
utils::blocks::type_list<Residuals...>> {
struct MakePhysicalRieszPlan<utils::blocks::type_list<Values...>, utils::blocks::type_list<Residuals...>> {
using Type = NormalizationPlan<
CoordinateComponent<
CoordinateKind::value,
@@ -544,9 +512,8 @@ export namespace mean_field::normalization {
template <typename Form>
requires utils::blocks::block_form_is_valid_v<Form>
using PhysicalRieszNormalizationPlanFor = typename detail::MakePhysicalRieszPlan<
typename Form::value_blocks,
typename Form::residual_blocks>::Type;
using PhysicalRieszNormalizationPlanFor =
typename detail::MakePhysicalRieszPlan<typename Form::value_blocks, typename Form::residual_blocks>::Type;
/*
* Public compile-time extension point for a normalization prescription.
@@ -557,11 +524,10 @@ export namespace mean_field::normalization {
* actually prepare.
*/
template <typename Prescription, typename Form> struct NormalizationCompilation {
using Plan = NormalizationPlan<>;
using Plan = NormalizationPlan<>;
static constexpr bool registered = false;
template <typename PhysicalCore, typename SpecificationTypes>
static constexpr bool runtimeAvailableFor = false;
template <typename PhysicalCore, typename SpecificationTypes> static constexpr bool runtimeAvailableFor = false;
};
/* Astronomy/numerics-facing package for a policy which prepares one
@@ -571,7 +537,7 @@ export namespace mean_field::normalization {
template <NormalizationPrescription Prescription, typename Form>
requires utils::blocks::block_form_is_valid_v<Form>
struct RuntimePreparedNormalizationCompilation {
using Plan = RuntimePreparedNormalizationPlanFor<Prescription, Form>;
using Plan = RuntimePreparedNormalizationPlanFor<Prescription, Form>;
static constexpr bool registered = CompleteNormalizationFor<Plan, Form>;
template <typename PhysicalCore, typename SpecificationTypes>
@@ -581,7 +547,7 @@ export namespace mean_field::normalization {
template <typename Form>
requires utils::blocks::block_form_is_valid_v<Form>
struct NormalizationCompilation<Unnormalized, Form> {
using Plan = IdentityNormalizationPlanFor<Form>;
using Plan = IdentityNormalizationPlanFor<Form>;
static constexpr bool registered = CompleteNormalizationFor<Plan, Form>;
template <typename PhysicalCore, typename SpecificationTypes>
@@ -591,21 +557,18 @@ export namespace mean_field::normalization {
template <RieszGeometryPolicy Geometry, ReferenceScalePolicy ScaleSource, typename Form>
requires utils::blocks::block_form_is_valid_v<Form>
struct NormalizationCompilation<PhysicalRieszDiagonal<Geometry, ScaleSource>, Form> {
using Plan = PhysicalRieszNormalizationPlanFor<Form>;
using Plan = PhysicalRieszNormalizationPlanFor<Form>;
static constexpr bool registered = CompleteNormalizationFor<Plan, Form>;
template <typename PhysicalCore, typename SpecificationTypes>
static constexpr bool runtimeAvailableFor =
registered &&
PhysicalRieszCoreRuntime<std::remove_cvref_t<PhysicalCore>> &&
detail::SpecificationSetPhysicalRieszRuntimeCoverage<
std::remove_cvref_t<SpecificationTypes>>::value;
registered && PhysicalRieszCoreRuntime<std::remove_cvref_t<PhysicalCore>> &&
detail::SpecificationSetPhysicalRieszRuntimeCoverage<std::remove_cvref_t<SpecificationTypes>>::value;
};
namespace detail {
template <typename Prescription, typename Form, typename = void>
struct NormalizationCompilationAudit {
using Plan = NormalizationPlan<>;
template <typename Prescription, typename Form, typename = void> struct NormalizationCompilationAudit {
using Plan = NormalizationPlan<>;
static constexpr bool registered = false;
};
@@ -616,34 +579,25 @@ export namespace mean_field::normalization {
Prescription,
Form,
std::void_t<
typename NormalizationCompilation<
std::remove_cvref_t<Prescription>,
std::remove_cvref_t<Form>>::Plan,
decltype(std::bool_constant<static_cast<bool>(
NormalizationCompilation<
std::remove_cvref_t<Prescription>,
std::remove_cvref_t<Form>>::registered)>{})>> {
using Compilation = NormalizationCompilation<
std::remove_cvref_t<Prescription>,
std::remove_cvref_t<Form>>;
using Plan = typename Compilation::Plan;
typename NormalizationCompilation<std::remove_cvref_t<Prescription>, std::remove_cvref_t<Form>>::Plan,
decltype(std::bool_constant<static_cast<bool>(NormalizationCompilation<
std::remove_cvref_t<Prescription>,
std::remove_cvref_t<Form>>::registered)>{})>> {
using Compilation = NormalizationCompilation<std::remove_cvref_t<Prescription>, std::remove_cvref_t<Form>>;
using Plan = typename Compilation::Plan;
static constexpr bool registered =
static_cast<bool>(Compilation::registered) &&
CompleteNormalizationFor<Plan, std::remove_cvref_t<Form>>;
static_cast<bool>(Compilation::registered) && CompleteNormalizationFor<Plan, std::remove_cvref_t<Form>>;
};
} // namespace detail
template <NormalizationPrescription Prescription, typename Form>
using NormalizationPlanFor = typename detail::NormalizationCompilationAudit<
std::remove_cvref_t<Prescription>,
Form>::Plan;
using NormalizationPlanFor =
typename detail::NormalizationCompilationAudit<std::remove_cvref_t<Prescription>, Form>::Plan;
template <typename Prescription, typename Form>
concept CompilableNormalizationFor =
detail::NormalizationCompilationAudit<
std::remove_cvref_t<Prescription>,
std::remove_cvref_t<Form>>::registered;
detail::NormalizationCompilationAudit<std::remove_cvref_t<Prescription>, std::remove_cvref_t<Form>>::registered;
/* The public runtime-preparation adapter is intentionally narrower than
* an arbitrary complete plan: every coordinate must name the exact policy
@@ -654,16 +608,10 @@ export namespace mean_field::normalization {
concept RuntimePreparedNormalizationFor =
NormalizationPrescription<std::remove_cvref_t<Prescription>> &&
utils::blocks::block_form_is_valid_v<std::remove_cvref_t<Form>> &&
CompilableNormalizationFor<
std::remove_cvref_t<Prescription>,
std::remove_cvref_t<Form>> &&
CompilableNormalizationFor<std::remove_cvref_t<Prescription>, std::remove_cvref_t<Form>> &&
std::same_as<
NormalizationPlanFor<
std::remove_cvref_t<Prescription>,
std::remove_cvref_t<Form>>,
RuntimePreparedNormalizationPlanFor<
std::remove_cvref_t<Prescription>,
std::remove_cvref_t<Form>>>;
NormalizationPlanFor<std::remove_cvref_t<Prescription>, std::remove_cvref_t<Form>>,
RuntimePreparedNormalizationPlanFor<std::remove_cvref_t<Prescription>, std::remove_cvref_t<Form>>>;
namespace detail {
template <
@@ -674,35 +622,22 @@ export namespace mean_field::normalization {
typename = void>
struct StellarNormalizationRuntimeAudit : std::false_type { };
template <
typename Prescription,
typename Form,
typename PhysicalCore,
typename SpecificationTypes>
template <typename Prescription, typename Form, typename PhysicalCore, typename SpecificationTypes>
struct StellarNormalizationRuntimeAudit<
Prescription,
Form,
PhysicalCore,
SpecificationTypes,
std::void_t<
std::enable_if_t<NormalizationCompilationAudit<
Prescription,
Form>::registered>,
decltype(std::bool_constant<static_cast<bool>(
NormalizationCompilation<
Prescription,
Form>::template runtimeAvailableFor<
PhysicalCore,
SpecificationTypes>)>{})>>
std::enable_if_t<NormalizationCompilationAudit<Prescription, Form>::registered>,
decltype(std::bool_constant<
static_cast<bool>(NormalizationCompilation<Prescription, Form>::
template runtimeAvailableFor<PhysicalCore, SpecificationTypes>)>{})>>
: std::bool_constant<
(std::same_as<Prescription, Unnormalized> ||
PhysicalRieszDiagonalPrescription<Prescription> ||
(std::same_as<Prescription, Unnormalized> || PhysicalRieszDiagonalPrescription<Prescription> ||
RuntimePreparedNormalizationFor<Prescription, Form>) &&
static_cast<bool>(NormalizationCompilation<
Prescription,
Form>::template runtimeAvailableFor<
PhysicalCore,
SpecificationTypes>)> { };
static_cast<bool>(NormalizationCompilation<Prescription, Form>::
template runtimeAvailableFor<PhysicalCore, SpecificationTypes>)> { };
} // namespace detail
/*
@@ -714,15 +649,10 @@ export namespace mean_field::normalization {
* assembly and global-scalar runtime preparation for every generated
* coordinate in the specification pack.
*/
template <
typename Prescription,
typename Form,
typename PhysicalCore,
typename SpecificationTypes>
concept StellarNormalizationRuntimeAvailableFor =
detail::StellarNormalizationRuntimeAudit<
std::remove_cvref_t<Prescription>,
std::remove_cvref_t<Form>,
std::remove_cvref_t<PhysicalCore>,
std::remove_cvref_t<SpecificationTypes>>::value;
template <typename Prescription, typename Form, typename PhysicalCore, typename SpecificationTypes>
concept StellarNormalizationRuntimeAvailableFor = detail::StellarNormalizationRuntimeAudit<
std::remove_cvref_t<Prescription>,
std::remove_cvref_t<Form>,
std::remove_cvref_t<PhysicalCore>,
std::remove_cvref_t<SpecificationTypes>>::value;
} // namespace mean_field::normalization

View File

@@ -11,10 +11,7 @@ export namespace mean_field::normalization {
struct NormalizationPrescriptionTag { };
template <typename Candidate>
concept NormalizationPrescription =
std::derived_from<
std::remove_cvref_t<Candidate>,
NormalizationPrescriptionTag>;
concept NormalizationPrescription = std::derived_from<std::remove_cvref_t<Candidate>, NormalizationPrescriptionTag>;
enum class CoordinateKind { value, residual };
@@ -50,44 +47,36 @@ export namespace mean_field::normalization {
* numerical value of that factor. The owner type prevents one policy from
* silently presenting another policy's runtime map as its own plan.
*/
template <NormalizationPrescription Prescription>
struct RuntimePreparedCoordinate final {
template <NormalizationPrescription Prescription> struct RuntimePreparedCoordinate final {
using PrescriptionType = std::remove_cvref_t<Prescription>;
};
template <RieszTopology Topology, PhysicalScaleKind Scale> struct PhysicalRieszCoordinate final {
static constexpr RieszTopology topology = Topology;
static constexpr PhysicalScaleKind scale = Scale;
static constexpr RieszTopology topology = Topology;
static constexpr PhysicalScaleKind scale = Scale;
};
struct UnsupportedPhysicalRieszCoordinate final { };
template <typename Block> struct PhysicalRieszBlockTraits {
using Method = UnsupportedPhysicalRieszCoordinate;
static constexpr bool registered = false;
using Method = UnsupportedPhysicalRieszCoordinate;
static constexpr bool registered = false;
};
template <CoordinateKind Kind, typename BlockList, typename MethodType>
struct CoordinateComponent final {
template <CoordinateKind Kind, typename BlockList, typename MethodType> 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<>>;
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 <typename Candidate> struct IsTypeList : std::false_type { };
template <typename... Types>
struct IsTypeList<utils::blocks::type_list<Types...>> : std::true_type { };
template <typename... Types> struct IsTypeList<utils::blocks::type_list<Types...>> : std::true_type { };
template <typename List, typename Base> struct IsUniqueDerivedBlockList : std::false_type { };
@@ -102,8 +91,7 @@ export namespace mean_field::normalization {
template <> struct IsCoordinateMethod<IdentityCoordinate> : std::true_type { };
template <NormalizationPrescription Prescription>
struct IsCoordinateMethod<RuntimePreparedCoordinate<Prescription>>
: std::true_type { };
struct IsCoordinateMethod<RuntimePreparedCoordinate<Prescription>> : std::true_type { };
template <RieszTopology Topology, PhysicalScaleKind Scale>
struct IsCoordinateMethod<PhysicalRieszCoordinate<Topology, Scale>> : std::true_type { };
@@ -121,10 +109,9 @@ export namespace mean_field::normalization {
template <RieszTopology Topology, PhysicalScaleKind Scale, typename Block>
struct MethodSupportsBlock<PhysicalRieszCoordinate<Topology, Scale>, Block>
: std::bool_constant<
PhysicalRieszBlockTraits<Block>::registered &&
std::same_as<
typename PhysicalRieszBlockTraits<Block>::Method,
PhysicalRieszCoordinate<Topology, Scale>>> { };
PhysicalRieszBlockTraits<Block>::registered && std::same_as<
typename PhysicalRieszBlockTraits<Block>::Method,
PhysicalRieszCoordinate<Topology, Scale>>> { };
template <typename Method, typename List> struct MethodSupportsEveryBlock : std::false_type { };
@@ -166,8 +153,7 @@ export namespace mean_field::normalization {
}();
static constexpr bool hasCoherentCoordinateLists = [] {
if constexpr (!hasValidKind || !IsTypeList<ValueBlocks>::value ||
!IsTypeList<ResidualBlocks>::value) {
if constexpr (!hasValidKind || !IsTypeList<ValueBlocks>::value || !IsTypeList<ResidualBlocks>::value) {
return false;
} else if constexpr (Candidate::kind == CoordinateKind::value) {
return std::same_as<ValueBlocks, Blocks> &&
@@ -182,8 +168,7 @@ export namespace mean_field::normalization {
static constexpr bool valid = hasValidKind && IsTypeList<Blocks>::value &&
IsCoordinateMethod<Method>::value && hasValidBlockList &&
hasCoherentCoordinateLists &&
MethodSupportsEveryBlock<Method, Blocks>::value;
hasCoherentCoordinateLists && MethodSupportsEveryBlock<Method, Blocks>::value;
};
template <typename... Lists> struct Concatenate;
@@ -205,23 +190,18 @@ export namespace mean_field::normalization {
template <typename List, typename Type> struct Append;
template <typename... Types, typename Appended>
struct Append<utils::blocks::type_list<Types...>, Appended> {
template <typename... Types, typename Appended> struct Append<utils::blocks::type_list<Types...>, Appended> {
using Type = utils::blocks::type_list<Types..., Appended>;
};
template <typename List, typename Type> using AppendT = typename Append<List, Type>::Type;
template <typename List, typename Type>
using AppendUniqueT = std::conditional_t<
utils::blocks::contains_type_v<Type, List>,
List,
AppendT<List, Type>>;
using AppendUniqueT = std::conditional_t<utils::blocks::contains_type_v<Type, List>, List, AppendT<List, Type>>;
template <typename Source, typename Excluded> struct ListDifference;
template <typename Excluded>
struct ListDifference<utils::blocks::type_list<>, Excluded> {
template <typename Excluded> struct ListDifference<utils::blocks::type_list<>, Excluded> {
using Type = utils::blocks::type_list<>;
};
@@ -260,10 +240,7 @@ export namespace mean_field::normalization {
};
template <typename List>
using RepeatedTypesT = typename CollectRepeatedTypes<
List,
List,
utils::blocks::type_list<>>::Type;
using RepeatedTypesT = typename CollectRepeatedTypes<List, List, utils::blocks::type_list<>>::Type;
template <typename Candidate, typename = void> struct PlanTraits {
static constexpr bool valid = false;
@@ -274,23 +251,20 @@ export namespace mean_field::normalization {
concept NormalizationComponent = detail::ComponentTraits<std::remove_cvref_t<Candidate>>::valid;
template <typename... Components> struct NormalizationPlan final {
using ComponentTypes = utils::blocks::type_list<Components...>;
using ValueBlocks = detail::ConcatenateT<typename Components::ValueBlocks...>;
using ResidualBlocks = detail::ConcatenateT<typename Components::ResidualBlocks...>;
using ComponentTypes = utils::blocks::type_list<Components...>;
using ValueBlocks = detail::ConcatenateT<typename Components::ValueBlocks...>;
using ResidualBlocks = detail::ConcatenateT<typename Components::ResidualBlocks...>;
};
namespace detail {
template <typename... Components>
struct PlanTraits<NormalizationPlan<Components...>> {
template <typename... Components> struct PlanTraits<NormalizationPlan<Components...>> {
static constexpr bool valid = (ComponentTraits<Components>::valid && ...);
};
template <typename Values, typename Residuals> struct MakeIdentityPlan;
template <typename... Values, typename... Residuals>
struct MakeIdentityPlan<
utils::blocks::type_list<Values...>,
utils::blocks::type_list<Residuals...>> {
struct MakeIdentityPlan<utils::blocks::type_list<Values...>, utils::blocks::type_list<Residuals...>> {
using Type = NormalizationPlan<
CoordinateComponent<CoordinateKind::value, utils::blocks::type_list<Values>, IdentityCoordinate>...,
CoordinateComponent<
@@ -299,30 +273,18 @@ export namespace mean_field::normalization {
IdentityCoordinate>...>;
};
template <
NormalizationPrescription Prescription,
typename Values,
typename Residuals>
template <NormalizationPrescription Prescription, typename Values, typename Residuals>
struct MakeRuntimePreparedPlan;
template <
NormalizationPrescription Prescription,
typename... Values,
typename... Residuals>
template <NormalizationPrescription Prescription, typename... Values, typename... Residuals>
struct MakeRuntimePreparedPlan<
Prescription,
utils::blocks::type_list<Values...>,
utils::blocks::type_list<Residuals...>> {
using Method = RuntimePreparedCoordinate<Prescription>;
using Type = NormalizationPlan<
CoordinateComponent<
CoordinateKind::value,
utils::blocks::type_list<Values>,
Method>...,
CoordinateComponent<
CoordinateKind::residual,
utils::blocks::type_list<Residuals>,
Method>...>;
using Type = NormalizationPlan<
CoordinateComponent<CoordinateKind::value, utils::blocks::type_list<Values>, Method>...,
CoordinateComponent<CoordinateKind::residual, utils::blocks::type_list<Residuals>, Method>...>;
};
} // namespace detail
@@ -331,46 +293,43 @@ export namespace mean_field::normalization {
template <typename Form>
requires utils::blocks::block_form_is_valid_v<Form>
using IdentityNormalizationPlanFor = typename detail::MakeIdentityPlan<
typename Form::value_blocks,
typename Form::residual_blocks>::Type;
using IdentityNormalizationPlanFor =
typename detail::MakeIdentityPlan<typename Form::value_blocks, typename Form::residual_blocks>::Type;
template <NormalizationPrescription Prescription, typename Form>
requires utils::blocks::block_form_is_valid_v<Form>
using RuntimePreparedNormalizationPlanFor =
typename detail::MakeRuntimePreparedPlan<
std::remove_cvref_t<Prescription>,
typename Form::value_blocks,
typename Form::residual_blocks>::Type;
using RuntimePreparedNormalizationPlanFor = typename detail::MakeRuntimePreparedPlan<
std::remove_cvref_t<Prescription>,
typename Form::value_blocks,
typename Form::residual_blocks>::Type;
template <typename Form, typename Plan>
requires utils::blocks::block_form_is_valid_v<Form>
struct NormalizationCoverage final {
using DeclaredValueBlocks = typename Plan::ValueBlocks;
using DeclaredValueBlocks = typename Plan::ValueBlocks;
using DeclaredResidualBlocks = typename Plan::ResidualBlocks;
using MissingValueBlocks = detail::ListDifferenceT<typename Form::value_blocks, DeclaredValueBlocks>;
using UnexpectedValueBlocks = detail::ListDifferenceT<DeclaredValueBlocks, typename Form::value_blocks>;
using RepeatedValueBlocks = detail::RepeatedTypesT<DeclaredValueBlocks>;
using MissingValueBlocks = detail::ListDifferenceT<typename Form::value_blocks, DeclaredValueBlocks>;
using UnexpectedValueBlocks = detail::ListDifferenceT<DeclaredValueBlocks, typename Form::value_blocks>;
using RepeatedValueBlocks = detail::RepeatedTypesT<DeclaredValueBlocks>;
using MissingResidualBlocks = detail::ListDifferenceT<typename Form::residual_blocks, DeclaredResidualBlocks>;
using UnexpectedResidualBlocks = detail::ListDifferenceT<DeclaredResidualBlocks, typename Form::residual_blocks>;
using RepeatedResidualBlocks = detail::RepeatedTypesT<DeclaredResidualBlocks>;
using MissingResidualBlocks = detail::ListDifferenceT<typename Form::residual_blocks, DeclaredResidualBlocks>;
using UnexpectedResidualBlocks =
detail::ListDifferenceT<DeclaredResidualBlocks, typename Form::residual_blocks>;
using RepeatedResidualBlocks = detail::RepeatedTypesT<DeclaredResidualBlocks>;
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 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;
hasEveryResidualBlock && hasOnlyResidualBlocks && hasUniqueResidualOwners;
};
template <typename Plan, typename Form>
concept CompleteNormalizationFor = utils::blocks::block_form_is_valid_v<Form> &&
NormalizationPlanType<Plan> &&
concept CompleteNormalizationFor = utils::blocks::block_form_is_valid_v<Form> && NormalizationPlanType<Plan> &&
NormalizationCoverage<Form, std::remove_cvref_t<Plan>>::complete;
} // namespace mean_field::normalization

View File

@@ -2,6 +2,7 @@ module;
#include <concepts>
#include <cstdint>
#include <expected>
#include <memory>
#include <span>
#include <stdexcept>
@@ -61,7 +62,7 @@ namespace mean_field::normalization::detail {
const field::ScalarBoundaryDofMap &surfaceMap
) {
mfem::Array<int> marker(finiteElements.mesh->bdr_attributes.Max());
marker = 0;
marker = 0;
constexpr int attribute = DomainSchema::template boundary_attribute<utils::domain::StellarSurface>();
if (attribute <= 0 || attribute > marker.Size()) {
throw std::invalid_argument("The reference mesh does not contain the stellar-surface boundary.");
@@ -107,25 +108,19 @@ export namespace mean_field::normalization {
* this layer never names a concrete integral or phase constraint.
*/
namespace detail {
template <typename Block>
using PhysicalRieszMethodFor = typename PhysicalRieszBlockTraits<Block>::Method;
template <typename Block> using PhysicalRieszMethodFor = typename PhysicalRieszBlockTraits<Block>::Method;
template <typename Block, typename = void>
struct IsGlobalGeneratedValueNormalization : std::false_type { };
template <typename Block, typename = void> struct IsGlobalGeneratedValueNormalization : std::false_type { };
template <typename Generated>
struct IsGlobalGeneratedValueNormalization<
utils::blocks::generated_value_block<Generated>,
std::void_t<
decltype(PhysicalRieszMethodFor<
utils::blocks::generated_value_block<Generated>>::topology),
decltype(PhysicalRieszMethodFor<
utils::blocks::generated_value_block<Generated>>::scale)>>
decltype(PhysicalRieszMethodFor<utils::blocks::generated_value_block<Generated>>::topology),
decltype(PhysicalRieszMethodFor<utils::blocks::generated_value_block<Generated>>::scale)>>
: std::bool_constant<
PhysicalRieszBlockTraits<
utils::blocks::generated_value_block<Generated>>::registered &&
PhysicalRieszMethodFor<
utils::blocks::generated_value_block<Generated>>::topology ==
PhysicalRieszBlockTraits<utils::blocks::generated_value_block<Generated>>::registered &&
PhysicalRieszMethodFor<utils::blocks::generated_value_block<Generated>>::topology ==
RieszTopology::global_scalar> { };
template <typename Blocks, typename Specification>
@@ -139,32 +134,26 @@ export namespace mean_field::normalization {
Generated,
Specification,
std::void_t<typename Generated::SpecificationType>>
: std::bool_constant<
std::same_as<typename Generated::SpecificationType, Specification>> { };
: std::bool_constant<std::same_as<typename Generated::SpecificationType, Specification>> { };
template <typename Specification, typename... Generated>
struct GeneratedValueBlocksBelongToSpecification<
utils::blocks::type_list<utils::blocks::generated_value_block<Generated>...>,
Specification>
: std::bool_constant<
(GeneratedCoordinateBelongsToSpecification<Generated, Specification>::value && ...)> { };
: std::bool_constant<(GeneratedCoordinateBelongsToSpecification<Generated, Specification>::value && ...)> {
};
template <typename Block, typename = void>
struct IsGlobalGeneratedResidualNormalization : std::false_type { };
template <typename Block, typename = void> struct IsGlobalGeneratedResidualNormalization : std::false_type { };
template <typename Generated>
struct IsGlobalGeneratedResidualNormalization<
utils::blocks::generated_residual_block<Generated>,
std::void_t<
decltype(PhysicalRieszMethodFor<
utils::blocks::generated_residual_block<Generated>>::topology),
decltype(PhysicalRieszMethodFor<
utils::blocks::generated_residual_block<Generated>>::scale)>>
decltype(PhysicalRieszMethodFor<utils::blocks::generated_residual_block<Generated>>::topology),
decltype(PhysicalRieszMethodFor<utils::blocks::generated_residual_block<Generated>>::scale)>>
: std::bool_constant<
PhysicalRieszBlockTraits<
utils::blocks::generated_residual_block<Generated>>::registered &&
PhysicalRieszMethodFor<
utils::blocks::generated_residual_block<Generated>>::topology ==
PhysicalRieszBlockTraits<utils::blocks::generated_residual_block<Generated>>::registered &&
PhysicalRieszMethodFor<utils::blocks::generated_residual_block<Generated>>::topology ==
RieszTopology::global_scalar> { };
template <typename Blocks, typename Specification>
@@ -174,14 +163,13 @@ export namespace mean_field::normalization {
struct GeneratedResidualBlocksBelongToSpecification<
utils::blocks::type_list<utils::blocks::generated_residual_block<Generated>...>,
Specification>
: std::bool_constant<
(GeneratedCoordinateBelongsToSpecification<Generated, Specification>::value && ...)> { };
: std::bool_constant<(GeneratedCoordinateBelongsToSpecification<Generated, Specification>::value && ...)> {
};
template <typename Blocks> struct PrepareGeneratedValueNormalizations {
static constexpr bool registered = false;
static constexpr bool registered = false;
template <typename Form>
static constexpr bool completeFor = false;
template <typename Form> static constexpr bool completeFor = false;
template <typename Form>
static void Apply(
@@ -192,14 +180,12 @@ export namespace mean_field::normalization {
}
};
template <typename... Blocks>
struct PrepareGeneratedValueNormalizations<utils::blocks::type_list<Blocks...>> {
static constexpr bool registered =
(IsGlobalGeneratedValueNormalization<Blocks>::value && ...);
template <typename... Blocks> struct PrepareGeneratedValueNormalizations<utils::blocks::type_list<Blocks...>> {
static constexpr bool registered = (IsGlobalGeneratedValueNormalization<Blocks>::value && ...);
template <typename Form>
static constexpr bool completeFor = registered &&
utils::blocks::block_form_is_valid_v<Form> &&
static constexpr bool completeFor =
registered && utils::blocks::block_form_is_valid_v<Form> &&
(utils::blocks::contains_type_v<Blocks, typename Form::value_blocks> && ...);
template <typename Form>
@@ -220,10 +206,9 @@ export namespace mean_field::normalization {
};
template <typename Blocks> struct PrepareGeneratedResidualNormalizations {
static constexpr bool registered = false;
static constexpr bool registered = false;
template <typename Form>
static constexpr bool completeFor = false;
template <typename Form> static constexpr bool completeFor = false;
template <typename Form>
static void Apply(
@@ -236,12 +221,11 @@ export namespace mean_field::normalization {
template <typename... Blocks>
struct PrepareGeneratedResidualNormalizations<utils::blocks::type_list<Blocks...>> {
static constexpr bool registered =
(IsGlobalGeneratedResidualNormalization<Blocks>::value && ...);
static constexpr bool registered = (IsGlobalGeneratedResidualNormalization<Blocks>::value && ...);
template <typename Form>
static constexpr bool completeFor = registered &&
utils::blocks::block_form_is_valid_v<Form> &&
static constexpr bool completeFor =
registered && utils::blocks::block_form_is_valid_v<Form> &&
(utils::blocks::contains_type_v<Blocks, typename Form::residual_blocks> && ...);
template <typename Form>
@@ -261,15 +245,13 @@ export namespace mean_field::normalization {
}
};
template <typename Specification, typename = void>
struct CompileStellarSpecificationNormalization {
using ValuePreparation = PrepareGeneratedValueNormalizations<void>;
using ResidualPreparation = PrepareGeneratedResidualNormalizations<void>;
template <typename Specification, typename = void> struct CompileStellarSpecificationNormalization {
using ValuePreparation = PrepareGeneratedValueNormalizations<void>;
using ResidualPreparation = PrepareGeneratedResidualNormalizations<void>;
static constexpr bool registered = false;
static constexpr bool registered = false;
template <typename Form>
static constexpr bool completeFor = false;
template <typename Form> static constexpr bool completeFor = false;
template <typename Form>
static void Apply(
@@ -277,8 +259,7 @@ export namespace mean_field::normalization {
const StellarCharacteristicScales &
) {
static_assert(
completeFor<Form>,
"The specification has no complete generated-coordinate normalization."
completeFor<Form>, "The specification has no complete generated-coordinate normalization."
);
}
};
@@ -287,32 +268,27 @@ export namespace mean_field::normalization {
struct CompileStellarSpecificationNormalization<
Specification,
std::void_t<
typename operators::StellarEquilibriumSpecificationCompilation<
Specification>::GeneratedValueBlocks,
typename operators::StellarEquilibriumSpecificationCompilation<Specification>::GeneratedValueBlocks,
typename operators::StellarEquilibriumSpecificationCompilation<
Specification>::GeneratedResidualBlocks>> {
using OperatorCompilation =
operators::StellarEquilibriumSpecificationCompilation<Specification>;
using ValuePreparation = PrepareGeneratedValueNormalizations<
typename OperatorCompilation::GeneratedValueBlocks>;
using ResidualPreparation = PrepareGeneratedResidualNormalizations<
typename OperatorCompilation::GeneratedResidualBlocks>;
using OperatorCompilation = operators::StellarEquilibriumSpecificationCompilation<Specification>;
using ValuePreparation =
PrepareGeneratedValueNormalizations<typename OperatorCompilation::GeneratedValueBlocks>;
using ResidualPreparation =
PrepareGeneratedResidualNormalizations<typename OperatorCompilation::GeneratedResidualBlocks>;
static constexpr bool registered = OperatorCompilation::complete &&
models::CompleteGeneratedNormalizationFor<
Specification> &&
models::CompleteGeneratedNormalizationFor<Specification> &&
GeneratedValueBlocksBelongToSpecification<
typename OperatorCompilation::GeneratedValueBlocks,
Specification>::value &&
GeneratedResidualBlocksBelongToSpecification<
typename OperatorCompilation::GeneratedResidualBlocks,
Specification>::value &&
ValuePreparation::registered &&
ResidualPreparation::registered;
ValuePreparation::registered && ResidualPreparation::registered;
template <typename Form>
static constexpr bool completeFor = registered &&
ValuePreparation::template completeFor<Form> &&
static constexpr bool completeFor = registered && ValuePreparation::template completeFor<Form> &&
ResidualPreparation::template completeFor<Form>;
template <typename Form>
@@ -366,9 +342,8 @@ export namespace mean_field::normalization {
Model,
Form,
std::void_t<typename std::remove_cvref_t<Model>::SpecificationTypes>>
: std::bool_constant<
PrepareSpecificationNormalizations<
typename std::remove_cvref_t<Model>::SpecificationTypes>::template completeFor<Form>> { };
: std::bool_constant<PrepareSpecificationNormalizations<
typename std::remove_cvref_t<Model>::SpecificationTypes>::template completeFor<Form>> { };
} // namespace detail
template <typename Specification>
@@ -400,9 +375,7 @@ export namespace mean_field::normalization {
template <typename Model, typename Form>
concept CompleteStellarNormalizationFor =
detail::StellarModelNormalizationCoverage<
std::remove_cvref_t<Model>,
std::remove_cvref_t<Form>>::value;
detail::StellarModelNormalizationCoverage<std::remove_cvref_t<Model>, std::remove_cvref_t<Form>>::value;
/*
* Physical Riesz preparation is an optional capability of a physical
@@ -418,8 +391,7 @@ export namespace mean_field::normalization {
template <typename Problem>
concept PhysicalRieszStellarEquilibriumProblem =
equilibrium::DiscretizedStellarEquilibriumProblem<std::remove_cvref_t<Problem>> &&
requires {
equilibrium::DiscretizedStellarEquilibriumProblem<std::remove_cvref_t<Problem>> && requires {
typename std::remove_cvref_t<Problem>::ModelType;
typename std::remove_cvref_t<Problem>::FormType;
typename std::remove_cvref_t<Problem>::PhysicalCoreType;
@@ -430,8 +402,7 @@ export namespace mean_field::normalization {
typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType,
typename std::remove_cvref_t<Problem>::FormType>;
requires CompleteStellarNormalizationFor<
typename std::remove_cvref_t<Problem>::ModelType,
typename std::remove_cvref_t<Problem>::FormType>;
typename std::remove_cvref_t<Problem>::ModelType, typename std::remove_cvref_t<Problem>::FormType>;
requires StellarNormalizationRuntimeAvailableFor<
typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType,
typename std::remove_cvref_t<Problem>::FormType,
@@ -450,42 +421,36 @@ export namespace mean_field::normalization {
template <PhysicalRieszStellarEquilibriumProblem Problem>
[[nodiscard]] DiagonalNormalization prepareNormalization(const Problem &problem) {
using ProblemType = std::remove_cvref_t<Problem>;
using Form = typename ProblemType::FormType;
using Form = typename ProblemType::FormType;
const fem::FEM &finiteElements = problem.GetDiscretization().finiteElementModel();
const fem::FEM &finiteElements =
equilibrium::detail::StellarEquilibriumProblemFactory::FiniteElementModel(problem);
if (!finiteElements.okay()) {
throw std::invalid_argument("Physical Riesz preparation requires a current finite-element model.");
}
const auto &physical = detail::PhysicalOperator(problem);
const auto &physical = detail::PhysicalOperator(problem);
const auto &gravityContext = physical.GetGravityContext();
const auto &enthalpyMap = physical.GetHydrostaticOperator().GetEnthalpyMap();
const auto scales = deriveStellarCharacteristicScales(
problem.GetNormalizationPrescription(),
problem.GetStellarModel()
);
const auto &enthalpyMap = physical.GetHydrostaticOperator().GetEnthalpyMap();
const auto scales =
deriveStellarCharacteristicScales(problem.GetNormalizationPrescription(), problem.GetStellarModel());
mfem::Array<int> stellarMarker =
utils::domain::make_attribute_marker<utils::domain::Stellar, detail::DomainSchema>(*finiteElements.mesh);
const mfem::Vector densityDiagonal = detail::GatherDiagonal(
detail::AssembleScalarMassDiagonal(*finiteElements.densityFes, &stellarMarker),
gravityContext.GetDensityMap(),
"density"
gravityContext.GetDensityMap(), "density"
);
const mfem::Vector enthalpyDiagonal = detail::GatherDiagonal(
detail::AssembleScalarMassDiagonal(*finiteElements.enthalpyFes, &stellarMarker),
enthalpyMap,
"enthalpy"
detail::AssembleScalarMassDiagonal(*finiteElements.enthalpyFes, &stellarMarker), enthalpyMap, "enthalpy"
);
const mfem::Vector gravityGradientDiagonal = detail::GatherDiagonal(
detail::AssembleHDivMassDiagonal(*finiteElements.gravityFluxFes),
gravityContext.GetGravityGradientMap(),
detail::AssembleHDivMassDiagonal(*finiteElements.gravityFluxFes), gravityContext.GetGravityGradientMap(),
"gravity-gradient"
);
const mfem::Vector gravityPotentialDiagonal = detail::GatherDiagonal(
detail::AssembleScalarMassDiagonal(*finiteElements.gravityPotentialFes),
gravityContext.GetGravityPotentialMap(),
"gravity-potential"
gravityContext.GetGravityPotentialMap(), "gravity-potential"
);
const field::ScalarBoundaryDofMap surfaceMap =
field::make_stellar_surface_scalar_dof_map<detail::DomainSchema>(*finiteElements.surfaceDeformationFes);
@@ -524,13 +489,11 @@ export namespace mean_field::normalization {
);
const mfem::Array<int> &surfaceRows = problem.GetPressureSurfaceRows().reduced_dofs();
builder.template SetHybridResidualBlock<utils::blocks::enthalpy::specific::residual>(
physicalScale<utils::blocks::enthalpy::specific::residual>(scales),
enthalpyDiagonal,
physicalScale<utils::blocks::enthalpy::specific::residual>(scales), enthalpyDiagonal,
std::span<const int>{surfaceRows.GetData(), static_cast<std::size_t>(surfaceRows.Size())}
);
detail::PrepareSpecificationNormalizations<typename ProblemType::ModelType::SpecificationTypes>::Apply(
builder,
scales
builder, scales
);
return std::move(builder).Build();
@@ -548,16 +511,11 @@ export namespace mean_field::normalization {
!std::same_as<
typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType,
Unnormalized> &&
!PhysicalRieszDiagonalPrescription<
typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType> &&
RuntimePreparedNormalizationOperation<Problem>)
[[nodiscard]] DiagonalNormalization prepareNormalization(
const Problem &problem
) {
return prepareStellarNormalization(
problem.GetNormalizationPrescription(),
problem
);
!PhysicalRieszDiagonalPrescription<typename std::remove_cvref_t<Problem>::NormalizationPrescriptionType> &&
RuntimePreparedNormalizationOperation<Problem>
)
[[nodiscard]] DiagonalNormalization prepareNormalization(const Problem &problem) {
return prepareStellarNormalization(problem.GetNormalizationPrescription(), problem);
}
/*
@@ -571,9 +529,7 @@ export namespace mean_field::normalization {
concept NormalizableStellarEquilibriumProblem =
equilibrium::DiscretizedStellarEquilibriumProblem<std::remove_cvref_t<Problem>> &&
requires(const std::remove_cvref_t<Problem> &problem) {
{
prepareNormalization(problem)
} -> std::same_as<DiagonalNormalization>;
{ prepareNormalization(problem) } -> std::same_as<DiagonalNormalization>;
};
struct NormalizedStellarEquilibriumStatistics final {
@@ -591,17 +547,14 @@ export namespace mean_field::normalization {
* implied.
*/
template <typename Candidate, typename Problem>
concept ProblemBoundStellarInverseFor =
NormalizableStellarEquilibriumProblem<std::remove_cvref_t<Problem>> &&
std::derived_from<std::remove_cvref_t<Candidate>, mfem::Solver> &&
requires(const std::remove_cvref_t<Candidate> &inverse) {
{
inverse.GetProblem()
} -> std::same_as<const std::remove_cvref_t<Problem> &>;
{
inverse.IsCurrent()
} -> std::same_as<bool>;
};
concept ProblemBoundStellarInverseFor = NormalizableStellarEquilibriumProblem<std::remove_cvref_t<Problem>> &&
std::derived_from<std::remove_cvref_t<Candidate>, mfem::Solver> &&
requires(const std::remove_cvref_t<Candidate> &inverse) {
{
inverse.GetProblem()
} -> std::same_as<const std::remove_cvref_t<Problem> &>;
{ inverse.IsCurrent() } -> std::same_as<bool>;
};
template <NormalizableStellarEquilibriumProblem Problem, typename PhysicalInverse>
requires ProblemBoundStellarInverseFor<PhysicalInverse, Problem>
@@ -623,11 +576,20 @@ export namespace mean_field::normalization {
using ProblemType = std::remove_cvref_t<Problem>;
public:
using Report = typename ProblemType::Report;
using PreparationResult = typename ProblemType::PreparationResult;
explicit NormalizedStellarEquilibriumOperator(ProblemType &problem)
: mfem::Operator(problem.EquationSize(), problem.StateSize()),
: mfem::Operator(
problem.EquationSize(),
problem.StateSize()
),
m_problem(&problem),
m_normalization(prepareNormalization(problem)),
m_scaledJacobian(problem.GetLinearizationOperator(), m_normalization),
m_scaledJacobian(
problem.GetLinearizationOperator(),
m_normalization
),
m_physicalState(problem.StateSize()),
m_physicalResidual(problem.EquationSize()),
m_normalizedResidual(problem.EquationSize()) {
@@ -646,7 +608,9 @@ export namespace mean_field::normalization {
const mfem::Vector &normalizedState,
const operators::StellarEquilibriumDependencies &dependencies,
const physics::RigidRotation &rotation
) requires(ProblemType::generatedRotationProviderCount == 0) {
)
requires(ProblemType::generatedRotationProviderCount == 0)
{
if (normalizedState.Size() != Width()) {
throw std::invalid_argument("The normalized stellar state has the wrong size.");
}
@@ -662,10 +626,37 @@ export namespace mean_field::normalization {
return report;
}
[[nodiscard]] PreparationResult TryPrepare(
const mfem::Vector &normalizedState,
const operators::StellarEquilibriumDependencies &dependencies,
const physics::RigidRotation &rotation
)
requires(ProblemType::generatedRotationProviderCount == 0)
{
if (normalizedState.Size() != Width()) {
throw std::invalid_argument("The normalized stellar state has the wrong size.");
}
m_isPrepared = false;
m_normalization.DenormalizeState(normalizedState, m_physicalState);
auto result = m_problem->TryPrepare(m_physicalState, dependencies, rotation);
if (!result.has_value()) {
return std::unexpected(result.error());
}
m_problem->BuildResidual(m_physicalResidual);
m_normalization.NormalizeResidual(m_physicalResidual, m_normalizedResidual);
m_physicalPreparationGeneration = m_problem->GetPreparationGeneration();
m_isPrepared = true;
++m_statistics.physicalPreparations;
return result;
}
[[nodiscard]] auto Prepare(
const mfem::Vector &normalizedState,
const operators::StellarEquilibriumDependencies &dependencies
) requires(ProblemType::generatedRotationProviderCount == 1) {
)
requires(ProblemType::generatedRotationProviderCount == 1)
{
if (normalizedState.Size() != Width()) {
throw std::invalid_argument("The normalized stellar state has the wrong size.");
}
@@ -681,6 +672,30 @@ export namespace mean_field::normalization {
return report;
}
[[nodiscard]] PreparationResult TryPrepare(
const mfem::Vector &normalizedState,
const operators::StellarEquilibriumDependencies &dependencies
)
requires(ProblemType::generatedRotationProviderCount == 1)
{
if (normalizedState.Size() != Width()) {
throw std::invalid_argument("The normalized stellar state has the wrong size.");
}
m_isPrepared = false;
m_normalization.DenormalizeState(normalizedState, m_physicalState);
auto result = m_problem->TryPrepare(m_physicalState, dependencies);
if (!result.has_value()) {
return std::unexpected(result.error());
}
m_problem->BuildResidual(m_physicalResidual);
m_normalization.NormalizeResidual(m_physicalResidual, m_normalizedResidual);
m_physicalPreparationGeneration = m_problem->GetPreparationGeneration();
m_isPrepared = true;
++m_statistics.physicalPreparations;
return result;
}
void BuildResidual(mfem::Vector &normalizedResidual) const {
VerifyPrepared();
normalizedResidual = m_normalizedResidual;
@@ -701,8 +716,8 @@ export namespace mean_field::normalization {
void RefreshNormalization() {
DiagonalNormalization refreshed = prepareNormalization(*m_problem);
m_normalization = std::move(refreshed);
m_isPrepared = false;
m_normalization = std::move(refreshed);
m_isPrepared = false;
++m_statistics.normalizationPreparations;
}
@@ -735,8 +750,12 @@ export namespace mean_field::normalization {
}
template <typename PhysicalInverse>
requires ProblemBoundStellarInverseFor<PhysicalInverse, Problem>
[[nodiscard]] NormalizedStellarPreconditioner<Problem, std::remove_cvref_t<PhysicalInverse>>
requires ProblemBoundStellarInverseFor<
PhysicalInverse,
Problem>
[[nodiscard]] NormalizedStellarPreconditioner<
Problem,
std::remove_cvref_t<PhysicalInverse>>
MakeScaledPreconditioner(PhysicalInverse &physicalInverse) const;
[[nodiscard]] bool IsPrepared() const noexcept {
@@ -802,16 +821,15 @@ export namespace mean_field::normalization {
requires ProblemBoundStellarInverseFor<PhysicalInverse, Problem>
class NormalizedStellarPreconditioner final : public mfem::Solver {
private:
using ProblemType = std::remove_cvref_t<Problem>;
using NormalizedOperator = NormalizedStellarEquilibriumOperator<ProblemType>;
using ProblemType = std::remove_cvref_t<Problem>;
using NormalizedOperator = NormalizedStellarEquilibriumOperator<ProblemType>;
using PhysicalInverseType = std::remove_cvref_t<PhysicalInverse>;
[[nodiscard]] static PhysicalInverseType &RequireAssociatedPhysicalInverse(
const NormalizedOperator &normalizedOperator,
PhysicalInverseType &physicalInverse
) {
if (std::addressof(physicalInverse.GetProblem()) !=
std::addressof(normalizedOperator.GetProblem())) {
if (std::addressof(physicalInverse.GetProblem()) != std::addressof(normalizedOperator.GetProblem())) {
throw std::invalid_argument(
"A normalized stellar preconditioner and its physical inverse must belong to the same problem."
);
@@ -832,7 +850,10 @@ export namespace mean_field::normalization {
m_normalizedOperator(&normalizedOperator),
m_physicalInverse(&physicalInverse),
m_scaled(
RequireAssociatedPhysicalInverse(normalizedOperator, physicalInverse),
RequireAssociatedPhysicalInverse(
normalizedOperator,
physicalInverse
),
normalizedOperator.GetPhysicalJacobian(),
normalizedOperator,
normalizedOperator.GetNormalization()
@@ -863,8 +884,7 @@ export namespace mean_field::normalization {
}
[[nodiscard]] bool IsCurrent() const {
return m_normalizedOperator->IsPrepared() &&
m_physicalInverse->IsCurrent();
return m_normalizedOperator->IsPrepared() && m_physicalInverse->IsCurrent();
}
[[nodiscard]] PhysicalInverseType &GetPhysicalInverse() noexcept {
@@ -904,14 +924,15 @@ export namespace mean_field::normalization {
template <NormalizableStellarEquilibriumProblem Problem>
template <typename PhysicalInverse>
requires ProblemBoundStellarInverseFor<PhysicalInverse, Problem>
NormalizedStellarPreconditioner<Problem, std::remove_cvref_t<PhysicalInverse>>
requires ProblemBoundStellarInverseFor<
PhysicalInverse,
Problem>
NormalizedStellarPreconditioner<
Problem,
std::remove_cvref_t<PhysicalInverse>>
NormalizedStellarEquilibriumOperator<Problem>::MakeScaledPreconditioner(PhysicalInverse &physicalInverse) const {
VerifyPrepared();
return NormalizedStellarPreconditioner<Problem, std::remove_cvref_t<PhysicalInverse>>{
*this,
physicalInverse
};
return NormalizedStellarPreconditioner<Problem, std::remove_cvref_t<PhysicalInverse>>{*this, physicalInverse};
}
template <NormalizableStellarEquilibriumProblem Problem>