Dense and sparse tensors (C code)

Dense tensors

Dense tensor structure, using row-major storage convention.

Enums

enum tensor_axis_range

Tensor axis alignment, used to specify multiplication.

Values:

enumerator TENSOR_AXIS_RANGE_LEADING

leading tensor axes

enumerator TENSOR_AXIS_RANGE_TRAILING

trailing tensor axes

enumerator TENSOR_AXIS_RANGE_NUM

number of tensor axis alignment modes

enum qr_mode

QR and RQ decomposition mode.

Values:

enumerator QR_REDUCED

matrix dimension between ‘q’ and ‘r’ is the minimum of the dimensions of ‘a’

enumerator QR_COMPLETE

‘q’ is a square unitary matrix

enumerator QR_NUM_MODES

number of decomposition modes

Functions

void allocate_dense_tensor(const enum numeric_type dtype, const int ndim, const ct_long *dim, struct dense_tensor *t)

Allocate memory for a dense tensor, and initialize the data entries with zeros.

void delete_dense_tensor(struct dense_tensor *t)

Delete a dense tensor (free memory).

void copy_dense_tensor(const struct dense_tensor *src, struct dense_tensor *dst)

Copy a tensor, allocating memory for the copy.

static inline ct_long dense_tensor_num_elements(const struct dense_tensor *t)

Calculate the number of elements of a dense tensor.

ct_long dense_tensor_num_nonzero_elements(const struct dense_tensor *t)

Count the number of non-zero elements of a dense tensor.

static inline ct_long tensor_index_to_offset(const int ndim, const ct_long *dim, const ct_long *index)

Convert tensor index to data offset.

static inline void offset_to_tensor_index(const int ndim, const ct_long *dim, const ct_long offset, ct_long *index)

Convert data offset to tensor index.

static inline void next_tensor_index(const int ndim, const ct_long *dim, ct_long *index)

Compute the lexicographically next tensor index.

void dense_tensor_trace(const struct dense_tensor *t, void *ret)

Compute the ‘trace’ of a tensor (generalization of the matrix trace); all dimensions of the tensor must agree.

void dense_tensor_cyclic_partial_trace(const struct dense_tensor *t, const int ndim_trace, struct dense_tensor *r)

Compute the “cyclic” partial trace, by tracing out the ‘ndim_trace’ leading with the ‘ndim_trace’ trailing axes.

void dense_tensor_cyclic_partial_trace_update(const struct dense_tensor *t, const int ndim_trace, struct dense_tensor *r)

Compute the “cyclic” partial trace, by tracing out the ‘ndim_trace’ leading with the ‘ndim_trace’ trailing axes, and add result to ‘r’.

‘r’ must have been allocated beforehand.

double dense_tensor_norm2(const struct dense_tensor *t)

Compute the 2-norm (Frobenius norm) of the tensor.

Result is returned as double also for single-precision tensor entries.

void scale_dense_tensor(const void *alpha, struct dense_tensor *t)

Scale tensor ‘t’ by ‘alpha’, which must be of the same data type as the tensor entries.

void rscale_dense_tensor(const void *alpha, struct dense_tensor *t)

Scale tensor ‘t’ by a real number ‘alpha’, which must be of the same precision as the tensor entries.

void reshape_dense_tensor(const int ndim, const ct_long *dim, struct dense_tensor *t)

Reshape dimensions, i.e., interpret as tensor of different dimension with the same number of elements.

void conjugate_dense_tensor(struct dense_tensor *t)

Elementwise complex conjugation of a dense tensor.

Function has no effect if entries are real-valued.

void dense_tensor_flatten_axes(struct dense_tensor *t, const int i_ax)

Flatten the two neighboring axes (tensor legs) ‘i_ax’ and ‘i_ax + 1’ into a single axis.

void dense_tensor_set_identity(struct dense_tensor *t)

Set the tensor to the identity operator; all dimensions of the tensor must agree.

void dense_tensor_fill_random_normal(const void *alpha, const void *shift, struct rng_state *rng_state, struct dense_tensor *t)

Fill a dense tensor with random normal entries.

void dense_tensor_transpose(const int *perm, const struct dense_tensor *t, struct dense_tensor *r)

Generalized transpose of a tensor ‘t’ such that the i-th axis in the output tensor ‘r’ is the perm[i]-th axis of the input tensor ‘t’.

Memory will be allocated for ‘r’.

void dense_tensor_conjugate_transpose(const int *perm, const struct dense_tensor *t, struct dense_tensor *r)

Generalized conjugate transpose of a tensor ‘t’ such that the i-th axis in the output tensor ‘r’ is the perm[i]-th axis of the input tensor ‘t’.

Memory will be allocated for ‘r’.

void dense_tensor_slice(const struct dense_tensor *t, const int i_ax, const ct_long *ind, const ct_long nind, struct dense_tensor *r)

Slice an axis of the tensor by selecting logical indices ‘ind’ along this axis.

Indices ‘ind’ can be duplicate and need not be sorted. Memory will be allocated for ‘r’.

void dense_tensor_slice_fill(const struct dense_tensor *t, const int i_ax, const ct_long *ind, const ct_long nind, struct dense_tensor *r)

Slice an axis of the tensor by selecting indices ‘ind’ along this axis.

Indices ‘ind’ can be duplicate and need not be sorted. ‘r’ must have been allocated beforehand.

void dense_tensor_pad_zeros(const struct dense_tensor *t, const ct_long *pad_before, const ct_long *pad_after, struct dense_tensor *r)

Pad a tensor with zeros according to the specified leading and trailing padding width for each axis.

void dense_tensor_scalar_multiply_add(const void *alpha, const struct dense_tensor *s, struct dense_tensor *t)

Scalar multiply and add two tensors: t = alpha*s + t; dimensions and data types of s and t must agree, and alpha must be of the same data type as tensor entries.

void dense_tensor_multiply_pointwise(const struct dense_tensor *s, const struct dense_tensor *t, const enum tensor_axis_range axrange, struct dense_tensor *r)

Pointwise multiplication of two tensors, using broadcasting. The output tensor ‘r’ has the same data type and dimension as ‘s’. The dimensions of ‘s’ and ‘t’ (starting from the leading or trailing dimension depending on ‘axrange’) must match.

Memory will be allocated for ‘r’.

void dense_tensor_multiply_pointwise_fill(const struct dense_tensor *s, const struct dense_tensor *t, const enum tensor_axis_range axrange, struct dense_tensor *r)

