## finite open, finite periodic and infinite periodic chains

How do I use this algorithm? What does that parameter do?
Qottmann
Posts: 14
Joined: 27 Mar 2019, 09:11
Location: ICFO Barcelona

### finite open, finite periodic and infinite periodic chains

Hello,

is there a way to have a finite periodic chain (so a ring) for the BoseHubbard model?
As far as I understand setting bc_MPS to "finite" gives a finite chain with open boundary conditions and "infinite" is basically performing iDMRG - or am I already getting this part wrong?

Best regards,
Korbinian
Johannes
Posts: 183
Joined: 21 Jul 2018, 12:52
Location: UC Berkeley

### Re: finite open, finite periodic and infinite periodic chains

Qottmann wrote: 14 Oct 2019, 10:19 is there a way to have a finite periodic chain (so a ring) for the BoseHubbard model?
Kind of. We do not support finite MPS with periodic boundaries for the MPS itself i.e. writing
$| \Psi\rangle = \sum Tr(A^{\sigma_1} \cdots A^{\sigma_L}) | \sigma_1 \cdots \sigma_L\rangle$
This is a form which is usefull analytically (e.g. if you write the ground state of the AKLT model on a finite ring), but not numerically, because it doesn't allow to define a canonical form.

However, you can define a bc_MPS="finite" and still have periodic couplings in your Hamiltonian. The price you pay for this is that the coupling over the "boundary" of the MPS is long range afterwards. Hence you can't use TEBD, and if you use DMRG, you should definitely use the mixer.
To do that, take a look at the parameters documented in init_lattice, i.e. use bc_MPS=True, bc_x="periodic".

Ian McCulloch once suggested that one can also use a different "enumeration" or "order" of the MPS compared to the physical sites in such a case to avoid having the terribly long range:
$| \Psi\rangle = \sum A^{\sigma_1} A^{\sigma_2} A^{\sigma_3} \cdots A^{\sigma_L}) | \sigma_1 \cdots \sigma_L\rangle$
one could use
$| \Psi\rangle = \sum A^{\sigma_L} A^{\sigma_1} A^{\sigma_{L-1}} A^{\sigma_2} A^{\sigma_{L-2}} A^{\sigma_3} \cdots A^{\sigma_{L/2}} | \sigma_1 \cdots \sigma_L\rangle$
In that way, a nearest neighbor coupling on the ring becomes a next-nearest neighbour coupling for the MPO.
I've never tried that out myself with TeNPy, but it is implemented already with the help of the order. I added a few lines in a git commit a few minutes ago such that you can now use order='folded' as model parameter for the tenpy.models.lattice.Chain.
Be aware the functions like the expectation_value, which return an array with the expectation value of a local operator on each site of an MPS will also be affected by that order. You can use the lattice method mps2lat_values to permute the values in the array such that it corresponds to the original/default order.
Qottmann
Posts: 14
Joined: 27 Mar 2019, 09:11
Location: ICFO Barcelona

### Re: finite open, finite periodic and infinite periodic chains

Johannes wrote: 15 Oct 2019, 15:15
Qottmann wrote: 14 Oct 2019, 10:19 is there a way to have a finite periodic chain (so a ring) for the BoseHubbard model?
(..)
In that way, a nearest neighbor coupling on the ring becomes a next-nearest neighbour coupling for the MPO.
I've never tried that out myself with TeNPy, but it is implemented already with the help of the order. I added a few lines in a git commit a few minutes ago such that you can now use order='folded' as model parameter for the tenpy.models.lattice.Chain.
Be aware the functions like the expectation_value, which return an array with the expectation value of a local operator on each site of an MPS will also be affected by that order. You can use the lattice method mps2lat_values to permute the values in the array such that it corresponds to the original/default order.
First of all thanks for providing this feature!

I am trying now to use this folding method. What @Johannes wrote here sounds like I can just give a Chain with order="folded" as the lattice in model_params, but is this really the case? Don't i need to have 2 single n-n coupling at initial and last bond and n-n-n-coupling in the bulk, in order to get the periodic circle?
Screenshot from 2020-09-02 17-21-44.png (11.32 KiB) Viewed 173 times
I am talking about n-n models that are inititated like

Code: Select all

