def inv(psi, src): self.history = [] verbose = g.default.is_verbose("mr") t = g.timer("mr") t("setup") r, mmr = g.copy(src), g.copy(src) mat(mmr, psi) r @= src - mmr r2 = g.norm2(r) ssq = g.norm2(src) # if ssq == 0.0: # assert r2 != 0.0 # need either source or psi to not be zero # ssq = r2 rsq = self.eps ** 2.0 * ssq for k in range(self.maxiter): t("mat") mat(mmr, r) t("inner") ip, mmr2 = g.inner_product_norm2(mmr, r) if mmr2 == 0.0: continue t("linearcomb") alpha = ip.real / mmr2 * self.relax psi += alpha * r t("axpy_norm") r2 = g.axpy_norm2(r, -alpha, mmr, r) t("other") self.history.append(r2) if verbose: g.message("mr: res^2[ %d ] = %g, target = %g" % (k, r2, rsq)) if r2 <= rsq: if verbose: t() g.message( "mr: converged in %d iterations, took %g s" % (k + 1, t.dt["total"]) ) g.message(t) break
def inv(psi, src, t): t("setup") r, mmr = g.copy(src), g.copy(src) mat(mmr, psi) r @= src - mmr r2 = g.norm2(r) ssq = g.norm2(src) # if ssq == 0.0: # assert r2 != 0.0 # need either source or psi to not be zero # ssq = r2 rsq = self.eps ** 2.0 * ssq for k in range(self.maxiter): t("mat") mat(mmr, r) t("inner") ip, mmr2 = g.inner_product_norm2(mmr, r) if mmr2 == 0.0: continue t("linearcomb") alpha = ip.real / mmr2 * self.relax psi += alpha * r t("axpy_norm") r2 = g.axpy_norm2(r, -alpha, mmr, r) t("other") self.log_convergence(k, r2, rsq) if r2 <= rsq: self.log(f"converged in {k+1} iterations") return self.log( f"NOT converged in {k+1} iterations; squared residual {r2:e} / {rsq:e}" )
def inv(psi, src): self.history = [] verbose = g.default.is_verbose("bicgstab") t = g.timer("bicgstab") t("setup") r, rhat, p, s = g.copy(src), g.copy(src), g.copy(src), g.copy(src) mmpsi, mmp, mms = g.copy(src), g.copy(src), g.copy(src) rho, rhoprev, alpha, omega = 1.0, 1.0, 1.0, 1.0 mat(mmpsi, psi) r @= src - mmpsi rhat @= r p @= r mmp @= r r2 = g.norm2(r) ssq = g.norm2(src) if ssq == 0.0: assert r2 != 0.0 # need either source or psi to not be zero ssq = r2 rsq = self.eps**2.0 * ssq for k in range(self.maxiter): t("inner") rhoprev = rho rho = g.inner_product(rhat, r).real t("linearcomb") beta = (rho / rhoprev) * (alpha / omega) p @= r + beta * p - beta * omega * mmp t("mat") mat(mmp, p) t("inner") alpha = rho / g.inner_product(rhat, mmp).real t("linearcomb") s @= r - alpha * mmp t("mat") mat(mms, s) t("inner") ip, mms2 = g.inner_product_norm2(mms, s) if mms2 == 0.0: continue t("linearcomb") omega = ip.real / mms2 psi += alpha * p + omega * s t("axpy_norm") r2 = g.axpy_norm2(r, -omega, mms, s) t("other") self.history.append(r2) if verbose: g.message("bicgstab: res^2[ %d ] = %g, target = %g" % (k, r2, rsq)) if r2 <= rsq: if verbose: t() g.message( "bicgstab: converged in %d iterations, took %g s" % (k + 1, t.dt["total"])) g.message(t) break
def inv(psi, src, t): t("setup") # parameters rlen = self.restartlen # tensors dtype_r, dtype_c = g.double.real_dtype, g.double.complex_dtype alpha = np.empty((rlen), dtype_c) beta = np.empty((rlen, rlen), dtype_c) gamma = np.empty((rlen), dtype_r) chi = np.empty((rlen), dtype_c) # fields r, mmpsi = g.copy(src), g.copy(src) p = [g.lattice(src) for i in range(rlen)] z = [g.lattice(src) for i in range(rlen)] # initial residual r2 = self.restart(mat, psi, mmpsi, src, r, p) # source ssq = g.norm2(src) if ssq == 0.0: assert r2 != 0.0 # need either source or psi to not be zero ssq = r2 # target residual rsq = self.eps ** 2.0 * ssq for k in range(self.maxiter): # iteration within current krylov space i = k % rlen # iteration criteria need_restart = i + 1 == rlen t("prec") if prec is not None: prec(p[i], r) else: p[i] @= r t("mat") mat(z[i], p[i]) t("ortho") g.orthogonalize(z[i], z[0:i], beta[:, i]) t("linalg") ip, z2 = g.inner_product_norm2(z[i], r) gamma[i] = z2 ** 0.5 if gamma[i] == 0.0: self.debug(f"breakdown, gamma[{i:d}] = 0") break z[i] /= gamma[i] alpha[i] = ip / gamma[i] r2 = g.axpy_norm2(r, -alpha[i], z[i], r) t("other") self.log_convergence((k, i), r2, rsq) if r2 <= rsq or need_restart: t("update_psi") self.update_psi(psi, alpha, beta, gamma, chi, p, i) if r2 <= rsq: msg = f"converged in {k+1} iterations; computed squared residual {r2:e} / {rsq:e}" if self.checkres: res = self.calc_res(mat, psi, mmpsi, src, r) msg += f"; true squared residual {res:e} / {rsq:e}" self.log(msg) return if need_restart: t("restart") r2 = self.restart(mat, psi, mmpsi, src, r, p) self.debug("performed restart") msg = f"NOT converged in {k+1} iterations; computed squared residual {r2:e} / {rsq:e}" if self.checkres: res = self.calc_res(mat, psi, mmpsi, src, r) msg += f"; true squared residual {res:e} / {rsq:e}" self.log(msg)
def inv(psi, src): self.history = [] # verbosity verbose = g.default.is_verbose("fgcr") # timing t = g.timer("fgcr") t("setup") # parameters rlen = self.restartlen # tensors dtype_r, dtype_c = g.double.real_dtype, g.double.complex_dtype alpha = np.empty((rlen), dtype_c) beta = np.empty((rlen, rlen), dtype_c) gamma = np.empty((rlen), dtype_r) chi = np.empty((rlen), dtype_c) # fields r, mmpsi = g.copy(src), g.copy(src) p = [g.lattice(src) for i in range(rlen)] z = [g.lattice(src) for i in range(rlen)] # initial residual r2 = self.restart(mat, psi, mmpsi, src, r, p) # source ssq = g.norm2(src) if ssq == 0.0: assert r2 != 0.0 # need either source or psi to not be zero ssq = r2 # target residual rsq = self.eps**2.0 * ssq for k in range(self.maxiter): # iteration within current krylov space i = k % rlen # iteration criteria reached_maxiter = k + 1 == self.maxiter need_restart = i + 1 == rlen t("prec") if prec is not None: prec(p[i], r) else: p[i] @= r t("mat") mat(z[i], p[i]) t("ortho") g.default.push_verbose("orthogonalize", False) g.orthogonalize(z[i], z[0:i], beta[:, i]) g.default.pop_verbose() t("linalg") ip, z2 = g.inner_product_norm2(z[i], r) gamma[i] = z2**0.5 if gamma[i] == 0.0: g.message("fgcr: breakdown, gamma[%d] = 0" % (i)) break z[i] /= gamma[i] alpha[i] = ip / gamma[i] r2 = g.axpy_norm2(r, -alpha[i], z[i], r) t("other") self.history.append(r2) if verbose: g.message("fgcr: res^2[ %d, %d ] = %g, target = %g" % (k, i, r2, rsq)) if r2 <= rsq or need_restart or reached_maxiter: t("update_psi") self.update_psi(psi, alpha, beta, gamma, chi, p, i) comp_res = r2 / ssq if r2 <= rsq: if verbose: t() g.message( "fgcr: converged in %d iterations, took %g s" % (k + 1, t.total)) g.message(t) if self.checkres: res = self.calc_res(mat, psi, mmpsi, src, r) / ssq g.message( "fgcr: computed res = %g, true res = %g, target = %g" % (comp_res**0.5, res**0.5, self.eps)) else: g.message( "fgcr: computed res = %g, target = %g" % (comp_res**0.5, self.eps)) break if reached_maxiter: if verbose: t() g.message( "fgcr: did NOT converge in %d iterations, took %g s" % (k + 1, t.dt["total"])) g.message(t) if self.checkres: res = self.calc_res(mat, psi, mmpsi, src, r) / ssq g.message( "fgcr: computed res = %g, true res = %g, target = %g" % (comp_res**0.5, res**0.5, self.eps)) else: g.message( "fgcr: computed res = %g, target = %g" % (comp_res**0.5, self.eps)) break if need_restart: t("restart") r2 = self.restart(mat, psi, mmpsi, src, r, p) if verbose: g.message("fgcr: performed restart")
def inv(psi, src, t): t("setup") r, rhat, p, s = g.copy(src), g.copy(src), g.copy(src), g.copy(src) mmpsi, mmp, mms = g.copy(src), g.copy(src), g.copy(src) rho, rhoprev, alpha, omega = 1.0, 1.0, 1.0, 1.0 mat(mmpsi, psi) r @= src - mmpsi rhat @= r p @= r mmp @= r r2 = g.norm2(r) ssq = g.norm2(src) if ssq == 0.0: assert r2 != 0.0 # need either source or psi to not be zero ssq = r2 rsq = self.eps**2.0 * ssq for k in range(self.maxiter): t("inner") rhoprev = rho rho = g.inner_product(rhat, r).real t("linearcomb") beta = (rho / rhoprev) * (alpha / omega) p @= r + beta * p - beta * omega * mmp t("mat") mat(mmp, p) t("inner") alpha = rho / g.inner_product(rhat, mmp).real t("linearcomb") s @= r - alpha * mmp t("mat") mat(mms, s) t("inner") ip, mms2 = g.inner_product_norm2(mms, s) if mms2 == 0.0: continue t("linearcomb") omega = ip.real / mms2 psi += alpha * p + omega * s t("axpy_norm") r2 = g.axpy_norm2(r, -omega, mms, s) t("other") self.log_convergence(k, r2, rsq) if r2 <= rsq: self.log(f"converged in {k+1} iterations") return self.log( f"NOT converged in {k+1} iterations; squared residual {r2:e} / {rsq:e}" )