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
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)))
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
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}
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}