def interpolate():
    """
    Generates "experimental data" and estimates the values using interpolation
    """
    x_grid = np.linspace(-2, 2, 30)
    y_grid = np.linspace(-2, 2, 30)
    # grid points used for spline
    X, Y = np.meshgrid(x_grid, y_grid)
    # spline object from X,Y
    spline_2d = spline(x=x_grid, y=y_grid, f=f(X, Y), dims=2)

    # x must be chosen so that y does not go over 2
    x = np.linspace(0, 2 / np.sqrt(1.75), 100)
    y = np.sqrt(1.75) * x
    spline_eval = []
    for point in range(len(x)):
        # go through containers x and y and evaluate spline at those points
        spline_eval.append(spline_2d.eval2d(x[point], y[point]))

    # accurate values for comparison
    accurate = f(x, y)

    fig = plt.figure()
    plt.plot(x, accurate, 'b', label='Real')
    plt.plot(x,
             np.squeeze(spline_eval),
             'r-.',
             label='Estimate from interpolation')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    plt.show()
Exemple #2
0
def main():
    #Read in the file
    filename = 'dft_chargedensity1.xsf'
    rho, lattice, grid, shift = read_example_xsf_density(filename)

    #Create data in initial coordinates
    a = np.linspace(0, lattice[0, 0], grid[0])
    b = np.linspace(0, lattice[1, 1], grid[1])
    c = np.linspace(0, lattice[2, 2], grid[2])

    #Create the interpolated data
    spline_data = spline(x=a, y=b, z=c, f=rho, dims=3)

    #Calculate the interpolation for the new coordinates
    r0 = np.array([0.1, 0.1, 2.8528])  #Given in the exercise
    r1 = np.array([4.45, 4.45, 2.8528])
    t = np.linspace(0, 1, 500)
    result = []
    for i in range(500):
        r = r0 + t[i] * (r1 - r0
                         )  #This is the new interpolation vector at index i
        inter = spline_data.eval3d(r[0], r[1], r[2])[0][0][0]
        result.append(inter)  #Store the values in a list

    length = np.linalg.norm(r1 - r0)  #Length of the interpoaltion line

    #Plot the electron density as a function of t
    plt.figure()
    plt.plot(t * length, result)
    plt.title('Electron density interpolation')
    plt.xlabel('Distance [Angstrom]')
    plt.xlim([0, 1 * length])
    plt.ylabel('Electron density')
    plt.grid()
    plt.show()
Exemple #3
0
def main():
    #Read in the file
    filename = 'dft_chargedensity2.xsf'
    rho, lattice, grid, shift = read_example_xsf_density(filename)
    A_inv = np.linalg.inv(np.transpose(lattice))  #The inverse of our matrix A

    #Create data in initial coordinates  in orthonormal basis
    a = np.linspace(0, 1, grid[0])
    b = np.linspace(0, 1, grid[1])
    c = np.linspace(0, 1, grid[2])

    spline_data = spline(x=a, y=b, z=c, f=rho, dims=3)

    #Input the values of the lines from starting to end point, along which the interpolation should be performed.
    vec = np.array([
        [-1.4466, 1.3073, 3.2115],  #start line 1
        [1.4361, 3.1883, 1.3542],  #end line 1
        [2.9996, 2.1733, 2.1462],  #start line 2
        [8.7516, 2.1733, 2.1462]
    ])  #end line 2

    t = np.linspace(0, 1, 500)

    counter = 0
    for j in range(
            0, 3, 2
    ):  #This gives the value 0 in the first iteration and 2 in the second.
        #(This loop is included because the spline in line 30 takes forever and I don't want to run that part twice)

        #Choose the vectors start and end points, so that we can construct the interpolation line r0+t[i]*(r1-r0):
        r0 = vec[j]
        r1 = vec[j + 1]

        result = []

        #Calculate the interpolation
        for i in range(500):
            r = np.mod(
                A_inv.dot(r0 + t[i] * (r1 - r0)), 1
            )  #This maps our vector according to r=A*alpha (r is our vector, A the transpose(lattice) and alpha our new coordinates)
            #The modulo is needed in case our interpolation vector is not in the unit cell anymore (see lecture slides week 4 p.3)
            inter = spline_data.eval3d(r[0], r[1], r[2])[0][0][0]
            result.append(inter)

        #Plot the figures
        counter += 1
        length = np.linalg.norm(r1 - r0)  #Length of the interpolation line

        plt.figure()
        plt.plot(t * length, result)
        plt.title('Interpolation along line {}'.format(counter))
        plt.xlabel('Distance [Angstrom]')
        plt.xlim([0, 1 * length])
        plt.ylabel('Electron density')
        plt.grid()
        plt.show()
