Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

X-ray spectroscopies

VeloxChem provides access to a range of X‑ray spectroscopies by combining density‑functional theory with response theory techniques that enable the description of core‑level excitations and their characteristic spectral signatures. These methods allow the simulation of X‑ray absorption, emission, and related core‑level properties, thereby enabling chemically intuitive interpretation of spectral features. For a comprehensive review of theoretical approaches to X‑ray spectroscopies, see Norman & Dreuw (2018).

The ESCA molecule, ethyl trifluoroacetate (CF₃–CO–O–CH₂–CH₃), became historically important in X‑ray and photoelectron spectroscopies because its C 1s photoelectron spectrum displays four well‑separated and chemically distinct carbon binding energies, spanning more than 8 eV—a uniquely clear demonstration of chemical shifts arising from different charge environments at individual atomic sites. This spectrum rapidly became the pedagogical showcase for ESCA (Electron Spectroscopy for Chemical Analysis) following Kai Siegbahn’s development of high‑resolution photoelectron spectroscopy in the 1960s, and it has since served as a benchmark for both experimental methodology and theoretical modeling of core‑level shifts. The molecule continues to be used in modern X‑ray and photoelectron studies as a canonical reference system to illustrate how core‑level binding energies encode local electronic structure and substituent effects, linking directly to the foundational ESCA work recognized in Siegbahn’s 1981 Nobel Prize.

Loading...

XPS

X-ray Photoelectron Spectroscopy (XPS) probes the binding energies of core electrons and yields element-specific, chemically sensitive spectra in which each peak reflects the local electronic environment of an individual atomic site. In VeloxChem, XPS binding energies are obtained through the ΔSCF approach: a ground-state SCF calculation is performed first, followed by a separate unrestricted SCF calculation for each core-hole state (i.e., one core electron is removed from the targeted atom). The binding energy for each site is then computed as the difference in total energies between the core-ionized and ground states, along with a correction for relativistic and relaxation effects. The XPSDriver automates this workflow—it iterates over all atoms of the chosen element, generates the corresponding core-hole reference states, and assembles the final spectrum.

Python script

import veloxchem as vlx

molecule = vlx.Molecule.read_xyz_string("""13
ESCA b3lyp/def2-svp optimized geometry
C              1.326024532622         0.471089167011        -1.154937296389
C              0.484399509715         0.908494386259         0.037569541020
C              0.270494167717        -0.188493907246         1.053914467110
O              0.701245126416        -1.308212251798         0.971080711541
C             -0.582260522270         0.210893702941         2.291730106998
F             -0.731967860619        -0.799813015071         3.135965340271
F             -1.800383044157         0.625073687043         1.897202571864
F              0.003899498844         1.231896946553         2.943599980006
H              1.453639490166         1.302028888463        -1.864264306255
H              0.853135331881        -0.368249103011        -1.686230702784
H              2.322713498820         0.134038471332        -0.833394707486
H              0.936346512410         1.764030447212         0.571699332428
H             -0.514670521097         1.267150587304        -0.270103071648""")

basis = vlx.MolecularBasis.read(molecule, "def2-svp")

scf_drv = vlx.ScfRestrictedDriver()
scf_drv.xcfun = "b3lyp"
scf_results = scf_drv.compute(molecule, basis)

xps_drv = vlx.XPSDriver()

xps_results_c = xps_drv.compute(molecule, basis, scf_drv, element='C')
<Figure size 800x500 with 2 Axes>

XPS spectra can also be calculated for several elements at a time:

# Compute XPS for C, O, and F at once
xps_multi = xps_drv.compute(molecule, basis, scf_drv, elements=['C', 'O', 'F'])

# Plot 1: Carbon with atom labels (default)
xps_drv.plot_spectrum(xps_multi, element='C', color='vlx',
                      broadening_value=1.0, show_atom_labels=True)
# Plot 2: Carbon color-coded by atom
xps_drv.plot_spectrum(xps_multi, element='C', color='cpk',
                      broadening_value=1.0, color_by_atom=True)

# Plot 3: Oxygen with atom labels
xps_drv.plot_spectrum(xps_multi, element='O', color='cpk',
                      broadening_value=1.0)

