Skip to content

Commit 7d2e555

Browse files
Implement StructuredVector for storing scaling dimensions (#185)
* Implement `StructuredVector` for storing scaling dimensions * fix include statement * fix bug * remove Adwait AI slop I'm losing the battle against entropy * small changes * fix typo
1 parent fa03f3f commit 7d2e555

7 files changed

Lines changed: 62 additions & 55 deletions

File tree

docs/src/cft.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ The `CFTData` struct has two fields:
2626
- `scaling_dimensions`
2727

2828
The `central_charge` can be either `missing` (when using the $[1, 1, 0]$ shape), or a number.
29-
The `scaling_dimensions` field is a `SectorVector` from TensorKit.jl.
29+
The `scaling_dimensions` field is a `StructuredVector`.
3030

3131
The `scaling_dimensions` can be indexed like an `AbstractVector` (i.e. with scalars, slices, ...), or with sectors (e.g. `Z2Irrep(0)`), which will provide the scaling dimensions associated with that sector/charge.
3232
To check which sectors you can index the `scaling_dimensions` with you can use `keys(scaling_dimensions)`.

src/TNRKit.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ include("schemes/correlationhotrg.jl")
5252

5353
#Thermal TNR
5454
include("schemes/ttnr.jl")
55+
5556
# Loop Methods
5657
include("schemes/looptnr.jl")
5758
include("schemes/symmetric_looptnr.jl")
@@ -124,6 +125,8 @@ export phi4_complex, phi4_complex_impϕ, phi4_complex_impϕdag, phi4_complex_imp
124125
include("utility/free_energy.jl")
125126
export free_energy
126127

128+
include("utility/structuredvector.jl")
129+
127130
include("utility/cft.jl")
128131
export CFTData, central_charge
129132

@@ -145,4 +148,5 @@ include("utility/blocking.jl")
145148
export block_tensors
146149

147150
include("utility/network_value.jl")
151+
148152
end

src/models/clock.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,3 @@ function ZN_gauge_theory_dual(N::Int, β::Real; T::Type{<:Number} = ComplexF64)
148148
symmetric_space symmetric_space symmetric_space_dual symmetric_space_dual,
149149
)
150150
end
151-
152-
ZN_gaugetheory_dual(N::Int, β::Real; kwargs...) = ZN_gauge_theory_dual(N, β; kwargs...)

src/models/ising.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ function ising_3D_free_energy_htse(β::Real; J::Real = 1.0, max_order::Int = 24)
5555
f -= series / β
5656
return f
5757
end
58-
ising_3d_free_energy_htse(; kwargs...) = ising_3D_free_energy_htse(ising_βc_3D; kwargs...)
58+
ising_3D_free_energy_htse(; kwargs...) = ising_3D_free_energy_htse(ising_βc_3D; kwargs...)
5959

