Example #1
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
Example #2
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}
Example #3
0
    def multifreq_1d(self, N, finaliterations, spectralxscale='linear',
                     solutionname='whitenoise', save=False):
        '''Generates 1-dimensional uniform noise with N unknowns, then applies
        Gauss-Siedel smoothing iterations to an initial zero-vector guess until
        finaliterations is reached, graphing the Fourier transform of the error
        each time. Does so pretty inefficiently, by doing 1 iteration, 2 iterations,
        3, iterations, etc. until finaliterations, instead of just doing
        finaliterations iterations, and graphing after each sweep.
    
        Uses ffmpeg and mplayer.'''
        if solutionname == 'summedsine':  # Summed sine waves of several frequencies.
            data = np.zeros((N,))  # initialize
            domainwidthsexponents = range(10)
            domainwidths = range(10)  # initialize
            for i in range(10):
                domainwidths[i] = float(N) / (2.0 ** domainwidthsexponents[i])
            for domainwidth in domainwidths:
                sininput = np.arange(0.0, domainwidth, domainwidth / N)
                xdata = (np.sin(sininput) / domainwidth * 10.0)[0:N:]
                data = data + xdata
        else:
            solutionname = 'whitenoise'
            data = np.random.random((N,))  # 1D white noise
        gif_output_name = 'spectral_solution_rate-%i_unknowns-%s_xscale-%s_solution.gif' % (N, spectralxscale, solutionname)

        A = operators.poisson((N,))
        b = tools.flexibleMmult(A, data)

        if self.saveFig:
            from scipy import fftpack
            import matplotlib.pyplot as plt
        #    Prepare for Graphing
            fig = plt.figure(figsize=(7.5, 7))
            fig.suptitle(gif_output_name)
            fig.subplots_adjust(wspace=.2)
            fig.subplots_adjust(hspace=.2)
            solnax = fig.add_subplot(211)  # subplot to hold the solution
            solnaxylim = [0, 1]
            specax = fig.add_subplot(212)  # subplot to hold the spectrum
            specaxylim = [10.0 ** (-18), 10.0 ** 3]

        solutions = []
        spectra = []
        filenames = []
        loop = 1  # for monitoring progress

        iterationslist = range(finaliterations)
    #    from random import shuffle
    #    shuffle(iterationslist)
        if save:
            iterations_to_save = range(1, finaliterations + 1)
            str_tosave = []
            for x in iterations_to_save:
                str_tosave.append(str(x))
            from os import system; system("mkdir -p output")
            csvfilelabel = 'iterative_spectra-%i_N' % N
            csvfile = open('output/%s.csv' % csvfilelabel, 'a')
            csvfile.write('frequency,' + ','.join(str_tosave) + '\n')
            csvfile.flush()
        for iterations in iterationslist:
            solutions.append(smooth(A,
                                             b,
                                             np.zeros((N,)),
                                             iterations)
                                            )
            if self.saveFig:
                spectra.append(fftpack.fft(b - tools.flexibleMmult(A,
                                                                   solutions[iterations]
                                                                   )
                                          )
                              )
            if self.saveFig:
                filebasename = '%i_unknowns-%i_iterations' % (N, iterations)
                filename = filebasename + '-solution.png'
                solnax.set_ylim(solnaxylim)
                solnax.set_autoscaley_on(False)
                solnax.set_title(filebasename + ': Solution')
                solnax.plot(solutions[iterations])
    
                specax.set_yscale('log')
                specax.set_xscale(spectralxscale)
                specax.set_ylim(specaxylim)
                specax.set_autoscaley_on(False)
                specax.set_title(filebasename + ': Solution Error (frequency domain)')
                specax.plot(spectra[iterations])

                filename = 'temp/' + filebasename + '-combined.png'
                filenames.append(filename)
                if self.saveFig: 
                    print "%i of %i: " % (loop, finaliterations) + "saving " + filename
                    fig.savefig(filename, dpi=80)
                solnax.cla()
                specax.cla()
            loop += 1
        frequencies = range(len(solutions[0]))
        for i in frequencies:
            towrite = '%i,' % frequencies[i]
            for spectrum in spectra:
                towrite += '%.8f,' % abs(spectrum[i])
            if save:
                csvfile.write(towrite + '\n')
                csvfile.flush()
        if save:
            csvfile.close()

        # make .gif and .mp4 files:
        if self.saveFig:
            # TODO (Tom) Might use subprocess to suppress super verbose ffmpeg
        #    import subprocess
        #    s = subprocess.Popen(['cowsay', 'hello']
        #    stderr=subprocess.STDOUT
        #    stdout=subprocess.PIPE).communicate()[0]
        #    print s
            torun = []
            torun.extend([
                'convert ' + ' '.join(filenames) + ' output/%s' % gif_output_name,
                'rm ' + ' '.join(filenames),
                'cp %s simple.gif' % ('output/' + gif_output_name),
                'mplayer -vo jpeg simple.gif > /dev/null 2> /dev/null',
                'ffmpeg -r 12 -i %%08d.jpg -y -an output/%s.avi > /dev/null' % gif_output_name,
                'rm simple.gif 0*.jpg',
                'ffmpeg -y -i output/%s.avi output/%s.mp4 > /dev/null && rm output/%s.avi' % (gif_output_name, gif_output_name, gif_output_name),
                ])
            for command in torun:
                system(command)
