Specifying symmetry#

YASTN specifies symmetry through any object that is a plain Python module or class which defines

  1. SYM_ID string label specyfying the symmetry

  2. NSYM number of elements in the charge vector. For example, NSYM=1 for \(U(1)\) or \(Z_2\) group. For product groups such as \(U(1)\times U(1)\), NSYM=2

  3. fuse function that specifies the addition of charges

Parent class for defining symmetry rules.

class yastn.sym.sym_abelian.sym_abelian[source]#

Interface to be subclassed for concrete symmetry implementations.

classmethod add_charges(*charges, signatures=None, new_signature=1) tuple[int, ...][source]#

Auxiliary function for adding tensor charges. It employs fuse() function and returns resulting charge as a tuple of integers.

Parameters:
  • charges (Sequence[tuple[int, …]]) – Sequence of charges to be added.

  • signatures (None | Sequence[int]) – Signature for provided charges. The default None uses signature 1 for all charges.

  • new_signature (int) – Signature for the addition result. The default is 1.

classmethod fuse(charges, signatures, new_signature) ndarray[int64][source]#

Fusion rule for abelian symmetry.

An i-th row charges[i,:,:] contains m length-NSYM charge vectors, where m is the number of legs being fused. For each row, the charge vectors are added up (fused) with selected signatures according to the group addition rules.

Parameters:
  • charges (np.ndarray[int]) – \(k \times m \times nsym\) matrix, where \(k\) is the number of independent blocks, and \(m\) is the number of fused legs.

  • signatures (np.ndarray[int]) – integer vector with \(m\) elements in \({-1, +1}\).

  • new_signature (int) – new signature for a new leg from fused legs.

Returns:

matrix of integers with shape (k, NSYM) of fused charges; includes multiplication by new_signature.

Return type:

np.ndarray[int]

classmethod zero() tuple[int, ...][source]#

Zero charge.

Example symmetries defined in YASTN#

  • \(U(1)\) symmetry

class sym_U1(sym_abelian):
    """U1 symmetry"""

    SYM_ID = 'U1'
    NSYM = 1  # single int is used to distinguish symmetry sectors

    @classmethod
    def fuse(cls, charges, signatures, new_signature):
        """ Fusion rule for U1 symmetry. """
        return new_signature * (charges.swapaxes(1, 2) @ signatures)
  • \(Z_2\) symmetry

class sym_Z2(sym_abelian):
    """Z2 symmetry"""

    SYM_ID = 'Z2'
    NSYM = 1  # single int is used to distinguish symmetry sectors

    @classmethod
    def fuse(cls, charges, signatures, new_signature):
        """ Fusion rule for Z2 symmetry. """
        return np.mod(new_signature * (charges.swapaxes(1, 2) @ signatures), 2)
  • \(Z_2\times U(1)\)

class sym_Z2xU1(sym_abelian):
    """ Z2xU1 symmetry"""

    SYM_ID = "Z2xU1"
    NSYM = 2

    def fuse(charges, signatures, new_signature):
        """ Fusion rule for Z2xU1 symmetry. """
        teff = new_signature * (charges.swapaxes(1,2) @ signatures)
        teff[:, 0] = np.mod(teff[:, 0], 2)
        return teff