Some basic questions on DMRG

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.