Esempio n. 1
1
def comparison_plot(f, u, Omega, filename='tmp.pdf',
                    plot_title='', ymin=None, ymax=None,
                    u_legend='approximation'):
    """Compare f(x) and u(x) for x in Omega in a plot."""
    x = sm.Symbol('x')
    print 'f:', f

    f = sm.lambdify([x], f, modules="numpy")
    u = sm.lambdify([x], u, modules="numpy")
    if len(Omega) != 2:
        raise ValueError('Omega=%s must be an interval (2-list)' % str(Omega))
    # When doing symbolics, Omega can easily contain symbolic expressions,
    # assume .evalf() will work in that case to obtain numerical
    # expressions, which then must be converted to float before calling
    # linspace below
    if not isinstance(Omega[0], (int,float)):
        Omega[0] = float(Omega[0].evalf())
    if not isinstance(Omega[1], (int,float)):
        Omega[1] = float(Omega[1].evalf())

    resolution = 401  # no of points in plot
    xcoor = linspace(Omega[0], Omega[1], resolution)
    # Vectorized functions expressions does not work with
    # lambdify'ed functions without the modules="numpy"
    exact  = f(xcoor)
    approx = u(xcoor)
    plot(xcoor, approx, '-')
    hold('on')
    plot(xcoor, exact, '-')
    legend([u_legend, 'exact'])
    title(plot_title)
    xlabel('x')
    if ymin is not None and ymax is not None:
        axis([xcoor[0], xcoor[-1], ymin, ymax])
    savefig(filename)
Esempio n. 2
0
def approximate(f, symbolic=False, d=1, N_e=4, Omega=[0, 1], filename='tmp'):
	phi = basis(d)
	print 'phi basis (reference element):\n', phi
	nodes, elements = mesh_uniform(N_e, d, Omega, symbolic)
	A, b = assemble(nodes, elements, phi, f, symbolic=symbolic)
	print 'nodes:', nodes
	print 'elements:', elements
	print 'A:\n', A
	print 'b:\n', b
	print sp.latex(A, mode='plain')
	#print sp.latex(b, mode='plain')
	if symbolic:
		c = A.LUsolve(b)
	else:
		c = np.linalg.solve(A, b)
	print 'c:\n', c
	print 'Plain interpolation/collocation:'
	x = sp.Symbol('x')
	f = sp.lambdify([x], f, modules='numpy')
	try:
		f_at_nodes = [f(xc) for xc in nodes]
	except NameError as e:
		raise NameError('numpy does not support special function:\n%s' % e)
	print f_at_nodes
	if not symbolic and filename is not None:
		xf = np.linspace(Omega[0], Omega[1], 10001)
		U = np.asarray(c)
		xu, u = u_glob(U, elements, nodes)
		plt.plot(xu, u, '-',
		xf, f(xf), '--')
		plt.legend(['u', 'f'])
		plt.savefig(filename + '.pdf')
		plt.savefig(filename + '.png')
Esempio n. 3
0
def run_solvers_and_check_amplitudes(solvers,
                                     timesteps_per_period=20,
                                     num_periods=1,
                                     I=1,
                                     w=2 * np.pi):
    P = 2 * np.pi / w  # duration of one period
    dt = P / timesteps_per_period
    Nt = num_periods * timesteps_per_period
    T = Nt * dt
    t_mesh = np.linspace(0, T, Nt + 1)

    file_name = 'Amplitudes'  # initialize filename for plot
    for solver in solvers:
        solver.set(f_kwargs={'w': w})
        solver.set_initial_condition([0, I])
        u, t = solver.solve(t_mesh)

        solver_name = \
               'CrankNicolson' if solver.__class__.__name__ == \
               'MidpointImplicit' else solver.__class__.__name__
        file_name = file_name + '_' + solver_name

        minima, maxima = minmax(t, u[:, 0])
        a = amplitudes(minima, maxima)
        plt.plot(range(len(a)), a, '-', label=solver_name)
        plt.hold('on')

    plt.xlabel('Number of periods')
    plt.ylabel('Amplitude (absolute value)')
    plt.legend(loc='upper left')
    plt.savefig(file_name + '.png')
    plt.savefig(file_name + '.pdf')
    plt.show()
def demo():
    """
    Demonstrate difference between Euler-Cromer and the
    scheme for the corresponding 2nd-order ODE.
    """
    I = 1.2
    V = 0.2
    m = 4
    b = 0.2
    s = lambda u: 2 * u
    F = lambda t: 0
    w = np.sqrt(2. / 4)  # approx freq
    dt = 0.9 * 2 / w  # longest possible time step
    w = 0.5
    P = 2 * pi / w
    T = 4 * P
    from vib import solver as solver2
    import scitools.std as plt
    for k in range(4):
        u2, t2 = solver2(I, V, m, b, s, F, dt, T, 'quadratic')
        u, v, t = solver(I, V, m, b, s, F, dt, T, 'quadratic')
        plt.figure()
        plt.plot(t, u, 'r-', t2, u2, 'b-')
        plt.legend(['Euler-Cromer', 'centered scheme'])
        plt.title('dt=%.3g' % dt)
        raw_input()
        plt.savefig('tmp_%d' % k + '.png')
        plt.savefig('tmp_%d' % k + '.pdf')
        dt /= 2
Esempio n. 5
0
    def plot(self, include_exact=True, plt=None):
        """
        Add solver.u curve to the plotting object plt,
        and include the exact solution if include_exact is True.
        This plot function can be called several times (if
        the solver object has computed new solutions).
        """
        if plt is None:
            import scitools.std  as plt # can use matplotlib as well

        plt.plot(self.solver.t, self.solver.u, '--o')
        plt.hold('on')
        theta2name = {0: 'FE', 1: 'BE', 0.5: 'CN'}
        name = theta2name.get(self.solver.theta, '')
        legends = ['numerical %s' % name]
        if include_exact:
            t_e = linspace(0, self.problem.T, 1001)
            u_e = self.problem.exact_solution(t_e)
            plt.plot(t_e, u_e, 'b-')
            legends.append('exact')
        plt.legend(legends)
        plt.xlabel('t')
        plt.ylabel('u')
        plt.title('theta=%g, dt=%g' %
                  (self.solver.theta, self.solver.dt))
        plt.savefig('%s_%g.png' % (name, self.solver.dt))
        return plt
Esempio n. 6
0
def run_solvers_and_check_amplitudes(solvers, timesteps_per_period=20,
                                     num_periods=1, I=1, w=2*np.pi):
    P = 2*np.pi/w  # duration of one period
    dt = P/timesteps_per_period
    Nt = num_periods*timesteps_per_period
    T = Nt*dt
    t_mesh = np.linspace(0, T, Nt+1)

    file_name = 'Amplitudes'   # initialize filename for plot
    for solver in solvers:
        solver.set(f_kwargs={'w': w})
        solver.set_initial_condition([0, I])
        u, t = solver.solve(t_mesh)

        solver_name = \
               'CrankNicolson' if solver.__class__.__name__ == \
               'MidpointImplicit' else solver.__class__.__name__
        file_name = file_name + '_' + solver_name

        minima, maxima = minmax(t, u[:,0])
        a = amplitudes(minima, maxima)
        plt.plot(range(len(a)), a, '-', label=solver_name)
        plt.hold('on')

    plt.xlabel('Number of periods')
    plt.ylabel('Amplitude (absolute value)')
    plt.legend(loc='upper left')
    plt.savefig(file_name + '.png')
    plt.savefig(file_name + '.pdf')
    plt.show()
Esempio n. 7
0
def u_P1():
    """
    Plot P1 basis functions and a resulting u to
    illustrate what it means to use finite elements.
    """
    import matplotlib.pyplot as plt
    x = [0, 1.5, 2.5, 3.5, 4]
    phi = [np.zeros(len(x)) for i in range(len(x)-2)]
    for i in range(len(phi)):
        phi[i][i+1] = 1
    #u = 5*x*np.exp(-0.25*x**2)*(4-x)
    u = [0, 8, 5, 4, 0]
    for i in range(len(phi)):
        plt.plot(x, phi[i], 'r-')  #, label=r'$\varphi_%d$' % i)
        plt.text(x[i+1], 1.2, r'$\varphi_%d$' % i)
    plt.plot(x, u, 'b-', label='$u$')
    plt.legend(loc='upper left')
    plt.axis([0, x[-1], 0, 9])
    plt.savefig('u_example_P1.png')
    plt.savefig('u_example_P1.pdf')
    # Mark elements
    for xi in x[1:-1]:
        plt.plot([xi, xi], [0, 9], 'm--')
    # Mark nodes
    #plt.plot(x, np.zeros(len(x)), 'ro', markersize=4)
    plt.savefig('u_example_P1_welms.png')
    plt.savefig('u_example_P1_welms.pdf')
    plt.show()
Esempio n. 8
0
def u_P1():
    """
    Plot P1 basis functions and a resulting u to
    illustrate what it means to use finite elements.
    """
    import matplotlib.pyplot as plt
    x = [0, 1.5, 2.5, 3.5, 4]
    phi = [np.zeros(len(x)) for i in range(len(x)-2)]
    for i in range(len(phi)):
        phi[i][i+1] = 1
    #u = 5*x*np.exp(-0.25*x**2)*(4-x)
    u = [0, 8, 5, 4, 0]
    for i in range(len(phi)):
        plt.plot(x, phi[i], 'r-')  #, label=r'$\varphi_%d$' % i)
        plt.text(x[i+1], 1.2, r'$\varphi_%d$' % i)
    plt.plot(x, u, 'b-', label='$u$')
    plt.legend(loc='upper left')
    plt.axis([0, x[-1], 0, 9])
    plt.savefig('tmp_u_P1.png')
    plt.savefig('tmp_u_P1.pdf')
    # Mark elements
    for xi in x[1:-1]:
        plt.plot([xi, xi], [0, 9], 'm--')
    # Mark nodes
    #plt.plot(x, np.zeros(len(x)), 'ro', markersize=4)
    plt.savefig('tmp_u_P1_welms.png')
    plt.savefig('tmp_u_P1_welms.pdf')
    plt.show()
Esempio n. 9
0
    def plot(self, include_exact=True, plt=None):
        """
        Add solver.u curve to scitools plotting object plt,
        and include the exact solution if include_exact is True.
        This plot function can be called several times (if
        the solver object has computed new solutions).
        """
        if plt is None:
            import scitools.std as plt

        plt.plot(self.solver.t, self.solver.u, '--o')
        plt.hold('on')
        theta = self.solver.get('theta')
        theta2name = {0: 'FE', 1: 'BE', 0.5: 'CN'}
        name = theta2name.get(theta, '')
        legends = ['numerical %s' % name]
        if include_exact:
            t_e = np.linspace(0, self.problem.get('T'), 1001)
            u_e = self.problem.exact_solution(t_e)
            plt.plot(t_e, u_e, 'b-')
            legends.append('exact')
        plt.legend(legends)
        plt.xlabel('t')
        plt.ylabel('u')
        dt = self.solver.get('dt')
        plt.title('theta=%g, dt=%g' % (theta, dt))
        plt.savefig('%s_%g.png' % (name, dt))
        return plt
Esempio n. 10
0
def demo():
    """
    Demonstrate difference between Euler-Cromer and the
    scheme for the corresponding 2nd-order ODE.
    """
    I = 1.2
    V = 0.2
    m = 4
    b = 0.2
    s = lambda u: 2 * u
    F = lambda t: 0
    w = np.sqrt(2.0 / 4)  # approx freq
    dt = 0.9 * 2 / w  # longest possible time step
    w = 0.5
    P = 2 * pi / w
    T = 4 * P
    from vib import solver as solver2
    import scitools.std as plt

    for k in range(4):
        u2, t2 = solver2(I, V, m, b, s, F, dt, T, "quadratic")
        u, v, t = solver(I, V, m, b, s, F, dt, T, "quadratic")
        plt.figure()
        plt.plot(t, u, "r-", t2, u2, "b-")
        plt.legend(["Euler-Cromer", "centered scheme"])
        plt.title("dt=%.3g" % dt)
        raw_input()
        plt.savefig("tmp_%d" % k + ".png")
        plt.savefig("tmp_%d" % k + ".pdf")
        dt /= 2
