def test_minres_deflation(self): # Create sparse symmetric problem. num_unknowns = 100 A = self._create_sparse_herm_indef_matrix(num_unknowns) rhs = np.ones( (num_unknowns,1) ) x0 = np.zeros( (num_unknowns,1) ) # get projection from scipy.sparse.linalg import eigs num_vecs = 6 D, W = eigs(A, k=num_vecs, v0=np.ones((num_unknowns,1))) # Uncomment next lines to perturb W #W = W + 1.e-10*np.random.rand(W.shape[0], W.shape[1]) #from scipy.linalg import qr #W, R = qr(W, mode='economic') AW = nm._apply(A, W) P, x0new = nm.get_projection( W, AW, rhs, x0 ) # Solve using MINRES. tol = 1.0e-9 out = nm.minres( A, rhs, x0new, Mr=P, tol=tol, maxiter=num_unknowns-num_vecs, full_reortho=True, return_basis=True ) # TODO: move to new unit test o = nm.get_p_ritz( W, AW, out['Vfull'], out['Hfull'] ) ritz_vals, ritz_vecs = nm.get_p_ritz( W, AW, out['Vfull'], out['Hfull'] ) # Make sure the method converged. self.assertEqual(out['info'], 0) # Check the residual. res = rhs - A * out['xk'] self.assertAlmostEqual( np.linalg.norm(res)/np.linalg.norm(rhs), 0.0, delta=tol )
def test_get_projection(self): N = 100 A = scipy.sparse.spdiags(range(1, N + 1), [0], N, N) b = np.ones((N, 1)) x0 = np.ones((N, 1)) # 'last' 2 eigenvectors W = np.zeros((N, 2)) W[-2, 0] = 1. W[-1, 1] = 1 AW = A * W P, x0new = nm.get_projection(W, AW, b, x0) # Check A*(P*I) against exact A*P AP = A * (P * np.eye(N)) AP_exact = scipy.sparse.spdiags( list(range(1, N - 1)) + [0, 0], [0], N, N) self.assertAlmostEqual(np.linalg.norm(AP - AP_exact), 0.0, delta=1e-14) # Check x0new x0new_exact = np.ones((N, 1)) x0new_exact[N - 2:N, 0] = [1. / (N - 1), 1. / N] self.assertAlmostEqual(np.linalg.norm(x0new - x0new_exact), 0.0, delta=1e-14)
def test_get_ritz(self): N = 10 A = scipy.sparse.spdiags(range(1, N + 1), [0], N, N) b = np.ones((N, 1)) x0 = np.ones((N, 1)) # 'last' 2 eigenvectors W = np.zeros((N, 2)) W[-2, 0] = 1. W[-1, 1] = 1 AW = A * W # Get the projection P, x0new = nm.get_projection(W, AW, b, x0) # Run MINRES (we are only interested in the Lanczos basis and tridiag matrix) out = nm.minres(A, b, x0new, Mr=P, tol=1e-14, maxiter=11, full_reortho=True, return_basis=True) # Get Ritz pairs ritz_vals, ritz_vecs = nm.get_p_ritz(W, AW, out['Vfull'], out['Hfull']) # Check Ritz pair residuals #ritz_res_exact = A*ritz_vecs - np.dot(ritz_vecs,np.diag(ritz_vals)) #for i in range(0,len(ritz_vals)): #norm_ritz_res_exact = np.linalg.norm(ritz_res_exact[:,i]) #self.assertAlmostEqual( abs(norm_ritz_res[i] - norm_ritz_res_exact), 0.0, delta=1e-13 ) # Check if Ritz values / vectors corresponding to W are still there ;) order = np.argsort(ritz_vals) # 'last' eigenvalue self.assertAlmostEqual(abs(ritz_vals[order[-1]] - N), 0.0, delta=1e-13) self.assertAlmostEqual(abs(ritz_vals[order[-2]] - (N - 1)), 0.0, delta=1e-13) # now the eigenvectors self.assertAlmostEqual(abs(nm._ipstd(ritz_vecs[:, order[-1]], W[:, 1])), 1.0, delta=1e-13) self.assertAlmostEqual(abs(nm._ipstd(ritz_vecs[:, order[-2]], W[:, 0])), 1.0, delta=1e-13)
def test_minres_deflation(self): # Create sparse symmetric problem. num_unknowns = 100 A = self._create_sparse_herm_indef_matrix(num_unknowns) rhs = np.ones((num_unknowns, 1)) x0 = np.zeros((num_unknowns, 1)) # get projection from scipy.sparse.linalg import eigs num_vecs = 6 D, W = eigs(A, k=num_vecs, v0=np.ones((num_unknowns, 1))) # Uncomment next lines to perturb W #W = W + 1.e-10*np.random.rand(W.shape[0], W.shape[1]) #from scipy.linalg import qr #W, R = qr(W, mode='economic') AW = nm._apply(A, W) P, x0new = nm.get_projection(W, AW, rhs, x0) # Solve using MINRES. tol = 1.0e-9 out = nm.minres(A, rhs, x0new, Mr=P, tol=tol, maxiter=num_unknowns - num_vecs, full_reortho=True, return_basis=True) # TODO: move to new unit test o = nm.get_p_ritz(W, AW, out['Vfull'], out['Hfull']) ritz_vals, ritz_vecs = nm.get_p_ritz(W, AW, out['Vfull'], out['Hfull']) # Make sure the method converged. self.assertEqual(out['info'], 0) # Check the residual. res = rhs - A * out['xk'] self.assertAlmostEqual(np.linalg.norm(res) / np.linalg.norm(rhs), 0.0, delta=tol)
def test_get_ritz(self): N = 10 A = scipy.sparse.spdiags( range(1,N+1), [0], N, N) b = np.ones( (N,1) ) x0 = np.ones( (N,1) ) # 'last' 2 eigenvectors W = np.zeros( (N,2) ) W[-2,0]=1. W[-1,1]=1 AW = A*W # Get the projection P, x0new = nm.get_projection(W, AW, b, x0) # Run MINRES (we are only interested in the Lanczos basis and tridiag matrix) out = nm.minres(A, b, x0new, Mr=P, tol=1e-14, maxiter=11, full_reortho=True, return_basis=True ) # Get Ritz pairs ritz_vals, ritz_vecs = nm.get_p_ritz(W, AW, out['Vfull'], out['Hfull'] ) # Check Ritz pair residuals #ritz_res_exact = A*ritz_vecs - np.dot(ritz_vecs,np.diag(ritz_vals)) #for i in range(0,len(ritz_vals)): #norm_ritz_res_exact = np.linalg.norm(ritz_res_exact[:,i]) #self.assertAlmostEqual( abs(norm_ritz_res[i] - norm_ritz_res_exact), 0.0, delta=1e-13 ) # Check if Ritz values / vectors corresponding to W are still there ;) order = np.argsort(ritz_vals) # 'last' eigenvalue self.assertAlmostEqual( abs(ritz_vals[order[-1]] - N), 0.0, delta=1e-13 ) self.assertAlmostEqual( abs(ritz_vals[order[-2]] - (N-1)), 0.0, delta=1e-13 ) # now the eigenvectors self.assertAlmostEqual( abs(nm._ipstd(ritz_vecs[:,order[-1]],W[:,1])), 1.0, delta=1e-13 ) self.assertAlmostEqual( abs(nm._ipstd(ritz_vecs[:,order[-2]],W[:,0])), 1.0, delta=1e-13 )
def test_get_projection(self): N = 100 A = scipy.sparse.spdiags( range(1,N+1), [0], N, N) b = np.ones( (N,1) ) x0 = np.ones( (N,1) ) # 'last' 2 eigenvectors W = np.zeros( (N,2) ) W[-2,0]=1. W[-1,1]=1 AW = A*W P, x0new = nm.get_projection(W, AW, b, x0) # Check A*(P*I) against exact A*P AP = A*(P*np.eye(N)) AP_exact = scipy.sparse.spdiags(list(range(1,N-1))+[0,0], [0], N, N) self.assertAlmostEqual( np.linalg.norm(AP-AP_exact), 0.0, delta=1e-14 ) # Check x0new x0new_exact = np.ones( (N,1) ) x0new_exact[N-2:N,0] = [1./(N-1),1./N] self.assertAlmostEqual( np.linalg.norm(x0new-x0new_exact), 0.0, delta=1e-14 )
def _solve_system(modeleval, filename, timestep, mu, args): # read the mesh print('Reading current psi...',) start = time.time() mesh, point_data, field_data = voropy.read(filename, timestep=timestep ) total = time.time() - start print('done (%gs).' % total) num_coords = len( mesh.node_coords ) # -------------------------------------------------------------------------- # set psi at which to create the Jacobian print('Creating initial guess and right-hand side...',) start = time.time() current_psi = (point_data['psi'][:,0] + 1j * point_data['psi'][:,1]).reshape(-1,1) # Perturb a bit. eps = 1.0e-10 perturbation = eps * (np.random.rand(num_coords) + 1j * np.random.rand(num_coords)) current_psi += perturbation.reshape(current_psi.shape) if args.bordering: phi0 = np.zeros((num_coords+1,1), dtype=complex) # right hand side x = np.empty((num_coords+1,1), dtype=complex) x[0:num_coords] = current_psi x[num_coords] = 0.0 else: # create right hand side and initial guess phi0 = np.zeros( (num_coords,1), dtype=complex ) x = current_psi # right hand side #rhs = np.ones( (num_coords,1), dtype=complex ) #rhs = np.empty( num_coords, dtype = complex ) #radius = np.random.rand( num_coords ) #arg = np.random.rand( num_coords ) * 2.0 * cmath.pi #for k in range( num_coords ): #rhs[ k ] = cmath.rect(radius[k], arg[k]) rhs = modeleval.compute_f(x=x, mu=mu, g=1.0) end = time.time() print('done. (%gs)' % (end - start)) print('||rhs|| = %g' % np.sqrt(modeleval.inner_product(rhs, rhs))) # -------------------------------------------------------------------------- # create the linear operator print('Getting Jacobian...',) start_time = time.clock() jacobian = modeleval.get_jacobian(x=x, mu=mu, g=1.0) end_time = time.clock() print('done. (%gs)' % (end_time - start_time)) # create precondictioner object print('Getting preconditioner...',) start_time = time.clock() prec = modeleval.get_preconditioner_inverse(x=x, mu=mu, g=1.0) end_time = time.clock() print('done. (%gs)' % (end_time - start_time)) # -------------------------------------------------------------------------- # Get reference solution #print 'Get reference solution (dim = %d)...' % (2*num_coords), #start_time = time.clock() #ref_sol, info, relresvec, errorvec = nm.minres_wrap( jacobian, rhs, #x0 = phi0, #tol = 1.0e-14, #M = prec, #inner_product = modeleval.inner_product, #explicit_residual = True #) #end_time = time.clock() #if info == 0: #print 'success!', #else: #print 'no convergence.', #print ' (', end_time - start_time, 's,', len(relresvec)-1 ,' iters).' if args.use_deflation: W = 1j * x AW = jacobian * W P, x0new = nm.get_projection(W, AW, rhs, phi0, inner_product = modeleval.inner_product ) else: #AW = np.zeros((len(current_psi),1), dtype=np.complex) P = None x0new = phi0 if args.krylov_method == 'cg': lin_solve = nm.cg elif args.krylov_method == 'minres': lin_solve = nm.minres #elif args.krylov_method == 'minresfo': #lin_solve = nm.minres #lin_solve_args.update({'full_reortho': True}) elif args.krylov_method == 'gmres': lin_solve = nm.gmres else: raise ValueError('Unknown Krylov solver ''%s''.' % args.krylov_method) print('Solving the system (len(x) = %d, bordering: %r)...' % (len(x), args.bordering),) start_time = time.clock() timer = False out = lin_solve(jacobian, rhs, x0new, tol = args.tolerance, Mr = P, M = prec, #maxiter = 2*num_coords, maxiter = 500, inner_product = modeleval.inner_product, explicit_residual = True, #timer=timer #exact_solution = ref_sol ) end_time = time.clock() print('done. (%gs)' % (end_time - start_time)) print('(%d,%d)' % (2*num_coords, len(out['relresvec'])-1)) # compute actual residual #res = rhs - jacobian * out['xk'] #print '||b-Ax|| = %g' % np.sqrt(modeleval.inner_product(res, res)) if timer: # pretty-print timings print(' '*22 + 'sum'.rjust(14) + 'mean'.rjust(14) + 'min'.rjust(14) + 'std dev'.rjust(14)) for key, item in out['times'].items(): print('\'%s\': %12g %12g %12g %12g' % (key.ljust(20), item.sum(), item.mean(), item.min(), item.std())) # Get the number of MG cycles. # 'modeleval.num_cycles' contains the number of MG cycles executed # for all AMG calls run. # In nm.minres, two calls to the precondictioner are done prior to the # actual iteration for the normalization of the residuals. # With explicit_residual=True, *two* calls to the preconditioner are done # in each iteration. # What we would like to have here is the number of V-cycles done per loop # when explicit_residual=False. Also, forget about the precondictioner # calls for the initialization. # Hence, cut of the first two and replace it by 0, and out of the # remainder take every other one. #nc = [0] + modeleval.tot_amg_cycles[2::2] #nc_cumsum = np.cumsum(nc) #pp.semilogy(nc_cumsum, out['relresvec'], color='0.0') #pp.show() #import matplotlib2tikz #matplotlib2tikz.save('cycle10.tex') #matplotlib2tikz.save('inf.tex') return out['relresvec']
def _solve_system(modeleval, filename, timestep, mu, args): # read the mesh print(("Reading current psi...", )) start = time.time() mesh, point_data, field_data = meshplex.read(filename, timestep=timestep) total = time.time() - start print(("done (%gs)." % total)) num_coords = len(mesh.node_coords) # set psi at which to create the Jacobian print(("Creating initial guess and right-hand side...", )) start = time.time() current_psi = (point_data["psi"][:, 0] + 1j * point_data["psi"][:, 1]).reshape(-1, 1) # Perturb a bit. eps = 1.0e-10 perturbation = eps * (np.random.rand(num_coords) + 1j * np.random.rand(num_coords)) current_psi += perturbation.reshape(current_psi.shape) if args.bordering: phi0 = np.zeros((num_coords + 1, 1), dtype=complex) # right hand side x = np.empty((num_coords + 1, 1), dtype=complex) x[0:num_coords] = current_psi x[num_coords] = 0.0 else: # create right hand side and initial guess phi0 = np.zeros((num_coords, 1), dtype=complex) x = current_psi # right hand side # rhs = np.ones( (num_coords,1), dtype=complex ) # rhs = np.empty( num_coords, dtype = complex ) # radius = np.random.rand( num_coords ) # arg = np.random.rand( num_coords ) * 2.0 * cmath.pi # for k in range( num_coords ): # rhs[ k ] = cmath.rect(radius[k], arg[k]) rhs = modeleval.compute_f(x=x, mu=mu, g=1.0) end = time.time() print(("done. (%gs)" % (end - start))) print(("||rhs|| = %g" % np.sqrt(modeleval.inner_product(rhs, rhs)))) # create the linear operator print(("Getting Jacobian...", )) start_time = time.clock() jacobian = modeleval.get_jacobian(x=x, mu=mu, g=1.0) end_time = time.clock() print(("done. (%gs)" % (end_time - start_time))) # create precondictioner object print(("Getting preconditioner...", )) start_time = time.clock() prec = modeleval.get_preconditioner_inverse(x=x, mu=mu, g=1.0) end_time = time.clock() print(("done. (%gs)" % (end_time - start_time))) # Get reference solution # print 'Get reference solution (dim = %d)...' % (2*num_coords), # start_time = time.clock() # ref_sol, info, relresvec, errorvec = nm.minres_wrap( jacobian, rhs, # x0 = phi0, # tol = 1.0e-14, # M = prec, # inner_product = modeleval.inner_product, # explicit_residual = True # ) # end_time = time.clock() # if info == 0: # print 'success!', # else: # print 'no convergence.', # print ' (', end_time - start_time, 's,', len(relresvec)-1 ,' iters).' if args.use_deflation: W = 1j * x AW = jacobian * W P, x0new = nm.get_projection(W, AW, rhs, phi0, inner_product=modeleval.inner_product) else: # AW = np.zeros((len(current_psi),1), dtype=np.complex) P = None x0new = phi0 if args.krylov_method == "cg": lin_solve = nm.cg elif args.krylov_method == "minres": lin_solve = nm.minres # elif args.krylov_method == 'minresfo': # lin_solve = nm.minres # lin_solve_args.update({'full_reortho': True}) elif args.krylov_method == "gmres": lin_solve = nm.gmres else: raise ValueError("Unknown Krylov solver " "%s" "." % args.krylov_method) print(("Solving the system (len(x) = %d, bordering: %r)..." % (len(x), args.bordering), )) start_time = time.clock() timer = False out = lin_solve( jacobian, rhs, x0new, tol=args.tolerance, Mr=P, M=prec, # maxiter = 2*num_coords, maxiter=500, inner_product=modeleval.inner_product, explicit_residual=True, # timer=timer # exact_solution = ref_sol ) end_time = time.clock() print(("done. (%gs)" % (end_time - start_time))) print(("(%d,%d)" % (2 * num_coords, len(out["relresvec"]) - 1))) # compute actual residual # res = rhs - jacobian * out['xk'] # print '||b-Ax|| = %g' % np.sqrt(modeleval.inner_product(res, res)) if timer: # pretty-print timings print((" " * 22 + "sum".rjust(14) + "mean".rjust(14) + "min".rjust(14) + "std dev".rjust(14))) for key, item in list(out["times"].items()): print(("'%s': %12g %12g %12g %12g" % (key.ljust(20), item.sum(), item.mean(), item.min(), item.std()))) # Get the number of MG cycles. # 'modeleval.num_cycles' contains the number of MG cycles executed # for all AMG calls run. # In nm.minres, two calls to the precondictioner are done prior to the # actual iteration for the normalization of the residuals. # With explicit_residual=True, *two* calls to the preconditioner are done # in each iteration. # What we would like to have here is the number of V-cycles done per loop # when explicit_residual=False. Also, forget about the precondictioner # calls for the initialization. # Hence, cut of the first two and replace it by 0, and out of the # remainder take every other one. # nc = [0] + modeleval.tot_amg_cycles[2::2] # nc_cumsum = np.cumsum(nc) # pp.semilogy(nc_cumsum, out['relresvec'], color='0.0') # pp.show() # import matplotlib2tikz # matplotlib2tikz.save('cycle10.tex') # matplotlib2tikz.save('inf.tex') return out["relresvec"]