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(