Kramers and quaternion decomposition of spinor expressions#518
Draft
kshitij-05 wants to merge 4 commits into
Draft
Kramers and quaternion decomposition of spinor expressions#518kshitij-05 wants to merge 4 commits into
kshitij-05 wants to merge 4 commits into
Conversation
Introduces the Kramers symmetry quantum number for relativistic
2-component theories, mirroring the existing Spin QN structure:
* space_qns.hpp: new `Kramers` enum (up/down/any/null) using bits
7-8 of the QN bitmask. Spin and Kramers are mutually exclusive
on a single index — an index is either spin-orbital (alpha/beta)
or relativistic-spinor (kramers-up/kramers-down), reflecting the
physical regime, not both.
* spinor.{hpp,cpp}: new module hosting both the Kramers tracer
(kramers_trace) and the upcoming quaternion decomposer (Phase 4).
Kramers index annotations use ⇑/⇓ glyphs (U+21D1/U+21D3),
distinct from spin's ↑/↓ so the QN families compose without
label collision.
* `make_kramers_up/dn/free(Index)` helpers parallel
`make_spinalpha/beta/free`, going through the IndexSpace registry
so spaces with the resulting (label, qns) tuple are reused.
* `append_kramers(expr, replacements)` applies an Index→Index
replacement map to all tensors in an expression (mirrors
`append_spin` in `spin.cpp`).
* `kramers_trace(expr)` MVP: collects every Kramers::any index in
the input, enumerates 2^N configurations (each index pinned to
up or down), and emits the resulting Sum of substituted copies.
No per-tensor TRS canonicalization or cross-tensor folding yet
— those iterations are deferred; the evaluator (LCAOFactory
canonical-storage layer) already collapses Kramers blocks to
orbit reps at integral-fetch time, so the MVP delivers correct
energies for closed-shell relativistic MP2/CC even without
symbolic folding. The Visscher Eq. 28 two-term form falls out
of subsequent simplification commits.
Add complex-arithmetic primitives on tensor expressions, and use them
inside kramers_trace to rewrite TRS-paired Kramers configurations as
explicit conjugates of one another.
Conjugation infrastructure (groundwork for Phase 4 quaternion decompose
as well):
* `toggle_conj_suffix(label)`: append/strip the `*` suffix that marks
a tensor as complex-conjugated. (z*)* = z by toggling.
* `conjugate(expr)`: recursively walks a SeQuant expression and
conjugates Constants, toggles `*` on Tensors, and distributes over
Products and Sums (Π zᵢ)* = Π zᵢ* and (Σ zᵢ)* = Σ zᵢ*.
* `real_part(expr) = (expr + conjugate(expr)) / 2` and
`imaginary_part(expr) = -i (expr - conjugate(expr)) / 2` —
materialized as ordinary Sum/Product/Constant trees so any standard
SeQuant evaluator can consume them; downstream callers can short-
circuit the (T + T*) → 2 Re(T) collapse if their output is known
to be real-scalar.
kramers_trace now applies the TRS rewrite:
* Enumerate the 2^N Kramers configurations as before.
* For each TRS pair (X, X̄), only build the lex-smaller X term;
materialize the X̄ partner as `conjugate(T_X)` (using the X
Kramers labels with `*`-suffixed tensor labels).
* Sign analysis: T_X̄ = Π_i tensor_i_X̄ = Π_i ((-1)^{k_i} tensor_i*_X);
for any all-internal-index contraction (every barred index appears in
an even number of tensors) the (-1)^{Σ k_i} factor is +1, so
T_X̄ ≡ conjugate(T_X) without an explicit sign.
Term count is unchanged (16 stays 16 for an MP2-shape input) but the
Sum now exposes the conjugate-pair structure symbolically, letting
evaluators short-circuit (one fetch + .conj()) and letting downstream
real-scalar callers collapse pairs to `2 Re(...)`.
The MVP enumeration path still falls out as a special case (when the
underlying expression has no Kramers::any indices, kramers_trace
returns it unchanged).
Replace the TRS-rewrite-only enumeration with the full open-shell
spin-trace pipeline applied to Kramers configs:
1. Substitute K_up/K_dn for each index per the 2^N enumeration.
2. expand_antisymm (skip_spinsymm=false — Kramers blocks have no
orthogonality, so every permutation contributes).
3. expand → flatten Products → rapid_simplify → canonicalize →
rapid_simplify per term.
4. Final cross-product expand + canonicalize so dummy renames fold
equivalents across Kramers configurations.
The TRS pair rewrite via conjugate() is dropped from kramers_trace
because it created NonSymm tensors with `*`-suffixed labels that
canonicalize couldn't fold across Kramers configs (it cuts the term
count in half but blocks the deeper antisym fold). The conjugate /
real_part / imaginary_part scaffolding is kept as groundwork for the
upcoming quaternion decomposer (Phase 4) and as a building block for
caller-side `2 Re(...)` collapse in real-scalar consumers.
End-to-end on h2o-sq_mp2-x2c-631g.json: SQ_MP2 produces a 20-term Sum
(down from the 16-term raw enumeration after factoring in the antisym
expansion's 16x blowup). Energy preserved to 1 ULP. The 20-term
plateau reflects what canonicalize-via-dummy-rename can fold without
post-expansion antisym recognition or point-group symmetry filters
(which Visscher Eq. 28 relies on for its 2-term form). Going below
20 requires either a real-part collapse pass (caller-side) or
non-expanded antisym (which loses the open-shell-style structure).
fce41f5 to
9d11e50
Compare
Adds the symbolic machinery to take a closed-shell all-spinor expression
to a minimal mixed antisymm/non-antisymm Kramers-restricted form:
- RealPart / ImagPart Expr nodes + conjugate / re / im helpers
- flip_kramers + fold_conj_pairs: O(n) hash-bucketed TRS conjugate-pair
fold, (A + A*) -> 2 Re(A)
- antisymm_recombine: inverse of expand_antisymm; recombines
direct/exchange NonSymm pairs into Kramers-restricted antisymm
tensors, iterated to a fixed point
- kramers_trace_cycles: cycle-driven tracer (contraction-graph cycle
decomposition + multiset enumeration)
- kramers_trace_burnside: orbit-representative enumeration under the
antisymmetrizer index-permutation group, via bit-permutation orbits
- cycle decomposition utilities (kramers_cycles, kramers_cycle_dump,
cycle_canonical_*) for inspection and cross-validation
All three tracers feed the same fold_conj_pairs -> antisymm_recombine
pipeline and are value-equivalent; they coexist for cross-checking.
9d11e50 to
4355525
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.