13#ifndef CD_KRYLOVGMRESIMPLEM_H
14#define CD_KRYLOVGMRESIMPLEM_H
26#include <CD_NamespaceHeader.H>
38 CH_TIME(
"KrylovGMRES::define");
43 m_allocRestart = std::max(1, m_restart);
45 m_basis.resize(m_allocRestart + 1);
46 for (
int i = 0; i < m_basis.size(); i++) {
47 m_op->create(m_basis[i], a_template);
49 m_op->create(m_w, a_template);
50 m_op->create(m_z, a_template);
51 m_op->create(m_c, a_template);
52 m_op->create(m_r, a_template);
54 m_H = Vector<Real>((m_allocRestart + 1) * m_allocRestart, 0.0);
55 m_cs = Vector<Real>(m_allocRestart, 0.0);
56 m_sn = Vector<Real>(m_allocRestart, 0.0);
57 m_g = Vector<Real>(m_allocRestart + 1, 0.0);
58 m_y = Vector<Real>(m_allocRestart, 0.0);
59 m_hcol = Vector<Real>(m_allocRestart, 0.0);
60 m_corr = Vector<Real>(m_allocRestart, 0.0);
70 for (
int i = 0; i < m_basis.size(); i++) {
71 m_op->clear(m_basis[i]);
96 CH_TIME(
"KrylovGMRES::solve");
98 CH_assert(m_isDefined);
104 const int m = m_allocRestart;
105 const int ldH = m + 1;
107 const auto Hidx = [ldH](
const int r,
const int c) ->
int {
113 op.
axby(m_r, a_rhs, m_r, 1.0, -1.0);
115 const Real beta0 = op.
norm(m_r, 2);
118 m_residualNorm = 0.0;
126 while (iter < m_maxIter && rnorm > m_eps * beta0) {
129 const Real beta = op.
norm(m_r, 2);
130 op.
assign(m_basis[0], m_r);
131 op.
scale(m_basis[0], 1.0 / beta);
133 for (
int i = 0; i <= m; i++) {
140 for (
int j = 0; j < m && iter < m_maxIter; j++) {
150 op.
mDotProduct(m_w, j + 1, &m_basis[0], &m_hcol[0]);
152 for (
int i = 0; i <= j; i++) {
153 op.
incr(m_w, m_basis[i], -m_hcol[i]);
154 m_H[Hidx(i, j)] = m_hcol[i];
157 if (m_reorthogonalize) {
158 op.
mDotProduct(m_w, j + 1, &m_basis[0], &m_corr[0]);
160 for (
int i = 0; i <= j; i++) {
161 op.
incr(m_w, m_basis[i], -m_corr[i]);
162 m_H[Hidx(i, j)] += m_corr[i];
166 const Real hjp1 = op.
norm(m_w, 2);
167 m_H[Hidx(j + 1, j)] = hjp1;
169 op.
assign(m_basis[j + 1], m_w);
170 op.
scale(m_basis[j + 1], 1.0 / hjp1);
174 for (
int k = 0; k < j; k++) {
175 const Real t = m_cs[k] * m_H[Hidx(k, j)] + m_sn[k] * m_H[Hidx(k + 1, j)];
176 m_H[Hidx(k + 1, j)] = -m_sn[k] * m_H[Hidx(k, j)] + m_cs[k] * m_H[Hidx(k + 1, j)];
181 const Real hjj = m_H[Hidx(j, j)];
182 const Real hj1j = m_H[Hidx(j + 1, j)];
183 const Real denom = std::sqrt(hjj * hjj + hj1j * hj1j);
189 m_cs[j] = hjj / denom;
190 m_sn[j] = hj1j / denom;
191 m_H[Hidx(j, j)] = denom;
192 m_H[Hidx(j + 1, j)] = 0.0;
194 const Real gtemp = m_cs[j] * m_g[j];
195 m_g[j + 1] = -m_sn[j] * m_g[j];
198 rnorm = std::abs(m_g[j + 1]);
201 if (m_verbosity >= 3) {
202 pout() <<
" KrylovGMRES:: iteration = " << iter <<
", rel. residual = " << (rnorm / m_residualScale)
206 if (rnorm <= m_eps * beta0 || hjp1 == 0.0) {
212 for (
int i = jUsed - 1; i >= 0; i--) {
215 for (
int k = i + 1; k < jUsed; k++) {
216 s -= m_H[Hidx(i, k)] * m_y[k];
219 m_y[i] = (m_H[Hidx(i, i)] != 0.0) ? s / m_H[Hidx(i, i)] : 0.0;
224 for (
int k = 0; k < jUsed; k++) {
225 op.
incr(m_c, m_basis[k], m_y[k]);
229 op.
incr(a_phi, m_z, 1.0);
233 op.
axby(m_r, a_rhs, m_r, 1.0, -1.0);
234 rnorm = op.
norm(m_r, 2);
241 m_exitStatus = (rnorm <= m_eps * beta0) ? 1 : 3;
242 m_residualNorm = rnorm;
245 return (m_exitStatus == 1);
248#include <CD_NamespaceFooter.H>
Restarted, right-preconditioned GMRES over an AMR hierarchy, with persistent basis and fused reductio...
Adapter presenting an already-defined AMRMultiGrid as a LinearOp over the AMR hierarchy.
Definition CD_AMRMultigridKrylovOp.H:78
void incr(Vector< LevelData< T > * > &a_lhs, const Vector< LevelData< T > * > &a_x, Real a_scale) override
Increment a_lhs += a_scale*a_x.
Definition CD_AMRMultigridKrylovOpImplem.H:275
void assign(Vector< LevelData< T > * > &a_lhs, const Vector< LevelData< T > * > &a_rhs) override
Copy a_rhs into a_lhs.
Definition CD_AMRMultigridKrylovOpImplem.H:154
void preCond(Vector< LevelData< T > * > &a_cor, const Vector< LevelData< T > * > &a_residual) override
Apply the preconditioner: a_cor approx L^{-1} a_residual via m_numVCycles multigrid cycles (cycle typ...
Definition CD_AMRMultigridKrylovOpImplem.H:97
void mDotProduct(const Vector< LevelData< T > * > &a_1, const int a_sz, const Vector< LevelData< T > * > a_2[], Real a_mdots[]) override
Batched inner products a_mdots[k] = dotProduct(a_1, a_2[k]) for k=0..a_sz-1.
Definition CD_AMRMultigridKrylovOpImplem.H:214
void axby(Vector< LevelData< T > * > &a_lhs, const Vector< LevelData< T > * > &a_x, const Vector< LevelData< T > * > &a_y, Real a_a, Real a_b) override
Set a_lhs = a_a*a_x + a_b*a_y.
Definition CD_AMRMultigridKrylovOpImplem.H:284
void applyOp(Vector< LevelData< T > * > &a_lhs, const Vector< LevelData< T > * > &a_phi, bool a_homogeneous=false) override
Matrix-vector product L(phi) over the AMR hierarchy (always homogeneous for the Krylov path).
Definition CD_AMRMultigridKrylovOpImplem.H:74
Real norm(const Vector< LevelData< T > * > &a_rhs, int a_ord) override
Norm of a_rhs. For a_ord==2 this is the inner-product-induced norm sqrt(dotProduct(x,...
Definition CD_AMRMultigridKrylovOpImplem.H:306
void setToZero(Vector< LevelData< T > * > &a_lhs) override
Set a_lhs = 0.
Definition CD_AMRMultigridKrylovOpImplem.H:322
void scale(Vector< LevelData< T > * > &a_lhs, const Real &a_scale) override
Scale a_lhs *= a_scale.
Definition CD_AMRMultigridKrylovOpImplem.H:297
bool isDefined() const noexcept
Whether define() has been called.
Definition CD_KrylovGMRESImplem.H:87
~KrylovGMRES() noexcept
Destructor. Frees the persistent basis and scratch.
Definition CD_KrylovGMRESImplem.H:29
void define(AMRMultigridKrylovOp< T > *a_op, const Vector< LevelData< T > * > &a_template) noexcept
Allocate the persistent basis (m_restart + 1 vectors) and scratch. Call once per regrid.
Definition CD_KrylovGMRESImplem.H:36
bool solve(Vector< LevelData< T > * > &a_phi, const Vector< LevelData< T > * > &a_rhs) noexcept
Solve a_op(a_phi) = a_rhs (homogeneous operator) with restarted GMRES(m_restart).
Definition CD_KrylovGMRESImplem.H:94
void undefine() noexcept
Free the persistent basis and scratch.
Definition CD_KrylovGMRESImplem.H:67