Pointwise multiplication of two tensors, using broadcasting. The output tensor ‘r’ has the same data type and dimension as ‘s’. The dimensions of ‘s’ and ‘t’ (starting from the leading or trailing dimension depending on ‘axrange’) must match.

‘r’ must have been allocated beforehand.

void dense_tensor_multiply_axis(const struct dense_tensor *s, const int i_ax, const struct dense_tensor *t, const enum tensor_axis_range axrange_t, struct dense_tensor *r)

Multiply the ‘i_ax’ axis of ‘s’ with the leading or trailing axis of ‘t’, preserving the overall dimension ordering of ‘s’.

void dense_tensor_multiply_axis_update(const void *alpha, const struct dense_tensor *s, const int i_ax, const struct dense_tensor *t, const enum tensor_axis_range axrange_t, const void *beta, struct dense_tensor *r)

Multiply the ‘i_ax’ axis of ‘s’ with the leading or trailing axis of ‘t’, preserving the overall dimension ordering of ‘s’, scale by ‘alpha’ and add result to ‘r’ scaled by beta: r <- alpha * s @ t + beta * r.

Assuming that ‘r’ has the appropriate dimensions.

void dense_tensor_dot(const struct dense_tensor *s, const enum tensor_axis_range axrange_s, const struct dense_tensor *t, const enum tensor_axis_range axrange_t, const int ndim_mult, struct dense_tensor *r)

Multiply (leading or trailing) ‘ndim_mult’ axes in ‘s’ by ‘ndim_mult’ axes in ‘t’, and store result in ‘r’. Whether to use leading or trailing axes is specified by axis range.

Memory will be allocated for ‘r’.

void dense_tensor_dot_update(const void *alpha, const struct dense_tensor *s, const enum tensor_axis_range axrange_s, const struct dense_tensor *t, const enum tensor_axis_range axrange_t, const int ndim_mult, const void *beta, struct dense_tensor *r)

Multiply (leading or trailing) ‘ndim_mult’ axes in ‘s’ by ‘ndim_mult’ axes in ‘t’, scale by ‘alpha’ and add result to ‘r’ scaled by beta: r <- alpha * s @ t + beta * r. Whether to use leading or trailing axes is specified by axis range.

Assuming that ‘r’ has the appropriate dimensions.

void dense_tensor_kronecker_product(const struct dense_tensor *s, const struct dense_tensor *t, struct dense_tensor *r)

Compute the Kronecker product of two tensors; the tensors must have the same degree.

void dense_tensor_concatenate(const struct dense_tensor *tlist, const int num_tensors, const int i_ax, struct dense_tensor *r)

Concatenate tensors along the specified axis. All other dimensions must respectively agree.

void dense_tensor_concatenate_fill(const struct dense_tensor *tlist, const int num_tensors, const int i_ax, struct dense_tensor *r)

Concatenate tensors along the specified axis. All other dimensions must respectively agree.

‘r’ must have been allocated beforehand with the correct data type and dimensions.

void dense_tensor_block_diag(const struct dense_tensor *tlist, const int num_tensors, const int *i_ax, const int ndim_block, struct dense_tensor *r)

Compose tensors along the specified axes, creating a block-diagonal pattern. All other dimensions must respectively agree.

void dense_tensor_block_diag_fill(const struct dense_tensor *tlist, const int num_tensors, const int *i_ax, const int ndim_block, struct dense_tensor *r)

Compose tensors along the specified axes, creating a block-diagonal pattern. All other dimensions must respectively agree.

‘r’ must have been allocated beforehand with the correct data type and dimensions.

int dense_tensor_qr(const struct dense_tensor *a, const enum qr_mode mode, struct dense_tensor *q, struct dense_tensor *r)

Compute the QR decomposition of the matrix ‘a’, and store the result in ‘q’ and ‘r’ (will be allocated).

int dense_tensor_qr_fill(const struct dense_tensor *a, const enum qr_mode mode, struct dense_tensor *q, struct dense_tensor *r)

Compute the QR decomposition of the matrix ‘a’, and store the result in ‘q’ and ‘r’, which must have been allocated beforehand.

int dense_tensor_rq(const struct dense_tensor *a, const enum qr_mode mode, struct dense_tensor *r, struct dense_tensor *q)

Compute the RQ decomposition (upper triangular times isometry) of the matrix ‘a’, and store the result in ‘r’ and ‘q’ (will be allocated).

int dense_tensor_rq_fill(const struct dense_tensor *a, const enum qr_mode mode, struct dense_tensor *r, struct dense_tensor *q)

Compute the RQ decomposition (upper triangular times isometry) of the matrix ‘a’, and store the result in ‘r’ and ‘q’, which must have been allocated beforehand.

int dense_tensor_eigh(const struct dense_tensor *a, struct dense_tensor *u, struct dense_tensor *lambda)

Compute the eigenvalues and -vectors of a (real symmetric or complex Hermitian) matrix ‘a’, and store the result in ‘u’ and ‘lambda’ (will be allocated). The eigenvalues are real and returned as vector.

int dense_tensor_eigh_fill(const struct dense_tensor *a, struct dense_tensor *u, struct dense_tensor *lambda)

Compute the eigenvalues and -vectors of a (real symmetric or complex Hermitian) matrix ‘a’, and store the result in ‘u’ and ‘lambda’, which must have been allocated beforehand. The eigenvalues are real and returned as vector.

int dense_tensor_svd(const struct dense_tensor *a, struct dense_tensor *u, struct dense_tensor *s, struct dense_tensor *vh)

Compute the “economical” SVD decomposition of the matrix ‘a’, and store the result in ‘u’, ‘s’ and ‘vh’ (will be allocated). The singular values ‘s’ are returned as vector.

int dense_tensor_svd_fill(const struct dense_tensor *a, struct dense_tensor *u, struct dense_tensor *s, struct dense_tensor *vh)

Compute the “economical” SVD decomposition of the matrix ‘a’, and store the result in ‘u’, ‘s’ and ‘vh’, which must have been allocated beforehand. The singular values ‘s’ are returned as vector.

void dense_tensor_block(const struct dense_tensor *t, const ct_long *sdim, const ct_long **idx, struct dense_tensor *r)

Extract the sub-block with dimensions ‘bdim’ by taking elements indexed by ‘idx’ along each dimension from the original tensor ‘t’; the degree remains the same as in ‘t’.

bool dense_tensor_allclose(const struct dense_tensor *s, const struct dense_tensor *t, const double tol)

Test whether two dense tensors agree elementwise within tolerance ‘tol’.

bool dense_tensor_is_zero(const struct dense_tensor *t, const double tol)