Esempio n. 11
0
def run_solvers_and_plot(solvers, rhs, T, dt, title=''):
    Nt = int(round(T/float(dt)))
    t_mesh = np.linspace(0, T, Nt+1)
    t_fine = np.linspace(0, T, 8*Nt+1)  # used for very accurate solution

    legends = []
    solver_exact = odespy.RK4(rhs)

    for solver in solvers:
        solver.set_initial_condition([rhs.I, 0])
        u, t = solver.solve(t_mesh)

        solver_name = 'CrankNicolson' if solver.__class__.__name__ == \
                      'MidpointImplicit' else solver.__class__.__name__

        if len(t_mesh) <= 50:
            plt.plot(t, u[:,0])             # markers by default
        else:
            plt.plot(t, u[:,0], '-2')       # no markers
        plt.hold('on')
        legends.append(solver_name)

    # Compare with RK4 on a much finer mesh
    solver_exact.set_initial_condition([rhs.I, 0])
    u_e, t_e = solver_exact.solve(t_fine)

    plt.plot(t_e, u_e[:,0], '-') # avoid markers by spec. line type
    legends.append('exact (RK4, dt=%g)' % (t_fine[1]-t_fine[0]))
    plt.legend(legends, loc='upper right')
    plt.xlabel('t');  plt.ylabel('u')
    plt.title(title)
    plotfilestem = '_'.join(legends)
    plt.savefig('tmp_%s.png' % plotfilestem)
    plt.savefig('tmp_%s.pdf' % plotfilestem)
Esempio n. 12
0
def run_solvers_and_plot(solvers, rhs, T, dt, title=''):
    Nt = int(round(T / float(dt)))
    t_mesh = np.linspace(0, T, Nt + 1)
    t_fine = np.linspace(0, T, 8 * Nt + 1)  # used for very accurate solution

    legends = []
    solver_exact = odespy.RK4(rhs)

    for solver in solvers:
        solver.set_initial_condition([rhs.I, 0])
        u, t = solver.solve(t_mesh)

        solver_name = 'CrankNicolson' if solver.__class__.__name__ == \
                      'MidpointImplicit' else solver.__class__.__name__

        if len(t_mesh) <= 50:
            plt.plot(t, u[:, 0])  # markers by default
        else:
            plt.plot(t, u[:, 0], '-2')  # no markers
        plt.hold('on')
        legends.append(solver_name)

    # Compare with RK4 on a much finer mesh
    solver_exact.set_initial_condition([rhs.I, 0])
    u_e, t_e = solver_exact.solve(t_fine)

    plt.plot(t_e, u_e[:, 0], '-')  # avoid markers by spec. line type
    legends.append('exact (RK4, dt=%g)' % (t_fine[1] - t_fine[0]))
    plt.legend(legends, loc='upper right')
    plt.xlabel('t')
    plt.ylabel('u')
    plt.title(title)
    plotfilestem = '_'.join(legends)
    plt.savefig('tmp_%s.png' % plotfilestem)
    plt.savefig('tmp_%s.pdf' % plotfilestem)
Esempio n. 13
0
def comparison_plot(u, Omega, u_e=None, filename='tmp.eps',
                    plot_title='', ymin=None, ymax=None):
    x = sp.Symbol('x')
    u = sp.lambdify([x], u, modules="numpy")
    if len(Omega) != 2:
        raise ValueError('Omega=%s must be an interval (2-list)' % str(Omega))
    # When doing symbolics, Omega can easily contain symbolic expressions,
    # assume .evalf() will work in that case to obtain numerical
    # expressions, which then must be converted to float before calling
    # linspace below
    if not isinstance(Omega[0], (int,float)):
        Omega[0] = float(Omega[0].evalf())
    if not isinstance(Omega[1], (int,float)):
        Omega[1] = float(Omega[1].evalf())

    resolution = 401  # no of points in plot
    xcoor = linspace(Omega[0], Omega[1], resolution)
    # Vectorized functions expressions does not work with
    # lambdify'ed functions without the modules="numpy"
    approx = u(xcoor)
    plot(xcoor, approx)
    legends = ['approximation']
    if u_e is not None:
        exact  = u_e(xcoor)
        hold('on')
        plot(xcoor, exact)
        legends = ['exact']
    legend(legends)
    title(plot_title)
    xlabel('x')
    if ymin is not None and ymax is not None:
        axis([xcoor[0], xcoor[-1], ymin, ymax])
    savefig(filename)
Esempio n. 14
0
def visualize(list_of_curves, legends, title='', filename='tmp'):
    """Plot list of curves: (u, t)."""
    for u, t in list_of_curves:
        plt.plot(t, u)
        plt.hold('on')
    plt.legend(legends)
    plt.xlabel('t')
    plt.ylabel('u')
    plt.title(title)
    plt.savefig(filename + '.png')
    plt.savefig(filename + '.pdf')
    plt.show()
Esempio n. 15
0
def visualize(list_of_curves, legends, title='', filename='tmp'):
    """Plot list of curves: (u, t)."""
    for u, t in list_of_curves:
        plt.plot(t, u)
        plt.hold('on')
    plt.legend(legends)
    plt.xlabel('t')
    plt.ylabel('u')
    plt.title(title)
    plt.savefig(filename + '.png')
    plt.savefig(filename + '.pdf')
    plt.show()
Esempio n. 16
0
def comparison_plot(f, u, Omega, filename='tmp.pdf'):
    x = sm.Symbol('x')
    f = sm.lambdify([x], f, modules="numpy")
    u = sm.lambdify([x], u, modules="numpy")
    resolution = 401  # no of points in plot
    xcoor  = linspace(Omega[0], Omega[1], resolution)
    exact  = f(xcoor)
    approx = u(xcoor)
    plot(xcoor, approx)
    hold('on')
    plot(xcoor, exact)
    legend(['approximation', 'exact'])
    savefig(filename)
Esempio n. 17
0
def plot_empirical_freq_and_amplitude(u, t):
    minima, maxima = minmax(t, u)
    p = periods(maxima)
    a = amplitudes(minima, maxima)
    plt.figure()
    from math import pi
    w = 2 * pi / p
    plt.plot(range(len(p)), w, 'r-')
    plt.hold('on')
    plt.plot(range(len(a)), a, 'b-')
    ymax = 1.1 * max(w.max(), a.max())
    ymin = 0.9 * min(w.min(), a.min())
    plt.axis([0, max(len(p), len(a)), ymin, ymax])
    plt.legend(['estimated frequency', 'estimated amplitude'],
               loc='upper right')
    return len(maxima)
Esempio n. 18
0
def plot_empirical_freq_and_amplitude(u, t):
    minima, maxima = minmax(t, u)
    p = periods(maxima)
    a = amplitudes(minima, maxima)
    plt.figure()
    from math import pi
    w = 2*pi/p    
    plt.plot(range(len(p)), w, 'r-')
    plt.hold('on')
    plt.plot(range(len(a)), a, 'b-')
    ymax = 1.1*max(w.max(), a.max())
    ymin = 0.9*min(w.min(), a.min())
    plt.axis([0, max(len(p), len(a)), ymin, ymax])
    plt.legend(['estimated frequency', 'estimated amplitude'],
               loc='upper right')
    return len(maxima)
Esempio n. 19
0
def run_solvers_and_plot(solvers, timesteps_per_period=20, num_periods=1, b=0):
    w = 2 * np.pi  # frequency of undamped free oscillations
    P = 2 * np.pi / w  # duration of one period
    dt = P / timesteps_per_period
    Nt = num_periods * timesteps_per_period
    T = Nt * dt
    t_mesh = np.linspace(0, T, Nt + 1)
    t_fine = np.linspace(0, T, 8 * Nt + 1)  # used for very accurate solution

    legends = []
    solver_exact = odespy.RK4(f)

    for solver in solvers:
        solver.set_initial_condition([solver.users_f.I, 0])
        u, t = solver.solve(t_mesh)

        solver_name = 'CrankNicolson' if solver.__class__.__name__ == \
                      'MidpointImplicit' else solver.__class__.__name__

        # Make plots (plot last 10 periods????)
        if num_periods <= 80:
            plt.figure(1)
            if len(t_mesh) <= 50:
                plt.plot(t, u[:, 0])  # markers by default
            else:
                plt.plot(t, u[:, 0], '-2')  # no markers
            plt.hold('on')
            legends.append(solver_name)

    # Compare with exact solution plotted on a very fine mesh
    #t_fine = np.linspace(0, T, 10001)
    #u_e = solver.users_f.exact(t_fine)
    # Compare with RK4 on a much finer mesh
    solver_exact.set_initial_condition([solver.users_f.I, 0])
    u_e, t_e = solver_exact.solve(t_fine)

    if num_periods < 80:
        plt.figure(1)
        plt.plot(t_e, u_e[:, 0], '-')  # avoid markers by spec. line type
        legends.append('exact (RK4)')
        plt.legend(legends, loc='upper left')
        plt.xlabel('t')
        plt.ylabel('u')
        plt.title('Time step: %g' % dt)
        plt.savefig('vib_%d_%d_u.png' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_u.pdf' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_u.eps' % (timesteps_per_period, num_periods))
Esempio n. 20
0
def run_solvers_and_plot(solvers, timesteps_per_period=20,
                         num_periods=1, b=0):
    w = 2*np.pi    # frequency of undamped free oscillations
    P = 2*np.pi/w  # duration of one period
    dt = P/timesteps_per_period
    Nt = num_periods*timesteps_per_period
    T = Nt*dt
    t_mesh = np.linspace(0, T, Nt+1)
    t_fine = np.linspace(0, T, 8*Nt+1)  # used for very accurate solution

    legends = []
    solver_exact = odespy.RK4(f)

    for solver in solvers:
        solver.set_initial_condition([solver.users_f.I, 0])
        u, t = solver.solve(t_mesh)

        solver_name = 'CrankNicolson' if solver.__class__.__name__ == \
                      'MidpointImplicit' else solver.__class__.__name__

        # Make plots (plot last 10 periods????)
        if num_periods <= 80:
            plt.figure(1)
            if len(t_mesh) <= 50:
                plt.plot(t, u[:,0])             # markers by default
            else:
                plt.plot(t, u[:,0], '-2')       # no markers
            plt.hold('on')
            legends.append(solver_name)

    # Compare with exact solution plotted on a very fine mesh
    #t_fine = np.linspace(0, T, 10001)
    #u_e = solver.users_f.exact(t_fine)
    # Compare with RK4 on a much finer mesh
    solver_exact.set_initial_condition([solver.users_f.I, 0])
    u_e, t_e = solver_exact.solve(t_fine)

    if num_periods < 80:
        plt.figure(1)
        plt.plot(t_e, u_e[:,0], '-') # avoid markers by spec. line type
        legends.append('exact (RK4)')
        plt.legend(legends, loc='upper left')
        plt.xlabel('t');  plt.ylabel('u')
        plt.title('Time step: %g' % dt)
        plt.savefig('vib_%d_%d_u.png' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_u.pdf' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_u.eps' % (timesteps_per_period, num_periods))
Esempio n. 21
0
def approximate(f, symbolic=False, d=1, N_e=4,
                Omega=[0, 1], filename='tmp'):
    phi = basis(d)
    print 'phi basis (reference element):\n', phi

    nodes, elements = mesh_uniform(N_e, d, Omega, symbolic)
    A, b = assemble(nodes, elements, phi, f, symbolic=symbolic)

    print 'nodes:', nodes
    print 'elements:', elements
    print 'A:\n', A
    print 'b:\n', b
    print sym.latex(A, mode='plain')
    #print sym.latex(b, mode='plain')

    if symbolic:
        c = A.LUsolve(b)
        c = [c[i,0] for i in range(c.shape[0])]
    else:
        c = np.linalg.solve(A, b)

    print 'c:\n', c

    print 'Plain interpolation/collocation:'
    x = sym.Symbol('x')
    f = sym.lambdify([x], f, modules='numpy')
    try:
        f_at_nodes = [f(xc) for xc in nodes]
    except NameError as e:
        raise NameError('numpy does not support special function:\n%s' % e)
    print f_at_nodes

    if not symbolic and filename is not None:
        xf = np.linspace(Omega[0], Omega[1], 10001)
        U = np.asarray(c)  # c is a plain array
        xu, u = u_glob(U, elements, nodes)
        import scitools.std as plt
        #import matplotlib.pyplot as plt
        plt.plot(xu, u, '-',
                 xf, f(xf), '--')
        plt.legend(['u', 'f'])
        plt.savefig(filename + '.pdf')
        plt.savefig(filename + '.png')

    return c
