예제 #1
0
 def stop(iteration, x):
     iterStatus = threshStatus = False
     if iterations is not None:
         iterStatus = (iteration >= iterations)
     if threshold is not None:
         norm = np.linalg.norm(getresidual(b, A, x, N))
         threshStatus = (norm < threshold)
     return iterStatus or threshStatus
예제 #2
0
 def stop(iteration, x):
     iterStatus = threshStatus = False
     if iterations is not None:
         iterStatus = (iteration >= iterations)
     if threshold is not None:
         norm = np.linalg.norm(getresidual(b, A, x, N))
         threshStatus = (norm < threshold)
     return iterStatus or threshStatus
예제 #3
0
 def test_gs_thresh(self):
     '''Test the Gauss-Siedel to-threshold solver.'''
     NX = 12
     NY = NX
     N = NX * NY
     A = operators.poisson((NX, NY,))
     b = np.random.random((N,))
     x_init = np.zeros((N,))
     threshold = 0.0001
     verbose = False
     x = smoothToThreshold(A, b, x_init,
                                                 threshold,
                                                 verbose=verbose)
     if self.verbose:
         print 'norm is', (np.linalg.norm(tools.getresidual(b, A, x, N)))
예제 #4
0
 def test_a(self):
     '''
     Poisson equation on a sine curve. In 3D?
     It wasn't originally, but the restriciton algorithm was having
     trouble with 1D. This might bear investigation.
     '''
     problemscale = 12
     size = problemscale ** 3
     gridLevels = 4
     u_zeros = np.zeros((size,))
     u_actual = np.sin(np.array(range(int(size))) * 3.0 / size).T
     A = operators.poisson((size,))
     b = tools.flexibleMmult(A, u_actual)
     uSmoothed = smooth(A, b, u_zeros, iterations=1)
     parameters = {'coarsestLevel': gridLevels - 1,
                   'problemShape': (problemscale, problemscale, problemscale),
                   'gridLevels': gridLevels,
                   'threshold': 8e-3,
                   }
     u_mmg = mgSolve(A, b, parameters)
     if self.verbose:
         print 'norm is', (np.linalg.norm(tools.getresidual(b, A, uSmoothed.reshape((size, 1)), size)))
     residual_norm = np.linalg.norm(tools.flexibleMmult(A, u_mmg) - b)
     assert parameters['threshold'] > residual_norm
예제 #5
0
def mgCycle(A, b, level, R, parameters, initial=None):
    """
    Internally used function that shows the actual multi-level solution method,
    through a recursive call within the "level < coarsestLevel" block, below.
    
    Parameters
    ----------
    A : list of ndarrays
        A list of square arrays; one for each level of resolution. As returned
        by operators.coeffecientList().
    b : ndarray
        top-level RHS vector
    level : int
        The current multigrid level. This value is 0 at the entry point for standard,
        recursive multigrid.
    R : list of ndarrays
        A list of (generally nonsquare) arrays; one for each transition between
        levels of resolution. As returned by operators.restrictionList().
    parameters : dict 
        A dictionary of parameters. See documentation for mgSolve() for details.
        
    Optional Parameters
    -------------------
    initial=np.zeros((b.size, )) : ndarray
        Initial iterate. Defaults to the zero vector, but the last supplied
        solution should be used for chained v-cycles.
    
    Returns
    -------
    
    uOut : ndarray
        solution
    
    infoDict
        Dictionary of information about the solution process. Fields:
        norm
            The final norm of the residual
    
    """
    verbose = parameters["verbose"]
    if initial is None:
        initial = np.zeros((b.size,))
    N = b.size

    # The general case is a recursive call. It comprises (1) pre-smoothing,
    # (2) finding the coarse residual, (3) solving for the coarse correction
    # to account for that residual via recursive call, (4) adding that
    # correction to the pre-smoothed solution, (5) then possibly post-smoothing.
    if level < parameters["coarsestLevel"]:
        # (1) pre-smoothing
        uApx = smooth(A[level], b, initial, parameters["preIterations"], verbose=verbose)

        # (2) coarse residual
        bCoarse = tools.flexibleMmult(R[level], b.reshape((N, 1)))
        NH = len(bCoarse)

        if verbose:
            print level * " " + "calling mgCycle at level %i" % level
        residual = tools.getresidual(b, A[level], uApx, N)
        coarseResidual = tools.flexibleMmult(R[level], residual.reshape((N, 1))).reshape((NH,))

        # (3) correction for residual via recursive call
        coarseCorrection = mgCycle(A, coarseResidual, level + 1, R, parameters)[0]
        correction = (tools.flexibleMmult(R[level].transpose(), coarseCorrection.reshape((NH, 1)))).reshape((N,))

        if parameters["postIterations"] > 0:
            # (5) post-smoothing
            uOut = smooth(A[level], b, uApx + correction, parameters["postIterations"], verbose=verbose)  # (4)
        else:
            uOut = uApx + correction  # (4)

        # Save norm, to monitor for convergence at topmost level.
        norm = scipy.sparse.base.np.linalg.norm(tools.getresidual(b, A[level], uOut, N))

    # The recursive calls only end when we're at the coarsest level, where
    # we simply apply the chosen coarse solver.
    else:
        norm = 0
        if verbose:
            print level * " " + "direct solving at level %i" % level
        uOut = coarseSolve(A[level], b.reshape((N, 1)))

    return uOut, {"norm": norm}
