Skip to content

Commit 87ae76e

Browse files
committed
Renormalized tensors before projections
* Renormalize corner tensors * Define the general compute_projector given left and right tensors on the bonds. * Modified sequential_projectors and simultaneous_projectors accordingly. * Define a help function ⊙(t1::AbstractTensorMap, t2::AbstractTensorMap)=twist(t1, filter(i -> !isdual(space(t1, i)), domainind(t1)))*t2
1 parent dd439e2 commit 87ae76e

4 files changed

Lines changed: 55 additions & 46 deletions

File tree

src/algorithms/ctmrg/projectors.jl

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,29 @@ end
6666
@non_differentiable _condition_number(S::AbstractTensorMap)
6767

6868
"""
69-
compute_projector(enlarged_corners, coordinate, alg::ProjectorAlgorithm)
70-
71-
Determine left and right projectors at the bond given determined by the enlarged corners
72-
and the given coordinate using the specified `alg`.
73-
"""
74-
function compute_projector(enlarged_corners, coordinate, alg::HalfInfiniteProjector)
75-
# SVD half-infinite environment
76-
halfinf = half_infinite_environment(enlarged_corners...)
77-
svd_alg = svd_algorithm(alg, coordinate)
78-
U, S, V, truncation_error = PEPSKit.tsvd!(halfinf, svd_alg; trunc=alg.trscheme)
69+
compute_projector(L::AbstractTensorMap, R::AbstractTensorMap, svd_alg, alg)
70+
71+
Given the bond connecting the left and right tensors, e.g. L and R, we compute the projectors on the bond.
72+
This is a general algorithm that can be used for any bond. The only thing you need worry about
73+
is the left and right tensors. After the projection, the arrow of the bond is now (L⊙P_L)←(P_R⊙R).
74+
75+
```
76+
L⊙R=(L⊙R)*(L⊙R)^-1*(L⊙R)=(L⊙R)*(U*S*V)^-1*(L⊙R)=(L⊙R)*V'S^{-1}U'*(L⊙R)=L⊙(R*V'*S^{-1/2})*(S^{-1/2}*U'*L)⊙R=L⊙P_L*P_R⊙R
77+
```
78+
"""
79+
#help function for the projection, particularly for the sign of fermions
80+
(t1::AbstractTensorMap, t2::AbstractTensorMap)=twist(t1, filter(i -> !isdual(space(t1, i)), domainind(t1)))*t2
81+
82+
function compute_projector(L::AbstractTensorMap, R::AbstractTensorMap, svd_alg, alg)
83+
if dim(codomain(L)) > dim(domain(L))
84+
_,L= leftorth!(L)
85+
R,_=rightorth!(R)
86+
end
87+
LR=LR
88+
n_factor=norm(LR)
89+
LR=LR/n_factor
90+
91+
U, S, V, truncation_error = PEPSKit.tsvd!(LR, svd_alg; trunc=alg.trscheme)
7992

8093
# Check for degenerate singular values
8194
Zygote.isderiving() && ignore_derivatives() do
@@ -85,29 +98,14 @@ function compute_projector(enlarged_corners, coordinate, alg::HalfInfiniteProjec
8598
end
8699
end
87100

88-
P_left, P_right = contract_projectors(U, S, V, enlarged_corners...)
101+
norm_factor = sqrt(n_factor)
102+
isqS = sdiag_pow(S, -0.5)
103+
PL = R * V' * isqS / norm_factor
104+
PR = isqS * U' * L / norm_factor
105+
89106
truncation_error /= norm(S)
90-
condition_number = @ignore_derivatives(_condition_number(S))
91-
return (P_left, P_right), (; truncation_error, condition_number, U, S, V)
92-
end
93-
function compute_projector(enlarged_corners, coordinate, alg::FullInfiniteProjector)
94-
halfinf_left = half_infinite_environment(enlarged_corners[1], enlarged_corners[2])
95-
halfinf_right = half_infinite_environment(enlarged_corners[3], enlarged_corners[4])
96-
97-
# SVD full-infinite environment
98-
fullinf = full_infinite_environment(halfinf_left, halfinf_right)
99-
svd_alg = svd_algorithm(alg, coordinate)
100-
U, S, V, truncation_error = PEPSKit.tsvd!(fullinf, svd_alg; trunc=alg.trscheme)
101-
102-
# Check for degenerate singular values
103-
Zygote.isderiving() && ignore_derivatives() do
104-
if alg.verbosity > 0 && is_degenerate_spectrum(S)
105-
svals = TensorKit.SectorDict(c => diag(b) for (c, b) in blocks(S))
106-
@warn("degenerate singular values detected: ", svals)
107-
end
107+
condition_number = ignore_derivatives() do
108+
_condition_number(S)
108109
end
109-
110-
P_left, P_right = contract_projectors(U, S, V, halfinf_left, halfinf_right)
111-
condition_number = @ignore_derivatives(_condition_number(S))
112-
return (P_left, P_right), (; truncation_error, condition_number, U, S, V)
110+
return (PL, PR), (; truncation_error, condition_number, U, S, V)
113111
end

src/algorithms/ctmrg/sequential.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ function sequential_projectors(
9090
r′ = _prev(r, size(env, 2))
9191
Q1 = TensorMap(EnlargedCorner(network, env, (SOUTHWEST, r, c)), SOUTHWEST)
9292
Q2 = TensorMap(EnlargedCorner(network, env, (NORTHWEST, r′, c)), NORTHWEST)
93-
return compute_projector((Q1, Q2), coordinate, alg)
93+
94+
svd_alg = svd_algorithm(alg, coordinate)
95+
96+
return compute_projector(Q1, Q2, svd_alg, alg)
9497
end
9598
function sequential_projectors(
9699
coordinate::NTuple{3,Int}, network, env::CTMRGEnv, alg::FullInfiniteProjector
@@ -105,9 +108,12 @@ function sequential_projectors(
105108
TensorMap(EnlargedCorner(network, env, coordinate_nw), NORTHWEST),
106109
TensorMap(EnlargedCorner(network, env, coordinate_ne), NORTHEAST),
107110
)
108-
return compute_projector(ec, coordinate, alg)
111+
svd_alg = svd_algorithm(alg, coordinate)
112+
Q1, Q2 = ec[1]ec[2], ec[3]ec[4]
113+
return compute_projector(Q1, Q2, svd_alg, alg)
109114
end
110115

116+
111117
"""
112118
renormalize_sequentially(col::Int, projectors, network, env)
113119

