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