예제 #6
0
def mgCycle(A, b, level, R, parameters, initial=None):
    """
    Internally used function that shows the actual multi-level solution method,
    through a recursive call within the "level < coarsestLevel" block, below.
    
    Parameters
    ----------
    A : list of ndarrays
        A list of square arrays; one for each level of resolution. As returned
        by operators.coeffecientList().
    b : ndarray
        top-level RHS vector
    level : int
        The current multigrid level. This value is 0 at the entry point for standard,
        recursive multigrid.
    R : list of ndarrays
        A list of (generally nonsquare) arrays; one for each transition between
        levels of resolution. As returned by operators.restrictionList().
    parameters : dict 
        A dictionary of parameters. See documentation for mgSolve() for details.
        
    Optional Parameters
    -------------------
    initial=np.zeros((b.size, )) : ndarray
        Initial iterate. Defaults to the zero vector, but the last supplied
        solution should be used for chained v-cycles.
    
    Returns
    -------
    
    uOut : ndarray
        solution
    
    infoDict
        Dictionary of information about the solution process. Fields:
        norm
            The final norm of the residual
    
    """
    verbose = parameters['verbose']
    if initial is None:
        initial = np.zeros((b.size, ))
    N = b.size
    
    # The general case is a recursive call. It comprises (1) pre-smoothing,
    # (2) finding the coarse residual, (3) solving for the coarse correction
    # to account for that residual via recursive call, (4) adding that
    # correction to the pre-smoothed solution, (5) then possibly post-smoothing. 
    if level < parameters['coarsestLevel']:
        # (1) pre-smoothing
        uApx = smooth(A[level], b, initial,
                                parameters['preIterations'], verbose=verbose)
        
        # (2) coarse residual
        bCoarse = tools.flexibleMmult(R[level], b.reshape((N, 1)))
        NH = len(bCoarse)
        
        if verbose: print level * " " + "calling mgCycle at level %i" % level
        residual = tools.getresidual(b, A[level], uApx, N)
        coarseResidual = tools.flexibleMmult(R[level], residual.reshape((N, 1))).reshape((NH,))
        
        # (3) correction for residual via recursive call
        coarseCorrection = mgCycle(A, coarseResidual, level+1, R, parameters)[0]
        correction = (tools.flexibleMmult(R[level].transpose(), coarseCorrection.reshape((NH, 1)))).reshape((N, ))
        
        if parameters['postIterations'] > 0:
            # (5) post-smoothing
            uOut = smooth(A[level],
                                    b,
                                    uApx + correction, # (4)
                                    parameters['postIterations'],
                                    verbose=verbose)
        else:
            uOut = uApx + correction # (4)
            
        # Save norm, to monitor for convergence at topmost level.
        norm = scipy.sparse.base.np.linalg.norm(tools.getresidual(b, A[level], uOut, N))
    
    # The recursive calls only end when we're at the coarsest level, where
    # we simply apply the chosen coarse solver.
    else:
        norm = 0
        if verbose: print level * " " + "direct solving at level %i" % level
        uOut = coarseSolve(A[level], b.reshape((N, 1)))
        
    return uOut, {'norm': norm}