Page 1 of 1

Energy gap for infinite system using segment DMRG?

Posted: 11 Apr 2021, 18:18
by rubenv
Hi everyone,

Currently, given a system, there are two ways of extracting an energy gap: either by doing finite DMRG (downside: there are boundary effects) or by doing periodic systems (downside: this is very costly since if naively requires the square of the original bond dimension).

Ideally, there is a third option, which avoids the above two downsides: one obtains the ground state on an infinitely-long system and one then uses segment DMRG to keep the left-infinite and right-infinite environments fixed, and then finds an orthogonal state where one only optimizes a finite number of sites in between these fixed environments.

My question: is this possible using the current package, or does this something we still need to implement? My confusion: it seems that MPS, MPOs and DMRG all allow for the 'segment' option (according to the documentation), but it is unclear to me at which point one actually feeds in the knowledge of the infinite left and right environments (which are of course crucial for correctly calculating the energy when doing DMRG).

With best wishes,
Ruben

Re: Energy gap for infinite system using segment DMRG?

Posted: 13 Apr 2021, 23:24
by Johannes
Hi Ruben,
you're right, the DMRG code supports segment boundary conditions already.
Right now, you need to extract the left and right environment from a previous DMRG run, and then specify it in resume_data['init_env_data'] to the subsequent DMRG run by hand.
There's still some subtleties, e.g. how to interpret the resulting energy - it just reports the total energy including the environments for the moment.

By chance, I'm working on this already and actually plan to have some results including an example jupyter notebook and likely a new simulation class for this by the end of the week....

Re: Energy gap for infinite system using segment DMRG?

Posted: 15 Apr 2021, 15:43
by rubenv
Hi Johannes,

Thanks, that is really helpful! I have been playing around with it today, but still can't seem to figure it out: how do I properly define the segment MPS form the original MPS?

Things I have tried (where psi is the original infinite g.s. MPS obtained from iDMRG):

Code: Select all

B = [psi.get_B(i).to_ndarray().transpose([1,0,2]) for i in range(psi.L)] ### this just gives us the B-matrices associated to psi
phi = MPS.from_Bflat(sites,B,bc='segment') ### for now just trying to create a segment version with the same unit cell size as original iMPS
But the resulting wavefunction is non-sensical (e.g., if I call 'canonical_form()', observables are no longer translation-invariant, indicating that I screwed up the state).

Variations of the above that also did not work:

Code: Select all

B = [psi.get_B(i).to_ndarray().transpose([1,0,2]) for i in range(psi.L)] 
S = [psi.get_SL(i) for i in range(psi.L)]
S = S+[S[0]]
phi = MPS.from_Bflat(sites,B,SVs=S,bc='segment')
and

Code: Select all

B = psi._B
S = psi._S
phi = MPS(sites,B,S,bc='segment')
Not sure what I am doing wrong (but might be some issue with the 'form' of the MPS). On a related note: I guess I should try to avoid calling canonical_form() before doing segment DMRG---or will it leave the 'segment links' unchanged such that the 'old' environment will still be compatible with those virtual legs?

Cheers,
Ruben