Home / The code

The code

QEpy’s Python layer, Fortran bridge, and Quantum ESPRESSO integration: how the pieces fit together and what each module provides.

Architecture overview

QEpy extends Quantum ESPRESSO with minimal changes to core routines (notably the SCF driver in qepy_electrons.f90). Python bindings are generated with f90wrap. The design centers on three layers:

EMBED embed_base
iterative flags, TDDFT state, SCF control hooks
PWSCF qepy_pwscf
qepy_electrons, ions, FFT grids

Input can come from a QE input file, a QEInput dictionary, or ASE Atoms. Output is accessible via Python arrays (with optional MPI gather to rank 0) or through driver.get_output() for the QE text log.

Units: QEpy uses atomic units: Bohr for lengths, Rydberg for energies. ASE integration converts automatically; direct Driver usage requires care.

qepy.driver: The Driver

The primary class for programmatic DFT. Construct with a QE input file and optional MPI communicator:

from qepy import Driver
from mpi4py import MPI

driver = Driver(
    inputfile='qe.in',
    comm=MPI.COMM_WORLD,   # or None for serial
    iterative=False,       # True → one SCF step at a time
    task='scf',            # 'scf' | 'nscf' | 'optical' | 'tddfpt_davidson'
    ldescf=True,           # print SCF correction each cycle
    logfile=None,          # None=screen, str=file, True=temp file
)

MPI communicator (comm)

The comm argument accepts an mpi4py communicator or None. Internally, QEpy converts mpi4py communicators to Fortran handles via comm.py2f() and passes them to QE’s my_world_comm (see Driver.comm and driver_initialize).

Import order matters: import qepy must come before from mpi4py import MPI (qepy/__init__.py handles this when you import from qepy first).

SCF & convergence

MethodDescription
driver.scf()Run full SCF to convergence (or use iterative mode). Calls qepy_electrons in Fortran.
driver.diagonalize()One diagonalization step (iterative mode).
driver.mix()One density-mixing step.
driver.check_convergence()Whether SCF has converged.
driver.get_scf_error()Current SCF residual.
driver.get_scf_steps()Number of SCF iterations completed.
driver.end_scf()Finalize after iterative loop.
driver.non_scf()NSCF calculation from saved charge density.
driver.stop()Clean shutdown and release QE workspace.
driver.save()Save wavefunctions, density, etc. to disk.
driver.restart()Restart with different QE program or options.
driver.electrons()Direct call to the Fortran qepy_electrons routine.

Density, potentials & XC

MethodDescription
get_density() / set_density()Total electron density on real-space grid.
get_core_density()Non-linear core correction density.
set_external_potential()Inject external potential (exttype, optional energy correction); uses embed%extpot.
get_hartree(), get_exchange_correlation()Individual energy components.
get_hartree_potential(), get_exchange_correlation_potential()Potential components on the grid.
get_effective_potential()Total effective single-particle potential.
update_exchange_correlation()Change XC functional (incl. libxc / DFTpy).
get_elf(), get_rdg()ELF and reduced density gradient.
get_local_pp()Local pseudopotential on the grid.

Structure, forces & stress

MethodDescription
get_energy() / calc_energy()Total energy (Ry).
get_forces()Forces on atoms (Ry/Bohr); optional component filter.
get_stress()Stress tensor (Ry/Bohr³); see also qepy_stress.f90.
update_ions()Update atomic positions and/or lattice.
get_ions_positions(), get_ions_lattice()Current ionic geometry.
get_ase_atoms()Export structure as ASE Atoms.

Electronic structure

MethodDescription
get_wave_function()Kohn–Sham orbitals for a band/k-point.
get_eigenvalues(), get_occupation_numbers()Band energies and occupations.
get_fermi_level()Fermi energy.
get_ibz_k_points(), get_k_point_weights()K-point mesh information.
get_number_of_bands(), get_number_of_spins()System dimensions.

TDDFT & TDDFPT

MethodDescription
task='optical'Real-time TDDFT via tddft_initialize (requires tddft=yes build with ce-tddft).
propagate()Advance real-time TDDFT by one time step.
get_dipole_tddft()Dipole moment during propagation.
task='tddfpt_davidson'Linear-response TDDFPT via tddfpt_initialize and qepy_lr_dav_main.f90.
tddfpt_davidson_scf()Davidson diag. step for TDDFPT.

DFTpy & grid utilities

qepy.calculator: QEpyCalculator

ASE-compatible calculator wrapping the Driver. Useful for geometry optimization, MD, and workflows that already use ASE:

from qepy.calculator import QEpyCalculator

calc = QEpyCalculator(inputfile='qe.in', comm=comm)
atoms.calc = calc
energy = atoms.get_potential_energy()
forces = atoms.get_forces()

Key methods: calculate(), get_potential_energy(), get_forces(), get_stress(). Units follow ASE conventions (eV, Å) rather than the Driver’s Ry/Bohr.

qepy.io: QEInput & output handling

Programmatic construction and parsing of QE input decks:

from qepy.io import QEInput

qeinput = QEInput()
qeinput.set('control', 'calculation', 'scf')
qeinput.set('system', 'ecutwfc', 40)
qeinput.write('generated.in')

# Or pass qe_options dict directly to Driver:
driver = Driver(qe_options={'system': {'ecutwfc': 40}}, atoms=atoms)

The I/O module also supports reading QE output via QEOutput (read_qe_input, get_output) for post-processing workflows (see pp/qepy_parse_output.ipynb).

python -m qepy: Command-line interface

The CLI module (cui/main.py) dispatches to wrapped QE executables and QEpy tools:

Under MPI, launch the Python module with your site’s MPI runner; the Fortran layer inherits the world communicator from qepy_pwscf.