Skip to content

Commit a0bc181

Browse files
Change c4CMT to c4vCTM and make it compatible with fermions. (#112)
* Fix c4CTM for fermions * fix fermionic test Fix scalefactor * update C4CTM test flip was forgotten for the Ising test * format fix * change arrow convention * formatting * name change * add docs * Update src/schemes/ctm/c4vctm.jl Co-authored-by: Victor Vanthilt <73738005+VictorVanthilt@users.noreply.github.com> * add some documentation * change c4ctm to c4vtm in docs and readme --------- Co-authored-by: Victor Vanthilt <73738005+VictorVanthilt@users.noreply.github.com>
1 parent 191a55c commit a0bc181

7 files changed

Lines changed: 207 additions & 131 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ The following schemes are currently implemented:
3333
- SLoopTNR (C4 & inversion symmetric LoopTNR)
3434
- ctm_HOTRG (Corner Transfer Matrix environment + HOTRG)
3535
- ctm_TRG (Corner Transfer Matrix environment + TRG)
36-
- c4CTM (c4 symmetric CTM)
36+
- c4vCTM (c4v symmetric CTM)
3737
- rCTM (reflection symmetric CTM)
3838

3939
This project is under active development. The interface is subject to changes. Any feedback about the user interface or the internals is much appreciated. The github discussions page is a great place to talk!

docs/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Many common TNR schemes have already been implemented:
2323
**CTM methods (yet to be documented)**
2424
* `ctm_TRG` (Corner Transfer Matrix environment + TRG)
2525
* `ctm_HOTRG` (Corner Transfer Matrix environment + HOTRG)
26-
* `c4CTM` (c4 symmetric CTM)
26+
* `c4vCTM` (c4v symmetric CTM)
2727
* `rCTM` (reflection symmetric CTM)
2828

2929
**3D cubic tensor networks**

src/TNRKit.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ include("schemes/atrg.jl")
2222
include("schemes/atrg3d.jl")
2323
# CTM methods
2424
include("schemes/ctm/utility.jl")
25-
include("schemes/ctm/c4ctm.jl")
25+
include("schemes/ctm/c4vctm.jl")
2626
include("schemes/ctm/rctm.jl")
2727
include("schemes/ctm/ctm_trg.jl")
2828
include("schemes/ctm/ctm_hotrg.jl")
@@ -49,7 +49,7 @@ export ATRG_3D
4949

5050
export CTM
5151
export Sublattice_CTM
52-
export c4CTM
52+
export c4vCTM
5353
export rCTM
5454
export ctm_TRG
5555
export ctm_HOTRG

src/schemes/ctm/c4ctm.jl

Lines changed: 0 additions & 123 deletions
This file was deleted.

src/schemes/ctm/c4vctm.jl

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
"""
2+
$(TYPEDEF)
3+
4+
C4v symmetric Corner Transfer Matrix Renormalization Group
5+
6+
### Constructors
7+
$(FUNCTIONNAME)(T)
8+
$(FUNCTIONNAME)(T, [, symmetrize=false])
9+
10+
c4vCTM can be called with a (2,2) tensor (West, South, North, East) with the usual arrow conventions (flipped arrow convention),
11+
or with a (0,4) tensor (North, East, South, West) (unflipped arrow convention).
12+
The keyword argument symmetrize makes the tensor C4v symmetric when set to true. If symmetrize = false, it checks the symmetry explicitly.
13+
14+
### Running the algorithm
15+
run!(::c4vCTM, trunc::TensorKit.TruncationSheme, stop::Stopcrit[, finalize_beginning=true, verbosity=1])
16+
17+
!!! info "verbosity levels"
18+
- 0: No output
19+
- 1: Print information at start and end of the algorithm
20+
- 2: Print information at each step
21+
22+
### Fields
23+
24+
$(TYPEDFIELDS)
25+
"""
26+
mutable struct c4vCTM{A, S}
27+
T::TensorMap{A, S, 0, 4}
28+
C::TensorMap{A, S, 1, 1}
29+
E::TensorMap{A, S, 2, 1}
30+
31+
function c4vCTM(T::TensorMap{A, S, 0, 4}) where {A, S}
32+
C, E = c4vCTM_init(T)
33+
34+
return new{A, S}(T, C, E)
35+
end
36+
end
37+
38+
function c4vCTM(T_flipped::TensorMap{A, S, 2, 2}; symmetrize = false) where {A, S}
39+
T_unflipped = permute(flip(T_flipped, (1, 2); inv = true), ((), (3, 4, 2, 1)))
40+
if symmetrize
41+
T_unflipped = symmetrize_C4v(T_unflipped)
42+
else
43+
@assert norm(T_flipped - T_flipped') < 1.0e-14
44+
@assert norm(T_unflipped - rotl90_pf(T_unflipped)) < 1.0e-14
45+
end
46+
return c4vCTM(T_unflipped)
47+
end
48+
49+
# Functions to permute (flipped and unflipped) tensors under 90 degree rotation
50+
function rotl90_pf(T::TensorMap{A, S, 2, 2}) where {A, S}
51+
return permute(T, ((3, 1), (4, 2)))
52+
end
53+
54+
function rotl90_pf(T::TensorMap{A, S, 0, 4}) where {A, S}
55+
return permute(T, ((), (2, 3, 4, 1)))
56+
end
57+
58+
# Function to construct a C4v symmetric tensor from a given tensor in the unflipped arrow convention
59+
function symmetrize_C4v(T_unflipped)
60+
T_c4_unflipped = (T_unflipped + rotl90_pf(T_unflipped) + rotl90_pf(rotl90_pf(T_unflipped)) + rotl90_pf(rotl90_pf(rotl90_pf(T_unflipped)))) / 4
61+
T_c4_flipped = permute(flip(T_c4_unflipped, (3, 4); inv = false), ((4, 3), (1, 2)))
62+
T_c4v_flipped = (T_c4_flipped + T_c4_flipped') / 2
63+
T_c4v_unflipped = permute(flip(T_c4v_flipped, (1, 2); inv = true), ((), (3, 4, 2, 1)))
64+
return T_c4v_unflipped
65+
end
66+
67+
# Below, I wrote a code with the following correspondence. (O,C,T) <=> (scheme.T, scheme.C, scheme.E)
68+
# https://www.issp.u-tokyo.ac.jp/public/caqmp2019/slides/808L_Okubo.pdf
69+
#=
70+
┌───────┐ ┌───────┐
71+
│ │ │ │
72+
│ │ │ │
73+
│ C ├──────►│ E ├──────►
74+
│ │ │ │
75+
└───────┘ └───────┘
76+
▲ ▲
77+
│ │
78+
│ │
79+
=#
80+
81+
function run!(
82+
scheme::c4vCTM, trunc::TensorKit.TruncationScheme, criterion::stopcrit;
83+
verbosity = 1
84+
)
85+
LoggingExtras.withlevel(; verbosity) do
86+
@infov 1 "Starting simulation\n $(scheme)\n"
87+
steps = 0
88+
crit = true
89+
ε = Inf
90+
S_prev = id(domain(scheme.C))
91+
92+
t = @elapsed while crit
93+
@infov 2 "Step $(steps + 1), ε = $(ε)"
94+
95+
S = step!(scheme, trunc)
96+
97+
if space(S) == space(S_prev)
98+
ε = norm(S^4 - S_prev^4)
99+
end
100+
101+
S_prev = S
102+
103+
steps += 1
104+
crit = criterion(steps, ε)
105+
end
106+
107+
@infov 1 "Simulation finished\n $(stopping_info(criterion, steps, ε))\n Elapsed time: $(t)s\n Iterations: $steps"
108+
end
109+
return lnz(scheme)
110+
end
111+
112+
function step!(scheme::c4vCTM, trunc)
113+
mat, U, S = find_U_sym(scheme, trunc)
114+
115+
@tensor scheme.C[-1; -2] := mat[1 2; 3 4] * U[3 4; -2] * conj(U[1 2; -1])
116+
@tensor scheme.E[-1 -2; -3] := scheme.E[1 5; 3] * flip(scheme.T, (3, 4); inv = true)[5 4 -2 2] *
117+
U[3 4; -3] *
118+
conj(U[1 2; -1])
119+
120+
scheme.C /= norm(scheme.C)
121+
scheme.E /= norm(scheme.E)
122+
return S
123+
end
124+
125+
function lnz(scheme::c4vCTM)
126+
Z, env = tensor2env(permute(flip(scheme.T, (3, 4); inv = true), ((4, 3), (1, 2))), scheme.C, scheme.E)
127+
# should be inv = false ??
128+
return real(log(network_value(Z, env)))
129+
end
130+
131+
function build_corner_matrix(scheme)
132+
@tensor opt = true mat[-1 -2; -3 -4] := scheme.C[1; 2] * scheme.E[-1 3; 1] *
133+
scheme.E[2 4; -3] *
134+
flip(scheme.T, 3; inv = true)[4 -4 -2 3]
135+
return mat
136+
end
137+
138+
function find_U_sym(scheme, trunc)
139+
mat = build_corner_matrix(scheme)
140+
# avoid symmetry breaking due to numerical accuracy
141+
mat = 0.5 * (mat + adjoint(mat))
142+
143+
U, S, _ = tsvd(mat; trunc = trunc & truncbelow(1.0e-20))
144+
return mat, U, S
145+
end
146+
147+
function c4vCTM_init(T::TensorMap{A, S, 0, 4}) where {A, S}
148+
S_type = scalartype(T)
149+
Vp = space(T)[1]'
150+
C = TensorMap(ones, S_type, oneunit(Vp) oneunit(Vp))
151+
E = TensorMap(ones, S_type, oneunit(Vp) Vp oneunit(Vp))
152+
return C, E
153+
end
154+
155+
function tensor2env(O, C, T)
156+
Z = InfinitePartitionFunction(O)
157+
env = CTMRGEnv(Z, space(C)[1])
158+
159+
for i in 1:4
160+
env.corners[i] = C
161+
env.edges[i] = T
162+
end
163+
164+
env.edges[3] = flip(T, 2)
165+
env.edges[4] = flip(T, 2)
166+
return Z, env
167+
end
168+
169+
function Base.show(io::IO, scheme::c4vCTM)
170+
println(io, "c4vCTM - C4v symmetric Corner Transfer Matrix")
171+
println(io, " * T: $(summary(scheme.T))")
172+
println(io, " * C: $(summary(scheme.C))")
173+
println(io, " * E: $(summary(scheme.E))")
174+
return nothing
175+
end

test/fermions.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,27 @@ end
3535
data = run!(scheme, truncdim(8), maxiter(10))
3636
@test free_energy(data, 1.0) f_bench rtol = 1.0e-3
3737
end
38+
39+
# === c4vCTM ===
40+
@testset "c4vCTM - Gross-Neveu Model" begin
41+
# Use the Gross-Neveu model, but symmetrize the tensor such that the conditions of C4vCTM are satisfied
42+
T_flipped = gross_neveu_start(0, 0, 0)
43+
T_unflipped = permute(flip(T_flipped, (1, 2); inv = true), ((), (3, 4, 2, 1)))
44+
T_unflipped_C4v = TNRKit.symmetrize_C4v(T_unflipped)
45+
T_flipped_C4v = permute(flip(T_unflipped_C4v, (3, 4); inv = false), ((4, 3), (1, 2)))
46+
47+
# Check symmetries
48+
49+
β = 1.0
50+
51+
# Calculate the free energy using c4vCTM
52+
data_c4vCTM = run!(c4vCTM(T_flipped_C4v), truncdim(8), maxiter(10))
53+
free_energy_c4vCTM = -data_c4vCTM / β
54+
55+
schemes = [TRG, BTRG, HOTRG, ATRG, LoopTNR]
56+
for scheme in schemes
57+
data = run!(scheme(T_flipped_C4v), truncdim(8), maxiter(10))
58+
scalefactor = scheme [HOTRG, ATRG] ? 4.0 : 2.0
59+
@test free_energy_c4vCTM free_energy(data, β; scalefactor) rtol = 1.0e-10
60+
end
61+
end

test/schemes.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,10 @@ end
166166
@test fs f_onsager rtol = 2.0e-5
167167
end
168168

169-
# c4CTM
170-
@testset "c4CTM - Ising Model" begin
171-
@info "c4CTM ising free energy"
172-
scheme = c4CTM(T)
169+
# c4vCTM
170+
@testset "c4vCTM - Ising Model" begin
171+
@info "c4vCTM ising free energy"
172+
scheme = c4vCTM(T)
173173
lz = run!(scheme, truncdim(24), trivial_convcrit(1.0e-9); verbosity = 1)
174174

175175
fs = lz * -1 / ising_βc

0 commit comments

Comments
 (0)