Semiempirical Methods

vibe-qc ships a self-contained semiempirical platform covering four method families, DFTB, GFN-xTB, NDDO, and INDO, for molecules and periodic solids. The platform is vibe-qc’s own implementation, not a wrapper around external programs (External QC codes (ORCA / Psi4 / others)). The MACE machine-learning interatomic potential is documented separately because it is an external pre-trained model, not a semiempirical electronic-structure method (Machine-learning interatomic potentials (MACE)).

Warning

Production readiness varies by method. DFTB is intended for screening/preoptimization; GFN2-xTB is gated experimental; PM6, OM2 and OM3 are production for molecular work (PES shape pinned by regression, published-benchmark validation for OM2, see the status table); OM1 is experimental until its analytic core-valence ECP lands; MSINDO is reference-parity validated for its current molecular scope. See the status table and the comparative production brief in Semiempirical and MACE method comparison.

Method families

Family

Methods

Best for

Cost

DFTB

DFTB0, SCC-DFTB, UDFTB0, USCC-DFTB

Screening, preoptimization

Fastest

GFN-xTB

GFN2-xTB

Organic / main-group

Fast

NDDO

PM6, OM1, OM2, OM3

Development benchmarking, pre-screening

Fast

INDO

MSINDO

Reference-parity molecular semiempirical runs inside the supported element/spin scope

Fast

Quick start

DFTB0, non-self-consistent tight-binding

from vibeqc.semiempirical import DFTB0Model
from vibeqc import Molecule, Atom

mol = Molecule([
    Atom(8, [0.00, 0.00, 0.00]),
    Atom(1, [1.55, 0.90, 0.00]),
    Atom(1, [-1.55, 0.90, 0.00]),
])

model = DFTB0Model(mol)
print(f"Energy: {model.energy():.6f} Ha")
print(f"Gradient shape: {model.gradient().shape}")  # (3, 3)

SCC-DFTB, self-consistent charges

from vibeqc.semiempirical import SCCDFTBModel

model = SCCDFTBModel(mol, charge_mixing=0.2)
print(f"Energy: {model.energy():.6f} Ha")

GFN2-xTB, published parameters (experimental)

from vibeqc.semiempirical import GFN2Model
from vibeqc.semiempirical.methods.gfn2_params import load_gfn2_params

params = load_gfn2_params()  # auto-fetches 86-element Grimme parameter set
model = GFN2Model(mol, params=params, warn=False)  # warn=False silences experimental gate
print(f"Energy: {model.energy():.6f} Ha")

Warning

GFN2-xTB is gated experimental. The H0/overlap deep-state bug was fixed 2026-06-01, and molecular AES (dipole + quadrupole), the GAM3 third-order term, and post-SCF native D4-style dispersion are now implemented. The remaining production gates are periodic AES image-cell multipole Ewald terms, stricter periodic molecular-limit parity, difficult periodic/polar fixtures, and a full external-parity matrix against xtb. See Method status. The post-SCF native D4 term is included for H, He, B, C, N, O, F, and Ne; outside that reference-data set GFN2 returns zero D4 and emits GFN2D4UnsupportedWarning.

PM6, NDDO with published parameters

from vibeqc.semiempirical import PM6Model

model = PM6Model(mol)
print(f"Energy: {model.energy():.6f} Ha")

OMx, orthogonalization-corrected NDDO

from vibeqc.semiempirical import OMxModel

model = OMxModel(mol, variant="om2")  # "om1", "om2", or "om3"
print(f"Energy: {model.energy():.6f} Ha")

Through run_job

All seven methods are available via vibeqc.runner.run_job():

from vibeqc import run_job

run_job(mol, method="dftb0", optimize=True, output="h2o_dftb0")
run_job(mol, method="pm6", output="h2o_pm6")
run_job(mol, method="gfn2_xtb", output="h2o_gfn2")   # emits experimental warning

Periodic systems

All families support Gamma-point periodic calculations with finite-difference gradients and stress.

DFTB periodic

from vibeqc._vibeqc_core import PeriodicSystem, Atom
from vibeqc._vibeqc_core import semiempirical as _se
import numpy as np

# 1D carbon chain
atoms = [Atom(6, [0.0, 0.0, 0.0])]
cell = np.diag([2.5, 30.0, 30.0])
system = PeriodicSystem(1, cell, atoms)

params = _se.SemiempiricalParameters.dftb0_default()
result = _se.run_dftb0_gamma(system, params)
print(f"Energy: {result.energy:.6f} Ha")

GFN2 periodic