Example #4
0
    def multifreq_2d(self, problemscale, finaliterations):
        '''Attempts to generate a pretty 2D solution, by summing several 2D
        sine waves of different frequencies. Then, proceeds to apply a GS smoother
        to the generated problem, saving pretty pictures after each iteration.
        This might work OK if problemscale is big enough.
        '''
        if self.saveFig:
            from scipy import fftpack
            import matplotlib.pyplot as plt
            from matplotlib import cm
            from mpl_toolkits.mplot3d import Axes3D

        # Generate test problem. Summed sine waves of several resolutions:
        NX = problemscale
        floatNX = float(NX)
        data = np.zeros((NX, NX))
        domainwidths = [floatNX, floatNX / 2.0, 10., 3.1415]
        for domainwidth in domainwidths:
            sininput = np.arange(0.0, domainwidth, domainwidth / NX)
            xdata = (np.sin(sininput) / domainwidth * 10.0)[0:NX:]
            data = data + xdata[:, np.newaxis] + xdata[:, np.newaxis].T
        X = np.tile(np.array(range(NX)), (NX, 1))
        Y = X.T

        if self.saveFig:
            # Prepare for Graphing:
            fig = plt.figure()
            ax = Axes3D(fig)
            ax.set_zlim3d([-1, 6])
            specfig = plt.figure()
            specax = specfig.add_subplot(111)
            specax.set_ylim([.000001, 10000])
            specax.set_autoscaley_on(False)
            specax.set_xscale('log')

        # Problem Setup:
        A = operators.poisson((NX, NX))
        solnforb = data.ravel().reshape((NX ** 2, 1))
        b = tools.flexibleMmult(A, solnforb)

        # Initial "Solution" placeholder:
        solutions = range(finaliterations)
        spectra = range(finaliterations)
        iterations = 0
        solutions[iterations] = np.zeros((NX, NX)).ravel()
        spectra[iterations] = b - tools.flexibleMmult(A, solutions[iterations])

        if self.saveFig:
            # Initial graphs:
            filebasename = 'output/N_%i-iterations_%i' % (NX ** 2, iterations)
            filename = filebasename + '.png'
            ax.set_title(filebasename)
            # surf = ax.plot_wireframe(X, Y, solutions[iterations].reshape(NX,NX),rstride=stridelength,cstride=stridelength)
            surf = ax.plot_surface(X, Y, data, cmap=cm.jet)
    #        print "saving", filename
            if self.saveFig: fig.savefig(filename)
            surf.remove()
            ax.cla()

            # Error Spectrum
            specax.plot(spectra[iterations])
            specax.set_title(filebasename + ': Error Spectrum')
            filename = filebasename + '-error.png'
            if self.saveFig: specfig.savefig(filename)
            del specax.lines[0]
            specax.cla()

        verbose = False
        for iterations in range(1, finaliterations):
            solutions[iterations] = smooth(A,
                                                    b,
                                                    np.zeros(NX ** 2),
                                                    iterations,
                                                    verbose=verbose
                                                   ).reshape(NX, NX)
            if self.saveFig:
                spectra[iterations] = fftpack.fft2(solutions[iterations])
            if self.saveFig:
                filebasename = 'output/N_%i-iterations_%i' % (NX ** 2, iterations)
                filename = filebasename + '-solution.png'
                ax.set_zlim3d([-1, 6])
                surf = ax.plot_surface(X, Y, solutions[iterations], cmap=cm.jet)
                ax.set_title(filebasename)
                surf = ax.plot_wireframe(X, Y, solutions[iterations])
    #            print "saving", filename
                if self.saveFig: fig.savefig(filename)
                surf.remove()
                ax.cla()
    
                specax.set_yscale('log')
                specax.set_ylim([.000001, 10000])
                specax.set_autoscaley_on(False)
                specax.set_xscale('log')
                specax.plot(spectra[iterations])
                specax.set_title(filebasename + ': Error Spectrum')
                filename = filebasename + '-error.png'
    #            print "saving", filename
                if self.saveFig: specfig.savefig(filename)
                del specax.lines[0]
                specax.cla()
Example #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, # (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}