Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

How do I use this algorithm? What does that parameter do?
Post Reply
dorf
Posts: 32
Joined: 16 Feb 2021, 16:34

Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by dorf »

Hello,
I would like to calculate the Dynamical Spin Structure and/or the Excitation spectrum of the 2 chain spin ladder, which I implemented below.Ultimately, I would like to compare the results to Neutron Scattering experiments. Using the ladder lattice of TenPy I constructed the model:

Code: Select all

class spinLadder(CouplingModel, MPOModel):
    # model as in 'Topological quantum paramagnet in a
    # quantum spin ladder', PHYSICAL REVIEW B 96, 220405(R) (2017)

    def __init__(self, model_params):

        # define some default parameters
        L = model_params.get('L', 2)
        J = model_params.get('J', 1.)
        K = model_params.get('K', 0.01)

        hy = model_params.get('hy', 0.)

        # initialize a ladder lattice with two spin-1/2 sites on it
        site1 = SpinHalfSite(conserve=None)
        site2 = SpinHalfSite(conserve=None)
        bc = 'periodic' if model_params['bc_MPS'] == 'infinite' else 'open'
        lat = Ladder(L, [site1, site2], bc=bc, bc_MPS=model_params['bc_MPS'])

        # initialize a coupling model
        CouplingModel.__init__(self, lat)

        # add terms of the Hamiltonian
        # intracell Heisenberg coupling (along the rungs of the ladder)
        self.add_coupling(J, 0, 'Sp', 1, 'Sm', 0, plus_hc=True)
        self.add_coupling(J, 0, 'Sz', 1, 'Sz', 0, plus_hc=True)
        # intercell Heisenberg coupling (along the length of the ladder)
        self.add_coupling(K, 0, 'Sp', 0, 'Sm', 1, plus_hc=True)
        self.add_coupling(K, 0, 'Sz', 0, 'Sz', 1, plus_hc=True)
        self.add_coupling(K, 1, 'Sp', 1, 'Sm', 1, plus_hc=True)
        self.add_coupling(K, 1, 'Sz', 1, 'Sz', 1, plus_hc=True)
        # odd-parity DM interactions # NOTE: check whether plus_hc=True is correct
        self.add_coupling(D, 0, 'Sz', 0, 'Sx', 1, plus_hc=True)
        self.add_coupling(-D, 0, 'Sx', 0, 'Sz', 1, plus_hc=True)
        self.add_coupling(D, 1, 'Sz', 1, 'Sx', 1, plus_hc=True)
        self.add_coupling(-D, 1, 'Sx', 1, 'Sz', 1, plus_hc=True)
        # even parity anisotropic interdimer coupling # NOTE: also chck with hc
        self.add_coupling(Gamma, 0, 'Sz', 0, 'Sx', 1, plus_hc=True)
        self.add_coupling(Gamma, 0, 'Sx', 0, 'Sz', 1, plus_hc=True)
        self.add_coupling(Gamma, 1, 'Sz', 1, 'Sx', 1, plus_hc=True)
        self.add_coupling(Gamma, 1, 'Sx', 1, 'Sz', 1, plus_hc=True)
        # add a magnetic field pointing in y direction
        self.add_onsite(hy, 0, 'Sy')
        self.add_onsite(hy, 1, 'Sy')
       
        # construct the Hamiltonian in the Matrix-Product-Operator (MPO) picture
        MPOModel.__init__(self, lat, self.calc_H_MPO())

I start within the limit of the singlet phase (the J on the rungs of the ladder is much stronger than the coupling along the chain). It is well known that the 2-chain ladder has a finite gap, which makes it very easy for the DMRG algorithm to find the system's ground state. The excitations are triplons. I wonder what the best way to proceed is. Since the ladder is not a NearestNeighbor model I can't just use the TEBD as implemented in TenPy. Even if it was, I am not sure whether a time evolution would be sensible to the excitations (I guess it depends on the size of the gap?!). I was thinking about adding one triplon manually somewhere in the initial product state for finite DMRG and start from there, but due to the antisymmetric exchange of my model (D and Gamma) S_z is not conserved. What feasible options do I have using TenPy?
Last edited by dorf on 01 Apr 2021, 21:19, edited 1 time in total.
User avatar
Johannes
Site Admin
Posts: 413
Joined: 21 Jul 2018, 12:52
Location: TU Munich

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by Johannes »

