vibeqc.hirshfeld_charges

vibeqc.hirshfeld_charges(result, basis, molecule, *, grid_options=None, rho_floor=1e-30, max_block_elems=50000000, nuclear_charges=None)[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(r) d^3r, w_A(r) = r_A^free(r) / S_B r_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 {r_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 r_A^free evaluated at the molecular geometry. No per-atom SCF, no ionic-fragment branching.

On an ECP calculation the promolecule is the valence-only free atom: the ECP operator the SCF ran with is read from result and handed to the atomic calculations, so the replaced core is neither occupied nor squeezed into the valence basis, and the promolecule integrates to the valence electron count the molecular density does. nuclear_charges (below) supplies the matching Z - n_core reference.

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 = r_A / r_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 chi_mu(r_g) is (n_block, n_bf); the grid is processed in blocks sized so n_block x n_bf never exceeds this many elements (~``8 x max_block_elems`` bytes of float64). Default 5x10⁷ ≈ 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.

  • nuclear_charges (Sequence[float] | None)

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:

  • ∫ r_mol - n_electrons should be < 5x10⁻⁵ on the default grid for typical first-row systems.

  • S q_A - molecule.charge should be < 1x10⁻⁶ 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.