Composite “3c” methods

The Grimme-school composite 3c methods bundle a tuned small basis, a modern dispersion correction (D3-BJ or D4), a geometric counterpoise correction (gCP), and — for some recipes — a modified short-range correction (3c-SRB) into a single user-facing keyword. The result is that one call gets you GMTKN55 / S22 / X23 accuracy comparable to a much-more-expensive parent functional + triple-zeta calculation at small-basis cost.

This chapter documents the v0.9.0 composite surface: the seven registered recipes, their current availability status, the vq.compute_gcp standalone API, and the contribution pathway for extending coverage to new bases / elements.

Quick start

import vibeqc as vq

mol = vq.Molecule.from_xyz("water_dimer.xyz")

# One call: bundles HF + MINIX basis + D3(BJ) + gCP(MINIX) + SRB
res = vq.run_job(mol, method="hf-3c", output="water_dimer_hf3c")

# Read the composite total off the output file or programmatically:
#   E_SCF + E_disp + E_gCP + E_SRB

Composite recipes are case-insensitive and accept the unicode-omega spelling: "ωB97X-3c" and "wb97x-3c" resolve to the same recipe.

Recipe catalogue

Composite

Best for

Basis

Disp.

SRB?

Availability today

HF-3c

Very large systems; mean-field qualitative

MINIX

D3(BJ)

yes

RUNNABLE (end-to-end)

PBEh-3c

Strong noncovalent geometries; geometry pre-step

def2-mSVP

D3(BJ)

no

PENDING_GCP_DATA

B97-3c

Workhorse GGA; transition metals

def2-mTZVP

D3(BJ)

yes

PENDING_GCP_DATA

B3LYP-3c

IR / vibrational frequencies (B3LYP’s strength)

def2-mSVP

D3(BJ)

no

PENDING_GCP_DATA

r²SCAN-3c

“Swiss army knife”; best general-purpose

def2-mTZVPP

D4

no

RUNNABLE (first turnkey 3c)

ωB97X-3c

Drug-like / pharma; barrier heights

vDZP

D4

no

RUNNABLE (SCF + D4; vDZP gCP partial)

HSE-3c

Solid-state range-separated; embedded clusters

def2-mSVP

D3(BJ)

no

RUNNABLE (turnkey)

Availability — what runs today

The v0.9.0 release lands the composite scaffolding (gCP standalone API, recipe registry, keyword-shortcut dispatcher, SRB pairwise correction). End-to-end runnability of a given composite depends on its prerequisites:

RUNNABLE

Every ingredient is wired today. vq.run_job(method="...") works end-to-end.

NEEDS_BASIS

The functional + dispersion + gCP framework are wired, but the target basis is not bundled in python/vibeqc/basis_library/basis/ (per the basissetdev rule — see project CLAUDE.md § 4, BSE-fetched basis sets travel via vqfetch or the basissetdev branch, not main). You can still run the composite by supplying the basis-set definition locally and pointing BasisSet(molecule, "/path/to/your_basis.g94") at it. The per-element gCP data tables (e_mis, n_virt, zeta) for the composite-specific bases are also pending — see Extending the gCP coverage below.

PENDING_F1

No composite carries this flag any more — F1 landed in v0.9.0. The CAM K-build (split into K_full + K_LR using libint’s Operator::erf_coulomb) is wired through FourIndexJKBuilder in v0.9.0; RSH SCF works for systems up to ~250 basis functions. The DirectJKBuilder / DFJKBuilder / COSXJKBuilder long-range K-build paths are queued as v0.9.x patches. Until those land, RSH SCF auto-selects SCFMode::CONVENTIONAL to route through FourIndex; if a user explicitly forces a non-FourIndex builder with an RSH functional, the first K-build call raises with the actionable “not yet wired for ” message.

PENDING_F3

No composite carries this flag any more — F3 landed in v0.9.0. The slot is retained for documentation completeness. The mGGA τ-density pipeline (τ assembly, v_τ Fock contribution) is wired in cpp/src/rks.cpp and cpp/src/uks.cpp; the τ-only mGGA aliases (TPSS, r²SCAN, SCAN, M06-L) are registered in cpp/src/xc.cpp. r²SCAN-3c is now NEEDS_BASIS. mGGA analytic gradient, Hessian, and periodic-SCF paths are explicitly gated for the v0.9.x patches with actionable errors at the call site (use vibeqc.gradient_fd(...) for the mGGA gradient today).

PENDING_GCP_DATA

