Source code for fcdmft.utils.arraymath

import scipy.linalg as sla
import numpy as np


def _is_contiguous(arr):
    return arr.flags['C_CONTIGUOUS'] or arr.flags['F_CONTIGUOUS']


[docs] def array_scale(arr, alpha): """Scale an array in place by a scalar with BLAS if possible. Parameters ---------- arr : array_like Array to be scaled. alpha : scalar Scale factor. Returns ------- arr : ndarray Scaled array equal to alpha * arr. """ if _is_contiguous(arr): scal = sla.get_blas_funcs('scal', (arr,)) scal(a=alpha, x=arr.reshape(-1)) else: arr *= alpha
[docs] def diag_array_view(arr): """ Returns a view of the diagonal of a N-d array. Parameters ---------- arr : (..., M, M) array_like Input array. Returns ------- diag : (..., M) ndarray View of the diagonal of the input array. """ if not (arr.ndim >= 2 and arr.shape[-1] == arr.shape[-2]): raise ValueError('Input must be a stack of square arrays.') diagstride = arr.strides[-1] + arr.strides[-2] diagshape = list(arr.shape[:-1]) diagstrides = list(arr.strides[:-1]) diagstrides[-1] = diagstride return np.lib.stride_tricks.as_strided(arr, shape=diagshape, strides=diagstrides)
[docs] def get_id_minus_pi(Pi): """Calculate I - Pi in place. Parameters ---------- Pi : (M, M) array_like Input matrix. Must be C-contiguous. Returns ------- id_minus_pi : (M, M) ndarray (I - Pi) """ if Pi.flags.f_contiguous: Pi_c = Pi.T else: Pi_c = Pi assert Pi_c.flags.c_contiguous Pi_diag = diag_array_view(Pi_c) Pi_diag -= 1.0 array_scale(Pi_c, -1.0) return Pi
[docs] def get_pi_inv(Pi, overwrite_input=False): """Calculate (I - Pi)^-1 - I. Parameters ---------- Pi : (M, M) array_like Input matrix. Must be C-contiguous. Returns ------- Pi_inv : (M, M) ndarray (I - Pi)^-1 - I. """ assert Pi.flags.c_contiguous Pi_diag = diag_array_view(Pi) Pi = get_id_minus_pi(Pi) Pi_inv = sla.inv(Pi.T, overwrite_a=overwrite_input, check_finite=False).T Pi_inv_diag = diag_array_view(Pi_inv) Pi_inv_diag -= 1.0 return Pi_inv
[docs] def mkslice(l): """ Try to make a slice from a list of integers. If this is not possible, return the input unchanged. Parameters ---------- l : slice | list | range | ndarray Various ways of representing a list of integer indices Returns ------- slice | list | ndarray slice if possible, otherwise returns the input unchanged """ # If l is already a slice, return it if isinstance(l, slice): return l if l is None or l == (): return slice(None) # range to slice is easy if isinstance(l, range): return slice(l.start, l.stop, l.step) if len(l) < 2: return l strides = np.diff(l) if not np.all(strides == strides[0]): return l else: start = l[0] stop = l[-1] + strides[0] step = strides[0] return slice(start, stop, step)