Some basic questions on DMRG

Hi,
I have a very basic questions.

  1. How do I save the dmrg output which comes on the screen (after sweep1 energy … etc) in a file for a future record. Is it possible without disturbing the inbuilt dmrg function?

  2. Using “silent” argument in the dmrg function, we can stop this information from coming up on the screen . If I am wrong please let me know.

  3. How many excited states can ITensor DMRG calculate with reliable accuracy?

Hi! Thanks for posting. ITensor DMRG backend has an observer object to handle exactly the situation like yours. You can refer to this section (Observer System for DMRG) in documentation. Your can also refer to the past discussion here.

  1. You can just create a new observer object to achieve the same. Pass this object to the inbuilt DMRG routine. Here is a MWE for storing the output to a file called dmrg_output.txt.
mutable struct DemoObserver <: AbstractObserver
  energy_tol::Float64
  last_energy::Float64
  output_file::String
  DemoObserver(energy_tol=0.0, output_file="dmrg_output.txt") = new(energy_tol, 1000.0, output_file)
end

function ITensors.checkdone!(o::DemoObserver; kwargs...)
 sw = kwargs[:sweep]
 energy = kwargs[:energy]
 if abs(energy-o.last_energy)/abs(energy) < o.energy_tol
   println("Stopping DMRG after sweep $sw")
   return true
 end
 # Otherwise, update last_energy and keep going
 o.last_energy = energy
 return false
end

function ITensors.measure!(o::DemoObserver; kwargs...)
 energy = kwargs[:energy]
 sweep = kwargs[:sweep]
 bond = kwargs[:bond]
 outputlevel = kwargs[:outputlevel]
 
 # Write to file
 open(o.output_file, "a") do f
   write(f, "Sweep $sweep, Energy $energy\n")
 end
 
 if outputlevel > 0
   println("Sweep $sweep at bond $bond, the energy is $energy")
 end
end

This is adapted from the linked documentation. Notice the new memeber attribute, output_file in DemoObserver class.

  1. Yeah, you can suppress terminal output by providing outputlevel=0 in the DMRG keyword argument. Here is a driver code for the same. This uses the DemoObserver object to store the output to a file.
let
   N = 10
   etol = 1E-4
 
   s = siteinds("S=1/2",N)
 
   a = OpSum()
   for n=1:N-1
     a += "Sz",n,"Sz",n+1
     a += 0.5,"S+",n,"S-",n+1
     a += 0.5,"S-",n,"S+",n+1
   end
   H = MPO(a,s)
   psi0 = random_mps(s;linkdims=4)
 
   nsweeps = 5
   cutoff = 1E-8
   maxdim = [10,20,100]
 
   obs = DemoObserver(etol)
 
   energy, psi = dmrg(H,psi0; nsweeps, cutoff, maxdim, observer=obs, outputlevel=0)
 
   return
 end
  1. I guess this depends on the Hamiltonian (spectrum gap). In my experience, I have obtained upto 4 excited states reliably. The degeneracy in spectrum may also affect the calculations. Obtaining excited states may require significantly more DMRG sweeps than the ground states.

Another suggestion for recording and saving screen output is the GNU “screen” command line application.

It is particularly useful when running jobs on a remote machine since you can log out while keeping your job running and log back in later.

1 Like

Thank you very much Sandipanmanna and Miles for your suggestions.

I have one more question .

While running the DMRG code, “randomMPS” works fine in my system but not “random_mps”. It shows the following error.

ERROR: LoadError: UndefVarError: random_mps not defined.

I do not understand what could be the problem.
I am using Julia version 1.9.0 just for information.

Could you please suggest something over this?

What version of ITensors.jl are you using? Is it updated to the latest version?

I am using ITensors v0.3.68

I see. The current version is 0.6.21 so most likely the reason you are not able to have the random_mps function is that you have not updated ITensors.jl.

Yeaahh. It worked. Thank you…