def test_transition_matrices(): nspins = 11 n = 2**nspins T_old = transition_matrix(n) T_dense = transition_matrix2(n) T_sparse = transition_matrix_sparse(n) assert np.array_equal(T_old.todense(), T_dense) assert np.array_equal(T_old.todense(), T_sparse.todense())
def test_dot_speed(): # Test suggests .dot has a modest speed advantage. # 10000 runs: 276s/298s/252s spin-8 star/at/dot E, V = np.linalg.eigh(H8_MATRIX) Vcol = csc_matrix(V) Vrow = csr_matrix(Vcol.T) T = transition_matrix(2**8) intensity_matrices = [ f(Vrow, T, Vcol, 1).todense() for f in [istar, iat, idot] ] for i in range(2): assert np.allclose(intensity_matrices[i], intensity_matrices[i + 1])
def simsignals(H, nspins): """ Calculates the eigensolution of the spin Hamiltonian H and, using it, returns the allowed transitions as list of (frequency, intensity) tuples. Parameters --------- H : ndarray the spin Hamiltonian. nspins : int the number of nuclei in the spin system. Returns ------- spectrum : [(float, float)...] a list of (frequency, intensity) tuples. """ """The original simsignals.""" # This routine was optimized for speed by vectorizing the intensity # calculations, replacing a nested-for signal-by-signal calculation. # Considering that hamiltonian was dramatically faster when refactored to # use arrays instead of sparse matrices, consider an array refactor to this # function as well. # The eigensolution calculation apparently must be done on a dense matrix, # because eig functions on sparse matrices can't return all answers?! # Using eigh so that answers have only real components and no residual small # unreal components b/c of rounding errors E, V = np.linalg.eigh(H) # V will be eigenvectors, v will be frequencies # 2019-04-27: the statement below may be wrong. May be entirely real already # Eigh still leaves residual 0j terms, so: V = np.asmatrix(V.real) # Calculate signal intensities Vcol = csc_matrix(V) Vrow = csr_matrix(Vcol.T) m = 2**nspins T = transition_matrix(m) I = Vrow * T * Vcol I = np.square(I.todense()) spectrum = [] for i in range(m - 1): for j in range(i + 1, m): if I[i, j] > 0.01: # consider making this minimum intensity # cutoff a function arg, for flexibility v = abs(E[i] - E[j]) spectrum.append((v, I[i, j])) return spectrum
def test_matrix_multiplication(): """A sanity test that all three versions of matrix multiplication are identical. """ E, V = np.linalg.eigh(H_RIOUX) Vcol = csc_matrix(V) Vrow = csr_matrix(Vcol.T) T = transition_matrix(8) Istar = Vrow * T * Vcol Iat = Vrow @ T @ Vcol Idot = Vrow.dot(T.dot(Vcol)) assert np.allclose(Istar.todense(), Iat.todense()) assert np.allclose(Istar.todense(), Idot.todense())
def new_simsignals(H, nspins): """Taking lessons from test results to create a faster simsignals function. """ m = 2**nspins E, V = np.linalg.eigh(H) T = transition_matrix(m) I = np.square(V.T.dot(T.dot(V))) spectrum = [] for i in range(m - 1): for j in range(i + 1, m): if I[i, j] > 0.01: # consider making this minimum intensity # cutoff a function arg, for flexibility v = abs(E[i] - E[j]) spectrum.append((v, I[i, j])) return spectrum
def test_new_matrix_simsignals(): # Testing with H11_MATRIX: dense is MUCH faster! # e.g. 13.8 vs. 13.6 vs. 0.28 s original/norow/dense # H11_NDARRAY 22.9 / 23.2 / 0.57 s n = 1 nspins = 11 E, V = np.linalg.eigh(H11_NDARRAY) T = transition_matrix(2**nspins) test_functions = [ original_intensity_matrix, norow_intensity_matrix, dense_intensity_matrix ] intensity_matrices = [] intensity_matrices.append((original_intensity_matrix(V, T, n).todense())) intensity_matrices.append((norow_intensity_matrix(V, T, n).todense())) intensity_matrices.append(dense_intensity_matrix(V, T, n)) assert np.allclose(intensity_matrices[0], intensity_matrices[1]) assert np.allclose(intensity_matrices[1], intensity_matrices[2])
def test_tm(): t_old = transition_matrix(2**11) t_new = cache_tm(2**11) assert np.array_equal(t_old.todense(), t_new.todense())
def test_cache_tm(): T1 = transition_matrix(2**3) T2 = cache_tm(2**3) assert np.array_equal(T1.todense(), T2.todense())