feat(solver/linear): Implemented a few linear solver frontends

As with much of the code, the actual solvers are implemented (through MFEM) in the backend. This provides an interface so we can more easily swap out the linear solvers on the backend in the future
This commit is contained in:
2026-11-09 13:25:52 -05:00
parent 64cc306a2c
commit f520fe5f03
3 changed files with 106 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
#include "serif/solver/linear/linear.hpp"
#include <algorithm>
#include <cmath>
#include <stdexcept>
#include "serif/utils/error/errors.hpp"
namespace serif::solver::linear {
void Control::validate() const {
utils::errors::serif_ensure<utils::errors::SERiFErrorCode::SOLVER_ERROR, std::invalid_argument>(
std::isfinite(relative_tolerance) && relative_tolerance >= 0.0 &&
std::isfinite(absolute_tolerance) && absolute_tolerance >= 0.0 && maximum_iterations > 0,
"A linear solve needs finite nonnegative tolerances and a positive iteration budget; received {}, {}, and {}.",
relative_tolerance, absolute_tolerance, maximum_iterations);
}
double Control::convergence_threshold(double right_hand_side_norm) const {
validate();
const double relative_threshold = relative_tolerance * right_hand_side_norm;
utils::errors::serif_ensure<utils::errors::SERiFErrorCode::SOLVER_ERROR, std::invalid_argument>(
std::isfinite(right_hand_side_norm) && right_hand_side_norm >= 0.0 && std::isfinite(relative_threshold),
"A linear convergence threshold needs a finite nonnegative right-hand-side norm and finite product with the relative tolerance; received {}.",
right_hand_side_norm);
return std::max(absolute_tolerance, relative_threshold);
}
void FGMRES::validate() const {
utils::errors::serif_ensure<utils::errors::SERiFErrorCode::SOLVER_ERROR, std::invalid_argument>(
restart_length > 0 && print_level >= -1 && print_level <= 3,
"FGMRES needs a positive restart length and print level between -1 and 3; received {} and {}.", restart_length, print_level);
}
}