# 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.