Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
61a88c1
Generalize environment gauge fixing
pbrehmer Jan 21, 2026
0ec910b
Add C4v CTMRG algorithm
pbrehmer Jan 21, 2026
7256f3f
Add C4v CTMRG rrules and defaults
pbrehmer Jan 21, 2026
1a326b9
Fix tensor decompositions
pbrehmer Jan 22, 2026
23c1610
Fix parameter selection
pbrehmer Jan 22, 2026
0a475fe
Make some tests runnable
pbrehmer Jan 22, 2026
094af8c
Fix some more stuff and add fixed_iterscheme C4v test
pbrehmer Jan 22, 2026
a6ce108
Comment out QR things for now
pbrehmer Jan 23, 2026
97760e8
Add gauge fixing and partition function C4v tests
pbrehmer Jan 23, 2026
6effabe
Fix differentiability and add C4v Heisenberg test
pbrehmer Jan 23, 2026
089a005
Automatically symmetrize optimization when alg=:c4v
pbrehmer Jan 23, 2026
f3d89e1
Fix unitcell test imports
pbrehmer Jan 23, 2026
fcdea38
Add eigh_wrapper test and fix IterEigh
pbrehmer Jan 23, 2026
7905570
Fix eigh_wrapper test imports
Yue-Zhengyuan Jan 24, 2026
30f484f
Update src/algorithms/ctmrg/gaugefix.jl
pbrehmer Jan 26, 2026
ee0b5e2
Rename to decomposition algorithm to `decomp_alg`
pbrehmer Jan 26, 2026
f4df969
Fix partition function test import
pbrehmer Jan 26, 2026
0968a4c
Update docstrings to `decomp_alg`
pbrehmer Jan 26, 2026
7651853
Fix flavors test import
pbrehmer Jan 26, 2026
461402e
Add docstrings
pbrehmer Jan 26, 2026
9a7f460
Fix `c4v_projector`
pbrehmer Jan 26, 2026
e2ea8dd
Update docstrings
pbrehmer Jan 28, 2026
3b9d769
Fix `:full` eigh pullback
pbrehmer Jan 28, 2026
2f109f0
Rename `decomp_alg` back to `decomposition_alg`
pbrehmer Jan 30, 2026
e8ea503
Update `initialize_random_c4v_env` and export
pbrehmer Jan 30, 2026
9fb5000
Add singlet corner C4v initialization function
pbrehmer Jan 30, 2026
43679c5
Merge remote-tracking branch 'upstream/master' into c4v-ctmrg
Yue-Zhengyuan Feb 2, 2026
4a39c6e
Rename `project_hermitian` to `hermitian_project`
pbrehmer Feb 2, 2026
e603c04
Improve `isfulleig`
pbrehmer Feb 2, 2026
08a1204
Remove QR file
pbrehmer Feb 2, 2026
abab399
Merge branch 'c4v-ctmrg' of github.com:quantumghent/PEPSKit.jl into c…
pbrehmer Feb 2, 2026
0f6b5c0
Rename `U` to `V` in eigendecomposition (consistent with MAK)
pbrehmer Feb 2, 2026
b182d90
Omit docstring type annotation
pbrehmer Feb 2, 2026
09b98c4
Move all imports to `src/PEPSKit.jl`
pbrehmer Feb 2, 2026
f07d268
Fix U->V relabeling
pbrehmer Feb 2, 2026
71371e5
Merge branch 'c4v-ctmrg' of github.com:quantumghent/PEPSKit.jl into c…
pbrehmer Feb 2, 2026
c094446
Fix SVD test
pbrehmer Feb 2, 2026
f7d1111
Move KrylovKitCRCExt to SVD file
pbrehmer Feb 2, 2026
f262a48
Fix `IterEigh` fixed_iterscheme test
pbrehmer Feb 2, 2026
fbbdaa0
Fix fixed_iterscheme test imports
Yue-Zhengyuan Feb 3, 2026
3f22fc4
Update fixed_iterscheme test
pbrehmer Feb 3, 2026
ea6e601
Merge branch 'c4v-ctmrg' of github.com:quantumghent/PEPSKit.jl into c…
pbrehmer Feb 3, 2026
fd46a73
Remove redundant import
pbrehmer Feb 3, 2026
defc782
Update fixed_iterscheme test for the 10000th time
pbrehmer Feb 3, 2026
483742b
Add Hermitian projection to `c4v_renormalize`
pbrehmer Feb 3, 2026
e580451
Rename `hermitian_project` to `_project_hermitian`
pbrehmer Feb 3, 2026
cef1161
Use `north_virtualspace` instead of `domain`
pbrehmer Feb 4, 2026
cdd8aa2
Add TODO
pbrehmer Feb 4, 2026
6960981
Adjust signature of `fix_global_phases`
pbrehmer Feb 4, 2026
c00129f
Fix `north_virtualspace` adjointness
pbrehmer Feb 4, 2026
76954b8
Change function argument order of `gauge_fix(env, ...)`
pbrehmer Feb 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "PEPSKit"
uuid = "52969e89-939e-4361-9b68-9bc7cde4bdeb"
authors = ["Paul Brehmer", "Lander Burgelman", "Lukas Devos <ldevos98@gmail.com>"]
version = "0.7.0"
authors = ["Paul Brehmer", "Lander Burgelman", "Lukas Devos <ldevos98@gmail.com>"]

