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

@@ -236,15 +236,13 @@ export namespace mean_field::preconditioning {
* assembly. The current kernels remain polytropic, but selection no
* longer embeds that closed-world type test in the descriptor concept.
*/
template <typename EquationOfState>
struct MaterialSurfaceEquationOfStateBackend {
template <typename EquationOfState> struct MaterialSurfaceEquationOfStateBackend {
static constexpr bool registered = false;
};
template <>
struct MaterialSurfaceEquationOfStateBackend<eos::Polytrope> {
template <> struct MaterialSurfaceEquationOfStateBackend<eos::Polytrope> {
static constexpr bool registered = true;
using CoreType = operators::PreparedStellarEquilibriumOperator;
using CoreType = operators::PreparedStellarEquilibriumOperator;
};
template <typename EquationOfState>
@@ -252,8 +250,7 @@ export namespace mean_field::preconditioning {
{
MaterialSurfaceEquationOfStateBackend<std::remove_cvref_t<EquationOfState>>::registered
} -> std::convertible_to<bool>;
requires MaterialSurfaceEquationOfStateBackend<
std::remove_cvref_t<EquationOfState>>::registered;
requires MaterialSurfaceEquationOfStateBackend<std::remove_cvref_t<EquationOfState>>::registered;
typename MaterialSurfaceEquationOfStateBackend<std::remove_cvref_t<EquationOfState>>::CoreType;
};
@@ -266,13 +263,11 @@ export namespace mean_field::preconditioning {
* truthful while the current kernels still consume the legacy physical
* core directly.
*/
template <typename EquationOfState, typename PhysicalCore>
struct MaterialSurfaceExecutableRuntime {
template <typename EquationOfState, typename PhysicalCore> struct MaterialSurfaceExecutableRuntime {
static constexpr bool available = false;
};
template <>
struct MaterialSurfaceExecutableRuntime<eos::Polytrope, operators::PreparedStellarEquilibriumOperator> {
template <> struct MaterialSurfaceExecutableRuntime<eos::Polytrope, operators::PreparedStellarEquilibriumOperator> {
static constexpr bool available = true;
};
@@ -280,33 +275,28 @@ export namespace mean_field::preconditioning {
concept ExecutableMaterialSurfaceRuntimeFor = requires {
{
MaterialSurfaceExecutableRuntime<
std::remove_cvref_t<EquationOfState>,
std::remove_cvref_t<PhysicalCore>>::available
std::remove_cvref_t<EquationOfState>, std::remove_cvref_t<PhysicalCore>>::available
} -> std::convertible_to<bool>;
requires MaterialSurfaceExecutableRuntime<
std::remove_cvref_t<EquationOfState>,
std::remove_cvref_t<PhysicalCore>>::available;
std::remove_cvref_t<EquationOfState>, std::remove_cvref_t<PhysicalCore>>::available;
};
template <typename Descriptor>
concept ImplementedMaterialSurfaceDescriptor =
MaterialSurfaceDescriptor<Descriptor> &&
ImplementedMaterialSurfaceEquationOfState<
typename Descriptor::ThermodynamicEquations::EquationOfStateType>;
ImplementedMaterialSurfaceEquationOfState<typename Descriptor::ThermodynamicEquations::EquationOfStateType>;
template <typename Descriptor, typename PhysicalCore>
concept MaterialSurfaceRuntimeFor =
ImplementedMaterialSurfaceDescriptor<Descriptor> && requires {
concept MaterialSurfaceRuntimeFor = ImplementedMaterialSurfaceDescriptor<Descriptor> && requires {
typename MaterialSurfaceEquationOfStateBackend<
typename std::remove_cvref_t<Descriptor>::ThermodynamicEquations::EquationOfStateType>::CoreType;
requires std::same_as<
std::remove_cvref_t<PhysicalCore>,
typename MaterialSurfaceEquationOfStateBackend<
typename std::remove_cvref_t<Descriptor>::ThermodynamicEquations::EquationOfStateType>::CoreType;
requires std::same_as<
std::remove_cvref_t<PhysicalCore>,
typename MaterialSurfaceEquationOfStateBackend<
typename std::remove_cvref_t<Descriptor>::ThermodynamicEquations::EquationOfStateType>::CoreType>;
requires ExecutableMaterialSurfaceRuntimeFor<
typename std::remove_cvref_t<Descriptor>::ThermodynamicEquations::EquationOfStateType,
PhysicalCore>;
};
typename std::remove_cvref_t<Descriptor>::ThermodynamicEquations::EquationOfStateType>::CoreType>;
requires ExecutableMaterialSurfaceRuntimeFor<
typename std::remove_cvref_t<Descriptor>::ThermodynamicEquations::EquationOfStateType, PhysicalCore>;
};
template <typename Candidate>
concept MaterialSurfacePreconditionerProblem =
@@ -778,14 +768,14 @@ export namespace mean_field::preconditioning {
fullEnthalpyDirection = enthalpyDirection;
m_operation->Mult(m_fullDirection, m_fullAction);
const auto fullActionView = m_operation->GetRootManifest().residualView(m_fullAction);
const auto fullActionView = m_operation->GetRootManifest().residualView(m_fullAction);
const auto fullDensityAction = fullActionView.block(utils::blocks::density_field.mass_term);
const auto fullSurfaceAction =
fullActionView.block(utils::blocks::surface_deformation_field.shape_equilibrium_term);
const auto fullEnthalpyAction = fullActionView.block(utils::blocks::enthalpy_field.specific_term);
densityAction = fullDensityAction;
surfaceAction = fullSurfaceAction;
enthalpyAction = fullEnthalpyAction;
densityAction = fullDensityAction;
surfaceAction = fullSurfaceAction;
enthalpyAction = fullEnthalpyAction;
}
void ApplyEnthalpyToDensity(
@@ -1121,6 +1111,79 @@ export namespace mean_field::preconditioning {
std::uint64_t regularizedEntries{0};
};
namespace detail {
[[nodiscard]] inline DiagonalPreparationQuality regularizeMaterialSurfaceDiagonal(
mfem::Vector &diagonal,
const MaterialSurfaceDiagonalOptions options,
const MPI_Comm communicator
) {
const int localOptionsAreValid = std::isfinite(options.relativeFloor) && options.relativeFloor >= 0.0 &&
std::isfinite(options.absoluteFloor) && options.absoluteFloor > 0.0
? 1
: 0;
int globalOptionsAreValid = 0;
if (MPI_Allreduce(&localOptionsAreValid, &globalOptionsAreValid, 1, MPI_INT, MPI_MIN, communicator) !=
MPI_SUCCESS) {
throw std::runtime_error("Material-surface regularization could not validate its options.");
}
if (globalOptionsAreValid == 0) {
throw std::invalid_argument("Material-surface diagonal floors must be finite and nonnegative.");
}
double localMaximum = 0.0;
double localMinimum = std::numeric_limits<double>::infinity();
int localEntriesAreFinite = 1;
for (int index = 0; index < diagonal.Size(); ++index) {
if (!std::isfinite(diagonal(index))) {
localEntriesAreFinite = 0;
continue;
}
const double magnitude = std::abs(diagonal(index));
localMaximum = std::max(localMaximum, magnitude);
localMinimum = std::min(localMinimum, magnitude);
}
int globalEntriesAreFinite = 0;
if (MPI_Allreduce(&localEntriesAreFinite, &globalEntriesAreFinite, 1, MPI_INT, MPI_MIN, communicator) !=
MPI_SUCCESS) {
throw std::runtime_error("Material-surface regularization could not validate its diagonal.");
}
if (globalEntriesAreFinite == 0) {
throw std::invalid_argument("A material-surface diagonal contains a non-finite entry.");
}
double globalMaximum = 0.0;
double globalMinimum = 0.0;
const int maximumStatus =
MPI_Allreduce(&localMaximum, &globalMaximum, 1, MPI_DOUBLE, MPI_MAX, communicator);
const int minimumStatus =
MPI_Allreduce(&localMinimum, &globalMinimum, 1, MPI_DOUBLE, MPI_MIN, communicator);
if (maximumStatus != MPI_SUCCESS || minimumStatus != MPI_SUCCESS) {
throw std::runtime_error("Material-surface regularization could not reduce diagonal magnitudes.");
}
const double floor = std::max(options.absoluteFloor, options.relativeFloor * globalMaximum);
std::uint64_t localRegularized = 0;
for (int index = 0; index < diagonal.Size(); ++index) {
if (std::abs(diagonal(index)) < floor) {
diagonal(index) = std::copysign(floor, diagonal(index) == 0.0 ? 1.0 : diagonal(index));
++localRegularized;
}
}
std::uint64_t globalRegularized = 0;
if (MPI_Allreduce(&localRegularized, &globalRegularized, 1, MPI_UINT64_T, MPI_SUM, communicator) !=
MPI_SUCCESS) {
throw std::runtime_error("Material-surface regularization could not count regularized entries.");
}
return {
.minimumAbsoluteEntryBeforeRegularization = globalMinimum,
.maximumAbsoluteEntryBeforeRegularization = globalMaximum,
.appliedFloor = floor,
.regularizedEntries = globalRegularized
};
}
} // namespace detail
struct SurfaceRieszCalibrationReport final {
SurfaceRieszCalibrationTarget target{SurfaceRieszCalibrationTarget::none};
int probeCount{0};
@@ -1522,40 +1585,7 @@ export namespace mean_field::preconditioning {
const MaterialSurfaceDiagonalOptions options,
const MPI_Comm communicator
) {
if (!std::isfinite(options.relativeFloor) || options.relativeFloor < 0.0 ||
!std::isfinite(options.absoluteFloor) || options.absoluteFloor <= 0.0) {
throw std::invalid_argument("Material-surface diagonal floors must be finite and nonnegative.");
}
double localMaximum = 0.0;
double localMinimum = std::numeric_limits<double>::infinity();
for (int index = 0; index < diagonal.Size(); ++index) {
if (!std::isfinite(diagonal(index))) {
throw std::invalid_argument("A material-surface diagonal contains a non-finite entry.");
}
const double magnitude = std::abs(diagonal(index));
localMaximum = std::max(localMaximum, magnitude);
localMinimum = std::min(localMinimum, magnitude);
}
double globalMaximum = 0.0;
double globalMinimum = 0.0;
MPI_Allreduce(&localMaximum, &globalMaximum, 1, MPI_DOUBLE, MPI_MAX, communicator);
MPI_Allreduce(&localMinimum, &globalMinimum, 1, MPI_DOUBLE, MPI_MIN, communicator);
const double floor = std::max(options.absoluteFloor, options.relativeFloor * globalMaximum);
std::uint64_t localRegularized = 0;
for (int index = 0; index < diagonal.Size(); ++index) {
if (std::abs(diagonal(index)) < floor) {
diagonal(index) = std::copysign(floor, diagonal(index) == 0.0 ? 1.0 : diagonal(index));
++localRegularized;
}
}
std::uint64_t globalRegularized = 0;
MPI_Allreduce(&localRegularized, &globalRegularized, 1, MPI_UINT64_T, MPI_SUM, communicator);
return {
.minimumAbsoluteEntryBeforeRegularization = globalMinimum,
.maximumAbsoluteEntryBeforeRegularization = globalMaximum,
.appliedFloor = floor,
.regularizedEntries = globalRegularized
};
return detail::regularizeMaterialSurfaceDiagonal(diagonal, options, communicator);
}
Block m_block;
@@ -2051,40 +2081,7 @@ export namespace mean_field::preconditioning {
const MaterialSurfaceDiagonalOptions options,
const MPI_Comm communicator
) {
if (!std::isfinite(options.relativeFloor) || options.relativeFloor < 0.0 ||
!std::isfinite(options.absoluteFloor) || options.absoluteFloor <= 0.0) {
throw std::invalid_argument("Material-surface diagonal floors must be finite and nonnegative.");
}
double localMaximum = 0.0;
double localMinimum = std::numeric_limits<double>::infinity();
for (int index = 0; index < diagonal.Size(); ++index) {
if (!std::isfinite(diagonal(index))) {
throw std::invalid_argument("A material-surface diagonal contains a non-finite entry.");
}
const double magnitude = std::abs(diagonal(index));
localMaximum = std::max(localMaximum, magnitude);
localMinimum = std::min(localMinimum, magnitude);
}
double globalMaximum = 0.0;
double globalMinimum = 0.0;
MPI_Allreduce(&localMaximum, &globalMaximum, 1, MPI_DOUBLE, MPI_MAX, communicator);
MPI_Allreduce(&localMinimum, &globalMinimum, 1, MPI_DOUBLE, MPI_MIN, communicator);
const double floor = std::max(options.absoluteFloor, options.relativeFloor * globalMaximum);
std::uint64_t localRegularized = 0;
for (int index = 0; index < diagonal.Size(); ++index) {
if (std::abs(diagonal(index)) < floor) {
diagonal(index) = std::copysign(floor, diagonal(index) == 0.0 ? 1.0 : diagonal(index));
++localRegularized;
}
}
std::uint64_t globalRegularized = 0;
MPI_Allreduce(&localRegularized, &globalRegularized, 1, MPI_UINT64_T, MPI_SUM, communicator);
return {
.minimumAbsoluteEntryBeforeRegularization = globalMinimum,
.maximumAbsoluteEntryBeforeRegularization = globalMaximum,
.appliedFloor = floor,
.regularizedEntries = globalRegularized
};
return detail::regularizeMaterialSurfaceDiagonal(diagonal, options, communicator);
}
Block m_block;
@@ -2111,7 +2108,9 @@ export namespace mean_field::preconditioning {
template <
MaterialSurfaceDescriptor Descriptor,
MaterialSurfaceFactorizationPolicy Policy>
requires MaterialSurfaceRuntimeFor<Descriptor, operators::PreparedStellarEquilibriumOperator>
requires MaterialSurfaceRuntimeFor<
Descriptor,
operators::PreparedStellarEquilibriumOperator>
[[nodiscard]] auto prepare(
const operators::PreparedStellarEquilibriumOperator &operation,
MaterialSurfaceBlock<
@@ -2127,12 +2126,17 @@ export namespace mean_field::preconditioning {
equilibrium::StellarEquilibriumModel Model,
equilibrium::StellarDiscretizationType Discretization,
MaterialSurfaceFactorizationPolicy Policy>
requires MaterialSurfacePreconditionerProblem<
equilibrium::StellarEquilibriumProblem<Model, Discretization>>
requires MaterialSurfacePreconditionerProblem<equilibrium::StellarEquilibriumProblem<
Model,
Discretization>>
[[nodiscard]] auto prepare(
const equilibrium::StellarEquilibriumProblem<Model, Discretization> &problem,
const equilibrium::StellarEquilibriumProblem<
Model,
Discretization> &problem,
MaterialSurfaceBlock<
MaterialSurfaceDescriptorFor<equilibrium::StellarEquilibriumProblem<Model, Discretization>>,
MaterialSurfaceDescriptorFor<equilibrium::StellarEquilibriumProblem<
Model,
Discretization>>,
backend::Diagonal,
backend::Diagonal,
Policy> block
@@ -2144,7 +2148,9 @@ export namespace mean_field::preconditioning {
MaterialSurfaceDescriptor Descriptor,
MaterialSurfaceFactorizationPolicy Policy,
backend::ApplicationMode Mode>
requires MaterialSurfaceRuntimeFor<Descriptor, operators::PreparedStellarEquilibriumOperator>
requires MaterialSurfaceRuntimeFor<
Descriptor,
operators::PreparedStellarEquilibriumOperator>
[[nodiscard]] auto prepare(
const operators::PreparedStellarEquilibriumOperator &operation,
MaterialSurfaceBlock<
@@ -2162,12 +2168,17 @@ export namespace mean_field::preconditioning {
equilibrium::StellarDiscretizationType Discretization,
MaterialSurfaceFactorizationPolicy Policy,
backend::ApplicationMode Mode>
requires MaterialSurfacePreconditionerProblem<
equilibrium::StellarEquilibriumProblem<Model, Discretization>>
requires MaterialSurfacePreconditionerProblem<equilibrium::StellarEquilibriumProblem<
Model,
Discretization>>
[[nodiscard]] auto prepare(
const equilibrium::StellarEquilibriumProblem<Model, Discretization> &problem,
const equilibrium::StellarEquilibriumProblem<
Model,
Discretization> &problem,
MaterialSurfaceBlock<
MaterialSurfaceDescriptorFor<equilibrium::StellarEquilibriumProblem<Model, Discretization>>,
MaterialSurfaceDescriptorFor<equilibrium::StellarEquilibriumProblem<
Model,
Discretization>>,
backend::Diagonal,
backend::HypreBoomerAMG<Mode>,
Policy,