def __call__(self, mat, src, psi): verbose = g.default.is_verbose("mr") t0 = time() r, mmr = g.copy(src), g.copy(src) mat(psi, mmr) r @= src - mmr ssq = g.norm2(src) rsq = self.eps**2. * ssq for k in range(self.maxiter): mat(r, mmr) ip, mmr2 = g.innerProductNorm2(mmr, r) if mmr2 == 0.: continue alpha = ip.real / mmr2 * self.relax psi += alpha * r r2 = g.axpy_norm2(r, -alpha, mmr, r) if verbose: g.message("res^2[ %d ] = %g" % (k, r2)) if r2 <= rsq: if verbose: t1 = time() g.message("Converged in %g s" % (t1 - t0)) break
def __call__(self, mat, src, psi): assert (src != psi) self.history = [] verbose = g.default.is_verbose("cg") t0 = g.time() p, mmp, r = g.copy(src), g.copy(src), g.copy(src) guess = g.norm2(psi) mat(psi, mmp) # in, out d = g.innerProduct(psi, mmp).real b = g.norm2(mmp) r @= src - mmp p @= r a = g.norm2(p) cp = a ssq = g.norm2(src) rsq = self.eps**2. * ssq for k in range(1, self.maxiter + 1): c = cp mat(p, mmp) dc = g.innerProduct(p, mmp) d = dc.real a = c / d cp = g.axpy_norm2(r, -a, mmp, r) b = cp / c psi += a * p p @= b * p + r self.history.append(cp) if verbose: g.message("res^2[ %d ] = %g" % (k, cp)) if cp <= rsq: if verbose: t1 = g.time() g.message("Converged in %g s" % (t1 - t0)) break
def __call__(self, mat, src, psi): verbose = g.default.is_verbose("bicgstab") t0 = time() 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., 1., 1., 1. mat(psi, mmpsi) r @= src - mmpsi rhat @= r p @= r mmp @= r ssq = g.norm2(src) rsq = self.eps**2. * ssq for k in range(self.maxiter): rhoprev = rho rho = g.innerProduct(rhat, r).real beta = (rho / rhoprev) * (alpha / omega) p @= r + beta * p - beta * omega * mmp mat(p, mmp) alpha = rho / g.innerProduct(rhat, mmp).real s @= r - alpha * mmp mat(s, mms) ip, mms2 = g.innerProductNorm2(mms, s) if mms2 == 0.: continue omega = ip.real / mms2 psi += alpha * p + omega * s r2 = g.axpy_norm2(r, -omega, mms, s) if verbose: g.message("res^2[ %d ] = %g" % (k, r2)) if r2 <= rsq: if verbose: t1 = time() g.message("Converged in %g s" % (t1 - t0)) break
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): assert src != psi self.history = [] verbose = g.default.is_verbose("cg") t = g.timer("cg") t("setup") p, mmp, r = g.copy(src), g.copy(src), g.copy(src) mat(mmp, psi) # in, out d = g.inner_product(psi, mmp).real b = g.norm2(mmp) r @= src - mmp p @= r a = g.norm2(p) cp = a ssq = g.norm2(src) if ssq == 0.0: assert a != 0.0 # need either source or psi to not be zero ssq = a rsq = self.eps ** 2.0 * ssq for k in range(1, self.maxiter + 1): c = cp t("mat") mat(mmp, p) t("inner") dc = g.inner_product(p, mmp) d = dc.real a = c / d t("axpy_norm") cp = g.axpy_norm2(r, -a, mmp, r) t("linearcomb") b = cp / c psi += a * p p @= b * p + r t("other") self.history.append(cp) if verbose: g.message("cg: res^2[ %d ] = %g, target = %g" % (k, cp, rsq)) if cp <= rsq: if verbose: t() g.message( "cg: converged in %d iterations, took %g s" % (k, 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, t): assert src != psi t("setup") p, mmp, r = g.copy(src), g.copy(src), g.copy(src) mat(mmp, psi) # in, out d = g.inner_product(psi, mmp).real b = g.norm2(mmp) r @= src - mmp p @= r a = g.norm2(p) cp = a ssq = g.norm2(src) if ssq == 0.0: psi[:] = 0 return rsq = self.eps ** 2.0 * ssq for k in range(self.maxiter): c = cp t("matrix") mat(mmp, p) t("inner_product") dc = g.inner_product(p, mmp) d = dc.real a = c / d t("axpy_norm2") cp = g.axpy_norm2(r, -a, mmp, r) t("linear combination") b = cp / c psi += a * p p @= b * p + r t("other") self.log_convergence(k, cp, rsq) if cp <= rsq: self.log(f"converged in {k+1} iterations") return self.log( f"NOT converged in {k+1} iterations; squared residual {cp:e} / {rsq:e}" )
def calc_res(self, mat, psi, mmpsi, src, r): mat(psi, mmpsi) return g.axpy_norm2(r, -1., mmpsi, src)
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): assert src != psi t("setup") p, mmp, r = g.lattice(src), g.lattice(src), g.lattice(src) if prec is not None: z = g.lattice(src) t("matrix") mat(mmp, psi) # in, out t("setup") g.axpy(r, -1.0, mmp, src) if prec is not None: z[:] = 0 prec(z, r) g.copy(p, z) cp = g.inner_product(r, z).real else: g.copy(p, r) cp = g.norm2(p) ssq = g.norm2(src) if ssq == 0.0: psi[:] = 0 return rsq = self.eps**2.0 * ssq for k in range(self.maxiter): c = cp t("matrix") mat(mmp, p) t("inner_product") d = g.inner_product(p, mmp).real a = c / d t("axpy_norm2") if prec is not None: # c = <r,z>, d = <p,A p> g.axpy(r, -a, mmp, r) t("prec") z[:] = 0 prec(z, r) t("axpy_norm2") cp = g.inner_product(r, z).real else: cp = g.axpy_norm2(r, -a, mmp, r) t("linear combination") b = cp / c psi += a * p if prec is not None: g.axpy(p, b, p, z) else: g.axpy(p, b, p, r) t("other") res = abs(cp) self.log_convergence(k, res, rsq) if k + 1 >= self.miniter: if self.eps_abs is not None and res <= self.eps_abs**2.0: self.log( f"converged in {k+1} iterations (absolute criterion)" ) return if res <= rsq: self.log(f"converged in {k+1} iterations") return self.log( f"NOT converged in {k+1} iterations; squared residual {res:e} / {rsq:e}" )
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 calc_res(self, mat, psi, mmpsi, src, r, t): t("res - mat") mat(mmpsi, psi) t("res - axpy") return g.axpy_norm2(r, -1.0, mmpsi, src)
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}" )
def __call__(self, mat, src, psi, prec=None): # verbosity verbose = g.default.is_verbose("fgcr") checkres = True # for now # total time tt0 = time() # parameters rlen = self.restartlen # tensors dtype_r, dtype_c = np.float64, np.complex128 alpha = np.empty((rlen), dtype_c) beta = np.empty((rlen, rlen), dtype_c) gamma = np.empty((rlen), dtype_r) delta = np.empty((rlen), dtype_c) # fields r, mmr, mmpsi = g.copy(src), g.copy(src), g.copy(src) p = [g.lattice(src) for i in range(rlen)] mmp = [g.lattice(src) for i in range(rlen)] # residual target ssq = g.norm2(src) rsq = self.eps**2. * ssq # initial values r2 = self.restart(mat, psi, mmpsi, src, r) 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 t0 = time() if not prec is None: prec(r, p[i]) else: p[i] @= r t1 = time() t2 = time() mat(p[i], mmp[i]) t3 = time() t4 = time() g.orthogonalize(mmp[i], mmp[0:i], beta[:, i]) t5 = time() t6 = time() ip, mmp2 = g.innerProductNorm2(mmp[i], r) gamma[i] = mmp2**0.5 if gamma[i] == 0.: g.message("fgcr breakdown, gamma[%d] = 0" % (i)) break mmp[i] /= gamma[i] alpha[i] = ip / gamma[i] r2 = g.axpy_norm2(r, -alpha[i], mmp[i], r) t7 = time() if verbose: g.message( "Timing[s]: Prec = %g, Matrix = %g, Orthog = %g, Rest = %g" % (t1 - t0, t3 - t2, t5 - t4, t7 - t6)) g.message("res^2[ %d, %d ] = %g" % (k, i, r2)) if r2 <= rsq or need_restart or reached_maxiter: self.update_psi(psi, alpha, beta, gamma, delta, p, i) if r2 <= rsq: if verbose: tt1 = time() g.message("Converged in %g s" % (tt1 - tt0)) if checkres: res = self.calc_res(mat, psi, mmpsi, src, r) / ssq g.message( "Computed res = %g, true res = %g, target = %g" % (r2**0.5, res**0.5, self.eps)) break if reached_maxiter: if verbose: tt1 = time() g.message("Did NOT converge in %g s" % (tt1 - tt0)) if checkres: res = self.calc_res(mat, psi, mmpsi, src, r) / ssq g.message( "Computed res = %g, true res = %g, target = %g" % (r2**0.5, res**0.5, self.eps)) if need_restart: r2 = self.restart(mat, psi, mmpsi, src, r) if verbose: g.message("Performed restart")
def inv(psi, src, t): if len(src) > 1: n = len(src) # do different sources separately for idx in range(n): inv(psi[idx::n], [src[idx]]) return src = src[0] scgs = [] for j, s in enumerate(self.shifts): scgs += [shifted_cg(psi[j], src, s)] t("setup") p, mmp, r = g.copy(src), g.copy(src), g.copy(src) x = g.copy(src) x[:] = 0 b = 0.0 a = g.norm2(p) cp = a assert a != 0.0 # need either source or psi to not be zero rsq = self.eps**2.0 * a for k in range(self.maxiter): c = cp t("matrix") mat(mmp, p) t("inner_product") dc = g.inner_product(p, mmp) d = dc.real om = b / a a = c / d om *= a t("axpy_norm2") cp = g.axpy_norm2(r, -a, mmp, r) t("linear combination") b = cp / c for cg in scgs: if not cg.converged: cg.step1(a, b, om) x += a * p p @= b * p + r for cg in scgs: if not cg.converged: cg.step2(r) t("other") for cg in scgs: msg = cg.check(cp, rsq) if msg: self.log(f"{msg} at iteration {k+1}") if sum([cg.converged for cg in scgs]) == ns: return self.log( f"NOT converged in {k+1} iterations; squared residual {cp:e} / {rsq:e}" )