/Perturbo_Tutorials

Tutorials for the Perturbo workshop 2020

PERTURBO Workshop Practice Handout

[TOC]

Introduction

This handout covers the four practice sessions in the PERTURBO workshop on Oct. 15, 2020. The first session is about how to install PERTURBO; the second is about how to prepare data for PERTURBO from Quantum Espresso (QE) and Wannier90 (W90); the third is to demonstrate how to run temperature-dependent transport using PERTURBO; the last is to run carrier dynamics using PERTURBO.

Practice 1: Perturbo Download and Installation

PERTURBO uses a few subroutines from QE and reads a few output files from W90. Therefore, please make sure your QE and W90 compiled sucessfully on your local cluster or laptop. In addition, PERTURBO uses the HDF5 format to store data, so please make sure you have the HDF5 library installed.

⚠️ PERTURBO requires the HDF5 library.

How to install Quantum Espresso?

The current release of PERTURBO supports QE6.5 and 6.4. In the following, we will use QE6.5. A quick way to install QE is as follows:

>> wget https://github.com/QEF/q-e/archive/qe-6.5.tar.gz
>> tar xvzf qe-6.5.tar.gz
>> cd q-e-qe-6.5
>> ./configure
>> make pw ph pp

More details on how to install QE please refer to the QE website.

⚠️ PERTURBO supports QE6.4 and 6.5.

How to install Wannier90?

Once QE is installed, it is easy to install W90 by the following commands:

>> cd q-e-qe-6.5
>> wget https://github.com/wannier-developers/wannier90/archive/v3.0.0.tar.gz
>> tar xvzf v3.0.0.tar.gz
>> cd wannier90-3.0.0
>> cp ./config/make.inc.xxx ./make.inc
>> make

More details on how to install W90 please refer to the W90 website.

How to install PERTURBO?

To get the source codes of PERTURBO, please click "Download" and fill the questionnaire here. Once QE is installed, it is easy to install PERTURBO by the following commands:

>> cd q-e-qe-6.5
>> git clone https://github.com/perturbo-code/perturbo.git
>> cd perturbo
>> vi make.sys

Modify the two flags FFLAGS and LDFLAGS for your compilers, for example,

<for intel compiler>
......
FFLAGS + = -qopenmp -cpp
LDFLAGS += -qopenmp
......

or

<for gfortran compiler>
......
FFLAGS + = -fopenmp -x f95-cpp-input
LDFLAGS += -fopenmp
......

Modify the two flags IFLAGS and HDF5LIB for your HDF5 library,

......
IFLAGS + = -I<path-to-your-hdf5-include>
HDF5_LIB += -L<path-to-your-hdf5-lib> -lhdf5 -lhdf5_fortran
......

After modifying the above flags in the make.sys file, simply type make to install PERTURBO. Two executables (qe2pert.x and perturbo.x) will show up in the perturbo/bin directory

Recommended directory hierarchy

Before running PERTURBO, we need to obtain the ground state of a system of interest, the associated Wannier functions, and the phonon deformation potentials. Therefore, there will be many input files and output data for QE and W90. Here we recommend a directory hierarchy for users to organize those input files and output data. There are three main directories, pw-ph-wan, qe2pert and perturbo. For example, if we are interested in silicon, we create the following directory hierarchy:

  • 📂 silicon
    • 📂 pw-ph-wan
      • 📁 scf: self-consistent calculations using QE
      • 📁 nscf: non-self-consistent calculations using QE
      • 📁 phonon: deformation potential computed using QE
      • 📁 wann: maximally localized Wannier functions obtained using W90
    • 📁 qe2pert: electron-phonon matrix elements in Wannier basis
    • 📂 perturbo
      • 📁 pert-band: interpolated band structures using perturbo.x
      • 📁 pert-trans: transport calculations using perturbo.x
      • 📁 pert-
      • more other calculation modes please see here.

Utilities provided on the PERTURBO website

Practice 2: Preliminary Steps

Now we have perturbo compiled and installed successfully. To run PERTURBO calculations, we have to prepare the electron-phonon (e-ph) matrix elements in Wannier basis and then store the related data in a HDF5 file, called prefix_.h5, generated by qe2pert.x.

In the following, we use silicon without spin-orbit coupling (SOC) to demonstrate how to use qe2pert.x and how to compute the e-ph matrix elements along a high symmetry $\mathbf{k}$-path. After the example, we will point out a few points of how to use PERTURBO (without going into many detials) for materials with SOC and polar materials.

