d_dmrg.py

on github (download).

"""Example illustrating the use of DMRG in tenpy.

The example functions in this class do the same as the ones in `toycodes/d_dmrg.py`,
but make use of the classes defined in tenpy.
"""
# Copyright (C) TeNPy Developers, Apache license

import numpy as np

from tenpy.algorithms import dmrg
from tenpy.models.spins import SpinModel
from tenpy.models.tf_ising import TFIChain
from tenpy.networks.mps import MPS


def example_DMRG_tf_ising_finite(L, g):
    print('finite DMRG, transverse field Ising model')
    print(f'L={L:d}, g={g:.2f}')
    model_params = dict(L=L, J=1.0, g=g, bc_MPS='finite', conserve=None)
    M = TFIChain(model_params)
    product_state = ['up'] * M.lat.N_sites
    psi = MPS.from_product_state(
        M.lat.mps_sites(), product_state, bc=M.lat.bc_MPS, unit_cell_width=M.lat.mps_unit_cell_width
    )
    dmrg_params = {
        'mixer': None,  # setting this to True helps to escape local minima
        'max_E_err': 1.0e-10,
        'trunc_params': {'chi_max': 30, 'svd_min': 1.0e-10},
        'combine': True,
    }
    info = dmrg.run(psi, M, dmrg_params)  # the main work...
    E = info['E']
    print(f'E = {E:.13f}')
    print('final bond dimensions: ', psi.chi)
    mag_x = np.sum(psi.expectation_value('Sigmax'))
    mag_z = np.sum(psi.expectation_value('Sigmaz'))
    print(f'magnetization in X = {mag_x:.5f}')
    print(f'magnetization in Z = {mag_z:.5f}')
    if L < 20:  # compare to exact result
        from tfi_exact import finite_gs_energy

        E_exact = finite_gs_energy(L, 1.0, g)
        print(f'Exact diagonalization: E = {E_exact:.13f}')
        print('relative error: ', abs((E - E_exact) / E_exact))
    return E, psi, M


def example_1site_DMRG_tf_ising_finite(L, g):
    print('single-site finite DMRG, transverse field Ising model')
    print(f'L={L:d}, g={g:.2f}')
    model_params = dict(L=L, J=1.0, g=g, bc_MPS='finite', conserve=None)
    M = TFIChain(model_params)
    product_state = ['up'] * M.lat.N_sites
    psi = MPS.from_product_state(
        M.lat.mps_sites(), product_state, bc=M.lat.bc_MPS, unit_cell_width=M.lat.mps_unit_cell_width
    )
    dmrg_params = {
        'mixer': True,  # setting this to True is essential for the 1-site algorithm to work.
        'max_E_err': 1.0e-10,
        'trunc_params': {'chi_max': 30, 'svd_min': 1.0e-10},
        'combine': False,
        'active_sites': 1,  # specifies single-site
    }
    info = dmrg.run(psi, M, dmrg_params)
    E = info['E']
    print(f'E = {E:.13f}')
    print('final bond dimensions: ', psi.chi)
    mag_x = np.sum(psi.expectation_value('Sigmax'))
    mag_z = np.sum(psi.expectation_value('Sigmaz'))
    print(f'magnetization in X = {mag_x:.5f}')
    print(f'magnetization in Z = {mag_z:.5f}')
    if L < 20:  # compare to exact result
        from tfi_exact import finite_gs_energy

        E_exact = finite_gs_energy(L, 1.0, g)
        print(f'Exact diagonalization: E = {E_exact:.13f}')
        print('relative error: ', abs((E - E_exact) / E_exact))
    return E, psi, M


def example_DMRG_tf_ising_infinite(g):
    print('infinite DMRG, transverse field Ising model')
    print(f'g={g:.2f}')
    model_params = dict(L=2, J=1.0, g=g, bc_MPS='infinite', conserve=None)
    M = TFIChain(model_params)
    product_state = ['up'] * M.lat.N_sites
    psi = MPS.from_product_state(
        M.lat.mps_sites(), product_state, bc=M.lat.bc_MPS, unit_cell_width=M.lat.mps_unit_cell_width
    )
    dmrg_params = {
        'mixer': True,  # setting this to True helps to escape local minima
        'trunc_params': {'chi_max': 30, 'svd_min': 1.0e-10},
        'max_E_err': 1.0e-10,
    }
    # Sometimes, we want to call a 'DMRG engine' explicitly
    eng = dmrg.TwoSiteDMRGEngine(psi, M, dmrg_params)
    E, psi = eng.run()  # equivalent to dmrg.run() up to the return parameters.
    print(f'E = {E:.13f}')
    print('final bond dimensions: ', psi.chi)
    mag_x = np.mean(psi.expectation_value('Sigmax'))
    mag_z = np.mean(psi.expectation_value('Sigmaz'))
    print(f'<sigma_x> = {mag_x:.5f}')
    print(f'<sigma_z> = {mag_z:.5f}')
    print('correlation length:', psi.correlation_length())
    # compare to exact result
    from tfi_exact import infinite_gs_energy

    E_exact = infinite_gs_energy(1.0, g)
    print(f'Analytic result: E (per site) = {E_exact:.13f}')
    print('relative error: ', abs((E - E_exact) / E_exact))
    return E, psi, M


