33 lines
1.7 KiB
C++
33 lines
1.7 KiB
C++
|
|
#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);
|
||
|
|
}
|
||
|
|
}
|