Two component Bose-Hubbard model

How do I use this algorithm? What does that parameter do?
Post Reply
dehond
Posts: 2
Joined: 08 Feb 2021, 20:00

Two component Bose-Hubbard model

Post by dehond »

I'm trying to use DMRG to calculate some ground state properties of the two-component Bose-Hubbard model on a one-dimensional chain:

\[ H = -t \sum_{< i,j >} \left( a_i^+ a_j + b_i^+ b_j + H.c. \right) + \frac{U}{2} \sum_i [a_i^+ a_i (a_i^+ a_i - 1) + b_i^+ b_i (b_i^+ b_i - 1)] + U_{AB} \sum_i a_i^+ a_i b_i^+ b_i, \]

where \(U\) and \(U_{AB}\) are the inter- and intrastate onsite interactions, respectively. I have implemented this as its own `CouplingMPOModel` class, while heeding some of the things I've learned from studying this topic on combining multiple charges on the same site.

Essentially I set up a superlattice with two sites in every unit cell: an _A_ site and a _B_ site. In the `init_lattice()` routine I use a `pairs` dictionary to get the geometry right:

Code: Select all

class TwoComponentBoseHubbardModel(CouplingMPOModel):
    def init_sites(self, model_params):
        n_max = model_params.get('n_max', 3)
        filling = model_params.get('filling', 1)
        conserve = model_params.get('conserve', 'N')
        if conserve == 'best':
            conserve = 'N'
            if self.verbose >= 1.:
                print(self.name + ": set conserve to", conserve)
        siteA = BosonSite(Nmax=n_max, conserve=conserve, filling=filling)
        siteB = BosonSite(Nmax=n_max, conserve=conserve, filling=filling)
        multi_sites_combine_charges([siteA, siteB])
        return [siteA, siteB]

        def init_lattice(self, model_params):
		pairs = {'onsite': [(0, 1, np.array([0]))], 'nearest_neighbors': [(0, 0, np.array([1])), (1, 1, np.array([1]))]}
		L = model_params.get('L', 10)
		sites = self.init_sites(model_params)
		lat = lattice.Lattice([L], sites, pairs = pairs)
		return lat	

	    def init_terms(self, model_params):
		t = model_params.get('t', 1.)
		U = model_params.get('U', 10.)
		UAB = model_params.get('UAB', 0.)
		mu = model_params.get('mu', 0)
		for u in range(len(self.lat.unit_cell)):
			self.add_onsite(-mu - U / 2., u, 'N')
			self.add_onsite(U / 2., u, 'NN')
		for u1, u2, dx in self.lat.pairs['nearest_neighbors']:
			self.add_coupling(-t, u1, 'Bd', u2, 'B', dx, plus_hc=True)
		for u1, u2, dx in self.lat.pairs['onsite']:
			self.add_coupling(UAB, u1, 'N', u2, 'N', dx)
With the initial state `psi = MPS.from_lat_product_state(M.lat, [[1, 1]])` and by using the mixer I believe this works correctly.

It does seem to me, though, that it runs a little inefficiently, so perhaps my choice of geometry is suboptimal. I need a bond dimension of about 300 to get a converged result for 20 sites. I must say I've never tried to use MPS algorithms on the Bose-Hubbard model before, so it may just be my inexperience (in which case, too bad!) On the other hand I wonder if the MPS representation is somehow more efficient if I use a ladder geometry, with the _A_ and _B_ sites being on either side of every rung.
User avatar
Johannes
Site Admin
Posts: 324
Joined: 21 Jul 2018, 12:52
Location: TU Munich

Re: Two component Bose-Hubbard model

Post by Johannes »

Your code looks right. I would have done it basically the same way :)
In the newest version of TeNPy, tenpy.networks.site.multi_sites_combine_charges is deprecated in favor of tenpy.networks.site.set_common_charges, you should call it with set_common_charges([siteA, siteB], 'independent').
This should make sure that the numbers of A and B bosons are individually conserved (as in your code, I think).

Whether you use ladder or the way you do it now, will not make any difference for speed - the DMRG will do the exact same thing, because you generate the same H_MPO in the end.
Combining the sites will make DMRG only scale worse, I would not recommend it - unless you find that you have a much stronger entanglement between A and B sites in the same unit cell than between the rungs, and you are limited by truncation on that particular bond.

I'm not sure what `n_max` you've set. Keep in mind that the local Hilbert space of Bosons is larger than the one of Fermions, so even if you have the same correlation length of say 1 site, the bosons do require a larger bond dimension. The larger your onsite U, the more suppressed higher-occupied sites are, and you get back to the hard-core boson limit for \( U \gg t\), which is equivalent to Fermions.
dehond
Posts: 2
Joined: 08 Feb 2021, 20:00

Re: Two component Bose-Hubbard model

Post by dehond »

That's great, thanks so much for having a look at my code and for your input!

ksuzuki
Posts: 2
Joined: 09 Dec 2021, 14:49

Re: Two component Bose-Hubbard model

Post by ksuzuki »

I used TwoSiteDMRGEngine for this code under the specified initial state psi = MPS.from_lat_product_state(M.lat, [[1, 1]]), but it did not successfully find the ground state.
I would appreciate it if you could tell me how you used it. 

Code: Select all

model_params=dict(L=L,n_max=n_max,t=t,U=U,UAB=UAB,mu=mu,conserve=None)
M=TwoComponentBoseHubbardModel(model_params) 
psi=MPS.from_lat_product_state(M.lat,[[1,1]])
dmrg_params = { 
        'mixer': None,  
        'max_E_err': 1.e-10, 
        'trunc_params': {
            'chi_max': 30,
            'svd_min': 1.e-10  
        },
        'combine': True 
    }
eng_dmrg = dmrg.TwoSiteDMRGEngine(psi,M,dmrg_params)
E, psi= eng_dmrg.run()
Last edited by ksuzuki on 10 Dec 2021, 06:29, edited 4 times in total.
User avatar
Johannes
Site Admin
Posts: 324
Joined: 21 Jul 2018, 12:52
Location: TU Munich

Re: Two component Bose-Hubbard model

Post by Johannes »

See the reply in the separate thread
Post Reply