|
主方程
- import numpy as np
- import time
- from dft2function import *
- time_begin = time.time()
- N =30 # 网格点数
- dx = dy =1 / (N +1) # 步长
- x = np.linspace(dx,1 - dx, N)
- y = np.linspace(dy,1 - dy, N)
- X, Y = np.meshgrid(x, y)
- num_electron = 5
- M_laplace=get_laplace(N);
- M_T = -1./2.*M_laplace;
-
- max_iter=100
- energy_tolerance=1e-5
- log={"energy":[float("inf")], "energy_diff":[float("inf")]}
- nxy=np.zeros([N,N])
- def print_log(i,log):
- print(f"step: {i:<5} energy: {log['energy'][-1]:<10.4f} energy_diff: {log['energy_diff'][-1]:.10f}")
- for i in range(max_iter):
- ex_energy, ex_potential=get_exchange(nxy,dx,dy)
- ha_potential=get_hatree(nxy,x,y)
- ext = get_ext(x,y)
- # Hamiltonian
- H=M_T+np.diagflat((ex_potential+ha_potential+ext).flatten())
-
- energy, psi= np.linalg.eigh(H)
-
- # log
- log["energy"].append(energy[0])
- energy_diff=energy[0]-log["energy"][-2]
- log["energy_diff"].append(energy_diff)
- print_log(i,log)
-
- # convergence
- if abs(energy_diff) < energy_tolerance:
- print("converged!")
- break
-
- # update density
- nxy=get_nx(num_electron, psi, dx,dy)
- nxy.resize([N,N])
- else:
- print("not converged")
- time_end = time.time()
- print("求解时间: {:.3f}".format(time_end-time_begin))
- import matplotlib.pyplot as plt
- fig, axs = plt.subplots(10, 10)
- for i in range(10):
- for j in range(10):
- axs[i, j].set_title("EigV: {:.3f}".format(energy[10*i+j]))
- axs[i, j].imshow(psi[:, 10*i+j].reshape(N, N))
- fig.tight_layout()
- plt.show()
复制代码 函数方程
- import numpy as np
- # 构造系数矩阵
- def get_laplace(N):
- T = np.zeros((N**2, N**2))
- for i in range(N):
- for j in range(N):
- k = i * N + j # 当前点索引
- T[k,k] = -4
- if i>0 : T[k,k-N] = 1
- if i<N-1: T[k,k+N] = 1
- if j>0 : T[k,k-1] = 1
- if j<N-1: T[k,k+1] = 1
- return T
- def integral(dx,dy,z,axis=0):
- return np.sum(z*dx*dy, axis=axis)
- def get_nx(num_electron, psi, dx,dy):
- # normalization
- I=integral(dx,dy,psi**2)
- normed_psi=psi/np.sqrt(I)[None, :]
- fn=[2 for _ in range(num_electron//2)]
- if num_electron % 2:
- fn.append(1)
- # density
- res=np.zeros_like(normed_psi[:,0])
- for ne, psi in zip(fn,normed_psi.T):
- res += ne*(psi**2)
- return res
- def get_exchange(nxy,dx,dy):
- energy=-3./4.*(3./np.pi)**(1./3.)*integral(dx,dy,nxy**(4./3.))
- potential=-(3./np.pi)**(1./3.)*nxy**(1./3.)
- return energy, potential
- def get_hatree(nxy,x,y,eps=1e-1):
- dx =x[1]-x[0]
- dy =y[1]-y[0]
- x1 = x[:,None,None,None]
- x2= x[None,:,None,None]
- y1 = y[None,None,:,None]
- y2= y[None,None,None,:]
- nx2y2 = nxy[None,:None,:]
- potential=np.sum(nx2y2*dx*dy/np.sqrt((x1-x2)**2+(y1-y2)**2+eps),axis=(-1,-3))
- return potential
- def get_ext(x,y):
- x2y2 = x[:,None]**2*y[None,:]**2
- return x2y2
复制代码 |
|