Test whether a dense tensors is entrywise zero within tolerance ‘tol’.

To test whether the tensor is exactly zero, set ‘tol = 0.0’.

bool dense_tensor_is_identity(const struct dense_tensor *t, const double tol)

Test whether a dense tensors is close to the identity matrix within tolerance ‘tol’.

bool dense_tensor_is_self_adjoint(const struct dense_tensor *t, const double tol)

Test whether a dense tensors is self-adjoint (a real symmetric or complex Hermitian matrix) within tolerance ‘tol’.

bool dense_tensor_is_isometry(const struct dense_tensor *t, const double tol, const bool transpose)

Test whether a dense tensors is an isometry within tolerance ‘tol’.

struct dense_tensor
#include <dense_tensor.h>

General dense tensor structure.

Public Members

void *data

data entries, array of dimension dim[0] x … x dim[ndim-1]

ct_long *dim

dimensions (width, height, …)

enum numeric_type dtype

numeric data type

int ndim

number of dimensions (degree)

Block-sparse tensors

Quantum numbers and corresponding utility functions.

Typedefs

typedef int32_t qnumber

Quantum number type for exploiting U(1) symmetries (like particle number or spin conservation).

For half-integer quantum numbers like spins, we store the physical quantum number times 2 to avoid rounding issues.

Enums

enum tensor_axis_direction

Tensor axis direction (orientation), equivalent to endowing quantum numbers with a sign factor.

Values:

enumerator TENSOR_AXIS_IN
enumerator TENSOR_AXIS_OUT

Functions

bool qnumber_all_equal(const ct_long n, const qnumber *qnums0, const qnumber *qnums1)

Test whether two arrays of quantum numbers match entrywise.

static inline qnumber qmin(const qnumber a, const qnumber b)

Minimum of two quantum numbers.

static inline qnumber qmax(const qnumber a, const qnumber b)

Maximum of two quantum numbers.

static inline qnumber encode_quantum_number_pair(const qnumber qa, const qnumber qb)

Encode a pair of quantum numbers into a single quantum number.

static inline void decode_quantum_number_pair(const qnumber qnum, qnumber *qa, qnumber *qb)

Decode a quantum number into two separate quantum numbers.

void qnumber_outer_sum(const int sign0, const qnumber *qnums0, const ct_long n0, const int sign1, const qnumber *qnums1, const ct_long n1, qnumber *ret)

Enumerate all pairwise sums of tuples formed from the provided quantum number arrays.

Block-sparse tensor structure.

Functions

void allocate_block_sparse_tensor(const enum numeric_type dtype, const int ndim, const ct_long *dim, const enum tensor_axis_direction *axis_dir, const qnumber **qnums, struct block_sparse_tensor *t)

Allocate memory for a block-sparse tensor, including the dense blocks for conserved quantum numbers.

void allocate_block_sparse_tensor_like(const struct block_sparse_tensor *s, struct block_sparse_tensor *t)

Allocate memory for a block-sparse tensor of the same type, dimensions, and quantum numbers as the provided tensor.

void delete_block_sparse_tensor(struct block_sparse_tensor *t)

Delete a block-sparse tensor (free memory).

void copy_block_sparse_tensor(const struct block_sparse_tensor *src, struct block_sparse_tensor *dst)

Copy a block-sparse tensor, allocating memory for the copy.

struct dense_tensor *block_sparse_tensor_get_block(const struct block_sparse_tensor *t, const qnumber *qnums)

Retrieve a dense block based on its quantum numbers.

void block_sparse_tensor_cyclic_partial_trace(const struct block_sparse_tensor *t, const int ndim_trace, struct block_sparse_tensor *r)

Compute the “cyclic” partial trace, by tracing out the ‘ndim_trace’ leading with the ‘ndim_trace’ trailing axes.

double block_sparse_tensor_norm2(const struct block_sparse_tensor *t)

Compute the 2-norm (Frobenius norm) of the tensor.

Result is returned as double also for single-precision tensor entries.

void block_sparse_tensor_reverse_axis_directions(struct block_sparse_tensor *t)

Reverse the tensor axis directions.

Reversing the axis directions does not affect the block sparsity structure.

void block_sparse_tensor_invert_axis_quantum_numbers(struct block_sparse_tensor *t, const int i_ax)

Flip the signs of the quantum numbers associated with a single tensor axis and reverse the direction of this axis.

void scale_block_sparse_tensor(const void *alpha, struct block_sparse_tensor *t)

Scale tensor ‘t’ by ‘alpha’.

Data types of all blocks and of ‘alpha’ must match.

void rscale_block_sparse_tensor(const void *alpha, struct block_sparse_tensor *t)

Scale tensor ‘t’ by a real number ‘alpha’.

Data type precision of all blocks and of ‘alpha’ must match.

void conjugate_block_sparse_tensor(struct block_sparse_tensor *t)

Elementwise conjugation of a block-sparse tensor.

void block_sparse_tensor_set_identity_blocks(struct block_sparse_tensor *t)

Set the dense blocks of the tensor to identity matrices, requiring same dimensions for quantum numbers appearing on both axes.

void block_sparse_tensor_fill_random_normal(const void *alpha, const void *shift, struct rng_state *rng_state, struct block_sparse_tensor *t)

Fill the non-zero blocks of a block-sparse tensor with random normal entries.

void block_sparse_to_dense_tensor(const struct block_sparse_tensor *s, struct dense_tensor *t)

Convert a block-sparse to an equivalent dense tensor.

void dense_to_block_sparse_tensor(const struct dense_tensor *t, const enum tensor_axis_direction *axis_dir, const qnumber **qnums, struct block_sparse_tensor *s)

Convert a dense to an equivalent block-sparse tensor, using the sparsity pattern imposed by the provided quantum numbers.

Entries in the dense tensor not adhering to the quantum number sparsity pattern are ignored.

void dense_to_block_sparse_tensor_entries(const struct dense_tensor *t, struct block_sparse_tensor *s)

Copy entries of a dense to an already allocated block-sparse tensor.

Entries in the dense tensor not adhering to the quantum number sparsity pattern are ignored.

void block_sparse_tensor_transpose(const int *perm, const struct block_sparse_tensor *t, struct block_sparse_tensor *r)

Generalized transpose of a tensor ‘t’ such that the i-th axis in the output tensor ‘r’ is the perm[i]-th axis of the input tensor ‘t’.

Memory will be allocated for ‘r’.

void block_sparse_tensor_conjugate_transpose(const int *perm, const struct block_sparse_tensor *t, struct block_sparse_tensor *r)