Exemple #4
0
def test_Interp2D():
    x = np.linspace(-2, 2, 40)
    y = np.linspace(-2, 2, 40)
    [X, Y] = np.meshgrid(x, y)
    F = fun_Simpson2D(X, Y)
    spl2d = spline(x=x, y=y, f=F, dims=2)
    xp = np.linspace(0, 2.0 / np.sqrt(2), 100)
    f = np.zeros((len(xp), ))
    ff = np.zeros((len(xp), ))
    for i in range(len(xp)):
        x0 = xp[i]
        y0 = np.sqrt(2) * xp[i]
        f[i] = spl2d.eval2d(x0, y0)
        ff[i] = fun_Simpson2D(x0, y0)
    plt.plot(xp, f, '-', xp, ff, 'o')
    plt.show()
Exemple #5
0
    rho_1, lattice_1, grid_1, shift_1 = read_xsf_example.\
        read_example_xsf_density(file_xsf_1)

    rho_2, lattice_2, grid_2, shift_2 = read_xsf_example.\
        read_example_xsf_density(file_xsf_2)

    # problem 2
    problem_2(rho_1, lattice_1, grid_1, file_xsf_1)
    problem_2(rho_2, lattice_2, grid_2, file_xsf_2)

    # problem 3
    x = np.linspace(0, 1, grid_1[0])
    y = np.linspace(0, 1, grid_1[1])
    z = np.linspace(0, 1, grid_1[2])

    spl3d_1 = spline.spline(x=x, y=y, z=z, f=rho_1, dims=3)
    line_1 = [[0.1, 0.1, 2.8528], [4.45, 4.45, 2.8528]]
    plot_electron_density(spl3d_1, lattice_1, line_1, 500,
                          file_xsf_1 + '\n' + str(line_1))

    # problem 4
    x = np.linspace(0, 1, grid_2[0])
    y = np.linspace(0, 1, grid_2[1])
    z = np.linspace(0, 1, grid_2[2])

    spl3d_2 = spline.spline(x=x, y=y, z=z, f=rho_2, dims=3)

    line_2 = [[-1.4466, 1.3073, 3.2115], [1.4361, 3.1883, 1.3542]]
    plot_electron_density(spl3d_2, lattice_2, line_2, 500,
                          file_xsf_2 + '\n' + str(line_2))
Exemple #6
0
def main():
    filename = 'dft_chargedensity2.xsf'
    rho, lattice, grid, shift = read_example_xsf_density(filename)
    
    #print(lattice)
    
    dlattice=1.0*lattice
    for i in range(3):
        dlattice[i,:]/=(grid[i]-1)
    dV = abs(linalg.det(dlattice))
    print('Num. electrons: ', sum(sum(sum(rho[0:-1,0:-1,0:-1])))*dV)

    print('Reciprocal lattice as [b1,b2,b3]: ')
    print(transpose(2.0*pi*linalg.inv(transpose(lattice))))

    if filename=='dft_chargedensity1.xsf':
        x = linspace(0,lattice[0,0],grid[0])
        y = linspace(0,lattice[1,1],grid[1])
        z = linspace(0,lattice[2,2],grid[2])

        int_dx = simps(rho,x=x,axis=0)
        int_dxdy = simps(int_dx,x=y,axis=0)
        int_dxdydz = simps(int_dxdy,x=z)
        print('  Simpson int = ',int_dxdydz)

        spl3d=spline(x=x,y=y,z=z,f=rho,dims=3)

        r1=array([0.1,0.1,2.8528])
        r2=array([4.45,4.45,2.8528])
        t = linspace(0,1,500)
        f = zeros(shape=shape(t))
        for i in range(len(t)):
            xx=r1+t[i]*(r2-r1)
            f[i]=spl3d.eval3d(xx[0],xx[1],xx[2])

        plot(t*sqrt(sum((r2-r1)**2)),f)
        show()
    else:
        inv_cell=linalg.inv(transpose(lattice))
        x = linspace(0,1.,grid[0])
        y = linspace(0,1.,grid[1])
        z = linspace(0,1.,grid[2])
        
        int_dx = simps(rho,x=x,axis=0)
        int_dxdy = simps(int_dx,x=y,axis=0)
        int_dxdydz = simps(int_dxdy,x=z)
        print('  Simpson int = ',int_dxdydz*abs(linalg.det(lattice)))

        spl3d=spline(x=x,y=y,z=z,f=rho,dims=3)
        
        r1=array([-1.4466, 1.3073, 3.2115])
        r2=array([1.4361, 3.1883, 1.3542])
        t = linspace(0,1,500)
        f = zeros(shape=shape(t))
        for i in range(len(t)):
            xx=inv_cell.dot(r1+t[i]*(r2-r1))
            f[i]=spl3d.eval3d(xx[0],xx[1],xx[2])

        figure()
        plot(t*sqrt(sum((r2-r1)**2)),f)

        r1=array([2.9996, 2.1733, 2.1462])
        r2=array([8.7516, 2.1733, 2.1462])
        t = linspace(0,1,500)
        f = zeros(shape=shape(t))
        uvec=ones(r1.shape)
        for i in range(len(t)):
            xx=mod(inv_cell.dot(r1+t[i]*(r2-r1)),uvec)
            f[i]=spl3d.eval3d(xx[0],xx[1],xx[2])

        figure()
        plot(t*sqrt(sum((r2-r1)**2)),f)
        show()
