feat(newton): first newton solver implementation
This commit is contained in:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user