Esempio n. 22
0
def approximate(f, symbolic=False, d=1, N_e=4, Omega=[0, 1], filename="tmp"):
    phi = basis(d)
    print "phi basis (reference element):\n", phi

    nodes, elements = mesh_uniform(N_e, d, Omega, symbolic)
    A, b = assemble(nodes, elements, phi, f, symbolic=symbolic)

    print "nodes:", nodes
    print "elements:", elements
    print "A:\n", A
    print "b:\n", b
    print sym.latex(A, mode="plain")
    # print sym.latex(b, mode='plain')

    if symbolic:
        c = A.LUsolve(b)
        c = [c[i, 0] for i in range(c.shape[0])]
    else:
        c = np.linalg.solve(A, b)

    print "c:\n", c

    print "Plain interpolation/collocation:"
    x = sym.Symbol("x")
    f = sym.lambdify([x], f, modules="numpy")
    try:
        f_at_nodes = [f(xc) for xc in nodes]
    except NameError as e:
        raise NameError("numpy does not support special function:\n%s" % e)
    print f_at_nodes

    if not symbolic and filename is not None:
        xf = np.linspace(Omega[0], Omega[1], 10001)
        U = np.asarray(c)  # c is a plain array
        xu, u = u_glob(U, elements, nodes)
        import scitools.std as plt

        # import matplotlib.pyplot as plt
        plt.plot(xu, u, "-", xf, f(xf), "--")
        plt.legend(["u", "f"])
        plt.savefig(filename + ".pdf")
        plt.savefig(filename + ".png")

    return c
def run_solver_and_plot(solver, timesteps_per_period=20,
                        num_periods=1, I=1, w=2*np.pi):
    P = 2*np.pi/w  # duration of one period
    dt = P/timesteps_per_period
    Nt = num_periods*timesteps_per_period
    T = Nt*dt
    t_mesh = np.linspace(0, T, Nt+1)

    solver.set(f_kwargs={'w': w})
    solver.set_initial_condition([0, I])
    u, t = solver.solve(t_mesh)

    from vib_undamped import solver
    u2, t2 = solver(I, w, dt, T)

    plt.plot(t, u[:,1], 'r-', t2, u2, 'b-')
    plt.legend(['Euler-Cromer', '2nd-order ODE'])
    plt.xlabel('t');  plt.ylabel('u')
    plt.savefig('tmp1.png'); plt.savefig('tmp1.pdf')
Esempio n. 24
0
def u_sines():
    """
    Plot sine basis functions and a resulting u to
    illustrate what it means to use global basis functions.
    """
    import matplotlib.pyplot as plt
    x = np.linspace(0, 4, 1001)
    psi0 = np.sin(2*np.pi/4*x)
    psi1 = np.sin(2*np.pi*x)
    psi2 = np.sin(2*np.pi*4*x)
    u = 4*psi0 - 0.5*psi1 - 0*psi2
    plt.plot(x, psi0, 'r-', label=r"$\psi_0$")
    plt.plot(x, psi1, 'g-', label=r"$\psi_1$")
    #plt.plot(x, psi2, label=r"$\psi_2$")
    plt.plot(x, u, 'b-', label=r"u")
    plt.legend()
    plt.savefig('tmp_u_sines.pdf')
    plt.savefig('tmp_u_sines.png')
    plt.show()
Esempio n. 25
0
def fe_basis_function_figure(d,
                             target_elm=[1],
                             N_e=3,
                             derivative=0,
                             filename='tmp.pdf',
                             labels=False):
    """
    Draw all basis functions (or their derivative), of degree d,
    associated with element target_elm (may be list of elements).
    Add a mesh with N_e elements.
    """
    nodes, elements = mesh_uniform(N_e, d)
    """
    x = 1.1
    print locate_element_vectorized(x, elements, nodes)
    print locate_element_scalar(x, elements, nodes)
    x = 0.1, 0.4, 0.8
    print locate_element_vectorized(x, elements, nodes)
    """
    if isinstance(target_elm, int):
        target_elm = [target_elm]  # wrap in list

    # Draw the basis functions for element 1
    phi_drawn = []  # list of already drawn phi functions
    ymin = ymax = 0
    for e in target_elm:
        for i in elements[e]:
            if not i in phi_drawn:
                x, y = phi_glob(i, elements, nodes, derivative=derivative)
                if x is None and y is None:
                    return  # abort
                ymax = max(ymax, max(y))
                ymin = min(ymin, min(y))
                plt.plot(x, y, '-')
                plt.hold('on')
                if labels:
                    if plt.backend == 'gnuplot':
                        if derivative == 0:
                            plt.legend(r'basis func. %d' % i)
                        else:
                            plt.legend(r'derivative of basis func. %d' % i)
                    elif plt.backend == 'matplotlib':
                        if derivative == 0:
                            plt.legend(r'\varphi_%d' % i)
                        else:
                            plt.legend(r"\varphi_%d'(x)" % i)
                phi_drawn.append(i)

    plt.axis([nodes[0], nodes[-1], ymin - 0.1, ymax + 0.1])
    plot_fe_mesh(nodes, elements, element_marker=[ymin - 0.1, ymax + 0.1])
    plt.hold('off')
    plt.savefig(filename)
Esempio n. 26
0
def u_sines():
    """
    Plot sine basis functions and a resulting u to
    illustrate what it means to use global basis functions.
    """
    import matplotlib.pyplot as plt
    x = np.linspace(0, 4, 1001)
    psi0 = np.sin(2*np.pi/4*x)
    psi1 = np.sin(2*np.pi*x)
    psi2 = np.sin(2*np.pi*4*x)
    #u = 4*psi0 - 0.5*psi1 - 0*psi2
    u = 4*psi0 - 0.5*psi1
    plt.plot(x, psi0, 'r-', label=r"$\psi_0$")
    plt.plot(x, psi1, 'g-', label=r"$\psi_1$")
    #plt.plot(x, psi2, label=r"$\psi_2$")
    plt.plot(x, u, 'b-', label=r"$u=4\psi_0 - \frac{1}{2}\psi_1$")
    plt.legend()
    plt.savefig('u_example_sin.pdf')
    plt.savefig('u_example_sin.png')
    plt.show()
Esempio n. 27
0
def fe_basis_function_figure(d, target_elm=[1], n_e=3,
                             derivative=0, filename='tmp.pdf',
                             labels=False):
    """
    Draw all basis functions (or their derivative), of degree d,
    associated with element target_elm (may be list of elements).
    Add a mesh with n_e elements.
    """
    nodes, elements = mesh_uniform(n_e, d)
    """
    x = 1.1
    print locate_element_vectorized(x, elements, nodes)
    print locate_element_scalar(x, elements, nodes)
    x = 0.1, 0.4, 0.8
    print locate_element_vectorized(x, elements, nodes)
    """
    if isinstance(target_elm, int):
        target_elm = [target_elm]  # wrap in list

    # Draw the basis functions for element 1
    phi_drawn = []  # list of already drawn phi functions
    ymin = ymax = 0
    for e in target_elm:
        for i in elements[e]:
            if not i in phi_drawn:
                x, y = phi_glob(i, elements, nodes,
                                derivative=derivative)
                if x is None and y is None:
                    return  # abort
                ymax = max(ymax, max(y))
                ymin = min(ymin, min(y))
                plt.plot(x, y, '-')
                plt.hold('on')
                if labels:
                    if plt.backend == 'gnuplot':
                        if derivative == 0:
                            plt.legend(r'basis function no. %d' % i)
                        else:
                            plt.legend(r'derivative of basis function no. %d' % i)
                    elif plt.backend == 'matplotlib':
                        if derivative == 0:
                            plt.legend(r'\varphi_%d' % i)
                        else:
                            plt.legend(r"\varphi_%d'(x)" % i)
                phi_drawn.append(i)

    plt.axis([nodes[0], nodes[-1], ymin-0.1, ymax+0.1])
    plot_fe_mesh(nodes, elements, element_marker=[ymin-0.1, ymax+0.1])
    plt.hold('off')
    plt.savefig(filename)
Esempio n. 28
0
def run_solver_and_plot(solver,
                        timesteps_per_period=20,
                        num_periods=1,
                        I=1,
                        w=2 * np.pi):
    P = 2 * np.pi / w  # duration of one period
    dt = P / timesteps_per_period
    Nt = num_periods * timesteps_per_period
    T = Nt * dt
    t_mesh = np.linspace(0, T, Nt + 1)

    solver.set(f_kwargs={'w': w})
    solver.set_initial_condition([0, I])
    u, t = solver.solve(t_mesh)

    from vib_undamped import solver
    u2, t2 = solver(I, w, dt, T)

    plt.plot(t, u[:, 1], 'r-', t2, u2, 'b-')
    plt.legend(['Euler-Cromer', '2nd-order ODE'])
    plt.xlabel('t')
    plt.ylabel('u')
    plt.savefig('tmp1.png')
    plt.savefig('tmp1.pdf')
Esempio n. 29
0
solvers = [
    odespy.RK2(f),
    odespy.RK3(f),
    odespy.RK4(f),
    # BackwardEuler must use Newton solver to converge
    # (Picard is default and leads to divergence)
    odespy.BackwardEuler(f, nonlinear_solver='Newton')
]

legends = []
for solver in solvers:
    solver.set_initial_condition(I)
    u, t = solver.solve(t_mesh)

    plt.plot(t, u)
    plt.hold('on')
    legends.append(solver.__class__.__name__)

# Compare with exact solution plotted on a very fine mesh
t_fine = np.linspace(0, T, 10001)
u_e = I * np.exp(-a * t_fine)
plt.plot(t_fine, u_e, '-')  # avoid markers by specifying line type
legends.append('exact')

plt.legend(legends)
plt.title('Time step: %g' % dt)
plt.savefig('odespy1_dt_%g.png' % dt)
plt.savefig('odespy1_dt_%g.pdf' % dt)
plt.show()
def approximate(f, symbolic=False, d=1, N_e=4, numint=None,
                Omega=[0, 1], collocation=False, filename='tmp'):
    """
    Compute the finite element approximation, using Lagrange
    elements of degree d, to a symbolic expression f (with x
    as independent variable) on a domain Omega. N_e is the
    number of elements.
    symbolic=True implies symbolic expressions in the
    calculations, while symbolic=False means numerical
    computing.
    numint is the name of the numerical integration rule
    (Trapezoidal, Simpson, GaussLegendre2, GaussLegendre3,
    GaussLegendre4, etc.). numint=None implies exact
    integration.
    """
    numint_name = numint  # save name
    if symbolic:
        if numint == 'Trapezoidal':
            numint = [[sym.S(-1), sym.S(1)], [sym.S(1), sym.S(1)]]  # sympy integers
        elif numint == 'Simpson':
            numint = [[sym.S(-1), sym.S(0), sym.S(1)],
                      [sym.Rational(1,3), sym.Rational(4,3), sym.Rational(1,3)]]
        elif numint == 'Midpoint':
            numint = [[sym.S(0)],  [sym.S(2)]]
        elif numint == 'GaussLegendre2':
            numint = [[-1/sym.sqrt(3), 1/sym.sqrt(3)], [sym.S(1), sym.S(1)]]
        elif numint == 'GaussLegendre3':
            numint = [[-sym.sqrt(sym.Rational(3,5)), 0,
                       sym.sqrt(sym.Rational(3,5))],
                      [sym.Rational(5,9), sym.Rational(8,9),
                       sym.Rational(5,9)]]
        elif numint is not None:
            print 'Numerical rule %s is not supported for symbolic computing' % numint
            numint = None
    else:
        if numint == 'Trapezoidal':
            numint = [[-1, 1], [1, 1]]
        elif numint == 'Simpson':
            numint = [[-1, 0, 1], [1./3, 4./3, 1./3]]
        elif numint == 'Midpoint':
            numint = [[0], [2]]
        elif numint == 'GaussLegendre2':
            numint = [[-1/sqrt(3), 1/sqrt(3)], [1, 1]]
        elif numint == 'GaussLegendre3':
            numint = [[-sqrt(3./5), 0, sqrt(3./5)],
                      [5./9, 8./9, 5./9]]
        elif numint == 'GaussLegendre4':
            numint = [[-0.86113631, -0.33998104,  0.33998104,  0.86113631],
                      [ 0.34785485,  0.65214515,  0.65214515,  0.34785485]]
        elif numint == 'GaussLegendre5':
            numint = [[-0.90617985, -0.53846931, -0.        ,  0.53846931,  0.90617985],
                      [ 0.23692689,  0.47862867,  0.56888889,  0.47862867,  0.23692689]]
        elif numint is not None:
            print 'Numerical rule %s is not supported for numerical computing' % numint
            numint = None


    vertices, cells, dof_map = mesh_uniform(N_e, d, Omega, symbolic)

    # phi is a list where phi[e] holds the basis in cell no e
    # (this is required by assemble, which can work with
    # meshes with different types of elements).
    # len(dof_map[e]) is the number of nodes in cell e,
    # and the degree of the polynomial is len(dof_map[e])-1
    phi = [basis(len(dof_map[e])-1) for e in range(N_e)]

    A, b = assemble(vertices, cells, dof_map, phi, f,
                    symbolic=symbolic, numint=numint)

    print 'cells:', cells
    print 'vertices:', vertices
    print 'dof_map:', dof_map
    print 'A:\n', A
    print 'b:\n', b
    #print sym.latex(A, mode='plain')
    #print sym.latex(b, mode='plain')

    if symbolic:
        c = A.LUsolve(b)
        c = np.asarray([c[i,0] for i in range(c.shape[0])])
    else:
        c = np.linalg.solve(A, b)

    print 'c:\n', c

    x = sym.Symbol('x')
    f = sym.lambdify([x], f, modules='numpy')

    if collocation and not symbolic:
        print 'Plain interpolation/collocation:'
        # Should use vertices, but compute all nodes!
        f_at_vertices = [f(xc) for xc in vertices]
        print f_at_vertices

    if filename is not None:
        title = 'P%d, N_e=%d' % (d, N_e)
        if numint is None:
            title += ', exact integration'
        else:
            title += ', integration: %s' % numint_name
        x_u, u, _ = u_glob(c, vertices, cells, dof_map,
                           resolution_per_element=51)
        x_f = np.linspace(Omega[0], Omega[1], 10001) # mesh for f
        import scitools.std as plt
        plt.plot(x_u, u, '-',
                 x_f, f(x_f), '--')
        plt.legend(['u', 'f'])
        plt.title(title)
        plt.savefig(filename + '.pdf')
        plt.savefig(filename + '.png')

    return c
