DMRG3S: strictly single-site DMRG subspace expansion (Hubig et al. 2015)#460
DMRG3S: strictly single-site DMRG subspace expansion (Hubig et al. 2015)#460VinceNeede wants to merge 10 commits into
Conversation
Replace the two near-duplicate sweep loops in `find_groundstate!` with a single loop over `direction in (:right, :left)`, dispatching on `Val` via `_sweep_range` and `dmrg_gauge!`. No behavioral change: `_sweep_range` reproduces the original site ranges, and `dmrg_gauge!` preserves the original left_gauge!/right_gauge! pairing per direction.
Add `FunctionalSchedule`, wrapping an arbitrary `(noise, iter, ϵ) -> noise` callable as a `NoiseSchedule`. Overload `∘` on `NoiseSchedule` to compose two schedules into a `FunctionalSchedule`, following the usual function composition convention (`s2` applied first, `s1` applied to its result). Add a `threshold` keyword to `ExponentialDecay`, snapping the decayed noise to exactly zero once it falls below it -- avoids running the (cheap but non-free) expansion step indefinitely on a vanishingly small amplitude. This also makes `ExponentialDecay ∘ Warmup` a natural way to combine a hard iteration cutoff with smooth decay.
|
Your PR no longer requires formatting changes. Thank you for your contribution! |
Codecov Report❌ Patch coverage is
... and 2 files with indirect coverage changes 🚀 New features to boost your workflow:
|
|
Thanks for this, I had a brief look and I think it already looks quite well. Considering the expansion algorithm itself - without having looked in a lot of detail so definitely feel free to tell me I'm wrong - I think it could be nice to avoid having both an For the TDVP implementation, I definitely agree to flush this one out first, and honestly it's probably easier to tackle and review that in a separate PR. Considering your other question, I'm definitely happy to add the |
Summary
Implements DMRG3S — strictly single-site DMRG with subspace expansion — from Hubig, McCulloch, Schollwöck & Wolf, Phys. Rev. B 91, 155115 (2015). Unlike CBE (
alg_expand), which enriches the bond before the local eigensolve, DMRG3S enriches it after, using a perturbation built from the just-optimized tensor, the local Hamiltonian, and the environment. This lets single-site DMRG escape local minima caused by missing quantum-number sectors that CBE-style pre-expansion can't reach.This PR also targets TDVP, pending design agreement
DMRG only for now. TDVP support belongs in this same PR, but I'd like design agreement on the interface below first, since it directly shapes how it plugs into TDVP too. Docs are also on hold for the same reason — no point documenting an interface that might still change.
What's here
find_groundstate!'s left-to-right and right-to-left sweeps from two separate, near-duplicate loops into a single loop overdirection in (:right, :left), dispatching onVal. No behavioral change; this just made room for the new expansion step without doubling its code.alg_post_expandfield onDMRG, dispatching a newpost_expand!step after the eigensolve, alongside the existing pre-eigensolvealg_expand. Default (NoExpand()) reproduces current behavior exactly.DMRG3S, with a composableNoiseSchedulefor the mixing factor (ExponentialDecay,Warmup,∘for combining them).alg_expandandalg_post_expandare independent and can be used together or separately.alg_gauge, since the bond would otherwise grow unboundedly each sweep.Open design questions for maintainers
alg_post_expandsentinel: I used a dedicatedNoExpand()type rather thannothing(whichalg_expanduses). This letsNoExpandcarry its ownpost_expand!method for dispatch, but it's an inconsistency withalg_expand's convention worth flagging.post_expand!call rather than kept separate, because splitting them left the MPS briefly inconsistent between steps (caught via a real bug during development — happy to share details). This does meanpost_expand!needsalg_gaugethreaded in as a parameter, coupling it to the gauge step more tightly thanalg_expandis.TODO before merge