31 if (A.rows() != n || A.cols() != n || x.
size() != n) {
32 throw std::invalid_argument(
"Dimension mismatch in operator GMRES solver");
35 throw std::invalid_argument(
"GMRES restart must be positive");
38 restart = std::min(restart, n);
41 std::vector<Vector> V;
42 V.reserve(restart + 1);
43 std::vector<std::vector<real>> H(restart, std::vector<real>(restart + 1, 0.0));
44 std::vector<real> cs(restart, 0.0);
45 std::vector<real> sn(restart, 0.0);
46 std::vector<real> g(restart + 1, 0.0);
51 while (total_iters < max_iter) {
54 for (
idx i = 0; i < n; ++i) {
59 result.residual =
beta;
61 result.converged =
true;
67 for (
idx i = 0; i < n; ++i) {
68 V[0][i] = r[i] /
beta;
72 std::fill(col.begin(), col.end(), 0.0);
74 std::fill(cs.begin(), cs.end(), 0.0);
75 std::fill(sn.begin(), sn.end(), 0.0);
76 std::fill(g.begin(), g.end(), 0.0);
80 for (; j < restart && total_iters < max_iter; ++j, ++total_iters) {
81 result.iterations = total_iters + 1;
83 A.apply(V[j], scratch);
88 if (h_next >
real(1
e-15)) {
96 for (
idx i = 0; i < j; ++i) {
97 real tmp = cs[i] * H[j][i] + sn[i] * H[j][i + 1];
98 H[j][i + 1] = -sn[i] * H[j][i] + cs[i] * H[j][i + 1];
102 real h0 = H[j][j], h1 = H[j][j + 1];
103 real denom = std::sqrt(h0 * h0 + h1 * h1);
104 if (denom <
real(1
e-15)) {
112 H[j][j] = cs[j] * h0 + sn[j] * h1;
115 g[j + 1] = -sn[j] * g[j];
118 result.residual = std::abs(g[j + 1]);
119 if (result.residual < tol) {
120 result.converged =
true;
127 std::vector<real> y(m, 0.0);
128 for (
idx i = m; i > 0;) {
131 for (
idx k = i + 1; k < m; ++k) {
132 y[i] -= H[k][i] * y[k];
137 for (
idx i = 0; i < m; ++i) {
138 for (
idx k = 0; k < n; ++k) {
139 x[k] += y[i] * V[i][k];
143 if (result.converged) {
SolverResult gmres(const Op &A, const Vector &b, Vector &x, real tol=1e-6, idx max_iter=1000, idx restart=30)
Operator GMRES for any adapter.