def init_terms(self, model_params):
# 0) Read and set parameters.
t = get_parameter(model_params, 't', 1., self.name, True)
U = get_parameter(model_params, 'U', 0., self.name, True)
for u in range(len(self.lat.unit_cell)):
for u1, u2, dx in self.lat.pairs['nearest_neighbors']:
self.add_coupling(-t, u1, 'Bd', u2, 'B', dx, plus_hc=True)
I am asking because the lattice.pairs entries are the same for a default and folded Chain. Or am I missing something in how CouplingMPOModels are created?

edit: I guess I am asking how I would implement it in the end. I am bit puzzled by the add_coupling routine and the fact that u1, and u2 are both 0 in the n-n case (general confusion, no specific to this post/model).

Maybe something like this could work:

Code: Select all

for u1, u2, dx in self.lat.pairs['nearest_neighbors']:
self.add_coupling(t * np.array([1,0,...0,1]), u1, 'Bd', u2, 'B', dx, plus_hc=True)
for u1, u2, dx in self.lat.pairs['next_nearest_neighbors']:
self.add_coupling(t * np.array([0,1,1,....,1,1,0]), u1, 'Bd', u2, 'B', dx, plus_hc=True)

so like "masking" the interactions as add_coupling can take numpy arrays of different strength,
Johannes
Posts: 183
Joined: 21 Jul 2018, 12:52
Location: UC Berkeley

### Re: finite open, finite periodic and infinite periodic chains

Oops!
There was a bug in init_lattice that the 'order' parameter was read out, but not used for 1D lattices (i.e. the Chain and Ladder).
I've quickly fixed this in 9e020640e180d6fb9d09f534a9c91fa047cf6bab.

After this fix, using order='folded' is really "enough", apart from making sure that you understand how to read expectation values etc.
Example:

Code: Select all

import tenpy
from tenpy.models.spins import SpinModel

M = SpinModel({'L': 10,
'Jx': 0., 'Jy': 0., 'Jz': 1.,
'bc_MPS': 'finite', 'bc_x': 'periodic',
'order': 'folded'})
print("order:")
print(M.lat.order)
print("coupling terms:")
print(M.all_coupling_terms().to_TermList())

ps = [['up'], ['down']] * (M.options['L']//2)  # Neel state in lattice order
psi = tenpy.networks.mps.MPS.from_lat_product_state(M.lat, ps)
Sz_mps = psi.expectation_value("Sz")
print("Sz_mps = ", Sz_mps)
Sz_lat = M.lat.mps2lat_values(Sz_mps)
print("Sz_lat = ", Sz_lat)

The output:

Code: Select all

Reading 'bc_MPS'='finite' for config SpinModel
SpinModel: set conserve to Sz
order:
[[0 0]
[9 0]
[1 0]
[8 0]
[2 0]
[7 0]
[3 0]
[6 0]
[4 0]
[5 0]]
coupling terms:
1.00000 * Sz_0 Sz_1 +
1.00000 * Sz_0 Sz_2 +
1.00000 * Sz_1 Sz_3 +
1.00000 * Sz_2 Sz_4 +
1.00000 * Sz_3 Sz_5 +
1.00000 * Sz_4 Sz_6 +
1.00000 * Sz_5 Sz_7 +
1.00000 * Sz_6 Sz_8 +
1.00000 * Sz_7 Sz_9 +
1.00000 * Sz_8 Sz_9
Sz_mps =  [ 0.5 -0.5 -0.5  0.5  0.5 -0.5 -0.5  0.5  0.5 -0.5]
Sz_lat =  [ 0.5 -0.5  0.5 -0.5  0.5 -0.5  0.5 -0.5  0.5 -0.5]

The entries of order define in which order the MPS winds, and indeed you get the same order as in the bottom of your figure (apart from the fact that python starts counting with 0, so you have to subtract 1).
The second print shows that the "long range" couplings appear correctly: 0-9 now label the sites inside the MPS (left to right in your figure), so we have coupling pairs (0,1), (i, i+2) for 0 < i < 8, and (8,9), as we expect from your figure.

The product state you define for from_lat_product_state is independent of the order, i.e. as you would write it down with "default" order. (The extra brackets are for the unit cell index, for example for the ladder you need two entries each.)

Finally, the function mps2lat_values can be used to convert an array of expectation values back into the canonical form again.