Source code for SU2xSU2.SU2_mat_routines

# Several functions to perform common matrix operations for SU(2) matrices.
# By exploiting their properties, these routines are more efficient than general matrix methods
# Specifically, an SU(2) matrix is fully specified by 4 real parameters:
# [[a0 + i*a3, a2 + i*a1],
# [-a2 + i*a1, a0 - i*a3]]
#
# The operations are designed to act on entire SU(2) valued lattices.
# The lattice is assumed to be square but can be of arbitrary dimension and size.


import numpy as np


[docs] def alpha_to_a(alpha): ''' A lattice of SU(2) matrices may be defined through the exponential map with parameters alpha. The exponential map can be explicitly evaluated, resulting in a linear combination of the Pauli matrices and unity: U = exp(i alpha_i sigma_i) = a_0*1 + i*a_i sigma_i This function finds the coefficients ``a`` based on ``alpha``. Parameters ---------- alpha: (lattice shape,3) array parameters when representing a SU(2) group element via the exponential map at every lattice site Returns ------- a: (lattice shape,4) array parameters of matrices at each lattice site when explicitly evaluating the exponential map ''' lattice_shape = alpha.shape[:-1] # gives tuple (L,...,L) a = np.empty(lattice_shape+(4,)) norm = np.sqrt(np.sum(alpha**2, axis=-1)) # (L,...,L) # to do arithmetic with another (L,...,L,3) array need to broadcast to include axis 2 alpha_norm = norm.reshape(lattice_shape+(1,)) # To avoid division by zero: if alpha_norm is 0, then alpha must be zero, such that the normalized alpha must be zero too alpha_unit = np.divide(alpha, alpha_norm, out=np.zeros_like(alpha), where=alpha_norm!=0) a[...,0] = np.cos(norm) a[...,1:] = alpha_unit * np.sin(alpha_norm) return a
[docs] def make_mats(a): ''' Constructs explicit matrices corresponding to parameter vector ``a``. Parameters ---------- a: (lattice shape,4) array parameters of the SU(2) valued lattice Returns ------- mats: (lattice shape) object array np.matrix instance at every site ''' lattice_shape = a.shape[:-1] # gives tuple (L,...,L) D = len(lattice_shape) L = lattice_shape[0] # make 2D array where each row gives the coordinates of a lattice site to later easily loop over all lattice sites with their coordinates grid = np.indices(lattice_shape) lattice_coords = np.reshape( np.moveaxis(grid, 0, -1), (L**D, D)) # array containing np.matrix objects mats = np.empty(lattice_shape, dtype=object) for coord in lattice_coords: mask = tuple(coord) paras = a[mask] # (4,) returns parameter vector at lattice site specified by coord mat = [[paras[0]+1j*paras[3], paras[2]+1j*paras[1]], [-paras[2]+1j*paras[1], paras[0]-1j*paras[3]]] mats[mask] = np.matrix(mat) return mats
### ----------------------- ### ### basic matrix quantities ### ### ----------------------- ###
[docs] def hc(a): ''' Returns the parameter vector of the hermitian conjugate at each lattice site. Parameters ---------- a: (lattice shape,4) array parameters of the SU(2) valued lattice Returns ------- a_hc: (lattice shape,4) array parameters of hermitian conjugate SU(2) valued lattice ''' a_hc = -a a_hc[...,0] = a[...,0] return a_hc
[docs] def tr(a): ''' Returns the trace of the matrices at each lattice site. Parameters ---------- a: (lattice shape,4) array parameters of the SU(2) valued lattice Returns ------- trace: (lattice shape) array trace at each site of the SU(2) valued lattice ''' trace = 2*a[...,0] return trace
[docs] def det(a): ''' The determinant of an SU(2) matrix is given by the squared length of the parameter vector. Parameters ---------- a: (lattice shape,4) array parameters of the SU(2) valued lattice Returns ------- determinant: (lattice shape) array determinants of the SU(2) valued lattice ''' determinant = norm2(a) return determinant
[docs] def norm2(a): ''' Returns squared norm of the parameter vector ``a``. Parameters ---------- a: (lattice shape,4) array parameters of the SU(2) valued lattice Returns ------- norm_sq: (lattice shape) array containing the norm at each site ''' norm_sq = np.sum(a**2, axis=-1) return norm_sq
[docs] def renorm(a): ''' Renormalises matrix to have det = 1 Parameters ---------- a: (lattice shape,4) array parameters of the SU(2) valued lattice Returns ------- renormed: (lattice shape,4) array renormalised parameters of the SU(2) valued lattice ''' lattice_shape = a.shape[:-1] # gives tuple (L,...,L) norm = np.sqrt(norm2(a)).reshape(lattice_shape+(1,)) # broadcast to do arithmetic with (lattice shape,4) array a renormed = np.divide(a, norm, out=np.zeros_like(a), where=norm!=0) return renormed
### ---------------------------- ### ### combining two SU(2) matrices ### ### ---------------------------- ###
[docs] def dot(a, b): ''' Computes the elementwise matrix product between two lattices of SU(2) matrices with parameter vectors ``a`` and ``b``. Parameters ---------- a: (lattice shape,4) array parameters of first SU(2) valued lattice b: (lattice shape,4) array parameters of second SU(2) valued lattice Returns ------- c: (lattice shape,4) array parameters of SU(2) valued lattice resulting from the elementwise matrix products ''' c = np.empty_like(a) c[...,0] = a[...,0]*b[...,0] - np.sum(a[...,1:]*b[...,1:], axis=-1) c[...,1] = a[...,0]*b[...,1] + a[...,1]*b[...,0] + a[...,3]*b[...,2] - a[...,2]*b[...,3] c[...,2] = a[...,0]*b[...,2] + a[...,2]*b[...,0] + a[...,1]*b[...,3] - a[...,3]*b[...,1] c[...,3] = a[...,0]*b[...,3] + a[...,3]*b[...,0] + a[...,2]*b[...,1] - a[...,1]*b[...,2] return c
[docs] def sum(a, b): ''' Computes the elementwise sum of two SU(2) valued lattices A and B with parameters ``a`` and ``b``. Let C = A + B, i.e. c = a + b. Note that the sum of two SU(2) matrices is proportional to an SU(2) matrix with proportionality constant ``k``, meaning D = C/k = 1/k (A + B) is in SU(2). To only having to perform manipulations on SU(2) matrices, the parameters ``d`` of the SU(2) valued lattice D and the constant ``k`` are returned such that their product gives the parameter vectors of C, the sum of lattice A and B. Parameters ---------- a: (lattice shape,4) array parameters of first SU(2) valued lattice b: (lattice shape,4) array parameters of second SU(2) valued lattice Returns ------- d: (lattice shape,4) array parameters of SU(2) valued lattice proportional to a+b k: (lattice shape,1) array proportionality constant between d and a+b ''' c = a + b k2 = 2*(a[...,0]*b[...,0] + np.sum(a[...,1:]*b[...,1:], axis=-1) + 1) # (L,...,L) lattice_shape = a.shape[:-1] # gives tuple (L,...,L) k = np.sqrt(k2, dtype=complex).reshape(lattice_shape+(1,)) d = c / k return d, k