Symmetric tensors in Cc4s

Table of Contents

1. Symmetries of tensors reading and writing

The storage and loading time of tensors can be reduced if the elements exhibit symmetries. If symmetries are considered the layout of the elements changes such that only symmetrically distinct elements are stored. The remaining elements are generated automatically by the given symmetry operation. Element-wise symmetry operations can be complex rotations, including the identity, and complex conjugations. A tensor can have multiple symmetries. The product of all powers form the entire symmetry group.

The storage layout of the elements in the tensor elements file, in binary or text, derives from the usual storage layout, ordered by the global index \(g = i_0 + L_0 (i_1 + L_1 i_2 \ldots )\) where \(i_0,\ldots\) are the tensor indices from left to right and \(L_0,\ldots\) are the corresponding index lengths. Let \(g'_\tau(g)\) be the image of the global index \(g\) under under the permutation \(\tau\) applied to the indices \(i_0,\ldots\), encoded in \(g\). The only elements kept in the storage layout are those with the smallest global index \(g'_\tau\) under all symmetry operation \(\tau\). The elements of these indices are the representative elements. The elements of the other indices are automatically generated.

For example, consider the following anti-symmetric \(3\times3\) matrix

\begin{equation*} A = \left( \begin{array}{rrr} 0 & -1 & +3 \\ +1 & 0 & -2 \\ -3 & +2 & 0 \end{array} \right). \end{equation*}

Using the Fortran convention for the matrix-vector product \(A[i,j]*v[j]\) we have a column-major layout and the global indices are as follows:

\begin{equation*} \left( \begin{array}{rrr} 0 & 3 & 6 \\ 1 & 4 & 7 \\ 2 & 5 & 8 \end{array} \right). \end{equation*}

The elements with the following global indices are related by the anti-sytmmetry: \(0\leftrightarrow 0\), \(1\leftrightarrow 3\), \(2\leftrightarrow 6\), \(4\leftrightarrow 4\), \(5\leftrightarrow 7\), and \(8\leftrightarrow 8\). Taking always the smallest global index, we arrive at the sorted global index list of the representative elements: \(0,1,2,4,5,8\). Thus, the six elements corresponding to these indices are stored and the elements file contains the numbers \(0,+1,-3,0,+2,0\), i.e. the lower-left part of the matrix. Note that also the zero elements are stored, although the value can only be 0, the only fixpoint of a 180 degrees rotation. In general, the set of fixpoints can be non-trivial, e.g. the real axis for complex conjugation. The additional memory consumption is negligible for larger tensors.

To tell Cc4s that the elements of a tensor are packed with respect to a symmetry, the symmetries must be entered in the symmetries entries in the descriptive yaml file. For the above anti-symmetric matrix there would be one entry:

symmetries:                             # generators of symmetries respected for storing
  - indexPermutation: [1,0]             # transposition the two indices
    order: 2                            # redundant, only used for checking
    elementsOperation: complexRotation  # rotate by 2nd roots of unity: -1
    operationPower: 1                   # use 1st power for each permutation: -1
                                        # use power 0 if symmetric not anti-symmetric

As a more complicated example, consider the anti-symmetry of the unrestricted doubles-amplitudes. This tensor is anti-symmetric with respect to the transposition of the first two indices and with respect to the transposition of the last two indices. There are two generators of the symmetry and the entries in the descriptive yaml file would be

symmetries:                             # generators of symmetries respected for storing
  - indexPermutation: [1,0,2,3]         # transposition the first two indices
    order: 2                            # redundant, only used for checking
    elementsOperation: complexRotation  # rotate by 2nd roots of unity: -1
    operationPower: 1                   # use 1st power for each permutation: -1
  - indexPermutation: [0,1,3,2]         # transposition the last two indices
    order: 2                            # redundant, only used for checking
    elementsOperation: complexRotation  # rotate by 2nd roots of unity: -1
    operationPower: 1                   # use 1st power for each permutation: -1

The entire symmetry group has 4 elements and consists of the four permutations \((0,1,2,3), (1,0,2,3), (0,1,3,2), (1,0,3,2)\) with the multiplication operations \(+1,-1,-1,+1\), respectively. Only a bit more than a fourth of the elements is stored, the other elements follow by symmetry.

As a last example, consider the symmetry of the closed-shell doubles-amplitudes. This tensor is symmetric only with respect to the simultaneous transposition of the first two indices and the last two indices. There is one generator of the symmetry and the entries in the descriptive yaml file would be

symmetries:                             # generators of symmetries respected for storing
  - indexPermutation: [1,0,3,2]         # simultaneous transposition two pairs of indices
    order: 2                            # redundant, only used for checking
    elementsOperation: complexRotation  # rotate by 2nd roots of unity: -1
    operationPower: 0                   # use 0th power for each permutation: +1

Index permutations with higher orders are possible, for example order three of the permutation \((1,2,0)\). They are only supported for the complexRotation operation corresponding to a complex rotation by 120 degrees, i.e. a multiplication by a third root of unity.

Each symmetry generator is described by the following fields

indexPermutation
The image of each index under the permutation under consideration. E.g. a 1 as the first element indicates that the first index (0) will be mapped to the second index (1) by the permutation.
order
The order \(n\) is the lowest non-zero number of repeated applications of the given indexPermutation to arrive at the identity permutation \((0,1,\ldots)\). Although order can be computed from the indexPermutation it must be given for redundancy.
elementOperation
Specifies how the tensor elements transform under the given indexPermutation. Can be complexRotation or complexConjugation. For complexConjugation the elements transform as \(z \mapsto \overline{z}\) for odd powers as specified below and the order of the permutations must be \(2\), i.e. a transposition. For complexRotation the order \(n\) can be arbitrary and the generally complex operation is given by \(z \mapsto z\, e^{2\pi i k/n}\), where \(k\) is the operationPower.
operationPower
Specifies the power \(k\) in the above equation for complexRotation. For the operation complexConjugation any odd power corresponds to the complex conjugation \(z \mapsto \overline{z}\) while every even power corresponds to the identity \(z \mapsto z\). Common combinations of elementOperation and operationPower \(k\) are: either complexRotation or complexConjugation with \(k=0\) for symmetric tensors, complexRotation with \(k=1\) for anti-symmetric tensors, and complexConjugation with \(k=1\) for hermitian tensors.

2. Reading symmetry packed tensors

The following sanity checks are currently NOT done while reading symmetry packed tensors:

  • The size of the elements file corresponds to the number of representative elements. E.g. 6 doubles for a \(3\times 3\) anti-symmetric of 64 bit doubles. Loading may crash otherwise.
  • The lengths and types of permuted index dimensions agree. Loading may crash otherwise.
  • The order of the given permutation agrees with the specified order. The specified order is ignored.
  • Complex rotations with orders \(n\) greater two are only applicable to complex tensor types. Currently, a multiplication with the real part of \(e^{2\pi i k/n}\) is used for real tensors, which does not yield the identity after \(n\) applications.
  • Elements of fix points of the index permutation are in the set of fix points of the specified symmetry operation. E.g. elements on the diagonal of a hermitian matrix are expected to be real. If they are not the read tensor will not exhibit the specified symmetry.

3. Writing symmetry packed tensors

When writing a tensor exhibiting symmetries you need to specify the symmetries that should be taken into consideration for storing as argument of the =Write+ algorithm. The following sanity checks are currently NOT done while writing symmetry packed tensors.

Created: 2024-09-16 Mon 13:59