def schwarz(A, x, b, iterations=1, subdomain=None, subdomain_ptr=None, inv_subblock=None, inv_subblock_ptr=None, sweep='forward'): """Perform Overlapping multiplicative Schwarz on the linear system Ax=b Parameters ---------- A : {csr_matrix, bsr_matrix} Sparse NxN matrix x : ndarray Approximate solution (length N) b : ndarray Right-hand side (length N) iterations : int Number of iterations to perform subdomain : {int array} Linear array containing each subdomain's elements subdomain_ptr : {int array} Pointer in subdomain, such that subdomain[subdomain_ptr[i]:subdomain_ptr[i+1]]] contains the _sorted_ indices in subdomain i inv_subblock : {int_array} Linear array containing each subdomain's inverted diagonal block of A inv_subblock_ptr : {int array} Pointer in inv_subblock, such that inv_subblock[inv_subblock_ptr[i]:inv_subblock_ptr[i+1]]] contains the inverted diagonal block of A for the i-th subdomain in _row_ major order sweep : {'forward','backward','symmetric'} Direction of sweep Returns ------- Nothing, x will be modified in place. Notes ----- If subdomains is None, then a point-wise iteration takes place, with the overlapping region defined by each degree-of-freedom's neighbors in the matrix graph. If subdomains is not None, but subblocks is, then the subblocks are formed internally. Currently only supports CSR matrices Examples -------- >>> ## Use Overlapping Schwarz 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)) >>> schwarz(A, x0, b, iterations=10) >>> print norm(b-A*x0) 0.126326160522 >>> # >>> ## Schwarz 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='schwarz', ... postsmoother='schwarz') >>> 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=['csr']) if subdomain is None and inv_subblock is not None: raise ValueError("inv_subblock must be None if subdomain is None") ## # If no subdomains are defined, the default is to use the sparsity pattern of A # to define the overlapping regions (subdomain, subdomain_ptr, inv_subblock, inv_subblock_ptr) = \ schwarz_parameters(A, subdomain, subdomain_ptr, inv_subblock, inv_subblock_ptr) if sweep == 'forward': row_start,row_stop,row_step = 0,subdomain_ptr.shape[0]-1,1 elif sweep == 'backward': row_start,row_stop,row_step = subdomain_ptr.shape[0]-2,-1,-1 elif sweep == 'symmetric': for iter in xrange(iterations): schwarz(A, x, b, iterations=1, subdomain=subdomain, subdomain_ptr=subdomain_ptr, inv_subblock=inv_subblock, inv_subblock_ptr=inv_subblock_ptr, sweep='forward') schwarz(A, x, b, iterations=1, subdomain=subdomain, subdomain_ptr=subdomain_ptr, inv_subblock=inv_subblock, inv_subblock_ptr=inv_subblock_ptr, sweep='backward') return else: raise ValueError("valid sweep directions are 'forward', 'backward', and 'symmetric'") ## # Call C code, need to make sure that subdomains are sorted and unique for iter in xrange(iterations): amg_core.overlapping_schwarz_csr(A.indptr, A.indices, A.data, x, b, inv_subblock, inv_subblock_ptr, subdomain, subdomain_ptr, subdomain_ptr.shape[0]-1, A.shape[0], row_start,row_stop,row_step)
def schwarz(A, x, b, iterations=1, subdomain=None, subdomain_ptr=None, inv_subblock=None, inv_subblock_ptr=None, sweep='forward'): """Perform Overlapping multiplicative Schwarz on the linear system Ax=b Parameters ---------- A : {csr_matrix, bsr_matrix} Sparse NxN matrix x : ndarray Approximate solution (length N) b : ndarray Right-hand side (length N) iterations : int Number of iterations to perform subdomain : {int array} Linear array containing each subdomain's elements subdomain_ptr : {int array} Pointer in subdomain, such that subdomain[subdomain_ptr[i]:subdomain_ptr[i+1]]] contains the _sorted_ indices in subdomain i inv_subblock : {int_array} Linear array containing each subdomain's inverted diagonal block of A inv_subblock_ptr : {int array} Pointer in inv_subblock, such that inv_subblock[inv_subblock_ptr[i]:inv_subblock_ptr[i+1]]] contains the inverted diagonal block of A for the i-th subdomain in _row_ major order sweep : {'forward','backward','symmetric'} Direction of sweep Returns ------- Nothing, x will be modified in place. Notes ----- If subdomains is None, then a point-wise iteration takes place, with the overlapping region defined by each degree-of-freedom's neighbors in the matrix graph. If subdomains is not None, but subblocks is, then the subblocks are formed internally. Currently only supports CSR matrices Examples -------- >>> ## Use Overlapping Schwarz 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)) >>> schwarz(A, x0, b, iterations=10) >>> print norm(b-A*x0) 0.126326160522 >>> # >>> ## Schwarz 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='schwarz', ... postsmoother='schwarz') >>> 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=['csr']) if subdomain is None and inv_subblock is not None: raise ValueError("inv_subblock must be None if subdomain is None") ## # If no subdomains are defined, the default is to use the sparsity pattern of A # to define the overlapping regions (subdomain, subdomain_ptr, inv_subblock, inv_subblock_ptr) = \ schwarz_parameters(A, subdomain, subdomain_ptr, inv_subblock, inv_subblock_ptr) if sweep == 'forward': row_start, row_stop, row_step = 0, subdomain_ptr.shape[0] - 1, 1 elif sweep == 'backward': row_start, row_stop, row_step = subdomain_ptr.shape[0] - 2, -1, -1 elif sweep == 'symmetric': for iter in xrange(iterations): schwarz(A, x, b, iterations=1, subdomain=subdomain, subdomain_ptr=subdomain_ptr, inv_subblock=inv_subblock, inv_subblock_ptr=inv_subblock_ptr, sweep='forward') schwarz(A, x, b, iterations=1, subdomain=subdomain, subdomain_ptr=subdomain_ptr, inv_subblock=inv_subblock, inv_subblock_ptr=inv_subblock_ptr, sweep='backward') return else: raise ValueError( "valid sweep directions are 'forward', 'backward', and 'symmetric'" ) ## # Call C code, need to make sure that subdomains are sorted and unique for iter in xrange(iterations): amg_core.overlapping_schwarz_csr(A.indptr, A.indices, A.data, x, b, inv_subblock, inv_subblock_ptr, subdomain, subdomain_ptr, subdomain_ptr.shape[0] - 1, A.shape[0], row_start, row_stop, row_step)