GW tutorial. Convergence and approximations (BN)
We have selected 2D hexagonal boron nitride to explain the use of yambopy. Along with this tutorial we show how to use yambopy to make efficient convergence tests, to compare different approximations and to analyze the results.
Initial steps with Quantum Espresso
Yambopy includes qepy, a module to handle QE-DFT calculations necessary to run Yambo.
The initial step consists of a self-consistent (scf) ground state calculation together with a non-self-consistent (nscf) calculation with QE using the gs_bn.py
file:
<source lang="bash">python gs_bn.py python gs_bn.py -sn</source>
We have set the non-self-consistent run with a wave-function cutoff of 60 Ry, 70 bands and a k-grid of 12x12x1
for Yambo calculations.
In addition, we can check if we get a reasonable band structure for our many-body calculations. We can define a path, for instance, in an hexagonal Brillouin zone:
<source lang="bash"> p = Path([ [[0.0, 0.0, 0.0],'$\Gamma$'],
[[0.5, 0.0, 0.0],'M'], [[1./3,1./3,0.0],'K'], [[0.0, 0.0, 0.0],'$\Gamma$']], [int(10*2),int(10),int(sqrt(5)*10)])
</source>
We obtain the band structure by doing:
<source lang="bash">python gs_bn.py -b</source>
The horizontal line marks the top of the valence band. The electronic bandgap has a value of 4.73 eV. In the next sections, we will show how to calculate the GW correction and the excitonic effects with BSE using Yambo in an automatic way.
GW convergence of the bandgap
(a) Calculations
We converge the main parameters of a GW calculation independently. In addition, we make use of the plasmon pole approximation for the dielectric function, and the Newton solver to find the GW correction to the LDA eigenvalues. We converge the band gap of BN (difference in energy of the bottom of the conduction and top of the valence band at the K point of the Brillouin zone). We have designed the script gw_conv_bn.py (folder ~/tutorial/bn) for this purpose.
We can select the GW calculation by calling the YamboIn
with the corresponding arguments:
<source lang="python">y = YamboIn.from_runlevel('yambo -d -p p -g n -V all',folder='gw_conv')</source>
The main variables of a GW calculation are:
EXXRLvcs
: Exchange self-energy cutoff
NGsBlkXp
: Cutoff of the dielectric function.
BndsRnXp
: Number of bands in the calculation of the dielectric function (PPA).
GbndRnge
: Self-energy. The number of bands.
We define a dictionary with all the parameters that we want to converge. Be aware of setting the right units and format for each parameter.
<source lang="python">conv = { 'EXXRLvcs': [[10,10,20,30,40,50,60,70,80,90,100],'Ry'],
'NGsBlkXp': [[0,0,1,2,3,4,5,6], 'Ry'], 'BndsRnXp': [[[1,10],[1,10],[1,20],[1,30],[1,40],[1,50],[1,60],[1,70]],] , 'GbndRnge': [[[1,10],[1,10],[1,20],[1,30],[1,40],[1,50],[1,60],[1,70]],] }</source>
The class YamboIn
includes the function optimize
, which is called here:
<source lang="python"> y.optimize(conv,folder='gw_conv',run=run,ref_run=False) </source>
The function optimize has two main arguments: the convergence dictionary, and a function run with the instructions to run the calculation, defined in our case like:
<source lang="python">
def run(filename): """ Function to be called by the optimize function """ folder = filename.split('.')[0] print(filename,folder) shell = bash() shell.add_command('cd gw_conv') shell.add_command('rm -f *.json %s/o-*'%folder) #cleanup shell.add_command('%s -F %s -J %s -C %s 2> %s.log'%(yambo,filename,folder,folder,folder)) shell.run() shell.clean()
</source>
We have defined interactive run, in the folder gw_conv
. We have also defined the name for each job, associated with the variable and its value.
(b) Analysis
Once all the calculations are finished it's time to analyse them. At this point yambopy will facilitate the analysis. Besides
the python module, yambopy
can also be called in the terminal to perform some post-analysis tasks:
<source lang="python">
$ yambopy analysebse -> Using ypp, you can study the convergence of BSE calculations in 2 ways: plotem1s -> Plot em1s calculation analysegw -> Study the convergence of GW calculations by looking at the change in bandgap value. mergeqp -> Merge QP databases test -> Run yambopy tests plotexcitons -> Plot excitons calculation
</source>
Calling yambopy analysegw
will display the help of the function:
<source lang="python">
Study the convergence of GW calculations by looking at the change in bandgap value.
The script reads from <folder> all results from <variable> calculations and display them.
Use the band and k-point options according to the size of your k-grid and the location of the band extrema.
Mandatory arguments are: folder -> Folder containing SAVE and convergence runs. var -> Variable tested (e.g. FFTGvecs)
Optional variables are: -bc, --bandc (int) -> Lowest conduction band number -kc, --kpointc (int) -> k-point index for conduction band -bv, --bandv (int) -> Highest valence band number -kv, --kpointv (int) -> k-point index for valence band -np, --nopack (flag) -> Do not call 'pack_files_in_folder' -nt, --notext (flag) -> Do not print a text file -nd, --nodraw (flag) -> Do not draw (plot) the result
</source>
Running the function selecting the bands and k-points, together with the parameter of convergence we will obtain the convergence plot.
<source lang="python"> yambopy analysegw -bc 5 -kc 7 -bv 4 -kv 7 gw_conv EXXRLvcs yambopy analysegw -bc 5 -kc 7 -bv 4 -kv 7 gw_conv NGsBlkXp yambopy analysegw -bc 5 -kc 7 -bv 4 -kv 7 gw_conv BndsRnXp yambopy analysegw -bc 5 -kc 7 -bv 4 -kv 7 gw_conv GbndRnge </source>
From the convergence plots, we can choose the set of converged parameters and repeat the calculation for finer k-grids until we reach convergence with the k-points. We have intentionally used non-converged parameters. Nevertheless, along this week you should have gotten enough expertise to push the convergence of the parameters and determine the correct convergence set of parameters. We invite you to enter in the python script, increase the parameters and check again the convergence for larger values!
In general, the convergence with the k-grid is done after these variables are converged and, in principle, it is also independent of them. We invite you to change the number of k-points in the file gs_bn.py using the variable kpoints_nscf.
GW calculation in regular k-grid
From the bandgap convergence study made above for a k-grid we can decide reasonable parameters. Another option is to decide a convergence threshold to establish the accuracy of the convergence. In this tutorial, in order to make calculations lighter, we have chosen the following parameters:
<source lang="bash"> EXXRLvcs = 60 Ry BndsRnXp = 40 bands NGsBlkXp = 3 Ry GbndRnge = 30 bands QPkrange = [1,12,2,6] </source>
We can change the gs_bn.py
scripts to calculate a non self-consistent run for a larger k-grid (9x9x1 will do the job). We can also change the number of bands to 40 in order to speed up a bit the QE calculation.
We can just simply run the code to calculate the GW corrections for all the points of the Brillouin zone by setting the converged parameters in the script gw_bn.py
. If we enter in the script we can check that we define a scheduler (the default is bash):
<source lang="bash"> scheduler = Scheduler.factory </source>
We just need to define the run level and the variables we are going to chang:
<source lang="bash"> y = YamboIn.from_runlevel('%s -p p -g n -V all'%yambo,folder='gw')
y['EXXRLvcs'] = [60,'Ry'] # Self-energy. Exchange y['BndsRnXp'] = [1,40] # Screening. Number of bands y['NGsBlkXp'] = [3,'Ry'] # Cutoff Screening y['GbndRnge'] = [1,30] # Self-energy. Number of bands y['QPkrange'] = [kpoint_start,kpoint_end,2,6] </source>
We can now run the script and obtain the GW in the full k-grid.
<source lang="bash"> python gw_bn.py </source>
If everything has worked fine now we will have inside the folder gw/yambo
the netCDF file ndb.QP
with the results of the GW calculation. We can analyze the results and/or use them in BSE calculations.
Plotting GW calculations. Scissor operator and GW band structure
If everything has worked fine now we can start using the yambopy analysis tools. For this purpose, we have created the script plot-qp.py
. Using this script we will be able to read the Yambo databases and plot the results. The file is structured as follows:
A. Define a path. Using qepy we can define a path to plot the band structure.
<source lang="bash"> npoints = 10 path = Path([ [[ 0.0, 0.0, 0.0],'$\Gamma$'],
[[ 0.5, 0.0, 0.0],'M'], [[1./3.,1./3., 0.0],'K'], [[ 0.0, 0.0, 0.0],'$\Gamma$']], [int(npoints*2),int(npoints),int(sqrt(5)*npoints)] )
</source>
B. Read Yambo lattice and QP databases.
<source lang="bash"> lat = YamboSaveDB.from_db_file(folder='gw/SAVE',filename='ns.db1') ydb = YamboQPDB.from_db(filename='ndb.QP',folder='gw/yambo') </source>
C. Plot all QP eigenvalues. A very typical plot when analyzing GW calculations is the plot of the GW eigenvalues versus LDA eigenvalues. You just need to indicate which band index corresponds to the top of the valence band.
<source lang="bash"> n_top_vb = 4 ydb.plot_scissor_ax(ax,n_top_vb) </source>
GW results (dots) and linear fitting (solid lines)
The first image shows all the GW energies along all the k-points of the Brillouin zone. A clearer picture can be obtained by plotting the band structure along the symmetry points GMKG by using the analyser:
<source lang="bash">python gw_conv_bn.py -r</source> We first pack the results into a json file and subsequently we use the analyser to create the object which contains all the information.
<source lang="bash">pack_files_in_folder('gw')
ya = YamboAnalyser('gw')</source>
The object ya
contains all the results written in the output. We can plot any output variable. In yambopy we provide a function to plot the band structure along a given path. The BN band structure is shown below. The GW correction opens the LDA band gap as expected.
Approximations of the dielectric function (COHSEX, PPA, Real axis integration)
We can use yambopy to examine different run levels. For instance, the approximations used to obtain the screening are the: (i) static screening or COHSEX, plasmon-pole approximations (PPA), or real axis integration. We have set the same parameters for each run, just changing the variable name for the number of bands and the cut-off of the screening.
<source lang="bash">COHSEX BndsRnXs = 24 bands NGsBlkXs = 3 Ry PPA BndsRnXp = 24 bands NGsBlkXp = 3 Ry RA BndsRnXd = 24 bands NGsBlkXd = 3 Ry</source> We have set the converged parameters and the function works by running:
<source lang="bash">python gw_conv_bn.py -x</source> We plot the band structure using the analyzer explained above.
<source lang="bash">python gw_conv_bn.py -xp</source> The PPA and the RA results are basically on top of each other. On the contrary, the COHSEX (static screening) makes a poor job, overestimating the bandgap correction.
Solvers (Newton, Secant, Green's function)
The solvers to find the QP correction from the self-energy can also be tested. We have included the Newton and the secant method. In the resulting band structures, we do not appreciate big differences. In any case it is worthy to test during the convergence procedure.