@@ -126,6 +126,42 @@ function _contract_edge_expr(rowrange, colrange)
126126 return edges_N, edges_E, edges_S, edges_W
127127end
128128
129+ function _contract_pf_edge_expr(rowrange, colrange)
130+ rmin, rmax = extrema(rowrange)
131+ cmin, cmax = extrema(colrange)
132+ gridsize = (rmax - rmin + 1 , cmax - cmin + 1 )
133+
134+ edges_N = map(1 : gridsize[2 ]) do i
135+ E_N = :(env. edges[NORTH, mod1($ (rmin - 1 ), end ), mod1($ (cmin + i - 1 ), end )])
136+ return tensorexpr(
137+ E_N, (envlabel(NORTH, i - 1 ), virtuallabel(NORTH, i)), envlabel(NORTH, i)
138+ )
139+ end
140+
141+ edges_E = map(1 : gridsize[1 ]) do i
142+ E_E = :(env. edges[EAST, mod1($ (rmin + i - 1 ), end ), mod1($ (cmax + 1 ), end )])
143+ return tensorexpr(
144+ E_E, (envlabel(EAST, i - 1 ), virtuallabel(EAST, i)), envlabel(EAST, i)
145+ )
146+ end
147+
148+ edges_S = map(1 : gridsize[2 ]) do i
149+ E_S = :(env. edges[SOUTH, mod1($ (rmax + 1 ), end ), mod1($ (cmin + i - 1 ), end )])
150+ return tensorexpr(
151+ E_S, (envlabel(SOUTH, i), virtuallabel(SOUTH, i)), envlabel(SOUTH, i - 1 )
152+ )
153+ end
154+
155+ edges_W = map(1 : gridsize[1 ]) do i
156+ E_W = :(env. edges[WEST, mod1($ (rmin + i - 1 ), end ), mod1($ (cmin - 1 ), end )])
157+ return tensorexpr(
158+ E_W, (envlabel(WEST, i), virtuallabel(WEST, i)), envlabel(WEST, i - 1 )
159+ )
160+ end
161+
162+ return edges_N, edges_E, edges_S, edges_W
163+ end
164+
129165function _contract_state_expr(rowrange, colrange, cartesian_inds= nothing )
130166 rmin, rmax = extrema(rowrange)
131167 cmin, cmax = extrema(colrange)
@@ -173,6 +209,96 @@ function _contract_state_expr(rowrange, colrange, cartesian_inds=nothing)
173209 end
174210end
175211
212+ function pf_tensor_expr(tensor_label, label_west, label_south, label_north, label_east, (len,place))
213+ if len == 1
214+ a = tensorexpr(
215+ tensor_label,
216+ ((label_west),(label_south),),
217+ ((label_north),(label_east),),
218+ )
219+ else
220+ if place == 1
221+ a = tensorexpr(
222+ tensor_label,
223+ ((label_west), (label_south),),
224+ ((label_north), (label_east), (virtuallabel(:op, len, place)),),
225+ )
226+ elseif place == len
227+ a = tensorexpr(
228+ tensor_label,
229+ ((virtuallabel(:op, len, place - 1 )), (label_west), (label_south),),
230+ ((label_north), (label_east),),
231+ )
232+ else
233+ a = tensorexpr(
234+ tensor_label,
235+ ((virtuallabel(:op, len, place - 1 )), (label_west), (label_south),),
236+ ((label_north), (label_east), (virtuallabel(:op, len, place)),),
237+ )
238+ end
239+ end
240+ return a
241+ end
242+
243+ function _contract_tensor_expr(O, pos, rowrange, colrange, cartesian_inds= nothing )
244+ rmin, rmax = extrema(rowrange)
245+ cmin, cmax = extrema(colrange)
246+ gridsize = (rmax - rmin + 1 , cmax - cmin + 1 )
247+ return map(Iterators. product(1 : gridsize[1 ], 1 : gridsize[2 ])) do (i, j)
248+ inds_id = if isnothing(cartesian_inds)
249+ nothing
250+ else
251+ findfirst(== (CartesianIndex(rmin + i - 1 , cmin + j - 1 )), cartesian_inds)
252+ end
253+ tensor_label = if isnothing(inds_id) || O <: Nothing
254+ :(pf[mod1($ (rmin + i - 1 ), end ), mod1($ (cmin + j - 1 ), end )])
255+ else
256+ :(O[$ inds_id])
257+ end
258+
259+ label_west = if j == 1
260+ virtuallabel(WEST, i)
261+ else
262+ virtuallabel(:horizontal, i, j - 1 )
263+ end
264+ label_south = if i == gridsize[1 ]
265+ virtuallabel(SOUTH, j)
266+ else
267+ virtuallabel(:vertical, i, j)
268+ end
269+ label_north = if i == 1
270+ virtuallabel(NORTH, j)
271+ else
272+ virtuallabel(:vertical, i - 1 , j)
273+ end
274+ label_east = if j == gridsize[2 ]
275+ virtuallabel(EAST, i)
276+ else
277+ virtuallabel(:horizontal, i, j)
278+ end
279+ if isnothing(inds_id) || O <: Nothing
280+ pf_tensor_expr(
281+ tensor_label,
282+ label_west,
283+ label_south,
284+ label_north,
285+ label_east,
286+ (1 ,1 ),
287+ )
288+
289+ else
290+ pf_tensor_expr(
291+ tensor_label,
292+ label_west,
293+ label_south,
294+ label_north,
295+ label_east,
296+ pos[inds_id],
297+ )
298+ end
299+ end
300+ end
301+
176302@generated function _contract_local_operator(
177303 inds:: NTuple{N,Val} ,
178304 O:: AbstractTensorMap{T,S,N,N} ,
270396 end
271397 return macroexpand(@__MODULE__, returnex)
272398end
399+
400+ # Partition function contractions
401+
402+ """
403+ contract_local_tensors(inds, [O], pf, env)
404+
405+ Contract a local tensor `O` inserted into a partition function `pf` at position `inds`,
406+ using the environment `env`.
407+ """
408+ function contract_local_tensors(
409+ inds:: NTuple{N,CartesianIndex{2}} ,
410+ O:: Union{Nothing,NTuple{N,AbstractTensorMap{T,S}}} ,
411+ pos:: Union{Nothing,NTuple{N,Tuple{Int,Int}}} ,
412+ pf:: InfinitePartitionFunction ,
413+ env:: CTMRGEnv{C,<:CTMRG_PF_EdgeTensor} ,
414+ ) where {N,T,S,C}
415+ static_inds = Val.(inds)
416+ static_pos = Val.(pos)
417+ return _contract_local_tensors(static_inds, O, static_pos, pf, env)
418+ end
419+ function contract_local_tensors(
420+ inds:: NTuple{N,Tuple{Int,Int}} ,
421+ O:: Union{Nothing,NTuple{N,AbstractTensorMap{T,S}}} ,
422+ pos:: Union{Nothing,NTuple{N,Tuple{Int,Int}}} ,
423+ pf:: InfinitePartitionFunction ,
424+ env:: CTMRGEnv{C,<:CTMRG_PF_EdgeTensor} ,
425+ ) where {N,T,S,C}
426+ return contract_local_tensors(CartesianIndex.(inds), O, pos, pf, env)
427+ end
428+ @generated function _contract_local_tensors(
429+ inds:: NTuple{N,Val} ,
430+ O:: Union{Nothing,NTuple{N,AbstractTensorMap{T,S}}} ,
431+ pos:: Union{Nothing,NTuple{N,Val}} ,
432+ pf:: InfinitePartitionFunction ,
433+ env:: CTMRGEnv{C,<:CTMRG_PF_EdgeTensor} ,
434+ ) where {N,T,S,C}
435+ # weird hack to extract information from Val
436+ cartesian_inds = collect(CartesianIndex{2 }, map(x -> x. parameters[1 ], inds. parameters))
437+ cartesian_pos = collect(Tuple{Int,Int}, map(x -> x. parameters[1 ], pos. parameters)) # weird hack to extract information from Val
438+ allunique(cartesian_inds) ||
439+ throw(ArgumentError(" Indices should not overlap: $cartesian_inds ." ))
440+ rowrange = getindex.(cartesian_inds, 1 )
441+ colrange = getindex.(cartesian_inds, 2 )
442+
443+ corner_NW, corner_NE, corner_SE, corner_SW = _contract_corner_expr(rowrange, colrange)
444+ edges_N, edges_E, edges_S, edges_W = _contract_pf_edge_expr(rowrange, colrange)
445+ tensors = _contract_tensor_expr(O, Tuple(cartesian_pos), rowrange, colrange, cartesian_inds)
446+
447+ multiplication_ex = Expr(
448+ :call,
449+ :* ,
450+ corner_NW,
451+ corner_NE,
452+ corner_SE,
453+ corner_SW,
454+ edges_N... ,
455+ edges_E... ,
456+ edges_S... ,
457+ edges_W... ,
458+ tensors... ,
459+ )
460+
461+ returnex = quote
462+ @autoopt @tensor opt = $ multiplication_ex
463+ end
464+ return macroexpand(@__MODULE__, returnex)
465+ end
0 commit comments