Package Guide
Define Grid for Calculations
Start by defining grid used in calculations
using HKQM
ceg = ElementGridSymmetricBox(5u"Å", 4, 24)
ElementGridSymmetricBox 4^3 elements and 24^3 Gauss points per element
This creates a cubic box with with side length of 5 Å that are divided to 4 elements and 24 Gauss-Lagrange points for each element. Resulting in total of (4*24)^3=884736
points.
The grid is also an Array that can be used as one
typeof(ceg) <: AbstractArray
true
size(ceg)
(24, 24, 24, 4, 4, 4)
eltype(ceg)
SVector{3, Float64} (alias for StaticArraysCore.SArray{Tuple{3}, Float64, 1, 3})
The values are x-, y- and z-coordinates of the grid point in bohr.
ceg[1,1,1,3,3,3]
3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3):
0.005684272564815695
0.005684272564815695
0.005684272564815695
Operator algebra
Generate basic operators for the grid
r = position_operator(ceg)
p = momentum_operator(ceg)
Operator 4^3 elements, 24^3 Gauss points per element
Operators have units defined with Unitful.jl package
unit(r)
a₀
unit(p)
ħ a₀^-1
These operator are vector operator and have length defined
length(r)
3
Individual components can be accessed with indexing
x = r[1]
y = r[2]
z = r[3]
Operators support basic algebra operations
r + r
2 * r
r + [1u"bohr", 2u"Å", 1u"pm"]
r + 1u"bohr"
r / 2
x * y
Units are checked for the operations and operations that do not make sense are prohibited
r + p
Vector operations are supported
r² = r ⋅ r
l = r × p
Common functions can be used also
sin(1u"bohr^-1" * x)
exp(-1u"bohr^-2" * r²)
Functions require that the input is unitless
exp(-r²)
Quantum States
Quantum states can be created from operators
ψ = QuantumState( exp(-2u"bohr^-2" * r²) )
Quantum state
States can be normalized
normalize!(ψ)
Quantum state
Complex conjugate can be taken with
ϕ = conj(ψ)
conj!(ψ)
Quantum states have linear algebra defined
2ψ - ψ
Quantum state
Inner product can be calculated with bracket
function
bracket(ψ, 2ψ)
2.0
Operators can be applied to quantum state by multiplication
x * ψ
Quantum state
Vector operators return arrays of quantum state
r * ψ
3-element Vector{QuantumState{Array{Float64, 6}, Float64}}:
Quantum state
Quantum state
Quantum state
Quantum states have units
unit(ψ)
unit( x * ψ )
a₀
Other Unitful functions like dimension
and uconvert
are defined also.
Expectational values of operators can be calculated with bracket
funtion
bracket(ψ, x, ψ)
-2.2188173684881792e-18 a₀
Slater Determinant
Slater determinant is orthonormal set of quantum states
st = SlaterDeterminant([ψ, (1u"bohr^-1"*x)*ψ])
SlaterDetermiant 2 orbitals
Slater determinant is an array of orbitals represented by quantum states
length(st)
2
st[1]
Quantum state
Hamilton Operator
Hamilton operator is a special operator that is needed for Helmholtz Greens function. To create it you need to create potential energy operator first
V = -30u"eV" * exp(-0.1u"bohr^-2" * r²)
H = HamiltonOperator(V)
Operator 4^3 elements, 24^3 Gauss points per element
Default mass is one electron mass and it can be customized with m
keyword
H_2me = HamiltonOperator(V; m=2u"me_au")
Solving Eigen-States of a Hamiltonian
You need to generate initial state for Hamiltonian that gives negative energy!
ψ = QuantumState( exp(-0.2u"bohr^-2" * r²) )
normalize!(ψ)
bracket(ψ, H, ψ)
-0.4887869883070721 Eₕ
After that Helmholtz Greens function can be used to generate better estimate for the lowest eigen-state
ϕ, E = solve_eigen_states(H, ψ; max_iter=10, rtol=1E-6)
(QuantumState[Quantum state], Quantity{Float64, 𝐋^2 𝐌 𝐓^-2, Unitful.FreeUnits{(Eₕ,), 𝐋^2 𝐌 𝐓^-2, nothing}}[-0.4978561191412073 Eₕ])
You can add more states to the solution by giving more initial states
ψ111 = particle_in_box(ceg, 1,1,1)
ψ112 = particle_in_box(ceg, 1,1,2)
ϕ2, E2 = solve_eigen_states(H, ψ111, ψ112)
(QuantumState[Quantum state, Quantum state], Quantity{Float64, 𝐋^2 𝐌 𝐓^-2, Unitful.FreeUnits{(Eₕ,), 𝐋^2 𝐌 𝐓^-2, nothing}}[-0.4978559490725577 Eₕ, -0.17245088784778714 Eₕ])
Once estimate is self consistent a true solution has been found.
Solving Hartree-Fock equation
Hartree-Fock equation can be solver with scf
command.
V = -100u"eV" * exp(-0.1u"bohr^-2" * r²)
H = HamiltonOperator(V)
ψ₁ = QuantumState( exp(-0.2u"bohr^-2" * r²) )
ψ₂ = 1u"bohr^-1"*r[1]*QuantumState( exp(-0.2u"bohr^-2" * r²) )
sd = SlaterDeterminant(ψ₁, ψ₂)
SlaterDetermiant 2 orbitals
To check that all eigen-values are negative calculate Fock matrix and look for diagonal values.
fock_matrix(sd, H)
After that you can solve Hartree-Fock equations
sd1 = scf(sd, H; tol=1E-6, max_iter=10)
tol
is maximum chance in orbital overlap until convergence is archived. max_iter
is maximum iterations calculated.
Hartree-Fock energy is calculated by calling hf_energy
hf_energy(sd1, H)
Orbital energies can be found from diagonal of Fock matrix
fock_matrix(sd1, H)
Check also that off-diagonal elements are insignificant to make sure the system real solution has been found.
Approximate Nuclear Potential
There is an approximation to nuclear potential defined in J. Chem. Phys. 121, 11587 (2004). It allows approximate electronic structure calculations.
Here is an example for Hydrogen molecule.
Define nuclear positions
r₁ = [0.37, 0., 0.] .* 1u"Å"
r₂ = [-0.37, 0., 0.] .* 1u"Å"
3-element Vector{Quantity{Float64, 𝐋, Unitful.FreeUnits{(Å,), 𝐋, nothing}}}:
-0.37 Å
0.0 Å
0.0 Å
After that create nuclear potential
V₁ = nuclear_potential_harrison_approximation(ceg, r₁, "H")
V₂ = nuclear_potential_harrison_approximation(ceg, r₂, "H")
V = V₁ + V₂
Operator 4^3 elements, 24^3 Gauss points per element
and Hamiltonian
H = HamiltonOperator(V)
Operator 4^3 elements, 24^3 Gauss points per element
Create initial orbital
ϕ = particle_in_box(ceg, 1,1,1)
ψ = SlaterDeterminant( ϕ )
SlaterDetermiant 1 orbitals
Solve SCF equations
ψ1 = scf(ψ, H)
Calculations in Magnetic Field
To calculate magnetic field effects on the above hydrogen molecule, start by defining magnetic field
B = [0., 0., 100.0].*u"T"
A = vector_potential(ceg, B...)
Operator 4^3 elements, 24^3 Gauss points per element
After that create a magnetic field Hamiltonian
Hm = HamiltonOperatorMagneticField(V,A)
Operator 4^3 elements, 24^3 Gauss points per element
You can then just solve the system like above
ψm = scf(ψ, Hm)
It is a good idea to start form the no magnetic field case. Because wavefunction is complex in magnetic field and thus more expensive to calculate. By starting from no field case you minimize the iterations needed to solve SCF equations.
ψm = scf(ψ1, Hm)
Magnetic current can be extracted with
# current for specific orbital
j1 = magnetic_current(ψm[1], Hm)
# total magnetic current
j = magnetic_current(ψm, Hm)
# para magnetic current
jp = para_magnetic_current(ψm)
In the future there will be a way to visualize or export the magnetic current!