Source code for meanfi.params.rparams

import numpy as np

from meanfi.tb.tb import _tb_type


[docs] def complex_to_real(z: np.ndarray) -> np.ndarray: """Split and concatenate real and imaginary parts of a complex array. Parameters ---------- z : Complex array. Returns ------- : Real array that concatenates the real and imaginary parts of the input array. """ return np.concatenate((np.real(z), np.imag(z)))
[docs] def real_to_complex(z: np.ndarray) -> np.ndarray: """Undo `complex_to_real`.""" return z[: len(z) // 2] + 1j * z[len(z) // 2 :]
[docs] def tb_to_rparams(tb: _tb_type) -> np.ndarray: """Parametrise a hermitian tight-binding dictionary by a real vector. Parameters ---------- tb : tight-binding dictionary. Returns ------- : 1D real vector that parametrises the tight-binding dictionary. """ ndim = len(list(tb)[0]) onsite_key = tuple(np.zeros((ndim,), dtype=int)) hopping_keys = sorted([key for key in tb.keys() if key != onsite_key]) hopping_keys = hopping_keys[: len(hopping_keys) // 2] onsite_upper_vals = tb[onsite_key][ np.triu_indices(tb[onsite_key].shape[-1], k=1) ].flatten() onsite_diag_vals = np.diag(tb[onsite_key]).real.flatten() hopping_vals = [tb[key].flatten() for key in hopping_keys] complex_vals = np.concatenate([onsite_upper_vals, *hopping_vals]) return np.concatenate([onsite_diag_vals, complex_to_real(complex_vals)])
[docs] def rparams_to_tb( tb_params: np.ndarray, tb_keys: list[tuple[None] | tuple[int, ...]], ndof: int ) -> _tb_type: """Extract a hermitian tight-binding dictionary from a real vector parametrisation. Parameters ---------- tb_params : 1D real array that parametrises the tight-binding dictionary. tb_keys : List of keys of the tight-binding dictionary. ndof : Number internal degrees of freedom within the unit cell. Returns ------- : Tight-biding dictionary. """ ndim = len(tb_keys[0]) hopping_shape = (len(tb_keys) - 1, ndof, ndof) onsite_idxs = ndof + ndof * (ndof - 1) // 2 onsite_key = tuple(np.zeros((ndim,), dtype=int)) # reconstruct the complex values onsite_diag_vals = tb_params[:ndof] complex_vals = real_to_complex(tb_params[ndof:]) onsite_upper_vals = complex_vals[: onsite_idxs - ndof] hopping_vals = complex_vals[(onsite_idxs - ndof) :] # first build onsite matrix onsite_matrix = np.zeros((ndof, ndof), dtype=complex) onsite_matrix[np.triu_indices(ndof, k=1)] = onsite_upper_vals onsite_matrix += onsite_matrix.conj().T onsite_matrix[np.diag_indices(ndof)] = onsite_diag_vals # then build hopping matrices hopping_matrices = np.zeros(hopping_shape, dtype=complex) N = len(tb_keys) // 2 hopping_matrices[:N] = hopping_vals.reshape(N, *hopping_shape[1:]) hopping_matrices[N:] = np.moveaxis( np.flip(hopping_matrices[:N], axis=0), -1, -2 ).conj() # combine all into a dictionary hopping_keys = sorted([key for key in tb_keys if key != onsite_key]) tb = {key: hopping_matrices[i] for i, key in enumerate(hopping_keys)} tb[onsite_key] = onsite_matrix return tb