6060
"""
6161
ising_bond_tensor(β::Real, T::Type{<:Number})

src/utility/cft.jl

Lines changed: 10 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,3 @@
1-
# Extensions on top of TensorKit.SectorVector
2-
Base.broadcasted(f, v::TensorKit.SectorVector) = TensorKit.SectorVector(broadcast(f, parent(v)), v.structure)
3-
Base.broadcasted(f, v::TensorKit.SectorVector, a) = TensorKit.SectorVector(broadcast(f, parent(v), a), v.structure)
4-
Base.broadcasted(f, a, v::TensorKit.SectorVector) = TensorKit.SectorVector(broadcast(f, a, parent(v)), v.structure)
5-
function Base.broadcasted(f, v1::TensorKit.SectorVector, v2::TensorKit.SectorVector)
6-
if v1.structure != v2.structure
7-
throw(ArgumentError("Cannot broadcast two SectorVectors with different structures"))
8-
end
9-
return TensorKit.SectorVector(broadcast(f, parent(v1), parent(v2)), v1.structure)
10-
end
11-
12-
function Base.filter(f, v::TensorKit.SectorVector)
13-
data = copy(parent(v))
14-
structure = copy(v.structure)
15-
16-
kept_inds = findall(f, parent(v))
17-
sectors = keys(structure)
18-
for (i, sector) in enumerate(sectors)
19-
structure[sector] = i == 1 ? (1:findlast(x -> x <= structure[sector].stop, kept_inds)) : ((structure[sectors[i - 1]].stop + 1):findlast(x -> x <= structure[sector].stop, kept_inds))
20-
end
21-
data = data[kept_inds]
22-
return TensorKit.SectorVector(data, structure)
23-
end
24-
25-
function Base.sort(v::TensorKit.SectorVector; kwargs...)
26-
# sort within the sectors, then concatenate the data and update the structure
27-
# Ideally this would sort the total data, but sectorvectors are only compatible with
28-
# structures that contain unitranges, we cannot interweave the data of different sectors.
29-
data = copy(parent(v))
30-
newdata = similar(data)
31-
structure = copy(v.structure)
32-
sectors = keys(structure)
33-
for sector in sectors
34-
newdata[structure[sector]] = sort(data[structure[sector]]; kwargs...)
35-
end
36-
return TensorKit.SectorVector(newdata, structure)
37-
end
38-
39-
Base.:*(a::Number, v::TensorKit.SectorVector) = scale(v, a)
40-
Base.:*(v::TensorKit.SectorVector, a::Number) = scale(v, a)
41-
421
"""
432
CFTData{E, I} where {E, I}
443
@@ -51,15 +10,15 @@ A struct to hold conformal data extracted from a TNR scheme.
5110
5211
# Fields
5312
- `central_charge::Union{E, Missing}`: The central charge of the CFT. Will be `nothing` if not calculated.
54-
- `scaling_dimensions::TensorKit.SectorVector{E, I}`: The scaling dimensions of the CFT, organized in a `TensorKit.SectorVector` where the sectors correspond to different spin sectors (or other quantum numbers) and the data contains the scaling dimensions within those sectors
13+
- `scaling_dimensions::StructuredVector{E, K, V, A}`: The scaling dimensions of the CFT, organized in a `StructuredVector` where the sectors correspond to different spin sectors (or other quantum numbers) and the data contains the scaling dimensions within those sectors
5514
5615
"""
57-
struct CFTData{E, I}
16+
struct CFTData{E, K, V, A <: AbstractVector{E}}
5817
"Central charge of the CFT. Will be `nothing` if not calculated."
5918
central_charge::Union{E, Missing}
6019

6120
"Scaling dimensions of the CFT."
62-
scaling_dimensions::TensorKit.SectorVector{E, I}
21+
scaling_dimensions::StructuredVector{E, K, V, A}
6322
end
6423

6524
function Base.show(io::IO, data::CFTData)
@@ -71,7 +30,8 @@ end
7130

7231
function CFTData(T::TensorMap{E, S, 2, 2}; shape = [sqrt(2), 2 * sqrt(2), 0], kwargs...) where {E, S}
7332
if shape == [1, 1, 0] # trivial implementation
74-
return CFTData(missing, _scaling_dimensions(T))
33+
scaling_dimensions = _scaling_dimensions(T)
34+
return CFTData(missing, StructuredVector(scaling_dimensions, Dict([Trivial => collect(eachindex(scaling_dimensions))])))
7535
else
7636
CFTData(T, T; shape, kwargs...)
7737
end
@@ -199,23 +159,23 @@ function spec(TA::TensorMap, TB::TensorMap, shape::Array; Nh = 25)
199159
norm_const_0 = spec_sector[one(I)][1]
200160
central_charge = 6 / pi / (Imτ - area / 4) * log(norm_const_0)
201161

202-
# Construct a SectorVector from the data of the different sectors
162+
# Construct a StructuredVector from the data of the different sectors
203163
data = ComplexF64[]
204-
structure = TensorKit.SectorDict{sectortype(xspace), UnitRange{Int}}()
164+
structure = Dict{eltype(sectors(fuse(xspace))), Vector{Int}}()
205165
last_index = 1
206166
for charge in sectors(fuse(xspace))
207167
DeltaS = -1 / (2 * pi * Imτ) * log.(spec_sector[charge] / norm_const_0)
208168
if !(relative_shift 0)
209169
push!(data, (real.(DeltaS) + imag.(DeltaS) / relative_shift * im)...)
210-
structure[charge] = last_index:(last_index + length(DeltaS) - 1)
170+
structure[charge] = [last_index:(last_index + length(DeltaS) - 1)...]
211171
else
212172
push!(data, real.(DeltaS)...)
213-
structure[charge] = last_index:(last_index + length(DeltaS) - 1)
173+
structure[charge] = [last_index:(last_index + length(DeltaS) - 1)...]
214174
end
215175
last_index += length(DeltaS)
216176
end
217177

218-
sv = TensorKit.SectorVector(data, structure)
178+
sv = StructuredVector(data, structure)
219179
sv = sort(sv; by = real)
220180
sv = filter(x -> real(x) 1.0e16, sv)
221181

src/utility/structuredvector.jl

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
struct StructuredVector{E, K, V, A <: AbstractVector{E}} <: AbstractVector{E}
2+
data::A
3+
structure::Dict{K, V}
4+
end
5+
6+
@inline Base.getindex(v::StructuredVector, i::Int) = getindex(parent(v), i)
7+
@inline Base.getindex(v::StructuredVector{E, K}, keys::K) where {E, K} = parent(v)[v.structure[keys]]
8+
@inline Base.setindex!(v::StructuredVector, val, i::Int) = setindex!(parent(v), val, i)
9+
10+
Base.size(v::StructuredVector, args...) = size(parent(v), args...)
11+
Base.size(v::StructuredVector) = size(parent(v))
12+
Base.copy(v::StructuredVector) = StructuredVector(copy(v.data), v.structure)
13+
Base.parent(v::StructuredVector) = v.data
14+
15+
function Base.sort(v::StructuredVector; kwargs...)
16+
p = sortperm(v.data; kwargs...)
17+
inv_p = invperm(p)
18+
newdict = Dict(k => sort(inv_p[v.structure[k]]) for k in keys(v.structure))
19+
return StructuredVector(v.data[p], newdict)
20+
end
21+
22+
function Base.filter(f, v::StructuredVector)
23+
kept_inds = findall(f, parent(v))
24+
data = parent(v)[kept_inds]
25+
old_to_new = Dict(old_ind => new_ind for (new_ind, old_ind) in enumerate(kept_inds))
26+
27+
new_structure = Dict{keytype(v.structure), Vector{Int}}()
28+
for (sector, inds) in v.structure
29+
new_structure[sector] = [old_to_new[ind] for ind in inds if haskey(old_to_new, ind)]
30+
end
31+
32+
return StructuredVector(data, new_structure)
33+
end
34+
35+
function Base.show(io::IO, v::StructuredVector)
36+
println(io, "StructuredVector with keys: ", keys(v.structure))
37+
return print(io, "Data: ", v.data)
38+
end
39+
40+
Base.:*(v::StructuredVector, x::Number) = StructuredVector(v.data .* x, v.structure)
41+
Base.:*(x::Number, v::StructuredVector) = StructuredVector(x .* v.data, v.structure)
42+
Base.:/(v::StructuredVector, x::Number) = StructuredVector(v.data ./ x, v.structure)
43+
Base.:/(x::Number, v::StructuredVector) = StructuredVector(x ./ v.data, v.structure)
44+
45+
Base.keys(v::StructuredVector) = keys(v.structure)

test/schemes/schemes.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ println("---------------------")
99

1010
T = classical_ising()
1111
T_3D = classical_ising_3D()
12-
const f_benchmark3D = ising_3D_free_energy_htse(ising_βc_3D)
12+
const f_benchmark3D = ising_3D_free_energy_htse()
1313

1414
function cft_finalize!(scheme)
1515
finalize!(scheme)

0 commit comments

Comments
 (0)