Spin Tracing¶
Equations derived by SeQuant’s Wick’s theorem machinery and the CC equation generator are, by default, expressed in a spin-orbital basis: every index implicitly ranges over spin-up (\(\alpha\)) and spin-down (\(\beta\)) single-particle states alike. For a spin-unrestricted (open-shell) reference that is exactly what is needed. For a spin-restricted, closed-shell reference, however, the spin degrees of freedom can be summed out analytically, yielding a smaller set of equations over spatial orbitals alone — a transformation commonly called spin tracing or spin adaptation. This is a standard step in deriving efficient closed-shell coupled-cluster and many-body perturbation theory equations for quantum chemistry.
The mbpt::Spin quantum number¶
Spin is represented as an ordinary index space quantum number, sequant::mbpt::Spin (alpha, beta, or
any/none for “unspecified/spin-free”), attached to an sequant::Index through its sequant::IndexSpace. Helper
functions such as sequant::mbpt::make_spinalpha(), sequant::mbpt::make_spinbeta(), and sequant::mbpt::to_spin()
add, change, or query this quantum number on individual indices:
// Spin quantum numbers can also be inspected/attached to individual
// indices directly, e.g. when interpreting an already spin-orbital
// expression by hand
Index i1_up = make_spinalpha(i1);
SEQUANT_ASSERT(to_spin(i1_up.space().qns()) == Spin::alpha);
Tracing spin out of an expression¶
Rather than manipulating spin labels index-by-index, the usual entry point is sequant::mbpt::spintrace(): given a spin-orbital
expression, it sums over the spin cases of its internal indices and returns the spin-free (spatial-orbital) result. In the simplest case
— where none of the involved index spaces are already split into separate alpha/beta subspaces — this amounts to summing the (identical)
spin-conserving contributions:
// register the standard occupied/virtual spaces used in single-reference
// quantum chemistry (see the User Guide's "Context and configuration" page)
load(Convention::SR);
Index i1(L"i_1"), a1(L"a_1");
TensorSymmetries particle_symmetric{.column = ColumnSymmetry::Symm};
// a spin-orbital expression: indices carry no explicit spin label, so each
// one implicitly ranges over both alpha and beta spin-orbitals
auto expr = ex<Tensor>(L"t", bra{i1}, ket{a1}, particle_symmetric) *
ex<Tensor>(L"F", bra{a1}, ket{i1}, particle_symmetric);
// spintrace() sums a spin-orbital expression over spin, producing its
// spin-free (spatial-orbital) form; the summation over the 2 spin cases
// that agree with each other produces the factor of 2 below
auto expr_st = spintrace(expr);
simplify(expr_st);
std::wcout << expr_st << std::endl;
Specialized variants exist for the more demanding cases that arise in practice:
sequant::mbpt::closed_shell_spintrace()is a more efficient alternative tospintracespecifically for closed-shell (spin-restricted) references, avoiding the exponential cost of the general algorithm.sequant::mbpt::closed_shell_CC_spintrace()additionally transforms the traced result into biorthogonal form, the representation typically wanted for closed-shell coupled-cluster equations (see Coupled-Cluster Class); it also factors out and re-applies the necessary (anti)symmetrizers.sequant::mbpt::open_shell_spintrace()andsequant::mbpt::open_shell_CC_spintrace()produce, instead of a single spin-free result, one expression per distinct spin case, appropriate for an unrestricted (open-shell) reference.
All of these expect their input to already be in a specific normal form (a leading antisymmetrizer, produced by “complete”
canonicalization — see Canonicalization, unless the expression doesn’t have any external indices (e.g. energy expressions)); consult their
reference documentation for the exact preconditions and options before using them on a new class of equations. For a worked example applying
closed_shell_CC_spintrace/open_shell_CC_spintrace to actual coupled-cluster amplitude equations, see Spin Tracing of Expressions in the Coupled-Cluster Class
page.