In 1920-1930, Schrödinger Equation provides a way to calculate the wavefunction
In 1964, Pierre Hohenberg and Walter Kohn established Density Functional Theory (DFT) that the ground-state properties of a many-electron system are uniquely determined by its electron density
The time-independent Schrödinger equation for a system of
-
$\hat{H}$ is the Hamiltonian operator, including kinetic and potential energies. -
$\Psi$ is the many-electron wavefunction, depending on the positions of all electrons. -
$E$ is the total energy of the system.
The Hamiltonian for such a system is:
where
- The first term represents the kinetic energy of each electron and
$V_{\text{ext}}$ (due to external potential). - The second summation accounts for electron-electron Coulomb interactions.
It is not easy to solve this equation due to the following issues,
- The wavefunction
$\Psi$ depends on$3N$ spatial coordinates, making it computationally infeasible for large$N$ . - Computational resources required grow exponentially with the number of electrons.
- Properly accounting for interactions and correlations between electrons is challenging.
- Methods like Hartree-Fock simplify the problem but neglect electron correlation, leading to inaccuracies.
Kohn and Hohenberg proofed two Theorems
-
The ground-state electron density
$\rho_0(\mathbf{r})$ uniquely determines the external potential$V_{\text{ext}}(\mathbf{r})$ , up to a constant, and hence all properties of the system. -
There exists a universal functional
$E[\rho]$ such that the ground-state energy$E_0$ can be obtained variationally:
where
From these two theorems, we can find that
- All observables are functionals of the electron density
$\rho(\mathbf{r})$ . - One can reduce the problem from dealing with a many-body wavefunction to a function of three spatial variables.
- The ground-state density
$\rho_0(\mathbf{r})$ minimizes the energy functional$E[\rho]$ .
In 1965, Walter Kohn and Lu Jeu Sham applied Variational Principle to develope a method to make DFT practical by introducing a system of non-interacting electrons that produce the same ground-state density as the interacting system.
Following Kohn-Sham Formalism, the total Energy Functional is expressed as:
-
$T_s[\rho]$ : Kinetic energy of non-interacting electrons. -
$E_{\text{ext}}[\rho]$ : Interaction with external potential. -
$E_H[\rho]$ : Hartree energy (classical electron-electron repulsion). -
$E_{\text{XC}}[\rho]$ : Exchange-correlation energy, encompassing all many-body effects.
Thus, the Schrödinger equation (now called Kohn-Sham Equations) becomes:
-
$\phi_i(\mathbf{r})$ : Kohn-Sham orbitals. -
$\epsilon_i$ : Orbital energies. -
$V_{\text{eff}}(\mathbf{r})$ : Effective potential.
Effective Potential is
-
$V_H(\mathbf{r})$ : Hartree potential. -
$V_{\text{XC}}(\mathbf{r}) = \frac{\delta E_{\text{XC}}[\rho]}{\delta \rho(\mathbf{r})}$ .
The Electron Density derived from the solution of KS equation:
To solve the KS equation, Exchange-Correlation Functional is a tricky term that represents the difference between the true kinetic and electron-electron interaction energies and those of the non-interacting reference system. The exact form is unknown. Hence approximations are necessary. Some commond choices are
Local Density Approximation (LDA)
assumes the exchange-correlation energy at a point depends only on the local density.
Generalized Gradient Approximation (GGA)
is a more advanced version by including density gradients to account for inhomogeneities. This can provide better accuracy for molecular and surface systems.
Since the electron density becomes the only concern of interest, one can start with a initial guess of the wavefunction and then solve the KS equations iteratively.
Now, we proceed to apply DFT to solve an One-Dimensional Harmonic Oscillator. Here we start by define the grid. We aim to find the wavefunction of an One-Dimensional Harmonic Oscillator.
-
Define a grid to describe the wavefunction spanning between at
$x_{\text{min}}$ and$x_{\text{max}}$ .
import numpy as np
import matplotlib.pyplot as plt
# Spatial grid parameters
x_min, x_max = -5.0, 5.0
N = 1000 # Number of grid points
x = np.linspace(x_min, x_max, N)
dx = x[1] - x[0]
-
Express the Kinetic energy (
$T$ ) and External Potential$V_{\text{ext}}(x)$ is simply a Harmonic potential:
T = (-2 * np.eye(N) + np.eye(N, k=1) + np.eye(N, k=-1)) / dx**2
V_ext = 0.5 * x**2
-
An initial guess of Electron Density as a function of
$r$ ,
rho = np.ones(N) * 1e-3 # Small initial density
- Iterative Solution
tolerance = 1e-6
max_iterations = 100
for iteration in range(max_iterations):
# Hartree potential
V_H = np.zeros(N)
for i in range(N):
V_H[i] = np.sum(rho * np.abs(x[i] - x) * dx)
# Exchange-correlation potential (simplified)
c = 1 # Constant for exchange
V_XC = -c / rho
# Effective potential
V_eff = V_ext + V_H + V_XC
# Total Hamiltonian
H = -0.5 * T + np.diag(V_eff)
# Solve eigenvalue problem
energies, wavefunctions = np.linalg.eigh(H)
# Update electron density
rho_new = np.abs(wavefunctions[:, 0])**2 # Ground state
# Check for convergence
if np.linalg.norm(rho_new - rho) < tolerance:
print(f'Converged after {iteration+1} iterations')
break
rho = rho_new
else:
print('Did not converge')
- Post-analysis
plt.plot(x, rho)
plt.title('Electron Density')
plt.xlabel('Position x')
plt.ylabel('Density ρ(x)')
plt.plot(x, V_eff, label='Effective Potential')
plt.plot(x, wavefunctions[:, 0], label='Ground State Wavefunction')
plt.legend()
plt.show()
In the Kohn-Sham formalism of DFT, the kinetic energy operator for an electron in one dimension is given by the Laplacian operator, which is the second derivative of the wavefunction with respect to position. The corresponding term in the Hamiltonian is:
To solve this equation numerically, we approximate the second derivative using the finite difference method. Consider a function
The expression tells us how to approximate the curvature of the function at each point using values of the function at neighboring points.
To apply this approximation to a system with (-2, +1, +1)
that multiply the values
-
np.eye(N)
: an identity matrix of$N \times N$ . -
np.eye(N, k=1)}
: a matrix of$N \times N$ with ones on the first upper diagonal. -
np.eye(N, k=-1)
: a matrix of$N \times N$ with ones on the first lower diagonal.
Thus, the combination of these matrices gives us a matrix representation of the finite difference approximation of the second derivative operator across the entire grid. The division by
For a 5-point grid, the matrix
This matrix will act on a vector representing the function
- Different Potentials: (e.g., a double-well potential)
- Modify the code to include additional occupied orbitals.
- Implement GGA or other exchange-correlation approximations.