def matvec(self, x): tol = 1e-6 maxiter = self.maxiter A = self._matvec b = self._rhs(x) y, info = gmres(A, b, orthog='mgs', tol=tol, maxiter=maxiter) return y
def solve(Mat, b, tol=1e-6, res=[], restart=None, maxiter=300): del res res = [] tt = time() x, info = gmres(Mat, b, orthog='mgs', tol=tol, residuals=res, restrt=restart, maxiter=maxiter) tt = time() - tt print(info, len(res)) res = np.array(res) return x
def my_gmres(mystr, M, b, tol, restart, maxiter): print(mystr.format(restart, maxiter), flush=True) res = [] tt = time() xx, info = gmres(M, b, orthog='mgs', tol=tol, residuals=res, restrt=restart, maxiter=maxiter) tt = time() - tt print(info, len(res)) oRes = np.array(res) Res = rescaleRes(oRes, lambda x: x, b) print('#time: {}'.format(tt)) return (xx, len(Res), Res, tt)
def jacobian_solver(self, psi, mu, rhs): def _apply_jacobian(phi): out = ((0.5 * self.A * phi) / self.mesh.control_volumes + (self.V - mu + 2.0 * (psi.real**2 + psi.imag**2)) * phi + psi**2 * phi.conj()) # out[self.mesh.is_boundary_node] = 1.0 return out n = len(self.mesh.points) jac = LinearOperator((n, n), dtype=complex, matvec=_apply_jacobian, rmatvec=_apply_jacobian) def prec(psi): def _apply(phi): prec = 0.5 * self.A diag = prec.diagonal() cv = self.mesh.control_volumes diag += (self.V + 2.0 * (psi.real**2 + psi.imag**2)) * cv prec.setdiag(diag) # TODO pyamg solve out = spsolve(prec, phi) return out num_unknowns = len(self.mesh.points) return LinearOperator( (num_unknowns, num_unknowns), dtype=complex, matvec=_apply, rmatvec=_apply, ) out, _ = krylov.gmres( A=jac, b=rhs, # M=prec(psi), inner=self.inner, maxiter=100, tol=1.0e-12, # Minv=prec_inv(psi), # U=1j * psi, ) return out.xk
def jacobian_solver(self, psi, mu, rhs): abs_psi2 = np.zeros(psi.shape[0]) abs_psi2[0::2] += psi[0::2]**2 + psi[1::2]**2 cv = to_real(self.mesh.control_volumes) def prec_inv(psi): prec_orig = pyfvm.get_fvm_matrix(self.mesh, edge_kernels=[Energy(mu)]) diag = prec_orig.diagonal() diag += self.g * 2.0 * (psi[0::2]**2 + psi[1::2]**2) * cv[0::2] prec_orig.setdiag(diag) return split_sparse_matrix(prec_orig).tocsr() def prec(psi): p = prec_inv(psi) def _apply(phi): out = spsolve(p, phi) return out num_unknowns = len(self.mesh.points) return LinearOperator( (2 * num_unknowns, 2 * num_unknowns), dtype=float, matvec=_apply, rmatvec=_apply, ) jac = self.jacobian(psi, mu) # Cannot use direct solve since jacobian is always singular # return spsolve(jac, rhs) sol, _ = krylov.gmres( A=jac, b=rhs, # TODO enable preconditioner # M=prec(psi), inner=self.inner, maxiter=100, tol=1.0e-12, ) return sol
def rescaleRes(res, P, b): scale = 1.0 / la.norm(P(b)) new_res = scale * res return new_res ################################################# print('\nWO restart={0} maxiter={1}'.format(restart, maxiter), flush=True) del res res = [] tt = time() xx, info = gmres(M, b, orthog='mgs', tol=tol, residuals=res, restrt=restart, maxiter=maxiter) tt = time() - tt print(info, len(res)) oResWO = np.array(res) ResWO = rescaleRes(oResWO, lambda x: x, b) print('#time: {}'.format(tt)) checker('Calderon WO', A, J, xx) ################################################# print('\nWO bicgstab maxiter={0}'.format(maxiter), flush=True) del res
print("nl:", nl, "dof:", dof) A, X = my.get_A(space, kk), my.get_X(space) b = my.rhs(space, funs) tt = time() - tt J = my.get_J(space) M = A - 0.5 * X MM = spla.LinearOperator(M.shape, matvec=M.matvec, dtype=complex) print('assembled.') res = [] tol = 1e-5 restart, maxiter = None, MM.shape[0] xx, info = gmres(MM, b, orthog='mgs', tol=tol, residuals=res, restrt=restart, maxiter=maxiter) print(info, len(res), MM.shape) ea, et = my.check_sol(space, kk, xx, b, diri, neum, A, X, J) DofErr[j][i, :] = dof, ea, et, tt lw, ms = 3, 10 f, axarr = plt.subplots(2, sharex=True) pls = zip(names, colors) for i, pl in enumerate(pls): n, c = pl axarr[0].loglog(DofErr[i][:, 0], DofErr[i][:, 1], c, label=n,
################################################# def rescaleRes(res, P, b): scale = 1.0 / la.norm(P(b)) new_res = scale * res return new_res ################################################# print("\nWO restart={0} maxiter={1}".format(restart, maxiter), flush=True) del res res = [] tt = time() xx, info = gmres(M, b, orthog="mgs", tol=tol, residuals=res, restrt=restart, maxiter=maxiter) tt = time() - tt print(info, len(res)) oResWO = np.array(res) ResWO = rescaleRes(oResWO, lambda x: x, b) print("#time: {}".format(tt)) checker("Calderon WO", A, J, xx) ################################################# print("\nWO bicgstab maxiter={0}".format(maxiter), flush=True) del res res = [] tt = time() xx, info = bicgstab(M, b, tol=tol, residuals=res, maxiter=maxiter)
a, b = fdir.projections(), fneu.projections() rhs_mtf = 0.5 * np.concatenate((a, -b, -a, -b)) fd, fn = a, b rescaleRes = lambda res, P, rhs: res / la.norm(P(rhs)) print('\nSTF restart={0} maxiter={1}'.format(restart, maxiter), flush=True) Mat, b = stf, rhs_stf print('size: ', stf.shape, 2*shape) del res res = [] tt = time() x_stf, info = gmres(Mat, b, orthog='mgs', tol=tol, residuals=res, restrt=restart, maxiter=maxiter) tt = time() - tt print(info, len(res)) oRes = np.array(res) ResSTF = rescaleRes(oRes, lambda x: x, b) print('#time: {}'.format(tt)) xd_stf, xn_stf = x_stf[0:shape], x_stf[shape:] print('\nMTF restart={0} maxiter={1}'.format(restart, maxiter), flush=True) Mat, b = mtf, rhs_mtf print('size: ', mtf.shape, 4*shape) del res res = []
################################################# def rescaleRes(res, P, b): scale = 1.0 / la.norm(P(b)) new_res = scale * res return new_res ################################################# print('\nWO restart={0} maxiter={1}'.format(restart, maxiter), flush=True) del res res = [] tt = time() xx, info = gmres(J, b, orthog='mgs', tol=tol, residuals=res, restrt=restart, maxiter=maxiter) tt = time() - tt print(info, len(res)) oResWO = np.array(res) ResWO_mass = rescaleRes(oResWO, lambda x: x, b) print('#time: {}'.format(tt)) checker('Calderon WO', A, J, xx) ################################################# print('\nWO restart={0} maxiter={1}'.format(restart, maxiter), flush=True) del res res = []
def jacobian_solver(self, psi, mu, rhs): keo = pyfvm.get_fvm_matrix(self.mesh, edge_kernels=[Energy(mu)]) cv = self.mesh.control_volumes def prec_inv(psi): prec = keo.copy() # Add diagonal to avoid singularity for mu = 0. Also, this is a better # preconditioner. diag = prec.diagonal() diag += self.g * 2.0 * (psi.real**2 + psi.imag**2) * cv prec.setdiag(diag) return prec def prec(psi): p = prec_inv(psi) def _apply(phi): # ml = pyamg.smoothed_aggregation_solver(p, phi) # out = ml.solve(b=phi, tol=1e-12) out = spsolve(p, phi) return out num_unknowns = len(self.mesh.points) return LinearOperator( (num_unknowns, num_unknowns), dtype=complex, matvec=_apply, rmatvec=_apply, ) jac = self.jacobian(psi, mu) sol, info = krylov.gmres( A=jac, b=rhs, M=prec(psi), inner=self.inner, maxiter=100, tol=1.0e-12, # Minv=prec_inv(psi), # U=1j * psi, ) print(f" GMRES: {info.numsteps} it, {info.resnorms[-1]:.3e} resnorm") if not info.success: raise pacopy.JacobianSolverError # print("Krylov residual:", out.resnorms[-1]) # res = jac * out.xk - rhs # print("Krylov residual (explicit):", np.sqrt(self.norm2_r(res))) # self.ax1.semilogy(out.resnorms) # self.ax1.grid() # plt.show() # Since # # (J_psi) psi = K psi + (-1 +2|psi|^2) psi - psi^2 conj(psi) # = K psi - psi + psi |psi|^2 # = f(psi), # # we have (J_psi)(i psi) = i f(psi). The RHS is typically f(psi) or # df/dlmbda(psi), but obviously # # <f(psi), (J_psi)(i psi)> = <f(psi), i f(psi)> = 0, # # so the i*psi-component in the solution plays no role if the rhs is f(psi). # Using 0 as a starting guess for Krylov, the solution will have no component in # the i*psi-direction. This means that the Newton updates won't jump around the # solution manifold. It wouldn't matter if they did, though. # TODO show this for df/dlmbda as well # i_psi = 1j * psi # out.xk -= self.inner(i_psi, out.xk) / self.inner(i_psi, i_psi) * i_psi # print("solution component i*psi", self.inner(i_psi, out.xk) / np.sqrt(self.inner(i_psi, i_psi))) return sol
def rescaleRes(res, P, b): scale = 1.0 / la.norm(P(b)) new_res = scale * res return new_res ################################################# print('\nWO restart={0} maxiter={1}'.format(restart, maxiter), flush=True) del res res = [] tt = time() xx, info = gmres(J, b, orthog='mgs', tol=tol, residuals=res, restrt=restart, maxiter=maxiter) tt = time() - tt print(info, len(res)) oResWO = np.array(res) ResWO_mass = rescaleRes(oResWO, lambda x: x, b) print('#time: {}'.format(tt)) checker('Calderon WO', A, J, xx) ################################################# print('\nWO restart={0} maxiter={1}'.format(restart, maxiter), flush=True) del res
stf, rhs_stf = STF.get(), STF.rhs() mtf, rhs_mtf = MTF.get(), MTF.rhs() rescaleRes = lambda res, P, rhs: res / la.norm(P(rhs)) print('\nSTF restart={0} maxiter={1}'.format(restart, maxiter), flush=True) Mat, b = stf, rhs_stf print('size: ', stf.shape, 2 * shape) del res res = [] tt = time() x_stf, info = gmres(Mat, b, orthog='mgs', tol=tol, residuals=res, restrt=restart, maxiter=maxiter) tt = time() - tt print(info, len(res)) oRes = np.array(res) ResSTF = rescaleRes(oRes, lambda x: x, b) print('#time: {}'.format(tt)) xd_stf, xn_stf = x_stf[0:shape], x_stf[shape:] print('\nMTF restart={0} maxiter={1}'.format(restart, maxiter), flush=True) Mat, b = mtf, rhs_mtf print('size: ', mtf.shape, 4 * shape) del res