Esempio n. 31
0
def approximate(f, d, N_e, numint, Omega=[0,1], filename='tmp'):
    """
    Compute the finite element approximation, using Lagrange
    elements of degree d, to a Python functionn f on a domain
    Omega. N_e is the number of elements.
    numint is the name of the numerical integration rule
    (Trapezoidal, Simpson, GaussLegendre2, GaussLegendre3,
    GaussLegendre4, etc.). numint=None implies exact
    integration.
    """
    from math import sqrt
    numint_name = numint  # save name
    if numint == 'Trapezoidal':
        numint = [[-1, 1], [1, 1]]
    elif numint == 'Simpson':
        numint = [[-1, 0, 1], [1./3, 4./3, 1./3]]
    elif numint == 'Midpoint':
        numint = [[0], [2]]
    elif numint == 'GaussLegendre2':
        numint = [[-1/sqrt(3), 1/sqrt(3)], [1, 1]]
    elif numint == 'GaussLegendre3':
        numint = [[-sqrt(3./5), 0, sqrt(3./5)],
                  [5./9, 8./9, 5./9]]
    elif numint == 'GaussLegendre4':
        numint = [[-0.86113631, -0.33998104,  0.33998104,
                   0.86113631],
                  [ 0.34785485,  0.65214515,  0.65214515,
                    0.34785485]]
    elif numint == 'GaussLegendre5':
        numint = [[-0.90617985, -0.53846931, -0.        ,
                   0.53846931,  0.90617985],
                  [ 0.23692689,  0.47862867,  0.56888889,
                    0.47862867,  0.23692689]]
    elif numint is not None:
        print 'Numerical rule %s is not supported for numerical computing' % numint
        sys.exit(1)


    vertices, cells, dof_map = mesh_uniform(N_e, d, Omega)

    # phi is a list where phi[e] holds the basis in cell no e
    # (this is required by assemble, which can work with
    # meshes with different types of elements).
    # len(dof_map[e]) is the number of nodes in cell e,
    # and the degree of the polynomial is len(dof_map[e])-1
    phi = [basis(len(dof_map[e])-1) for e in range(N_e)]

    A, b = assemble(vertices, cells, dof_map, phi, f,
                    numint=numint)

    print 'cells:', cells
    print 'vertices:', vertices
    print 'dof_map:', dof_map
    print 'A:\n', A
    print 'b:\n', b
    c = np.linalg.solve(A, b)
    print 'c:\n', c

    if filename is not None:
        title = 'P%d, N_e=%d' % (d, N_e)
        title += ', integration: %s' % numint_name
        x_u, u, _ = u_glob(np.asarray(c), vertices, cells, dof_map,
                           resolution_per_element=51)
        x_f = np.linspace(Omega[0], Omega[1], 10001) # mesh for f
        import scitools.std as plt
        plt.plot(x_u, u, '-',
                 x_f, f(x_f), '--')
        plt.legend(['u', 'f'])
        plt.title(title)
        plt.savefig(filename + '.pdf')
        plt.savefig(filename + '.png')
    return c
Esempio n. 32
0
def f(u, t):
    return -a * u


def exact_solution(t):
    return I * np.exp(-a * t)


I = 1
a = 2
T = 5
tol = float(sys.argv[1])
solver = odespy.DormandPrince(f, atol=tol, rtol=0.1 * tol)

N = 1  # just one step - let the scheme find its intermediate points
t_mesh = np.linspace(0, T, N + 1)
t_fine = np.linspace(0, T, 10001)

solver.set_initial_condition(I)
u, t = solver.solve(t_mesh)

# u and t will only consist of [I, u^N] and [0,T]
# solver.u_all and solver.t_all contains all computed points
plt.plot(solver.t_all, solver.u_all, 'ko')
plt.hold('on')
plt.plot(t_fine, exact_solution(t_fine), 'b-')
plt.legend(['tol=%.0E' % tol, 'exact'])
plt.savefig('tmp_odespy_adaptive.png')
plt.show()
Esempio n. 33
0
def estimate(truncation_error, T, N_0, m, makeplot=True):
    """
    Compute the truncation error in a problem with one independent
    variable, using m meshes, and estimate the convergence
    rate of the truncation error.

    The user-supplied function truncation_error(dt, N) computes
    the truncation error on a uniform mesh with N intervals of
    length dt::

      R, t, R_a = truncation_error(dt, N)

    where R holds the truncation error at points in the array t,
    and R_a are the corresponding theoretical truncation error
    values (None if not available).

    The truncation_error function is run on a series of meshes
    with 2**i*N_0 intervals, i=0,1,...,m-1.
    The values of R and R_a are restricted to the coarsest mesh.
    and based on these data, the convergence rate of R (pointwise)
    and time-integrated R can be estimated empirically.
    """
    N = [2**i*N_0 for i in range(m)]

    R_I = np.zeros(m) # time-integrated R values on various meshes
    R   = [None]*m    # time series of R restricted to coarsest mesh
    R_a = [None]*m    # time series of R_a restricted to coarsest mesh
    dt = np.zeros(m)
    legends_R = [];  legends_R_a = []  # all legends of curves

    for i in range(m):
        dt[i] = T/float(N[i])
        R[i], t, R_a[i] = truncation_error(dt[i], N[i])

        R_I[i] = np.sqrt(dt[i]*np.sum(R[i]**2))

        if i == 0:
            t_coarse = t           # the coarsest mesh

        stride = N[i]/N_0
        R[i] = R[i][::stride]      # restrict to coarsest mesh
        R_a[i] = R_a[i][::stride]

        if makeplot:
            plt.figure(1)
            plt.plot(t_coarse, R[i], log='y')
            legends_R.append('N=%d' % N[i])
            plt.hold('on')

            plt.figure(2)
            plt.plot(t_coarse, R_a[i] - R[i], log='y')
            plt.hold('on')
            legends_R_a.append('N=%d' % N[i])

    if makeplot:
        plt.figure(1)
        plt.xlabel('time')
        plt.ylabel('pointwise truncation error')
        plt.legend(legends_R)
        plt.savefig('R_series.png')
        plt.savefig('R_series.pdf')
        plt.figure(2)
        plt.xlabel('time')
        plt.ylabel('pointwise error in estimated truncation error')
        plt.legend(legends_R_a)
        plt.savefig('R_error.png')
        plt.savefig('R_error.pdf')

    # Convergence rates
    r_R_I = convergence_rates(dt, R_I)
    print 'R integrated in time; r:',
    print ' '.join(['%.1f' % r for r in r_R_I])
    R = np.array(R)  # two-dim. numpy array
    r_R = [convergence_rates(dt, R[:,n])[-1]
           for n in range(len(t_coarse))]

    # Plot convergence rates
    if makeplot:
        plt.figure()
        plt.plot(t_coarse, r_R)
        plt.xlabel('time')
        plt.ylabel('r')
        plt.axis([t_coarse[0], t_coarse[-1], 0, 2.5])
        plt.title('Pointwise rate $r$ in truncation error $\sim\Delta t^r$')
        plt.savefig('R_rate_series.png')
        plt.savefig('R_rate_series.pdf')
Esempio n. 34
0
def run(gamma, beta=10, delta=40, scaling=1, animate=False):
    """Run the scaled model for welding."""
    if scaling == 1:
        v = gamma
        a = 1
    elif scaling == 2:
        v = 1
        a = 1.0/gamma

    b = 0.5*beta**2
    L = 1.0
    ymin = 0
    # Need gloal to be able change ymax in closure process_u
    global ymax
    ymax = 1.2

    I = lambda x: 0
    f = lambda x, t: delta*np.exp(-b*(x - v*t)**2)

    import time
    import scitools.std as plt
    plot_arrays = []

    def process_u(u, x, t, n):
        global ymax
        if animate:
            plt.plot(x, u, 'r-',
                     x, f(x, t[n])/delta, 'b-',
                     axis=[0, L, ymin, ymax], title='t=%f' % t[n],
                     xlabel='x', ylabel='u and f/%g' % delta)
        if t[n] == 0:
            time.sleep(1)
            plot_arrays.append(x)
        dt = t[1] - t[0]
        tol = dt/10.0
        if abs(t[n] - 0.2) < tol or abs(t[n] - 0.5) < tol:
            plot_arrays.append((u.copy(), f(x, t[n])/delta))
            if u.max() > ymax:
                ymax = u.max()

    Nx = 100
    D = 10
    T = 0.5
    u_L = u_R = 0
    theta = 1.0
    cpu = solver(
        I, a, f, L, Nx, D, T, theta, u_L, u_R, user_action=process_u)
    x = plot_arrays[0]
    plt.figure()
    for u, f in plot_arrays[1:]:
        plt.plot(x, u, 'r-', x, f, 'b--', axis=[x[0], x[-1], 0, ymax],
                 xlabel='$x$', ylabel=r'$u, \ f/%g$' % delta)
        plt.hold('on')
    plt.legend(['$u,\\ t=0.2$', '$f/%g,\\ t=0.2$' % delta,
                '$u,\\ t=0.5$', '$f/%g,\\ t=0.5$' % delta])
    filename = 'tmp1_gamma%g_s%d' % (gamma, scaling)
    s = 'diffusion' if scaling == 1 else 'source'
    plt.title(r'$\beta = %g,\ \gamma = %g,\ $' % (beta, gamma)
              + 'scaling=%s' % s)
    plt.savefig(filename + '.pdf');  plt.savefig(filename + '.png')
    return cpu
