Example #1
0
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)
Example #2
0
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)