Generalized conjugate transpose of a tensor ‘t’ such that the i-th axis in the output tensor ‘r’ is the perm[i]-th axis of the input tensor ‘t’.

Memory will be allocated for ‘r’.

void block_sparse_tensor_flatten_axes(const struct block_sparse_tensor *t, const int i_ax, const enum tensor_axis_direction new_axis_dir, struct block_sparse_tensor *r)

Flatten the two neighboring axes (tensor legs) ‘i_ax’ and ‘i_ax + 1’ into a single axis.

Memory will be allocated for ‘r’.

Note: this operation changes the internal dense block structure.

void block_sparse_tensor_split_axis(const struct block_sparse_tensor *t, const int i_ax, const ct_long new_dim_logical[2], const enum tensor_axis_direction new_axis_dir[2], const qnumber *new_qnums_logical[2], struct block_sparse_tensor *r)

Split the axis (tensor leg) ‘i_ax’ into two neighboring axes, using the provided quantum numbers.

Memory will be allocated for ‘r’.

Note: this operation changes the internal dense block structure.

void delete_block_sparse_tensor_axis_matricization_info(struct block_sparse_tensor_axis_matricization_info *info)

Delete a block-sparse tensor matricization information object (free memory).

void block_sparse_tensor_matricize_axis(const struct block_sparse_tensor *t, const int i_ax_tns, const int i_ax_mat, const enum tensor_axis_direction flattened_axes_dir, struct block_sparse_tensor *mat, struct block_sparse_tensor_axis_matricization_info *info)

Matricize a tensor by isolating the axis ‘i_ax_tns’ and combining (flattening) the remaining axes. ‘i_ax_mat’ specifies whether ‘i_ax_tns’ is the leading or trailing dimension of the new matrix. ‘flattened_axes_dir’ is the axis direction of the combined (flattened) axes. ‘info’ will be filled and can be used to undo the matricization.

void block_sparse_tensor_dematricize_axis(const struct block_sparse_tensor *mat, const struct block_sparse_tensor_axis_matricization_info *info, struct block_sparse_tensor *t)

Undo the axis matricization of a tensor.

void block_sparse_tensor_slice(const struct block_sparse_tensor *t, const int i_ax, const ct_long *ind, const ct_long nind, struct block_sparse_tensor *r)

Slice an axis of the tensor by selecting logical indices ‘ind’ along this axis.

Indices ‘ind’ can be duplicate and need not be sorted. Memory will be allocated for ‘r’.

void block_sparse_tensor_scalar_multiply_add(const void *alpha, const struct block_sparse_tensor *s, struct block_sparse_tensor *t)

Scalar multiply and add two tensors: t = alpha*s + t; dimensions, data types and quantum numbers of s and t must agree, and alpha must be of the same data type as tensor entries.

void block_sparse_tensor_multiply_pointwise_vector(const struct block_sparse_tensor *s, const struct dense_tensor *t, const enum tensor_axis_range axrange, struct block_sparse_tensor *r)

Pointwise multiply the entries of ‘s’ along its leading or trailing axis with the vector ‘t’. The output tensor ‘r’ has the same data type and dimension as ‘s’.

Memory will be allocated for ‘r’.

void block_sparse_tensor_multiply_axis(const struct block_sparse_tensor *s, const int i_ax, const struct block_sparse_tensor *t, const enum tensor_axis_range axrange_t, struct block_sparse_tensor *r)

Multiply the ‘i_ax’ axis of ‘s’ with the leading or trailing axis of ‘t’, preserving the overall dimension ordering of ‘s’.

void block_sparse_tensor_dot(const struct block_sparse_tensor *s, const enum tensor_axis_range axrange_s, const struct block_sparse_tensor *t, const enum tensor_axis_range axrange_t, const int ndim_mult, struct block_sparse_tensor *r)

Multiply (leading or trailing) ‘ndim_mult’ axes in ‘s’ by ‘ndim_mult’ axes in ‘t’, and store result in ‘r’. Whether to use leading or trailing axes is specified by axis range.

Memory will be allocated for ‘r’. Operation requires that the quantum numbers of the to-be contracted axes match, and that the axis directions are reversed between the tensors.

void block_sparse_tensor_concatenate(const struct block_sparse_tensor *tlist, const int num_tensors, const int i_ax, struct block_sparse_tensor *r)

Concatenate tensors along the specified axis. All other dimensions and their quantum numbers must respectively agree.

void block_sparse_tensor_block_diag(const struct block_sparse_tensor *tlist, const int num_tensors, const int *i_ax, const int ndim_block, struct block_sparse_tensor *r)

Compose tensors along the specified axes, creating a block-diagonal pattern. All other dimensions and their quantum numbers must respectively agree.

int block_sparse_tensor_qr(const struct block_sparse_tensor *a, const enum qr_mode mode, struct block_sparse_tensor *q, struct block_sparse_tensor *r)

Compute the logical QR decomposition of a block-sparse matrix.

The logical quantum numbers of the axis connecting Q and R will be sorted. The logical R matrix is upper-triangular after sorting its second dimension by quantum numbers.

int block_sparse_tensor_rq(const struct block_sparse_tensor *a, const enum qr_mode mode, struct block_sparse_tensor *r, struct block_sparse_tensor *q)

Compute the logical RQ decomposition of a block-sparse matrix.

The logical quantum numbers of the axis connecting R and Q will be sorted. The logical R matrix is upper-triangular after sorting its first dimension by quantum numbers.

int block_sparse_tensor_svd(const struct block_sparse_tensor *a, struct block_sparse_tensor *u, struct dense_tensor *s, struct block_sparse_tensor *vh)

Compute the logical SVD decomposition of a block-sparse matrix.

The logical quantum numbers of the axis connecting ‘u’ and ‘vh’ will be sorted. The singular values are returned in a dense vector.

bool block_sparse_tensor_allclose(const struct block_sparse_tensor *s, const struct block_sparse_tensor *t, const double tol)

Test whether two block-sparse tensors agree in terms of quantum numbers and entries within tolerance ‘tol’.

bool dense_block_sparse_tensor_allclose(const struct dense_tensor *s, const struct block_sparse_tensor *t, const double tol)

Test whether a dense and a block-sparse tensor agree elementwise within tolerance ‘tol’.

bool block_sparse_tensor_is_identity(const struct block_sparse_tensor *t, const double tol)

Test whether a block-sparse tensors is close to the identity map within tolerance ‘tol’.

