Choosing a periodic method: GDF, BIPOLE, and GPW / GAPW¶
A molecular calculation has exactly one way to build the Coulomb (and exchange) matrices. A periodic one has a choice, because the bare lattice sum of \(1/r\) over an infinite crystal diverges, and there is more than one good way to tame it. This page is the map: what the routes are, how to switch between them with a single keyword, and how to pick the right one.
See also
This is the hands-on companion to the reference page periodic-SCF methods, which derives why the lattice sum diverges and how each route fixes it (Ewald splitting, density fitting, FFT-Poisson on a grid). Read that page when you want the theory; read this one when you want to run something.
When you go to validate a route against an external program, see periodic JK routes & parity policy: each route is checked against a program from its own method family (GDF ↔ PySCF, BIPOLE ↔ CRYSTAL, GPW / GAPW ↔ CP2K / GPAW), and cross-family comparison is a trap.
One system, several routes¶
You select the route with the jk_method keyword on run_periodic_job.
The system, basis, and method stay the same, only the Coulomb engine
underneath changes:
import vibeqc as vq
# ... define `system` (a PeriodicSystem) and `basis` ...
# Production default for closed-shell RHF / RKS (Gamma or multi-k):
res = vq.run_periodic_job(system, basis, method="RKS", functional="pbe",
kpoints=[4, 4, 4], jk_method="gdf")
# BIPOLE: the Ewald J-split route (open shell, hybrids, CRYSTAL14 cross-validation):
res = vq.run_periodic_job(system, basis, method="RKS", functional="pbe",
kpoints=[4, 4, 4], jk_method="bipole")
# Plane-wave routes (run full SCF today; you opt in to a maturity warning):
res = vq.run_periodic_job(system, basis, method="RKS", functional="pbe",
jk_method="gpw") # or jk_method="gapw"
# Independent finite cyclic-cluster RHF/RKS (experimental):
res = vq.run_periodic_job(system, basis, method="RKS", functional="pbe0",
jk_method="aiccm2026dev-b",
aiccm_lattice_extension=[4, 4, 4],
aiccm_backend="rijcosx")
If you omit jk_method (or pass "auto"), vibe-qc chooses for you:
GDF for closed-shell RHF/RKS, BIPOLE for open-shell UHF/UKS. The
default is already a production-quality route; you reach for this page
when the default is not the one you want. (Open-shell GDF also ships and
is reachable with an explicit jk_method="gdf"; AUTO keeps BIPOLE as the
open-shell default by design.)
The routes¶
GDF, Gaussian density fitting. The production default for
closed-shell HF and KS, at \(\Gamma\) and at a full k-mesh, with open-shell
UHF / UKS available too (Gamma and multi-k). It projects the AO pair
density onto a charge-compensated auxiliary basis, which cancels the
divergent monopole at the source and leaves a finite, fast Coulomb
metric. Best all-round choice for ionic and covalent insulators. Deep
dive: density_fitting.md.
BIPOLE, an Ewald J-split. Splits \(1/r\) into a short-range
piece summed in real space and a long-range piece summed in reciprocal
space, sharing a single Ewald parameter across the electron-nucleus,
electron-electron, and nucleus-nucleus terms. This is the route for open-shell systems, hybrid functionals
at multiple k-points, and cross-validating against a CRYSTAL14 reference. Production
for 3D; the multi-k corrected-gauge exchange is an active frontier. Deep
dive: bipole.md.
GPW, Gaussian + plane-wave. Carries the density on a uniform grid and
solves the Poisson equation by FFT (an \(\mathcal{O}(N_g\log N_g)\) Hartree
build), pinning the \(\mathbf{G}=0\) component to zero for a neutral cell.
It runs a full SCF today: \(\Gamma\)-point RHF, RKS, UHF, and UKS plus
multi-k RKS, with forces, the finite-difference Hessian, DFT+U, smearing,
and D3(BJ) dispersion. It carries an all-electron density on the grid, so
no pseudopotential files are involved. Opt in and it emits a maturity
warning (GAPWExperimentalWarning). Deep dive:
gapw.md.
GAPW, Gaussian-augmented plane-wave. GPW plus a per-atom radial
augmentation that sharpens all-electron accuracy by splitting the Hartree
potential into a smooth grid part and a hard atomic correction. Same SCF
coverage and same opt-in maturity warning as GPW. Deep dive:
gapw.md.
RIJCOSX, density-fitted J plus chain-of-spheres K. Builds the Coulomb
matrix by GDF density fitting and the exchange by a seminumerical
chain-of-spheres (COSX) sum on a periodic Becke grid. It runs a full
\(\Gamma\)-point RHF SCF today. It is at parity with GDF for vacuum-padded
(molecular-limit) cells; its tight-cell exchange K is still being brought
to GDF parity, so use GDF for production tight-cell hybrids meanwhile.
Deep dive: density_fitting.md.
Note
The plane-wave routes are vibe-qc’s own grid / projector-augmented implementation. GPW and GAPW are computed entirely by vibe-qc’s own kernels (GAPW is the all-electron, projector-augmented variant), and the ASE Calculator and command-line interface mirror GPAW’s so a GPAW user is at home. The separate external GPAW code is used only as an out-of-process parity reference; vibe-qc never imports it or calls it to compute an energy.
Note
Beyond the k-point routes: the cyclic cluster model (CCM). vibe-qc’s signature periodic approach is real-space rather than reciprocal-space: the cyclic cluster model treats a crystal as a single finite cyclic cluster rather than sampling the Brillouin zone. It is available today at the semi-empirical (MSINDO) level; the ab-initio CCM (Hartree-Fock through coupled cluster) is under development. See the CCM tutorial and the CCM reference.
How to choose¶
All of these compute the same periodic Hamiltonian; at convergence they agree on the total energy. They differ in cost, in which methods they support, and in maturity. Pick by your situation:
Your situation |
Route |
Why |
|---|---|---|
Closed-shell RHF / RKS, \(\Gamma\) or multi-k |
GDF (default) |
fastest production route; chemical accuracy on insulators |
Open-shell UHF / UKS |
BIPOLE (AUTO default) or GDF |
both run open-shell \(\Gamma\) + multi-k; AUTO keeps BIPOLE |
Hybrid functional at multiple k-points |
BIPOLE |
carries exact-exchange K at \(\mathbf{k}\neq 0\) |
Cross-validating against CRYSTAL |
BIPOLE |
the shared-\(\alpha\) Ewald J-split gives directly comparable energies |
Tight ionic crystal at \(\Gamma\) |
GDF |
auxiliary fit avoids grid / Ewald overhead |
Plane-wave Hartree-J, large smooth-density cell |
GPW |
smooth-grid FFT-Poisson Hartree; \(\Gamma\) RHF/RKS/UHF/UKS + multi-k RKS |
Plane-wave with all-electron augmentation |
GAPW |
per-atom augmentation, no pseudopotential files |
Seminumerical exchange at \(\Gamma\) (molecular-limit cells) |
RIJCOSX |
GDF-J + chain-of-spheres COSX-K; use GDF for tight-cell hybrids |
Important
The automatic default (GDF for closed-shell, BIPOLE for
open-shell) already covers closed- and open-shell work, and both are
mature production routes. GPW, GAPW, and RIJCOSX also run a
full SCF today and are reached by an explicit jk_method=; they carry an
opt-in maturity warning because their feature surface is still filling in
(RIJCOSX is \(\Gamma\)-only RHF and its tight-cell exchange is not yet at
GDF parity). For a hybrid functional on a tight ionic crystal, stay on
GDF or BIPOLE until those gaps close.
Running a real comparison¶
The honest way to compare routes is to run the same crystal through more than one and watch the total energy land on the same value; they are different engines for one Hamiltonian, so any disagreement beyond the fitting/grid tolerance is a bug, not a feature.
Good starting points, all with verified reference output you can diff against:
The periodic foundations: periodic_hf and periodic_dft.
A full multi-k walkthrough on the default GDF route: lih_multi_k and lih_pob_tzvp_solid_state.
The runnable scripts under
examples/periodic/(LiH, MgO, NaCl, and more); changejk_methodand re-run to see the routes agree.
For the k-space machinery every periodic route shares (the Brillouin zone, Bloch phase, and why a k-mesh is needed at all), read kpoints_brillouin_bloch.