from vibeqc._vibeqc_core.semiempirical import xtb as _xtb
from vibeqc.semiempirical.methods.gfn2_params import load_gfn2_params

params = load_gfn2_params()
result = _xtb.run_gfn2_xtb_gamma(system, params)

PM6 / OMx periodic

from vibeqc.semiempirical import PeriodicPM6Model, PeriodicOMxModel

pm6 = PeriodicPM6Model(system)
print(f"PM6: {pm6.energy():.6f} Ha")

omx = PeriodicOMxModel(system, variant="om2")
print(f"OM2: {omx.energy():.6f} Ha")

Preoptimization workflows

Use semiempirical methods for fast structure preoptimization before an expensive DFT calculation:

from vibeqc.semiempirical import preoptimize_periodic

# Preoptimize a periodic system with DFTB0, then run DFT
preoptimize_periodic(
    system,
    method="dftb0",
    fmax=0.01,
)

For molecular systems, use optimize=True with run_job:

from vibeqc import run_job

# Preoptimize with DFTB0, then refine with DFT
run_job(mol, method="dftb0", optimize=True)
run_job(mol, method="rks", functional="PBE", basis="def2-svp", optimize=True)

Method status

Method

Status

Energy accuracy

Gradient

Periodic

Open-shell

Elements

DFTB0 / UDFTB0

Screening/preopt

In-house parameters, not DFTB+ parity

Analytic

Gamma + k

yes

91 in-house

SCC-DFTB / USCC

Screening/preopt

In-house parameters, not DFTB+ parity

Analytic

Gamma + k

yes

91 in-house

GFN2-xTB

Gated experimental

External xTB parity matrix still open

Analytic (FD-consistent to <1e-5 Ha/bohr on H2O/CH4/NH3: full H0 shape + shell-ES + 3rd-order + AES derivatives; periodic Gamma is fixed-charge)

Gamma + k, experimental

yes

86 fetched (LGPL)

PM6 / UPM6

Production (molecular)

Physical PES pinned by regression; spherical Klopman-Ohno fallback where MOPAC diatomic data is absent (wells ~0.1-0.3 bohr long)

FD

Gamma, experimental

yes

82 bundled MOPAC

OM2 / OM3

Production (molecular)

Published OMx Hamiltonian (Dral 2016); relative energetics match published benchmarks (H3- bend 0.1 kcal/mol, ethane barrier ±0.6); bond minima ~0.1-0.2 Å long (documented integral stand-ins)

FD

Gamma, legacy-model parity only

yes (UHF)

5 published (H,C,N,O,F)

OM1

Experimental (warns)

Analytic core-valence ECP (Kolb-Thiel 1993) not implemented; X-H bonds ~0.3 A short, close contacts can collapse

FD

Gamma, legacy-model parity only

yes (UHF)

5 published (H,C,N,O,F)

MSINDO

Production within scope

Reference MSINDO parity ≤1 µHa (INDO + NDDO)

FD and analytic molecular/CCM paths

CCM 1-D/2-D/3-D + Ewald

UHF s/p/d within validated fixtures

H-Xe (Z=1-54); NDDO H,Li-F,Na-Cl

The same implementation labels are available from Python through vibeqc.semiempirical.semiempirical_route_status(route). Routes such as msindo-cis, msindo-cis-gradient, msindo-ovgf, msindo-md, and msindo-metadynamics are explicitly marked python-reference until their hot loops move to native kernels or are declared intentionally orchestration-only. periodic-pm6 and periodic-omx are marked mixed-native: Gamma energy uses native NDDO kernels, while the current gradient, stress, and cell-optimization helpers still rely on finite-difference Python orchestration. The lookup also labels molecular pm6-gradient-fd and omx-gradient-fd as native-fd: their displacement loops are C++-backed, but they remain finite-difference stopgaps until analytic molecular NDDO gradients land. The lookup accepts public method aliases such as dftb0, scc-dftb, gfn2xtb, om2, om2-gradient-fd, gfn2, msindo, and ccm.

Direct run_semiempirical(...) results compute gradients lazily when result.gradient() is called. DFTB0/SCC-DFTB, GFN2-xTB, PM6/UPM6, and OMx expose their existing gradient surfaces through that adapter, while closed-shell MSINDO INDO uses the native analytic-gradient route there. MSINDO NDDO and open-shell MSINDO keep gradient() unset at the unified runner layer until those gradient surfaces are promoted. Geometry-optimizer SemiempiricalProvider calls the same unified runner, preserving the documented MSINDO finite-difference force fallback when a MSINDO result is energy-only.

See also

