import numpy as np
import matplotlib.pyplot as plt
f = lambdify([x], tanh(arg), modules='numpy')

# Compute exact f on a fine mesh
x_fine = np.linspace(0, 1, 101)
f_fine = f(x_fine)

for d in 3, 4:
    for N_e in 1, 2, 4:
        h = 1.0 / N_e  # element length
        vertices = [i * h for i in range(N_e + 1)]
        cells = [[e, e + 1] for e in range(N_e)]
        dof_map = [[d * e + i for i in range(d + 1)] for e in range(N_e)]
        N_n = d * N_e + 1  # Number of nodes
        x_nodes = np.linspace(0, 1, N_n)  # Node coordinates
        U = f(x_nodes)  # Interpolation method samples node values
        x, u, _ = u_glob(U,
                         vertices,
                         cells,
                         dof_map,
                         resolution_per_element=51)
        plt.figure()
        plt.plot(x, u, '-', x_fine, f_fine, '--', x_nodes, U, 'bo')
        plt.legend(
            ['%d P%d elements' % (N_e, d), 'exact', 'interpolation points'],
            loc='upper left')
        plt.savefig('tmp_%d_P%d.pdf' % (N_e, d))
        plt.savefig('tmp_%d_P%d.png' % (N_e, d))
plt.show()
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
Exemple #3
0
 results[case] = {}
 for d in d_values:
     results[case][d] = {'E': [], 'h': [], 'r': []}
     for N_e in [4, 8, 16, 32, 64, 128]:
         try:
             c = approximate(
                 f, symbolic=False,
                 numint='GaussLegendre%d' % (d+1),
                 d=d, N_e=N_e, Omega=Omega,
                 filename='tmp_%s_d%d_e%d' % (case, d, N_e))
         except np.linalg.linalg.LinAlgError as e:
             print str(e)
             continue
         vertices, cells, dof_map = mesh_uniform(
             N_e, d, Omega, symbolic=False)
         xc, u, _ = u_glob(c, vertices, cells, dof_map, 51)
         e = f_func(xc) - u
         # Trapezoidal integration of the L2 error over the
         # xc/u patches
         e2 = e**2
         L2_error = 0
         for i in range(len(xc)-1):
             L2_error += 0.5*(e2[i+1] + e2[i])*(xc[i+1] - xc[i])
         L2_error = np.sqrt(L2_error)
         h = (Omega[1] - Omega[0])/float(N_e)
         results[case][d]['E'].append(L2_error)
         results[case][d]['h'].append(h)
     # Compute rates
     h = results[case][d]['h']
     E = results[case][d]['E']
     for i in range(len(h)-1):
Exemple #4
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
 results[case] = {}
 for d in d_values:
     results[case][d] = {'E': [], 'h': [], 'r': []}
     for N_e in [4, 8, 16, 32, 64, 128]:
         try:
             c = approximate(
                 f, symbolic=False,
                 numint='GaussLegendre%d' % (d+1),
                 d=d, N_e=N_e, Omega=Omega,
                 filename='tmp_%s_d%d_e%d' % (case, d, N_e))
         except np.linalg.linalg.LinAlgError as e:
             print(str(e))
             continue
         vertices, cells, dof_map = mesh_uniform(
             N_e, d, Omega, symbolic=False)
         xc, u, _ = u_glob(c, vertices, cells, dof_map, 51)
         e = f_func(xc) - u
         # Trapezoidal integration of the L2 error over the
         # xc/u patches
         e2 = e**2
         L2_error = 0
         for i in range(len(xc)-1):
             L2_error += 0.5*(e2[i+1] + e2[i])*(xc[i+1] - xc[i])
         L2_error = np.sqrt(L2_error)
         h = (Omega[1] - Omega[0])/float(N_e)
         results[case][d]['E'].append(L2_error)
         results[case][d]['h'].append(h)
     # Compute rates
     h = results[case][d]['h']
     E = results[case][d]['E']
     for i in range(len(h)-1):
Exemple #6
0
# Interpolation method
import numpy as np
import matplotlib.pyplot as plt
f = lambdify([x], tanh(arg), modules='numpy')

# Compute exact f on a fine mesh
x_fine = np.linspace(0, 1, 101)
f_fine = f(x_fine)

for d in 3, 4:
    for N_e in 1, 2, 4:
        h = 1.0/N_e  # element length
        vertices = [i*h for i in range(N_e+1)]
        cells = [[e, e+1] for e in range(N_e)]
        dof_map = [[d*e + i for i in range(d+1)] for e in range(N_e)]
        N_n = d*N_e + 1  # Number of nodes
        x_nodes = np.linspace(0, 1, N_n)  # Node coordinates
        U = f(x_nodes)  # Interpolation method samples node values
        x, u, _ = u_glob(U, vertices, cells, dof_map,
                         resolution_per_element=51)
        plt.figure()
        plt.plot(x, u, '-', x_fine, f_fine, '--',
                 x_nodes, U, 'bo')
        plt.legend(['%d P%d elements' % (N_e, d),
                    'exact', 'interpolation points'],
                   loc='upper left')
        plt.savefig('tmp_%d_P%d.pdf' % (N_e, d))
        plt.savefig('tmp_%d_P%d.png' % (N_e, d))
plt.show()