bool block_sparse_tensor_is_isometry(const struct block_sparse_tensor *t, const double tol, const bool transpose)

Test whether a block-sparse tensors is an isometry within tolerance ‘tol’.

void block_sparse_tensor_augment_identity_blocks(const struct block_sparse_tensor *t, const bool transpose, struct block_sparse_tensor *ret)

Augment a block-sparse matrix by padding identities for quantum number sectors along the first axis which are absent along the second axis.

ct_long block_sparse_tensor_num_elements_blocks(const struct block_sparse_tensor *t)

Overall number of entries in the blocks of the tensor.

void block_sparse_tensor_serialize_entries(const struct block_sparse_tensor *t, void *entries)

Store the block entries in a linear array.

void block_sparse_tensor_deserialize_entries(struct block_sparse_tensor *t, const void *entries)

Fill the block entries from a linear array.

void create_block_sparse_tensor_entry_accessor(const struct block_sparse_tensor *t, struct block_sparse_tensor_entry_accessor *acc)

Create a block-sparse tensor element accessor.

void delete_block_sparse_tensor_entry_accessor(struct block_sparse_tensor_entry_accessor *acc)

Delete a block-sparse tensor element accessor (free memory).

void *block_sparse_tensor_get_entry(const struct block_sparse_tensor_entry_accessor *acc, const ct_long *index)

Retrieve a pointer to an individual entry of a block-sparse tensor, or NULL if the provided index does not correspond to a valid block.

struct block_sparse_tensor
#include <block_sparse_tensor.h>

Block-sparse tensor structure.

Sparsity structure is imposed by additive quantum numbers.

Public Members

struct dense_tensor **blocks

dense blocks, array of size dim_blocks[0] x … x dim_blocks[ndim-1]; contains NULL pointers for non-conserved quantum numbers

ct_long *dim_blocks

block dimensions

ct_long *dim_logical

logical dimensions of the overall tensor

enum tensor_axis_direction *axis_dir

tensor axis directions

qnumber **qnums_blocks

block quantum numbers along each dimension (must be sorted and pairwise different)

qnumber **qnums_logical

logical quantum numbers along each dimension (not necessarily sorted, can be duplicate)

enum numeric_type dtype

numeric data type

int ndim

number of dimensions (degree)

struct block_sparse_tensor_flatten_axes_record
#include <block_sparse_tensor.h>

Temporary data structure for recording the dimensions and quantum numbers before flattening two axes.

Public Members

ct_long dim_logical[2]

logical dimensions

enum tensor_axis_direction axis_dir[2]

tensor axis directions

qnumber *qnums_logical[2]

logical quantum numbers

struct block_sparse_tensor_axis_matricization_info
#include <block_sparse_tensor.h>

Dimension, quantum number and axis ordering information describing the axis matricization of a tensor. This information is required to undo the matricization.

Public Members

struct block_sparse_tensor_flatten_axes_record *records

axes flattening records; array of length ‘ndim - 2’

int i_ax_tns

isolated axis index of the original tensor

int i_ax_mat

corresponding axis index of the matrix (whether ‘i_ax’ becomes the leading or trailing dimension)

int ndim

number of dimensions (degree) of the original tensor

struct block_sparse_tensor_entry_accessor
#include <block_sparse_tensor.h>

Entry access utility data structure for a block-sparse tensor.

Entry-wise access is comparatively slow.

Public Members

const struct block_sparse_tensor *tensor

reference to tensor

ct_long **index_map_blocks

map from logical index to corresponding block index

ct_long **index_map_block_entries

map from logical index to corresponding block entry index

SU(2) symmetric tensors

Clebsch-Gordan coefficient tables.

‘j’ quantum numbers are represented times 2, to support half-integers. ‘m’ quantum numbers are enumerated as (j, j - 1, …, -j).

This file has been generated by ‘clebsch_gordan_gen.py’.

Functions

double clebsch_gordan(const qnumber j1, const qnumber j2, const qnumber j3, const int im1, const int im2, const int im3)

Evaluate the Clebsch-Gordan coefficient at the provided ‘j’ quantum numbers (represented times 2) and ‘m’ quantum number indices.

SU(2) recoupling coefficient tables.

‘j’ quantum numbers are represented times 2, to support half-integers.

This file has been generated by ‘su2_recoupling_gen.py’.

Functions

double su2_recoupling_coefficient(const qnumber ja, const qnumber jb, const qnumber jc, const qnumber js, const qnumber je, const qnumber jf)

Retrieve the SU(2) recoupling coefficient for the provided ‘j’ quantum numbers (represented times 2).

Internal tree data structures for SU(2) symmetric tensors.

Functions

void copy_su2_tree(const struct su2_tree_node *src, struct su2_tree_node *dst)

Make a deep copy of an SU(2) symmetry tree.

void delete_su2_tree(struct su2_tree_node *tree)

Delete an SU(2) symmetry tree (free memory).

The root node must be deallocated by the calling function.

static inline bool su2_tree_node_is_leaf(const struct su2_tree_node *node)

Whether an SU(2) symmetry tree node is a leaf.

bool su2_tree_equal(const struct su2_tree_node *s, const struct su2_tree_node *t)

Whether two SU(2) symmetry trees are logically equal.

bool su2_tree_equal_topology(const struct su2_tree_node *s, const struct su2_tree_node *t)

Whether two SU(2) symmetry trees have the same topology.

bool su2_tree_contains_leaf(const struct su2_tree_node *tree, const int i_ax)

Whether the SU(2) symmetry tree contains a leaf with axis index ‘i_ax’.

const struct su2_tree_node *su2_tree_find_node(const struct su2_tree_node *tree, const int i_ax)

Locate the node with axis index ‘i_ax’, returning NULL if such a node cannot be found.

const struct su2_tree_node *su2_tree_find_parent_node(const struct su2_tree_node *tree, const int i_ax)

Locate the parent of the node with axis index ‘i_ax’, returning NULL if parent cannot be found.

int su2_tree_num_nodes(const struct su2_tree_node *tree)

Number of nodes in an SU(2) symmetry tree.

int su2_tree_axes_list(const struct su2_tree_node *tree, int *list)

Fill the list of axis indices contained in the tree, and return the number of axes.

void su2_tree_axes_indicator(const struct su2_tree_node *tree, bool *indicator)

Fill the indicator with the axes indexed by the tree.

void su2_tree_update_axes_indices(struct su2_tree_node *tree, const int *axis_map)

Update the axes indices using the provided map.

const struct su2_tree_node *su2_subtree_with_leaf_axes(const struct su2_tree_node *tree, const int *i_ax, const int num_axes)