Esempio n. 35
0
def approximate(f, symbolic=False, d=1, N_e=4, numint=None,
                Omega=[0, 1], filename='tmp'):
    if symbolic:
        if numint == 'Trapezoidal':
            numint = [[sp.S(-1), sp.S(1)], [sp.S(1), sp.S(1)]]  # sympy integers
        elif numint == 'Simpson':
            numint = [[sp.S(-1), sp.S(0), sp.S(1)],
                      [sp.Rational(1,3), sp.Rational(4,3), sp.Rational(1,3)]]
        elif numint == 'Midpoint':
            numint = [[sp.S(0)],  [sp.S(2)]]
        elif numint == 'GaussLegendre2':
            numint = [[-1/sp.sqrt(3), 1/sp.sqrt(3)], [sp.S(1), sp.S(1)]]
        elif numint == 'GaussLegendre3':
            numint = [[-sp.sqrt(sp.Rational(3,5)), 0,
                       sp.sqrt(sp.Rational(3,5))],
                      [sp.Rational(5,9), sp.Rational(8,9),
                       sp.Rational(5,9)]]
        elif numint is not None:
            print 'Numerical rule %s is not supported' % numint
            numint = None
    else:
        if numint == 'Trapezoidal':
            numint = [[-1, 1], [1, 1]]
        elif numint == 'Simpson':
            numint = [[-1, 0, 1], [1./3, 4./3, 1./3]]
        elif numint == 'Midpoint':
            numint = [[0], [2]]
        elif numint == 'GaussLegendre2':
            numint = [[-1/sqrt(3), 1/sqrt(3)], [1, 1]]
        elif numint == 'GaussLegendre3':
            numint = [[-sqrt(3./5), 0, sqrt(3./5)],
                      [5./9, 8./9, 5./9]]
        elif numint is not None:
            print 'Numerical rule %s is not supported' % numint
            numint = None


    vertices, cells, dof_map = mesh_uniform(N_e, d, Omega, symbolic)

    # phi is a list where phi[e] holds the basis in cell no e
    # (this is required by assemble, which can work with
    # meshes with different types of elements).
    # len(dof_map[e]) is the number of nodes in cell e,
    # and the degree of the polynomial is len(dof_map[e])-1
    phi = [basis(len(dof_map[e])-1) for e in range(N_e)]

    print 'phi basis (reference element):\n', phi
    A, b = assemble(vertices, cells, dof_map, phi, f,
                    symbolic=symbolic, numint=numint)

    print 'cells:', cells
    print 'vertices:', vertices
    print 'dof_map:', dof_map
    print 'A:\n', A
    print 'b:\n', b
    #print sp.latex(A, mode='plain')
    #print sp.latex(b, mode='plain')

    if symbolic:
        c = A.LUsolve(b)
    else:
        c = np.linalg.solve(A, b)

    print 'c:\n', c

    if not symbolic:
        print 'Plain interpolation/collocation:'
        x = sp.Symbol('x')
        f = sp.lambdify([x], f, modules='numpy')
        try:
            f_at_vertices = [f(xc) for xc in vertices]
            print f_at_vertices
        except Exception as e:
            print 'could not evaluate f numerically:'
            print e
    # else: nodes are symbolic so f(nodes[i]) only makes sense
    # in the non-symbolic case

    if not symbolic and filename is not None:
        title = 'P%d, N_e=%d' % (d, N_e)
        if numint is None:
            title += ', exact integration'
        else:
            title += ', integration: %s' % numint
        x_u, u = u_glob(np.asarray(c), vertices, cells, dof_map,
                        resolution_per_element=51)
        x_f = np.linspace(Omega[0], Omega[1], 10001) # mesh for f
        plt.plot(x_u, u, '-',
                 x_f, f(x_f), '--')
        plt.legend(['u', 'f'])
        plt.title(title)
        plt.savefig(filename + '.pdf')
        plt.savefig(filename + '.png')
    return c
Esempio n. 36
0
def run_solvers_and_plot(solvers, timesteps_per_period=20,
                         num_periods=1, I=1, w=2*np.pi):
    P = 2*np.pi/w  # duration of one period
    dt = P/timesteps_per_period
    Nt = num_periods*timesteps_per_period
    T = Nt*dt
    t_mesh = np.linspace(0, T, Nt+1)

    legends = []
    for solver in solvers:
        solver.set(f_kwargs={'w': w})
        solver.set_initial_condition([I, 0])
        u, t = solver.solve(t_mesh)

        # Compute energy
        dt = t[1] - t[0]
        E = 0.5*((u[2:,0] - u[:-2,0])/(2*dt))**2 + 0.5*w**2*u[1:-1,0]**2
        # Compute error in energy
        E0 = 0.5*0**2 + 0.5*w**2*I**2
        e_E = E - E0

        solver_name = 'CrankNicolson' if solver.__class__.__name__ == \
                      'MidpointImplicit' else solver.__class__.__name__
        print '*** Relative max error in energy for %s [0,%g] with dt=%g: %.3E' % (solver_name, t[-1], dt, np.abs(e_E).max()/E0)

        # Make plots
        if num_periods <= 80:
            plt.figure(1)
            if len(t_mesh) <= 50:
                plt.plot(t, u[:,0])             # markers by default
            else:
                plt.plot(t, u[:,0], '-2')       # no markers
            plt.hold('on')
            legends.append(solver.__class__.__name__)
            plt.figure(2)
            if len(t_mesh) <= 50:
                plt.plot(u[:,0], u[:,1])        # markers by default
            else:
                plt.plot(u[:,0], u[:,1], '-2')  # no markers
            plt.hold('on')

        if num_periods > 20:
            minima, maxima = minmax(t, u[:,0])
            p = periods(maxima)
            a = amplitudes(minima, maxima)
            plt.figure(3)
            plt.plot(range(len(p)), 2*np.pi/p, '-')
            plt.hold('on')
            plt.figure(4)
            plt.plot(range(len(a)), a, '-')
            plt.hold('on')

    # Compare with exact solution plotted on a very fine mesh
    t_fine = np.linspace(0, T, 10001)
    u_e = I*np.cos(w*t_fine)
    v_e = -w*I*np.sin(w*t_fine)

    if num_periods < 80:
        plt.figure(1)
        plt.plot(t_fine, u_e, '-') # avoid markers by spec. line type
        legends.append('exact')
        plt.legend(legends, loc='upper left')
        plt.xlabel('t');  plt.ylabel('u')
        plt.title('Time step: %g' % dt)
        plt.savefig('vib_%d_%d_u.png' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_u.pdf' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_u.eps' % (timesteps_per_period, num_periods))

        plt.figure(2)
        plt.plot(u_e, v_e, '-') # avoid markers by spec. line type
        plt.legend(legends, loc='lower right')
        plt.xlabel('u(t)');  plt.ylabel('v(t)')
        plt.title('Time step: %g' % dt)
        plt.savefig('vib_%d_%d_pp.png' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_pp.pdf' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_pp.eps' % (timesteps_per_period, num_periods))
        del legends[-1]  # fig 3 and 4 does not have exact value

    if num_periods > 20:
        plt.figure(3)
        plt.legend(legends, loc='center right')
        plt.title('Empirically estimated periods')
        plt.savefig('vib_%d_%d_p.eps' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_p.png' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_p.eps' % (timesteps_per_period, num_periods))
        plt.figure(4)
        plt.legend(legends, loc='center right')
        plt.title('Empirically estimated amplitudes')
        plt.savefig('vib_%d_%d_a.eps' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_a.png' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_a.eps' % (timesteps_per_period, num_periods))
t_mesh = np.linspace(0, T, Nt + 1)
t_fine = np.linspace(0, T, 10001)

solver.set_initial_condition(u0)
u, t = solver.solve(t_mesh)

# u and t will only consist of [I, u^Nt] and [0,T], i.e. 2 values
# each, while solver.u_all and solver.t_all contain all computed
# points. solver.u_all is a list with arrays, one array (with 2
# values) for each point in time.
u_adaptive = np.array(solver.u_all)

# For comparison, we solve also with simple FDM method
import sys, os
sys.path.insert(0, os.path.join(os.pardir, 'src-vib'))
from vib_undamped import solver as simple_solver
Nt_simple = len(solver.t_all)
dt = float(T) / Nt_simple
u_simple, t_simple = simple_solver(I, w, dt, T)

# Compare in plot: adaptive, constant dt, exact
plt.plot(solver.t_all, u_adaptive[:, 0], 'k-')
plt.hold('on')
plt.plot(t_simple, u_simple, 'r--')
plt.plot(t_fine, u_exact(t_fine), 'b-')
plt.legend(['tol=%.0E' % tol, 'u simple', 'exact'])
plt.savefig('tmp_odespy_adaptive.png')
plt.savefig('tmp_odespy_adaptive.pdf')
plt.show()
raw_input()
Esempio n. 38
0
    T = num_periods * P
    t = np.linspace(0, T, time_steps_per_period * num_periods + 1)
    import odespy

    def f(u, t, alpha):
        # Note the sequence of unknowns: v, u (v=du/dt)
        v, u = u
        return [-alpha * np.sign(v) - u, v]

    solver = odespy.RK4(f, f_args=[alpha])
    solver.set_initial_condition([beta, 1])  # sequence must match f
    uv, t = solver.solve(t)
    u = uv[:, 1]  # recall sequence in f: v, u
    v = uv[:, 0]
    return u, t


if __name__ == '__main__':
    alpha_values = [0, 0.05, 0.1]
    for alpha in alpha_values:
        u, t = simulate(alpha, 0, 6, 60)
        plt.plot(t, u)
        plt.hold('on')
    plt.legend([r'$\alpha=%g$' % alpha for alpha in alpha_values])
    plt.xlabel(r'$\bar t$')
    plt.ylabel(r'$\bar u$')
    plt.savefig('tmp.png')
    plt.savefig('tmp.pdf')
    plt.show()
    raw_input()  # for scitools' matplotlib engine
Esempio n. 39
0
def run(gamma, beta=10, delta=40, scaling=1, animate=False):
    """Run the scaled model for welding."""
    gamma = float(gamma)  # avoid integer division
    if scaling == 'a':
        v = gamma
        a = 1
        L = 1.0
        b = 0.5 * beta**2
    elif scaling == 'b':
        v = 1
        a = 1.0 / gamma
        L = 1.0
        b = 0.5 * beta**2
    elif scaling == 'c':
        v = 1
        a = beta / gamma
        L = beta
        b = 0.5
    elif scaling == 'd':
        # PDE: u_t = gamma**(-1)u_xx + gamma**(-1)*delta*f
        v = 1
        a = 1.0 / gamma
        L = 1.0
        b = 0.5 * beta**2
        delta *= 1.0 / gamma

    ymin = 0
    # Need global ymax to be able change ymax in closure process_u
    global ymax
    ymax = 1.2

    I = lambda x: 0
    f = lambda x, t: delta * np.exp(-b * (x - v * t)**2)

    import time
    import scitools.std as plt
    plot_arrays = []
    if scaling == 'c':
        plot_times = [0.2 * beta, 0.5 * beta]
    else:
        plot_times = [0.2, 0.5]

    def process_u(u, x, t, n):
        """
        Animate u, and store arrays in plot_arrays if
        t coincides with chosen times for plotting (plot_times).
        """
        global ymax
        if animate:
            plt.plot(x,
                     u,
                     'r-',
                     x,
                     f(x, t[n]) / delta,
                     'b-',
                     axis=[0, L, ymin, ymax],
                     title='t=%f' % t[n],
                     xlabel='x',
                     ylabel='u and f/%g' % delta)
        if t[n] == 0:
            time.sleep(1)
            plot_arrays.append(x)
        dt = t[1] - t[0]
        tol = dt / 10.0
        if abs(t[n] - plot_times[0]) < tol or \
           abs(t[n] - plot_times[1]) < tol:
            plot_arrays.append((u.copy(), f(x, t[n]) / delta))
            if u.max() > ymax:
                ymax = u.max()

    Nx = 100
    D = 10
    if scaling == 'c':
        T = 0.5 * beta
    else:
        T = 0.5
    u_L = u_R = 0
    theta = 1.0
    cpu = solver(I, a, f, L, Nx, D, T, theta, u_L, u_R, user_action=process_u)
    x = plot_arrays[0]
    plt.figure()
    for u, f in plot_arrays[1:]:
        plt.plot(x,
                 u,
                 'r-',
                 x,
                 f,
                 'b--',
                 axis=[x[0], x[-1], 0, ymax],
                 xlabel='$x$',
                 ylabel=r'$u, \ f/%g$' % delta)
        plt.hold('on')
    plt.legend([
        '$u,\\ t=%g$' % plot_times[0],
        '$f/%g,\\ t=%g$' % (delta, plot_times[0]),
        '$u,\\ t=%g$' % plot_times[1],
        '$f/%g,\\ t=%g$' % (delta, plot_times[1])
    ])
    filename = 'tmp1_gamma%g_%s' % (gamma, scaling)
    plt.title(r'$\beta = %g,\ \gamma = %g,\ $' % (beta, gamma) +
              'scaling=%s' % scaling)
    plt.savefig(filename + '.pdf')
    plt.savefig(filename + '.png')
    return cpu
Esempio n. 40
0
    T = num_periods * P
    t = np.linspace(0, T, time_steps_per_period * num_periods + 1)
    import odespy

    def f(u, t, alpha):
        # Note the sequence of unknowns: v, u (v=du/dt)
        v, u = u
        return [-alpha * np.sign(v) - u, v]

    solver = odespy.RK4(f, f_args=[alpha])
    solver.set_initial_condition([beta, 1])  # sequence must match f
    uv, t = solver.solve(t)
    u = uv[:, 1]  # recall sequence in f: v, u
    v = uv[:, 0]
    return u, t


