Excitations with DMRG and segment boundary conditions
This notebook illustrates how we can find excited states with DMRG.
The idea is that we run a first DMRG to find the ground state \(|\psi_0\rangle\) and then run DMRG on a modified Hamiltonian
to find the first excited state \(|\psi_1\rangle\).
For the second excited state, we would use
and so on.
In the infinite case, this doesn’t work because the overlaps/projectors are no longer well defined. However, we can consider a finite segment in the infinite chain, and take the limit of making that segment very big.
[1]:
import numpy as np
import matplotlib.pyplot as plt
np.set_printoptions(precision=5, suppress=True, linewidth=100)
plt.rcParams['figure.dpi'] = 150
[2]:
import tenpy
from tenpy.algorithms import dmrg
from tenpy.networks.mps import MPS
from tenpy.models.tf_ising import TFIChain
from tenpy.networks.mpo import MPOEnvironment
tenpy.tools.misc.setup_logging(to_stdout="INFO")
/Users/jakobunfried/repos/tenpy/tenpy/tools/optimization.py:317: UserWarning: Couldn't load compiled cython code. Code will run a bit slower.
warnings.warn("Couldn't load compiled cython code. Code will run a bit slower.")
Infinite Systems with a modified center: segment boundary conditions
For infinite systems, the issue arrises that the overlap of two different states is formally always zero. However, we can look for excitations on a finite “segment” in the center and keep everything outside this segment fixed:
fixed left half-infinte chain | "segment" | fixed right half-infinte chain
... --A[-3]--A[-2]--A[-1]--C[0]--C[1]--C[2]-- ... --C[L-2]--C[L-1]--B[L]--B[L+1]--B[L+2]-- ...
Here, all the A of the left half-chain have to be in left-canonical form, all the B on the right are right-canonical, and the C can be in any canonical form, with a center matrix somewhere (where we do DMRG). Since we keep the A and B fixed, the overlap with a state of modified C is well definied again, and we can use the same trick to orhtogonalize against previously found states.
In DMRG, we can acchieve this situation by just fixing the environments at the boundaries of the segment. If we take trivial boundaries on one of the two sides, we can study the boundary of a half-infinite chain.
[3]:
model_params = {
'J': 1. , 'g': 1.5,
'L': 2,
'bc_MPS': 'infinite',
'conserve': 'best',
}
M_i = TFIChain(model_params)
INFO : TFIChain: reading 'bc_MPS'='infinite'
INFO : TFIChain: reading 'conserve'='best'
INFO : TFIChain: set conserve to parity
INFO : TFIChain: reading 'L'=2
INFO : TFIChain: reading 'J'=1.0
INFO : TFIChain: reading 'g'=1.5
[4]:
# first dmrg run for *infinite* lattice
psi0_i = MPS.from_lat_product_state(M_i.lat, [['up']])
dmrg_params = {
'mixer': True,
'max_E_err': 1.e-10,
'trunc_params': {
'chi_max': 100,
'svd_min': 1.e-10,
},
}
eng0_i = dmrg.TwoSiteDMRGEngine(psi0_i, M_i, dmrg_params)
E0_i, _ = eng0_i.run()
resume_psi0_i = eng0_i.get_resume_data(sequential_simulations=True)
INFO : TwoSiteDMRGEngine: subconfig 'trunc_params'=Config(<2 options>, 'trunc_params')
INFO : start environment_sweep
INFO : trunc_params: reading 'chi_max'=100
INFO : trunc_params: reading 'svd_min'=1e-10
INFO : TwoSiteDMRGEngine: reading 'mixer'=True
INFO : activate DensityMatrixMixer with initial amplitude 1e-05
INFO : Running sweep with optimization
INFO : start environment_sweep
INFO : checkpoint after sweep 10
energy=-1.6719262215362640, max S=0.1534954326827670, age=128, norm_err=1.5e-15
Current memory usage 187.8MB, wall time: 0.3s
Delta E = nan, Delta S = 1.5350e-02 (per sweep)
max trunc_err = 2.8652e-20, max E_trunc = 1.1369e-13
chi: [22, 22]
================================================================================
INFO : Running sweep with optimization
INFO : start environment_sweep
INFO : checkpoint after sweep 20
energy=-1.6719262215361965, max S=0.1534917776136824, age=248, norm_err=9.2e-16
Current memory usage 188.0MB, wall time: 0.6s
Delta E = 6.7502e-15, Delta S = -3.6551e-07 (per sweep)
max trunc_err = 2.6514e-20, max E_trunc = 4.5475e-13
chi: [21, 22]
================================================================================
INFO : TwoSiteDMRGEngine: reading 'max_E_err'=1e-10
INFO : TwoSiteDMRGEngine: Convergence criterion reached with enabled mixer. Disable mixer and continue.
INFO : deactivate DensityMatrixMixer with final amplitude 1.5624999999999996e-07
INFO : Running sweep with optimization
INFO : start environment_sweep
INFO : checkpoint after sweep 30
energy=-1.6719262215360970, max S=0.1534912555393442, age=368, norm_err=1.5e-15
Current memory usage 188.5MB, wall time: 0.2s
Delta E = 9.9476e-15, Delta S = -5.2207e-08 (per sweep)
max trunc_err = 1.8040e-20, max E_trunc = 6.8212e-13
chi: [21, 21]
================================================================================
INFO : TwoSiteDMRGEngine finished after 30 sweeps, max chi=21
[5]:
resume_psi0_i
[5]:
{'psi': <tenpy.networks.mps.MPS at 0x163864ec0>,
'sequential_simulations': True,
'init_env_data': {'init_LP': <npc.Array shape=(21, 3, 21) labels=['vR*', 'wR', 'vR']>,
'age_LP': 184,
'init_RP': <npc.Array shape=(21, 3, 21) labels=['vL', 'wL', 'vL*']>,
'age_RP': 184}}
[6]:
psi0_i.entanglement_entropy()
[6]:
array([0.15349, 0.15349])
[7]:
enlarge = 10 # this is a parameter: how large should the "segment" be?
# beware: if you have gapless excitations, this will induce a "finite-size" gap ~ 1/(enlarge*N_sites_per_unit_cell)
M_s = M_i.extract_segment(enlarge=enlarge)
first, last = M_s.lat.segment_first_last
psi0_s = psi0_i.extract_segment(first, last)
init_env_data = eng0_i.env.get_initialization_data(first, last)
psi1_s = psi0_s.copy() # TODO: perturb this a little bit
resume_psi1_s = {'init_env_data': init_env_data}
Note: there is a somewhat arbitrary constant in the energy depending on the number of contracted sites in the environment. You should only compare energy differences!
[8]:
eng = dmrg.TwoSiteDMRGEngine(psi1_s, M_s, dmrg_params, resume_data=resume_psi1_s)
E1_s, _ = eng.run()
INFO : TwoSiteDMRGEngine: reading 'diag_method'='default'
INFO : TwoSiteDMRGEngine: subconfig 'trunc_params'=Config(<5 options>, 'trunc_params')
INFO : TwoSiteDMRGEngine: reading 'max_N_sites_per_ring'=18
INFO : TwoSiteDMRGEngine: reading 'combine'=False
INFO : TwoSiteDMRGEngine: subconfig 'lanczos_params'=Config(<9 options>, 'lanczos_params')
INFO : TwoSiteDMRGEngine: reading 'chi_list'=None
INFO : TwoSiteDMRGEngine: reading 'N_sweeps_check'=10
INFO : TwoSiteDMRGEngine: subconfig 'mixer_params'=Config(<3 options>, 'mixer_params')
INFO : TwoSiteDMRGEngine: reading 'mixer'=True
INFO : activate DensityMatrixMixer with initial amplitude 1e-05
INFO : TwoSiteDMRGEngine: reading 'max_sweeps'=1000
INFO : TwoSiteDMRGEngine: reading 'max_hours'=8760
INFO : TwoSiteDMRGEngine: reading 'P_tol_to_trunc'=0.05
INFO : TwoSiteDMRGEngine: reading 'P_tol_min'=5.0000000000000005e-22
INFO : TwoSiteDMRGEngine: reading 'P_tol_max'=0.0001
INFO : TwoSiteDMRGEngine: reading 'E_tol_to_trunc'=None
INFO : Running sweep with optimization
INFO : TwoSiteDMRGEngine: reading 'max_N_for_ED'=400
INFO : checkpoint after sweep 10
energy=-647.1479565066215400, max S=0.1534963973666747, age=388, norm_err=4.7e-12
Current memory usage 189.7MB, wall time: 3.2s
Delta E = nan, Delta S = 2.7062e-08 (per sweep)
max trunc_err = 4.0132e-20, max E_trunc = 1.4779e-12
chi: [21, 24, 23, 23, 23, 26, 22, 22, 23, 21, 24, 23, 22, 20, 22, 23, 23, 23, 23, 24, 21]
================================================================================
INFO : Running sweep with optimization
INFO : checkpoint after sweep 20
energy=-647.1479565066206305, max S=0.1534918982875756, age=388, norm_err=4.3e-12
Current memory usage 189.8MB, wall time: 3.0s
Delta E = 9.0949e-14, Delta S = -2.3679e-08 (per sweep)
max trunc_err = 3.5087e-20, max E_trunc = 2.2737e-12
chi: [21, 24, 24, 21, 25, 19, 22, 21, 19, 23, 22, 21, 24, 22, 22, 22, 20, 24, 22, 24, 21]
================================================================================
INFO : TwoSiteDMRGEngine: reading 'max_E_err'=1e-10
INFO : TwoSiteDMRGEngine: reading 'max_S_err'=1e-05
INFO : TwoSiteDMRGEngine: Convergence criterion reached with enabled mixer. Disable mixer and continue.
INFO : deactivate DensityMatrixMixer with final amplitude 1.5624999999999996e-07
INFO : Running sweep with optimization
INFO : checkpoint after sweep 30
energy=-647.1479565066197210, max S=0.1534912555394641, age=388, norm_err=1.2e-13
Current memory usage 189.8MB, wall time: 1.2s
Delta E = 9.0949e-14, Delta S = -3.3829e-09 (per sweep)
max trunc_err = 1.8301e-20, max E_trunc = 1.0232e-12
chi: [21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21]
================================================================================
INFO : TwoSiteDMRGEngine: reading 'norm_tol'=1e-05
INFO : TwoSiteDMRGEngine: reading 'norm_tol_final'=1e-10
INFO : TwoSiteDMRGEngine finished after 30 sweeps, max chi=21
INFO : TwoSiteDMRGEngine: reading 'max_trunc_err'=0.0001
[9]:
psi1_s.entanglement_entropy()
[9]:
array([0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349,
0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349,
0.15349])
[10]:
psi1_s.entanglement_entropy() - np.mean(psi0_i.entanglement_entropy())
[10]:
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
project left boundary onto largest right schmidt state, use trivial/finite left bc
[11]:
psi_halfinf = psi0_s.copy() # the original MPS
S = psi0_s.get_SL(0)
proj = np.zeros(len(S), bool)
proj[np.argmax(S)] = True
B = psi_halfinf.get_B(0, form='B')
B.iproject(proj, 'vL')
psi_halfinf.set_B(0, B, form='B')
psi_halfinf.set_SL(0, np.ones(1, float))
psi_halfinf.canonical_form_finite()
psi_halfinf.test_sanity()
init_env_data_halfinf = init_env_data.copy()
LP = MPOEnvironment(psi0_i, M_i.H_MPO, psi0_i).init_LP(0, 0)
LP.iproject(proj, 'vR')
LP.iproject(proj, 'vR*')
init_env_data_halfinf['init_LP'] = LP
init_env_data_halfinf['age_LP'] = 0
B.get_leg('vL').test_contractible(LP.get_leg('vR'))
[12]:
eng_halfinf = dmrg.TwoSiteDMRGEngine(psi_halfinf, M_s, dmrg_params,
resume_data={'init_env_data': init_env_data_halfinf})
E_halfinf, _ = eng_halfinf.run()
INFO : TwoSiteDMRGEngine: reading 'diag_method'='default'
INFO : TwoSiteDMRGEngine: subconfig 'trunc_params'=Config(<5 options>, 'trunc_params')
INFO : TwoSiteDMRGEngine: reading 'max_N_sites_per_ring'=18
INFO : TwoSiteDMRGEngine: reading 'combine'=False
INFO : TwoSiteDMRGEngine: subconfig 'lanczos_params'=Config(<9 options>, 'lanczos_params')
INFO : TwoSiteDMRGEngine: reading 'chi_list'=None
INFO : TwoSiteDMRGEngine: reading 'N_sweeps_check'=10
INFO : TwoSiteDMRGEngine: subconfig 'mixer_params'=Config(<3 options>, 'mixer_params')
INFO : TwoSiteDMRGEngine: reading 'mixer'=True
INFO : activate DensityMatrixMixer with initial amplitude 1e-05
INFO : TwoSiteDMRGEngine: reading 'max_sweeps'=1000
INFO : TwoSiteDMRGEngine: reading 'max_hours'=8760
INFO : TwoSiteDMRGEngine: reading 'P_tol_to_trunc'=0.05
INFO : TwoSiteDMRGEngine: reading 'P_tol_min'=5.0000000000000005e-22
INFO : TwoSiteDMRGEngine: reading 'P_tol_max'=0.0001
INFO : TwoSiteDMRGEngine: reading 'E_tol_to_trunc'=None
INFO : Running sweep with optimization
INFO : TwoSiteDMRGEngine: reading 'max_N_for_ED'=400
INFO : checkpoint after sweep 10
energy=-340.2012366301067914, max S=0.1534912551231609, age=204, norm_err=4.9e-12
Current memory usage 189.8MB, wall time: 2.8s
Delta E = nan, Delta S = 6.6249e-04 (per sweep)
max trunc_err = 3.6382e-20, max E_trunc = 3.9790e-13
chi: [1, 2, 4, 8, 14, 19, 23, 22, 25, 21, 21, 22, 24, 22, 18, 24, 22, 24, 19, 24, 21]
================================================================================
INFO : Running sweep with optimization
INFO : checkpoint after sweep 20
energy=-340.2012366301066209, max S=0.1534912551231697, age=204, norm_err=3.3e-12
Current memory usage 189.8MB, wall time: 2.6s
Delta E = 1.7053e-14, Delta S = -2.3272e-08 (per sweep)
max trunc_err = 3.2117e-20, max E_trunc = 3.9790e-13
chi: [1, 2, 4, 8, 14, 22, 21, 23, 23, 21, 21, 24, 23, 23, 24, 21, 23, 21, 24, 23, 21]
================================================================================
INFO : TwoSiteDMRGEngine: reading 'max_E_err'=1e-10
INFO : TwoSiteDMRGEngine: reading 'max_S_err'=1e-05
INFO : TwoSiteDMRGEngine: Convergence criterion reached with enabled mixer. Disable mixer and continue.
INFO : deactivate DensityMatrixMixer with final amplitude 1.5624999999999996e-07
INFO : Running sweep with optimization
INFO : checkpoint after sweep 30
energy=-340.2012366301067345, max S=0.1534912551232007, age=204, norm_err=7.8e-14
Current memory usage 189.8MB, wall time: 1.4s
Delta E = -1.1369e-14, Delta S = -3.3246e-09 (per sweep)
max trunc_err = 1.8076e-20, max E_trunc = 3.9790e-13
chi: [1, 2, 4, 8, 13, 17, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21]
================================================================================
INFO : TwoSiteDMRGEngine: reading 'norm_tol'=1e-05
INFO : TwoSiteDMRGEngine: reading 'norm_tol_final'=1e-10
INFO : TwoSiteDMRGEngine finished after 30 sweeps, max chi=21
INFO : TwoSiteDMRGEngine: reading 'max_trunc_err'=0.0001
[13]:
psi_halfinf.entanglement_entropy()
[13]:
array([-0. , 0.13332, 0.14834, 0.15192, 0.15297, 0.15331, 0.15343, 0.15347, 0.15348,
0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349, 0.15349,
0.15349, 0.15349, 0.15349])
[14]:
psi_halfinf.expectation_value('Sigmaz')
[14]:
array([0.94082, 0.88667, 0.87957, 0.87797, 0.87753, 0.8774 , 0.87735, 0.87734, 0.87733, 0.87733,
0.87733, 0.87733, 0.87733, 0.87733, 0.87733, 0.87733, 0.87733, 0.87733, 0.87733, 0.87733])
[15]:
psi_halfinf.L
[15]:
20
modify model on left boundary
[16]:
model_params_defect = {
'J': 1. , 'g': [0.] + [model_params['g']] * (psi_halfinf.L-1),
'L': psi_halfinf.L,
'bc_MPS': 'segment', # <- this is not strictly allowed, but works here anyway
'conserve': 'best',
}
# hack to get away with bc_MPS='segment'
tenpy.networks.mpo.MPOGraph.test_sanity = lambda self: None
M_s_defect = TFIChain(model_params_defect)
INFO : TFIChain: reading 'bc_MPS'='segment'
INFO : TFIChain: reading 'conserve'='best'
INFO : TFIChain: set conserve to parity
INFO : TFIChain: reading 'L'=20
INFO : TFIChain: reading 'J'=1.0
INFO : TFIChain: reading 'g'=[0.0, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5]
[17]:
psi_defect = psi_halfinf.copy()
eng_defect = dmrg.TwoSiteDMRGEngine(psi_defect, M_s_defect, dmrg_params,
resume_data={'init_env_data': init_env_data_halfinf})
eng_defect.run()
INFO : TwoSiteDMRGEngine: reading 'diag_method'='default'
INFO : TwoSiteDMRGEngine: subconfig 'trunc_params'=Config(<5 options>, 'trunc_params')
INFO : TwoSiteDMRGEngine: reading 'max_N_sites_per_ring'=18
INFO : TwoSiteDMRGEngine: reading 'combine'=False
INFO : TwoSiteDMRGEngine: subconfig 'lanczos_params'=Config(<9 options>, 'lanczos_params')
INFO : TwoSiteDMRGEngine: reading 'chi_list'=None
INFO : TwoSiteDMRGEngine: reading 'N_sweeps_check'=10
INFO : TwoSiteDMRGEngine: subconfig 'mixer_params'=Config(<3 options>, 'mixer_params')
INFO : TwoSiteDMRGEngine: reading 'mixer'=True
INFO : activate DensityMatrixMixer with initial amplitude 1e-05
INFO : TwoSiteDMRGEngine: reading 'max_sweeps'=1000
INFO : TwoSiteDMRGEngine: reading 'max_hours'=8760
INFO : TwoSiteDMRGEngine: reading 'P_tol_to_trunc'=0.05
INFO : TwoSiteDMRGEngine: reading 'P_tol_min'=5.0000000000000005e-22
INFO : TwoSiteDMRGEngine: reading 'P_tol_max'=0.0001
INFO : TwoSiteDMRGEngine: reading 'E_tol_to_trunc'=None
INFO : Running sweep with optimization
INFO : TwoSiteDMRGEngine: reading 'max_N_for_ED'=400
INFO : checkpoint after sweep 10
energy=-338.8852443072402139, max S=0.3812662616169735, age=204, norm_err=1.2e-12
Current memory usage 189.8MB, wall time: 3.6s
Delta E = nan, Delta S = 2.9157e-03 (per sweep)
max trunc_err = 3.9105e-20, max E_trunc = 4.5475e-13
chi: [1, 2, 4, 8, 14, 24, 25, 22, 23, 25, 25, 26, 23, 25, 24, 23, 23, 26, 22, 26, 21]
================================================================================
INFO : Running sweep with optimization
INFO : checkpoint after sweep 20
energy=-338.8852443072409528, max S=0.3812643297151876, age=204, norm_err=2.2e-12
Current memory usage 189.8MB, wall time: 3.1s
Delta E = -7.3896e-14, Delta S = -1.0168e-08 (per sweep)
max trunc_err = 3.4294e-20, max E_trunc = 6.2528e-13
chi: [1, 2, 4, 8, 15, 22, 24, 24, 25, 24, 25, 25, 25, 24, 27, 24, 26, 24, 24, 26, 21]
================================================================================
INFO : TwoSiteDMRGEngine: reading 'max_E_err'=1e-10
INFO : TwoSiteDMRGEngine: reading 'max_S_err'=1e-05
INFO : TwoSiteDMRGEngine: Convergence criterion reached with enabled mixer. Disable mixer and continue.
INFO : deactivate DensityMatrixMixer with final amplitude 1.5624999999999996e-07
INFO : Running sweep with optimization
INFO : checkpoint after sweep 30
energy=-338.8852443072381675, max S=0.3812640537280537, age=204, norm_err=8.0e-14
Current memory usage 189.8MB, wall time: 1.4s
Delta E = 2.7853e-13, Delta S = -1.4526e-09 (per sweep)
max trunc_err = 2.0592e-20, max E_trunc = 5.6843e-13
chi: [1, 2, 4, 8, 15, 20, 23, 24, 25, 26, 26, 24, 24, 24, 24, 24, 24, 24, 24, 24, 21]
================================================================================
INFO : TwoSiteDMRGEngine: reading 'norm_tol'=1e-05
INFO : TwoSiteDMRGEngine: reading 'norm_tol_final'=1e-10
INFO : TwoSiteDMRGEngine finished after 30 sweeps, max chi=26
INFO : TwoSiteDMRGEngine: reading 'max_trunc_err'=0.0001
[17]:
(np.float64(-338.88524430723817), <tenpy.networks.mps.MPS at 0x1638035c0>)
[18]:
psi_defect.entanglement_entropy()
[18]:
array([-0. , 0.38126, 0.2482 , 0.1929 , 0.16987, 0.16032, 0.15635, 0.15469, 0.154 ,
0.15371, 0.15358, 0.15353, 0.15351, 0.1535 , 0.15349, 0.15349, 0.15349, 0.15349,
0.15349, 0.15349, 0.15349])
[19]:
psi_defect.expectation_value('Sigmaz')
[19]:
array([0.74536, 0.74534, 0.83553, 0.86216, 0.87149, 0.87501, 0.87639, 0.87694, 0.87717, 0.87726,
0.8773 , 0.87732, 0.87732, 0.87733, 0.87733, 0.87733, 0.87733, 0.87733, 0.87733, 0.87733])