[deps]
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
Expand Down
11 changes: 11 additions & 0 deletions src/Defaults.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,20 @@ const svd_rrule_alg = :full # ∈ {:full, :gmres, :bicgstab, :arnoldi}
const svd_rrule_broadening = 1.0e-13
const krylovdim_factor = 1.4

# eigh forward & reverse
const eigh_fwd_alg = :qriteration
const eigh_rrule_alg = :trunc
const eigh_rrule_verbosity = 0

# QR forward & reverse
# const qr_fwd_alg = :something # TODO
# const qr_rrule_alg = :something
# const qr_rrule_verbosity = :something

# Projectors
const projector_alg = :halfinfinite # ∈ {:halfinfinite, :fullinfinite}
const projector_verbosity = 0
const projector_alg_c4v = :c4v_eigh

# Fixed-point gradient
const gradient_tol = 1.0e-6
Expand Down
8 changes: 6 additions & 2 deletions src/PEPSKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ include("Defaults.jl") # Include first to allow for docstring interpolation wit

include("utility/util.jl")
include("utility/diffable_threads.jl")
include("utility/eigh.jl")
include("utility/svd.jl")
# include("utility/qr.jl")
include("utility/rotations.jl")
include("utility/hook_pullback.jl")
include("utility/autoopt.jl")
Expand All @@ -42,6 +44,8 @@ include("networks/infinitesquarenetwork.jl")
include("states/infinitepeps.jl")
include("states/infinitepartitionfunction.jl")

include("utility/symmetrization.jl")

include("operators/infinitepepo.jl")
include("operators/transfermatrix.jl")
include("operators/localoperator.jl")
Expand Down Expand Up @@ -71,6 +75,7 @@ include("algorithms/ctmrg/projectors.jl")
include("algorithms/ctmrg/simultaneous.jl")
include("algorithms/ctmrg/sequential.jl")
include("algorithms/ctmrg/gaugefix.jl")
include("algorithms/ctmrg/c4v.jl")

include("algorithms/truncation/truncationschemes.jl")
include("algorithms/truncation/fullenv_truncation.jl")
Expand All @@ -89,8 +94,6 @@ include("algorithms/transfermatrix.jl")
include("algorithms/toolbox.jl")
include("algorithms/correlators.jl")

include("utility/symmetrization.jl")

include("algorithms/optimization/fixed_point_differentiation.jl")
include("algorithms/optimization/peps_optimization.jl")

Expand All @@ -102,6 +105,7 @@ export SVDAdjoint, FullSVDReverseRule, IterSVD
export CTMRGEnv, SequentialCTMRG, SimultaneousCTMRG
export FixedSpaceTruncation, SiteDependentTruncation
export HalfInfiniteProjector, FullInfiniteProjector
export EighAdjoint, IterEigh, C4vCTMRG, C4vEighProjector, C4vQRProjector
export LocalOperator, physicalspace
export product_peps
export reduced_densitymatrix, expectation_value, network_value, cost_function
Expand Down
144 changes: 144 additions & 0 deletions src/algorithms/ctmrg/c4v.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
struct C4vCTMRG{P <: ProjectorAlgorithm} <: CTMRGAlgorithm
tol::Float64
maxiter::Int
miniter::Int
verbosity::Int
projector_alg::P
end
function C4vCTMRG(; kwargs...)
return CTMRGAlgorithm(; alg = :c4v, kwargs...)
end
CTMRG_SYMBOLS[:c4v] = C4vCTMRG

