Modern functionals: VV10 and the ωB97X-V / ωB97M-V wave¶
vibe-qc’s range-separated hybrids spent a release without their intended correlation partner: the “-V” members (ωB97X-V, ωB97M-V) are defined with the VV10 nonlocal correlation term, and without it they cannot be run as their authors meant. That gap is now closed. With the VV10 kernel in the C++ core, those functionals evaluate completely and self-consistently, and the same wave adds the r2SCAN01 meta-GGA and the revDSD-PBEP86-D4 double hybrid. This page is the worked companion to the functionals user guide; it shows how to invoke each new functional and what it is for. For the older, conventional range-separated hybrid ωB97X (which carries no VV10 term), start with Range-separated hybrids: ωB97X.
Status: preview
VV10 and the -V range-separated hybrids are production for molecular RKS and
UKS energies, but their analytic nuclear gradients are incomplete: the
gradient kernel omits the long-range exact-exchange term and the VV10
nonlocal term (GitLab #571), so compute_gradient_rks and
compute_gradient_uks refuse them unless you pass
allow_incomplete=True, and run_job(optimize=True) falls back to finite
differences of the energy. Periodic use is not available. r2SCAN01 has an
analytic gradient and is not affected. See
Methods: theory and status.
Every snippet below uses water at a fixed geometry so you can paste and run them directly:
import vibeqc as vq
mol = vq.Molecule(
[
vq.Atom(8, [0.0, 0.00, 0.00]),
vq.Atom(1, [0.0, 1.43, -0.98]),
vq.Atom(1, [0.0, -1.43, -0.98]),
]
)
VV10: the nonlocal correlation piece¶
VV10 (Vydrov and Van Voorhis 2010) adds a genuinely nonlocal correlation term: a double integral over all pairs of grid points that recovers long-range dispersion from the density alone, with no empirical pairwise C6 table. It is the ingredient that completes the “-V” functionals below. vibe-qc ships it both as a standalone functional and as a kernel you can call on any grid:
basis = vq.BasisSet(mol, "cc-pvdz")
opts = vq.RKSOptions()
opts.functional = "vv10" # rPW86 exchange + PBE correlation + the VV10 nonlocal term
result = vq.run_rks(mol, basis, opts)
print(f"E(VV10) = {result.energy:.6f} Ha")
# E(VV10) = -76.504441 Ha
The nonlocal potential is folded into the SCF exchange-correlation
build, so both the energy and its potential are exact (not a post-hoc
add-on). The C++ kernel is exposed directly as
vibeqc.compute_vv10(coords, weights, rho, sigma, b, C) for evaluation
on an arbitrary density, with the published parameters b = 5.9,
C = 0.0093. vibe-qc’s kernel matches PySCF’s _vv10nlc on a shared
water / cc-pVDZ grid to within 1e-8 Ha (tests/test_vv10.py).
Inside an SCF the nonlocal double integral runs on its own, coarser grid:
GridOptions.vv10_grid_factor (default 3.0) divides the radial and
angular resolution of the XC grid for the VV10 term only, the same
practice Vydrov and Van Voorhis used in their implementation paper (a
coarse SG-1 grid for the nonlocal term under a (75, 302) grid for the
semilocal part, because the nonlocal term is far less sensitive to grid
fineness). Set opts.grid.vv10_grid_factor = 1.0 to evaluate VV10 on the
full XC grid when you need the dense reference.
ωB97X-V and ωB97M-V: the complete range-separated hybrids¶
These are the functionals that VV10 unlocks. ωB97X-V is a range-separated GGA hybrid plus VV10; ωB97M-V is a range-separated meta-GGA hybrid plus VV10, and is among the best-performing functionals on broad main-group benchmarks. Both compose three advanced pieces at once: the erf-attenuated long-range exact exchange, the semilocal (meta-)GGA, and the VV10 nonlocal term. You select them by name, exactly like any other functional:
opts = vq.RKSOptions()
opts.functional = "wb97m-v" # range-separated meta-GGA + VV10 in one functional
result = vq.run_rks(mol, basis, opts)
print(f"E(ωB97M-V) = {result.energy:.6f} Ha")
# E(ωB97M-V) = -76.383379 Ha (ωB97X-V gives -76.385779 Ha)
vibe-qc reproduces PySCF’s dft.RKS(xc="wb97m-v", nlc="VV10") to within
5e-5 Ha at the same grid (tests/test_wb97m_v.py); ωB97X-V matches its
PySCF reference to the same tolerance (tests/test_vv10.py). The
Functional resolver carries the recipe, so you can confirm what you are
running:
fn = vq.Functional("wb97m-v")
print(fn.is_range_separated) # True
print(fn.rsh_omega) # 0.3 (bohr^-1)
print(fn.needs_vv10) # True
print(fn.vv10_b, fn.vv10_C) # 6.0 0.01 (the -V functionals re-fit b and C)
Important
The “-V” range-separated hybrids run through direct SCF only. As with
plain ωB97X, the erf-attenuated exchange has no 3-centre density-fitting
path yet, so the molecular driver selects the direct Fock builder
automatically; leave density_fit at its default. They are molecular
RKS / UKS only (periodic RSH and periodic VV10 are queued), and have
no analytic gradient yet, finite-difference geometry optimization
works via run_job(..., optimize=True).
r2SCAN01: a re-regularized meta-GGA¶
r2SCAN01 (Furness et al. 2022) targets a known weakness of r²SCAN: it restores the fourth-order term of the slowly-varying gradient expansion that r²SCAN drops, by re-regularizing with a larger η. The practical effect is better behaviour for slowly-varying densities, bulk metals and bonding regions, where r²SCAN slightly underbinds. It is a pure meta-GGA (no exact exchange), so it is cheap, and it is τ-only (laplacian-free), which fits vibe-qc’s meta-GGA grid:
basis_svp = vq.BasisSet(mol, "def2-svp")
opts = vq.RKSOptions()
opts.functional = "r2scan01"
result = vq.run_rks(mol, basis_svp, opts)
print(f"E(r2SCAN01) = {result.energy:.6f} Ha")
For this water geometry in def2-SVP, vibe-qc returns E = -76.3151 Ha
(-76.315067 in a run on a vibe-qc 0.17.10 development build),
matching PySCF’s MGGA_X/C_R2SCAN01 to 3.9 µHa (the asserted reference
in tests/test_xc.py). Unlike the range-separated hybrids above,
r2SCAN01 has analytic molecular gradients (the Pulay force includes
the τ term), so native geometry optimization works.
revDSD-PBEP86-D4: a re-parametrized double hybrid¶
A double hybrid runs a hybrid-DFT SCF step and adds a scaled MP2 correlation correction. revDSD-PBEP86-D4 (Santra, Sylvetsky and Martin 2019) is a careful re-fit of DSD-PBEP86 with two distinguishing features: an asymmetric MP2 scaling (different coefficients for opposite-spin and same-spin pairs), and D4 as its native dispersion, the functional coefficients were fit jointly with the D4 damping, so D4 is part of the definition rather than an afterthought. Use the dedicated dispatcher:
basis = vq.BasisSet(mol, "cc-pvdz")
result = vq.run_revdsd_pbep86(mol, basis)
print(f"E(hybrid SCF step) = {result.rks.energy:.6f} Ha")
print(f"E(MP2 correction) = {result.mp2.e_correlation:.6f} Ha") # 0.5922*E_os + 0.0636*E_ss
print(f"E(revDSD-PBEP86) = {result.e_total:.6f} Ha")
# E(revDSD-PBEP86) = -76.271466 Ha
The SCF base is 0.69 HF + 0.31 PBE exchange + 0.4210 P86 correlation; the
MP2 correction uses c_os = 0.5922 and c_ss = 0.0636. The dispatcher
returns a DoubleHybridResult carrying .rks, .mp2, and .e_total,
and matches a PySCF reference to within 5e-5 Ha
(tests/test_revdsd_pbep86.py). To obtain the published
revDSD-PBEP86-D4 total, add the native dispersion:
result = vq.run_revdsd_pbep86(mol, basis, dispersion="d4")
Note
dispersion="d4" needs the optional dftd4 package (pip install dftd4); without it, drop the keyword for the SCF + MP2 total. Note also
that the older revDSD-PBEP86-D3BJ uses a different coefficient fit
and is not reachable through this alias, the revdsd-pbep86 name is the
D4-native parametrization.
Theory¶
Range separation, restated. The -V hybrids build on the erf-split exchange of the previous tutorial: a fraction \(\alpha\) of exact exchange at short range that rises to \(\alpha+\beta\) at long range, with a semilocal (meta-)GGA for the rest (Mardirossian, Narbe and Head-Gordon, Martin (2014). *ωB97X-V: A 10-parameter, range-separated hybrid, generalized gradient approximation density functional with nonlocal correlation, designed by a survival-of-the-fittest strategy.* Physical Chemistry Chemical Physics, **16**(21), 9904–9924. doi:[10.1039/C3CP54374A](https://doi.org/10.1039/C3CP54374A), Mardirossian, Narbe and Head-Gordon, Martin (2016). *ωB97M-V: A combinatorially optimized, range-separated hybrid, meta-GGA density functional with VV10 nonlocal correlation.* Journal of Chemical Physics, **144**(21), 214110. doi:[10.1063/1.4952647](https://doi.org/10.1063/1.4952647)). For ωB97X-V the split is \(\alpha = 0.167\), \(\beta = 0.833\) and for ωB97M-V \(\alpha = 0.15\), \(\beta = 0.85\), both with \(\omega = 0.3\ \text{bohr}^{-1}\): as in ωB97X the long-range limit is 100 percent exact exchange, which puts the \(-1/r\) tail in the exchange potential. What these functionals add is a nonlocal correlation term.
The VV10 nonlocal kernel. Semilocal correlation cannot describe the long-range dispersion that arises from correlated charge fluctuations on distant fragments. VV10 (Vydrov, Oleg A. and Van Voorhis, Troy (2010). *Nonlocal van der Waals density functional: The simpler the better.* Journal of Chemical Physics, **133**(24), 244103. doi:[10.1063/1.3521275](https://doi.org/10.1063/1.3521275)) adds it as a double integral over the electron density,
with \(R = |\mathbf r - \mathbf r'|\), \(g'\) the same expression at \(\mathbf r'\), and
Here \(\rho\) is the electron density, \(\omega_p\) the local plasma frequency,
and the constant \(\beta\) makes \(E_c^\text{nl}\) vanish for the uniform
electron gas, so the nonlocal term is a pure correction. The two empirical
parameters do distinct jobs: \(C\) enters \(\omega_g\) and so sets the size of the
asymptotic \(C_6\) dispersion coefficient, while \(b\) controls \(\kappa\) and thus
the short-range damping, that is, how the dispersion switches off where the
densities overlap. The standalone vv10 functional (rPW86 exchange plus PBE
correlation plus VV10) uses \(b = 5.9\), \(C = 0.0093\); the -V functionals use
the pair \(b = 6.0\), \(C = 0.01\) chosen by their authors (Functional.vv10_b,
vv10_C).
Why ωB97X-V and ωB97M-V need it. The empirical coefficients of the
semilocal exchange and correlation and the exact-exchange fractions of these
functionals were optimised on a large training set together with the VV10 term
already present. The semilocal part therefore does not describe
noncovalent interactions on its own, and running it without VV10 evaluates a
different, unbalanced functional. Cost is the price: the double integral runs
over pairs of grid points, \(O(N_\text{grid}^2)\), which is why vibe-qc
evaluates it on a coarser grid (GridOptions.vv10_grid_factor, default 3.0)
than the semilocal part. The nonlocal potential is included self-consistently,
not added afterwards. Two limits remain, both stated in the status note above:
no complete analytic gradient, and no density-fitted exchange for the
erf-attenuated part.
What ships, and what is still queued¶
The table is the snapshot for this functional wave:
Functional |
|
Status |
|---|---|---|
VV10 (standalone) |
|
✅ shipped, molecular RKS / UKS, self-consistent |
ωB97X-V |
|
✅ shipped, molecular, direct SCF, FD gradient |
ωB97M-V |
|
✅ shipped, molecular, direct SCF, FD gradient |
r2SCAN01 |
|
✅ shipped, molecular, analytic gradient |
revDSD-PBEP86(-D4) |
|
✅ shipped via |
ωB97M(2) |
|
⏳ gated, needs a from-scratch B97M meta-GGA base (not in libxc) |
Periodic RSH / periodic VV10 |
(n/a) |
⏳ queued |
RSH analytic gradients, RSH + density fitting |
(n/a) |
⏳ queued |
xc="wb97m(2)" raises a clear message explaining why it is held back: it
is the one member of this family that is not a composition of stock libxc
parts (its SCF base is a re-optimised B97M power series that libxc does
not ship).
References¶
VV10. O. A. Vydrov, T. Van Voorhis, J. Chem. Phys. 133, 244103 (2010).
ωB97X-V. N. Mardirossian, M. Head-Gordon, Phys. Chem. Chem. Phys. 16, 9904 (2014).
ωB97M-V. N. Mardirossian, M. Head-Gordon, J. Chem. Phys. 144, 214110 (2016).
r2SCAN01. J. W. Furness, A. D. Kaplan, J. Ning, J. P. Perdew, J. Sun, J. Chem. Phys. 156, 034109 (2022).
revDSD-PBEP86. G. Santra, N. Sylvetsky, J. M. L. Martin, J. Phys. Chem. A 123, 5129 (2019).
D4 dispersion. E. Caldeweyher, C. Bannwarth, S. Grimme, J. Chem. Phys. 150, 154122 (2019).
Each functional’s route is registered in the bundled
citation database, so a job that uses one
auto-emits the right reference in its .bibtex and .references
siblings; the entries above are the authoritative form.
Next¶
User guide: functionals, the API reference this tutorial is the worked companion to.
Range-separated hybrids: ωB97X, the conventional (no-VV10) long-range-corrected hybrid and the HOMO ≈ −IP demonstration.
Double hybrids: B2PLYP, the annotated walk-through of the hybrid-SCF-plus-scaled-MP2 machinery that revDSD-PBEP86 rides.
Dispersion corrections, the D3 and D4 story behind the
dispersion="d4"keyword.