src/algorithms/ctmrg/simultaneous.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ function simultaneous_projectors(
7777
) where {E}
7878
coordinate′ = _next_coordinate(coordinate, size(enlarged_corners)[2:3]...)
7979
ec = (enlarged_corners[coordinate...], enlarged_corners[coordinate′...])
80-
return compute_projector(ec, coordinate, alg)
80+
svd_alg = svd_algorithm(alg, coordinate)
81+
82+
return compute_projector(ec[1], ec[2], svd_alg, alg)
8183
end
8284
function simultaneous_projectors(
8385
coordinate, enlarged_corners::Array{E,3}, alg::FullInfiniteProjector
@@ -92,7 +94,9 @@ function simultaneous_projectors(
9294
enlarged_corners[coordinate2...],
9395
enlarged_corners[coordinate3...],
9496
)
95-
return compute_projector(ec, coordinate, alg)
97+
svd_alg = svd_algorithm(alg, coordinate)
98+
Q1, Q2 = ec[1]ec[2], ec[3]ec[4]
99+
return compute_projector(Q1, Q2, svd_alg, alg)
96100
end
97101

98102
"""

src/algorithms/ctmrg/sparse_environments.jl

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,16 @@ Instantiate enlarged corner as `TensorMap` where `dir` selects the correct contr
6060
direction, i.e. the way the environment and PEPS tensors connect.
6161
"""
6262
function TensorKit.TensorMap(Q::EnlargedCorner, dir::Int)
63-
if dir == NORTHWEST
64-
return enlarge_northwest_corner(Q.E_1, Q.C, Q.E_2, Q.A)
65-
elseif dir == NORTHEAST
66-
return enlarge_northeast_corner(Q.E_1, Q.C, Q.E_2, Q.A)
67-
elseif dir == SOUTHEAST
68-
return enlarge_southeast_corner(Q.E_1, Q.C, Q.E_2, Q.A)
69-
elseif dir == SOUTHWEST
70-
return enlarge_southwest_corner(Q.E_1, Q.C, Q.E_2, Q.A)
71-
end
63+
corner_functions = Dict(
64+
NORTHWEST => enlarge_northwest_corner,
65+
NORTHEAST => enlarge_northeast_corner,
66+
SOUTHEAST => enlarge_southeast_corner,
67+
SOUTHWEST => enlarge_southwest_corner
68+
)
69+
70+
haskey(corner_functions, dir) || error("Wrong direction: $dir")
71+
corner = corner_functions[dir](Q.E_1, Q.C, Q.E_2, Q.A)
72+
return corner / norm(corner)
7273
end
7374

7475
function renormalize_northwest_corner(ec::EnlargedCorner, P_left, P_right)

0 commit comments

Comments
 (0)