Preparation for PERTURBO: silicon as an example

The following are the main steps to prepare prefix_epwan.h5:

  1. SCF calculation using pw.x
  2. Phonon calculation using ph.x
  3. NSCF calculation using pw.x
  4. Wannier functions using wannier90.x
  5. e-ph matrix elements using qe2pert.x

❗ Please refer to the instructions of how to perform the above steps.

Here we mention only a point that users need to pay attention to. In the phonon input file, ph-ref.in, which we have prepared for the phonon calculation in the tutorial, for example,

&inputph
  verbosity='debug'
  tr2_ph=1.0d-17
  prefix='si'
  ldisp=.true.
  epsil=.true.
  lqdir=.true.
  outdir='./tmp'
  fildyn='si.dyn.xml'
  fildvscf='dvscf'
  nq1=8, nq2=8, nq3=8,
  start_q=1, last_q=1
/

where the variable fildyn must have an extension of .xml and the $\mathbf{q}$-grid (nq1, nq2, and nq3) must be commensurate with the $\mathbf{k}$-grid used in the NSCF calculation. For example, a $\mathbf{q}$-grid of 8x8x8 is commensurate with a $\mathbf{k}$-grid of 8x8x8 or 16x16x16, but not with a $\mathbf{k}$-grid of 10x10x10.

PERTURBO for computing e-ph matrix elements: silicon as an example

We will use the HDF5 file si_epwan.h5 (downlaod it here).

In the PERTURBO calculation mode 'ephmat', the e-ph matrix elements $|g_{\mu}(\mathbf{k},\mathbf{q})|$ at crystal momentum at $\mathbf{k}$ and $\mathbf{q}$ for a phonon mode $\mu$ are computed using the following formula:

$|g_{\mu}(\mathbf{k},\mathbf{q})|=\sqrt{\sum_{mn}|g_{\mu}(\mathbf{k},\mathbf{q})|^2/N_{b}}$

where $m$ and $n$ are the band indices of interest and $N_{b}$ is the number of bands taken into consideration.

Here is the example of the perturbo input file for the calculation mode 'ephmat', pert.in (the example files can be downloaded here):

&perturbo
 prefix = 'si'
 calc_mode = 'ephmat'
 fklist = 'eph.kpt'
 fqlist = 'eph.qpt'
 
 band_min = 2
 band_max = 4
 
 phfreq_cutoff = 1 ! meV

where fklist is the file containing the list of $\mathbf{k}$-points, fqlist is the file containing the list of $\mathbf{q}$-points, and phfreq_cutoff is the energy below which the phonon modes will not be not computed.

To run the calculation, we type

>> mpirun -n 1 [perturbo-path]/bin/perturbo.x -npools 1 -i pert.in > pert.out

It gives a file called si.ephmat, which contains the $\mathbf{k}$- and $\mathbf{q}$-point coordinate for plotting, phonon energy, deformation energy, and the e-ph matrix elements.

Spin-orbit coupling: silicon as an example

PERTURBO supports both collinear and noncollinear calculations as well as SOC and fully-relativistic pseudopotentials.

Here we use silicon with SOC as an example (please refer to the example on the PERTURBO website). In the following, we just point out the difference of the input files for qe2pert.x and perturbo.x between the two cases: silicon with and without SOC.

If one uses 16 bands in the NSCF and Wannierization calculations for silicon without SOC, then one should doubles the number of bands for silicon with SOC. For example, for silicon with SOC, the input file for qe2pert.x:

! silicon with SOC
&qe2pert
 prefix='si'
 outdir='./tmp'
 phdir='../pw-ph-wann/phonon/References/save'
 nk1=8, nk2=8, nk3=8
 dft_band_min = 1
 dft_band_max = 32
 num_wann = 16
 lwannier=.true.
/

compared to the case of silicon without SOC:

! silicon without SOC
&qe2pert
 prefix='si'
 outdir='./tmp'
 phdir='../pw-ph-wann/phonon/References/save'
 nk1=8, nk2=8, nk3=8
 dft_band_min = 1
 dft_band_max = 16
 num_wann = 8
 lwannier=.true.
/

Note the difference of dft_band_min, dft_band_max, and num_wann between the two input files.

For the input files for perturbo.x, we need to modify the band-related variables . For example, for silicon with SOC, the input file:

