Wavefunction tutorial
Requirements
Software components
nanotools
RESCU+
Pseudopotentials
I will need the following pseudopotentials.
C_AtomicData.mat
Let’s copy them from the pseudo database to the current working directory and export RESCUPLUS_PSEUDO=$PWD
.
Briefing
In this tutorial, I show how to calculate the real space wavefunctions of graphene at a few k-points.
Setup
Create the Python script etot.py
with the following content (see the tutorial on TotalEnergy)
from nanotools import Atoms, Cell, System, TotalEnergy
import numpy as np
a = 2.46 # lattice constant (ang)
avec = [
[.5*a, np.sqrt(3)/2*a, 0.],
[.5*a,-np.sqrt(3)/2*a, 0.],
[0.,0.,10.583544213400000],
]
cell = Cell(avec=avec, resolution=0.12)
fxyz = [[2/3, 1/3, 0.5],[1/3, 2/3, 0.5]]
atoms = Atoms(fractional_positions=fxyz, formula="CC")
sys = System(cell=cell, atoms=atoms)
sys.kpoint.set_grid([15,15,1])
calc = TotalEnergy(sys)
calc.solve()
and wvf.py
from nanotools import Wavefunction as WF
import numpy as np
calc = WF.from_totalenergy("nano_scf_out.json")
calc.system.kpoint.set_grid([4,4,1], shift = [.5, .5, 0.])
calc.solve()
Explanations
Here is a high level view of the calculation workflow:
Initialize the Wavefunction calculator from a ground state calculation (
TotalEnergy
).Perform a wavefunction calculation (non-self-consistently) for a given set of k-points and compute the wavefunction.
Initialize the Wavefunction calculator
Upon completing the total energy calculation, the results are saved in nano_scf_out.json
.
I will initialize a Wavefunction
calculator using the class method from_totalenergy
.
calc = WF.from_totalenergy("nano_scf_out.json")
calc.system.kpoint.set_grid([4,4,1], shift = [.5, .5, 0.])
calc.solve()
The method from_totalenergy
will copy the system information and initialize the Wavefunction
calculator.
I then set the k-point to a \(4\times 4\times 1\) grid.
Alternatively, I can directly set the k-point coordinates for which I want the real space wavefunctions calling set_fractional_coordinates
from the Kpoint
class.
Wavefunction calculation
RESCU+’s solvers are invoked calling the solve
method
calc.solve()
The method writes all parameters to a JSON file, then calls the relevant (Fortran) program, then loads the data back into the calculator.
The output of rescuplus
goes to nano_wvf_out.h5
and nano_wvf_out.json
.
As other real space data, the local DOSes are stored in nano_wvf_out.h5
similarly with density, i.e. under /wavefunctions/#/field
where #
is an index running over all k-points.
If spin is accounted for, then the paths to the spin-up and spin-down wavefunctions are /wavefunctions/spin-up/#/field
and /wavefunctions/spin-down/#/field
respectively.
Besides, the k-point fractional coordinates and grid information are found in /wavefunctions/#/kpoint
and /wavefunctions/#/cell
.
Target specific eigenstates
It is sometimes useful to target specific states in the band structure.
In large scale calculations, for example, where one might be interested in a few states, it is not necessary to compute the real space representation of thousands of eigenstates.
Taking the above system as example, we can compute the wavefunctions of the 4th and 5th band at k-point [.1,.2,.3]
as follows
from nanotools import Wavefunction as WF
import numpy as np
calc = WF.from_totalenergy("nano_scf_out.json")
calc.system.kpoint.set_fractional_coordinates([[.1,.2,.3]])
calc.solver.eig.target_irange = [3,4]
calc.solve()
We invoke the Kpoint
object’s method set_fractional_coordinates
to directly set the k-points to [.1,.2,.3]
.
We also set the eigensolver parameter target_irange
to [3,4]
.
Note that target_irange
is an index range, and hence all states between target_irange[0]
and target_irange[1]
will be computed.