Script

download script

  1#
  2import sys, os
  3
  4os.environ["KMP_DUPLICATE_LIB_OK"] = (
  5    "True"  # uncomment this line if omp error occurs on OSX for python 3
  6)
  7os.environ["OMP_NUM_THREADS"] = "1"  # set number of OpenMP threads to run in parallel
  8os.environ["MKL_NUM_THREADS"] = "1"  # set number of MKL threads to run in parallel
  9#
 10
 11#######################################################################
 12#                            example 20                               #
 13# This example shows how to use the `Lanczos` submodule of the        #
 14# `tools` module to compute the time evolution of a quantum state     #
 15# and how to find ground states of hermitian Hamiltonians.            #
 16#######################################################################
 17from quspin.basis import spin_basis_1d
 18from quspin.operators import hamiltonian
 19from scipy.sparse.linalg import expm_multiply
 20from quspin.tools.lanczos import lanczos_full, lanczos_iter, lin_comb_Q_T, expm_lanczos
 21import numpy as np
 22import scipy.linalg as sla
 23
 24#
 25np.random.seed(17)  # set random seed, cf initial state below
 26#
 27##### Heisenberg model
 28L = 20  # system size
 29dt = 0.1  # unitary evolution time step
 30# basis object
 31basis = spin_basis_1d(L, m=0, kblock=0, pblock=1, zblock=1, pauli=False)
 32print("\nHilbert space dimension: {}.\n".format(basis.Ns))
 33# Heisenberg Hamiltonian
 34J_list = [[1.0, i, (i + 1) % L] for i in range(L)]
 35static = [[op, J_list] for op in ["xx", "yy", "zz"]]
 36H = hamiltonian(static, [], basis=basis, dtype=np.float64)
 37#
 38##### Lanczos time evolution calculation
 39#
 40m_evo = 20  # Krylov subspace dimension
 41#
 42# initial states
 43v0 = np.random.normal(0, 1, size=basis.Ns)
 44v0 /= np.linalg.norm(v0)
 45# make copies to test the lanczos routines independently
 46v_expm_multiply = v0.copy()
 47v_lanczos_full = v0.copy()
 48v_lanczos_iter = v0.copy()
 49#
 50print("\nchecking lanczos matrix exponential calculation:\n")
 51for i in range(100):
 52    # compute Lanczos decomposition
 53    E_full, V_full, Q_full = lanczos_full(
 54        H, v_lanczos_full, m_evo
 55    )  # all Lanczos vectors at once
 56    E_iter, V_iter, Q_iter = lanczos_iter(
 57        H, v_lanczos_iter, m_evo
 58    )  # Lanczos vectors as an iterator
 59    # evolve quantum state using different routines
 60    v_expm_multiply = expm_multiply(
 61        -1j * dt * H.static, v_expm_multiply
 62    )  # cf tools.expm_multiply_parallel with OMP speedup
 63    v_lanczos_full = expm_lanczos(E_full, V_full, Q_full, a=-1j * dt)
 64    v_lanczos_iter = expm_lanczos(E_iter, V_iter, Q_iter, a=-1j * dt)
 65    # test results against each other
 66    np.testing.assert_allclose(v_lanczos_full, v_expm_multiply, atol=1e-10, rtol=0)
 67    np.testing.assert_allclose(v_lanczos_iter, v_expm_multiply, atol=1e-10, rtol=0)
 68    #
 69    print("finished unitary evolution step: {0:d}.".format(i))
 70#
 71print("\ntime evolution complete.\n")
 72#
 73###### Lanczos ground state calculation
 74#
 75# compute exact GS data
 76E_GS, psi_GS = H.eigsh(k=1, which="SA")
 77psi_GS = psi_GS.ravel()
 78#
 79###### apply Lanczos
 80# initial state for Lanczos algorithm
 81v0 = np.random.normal(0, 1, size=basis.Ns)
 82v0 /= np.linalg.norm(v0)
 83#
 84m_GS = 50  # Krylov subspace dimension
 85#
 86# Lanczos finds the largest-magnitude eigenvalues:
 87E, V, Q_T = lanczos_full(H, v0, m_GS, full_ortho=False)
 88#
 89# check GS energy convergence
 90try:
 91    # compute difference to exact GS energy value
 92    dE = np.abs(E[0] - E_GS[0])
 93    assert dE < 1e-10
 94except AssertionError:
 95    raise AssertionError(
 96        "Energy failed to converge |E_lanczos-E_exact| = {} > 1e-10".format(dE)
 97    )
 98#
 99# compute ground state vector
100psi_GS_lanczos = lin_comb_Q_T(V[:, 0], Q_T)
101# check ground state convergence
102try:
103    # compute fidelity of being in exact GS
104    F = np.abs(np.log(np.abs(np.vdot(psi_GS_lanczos, psi_GS))))
105    assert F < 1e-10
106except AssertionError:
107    raise AssertionError(
108        "wavefunction failed to converge to fidelity = {} > 1e-10".format(F)
109    )
110#
111print("\nground state calculation complete.\n")