struct C4vEighProjector{S <: EighAdjoint, T} <: ProjectorAlgorithm
decomp_alg::S
trunc::T
verbosity::Int
end
function C4vEighProjector(; kwargs...)
return ProjectorAlgorithm(; alg = :c4v_eigh, kwargs...)
end
PROJECTOR_SYMBOLS[:c4v_eigh] = C4vEighProjector

# struct C4vQRProjector{S, T} <: ProjectorAlgorithm
# decomp_alg::S
# verbosity::Int
# end
# function C4vQRProjector(; kwargs...)
# return ProjectorAlgorithm(; alg = :c4v_qr, kwargs...)
# end
# PROJECTOR_SYMBOLS[:c4v_qr] = C4vQRProjector

#
## C4v-symmetric CTMRG iteration (called through `leading_boundary`)
#

function ctmrg_iteration(
network,
env::CTMRGEnv,
alg::C4vCTMRG,
)
enlarged_corner = c4v_enlarge(network, env, alg.projector_alg)
corner′, projector, info = c4v_projector(enlarged_corner, alg.projector_alg)
edge′ = c4v_renormalize(network, env, projector)
return CTMRGEnv(corner′, edge′), info
end

function c4v_enlarge(network, env, ::C4vEighProjector)
return TensorMap(EnlargedCorner(network, env, (NORTHWEST, 1, 1)))
end
# function c4v_enlarge(enlarged_corner, alg::C4vQRProjector)
# # TODO
# end

