vibeqc.hirshfeld_charges

vibeqc.hirshfeld_charges(result, basis, molecule, *, grid_options=None, rho_floor=1e-30, max_block_elems=50000000)[source]

Classical Hirshfeld atomic partial charges from a converged SCF.

Hirshfeld, F. L. Theor. Chim. Acta 44, 129 (1977).

q_A = Z_A − ∫ w_A(r) ρ(r) d³r, w_A(r) = ρ_A^free(r) / Σ_B ρ_B^free(r).

Unlike mulliken_charges() and loewdin_charges(), Hirshfeld is a real-space partition rather than a basis-space partition — far less sensitive to diffuse functions, and the standard input charge for charge-dependent dispersion methods like the D4 refinement scheduled for vibe-qc v0.10.0 D2b.

The promolecular reference {ρ_A^free} is obtained for free from vibeqc.sad_density() — it returns the SAD initial-guess density matrix, which is block-diagonal by atom (each atomic SCF runs in vacuum, contributes to its own AO range, off- diagonal blocks are zero). Restricting the AO sum to atom A’s basis-function range gives ρ_A^free evaluated at the molecular geometry. No per-atom SCF, no ionic-fragment branching.

Parameters:
  • result – SCF result from vibeqc.run_rhf / run_rks / run_uhf / run_uks. The total density matrix is extracted via _total_density() (handles both the closed-shell .density and the open-shell .density_alpha + .density_beta schemas).

  • basis (vibeqc._vibeqc_core.BasisSet) – The same BasisSet used to run the SCF.

  • molecule (vibeqc._vibeqc_core.Molecule) – The same Molecule used to run the SCF.

  • grid_options (vibeqc._vibeqc_core.GridOptions | None) – Optional GridOptions for the Becke-Lebedev- Treutler integration grid. Defaults to GridOptions() (vibe-qc’s DFT-default level). Hirshfeld weights are smooth so the default grid is plenty for sub-millielectron charge accuracy; tighten only for explicit grid-convergence studies.

  • rho_floor (float) – Promolecule density floor to keep w_A = ρ_A / ρ_pro well-defined in vacuum regions far from any atom. Default 1e-30 is well below any grid point that contributes meaningfully to the integral.

  • max_block_elems (int) – Memory cap for the grid sweep. The AO matrix χ_μ(r_g) is (n_block, n_bf); the grid is processed in blocks sized so n_block × n_bf never exceeds this many elements (~``8 × max_block_elems`` bytes of float64). Default 5×10⁷ ≈ 400 MB per block. Small molecules fit in a single block (no behaviour change); large systems are swept block-by-block so the function never materialises a multi-gigabyte AO matrix. The result is independent of the block size to floating-point round-off.

Returns:

Rich dataclass; HirshfeldResult.charges is the (n_atoms,) array if you want bare-array semantics matching mulliken_charges(). The other fields carry per-atom integrated electron populations and grid- normalisation sanity numbers.

Return type:

HirshfeldResult

Notes

Numerical-quality knobs:

  • ρ_mol n_electrons should be < 5×10⁻⁵ on the default grid for typical first-row systems.

  • Σ q_A molecule.charge should be < 1×10⁻⁶ e (exact identity from the Hirshfeld weight normalisation; only grid error introduces residual).

Classical Hirshfeld charges in vibe-qc come out ~0.04-0.06 e more negative on heavy atoms than ORCA-reported values because the promolecule is constructed in the molecular basis (SAD-derived) rather than from tabulated Slater-type atomic densities. Documentable trade-off — switch sources via a future promolecule="slater" kwarg if byte-equal ORCA parity matters.

The iterative Hirshfeld variant (Bultinck et al., J. Chem. Phys. 126, 144111 (2007)) — which is less promolecule- sensitive — is a clean follow-on; same API, different inner loop. Tracked as a v0.10.0 D2b-i candidate.