! silicon with SOC
&perturbo
 ...
 band_min = 3
 band_max = 8
 ...
/

compared to

! silicon with SOC
&perturbo
 ...
 band_min = 2
 band_max = 4
 ...
/

Polar materials: GaAs as an example

PERTURBO also supports polar materilas. The example of GaAs can be found on the website (here). One additional point we would like to point out is that in the phonon calculation, the variable epsil needs to be set to .true. for polar materials.

Practice 3: Charge Transport Calculation

Here we look at the temperature-dependent mobility of GaAs. We start from the qe2pert-generated gaas_epwan.h5 file, which can be downloaded here.

Python script for generating input files

To get input files for PERTURBO, we provide a python script generate_input.py in the perturbo/utils directory.

To see what options the python script provides, one can type

>> [perturbo-path]/utils/generate_input.py --help

To generate an input file for a calculation mode, one can use

>> [perturbo-path]/utils/generate_input.py --calc_mode <calc_mode>
or 
>> [perturbo-path]/utils/generate_input.py -c <calc_mode>

where <calc_mode> is the calculation mode provided in PERTURBO (see the calculation mode options here). The python script generates a file pert.in for PERTURBO calculations.

For example, to get the input file for the calculation mode 'bands' for perturbo.x, one can type

>> [perturbo-path]/utils/generate_input.py -c bands --prefix=gaas -i pert-bands.in

where the option --prefix=gaas modifies the variable prefix in the input file. The generated input file is shown below:

! This input file for PERTURBO was generated by generate_input.py script

&perturbo
! ***Mandatory parameters***
 calc_mode           = 'bands'
 prefix              = 'gaas'
 fklist              = 'gaas.kpt'
/

Here we modified the content of the fklist from 'prefix_tet.kpt' to 'gaas.kpt'.

We need to prepare the 'gaas.kpt' file, which contains the $\mathbf{k}$-path for the electronic band structure of interest. There are two ways to prepare the file: (1) provide all the $\mathbf{k}$-points along the path; (2) provide only the high symmetric $\mathbf{k}$-points. For example, in this GaAs case, we prepare in the file 'gaas.kpt':

3
0.5 0.5 0.5  50  !L
0.0 0.0 0.0  50  !G
0.5 0.0 0.0   1  !X

The first number is the number of lines after the first line. The first to third column means the coordinates of the $\mathbf{k}$-points in crystal coordinates. The forth column means the number of $\mathbf{k}$-points from the current one to the next one.

We are ready to run the band structure calculation. We type

>> [perturbo-path]/bin/perturbo.x -i pert-bands.in

The band structure is stored in a file called 'gaas.bands', from which we can use gnuplot to plot the band structure. For example,

>> gnuplot
>> plot "gaas.bands" u 1:5 w l lw 2

Transport calculation setup

To do the transport calculation, we need to perform a setup step, in which we select a set of $\mathbf{k}$-points involved in the transport and the correponding chemical potential for a given carrier concentration.

To get the input file for the setup, we type

>> [perturbo-path]/utils/generate_input.py -c setup --prefix=gaas -i pert-setup.in

We obtain a input file like the one shown below:

! This input file for PERTURBO was generated by generate_input.py script

&perturbo
! ***Mandatory parameters***
 calc_mode           = 'setup'
 prefix              = 'gaas'
 boltz_kdim(1)       = 160
 boltz_kdim(2)       = 160
 boltz_kdim(3)       = 160
 ftemper             = 'gaas.temper'

 band_min = 5
 band_max = 5

 boltz_emin = 6.0
 boltz_emax = 6.3

! ***Optional parameters***
! band_min           = 1
! band_max           = 9999999
! boltz_emin         = -9999.0         ! eV
! boltz_emax         = 9999.0          ! eV
! hole               = .false.
/

Note that we modified the file for our system.

We need to prepare a file 'gaas.temper', which contains the information of temperature (1st column; unit: K), chemical potential (2nd column; unit: eV) and carrier concentration (3rd column; unit: cm$^{-3}$):

5 T
150   6.0   1.0E+16
200   6.0   1.0E+16
250   6.0   1.0E+16
300   6.0   1.0E+16
350   6.0   1.0E+16

In the first line, the first number means how many conditions to compute; the second number is a logical flag, if it is T, then it computes the corresponding chemical potential for the given carrier concentration (the second column will be overwrite with the computed one), while if it is F, then it will use the chemical potential provided in this file for transport calculations (the third column is then not used).

