def gauss_seidel_nr(A, x, b, iterations=1, sweep='forward', omega=1.0, Dinv=None): """Perform Gauss-Seidel iterations on the linear system A.H A x = A.H b Parameters ---------- A : csr_matrix Sparse NxN matrix x : { ndarray } Approximate solution (length N) b : { ndarray } Right-hand side (length N) iterations : { int } Number of iterations to perform sweep : {'forward','backward','symmetric'} Direction of sweep omega : { float} Relaxation parameter typically in (0, 2) if omega != 1.0, then algorithm becomes SOR on A.H A Dinv : { ndarray} Inverse of diag(A.H A), (length N) Returns ------- Nothing, x will be modified in place. References ---------- .. [1] Yousef Saad, "Iterative Methods for Sparse Linear Systems, Second Edition", SIAM, pp. 247-9, 2003 http://www-users.cs.umn.edu/~saad/books.html Examples -------- >>> ## Use NR Gauss-Seidel as a Stand-Alone Solver >>> from pyamg.relaxation import * >>> from pyamg.gallery import poisson >>> from pyamg.util.linalg import norm >>> import numpy >>> A = poisson((10,10), format='csr') >>> x0 = numpy.zeros((A.shape[0],1)) >>> b = numpy.ones((A.shape[0],1)) >>> gauss_seidel_nr(A, x0, b, iterations=10, sweep='symmetric') >>> print norm(b-A*x0) 8.45044864352 >>> # >>> ## Use NR Gauss-Seidel as the Multigrid Smoother >>> from pyamg import smoothed_aggregation_solver >>> sa = smoothed_aggregation_solver(A, B=numpy.ones((A.shape[0],1)), ... coarse_solver='pinv2', max_coarse=50, ... presmoother=('gauss_seidel_nr', {'sweep' : 'symmetric'}), ... postsmoother=('gauss_seidel_nr', {'sweep' : 'symmetric'})) >>> x0=numpy.zeros((A.shape[0],1)) >>> residuals=[] >>> x = sa.solve(b, x0=x0, tol=1e-8, residuals=residuals) """ A,x,b = make_system(A, x, b, formats=['csc']) # Dinv for A.H*A if Dinv == None: Dinv = numpy.ravel(get_diagonal(A, norm_eq=1, inv=True)) if sweep == 'forward': col_start,col_stop,col_step = 0,len(x),1 elif sweep == 'backward': col_start,col_stop,col_step = len(x)-1,-1,-1 elif sweep == 'symmetric': for iter in xrange(iterations): gauss_seidel_nr(A, x, b, iterations=1, sweep='forward', omega=omega, Dinv=Dinv) gauss_seidel_nr(A, x, b, iterations=1, sweep='backward', omega=omega, Dinv=Dinv) return else: raise ValueError("valid sweep directions are 'forward', 'backward', and 'symmetric'") ## # Calculate initial residual r = b - A*x for i in xrange(iterations): amg_core.gauss_seidel_nr(A.indptr, A.indices, A.data, x, r, col_start, col_stop, col_step, Dinv, omega)
def gauss_seidel_nr(A, x, b, iterations=1, sweep='forward', omega=1.0, Dinv=None): """Perform Gauss-Seidel iterations on the linear system A.H A x = A.H b Parameters ---------- A : csr_matrix Sparse NxN matrix x : { ndarray } Approximate solution (length N) b : { ndarray } Right-hand side (length N) iterations : { int } Number of iterations to perform sweep : {'forward','backward','symmetric'} Direction of sweep omega : { float} Relaxation parameter typically in (0, 2) if omega != 1.0, then algorithm becomes SOR on A.H A Dinv : { ndarray} Inverse of diag(A.H A), (length N) Returns ------- Nothing, x will be modified in place. References ---------- .. [1] Yousef Saad, "Iterative Methods for Sparse Linear Systems, Second Edition", SIAM, pp. 247-9, 2003 http://www-users.cs.umn.edu/~saad/books.html Examples -------- >>> ## Use NR Gauss-Seidel as a Stand-Alone Solver >>> from pyamg.relaxation import * >>> from pyamg.gallery import poisson >>> from pyamg.util.linalg import norm >>> import numpy >>> A = poisson((10,10), format='csr') >>> x0 = numpy.zeros((A.shape[0],1)) >>> b = numpy.ones((A.shape[0],1)) >>> gauss_seidel_nr(A, x0, b, iterations=10, sweep='symmetric') >>> print norm(b-A*x0) 8.45044864352 >>> # >>> ## Use NR Gauss-Seidel as the Multigrid Smoother >>> from pyamg import smoothed_aggregation_solver >>> sa = smoothed_aggregation_solver(A, B=numpy.ones((A.shape[0],1)), ... coarse_solver='pinv2', max_coarse=50, ... presmoother=('gauss_seidel_nr', {'sweep' : 'symmetric'}), ... postsmoother=('gauss_seidel_nr', {'sweep' : 'symmetric'})) >>> x0=numpy.zeros((A.shape[0],1)) >>> residuals=[] >>> x = sa.solve(b, x0=x0, tol=1e-8, residuals=residuals) """ A, x, b = make_system(A, x, b, formats=['csc']) # Dinv for A.H*A if Dinv == None: Dinv = numpy.ravel(get_diagonal(A, norm_eq=1, inv=True)) if sweep == 'forward': col_start, col_stop, col_step = 0, len(x), 1 elif sweep == 'backward': col_start, col_stop, col_step = len(x) - 1, -1, -1 elif sweep == 'symmetric': for iter in xrange(iterations): gauss_seidel_nr(A, x, b, iterations=1, sweep='forward', omega=omega, Dinv=Dinv) gauss_seidel_nr(A, x, b, iterations=1, sweep='backward', omega=omega, Dinv=Dinv) return else: raise ValueError( "valid sweep directions are 'forward', 'backward', and 'symmetric'" ) ## # Calculate initial residual r = b - A * x for i in xrange(iterations): amg_core.gauss_seidel_nr(A.indptr, A.indices, A.data, x, r, col_start, col_stop, col_step, Dinv, omega)