Features · Compilation · Examples · Docs
Quantum Acorn, a collection of electronic structure methods compiled into a dependency-free binary. If you are here for the educational scripts, you can find them in the education folder.
Below are all the important features of Acorn divided into categories.
- Restricted Hartree–Fock Method with DIIS
- Møller–Plesset Perturbation Theory
- Full Configuration Interaction
- Quantum Dynamics with Arbitrary Number of States & Dimensions
- Fewest Switches Surface Hopping Dynamics
- Landau–Zener Surface Hopping Dynamics
- Mapping Approach to Surface Hopping Dynamics
Since the software is coded in zig, you need to have the zig compiler installed on your system. You can download the latest version of the zig compiler from the official website or install it from your favourite package manager. After you have installed the zig compiler, navigate to the project root and run the following command to compile the project.
zig build
This will compile the project and create a binary file named acorn
in the zig-out/arch-os
folder, where arch
is the architecture of your system and os
is the operating system you are using. If you don't know your CPU architecture, you probably want the x86_64
binary. You can also perform tests on the project by running the following command.
zig build test
If some tests fail, let me know by creating an issue. If all the tests pass, you can run the binary file using the following command.
./zig-out/arch-os/acorn
You should see the version of the compiler and execution time of the program. If you see this, the program is working correctly.
Below are some examples of the quantum mechanical methods implemented in Acorn. The plotting commands use the script plot.py
in the python
folder. You can use this script to plot the data generated by the program.
- Real Time Adiabatic Quantum Dynamics
- Real Time Nonadiabatic Quantum Dynamics
- Surface Hopping Dynamics
This example demonstrates the real-time quantum dynamics of a particle in a harmonic potential. The particle is initialized in a Gaussian wavepacket and allowed to evolve in time. The wavefunction is written to a file named WAVEFUNCTION.mat
in the current directory. The input file for this example is shown below.
{
"quantum_dynamics" : {
"adiabatic" : false,
"iterations" : 1000,
"mode" : [0, 1],
"time_step" : 0.1,
"grid" : {
"limits" : [-8, 8],
"points" : 512
},
"initial_conditions" : {
"mass" : 1,
"momentum" : [0],
"position" : [1],
"state" : 0,
"gamma" : 2
},
"write" : {
"wavefunction" : "WAVEFUNCTION.mat",
"autocorrelation_function" : "ACF.mat",
"spectrum" : "SPECTRUM.mat"
},
"potential" : "harmonic1D_1"
}
}
The input file can be run like any other program in Acorn, no special flags are required. This simulation is fast and should complete in under a second. You can visualize the wavefunction, autocorrelation function or the vibrational spectrum with the commands below.
lines.py WAVEFUNCTION.mat:0,1 --legends every "Re(\$\Psi_0\$)" "Im(\$\Psi_0\$)" --xlabel "Coordinate (a.u.)" --ylabel "Wavefunction" --animate 2
lines.py ACF.mat:0,1 SPECTRUM.mat --figsize 6 16 --legends 0,1 "Re(\$<\Psi_0|\Psi>\$)" "Im(\$<\Psi_0|\Psi>\$)" --subplots 121 121 122 --xlabel "Time (a.u.)" "Energy (a.u.)" --xlim nan nan 0 6 --ylabel "ACF" "Intensity"
Acorn also supports higher dimensions. As an example you can simulate a 2D wavefunction in a 2D harmonic potential using the following input.
{
"quantum_dynamics" : {
"adiabatic" : false,
"iterations" : 1000,
"mode" : [0, 1],
"time_step" : 0.1,
"grid" : {
"limits" : [-8, 8],
"points" : 256
},
"initial_conditions" : {
"mass" : 1,
"momentum" : [0, 0],
"position" : [1, 1],
"state" : 0,
"gamma" : 2
},
"write" : {
"wavefunction" : "WAVEFUNCTION.mat",
"autocorrelation_function" : "ACF.mat",
"spectrum" : "SPECTRUM.mat"
},
"potential" : "harmonic2D_1"
}
}
This simulation takes a few seconds, since the time complexity increases exponentially. Visualizing the 3D complex wavefunction is a little tricky. One way is to plot the square of the wavefunction on a 2D heatmap. You can visualize the wavefunction this way and ACF with spectrum the same way as above with the commands below.
heatmap.py WAVEFUNCTION.mat:0,1 --xlabel "Coordinate (a.u.)" --ylabel "Coordinate (a.u.)" --transform norm --animate 2
lines.py ACF.mat:0,1 SPECTRUM.mat --figsize 6 16 --legends 0,1 "Re(\$<\Psi_0|\Psi>\$)" "Im(\$<\Psi_0|\Psi>\$)" --subplots 121 121 122 --xlabel "Time (a.u.)" "Energy (a.u.)" --xlim nan nan 0 9 --ylabel "ACF" "Intensity"
This example demonstrates the real-time quantum dynamics of a first Tully potential in the adiabatic basis. It exports the resulting time-dependent wavefunction and the potential. The input file for this example is shown below.
{
"quantum_dynamics" : {
"adiabatic" : true,
"iterations" : 500,
"mode" : [0, 1],
"time_step" : 10,
"grid" : {
"limits" : [-16, 32],
"points" : 2048
},
"initial_conditions" : {
"mass" : 2000,
"momentum" : [10],
"position" : [-10],
"state" : 1,
"gamma" : 2
},
"write" : {
"wavefunction" : "WAVEFUNCTION.mat",
"population" : "POPULATION.mat"
},
"potential" : "tully1D_1"
}
}
This simulation is fast and should complete approximately in a second. You can visualize the wavefunction and state population with the commands below. The wavefunctions on each states are vertically separated for better visualization.
lines.py WAVEFUNCTION.mat:0,1,2,3 --legends every "Re(\$\Psi_0\$)" "Im(\$\Psi_0\$)" "Re(\$\Psi_1\$)" "Im(\$\Psi_1\$)" --offsets every -1 -1 1 1 --xlabel "Coordinate (a.u.)" --ylabel "Wavefunction" --animate 4
lines.py POPULATION.mat --legends every "S\$_0\$" "S\$_1\$" --xlabel "Time (a.u.)" --ylabel "Population"
This example demonstrates how to run a surface hopping dynamics. The below example executes a Fewest Switches Surface Hopping (FSSH) dynamics on the same potential as the real-time nonadiabatic dynamics example above.
{
"classical_dynamics" : {
"adiabatic" : true,
"iterations" : 5000,
"time_step" : 1,
"trajectories" : 1000,
"initial_conditions" : {
"mass" : [2000],
"momentum_mean" : [10],
"momentum_std" : [1],
"position_mean" : [-10],
"position_std" : [0.5],
"state" : [0, 1]
},
"log_intervals" : {
"iteration" : 500,
"trajectory" : 100
},
"write" : {
"population_mean" : "POPULATION_MEAN.mat"
},
"potential" : "tully1D_1",
"fewest_switches" : {}
}
}
This simulation is slow and will take a few second to complete. You can visualize the mean population of each state with the command below.
lines.py POPULATION_MEAN.mat --legends every "S\$_0\$" "S\$_1\$" --xlabel "Time (a.u.)" --ylabel "Population"