if __name__ == "__main__":
    alpha_values = [0, 0.05, 0.1]
    for alpha in alpha_values:
        u, t = simulate(alpha, 0, 6, 60)
        plt.plot(t, u)
        plt.hold("on")
    plt.legend([r"$\alpha=%g$" % alpha for alpha in alpha_values])
    plt.xlabel(r"$\bar t$")
    plt.ylabel(r"$\bar u$")
    plt.savefig("tmp.png")
    plt.savefig("tmp.pdf")
    plt.show()
    raw_input()  # for scitools' matplotlib engine
Esempio n. 41
0
import sys
#import matplotlib.pyplot as plt
import scitools.std as plt

def f(u, t):
    return -a*u

def u_exact(t):
    return I*np.exp(-a*t)

I = 1; a = 2; T = 5
tol = float(sys.argv[1])
solver = odespy.DormandPrince(f, atol=tol, rtol=0.1*tol)

Nt = 1  # just one step - let the scheme find its intermediate points
t_mesh = np.linspace(0, T, Nt+1)
t_fine = np.linspace(0, T, 10001)

solver.set_initial_condition(I)
u, t = solver.solve(t_mesh)

# u and t will only consist of [I, u^Nt] and [0,T]
# solver.u_all and solver.t_all contains all computed points
plt.plot(solver.t_all, solver.u_all, 'ko')
plt.hold('on')
plt.plot(t_fine, u_exact(t_fine), 'b-')
plt.legend(['tol=%.0E' % tol, 'exact'])
plt.savefig('tmp_odespy_adaptive.png')
plt.show()

Esempio n. 42
0
def approximate(f, d, N_e, numint, Omega=[0, 1], filename='tmp'):
    """
    Compute the finite element approximation, using Lagrange
    elements of degree d, to a Python functionn f on a domain
    Omega. N_e is the number of elements.
    numint is the name of the numerical integration rule
    (Trapezoidal, Simpson, GaussLegendre2, GaussLegendre3,
    GaussLegendre4, etc.). numint=None implies exact
    integration.
    """
    from math import sqrt
    numint_name = numint  # save name
    if numint == 'Trapezoidal':
        numint = [[-1, 1], [1, 1]]
    elif numint == 'Simpson':
        numint = [[-1, 0, 1], [1. / 3, 4. / 3, 1. / 3]]
    elif numint == 'Midpoint':
        numint = [[0], [2]]
    elif numint == 'GaussLegendre2':
        numint = [[-1 / sqrt(3), 1 / sqrt(3)], [1, 1]]
    elif numint == 'GaussLegendre3':
        numint = [[-sqrt(3. / 5), 0, sqrt(3. / 5)], [5. / 9, 8. / 9, 5. / 9]]
    elif numint == 'GaussLegendre4':
        numint = [[-0.86113631, -0.33998104, 0.33998104, 0.86113631],
                  [0.34785485, 0.65214515, 0.65214515, 0.34785485]]
    elif numint == 'GaussLegendre5':
        numint = [[-0.90617985, -0.53846931, -0., 0.53846931, 0.90617985],
                  [0.23692689, 0.47862867, 0.56888889, 0.47862867, 0.23692689]]
    elif numint is not None:
        print 'Numerical rule %s is not supported '\
              'for numerical computing' % numint
        sys.exit(1)

    vertices, cells, dof_map = mesh_uniform(N_e, d, Omega)

    # phi is a list where phi[e] holds the basis in cell no e
    # (this is required by assemble, which can work with
    # meshes with different types of elements).
    # len(dof_map[e]) is the number of nodes in cell e,
    # and the degree of the polynomial is len(dof_map[e])-1
    phi = [basis(len(dof_map[e]) - 1) for e in range(N_e)]

    A, b = assemble(vertices, cells, dof_map, phi, f, numint=numint)

    print 'cells:', cells
    print 'vertices:', vertices
    print 'dof_map:', dof_map
    print 'A:\n', A
    print 'b:\n', b
    c = np.linalg.solve(A, b)
    print 'c:\n', c

    if filename is not None:
        title = 'P%d, N_e=%d' % (d, N_e)
        title += ', integration: %s' % numint_name
        x_u, u, _ = u_glob(np.asarray(c),
                           vertices,
                           cells,
                           dof_map,
                           resolution_per_element=51)
        x_f = np.linspace(Omega[0], Omega[1], 10001)  # mesh for f
        import scitools.std as plt
        plt.plot(x_u, u, '-', x_f, f(x_f), '--')
        plt.legend(['u', 'f'])
        plt.title(title)
        plt.savefig(filename + '.pdf')
        plt.savefig(filename + '.png')
    return c
Esempio n. 43
0
def run(gamma, beta=10, delta=40, scaling=1, animate=False):
    """Run the scaled model for welding."""
    gamma = float(gamma)  # avoid integer division
    if scaling == 'a':
        v = gamma
        a = 1
        L = 1.0
        b = 0.5*beta**2
    elif scaling == 'b':
        v = 1
        a = 1.0/gamma
        L = 1.0
        b = 0.5*beta**2
    elif scaling == 'c':
        v = 1
        a = beta/gamma
        L = beta
        b = 0.5
    elif scaling == 'd':
        # PDE: u_t = gamma**(-1)u_xx + gamma**(-1)*delta*f
        v = 1
        a = 1.0/gamma
        L = 1.0
        b = 0.5*beta**2
        delta *= 1.0/gamma

    ymin = 0
    # Need global ymax to be able change ymax in closure process_u
    global ymax
    ymax = 1.2

    I = lambda x: 0
    f = lambda x, t: delta*np.exp(-b*(x - v*t)**2)

    import time
    import scitools.std as plt
    plot_arrays = []
    if scaling == 'c':
        plot_times = [0.2*beta, 0.5*beta]
    else:
        plot_times = [0.2, 0.5]

    def process_u(u, x, t, n):
        """
        Animate u, and store arrays in plot_arrays if
        t coincides with chosen times for plotting (plot_times).
        """
        global ymax
        if animate:
            plt.plot(x, u, 'r-',
                     x, f(x, t[n])/delta, 'b-',
                     axis=[0, L, ymin, ymax], title='t=%f' % t[n],
                     xlabel='x', ylabel='u and f/%g' % delta)
        if t[n] == 0:
            time.sleep(1)
            plot_arrays.append(x)
        dt = t[1] - t[0]
        tol = dt/10.0
        if abs(t[n] - plot_times[0]) < tol or \
           abs(t[n] - plot_times[1]) < tol:
            plot_arrays.append((u.copy(), f(x, t[n])/delta))
            if u.max() > ymax:
                ymax = u.max()

    Nx = 100
    D = 10
    if scaling == 'c':
        T = 0.5*beta
    else:
        T = 0.5
    u_L = u_R = 0
    theta = 1.0
    cpu = solver(
        I, a, f, L, Nx, D, T, theta, u_L, u_R, user_action=process_u)
    x = plot_arrays[0]
    plt.figure()
    for u, f in plot_arrays[1:]:
        plt.plot(x, u, 'r-', x, f, 'b--', axis=[x[0], x[-1], 0, ymax],
                 xlabel='$x$', ylabel=r'$u, \ f/%g$' % delta)
        plt.hold('on')
    plt.legend(['$u,\\ t=%g$' % plot_times[0],
                '$f/%g,\\ t=%g$' % (delta, plot_times[0]),
                '$u,\\ t=%g$' % plot_times[1],
                '$f/%g,\\ t=%g$' % (delta, plot_times[1])])
    filename = 'tmp1_gamma%g_%s' % (gamma, scaling)
    plt.title(r'$\beta = %g,\ \gamma = %g,\ $' % (beta, gamma)
              + 'scaling=%s' % scaling)
    plt.savefig(filename + '.pdf');  plt.savefig(filename + '.png')
    return cpu
Esempio n. 44
0
solver.set_initial_condition(u0)
u, t = solver.solve(t_mesh)

# u and t will only consist of [I, u^Nt] and [0,T], i.e. 2 values 
# each, while solver.u_all and solver.t_all contain all computed 
# points. solver.u_all is a list with arrays, one array (with 2 
# values) for each point in time.
u_adaptive = np.array(solver.u_all)

# For comparison, we solve also with simple FDM method
Nt_simple = len(solver.t_all)   # get no of time steps from ad. meth.
t_simple = np.linspace(0, T, Nt_simple+1)   # create equal steps
dt = t_simple[1] - t_simple[0]          # constant time step
u_simple = np.zeros(Nt_simple+1)
u_simple[0] = I
u_simple[1] = u_simple[0] - 0.5*dt**2*w**2*u_simple[0]
for n in range(1, Nt_simple):
    u_simple[n+1] = 2*u_simple[n] - u_simple[n-1] - \
    dt**2*w**2*u_simple[n]

plt.plot(solver.t_all, u_adaptive[:,0], 'k-')
plt.hold('on')
plt.plot(t_simple, u_simple, 'r--')
plt.plot(t_fine, u_exact(t_fine), 'b-')
plt.legend(['tol=%.0E' % tol, 'u simple', 'exact'])
plt.savefig('tmp_odespy_adaptive.png')
plt.savefig('tmp_odespy_adaptive.pdf')
plt.show()

Esempio n. 45
0
def run_solvers_and_plot(solvers,
                         timesteps_per_period=20,
                         num_periods=1,
                         I=1,
                         w=2 * np.pi):
    P = 2 * np.pi / w  # one period
    dt = P / timesteps_per_period
    N = num_periods * timesteps_per_period
    T = N * dt
    t_mesh = np.linspace(0, T, N + 1)

    legends = []
    for solver in solvers:
        solver.set(f_kwargs={'w': w})
        solver.set_initial_condition([I, 0])
        u, t = solver.solve(t_mesh)

        # Make plots
        if num_periods <= 80:
            plt.figure(1)
            if len(t_mesh) <= 50:
                plt.plot(t, u[:, 0])  # markers by default
            else:
                plt.plot(t, u[:, 0], '-2')  # no markers
            plt.hold('on')
            legends.append(solver.__class__.__name__)
            plt.figure(2)
            if len(t_mesh) <= 50:
                plt.plot(u[:, 0], u[:, 1])  # markers by default
            else:
                plt.plot(u[:, 0], u[:, 1], '-2')  # no markers
            plt.hold('on')

        if num_periods > 20:
            minima, maxima = minmax(t, u[:, 0])
            p = periods(maxima)
            a = amplitudes(minima, maxima)
            plt.figure(3)
            plt.plot(range(len(p)), 2 * np.pi / p, '-')
            plt.hold('on')
            plt.figure(4)
            plt.plot(range(len(a)), a, '-')
            plt.hold('on')

    # Compare with exact solution plotted on a very fine mesh
    t_fine = np.linspace(0, T, 10001)
    u_e = I * np.cos(w * t_fine)
    v_e = -w * I * np.sin(w * t_fine)

    if num_periods < 80:
        plt.figure(1)
        plt.plot(t_fine, u_e, '-')  # avoid markers by spec. line type
        legends.append('exact')
        plt.legend(legends, loc='upper left')
        plt.xlabel('t')
        plt.ylabel('u')
        plt.title('Time step: %g' % dt)
        plt.savefig('vb_%d_%d_u.png' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_u.pdf' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_u.eps' % (timesteps_per_period, num_periods))

        plt.figure(2)
        plt.plot(u_e, v_e, '-')  # avoid markers by spec. line type
        plt.legend(legends, loc='lower right')
        plt.xlabel('u(t)')
        plt.ylabel('v(t)')
        plt.title('Time step: %g' % dt)
        plt.savefig('vb_%d_%d_pp.png' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_pp.pdf' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_pp.eps' % (timesteps_per_period, num_periods))
        del legends[-1]  # fig 3 and 4 does not have exact value

    if num_periods > 20:
        plt.figure(3)
        plt.legend(legends, loc='center right')
        plt.title('Empirically estimated periods')
        plt.savefig('vb_%d_%d_p.eps' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_p.png' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_p.eps' % (timesteps_per_period, num_periods))
        plt.figure(4)
        plt.legend(legends, loc='center right')
        plt.title('Empirically estimated amplitudes')
        plt.savefig('vb_%d_%d_a.eps' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_a.png' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_a.eps' % (timesteps_per_period, num_periods))
