From 40b2c4e9ec3dba2b7bbd2dfed327940a8e42f847 Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Sat, 20 Jun 2026 10:53:09 +0800 Subject: [PATCH 1/7] Add non-breaking iterable Renormalizer interface for TRG - New Renormalizer{A,S,D} iterable state machine with Base.iterate - TNRParams abstract type for pure algorithm descriptors - TRGParams <: TNRParams with trunc and stop fields - Generic iteration: step!(state, trunc) + finalize!(state) + push! - Old TRG{E,S,TT} <: TNRScheme{E,S} preserved as state type - Legacy run!(::TRG, trunc, criterion) delegates to Renormalizer - rgstep! exported for single-step advancement - gs_degeneracy.jl: tensor-level methods, shared helper (-110 lines) - cft.jl: extract _row_transfer_matrix helper - Finalizer infrastructure marked with TODO for future removal - 10 files, +247/-148 vs upstream/master Co-Authored-By: Claude Opus 4.8 --- .gitignore | 1 + examples/example.jl | 27 ++++++ src/TNRKit.jl | 7 +- src/schemes/renormalizer.jl | 77 +++++++++++++++++ src/schemes/tnrscheme.jl | 3 +- src/schemes/trg.jl | 53 ++++++++++++ src/utility/cft.jl | 27 +++--- src/utility/finalize.jl | 8 ++ src/utility/gs_degeneracy.jl | 156 ++++++++++------------------------- test/schemes/schemes.jl | 33 +++----- 10 files changed, 244 insertions(+), 148 deletions(-) create mode 100644 src/schemes/renormalizer.jl diff --git a/.gitignore b/.gitignore index d2e3e08d..1fdef104 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ Manifest.toml .vscode docs/build/ .DS_Store +CLAUDE.md diff --git a/examples/example.jl b/examples/example.jl index 17c2bd11..36a1e7ae 100644 --- a/examples/example.jl +++ b/examples/example.jl @@ -27,3 +27,30 @@ scheme = HOTRG(classical_ising(1.0)) # run the HOTRG scheme data = run!(scheme, trunc, stopping_criterion) + +# ---- iterable `Renormalizer` interface ---- + +# create a pure algorithm config (kwargs with sensible defaults) +params = TRGParams(; trunc = trunc, stop = stopping_criterion) +renorm = Renormalizer(params, classical_ising(1.0)) + +# run all steps with logging +state, data = run!(renorm; verbosity = 1) +f = free_energy(data, 1.0) + +# or, step through manually +renorm = Renormalizer(params, classical_ising(1.0)) +for (state, data) in renorm + τ0, _ = extract_tau_and_c(state.T; fast = true) + # each iteration yields the state after one RG step + # renorm.step tracks how many steps have been completed +end +# renorm.step is the number of completed steps + +# or, advance one step at a time +renorm = Renormalizer(params, classical_ising(1.0)) +rgstep!(renorm) # throws if stop criterion already met +rgstep!(renorm) + +# access the current tensor directly from the state +T_final = renorm.state.T diff --git a/src/TNRKit.jl b/src/TNRKit.jl index 7bc3a089..f441391a 100644 --- a/src/TNRKit.jl +++ b/src/TNRKit.jl @@ -23,6 +23,7 @@ export trivial_convcrit # schemes include("schemes/tnrscheme.jl") +include("schemes/renormalizer.jl") include("schemes/trg.jl") include("schemes/btrg.jl") include("schemes/hotrg.jl") @@ -60,9 +61,9 @@ include("schemes/looptnr.jl") include("schemes/symmetric_looptnr.jl") export classical_ising_inv # Ising model with all legs in codomain -export TNRScheme +export Renormalizer, TNRScheme, TNRParams -export TRG +export TRG, TRGParams export BTRG export HOTRG export HOTRG_3D @@ -90,7 +91,7 @@ export CorrelationHOTRG export LoopTNR, LoopParameters export SLoopTNR -export run! +export run!, rgstep! # models include("models/ising.jl") diff --git a/src/schemes/renormalizer.jl b/src/schemes/renormalizer.jl new file mode 100644 index 00000000..0b091689 --- /dev/null +++ b/src/schemes/renormalizer.jl @@ -0,0 +1,77 @@ +abstract type TNRParams end + +""" +$(TYPEDEF) + +Iterator that performs RG coarse-graining steps on network tensors. + +# Fields +$(TYPEDFIELDS) + +# Iterator +In a for-loop, each iteration yields `(state, data)` after each RG step. +Stops when the algorithm's stopping criterion is met. +""" +mutable struct Renormalizer{A <: TNRParams, S, D} + "Algorithm configuration (truncation, maxiter, etc.)" + alg::A + "Algorithm-specific state holding all network tensors" + state::S + "Accumulated per-step data (data[1] is the initial value)" + data::Vector{D} + "Number of RG steps performed so far" + step::Int +end + +Renormalizer(alg::A, state::S, data::Vector{D}) where {A, S, D} = Renormalizer{A, S, D}(alg, state, data, 0) +Renormalizer(alg::A, state::S, data::Vector{D}, step::Int) where {A, S, D} = Renormalizer{A, S, D}(alg, state, data, step) + +function Base.iterate(r::Renormalizer) + return iterate(r, 0) +end + +function Base.iterate(r::Renormalizer, n::Int) + r.alg.stop(n, r.data) || return nothing + step!(r.state, r.alg.trunc) + val = finalize!(r.state) + push!(r.data, val) + r.step = n + 1 + return ((r.state, r.data), n + 1) +end + +function Base.show(io::IO, r::Renormalizer) + println(io, "Renormalizer") + println(io, " * algorithm: $(nameof(typeof(r.alg)))") + println(io, " * state: $(nameof(typeof(r.state)))") + println(io, " * step: $(r.step)") + println(io, " * data: $(length(r.data)) entries") + return nothing +end + +""" + rgstep!(r::Renormalizer) + +Perform one RG coarse-graining step. Wraps `Base.iterate`. +Throws an error if the stopping criterion has already been met. +""" +function rgstep!(r::Renormalizer) + r.alg.stop(r.step, r.data) || error("stop criterion reached") + iterate(r, r.step) + return r +end + +""" + run!(renorm::Renormalizer; verbosity=1) + +Run the RG flow to completion. Returns `(final_state, data)`. +""" +function run!(renorm::Renormalizer; verbosity = 1) + LoggingExtras.withlevel(; verbosity) do + @infov 1 "Starting simulation\n $(renorm.state)\n" + t = @elapsed for (_, data) in renorm + @infov 2 "Step $(renorm.step), data[end]: $(data[end])" + end + @infov 1 "Simulation finished\n $(stopping_info(renorm.alg.stop, renorm.step, renorm.data))\n Elapsed time: $(t)s\n Iterations: $(renorm.step)" + end + return renorm.state, renorm.data +end diff --git a/src/schemes/tnrscheme.jl b/src/schemes/tnrscheme.jl index 00f5d365..8b56caec 100644 --- a/src/schemes/tnrscheme.jl +++ b/src/schemes/tnrscheme.jl @@ -1,5 +1,4 @@ # Extra code to make output type available -function step! end function finalize! end """ @@ -30,6 +29,8 @@ const ImpurityHOTRG_Finalizer = Finalizer(finalize!, Tuple{Float64, Float64, Flo # Finalization functions for the various TNR schemes abstract type TNRScheme{E, S} end +# TODO: This should be eventually replaced by `run!(renorm::Renormalizer; verbosity = 1)`. +# Finalizers will be dropped at the end. function run!(scheme::TNRScheme, trscheme::TruncationStrategy, criterion::stopcrit, finalizer::Finalizer{E}; finalize_beginning = true, verbosity = 1) where {E} data = Vector{E}() diff --git a/src/schemes/trg.jl b/src/schemes/trg.jl index af1c9f43..9cd9870d 100644 --- a/src/schemes/trg.jl +++ b/src/schemes/trg.jl @@ -34,6 +34,39 @@ mutable struct TRG{E, S, TT <: AbstractTensorMap{E, S, 2, 2}} <: TNRScheme{E, S} end end +""" +$(TYPEDEF) + +Parameters for the Tensor Renormalization Group algorithm. + +# Constructors + +All parameters are passed as keyword arguments with sensible defaults: + + $(FUNCTIONNAME)(; trunc=truncrank(16), stop=maxiter(20)) + +# Fields + +$(TYPEDFIELDS) +""" +Base.@kwdef struct TRGParams <: TNRParams + "Truncation strategy for SVD steps" + trunc::TruncationStrategy = truncrank(16) + "Stopping criterion" + stop::stopcrit = maxiter(20) +end + +function Renormalizer(params::TRGParams, T::TT) where {TT} + scheme = TRG(T) + n = finalize!(scheme) + return Renormalizer(params, scheme, [n]) +end + +function Renormalizer(params::TRGParams, scheme::TRG) + n = finalize!(scheme) + return Renormalizer(params, scheme, [n]) +end + function step!(scheme::TRG, trunc::TruncationStrategy) A, B = SVD12(scheme.T, trunc) Tp = transpose(scheme.T, ((2, 4), (1, 3))) @@ -42,8 +75,28 @@ function step!(scheme::TRG, trunc::TruncationStrategy) return scheme end +# TODO: legacy `run!` interface for backward compatibility. To be removed later. +function run!( + scheme::TRG, + trscheme::TruncationStrategy, + criterion::stopcrit; + verbosity = 1, + ) + params = TRGParams(; trunc = trscheme, stop = criterion) + renorm = Renormalizer(params, scheme) + _, data = run!(renorm; verbosity) + return data +end + function Base.show(io::IO, scheme::TRG) println(io, "TRG - Tensor Renormalization Group") println(io, " * T: $(summary(scheme.T))") return nothing end + +function Base.show(io::IO, params::TRGParams) + println(io, "TRGParams") + println(io, " * truncation: $(params.trunc)") + println(io, " * stop: $(params.stop)") + return nothing +end diff --git a/src/utility/cft.jl b/src/utility/cft.jl index 2cc09fef..93559ccf 100644 --- a/src/utility/cft.jl +++ b/src/utility/cft.jl @@ -67,22 +67,29 @@ function CFTData( end end +""" + _row_transfer_matrix(T::AbstractTensorMap, unitcell::Int) + +Build a row transfer matrix from `unitcell` copies of the tensor `T` +concatenated horizontally with periodic boundary conditions. +""" +function _row_transfer_matrix(T::AbstractTensorMap, unitcell::Int) + indices = [[i, -i, -(i + unitcell), i + 1] for i in 1:unitcell] + indices[end][4] = 1 + Tcontracted = ncon(fill(T, unitcell), indices) + outinds = ntuple(i -> i, unitcell) + ininds = ntuple(i -> unitcell + i, unitcell) + return permute(Tcontracted, (outinds, ininds)) +end + """ Construct the transfer matrix along vertical direction with `unitcell` copies of `T` concatenated horizontally. `τ0` is the modular parameter of a single `T`. """ function _scaling_dimensions(T::TensorMap{E, S, 2, 2}, τ0::Number; unitcell = 1) where {E, S} - indices = [[i, -i, -(i + unitcell), i + 1] for i in 1:unitcell] - indices[end][4] = 1 - - T = ncon(fill(T, unitcell), indices) - # restore leg convention - outinds = Tuple(collect(1:unitcell)) - ininds = Tuple(collect((unitcell + 1):(2unitcell))) - T = permute(T, (outinds, ininds)) - - sv = StructuredVector(eig_vals(T)) + tm = _row_transfer_matrix(T, unitcell) + sv = StructuredVector(eig_vals(tm)) sv = filter(x -> real(x) > 0 && abs(x) > 1.0e-12, sv) isempty(sv) && throw(ArgumentError("No valid eigenvalues found in transfer matrix spectrum.")) diff --git a/src/utility/finalize.jl b/src/utility/finalize.jl index ec271ed1..075312cb 100644 --- a/src/utility/finalize.jl +++ b/src/utility/finalize.jl @@ -1,3 +1,7 @@ +# ======================================================== +# normalization after an RG step for different TNR schemes +# ======================================================== + const simple_scheme = Union{TRG, ATRG, HOTRG} # 1x1 unitcell finalize @@ -134,6 +138,10 @@ function finalize_phase23!(scheme::CorrelationHOTRG) return n, n_imp, n_imp end +# ===================================================================== +# TODO: remove the following once Renormalizer interface is finished +# ===================================================================== + # cft data finalize function finalize_cftdata!(scheme::TNRScheme) finalize!(scheme) diff --git a/src/utility/gs_degeneracy.jl b/src/utility/gs_degeneracy.jl index cffd000f..2be2c2b0 100644 --- a/src/utility/gs_degeneracy.jl +++ b/src/utility/gs_degeneracy.jl @@ -4,147 +4,77 @@ Calculates the Ground State Degeneracy (GSD) from the fixed-point tensor of a TNRScheme, using the eigenvalues of the transfer matrix. The GSD is the exponential of the Shannon entropy. """ -function ground_state_degeneracy(scheme::TNRScheme{E}, unitcell::Int = 1) where {E} - # Construct contraction indices - indices = Vector{NTuple{4, Int}}(undef, unitcell) - for i in 1:unitcell - indices[i] = (i, -i, -(i + unitcell), i + 1) - end - indices[end] = (unitcell, -unitcell, -(unitcell + unitcell), 1) - - # Contract tensors - Ts = fill(scheme.T, unitcell) - T = ncon(Ts, indices) - - # Construct static tuple indices - outinds = ntuple(i -> i, unitcell) - ininds = ntuple(i -> unitcell + i, unitcell) - - T = permute(T, (outinds, ininds)) - - # Compute normalized eigenvalues - D, _ = eig_full(T) - D = D / tr(D) - vals = filter(!iszero, abs.(D.data)) - # Shannon entropy (stable + efficient) - S = 0.0 - for v in vals - ev = abs(v) - if ev > 0 - S -= ev * log(ev) - end - end - - return exp(S) +function ground_state_degeneracy(T::AbstractTensorMap, unitcell::Int = 1) + tm = _row_transfer_matrix(T, unitcell) + return _ground_state_degeneracy(tm) end -function ground_state_degeneracy(scheme::BTRG{E}; unitcell::Int = 1) where {E} - indices = Vector{NTuple{4, Int}}(undef, unitcell) - for i in 1:unitcell - indices[i] = (i, -i, -(i + unitcell), i + 1) - end - indices[end] = (unitcell, -unitcell, -(unitcell + unitcell), 1) - +function ground_state_degeneracy(TA::AbstractTensorMap, TB::AbstractTensorMap) + # 2-column transfer matrix + @tensor tm[-1 -2; -3 -4] := TA[-1 1; 3 2] * TB[2 6; 4 -3] * + TB[-2 3; 1 5] * TA[5 4; 6 -4] + return _ground_state_degeneracy(tm) +end +ground_state_degeneracy(scheme::TNRScheme; unitcell::Int = 1) = ground_state_degeneracy(scheme.T, unitcell) +function ground_state_degeneracy(scheme::BTRG; unitcell::Int = 1) @tensor T_unit[-1 -2; -3 -4] := scheme.T[1 2; -3 -4] * scheme.S1[-2; 2] * scheme.S2[-1; 1] - T = ncon(fill(T_unit, unitcell), indices) - - # Construct static tuple indices - outinds = ntuple(i -> i, unitcell) - ininds = ntuple(i -> unitcell + i, unitcell) - - T = permute(T, (outinds, ininds)) - D, _ = eig_full(T) - D = D / tr(D) - vals = filter(!iszero, abs.(D.data)) - # Shannon entropy (stable + efficient) - S = 0.0 - for v in vals - ev = abs(v) - if ev > 0 - S -= ev * log(ev) - end - end - - return exp(S) + return ground_state_degeneracy(T_unit, unitcell) end -function ground_state_degeneracy(scheme::LoopTNR{E}) where {E} - norm_const = area_term(scheme.TA, scheme.TB) - T1 = scheme.TA / abs(norm_const)^(1 / 4) - T2 = scheme.TB / abs(norm_const)^(1 / 4) - @tensor T_unit[-1 -2; -3 -4] := T1[-1 1; 3 2] * T2[2 6; 4 -3] * - T2[-2 3; 1 5] * T1[5 4; 6 -4] - - D, _ = eig_full(T_unit) +ground_state_degeneracy(scheme::LoopTNR) = ground_state_degeneracy(scheme.TA, scheme.TB) +# helper function +function _ground_state_degeneracy(tm::AbstractTensorMap{E, S, N, N}) where {E, S, N} + D, _ = eig_full(tm) D = D / tr(D) - vals = filter(!iszero, abs.(D.data)) - # Shannon entropy (stable + efficient) - S = 0.0 - for v in vals - ev = abs(v) - if ev > 0 - S -= ev * log(ev) - end - end - - return exp(S) + evs = filter(!iszero, abs.(D.data)) + entropy = -sum(evs .* log.(evs)) + return exp(entropy) end """ $(SIGNATURES) -Calculates the Gu-Wen ratio X1 and X2 from the fixed-point tensor of a TNRScheme. +Calculates the Gu-Wen ratio X1 and X2 from the fixed-point tensor(s). The Gu-Wen ratios are related to the Ground state Degeneracy and the the scaling dimensions. See references. # References * [Zheng-Cheng Gu & Xiao-Gang Wen. PhysRevB.80.155131](@cite gu2009) * [Satoshi Morita et al. arxiv:2512.03395](@cite morita2025) """ -function gu_wen_ratio(scheme::TNRScheme{E}) where {E} - T_unit = scheme.T - - one_norm = norm(@tensor T_unit[1 2; 2 1]) - two_norm_X1 = norm(@tensor T_unit[1 2; 2 3] * T_unit[3 4; 4 1]) - two_norm_X2 = norm(@tensor T_unit[1 2; 3 4] * T_unit[4 3; 2 1]) - +function gu_wen_ratio(T::AbstractTensorMap{E, S, 2, 2}) where {E, S} + one_norm = norm(@tensor T[1 2; 2 1]) + two_norm_X1 = norm(@tensor T[1 2; 2 3] * T[3 4; 4 1]) + two_norm_X2 = norm(@tensor T[1 2; 3 4] * T[4 3; 2 1]) X1 = (one_norm^2) / (two_norm_X1) X2 = (one_norm^2) / (two_norm_X2) return X1, X2 end -function gu_wen_ratio(scheme::BTRG{E}) where {E} - @tensor T_unit[-1 -2; -3 -4] := scheme.T[1 2; -3 -4] * scheme.S1[-2; 2] * - scheme.S2[-1; 1] - - one_norm = norm(@tensor T_unit[1 2; 2 1]) - two_norm_X1 = norm(@tensor T_unit[1 2; 2 3] * T_unit[3 4; 4 1]) - two_norm_X2 = norm(@tensor T_unit[1 2; 3 4] * T_unit[4 3; 2 1]) - - X1 = (one_norm^2) / (two_norm_X1) - X2 = (one_norm^2) / (two_norm_X2) - return X1, X2 -end -function gu_wen_ratio(scheme::LoopTNR{E}) where {E} - T1 = scheme.TA - T2 = scheme.TB +function gu_wen_ratio( + TA::AbstractTensorMap{E, S, 2, 2}, TB::AbstractTensorMap{E, S, 2, 2} + ) where {E, S} one_norm = norm( - @tensor opt = true T1[1 2; 3 4] * T2[4 5; 6 1] * - T2[7 3; 2 8] * T1[8 6; 5 7] + @tensor opt = true TA[1 2; 3 4] * TB[4 5; 6 1] * + TB[7 3; 2 8] * TA[8 6; 5 7] ) - two_norm_X1 = norm( - @tensor opt = true T1[1 2; 3 4] * T2[4 5; 6 7] * - T1[7 8; 9 10] * T2[10 11; 12 1] * - T2[13 3; 2 14] * T1[14 6; 5 15] * T2[15 9; 8 16] * T1[16 12; 11 13] + @tensor opt = true TA[1 2; 3 4] * TB[4 5; 6 7] * + TA[7 8; 9 10] * TB[10 11; 12 1] * + TB[13 3; 2 14] * TA[14 6; 5 15] * TB[15 9; 8 16] * TA[16 12; 11 13] ) - two_norm_X2 = norm( - @tensor opt = true T1[1 2; 3 4] * T2[4 5; 6 7] * - T1[7 8; 9 10] * T2[10 11; 12 1] * - T2[13 9; 2 14] * T1[14 12; 5 15] * - T2[15 3; 8 16] * T1[16 6; 11 13] + @tensor opt = true TA[1 2; 3 4] * TB[4 5; 6 7] * + TA[7 8; 9 10] * TB[10 11; 12 1] * + TB[13 9; 2 14] * TA[14 12; 5 15] * + TB[15 3; 8 16] * TA[16 6; 11 13] ) - X1 = (one_norm^2) / (two_norm_X1) X2 = (one_norm^2) / (two_norm_X2) return X1, X2 end +gu_wen_ratio(scheme::TNRScheme) = gu_wen_ratio(scheme.T) +function gu_wen_ratio(scheme::BTRG) + @tensor T_unit[-1 -2; -3 -4] := scheme.T[1 2; -3 -4] * scheme.S1[-2; 2] * + scheme.S2[-1; 1] + return gu_wen_ratio(T_unit) +end +gu_wen_ratio(scheme::LoopTNR) = gu_wen_ratio(scheme.TA, scheme.TB) diff --git a/test/schemes/schemes.jl b/test/schemes/schemes.jl index b428a0a6..262276d9 100644 --- a/test/schemes/schemes.jl +++ b/test/schemes/schemes.jl @@ -17,19 +17,9 @@ const T_aniso = classical_ising(Z2Irrep, βc_aniso; Jx = Jx_aniso, Jy = Jy_aniso const f_aniso_exact = f_onsager_anisotropic(βc_aniso, Jx_aniso, Jy_aniso) const τ_aniso_exact = sinh(2 * βc_aniso * Jx_aniso) -function cft_finalize!(scheme) - finalize!(scheme) - return CFTData(scheme) -end - """ Normalize the tensor, return the normalization factor and elementary modular parameter """ -function tau_finalize!(scheme::TRG) - n = finalize!(scheme) - τ0, c = extract_tau_and_c(scheme.T; fast = false) - return (n, τ0) -end function tau_finalize!(scheme::LoopTNR) n = finalize!(scheme) τ0, c = extract_tau_and_c(scheme.TA, scheme.TB; fast = false) @@ -40,27 +30,28 @@ end @testset "TRG - Anisotropic Ising Model" begin @info "Anisotropy: Jx = $(Jx_aniso), Jy = $(Jy_aniso)" @info "TRG anisotropic ising free energy" - scheme = TRG(T_aniso) - elt = scalartype(T_aniso) - finalizer = Finalizer(tau_finalize!, Tuple{elt, complex(elt)}) - data = run!(scheme, truncrank(24), maxiter(25), finalizer) - - ns = map(Base.Fix2(getindex, 1), data) - @test free_energy(ns, βc_aniso) ≈ f_aniso_exact rtol = 2.0e-6 + params = TRGParams(; trunc = truncrank(24), stop = maxiter(25)) + renorm = Renormalizer(params, T_aniso) + T_step10 = nothing + τs = complex(scalartype(T_aniso))[] + for (state, _) in renorm + τ = first(extract_tau_and_c(state.T; fast = false)) + @info "* Step $(renorm.step): τ = $τ." + push!(τs, τ) + (renorm.step == 10) && (T_step10 = state.T) + end + @test free_energy(renorm.data, βc_aniso) ≈ f_aniso_exact rtol = 2.0e-6 @info "TRG τ → (τ - 1) / (τ + 1)" f_trg(τ) = (τ - 1) / (τ + 1) - τs = map(Base.Fix2(getindex, 2), data) for n in 5:7 @test τs[n + 1] ≈ f_trg(τs[n]) rtol = 5.0e-2 @info "* verified for step $(n - 1) → $n" end @info "TRG anisotropic ising CFT data — shape [1, 1, 0]" - scheme = TRG(T_aniso) - run!(scheme, truncrank(24), maxiter(10)) # use fast tau algorithm below - cft = CFTData(scheme; shape = [1, 1, 0]) + cft = CFTData(T_step10; shape = [1, 1, 0]) sd_all = real(cft.scaling_dimensions) cft_sorted = sort(sd_all[2:end]; by = abs) From 0947ede735ddb402727f1cad86740ced7effab2a Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Tue, 23 Jun 2026 09:03:47 +0800 Subject: [PATCH 2/7] Clean up after merge --- src/utility/cft.jl | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/utility/cft.jl b/src/utility/cft.jl index 0f71c62d..d603ced5 100644 --- a/src/utility/cft.jl +++ b/src/utility/cft.jl @@ -67,21 +67,6 @@ function CFTData( end end -""" - _row_transfer_matrix(T::AbstractTensorMap, unitcell::Int) - -Build a row transfer matrix from `unitcell` copies of the tensor `T` -concatenated horizontally with periodic boundary conditions. -""" -function _row_transfer_matrix(T::AbstractTensorMap, unitcell::Int) - indices = [[i, -i, -(i + unitcell), i + 1] for i in 1:unitcell] - indices[end][4] = 1 - Tcontracted = ncon(fill(T, unitcell), indices) - outinds = ntuple(i -> i, unitcell) - ininds = ntuple(i -> unitcell + i, unitcell) - return permute(Tcontracted, (outinds, ininds)) -end - """ Construct the transfer matrix along vertical direction with `unitcell` copies of `T` concatenated horizontally. From c180d162897a6d5b321b9ac0323c479d1b960a34 Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Thu, 25 Jun 2026 20:32:16 +0800 Subject: [PATCH 3/7] Drop backward compatibility for TRG --- examples/example.jl | 14 +++---- src/TNRKit.jl | 4 +- src/schemes/renormalizer.jl | 24 +++++------ src/schemes/trg.jl | 84 +++++++++++++------------------------ src/utility/finalize.jl | 11 ++++- src/utility/free_energy.jl | 2 +- test/fermions/fermions.jl | 14 +++++-- test/models/models.jl | 5 ++- test/schemes/schemes.jl | 21 +++++----- 9 files changed, 83 insertions(+), 96 deletions(-) diff --git a/examples/example.jl b/examples/example.jl index 36a1e7ae..4cf699aa 100644 --- a/examples/example.jl +++ b/examples/example.jl @@ -9,12 +9,8 @@ stopping_criterion = convcrit(1.0e-16, trg_f) & maxiter(20) # choose a TensorKit truncation scheme trunc = truncrank(16) & trunctol(atol = 1.0e-40) -# initialize the TRG scheme -scheme = TRG(classical_ising(1.0)) -# run the TRG scheme (and normalize and store the norm in the beginning (finalize_beginning=true)) -data = run!(scheme, trunc, stopping_criterion; finalize_beginning = true) -# or: data = run!(scheme, truncrank(16)), this will default to maxiter(100) +# ---- old interface (other schemes) ---- # initialize the BTRG scheme scheme = BTRG(classical_ising(1.0), -0.5) @@ -31,15 +27,15 @@ data = run!(scheme, trunc, stopping_criterion) # ---- iterable `Renormalizer` interface ---- # create a pure algorithm config (kwargs with sensible defaults) -params = TRGParams(; trunc = trunc, stop = stopping_criterion) -renorm = Renormalizer(params, classical_ising(1.0)) +alg = TRG(; trunc = trunc, stop = stopping_criterion) +renorm = Renormalizer(alg, classical_ising(1.0)) # run all steps with logging state, data = run!(renorm; verbosity = 1) f = free_energy(data, 1.0) # or, step through manually -renorm = Renormalizer(params, classical_ising(1.0)) +renorm = Renormalizer(alg, classical_ising(1.0)) for (state, data) in renorm τ0, _ = extract_tau_and_c(state.T; fast = true) # each iteration yields the state after one RG step @@ -48,7 +44,7 @@ end # renorm.step is the number of completed steps # or, advance one step at a time -renorm = Renormalizer(params, classical_ising(1.0)) +renorm = Renormalizer(alg, classical_ising(1.0)) rgstep!(renorm) # throws if stop criterion already met rgstep!(renorm) diff --git a/src/TNRKit.jl b/src/TNRKit.jl index 055f0008..f7945139 100644 --- a/src/TNRKit.jl +++ b/src/TNRKit.jl @@ -62,9 +62,9 @@ include("schemes/looptnr.jl") include("schemes/symmetric_looptnr.jl") export classical_ising_inv # Ising model with all legs in codomain -export Renormalizer, TNRScheme, TNRParams +export Renormalizer, TNRScheme, TNRAlgorithm -export TRG, TRGParams +export TRG, OneSiteState export BTRG export HOTRG export HOTRG_3D diff --git a/src/schemes/renormalizer.jl b/src/schemes/renormalizer.jl index 0b091689..15baf1d1 100644 --- a/src/schemes/renormalizer.jl +++ b/src/schemes/renormalizer.jl @@ -1,4 +1,4 @@ -abstract type TNRParams end +abstract type TNRAlgorithm end """ $(TYPEDEF) @@ -12,12 +12,12 @@ $(TYPEDFIELDS) In a for-loop, each iteration yields `(state, data)` after each RG step. Stops when the algorithm's stopping criterion is met. """ -mutable struct Renormalizer{A <: TNRParams, S, D} +mutable struct Renormalizer{A <: TNRAlgorithm, S, D} "Algorithm configuration (truncation, maxiter, etc.)" alg::A - "Algorithm-specific state holding all network tensors" + "Algorithm-specific state holding all involved tensors" state::S - "Accumulated per-step data (data[1] is the initial value)" + "Accumulated per-step data" data::Vector{D} "Number of RG steps performed so far" step::Int @@ -32,7 +32,7 @@ end function Base.iterate(r::Renormalizer, n::Int) r.alg.stop(n, r.data) || return nothing - step!(r.state, r.alg.trunc) + step!(r.state, r.alg) val = finalize!(r.state) push!(r.data, val) r.step = n + 1 @@ -57,7 +57,7 @@ Throws an error if the stopping criterion has already been met. function rgstep!(r::Renormalizer) r.alg.stop(r.step, r.data) || error("stop criterion reached") iterate(r, r.step) - return r + return r.state, r.data end """ @@ -65,13 +65,13 @@ end Run the RG flow to completion. Returns `(final_state, data)`. """ -function run!(renorm::Renormalizer; verbosity = 1) +function run!(r::Renormalizer; verbosity = 1) LoggingExtras.withlevel(; verbosity) do - @infov 1 "Starting simulation\n $(renorm.state)\n" - t = @elapsed for (_, data) in renorm - @infov 2 "Step $(renorm.step), data[end]: $(data[end])" + @infov 1 "Starting simulation\n $(r.state)\n" + t = @elapsed for (_, data) in r + @infov 2 "Step $(r.step), data[end]: $(data[end])" end - @infov 1 "Simulation finished\n $(stopping_info(renorm.alg.stop, renorm.step, renorm.data))\n Elapsed time: $(t)s\n Iterations: $(renorm.step)" + @infov 1 "Simulation finished\n $(stopping_info(r.alg.stop, r.step, r.data))\n Elapsed time: $(t)s\n Iterations: $(r.step)" end - return renorm.state, renorm.data + return r.state, r.data end diff --git a/src/schemes/trg.jl b/src/schemes/trg.jl index 9cd9870d..de209042 100644 --- a/src/schemes/trg.jl +++ b/src/schemes/trg.jl @@ -1,43 +1,33 @@ """ $(TYPEDEF) -Tensor Renormalization Group +State holding a single tensor for a 1-site unit cell. # Constructors $(FUNCTIONNAME)(T) -# Running the algorithm - run!(::TRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=default_Finalizer, finalize_beginning=true, verbosity=1]) -Each step rescales the lattice by a (linear) factor of √2, -and rotate the lattice by 45 degrees in counter clockwise direction. -The elementary modular parameter `τ₀ ↦ (τ₀ - 1) / (τ₀ + 1)`. - -!!! info "verbosity levels" - - 0: No output - - 1: Print information at start and end of the algorithm - - 2: Print information at each step - # Fields $(TYPEDFIELDS) - -# References -* [Levin & Nave Phys. Rev. Letters 99(12) (2007)](@cite levin2007) """ -mutable struct TRG{E, S, TT <: AbstractTensorMap{E, S, 2, 2}} <: TNRScheme{E, S} +mutable struct OneSiteState{TT <: AbstractTensorMap{<:Any, <:Any, 2, 2}} "central tensor" T::TT - function TRG(T::TT) where {E, S, TT <: AbstractTensorMap{E, S, 2, 2}} - return new{E, S, TT}(T) + function OneSiteState(T::TT) where {TT <: AbstractTensorMap{<:Any, <:Any, 2, 2}} + return new{TT}(T) end end """ $(TYPEDEF) -Parameters for the Tensor Renormalization Group algorithm. +Tensor Renormalization Group algorithm. + +Each step rescales the lattice by a (linear) factor of √2, +and rotates the lattice by 45 degrees in counter clockwise direction. +The elementary modular parameter `τ₀ ↦ (τ₀ - 1) / (τ₀ + 1)`. # Constructors @@ -48,55 +38,37 @@ All parameters are passed as keyword arguments with sensible defaults: # Fields $(TYPEDFIELDS) + +# References +* [Levin & Nave Phys. Rev. Letters 99(12) (2007)](@cite levin2007) """ -Base.@kwdef struct TRGParams <: TNRParams +Base.@kwdef struct TRG <: TNRAlgorithm "Truncation strategy for SVD steps" trunc::TruncationStrategy = truncrank(16) "Stopping criterion" stop::stopcrit = maxiter(20) end -function Renormalizer(params::TRGParams, T::TT) where {TT} - scheme = TRG(T) - n = finalize!(scheme) - return Renormalizer(params, scheme, [n]) -end - -function Renormalizer(params::TRGParams, scheme::TRG) - n = finalize!(scheme) - return Renormalizer(params, scheme, [n]) -end - -function step!(scheme::TRG, trunc::TruncationStrategy) - A, B = SVD12(scheme.T, trunc) - Tp = transpose(scheme.T, ((2, 4), (1, 3))) - C, D = SVD12(Tp, trunc) - @plansor scheme.T[-1 -2; -3 -4] := D[-2; 1 2] * B[-1; 4 1] * C[4 3; -3] * A[3 2; -4] - return scheme +function Renormalizer(alg::TRG, T::TT) where {TT} + state = OneSiteState(T) + return Renormalizer(alg, state, scalartype(T)[]) end -# TODO: legacy `run!` interface for backward compatibility. To be removed later. -function run!( - scheme::TRG, - trscheme::TruncationStrategy, - criterion::stopcrit; - verbosity = 1, - ) - params = TRGParams(; trunc = trscheme, stop = criterion) - renorm = Renormalizer(params, scheme) - _, data = run!(renorm; verbosity) - return data +function Renormalizer(alg::TRG, state::OneSiteState) + return Renormalizer(alg, state, scalartype(state.T)[]) end -function Base.show(io::IO, scheme::TRG) - println(io, "TRG - Tensor Renormalization Group") - println(io, " * T: $(summary(scheme.T))") - return nothing +function step!(state::OneSiteState, alg::TRG) + A, B = SVD12(state.T, alg.trunc) + Tp = transpose(state.T, ((2, 4), (1, 3))) + C, D = SVD12(Tp, alg.trunc) + @plansor state.T[-1 -2; -3 -4] := D[-2; 1 2] * B[-1; 4 1] * C[4 3; -3] * A[3 2; -4] + return state end -function Base.show(io::IO, params::TRGParams) - println(io, "TRGParams") - println(io, " * truncation: $(params.trunc)") - println(io, " * stop: $(params.stop)") +function Base.show(io::IO, alg::TRG) + println(io, "TRG") + println(io, " * truncation: $(alg.trunc)") + println(io, " * stop: $(alg.stop)") return nothing end diff --git a/src/utility/finalize.jl b/src/utility/finalize.jl index 075312cb..a4d9b12a 100644 --- a/src/utility/finalize.jl +++ b/src/utility/finalize.jl @@ -2,7 +2,16 @@ # normalization after an RG step for different TNR schemes # ======================================================== -const simple_scheme = Union{TRG, ATRG, HOTRG} +# 1x1 unitcell finalize +function finalize!(state::OneSiteState) + n = norm(@tensor state.T[1 2; 2 1]) + state.T /= n + return n +end + +# Below: for use with old `TNRScheme` interface. + +const simple_scheme = Union{OneSiteState, ATRG, HOTRG} # 1x1 unitcell finalize function finalize!(scheme::simple_scheme) diff --git a/src/utility/free_energy.jl b/src/utility/free_energy.jl index 65604d04..43810b89 100644 --- a/src/utility/free_energy.jl +++ b/src/utility/free_energy.jl @@ -12,7 +12,7 @@ and computes the free energy. """ function free_energy(data, β; scalefactor = 2.0, initial_size = 1.0) lnz = 0.0 - x = 1.0 - log(initial_size) / log(scalefactor) + x = -log(initial_size) / log(scalefactor) for (i, z) in enumerate(data) lnz += log(z) * scalefactor^(x - i) end diff --git a/test/fermions/fermions.jl b/test/fermions/fermions.jl index f434c503..cbcb3762 100644 --- a/test/fermions/fermions.jl +++ b/test/fermions/fermions.jl @@ -7,8 +7,9 @@ T = gross_neveu_start(0, 0, 0) # === TRG === @testset "TRG - Gross-Neveu Model" begin - scheme = TRG(T) - data = run!(scheme, truncrank(16), maxiter(25)) + alg = TRG(; trunc = truncrank(16), stop = maxiter(25)) + renorm = Renormalizer(alg, T) + _, data = run!(renorm; verbosity = 0) @test free_energy(data, 1.0) ≈ f_bench rtol = 1.0e-3 end @@ -56,7 +57,14 @@ end data_c4vCTM = run!(c4vCTM(T_flipped_C4v), truncrank(8), maxiter(10)) free_energy_c4vCTM = -data_c4vCTM / β - schemes = [TRG, BTRG, HOTRG, ATRG, LoopTNR] + # TRG with new iterable interface + alg = TRG(; trunc = truncrank(8), stop = maxiter(10)) + renorm = Renormalizer(alg, T_flipped_C4v) + _, data = run!(renorm; verbosity = 0) + @test free_energy_c4vCTM ≈ free_energy(data, β; scalefactor = 2.0) rtol = 1.0e-9 + + # old interface + schemes = [BTRG, HOTRG, ATRG, LoopTNR] for scheme in schemes data = run!(scheme(T_flipped_C4v), truncrank(8), maxiter(10)) scalefactor = scheme ∈ [HOTRG, ATRG] ? 4.0 : 2.0 diff --git a/test/models/models.jl b/test/models/models.jl index d4ccbbd5..68a54d2c 100644 --- a/test/models/models.jl +++ b/test/models/models.jl @@ -44,8 +44,9 @@ model_temp_answer_string_3d = [ for (model, temp, answer, description) in model_temp_answer_string_2d @testset "$(description)" begin - scheme = TRG(model) - data = run!(scheme, truncrank(16), maxiter(25)) + alg = TRG(; trunc = truncrank(16), stop = maxiter(25)) + renorm = Renormalizer(alg, model) + _, data = run!(renorm; verbosity = 0) @test free_energy(data, temp) ≈ answer rtol = 1.0e-3 end end diff --git a/test/schemes/schemes.jl b/test/schemes/schemes.jl index 262276d9..625c2b91 100644 --- a/test/schemes/schemes.jl +++ b/test/schemes/schemes.jl @@ -30,8 +30,8 @@ end @testset "TRG - Anisotropic Ising Model" begin @info "Anisotropy: Jx = $(Jx_aniso), Jy = $(Jy_aniso)" @info "TRG anisotropic ising free energy" - params = TRGParams(; trunc = truncrank(24), stop = maxiter(25)) - renorm = Renormalizer(params, T_aniso) + alg = TRG(; trunc = truncrank(24), stop = maxiter(25)) + renorm = Renormalizer(alg, T_aniso) T_step10 = nothing τs = complex(scalartype(T_aniso))[] for (state, _) in renorm @@ -60,20 +60,21 @@ end @info "Obtained scaling dimensions: Δ₁ = $(cft_sorted[1]), Δ₂ = $(cft_sorted[2])" @info "TRG anisotropic ising ground state degeneracy" + alg = TRG(; trunc = truncrank(16), stop = maxiter(20)) T1 = classical_ising(βc_aniso - 0.01; Jx = Jx_aniso, Jy = Jy_aniso) - scheme = TRG(T1) - run!(scheme, truncrank(16), maxiter(20)) - gsd = ground_state_degeneracy(scheme) - X1, X2 = gu_wen_ratio(scheme) + renorm = Renormalizer(alg, T1) + run!(renorm; verbosity = 0) + gsd = ground_state_degeneracy(renorm.state) + X1, X2 = gu_wen_ratio(renorm.state) @test gsd ≈ 1 rtol = 1.0e-2 @test X1 ≈ 1.0 rtol = 1.0e-2 @test X2 ≈ 1.0 rtol = 1.0e-2 T2 = classical_ising(βc_aniso + 0.01; Jx = Jx_aniso, Jy = Jy_aniso) - scheme = TRG(T2) - run!(scheme, truncrank(16), maxiter(20)) - gsd = ground_state_degeneracy(scheme) - X1, X2 = gu_wen_ratio(scheme) + renorm = Renormalizer(alg, T2) + run!(renorm; verbosity = 0) + gsd = ground_state_degeneracy(renorm.state) + X1, X2 = gu_wen_ratio(renorm.state) @test gsd ≈ 2 rtol = 1.0e-2 @test X1 ≈ 2.0 rtol = 1.0e-2 @test X2 ≈ 2.0 rtol = 1.0e-2 From 503fda6cc666a4c7c7205a99960573e958340cce Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Thu, 25 Jun 2026 20:35:21 +0800 Subject: [PATCH 4/7] Remove `finalize_beginning` --- README.md | 2 +- docs/src/finalizers.md | 2 +- docs/src/index.md | 2 +- src/schemes/atrg.jl | 2 +- src/schemes/atrg3d.jl | 2 +- src/schemes/btrg.jl | 2 +- src/schemes/ctm/c4vctm.jl | 2 +- src/schemes/ctm/honeycomb.jl | 4 ++-- src/schemes/ctm/triangular.jl | 4 ++-- src/schemes/hotrg.jl | 2 +- src/schemes/hotrg3d.jl | 2 +- src/schemes/impurityhotrg.jl | 2 +- src/schemes/impuritytrg.jl | 2 +- src/schemes/looptnr.jl | 7 +------ src/schemes/symmetric_looptnr.jl | 8 ++------ src/schemes/tnrscheme.jl | 8 ++------ src/schemes/ttnr.jl | 9 ++------- test/models/models.jl | 4 ++-- test/schemes/schemes.jl | 3 +-- 19 files changed, 25 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 47891018..9c88923a 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ scheme = BTRG(T) # Bond-weighted TRG (excellent choice) data = run!(scheme, truncrank(16), maxiter(25)) # max bond-dimension of 16, for 25 iterations ``` -`data` now contains 26 norms of the tensor, 1 for every time the tensor was normalized. (By default there is a normalization step before the first coarse-graining step wich can be turned off by changing the kwarg `run!(...; finalize_beginning=false)`) +`data` now contains 25 norms of the tensor, 1 for every time the tensor was normalized. Using these norms you could, for example, calculate the free energy of the critical classical Ising model: ```Julia diff --git a/docs/src/finalizers.md b/docs/src/finalizers.md index a4fa12d3..37a012fc 100644 --- a/docs/src/finalizers.md +++ b/docs/src/finalizers.md @@ -1,5 +1,5 @@ # Finalizers -At the end of every TNR step (and before the first step if `finalize_beginning=true` is chose in the `run!` function, which is default behaviour), the state of the scheme is finalized. +At the end of every TNR step, the state of the scheme is finalized. By default this finalization process is as follow: diff --git a/docs/src/index.md b/docs/src/index.md index 0cd019e5..3e72fb44 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -58,7 +58,7 @@ T = classical_ising(ising_βc) # partition function of classical Ising model at scheme = BTRG(T) # Bond-weighted TRG (excellent choice) data = run!(scheme, truncrank(16), maxiter(25)) # max bond-dimension of 16, for 25 iterations ``` -`data` now contains 26 norms of the tensor, 1 for every time the tensor was normalized. (By default there is a normalization step before the first coarse-graining step wich can be turned off by changing the kwarg `run!(...; finalize_beginning=false)`) +`data` now contains 25 norms of the tensor, 1 for every time the tensor was normalized. Using these norms you could, for example, calculate the free energy of the critical classical Ising model: ```Julia diff --git a/src/schemes/atrg.jl b/src/schemes/atrg.jl index a07b7c46..87df95a4 100644 --- a/src/schemes/atrg.jl +++ b/src/schemes/atrg.jl @@ -7,7 +7,7 @@ Anisotropic Tensor Renormalization Group $(FUNCTIONNAME)(T) # Running the algorithm - run!(::ATRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=default_Finalizer, finalize_beginning=true, verbosity=1]) + run!(::ATRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=default_Finalizer, verbosity=1]) Each step rescales the lattice by a (linear) factor of √2 diff --git a/src/schemes/atrg3d.jl b/src/schemes/atrg3d.jl index bbf7843f..20f8d7bf 100644 --- a/src/schemes/atrg3d.jl +++ b/src/schemes/atrg3d.jl @@ -7,7 +7,7 @@ $(TYPEDEF) $(FUNCTIONNAME)(T) # Running the algorithm - run!(::ATRG_3D, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=defualt_Finalizer, finalize_beginning=true,verbosity=1]) + run!(::ATRG_3D, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=defualt_Finalizer, verbosity=1]) Each step rescales the lattice by a (linear) factor of 2 diff --git a/src/schemes/btrg.jl b/src/schemes/btrg.jl index c2d4febc..f64a1366 100644 --- a/src/schemes/btrg.jl +++ b/src/schemes/btrg.jl @@ -7,7 +7,7 @@ Bond-weighted Tensor Renormalization Group $(FUNCTIONNAME)(T [, k=-1/2]) # Running the algorithm - run!(::BTRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=default_Finalizer, finalize_beginning=true, verbosity=1]) + run!(::BTRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=default_Finalizer, verbosity=1]) Each step rescales the lattice by a (linear) factor of √2 diff --git a/src/schemes/ctm/c4vctm.jl b/src/schemes/ctm/c4vctm.jl index e0af75bb..2cd38041 100644 --- a/src/schemes/ctm/c4vctm.jl +++ b/src/schemes/ctm/c4vctm.jl @@ -12,7 +12,7 @@ or with a (0,4) tensor (North, East, South, West) (unflipped arrow convention). The keyword argument symmetrize makes the tensor C4v symmetric when set to true. If symmetrize = false, it checks the symmetry explicitly. # Running the algorithm - run!(::c4vCTM, trunc::TruncationStrategy, stop::Stopcrit[, finalize_beginning=true, verbosity=1]) + run!(::c4vCTM, trunc::TruncationStrategy, stop::Stopcrit[, verbosity=1]) !!! info "verbosity levels" - 0: No output diff --git a/src/schemes/ctm/honeycomb.jl b/src/schemes/ctm/honeycomb.jl index d9124547..eb580362 100644 --- a/src/schemes/ctm/honeycomb.jl +++ b/src/schemes/ctm/honeycomb.jl @@ -25,7 +25,7 @@ or with a (0,3) tensor (120°, 0°, 240°) where all arrows point inward (unflip The keyword argument symmetrize makes the tensor C6v symmetric when set to true. If symmetrize = false, it checks the symmetry explicitly. # Running the algorithm - run!(::CTM, trunc::TruncationStrategy, stop::Stopcrit[, finalize_beginning=true, verbosity=1]) + run!(::CTM, trunc::TruncationStrategy, stop::Stopcrit[, verbosity=1]) !!! info "verbosity levels" - 0: No output @@ -131,7 +131,7 @@ In the flipped arrow convention, the arrows point from (120°) to (240°, 0°). or with a (0,3) tensor (120°, 0°, 240°) where all arrows point inward (unflipped arrow convention). # Running the algorithm - run!(::CTM, trunc::TruncationStrategy, stop::Stopcrit[, finalize_beginning=true, verbosity=1]) + run!(::CTM, trunc::TruncationStrategy, stop::Stopcrit[, verbosity=1]) !!! info "verbosity levels" - 0: No output diff --git a/src/schemes/ctm/triangular.jl b/src/schemes/ctm/triangular.jl index 46e2dbfe..9c337c10 100644 --- a/src/schemes/ctm/triangular.jl +++ b/src/schemes/ctm/triangular.jl @@ -25,7 +25,7 @@ or with a (0,6) tensor (120°, 60°, 0°, 300°, 240°, 180°) where all arrows The keyword argument symmetrize makes the tensor C6v symmetric when set to true. If symmetrize = false, it checks the symmetry explicitly. # Running the algorithm - run!(::CTM, trunc::TruncationStrategy, stop::Stopcrit[, finalize_beginning=true, verbosity=1]) + run!(::CTM, trunc::TruncationStrategy, stop::Stopcrit[, verbosity=1]) !!! info "verbosity levels" - 0: No output @@ -100,7 +100,7 @@ or with a (0,6) tensor (120°, 60°, 0°, 300°, 240°, 180°) where all arrows The keyword argument symmetrize makes the tensor C6v symmetric when set to true. If symmetrize = false, it checks the symmetry explicitly. # Running the algorithm - run!(::c6vCTM, trunc::MatrixAlgebraKit.TruncationStrategy, stop::Stopcrit[, finalize_beginning=true, projectors=:twothirds, conditioning=true, verbosity=1]) + run!(::c6vCTM, trunc::MatrixAlgebraKit.TruncationStrategy, stop::Stopcrit[, projectors=:twothirds, conditioning=true, verbosity=1]) `projectors` can either be :twothirds or :full, determining the type of projectors used in the renormalization step. This is based on https://arxiv.org/abs/2510.04907v1. `conditioning` determines whether to condition the second projector construction. This is based on https://doi.org/10.1103/PhysRevB.98.235148. diff --git a/src/schemes/hotrg.jl b/src/schemes/hotrg.jl index c6d787db..06b772ed 100644 --- a/src/schemes/hotrg.jl +++ b/src/schemes/hotrg.jl @@ -7,7 +7,7 @@ Higher-Order Tensor Renormalization Group $(FUNCTIONNAME)(T) # Running the algorithm - run!(::HOTRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=default_Finalizer, finalize_beginning=true, verbosity=1]) + run!(::HOTRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=default_Finalizer, verbosity=1]) Each step rescales the lattice by a (linear) factor of 2 diff --git a/src/schemes/hotrg3d.jl b/src/schemes/hotrg3d.jl index 0be920a1..d2eabf94 100644 --- a/src/schemes/hotrg3d.jl +++ b/src/schemes/hotrg3d.jl @@ -7,7 +7,7 @@ $(TYPEDEF) $(FUNCTIONNAME)(T) # Running the algorithm - run!(::HOTRG_3D, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=default_Finalizer, finalize_beginning=true, verbosity=1]) + run!(::HOTRG_3D, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=default_Finalizer, verbosity=1]) Each step rescales the lattice by a (linear) factor of 2 diff --git a/src/schemes/impurityhotrg.jl b/src/schemes/impurityhotrg.jl index 4d3b32ba..f38e8e4c 100644 --- a/src/schemes/impurityhotrg.jl +++ b/src/schemes/impurityhotrg.jl @@ -7,7 +7,7 @@ Single impurity method for Higher-Order Tensor Renormalization Group (for 2nd or $(FUNCTIONNAME)(T, T_imp_order1_1, T_imp_order1_2, T_imp_order2) # Running the algorithm - run!(::ImpurityHOTRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=ImpurityHOTRG_Finalizer, finalize_beginning=true, verbosity=1]) + run!(::ImpurityHOTRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=ImpurityHOTRG_Finalizer, verbosity=1]) Each step rescales the lattice by a (linear) factor of 2 diff --git a/src/schemes/impuritytrg.jl b/src/schemes/impuritytrg.jl index 12235d11..4974b65b 100644 --- a/src/schemes/impuritytrg.jl +++ b/src/schemes/impuritytrg.jl @@ -7,7 +7,7 @@ Impurity method for Tensor Renormalization Group $(FUNCTIONNAME)(T, T_imp1, T_imp2, T_imp3, T_imp4) # Running the algorithm - run!(::ImpurityTRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=ImpurityTRG_Finalizer, finalize_beginning=true, verbosity=1]) + run!(::ImpurityTRG, trunc::TruncationStrategy, stop::Stopcrit[, finalizer=ImpurityTRG_Finalizer, verbosity=1]) Each step rescales the lattice by a (linear) factor of √2 diff --git a/src/schemes/looptnr.jl b/src/schemes/looptnr.jl index 8905cd94..6bf9b054 100644 --- a/src/schemes/looptnr.jl +++ b/src/schemes/looptnr.jl @@ -10,7 +10,7 @@ Loop Optimization for Tensor Network Renormalization # Running the algorithm run!(::LoopTNR, trunc::TruncationStrategy, criterion::stopcrit, [parameters::LoopParameters], [finalizer::Finalizer]; - [entanglement_criterion::stopcrit, finalize_beginning=true, verbosity=1]) + [entanglement_criterion::stopcrit, verbosity=1]) # LoopParameters See also: [`LoopParameters`](@ref) @@ -490,17 +490,12 @@ function run!( criterion::stopcrit, loop_condition::LoopParameters, finalizer::Finalizer{E}; entanglement_criterion = default_entanglement_criterion, - finalize_beginning = true, verbosity = 1 ) where {E} data = Vector{E}() LoggingExtras.withlevel(; verbosity) do @infov 1 "Starting simulation\n $(scheme)\n" - if finalize_beginning - push!(data, finalizer.f!(scheme)) - end - steps = 0 crit = true diff --git a/src/schemes/symmetric_looptnr.jl b/src/schemes/symmetric_looptnr.jl index 2481cbae..691ce6f6 100644 --- a/src/schemes/symmetric_looptnr.jl +++ b/src/schemes/symmetric_looptnr.jl @@ -9,7 +9,7 @@ c4 & inversion symmetric Loop Optimization for Tensor Network Renormalization # Running the algorithm run!(::SLoopTNR, trscheme::TruncationStrategy, - criterion::TNRKit.stopcrit[, finalizer=default_Finalizer, finalize_beginning=true, oneloop=true, + criterion::TNRKit.stopcrit[, finalizer=default_Finalizer, oneloop=true, verbosity=1]) `oneloop=true` will use disentangled tensors as a starting guess for the optimization. @@ -194,17 +194,13 @@ end function run!( scheme::SLoopTNR, trscheme::TruncationStrategy, - criterion::TNRKit.stopcrit; finalizer = default_Finalizer, finalize_beginning = true, oneloop = true, + criterion::TNRKit.stopcrit; finalizer = default_Finalizer, oneloop = true, verbosity = 1 ) data = output_type(finalizer)[] LoggingExtras.withlevel(; verbosity) do @infov 1 "Starting simulation\n $(scheme)\n" - - if finalize_beginning - push!(data, finalizer.f!(scheme)) - end steps = 0 crit = true diff --git a/src/schemes/tnrscheme.jl b/src/schemes/tnrscheme.jl index 8b56caec..8ae7177f 100644 --- a/src/schemes/tnrscheme.jl +++ b/src/schemes/tnrscheme.jl @@ -9,7 +9,7 @@ Finalizer for TNR schemes # Constructors Finalizer(f!::Function, E::Type) -A Finalizer holds a function `f!` that is to be applied to a TNR scheme after each step of the algorithm (and at the beginning if specified by `run!(;finalize_beginning=true)`, which is the default behavior). +A Finalizer holds a function `f!` that is to be applied to a TNR scheme after each step of the algorithm. The type parameter `E` indicates the output type of `f!`, which is used to create an array of the correct type to hold the outputs. """ struct Finalizer{E} # E is the output type of f @@ -31,16 +31,12 @@ abstract type TNRScheme{E, S} end # TODO: This should be eventually replaced by `run!(renorm::Renormalizer; verbosity = 1)`. # Finalizers will be dropped at the end. -function run!(scheme::TNRScheme, trscheme::TruncationStrategy, criterion::stopcrit, finalizer::Finalizer{E}; finalize_beginning = true, verbosity = 1) where {E} +function run!(scheme::TNRScheme, trscheme::TruncationStrategy, criterion::stopcrit, finalizer::Finalizer{E}; verbosity = 1) where {E} data = Vector{E}() LoggingExtras.withlevel(; verbosity) do @infov 1 "Starting simulation\n $(scheme)\n" - if finalize_beginning - push!(data, finalizer.f!(scheme)) - end - steps = 0 crit = true diff --git a/src/schemes/ttnr.jl b/src/schemes/ttnr.jl index 2d2d2a62..f2110e05 100644 --- a/src/schemes/ttnr.jl +++ b/src/schemes/ttnr.jl @@ -63,7 +63,7 @@ Thermal Tensor Network Renormalization on a square-lattice # Running the algorithm run!(::ThermalTNR, A::AbstractMatrix{<:AbstractTensorMap}, trunc::TruncationStrategy, criterion::stopcrit[ - , finalizer=default_Finalizer, finalize_beginning=true, verbosity=1]) + , finalizer=default_Finalizer, verbosity=1]) # Fields @@ -255,17 +255,12 @@ end function run!( scheme::ThermalTNR, layer::TNO, trscheme::TruncationStrategy, - criterion::stopcrit, finalizer::Finalizer{E}; - finalize_beginning = true, verbosity = 1 + criterion::stopcrit, finalizer::Finalizer{E}; verbosity = 1 ) where {E} data = Vector{E}() LoggingExtras.withlevel(; verbosity) do @infov 1 "Starting simulation\n $(scheme)\n" - if finalize_beginning - push!(data, finalizer.f!(scheme)) - end - steps = 0 crit = true diff --git a/test/models/models.jl b/test/models/models.jl index 68a54d2c..1d41e89b 100644 --- a/test/models/models.jl +++ b/test/models/models.jl @@ -202,7 +202,7 @@ end scheme = LoopTNR(T) elt = scalartype(T) finalizer = Finalizer(cc_finalize!, Tuple{elt, complex(elt), elt}) - data = run!(scheme, truncrank(16), maxiter(16), finalizer; finalize_beginning = false) + data = run!(scheme, truncrank(16), maxiter(16), finalizer) @test last(data)[3] ≈ 0.5 atol = 1.0e-2 end @@ -234,7 +234,7 @@ end scheme = LoopTNR(T) elt = scalartype(T) finalizer = Finalizer(cc_finalize!, Tuple{elt, complex(elt), elt}) - data = run!(scheme, truncrank(16), maxiter(8), finalizer; finalize_beginning = false) + data = run!(scheme, truncrank(16), maxiter(8), finalizer) @test last(data)[3] ≈ 0.5 atol = 1.0e-2 for shape in ([√2, 2√2, 0], [1, 4, 1], [1, 8, 1], [4 / √10, 2√10, 2 / √10]) cft = CFTData(scheme; shape = shape) diff --git a/test/schemes/schemes.jl b/test/schemes/schemes.jl index 625c2b91..f8fd3276 100644 --- a/test/schemes/schemes.jl +++ b/test/schemes/schemes.jl @@ -720,8 +720,7 @@ function _thermal_zn2_gu_wen_x1(β, Lz; χttnr = 12, χbtrg = 16, btrg_steps = 1 @tensor effective_tensor[-1 -2 -3 -4] := scheme.T[1, 1][p p; -1 -2 -3 -4] btrg = BTRG(permute(effective_tensor, ((1, 2), (3, 4)))) ratios = run!( - btrg, truncrank(χbtrg), maxiter(btrg_steps), guwenratio_Finalizer; - finalize_beginning = false, verbosity = 0, + btrg, truncrank(χbtrg), maxiter(btrg_steps), guwenratio_Finalizer; verbosity = 0, ) x1, _ = last(ratios) From 0f2149c76ad8080e84d614ff9682ec7bb6ee9f1a Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Fri, 26 Jun 2026 11:24:07 +0800 Subject: [PATCH 5/7] Fix Correlation HOTRG initial size (?) --- test/schemes/schemes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/schemes/schemes.jl b/test/schemes/schemes.jl index f8fd3276..0fd15d0e 100644 --- a/test/schemes/schemes.jl +++ b/test/schemes/schemes.jl @@ -562,7 +562,7 @@ end data = run!(scheme, truncrank(16), maxiter(25)) - @test free_energy(getindex.(data, 1), ising_βc; scalefactor = 4.0, initial_size = 4.0) ≈ f_onsager rtol = 1.0e-4 + @test free_energy(getindex.(data, 1), ising_βc; scalefactor = 4.0) ≈ f_onsager rtol = 1.0e-4 end @testset "Correlation HOTRG - Magnetisation Correlation" begin From 537e833d1ca3028a1eebc2cedede956f8f124a97 Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Fri, 26 Jun 2026 11:34:39 +0800 Subject: [PATCH 6/7] Clean up tests --- test/models/models.jl | 6 +- test/schemes/schemes.jl | 150 +++++++++++++++++----------------------- 2 files changed, 65 insertions(+), 91 deletions(-) diff --git a/test/models/models.jl b/test/models/models.jl index 1d41e89b..b0ed3e29 100644 --- a/test/models/models.jl +++ b/test/models/models.jl @@ -214,9 +214,9 @@ end T = vertical_stack_exp(T, nfold, trunc_stack) @info "CFT data from TRG" - scheme = TRG(T) - run!(scheme, truncrank(24), maxiter(8)) - cft = CFTData(scheme; shape = [1, 1, 0]) + alg = TRG(; trunc = truncrank(24), stop = maxiter(8)) + state, _ = run!(Renormalizer(alg, T); verbosity = 0) + cft = CFTData(state.T; shape = [1, 1, 0]) c = cft.central_charge sd = cft.scaling_dimensions d_1 = real(sd[(:NS, FermionParity(0))][2]) diff --git a/test/schemes/schemes.jl b/test/schemes/schemes.jl index 0fd15d0e..cf082ad2 100644 --- a/test/schemes/schemes.jl +++ b/test/schemes/schemes.jl @@ -61,23 +61,18 @@ end @info "TRG anisotropic ising ground state degeneracy" alg = TRG(; trunc = truncrank(16), stop = maxiter(20)) - T1 = classical_ising(βc_aniso - 0.01; Jx = Jx_aniso, Jy = Jy_aniso) - renorm = Renormalizer(alg, T1) - run!(renorm; verbosity = 0) - gsd = ground_state_degeneracy(renorm.state) - X1, X2 = gu_wen_ratio(renorm.state) - @test gsd ≈ 1 rtol = 1.0e-2 - @test X1 ≈ 1.0 rtol = 1.0e-2 - @test X2 ≈ 1.0 rtol = 1.0e-2 - - T2 = classical_ising(βc_aniso + 0.01; Jx = Jx_aniso, Jy = Jy_aniso) - renorm = Renormalizer(alg, T2) - run!(renorm; verbosity = 0) - gsd = ground_state_degeneracy(renorm.state) - X1, X2 = gu_wen_ratio(renorm.state) - @test gsd ≈ 2 rtol = 1.0e-2 - @test X1 ≈ 2.0 rtol = 1.0e-2 - @test X2 ≈ 2.0 rtol = 1.0e-2 + for (Δβ, gsd0, X10, X20) in [ + (-0.01, 1, 1.0, 1.0), (0.01, 2, 2.0, 2.0), + ] + T1 = classical_ising(βc_aniso + Δβ; Jx = Jx_aniso, Jy = Jy_aniso) + renorm = Renormalizer(alg, T1) + state, = run!(renorm; verbosity = 0) + gsd = ground_state_degeneracy(state.T) + X1, X2 = gu_wen_ratio(state.T) + @test gsd ≈ gsd0 rtol = 1.0e-2 + @test X1 ≈ X10 rtol = 1.0e-2 + @test X2 ≈ X20 rtol = 1.0e-2 + end end # BTRG @@ -98,23 +93,18 @@ end @test cft[2] ≈ ising_cft_exact[2] rtol = 2.0e-2 @info "BTRG ising ground state degeneracy" - T1 = classical_ising(ising_βc - 0.01) - scheme = BTRG(T1) - run!(scheme, truncrank(16), maxiter(20)) - gsd = ground_state_degeneracy(scheme) - X1, X2 = gu_wen_ratio(scheme) - @test gsd ≈ 1 rtol = 1.0e-2 - @test X1 ≈ 1.0 rtol = 1.0e-2 - @test X2 ≈ 1.0 rtol = 1.0e-2 - - T2 = classical_ising(ising_βc + 0.01) - scheme = BTRG(T2) - run!(scheme, truncrank(16), maxiter(20)) - gsd = ground_state_degeneracy(scheme) - X1, X2 = gu_wen_ratio(scheme) - @test gsd ≈ 2 rtol = 1.0e-2 - @test X1 ≈ 2.0 rtol = 1.0e-2 - @test X2 ≈ 2.0 rtol = 1.0e-2 + for (Δβ, gsd0, X10, X20) in [ + (-0.01, 1, 1.0, 1.0), (0.01, 2, 2.0, 2.0), + ] + T1 = classical_ising(ising_βc + Δβ) + scheme = BTRG(T1) + run!(scheme, truncrank(16), maxiter(20)) + gsd = ground_state_degeneracy(scheme) + X1, X2 = gu_wen_ratio(scheme) + @test gsd ≈ gsd0 rtol = 1.0e-2 + @test X1 ≈ X10 rtol = 1.0e-2 + @test X2 ≈ X20 rtol = 1.0e-2 + end end # HOTRG @@ -135,23 +125,18 @@ end @test cft[2] ≈ ising_cft_exact[2] rtol = 1.0e-2 @info "HOTRG ising ground state degeneracy" - T1 = classical_ising(ising_βc - 0.01) - scheme = HOTRG(T1) - run!(scheme, truncrank(12), maxiter(20)) - gsd = ground_state_degeneracy(scheme) - X1, X2 = gu_wen_ratio(scheme) - @test gsd ≈ 1 rtol = 1.0e-2 - @test X1 ≈ 1.0 rtol = 1.0e-2 - @test X2 ≈ 1.0 rtol = 1.0e-2 - - T2 = classical_ising(ising_βc + 0.01) - scheme = HOTRG(T2) - run!(scheme, truncrank(12), maxiter(20)) - gsd = ground_state_degeneracy(scheme) - X1, X2 = gu_wen_ratio(scheme) - @test gsd ≈ 2 rtol = 1.0e-2 - @test X1 ≈ 2.0 rtol = 1.0e-2 - @test X2 ≈ 2.0 rtol = 1.0e-2 + for (Δβ, gsd0, X10, X20) in [ + (-0.01, 1, 1.0, 1.0), (0.01, 2, 2.0, 2.0), + ] + T1 = classical_ising(ising_βc + Δβ) + scheme = HOTRG(T1) + run!(scheme, truncrank(12), maxiter(20)) + gsd = ground_state_degeneracy(scheme) + X1, X2 = gu_wen_ratio(scheme) + @test gsd ≈ gsd0 rtol = 1.0e-2 + @test X1 ≈ X10 rtol = 1.0e-2 + @test X2 ≈ X20 rtol = 1.0e-2 + end end # ATRG @@ -172,23 +157,18 @@ end @test cft[2] ≈ ising_cft_exact[2] rtol = 1.0e-2 @info "ATRG ising ground state degeneracy" - T1 = classical_ising(ising_βc - 0.01) - scheme = ATRG(T1) - run!(scheme, truncrank(16), maxiter(20)) - gsd = ground_state_degeneracy(scheme) - X1, X2 = gu_wen_ratio(scheme) - @test gsd ≈ 1 rtol = 1.0e-2 - @test X1 ≈ 1.0 rtol = 1.0e-2 - @test X2 ≈ 1.0 rtol = 1.0e-2 - - T2 = classical_ising(ising_βc + 0.01) - scheme = ATRG(T2) - run!(scheme, truncrank(16), maxiter(20)) - gsd = ground_state_degeneracy(scheme) - X1, X2 = gu_wen_ratio(scheme) - @test gsd ≈ 2 rtol = 1.0e-2 - @test X1 ≈ 2.0 rtol = 1.0e-2 - @test X2 ≈ 2.0 rtol = 1.0e-2 + for (Δβ, gsd0, X10, X20) in [ + (-0.01, 1, 1.0, 1.0), (0.01, 2, 2.0, 2.0), + ] + T1 = classical_ising(ising_βc + Δβ) + scheme = ATRG(T1) + run!(scheme, truncrank(16), maxiter(20)) + gsd = ground_state_degeneracy(scheme) + X1, X2 = gu_wen_ratio(scheme) + @test gsd ≈ gsd0 rtol = 1.0e-2 + @test X1 ≈ X10 rtol = 1.0e-2 + @test X2 ≈ X20 rtol = 1.0e-2 + end end # LoopTNR @@ -214,13 +194,12 @@ end τs = map(Base.Fix2(getindex, 2), data) for n in 5:8 @test τs[n + 1] ≈ f_looptnr(τs[n]) rtol = 2.0e-2 - @info "* verified for step $(n - 1) → $n" + @info "* verified for step $n → $(n + 1)" end @info "Theory value of τ for anisotropic Ising" for n in (4, 8, 12) - # n + 1 due to finalizing the initial tensor - τ = τs[n + 1] + τ = τs[n] @test real(τ) ≈ 0 atol = 1.0e-3 @test imag(τ) ≈ τ_aniso_exact rtol = 2.0e-3 @info "* τ = $τ ≈ $(τ_aniso_exact)im verified for step $n" @@ -274,23 +253,18 @@ end end @info "LoopTNR anisotropic ising ground state degeneracy" - T1 = classical_ising(βc_aniso - 0.01; Jx = Jx_aniso, Jy = Jy_aniso) - scheme = LoopTNR(T1) - run!(scheme, truncrank(12), maxiter(20)) - gsd = ground_state_degeneracy(scheme) - X1, X2 = gu_wen_ratio(scheme) - @test gsd ≈ 1 rtol = 1.0e-2 - @test X1 ≈ 1.0 rtol = 1.0e-2 - @test X2 ≈ 1.0 rtol = 1.0e-2 - - T2 = classical_ising(βc_aniso + 0.01; Jx = Jx_aniso, Jy = Jy_aniso) - scheme = LoopTNR(T2) - run!(scheme, truncrank(12), maxiter(20)) - gsd = ground_state_degeneracy(scheme) - X1, X2 = gu_wen_ratio(scheme) - @test gsd ≈ 2 rtol = 1.0e-2 - @test X1 ≈ 2.0 rtol = 1.0e-2 - @test X2 ≈ 2.0 rtol = 1.0e-2 + for (Δβ, gsd0, X10, X20) in [ + (-0.01, 1, 1.0, 1.0), (0.01, 2, 2.0, 2.0), + ] + T1 = classical_ising(βc_aniso + Δβ; Jx = Jx_aniso, Jy = Jy_aniso) + scheme = LoopTNR(T1) + run!(scheme, truncrank(12), maxiter(20)) + gsd = ground_state_degeneracy(scheme) + X1, X2 = gu_wen_ratio(scheme) + @test gsd ≈ gsd0 rtol = 1.0e-2 + @test X1 ≈ X10 rtol = 1.0e-2 + @test X2 ≈ X20 rtol = 1.0e-2 + end end @testset "LoopTNR - Ising Model - Dense Solver - NNR" begin From caa125c8fa06997c8c5526fb7b9be3b5cc5f9aea Mon Sep 17 00:00:00 2001 From: Yue Zhengyuan Date: Fri, 26 Jun 2026 11:58:30 +0800 Subject: [PATCH 7/7] More cleanups --- src/schemes/renormalizer.jl | 2 +- src/utility/finalize.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/schemes/renormalizer.jl b/src/schemes/renormalizer.jl index 15baf1d1..8755b892 100644 --- a/src/schemes/renormalizer.jl +++ b/src/schemes/renormalizer.jl @@ -61,7 +61,7 @@ function rgstep!(r::Renormalizer) end """ - run!(renorm::Renormalizer; verbosity=1) + run!(r::Renormalizer; verbosity=1) Run the RG flow to completion. Returns `(final_state, data)`. """ diff --git a/src/utility/finalize.jl b/src/utility/finalize.jl index a4d9b12a..54dfdb01 100644 --- a/src/utility/finalize.jl +++ b/src/utility/finalize.jl @@ -11,7 +11,7 @@ end # Below: for use with old `TNRScheme` interface. -const simple_scheme = Union{OneSiteState, ATRG, HOTRG} +const simple_scheme = Union{ATRG, HOTRG} # 1x1 unitcell finalize function finalize!(scheme::simple_scheme)