Your new question is probably the follow up on this, so I guess I'm already a bit too late (Sorry :oops: ), but let me comment anyways.

The first "standard" thing to do is to just calculate the next excited states (assuming that you have a finite system) using the "orthogonal_to" parameter of DMRG. This only works well for a couple of states, but it can give you some insights especially if you also analyze the excited state you get in more detail.
(For an infinite system, you can extract a small part with "segment" boundary conditions and look at the excitations within that segment.)

The "Dynamical spin Structure factor", which you already mentioned in the topic title, is also an option; TeNPy provides you with the basic tools for that:
  1. DMRG to find the ground state
  2. MPS.apply_local_op() to get \(B_j| \psi\rangle\) (for fixed \(j\)
  3. TEBD (if NearestNeighborModel) or TDVP or ExpMPOEvolution for time evolving \(B_j|\psi\rangle\)
  4. MPSEnvironment.expectation_value to get \(C(t)=\langle \psi|A_i(t)B_j|\psi\rangle\)
Afterwards, you can do a Fourier trafo of C(t) to get the dynamical spin structure factor.
dorf
Posts: 32
Joined: 16 Feb 2021, 16:34

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by dorf »

Thanks a lot. I was a little overwhelmed with the many possibilities, but I settled on trying out ExpMPOEvolution.
In the last step, why should I use mpsenvironment.expectation_value instead of the mps.method?
User avatar
Johannes
Site Admin
Posts: 413
Joined: 21 Jul 2018, 12:52
Location: TU Munich

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by Johannes »

The MPS.expectation_value method for a given \(|\phi\rangle\) gives you \(\langle\phi|A_i|\phi\rangle\), but you need
\(\langle\psi|A_i|\phi\rangle\) with \(|\phi\rangle = \exp(-i H t) B_j |\psi_0\rangle\).
The latter is exactly what MPSEnvironment.expectation_value provides.
dorf
Posts: 32
Joined: 16 Feb 2021, 16:34

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by dorf »

I see, thanks for your help!
Best regards!
dorf
Posts: 32
Joined: 16 Feb 2021, 16:34

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by dorf »

Quick Follow-up question:

So I guess the code to obtain the structure factor C^zz_ij could look something like this (already having calculated the iDMRG ground state psi_0):

Code: Select all

    C_ij = []
    for site in range(num_sites):

        # apply the first operator to the ground state
        psi = psi_0.copy()
        psi.apply_local_op(site, 'Sz')

        # now evolve this wave function 
        evol = mpo_evolution.ExpMPOEvolution(psi, model, evol_params)
        psi = evol.run()

        # initialize the 'environment' of this state, together with the ground state
        # and calculate expectation value
        env = MPSEnvironment(psi_0, psi)
        C_i = env.expectation_value(['Sz]*num_sites, range(num_sites))
        C_ij.append(C_i)

    return C_ij
1. How do I make sure that the LegCharge is compatible when I instantiate the MPS environment?
2. Depending on the operator and it's action on the ground state I probably need to enlarge the unit cell, right?
3. The default parameters for the ExpMPOEvolution only evolve one time step. In your experience, how much is needed to obtain decent results?
dorf
Posts: 32
Joined: 16 Feb 2021, 16:34

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by dorf »

So I guess the problem is that the maximal bond dimensions of the iDMRG ground state psi_0, and the time evolved ground state psi are different. I passed the same chi_max to both algorithms, but since psi_0 is closer to a product state it doesn't need a very high chi.

Is there a way to 'grow' psi_0 to make the legs compatible, or should I use e.g. svd_theta to truncate psi somehow?

If I interpret the schematic at MPSEnvironment correctly it's only the LPs and RPs that have to match, right? Can I use the functionality of this class to calculate the expectation value?
User avatar
Johannes
Site Admin
Posts: 413
Joined: 21 Jul 2018, 12:52
Location: TU Munich

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by Johannes »

To be clear: you need to evolve this for much longer than just a few steps, and continuously take measurements for \(C_ij(t)\). In the end, you can then fourier-transform \(C_ij(t)\), both in space and time, to get \(C_k(\omega)\), which is what you're really interested in, right? The maximal time you reach (without truncation too much) in the time evolution determines the resolution of \(\omega\), so you want to push that as far as possible with reasonable numerical effort.
In some cases, you can argue with translation invariance that it suffices to calculate \(C^{zz}_{ij}(t)\) for fixed j, such that you only need to do a single (costly) time evolution for fixed j in the center of the chain.

The ExpMPOEvolution takes truncation parameters as arguments which you can adjust to allow a growth of the bond dimension.
dorf
Posts: 32
Joined: 16 Feb 2021, 16:34

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by dorf »

Thank you very much for the answer. I calculated the time evolution for a t that provides me with a sufficient frequency resolution (for first tests in any case). However, I’m still concerned with the technicality that I mentioned above that I get the Error ‘incompatible leg charge’ when I want to contract the ground state and the evolved state using MPSEnvironment. What is the standard way within tenpy to do it? I assume that with leg charge the bond dimension the two algorithms converged to for the different sites is meant?
User avatar
Johannes
Site Admin
Posts: 413
Joined: 21 Jul 2018, 12:52
Location: TU Munich

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by Johannes »

Would you mind to provide a traceback? An "incompatible LegCharge" means it's trying to contract two legs with different charges somewhere, not necessarily in the MPS bonds.
dorf
Posts: 32
Joined: 16 Feb 2021, 16:34

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by dorf »

Sorry for my late reply, I really appreciate the help.

Below you find the traceback, after I called MPSEnvironment(psi_0, testpsi) with psi_0 being an iDMRG ground state to which applied 'Sz' to some site with mps.apply_local_op, and testpsi the output of ExpMPOEvolution where psi_0.apply_local_op(someSite, 'Sz') was evolved.

In [13]: MPSEnvironment(psi_0, testpsi)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-13-56751453b68a> in <module>
----> 1 MPSEnvironment(psi_0, testpsi)

~/.local/lib/python3.6/site-packages/tenpy/networks/mps.py in __init__(self, bra, ket, init_LP, init_RP, age_LP, age_RP)
3508 self._finite = self.ket.finite # just for _to_valid_index
3509 if init_LP is None:
-> 3510 init_LP = self.init_LP(0)
3511 self.set_LP(0, init_LP, age=age_LP)
3512 if init_RP is None:

~/.local/lib/python3.6/site-packages/tenpy/networks/mps.py in init_LP(self, i)
3541 leg_ket = self.ket.get_B(i, None).get_leg('vL')s.
3542 leg_bra = self.bra.get_B(i, None).get_leg('vL')
-> 3543 leg_ket.test_equal(leg_bra)
3544 init_LP = npc.diag(1., leg_ket, dtype=self.dtype, labels=['vR*', 'vR'])
3545 return init_LP

~/.local/lib/python3.6/site-packages/tenpy/linalg/charges.py in test_equal(self, other)
841 not np.array_equal(self.charges * self.qconj, other.charges * other.qconj):
842 raise ValueError("incompatible LegCharge\n" +
--> 843 vert_join(["self\n" + str(self), "other\n" + str(other)], delim=' | '))
844
845 def get_block_sizes(self):

ValueError: incompatible LegCharge
self | other
+1 | +1
0 [] | 0 []
18 | 9




UPDATE:
Renomalizing testpsi with testpsi.canonical_form() seems to work with MPSEnvironment. I will make some test and see whether I get reasonable results.
dorf
Posts: 32
Joined: 16 Feb 2021, 16:34

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by dorf »

So after a couple of tests, the problem described above persists to occur for many combinations of states. At each time point t of the evolution I want to initialize an MPSEnvironment for all j for <psi_0 | psi_j> with |psi_j> being the time evolved state at time t with |psi_j> = U S_j |psi_0>, to then calculate the expectation values for some S_i to then obtain the structure factor C_ij.

But for many |psi_j> the error described above is raised, albeit calling canonical_form() on the psi_j before trying to build the MPSEnvironment. Is think I'm missing something. Is there someway to make the results of the time evolution consistently compatible with the iDMRG ground state result? I'm using the same truncation parameters on both algorithms.
User avatar
Johannes
Site Admin
Posts: 413
Joined: 21 Jul 2018, 12:52
Location: TU Munich

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by Johannes »

Sorry, I didn't realize you were looking at infinite MPS.
For an infinite MPS, the leg between unit cells is non-trivial, and in general changes when you do a time evolution.
This is where the error is coming from: when you initialize the MPSEnvironment, it needs to know how to connect the left-/right-most virtual legs of the bra and ket with each other, and it complains that they are different, so the default of "connect it with an identity" doesn't make sense.

The issuse there is that formally any two states |psi> and |phi> which are not exactly the same (up to a prefactor) have formally overlap 0.
To be honest, it's not completely clear to me how to resolve this.
In general, I think you want to avoid the "light cone" of the operator you applied to hit the boundary of your system, so roughly speaking you don't want to have a non-trivial time evolution on this leg anyways; however, the DMRG ground state is not an exact eigenstate of the system, so it might have a non-trivial evolution anyways.

Of course, for now one resolution is to look at a finite system. But in general this should also work for infinite systems...
dorf
Posts: 32
Joined: 16 Feb 2021, 16:34

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by dorf »

Dear Johannes,
thank you very much for your help. For the moment I'm fine working with finite systems, as well. I mostly started with iDMRG because I followed the rough description given in Sec. IV in this work: https://arxiv.org/pdf/1804.06811.pdf
it is explicitly mentioned that an iDMRG ground state is used.

The 'light cone' is just the time evolution operator for the DMRG Hamiltonians, isn't it? So I would only include apply it to sites away from the boundary?
rubenv
Posts: 6
Joined: 03 Mar 2021, 16:15

Re: RuntimeWarning and how to fix it

Post by rubenv »

Hello! So when I calculated the dynamic spin structure factor for https://arxiv.org/abs/1701.04678, I also used iDMRG for the ground state. When calculating the overlap, I actually just used a random vector at the edge. The reasoning is: you want to take your cylinder segment wide enough anyway such that the boundary is decoupled from the bulk. Hence, a random vector is actually a useful diagnostic for figuring out whether your cylinder is long enough: you expect that by the time the random vector propagates inward, the transfer matrix has been applied enough times such that it now looks like the semi-infinite environment. Indeed, if you see random noise popping up in your physical signal, you conclude that your cylinder was too short.

For the same reason, results are equally good if you use finite DMRG (because, again, if you start noticing the boundary, it means your system is too small). The main advantage of using iDMRG is, of course, that it is typically faster to find the ground state.

I hope that helps!

NB: in chapter 5 of my thesis, I give some more conceptual and technical details for calculating S(k,w) in 2D using MPS-based methods https://tud.qucosa.de/api/qucosa%3A3560 ... ent/ATT-0/
dorf
Posts: 32
Joined: 16 Feb 2021, 16:34

Re: Dynamical spin Structure Factor/ Excitation Spectrum of Spin Ladder

Post by dorf »

Thank you very much for the additional information. This is super helpful! Best regards!
Post Reply