# Plot 4: Fluorine with atom labels
xps_drv.plot_spectrum(xps_multi, element='F', color='cpk',
                      broadening_value=1.0)

NEXAFS

NEXAFS (or XANES) spectra can be calculated with the CPP solver by choosing the range of frequencies to the near ionization edge of the element you wish to probe. In terms of choice of functional, the version of the CAM-B3LYP functional with 100% exchange in the asymptotic limit as introduced by Ekström & Norman (2006) has been shown in a comprehensive benchmark study to perform particularly well, see Fransson et al. (2021).

Python script

import veloxchem as vlx
import numpy as np

molecule = vlx.Molecule.read_xyz_string("""13
ESCA b3lyp/def2-svp optimized geometry
C              1.326024532622         0.471089167011        -1.154937296389
C              0.484399509715         0.908494386259         0.037569541020
C              0.270494167717        -0.188493907246         1.053914467110
O              0.701245126416        -1.308212251798         0.971080711541
C             -0.582260522270         0.210893702941         2.291730106998
F             -0.731967860619        -0.799813015071         3.135965340271
F             -1.800383044157         0.625073687043         1.897202571864
F              0.003899498844         1.231896946553         2.943599980006
H              1.453639490166         1.302028888463        -1.864264306255
H              0.853135331881        -0.368249103011        -1.686230702784
H              2.322713498820         0.134038471332        -0.833394707486
H              0.936346512410         1.764030447212         0.571699332428
H             -0.514670521097         1.267150587304        -0.270103071648""")

basis = vlx.MolecularBasis.read(molecule, "def2-svp")

scf_drv = vlx.ScfRestrictedDriver()
scf_drv.xcfun = "cam-b3lyp-100"
scf_results = scf_drv.compute(molecule, basis)

cpp_drv = vlx.ComplexResponse()
cpp_drv.frequencies = np.arange(10.1, 10.4, 0.0025)
cpp_drv.property = "absorption"

cpp_results = cpp_drv.compute(molecule, basis, scf_results)
<Figure size 800x500 with 1 Axes>

Text file

@jobs
task: response
@end

@method settings
xcfun: cam-b3lyp
basis: def2-svp
@end

@response
property: absorption (cpp)
# frequency region (and resolution)
frequencies: 10.1-10.4 (0.0025)
@end

@molecule
charge: 0
multiplicity: 1
xyz:  
...
@end

Please refer to the keyword list for a complete set of options.

RIXS

RIXS is a photon-in-photon-out technique which transfers the element- and site-selectivity of XAS to the valence-excited state manifold. The double differential scattering cross-section corresponding to the electronic inelastic process is described within the Kramers-Heisenberg-Dirac (KHD) formulation:

d2σ(ω,ω)dωdω=(reme)2ωωfnfεp^nnεp^0(ω+ω0ωn)+iΓn/22δ(ω+ωf0ω)\frac{\mathrm{d}^2\sigma(\omega, \omega')}{\mathrm{d}\omega\,\,\mathrm{d}\omega'} = \left(\frac{r_e}{m_e}\right)^2\frac{\omega'}{\omega}\sum_{f}\left| \sum_n \frac{\langle f | \boldsymbol{\varepsilon'}\cdot\mathbf{\hat{p}} | n \rangle\langle n | \boldsymbol{\varepsilon}\cdot\mathbf{\hat{p}} | 0 \rangle}{\hbar(\omega + \omega_0 - \omega_n) + i\Gamma_n/2} \right|^2\delta(\omega' + \omega_{f0} - \omega)

Here, ω\hbar\omega and ω\hbar\omega' are the incoming, respectively outgoing photon energies, 0|0\rangle is the electronic ground state, f|f\rangle is a final valence-excited state, n|n\rangle is an intermediate core-excited state and ω0\hbar\omega_0, ωf\hbar\omega_f, and ωn\hbar\omega_n are their respective energies. The constants rer_e and mem_e are the classical electron radius, respectively the electron mass, while ε\boldsymbol{\varepsilon} and ε\boldsymbol{\varepsilon'} are, respectively, the incoming and outgoing polarization vectors. Γn\Gamma_n is the full-width-at-half-maximum lifetime broadening of the core-excited intermediate state n|n\rangle.

Although computing RIXS scattering cross-sections formally requires quadratic response for the core-to-valence transition dipole moments, these second-order matrix elements may be approximated at first-order similarly as, e.g., for excited-state absorption. In this approach, the scattering cross-sections can be determined from two TDDFT calculations, one to obtain the valence-excited states and the other to obtain the core-excited states. The state-to-state transition density matrices are then computed using the linear-response (LR) eigenvectors. A detailed discussion of the theory, as well as a benchmark of the VeloxChem LR-TDDFT implementaion can be found in Vitols et al. (2025).

RIXS calculations can be performed using the RixsDriver, as shown below.

Python script

import veloxchem as vlx

molecule = vlx.Molecule.read_xyz_string("""13
ESCA b3lyp/def2-svp optimized geometry
C              1.326024532622         0.471089167011        -1.154937296389
C              0.484399509715         0.908494386259         0.037569541020
C              0.270494167717        -0.188493907246         1.053914467110
O              0.701245126416        -1.308212251798         0.971080711541
C             -0.582260522270         0.210893702941         2.291730106998
F             -0.731967860619        -0.799813015071         3.135965340271
F             -1.800383044157         0.625073687043         1.897202571864
F              0.003899498844         1.231896946553         2.943599980006
H              1.453639490166         1.302028888463        -1.864264306255
H              0.853135331881        -0.368249103011        -1.686230702784
H              2.322713498820         0.134038471332        -0.833394707486
H              0.936346512410         1.764030447212         0.571699332428
H             -0.514670521097         1.267150587304        -0.270103071648""")

basis = vlx.MolecularBasis.read(molecule, "def2-svp")

xcfun = "cam-b3lyp"

scf_drv = vlx.ScfRestrictedDriver()
scf_drv.xcfun = xcfun
scf_results = scf_drv.compute(molecule, basis)

rixs_drv = vlx.RixsDriver()
rixs_drv.nstates = 20   # number of final valence-excited states
rixs_drv.num_core_orbitals = 8   # number of core orbitals
rixs_drv.num_core_states = 10  # number of intermediate core-excited states

rixs_drv.photon_energy = 276 / vlx.hartree_in_ev()  # value of the incoming photon energy in a.u.

rixs_results = rixs_drv.compute(molecule, basis, scf_results)

Text file

@jobs
task: response
@end

@method settings
xcfun: cam-b3lyp
basis: def2-svp
@end

@response
property: rixs
photon_energy: 10.1428
nstates: 20
num_core_orbitals: 8
num_core_states: 10
@end

@molecule
charge: 0
multiplicity: 1
xyz:  
...
@end
References
  1. Norman, P., & Dreuw, A. (2018). Simulating X-ray Spectroscopies and Calculating Core-Excited States of Molecules. Chem. Rev., 118(15), 7208–7248. 10.1021/acs.chemrev.8b00156
  2. Brumboiu, I. E., & Fransson, T. (2022). Core–hole delocalization for modeling x-ray spectroscopies: A cautionary tale. J. Chem. Phys., 156(21). 10.1063/5.0088195
  3. Ekström, U., & Norman, P. (2006). X-ray absorption spectra from the resonant-convergent first-order polarization propagator approach. Phys. Rev. A, 74(4), 042722. 10.1103/PhysRevA.74.042722
  4. Fransson, T., Brumboiu, I. E., Vidal, M. L., Norman, P., Coriani, S., & Dreuw, A. (2021). XABOOM: An X-ray Absorption Benchmark of Organic Molecules Based on Carbon, Nitrogen, and Oxygen 1s → π* Transitions. J. Chem. Theory Comput., 17(3), 1618–1637. 10.1021/acs.jctc.0c01082
  5. Vitols, E., Vaz da Cruz, V., Fransson, T., & Brumboiu, I. E. (2025). Resonant Inelastic X-ray Scattering: How Well Does LR-TDDFT Perform? J. Phys. Chem. A, 129(38), 8783–8797. 10.1021/acs.jpca.5c04528