Semiempirical and MACE method comparison for production guidance and ../semiempirical_acceptance_matrix.py for the living validation-gate matrix.

Element coverage

DFTB, 91 elements (H-U except Po/Z=84), including 3d/4d/5d transition metals, lanthanides (La-Lu), and early actinides (Ac-U). All parameters are in-house estimates; DFT-fitted production repulsive potentials are deferred.

GFN2-xTB, 86 elements from the published Grimme-group parameter set. Parameters are fetched on demand at first use (LGPL-3.0 licensed, not bundled, see ADR-002).

PM6, 82 elements from the bundled MOPAC PM6 parameter cache (Apache-2.0 provenance in the TOML header), with the Stewart 2007 H/C/N/O/F subset still available. The public wrapper auto-selects the MOPAC-derived cache for elements outside H/C/N/O/F.

OMx, 5 elements (H, C, N, O, F) from Dral 2016 Tables 1-3.

# Check element coverage
from vibeqc.semiempirical import SemiempiricalParameters

params = SemiempiricalParameters.dftb0_default()
elements = [Z for Z in range(1, 93) if params.has_element(Z)]
print(f"DFTB covers {len(elements)} elements")

Parameter customisation

DFTB custom parameters

from vibeqc.semiempirical import SemiempiricalParameters

custom = SemiempiricalParameters()
custom.add_element(
    Z=1, on_site=[-0.21], zeta=[1.24],
    hubbard_u=0.42, valence_electrons=1,
)
custom.add_element(
    Z=8, on_site=[-0.89, -0.33], zeta=[2.25, 2.25],
    hubbard_u=0.45, valence_electrons=6,
)
# Set repulsive pair (R⁻¹² form)
custom.set_repulsive_pair_analytic(1, 1, A=5.0)
custom.set_repulsive_pair_analytic(1, 8, A=15.0)
custom.set_repulsive_pair_analytic(8, 8, A=40.0)

model = DFTB0Model(mol, params=custom)

GFN2 parameters

GFN2-xTB parameters are fetched automatically from the Grimme group’s GitHub repository. To force a refresh:

from vibeqc.semiempirical.methods.gfn2_params import load_gfn2_params

params = load_gfn2_params(force_refetch=True)

PM6 parameters

from vibeqc.semiempirical.methods.pm6_params import load_pm6_params

params = load_pm6_params()
model = PM6Model(mol, params=params)

Comparing against external programs

Reference energies from external programs can be obtained via out-of-process subprocess runners (External QC codes (ORCA / Psi4 / others)):

from examples.regression.core.runner_xtb import energy as xtb_energy
from examples.regression.core.runner_mopac import energy as mopac_energy
from examples.regression.core.runner_dftbp import energy as dftbp_energy

print(f"xTB GFN2 H2O:  {xtb_energy('H2O'):.6f} Eh")
print(f"MOPAC PM6 H2O: {mopac_energy('H2O'):.6f} Ha")
print(f"DFTB+ H2O:     {dftbp_energy('H2O'):.6f} Ha")

These runners require the external program to be installed on $PATH (see each runner’s docstring for install instructions).

Performance tips

  • DFTB0 is 3-5× faster than SCC‑DFTB (no SCF loop). Use it for preoptimization where charge self-consistency is less important.

  • DFTB gradients (DFTB0 and SCC-DFTB) are analytic and match finite differences tightly; the SCC energy is variational in the density, so its fixed-charge gradient is exact at SCC convergence.

  • Periodic systems support Gamma-point for all methods; DFTB also supports k-point meshes. Increase the lattice cutoff (cutoff_bohr) for tight cells.

  • Memory is negligible, the basis is minimal (one function per valence shell).

Known limitations

  • DFTB repulsive potentials are in-house R−12 estimates; DFT-fitted production repulsives are deferred.

  • GFN2-xTB still lacks periodic AES image-cell multipole Ewald terms and a closed external xtb parity matrix (Method status).

  • PM6 reports a PM6-like total, not a MOPAC heat of formation; use MOPAC out-of-process when exact MOPAC convention parity is required.

  • OM2/OM3 are production molecular paths within their documented H/C/N/O/F scope; OM1 remains experimental until the analytic core-valence ECP lands.

  • Periodic GFN2/NDDO gradients are finite-difference only; analytic periodic NDDO gradients are deferred.

  • MSINDO molecular closed-shell analytic gradients and closed-shell CCM analytic / finite-difference gradients are available through the native route inside their documented scopes. NDDO, odd-electron analytic gradients, and excited-state/root-tracking gradients remain on their documented fallback or reference paths. See MSINDO (semiempirical INDO).