Bipartitioning infinite MPS into 2 semi-infinite chains

How do I use this algorithm? What does that parameter do?
jamarks
Posts: 6
Joined: 01 May 2020, 19:14

Bipartitioning infinite MPS into 2 semi-infinite chains

Post by jamarks »

I'm trying to compute the Resta Polarization of a Fermionic SSH chain according to the method described in https://arxiv.org/pdf/1810.07043.pdf equations 13-15. In particular, I need to compute 'particle imbalance' by partitioning the system into 2 semi-infinite chains, and tracing out one of these to get components of the reduced density matrix. When I use the

Code: Select all

get_rho_segment([0], 1)
function, I end up getting a trivial 2x2 matrix, and I'm pretty sure I'm not accurately cutting the system into semi-infinite chains.

Does anyone know how to bipartition an infinite MPS into 2 semi-infinite chains so that I can compute the Resta polarization?

Thank you in advance for the help :)

gunheepark0229
Posts: 9
Joined: 15 May 2020, 10:52

Re: Bipartitioning infinite MPS into 2 semi-infinite chains

Post by gunheepark0229 »

There is a relevant post here!

viewtopic.php?f=7&t=95

User avatar
Johannes
Site Admin
Posts: 179
Joined: 21 Jul 2018, 12:52
Location: UC Berkeley

Re: Bipartitioning infinite MPS into 2 semi-infinite chains

Post by Johannes »

You want to cut the system into two halves, but get_rho_segment extracts the density matrix for the *few* sites you give as argument, so that's the wrong function.

The equations from the cited paper is really what's calculated by average_charge of the MPS (up to the prefactor constants, I believe), take a look at the (two-line) implementation of the function and probablity_per_charge.

Note that for infinite MPS this value is only defined modulo 1, i.e. 0.123 and 1.123 are equivalent: we need to subtract (somewhat) arbitrary integer numbers of charges to get a finite value.
However, adiabatically following the change of the value still makes sence, since then really you are interested in the *differences* of the charge values only - this is what's done in the paper.

The examples/chern_insulators/chiral_pi_flux.py make a similar "experiment" of flux pumping and following the value of the average charge, you can probably base your code on that example.

jamarks
Posts: 6
Joined: 01 May 2020, 19:14

Re: Bipartitioning infinite MPS into 2 semi-infinite chains

Post by jamarks »

Hi Johannes,

Thank you so much for your helpful and detailed response. I am indeed aware that the polarization is only defined modulo 1, but would still like to be able to compute this quantity.

The code you reference, which demonstrates flux pumping, (and the function 'average_charge',) is close to what I am looking for. However, the example in the code is still for finite systems, whereas I am looking to do this for iMPS. I tried to modify the example and played around with 'probability_per_charge' for infinite systems, but was not able to obtain any reasonable results. How does one properly use these functions on iMPS to get the polarization for infinite systems?

User avatar
Johannes
Site Admin
Posts: 179
Joined: 21 Jul 2018, 12:52
Location: UC Berkeley

Re: Bipartitioning infinite MPS into 2 semi-infinite chains

Post by Johannes »

I'm not sure what's the problem here?

The chiral_pi_flux.py example does work directly in the thermodynamic limit with infinite MPS.
Running it generates chiral_pi_flux_charge_pump.pdf, the equivalent of Fig. 4 in the paper you quote, and chiral_pi_flux_ent_spec_flow.pdf, the equivalent of Fig. 8.
The P from the paper is simply what's returned by average_charge.

How did you define the model?
average_charge does only work if you use charge conservation. Is that the issue?

jamarks
Posts: 6
Joined: 01 May 2020, 19:14

Re: Bipartitioning infinite MPS into 2 semi-infinite chains

Post by jamarks »

Hi Johannes,

Thanks again for the reply. The issue is that I'm using GroupedSite, and in addition to the Polarization, I am also interested in obtaining the eigenvalues of the transfer matrix. I've found that when I define the GroupedSite using charges = 'same', the TransferMatrix ends up having no eigenvalues after a few evolution steps, so I am forced to use charges='drop'. On the other hand, average_charge only gives a non-empty array when charges = 'same'.

User avatar
Johannes
Site Admin
Posts: 179
Joined: 21 Jul 2018, 12:52
Location: UC Berkeley

Re: Bipartitioning infinite MPS into 2 semi-infinite chains

Post by Johannes »

Hang on - you're running DMRG to obtain ground states, right? What do you mean with the "evolution" steps?
Why do you need the GroupedSite at all, if you're only running DMRG? Can you specify the hamiltonian?
And the transfer matrix between which states? You might need to explicitly set charge_sector=None, but then the charge conservation should have no effect on the eigenvalues of the transfer matrix.

