Implementation notes#
2026-07-09 – built and validated#
Implemented as bsse.py / bsse_parameters.py / tk_bsse.py /
bsse_step.py (+ entry points, data/bssegradient.cmp). orca_base grew
_resources/_mpi_env (extracted from run_orca), run_orca_compound,
and _read_engrad.
Double-hybrid energy gotcha (important, and relevant to the general step)#
The shipped Compound script reads ORCA’s SCF_Energy property for each
sub-calculation. For a double hybrid (the campaign’s REVDSD-PBEP86-D4/2021)
that is only the SCF part – it omits the (scaled) MP2 correlation, which for
Ar2/def2-TZVP is ~0.2 Eh. So the script’s result.engrad
energy is an SCF-level counterpoise energy, and comparing it to the true total
gave a nonsensical “correction” of 130 kcal/mol on the first run.
The script’s gradient is fine: it operates on Nuclear_Gradient
(Property_Base=true), which is the full-method (relaxed-density MP2 +
dispersion) gradient.
Fix (method-general): ignore the script’s energy; compute the corrected energy
in Python from each sub-job’s FINAL SINGLE POINT ENERGY – the true total
that matches the gradient. The five sub-jobs are delimited in orca.out by
COMPOUND JOB 1..5 (in the order fragA(AB), monA, fragB(AB), monB, dimer);
take the last FINAL SINGLE POINT ENERGY in each block so an optimized
monomer’s converged value wins. Dispersion has no BSSE (ghost centres have no
nuclei) and cancels in the correction terms, so FINAL SINGLE POINT ENERGY is
consistent for -D methods too. This removed the need for an HF/DFT-only
restriction: any analytic-gradient method works (HF, DFT incl.
dispersion-corrected and double hybrids, MP2/RI-MP2); only numerical-gradient
methods ((DLPNO-)CCSD(T)) are refused.
Validation#
Testing/bsse.flow on Ar-Ar (REVDSD-PBEP86-D4/2021/def2-TZVP) gives:
uncorrected -1054.38210538 E_h (matches a plain single-point Energy run),
corrected -1054.38198513 E_h,
BSSE correction 0.00012024 E_h = 0.0755 kcal/mol (physically sane for a rare-gas dimer at a triple-zeta double hybrid).
Confirmed on this machine that the %Compound "file.cmp" with <var=val;> end
injection syntax and the ghost notation (element + : in the *xyzfile)
both work as written.
Still open / deferred to the general step: per-fragment charge & multiplicity (only neutral-singlet now), N > 2 fragments, non-ORCA engines, and a finite-difference check of the corrected gradient.