Source code for ctm.generic_abelian.ctm_components

from config import ctm_args
from tn_interface_abelian import contract

# TODO inject ctm_args from env into halves_* and c2x2_* function
# TODO checkpointing for construction of halves ?
# torch.utils.checkpoint import checkpoint

#####################################################################
# functions building pair of 4x2 (or 2x4) halves of 4x4 TN
#####################################################################
[docs]def halves_of_4x4_CTM_MOVE_UP(coord, state, env, verbosity=0): r""" :param coord: site for which to build two halfs of 2x2 subsystem embedded in environment :type coord: tuple(int,int) :param state: wavefunction :type state: IPEPS_ABELIAN :param env: environment :type env: ENV_ABELIAN :return: right and left half of the system as matrices :rtype: yastn.Tensor, yastn.Tensor Builds right and left half of 2x2 subsystem embedded into environment. The `coord` specifies the upper-right site of the 2x2 subsystem. Performs following contraction and then reshaping the resulting tensors into matrices:: C T T C = C2x2_LU(coord+(-1,0)) C2x2(coord) T A B(coord) T C2x2_LD(coord+(-1,1)) C2x2(coord+(0,1)) T C D T C T T C C2x2--1->0 0--C2x2(coord) = _0 0_ |0 1| | | |0 0| half2 half1 C2x2--1 1--C2x2 |_1 1_| """ # RU, RD, LU, LD tensors= c2x2_RU_t(coord,state,env) + c2x2_RD_t((coord[0], coord[1]+1),state,env) \ + c2x2_LU_t((coord[0]-1, coord[1]),state,env) + c2x2_LD_t((coord[0]-1, coord[1]+1),state,env) if ctm_args.fwd_checkpoint_halves: # return checkpoint(halves_of_4x4_CTM_MOVE_UP_c,*tensors) raise RuntimeError("Checkpointing not implemented") else: return halves_of_4x4_CTM_MOVE_UP_c(*tensors)
def halves_of_4x4_CTM_MOVE_UP_t(coord, state, env): # RU, RD, LU, LD tensors= c2x2_RU_t(coord,state,env) + c2x2_RD_t((coord[0], coord[1]+1),state,env) \ + c2x2_LU_t((coord[0]-1, coord[1]),state,env) + c2x2_LD_t((coord[0]-1, coord[1]+1),state,env) return tensors def halves_of_4x4_CTM_MOVE_UP_c(*tensors): # C T T C = C2x2_LU(coord+(-1,0)) C2x2(coord) # T A B(coord) T C2x2_LD(coord+(-1,1)) C2x2(coord+(0,1)) # T C D T # C T T C # C2x2--1->0 0--C2x2(coord) = _0(-1) (+1)0_ # |0 1| | | # |0 0| half2 half1 # C2x2--1 1--C2x2 |_1(-1) (+1)1_| c2x2_RU= c2x2_RU_c(*tensors[0:4]) c2x2_RD= c2x2_RD_c(*tensors[4:8]) R= contract(c2x2_RU,c2x2_RD,([1],[0])) c2x2_LU= c2x2_LU_c(*tensors[8:12]) c2x2_LD= c2x2_LD_c(*tensors[12:16]) Rt= contract(c2x2_LU, c2x2_LD,([0],[0])) return R, Rt
[docs]def halves_of_4x4_CTM_MOVE_LEFT(coord, state, env, verbosity=0): r""" :param coord: site for which to build two halfs of 2x2 subsystem embedded in environment :type coord: tuple(int,int) :param state: wavefunction :type state: IPEPS_ABELIAN :param env: environment :type env: ENV_ABELIAN :return: upper and lower half of the system as matrices :rtype: yastn.Tensor, yastn.Tensor Builds upper and lower half of 2x2 subsystem embedded into environment. The `coord` specifies the upper-left site of the 2x2 subsystem. Performs following contraction and then reshaping the resulting tensors into matrices:: C T T C = C2x2_LU(coord) C2x2(coord+(1,0)) T A(coord) B T C2x2_LD(coord+(0,1)) C2x2(coord+(1,1)) T C D T C T T C C2x2(coord)--1 0--C2x2 = half1 |0 1| |0 |1 |0 1<-0| |0 |1 C2x2--1 1---------C2x2 half2 """ # LU, RU, LS, RD tensors= c2x2_LU_t(coord,state,env) + c2x2_RU_t((coord[0]+1, coord[1]),state,env) \ + c2x2_LD_t((coord[0], coord[1]+1),state,env) + c2x2_RD_t((coord[0]+1, coord[1]+1),state,env) if ctm_args.fwd_checkpoint_halves: # return checkpoint(halves_of_4x4_CTM_MOVE_LEFT_c,*tensors) raise RuntimeError("Checkpointing not implemented") else: return halves_of_4x4_CTM_MOVE_LEFT_c(*tensors)
def halves_of_4x4_CTM_MOVE_LEFT_t(coord, state, env): # LU, RU, LS, RD tensors= c2x2_LU_t(coord,state,env) + c2x2_RU_t((coord[0]+1, coord[1]),state,env) \ + c2x2_LD_t((coord[0], coord[1]+1),state,env) + c2x2_RD_t((coord[0]+1, coord[1]+1),state,env) return tensors def halves_of_4x4_CTM_MOVE_LEFT_c(*tensors): # C T T C = C2x2_LU(coord) C2x2(coord+(1,0)) # T A(coord) B T C2x2_LD(coord+(0,1)) C2x2(coord+(1,1)) # T C D T # C T T C # C2x2(coord)--1 0--C2x2 = half1---- # |0 1| |0(-1) |1(-1) # # |0 1<-0| |0(+1) |1(+1) # C2x2--1 1---------C2x2 half2---- c2x2_LU= c2x2_LU_c(*tensors[0:4]) c2x2_RU= c2x2_RU_c(*tensors[4:8]) R= contract(c2x2_LU,c2x2_RU,([1],[0])) c2x2_LD= c2x2_LD_c(*tensors[8:12]) c2x2_RD= c2x2_RD_c(*tensors[12:16]) Rt= contract(c2x2_LD,c2x2_RD,([1],[1])) return R, Rt
[docs]def halves_of_4x4_CTM_MOVE_DOWN(coord, state, env, verbosity=0): r""" :param coord: site for which to build two halfs of 2x2 subsystem embedded in environment :type coord: tuple(int,int) :param state: wavefunction :type state: IPEPS_ABELIAN :param env: environment :type env: ENV_ABELIAN :return: left and right half of the system as matrices :rtype: yastn.Tensor, yastn.Tensor Builds left and right half of 2x2 subsystem embedded into environment. The `coord` specifies the lower-left site of the 2x2 subsystem. Performs following contraction and then reshaping the resulting tensors into matrices:: C T T C = C2x2_LU(coord+(0,-1)) C2x2(coord+(1,-1)) T A B T C2x2_LD(coord) C2x2(coord+(1,0)) T C(coord) D T C T T C C2x2---------1 1<-0--C2x2 = _1 1_ |0 |1 | | |0 |0 half1 half2 C2x2(coord)--1->0 0<-1--C2x2 |_0 0_| """ # LD, LU, RD, RU tensors= c2x2_LD_t(coord,state,env) + c2x2_LU_t((coord[0], coord[1]-1),state,env) \ + c2x2_RD_t((coord[0]+1, coord[1]),state,env) + c2x2_RU_t((coord[0]+1, coord[1]-1),state,env) if ctm_args.fwd_checkpoint_halves: # return checkpoint(halves_of_4x4_CTM_MOVE_DOWN_c,*tensors) raise RuntimeError("Checkpointing not implemented") else: return halves_of_4x4_CTM_MOVE_DOWN_c(*tensors)
def halves_of_4x4_CTM_MOVE_DOWN_t(coord, state, env): # LD, LU, RD, RU tensors= c2x2_LD_t(coord,state,env) + c2x2_LU_t((coord[0], coord[1]-1),state,env) \ + c2x2_RD_t((coord[0]+1, coord[1]),state,env) + c2x2_RU_t((coord[0]+1, coord[1]-1),state,env) return tensors def halves_of_4x4_CTM_MOVE_DOWN_c(*tensors): # C T T C = C2x2_LU(coord+(0,-1)) C2x2(coord+(1,-1)) # T A B T C2x2_LD(coord) C2x2(coord+(1,0)) # T C(coord) D T # C T T C # C2x2---------1 1<-0--C2x2 = _1(-1) (+1)1_ # |0 |1 | | # |0 |0 half1 half2 # C2x2(coord)--1->0 0<-1--C2x2 |_0(-1) (+1)0_| c2x2_LD= c2x2_LD_c(*tensors[0:4]) c2x2_LU= c2x2_LU_c(*tensors[4:8]) R= contract(c2x2_LD,c2x2_LU,([0],[0])) c2x2_RD= c2x2_RD_c(*tensors[8:12]) c2x2_RU= c2x2_RU_c(*tensors[12:16]) Rt= contract(c2x2_RD,c2x2_RU,([0],[1])) return R, Rt
[docs]def halves_of_4x4_CTM_MOVE_RIGHT(coord, state, env, verbosity=0): r""" :param coord: site for which to build two halfs of 2x2 subsystem embedded in environment :type coord: tuple(int,int) :param state: wavefunction :type state: IPEPS_ABELIAN :param env: environment :type env: ENV_ABELIAN :return: upper and lower half of the system as matrices :rtype: yastn.Tensor, yastn.Tensor Builds uoper and lower half of 2x2 subsystem embedded into environment. The `coord` specifies the lower-right site of the 2x2 subsystem. Performs following contraction and then reshaping the resulting tensors into matrices:: C T T C = C2x2_LU(coord+(-1,-1)) C2x2(coord+(0,-1)) T A B T C2x2_LD(coord+(-1,0)) C2x2(coord) T C D(coord) T C T T C C2x2--1 0--C2x2 = half2 |0->1 |1->0 |1 |0 |0->1 |0 |1 |0 C2x2--1 1--C2x2(coord) half1 """ # RD, LD, RU, LU tensors= c2x2_RD_t(coord,state,env) + c2x2_LD_t((coord[0]-1, coord[1]),state,env) \ + c2x2_RU_t((coord[0], coord[1]-1),state,env) + c2x2_LU_t((coord[0]-1, coord[1]-1),state,env) if ctm_args.fwd_checkpoint_halves: # return checkpoint(halves_of_4x4_CTM_MOVE_RIGHT_c,*tensors) raise RuntimeError("Checkpointing not implemented") else: return halves_of_4x4_CTM_MOVE_RIGHT_c(*tensors)
def halves_of_4x4_CTM_MOVE_RIGHT_t(coord, state, env): # RD, LD, RU, LU tensors= c2x2_RD_t(coord,state,env) + c2x2_LD_t((coord[0]-1, coord[1]),state,env) \ + c2x2_RU_t((coord[0], coord[1]-1),state,env) + c2x2_LU_t((coord[0]-1, coord[1]-1),state,env) return tensors def halves_of_4x4_CTM_MOVE_RIGHT_c(*tensors): # C T T C = C2x2_LU(coord+(-1,-1)) C2x2(coord+(0,-1)) # T A B T C2x2_LD(coord+(-1,0)) C2x2(coord) # T C D(coord) T # C T T C # C2x2--1 0--C2x2 = ------half2 # |0->1 |1->0 |1(-1) |0(-1) # # |0->1 |0 |1(+1) |0(+1) # C2x2--1 1--C2x2(coord) ------half1 c2x2_RD= c2x2_RD_c(*tensors[0:4]) c2x2_LD= c2x2_LD_c(*tensors[4:8]) R= contract(c2x2_RD,c2x2_LD,([1],[1])) c2x2_RU= c2x2_RU_c(*tensors[8:12]) c2x2_LU= c2x2_LU_c(*tensors[12:16]) Rt= contract(c2x2_RU,c2x2_LU,([0],[1])) return R, Rt ##################################################################### # functions building 2x2 Corner #####################################################################
[docs]def c2x2_LU(coord, state, env, verbosity=0): r""" :param coord: site for which to build enlarged upper-left corner :type coord: tuple(int,int) :param state: wavefunction :type state: IPEPS_ABELIAN :param env: environment :type env: ENV_ABELIAN :return: enlarged upper-left corner :rtype: yastn.Tensor Builds upper-left corner at site `coord` by performing following contraction and then reshaping the resulting tensor into matrix:: C----T--2 => C2x2--(2,3)->1(-1) | | | | | (0,1)->0(-1) T----A(coord)--3 | | 0 1 """ C = env.C[(state.vertexToSite(coord),(-1,-1))] T1 = env.T[(state.vertexToSite(coord),(0,-1))] T2 = env.T[(state.vertexToSite(coord),(-1,0))] A = state.site(coord) tensors= C, T1, T2, A if ctm_args.fwd_checkpoint_c2x2: C2x2= checkpoint(c2x2_LU_c,*tensors) else: C2x2= c2x2_LU_c(*tensors) if verbosity>0: print("C2X2 LU "+str(coord)+"->"+str(state.vertexToSite(coord))+" (-1,-1)") if verbosity>1: print(C2x2) return C2x2
def c2x2_LU_t(coord, state, env): tensors= env.C[(state.vertexToSite(coord),(-1,-1))], \ env.T[(state.vertexToSite(coord),(0,-1))], \ env.T[(state.vertexToSite(coord),(-1,0))], \ state.site(coord) return tensors def c2x2_LU_c(*tensors): C, T1, T2, A= tensors # C--10--T1--2 # 0 1 C2x2 = contract(C, T1, ([1],[0])) # C------T1--2->1 # 0 1->0 # 0 # T2--2->3 # 1->2 C2x2 = contract(C2x2, T2, ([0],[0])) # C--------T1--1->0(-1) # | 0 # | 0 # T2--3 1--A--3(-1) # 2->1(-1) 2(-1) C2x2 = contract(C2x2, A, ([0,3],[0,1])) # permute 0123->1203 # reshape (12)(03)->01 C2x2= C2x2.fuse_legs(axes=((1,2),(0,3))) # C2x2--1(-1) # | # 0(-1) return C2x2
[docs]def c2x2_RU(coord, state, env, verbosity=0): r""" :param coord: site for which to build enlarged upper-right corner :type coord: tuple(int,int) :param state: wavefunction :type state: IPEPS_ABELIAN :param env: environment :type env: ENV_ABELIAN :return: enlarged upper-left corner :rtype: yastn.Tensor Builds upper-right corner at site `coord` by performing following contraction and then reshaping the resulting tensor into matrix:: 0--T---------C => (+)0<-(0,1)--C2x2 | | | | | (-)1<-(2,3) 1--A(coord)--T 3 2 """ C = env.C[(state.vertexToSite(coord),(1,-1))] T1 = env.T[(state.vertexToSite(coord),(1,0))] T2 = env.T[(state.vertexToSite(coord),(0,-1))] A = state.site(coord) tensors= C, T1, T2, A if ctm_args.fwd_checkpoint_c2x2: C2x2= checkpoint(c2x2_RU_c,*tensors) else: C2x2= c2x2_RU_c(*tensors) if verbosity>0: print("C2X2 RU "+str(coord)+"->"+str(state.vertexToSite(coord))+" (1,-1)") if verbosity>1: print(C2x2) return C2x2
def c2x2_RU_t(coord, state, env): tensors= env.C[(state.vertexToSite(coord),(1,-1))], \ env.T[(state.vertexToSite(coord),(1,0))], \ env.T[(state.vertexToSite(coord),(0,-1))], \ state.site(coord) return tensors def c2x2_RU_c(*tensors): C, T1, T2, A= tensors # 0--C # 1 # 0 # 1--T1 # 2 C2x2 = contract(C, T1, ([1],[0])) # 2<-0--T2--2 0--C # 3<-1 | # 0<-1--T1 # 1<-2 C2x2 = contract(C2x2, T2, ([0],[2])) # (+1)1<-2--T2--------C # 3 | # 0 | # (+1)2<-1--A--3 0----T1 # (-1)3<-2 (-1)0<-1 C2x2 = contract(C2x2, A, ([0,3],[3,0])) # permute 0123->1203 # reshape (12)(03)->01 C2x2= C2x2.fuse_legs(axes=((1,2),(0,3))) # (+1)0--C2x2 # | # (-1)1 return C2x2
[docs]def c2x2_RD(coord, state, env, verbosity=0): r""" :param coord: site for which to build enlarged lower-right corner :type coord: tuple(int,int) :param state: wavefunction :type state: IPEPS_ABELIAN :param env: environment :type env: ENV_ABELIAN :return: enlarged upper-left corner :rtype: yastn.Tensor Builds lower-right corner at site `coord` by performing following contraction and then reshaping the resulting tensor into matrix:: 1 0 3--A(coord)--T => (+)0<-(0,1) | | | | | (+)1<-(2,3)--C2x2 2--T---------C """ C = env.C[(state.vertexToSite(coord),(1,1))] T1 = env.T[(state.vertexToSite(coord),(0,1))] T2 = env.T[(state.vertexToSite(coord),(1,0))] A = state.site(coord) tensors= C, T1, T2, A if ctm_args.fwd_checkpoint_c2x2: C2x2= checkpoint(c2x2_RD_c,*tensors) else: C2x2= c2x2_RD_c(*tensors) if verbosity>0: print("C2X2 RD "+str(coord)+"->"+str(state.vertexToSite(coord))+" (1,1)") if verbosity>1: print(C2x2) return C2x2
def c2x2_RD_t(coord, state, env): tensors= env.C[(state.vertexToSite(coord),(1,1))], \ env.T[(state.vertexToSite(coord),(0,1))], \ env.T[(state.vertexToSite(coord),(1,0))], \ state.site(coord) return tensors def c2x2_RD_c(*tensors): C, T1, T2, A= tensors # 1<-0 0 # 2<-1--T1--2 1--C C2x2 = contract(C, T1, ([1],[2])) # 2<-0 # 3<-1--T2 # 2 # 0<-1 0 # 1<-2--T1---C C2x2 = contract(C2x2, T2, ([0],[2])) # 2<-0 1<-2 # 3<-1--A--3 3--T2 # 2 | # 0 | # 0<-1--T1------C C2x2 = contract(C2x2, A, ([0,3],[2,3])) # permute 0123->1203 # reshape (12)(03)->01 C2x2= C2x2.fuse_legs(axes=((1,2),(0,3))) # (+1)0 # | # (+1)1--C2x2 return C2x2
[docs]def c2x2_LD(coord, state, env, verbosity=0): r""" :param coord: site for which to build enlarged lower-right corner :type coord: tuple(int,int) :param state: wavefunction :type state: IPEPS_ABELIAN :param env: environment :type env: ENV_ABELIAN :return: enlarged upper-left corner :rtype: yastn.Tensor Builds lower-right corner at site `coord` by performing following contraction and then reshaping the resulting tensor into matrix:: 0 1 T--A(coord)--3 | | (0,1)->0(+) | | | C--T---------2 => C2x2--(2,3)->1(-) """ C = env.C[(state.vertexToSite(coord),(-1,1))] T1 = env.T[(state.vertexToSite(coord),(-1,0))] T2 = env.T[(state.vertexToSite(coord),(0,1))] A = state.site(coord) tensors= C, T1, T2, A if ctm_args.fwd_checkpoint_c2x2: C2x2= checkpoint(c2x2_LD_c,*tensors) else: C2x2= c2x2_LD_c(*tensors) if verbosity>0: print("C2X2 LD "+str(coord)+"->"+str(state.vertexToSite(coord))+" (-1,1)") if verbosity>1: print(C2x2) return C2x2
def c2x2_LD_t(coord, state, env): tensors= env.C[(state.vertexToSite(coord),(-1,1))], \ env.T[(state.vertexToSite(coord),(-1,0))], \ env.T[(state.vertexToSite(coord),(0,1))], \ state.site(coord) return tensors def c2x2_LD_c(*tensors): C, T1, T2, A= tensors # 0->1(+1) # T1--2(-1) # 1(-1) # 0(+1) # C--1->0(-1) C2x2 = contract(C, T1, ([0],[1])) # 1->0 # T1--2->1 # | # | 0->2 # C--0 1--T2--2->3 C2x2 = contract(C2x2, T2, ([0],[1])) # 0 0->2 # T1--1 1--A--3 # | 2 # | 2 # C--------T2--3->1 C2x2 = contract(C2x2, A, ([1,2],[1,2])) # permute 0123->0213 # reshape (02)(13)->01 C2x2= C2x2.fuse_legs(axes=((0,2),(1,3))) # 0(+1) # | # C2x2--1(-1) return C2x2 ##################################################################### # generic enlarged corner ##################################################################### # TODO currently operates on ``sites`` of IPEPS_ABELIAN, where the # fusion of physical DoFs has been already performed. One has to # unfuse # TODO in case of contracted physical space, is trace of physical space # of open double-layer faster then construction from scratch?
[docs]def double_layer_a(state, coord, open_sites=[], force_cpu=False, verbosity=0): r""" :param state: underlying wavefunction :param coord: vertex (x,y) for which the reduced density matrix is constructed :param open_sites: a list DoFs to leave open (uncontracted). :param force_cpu: perform on CPU :type state: IPEPS_ABELIAN :type coord: tuple(int,int) :type open_sites: list(int) :type force_cpu: bool :return: result of contraction of double-layer tensor :rtype: yastn.Tensor Build double-layer tensor of iPEPS with open or fully contracted physical space:: (+) / (+)--A*--(-) (-) (-)/| / -> | (-)--a*a--(+) s' 0 / \ ? (+) s,s' s 0 | (-)\| (-)--A--(+) (+)/ Default results in contraction over DoF. Physical indices are aggregated into a single index with structure :math:`|ket \rangle\langle bra| = s;s'`. The available choices for ``open_sites`` are: [], [0]. """ # special handling of all physical indices open (provided by IPEPS_ABELIAN # pre-computation if open_sites==[0]: if not state.sites_dl_open is None: a= state.site_dl_open(coord).to('cpu') if force_cpu else state.site_dl_open(coord) # move physical index to last position a= permute(a,(1,2,3,4,0)) else: A= state.site(coord).to('cpu') if force_cpu else state.site(coord) a= _fused_open_dl_site(A, fusion_level="full") a= permute(a,(1,2,3,4,0)) elif open_sites==[]: # special handling of no physical spaces open (most common case) if not state.sites_dl is None: a= state.site_dl(coord).to('cpu') if force_cpu else state.site_dl(coord) else: # no open double-layer present in state, recompute from scratch A= state.site(coord).to('cpu') if force_cpu else state.site(coord) a= _fused_dl_site(A) if verbosity>1: print(f"double_layer_a({coord},{open_sites}) {a}") return a
def _enlarged_corner(coord, state, env, corner, double_layer_f, open_sites=[], \ force_cpu=False, verbosity=0): r""" :param coord: vertex (x,y) for which the enlarged corner is constructed :param state: underlying wavefunction :param env: environment corresponding to ``state`` :param corner: which corner to construct. The four options are: 'LU', 'RU', 'RD', and 'LD' for "left up" corner, "right up" corner, "right down" corner, and "left down" corner. :param open_sites: a list DoFs to leave open (uncontracted). :param force_cpu: perform on CPU :type coord: tuple(int,int) :type state: IPEPS_KAGOME_ABELIAN :type env: ENV_ABELIAN :type corner: str :type open_sites: list(int) :type force_cpu: bool :return: result of (partial) contraction of double-layer tensor :rtype: yastn.tensor Builds enlarged corner relative to the site at ``coord`` from the environment:: C---T--- | | | | --a*a--T T--a*a-- | | | | for corner='LU', or ---T---C for corner='RD' The resulting tensor is always reshaped into either rank-2 or rank-3 if some DoFs are left open on the double-layer. In the latter case, these open physical indices are aggregated into the last index of the resulting tensor. The index-ordering convention for enlarged corners follows convention for corner tensors of the environment ``env``. If ``open_sites=0`` returned tensor has rank-2, where env. indices and auxiliary indices of double-layer tensor in the same direction were fused into a single index. If some DoFs remain open, then returned tensor is rank-3 with extra index carrying all physical DoFs fused in `:math:`|ket \rangle\langle bra|` order:: C---T---\ C---T---\ | | --1 | | --1 T--a*a--/ T--a*a--/ \ / \ / \ | | 2 0 for open_sites=[], or 0 for non-empty open_sites """ assert corner in ['LU','RU','RD','LD'],"Invalid choice of corner: "+corner a = double_layer_f(state, coord, open_sites, force_cpu=force_cpu,\ verbosity=verbosity) if corner == 'LU': if force_cpu: C = env.C[(state.vertexToSite(coord), (-1, -1))].to('cpu') T1 = env.T[(state.vertexToSite(coord), (0, -1))].to('cpu') T2 = env.T[(state.vertexToSite(coord), (-1, 0))].to('cpu') else: C = env.C[(state.vertexToSite(coord), (-1, -1))] T1 = env.T[(state.vertexToSite(coord), (0, -1))] T2 = env.T[(state.vertexToSite(coord), (-1, 0))] # C--10--T1--2 # 0 1 C2x2_LU = contract(C, T1, ([1], [0])) # C------T1--2->1(-) # 0 1->0(-) # 0 # T2--2->3(-) # 1->2(-) C2x2_LU = contract(C2x2_LU, T2, ([0], [0])) # C----------T1--1->0(-) # | 0 # | 0 # T2--3 1----a--3(+) # 2->1(-) (+)2\... C2x2_LU = contract(C2x2_LU, a, ([0, 3], [0, 1])) # permute 0123...->1203... # reshape (12)(03)...->01... # C2x2--1(-) # |\... # 0(-) fuse_axes= ((1,2),(0,3)) if len(open_sites)==0 else ((1,2),(0,3),4) C2x2_LU = C2x2_LU.fuse_legs(axes=fuse_axes) if verbosity > 1: print("C2X2 LU " + str(coord) + "->" + str(state.vertexToSite(coord))\ + " (-1,-1): " + str(C2x2_LU.show_properties())) return C2x2_LU elif corner == 'RU': if force_cpu: C = env.C[(state.vertexToSite(coord), (1, -1))].to('cpu') T1 = env.T[(state.vertexToSite(coord), (1, 0))].to('cpu') T2 = env.T[(state.vertexToSite(coord), (0, -1))].to('cpu') else: C = env.C[(state.vertexToSite(coord), (1, -1))] T1 = env.T[(state.vertexToSite(coord), (1, 0))] T2 = env.T[(state.vertexToSite(coord), (0, -1))] # 0--C # 1 # 0 # 1--T1 # 2 C2x2_RU = contract(C, T1, ([1], [0])) # (+)2<-0--T2--2 0--C # (-)3<-1 | # (+)0<-1--T1 # (-)1<-2 C2x2_RU = contract(C2x2_RU, T2, ([0], [2])) # (+)1<-2--T2------C # .. 3 | # \0 | # (-)2<-1--a--3 0--T1 # (-)3<-2 (-)0<-1 C2x2_RU = contract(C2x2_RU, a, ([0, 3], [3, 0])) # permute 0123...->1203... # reshape (12)(03)...->01... # (+)0--C2x2 # ../| # 1(-) fuse_axes= ((1,2),(0,3)) if len(open_sites)==0 else ((1,2),(0,3),4) C2x2_RU = C2x2_RU.fuse_legs(axes=fuse_axes) if verbosity > 1: print("C2X2 RU " + str((coord[0] + vec[0], coord[1] + vec[1])) + "->"\ + str(shitf_coord) + " (1,-1): " + str(C2x2_RU.show_properties())) return C2x2_RU elif corner == 'RD': if force_cpu: C = env.C[(state.vertexToSite(coord), (1, 1))].to('cpu') T1 = env.T[(state.vertexToSite(coord), (0, 1))].to('cpu') T2 = env.T[(state.vertexToSite(coord), (1, 0))].to('cpu') else: C = env.C[(state.vertexToSite(coord), (1, 1))] T1 = env.T[(state.vertexToSite(coord), (0, 1))] T2 = env.T[(state.vertexToSite(coord), (1, 0))] # 1<-0 0 # 2<-1--T1--2 1--C C2x2_RD = contract(C, T1, ([1], [2])) # (+)2<-0 # (+)3<-1--T2 # 2 # (+)0<-1 0 # (+)1<-2--T1---C C2x2_RD = contract(C2x2_RD, T2, ([0], [2])) # (-)2<-0 (+)1<-2 # (-)3<-1--a--3 3--T2 # 2\... | # 0 | # (+)0<-1--T1------C C2x2_RD = contract(C2x2_RD, a, ([0, 3], [2, 3])) # permute 0123...->1203... # reshape (12)(03)...->01... # (+)0 ... # |/ # (+)1--C2x2 fuse_axes= ((1,2),(0,3)) if len(open_sites)==0 else ((1,2),(0,3),4) C2x2_RD = C2x2_RD.fuse_legs(axes=fuse_axes) if verbosity > 1: print("C2X2 RD " + str((coord[0] + vec[0], coord[1] + vec[1])) + "->"\ + str(shitf_coord) + " (1,1): " + str(C2x2_RD.show_properties())) return C2x2_RD elif corner == 'LD': if force_cpu: C = env.C[(state.vertexToSite(coord), (-1, 1))].to('cpu') T1 = env.T[(state.vertexToSite(coord), (-1, 0))].to('cpu') T2 = env.T[(state.vertexToSite(coord), (0, 1))].to('cpu') else: C = env.C[(state.vertexToSite(coord), (-1, 1))] T1 = env.T[(state.vertexToSite(coord), (-1, 0))] T2 = env.T[(state.vertexToSite(coord), (0, 1))] # 0->1 # T1--2 # 1 # 0 # C--1->0 C2x2_LD = contract(C, T1, ([0], [1])) # 1->0(+) # T1--2->1(-) # | # | 0->2(-) # C--0 1--T2--2->3(-) C2x2_LD = contract(C2x2_LD, T2, ([0], [1])) # 0(+) 0->2(-) # T1--1 1--a--3(+) # | 2\... # | 2 # C--------T2--3->1(-) C2x2_LD = contract(C2x2_LD, a, ([1, 2], [1, 2])) # permute 0123...->0213... # reshape (02)(13)...->01... # (+)0 ... # |/ # C2x2--1(-) fuse_axes= ((0,2),(1,3)) if len(open_sites)==0 else ((0,2),(1,3),4) C2x2_LD = C2x2_LD.fuse_legs(axes=fuse_axes) if verbosity > 1: print("C2X2 LD " + str((coord[0] + vec[0], coord[1] + vec[1])) + "->"\ + str(shitf_coord) + " (-1,1): " + str(C2x2_LD.show_properties())) return C2x2_LD def enlarged_corner(coord, state, env, corner, open_sites=[], force_cpu=False, verbosity=0): return _enlarged_corner(coord,state,env,corner,double_layer_a,\ open_sites=open_sites,force_cpu=force_cpu,verbosity=verbosity)