Esempio n. 46
0
dt = float(sys.argv[1]) if len(sys.argv) >= 2 else 0.75
Nt = int(round(T/dt))
t_mesh = np.linspace(0, Nt*dt, Nt+1)

solvers = [odespy.RK2(f),
           odespy.RK3(f),
           odespy.RK4(f),
           # BackwardEuler must use Newton solver to converge
           odespy.BackwardEuler(f, nonlinear_solver='Newton')]

legends = []
for solver in solvers:
    solver.set_initial_condition(I)
    u, t = solver.solve(t_mesh)

    plt.plot(t, u)
    plt.hold('on')
    legends.append(solver.__class__.__name__)

# Compare with exact solution plotted on a very fine mesh
t_fine = np.linspace(0, T, 10001)
u_e = I*np.exp(-a*t_fine)
plt.plot(t_fine, u_e, '-') # avoid markers by specifying line type
legends.append('exact')

plt.legend(legends)
plt.title('Time step: %g' % dt)
plt.savefig('odespy1_dt_%g.png' % dt)
plt.savefig('odespy1_dt_%g.pdf' % dt)
plt.show()
def approximate(f, symbolic=False, d=1, N_e=4, numint=None,
                Omega=[0, 1], filename='tmp'):
    """
    Compute the finite element approximation, using Lagrange
    elements of degree d, to a symbolic expression f (with x
    as independent variable) on a domain Omega. N_e is the
    number of elements.
    symbolic=True implies symbolic expressions in the
    calculations, while symbolic=False means numerical
    computing.
    numint is the name of the numerical integration rule
    (Trapezoidal, Simpson, GaussLegendre2, GaussLegendre3,
    GaussLegendre4, etc.). numint=None implies exact
    integration.
    """
    numint_name = numint  # save name
    if symbolic:
        if numint == 'Trapezoidal':
            numint = [[sym.S(-1), sym.S(1)], [sym.S(1), sym.S(1)]]  # sympy integers
        elif numint == 'Simpson':
            numint = [[sym.S(-1), sym.S(0), sym.S(1)],
                      [sym.Rational(1,3), sym.Rational(4,3), sym.Rational(1,3)]]
        elif numint == 'Midpoint':
            numint = [[sym.S(0)],  [sym.S(2)]]
        elif numint == 'GaussLegendre2':
            numint = [[-1/sym.sqrt(3), 1/sym.sqrt(3)], [sym.S(1), sym.S(1)]]
        elif numint == 'GaussLegendre3':
            numint = [[-sym.sqrt(sym.Rational(3,5)), 0,
                       sym.sqrt(sym.Rational(3,5))],
                      [sym.Rational(5,9), sym.Rational(8,9),
                       sym.Rational(5,9)]]
        elif numint is not None:
            print 'Numerical rule %s is not supported for symbolic computing' % numint
            numint = None
    else:
        if numint == 'Trapezoidal':
            numint = [[-1, 1], [1, 1]]
        elif numint == 'Simpson':
            numint = [[-1, 0, 1], [1./3, 4./3, 1./3]]
        elif numint == 'Midpoint':
            numint = [[0], [2]]
        elif numint == 'GaussLegendre2':
            numint = [[-1/sqrt(3), 1/sqrt(3)], [1, 1]]
        elif numint == 'GaussLegendre3':
            numint = [[-sqrt(3./5), 0, sqrt(3./5)],
                      [5./9, 8./9, 5./9]]
        elif numint == 'GaussLegendre4':
            numint = [[-0.86113631, -0.33998104,  0.33998104,  0.86113631],
                      [ 0.34785485,  0.65214515,  0.65214515,  0.34785485]]
        elif numint == 'GaussLegendre5':
            numint = [[-0.90617985, -0.53846931, -0.        ,  0.53846931,  0.90617985],
                      [ 0.23692689,  0.47862867,  0.56888889,  0.47862867,  0.23692689]]
        elif numint is not None:
            print 'Numerical rule %s is not supported for numerical computing' % numint
            numint = None


    vertices, cells, dof_map = mesh_uniform(N_e, d, Omega, symbolic)

    # phi is a list where phi[e] holds the basis in cell no e
    # (this is required by assemble, which can work with
    # meshes with different types of elements).
    # len(dof_map[e]) is the number of nodes in cell e,
    # and the degree of the polynomial is len(dof_map[e])-1
    phi = [basis(len(dof_map[e])-1) for e in range(N_e)]

    print 'phi basis (reference element):\n', phi
    A, b = assemble(vertices, cells, dof_map, phi, f,
                    symbolic=symbolic, numint=numint)

    print 'cells:', cells
    print 'vertices:', vertices
    print 'dof_map:', dof_map
    print 'A:\n', A
    print 'b:\n', b
    #print sym.latex(A, mode='plain')
    #print sym.latex(b, mode='plain')

    if symbolic:
        c = A.LUsolve(b)
    else:
        c = np.linalg.solve(A, b)

    print 'c:\n', c

    if not symbolic:
        print 'Plain interpolation/collocation:'
        x = sym.Symbol('x')
        f = sym.lambdify([x], f, modules='numpy')
        try:
            f_at_vertices = [f(xc) for xc in vertices]
            print f_at_vertices
        except Exception as e:
            print 'could not evaluate f numerically:'
            print e
    # else: nodes are symbolic so f(nodes[i]) only makes sense
    # in the non-symbolic case

    if filename is not None:
        title = 'P%d, N_e=%d' % (d, N_e)
        if numint is None:
            title += ', exact integration'
        else:
            title += ', integration: %s' % numint_name
        x_u, u = u_glob(np.asarray(c), vertices, cells, dof_map,
                        resolution_per_element=51)
        x_f = np.linspace(Omega[0], Omega[1], 10001) # mesh for f
        import scitools.std as plt
        plt.plot(x_u, u, '-',
                 x_f, f(x_f), '--')
        plt.legend(['u', 'f'])
        plt.title(title)
        plt.savefig(filename + '.pdf')
        plt.savefig(filename + '.png')
    return c
import scitools.std as plt
import sys
import numpy as np
import matplotlib.pyplot as plt

x, y = np.loadtxt('volt.txt', delimiter=',', unpack=True)

plt.figure(1)
plt.plot(x, y, '*', linewidth=1)  # avoid markers by spec. line type
#plt.xlim([0.0, 10])
#plt.ylim([0.0, 2])
plt.legend(['Force-- Tip'],
           loc='upper right',
           prop={"family": "Times New Roman"})
plt.xlabel('Sampled time')
plt.ylabel('$Force /m$')
plt.savefig('volt1v.png')
plt.savefig('volt1v.pdf')
plt.hold(True)
Esempio n. 49
0
def approximate(f, symbolic=False, d=1, N_e=4, numint=None, Omega=[0, 1], filename="tmp"):
    if symbolic:
        if numint == "Trapezoidal":
            numint = [[sm.S(-1), sm.S(1)], [sm.S(1), sm.S(1)]]  # sympy integers
        elif numint == "Simpson":
            numint = [[sm.S(-1), sm.S(0), sm.S(1)], [sm.Rational(1, 3), sm.Rational(4, 3), sm.Rational(1, 3)]]
        elif numint == "Midpoint":
            numint = [[sm.S(0)], [sm.S(2)]]
        elif numint == "GaussLegendre2":
            numint = [[-1 / sm.sqrt(3), 1 / sm.sqrt(3)], [sm.S(1), sm.S(1)]]
        elif numint == "GaussLegendre3":
            numint = [
                [-sm.sqrt(sm.Rational(3, 5)), 0, sm.sqrt(sm.Rational(3, 5))],
                [sm.Rational(5, 9), sm.Rational(8, 9), sm.Rational(5, 9)],
            ]
        elif numint is not None:
            print "Numerical rule %s is not supported" % numint
            numint = None
    else:
        if numint == "Trapezoidal":
            numint = [[-1, 1], [1, 1]]
        elif numint == "Simpson":
            numint = [[-1, 0, 1], [1.0 / 3, 4.0 / 3, 1.0 / 3]]
        elif numint == "Midpoint":
            numint = [[0], [2]]
        elif numint == "GaussLegendre2":
            numint = [[-1 / sqrt(3), 1 / sqrt(3)], [1, 1]]
        elif numint == "GaussLegendre3":
            numint = [[-sqrt(3.0 / 5), 0, sqrt(3.0 / 5)], [5.0 / 9, 8.0 / 9, 5.0 / 9]]
        elif numint is not None:
            print "Numerical rule %s is not supported" % numint
            numint = None

    vertices, cells, dof_map = mesh_uniform(N_e, d, Omega, symbolic)

    # phi is a list where phi[e] holds the basis in cell no e
    # (this is required by assemble, which can work with
    # meshes with different types of elements).
    # len(dof_map[e]) is the number of nodes in cell e,
    # and the degree of the polynomial is len(dof_map[e])-1
    phi = [basis(len(dof_map[e]) - 1) for e in range(N_e)]

    print "phi basis (reference element):\n", phi
    A, b = assemble(vertices, cells, dof_map, phi, f, symbolic=symbolic, numint=numint)

    print "cells:", cells
    print "vertices:", vertices
    print "dof_map:", dof_map
    print "A:\n", A
    print "b:\n", b
    # print sm.latex(A, mode='plain')
    # print sm.latex(b, mode='plain')

    if symbolic:
        c = A.LUsolve(b)
    else:
        c = np.linalg.solve(A, b)

    print "c:\n", c

    if not symbolic:
        print "Plain interpolation/collocation:"
        x = sm.Symbol("x")
        f = sm.lambdify([x], f, modules="numpy")
        try:
            f_at_vertices = [f(xc) for xc in vertices]
            print f_at_vertices
        except Exception as e:
            print "could not evaluate f numerically:"
            print e
    # else: nodes are symbolic so f(nodes[i]) only makes sense
    # in the non-symbolic case

    if not symbolic and filename is not None:
        title = "P%d, N_e=%d" % (d, N_e)
        if numint is None:
            title += ", exact integration"
        else:
            title += ", integration: %s" % numint
        x_u, u = u_glob(np.asarray(c), vertices, cells, dof_map, resolution_per_element=51)
        x_f = np.linspace(Omega[0], Omega[1], 10001)  # mesh for f
        plt.plot(x_u, u, "-", x_f, f(x_f), "--")
        plt.legend(["u", "f"])
        plt.title(title)
        plt.savefig(filename + ".pdf")
        plt.savefig(filename + ".png")
    return c
