def _SolveImpl(self, rhs: BaseVector, sol: BaseVector): d, w, s = [sol.CreateVector() for i in range(3)] conjugate = self.conjugate d.data = rhs - self.mat * sol w.data = self.pre * d s.data = w wdn = w.InnerProduct(d, conjugate=conjugate) if self.CheckResidual(sqrt(abs(wdn))): return while True: w.data = self.mat * s wd = wdn as_s = s.InnerProduct(w, conjugate=conjugate) if as_s == 0 or wd == 0: break alpha = wd / as_s sol.data += alpha * s d.data += (-alpha) * w w.data = self.pre * d wdn = w.InnerProduct(d, conjugate=conjugate) if self.CheckResidual(sqrt(abs(wdn))): return beta = wdn / wd s *= beta s.data += w
def _SolveImpl(self, rhs: BaseVector, sol: BaseVector): r = rhs.CreateVector() d = sol.CreateVector() r.data = rhs - self.mat * sol d.data = self.pre * r res_norm = abs(InnerProduct(d, r)) if self.CheckResidual(res_norm): return while True: sol.data += self.dampfactor * d r.data = rhs - self.mat * sol d.data = self.pre * r res_norm = abs(InnerProduct(d, r)) if self.CheckResidual(res_norm): return
def Solve(self, rhs: BaseVector, sol: Optional[BaseVector] = None, initialize: bool = True) -> BaseVector: old_status = _GetStatus() _PushStatus(self.name + " Solve") _SetThreadPercentage(0) if sol is None: sol = rhs.CreateVector() initialize = True if initialize: sol[:] = 0 self.sol = sol self._SolveImpl(rhs=rhs, sol=sol) if old_status[0] != "idle": _PushStatus(old_status[0]) _SetThreadPercentage(old_status[1]) return sol
def _SolveImpl(self, rhs: BaseVector, sol: BaseVector): is_complex = rhs.is_complex A, pre, innerproduct, norm = self.mat, self.pre, self.innerproduct, self.norm n = len(rhs) m = self.maxiter sn = Vector(m, is_complex) cs = Vector(m, is_complex) sn[:] = 0 cs[:] = 0 if self.callback_sol is not None: sol_start = sol.CreateVector() sol_start.data = sol r = rhs.CreateVector() tmp = rhs.CreateVector() tmp.data = rhs - A * sol r.data = pre * tmp Q = [] H = [] Q.append(rhs.CreateVector()) r_norm = norm(r) if self.CheckResidual(abs(r_norm)): return sol Q[0].data = 1. / r_norm * r beta = Vector(m + 1, is_complex) beta[:] = 0 beta[0] = r_norm def arnoldi(A, Q, k): q = rhs.CreateVector() tmp.data = A * Q[k] q.data = pre * tmp h = Vector(m + 1, is_complex) h[:] = 0 for i in range(k + 1): h[i] = innerproduct(Q[i], q) q.data += (-1) * h[i] * Q[i] h[k + 1] = norm(q) if abs(h[k + 1]) < 1e-12: return h, None q *= 1. / h[k + 1].real return h, q def givens_rotation(v1, v2): if v2 == 0: return 1, 0 elif v1 == 0: return 0, v2 / abs(v2) else: t = sqrt((v1.conjugate() * v1 + v2.conjugate() * v2).real) cs = abs(v1) / t sn = v1 / abs(v1) * v2.conjugate() / t return cs, sn def apply_givens_rotation(h, cs, sn, k): for i in range(k): temp = cs[i] * h[i] + sn[i] * h[i + 1] h[i + 1] = -sn[i].conjugate() * h[i] + cs[i].conjugate() * h[i + 1] h[i] = temp cs[k], sn[k] = givens_rotation(h[k], h[k + 1]) h[k] = cs[k] * h[k] + sn[k] * h[k + 1] h[k + 1] = 0 def calcSolution(k): # if callback_sol is set we need to recompute solution in every step if self.callback_sol is not None: sol.data = sol_start mat = Matrix(k + 1, k + 1, is_complex) for i in range(k + 1): mat[:, i] = H[i][:k + 1] rs = Vector(k + 1, is_complex) rs[:] = beta[:k + 1] y = mat.I * rs for i in range(k + 1): sol.data += y[i] * Q[i] for k in range(m): h, q = arnoldi(A, Q, k) H.append(h) if q is None: break Q.append(q) apply_givens_rotation(h, cs, sn, k) beta[k + 1] = -sn[k].conjugate() * beta[k] beta[k] = cs[k] * beta[k] error = abs(beta[k + 1]) if self.callback_sol is not None: calcSolution(k) if self.CheckResidual(error): break if self.restart is not None and ( k + 1 == self.restart and not (self.restart == self.maxiter)): calcSolution(k) del Q restarted_solver = GMResSolver(mat=self.mat, pre=self.pre, tol=0, atol=self._final_residual, callback=self.callback, callback_sol=self.callback_sol, maxiter=self.maxiter, restart=self.restart, printrates=self.printrates) restarted_solver.iterations = self.iterations sol = restarted_solver.Solve(rhs=rhs, sol=sol, initialize=False) self.residuals += restarted_solver.residuals self.iterations = restarted_solver.iterations return sol calcSolution(k) return sol
def _SolveImpl(self, rhs: BaseVector, sol: BaseVector): pre, mat, u = self.pre, self.mat, sol v_new = rhs.CreateVector() v = rhs.CreateVector() v_old = rhs.CreateVector() w_new = rhs.CreateVector() w = rhs.CreateVector() w_old = rhs.CreateVector() z_new = rhs.CreateVector() z = rhs.CreateVector() mz = rhs.CreateVector() v.data = rhs - mat * u z.data = pre * v #First Step gamma = sqrt(InnerProduct(z, v)) gamma_new = 0 z.data = 1 / gamma * z v.data = 1 / gamma * v ResNorm = gamma ResNorm_old = gamma if self.CheckResidual(ResNorm): return eta_old = gamma c_old = 1 c = 1 s_new = 0 s = 0 s_old = 0 v_old[:] = 0.0 w_old[:] = 0.0 w[:] = 0.0 k = 1 while True: mz.data = mat * z delta = InnerProduct(mz, z) v_new.data = mz - delta * v - gamma * v_old z_new.data = pre * v_new gamma_new = sqrt(InnerProduct(z_new, v_new)) z_new *= 1 / gamma_new v_new *= 1 / gamma_new alpha0 = c * delta - c_old * s * gamma alpha1 = sqrt(alpha0 * alpha0 + gamma_new * gamma_new) #** alpha2 = s * delta + c_old * c * gamma alpha3 = s_old * gamma c_new = alpha0 / alpha1 s_new = gamma_new / alpha1 w_new.data = z - alpha3 * w_old - alpha2 * w w_new.data = 1 / alpha1 * w_new u.data += c_new * eta_old * w_new eta = -s_new * eta_old #update of residuum ResNorm = abs(s_new) * ResNorm_old if self.CheckResidual(ResNorm): return k += 1 # shift vectors by renaming v_old, v, v_new = v, v_new, v_old w_old, w, w_new = w, w_new, w_old z, z_new = z_new, z eta_old = eta s_old = s s = s_new c_old = c c = c_new gamma = gamma_new ResNorm_old = ResNorm
def _SolveImpl(self, rhs: BaseVector, sol: BaseVector): u, mat, ep, pre1, pre2 = sol, self.mat, self.ep, self.pre, self.pre2 r = rhs.CreateVector() v = rhs.CreateVector() v_tld = rhs.CreateVector() w = rhs.CreateVector() w_tld = rhs.CreateVector() y = rhs.CreateVector() y_tld = rhs.CreateVector() z = rhs.CreateVector() z_tld = rhs.CreateVector() p = rhs.CreateVector() p_tld = rhs.CreateVector() q = rhs.CreateVector() d = rhs.CreateVector() s = rhs.CreateVector() r.data = rhs - mat * u v_tld.data = r y.data = pre1 * v_tld rho = InnerProduct(y, y) rho = sqrt(rho) w_tld.data = r z.data = pre2.T * w_tld if pre2 else w_tld xi = InnerProduct(z, z) xi = sqrt(xi) gamma = 1.0 eta = -1.0 theta = 0.0 for i in range(1, self.maxiter + 1): if (rho == 0.0): print('Breakdown in rho') return if (xi == 0.0): print('Breakdown in xi') return v.data = (1.0 / rho) * v_tld y.data = (1.0 / rho) * y w.data = (1.0 / xi) * w_tld z.data = (1.0 / xi) * z delta = InnerProduct(z, y) if (delta == 0.0): print('Breakdown in delta') return y_tld.data = pre2 * y if pre2 else y z_tld.data = pre1.T * z if (i > 1): p.data = (-xi * delta / ep) * p p.data += y_tld q.data = (-rho * delta / ep) * q q.data += z_tld else: p.data = y_tld q.data = z_tld p_tld.data = mat * p ep = InnerProduct(q, p_tld) if (ep == 0.0): print('Breakdown in epsilon') return beta = ep / delta if (beta == 0.0): print('Breakdown in beta') return v_tld.data = p_tld - beta * v y.data = pre1 * v_tld rho_1 = rho rho = InnerProduct(y, y) rho = sqrt(rho) w_tld.data = mat.T * q w_tld.data -= beta * w z.data = pre2.T * w_tld if pre2 else w_tld xi = InnerProduct(z, z) xi = sqrt(xi) gamma_1 = gamma theta_1 = theta theta = rho / (gamma_1 * abs(beta)) gamma = 1.0 / sqrt(1.0 + theta * theta) if (gamma == 0.0): print('Breakdown in gamma') return eta = -eta * rho_1 * gamma * gamma / (beta * gamma_1 * gamma_1) if (i > 1): d.data = (theta_1 * theta_1 * gamma * gamma) * d d.data += eta * p s.data = (theta_1 * theta_1 * gamma * gamma) * s s.data += eta * p_tld else: d.data = eta * p s.data = eta * p_tld u.data += d r.data -= s #Projected residuum: Better terminating condition necessary? v.data = self.pre * r ResNorm = sqrt(InnerProduct(r, v)) # ResNorm = sqrt( np.dot(r.FV().NumPy()[fdofs],r.FV().NumPy()[fdofs])) #ResNorm = sqrt(InnerProduct(r,r)) if self.CheckResidual(ResNorm): return