def example_1site_DMRG_tf_ising_infinite(g):
    print('single-site infinite DMRG, transverse field Ising model')
    print(f'g={g:.2f}')
    model_params = dict(L=2, J=1.0, g=g, bc_MPS='infinite', conserve=None)
    M = TFIChain(model_params)
    product_state = ['up'] * M.lat.N_sites
    psi = MPS.from_product_state(
        M.lat.mps_sites(), product_state, bc=M.lat.bc_MPS, unit_cell_width=M.lat.mps_unit_cell_width
    )
    dmrg_params = {
        'mixer': True,  # setting this to True is essential for the 1-site algorithm to work.
        'trunc_params': {'chi_max': 30, 'svd_min': 1.0e-10},
        'max_E_err': 1.0e-10,
        'combine': True,
    }
    eng = dmrg.SingleSiteDMRGEngine(psi, M, dmrg_params)
    E, psi = eng.run()  # equivalent to dmrg.run() up to the return parameters.
    print(f'E = {E:.13f}')
    print('final bond dimensions: ', psi.chi)
    mag_x = np.mean(psi.expectation_value('Sigmax'))
    mag_z = np.mean(psi.expectation_value('Sigmaz'))
    print(f'<sigma_x> = {mag_x:.5f}')
    print(f'<sigma_z> = {mag_z:.5f}')
    print('correlation length:', psi.correlation_length())
    # compare to exact result
    from tfi_exact import infinite_gs_energy

    E_exact = infinite_gs_energy(1.0, g)
    print(f'Analytic result: E (per site) = {E_exact:.13f}')
    print('relative error: ', abs((E - E_exact) / E_exact))


def example_DMRG_heisenberg_xxz_infinite(Jz, conserve='best'):
    print('infinite DMRG, Heisenberg XXZ chain')
    print(f'Jz={Jz:.2f}, conserve={conserve!r}')
    model_params = dict(
        L=2,
        S=0.5,  # spin 1/2
        Jx=1.0,
        Jy=1.0,
        Jz=Jz,  # couplings
        bc_MPS='infinite',
        conserve=conserve,
    )
    M = SpinModel(model_params)
    product_state = ['up', 'down']  # initial Neel state
    psi = MPS.from_product_state(
        M.lat.mps_sites(), product_state, bc=M.lat.bc_MPS, unit_cell_width=M.lat.mps_unit_cell_width
    )
    dmrg_params = {
        'mixer': True,  # setting this to True helps to escape local minima
        'trunc_params': {
            'chi_max': 100,
            'svd_min': 1.0e-10,
        },
        'max_E_err': 1.0e-10,
    }
    info = dmrg.run(psi, M, dmrg_params)
    E = info['E']
    print(f'E = {E:.13f}')
    print('final bond dimensions: ', psi.chi)
    Sz = psi.expectation_value('Sz')  # Sz instead of Sigma z: spin-1/2 operators!
    mag_z = np.mean(Sz)
    print(f'<S_z> = [{Sz[0]:.5f}, {Sz[1]:.5f}]; mean ={mag_z:.5f}')
    # note: it's clear that mean(<Sz>) is 0: the model has Sz conservation!
    print('correlation length:', psi.correlation_length())
    corrs = psi.correlation_function('Sz', 'Sz', sites1=range(10))
    print('correlations <Sz_i Sz_j> =')
    print(corrs)
    return E, psi, M


if __name__ == '__main__':
    import logging

    logging.basicConfig(level=logging.INFO)
    example_DMRG_tf_ising_finite(L=10, g=1.0)
    print('-' * 100)
    example_1site_DMRG_tf_ising_finite(L=10, g=1.0)
    print('-' * 100)
    example_DMRG_tf_ising_infinite(g=1.5)
    print('-' * 100)
    example_1site_DMRG_tf_ising_infinite(g=1.5)
    print('-' * 100)
    example_DMRG_heisenberg_xxz_infinite(Jz=1.5)