def run_solvers_and_plot(solvers,
                         timesteps_per_period=20,
                         num_periods=1,
                         I=1,
                         w=2 * np.pi):
    P = 2 * np.pi / w  # duration of one period
    dt = P / timesteps_per_period
    Nt = num_periods * timesteps_per_period
    T = Nt * dt
    t_mesh = np.linspace(0, T, Nt + 1)

    legends = []
    for solver in solvers:
        solver.set(f_kwargs={'w': w})
        solver.set_initial_condition([I, 0])
        u, t = solver.solve(t_mesh)

        # Compute energy
        dt = t[1] - t[0]
        E = 0.5 * ((u[2:, 0] - u[:-2, 0]) /
                   (2 * dt))**2 + 0.5 * w**2 * u[1:-1, 0]**2
        # Compute error in energy
        E0 = 0.5 * 0**2 + 0.5 * w**2 * I**2
        e_E = E - E0

        solver_name = 'CrankNicolson' if solver.__class__.__name__ == \
                      'MidpointImplicit' else solver.__class__.__name__
        print '*** Relative max error in energy for %s [0,%g] with dt=%g: %.3E' % (
            solver_name, t[-1], dt, np.abs(e_E).max() / E0)

        # Make plots
        if num_periods <= 80:
            plt.figure(1)
            if len(t_mesh) <= 50:
                plt.plot(t, u[:, 0])  # markers by default
            else:
                plt.plot(t, u[:, 0], '-2')  # no markers
            plt.hold('on')
            legends.append(solver_name)
            plt.figure(2)
            if len(t_mesh) <= 50:
                plt.plot(u[:, 0], u[:, 1])  # markers by default
            else:
                plt.plot(u[:, 0], u[:, 1], '-2')  # no markers
            plt.hold('on')

        if num_periods > 20:
            minima, maxima = minmax(t, u[:, 0])
            p = periods(maxima)
            a = amplitudes(minima, maxima)
            plt.figure(3)
            plt.plot(range(len(p)), 2 * np.pi / p, '-')
            plt.hold('on')
            plt.figure(4)
            plt.plot(range(len(a)), a, '-')
            plt.hold('on')

    # Compare with exact solution plotted on a very fine mesh
    t_fine = np.linspace(0, T, 10001)
    u_e = I * np.cos(w * t_fine)
    v_e = -w * I * np.sin(w * t_fine)

    if num_periods < 80:
        plt.figure(1)
        plt.plot(t_fine, u_e, '-')  # avoid markers by spec. line type
        legends.append('exact')
        plt.legend(legends, loc='upper left')
        plt.xlabel('t')
        plt.ylabel('u')
        plt.title('Time step: %g' % dt)
        plt.savefig('vib_%d_%d_u.png' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_u.pdf' % (timesteps_per_period, num_periods))

        plt.figure(2)
        plt.plot(u_e, v_e, '-')  # avoid markers by spec. line type
        plt.legend(legends, loc='lower right')
        plt.xlabel('u(t)')
        plt.ylabel('v(t)')
        plt.title('Time step: %g' % dt)
        plt.savefig('vib_%d_%d_pp.png' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_pp.pdf' % (timesteps_per_period, num_periods))
        del legends[-1]  # fig 3 and 4 does not have exact value

    if num_periods > 20:
        plt.figure(3)
        plt.legend(legends, loc='center right')
        plt.title('Empirically estimated periods')
        plt.savefig('vib_%d_%d_p.pdf' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_p.png' % (timesteps_per_period, num_periods))
        plt.figure(4)
        plt.legend(legends, loc='center right')
        plt.title('Empirically estimated amplitudes')
        plt.savefig('vib_%d_%d_a.pdf' % (timesteps_per_period, num_periods))
        plt.savefig('vib_%d_%d_a.png' % (timesteps_per_period, num_periods))
Esempio n. 51
0
    import odespy

    def f(u, t, Theta):
        # Note the sequence of unknowns: omega, theta
        # omega = d(theta)/dt, angular velocity
        omega, theta = u
        return [-Theta**(-1) * np.sin(Theta * theta), omega]

    solver = odespy.RK4(f, f_args=[Theta])
    solver.set_initial_condition([0, 1])  # sequence must match f
    u, t = solver.solve(t)
    theta = u[:, 1]  # recall sequence in f: omega, theta
    return theta, t


if __name__ == '__main__':
    Theta_values_degrees = [1, 20, 45, 60]
    for Theta_degrees in Theta_values_degrees:
        Theta = Theta_degrees * np.pi / 180
        theta, t = simulate(Theta, 6, 60)
        plt.plot(t, theta)
        plt.hold('on')
    plt.legend([r'$\Theta=%g$' % Theta for Theta in Theta_values_degrees],
               loc='lower left')
    plt.xlabel(r'$\bar t$')
    plt.ylabel(r'$\bar\theta$')
    plt.savefig('tmp.png')
    plt.savefig('tmp.pdf')
    plt.show()
    raw_input()
Esempio n. 52
0
def approximate(f,
                symbolic=False,
                d=1,
                N_e=4,
                numint=None,
                Omega=[0, 1],
                filename='tmp'):
    if symbolic:
        if numint == 'Trapezoidal':
            numint = [[sm.S(-1), sm.S(1)], [sm.S(1),
                                            sm.S(1)]]  # sympy integers
        elif numint == 'Simpson':
            numint = [[sm.S(-1), sm.S(0), sm.S(1)],
                      [
                          sm.Rational(1, 3),
                          sm.Rational(4, 3),
                          sm.Rational(1, 3)
                      ]]
        elif numint == 'Midpoint':
            numint = [[sm.S(0)], [sm.S(2)]]
        elif numint == 'GaussLegendre2':
            numint = [[-1 / sm.sqrt(3), 1 / sm.sqrt(3)], [sm.S(1), sm.S(1)]]
        elif numint == 'GaussLegendre3':
            numint = [[
                -sm.sqrt(sm.Rational(3, 5)), 0,
                sm.sqrt(sm.Rational(3, 5))
            ], [sm.Rational(5, 9),
                sm.Rational(8, 9),
                sm.Rational(5, 9)]]
        elif numint is not None:
            print 'Numerical rule %s is not supported' % numint
            numint = None
    else:
        if numint == 'Trapezoidal':
            numint = [[-1, 1], [1, 1]]
        elif numint == 'Simpson':
            numint = [[-1, 0, 1], [1. / 3, 4. / 3, 1. / 3]]
        elif numint == 'Midpoint':
            numint = [[0], [2]]
        elif numint == 'GaussLegendre2':
            numint = [[-1 / sqrt(3), 1 / sqrt(3)], [1, 1]]
        elif numint == 'GaussLegendre3':
            numint = [[-sqrt(3. / 5), 0, sqrt(3. / 5)],
                      [5. / 9, 8. / 9, 5. / 9]]
        elif numint is not None:
            print 'Numerical rule %s is not supported' % numint
            numint = None

    vertices, cells, dof_map = mesh_uniform(N_e, d, Omega, symbolic)

    # phi is a list where phi[e] holds the basis in cell no e
    # (this is required by assemble, which can work with
    # meshes with different types of elements).
    # len(dof_map[e]) is the number of nodes in cell e,
    # and the degree of the polynomial is len(dof_map[e])-1
    phi = [basis(len(dof_map[e]) - 1) for e in range(N_e)]

    print 'phi basis (reference element):\n', phi
    A, b = assemble(vertices,
                    cells,
                    dof_map,
                    phi,
                    f,
                    symbolic=symbolic,
                    numint=numint)

    print 'cells:', cells
    print 'vertices:', vertices
    print 'dof_map:', dof_map
    print 'A:\n', A
    print 'b:\n', b
    #print sm.latex(A, mode='plain')
    #print sm.latex(b, mode='plain')

    if symbolic:
        c = A.LUsolve(b)
    else:
        c = np.linalg.solve(A, b)

    print 'c:\n', c

    if not symbolic:
        print 'Plain interpolation/collocation:'
        x = sm.Symbol('x')
        f = sm.lambdify([x], f, modules='numpy')
        try:
            f_at_vertices = [f(xc) for xc in vertices]
            print f_at_vertices
        except Exception as e:
            print 'could not evaluate f numerically:'
            print e
    # else: nodes are symbolic so f(nodes[i]) only makes sense
    # in the non-symbolic case

    if not symbolic and filename is not None:
        title = 'P%d, N_e=%d' % (d, N_e)
        if numint is None:
            title += ', exact integration'
        else:
            title += ', integration: %s' % numint
        x_u, u = u_glob(np.asarray(c),
                        vertices,
                        cells,
                        dof_map,
                        resolution_per_element=51)
        x_f = np.linspace(Omega[0], Omega[1], 10001)  # mesh for f
        plt.plot(x_u, u, '-', x_f, f(x_f), '--')
        plt.legend(['u', 'f'])
        plt.title(title)
        plt.savefig(filename + '.pdf')
        plt.savefig(filename + '.png')
    return c
Esempio n. 53
0
def run(gamma, beta=10, delta=40, scaling=1, animate=False):
    """Run the scaled model for welding."""
    if scaling == 1:
        v = gamma
        a = 1
    elif scaling == 2:
        v = 1
        a = 1.0 / gamma

    b = 0.5 * beta**2
    L = 1.0
    ymin = 0
    # Need gloal to be able change ymax in closure process_u
    global ymax
    ymax = 1.2

    I = lambda x: 0
    f = lambda x, t: delta * np.exp(-b * (x - v * t)**2)

    import time
    import scitools.std as plt
    plot_arrays = []

    def process_u(u, x, t, n):
        global ymax
        if animate:
            plt.plot(x,
                     u,
                     'r-',
                     x,
                     f(x, t[n]) / delta,
                     'b-',
                     axis=[0, L, ymin, ymax],
                     title='t=%f' % t[n],
                     xlabel='x',
                     ylabel='u and f/%g' % delta)
        if t[n] == 0:
            time.sleep(1)
            plot_arrays.append(x)
        dt = t[1] - t[0]
        tol = dt / 10.0
        if abs(t[n] - 0.2) < tol or abs(t[n] - 0.5) < tol:
            plot_arrays.append((u.copy(), f(x, t[n]) / delta))
            if u.max() > ymax:
                ymax = u.max()

    Nx = 100
    D = 10
    T = 0.5
    u_L = u_R = 0
    theta = 1.0
    cpu = solver(I, a, f, L, Nx, D, T, theta, u_L, u_R, user_action=process_u)
    x = plot_arrays[0]
    plt.figure()
    for u, f in plot_arrays[1:]:
        plt.plot(x,
                 u,
                 'r-',
                 x,
                 f,
                 'b--',
                 axis=[x[0], x[-1], 0, ymax],
                 xlabel='$x$',
                 ylabel=r'$u, \ f/%g$' % delta)
        plt.hold('on')
    plt.legend([
        '$u,\\ t=0.2$',
        '$f/%g,\\ t=0.2$' % delta, '$u,\\ t=0.5$',
        '$f/%g,\\ t=0.5$' % delta
    ])
    filename = 'tmp1_gamma%g_s%d' % (gamma, scaling)
    s = 'diffusion' if scaling == 1 else 'source'
    plt.title(r'$\beta = %g,\ \gamma = %g,\ $' % (beta, gamma) +
              'scaling=%s' % s)
    plt.savefig(filename + '.pdf')
    plt.savefig(filename + '.png')
    return cpu
Esempio n. 54
0
def run_solvers_and_plot(solvers, timesteps_per_period=20,
                         num_periods=1, I=1, w=2*np.pi):
    P = 2*np.pi/w  # one period
    dt = P/timesteps_per_period
    N = num_periods*timesteps_per_period
    T = N*dt
    t_mesh = np.linspace(0, T, N+1)

    legends = []
    for solver in solvers:
        solver.set(f_kwargs={'w': w})
        solver.set_initial_condition([I, 0])
        u, t = solver.solve(t_mesh)

        # Make plots
        if num_periods <= 80:
            plt.figure(1)
            if len(t_mesh) <= 50:
                plt.plot(t, u[:,0])             # markers by default
            else:
                plt.plot(t, u[:,0], '-2')       # no markers
            plt.hold('on')
            legends.append(solver.__class__.__name__)
            plt.figure(2)
            if len(t_mesh) <= 50:
                plt.plot(u[:,0], u[:,1])        # markers by default
            else:
                plt.plot(u[:,0], u[:,1], '-2')  # no markers
            plt.hold('on')

        if num_periods > 20:
            minima, maxima = minmax(t, u[:,0])
            p = periods(maxima)
            a = amplitudes(minima, maxima)
            plt.figure(3)
            plt.plot(range(len(p)), 2*np.pi/p, '-')
            plt.hold('on')
            plt.figure(4)
            plt.plot(range(len(a)), a, '-')
            plt.hold('on')

    # Compare with exact solution plotted on a very fine mesh
    t_fine = np.linspace(0, T, 10001)
    u_e = I*np.cos(w*t_fine)
    v_e = -w*I*np.sin(w*t_fine)

    if num_periods < 80:
        plt.figure(1)
        plt.plot(t_fine, u_e, '-') # avoid markers by spec. line type
        legends.append('exact')
        plt.legend(legends, loc='upper left')
        plt.xlabel('t');  plt.ylabel('u')
        plt.title('Time step: %g' % dt)
        plt.savefig('vb_%d_%d_u.png' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_u.pdf' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_u.eps' % (timesteps_per_period, num_periods))

        plt.figure(2)
        plt.plot(u_e, v_e, '-') # avoid markers by spec. line type
        plt.legend(legends, loc='lower right')
        plt.xlabel('u(t)');  plt.ylabel('v(t)')
        plt.title('Time step: %g' % dt)
        plt.savefig('vb_%d_%d_pp.png' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_pp.pdf' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_pp.eps' % (timesteps_per_period, num_periods))
        del legends[-1]  # fig 3 and 4 does not have exact value

    if num_periods > 20:
        plt.figure(3)
        plt.legend(legends, loc='center right')
        plt.title('Empirically estimated periods')
        plt.savefig('vb_%d_%d_p.eps' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_p.png' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_p.eps' % (timesteps_per_period, num_periods))
        plt.figure(4)
        plt.legend(legends, loc='center right')
        plt.title('Empirically estimated amplitudes')
        plt.savefig('vb_%d_%d_a.eps' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_a.png' % (timesteps_per_period, num_periods))
        plt.savefig('vb_%d_%d_a.eps' % (timesteps_per_period, num_periods))