def main():
    gridpoints = 41  # this must be form N*20 + 1 to include the plates and work correctly!
    if np.mod(gridpoints - 1, 20) != 0:
        print("Error: gridpoints must of form N*20 + 1")
        return

    tol = 1e-23  # tolerance for convergence
    max_iters = 5000  # maximum amount of 'updates' allowed (prevents infinite loops)
    epsilon = 8.8e-12  # permittivity, in case charges are present
    q = 1.602176634e-19  # elementary charge

    x_min, x_max = (-1, 1)
    y_min, y_max = (-1, 1)

    x = np.linspace(x_min, x_max, gridpoints)
    y = np.linspace(y_min, y_max, gridpoints)
    h = x[1] - x[0]

    X, Y = np.meshgrid(x, y, indexing='ij')  # for plotting

    fig, ax = subplots()
    ax.set_xticks(np.arange(x_min, x_max, h))
    ax.set_yticks(np.arange(y_min, y_max, h))
    ax.set_xlim(x_min, x_max)
    ax.set_ylim(x_min, x_max)
    ax.set_title(
        "Set point charges using mouse. Left click = add positive charge, right click = add negative charge\n "
        "You may add or remove multiple charges for each point. continue by closing figure."
    )
    ax.grid(True)
    ax.set_aspect('equal', 'box')

    rho_mat = np.zeros(
        [gridpoints,
         gridpoints])  # rho will contain the charges (negative or positive)

    clicked = False

    # update rho_mat by user mouse clicks until the figure is closed.
    def onclick(event):
        ix, iy = event.xdata, event.ydata
        if str(ix) == 'None' or str(iy) == 'None':
            return

        ix_index = int(np.round((ix - x_min) / h))
        iy_index = int(np.round((iy - y_min) / h))

        ix = x[ix_index]
        iy = y[iy_index]
        if str(
                event.button
        ) == "MouseButton.LEFT" or event.button == 1:  # same thing on different PC's
            rho_mat[ix_index, iy_index] += q
        elif str(event.button) == "MouseButton.RIGHT" or event.button == 3:
            rho_mat[ix_index, iy_index] -= q
        else:
            return

        tot_point_charge = np.copy(rho_mat[ix_index, iy_index])
        # different colors for different charges
        if tot_point_charge > 0:
            color = 'r'
        elif tot_point_charge < 0:
            color = 'b'
        else:
            color = 'w'

        transparency = min(np.abs(tot_point_charge) / q * 0.1, 1)
        print("[" + str(np.round(ix, decimals=3)) + ", " +
              str(np.round(iy, decimals=3)) + "] Total charge: " +
              str(int(tot_point_charge / q)) + "q")

        ax.scatter(
            ix, iy, c='w', s=120
        )  # this allows color changes for the point (from red to blue etc..)
        ax.scatter(ix, iy, c=color, alpha=transparency, s=120)

        fig.canvas.draw()

    fig.canvas.mpl_connect('button_press_event', onclick)
    show()

    if np.count_nonzero(rho_mat) == 0:
        print("Error: You must add point charges!")
        return

    # initialize phi matrix with given boundary conditions
    initial_phi_matrix = np.zeros([gridpoints, gridpoints
                                   ])  # first index is x, second index is y

    boundary_matrix = np.zeros(
        [gridpoints,
         gridpoints])  # boundary matrix is the same form as initial phi matrix
    # value is 1 for boundary points, 0 for others.

    # add square boundaries
    boundary_matrix[:, 0] = 1.
    boundary_matrix[:, -1] = 1.
    boundary_matrix[0, :] = 1.
    boundary_matrix[-1, :] = 1.

    print("Starting SOR method iteration...")
    solved_phi_matrix = solve_poisson_sor_method(initial_phi_matrix,
                                                 boundary_matrix,
                                                 rho_mat,
                                                 h,
                                                 epsilon,
                                                 tol=tol,
                                                 max_iters=max_iters,
                                                 omega=1.8)

    rcParams.update({'font.size': 13})

    phi_gradient = np.array(np.gradient(solved_phi_matrix, h))
    e_field = -1 * phi_gradient
    e_field_x = e_field[0, :, :]
    e_field_y = e_field[1, :, :]

    quiverfig, quiver_ax = subplots()
    quiver_ax.quiver(X, Y, e_field_x, e_field_y, angles='xy', scale_units='xy')

    # add point charge markers
    for i in range(rho_mat.shape[0]):
        for j in range(rho_mat.shape[1]):
            tot_point_charge = rho_mat[i, j]
            transparency = min(np.abs(tot_point_charge) / q * 0.25, 1)
            if tot_point_charge > q / 2:
                quiver_ax.scatter(x_min + h * i,
                                  y_min + h * j,
                                  alpha=transparency,
                                  c='r',
                                  s=250)
            elif tot_point_charge < -q / 2:
                quiver_ax.scatter(x_min + h * i,
                                  y_min + h * j,
                                  alpha=transparency,
                                  c='b',
                                  s=250)

    # plot boundaries (left, right, up, down)
    lbound_x, lbound_y = x_min * np.ones(100), np.linspace(y_min, y_max, 100)
    rbound_x, rbound_y = x_max * np.ones(100), np.linspace(y_min, y_max, 100)
    ubound_x, ubound_y = np.linspace(x_min, x_max, 100), y_max * np.ones(100)
    dbound_x, dbound_y = np.linspace(x_min, x_max, 100), y_min * np.ones(100)
    quiver_ax.plot(lbound_x, lbound_y, 'k-', linewidth=3)
    quiver_ax.plot(rbound_x, rbound_y, 'k-', linewidth=3)
    quiver_ax.plot(ubound_x, ubound_y, 'k-', linewidth=3)
    quiver_ax.plot(dbound_x, dbound_y, 'k-', linewidth=3)
    quiver_ax.set_aspect('equal', 'box')
    title(
        'E-field visualization in xy-plane with custom point charges. Red = positive, blue = negative'
    )
    xlabel('x')
    ylabel('y')

    # interpolate potential field with spline and plot it
    spl2d = spline(x=x, y=y, f=solved_phi_matrix, dims=2)
    xx = np.linspace(x_min, x_max, gridpoints * 5)
    yy = np.linspace(y_min, y_max, gridpoints * 5)

    Z = spl2d.eval2d(xx, yy)
    XX, YY = np.meshgrid(xx, yy, indexing='ij')
    fig, ax = subplots(1, 1)

    # colormap scaling
    if np.min(Z) >= 0:
        vmin = 0
        vmax = np.max(Z)
        cmap = 'Reds'
    elif np.max(Z) <= 0:
        vmax = 0
        vmin = np.min(Z)
        cmap = 'Blues'
    else:
        vmax = max(np.abs(np.min(Z)), np.max(Z))
        vmin = -vmax
        cmap = 'RdBu_r'

    c = ax.pcolor(XX, YY, Z, vmin=vmin, vmax=vmax, cmap=cmap)
    # c = ax.pcolor(X, Y, solved_phi_matrix, vmin=vmin, vmax=vmax, cmap=cmap)
    colorbar(c)
    xlabel('x')
    ylabel('y')
    title('Electric potential (spline interpolation)')
    ax.set_aspect('equal', 'box')

    show()