feat(newton): first newton solver implementation
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
module;
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <mfem.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
export module mean_field:operators.context.gravity_field;
|
||||
export import :fem;
|
||||
@@ -58,6 +60,23 @@ export namespace mean_field::operators::context::gravity_field {
|
||||
}
|
||||
};
|
||||
|
||||
enum class GravityFieldPreparationRejectionReason : std::uint8_t { invalid_mapping, non_finite_arithmetic };
|
||||
|
||||
struct GravityFieldPreparationRejection final {
|
||||
GravityFieldPreparationRejectionReason reason{GravityFieldPreparationRejectionReason::invalid_mapping};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::valid};
|
||||
};
|
||||
|
||||
template <typename Report>
|
||||
using GravityFieldPreparationResult = std::expected<Report, GravityFieldPreparationRejection>;
|
||||
|
||||
[[noreturn]] inline void throwGravityFieldPreparationRejection(const GravityFieldPreparationRejection &rejection) {
|
||||
if (rejection.reason == GravityFieldPreparationRejectionReason::non_finite_arithmetic) {
|
||||
throw std::domain_error("Prepared gravity-field data contained non-finite arithmetic.");
|
||||
}
|
||||
throw std::domain_error("Prepared gravity-field data could not map the candidate geometry.");
|
||||
}
|
||||
|
||||
class GravityFieldGeometryContext {
|
||||
public:
|
||||
GravityFieldGeometryContext(
|
||||
@@ -76,12 +95,24 @@ export namespace mean_field::operators::context::gravity_field {
|
||||
DisplacementRevision displacement_revision
|
||||
);
|
||||
|
||||
[[nodiscard]] GravityFieldPreparationResult<GravityFieldGeometryPreparation> TryPrepare(
|
||||
const mfem::Vector &displacement,
|
||||
DiscretizationRevision discretization_revision,
|
||||
DisplacementRevision displacement_revision
|
||||
);
|
||||
|
||||
GravityFieldGeometryPreparation PreparePrimal(
|
||||
const mfem::Vector &displacement,
|
||||
DiscretizationRevision discretization_revision,
|
||||
DisplacementRevision displacement_revision
|
||||
);
|
||||
|
||||
[[nodiscard]] GravityFieldPreparationResult<GravityFieldGeometryPreparation> TryPreparePrimal(
|
||||
const mfem::Vector &displacement,
|
||||
DiscretizationRevision discretization_revision,
|
||||
DisplacementRevision displacement_revision
|
||||
);
|
||||
|
||||
[[nodiscard]] const PreparedMappedHDivMassOperator &GetMassOperator() const;
|
||||
[[nodiscard]] const PreparedMappedGravitySourceOperator &GetSourceOperator() const;
|
||||
[[nodiscard]] const mfem::Operator &GetDivergenceOperator() const;
|
||||
@@ -95,7 +126,7 @@ export namespace mean_field::operators::context::gravity_field {
|
||||
private:
|
||||
enum class PreparationMode : std::uint8_t { primal, linearization };
|
||||
|
||||
GravityFieldGeometryPreparation PrepareImpl(
|
||||
[[nodiscard]] GravityFieldPreparationResult<GravityFieldGeometryPreparation> TryPrepareImpl(
|
||||
const mfem::Vector &displacement,
|
||||
DiscretizationRevision discretization_revision,
|
||||
DisplacementRevision displacement_revision,
|
||||
@@ -147,6 +178,11 @@ export namespace mean_field::operators::context::gravity_field {
|
||||
const GravityFieldRevisions &revisions
|
||||
);
|
||||
|
||||
[[nodiscard]] GravityFieldPreparationResult<GravityFieldPreparationReport> TryPrepare(
|
||||
const GravityFieldStateView &state,
|
||||
const GravityFieldRevisions &revisions
|
||||
);
|
||||
|
||||
[[nodiscard]] const GravityFieldGeometryContext &GetGeometryContext() const;
|
||||
[[nodiscard]] const mfem::Vector &GetDensityTrue() const;
|
||||
[[nodiscard]] const mfem::Vector &GetGravityGradientTrue() const;
|
||||
|
||||
@@ -24,6 +24,13 @@ export namespace mean_field::operators {
|
||||
const context::gravity_field::GravityFieldRevisions &revisions
|
||||
);
|
||||
|
||||
[[nodiscard]] context::gravity_field::GravityFieldPreparationResult<
|
||||
context::gravity_field::GravityFieldPreparationReport>
|
||||
TryPrepare(
|
||||
const mfem::Vector &state,
|
||||
const context::gravity_field::GravityFieldRevisions &revisions
|
||||
);
|
||||
|
||||
void Mult(
|
||||
const mfem::Vector &state,
|
||||
mfem::Vector &residual
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
module;
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
|
||||
#include <mfem.hpp>
|
||||
|
||||
export module mean_field:operators.kernels.gravity_displacement_force;
|
||||
@@ -8,6 +11,24 @@ export import :fem;
|
||||
export import :mapping.domain_mapper;
|
||||
|
||||
export namespace mean_field::operators::kernels {
|
||||
enum class GravityDisplacementForceRejectionReason : std::uint8_t { invalid_mapping, non_finite_arithmetic };
|
||||
|
||||
struct GravityDisplacementForceRejection final {
|
||||
GravityDisplacementForceRejectionReason reason{GravityDisplacementForceRejectionReason::invalid_mapping};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::valid};
|
||||
};
|
||||
|
||||
using GravityDisplacementForceResult = std::expected<void, GravityDisplacementForceRejection>;
|
||||
|
||||
[[nodiscard]] GravityDisplacementForceResult try_apply_gravity_displacement_force_residual(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const mfem::Vector &densityTrue,
|
||||
const mfem::Vector &gravityGradientTrue,
|
||||
const mfem::Vector &displacementTrue,
|
||||
mfem::Vector &residualTrue
|
||||
);
|
||||
|
||||
void apply_gravity_displacement_force_residual(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
module;
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
|
||||
#include <mfem.hpp>
|
||||
|
||||
export module mean_field:operators.kernels.rotational_displacement_force;
|
||||
@@ -9,6 +12,24 @@ export import :mapping.domain_mapper;
|
||||
export import :physics.rigid_rotation;
|
||||
|
||||
export namespace mean_field::operators::kernels {
|
||||
enum class RotationalDisplacementForceRejectionReason : std::uint8_t { invalid_mapping, non_finite_arithmetic };
|
||||
|
||||
struct RotationalDisplacementForceRejection final {
|
||||
RotationalDisplacementForceRejectionReason reason{RotationalDisplacementForceRejectionReason::invalid_mapping};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::valid};
|
||||
};
|
||||
|
||||
using RotationalDisplacementForceResult = std::expected<void, RotationalDisplacementForceRejection>;
|
||||
|
||||
[[nodiscard]] RotationalDisplacementForceResult try_apply_rotational_displacement_force_residual(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const physics::RigidRotation &rotation,
|
||||
const mfem::Vector &densityTrue,
|
||||
const mfem::Vector &displacementTrue,
|
||||
mfem::Vector &residualTrue
|
||||
);
|
||||
|
||||
/*
|
||||
* Rotational contribution to the displacement row:
|
||||
*
|
||||
|
||||
@@ -2,6 +2,10 @@ module;
|
||||
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include <mfem.hpp>
|
||||
@@ -45,6 +49,52 @@ export namespace mean_field::operators {
|
||||
constexpr auto operator<=>(const PreparedAngularMomentumReport &) const = default;
|
||||
};
|
||||
|
||||
enum class AngularMomentumPreparationRejectionReason : std::uint8_t {
|
||||
inverted_geometry,
|
||||
non_finite_geometry,
|
||||
non_finite_angular_velocity,
|
||||
non_finite_density,
|
||||
negative_moment_of_inertia,
|
||||
non_finite_moment_of_inertia,
|
||||
non_finite_residual
|
||||
};
|
||||
|
||||
/*
|
||||
* A trial state can fail to define the angular-momentum invariant without
|
||||
* violating the operator's structural contract. Keep that distinction in
|
||||
* a fixed-size value so a line search can reject the candidate without
|
||||
* constructing or transporting an exception.
|
||||
*/
|
||||
struct AngularMomentumPreparationRejection final {
|
||||
AngularMomentumPreparationRejectionReason reason{AngularMomentumPreparationRejectionReason::inverted_geometry};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::valid};
|
||||
double momentOfInertia{std::numeric_limits<double>::quiet_NaN()};
|
||||
};
|
||||
|
||||
using AngularMomentumPreparationResult =
|
||||
std::expected<PreparedAngularMomentumReport, AngularMomentumPreparationRejection>;
|
||||
|
||||
[[noreturn]] inline void
|
||||
throwAngularMomentumPreparationRejection(const AngularMomentumPreparationRejection &rejection) {
|
||||
switch (rejection.reason) {
|
||||
case AngularMomentumPreparationRejectionReason::inverted_geometry:
|
||||
throw std::domain_error("The angular-momentum trial inverts mapped geometry.");
|
||||
case AngularMomentumPreparationRejectionReason::non_finite_geometry:
|
||||
throw std::domain_error("The angular-momentum trial produced non-finite mapped geometry.");
|
||||
case AngularMomentumPreparationRejectionReason::non_finite_angular_velocity:
|
||||
throw std::domain_error("The angular-momentum trial has a non-finite angular velocity.");
|
||||
case AngularMomentumPreparationRejectionReason::non_finite_density:
|
||||
throw std::domain_error("The angular-momentum trial produced a non-finite interpolated density.");
|
||||
case AngularMomentumPreparationRejectionReason::negative_moment_of_inertia:
|
||||
throw std::domain_error("The angular-momentum trial produced a negative moment of inertia.");
|
||||
case AngularMomentumPreparationRejectionReason::non_finite_moment_of_inertia:
|
||||
throw std::domain_error("The angular-momentum trial produced a non-finite moment of inertia.");
|
||||
case AngularMomentumPreparationRejectionReason::non_finite_residual:
|
||||
throw std::domain_error("The angular-momentum trial produced a non-finite residual.");
|
||||
}
|
||||
throw std::logic_error("An unknown angular-momentum trial rejection was reported.");
|
||||
}
|
||||
|
||||
struct AngularMomentumConstraintReport final {
|
||||
double targetAngularMomentum;
|
||||
double achievedAngularMomentum;
|
||||
@@ -97,6 +147,11 @@ export namespace mean_field::operators {
|
||||
const AngularMomentumDependencies &dependencies
|
||||
);
|
||||
|
||||
[[nodiscard]] AngularMomentumPreparationResult TryPrepare(
|
||||
double angularVelocity,
|
||||
const AngularMomentumDependencies &dependencies
|
||||
);
|
||||
|
||||
void BuildResidual(mfem::Vector &residual) const;
|
||||
|
||||
void ApplyDensityJacobianAction(
|
||||
@@ -156,9 +211,9 @@ export namespace mean_field::operators {
|
||||
};
|
||||
|
||||
void BuildStaticPlan();
|
||||
void RefreshGeometry(const mfem::Vector &displacement);
|
||||
void RefreshDensity(const mfem::Vector &density);
|
||||
void AssembleResidual();
|
||||
[[nodiscard]] std::optional<mapping::MappingStatus> RefreshGeometry(const mfem::Vector &displacement);
|
||||
[[nodiscard]] bool RefreshDensity(const mfem::Vector &density);
|
||||
[[nodiscard]] std::optional<AngularMomentumPreparationRejection> TryAssembleResidual();
|
||||
void VerifyPrepared() const;
|
||||
|
||||
[[nodiscard]] double EvaluateDensityMomentActionLocal(const mfem::Vector &densityVariation) const;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
module;
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <mfem.hpp>
|
||||
#include <vector>
|
||||
|
||||
@@ -22,6 +23,29 @@ export namespace mean_field::operators {
|
||||
}
|
||||
};
|
||||
|
||||
enum class BarotropicClosurePreparationRejectionReason : std::uint8_t {
|
||||
mapping_failure,
|
||||
invalid_quadrature_data,
|
||||
equation_of_state
|
||||
};
|
||||
|
||||
/*
|
||||
* A rejected candidate is part of the nonlinear-solver control flow, not
|
||||
* an exceptional API failure. Keep the payload fixed-size so it can be
|
||||
* selected deterministically across ranks without allocating. Only the
|
||||
* detail associated with `reason` is meaningful.
|
||||
*/
|
||||
struct BarotropicClosurePreparationRejection final {
|
||||
BarotropicClosurePreparationRejectionReason reason{
|
||||
BarotropicClosurePreparationRejectionReason::mapping_failure
|
||||
};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::non_finite_result};
|
||||
eos::EvaluationErrorCode equationOfStateError{eos::EvaluationErrorCode::nonfinite_result};
|
||||
};
|
||||
|
||||
using BarotropicClosurePreparationResult =
|
||||
std::expected<PreparedBarotropicClosureReport, BarotropicClosurePreparationRejection>;
|
||||
|
||||
class PreparedBarotropicClosureOperator final : public mfem::Operator {
|
||||
public:
|
||||
PreparedBarotropicClosureOperator(
|
||||
@@ -40,6 +64,11 @@ export namespace mean_field::operators {
|
||||
const context::barotropic::BarotropicClosureDependencies &dependencies
|
||||
);
|
||||
|
||||
[[nodiscard]] BarotropicClosurePreparationResult TryPrepare(
|
||||
const context::barotropic::BarotropicClosureStateView &state,
|
||||
const context::barotropic::BarotropicClosureDependencies &dependencies
|
||||
);
|
||||
|
||||
void Mult(
|
||||
const mfem::Vector &densityVariation,
|
||||
const mfem::Vector &enthalpyVariation,
|
||||
|
||||
@@ -2,6 +2,8 @@ module;
|
||||
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <optional>
|
||||
|
||||
#include <mfem.hpp>
|
||||
|
||||
@@ -18,6 +20,28 @@ export import :physics.rigid_rotation;
|
||||
export import :utils.blocks;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
enum class DisplacementResidualPreparationRejectionSource : std::uint8_t {
|
||||
pressure,
|
||||
gravity,
|
||||
rotation,
|
||||
composition
|
||||
};
|
||||
|
||||
enum class DisplacementResidualPreparationRejectionReason : std::uint8_t {
|
||||
equation_of_state,
|
||||
invalid_mapping,
|
||||
non_finite_arithmetic
|
||||
};
|
||||
|
||||
struct DisplacementResidualPreparationRejection final {
|
||||
DisplacementResidualPreparationRejectionSource source{DisplacementResidualPreparationRejectionSource::pressure};
|
||||
DisplacementResidualPreparationRejectionReason reason{
|
||||
DisplacementResidualPreparationRejectionReason::equation_of_state
|
||||
};
|
||||
eos::EvaluationErrorCode equationOfStateCode{eos::EvaluationErrorCode::nonfinite_result};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::valid};
|
||||
};
|
||||
|
||||
struct DisplacementResidualDependencyStamp final {
|
||||
std::uint64_t identity{0};
|
||||
std::uint64_t revision{0};
|
||||
@@ -104,6 +128,15 @@ export namespace mean_field::operators {
|
||||
const physics::RigidRotation &rotation
|
||||
);
|
||||
|
||||
[[nodiscard]] std::expected<
|
||||
PreparedDisplacementResidualReport,
|
||||
DisplacementResidualPreparationRejection>
|
||||
TryPrepare(
|
||||
const DisplacementResidualStateView &state,
|
||||
const DisplacementResidualDependencies &dependencies,
|
||||
const physics::RigidRotation &rotation
|
||||
);
|
||||
|
||||
void BuildResidual(mfem::Vector &residual) const;
|
||||
|
||||
void ApplyDensityJacobianAction(
|
||||
@@ -154,7 +187,7 @@ export namespace mean_field::operators {
|
||||
GetGravityContext() const noexcept;
|
||||
|
||||
private:
|
||||
void AssembleResidual();
|
||||
[[nodiscard]] std::optional<DisplacementResidualPreparationRejection> AssembleResidual();
|
||||
void VerifyPrepared() const;
|
||||
|
||||
const fem::FEM &m_fem;
|
||||
|
||||
@@ -2,6 +2,7 @@ module;
|
||||
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <vector>
|
||||
|
||||
#include <mfem.hpp>
|
||||
@@ -11,6 +12,7 @@ export module mean_field:operators.prepared_gravity_displacement_force;
|
||||
export import :fem;
|
||||
export import :mapping.domain_mapper;
|
||||
export import :operators.context.gravity_field;
|
||||
export import :operators.kernels.gravity_displacement_force;
|
||||
export import :utils.blocks;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
@@ -57,6 +59,11 @@ export namespace mean_field::operators {
|
||||
*/
|
||||
PreparedGravityDisplacementForceReport Prepare();
|
||||
|
||||
[[nodiscard]] std::expected<
|
||||
PreparedGravityDisplacementForceReport,
|
||||
kernels::GravityDisplacementForceRejection>
|
||||
TryPrepare();
|
||||
|
||||
void BuildResidual(mfem::Vector &residual) const;
|
||||
|
||||
void ApplyDensityJacobianAction(
|
||||
@@ -106,7 +113,10 @@ export namespace mean_field::operators {
|
||||
|
||||
private:
|
||||
void VerifyPrepared() const;
|
||||
void PrepareElementData();
|
||||
[[nodiscard]] std::expected<
|
||||
void,
|
||||
kernels::GravityDisplacementForceRejection>
|
||||
TryPrepareElementData();
|
||||
void ApplyPreparedCompleteJacobianActionTrue(
|
||||
const mfem::Vector &densityVariationTrue,
|
||||
const mfem::Vector &displacementVariationTrue,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
module;
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <mfem.hpp>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
export module mean_field:operators.prepared_gravity_source;
|
||||
@@ -10,6 +12,23 @@ export import :field.mfem;
|
||||
export import :mapping.domain_mapper;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
enum class GravitySourcePreparationRejectionReason : std::uint8_t { invalid_mapping, non_finite_arithmetic };
|
||||
|
||||
struct GravitySourcePreparationRejection final {
|
||||
GravitySourcePreparationRejectionReason reason{GravitySourcePreparationRejectionReason::invalid_mapping};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::valid};
|
||||
};
|
||||
|
||||
using GravitySourcePreparationResult = std::expected<void, GravitySourcePreparationRejection>;
|
||||
|
||||
[[noreturn]] inline void
|
||||
throwGravitySourcePreparationRejection(const GravitySourcePreparationRejection &rejection) {
|
||||
if (rejection.reason == GravitySourcePreparationRejectionReason::non_finite_arithmetic) {
|
||||
throw std::domain_error("Prepared gravity-source data contained non-finite arithmetic.");
|
||||
}
|
||||
throw std::domain_error("Prepared gravity-source data could not map the candidate geometry.");
|
||||
}
|
||||
|
||||
class PreparedMappedGravitySourceOperator final : public mfem::Operator {
|
||||
public:
|
||||
PreparedMappedGravitySourceOperator(
|
||||
@@ -19,6 +38,8 @@ export namespace mean_field::operators {
|
||||
|
||||
void Prepare(const mfem::Vector &displacement);
|
||||
void PreparePrimal(const mfem::Vector &displacement);
|
||||
[[nodiscard]] GravitySourcePreparationResult TryPrepare(const mfem::Vector &displacement);
|
||||
[[nodiscard]] GravitySourcePreparationResult TryPreparePrimal(const mfem::Vector &displacement);
|
||||
void Mult(
|
||||
const mfem::Vector &density,
|
||||
mfem::Vector &action
|
||||
@@ -68,7 +89,7 @@ export namespace mean_field::operators {
|
||||
mfem::Vector quadrature_data;
|
||||
};
|
||||
|
||||
void PrepareImpl(
|
||||
[[nodiscard]] GravitySourcePreparationResult TryPrepareImpl(
|
||||
const mfem::Vector &displacement,
|
||||
PreparationMode mode
|
||||
);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
module;
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <mfem.hpp>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
export module mean_field:operators.prepared_hdiv_mass;
|
||||
@@ -10,6 +12,22 @@ export import :field.mfem;
|
||||
export import :mapping.domain_mapper;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
enum class HDivMassPreparationRejectionReason : std::uint8_t { invalid_mapping, non_finite_arithmetic };
|
||||
|
||||
struct HDivMassPreparationRejection final {
|
||||
HDivMassPreparationRejectionReason reason{HDivMassPreparationRejectionReason::invalid_mapping};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::valid};
|
||||
};
|
||||
|
||||
using HDivMassPreparationResult = std::expected<void, HDivMassPreparationRejection>;
|
||||
|
||||
[[noreturn]] inline void throwHDivMassPreparationRejection(const HDivMassPreparationRejection &rejection) {
|
||||
if (rejection.reason == HDivMassPreparationRejectionReason::non_finite_arithmetic) {
|
||||
throw std::domain_error("Prepared H(div) mass data contained non-finite arithmetic.");
|
||||
}
|
||||
throw std::domain_error("Prepared H(div) mass data could not map the candidate geometry.");
|
||||
}
|
||||
|
||||
class PreparedMappedHDivMassOperator final : public mfem::Operator {
|
||||
public:
|
||||
PreparedMappedHDivMassOperator(
|
||||
@@ -19,6 +37,8 @@ export namespace mean_field::operators {
|
||||
|
||||
void Prepare(const mfem::Vector &displacement);
|
||||
void PreparePrimal(const mfem::Vector &displacement);
|
||||
[[nodiscard]] HDivMassPreparationResult TryPrepare(const mfem::Vector &displacement);
|
||||
[[nodiscard]] HDivMassPreparationResult TryPreparePrimal(const mfem::Vector &displacement);
|
||||
void Mult(
|
||||
const mfem::Vector &gravity_gradient,
|
||||
mfem::Vector &action
|
||||
@@ -54,8 +74,8 @@ export namespace mean_field::operators {
|
||||
mfem::DenseMatrix frozenMappingData;
|
||||
};
|
||||
|
||||
void PrepareVariationData();
|
||||
void PrepareImpl(
|
||||
[[nodiscard]] mapping::MappingStatus PrepareVariationData();
|
||||
[[nodiscard]] HDivMassPreparationResult TryPrepareImpl(
|
||||
const mfem::Vector &displacement,
|
||||
PreparationMode mode
|
||||
);
|
||||
|
||||
@@ -3,7 +3,9 @@ module;
|
||||
#include <compare>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include <mfem.hpp>
|
||||
@@ -30,6 +32,35 @@ export namespace mean_field::operators {
|
||||
}
|
||||
};
|
||||
|
||||
enum class HydrostaticEquilibriumPreparationRejectionReason : std::uint8_t {
|
||||
inverted_geometry,
|
||||
non_finite_geometry,
|
||||
non_finite_residual
|
||||
};
|
||||
|
||||
struct HydrostaticEquilibriumPreparationRejection final {
|
||||
HydrostaticEquilibriumPreparationRejectionReason reason{
|
||||
HydrostaticEquilibriumPreparationRejectionReason::inverted_geometry
|
||||
};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::valid};
|
||||
};
|
||||
|
||||
using HydrostaticEquilibriumPreparationResult =
|
||||
std::expected<PreparedHydrostaticEquilibriumReport, HydrostaticEquilibriumPreparationRejection>;
|
||||
|
||||
[[noreturn]] inline void
|
||||
throwHydrostaticEquilibriumPreparationRejection(const HydrostaticEquilibriumPreparationRejection &rejection) {
|
||||
switch (rejection.reason) {
|
||||
case HydrostaticEquilibriumPreparationRejectionReason::non_finite_geometry:
|
||||
throw std::domain_error("Prepared hydrostatic equilibrium encountered non-finite mapped geometry.");
|
||||
case HydrostaticEquilibriumPreparationRejectionReason::non_finite_residual:
|
||||
throw std::domain_error("Prepared hydrostatic equilibrium produced a non-finite residual.");
|
||||
case HydrostaticEquilibriumPreparationRejectionReason::inverted_geometry:
|
||||
default:
|
||||
throw std::domain_error("Prepared hydrostatic equilibrium encountered inverted mapped geometry.");
|
||||
}
|
||||
}
|
||||
|
||||
struct PreparedHydrostaticAlgebraicJacobianStatistics {
|
||||
std::uint64_t preparations{0};
|
||||
std::uint64_t enthalpyApplications{0};
|
||||
@@ -102,6 +133,12 @@ export namespace mean_field::operators {
|
||||
const physics::RigidRotation &rotation
|
||||
);
|
||||
|
||||
[[nodiscard]] HydrostaticEquilibriumPreparationResult TryPrepare(
|
||||
const context::hydrostatic::HydrostaticEquilibriumStateView &state,
|
||||
const context::hydrostatic::HydrostaticEquilibriumDependencies &dependencies,
|
||||
const physics::RigidRotation &rotation
|
||||
);
|
||||
|
||||
void BuildResidual(mfem::Vector &residual) const;
|
||||
|
||||
void ApplyEnthalpyJacobianAction(
|
||||
@@ -221,12 +258,12 @@ export namespace mean_field::operators {
|
||||
};
|
||||
|
||||
void PrepareStaticPlan();
|
||||
void PrepareGeometry();
|
||||
void PrepareAlgebraicJacobianBlocks();
|
||||
void PrepareRotation();
|
||||
void PrepareBaseState();
|
||||
[[nodiscard]] std::optional<mapping::MappingStatus> PrepareGeometry();
|
||||
[[nodiscard]] bool PrepareAlgebraicJacobianBlocks();
|
||||
[[nodiscard]] bool PrepareRotation();
|
||||
[[nodiscard]] bool PrepareBaseState();
|
||||
void FinalizeDisplacementJacobianPreparation();
|
||||
void AssembleCachedResidual();
|
||||
[[nodiscard]] bool AssembleCachedResidual();
|
||||
void VerifyPrepared() const;
|
||||
|
||||
const fem::FEM &m_fem;
|
||||
|
||||
@@ -2,7 +2,9 @@ module;
|
||||
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <mfem.hpp>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
export module mean_field:operators.prepared_mass_normalization;
|
||||
@@ -59,6 +61,28 @@ export namespace mean_field::operators {
|
||||
constexpr auto operator<=>(const PreparedMassNormalizationReport &) const = default;
|
||||
};
|
||||
|
||||
enum class MassNormalizationPreparationRejectionReason : std::uint8_t {
|
||||
mapping_failure,
|
||||
non_finite_density_interpolation,
|
||||
non_finite_assembled_mass
|
||||
};
|
||||
|
||||
/*
|
||||
* Candidate rejection is deliberately represented without text or owned
|
||||
* storage. That makes the result cheap to propagate through a line search
|
||||
* and gives the MPI implementation a deterministic, allocation-free value
|
||||
* to select on every rank.
|
||||
*/
|
||||
struct MassNormalizationPreparationRejection final {
|
||||
MassNormalizationPreparationRejectionReason reason{
|
||||
MassNormalizationPreparationRejectionReason::mapping_failure
|
||||
};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::non_finite_result};
|
||||
};
|
||||
|
||||
using MassNormalizationPreparationResult =
|
||||
std::expected<PreparedMassNormalizationReport, MassNormalizationPreparationRejection>;
|
||||
|
||||
struct PreparedMassNormalizationActionStatistics final {
|
||||
std::uint64_t densityApplications{0};
|
||||
std::uint64_t displacementApplications{0};
|
||||
@@ -109,6 +133,16 @@ export namespace mean_field::operators {
|
||||
const MassNormalizationDependencies &dependencies
|
||||
);
|
||||
|
||||
[[nodiscard]] MassNormalizationPreparationResult TryPrepare(
|
||||
const MassNormalizationStateView &state,
|
||||
const MassNormalizationDependencies &dependencies
|
||||
);
|
||||
|
||||
[[nodiscard]] MassNormalizationPreparationResult TryPrepare(
|
||||
const models::CompiledFixedMass &constraint,
|
||||
const MassNormalizationDependencies &dependencies
|
||||
);
|
||||
|
||||
void BuildResidual(mfem::Vector &residual) const;
|
||||
|
||||
void ApplyDensityJacobianAction(
|
||||
@@ -179,9 +213,11 @@ export namespace mean_field::operators {
|
||||
};
|
||||
|
||||
void BuildStaticPlan();
|
||||
void RefreshGeometry(const mfem::Vector &displacement);
|
||||
void RefreshDensity(const mfem::Vector &density);
|
||||
void AssembleResidual();
|
||||
[[nodiscard]] std::optional<MassNormalizationPreparationRejection>
|
||||
RefreshGeometry(const mfem::Vector &displacement);
|
||||
[[nodiscard]] std::optional<MassNormalizationPreparationRejection> RefreshDensity(const mfem::Vector &density);
|
||||
[[nodiscard]] std::optional<MassNormalizationPreparationRejection> AssembleResidual();
|
||||
[[nodiscard]] std::optional<MassNormalizationPreparationRejection> UpdateResidualForTargetMass();
|
||||
void VerifyPrepared() const;
|
||||
|
||||
[[nodiscard]] double EvaluateDensityActionLocal(const mfem::Vector &densityVariation) const;
|
||||
|
||||
@@ -3,6 +3,7 @@ module;
|
||||
#include <compare>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
@@ -18,6 +19,18 @@ export import :operators.context.pressure_force;
|
||||
export import :utils.blocks;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
enum class PressureForcePreparationRejectionReason : std::uint8_t {
|
||||
equation_of_state,
|
||||
invalid_mapping,
|
||||
non_finite_arithmetic
|
||||
};
|
||||
|
||||
struct PressureForcePreparationRejection final {
|
||||
PressureForcePreparationRejectionReason reason{PressureForcePreparationRejectionReason::equation_of_state};
|
||||
eos::EvaluationErrorCode equationOfStateCode{eos::EvaluationErrorCode::nonfinite_result};
|
||||
mapping::MappingStatus mappingStatus{mapping::MappingStatus::valid};
|
||||
};
|
||||
|
||||
struct PreparedPressureForceReport final {
|
||||
context::pressure_force::PressureForcePreparationReport contextReport;
|
||||
|
||||
@@ -92,6 +105,14 @@ export namespace mean_field::operators {
|
||||
const context::pressure_force::PressureForceDependencies &dependencies
|
||||
);
|
||||
|
||||
[[nodiscard]] std::expected<
|
||||
PreparedPressureForceReport,
|
||||
PressureForcePreparationRejection>
|
||||
TryPrepare(
|
||||
const context::pressure_force::PressureForceStateView &state,
|
||||
const context::pressure_force::PressureForceDependencies &dependencies
|
||||
);
|
||||
|
||||
void BuildResidual(mfem::Vector &residual) const;
|
||||
|
||||
void ApplyEnthalpyJacobianAction(
|
||||
@@ -206,12 +227,12 @@ export namespace mean_field::operators {
|
||||
};
|
||||
|
||||
void PrepareStaticPlan();
|
||||
void PrepareGeometry();
|
||||
void PrepareMaterialState();
|
||||
[[nodiscard]] std::optional<PressureForcePreparationRejection> PrepareGeometry();
|
||||
[[nodiscard]] std::optional<PressureForcePreparationRejection> PrepareMaterialState();
|
||||
|
||||
void FinalizeDisplacementJacobianPreparation();
|
||||
|
||||
void AssembleCachedResidual();
|
||||
[[nodiscard]] std::optional<PressureForcePreparationRejection> AssembleCachedResidual();
|
||||
|
||||
void VerifyPrepared() const;
|
||||
|
||||
@@ -301,4 +322,4 @@ export namespace mean_field::operators {
|
||||
|
||||
const PreparedPressureForceOperator &m_preparedOperator;
|
||||
};
|
||||
} // namespace mean_field::operators
|
||||
} // namespace mean_field::operators
|
||||
|
||||
@@ -2,6 +2,7 @@ module;
|
||||
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
@@ -12,6 +13,7 @@ export module mean_field:operators.prepared_rotational_displacement_force;
|
||||
export import :fem;
|
||||
export import :mapping.domain_mapper;
|
||||
export import :operators.context.rotational_displacement_force;
|
||||
export import :operators.kernels.rotational_displacement_force;
|
||||
export import :physics.rigid_rotation;
|
||||
export import :utils.blocks;
|
||||
|
||||
@@ -61,6 +63,15 @@ export namespace mean_field::operators {
|
||||
const physics::RigidRotation &rotation
|
||||
);
|
||||
|
||||
[[nodiscard]] std::expected<
|
||||
PreparedRotationalDisplacementForceReport,
|
||||
kernels::RotationalDisplacementForceRejection>
|
||||
TryPrepare(
|
||||
const context::rotational_displacement_force::RotationalDisplacementForceStateView &state,
|
||||
const context::rotational_displacement_force::RotationalDisplacementForceDependencies &dependencies,
|
||||
const physics::RigidRotation &rotation
|
||||
);
|
||||
|
||||
void BuildResidual(mfem::Vector &residual) const;
|
||||
|
||||
void ApplyDensityJacobianAction(
|
||||
@@ -104,7 +115,10 @@ export namespace mean_field::operators {
|
||||
|
||||
private:
|
||||
void VerifyPrepared() const;
|
||||
void PrepareElementData();
|
||||
[[nodiscard]] std::expected<
|
||||
void,
|
||||
kernels::RotationalDisplacementForceRejection>
|
||||
TryPrepareElementData();
|
||||
void ApplyPreparedCompleteJacobianActionTrue(
|
||||
const mfem::Vector &densityVariationTrue,
|
||||
const mfem::Vector &displacementVariationTrue,
|
||||
|
||||
@@ -3,10 +3,14 @@ module;
|
||||
#include <compare>
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <mfem.hpp>
|
||||
#include <mpi.h>
|
||||
|
||||
export module mean_field:operators.prepared_stellar_equilibrium;
|
||||
|
||||
@@ -72,6 +76,70 @@ export namespace mean_field::operators {
|
||||
}
|
||||
};
|
||||
|
||||
enum class StellarEquilibriumPreparationRejectionReason : std::uint8_t {
|
||||
inverted_geometry,
|
||||
non_finite_geometry,
|
||||
thermodynamic_domain,
|
||||
non_finite_thermodynamics,
|
||||
inadmissible_physics,
|
||||
non_finite_physics
|
||||
};
|
||||
|
||||
enum class StellarEquilibriumPreparationStage : std::uint8_t {
|
||||
unspecified,
|
||||
generated_geometry,
|
||||
gravity,
|
||||
barotropic_closure,
|
||||
hydrostatic_equilibrium,
|
||||
displacement_residual,
|
||||
pressure_force,
|
||||
gravity_displacement_force,
|
||||
rotational_displacement_force,
|
||||
displacement_composition,
|
||||
mass_normalization,
|
||||
model_specification
|
||||
};
|
||||
|
||||
/*
|
||||
* A candidate state that cannot define a physical mapped domain is an
|
||||
* expected line-search outcome, not an exceptional program failure. Keep
|
||||
* this payload fixed-size so every trial can report it without allocating.
|
||||
*/
|
||||
struct StellarEquilibriumPreparationRejection final {
|
||||
StellarEquilibriumPreparationRejectionReason reason{
|
||||
StellarEquilibriumPreparationRejectionReason::inverted_geometry
|
||||
};
|
||||
StellarEquilibriumPreparationStage stage{StellarEquilibriumPreparationStage::unspecified};
|
||||
double minimumJacobianDeterminant{std::numeric_limits<double>::quiet_NaN()};
|
||||
eos::EvaluationErrorCode thermodynamicErrorCode{eos::EvaluationErrorCode::nonfinite_result};
|
||||
};
|
||||
|
||||
template <typename Report>
|
||||
using StellarEquilibriumPreparationResult = std::expected<Report, StellarEquilibriumPreparationRejection>;
|
||||
|
||||
[[noreturn]] inline void
|
||||
throwStellarEquilibriumPreparationRejection(const StellarEquilibriumPreparationRejection &rejection) {
|
||||
switch (rejection.reason) {
|
||||
case StellarEquilibriumPreparationRejectionReason::non_finite_geometry:
|
||||
throw std::domain_error("The prepared domain deformation has non-finite mapped geometry.");
|
||||
case StellarEquilibriumPreparationRejectionReason::thermodynamic_domain:
|
||||
throw eos::EvaluationError(
|
||||
rejection.thermodynamicErrorCode, "The stellar state lies outside the equation-of-state domain."
|
||||
);
|
||||
case StellarEquilibriumPreparationRejectionReason::non_finite_thermodynamics:
|
||||
throw eos::EvaluationError(
|
||||
rejection.thermodynamicErrorCode, "The stellar state produced non-finite thermodynamic data."
|
||||
);
|
||||
case StellarEquilibriumPreparationRejectionReason::inadmissible_physics:
|
||||
throw std::domain_error("The stellar state is physically inadmissible.");
|
||||
case StellarEquilibriumPreparationRejectionReason::non_finite_physics:
|
||||
throw std::domain_error("The stellar state produced non-finite physical data.");
|
||||
case StellarEquilibriumPreparationRejectionReason::inverted_geometry:
|
||||
throw std::domain_error("The prepared domain deformation inverts at least one volume element.");
|
||||
}
|
||||
throw std::logic_error("Unknown stellar-equilibrium candidate-rejection reason.");
|
||||
}
|
||||
|
||||
struct PreparedStellarEquilibriumStatistics final {
|
||||
std::uint64_t residualAssemblies{0};
|
||||
std::uint64_t residualApplications{0};
|
||||
@@ -159,6 +227,12 @@ export namespace mean_field::operators {
|
||||
const physics::RigidRotation &rotation
|
||||
);
|
||||
|
||||
[[nodiscard]] StellarEquilibriumPreparationResult<PreparedStellarEquilibriumReport> TryPrepare(
|
||||
const mfem::Vector &state,
|
||||
const StellarEquilibriumDependencies &dependencies,
|
||||
const physics::RigidRotation &rotation
|
||||
);
|
||||
|
||||
void BuildResidual(mfem::Vector &residual) const;
|
||||
|
||||
void Mult(
|
||||
@@ -188,12 +262,9 @@ export namespace mean_field::operators {
|
||||
[[nodiscard]] const PreparedHydrostaticEquilibriumOperator &GetHydrostaticOperator() const noexcept;
|
||||
[[nodiscard]] const PreparedDisplacementResidualOperator &GetDisplacementOperator() const noexcept;
|
||||
[[nodiscard]] const PreparedMassNormalizationOperator &GetMassNormalizationOperator() const noexcept;
|
||||
[[nodiscard]] double ApplyDensityVolumeIntegralDensityAction(
|
||||
const mfem::Vector &densityDirection
|
||||
) const;
|
||||
[[nodiscard]] double ApplyDensityVolumeIntegralSurfaceShapeAction(
|
||||
const mfem::Vector &surfaceShapeDirection
|
||||
) const;
|
||||
[[nodiscard]] double ApplyDensityVolumeIntegralDensityAction(const mfem::Vector &densityDirection) const;
|
||||
[[nodiscard]] double
|
||||
ApplyDensityVolumeIntegralSurfaceShapeAction(const mfem::Vector &surfaceShapeDirection) const;
|
||||
[[nodiscard]] const PreparedPressureSurfaceConstraint &GetSurfaceConstraintOperator() const noexcept;
|
||||
[[nodiscard]] const deformation::PreparedDomainDeformationRuntime &GetDomainDeformation() const noexcept;
|
||||
[[nodiscard]] const mfem::Vector &GetSurfaceDeformationParameters() const;
|
||||
@@ -222,6 +293,7 @@ export namespace mean_field::operators {
|
||||
void VerifyPrepared() const;
|
||||
|
||||
StellarEquilibriumRootManifest m_rootManifest;
|
||||
MPI_Comm m_communicator{MPI_COMM_NULL};
|
||||
mfem::Array<int> m_gravityStateOffsets;
|
||||
|
||||
context::gravity_field::GravityFieldLinearizationContext m_gravityContext;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@ module;
|
||||
#include <concepts>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@@ -28,12 +29,11 @@ export namespace mean_field::equilibrium {
|
||||
static constexpr bool complete = false;
|
||||
};
|
||||
|
||||
template <model::StellarModelType Model>
|
||||
struct StellarSurfaceCompilationAudit<Model, true> {
|
||||
template <model::StellarModelType Model> struct StellarSurfaceCompilationAudit<Model, true> {
|
||||
private:
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
using EquationOfState = typename ModelType::EquationOfStateType;
|
||||
using Form = operators::CompiledStellarEquilibriumForm<ModelType>;
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
using EquationOfState = typename ModelType::EquationOfStateType;
|
||||
using Form = operators::CompiledStellarEquilibriumForm<ModelType>;
|
||||
using AvailableEquations = material::StellarEquilibriumThermodynamicEquations;
|
||||
|
||||
static constexpr bool thermodynamicsCompilable =
|
||||
@@ -46,14 +46,12 @@ export namespace mean_field::equilibrium {
|
||||
} else {
|
||||
using ThermodynamicEquations =
|
||||
material::CompiledThermodynamicEquationsT<EquationOfState, Form, AvailableEquations>;
|
||||
using Formulation = typename ThermodynamicEquations::PressureSurfaceFormulation;
|
||||
using CompiledSurface =
|
||||
surface::CompiledPressureSurfaceConstraintT<Formulation, EquationOfState>;
|
||||
using Formulation = typename ThermodynamicEquations::PressureSurfaceFormulation;
|
||||
using CompiledSurface = surface::CompiledPressureSurfaceConstraintT<Formulation, EquationOfState>;
|
||||
return requires(const ModelType &model) {
|
||||
{
|
||||
surface::compilePressureSurfaceConstraint<Formulation>(
|
||||
model.surfaceCondition(),
|
||||
model.equationOfState()
|
||||
model.surfaceCondition(), model.equationOfState()
|
||||
)
|
||||
} -> std::same_as<CompiledSurface>;
|
||||
};
|
||||
@@ -77,8 +75,7 @@ export namespace mean_field::equilibrium {
|
||||
requires operators::StellarEquilibriumSystemCompilable<std::remove_cvref_t<Candidate>>;
|
||||
requires hasStellarEquilibriumSurfaceCompilation<std::remove_cvref_t<Candidate>>;
|
||||
requires operators::CompilableRootManifestFor<
|
||||
std::remove_cvref_t<Candidate>,
|
||||
operators::CompiledStellarEquilibriumForm<std::remove_cvref_t<Candidate>>>;
|
||||
std::remove_cvref_t<Candidate>, operators::CompiledStellarEquilibriumForm<std::remove_cvref_t<Candidate>>>;
|
||||
requires operators::hasStellarEquilibriumCoreRuntime<std::remove_cvref_t<Candidate>>;
|
||||
requires operators::hasCompleteStellarEquilibriumRuntime<std::remove_cvref_t<Candidate>>;
|
||||
requires operators::stellarEquilibriumRotationProviderCount<std::remove_cvref_t<Candidate>> <= 1;
|
||||
@@ -105,19 +102,16 @@ export namespace mean_field::equilibrium {
|
||||
operators::StellarEquilibriumPhysicalCoreType<std::remove_cvref_t<Model>>,
|
||||
typename std::remove_cvref_t<Model>::SpecificationTypes>> { };
|
||||
|
||||
struct StellarEquilibriumProblemFactory;
|
||||
} // namespace detail
|
||||
|
||||
template <
|
||||
StellarEquilibriumModel Model,
|
||||
StellarDiscretizationType Discretization = StellarDiscretization>
|
||||
template <StellarEquilibriumModel Model, StellarDiscretizationType Discretization = StellarDiscretization>
|
||||
requires detail::StellarEquilibriumModelDiscretizationStructureAudit<
|
||||
std::remove_cvref_t<Model>,
|
||||
std::remove_cvref_t<Discretization>>::value
|
||||
class StellarEquilibriumProblem final {
|
||||
public:
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
using DiscretizationType = std::remove_cvref_t<Discretization>;
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
using DiscretizationType = std::remove_cvref_t<Discretization>;
|
||||
using NormalizationPrescriptionType = typename DiscretizationType::NormalizationPrescriptionType;
|
||||
|
||||
static constexpr bool hasFixedCentralDensity =
|
||||
@@ -128,13 +122,15 @@ export namespace mean_field::equilibrium {
|
||||
operators::stellarEquilibriumRotationProviderCount<ModelType>;
|
||||
static constexpr bool symbolicallySquare = ModelType::symbolicallySquare;
|
||||
|
||||
using PreparedOperatorType = operators::PreparedVariadicStellarEquilibriumOperator<ModelType>;
|
||||
using PhysicalCoreType = typename PreparedOperatorType::PhysicalCoreType;
|
||||
using FormType = operators::CompiledStellarEquilibriumForm<ModelType>;
|
||||
using JacobianFormType = operators::CompiledStellarEquilibriumJacobianForm<ModelType>;
|
||||
using ManifestType = operators::EquilibriumSystemManifest<ModelType, FormType, JacobianFormType>;
|
||||
using EquationOfStateType = model::EquationOfStateType<ModelType>;
|
||||
using SurfaceConditionType = model::SurfaceConditionType<ModelType>;
|
||||
using PreparedOperatorType = operators::PreparedVariadicStellarEquilibriumOperator<ModelType>;
|
||||
using Report = typename PreparedOperatorType::Report;
|
||||
using PreparationResult = typename PreparedOperatorType::PreparationResult;
|
||||
using PhysicalCoreType = typename PreparedOperatorType::PhysicalCoreType;
|
||||
using FormType = operators::CompiledStellarEquilibriumForm<ModelType>;
|
||||
using JacobianFormType = operators::CompiledStellarEquilibriumJacobianForm<ModelType>;
|
||||
using ManifestType = operators::EquilibriumSystemManifest<ModelType, FormType, JacobianFormType>;
|
||||
using EquationOfStateType = model::EquationOfStateType<ModelType>;
|
||||
using SurfaceConditionType = model::SurfaceConditionType<ModelType>;
|
||||
using AvailableThermodynamicEquations = material::StellarEquilibriumThermodynamicEquations;
|
||||
using ThermodynamicEquationsType =
|
||||
material::CompiledThermodynamicEquationsT<EquationOfStateType, FormType, AvailableThermodynamicEquations>;
|
||||
@@ -147,17 +143,18 @@ export namespace mean_field::equilibrium {
|
||||
|
||||
StellarEquilibriumProblem(
|
||||
ModelType stellarModel,
|
||||
DiscretizationType discretization
|
||||
DiscretizationType discretization,
|
||||
fem::FEM &finiteElementModel
|
||||
)
|
||||
: m_stellarModel(std::make_shared<ModelType>(std::move(stellarModel))),
|
||||
m_discretization(std::move(discretization)),
|
||||
m_compiledSurfaceConstraint(CompileSurfaceConstraint(*m_stellarModel)),
|
||||
m_preparedOperator(
|
||||
m_discretization.finiteElementModel(),
|
||||
finiteElementModel,
|
||||
m_discretization.domainMapper(),
|
||||
m_stellarModel,
|
||||
operators::PressureSurfaceConstraintView{m_compiledSurfaceConstraint},
|
||||
CompileDefaultDomainDeformation(m_discretization.finiteElementModel())
|
||||
CompileDefaultDomainDeformation(finiteElementModel)
|
||||
) {
|
||||
VerifyProblem();
|
||||
}
|
||||
@@ -176,6 +173,12 @@ export namespace mean_field::equilibrium {
|
||||
return m_discretization;
|
||||
}
|
||||
|
||||
[[nodiscard]] MPI_Comm GetCommunicator() const & {
|
||||
return m_discretization.communicator();
|
||||
}
|
||||
|
||||
[[nodiscard]] MPI_Comm GetCommunicator() const && = delete;
|
||||
|
||||
[[nodiscard]] const NormalizationPrescriptionType &GetNormalizationPrescription() const noexcept {
|
||||
return m_discretization.normalizationPrescription();
|
||||
}
|
||||
@@ -236,21 +239,54 @@ export namespace mean_field::equilibrium {
|
||||
const mfem::Vector &state,
|
||||
const operators::StellarEquilibriumDependencies &dependencies,
|
||||
const physics::RigidRotation &rotation
|
||||
) requires(generatedRotationProviderCount == 0) {
|
||||
)
|
||||
requires(generatedRotationProviderCount == 0)
|
||||
{
|
||||
auto report = m_preparedOperator.Prepare(state, dependencies, rotation);
|
||||
++m_preparationGeneration;
|
||||
return report;
|
||||
}
|
||||
|
||||
[[nodiscard]] PreparationResult TryPrepare(
|
||||
const mfem::Vector &state,
|
||||
const operators::StellarEquilibriumDependencies &dependencies,
|
||||
const physics::RigidRotation &rotation
|
||||
)
|
||||
requires(generatedRotationProviderCount == 0)
|
||||
{
|
||||
auto result = m_preparedOperator.TryPrepare(state, dependencies, rotation);
|
||||
if (!result.has_value()) {
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
++m_preparationGeneration;
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Prepare(
|
||||
const mfem::Vector &state,
|
||||
const operators::StellarEquilibriumDependencies &dependencies
|
||||
) requires(generatedRotationProviderCount == 1) {
|
||||
)
|
||||
requires(generatedRotationProviderCount == 1)
|
||||
{
|
||||
auto report = m_preparedOperator.Prepare(state, dependencies);
|
||||
++m_preparationGeneration;
|
||||
return report;
|
||||
}
|
||||
|
||||
[[nodiscard]] PreparationResult TryPrepare(
|
||||
const mfem::Vector &state,
|
||||
const operators::StellarEquilibriumDependencies &dependencies
|
||||
)
|
||||
requires(generatedRotationProviderCount == 1)
|
||||
{
|
||||
auto result = m_preparedOperator.TryPrepare(state, dependencies);
|
||||
if (!result.has_value()) {
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
++m_preparationGeneration;
|
||||
return result;
|
||||
}
|
||||
|
||||
void BuildResidual(mfem::Vector &residual) const {
|
||||
m_preparedOperator.BuildResidual(residual);
|
||||
}
|
||||
@@ -266,8 +302,7 @@ export namespace mean_field::equilibrium {
|
||||
[[nodiscard]] static CompiledSurfaceConstraintType CompileSurfaceConstraint(const ModelType &stellarModel) {
|
||||
return surface::compilePressureSurfaceConstraint<
|
||||
typename ThermodynamicEquationsType::PressureSurfaceFormulation>(
|
||||
stellarModel.surfaceCondition(),
|
||||
stellarModel.equationOfState()
|
||||
stellarModel.surfaceCondition(), stellarModel.equationOfState()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -318,28 +353,25 @@ export namespace mean_field::equilibrium {
|
||||
template <
|
||||
typename Model,
|
||||
typename Discretization,
|
||||
bool StructurallyCompatible =
|
||||
StellarEquilibriumModelDiscretizationStructureAudit<
|
||||
std::remove_cvref_t<Model>,
|
||||
std::remove_cvref_t<Discretization>>::value>
|
||||
bool StructurallyCompatible = StellarEquilibriumModelDiscretizationStructureAudit<
|
||||
std::remove_cvref_t<Model>,
|
||||
std::remove_cvref_t<Discretization>>::value>
|
||||
struct StellarEquilibriumModelDiscretizationOperationAudit : std::false_type { };
|
||||
|
||||
template <typename Model, typename Discretization>
|
||||
struct StellarEquilibriumModelDiscretizationOperationAudit<
|
||||
Model,
|
||||
Discretization,
|
||||
true> {
|
||||
struct StellarEquilibriumModelDiscretizationOperationAudit<Model, Discretization, true> {
|
||||
private:
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
using DiscretizationType = std::remove_cvref_t<Discretization>;
|
||||
using Problem = StellarEquilibriumProblem<ModelType, DiscretizationType>;
|
||||
using Prescription = typename DiscretizationType::NormalizationPrescriptionType;
|
||||
using Problem = StellarEquilibriumProblem<ModelType, DiscretizationType>;
|
||||
using Prescription = typename DiscretizationType::NormalizationPrescriptionType;
|
||||
|
||||
public:
|
||||
static constexpr bool value = [] {
|
||||
if constexpr (
|
||||
std::same_as<Prescription, normalization::Unnormalized> ||
|
||||
normalization::PhysicalRieszDiagonalPrescription<Prescription>) {
|
||||
normalization::PhysicalRieszDiagonalPrescription<Prescription>
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return normalization::RuntimePreparedNormalizationOperation<Problem>;
|
||||
@@ -362,46 +394,99 @@ export namespace mean_field::equilibrium {
|
||||
std::remove_cvref_t<Model>,
|
||||
std::remove_cvref_t<Discretization>>::value;
|
||||
|
||||
namespace detail {
|
||||
/* The structurally formed problem type is needed to probe the ADL
|
||||
* operation without a recursive concept. Its constructor remains
|
||||
* private, and this factory is the single construction authority after
|
||||
* the complete public compatibility contract has succeeded. */
|
||||
struct StellarEquilibriumProblemFactory final {
|
||||
template <StellarEquilibriumModel Model, StellarDiscretizationType Discretization>
|
||||
requires StellarEquilibriumModelDiscretizationCompatible<Model, Discretization>
|
||||
[[nodiscard]] static auto Create(
|
||||
Model &&stellarModel,
|
||||
Discretization discretization
|
||||
) {
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
using DiscretizationType = std::remove_cvref_t<Discretization>;
|
||||
return StellarEquilibriumProblem<ModelType, DiscretizationType>{
|
||||
std::forward<Model>(stellarModel),
|
||||
std::move(discretization)
|
||||
};
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace mean_field::equilibrium
|
||||
|
||||
template <StellarEquilibriumModel Model, StellarDiscretizationType Discretization>
|
||||
requires StellarEquilibriumModelDiscretizationCompatible<Model, Discretization>
|
||||
namespace mean_field::equilibrium::detail {
|
||||
/* The structurally formed problem type is needed to probe the ADL
|
||||
* operation without a recursive concept. Its constructor remains
|
||||
* private, and this factory is the single construction authority after
|
||||
* the complete public compatibility contract has succeeded. */
|
||||
struct StellarEquilibriumProblemFactory final {
|
||||
template <
|
||||
StellarEquilibriumModel Model,
|
||||
StellarDiscretizationType Discretization>
|
||||
requires StellarEquilibriumModelDiscretizationCompatible<
|
||||
Model,
|
||||
Discretization>
|
||||
[[nodiscard]] static auto Create(
|
||||
Model &&stellarModel,
|
||||
Discretization discretization
|
||||
) {
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
using DiscretizationType = std::remove_cvref_t<Discretization>;
|
||||
fem::FEM &finiteElementModel = discretization.MutableFiniteElementModelForAssembly();
|
||||
return StellarEquilibriumProblem<ModelType, DiscretizationType>{
|
||||
std::forward<Model>(stellarModel), std::move(discretization), finiteElementModel
|
||||
};
|
||||
}
|
||||
|
||||
template <
|
||||
StellarEquilibriumModel Model,
|
||||
StellarDiscretizationType Discretization>
|
||||
requires StellarEquilibriumModelDiscretizationCompatible<
|
||||
Model,
|
||||
Discretization>
|
||||
[[nodiscard]] static auto CreateOwned(
|
||||
Model &&stellarModel,
|
||||
Discretization discretization
|
||||
) {
|
||||
using ModelType = std::remove_cvref_t<Model>;
|
||||
using DiscretizationType = std::remove_cvref_t<Discretization>;
|
||||
using ProblemType = StellarEquilibriumProblem<ModelType, DiscretizationType>;
|
||||
fem::FEM &finiteElementModel = discretization.MutableFiniteElementModelForAssembly();
|
||||
return std::unique_ptr<ProblemType>{
|
||||
new ProblemType{std::forward<Model>(stellarModel), std::move(discretization), finiteElementModel}
|
||||
};
|
||||
}
|
||||
|
||||
template <DiscretizedStellarEquilibriumProblem Problem>
|
||||
[[nodiscard]] static fem::FEM &MutableFiniteElementModelForProjection(Problem &problem) {
|
||||
return problem.m_discretization.MutableFiniteElementModelForAssembly();
|
||||
}
|
||||
|
||||
template <DiscretizedStellarEquilibriumProblem Problem>
|
||||
[[nodiscard]] static const fem::FEM &FiniteElementModel(const Problem &problem) {
|
||||
return problem.m_discretization.RequireFiniteElementModel();
|
||||
}
|
||||
};
|
||||
} // namespace mean_field::equilibrium::detail
|
||||
|
||||
export namespace mean_field::equilibrium {
|
||||
template <
|
||||
StellarEquilibriumModel Model,
|
||||
StellarDiscretizationType Discretization>
|
||||
requires StellarEquilibriumModelDiscretizationCompatible<
|
||||
Model,
|
||||
Discretization>
|
||||
[[nodiscard]] auto discretize(
|
||||
Model &&stellarModel,
|
||||
Discretization discretization
|
||||
) {
|
||||
return detail::StellarEquilibriumProblemFactory::Create(
|
||||
std::forward<Model>(stellarModel),
|
||||
std::move(discretization)
|
||||
std::forward<Model>(stellarModel), std::move(discretization)
|
||||
);
|
||||
}
|
||||
|
||||
template <StellarEquilibriumModel Model>
|
||||
requires StellarEquilibriumModelDiscretizationCompatible<Model, StellarDiscretization>
|
||||
requires StellarEquilibriumModelDiscretizationCompatible<
|
||||
Model,
|
||||
StellarDiscretization>
|
||||
[[nodiscard]] auto discretize(
|
||||
Model &&stellarModel,
|
||||
fem::FEM &finiteElementModel
|
||||
fem::FEM &&finiteElementModel
|
||||
) {
|
||||
return discretize(std::forward<Model>(stellarModel), StellarDiscretization{finiteElementModel});
|
||||
return discretize(std::forward<Model>(stellarModel), StellarDiscretization{std::move(finiteElementModel)});
|
||||
}
|
||||
|
||||
template <StellarEquilibriumModel Model>
|
||||
requires StellarEquilibriumModelDiscretizationCompatible<
|
||||
Model,
|
||||
StellarDiscretization>
|
||||
StellarEquilibriumProblem<
|
||||
std::remove_cvref_t<Model>,
|
||||
StellarDiscretization>
|
||||
discretize(
|
||||
Model &&,
|
||||
fem::FEM &
|
||||
) = delete;
|
||||
} // namespace mean_field::equilibrium
|
||||
|
||||
@@ -17,10 +17,9 @@ export namespace mean_field::equilibrium {
|
||||
|
||||
template <StellarEquilibriumModel Model>
|
||||
[[nodiscard]] auto makeStellarEquilibriumSystem(
|
||||
fem::FEM &finiteElementModel,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
fem::FEM &&finiteElementModel,
|
||||
Model &&stellarModel
|
||||
) {
|
||||
return discretize(std::forward<Model>(stellarModel), StellarDiscretization{finiteElementModel, domainMapper});
|
||||
return discretize(std::forward<Model>(stellarModel), std::move(finiteElementModel));
|
||||
}
|
||||
} // namespace mean_field::equilibrium
|
||||
|
||||
Reference in New Issue
Block a user