We are ready to run the setup calculation:

>> export OMP_NUM_THREADS=4
>> mpirun -np 4 [perturbo-path]/perturbo.x -npools 4 -i pert-setup.in

We obtain the $\mathbf{k}$-points that are involved in the transport in the file 'gaas_tet.kpt'. The computed chemical potentials and carrier concentrations are stored in a file called 'gaas.doping'. The file 'gaas.temper' is updated

Relaxation time approximation for carrier mobility

To get the input file for transport calculation, we type

>> [perturbo-path]/utils/generate_input.py -c trans --prefix=gaas -i pert-trans.in

We obtain a input file named pert-trans.in, and we edit the parameters to be consistent with the setup calculations (one can also modify the input file for the setup calculation):

&perturbo
! ***Mandatory parameters***
 calc_mode           = 'trans'
 prefix              = 'gaas'
 boltz_kdim(1)       = 160
 boltz_kdim(2)       = 160
 boltz_kdim(3)       = 160
 ftemper             = 'gaas.temper'

 band_min = 5
 band_max = 5

 boltz_emin = 6.0
 boltz_emax = 6.3

 boltz_nstep = 1 ! RTA, only compute the initial step 
 tmp_dir = './tmp'
 debug=.true.

! ***Optional parameters***
! boltz_qdim(1)      = boltz_kdim(1)
! boltz_qdim(2)      = boltz_kdim(2)
! boltz_qdim(3)      = boltz_kdim(3)
! band_min           = 1
! band_max           = 9999999
! boltz_emin         = -9999.0         ! eV
! boltz_emax         = 9999.0          ! eV
! delta_smear        = 10.0            ! meV
! phfreq_cutoff      = 1.0             ! meV
! boltz_nstep        = 50
! boltz_de           = 1.0             ! meV
! trans_thr          = 0.002
! hole               = .false.
! load_scatter_eph   = .false.
! tmp_dir            = './tmp'
/

In the debug mode (debug=.true.), the code outputs the computed scattering rates.

Then we type

>> export OMP_NUM_THREADS=4
>> mpirun -np 4 <perturbo-path>/perturbo.x -npools 4 -i pert-trans.in

to compute and store e-ph matrix elements in the HDF5 files in directory ./tmp, e.g., gaasephg2p1.h5. The e-ph matrix elements can be reused in the iterative approach (see below). The carrier mobility is stored in the file 'gaas.cond'.

Iterative approach for carrier mobility

We modify the input file for the previous transport calculation. Note that we can use the e-ph matrix elements obtained in the RTA by providing a flag load_scatter_eph in the input file:

&perturbo
! ***Mandatory parameters***
 calc_mode           = 'trans'
 prefix              = 'gaas'
 boltz_kdim(1)       = 160
 boltz_kdim(2)       = 160
 boltz_kdim(3)       = 160
 ftemper             = 'gaas.temper'

 band_min = 5
 band_max = 5

 boltz_emin = 6.0
 boltz_emax = 6.3

 boltz_nstep = 1 ! RTA, only compute the initial step 
 tmp_dir = './tmp'
 debug=.true.
 
 load_scatter_eph  = .true.


! ***Optional parameters***
! boltz_qdim(1)      = boltz_kdim(1)
! boltz_qdim(2)      = boltz_kdim(2)
! boltz_qdim(3)      = boltz_kdim(3)
! band_min           = 1
! band_max           = 9999999
! boltz_emin         = -9999.0         ! eV
! boltz_emax         = 9999.0          ! eV
! delta_smear        = 10.0            ! meV
! phfreq_cutoff      = 1.0             ! meV
! boltz_nstep        = 50
! boltz_de           = 1.0             ! meV
! trans_thr          = 0.002
! hole               = .false.
! tmp_dir            = './tmp'
/

In additiona, to obatin the Seebeck coefficients, we can use the calculation mode 'trans-pp' after the mode 'trans', and the results are outputed in file 'gaas.transcoef'.

Practice 4: Ultrafast Dynamics in the BTE framework

In this part, we will perform the ultrafast electron dynamics in Si including the electron-phonon interactions.

We assume that the qe2pert calculation is already performed and we have the si_epwan.h5 file. In order to obtain the time-dependent electron population, one needs to go though the following steps:

  1. calc_mode = setup
  2. calc_mode = dynamics-run
  3. calc_mode = dynamics-pp