function c4v_projector(enlarged_corner, alg::C4vEighProjector)
hermitian_corner = 0.5 * (enlarged_corner + enlarged_corner') / norm(enlarged_corner)
trunc = truncation_strategy(alg, enlarged_corner)
D, U, info = eigh_trunc!(hermitian_corner, decomposition_algorithm(alg); trunc)

# Check for degenerate eigenvalues
Zygote.isderiving() && ignore_derivatives() do
if alg.verbosity > 0 && is_degenerate_spectrum(D)
vals = TensorKit.SectorDict(c => diag(b) for (c, b) in blocks(D))
@warn("degenerate eigenvalues detected: ", vals)
end
end

return D / norm(D), U, (; D, U, info...)
end
# function c4v_projector(enlarged_corner, alg::C4vQRProjector)
# # TODO
# end

function c4v_renormalize(network, env, projector)
new_edge = renormalize_north_edge(env.edges[1], projector, projector', network[1, 1])
return new_edge / norm(new_edge)
end
Comment on lines +142 to +146
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need to further project_hermitian the updated edge with respect to the two environment indices to eliminate numerical errors?

See also the QR-CTM code which does this step.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

BTW, I would add a leading underscore (_project_hermitian) to avoid conflict with MAK. But it's just my opinion...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In addition, do we have tests with fermions to see if project_hermitian for edges is correctly defined? I'm not quite confident on the usage of flip there unless it's proven correct.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good point, thanks! Probably doesn't make too much of a difference but it should stabilize the method.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

In addition, do we have tests with fermions to see if project_hermitian for edges is correctly defined? I'm not quite confident on the usage of flip there unless it's proven correct.

Good point, I'm also not sure if flip and _dag work for fermions right away. Would you have an idea for a quick test? (I wouldn't want to add too much more to this PR.)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's leave the fermions for a follow up, it will be easier to review what is going on that way.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The test idea is simple: create a random fermionic state with C4v, converge the environment with both C4v and asymmetric CTMRG, and evaluate the expectation value of a random operator, which should be the same for both cases. But frankly, I'm not even sure if the current symmetrize! plays nicely with permutation signs from FermionParity.


function CTMRGEnv(
corner::AbstractTensorMap{T, S, 1, 1}, edge::AbstractTensorMap{T′, S, N, 1}
) where {T, T′, S, N}
corners = fill(corner, 4, 1, 1)
edge_SW = physical_flip(edge)
edges = reshape([edge, edge, edge_SW, edge_SW], (4, 1, 1))
return CTMRGEnv(corners, edges)
end

#
## utility
#

# Adjoint of an edge tensor, but permutes the physical spaces back into the codomain.
# Intuitively, this conjugates a tensor and then reinterprets its 'direction' as an edge tensor.
function _dag(A::AbstractTensorMap{T, S, N, 1}) where {T, S, N}
return permute(A', ((1, (3:(N + 1))...), (2,)))
end
function physical_flip(A::AbstractTensorMap{T, S, N, 1}) where {T, S, N}
return flip(A, 2:N)
end
function project_hermitian(E::AbstractTensorMap{T, S, N, 1}) where {T, S, N}
Comment thread
pbrehmer marked this conversation as resolved.
Outdated
E´ = (E + physical_flip(_dag(E))) / 2
return E´
end
function project_hermitian(C::AbstractTensorMap{T, S, 1, 1}) where {T, S}
C´ = (C + C') / 2
return C´
end

# should perform this check at the beginning of `leading_boundary` really...
function check_symmetry(state, ::RotateReflect; atol = 1.0e-10)
@assert length(state) == 1 "check_symmetry only works for single site unit cells"
@assert norm(state[1] - _fit_spaces(rotl90(state[1]), state[1])) /
norm(state[1]) < atol "not rotation invariant"
@assert norm(state[1] - _fit_spaces(herm_depth(state[1]), state[1])) /
norm(state[1]) < atol "not hermitian-reflection invariant"
return nothing
end

#
## environment initialization
#

# TODO: rewrite this using `initialize_environment` and C4v-specific initialization algorithms
# environment with dummy corner singlet(V) ← singlet(V) and identity edge V ← V, initialized at dim(Venv)
# function initialize_singlet_c4v_env(Vpeps::ElementarySpace, Venv::ElementarySpace, T = ComplexF64)
# corner₀ = DiagonalTensorMap(zeros(real(T), Venv ← Venv))
# corner₀.data[1] = one(real(T))
# edge₀ = permute(id(T, Venv ⊗ Vpeps), ((1, 2, 4), (3,)))
# return CTMRGEnv(corner₀, edge₀)
# end

function initialize_random_c4v_env(Vstate::VectorSpace, Venv::ElementarySpace, T = ComplexF64)
corner₀ = DiagonalTensorMap(randn(real(T), Venv ← Venv))
edge₀ = randn(T, Venv ⊗ Vstate ← Venv)
edge₀ = project_hermitian(edge₀)
return CTMRGEnv(corner₀, edge₀)
end
function initialize_random_c4v_env(state::InfinitePEPS, Venv::ElementarySpace, T = scalartype(state))
Vpeps = domain(state[1])[1]
Comment thread
pbrehmer marked this conversation as resolved.
Outdated
return initialize_random_c4v_env(Vpeps ⊗ Vpeps', Venv, T)
end
function initialize_random_c4v_env(state::InfinitePartitionFunction, Venv::ElementarySpace, T = scalartype(state))
Vpf = domain(state[1])[1]
return initialize_random_c4v_env(Vpf, Venv, T)
end
10 changes: 6 additions & 4 deletions src/algorithms/ctmrg/ctmrg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,19 @@ function CTMRGAlgorithm(;
maxiter = Defaults.ctmrg_maxiter, miniter = Defaults.ctmrg_miniter,
verbosity = Defaults.ctmrg_verbosity,
trunc = (; alg = Defaults.trunc),
svd_alg = (;),
decomp_alg = (;),
projector_alg = Defaults.projector_alg, # only allows for Symbol/NamedTuple to expose projector kwargs
)
# replace symbol with projector alg type
haskey(CTMRG_SYMBOLS, alg) || throw(ArgumentError("unknown CTMRG algorithm: $alg"))
alg_type = CTMRG_SYMBOLS[alg]

# parse CTMRG projector algorithm

if alg == :c4v && projector_alg == Defaults.projector_alg
projector_alg = Defaults.projector_alg_c4v
end
projector_algorithm = ProjectorAlgorithm(;
alg = projector_alg, svd_alg, trunc, verbosity
alg = projector_alg, decomp_alg, trunc, verbosity
)

return alg_type(tol, maxiter, miniter, verbosity, projector_algorithm)
Expand Down Expand Up @@ -76,7 +78,7 @@ supplied via the keyword arguments or directly as an [`CTMRGAlgorithm`](@ref) st
- `:truncrank` : Additionally supply truncation dimension `η`; truncate such that the 2-norm of the truncated values is smaller than `η`
- `:truncspace` : Additionally supply truncation space `η`; truncate according to the supplied vector space
- `:trunctol` : Additionally supply singular value cutoff `η`; truncate such that every retained singular value is larger than `η`
* `svd_alg::Union{<:SVDAdjoint,NamedTuple}` : SVD algorithm for computing projectors. See also [`SVDAdjoint`](@ref). By default, a reverse-rule tolerance of `tol=1e1tol` where the `krylovdim` is adapted to the `env₀` environment dimension.
* `decomp_alg::Union{<:DecompositionAdjoint,NamedTuple}` : Tensor decomposition algorithm for computing projectors. See e.g. [`SVDAdjoint`](@ref).
* `projector_alg::Symbol=:$(Defaults.projector_alg)` : Variant of the projector algorithm. See also [`ProjectorAlgorithm`](@ref).
- `:halfinfinite` : Projection via SVDs of half-infinite (two enlarged corners) CTMRG environments.
- `:fullinfinite` : Projection via SVDs of full-infinite (all four enlarged corners) CTMRG environments.
Expand Down
90 changes: 86 additions & 4 deletions src/algorithms/ctmrg/gaugefix.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
"""
gauge_fix(alg::CTMRGAlgorithm, signs, info)
gauge_fix(alg::ProjectorAlgorithm, signs, info)

Fix the free gauges of the tensor decompositions associated with `alg`.
"""
function gauge_fix(alg::CTMRGAlgorithm, signs, info)
alg_fixed = @set alg.projector_alg = gauge_fix(alg.projector_alg, signs, info)
return alg_fixed
end
function gauge_fix(alg::ProjectorAlgorithm, signs, info)
decomp_alg_fixed = gauge_fix(decomposition_algorithm(alg), signs, info)
alg_fixed = @set alg.decomp_alg = decomp_alg_fixed # every ProjectorAlgorithm needs an `decomp_alg` field?
alg_fixed = @set alg_fixed.trunc = notrunc()
return alg_fixed
end

"""
$(TYPEDEF)

CTMRG environment gauge fixing algorithm implementing the "general" technique from
https://arxiv.org/abs/2311.11894. This works by constructing a transfer matrix consisting
of an edge tensor and a random MPS, thus scrambling potential degeneracies, and then
performing a QR decomposition to extract the gauge signs. This is adapted accordingly for
asymmetric CTMRG algorithms using multi-site unit cell transfer matrices.
"""
struct ScramblingEnvGauge end
Comment thread
lkdvos marked this conversation as resolved.

"""
$(TYPEDEF)

C4v-symmetric equivalent of the [ScramblingEnvGauge`](@ref) environment gauge fixing
algorithm.
"""
struct ScramblingEnvGaugeC4v end

"""
$(SIGNATURES)

Expand All @@ -6,15 +42,14 @@ This assumes that the `envfinal` is the result of one CTMRG iteration on `envpre
Given that the CTMRG run is converged, the returned environment will be
element-wise converged to `envprev`.
"""
function gauge_fix(envprev::CTMRGEnv{C, T}, envfinal::CTMRGEnv{C, T}) where {C, T}
function gauge_fix(envfinal::CTMRGEnv{C, T}, ::ScramblingEnvGauge, envprev::CTMRGEnv{C, T}) where {C, T}
Comment thread
lkdvos marked this conversation as resolved.
Outdated
# Check if spaces in envprev and envfinal are the same
same_spaces = map(eachcoordinate(envfinal, 1:4)) do (dir, r, c)
space(envfinal.edges[dir, r, c]) == space(envprev.edges[dir, r, c]) &&
space(envfinal.corners[dir, r, c]) == space(envprev.corners[dir, r, c])
end
@assert all(same_spaces) "Spaces of envprev and envfinal are not the same"

# Try the "general" algorithm from https://arxiv.org/abs/2311.11894
signs = map(eachcoordinate(envfinal, 1:4)) do (dir, r, c)
# Gather edge tensors and pretend they're InfiniteMPSs
if dir == NORTH
Expand Down Expand Up @@ -54,6 +89,42 @@ function gauge_fix(envprev::CTMRGEnv{C, T}, envfinal::CTMRGEnv{C, T}) where {C,
return fix_global_phases(envprev, CTMRGEnv(cornersfix, edgesfix)), signs
end

# C4v specialized gauge fixing routine with Hermitian transfer matrix
function gauge_fix(envfinal::CTMRGEnv{C, T}, ::ScramblingEnvGaugeC4v, envprev::CTMRGEnv{C, T}) where {C, T}
# Check if spaces in envprev and envfinal are the same
same_spaces = map(eachcoordinate(envfinal, 1:4)) do (dir, r, c)
space(envfinal.edges[dir, r, c]) == space(envprev.edges[dir, r, c]) &&
space(envfinal.corners[dir, r, c]) == space(envprev.corners[dir, r, c])
end
@assert all(same_spaces) "Spaces of envprev and envfinal are not the same"

# "general" algorithm from https://arxiv.org/abs/2311.11894
Tprev = envprev.edges[1, 1, 1]
Tfinal = envfinal.edges[1, 1, 1]

# Random Hermitian MPS of same bond dimension
# (make Hermitian such that T-M transfer matrix has real eigenvalues)
M = project_hermitian(randn(scalartype(Tfinal), space(Tfinal)))

# Find right fixed points of mixed transfer matrices
ρinit = randn(
scalartype(T), MPSKit._lastspace(Tfinal)' ← MPSKit._lastspace(M)'
)
ρprev = c4v_transfermatrix_fixedpoint(Tprev, M, ρinit)
ρfinal = c4v_transfermatrix_fixedpoint(Tfinal, M, ρinit)

# Decompose and multiply
Qprev, = left_orth!(ρprev)
Qfinal, = left_orth!(ρfinal)

σ = Qprev * Qfinal'

@tensor cornerfix[χ_in; χ_out] := σ[χ_in; χ1] * envfinal.corners[1][χ1; χ2] * conj(σ[χ_out; χ2])
@tensor edgefix[χ_in D_in_above D_in_below; χ_out] :=
σ[χ_in; χ1] * envfinal.edges[1][χ1 D_in_above D_in_below; χ2] * conj(σ[χ_out; χ2])
return CTMRGEnv(cornerfix, edgefix), fill(σ, (4, 1, 1))
end

# this is a bit of a hack to get the fixed point of the mixed transfer matrix
# because MPSKit is not compatible with AD
# NOTE: the action of the transfer operator here is NOT the same as that of
Expand Down Expand Up @@ -82,6 +153,13 @@ function transfermatrix_fixedpoint(tops, bottoms, ρinit)
end
return first(vecs)
end
function c4v_transfermatrix_fixedpoint(top, bottom, ρinit)
_, vecs, info = eigsolve(ρinit, 1, :LM, Lanczos()) do ρ
PEPSKit.mps_transfer_right(ρ, top, bottom)
end
info.converged > 0 || @warn "eigsolve did not converge"
return first(vecs)
end

# Explicit fixing of relative phases (doing this compactly in a loop is annoying)
function fix_relative_phases(envfinal::CTMRGEnv, signs)
Expand Down Expand Up @@ -168,8 +246,12 @@ end
Check if the element-wise difference of the corner and edge tensors of the final and fixed
CTMRG environments are below `atol` and return the maximal difference.
"""
function calc_elementwise_convergence(envfinal::CTMRGEnv, envfix::CTMRGEnv; atol::Real = 1.0e-6)
ΔC = envfinal.corners .- envfix.corners
function calc_elementwise_convergence(
envfinal::CTMRGEnv{C}, envfix::CTMRGEnv{C′}; atol::Real = 1.0e-6
) where {C, C′}
Cfinal = (C <: DiagonalTensorMap) ? convert.(TensorMap, envfinal.corners) : envfinal.corners
Comment thread
pbrehmer marked this conversation as resolved.
Cfix = (C′ <: DiagonalTensorMap) ? convert.(TensorMap, envfix.corners) : envfix.corners
ΔC = Cfinal .- Cfix
ΔCmax = norm(ΔC, Inf)
ΔCmean = norm(ΔC)
@debug "maxᵢⱼ|Cⁿ⁺¹ - Cⁿ|ᵢⱼ = $ΔCmax mean |Cⁿ⁺¹ - Cⁿ|ᵢⱼ = $ΔCmean"
Expand Down
Loading
Loading