|
| 1 | +#= |
| 2 | +The construction of bond environment for Neighborhood Tensor Update (NTU) |
| 3 | +is adapted from YASTN (https://github.com/yastn/yastn). |
| 4 | +Copyright 2024 The YASTN Authors. All Rights Reserved. |
| 5 | +Licensed under the Apache License, Version 2.0 |
| 6 | +=# |
| 7 | + |
| 8 | +""" |
| 9 | +Algorithms to construct bond environment for Neighborhood Tensor Update (NTU). |
| 10 | +""" |
| 11 | +abstract type NeighbourEnv end |
| 12 | + |
| 13 | +""" |
| 14 | +SVD with `truncrank(1)`. |
| 15 | +""" |
| 16 | +function _svd_cut!(t::AbstractTensorMap) |
| 17 | + t1, s, t2 = svd_trunc!(t; trunc = truncrank(1)) |
| 18 | + return absorb_s(t1, s, t2) |
| 19 | +end |
| 20 | + |
| 21 | +""" |
| 22 | +Algorithm struct for "NTU-NN" bond environment. |
| 23 | +""" |
| 24 | +struct NNEnv <: NeighbourEnv end |
| 25 | +""" |
| 26 | +Calculate the bond environment within "NTU-NN" approximation. |
| 27 | +``` |
| 28 | + -1 ●=======● |
| 29 | + ║ ║ |
| 30 | + 0 ●===X== ==Y===● |
| 31 | + ║ ║ |
| 32 | + 1 ●=======● |
| 33 | + -1 0 1 2 |
| 34 | +``` |
| 35 | +""" |
| 36 | +function bondenv_ntu( |
| 37 | + row::Int, col::Int, X::T, Y::T, state::S, alg::NNEnv |
| 38 | + ) where {T, S <: InfiniteState} |
| 39 | + neighbors = [(-1, 0), (0, -1), (1, 0), (1, 1), (0, 2), (-1, 1)] |
| 40 | + m = collect_neighbors(state, row, col, neighbors) |
| 41 | + X, Y = _prepare_site_tensor(X), _prepare_site_tensor(Y) |
| 42 | + # southwest half |
| 43 | + @autoopt @tensor benv_sw[Dse1 Dse0 Dw1 Dw0 Dnw1 Dnw0] := |
| 44 | + cor_se(m[1, 1])[Dse1 Dse0 Ds1 Ds0] * |
| 45 | + cor_sw(m[1, 0])[Dsw1 Dsw0 Ds1 Ds0] * |
| 46 | + edge_w(X, hair_w(m[0, -1]))[Dnw1 Dnw0 Dw1 Dw0 Dsw1 Dsw0] |
| 47 | + normalize!(benv_sw, Inf) |
| 48 | + # northeast half |
| 49 | + @autoopt @tensor benv_ne[Dnw1 Dnw0 De1 De0 Dse1 Dse0] := |
| 50 | + cor_nw(m[-1, 0])[Dn1 Dn0 Dnw1 Dnw0] * |
| 51 | + cor_ne(m[-1, 1])[Dne1 Dne0 Dn1 Dn0] * |
| 52 | + edge_e(Y, hair_e(m[0, 2]))[Dne1 Dne0 Dse1 Dse0 De1 De0] |
| 53 | + normalize!(benv_ne, Inf) |
| 54 | + @tensor benv[Dw1 De1; Dw0 De0] := |
| 55 | + benv_sw[Dse1 Dse0 Dw1 Dw0 Dnw1 Dnw0] * benv_ne[Dnw1 Dnw0 De1 De0 Dse1 Dse0] |
| 56 | + normalize!(benv, Inf) |
| 57 | + return benv |
| 58 | +end |
| 59 | + |
| 60 | +""" |
| 61 | +Algorithm struct for "NTU-NN+" bond environment. |
| 62 | +""" |
| 63 | +struct NNpEnv <: NeighbourEnv end |
| 64 | +""" |
| 65 | +Calculate the bond environment within "NTU-NN+" approximation. |
| 66 | +``` |
| 67 | + -2 ●.......● |
| 68 | + ║ ║ |
| 69 | + -1 ○===●=======●===○ |
| 70 | + ║ ║ ║ ║ |
| 71 | + 0 ●===●===X== ==Y===●===● |
| 72 | + ║ ║ ║ ║ |
| 73 | + 1 ○===●=======●===○ |
| 74 | + ║ ║ |
| 75 | + 2 ●.......● |
| 76 | + -2 -1 0 1 2 3 |
| 77 | +``` |
| 78 | +Dotted lines and ○ are splitted using SVD with `truncrank(1)`. |
| 79 | +""" |
| 80 | +function bondenv_ntu( |
| 81 | + row::Int, col::Int, X::T, Y::T, state::S, alg::NNpEnv |
| 82 | + ) where {T, S <: InfiniteState} |
| 83 | + neighbors = [ |
| 84 | + (-1, -1), (0, -1), (1, -1), (1, 0), (1, 1), (1, 2), (0, 2), (-1, 2), |
| 85 | + (-1, 1), (-1, 0), (0, -2), (2, 0), (2, 1), (0, 3), (-2, 1), (-2, 0), |
| 86 | + ] |
| 87 | + ms = collect_neighbors(state, row, col, neighbors) |
| 88 | + X, Y = _prepare_site_tensor(X), _prepare_site_tensor(Y) |
| 89 | + |
| 90 | + # ---- hairs (size D^2) with a 1D auxiliary leg ---- |
| 91 | + |
| 92 | + @tensor top[-1 -2; -3 -4] := cor_nw(ms[-2, 0])[1 2 -1 -2] * cor_ne(ms[-2, 1])[-3 -4 1 2] |
| 93 | + tl, tr = _svd_cut!(top) |
| 94 | + |
| 95 | + @tensor bot[-1 -2; -3 -4] := cor_sw(ms[2, 0])[-1 -2 1 2] * cor_se(ms[2, 1])[-3 -4 1 2] |
| 96 | + bl, br = _svd_cut!(bot) |
| 97 | + |
| 98 | + nw = permute(cor_nw(ms[-1, -1]), ((3, 4), (1, 2))) |
| 99 | + nw1, nw2 = _svd_cut!(nw) |
| 100 | + |
| 101 | + ne = permute(cor_ne(ms[-1, 2]), ((3, 4), (1, 2))) |
| 102 | + ne1, ne2 = _svd_cut!(ne) |
| 103 | + |
| 104 | + sw = permute(cor_sw(ms[1, -1]), ((1, 2), (3, 4))) |
| 105 | + sw1, sw2 = _svd_cut!(sw) |
| 106 | + |
| 107 | + se = permute(cor_se(ms[1, 2]), ((3, 4), (1, 2))) |
| 108 | + se1, se2 = _svd_cut!(se) |
| 109 | + |
| 110 | + m = ms[0, -1] |
| 111 | + @tensoropt hW[anw DXw1 DXw0 asw] := |
| 112 | + hair_w(ms[0, -2])[Dw21 Dw20] * |
| 113 | + nw1[Dnw11 Dnw10 anw] * sw1[Dsw11 Dsw10 asw] * |
| 114 | + twistdual(m, 1)[p Dnw10 DXw0 Dsw10 Dw20] * |
| 115 | + conj(m[p Dnw11 DXw1 Dsw11 Dw21]) |
| 116 | + |
| 117 | + m = ms[0, 2] |
| 118 | + @tensoropt hE[ane DYe1 DYe0 ase] := |
| 119 | + hair_e(ms[0, 3])[De21 De20] * |
| 120 | + ne2[ane Dne21 Dne20] * se2[ase Dse21 Dse20] * |
| 121 | + twistdual(m, 1)[p Dne20 De20 Dse20 DYe0] * |
| 122 | + conj(m[p Dne21 De21 Dse21 DYe1]) |
| 123 | + |
| 124 | + # ---- corners (size D^4) with a 1D auxiliary leg ---- |
| 125 | + |
| 126 | + m = ms[-1, 0] |
| 127 | + @tensoropt NW[at Dn1 Dn0 DXn1 DXn0 anw] := |
| 128 | + tl[Dtl1 Dtl0 at] * nw2[anw Dnw21 Dnw20] * |
| 129 | + twistdual(m, 1)[p Dtl0 Dn0 DXn0 Dnw20] * |
| 130 | + conj(m[p Dtl1 Dn1 DXn1 Dnw21]) |
| 131 | + |
| 132 | + m = ms[-1, 1] |
| 133 | + @tensoropt NE[at Dn1 Dn0 DYn1 DYn0 ane] := |
| 134 | + tr[at Dtr1 Dtr0] * ne1[Dne11 Dne10 ane] * |
| 135 | + twistdual(m, 1)[p Dtr0 Dne10 DYn0 Dn0] * |
| 136 | + conj(m[p Dtr1 Dne11 DYn1 Dn1]) |
| 137 | + |
| 138 | + m = ms[1, 0] |
| 139 | + @tensoropt SW[asw DXs1 DXs0 Ds1 Ds0 ab] := |
| 140 | + bl[Dbl1 Dbl0 ab] * sw2[asw Dsw21 Dsw20] * |
| 141 | + twistdual(m, 1)[p DXs0 Ds0 Dbl0 Dsw20] * |
| 142 | + conj(m[p DXs1 Ds1 Dbl1 Dsw21]) |
| 143 | + |
| 144 | + m = ms[1, 1] |
| 145 | + @tensoropt SE[ase DYs1 DYs0 Ds1 Ds0 ab] := |
| 146 | + br[ab Dbr1 Dbr0] * se1[Dse11 Dse10 ase] * |
| 147 | + twistdual(m, 1)[p DYs0 Dse10 Dbr0 Ds0] * |
| 148 | + conj(m[p DYs1 Dse11 Dbr1 Ds1]) |
| 149 | + |
| 150 | + # ---- left half ---- |
| 151 | + @tensoropt benvL[at Dn1 Dn0 Dw1 Dw0 Ds1 Ds0 ab] := |
| 152 | + hW[anw DXw1 DXw0 asw] * |
| 153 | + NW[at Dn1 Dn0 DXn1 DXn0 anw] * |
| 154 | + SW[asw DXs1 DXs0 Ds1 Ds0 ab] * |
| 155 | + twistdual(X, 1)[p DXn0 Dw0 DXs0 DXw0] * |
| 156 | + conj(X[p DXn1 Dw1 DXs1 DXw1]) |
| 157 | + normalize!(benvL, Inf) |
| 158 | + |
| 159 | + # ---- right half ---- |
| 160 | + |
| 161 | + @tensoropt benvR[at Dn1 Dn0 De1 De0 Ds1 Ds0 ab] := |
| 162 | + hE[ane DYe1 DYe0 ase] * |
| 163 | + NE[at Dn1 Dn0 DYn1 DYn0 ane] * |
| 164 | + SE[ase DYs1 DYs0 Ds1 Ds0 ab] * |
| 165 | + twistdual(Y, 1)[p DYn0 DYe0 DYs0 De0] * |
| 166 | + conj(Y[p DYn1 DYe1 DYs1 De1]) |
| 167 | + normalize!(benvR, Inf) |
| 168 | + |
| 169 | + # ---- the full NN+ environment ---- |
| 170 | + |
| 171 | + @tensor benv[Dw1, De1; Dw0, De0] := |
| 172 | + benvL[at Dn1 Dn0 Dw1 Dw0 Ds1 Ds0 ab] * |
| 173 | + benvR[at Dn1 Dn0 De1 De0 Ds1 Ds0 ab] |
| 174 | + normalize!(benv, Inf) |
| 175 | + return benv |
| 176 | +end |
| 177 | + |
| 178 | +""" |
| 179 | +Algorithm struct for "NTU-NNN" bond environment. |
| 180 | +""" |
| 181 | +struct NNNEnv <: NeighbourEnv end |
| 182 | +""" |
| 183 | +Calculates the bond environment within "NTU-NNN" approximation. |
| 184 | +``` |
| 185 | + -1 ●===●=======●===● |
| 186 | + ║ ║ ║ ║ |
| 187 | + 0 ●===X== ==Y===● |
| 188 | + ║ ║ ║ ║ |
| 189 | + 1 ●===●=======●===● |
| 190 | + -1 0 1 2 |
| 191 | +``` |
| 192 | +""" |
| 193 | +function bondenv_ntu( |
| 194 | + row::Int, col::Int, X::T, Y::T, state::S, alg::NNNEnv |
| 195 | + ) where {T, S <: InfiniteState} |
| 196 | + neighbors = [ |
| 197 | + (-1, -1), (0, -1), (1, -1), |
| 198 | + (1, 0), (1, 1), (1, 2), (0, 2), |
| 199 | + (-1, 2), (-1, 1), (-1, 0), |
| 200 | + ] |
| 201 | + m = collect_neighbors(state, row, col, neighbors) |
| 202 | + X, Y = _prepare_site_tensor(X), _prepare_site_tensor(Y) |
| 203 | + #= left half |
| 204 | + -1 ●======●=== -1/-2 |
| 205 | + ║ ║ |
| 206 | + 0 ●======X=== -3/-4 |
| 207 | + ║ ║ |
| 208 | + ....D1.....D2... |
| 209 | + ║ ║ |
| 210 | + 1 ●==D3==●=== -5/-6 |
| 211 | + -1 0 |
| 212 | + =# |
| 213 | + vecl = enlarge_corner_nw(cor_nw(m[-1, -1]), edge_n(m[-1, 0]), edge_w(m[0, -1]), X) |
| 214 | + @tensor vecl[:] := |
| 215 | + cor_sw(m[1, -1])[D11 D10 D31 D30] * |
| 216 | + edge_s(m[1, 0])[D21 D20 -5 -6 D31 D30] * |
| 217 | + vecl[D11 D10 D21 D20 -1 -2 -3 -4] |
| 218 | + normalize!(vecl, Inf) |
| 219 | + #= right half |
| 220 | + -1 -1/-2===●==D1==● |
| 221 | + ║ ║ |
| 222 | + ........D2.....D3... |
| 223 | + ║ ║ |
| 224 | + 0 -3/-4===Y======● |
| 225 | + ║ ║ |
| 226 | + 1 -5/-6===●======● |
| 227 | + 0 1 |
| 228 | + =# |
| 229 | + vecr = enlarge_corner_se(cor_se(m[1, 2]), edge_s(m[1, 1]), edge_e(m[0, 2]), Y) |
| 230 | + @tensor vecr[:] := |
| 231 | + edge_n(m[-1, 1])[D11 D10 D21 D20 -1 -2] * |
| 232 | + cor_ne(m[-1, 2])[D31 D30 D11 D10] * |
| 233 | + vecr[D21 D20 D31 D30 -3 -4 -5 -6] |
| 234 | + normalize!(vecr, Inf) |
| 235 | + # combine left and right part |
| 236 | + @tensor benv[-1 -2; -3 -4] := vecl[1 2 -1 -3 3 4] * vecr[1 2 -2 -4 3 4] |
| 237 | + normalize!(benv, Inf) |
| 238 | + return benv |
| 239 | +end |
0 commit comments