Auxiliary second-order Green’s function perturbation theory (AGF2)#
Modules: pyscf.agf2
Introduction#
Auxiliary second-order Green’s function perturbation theory (AGF2)
[42, 43] is an iterative,
Basic usage of AGF2 as given in examples/agf2/00-simple_agf2.py, as
#!/usr/bin/env python
#
# Author: Oliver J. Backhouse <olbackhouse@gmail.com>
# George H. Booth <george.booth@kcl.ac.uk>
#
'''
A simple example of restricted AGF2. AGF2 will compute correlation energies, one-particle
properties and charged excitations / energy levels via an iterated, renormalized perturbation
theory.
Default AGF2 corresponds to the AGF2(1,0) method outlined in the papers:
- O. J. Backhouse, M. Nusspickel and G. H. Booth, J. Chem. Theory Comput., 16, 1090 (2020).
- O. J. Backhouse and G. H. Booth, J. Chem. Theory Comput., 16, 6294 (2020).
'''
from pyscf import gto, scf, agf2
mol = gto.M(atom='O 0 0 0; H 0 0 1; H 0 1 0', basis='cc-pvdz')
mf = scf.RHF(mol)
mf.conv_tol = 1e-12
mf.run()
# Run an AGF2 calculation
gf2 = agf2.AGF2(mf)
gf2.conv_tol = 1e-7
gf2.run(verbose=4)
# Print the first 3 ionization potentials
# Note that there is no additional cost to write out larger numbers of excitations.
gf2.ipagf2(nroots=3)
# Print the first 3 electron affinities
gf2.eaagf2(nroots=3)
Theory#
In AGF2, one iteratively solves the Dyson equation
using the self-energy correct through second-order perturbation theory, which can be written as
In AGF2, the first two spectral moments of the MP2 self-energy,
are used as a conserved quantity in order to coarse-grain this frequency
dependence as a set of compressed and renormalized
where
Additionally, once projected into the physical space, the QMOs define a
correlated (non-idempotent) density matrix, permitting a further
self-consistency in the Fock matrix in a similar fashion to a Hartree–Fock
calculation.
The correct number of electrons remain in the physical space throughout this
process via optimisation of a chemical potential
Photoemission spectra#
The compression of the effective dynamics performed in AGF2 permits the calculation of the full spectrum of charged excitations, as no additional computational effort is required for this (in contrast to iterative eigensolvers of effective hamiltonians), and the computational effort is therefore independent of the number of excitations requested. An example of a calculation which provides the full spectral function can be found in examples/agf2/03-photoemission_spectra.py:
#!/usr/bin/env python
#
# Author: Oliver J. Backhouse <olbackhouse@gmail.com>
# George H. Booth <george.booth@kcl.ac.uk>
#
'''
Use a converged AGF2 calculation to build the full photoemission (quasiparticle) spectrum
Default AGF2 corresponds to the AGF2(1,0) method outlined in the papers:
- O. J. Backhouse, M. Nusspickel and G. H. Booth, J. Chem. Theory Comput., 16, 1090 (2020).
- O. J. Backhouse and G. H. Booth, J. Chem. Theory Comput., 16, 6294 (2020).
'''
import numpy
from pyscf import gto, scf, agf2
mol = gto.M(atom='O 0 0 0; H 0 0 1; H 0 1 0', basis='cc-pvdz')
mf = scf.RHF(mol)
mf.conv_tol = 1e-12
mf.run()
# Run an AGF2 calculation
gf2 = agf2.AGF2(mf)
gf2.conv_tol = 1e-7
gf2.run()
# Access the GreensFunction object and compute the spectrum
gf = gf2.gf
grid = numpy.linspace(-10.0, 10.0, 1000)
eta = 0.02
spectrum = gf.real_freq_spectrum(grid, eta=eta)
# The array `spectrum` is now a length nfreq array of the
# spectral function -1/pi * Tr[Im[G(\omega + i\eta)]].
# Note that for UHF AGF2 calculations, the individual gf
# elements can be passed to real_freq_spectrum in order
# to obtain the spin-resolved spectra.
# We can also build the self-energy on the real-frequency axis
# by accessing the renormalized auxiliary states:
e = gf2.se.energy - gf2.se.chempot
v = gf2.se.coupling
denom = grid[:,None] - (e + numpy.sign(e)*eta*1.0j)[None]
se = numpy.einsum('xk,yk,wk->wxy', v, v.conj(), 1./denom)
Additionally, the Dyson orbitals corresponding to individual excitations are accessible directly from the method, which can be seen in examples/agf2/10-dyson_orbitals.py.
Restart a calculation#
The contents of an AGF2 calculation can be dumped to the disk via the familiar
PySCF chkfile
utilities.
By default, an AGF2 method will inherit the chkfile
attribute of the
underlying Hartree–Fock reference object.
An example of restoring an AGF2 calculation from a checkpoint file can be found
in examples/agf2/04-restart.py:
#!/usr/bin/env python
#
# Author: Oliver J. Backhouse <olbackhouse@gmail.com>
# George H. Booth <george.booth@kcl.ac.uk>
#
'''
An example of restarting an AGF2 calculation.
The agf2.chkfile module provides similar functionality to the existing
chkfile utilities in pyscf, but prevents failure during MPI runs.
'''
import numpy
from pyscf import gto, scf, agf2, lib
mol = gto.M(atom='O 0 0 0; H 0 0 1; H 0 1 0', basis='cc-pvdz', verbose=5)
mf = scf.RHF(mol)
mf.conv_tol = 1e-12
# if we are using MPI, we only want pyscf to save a chkfile on the root process:
if agf2.mpi_helper.rank == 0:
mf.chkfile = 'agf2.chk'
mf.run()
# Run an AGF2 calculation:
gf2 = agf2.AGF2(mf)
gf2.conv_tol = 1e-7
gf2.max_cycle = 3
gf2.run()
# Restore the Mole and SCF first
mol = agf2.chkfile.load_mol('agf2.chk')
mf = scf.RHF(mol)
mf.__dict__.update(agf2.chkfile.load('agf2.chk', 'scf'))
# Restore the AGF2 calculation
gf2a = agf2.AGF2(mf)
gf2a.__dict__.update(agf2.chkfile.load_agf2('agf2.chk')[1])
gf2a.max_cycle = 50
gf2a.run()
Parallelisation#
The AGF2 module supports both MPI an OpenMP parallelisation in an aim to provide
a scalable method applicable to interesting problems in quantum chemistry.
Furthermore, the dominant scaling step is embarrassingly parallel.
Distribution of computational load is handled by the optional dependency
mpi4py
, and will run without MPI using OpenMP threads if an installation
cannot be found.