Step 1: setup calculation

Obtain the input file using the Python script:

>> [perturbo-path]/utils/generate_input.py -c setup --prefix=si -i pert_setup.in

or from the website (click on setup and then copy the input file text), after that open a new file pert_setup.in and paste the input file text. Modify prefix = si and ftemper = 'si.ftemper'.

Here, for demonstration purposes, we use a relatively small $\mathbf{k}$-grid of 40$^3$ points. We select the 5$^{\mathrm{th}}$ and 6$^{\mathrm{th}}$ bands (first two conduction bands) and the energy window from 6.8 eV to 7.4 eV. The input file for the setup calculation mode:

&perturbo
! ***Mandatory parameters***
 calc_mode           = 'setup'
 prefix              = 'si'
 boltz_kdim(1)       = 40
 boltz_kdim(2)       = 40
 boltz_kdim(3)       = 40
 ftemper             = 'si.temper'


! ***Optional parameters***
 band_min           = 5
 band_max           = 6
 boltz_emin         = 6.8         ! eV
 boltz_emax         = 7.4         ! eV
! hole              = .false.
/

Create the si.ftemper file:

1 T
300.00   6.52   1.0E+18

Link the si_epwan.h5 file:

ln -s <epwan_directory>/si_epwan.h5 .

Run the calculation (in this example we use 5 OpenMP threads and 4 MPI tasks)

>> export OMP_NUM_THREADS=5
>> mpirun -np 4 <perturbo-path>/perturbo.x -npools 4 -i pert_setup.in

Step 2: dynamics-run calculation

Obtain the input file using the Python script:

>> [perturbo-path]/utils/generate_input.py -c dynamics-run --prefix=si -i dynamics_run.in

or from the website (click on dynamics-run and then copy the input file text), after that please open a new file pert_dynamics.in and paste the input file text. We select a Gaussian excitation at 7.0 eV with 40.0 meV smearing. The simulation will be performed for 100 steps with 1.0 fs time step. Modify the file in the following way:

&perturbo
! ***Mandatory parameters***
 calc_mode           = 'dynamics-run'
 prefix              = 'si'
 boltz_kdim(1)       = 40
 boltz_kdim(2)       = 40
 boltz_kdim(3)       = 40
 ftemper             = 'si.temper'
 boltz_nstep         = 100
 output_nstep        = 1
 time_step           = 1.0        ! fs
 boltz_init_dist     = 'gaussian'


! ***Optional parameters***
 solver             = 'euler'
 boltz_init_e0      = 7.0        ! eV
 boltz_init_smear   = 40.0       ! meV
 phfreq_cutoff      = 1.0        ! meV
 band_min           = 5
 band_max           = 6
 boltz_emin         = 6.8        ! eV
 boltz_emax         = 7.4        ! eV
/

Run the calculation

>> mpirun -np 4 [perturbo-path]/bin/perturbo.x -npools 4 -i pert_dynamics.in

In order to test the restart option, modify the following parameters in the input file pert_dynamics.in:

 boltz_nstep         = 20
 boltz_init_dist     = 'restart'

Run the calculation

>> mpirun -np 4 <perturbo-path>/perturbo.x -npools 4 -i pert_dynamics.in

You could open and analyze the si_cdyna.h5 file with HDFview or h5ls. The structure of the file is explained here.

Step 3: dynamics-pp calculation

In order to create the input file for the postprocessing mode, take the input file from the previous calculation (dynamics-run) and change dynamics-run to dynamics-pp.

Run the calculation

>> mpirun -np 4 <perturbo-path>/perturbo.x -npools 4 -i pert_dynamics.in

This calculation generates the si_popu.h5 and si_cdyna.dat output files. si_popu.h5 contains the time-dependent electron population (click here to see the structure of the file) and si_cdyna.dat contains the number of carriers per unit cell as a function of time.

The following is a python script to plot one electron population snapshot:

###!/usr/bin/env python3
"""
Plot the carrier population as a function of energy for one selected time.
The electron population and energy are read from the 'prefix'_popu.h5 HDF5 file generated by PERTURBO
after "calc_mode=dynamics_run" and "calc_mode=dynamics_pp" simulations.
"""
import h5py
import matplotlib.pyplot as plt

prefix='si'
snap_number=25

# load the HDF5 file
h5file = h5py.File(prefix+'_popu.h5', 'r')

