# Julia script for calculating energy gaps

Hi there,

Is there any existing Julia script for calculating exited MPS states using DMRG? I could only find the C++ version here.

Hi Arnab,
Thanks for the question - we do need to post a code example for this. Here is a short explanation though, and using it you ought to be able to adapt one of the other DMRG code examples to do excited states.

1. say you calculate the ground state as follows:

energy0,psi0 = dmrg(H,psi0_i,sweeps)

where here psi0_i is the initial guess for the ground state and psi0 is the optimized ground state.

1. now you can calculate the first excited state as:

energy1,psi1 = dmrg(H,[psi0],psi1_i,sweeps;weight=weight)

where psi1_i is the initial guess for the first excited state and weight is a positive number that you can adjust to penalize non-orthogonality of the ground and first excited state by different amounts (like a Lagrange multiplier).

1. you can continue to calculate the second excited state as:

energy2,psi2 = dmrg(H,[psi0,psi1],psi2_i,sweeps; weight=weight)

One tip is to do lots more sweeps for excited states than for ground states. Use your best judgement, and make sure that the energy is no longer changing over multiple sweeps before being sure things have converged. People often ask what value to take for the weight and I do not know because it is problem-dependent. Taking the weight to be 1.0 (the default) is good for most purposes though you can try other values to see if it speeds up convergence.

Hope that helps!

Miles

commented by (270 points)
edited by
Hi Miles,

Thank you so much for the detailed reply.  It works perfectly well for a product state Hamiltonian. However, for some reason, it doesn't  converge and gives values that I don't understand for a Cluster Hamiltonian with open boundary conditions in a 1D chain. When I run the following script for I get an energy gap of around 4 to 5 and the result fluctuates with every sweep. I would have expected it to just give me an energy gap of 2.

psi = randomMPS(sites,bond_dim)
energy0,psi0 = dmrg(H,psi,sweeps)
sweeps = Sweeps(50)
energy1,psi1 = dmrg(H,[psi0],psi,sweeps;weight=5)

Edit: It seems like with the above script I am only exploring the MPS with bond dimension 1 for the excited states. How do I change that?

Thanks again for being so patient with my rudimentary queries.
commented by (50.5k points)
Hi Arnab, thanks for trying some more things and printing out the MPS (in order to see it's bond dimension 1). So the issue is that you have not set any DMRG accuracy / sweeping parameters besides the number of sweeps. If you add a line like:

maxdim!(sweeps,10,20,40,80,100,200,400)

before you call DMRG then the bond dimension will be allowed to grow. I'd also recommend setting a cutoff, such as

cutoff!(sweeps,1E-8)

Hope that fixes things! Good idea to do 50 sweeps for an excited state. It's best to do at least 20 for those, or as many as needed until the energy is barely changing in the last 5 sweeps or so.

Best,
Miles