The basis-fit (σ, α, β) constants are registered for the recipe’s basis, but the per-element e_mis / n_virt / zeta tables are not yet bundled. Bundled coverage in v0.9.0 first-cut: H, C, N, O, F at def2-SVP and def2-TZVP (the most-published reference slice in the Kruse-Grimme 2012 paper). Coverage for the other bases is the natural next-commit unit — see Extending the gCP coverage.

You can introspect this at runtime:

for r in vq.list_composites():
    print(f"{r.name}  ->  {r.availability.value}  ({r.notes})")

The gCP standalone API

The geometric counterpoise correction is exposed as a standalone function, independent of the composite-recipe dispatcher:

import vibeqc as vq

mol = vq.Molecule.from_xyz("water_dimer.xyz")
res = vq.compute_gcp(mol, "def2-svp")
print(f"E_gCP = {res.energy:.6f} Ha = {res.energy * 627.5:.4f} kcal/mol")

Returns a GCPResult with .energy (Hartree), .basis_name, the .params actually used (so SCF logs can record provenance), and an optional .gradient when with_gradient=True is passed.

Behind the scenes — Kruse-Grimme 2012 form

\[E_\mathrm{gCP} = \sigma \sum_a \sum_{b \neq a} \frac{ e^{-\alpha R_{ab}^\beta} \, e_a^\mathrm{MIS} } { \sqrt{ N_b^\mathrm{virt} \, S_{ab} } }\]

where σ, α, β are basis-set-specific fit parameters (Kruse-Grimme 2012 Table 2), e_a^MIS is the per-atom “missing basis-set incompleteness” energy (Hartree, always negative; per- element tabulation in Table 3 / SI of the paper), N_b^virt is the number of virtual orbitals of atom b in the target basis, and S_ab is the geometric-mean 1s-STO overlap of atoms a and b. The sign of E_gCP is always positive — gCP opposes the BSSE over-binding of incomplete basis sets.

For full details and the per-basis citation chain, see vibeqc.gcp.

Extending the gCP coverage

The v0.9.0 first cut bundles per-element data for H / C / N / O / F at def2-SVP and def2-TZVP. To extend coverage, follow the workflow in the data_library standard:

  1. For a new element at a bundled basis — add a new [elements.<symbol>] table to the matching python/vibeqc/data_library/gcp/<basis>.toml file. Populate e_mis / n_virt / zeta from the cited source (the file’s metadata.citation). Add a regression test in tests/test_gcp.py that hits the new element.

  2. For a new basis — copy data_library/gcp/_template.toml to a new <name>.toml, fill in the [metadata] block (citation, DOI, license posture), transcribe the (σ, α, β) constants and per-element data, then expose the new keyword under a recipe in python/vibeqc/composites.py if it’s part of a composite.

  3. For a one-off run with un-bundled data — pass an explicit params= to vq.compute_gcp:

    custom = vq.GCPParams(
        basis_name="my-basis",
        sigma=0.3845, alpha=0.7400, beta=1.4366,
        e_mis={6: 0.0273, 7: 0.0457, ...},
        n_virt={6: 9.0, 7: 9.0, ...},
        zeta={6: 5.67, 7: 6.66, ...},
        citation="my reference",
    )
    res = vq.compute_gcp(mol, params=custom)
    

Citations

When you publish results from a 3c composite, cite all four of:

  1. vibe-qc per CITATION.cff + the JCC release paper once published.

  2. The composite-method paper:

    • HF-3c: Sure & Grimme, J. Comput. Chem. 34, 1672 (2013).

    • PBEh-3c: Grimme, Brandenburg, Bannwarth, Hansen, J. Chem. Phys. 143, 054107 (2015).

    • B97-3c: Brandenburg, Bannwarth, Hansen, Grimme, J. Chem. Phys. 148, 064104 (2018).

    • r²SCAN-3c: Grimme, Hansen, Ehlert, Mewes, J. Chem. Phys. 154, 064103 (2021).

    • ωB97X-3c: Müller, Hansen, Grimme, J. Chem. Phys. 158, 014103 (2023).

  3. gCP: Kruse & Grimme, J. Chem. Phys. 136, 154101 (2012).

  4. Dispersion:

    • D3-BJ: Grimme, Ehrlich, Goerigk, J. Comput. Chem. 32, 1456 (2011).

    • D4: Caldeweyher, Bannwarth, Grimme, J. Chem. Phys. 150, 154122 (2019).

The recipe’s .citation field surfaces the canonical originator paper in the SCF log, and compute_gcp records the parameter-source publication in GCPResult.params.citation.