This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

Notebooks · lib/hf/jk

Coulomb and exchange matrices from packed integrals, three ways

The two-electron part of the Fock matrix is built from two contractions of the electron repulsion integrals (ij|kl) (chemist's notation) with a density D:

J_ij = sum_kl (ij|kl) D_kl        Coulomb: the field of the whole density
K_ik = sum_jl (ij|kl) D_jl        exchange: the same integrals, indices crossed

A closed shell uses F = H + J - K/2 with the total density; UHF uses F_s = H + J(Da) + J(Db) - K(D_s) for each spin.

The integrals are stored once per 8-fold symmetry class (lib/hf/eri_store), so for n = 19 there are 18,145 values instead of 130,321. The members:

  • jk_packed (member 0, production): one pass over the packed vector. Each stored value stands for up to 8 index orders; it is scaled by 1/2 for each coincidence (i = j, k = l, ij = kl), which leaves exactly one unit of weight per distinct order, and then added in all 8 orders. That touches each stored value once and needs no branch per order.
  • jk_pairs: the integrals as an npair x npair matrix. J is a matrix-vector product over pairs; K reads the matrix through a table of pair indices, one term per (i, j, k, l).
  • jk_dense: unpack to the full [n, n, n, n] tensor and apply the definitions above literally. It costs n^4 memory and time and exists to be obviously right.

Member signature, frozen: (X1, X2, X3, D, opts) -> [2 ndens, n, n], where X1 is the packed vector for these in-core members (X2, X3 and opts are not read), D is [ndens, n, n] and the result holds J(D_0), K(D_0), J(D_1), K(D_1). A direct member, which computes integrals on the fly, would take the atoms, shells and prims packs in X1..X3 instead; that is why the signature has three slots.

None of the members assumes D is symmetric.

jk_of(Gp, D, opts) runs the member opts[OPT_JK] names: these three, or the direct member int_jk_direct (lib/hf/jk_direct), which reads a basis blob in Gp instead of packed integrals. It calls each by name, the production member jk_packed when the option is left at its default, so the SCF reaches J and K without a registry. jk_methods() lists the three in-core members for the tests and sweeps that run them side by side; int_jk_methods() (lib/hf/integrals) adds the direct one.

Used with import hf.jk.

Look inside this program

  • Atlas

    The program’s map: every function and which calls which.

  • There’s no recorded run of this program yet.

Shift+Enter in a cell runs it and moves to the next. Running a cell runs every cell above it too, as one program.

[1]lines 51–262