From 2f4afa76960496d2ff880972db98942352462aab Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 5 Oct 2026 18:39:09 -0400 Subject: [PATCH 1/3] Replace deprecated verbosity APIs with phase logging macros --- src/MPSKit.jl | 1 + src/algorithms/approximate/fvomps.jl | 20 ++--- src/algorithms/approximate/idmrg.jl | 20 ++--- src/algorithms/approximate/vomps.jl | 10 +-- src/algorithms/fixedpoint.jl | 2 +- src/algorithms/groundstate/dmrg.jl | 14 +-- .../groundstate/gradient_grassmann.jl | 4 +- src/algorithms/groundstate/idmrg.jl | 16 ++-- src/algorithms/groundstate/vumps.jl | 14 +-- src/algorithms/propagator/corvector.jl | 20 ++--- src/algorithms/statmech/idmrg.jl | 20 ++--- src/algorithms/statmech/vomps.jl | 10 +-- src/algorithms/timestep/time_evolve.jl | 8 +- src/utility/logging.jl | 86 +++++++++++++++++++ 14 files changed, 166 insertions(+), 79 deletions(-) diff --git a/src/MPSKit.jl b/src/MPSKit.jl index dee5e6498..4111185cc 100644 --- a/src/MPSKit.jl +++ b/src/MPSKit.jl @@ -58,6 +58,7 @@ using Compat: @compat @compat public DynamicTols, DynamicTol, AdaptiveKrylov @compat public VERBOSE_NONE, VERBOSE_WARN, VERBOSE_CONV, VERBOSE_ITER, VERBOSE_ALL @compat public IterLog, loginit!, logiter!, logfinish!, logcancel! +@compat public @log_initialization, @log_iteration, @log_convergence, @log_nonconvergence @compat public default_allocator # Imports diff --git a/src/algorithms/approximate/fvomps.jl b/src/algorithms/approximate/fvomps.jl index 8de9325f5..465b40f1b 100644 --- a/src/algorithms/approximate/fvomps.jl +++ b/src/algorithms/approximate/fvomps.jl @@ -4,8 +4,8 @@ function approximate!(ψ::AbstractFiniteMPS, Oϕ, alg::DMRG2, envs = environment iter = 0 log = IterLog("DMRG2") - LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ) + with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ) for outer iter in 1:(alg.maxiter) ϵ = 0.0 for pos in [1:(length(ψ) - 1); (length(ψ) - 2):-1:1] @@ -23,13 +23,13 @@ function approximate!(ψ::AbstractFiniteMPS, Oϕ, alg::DMRG2, envs = environment ψ, envs = alg.finalize(iter, ψ, Oϕ, envs)::Tuple{typeof(ψ), typeof(envs)} if ϵ <= alg.tol - @infov 2 logfinish!(log, iter, ϵ) + @log_convergence logfinish!(log, iter, ϵ) break end if iter == alg.maxiter - @warnv 1 logcancel!(log, iter, ϵ) + @log_nonconvergence logcancel!(log, iter, ϵ) else - @infov 3 logiter!(log, iter, ϵ) + @log_iteration logiter!(log, iter, ϵ) end end end @@ -43,8 +43,8 @@ function approximate!(ψ::AbstractFiniteMPS, Oϕ, alg::DMRG, envs = environments iter = 0 log = IterLog("DMRG") - LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ) + with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ) for outer iter in 1:(alg.maxiter) ϵ = 0.0 for pos in [1:(length(ψ) - 1); length(ψ):-1:2] @@ -59,13 +59,13 @@ function approximate!(ψ::AbstractFiniteMPS, Oϕ, alg::DMRG, envs = environments ψ, envs = alg.finalize(iter, ψ, Oϕ, envs)::Tuple{typeof(ψ), typeof(envs)} if ϵ <= alg.tol - @infov 2 logfinish!(log, iter, ϵ) + @log_convergence logfinish!(log, iter, ϵ) break end if iter == alg.maxiter - @warnv 1 logcancel!(log, iter, ϵ) + @log_nonconvergence logcancel!(log, iter, ϵ) else - @infov 3 logiter!(log, iter, ϵ) + @log_iteration logiter!(log, iter, ϵ) end end end diff --git a/src/algorithms/approximate/idmrg.jl b/src/algorithms/approximate/idmrg.jl index f7422c2e6..8b8079379 100644 --- a/src/algorithms/approximate/idmrg.jl +++ b/src/algorithms/approximate/idmrg.jl @@ -7,8 +7,8 @@ function approximate!( ϵ::Float64 = 2 * alg.tol iter = 0 - LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ) + with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ) for outer iter in 1:(alg.maxiter) C_current = ψ.C[:, 0] @@ -43,13 +43,13 @@ function approximate!( ϵ = norm(C_current - ψ.C[:, 0]) if ϵ <= alg.tol - @infov 2 logfinish!(log, iter, ϵ) + @log_convergence logfinish!(log, iter, ϵ) break end if iter == alg.maxiter - @warnv 1 logcancel!(log, iter, ϵ) + @log_nonconvergence logcancel!(log, iter, ϵ) else - @infov 3 logiter!(log, iter, ϵ) + @log_iteration logiter!(log, iter, ϵ) end end end @@ -75,8 +75,8 @@ function approximate!( iter = 0 ϵ_truncs = PeriodicMatrix(zeros(real(scalartype(ψ)), length(ψ), width(ψ))) - LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ) + with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ) for outer iter in 1:(alg.maxiter) C_current = ψ.C[:, 0] @@ -177,13 +177,13 @@ function approximate!( end if ϵ <= alg.tol - @infov 2 logfinish!(log, iter, ϵ) + @log_convergence logfinish!(log, iter, ϵ) break end if iter == alg.maxiter - @warnv 1 logcancel!(log, iter, ϵ) + @log_nonconvergence logcancel!(log, iter, ϵ) else - @infov 3 logiter!(log, iter, ϵ) + @log_iteration logiter!(log, iter, ϵ) end end end diff --git a/src/algorithms/approximate/vomps.jl b/src/algorithms/approximate/vomps.jl index 2acdbb00b..475913e08 100644 --- a/src/algorithms/approximate/vomps.jl +++ b/src/algorithms/approximate/vomps.jl @@ -30,19 +30,19 @@ function _approximate_vomps(mps, toapprox, alg::VOMPS, envs) state = VOMPSState(mps, toapprox, envs, iter, ϵ) it = IterativeSolver(alg, state) - return LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ) + return with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ) for (mps, envs, ϵ) in it if ϵ ≤ alg.tol - @infov 2 logfinish!(log, it.iter, ϵ) + @log_convergence logfinish!(log, it.iter, ϵ) return mps, envs, AlgorithmInfo(; converged = true, galerkin = ϵ, numiter = it.iter) end if it.iter ≥ alg.maxiter - @warnv 1 logcancel!(log, it.iter, ϵ) + @log_nonconvergence logcancel!(log, it.iter, ϵ) return mps, envs, AlgorithmInfo(; converged = false, galerkin = ϵ, numiter = it.iter) end - @infov 3 logiter!(log, it.iter, ϵ) + @log_iteration logiter!(log, it.iter, ϵ) end # this should never be reached diff --git a/src/algorithms/fixedpoint.jl b/src/algorithms/fixedpoint.jl index 26b692e11..399ff174f 100644 --- a/src/algorithms/fixedpoint.jl +++ b/src/algorithms/fixedpoint.jl @@ -18,6 +18,6 @@ function fixedpoint(A, x₀, which::Symbol, alg::Lanczos) end function fixedpoint(A, x₀, which::Symbol, alg::Arnoldi) TT, vecs, vals, info = schursolve(A, x₀, 1, which, alg) - size(TT, 2) > 1 && TT[2, 1] != 0 && @warnv 1 "non-unique fixed point detected" + size(TT, 2) > 1 && TT[2, 1] != 0 && @warn "non-unique fixed point detected" _group = :mpskit_warning return vals[1], vecs[1], info end diff --git a/src/algorithms/groundstate/dmrg.jl b/src/algorithms/groundstate/dmrg.jl index 7b5bb3491..b2400fdfa 100644 --- a/src/algorithms/groundstate/dmrg.jl +++ b/src/algorithms/groundstate/dmrg.jl @@ -310,8 +310,8 @@ function find_groundstate_sweep!( fwd, bwd = _sweep_ranges(alg, ψ) iter = 0 - LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ_global, expectation_value(ψ, H, envs)) + with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ_global, expectation_value(ψ, H, envs)) for outer iter in 1:(alg.maxiter) @timeit timeroutput "sweep" begin # left-to-right @@ -349,15 +349,15 @@ function find_groundstate_sweep!( # truncation error rather than the (unreachable) bare `tol`. With no truncation # (`ϵ_truncs .= 0`, e.g. single-site/QR gauge) this reduces to the plain `ϵ_global ≤ tol`. if ϵ_global <= max(alg.tol, maximum(ϵ_truncs)) - @infov 4 TimerReport(timeroutput) - @infov 2 logfinish!(log, iter, ϵ_global, expectation_value(ψ, H, envs)) + @info TimerReport(timeroutput) _group = :mpskit_timing + @log_convergence logfinish!(log, iter, ϵ_global, expectation_value(ψ, H, envs)) break end if iter == alg.maxiter - @infov 4 TimerReport(timeroutput) - @warnv 1 logcancel!(log, iter, ϵ_global, expectation_value(ψ, H, envs)) + @info TimerReport(timeroutput) _group = :mpskit_timing + @log_nonconvergence logcancel!(log, iter, ϵ_global, expectation_value(ψ, H, envs)) else - @infov 3 logiter!(log, iter, ϵ_global, expectation_value(ψ, H, envs)) + @log_iteration logiter!(log, iter, ϵ_global, expectation_value(ψ, H, envs)) end end end diff --git a/src/algorithms/groundstate/gradient_grassmann.jl b/src/algorithms/groundstate/gradient_grassmann.jl index 365c20bee..d44c86151 100644 --- a/src/algorithms/groundstate/gradient_grassmann.jl +++ b/src/algorithms/groundstate/gradient_grassmann.jl @@ -121,8 +121,8 @@ function _find_groundstate(ψ, H, alg::GradientGrassmann, envs, scheduler, timer isometrictransport = true, ) - LoggingExtras.withlevel(; verbosity = method_verbosity) do - @infov 4 TimerReport(timeroutput) + with_verbosity(; verbosity = method_verbosity) do + @info TimerReport(timeroutput) _group = :mpskit_timing end info = _optimkit_info(alg, x, f, g, normgradhistory) diff --git a/src/algorithms/groundstate/idmrg.jl b/src/algorithms/groundstate/idmrg.jl index b6da37a17..a0c314148 100644 --- a/src/algorithms/groundstate/idmrg.jl +++ b/src/algorithms/groundstate/idmrg.jl @@ -108,8 +108,8 @@ function _find_groundstate_idmrg(mps, operator, alg::alg_type, envs) where {alg_ ϵ = calc_galerkin(mps, operator, mps, envs; alg.backend, allocator) E = zero(TensorOperations.promote_contract(scalartype(mps), scalartype(operator))) - LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 begin + with_verbosity(; alg.verbosity) do + @log_initialization begin E = expectation_value(mps, operator, envs) loginit!(log, ϵ, E) end @@ -119,19 +119,19 @@ function _find_groundstate_idmrg(mps, operator, alg::alg_type, envs) where {alg_ state = IDMRGState(mps, operator, envs, iter, ϵ, ϵ_truncs, E, timeroutput, allocator) it = IterativeSolver(alg, state) - return LoggingExtras.withlevel(; alg.verbosity) do + return with_verbosity(; alg.verbosity) do for (mps, envs, ϵ, ΔE) in it if ϵ ≤ alg.tol - @infov 4 TimerReport(timeroutput) - @infov 2 logfinish!(log, it.iter, ϵ, ΔE) + @info TimerReport(timeroutput) _group = :mpskit_timing + @log_convergence logfinish!(log, it.iter, ϵ, ΔE) break end if it.iter ≥ alg.maxiter - @infov 4 TimerReport(timeroutput) - @warnv 1 logcancel!(log, it.iter, ϵ, ΔE) + @info TimerReport(timeroutput) _group = :mpskit_timing + @log_nonconvergence logcancel!(log, it.iter, ϵ, ΔE) break end - @infov 3 logiter!(log, it.iter, ϵ, ΔE) + @log_iteration logiter!(log, it.iter, ϵ, ΔE) end alg_gauge = adapt_solver(alg.alg_gauge; iter = it.state.iter, g_global = it.state.ϵ) diff --git a/src/algorithms/groundstate/vumps.jl b/src/algorithms/groundstate/vumps.jl index 48e783d98..9e7b144ef 100644 --- a/src/algorithms/groundstate/vumps.jl +++ b/src/algorithms/groundstate/vumps.jl @@ -82,21 +82,21 @@ function dominant_eigsolve( state = VUMPSState(mps, operator, envs, iter, ϵ, which, timeroutput) it = IterativeSolver(alg, state) - result = LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ, vumps_objective(mps, operator, envs)) + result = with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ, vumps_objective(mps, operator, envs)) for (mps, envs, ϵ) in it if ϵ ≤ alg.tol - @infov 4 TimerReport(timeroutput) - @infov 2 logfinish!(log, it.iter, ϵ, vumps_objective(mps, operator, envs)) + @info TimerReport(timeroutput) _group = :mpskit_timing + @log_convergence logfinish!(log, it.iter, ϵ, vumps_objective(mps, operator, envs)) return mps, envs, AlgorithmInfo(; converged = true, galerkin = ϵ, numiter = it.iter) end if it.iter ≥ alg.maxiter - @infov 4 TimerReport(timeroutput) - @warnv 1 logcancel!(log, it.iter, ϵ, vumps_objective(mps, operator, envs)) + @info TimerReport(timeroutput) _group = :mpskit_timing + @log_nonconvergence logcancel!(log, it.iter, ϵ, vumps_objective(mps, operator, envs)) return mps, envs, AlgorithmInfo(; converged = false, galerkin = ϵ, numiter = it.iter) end - @infov 3 logiter!(log, it.iter, ϵ, vumps_objective(mps, operator, envs)) + @log_iteration logiter!(log, it.iter, ϵ, vumps_objective(mps, operator, envs)) end # this should never be reached diff --git a/src/algorithms/propagator/corvector.jl b/src/algorithms/propagator/corvector.jl index 347411f57..bd72f892c 100644 --- a/src/algorithms/propagator/corvector.jl +++ b/src/algorithms/propagator/corvector.jl @@ -80,8 +80,8 @@ function propagator( ϵ = 2 * alg.tol log = IterLog("DDMRG") - LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ) + with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ) for iter in 1:(alg.maxiter) ϵ = 0.0 @@ -100,13 +100,13 @@ function propagator( end if ϵ <= alg.tol - @infov 2 logfinish!(log, iter, ϵ) + @log_convergence logfinish!(log, iter, ϵ) break end if iter == alg.maxiter - @warnv 1 logcancel!(log, iter, ϵ) + @log_nonconvergence logcancel!(log, iter, ϵ) else - @infov 3 logiter!(log, iter, ϵ) + @log_iteration logiter!(log, iter, ϵ) end end end @@ -157,8 +157,8 @@ function propagator( ϵ = 2 * alg.tol log = IterLog("DDMRG") - LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ) + with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ) for iter in 1:(alg.maxiter) ϵ = 0.0 @@ -177,13 +177,13 @@ function propagator( end if ϵ <= alg.tol - @infov 2 logfinish!(log, iter, ϵ) + @log_convergence logfinish!(log, iter, ϵ) break end if iter == alg.maxiter - @warnv 1 logcancel!(log, iter, ϵ) + @log_nonconvergence logcancel!(log, iter, ϵ) else - @infov 3 logiter!(log, iter, ϵ) + @log_iteration logiter!(log, iter, ϵ) end end end diff --git a/src/algorithms/statmech/idmrg.jl b/src/algorithms/statmech/idmrg.jl index cc6954e5e..8e5a9b0f0 100644 --- a/src/algorithms/statmech/idmrg.jl +++ b/src/algorithms/statmech/idmrg.jl @@ -6,8 +6,8 @@ function leading_boundary( ϵ::Float64 = 2 * alg.tol iter = 0 - LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ, leading_eigenvalue(ψ, operator, envs)) + with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ, leading_eigenvalue(ψ, operator, envs)) for outer iter in 1:(alg.maxiter) alg_eigsolve = adapt_solver(alg.alg_eigsolve; iter, g_global = ϵ) C_current = ψ.C[:, 0] @@ -44,13 +44,13 @@ function leading_boundary( ϵ = norm(C_current - ψ.C[:, 0]) if ϵ <= alg.tol - @infov 2 logfinish!(log, iter, ϵ, leading_eigenvalue(ψ, operator, envs)) + @log_convergence logfinish!(log, iter, ϵ, leading_eigenvalue(ψ, operator, envs)) break end if iter == alg.maxiter - @warnv 1 logcancel!(log, iter, ϵ, leading_eigenvalue(ψ, operator, envs)) + @log_nonconvergence logcancel!(log, iter, ϵ, leading_eigenvalue(ψ, operator, envs)) else - @infov 3 logiter!(log, iter, ϵ, leading_eigenvalue(ψ, operator, envs)) + @log_iteration logiter!(log, iter, ϵ, leading_eigenvalue(ψ, operator, envs)) end end end @@ -72,8 +72,8 @@ function leading_boundary( iter = 0 ϵ_truncs = PeriodicMatrix(zeros(real(scalartype(ψ)), length(ψ), width(ψ))) - LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ) + with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ) for outer iter in 1:(alg.maxiter) alg_eigsolve = adapt_solver(alg.alg_eigsolve; iter, g_global = ϵ) C_current = ψ.C[:, 0] @@ -182,13 +182,13 @@ function leading_boundary( end if ϵ <= alg.tol - @infov 2 logfinish!(log, iter, ϵ) + @log_convergence logfinish!(log, iter, ϵ) break end if iter == alg.maxiter - @warnv 1 logcancel!(log, iter, ϵ) + @log_nonconvergence logcancel!(log, iter, ϵ) else - @infov 3 logiter!(log, iter, ϵ) + @log_iteration logiter!(log, iter, ϵ) end end end diff --git a/src/algorithms/statmech/vomps.jl b/src/algorithms/statmech/vomps.jl index 48d9b7bf4..55c006cef 100644 --- a/src/algorithms/statmech/vomps.jl +++ b/src/algorithms/statmech/vomps.jl @@ -70,19 +70,19 @@ function dominant_eigsolve( state = VOMPSState(mps, operator, envs, iter, ϵ) it = IterativeSolver(alg, state) - return LoggingExtras.withlevel(; alg.verbosity) do - @infov 2 loginit!(log, ϵ, leading_eigenvalue(mps, operator, envs)) + return with_verbosity(; alg.verbosity) do + @log_initialization loginit!(log, ϵ, leading_eigenvalue(mps, operator, envs)) for (mps, envs, ϵ) in it if ϵ ≤ alg.tol - @infov 2 logfinish!(log, it.iter, ϵ, leading_eigenvalue(mps, operator, envs)) + @log_convergence logfinish!(log, it.iter, ϵ, leading_eigenvalue(mps, operator, envs)) return mps, envs, AlgorithmInfo(; converged = true, galerkin = ϵ, numiter = it.iter) end if it.iter ≥ alg.maxiter - @warnv 1 logcancel!(log, it.iter, ϵ, leading_eigenvalue(mps, operator, envs)) + @log_nonconvergence logcancel!(log, it.iter, ϵ, leading_eigenvalue(mps, operator, envs)) return mps, envs, AlgorithmInfo(; converged = false, galerkin = ϵ, numiter = it.iter) end - @infov 3 logiter!(log, it.iter, ϵ, leading_eigenvalue(mps, operator, envs)) + @log_iteration logiter!(log, it.iter, ϵ, leading_eigenvalue(mps, operator, envs)) end # this should never be reached diff --git a/src/algorithms/timestep/time_evolve.jl b/src/algorithms/timestep/time_evolve.jl index 0214b8e88..9d9e87f40 100644 --- a/src/algorithms/timestep/time_evolve.jl +++ b/src/algorithms/timestep/time_evolve.jl @@ -45,8 +45,8 @@ for (timestep, time_evolve) in zip((:timestep, :timestep!), (:time_evolve, :time log = IterLog(string(nameof(typeof(alg)))) truncation_errors = [] ϵ_max = 0.0 - LoggingExtras.withlevel(; verbosity) do - @infov 2 loginit!(log, 0.0, first(t_span)) + with_verbosity(; verbosity) do + @log_initialization loginit!(log, 0.0, first(t_span)) for iter in 1:(length(t_span) - 1) t = t_span[iter] dt = t_span[iter + 1] - t @@ -63,9 +63,9 @@ for (timestep, time_evolve) in zip((:timestep, :timestep!), (:time_evolve, :time ϵ_step = Float64(maximum(info_step.truncation_errors; init = 0.0)) end ϵ_max = max(ϵ_max, ϵ_step) - @infov 3 logiter!(log, iter, ϵ_step, t) + @log_iteration logiter!(log, iter, ϵ_step, t) end - @infov 2 logfinish!(log, length(t_span), ϵ_max, t_span[end]) + @log_convergence logfinish!(log, length(t_span), ϵ_max, t_span[end]) end info = AlgorithmInfo(; numiter = length(t_span) - 1, diff --git a/src/utility/logging.jl b/src/utility/logging.jl index bffa650a4..497bcf120 100644 --- a/src/utility/logging.jl +++ b/src/utility/logging.jl @@ -2,10 +2,41 @@ module IterativeLoggers export IterLog export loginit!, logiter!, logfinish!, logcancel! +export @log_initialization, @log_iteration, @log_convergence, @log_nonconvergence export format_time +export with_verbosity using Printf: @printf, @sprintf +using LoggingExtras: EarlyFilteredLogger, current_logger, with_logger +import LoggingExtras + +const VERBOSITY_LEVELS = ( + mpskit_initialization = 2, + mpskit_iteration = 3, + mpskit_convergence = 2, + mpskit_nonconvergence = 1, + mpskit_warning = 1, + mpskit_timing = 4, +) + +""" + with_verbosity(f; verbosity::Integer) + +Run `f` with MPSKit's numeric verbosity filter. Messages use standard logging macros +with symbolic groups so suppressed messages are filtered before evaluating their contents. +Messages in other groups pass through unchanged. As with `LoggingExtras.withlevel`, +the current logger's severity threshold is temporarily overridden to `Info`. +""" +function with_verbosity(f; verbosity::Integer) + return LoggingExtras.withlevel() do + logger = EarlyFilteredLogger(current_logger()) do args + level = get(VERBOSITY_LEVELS, args.group, nothing) + return isnothing(level) || verbosity >= level + end + return with_logger(f, logger) + end +end @enum LogState INIT ITER CONV CANCEL @@ -87,6 +118,61 @@ function logcancel!( return log end +# Standard algorithm messages +# --------------------------- + +# Expand directly to a standard logging macro at the caller's source location. +function phase_log_expr(source, severity, group, message, args...) + return Expr( + :macrocall, GlobalRef(Base, severity), source, message, + Expr(:(=), :_group, QuoteNode(group)), args... + ) +end + +""" + @log_initialization message args... + +Log `message` at `Info` severity in the `:mpskit_initialization` group (verbosity 2). +The message is evaluated only when enabled; standard logging metadata is supported. + +```julia +@log_initialization loginit!(log, error, expectation_value(ψ, H, envs)) +``` +""" +macro log_initialization(message, args...) + return esc(phase_log_expr(__source__, Symbol("@info"), :mpskit_initialization, message, args...)) +end + +""" + @log_iteration message args... + +Log `message` at `Info` severity in the `:mpskit_iteration` group (verbosity 3). +The message is evaluated only when enabled; standard logging metadata is supported. +""" +macro log_iteration(message, args...) + return esc(phase_log_expr(__source__, Symbol("@info"), :mpskit_iteration, message, args...)) +end + +""" + @log_convergence message args... + +Log `message` at `Info` severity in the `:mpskit_convergence` group (verbosity 2). +The message is evaluated only when enabled; standard logging metadata is supported. +""" +macro log_convergence(message, args...) + return esc(phase_log_expr(__source__, Symbol("@info"), :mpskit_convergence, message, args...)) +end + +""" + @log_nonconvergence message args... + +Log `message` at `Warn` severity in the `:mpskit_nonconvergence` group (verbosity 1). +The message is evaluated only when enabled; standard logging metadata is supported. +""" +macro log_nonconvergence(message, args...) + return esc(phase_log_expr(__source__, Symbol("@warn"), :mpskit_nonconvergence, message, args...)) +end + # Output # ------ From 054466fde424bb3bd34f15c9b093d91aa0e90af7 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 5 Oct 2026 18:39:18 -0400 Subject: [PATCH 2/3] Make canonicalization logging consistent with other algorithms --- src/states/ortho.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/states/ortho.jl b/src/states/ortho.jl index 5a456f120..d7a53a82d 100644 --- a/src/states/ortho.jl +++ b/src/states/ortho.jl @@ -226,26 +226,26 @@ function uniform_leftorth!( backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() ) C[end] = normalize!(C₀) - return LoggingExtras.withlevel(; alg.verbosity) do + return with_verbosity(; alg.verbosity) do # initialize algorithm and temporary variables log = IterLog("LC") A_tail = _transpose_tail.(A) # pre-transpose A CA_tail = similar.(A_tail) # pre-allocate workspace state = (; AL, C, A, A_tail, CA_tail, iter = 0, ϵ = Inf, timeroutput, backend, allocator) it = IterativeSolver(alg, state) - loginit!(log, it.ϵ) + @log_initialization loginit!(log, it.ϵ) # iteratively solve for (AL, C) in it iter, ϵ = it.iter, it.ϵ if ϵ <= it.tol - @infov 2 logfinish!(log, iter, ϵ) + @log_convergence logfinish!(log, iter, ϵ) return AL, C elseif iter > it.maxiter - @warnv 2 logcancel!(log, iter, ϵ) + @log_nonconvergence logcancel!(log, iter, ϵ) return AL, C end - @infov 3 logiter!(log, iter, ϵ) + @log_iteration logiter!(log, iter, ϵ) end end end @@ -295,25 +295,25 @@ function uniform_rightorth!( backend::AbstractBackend = DefaultBackend(), allocator = DefaultAllocator() ) C[end] = normalize!(C₀) - return LoggingExtras.withlevel(; alg.verbosity) do + return with_verbosity(; alg.verbosity) do # initialize algorithm and temporary variables log = IterLog("RC") AC_tail = _similar_tail.(A) # pre-allocate workspace state = (; AR, C, A, AC_tail, iter = 0, ϵ = Inf, timeroutput, backend, allocator) it = IterativeSolver(alg, state) - loginit!(log, it.ϵ) + @log_initialization loginit!(log, it.ϵ) # iteratively solve for (AR, C) in it iter, ϵ = it.iter, it.ϵ if ϵ <= it.tol - @infov 2 logfinish!(log, iter, ϵ) + @log_convergence logfinish!(log, iter, ϵ) return AR, C elseif iter > it.maxiter - @warnv 2 logcancel!(log, iter, ϵ) + @log_nonconvergence logcancel!(log, iter, ϵ) return AR, C end - @infov 3 logiter!(log, iter, ϵ) + @log_iteration logiter!(log, iter, ϵ) end end end From 3d5e66de57b381ddac3157f98c06da3c94bd0cef Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 5 Oct 2026 18:39:21 -0400 Subject: [PATCH 3/3] Allow LoggingExtras 1.x and document the logging migration --- Project.toml | 2 +- docs/src/changelog.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 9d608a4a6..6cedf7583 100644 --- a/Project.toml +++ b/Project.toml @@ -43,7 +43,7 @@ DocStringExtensions = "0.9.3" HalfIntegers = "1.6.0" KrylovKit = "0.8.3, 0.9.2, 0.10" LinearAlgebra = "1.6" -LoggingExtras = "~1.0" +LoggingExtras = "1" MatrixAlgebraKit = "0.6.5" OhMyThreads = "0.7, 0.8" OptimKit = "0.4, 0.5" diff --git a/docs/src/changelog.md b/docs/src/changelog.md index 401d5a827..c14908b1d 100644 --- a/docs/src/changelog.md +++ b/docs/src/changelog.md @@ -49,6 +49,10 @@ When releasing a new version, move the "Unreleased" changes to a new version sec ### Changed +- Algorithm logging now uses named initialization, iteration, convergence, and non-convergence + groups, replacing the deprecated LoggingExtras verbosity APIs. LoggingExtras 1.1 and 1.2 are + supported alongside 1.0. Canonicalization now logs initialization at verbosity 2 and + non-convergence warnings at verbosity 1, consistently with the other algorithms. - `FiniteMPOHamiltonian`/`InfiniteMPOHamiltonian` constructed from a set of local terms now share virtual channels between terms that start out with the same operators, up to a scalar factor, and add up terms that are linearly dependent. The resulting Hamiltonian is unchanged, but its