Coupled-Cluster Class

Coupled-cluster (CC) theory is one of the most accurate and widely used quantum chemistry methods for describing electron correlation in molecular systems. It represents the many-electron wavefunction using an exponential ansatz:

\[|\Psi_{\text{CC}}\rangle = e^{\hat{T}}|\Phi_0\rangle\]

where \(|\Phi_0\rangle\) is a reference determinant (typically Hartree-Fock), and \(\hat{T}\) is a cluster operator that generates excited determinants. The cluster operator is typically expanded as:

\[\hat{T} = \hat{T}_1 + \hat{T}_2 + \hat{T}_3 + \ldots\]

where \(\hat{T}_n\) generates \(n\)-fold excited determinants. For computational tractability, the cluster operator is usually truncated. For example, CCSD includes only single and double excitations (\(\hat{T} = \hat{T}_1 + \hat{T}_2\)).

The CC class provides a convenient interface for setting up and processing CC equations using SeQuant’s symbolic algebra engine. It supports various CC formulations, including traditional, unitary, and orbital-optimized ansätze.

Overview

The CC class can be used to derive:

  • Ground state amplitude equations

  • λ (de-excitation) amplitude equations

  • Equation-of-motion (EOM) CC equations for excited states

  • Response equations for properties and perturbations

Expressions are generated in spin-orbital basis and can be post-processed using SeQuant’s spin-tracing capabilities. See Spin Tracing of Expressions for more details.

Ansatz Options

The CC class supports several CC ansätze through the CC::Ansatz enum:

  • Ansatz::T: Traditional CC ansatz, where the wavefunction is represented as \(|\Psi_{\text{CC}}\rangle = e^{\hat{T}}|\Phi_0\rangle\). This is the standard approach used in most implementations.

  • Ansatz::oT: Orbital-optimized traditional ansatz. Singles amplitudes (\(\hat{T}_1\)) are excluded from the cluster operator, with orbital optimization performed instead.

  • Ansatz::U: Unitary CC ansatz, where the wavefunction is represented as \(|\Psi_{\text{UCC}}\rangle = e^{\hat{T} - \hat{T}^\dagger}|\Phi_0\rangle\). Particularly useful for quantum computing applications.

  • Ansatz::oU: Orbital-optimized unitary ansatz, combines both unitary and orbital optimized ansätze.

Key Methods

Lie Similarity Transformation

ExprPtr lst(ExprPtr A, ExprPtr B, size_t r);

Returns Lie similarity transformation, \(\bar{A} = e^{-\hat{B}} \hat{A} e^{\hat{B}}\), as a series of nested commutators, \([\hat{A},\hat{B}]\), \([[\hat{A},\hat{B}],\hat{B}]\), etc., up to order r.

Ground State Amplitudes

std::vector<ExprPtr> t(size_t commutator_rank = 4,
                       size_t pmax = std::numeric_limits<size_t>::max(),
                       size_t pmin = 0);

Derives the equations for the \(t\) amplitudes (\(\langle \Phi_P|\bar{H}|\Phi_0 \rangle = 0\)) up to specified excitation levels.

std::vector<ExprPtr> λ(size_t commutator_rank = 4);

Derives the equations for the \(\lambda\) de-excitation amplitudes.

Coupled-Cluster Response

std::vector<ExprPtr> t_pt(size_t order = 1, size_t rank = 1);
std::vector<ExprPtr> λ_pt(size_t order = 1, size_t rank = 1);

Derives perturbed amplitude equations for response theory calculations.

Equation-of-Motion Coupled-Cluster

std::vector<ExprPtr> eom_r(nₚ np, nₕ nh);
std::vector<ExprPtr> eom_l(nₚ np, nₕ nh);

Derives equation-of-motion coupled-cluster (EOM-CC) equations for excited states. The eom_r method generates equations for the right eigenvectors, while eom_l generates equations for the left eigenvectors.

Examples

The following examples demonstrate how to use the CC class to derive CC equations for various ansätze and excitation levels.

From this point onward, assume the following namespaces are imported, and the sequant::Context is configured as shown.

using namespace sequant;
using namespace sequant::mbpt;
set_default_context({.index_space_registry_shared_ptr = make_min_sr_spaces(),
                     .vacuum = Vacuum::SingleProduct});

Ground State CC Amplitude Equations

// Traditional CCSD
auto t_eqs = CC{2}.t();
std::wcout << "T1: " << to_latex(t_eqs[1]) << "\n"
           << "T2: " << to_latex(t_eqs[2]) << "\n";

// Lambda equations
auto l_eqs = CC{2}.λ();
std::wcout << "λ1: " << to_latex(l_eqs[1]) << "\n"
           << "λ2: " << to_latex(l_eqs[2]) << "\n";

// Unitary CCSD
auto Ut_eqs =
    CC{2, CC::Ansatz::U}.t(4);  // Use 4th-order commutator expansion
std::wcout << "T1 (UCC): " << to_latex(Ut_eqs[1]) << "\n"
           << "T2 (UCC): " << to_latex(Ut_eqs[2]) << "\n";

// Orbital-optimized CCSD
auto oT_eqs = CC{2, CC::Ansatz::oT}.t();
std::wcout << "T2 (oT): " << to_latex(oT_eqs[2]) << "\n";

EOM-CC Equations

// EE-EOM-CCSD (excitation energy)
auto r_eqs = CC{2}.eom_r(nₚ(2), nₕ(2));
std::wcout << "R1: " << to_latex(r_eqs[1]) << "\n"
           << "R2: " << to_latex(r_eqs[2]) << "\n";

//  EE-EOM-CCSD Left eigenvectors
auto ee_l_eqs = CC{2}.eom_l(nₚ(2), nₕ(2));
std::wcout << "L1: " << to_latex(l_eqs[1]) << "\n"
           << "L2: " << to_latex(l_eqs[2]) << "\n";

// IP-EOM-CCSD (ionization potential)
auto ip_eqs = CC{2}.eom_r(nₚ(0), nₕ(1));
std::wcout << "IP-R1: " << to_latex(ip_eqs[0]) << "\n";

// EA-EOM-CCSD (electron attachment)
auto ea_eqs = CC{2}.eom_r(nₚ(1), nₕ(0));
std::wcout << "EA-R1: " << to_latex(ea_eqs[0]) << "\n";

Response and Perturbation Equations

// First-order perturbed amplitude equations
auto t_pt = CC{2}.t_pt(1, 1);
std::wcout << "T1 perturbed: " << to_latex(t_pt[1]) << "\n"
           << "T2 perturbed: " << to_latex(t_pt[2]) << "\n";

// First-order perturbed Lambda amplitude equations
auto l_pt = CC{2}.λ_pt(1, 1);
std::wcout << "λ1 perturbed: " << to_latex(l_pt[1]) << "\n"
           << "λ2 perturbed: " << to_latex(l_pt[2]) << "\n";

Advanced Usage

Truncating the Commutator Expansion

For traditional CC with two-body Hamiltonians, the commutator expansion is truncated at the a 4th-order. However, for unitary CC or other Hamiltonians, you may need to explicitly set the commutator rank:

// Unitary CCSDT with 6th-order commutator expansion
auto Ut_ccsdt = CC{3, CC::Ansatz::U}.t(6);

Spin Tracing of Expressions

Equations generated by the CC class are in spin-orbital basis. SeQuant also provides capability to transform these equations into spin-traced forms.

Make sure to include the <SeQuant/domain/mbpt/spin.hpp> header to access spin-tracing functions.

// Generate CCSD R2 equation
auto ccsd_eqs = CC{2}.t();
auto t2_eq = t_eqs[2];

// Convert to the closed-shell spin-traced form
auto t2_cs = closed_shell_CC_spintrace(t2_eq);
std::wcout << "Closed-shell spin-traced CCSD-R2: " << to_latex(t2_cs) << "\n";

// Convert to the open-shell spin-traced form
auto t2_os = open_shell_CC_spintrace(
    t2_eq);  // vector of expressions: {ɑɑ, ɑβ, ββ} blocks
std::wcout << "Open-shell spin-traced CCSD-R2:\n";
for (const auto& eq : t2_os) {
  std::wcout << to_latex(eq) << "\n";
}