Skip to content

Commit

Permalink
Output eigenvalue from ITensorTDVP.dmrg and dmrg_x (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
mtfishman committed May 6, 2024
1 parent 8ecdb83 commit 4669573
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "ITensorTDVP"
uuid = "25707e16-a4db-4a07-99d9-4d67b7af0342"
authors = ["Matthew Fishman <mfishman@flatironinstitute.org> and contributors"]
version = "0.2.6"
version = "0.3.0"

[deps]
ITensors = "9136182c-28ba-11e9-034c-db9fb085ebd5"
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ pkg> add ITensorTDVP

## News

### ITensorTDVP.jl v0.3 Release Notes

#### Breaking changes

- `ITensorTDVP.dmrg` and `ITensorTDVP.dmrg_x` now output a tuple containing the eigenvalue and eigenvector, while before they just output the eigenvector. You should update code like this:
```julia
psi = dmrg_x(H, psi0; nsweeps=10, maxdim=100, cutoff=1e-6)
psi = ITensorTDVP.dmrg(H, psi0; nsweeps=10, maxdim=100, cutoff=1e-6)
```
to:
```julia
energy, psi = dmrg_x(H, psi0; nsweeps=10, maxdim=100, cutoff=1e-6)
energy, psi = ITensorTDVP.dmrg(H, psi0; nsweeps=10, maxdim=100, cutoff=1e-6)
```

### ITensorTDVP.jl v0.2 Release Notes

#### Breaking changes
Expand Down
6 changes: 3 additions & 3 deletions examples/01_tdvp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ function main()

e2, ϕ2 = ITensors.dmrg(H, ψ; nsweeps=10, maxdim=20, cutoff=1e-10)

@show inner(ϕ2', H, ϕ2) / inner(ϕ2, ϕ2)
@show inner(ϕ2', H, ϕ2) / inner(ϕ2, ϕ2), e2

ϕ3 = ITensorTDVP.dmrg(H, ψ; nsweeps=10, maxdim=20, cutoff=1e-10, outputlevel=1)
e3, ϕ3 = ITensorTDVP.dmrg(H, ψ; nsweeps=10, maxdim=20, cutoff=1e-10, outputlevel=1)

@show inner(ϕ3', H, ϕ3) / inner(ϕ3, ϕ3)
@show inner(ϕ3', H, ϕ3) / inner(ϕ3, ϕ3), e3
return nothing
end

Expand Down
4 changes: 2 additions & 2 deletions examples/02_dmrg-x.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ function main()
nsweeps=10, reverse_step=false, normalize=true, maxdim=20, cutoff=1e-10, outputlevel=1
)

ϕ = dmrg_x(H, ψ; dmrg_x_kwargs...)
e, ϕ = dmrg_x(H, ψ; dmrg_x_kwargs...)

@show inner', H, ψ) / inner(ψ, ψ)
@show inner(H, ψ, H, ψ) - inner', H, ψ)^2
@show inner', H, ϕ) / inner(ϕ, ϕ)
@show inner', H, ϕ) / inner(ϕ, ϕ), e
@show inner(H, ϕ, H, ϕ) - inner', H, ϕ)^2
return nothing
end
Expand Down
1 change: 1 addition & 0 deletions examples/Project.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[deps]
ITensorTDVP = "25707e16-a4db-4a07-99d9-4d67b7af0342"
ITensors = "9136182c-28ba-11e9-034c-db9fb085ebd5"
KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
10 changes: 7 additions & 3 deletions src/dmrg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ function dmrg_solver(
maxiter=solver_maxiter,
verbosity=solver_verbosity,
)
psi = vecs[1]
return psi, info
return vecs[1], (; info, eigval=vals[1])
end
return solver
end
Expand All @@ -36,9 +35,13 @@ function dmrg(
solver_krylovdim=default_solver_krylovdim(eigsolve),
solver_maxiter=default_solver_maxiter(eigsolve),
solver_verbosity=default_solver_verbosity(),
(observer!)=default_observer!(),
kwargs...,
)
reverse_step = false
info_ref! = Ref{Any}()
info_observer! = values_observer(; info=info_ref!)
observer! = compose_observers(observer!, info_observer!)
psi = alternating_update(
dmrg_solver(
eigsolve;
Expand All @@ -52,7 +55,8 @@ function dmrg(
H,
psi0;
reverse_step,
observer!,
kwargs...,
)
return psi
return info_ref![].eigval, psi
end
15 changes: 11 additions & 4 deletions src/dmrg_x.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@ function dmrg_x_solver(PH, t, psi0; current_time, outputlevel)
H = contract(PH, ITensor(true))
D, U = eigen(H; ishermitian=true)
u = uniqueind(U, H)
u′ = uniqueind(D, U)
max_overlap, max_ind = findmax(abs, array(psi0 * dag(U)))
U_max = U * dag(onehot(eltype(U), u => max_ind))
return U_max, nothing
D_max = D[u′ => max_ind, u => max_ind]
return U_max, (; eigval=D_max)
end

function dmrg_x(PH, psi0::MPS; reverse_step=false, kwargs...)
psi = alternating_update(dmrg_x_solver, PH, psi0; reverse_step, kwargs...)
return psi
function dmrg_x(
PH, psi0::MPS; reverse_step=false, (observer!)=default_observer!(), kwargs...
)
info_ref = Ref{Any}()
info_observer! = values_observer(; info=info_ref)
observer! = compose_observers(observer!, info_observer!)
psi = alternating_update(dmrg_x_solver, PH, psi0; reverse_step, observer!, kwargs...)
return info_ref[].eigval, psi
end
22 changes: 22 additions & 0 deletions src/update_observer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,25 @@ using ITensors.ITensorMPS: ITensorMPS
function update_observer!(observer::ITensorMPS.AbstractObserver; kwargs...)
return ITensorMPS.measure!(observer; kwargs...)
end

struct ValuesObserver{Values<:NamedTuple}
values::Values
end
function update_observer!(observer::ValuesObserver; kwargs...)
for key in keys(observer.values)
observer.values[key][] = kwargs[key]
end
return observer
end
values_observer(; kwargs...) = ValuesObserver(NamedTuple(kwargs))

struct ComposedObservers{Observers<:Tuple}
observers::Observers
end
compose_observers(observers...) = ComposedObservers(observers)
function update_observer!(observer::ComposedObservers; kwargs...)
for observerᵢ in observer.observers
update_observer!(observerᵢ; kwargs...)
end
return observer
end
4 changes: 3 additions & 1 deletion test/test_dmrg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ using Test: @test, @testset
psi = randomMPS(elt, s, j -> isodd(j) ? "" : ""; linkdims=20)
nsweeps = 10
maxdim = [10, 20, 40, 100]
psi = ITensorTDVP.dmrg(
e, psi = ITensorTDVP.dmrg(
H, psi; nsweeps, maxdim, cutoff, nsite, solver_krylovdim=3, solver_maxiter=1
)
@test inner(psi', H, psi) e
e2, psi2 = ITensors.dmrg(H, psi; nsweeps, maxdim, cutoff, outputlevel=0)
@test ITensors.scalartype(psi2) == elt
@test e2 isa real(elt)
@test e e2 rtol = (eps(real(elt))) * 10
@test inner(psi', H, psi) inner(psi2', H, psi2) rtol = (eps(real(elt))) * 10
end
end
6 changes: 4 additions & 2 deletions test/test_dmrg_x.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ using Test: @test, @testset
dmrg_x_kwargs = (
nsweeps=20, reverse_step=false, normalize=true, maxdim=20, cutoff=1e-10, outputlevel=0
)
ϕ = dmrg_x(ProjMPO(H), ψ; nsite=2, dmrg_x_kwargs...)
e, ϕ = dmrg_x(ProjMPO(H), ψ; nsite=2, dmrg_x_kwargs...)
@test ITensors.scalartype(ϕ) == elt
@test inner', H, ϕ) / inner(ϕ, ϕ) e
@test inner(H, ψ, H, ψ) inner', H, ψ)^2 rtol = eps(real(elt))
@test inner', H, ψ) / inner(ψ, ψ) inner', H, ϕ) / inner(ϕ, ϕ) rtol = 1e-1
@test inner(H, ϕ, H, ϕ) inner', H, ϕ)^2 rtol = eps(real(elt))
ϕ̃ = dmrg_x(ProjMPO(H), ϕ; nsite=1, dmrg_x_kwargs...)
ẽ, ϕ̃ = dmrg_x(ProjMPO(H), ϕ; nsite=1, dmrg_x_kwargs...)
@test ITensors.scalartype(ϕ̃) == elt
@test inner(ϕ̃', H, ϕ̃) / inner(ϕ̃, ϕ̃)
@test inner', H, ψ) / inner(ψ, ψ) inner(ϕ̃', H, ϕ̃) / inner(ϕ̃, ϕ̃) rtol = 1e-1
scale(::Type{Float32}) = 10^2
scale(::Type{Float64}) = 10^5
Expand Down
2 changes: 1 addition & 1 deletion test/test_linsolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ using Random: Random
state = [isodd(n) ? "Up" : "Dn" for n in 1:N]
Random.seed!(1234)
x_c = randomMPS(elt, s, state; linkdims=2)
x_c = dmrg(H, x_c; nsweeps=10, cutoff=1e-6, maxdim=20, outputlevel=0)
e, x_c = dmrg(H, x_c; nsweeps=10, cutoff=1e-6, maxdim=20, outputlevel=0)
@test ITensors.scalartype(x_c) == elt
# Compute `b = H * x_c`
b = apply(H, x_c; cutoff=1e-8)
Expand Down

2 comments on commit 4669573

@mtfishman
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/106227

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.3.0 -m "<description of version>" 46695737f57317d49e46a2e8c800cfb7228df0fc
git push origin v0.3.0

Please sign in to comment.