jamarks
Posts: 6
Joined: 01 May 2020, 19:14

Re: Bipartitioning infinite MPS into 2 semi-infinite chains

Post by jamarks »

I'm using TEBD to get the ground state, and to do the real-time evolution. Here's the model definition:

Code: Select all

from tenpy.models.model import NearestNeighborModel, CouplingMPOModel
from tenpy.models.lattice import Site, Chain
from tenpy.networks.site import FermionSite, GroupedSite

class SSHIntModel(CouplingMPOModel):
	def init_sites(self, model_params):
		fs = FermionSite(conserve = 'N')
		gs = GroupedSite([fs, fs], labels = ['A', 'B'], charges = 'drop')
		gs.add_op('Sz', gs.NA - gs.NB, False)
		return gs

	def init_lattice(self, model_params):
		bc_MPS = model_params.get('bc_MPS', 'infinite')
		bc = 'periodic' if bc_MPS == 'infinite' else 'open'
		nsys = model_params.get('nsys') if bc_MPS == 'finite' else 2
		self.L = nsys
		fs = self.init_sites(model_params)
		lat = Chain(nsys, fs, bc=bc, bc_MPS=bc_MPS)
		return lat

	def init_terms(self, model_params):
		J = model_params.get('J', 0.)
		d = model_params.get('d', 1.)
		tau = model_params.get('tau', 1.)
		V = model_params.get('V', 0.)
		dlt = model_params.get('dlt', 0.)

		#### Staggered Onsite Potential ####
		if dlt != 0.:
			self.add_onsite(dlt, 0, 'Sz')

		#### intracell hopping terms ####
		self.add_onsite(-J, 0, 'CdA CB')
		self.add_onsite(J, 0, 'CA CdB')

		#### intercell hopping terms ####
		hop_plus = (d + tau)/2.
		self.add_coupling(-hop_plus, 0, 'CdB', 0, 'CA', [1])
		self.add_coupling(-hop_plus, 0, 'CdA', 0, 'CB', [-1])

		hop_minus = (d - tau)/2.
		self.add_coupling(-hop_minus, 0, 'CdA', 0, 'CB', [1])
		self.add_coupling(-hop_minus, 0, 'CdB', 0, 'CA', [-1])

		#### interaction terms ####
		if V != 0:
			self.add_coupling(V, 0, 'NA', 0, 'NB', [1])
			self.add_coupling(V, 0, 'NB', 0, 'NA', [1])

def get_sshint_model(model_params):
	M = SSHIntModel(model_params)
	return NearestNeighborModel.from_MPOModel(M)			

User avatar
Johannes
Site Admin
Posts: 179
Joined: 21 Jul 2018, 12:52
Location: UC Berkeley

Re: Bipartitioning infinite MPS into 2 semi-infinite chains

Post by Johannes »

Why are you trying to do the time evolution? The paper you cited does *not* use TEBD, it uses DMRG!
arxiv 1810.07043, Sec. III a wrote: We define \(\theta = 2\pi t/T\), assume adiabaticity and work in the instantaneous eigenbasis of \(H(\theta)\). Hence, the charge transport becomes independent of the time scale \(T\).
"Adiabatically" implies that the time evolution is slow enough to always stay in the ground state of the system.
So you really just run DMRG (which is way more efficient than imaginary TEBD!) to find the ground state for increasing \(\theta = 0, ..., 2\pi\) in sufficiently small steps; probably something like 20-30 steps in total is enough to capture the physics. To ensure the "adiabaticity" for the DMRG, you should initialize each run of DMRG with the initial state and environment from the previous \(\theta\).

jamarks
Posts: 6
Joined: 01 May 2020, 19:14

Re: Bipartitioning infinite MPS into 2 semi-infinite chains

Post by jamarks »

Thanks again for the reply. I fully recognize the different between the 'adiabatic' evolution that is entailed by charge pumping, and the real time evolution that I am doing. The basic idea I am looking at is quenches in order-obstructed SPT phases. As such, I am interested in looking at the evolution of the polarization during the course of a quench - so I do actually need to do the real-time evolution. And I know that the particular values taken by the polarization during the quench are not meaningful, but their changes over time are.

Also, the reason I am using TEBD rather than DMRG is that I am doing both real and imaginary evolution, working with infinite systems. And from what I can tell, TeNPy's dmrg/tdvp do not allow for real-time evolution of iMPS. Am I somehow mistaken?

Thanks,
Jacob

Post Reply