Skip to content

Comments

Fixing time_start argument in tdvp#172

Open
osvathbotond wants to merge 2 commits intoITensor:mainfrom
osvathbotond:feature/tdvp_time_start_fix
Open

Fixing time_start argument in tdvp#172
osvathbotond wants to merge 2 commits intoITensor:mainfrom
osvathbotond:feature/tdvp_time_start_fix

Conversation

@osvathbotond
Copy link

Description

In the current tdvp implementation, the "time_start" argument is not working as I'd expect it to. If we set t=10.0, time_start=5.0 and dt=1.0, it'll calculate that it needs 10 steps in total, so it'll go until 15.0 instead of the desired 10.0.

Minimal demonstration of previous behavior

using ITensors, ITensorMPS

using Compat: @compat
using ITensors: ITensor, array, inds, itensor
using ITensorMPS: TimeDependentSum, to_vec
using KrylovKit: exponentiate
using OrdinaryDiffEqTsit5: ODEProblem, Tsit5, solve

function krylov_updater(operator, init; internal_kwargs, kwargs...)
  @compat (; current_time, time_step) = (; current_time=zero(Bool), internal_kwargs...)
  state, info = exponentiate(operator(current_time), time_step, init; kwargs...)
  return state, (; info)
end

function get_sites(N)
    sites = siteinds("S=1/2", N)
    return sites
end

function get_H(Jz, Jxy, sites)
    N = length(sites)
    os = OpSum()
    for j in 1:(N - 1)
        os += Jz, "Sz", j, "Sz", j + 1
        os += 0.5*Jxy, "S+", j, "S-", j + 1
        os += 0.5*Jxy, "S-", j, "S+", j + 1
    end
    H = MPO(os, sites)
    return H
end

function get_psi(H, sites)
    psi0 = random_mps(sites)

    nsweeps = 5
    maxdim = [10, 20, 100, 100, 200]
    cutoff = 1.0e-10

    energy, psi = dmrg(H, psi0; nsweeps, maxdim, cutoff)
    return psi
end

function generate_fs(T)
    function f1(t)
        normalized_time = t */ (2 * T))
        f = sin(normalized_time)^2
        return 1-f
    end

    function f2(t)
        normalized_time = t */ (2 * T))
        f = sin(normalized_time)^2
        return f
    end

    return f1, f2
end



function main()
    Jz = 1.0
    Jxy = 1.0
    N = 100
    dt = 1.0
    T = 10.0


    sites = get_sites(N)
    H1 = get_H(Jz, 0, sites)
    H2 = get_H(0, Jxy, sites)

    psi_1 = get_psi(H1, sites)

    f1, f2 = generate_fs(T)

    psi_Thalf = tdvp(-im * TimeDependentSum([f1, f2], [H1, H2]), T/2, complex.(psi_1); updater=krylov_updater, nsite=2, time_step=dt, cutoff=1e-5, maxdim=200, outputlevel=1);
    psi_T = tdvp(-im * TimeDependentSum([f1, f2], [H1, H2]), T, complex.(psi_Thalf); updater=krylov_updater, nsite=2, time_step=dt, cutoff=1e-5, maxdim=200, time_start=T/2, outputlevel=1);
end

main()

Output:

After sweep 1 energy=-24.749999996767972  maxlinkdim=2 maxerr=9.24E-11 time=16.436
After sweep 2 energy=-24.75  maxlinkdim=1 maxerr=7.86E-49 time=0.068
After sweep 3 energy=-24.75  maxlinkdim=1 maxerr=0.00E+00 time=0.057
After sweep 4 energy=-24.75  maxlinkdim=1 maxerr=0.00E+00 time=0.054
After sweep 5 energy=-24.75  maxlinkdim=1 maxerr=0.00E+00 time=0.054
After sweep 1: maxlinkdim=1 maxerr=2.36E-06 current_time=1.0 time=25.88
After sweep 2: maxlinkdim=2 maxerr=4.88E-06 current_time=2.0 time=0.278
After sweep 3: maxlinkdim=2 maxerr=1.12E-07 current_time=3.0 time=0.409
After sweep 4: maxlinkdim=2 maxerr=4.69E-06 current_time=4.0 time=0.503
After sweep 5: maxlinkdim=3 maxerr=6.63E-06 current_time=5.0 time=1.065
After sweep 1: maxlinkdim=4 maxerr=1.74E-06 current_time=6.0 time=2.651
After sweep 2: maxlinkdim=5 maxerr=8.41E-06 current_time=7.0 time=3.405
After sweep 3: maxlinkdim=6 maxerr=9.99E-06 current_time=8.0 time=3.241
After sweep 4: maxlinkdim=8 maxerr=9.19E-06 current_time=9.0 time=3.686
After sweep 5: maxlinkdim=11 maxerr=8.79E-06 current_time=10.0 time=4.237
After sweep 6: maxlinkdim=15 maxerr=9.83E-06 current_time=11.0 time=5.449
After sweep 7: maxlinkdim=22 maxerr=9.96E-06 current_time=12.0 time=8.616
After sweep 8: maxlinkdim=33 maxerr=9.66E-06 current_time=13.0 time=16.147
After sweep 9: maxlinkdim=47 maxerr=9.83E-06 current_time=14.0 time=27.608
After sweep 10: maxlinkdim=70 maxerr=9.90E-06 current_time=15.0 time=55.292

