Symmetry Reduction Implementation — Status & Handover

Last updated: 2026-05-22 | Phase: complete — all milestones shipped

Purpose

This file is the single persistent handover for the symmetry-reduction workstream. Another chat can resume immediately from this file alone.

Milestone Status

#

Milestone

Status

What

M1

Primitive-cell reduction

symmetry=True in run_periodic_job

M2

1e compute reduction library

C++ + Python for S,T integrals

M2a

Wire M2 into 5 drivers

GDF + 4×BIPOLE auto-use reduced S/T

M3

2e Γ-only explicit kernel

build_jk_gamma_molecular_limit_explicit

M3b

2e multi-k explicit kernel

build_jk_2e_real_space_explicit

M3b

2e Fock compute reduction

Blocked at mathematical level. Three approaches tried: (1) per-cell J(g) reconstruction — fails because J(g) involves internal sum over g_λ; (2) density symmetrization — breaks idempotency; (3) MO coefficient symmetrization — group-averaging changes subspace span. The ERI 4-index tensor requires per-representative evaluation with separate J/K accumulation, needing a new C++ kernel.

M4

IBZ-native SCF

All 4 BIPOLE drivers use IBZ for diag

M5

Symmetrization library

symmetry_scf.py

M5a

J/K stabilisation in GDF

symmetry_stabilize=True

SYM5

Symmetrized forces

symmetrize_forces()

Key Discoveries

  1. V_nuc is not translation-invariant — the nuclear potential depends on absolute nuclear positions, so Wigner-D reconstruction does not work for V integrals or for the Hcore part of Fock symmetrization.

  2. Molecular overlap S(g=0) is not P·S·P^T-invariant for non-origin-fixed atoms — per-atom lattice shifts under symmetry operations cause cross-term sub-blocks to map to different cells. The SYM2c atom-pair- sub-block formula handles this correctly.

  3. Density symmetrization breaks idempotency — group-averaging D produces a matrix not representable as C·C^T. Fock symmetrization of the 2e part (J, K only) is feasible but has not been integrated.

Module Map

Module

Purpose

symmetry_core.py

Wigner D-matrices (SYM1)

symmetry_ao.py

AO permutation matrices (SYM2a)

symmetry_lattice.py

Lattice-cell orbits (SYM2b)

symmetry_lattice_c.py

Atom-pair orbits (SYM2c)

symmetry_integrals.py

Storage-reduced 1e integrals (SYM3a)

symmetry_integrals_reduced.py

Compute-reduced 1e integrals (SYM3b)

symmetry_scf.py

Group-averaging operators (M5)

periodic_runner.py

reduce_to_primitive kwarg (M1)

periodic_rhf_gdf.py

GDF driver with auto M2a

pbc_bipole*.py

BIPOLE drivers with auto M2a

periodic_fock.cpp

build_jk_gamma_molecular_limit_explicit (M3)

Next Steps

  1. M3b — Python orbit orchestration for 2e Fock: partition (c_g, c_p) cell pairs into orbits, call explicit-cell kernel at representatives, reconstruct full J/K via Wigner-D. High implementation effort.

  2. M4 — IBZ-native Fock build: build F(k) only at irreducible k-points, reconstruct full-mesh density from IBZ. Requires non-symmorphic support.

  3. M5 integration — Wire J/K-only symmetrization into SCF drivers as an optional convergence aid (disabled by default).

C++ Changes (for reference)

  • lattice_integrals.cpp: compute_1e_lattice_matrix_explicit() + public wrappers compute_overlap/kinetic/nuclear_lattice_explicit()

  • periodic_fock.cpp: build_jk_gamma_molecular_limit_explicit()

  • lattice_integrals.hpp, periodic_fock.hpp: declarations

  • bindings.cpp: pybind11 bindings