Find the subtree with the specified leaf axis indices.

Ordering of axis indices is not relevant. Returns NULL if subtree does not exist.

struct su2_tree_node *su2_tree_replace_subtree(struct su2_tree_node *tree, const int i_ax, struct su2_tree_node *subtree)

Replace the proper subtree with axis index ‘i_ax’ by ‘subtree’, and return a pointer to the old subtree, or NULL if ‘i_ax’ cannot be found.

void su2_tree_fmove_left(struct su2_tree_node *tree)

Perform an in-place left-rotating F-move rooted at the node pointed to by ‘tree’, retaining the axis indices.

void su2_tree_fmove_right(struct su2_tree_node *tree)

Perform an in-place right-rotating F-move rooted at the node pointed to by ‘tree’, retaining the axis indices.

double su2_tree_eval_clebsch_gordan(const struct su2_tree_node *tree, const qnumber *jlist, const int *im_leaves, const int im_root)

Evaluate the SU(2) symmetry tree by contracting it, interpreting the nodes as Clebsch-Gordan coefficients. The ‘j’ quantum number configuration and the ‘m’ quantum numbers at the leaves and root are prescribed.

void su2_tree_enumerate_charge_sectors(const struct su2_tree_node *tree, const int ndim, const struct su2_irreducible_list *leaf_ranges, struct charge_sectors *sectors)

Enumerate all “charge sectors” (‘j’ quantum number configurations) for a given tree layout. ‘ndim’ is the number of ‘j’ quantum numbers. The output array ‘sectors’ will be allocated, with dimension ‘number of sectors x ndim’.

void copy_su2_fuse_split_tree(const struct su2_fuse_split_tree *src, struct su2_fuse_split_tree *dst)

Make a deep copy of a fuse and split tree.

void delete_su2_fuse_split_tree(struct su2_fuse_split_tree *tree)

Delete a fuse and split tree (free memory).

bool su2_fuse_split_tree_is_consistent(const struct su2_fuse_split_tree *tree)

Internal consistency check of the fuse and split tree data structure.

bool su2_fuse_split_tree_equal(const struct su2_fuse_split_tree *s, const struct su2_fuse_split_tree *t)

Whether two fuse and split trees are logically equal.

void su2_fuse_split_tree_flip(struct su2_fuse_split_tree *tree)

Flip the fuse and split trees.

void su2_fuse_split_tree_update_axes_indices(struct su2_fuse_split_tree *tree, const int *axis_map)

Update the axes indices of a fuse and split tree using the provided map.

double su2_fuse_split_tree_eval_clebsch_gordan(const struct su2_fuse_split_tree *tree, const qnumber *jlist, const int *im_leaves)

Evaluate the fuse and split tree by contracting both subtrees, interpreting the nodes as Clebsch-Gordan coefficients. The ‘j’ quantum number configuration and the ‘m’ quantum numbers at the leaves are prescribed.

void su2_fuse_split_tree_enumerate_charge_sectors(const struct su2_fuse_split_tree *tree, const struct su2_irreducible_list *leaf_ranges, struct charge_sectors *sectors)

Enumerate all “charge sectors” (‘j’ quantum number configurations) for a given fuse and split tree layout.

struct su2_tree_node
#include <su2_tree.h>

SU(2) symmetry tree node.

Public Members

int i_ax

tensor axis index (logical or auxiliary for leaf nodes, otherwise internal)

struct su2_tree_node *c[2]

pointer to left and right child nodes; NULL for a leaf node

struct su2_fuse_split_tree
#include <su2_tree.h>

Internal fuse and split tree of an SU(2) symmetric tensor.

Public Members

struct su2_tree_node *tree_fuse

root of fusion tree

struct su2_tree_node *tree_split

root of splitting tree

int ndim

overall number of dimensions

Internal temporary graph data structure for SU(2) symmetric tensors.

Enums

enum su2_graph_node_type

SU(2) symmetry graph node type.

Values:

enumerator SU2_GRAPH_NODE_FUSE

fusion node

enumerator SU2_GRAPH_NODE_SPLIT

splitting node

Functions

void copy_su2_graph(const struct su2_graph *src, struct su2_graph *dst)

Copy an SU(2) symmetry graph.

void delete_su2_graph(struct su2_graph *graph)

Delete an SU(2) symmetry graph (free memory).

bool su2_graph_is_consistent(const struct su2_graph *graph)

Internal consistency check of the SU(2) symmetry graph data structure.

bool su2_graph_equal(const struct su2_graph *f, const struct su2_graph *g)

Whether two SU(2) symmetry graphs are logically equal.

void su2_graph_from_fuse_split_tree(const struct su2_fuse_split_tree *tree, struct su2_graph *graph)

Construct an SU(2) symmetry graph from a fuse and split tree.

bool su2_graph_has_fuse_split_tree_topology(const struct su2_graph *graph)

Whether an SU(2) symmetry graph has the same topology as a fuse and split tree.

void su2_graph_to_fuse_split_tree(const struct su2_graph *graph, struct su2_fuse_split_tree *tree)

Convert an SU(2) symmetry graph with fuse and split tree topology to an actual tree.

bool su2_graph_is_yoga_edge(const struct su2_graph *graph, const int eid)

Whether an SU(2) symmetry graph edge is at the center of an elementary yoga subtree.

void su2_graph_yoga_to_simple_subtree(struct su2_graph *graph, const int eid)

Convert an internal elementary yoga subtree to a simple subtree.

void su2_graph_connect(const struct su2_graph *f, const int *edge_map_f, const struct su2_graph *g, const int *edge_map_g, struct su2_graph *connected_graph)

Connect two graphs after applying the edge index maps; edges with the same resulting index must be outer edges and are merged.

This function assumes a disjoint union for the nodes.

struct su2_graph_node
#include <su2_graph.h>

SU(2) symmetry graph node.

Convention for orientations:

fusion node: c[0] c[1] ╲╱ │ p

splitting node: p │ ╱╲ c[0] c[1]

Public Members

int eid_parent

index of parent edge

int eid_child[2]

indices of left and right child edges

enum su2_graph_node_type type

node type (fusion or splitting)

struct su2_graph_edge
#include <su2_graph.h>

SU(2) symmetry graph edge.

Public Members

int nid[2]

index of connected upstream and downstream node, or -1 if not connected

struct su2_graph
#include <su2_graph.h>

SU(2) symmetry graph: temporary data structure for representing the structural tensor.

The graph can contain loops.

Public Members