# get the data
energy_ev = h5file['energy_grid_ev'][()]
population = h5file['energy_distribution']['popu_t'+str(snap_number)][()]
h5file.close()

# plot the data
plt.figure(figsize = (12,8))

plt.plot(energy_ev,population,marker='o',linestyle='', markersize=2.5)

plt.xlabel('Energy (eV)', fontsize = 20)
plt.ylabel('Electron population', fontsize = 20)
plt.xticks(fontsize= 18)
plt.yticks(fontsize= 18)
plt.savefig('snap.pdf')
#plt.show()

The following is a python script to plot the heatmap of carrier population as a function of energy for several times:

#!/usr/bin/env python3
"""
Plot the heatmap of carrier population as a function of energy for several times.
The electron population and energy are read from the 'prefix'_popu.h5 HDF5 file generated by PERTURBO
after "calc_mode=dynamics_run" and "calc_mode=dynamics_pp" simulations.
"""

import h5py, sys
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,
                               AutoMinorLocator)

#####################################################################################################
# Set common figure parameters
plotparams = {'figure.figsize': (12, 8),
              'axes.grid': False,
              'lines.linewidth': 2.5,
              'axes.linewidth': 1.1,
              'lines.markersize': 10,
              'xtick.bottom': True,
              'xtick.top': True,
              'xtick.direction': 'in',
              'xtick.minor.visible': True,
              'ytick.left': True,
              'ytick.right': True,
              'ytick.direction': 'in',
              'ytick.minor.visible': True,
              'figure.autolayout': False,
              'mathtext.fontset': 'dejavusans', # 'cm' 'stix'
              'mathtext.default' : 'it',
              'xtick.major.size': 4.5,
              'ytick.major.size': 4.5,
              'xtick.minor.size': 2.5,
              'ytick.minor.size': 2.5,
              'legend.handlelength': 3.0,
              'font.size': 20}

plt.rcParams.update(plotparams)
#####################################################################################################

# Prefix of the PERTURBO calculation, the same as in pert.in
prefix = 'si'

# Time step of the simulation, the same as in pert.in
tstep = 1.0

# The output_nstep parameter, the same as in pert.in
output_nstep = 1

# Time step for plotting
plot_step = 1


# Plot parameters
fig = plt.figure(figsize = (12,8))
ax1 = fig.add_subplot(1,1,1)
plt.subplots_adjust(top=0.90, bottom=0.15, left=0.15, right=0.9)


# Load the 'prefix'_popu.h5 HDF5 file
h5file = h5py.File('{}_popu.h5'.format(prefix), 'r')

# Get the times array
times = h5file['times_fs'][()][:-1]

# Get the energy grid
energy_ev = h5file['energy_grid_ev'][()]

# Determine the minimum and maximum times
time_min = min(times)
time_max = max(times)
times = times[ (time_min <= times) & (times <= time_max) ]

# Define the colormap for plots
cmap = plt.cm.coolwarm_r
color=cmap(np.linspace(0,1,(time_max-time_min+1)/tstep))

# Loop over time
for isnap in list(range(1,int(len(times)/output_nstep),plot_step)):
   # Get the population corresponding to isnap
   population = h5file['energy_distribution']['popu_t'+str(isnap)][()]

   # Plot the population with the color corresponding to isnap
   plt.plot(energy_ev,population,linestyle='-',color=color[isnap])

# Close the HDF5 file
h5file.close()


# Set up the colorbar
norm = mpl.colors.Normalize(vmin=time_min, vmax=time_max)
divider = make_axes_locatable(ax1)
cax = divider.append_axes("right", size="5%", pad=0.1)

cbar = plt.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),cax=cax,format='%i')
cbar.set_label(label='time (fs)', fontsize=plotparams['font.size']+5)

# Axes labels
ax1.set_xlabel('Energy (eV)',fontsize=plotparams['font.size']+5)
ax1.set_ylabel('Electron population',fontsize=plotparams['font.size']+5)
ax1.yaxis.set_major_formatter(FormatStrFormatter('%.1E'))

# Save the figure
fig.savefig('population.pdf')

#plt.show()

Conclusion

Here we have covered the basic workflow of how to run carrier transport and dynamics. In the future, we will include more features into PERTURBO, stay tuned! If any questions that we can answer, please send us emails (perturbo@caltech.edu).

Thank you very much!

PERTURBO team at Marco Bernardi Reserach Group, 2020/10/08