# Cheat sheet#

Here we provide quick reference calculation for some of the most common X-ray spectrum calculations, considering XPS/IE, XAS, and (non-resonant) XES of water, as well as a typical workflow.

## IEs and XPS#

### Koopmans’ theorem#

While it is not recommended for any production calculations, estimates of ionization energies can be obtained from Koopmans’ theorem:

import numpy as np
import veloxchem as vlx

# for vlx
silent_ostream = vlx.OutputStream(None)
from mpi4py import MPI

comm = MPI.COMM_WORLD
# au to eV conversion factor
au2ev = 27.211386

water_mol_str = """
O       0.0000000000     0.0000000000     0.1178336003
H      -0.7595754146    -0.0000000000    -0.4713344012
H       0.7595754146     0.0000000000    -0.4713344012
"""

# Create veloxchem mol and basis objects

# Perform SCF calculation
scf_gs = vlx.ScfRestrictedDriver(comm, ostream=silent_ostream)
scf_results = scf_gs.compute(mol_vlx, bas_vlx)

# Extract orbital energies
orbital_energies = scf_results["E_alpha"]

print("1s E from Koopmans' theorem:", np.around(au2ev * orbital_energies, 2), "eV")

1s E from Koopmans' theorem: -559.5 eV


### $$\Delta$$-methods#

Substantially improved ionization energies are obtained using $$\Delta$$-methods, where the energy difference of the ground state and core-hole state is used to estimate the IE:

Note

pyscf version - to be changed

import copy

import numpy as np
from pyscf import gto, mp, scf

water_xyz = """
O       0.0000000000     0.0000000000     0.1178336003
H      -0.7595754146    -0.0000000000    -0.4713344012
H       0.7595754146     0.0000000000    -0.4713344012
"""

# Create pyscf mol object
mol = gto.Mole()
mol.atom = water_xyz
mol.basis = "6-31G"
mol.build()

# Perform unrestricted SCF calculation
scf_gs = scf.UHF(mol)
scf_gs.kernel()

# Copy molecular orbitals and occupations
mo0 = copy.deepcopy(scf_gs.mo_coeff)
occ0 = copy.deepcopy(scf_gs.mo_occ)

# Create 1s core-hole by setting alpha_0 population to zero
occ0 = 0.0

# Perform unrestricted SCF calculation with MOM constraint
scf_ion = scf.UHF(mol)
scf_ion.kernel()

# Run MP2 on neutral and core-hole state
mp_res = mp.MP2(scf_gs).run()
mp_ion = mp.MP2(scf_ion).run()

# IE from energy difference
print(
"HF ionization energy:",
np.around(au2ev * (scf_ion.energy_tot() - scf_gs.energy_tot()), 2),
"eV",
)
print(
"MP2 ionzation energy:", np.around(au2ev * (mp_ion.e_tot - mp_res.e_tot), 2), "eV"
)


## XAS#

Absorption spectra can be calculated using CVS-ADC:

import gator
import matplotlib.pyplot as plt

water_mol_str = """
O       0.0000000000     0.0000000000     0.1178336003
H      -0.7595754146    -0.0000000000    -0.4713344012
H       0.7595754146     0.0000000000    -0.4713344012
"""

# Construct structure and basis objects
struct = gator.get_molecule(water_mol_str)
basis = gator.get_molecular_basis(struct, "6-31G")

# Perform SCF calculation
scf_gs = gator.run_scf(struct, basis)

# Calculate the 6 lowest eigenstates with CVS restriction to MO #1 (oxygen 1s)
struct, basis, scf_gs, method="cvs-adc2x", singlets=4, core_orbitals=1
)

# Print information on eigenstates

plt.figure(figsize=(6, 5))
# Convolute using functionalities available in gator and adcc
plt.show()

+--------------------------------------------------------------+
| cvs-adc2x                               singlet ,  converged |
+--------------------------------------------------------------+
|  #        excitation energy     osc str    |v1|^2    |v2|^2  |
|          (au)           (eV)                                 |
|  0      19.71638      536.5099   0.0178       0.8       0.2  |
|  1       19.7967      538.6956   0.0373    0.8087    0.1913  |
|  2      20.49351      557.6567   0.0099    0.7858    0.2142  |
|  3      20.50482      557.9647   0.1016    0.8441    0.1559  |
+--------------------------------------------------------------+ ## XES#

The non-resonant X-ray emission spectrum can be calculated with a two-step approach using ADC:

Note

pyscf version - to be changed

import copy

import matplotlib.pyplot as plt
import numpy as np
from pyscf import gto, mp, scf

water_xyz = """
O       0.0000000000     0.0000000000     0.1178336003
H      -0.7595754146    -0.0000000000    -0.4713344012
H       0.7595754146     0.0000000000    -0.4713344012
"""

# Create pyscf mol object
mol = gto.Mole()
mol.atom = water_xyz
mol.basis = "6-31G"
mol.build()

# Perform unrestricted SCF calculation
scf_res = scf.UHF(mol)
scf_res.kernel()

# Copy molecular orbitals
mo0 = copy.deepcopy(scf_res.mo_coeff)
occ0 = copy.deepcopy(scf_res.mo_occ)

# Create 1s core-hole by setting alpha_0 population to zero
occ0 = 0.0

# Perform unrestricted SCF calculation with MOM constraint
scf_ion = scf.UHF(mol)
scf_ion.kernel()