Minimal demonstration of new behavior

using ITensors, ITensorMPS

using Compat: @compat
using ITensors: ITensor, array, inds, itensor
using ITensorMPS: TimeDependentSum, to_vec
using KrylovKit: exponentiate
using OrdinaryDiffEqTsit5: ODEProblem, Tsit5, solve

function krylov_updater(operator, init; internal_kwargs, kwargs...)
  @compat (; current_time, time_step) = (; current_time=zero(Bool), internal_kwargs...)
  state, info = exponentiate(operator(current_time), time_step, init; kwargs...)
  return state, (; info)
end

function get_sites(N)
    sites = siteinds("S=1/2", N)
    return sites
end

function get_H(Jz, Jxy, sites)
    N = length(sites)
    os = OpSum()
    for j in 1:(N - 1)
        os += Jz, "Sz", j, "Sz", j + 1
        os += 0.5*Jxy, "S+", j, "S-", j + 1
        os += 0.5*Jxy, "S-", j, "S+", j + 1
    end
    H = MPO(os, sites)
    return H
end

function get_psi(H, sites)
    psi0 = random_mps(sites)

    nsweeps = 5
    maxdim = [10, 20, 100, 100, 200]
    cutoff = 1.0e-10

    energy, psi = dmrg(H, psi0; nsweeps, maxdim, cutoff)
    return psi
end

function generate_fs(T)
    function f1(t)
        normalized_time = t */ (2 * T))
        f = sin(normalized_time)^2
        return 1-f
    end

    function f2(t)
        normalized_time = t */ (2 * T))
        f = sin(normalized_time)^2
        return f
    end

    return f1, f2
end



function main()
    Jz = 1.0
    Jxy = 1.0
    N = 100
    dt = 1.0
    T = 10.0


    sites = get_sites(N)
    H1 = get_H(Jz, 0, sites)
    H2 = get_H(0, Jxy, sites)

    psi_1 = get_psi(H1, sites)

    f1, f2 = generate_fs(T)

    psi_Thalf = tdvp(-im * TimeDependentSum([f1, f2], [H1, H2]), T/2, complex.(psi_1); updater=krylov_updater, nsite=2, time_step=dt, cutoff=1e-5, maxdim=200, outputlevel=1);
    psi_T = tdvp(-im * TimeDependentSum([f1, f2], [H1, H2]), T, complex.(psi_Thalf); updater=krylov_updater, nsite=2, time_step=dt, cutoff=1e-5, maxdim=200, time_start=T/2, outputlevel=1);
end

main()

Output:

After sweep 1 energy=-24.75  maxlinkdim=1 maxerr=8.01E-11 time=15.110
After sweep 2 energy=-24.75  maxlinkdim=1 maxerr=0.00E+00 time=0.057
After sweep 3 energy=-24.75  maxlinkdim=1 maxerr=0.00E+00 time=0.055
After sweep 4 energy=-24.75  maxlinkdim=1 maxerr=0.00E+00 time=0.058
After sweep 5 energy=-24.75  maxlinkdim=1 maxerr=0.00E+00 time=0.054
After sweep 1: maxlinkdim=1 maxerr=2.36E-06 current_time=1.0 time=25.115
After sweep 2: maxlinkdim=2 maxerr=4.88E-06 current_time=2.0 time=0.283
After sweep 3: maxlinkdim=2 maxerr=1.12E-07 current_time=3.0 time=0.393
After sweep 4: maxlinkdim=2 maxerr=4.69E-06 current_time=4.0 time=0.534
After sweep 5: maxlinkdim=3 maxerr=6.63E-06 current_time=5.0 time=1.098
After sweep 1: maxlinkdim=4 maxerr=1.74E-06 current_time=6.0 time=2.639
After sweep 2: maxlinkdim=5 maxerr=8.41E-06 current_time=7.0 time=3.242
After sweep 3: maxlinkdim=6 maxerr=9.99E-06 current_time=8.0 time=3.255
After sweep 4: maxlinkdim=8 maxerr=9.19E-06 current_time=9.0 time=3.606
After sweep 5: maxlinkdim=11 maxerr=8.79E-06 current_time=10.0 time=4.123

How Has This Been Tested?

I didn't create any new tests.

Checklist:

  • My code follows the style guidelines of this project. Please run using JuliaFormatter; format(".") in the base directory of the repository (~/.julia/dev/ITensorMPS) to format your code according to our style guidelines.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that verify the behavior of the changes I made.
  • I have made corresponding changes to the documentation.
  • My changes generate no new warnings.
  • Any dependent changes have been merged and published in downstream modules.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 8, 2026

Your PR no longer requires formatting changes. Thank you for your contribution!

@codecov
Copy link

codecov bot commented Feb 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.31%. Comparing base (d13c9e1) to head (e5eb661).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #172   +/-   ##
=======================================
  Coverage   90.31%   90.31%           
=======================================
  Files          54       54           
  Lines        3604     3604           
=======================================
  Hits         3255     3255           
  Misses        349      349           
Flag Coverage Δ
docs 17.98% <0.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant