OpSum
Object representing a generic many-body operator by a sum of operators of the form $$ \mathcal{O} = \sum_i c_i \mathcal{O}_i. $$
Sources: opsum.hpp ยท opsum.cpp
An OpSum is consists of a sum of pairs given by
-
A coupling constant \(c_i\) which is given by a either a string name or a real/complex number.
-
An operator \(\mathcal{O}_i\) defined by an Op object.
Generically, an OpSum can thus have coupling constants defined by either strings or numerical real/complex numbers. We call an OpSum plain if its couplings are only numerical numbers, and not strings. String couplings can be defined by using the access operator[]. If all string coupling constants are defined, the OpSum can be converted to a plain OpSum using the plain method shown below.
Thus, OpSums can be defined independently of the numerical values of the coupling constants, e.g. in an input file. Upon execution of the code, these constants can then be set. Most operations in XDiag require the OpSum to be convertible to a plain OpSum.
OpSums can be added and subtracted, as well as multiplied with and divided by a scalar value, i.e. a real or complex number. In addition, two OpSums can be multiplied with one another, forming the (generally non-commutative) product of the two operators. Together, these operations turn the set of OpSums into an algebra. Complemented by the Hermitian conjugation hc, which is an involution satisfying \((\mathcal{A}\mathcal{B})^\dagger = \mathcal{B}^\dagger\mathcal{A}^\dagger\), the OpSums form an involutive algebra (\(*\)-algebra).
Constructors
The following constructors create an OpSum with a single pair of coupling and operator. Additional terms can be added using the + and += operators explained further below. If no coupling is given, a numerical coefficient of 1.0 is assumed.
| Parameter | Description | Default |
|---|---|---|
| coupling | A coupling which is either a string or a real/complex number | 1.0 |
| op | An Op which describes the type of operator |
Alternatively, an OpSum can also be constructed via the * operator, for example:
Complex couplings
XDiag allows all couplings to be complex. A complex coupling always acts as a plain prefactor \(c\) multiplying the operator. Under Hermitian conjugation with hc, the coupling is complex-conjugated to \(c^*\) (while the operator type is mapped to its Hermitian-conjugate partner, e.g. \(\mathrm{hc}(S^+) = S^-\)),
Consequently, a complex coupling generally turns a Hermitian operator into a non-Hermitian one. This holds for all operator types, including hopping (Hop, Hopup, Hopdn) and exchange (Exchange) terms: a complex coupling on such a term is not invariant under hc. To build a Hermitian operator from a complex coupling, add the Hermitian conjugate explicitly, e.g. ops + hc(ops).
Changed in version 0.5
Prior to version 0.5, the hopping (Hop, Hopup, Hopdn) and exchange (Exchange) operators were defined to be Hermitian even in the presence of a complex coupling, i.e. the coupling entered as \(t\,c^\dagger_i c_j + t^* c^\dagger_j c_i\). This convention was changed, because with it the OpSum objects would not form an algebra. Since then, a complex coupling is a plain prefactor as described above. To obtain the antisymmetric (non-Hermitian) hopping and exchange terms, the dedicated operator types HopAsym and ExchangeAsym (as well as the spin-resolved HopupAsym and HopdnAsym) were introduced.
Methods
plain
Converts an OpSum with possible string couplings to an OpSum with purely numerical real/complex couplings.
operator* (Creation)
Creates an OpSum with a single pair of coupling constant and an Op object.
operator+ / operator +=
Adds two OpSum objects \(\mathcal{A} = \sum_i a_i \mathcal{A}_i\) and \(\mathcal{B} = \sum_i b_i \mathcal{B}_i\) to for the sum of the two operators, $$ \mathcal{A} + \mathcal{B} = \sum_i a_i \mathcal{A}_i + \sum_i b_i \mathcal{B}_i$$
operator- / operator -=
Subtracts to OpSum objects.
operator* , operator/ (scalar muliplication/division)
Multiplies an OpSum \(\mathcal{A} = \sum_i a_i \mathcal{A}_i\) with a scalar \(b\) to form
Base.:*(coupling::Int64, ops::OpSum)::OpSum
Base.:*(coupling::Float64, ops::OpSum)::OpSum
Base.:*(coupling::ComplexF64, ops::OpSum)::OpSum
Base.:*(ops::OpSum, coupling::Int64)::OpSum
Base.:*(ops::OpSum, coupling::Float64)::OpSum
Base.:*(ops::OpSum, coupling::ComplexF64)::OpSum
Base.:/(ops::OpSum, coupling::Int6464)::OpSum
Base.:/(ops::OpSum, coupling::Float64)::OpSum
Base.:/(ops::OpSum, coupling::ComplexF64)::OpSum
OpSum &operator*=(int64_t scalar);
OpSum &operator*=(double scalar);
OpSum &operator*=(complex scalar);
OpSum &operator/=(int64_t scalar);
OpSum &operator/=(double scalar);
OpSum &operator/=(complex scalar);
OpSum operator*(int64_t scalar, OpSum const &op);
OpSum operator*(double scalar, OpSum const &op);
OpSum operator*(complex scalar, OpSum const &op);
OpSum operator*(OpSum const &op, double scalar);
OpSum operator*(OpSum const &op, int64_t scalar);
OpSum operator*(OpSum const &op, complex scalar);
OpSum operator/(OpSum const &op, int64_t scalar);
OpSum operator/(OpSum const &op, double scalar);
OpSum operator/(OpSum const &op, complex scalar);
operator* (algebra product)
Multiplies two OpSum objects \(\mathcal{A} = \sum_i a_i \mathcal{A}_i\) and \(\mathcal{B} = \sum_j b_j \mathcal{B}_j\) to form their operator product, distributing over the sums,
The product is generally non-commutative, reflecting that quantum mechanical operators need not commute. It can be used to build composite operators, e.g. correlation functions or powers of a Hamiltonian, from elementary building blocks.
operator[]
Sets a coupling constant defined as a string to a numerical value.
isreal
Returns whether an OpSum is a real operator.
to_string (operator<<)
Converts the OpSum to a readable string representation.
Usage Example
// Define the 1D transverse-field Ising chain
int N = 12;
double J = 1.0;
double h = 0.5;
auto Sx = arma::mat("0 1; 1 0");
// Option 1: coupling constants as numbers
auto ops1 = OpSum();
for (int i = 0; i<N; ++i) {
ops1 += J * Op("SzSz", {i, (i+1)%N});
ops1 += h * Op("Matrix", i, Sx);
}
// Option 2: coupling constants as strings
auto ops2 = OpSum();
for (int i = 0; i<N; ++i) {
ops2 += "J" * Op("SzSz", {i, (i+1)%N});
ops2 += "h" * Op("Matrix", i, Sx);
}
ops2["J"] = J;
ops2["h"] = h;