struct su2_graph_node *nodes

nodes

struct su2_graph_edge *edges

edges; array indices correspond to logical axis indices

int num_nodes

overall number of nodes

int num_edges

overall number of edges (corresponds to logical number of dimensions)

Irreducible ‘j’ quantum number configurations for SU(2) symmetric tensors.

Functions

void allocate_su2_irreducible_list(const int num, struct su2_irreducible_list *list)

Allocate a list of irreducible ‘j’ quantum numbers.

void copy_su2_irreducible_list(const struct su2_irreducible_list *src, struct su2_irreducible_list *dst)

Copy a list of irreducible ‘j’ quantum numbers.

void delete_su2_irreducible_list(struct su2_irreducible_list *list)

Delete a list of irreducible ‘j’ quantum numbers (free memory).

bool su2_irreducible_list_equal(const struct su2_irreducible_list *s, const struct su2_irreducible_list *t)

Whether two irreducible ‘j’ quantum number lists are logically equal.

int compare_su2_irreducible_lists(const struct su2_irreducible_list *s, const struct su2_irreducible_list *t)

Comparison function for lexicographical sorting, assuming that both lists have the same length.

void su2_irreps_tensor_product(const struct su2_irreducible_list *irreps_a, const ct_long *dim_degen_a, const struct su2_irreducible_list *irreps_b, const ct_long *dim_degen_b, struct su2_irreducible_list *irreps_prod, ct_long **dim_degen_prod)

Enumerate all admissible irreducible quantum numbers and corresponding degeneracies when computing the tensor product of two irreducible configurations.

void allocate_charge_sectors(const ct_long nsec, const int ndim, struct charge_sectors *sectors)

Allocate a charge sector array.

void copy_charge_sectors(const struct charge_sectors *src, struct charge_sectors *dst)

Copy a charge sector array.

void delete_charge_sectors(struct charge_sectors *sectors)

Delete a charge sector array (free memory).

ct_long charge_sector_index(const struct charge_sectors *sectors, const qnumber *jlist)

Find the index of charge sector ‘jlist’, assuming that the list of charge sectors is sorted. Returns -1 if charge sector cannot be found.

bool charge_sectors_equal(const struct charge_sectors *s, const struct charge_sectors *t)

Whether two charge sector arrays are logically equal.

int su2_irrep_trie_num_leaves(const int height, const struct su2_irrep_trie_node *trie)

Count the leaves of an irreducible ‘j’ quantum number search trie.

void **su2_irrep_trie_search_insert(const qnumber *jlist, const int num, struct su2_irrep_trie_node *trie)

Search or insert an irreducible ‘j’ quantum number configuration into the trie, returning a reference to the corresponding data pointer.

void **su2_irrep_trie_enumerate_configurations(const int height, const struct su2_irrep_trie_node *trie, struct charge_sectors *sectors)

Enumerate all irreducible ‘j’ quantum number configurations stored in the trie, and return the corresponding array of data pointers at the leaves.

void delete_su2_irrep_trie(const int height, struct su2_irrep_trie_node *trie)

Recursively delete all search trie nodes (free memory).

This function does not free the data pointers at the leaves.

struct su2_irreducible_list
#include <su2_irreps.h>

List of irreducible ‘j’ quantum numbers.

Public Members

qnumber *jlist

‘j’ quantum numbers times 2 (must be unique)

int num

number of irreducible SU(2) subspaces (length of jlist)

struct charge_sectors
#include <su2_irreps.h>

Charge sectors (‘j’ quantum number configurations).

Public Members

qnumber *jlists

matrix of ‘j’ quantum numbers times 2, of dimension nsec x ndim; must be sorted lexicographically

ct_long nsec

number of sectors (configurations)

int ndim

number of dimensions (‘j’ quantum numbers in each configuration)

struct su2_irrep_trie_node
#include <su2_irreps.h>

Trie (prefix tree) node for irreducible ‘j’ quantum number configurations (temporary data structure).

Public Members

qnumber *jvals

irreducible ‘j’ quantum number values at current level, must be distinct and sorted

void **cdata

pointers to child nodes or data values

int length

length of ‘jvals’ and ‘cdata’ arrays

Data structures and functions for SU(2) symmetric tensors.

Functions

void allocate_empty_su2_tensor(const enum numeric_type dtype, const int ndim_logical, int ndim_auxiliary, const struct su2_fuse_split_tree *tree, const struct su2_irreducible_list *outer_irreps, const ct_long **dim_degen, struct su2_tensor *t)

Allocate an “empty” SU(2) symmetric tensor, without the charge sectors and dense “degeneracy” tensors.

void allocate_su2_tensor(const enum numeric_type dtype, const int ndim_logical, int ndim_auxiliary, const struct su2_fuse_split_tree *tree, const struct su2_irreducible_list *outer_irreps, const ct_long **dim_degen, struct su2_tensor *t)

Allocate memory for an SU(2) symmetric tensor, including the dense “degeneracy” tensors, and enumerate all possible charge sectors.

void delete_su2_tensor(struct su2_tensor *t)

Delete an SU(2) symmetric tensor (free memory).

void copy_su2_tensor(const struct su2_tensor *src, struct su2_tensor *dst)

Copy an SU(2) tensor, allocating memory for the copy.

static inline int su2_tensor_ndim_internal(const struct su2_tensor *t)

Number of internal dimensions of an SU(2) symmetric tensor.

static inline int su2_tensor_ndim(const struct su2_tensor *t)

Number of overall dimensions of an SU(2) symmetric tensor.

ct_long su2_tensor_dim_logical_axis(const struct su2_tensor *t, const int i_ax)

Logical dimension of axis ‘i_ax’ of SU(2) tensor ‘t’.

ct_long su2_tensor_num_elements_logical(const struct su2_tensor *t)

Calculate the logical number of elements of an SU(2) tensor.

Assuming that auxiliary axes have dimension 1.

enum tensor_axis_direction su2_tensor_logical_axis_direction(const struct su2_tensor *t, const int i_ax)

Logical direction of axis ‘i_ax’ of SU(2) tensor ‘t’.

bool su2_tensor_is_consistent(const struct su2_tensor *t)

Internal consistency check of an SU(2) symmetric tensor.

static inline void su2_tensor_flip_trees(struct su2_tensor *t)
bool su2_tensor_delete_charge_sector(struct su2_tensor *t, const qnumber *jlist)

Delete an individual charge sector of the SU(2) symmetric tensor, returning true if the charge sector was actually found and deleted.

void scale_su2_tensor(const void *alpha, struct su2_tensor *t)

Scale tensor ‘t’ by ‘alpha’.

Data types of all “degeneracy” tensors and of ‘alpha’ must match.

void rscale_su2_tensor(const void *alpha, struct su2_tensor *t)

Scale tensor ‘t’ by a real number ‘alpha’.

Data type precision of all “degeneracy” tensors and of ‘alpha’ must match.

void conjugate_su2_tensor(struct su2_tensor *t)

Elementwise complex conjugation of an SU(2) symmetric tensor.

Function has no effect if entries are real-valued.

void su2_tensor_fill_random_normal(const void *alpha, const void *shift, struct rng_state *rng_state, struct su2_tensor *t)

Fill the dense degeneracy tensors of an SU(2) symmetric tensor with random normal entries.

void su2_tensor_transpose(const int *perm, const struct su2_tensor *t, struct su2_tensor *r)

Generalized transpose of a tensor ‘t’ such that the i-th axis in the output tensor ‘r’ is the perm[i]-th axis of the input tensor ‘t’.

‘perm’ refers to all dimensions (logical, auxiliary and internal) and must not mix axes types.

void su2_tensor_transpose_logical(const int *perm, const struct su2_tensor *t, struct su2_tensor *r)

Generalized transpose of the logical axes of the SU(2) tensor ‘t’ such that the i-th axis in the output tensor ‘r’ is the perm[i]-th axis of the input tensor ‘t’.

The auxiliary and internal axes ordering remains unchanged.

void su2_tensor_fmove(const struct su2_tensor *t, const int i_ax, struct su2_tensor *r)

Perform an F-move on the internal axis ‘i_ax’.

void su2_tensor_reverse_axis_simple(struct su2_tensor *t, const int i_ax)

Reverse the logical axis (tensor leg) ‘i_ax’, assuming that the SU(2) tensor is still described by a fusion-splitting tree after the reversal and that no auxiliary axis needs to be introduced.

void su2_tensor_fuse_axes(const struct su2_tensor *t, const int i_ax_0, const int i_ax_1, struct su2_tensor *r)

Fuse the two logical axes (tensor legs) ‘i_ax_0’ and ‘i_ax_1’ (with i_ax_0 < i_ax_1) into a single axis with index ‘i_ax_0’, corresponding to the contraction with a “fusion” Clebsch-Gordan node. The axes must have the same direction and must be direct siblings in the fusion-splitting tree. The parent node of (i_ax_0, i_ax_1) in the fusion-splitting tree is deleted, and its (internal) upward axis index becomes ‘i_ax_0’.

void su2_tensor_split_axis(const struct su2_tensor *t, const int i_ax_split, const int i_ax_add, const bool tree_left_child, const struct su2_irreducible_list outer_irreps[2], const ct_long *dim_degen[2], struct su2_tensor *r)

Split the logical axis (tensor leg) ‘i_ax_split’ into two logical axes, ‘i_ax_split’ and ‘i_ax_add’ (with i_ax_split < i_ax_add), corresponding to attaching a “splitting” Clebsch-Gordan node. ‘tree_left_child’ indicates whether the new axis ‘i_ax_split’ is the left child in the fusion-splitting tree. The arguments ‘outer_irreps’ and ‘dim_degen’ specify the ‘j’ quantum numbers and degeneracies of the new axes ‘i_ax_split’ and ‘i_ax_add’.

The axis ‘i_ax_split’ in the original fusion-splitting tree becomes the last inner axis of the new tensor.

void su2_tensor_contract_simple(const struct su2_tensor *s, const int *i_ax_s, const struct su2_tensor *t, const int *i_ax_t, const int ndim_mult, struct su2_tensor *r)

Contract two SU(2) tensors for the scenario that the to-be contracted axes form subtrees with matching topology and that the resulting fusion-splitting tree is again simple.

void su2_tensor_contract_yoga(const struct su2_tensor *s, const int i_ax_s, const struct su2_tensor *t, const int i_ax_t, struct su2_tensor *r)

Contract two SU(2) tensors along a single logical axis, for the scenario that the resulting structural tensor contains a yoga subtree which can be converted to a fusion-splitting tree in a single step.

void su2_to_dense_tensor(const struct su2_tensor *s, struct dense_tensor *t)

Convert an SU(2) symmetric to an equivalent dense tensor.

bool su2_tensor_allclose(const struct su2_tensor *s, const struct su2_tensor *t, const double tol)

Test whether two SU(2) tensors agree in terms of quantum numbers, internal tree structure and degeneracy tensor entries within tolerance ‘tol’.

bool dense_su2_tensor_allclose(const struct dense_tensor *s, const struct su2_tensor *t, const double tol)

Test whether a dense and an SU(2) symmetric tensor agree elementwise within tolerance ‘tol’.

struct su2_tensor
#include <su2_tensor.h>

SU(2) symmetric tensor (assumed to be described internally by a fusion-splitting tree).

Axes are enumerated in the order “logical”, “auxiliary”, “internal”; number of internal dimensions is ndim_logical + ndim_auxiliary - 3

Public Members

struct su2_fuse_split_tree tree

internal fusion-splitting tree

struct su2_irreducible_list *outer_irreps

lists of irreducible ‘j’ quantum numbers times 2, for each outer (logical and auxiliary) axis

struct charge_sectors charge_sectors

charge sectors (irreducible logical, auxiliary and internal ‘j’ quantum number configurations), computed from ‘tree’ and ‘outer_irreps’, and sorted lexicographically

struct dense_tensor **degensors

dense “degeneracy” tensors, pointer array of length “number of charge sectors”

ct_long **dim_degen

degeneracy dimension for each logical axis; indexed by corresponding ‘j’ quantum number

enum numeric_type dtype

numeric data type

int ndim_logical

number of logical dimensions

int ndim_auxiliary

number of auxiliary dimensions (dummy outer axes in fusion-splitting tree)

Utility functions for SU(2) symmetric tensors.

Functions

void su2_convert_yoga_to_simple_subtree(const struct su2_tensor_data *data_yoga, struct su2_graph *graph, const int eid, struct su2_tensor_data *data_simple)

Convert a yoga to a simple subtree by a corresponding linear transformation of the dense “degeneracy” tensors.

struct su2_tensor_data
#include <su2_util.h>

Essential data stored in an SU(2) symmetric tensor.

Public Members

struct charge_sectors charge_sectors

charge sectors (irreducible ‘j’ quantum number configurations)

struct dense_tensor **degensors

dense “degeneracy” tensors, pointer array of length “number of charge sectors”