def get_initial_tensor_CDL_3d(pars): delta = np.eye(2, dtype=pars["dtype"]) A = np.einsum( ("ae,fi,jm,nb,cq,rk,lu,vd,gs,to,pw,xh -> abcdefghijklmnopqrstuvwx"), *((delta,) * 12) ) return Tensor.from_ndarray(A.reshape((16, 16, 16, 16, 16, 16)))
def get_initial_tensor_CQL_3d(pars): delta = np.array([[[1, 0], [0, 0]], [[0, 0], [0, 1]]]) A = np.einsum( ("aeu,fiv,gjq,hbr,mcw,nxk,ols,ptd " "-> abcdefghijklmnopqrstuvwx"), *((delta,) * 8) ) return Tensor.from_ndarray(A.reshape((16, 16, 16, 16, 16, 16)))
def get_KW_unitary(pars): """ The unitary that moves the Kramers-Wannier duality defect of the classical 2D square lattice Ising model. """ CZ = Csigma_np("z") # fmt: off U = ncon((CZ, R(np.pi / 4, 'z'), R(np.pi / 4, 'x'), R(np.pi / 4, 'y')), ([-1, -2, 5, 6], [-3, 5], [3, 6], [-4, 3])) # fmt: on u = symmetry_bases["ising"] u_dg = u.T.conjugate() U = ncon( (U, u, u_dg, u_dg, u), ([1, 2, 3, 4], [-1, 1], [-2, 2], [3, -3], [4, -4]), ) U *= -1j if pars["symmetry_tensors"]: U = TensorZ2.from_ndarray( U, shape=[[1, 1]] * 4, qhape=[[0, 1]] * 4, dirs=[1, 1, -1, -1] ) else: U = Tensor.from_ndarray(U, dirs=[1, 1, 1, -1, -1, -1]) return U
def get_initial_sixvertex_tensor(pars): try: a = pars["sixvertex_a"] b = pars["sixvertex_b"] c = pars["sixvertex_c"] except KeyError: u = pars["sixvertex_u"] lmbd = pars["sixvertex_lambda"] rho = pars["sixvertex_rho"] a = rho * np.sin(lmbd - u) b = rho * np.sin(u) c = rho * np.sin(lmbd) A_0 = np.zeros((2, 2, 2, 2), dtype=pars["dtype"]) A_0[1, 0, 0, 1] = a A_0[0, 1, 1, 0] = a A_0[0, 0, 1, 1] = b A_0[1, 1, 0, 0] = b A_0[0, 1, 0, 1] = c A_0[1, 0, 1, 0] = c if pars["symmetry_tensors"]: dim = [1, 1] qim = [-1, 1] A_0 = TensorU1.from_ndarray( A_0, shape=[dim] * 4, qhape=[qim] * 4, dirs=[1, 1, 1, 1] ) A_0 = A_0.flip_dir(2) A_0 = A_0.flip_dir(3) else: A_0 = Tensor.from_ndarray(A_0) return A_0
def convertAbe(A): """ Convert A to class abeliantensors if it is not """ if type(A).__module__.split(".")[0] != 'abeliantensors': A = Tensor.from_ndarray(A) return A
def get_initial_impurity(pars, legs=(3,), factor=3, **kwargs): if kwargs: pars = pars.copy() pars.update(kwargs) A_pure = get_initial_tensor(pars) model = pars["model"] impurity = pars["impurity"] try: impurity_matrix = impurity_dict[model][impurity](pars) except KeyError: msg = "Unknown (model, impurity) combination: ({}, {})".format( model, impurity ) raise ValueError(msg) # TODO The expectation that everything is in the symmetry basis # clashes with how 2D ising and potts initial tensors are generated. if not pars["symmetry_tensors"]: impurity_matrix = Tensor.from_ndarray(impurity_matrix.to_ndarray()) # TODO This was commented in before 2019-09-06. Why? It's clearly wrong # for 3D Ising U-impurity and id-impurity. # impurity_matrix *= -1 A_impure = 0 if 0 in legs: A_impure += ncon( (A_pure, impurity_matrix), ([1, -2, -3, -4, -5, -6], [1, -1]) ) if 1 in legs: A_impure += ncon( (A_pure, impurity_matrix), ([-1, 2, -3, -4, -5, -6], [2, -2]) ) if 2 in legs: A_impure += ncon( (A_pure, impurity_matrix.transpose()), ([-1, -2, 3, -4, -5, -6], [3, -3]), ) if 3 in legs: A_impure += ncon( (A_pure, impurity_matrix.transpose()), ([-1, -2, -3, 4, -5, -6], [4, -4]), ) if 4 in legs: A_impure += ncon( (A_pure, impurity_matrix), ([-1, -2, -3, -4, 5, -6], [5, -5]) ) if 5 in legs: A_impure += ncon( (A_pure, impurity_matrix.transpose()), ([-1, -2, -3, -4, -5, 6], [6, -6]), ) # TODO This was commented in before 2019-09-06. Why? It's clearly wrong # for 3D Ising U-impurity and id-impurity. # A_impure *= factor return A_impure
def get_initial_tensor_CDL_3d_v2(pars): delta = np.eye(2, dtype=pars["dtype"]) A = ncon( (delta,) * 12, # fmt: off ( [-11, -21], [-12, -41], [-13, -51], [-14, -61], [-31, -22], [-32, -42], [-33, -52], [-34, -62], [-23, -63], [-64, -43], [-44, -53], [-54, -24], ), # fmt: on ) return Tensor.from_ndarray(A.reshape((16, 16, 16, 16, 16, 16)))
def get_initial_tensor_ising_3d(pars): beta = pars["beta"] ham = ising3d_ham(beta) A_0 = np.einsum( "ai,aj,ak,al,am,an -> ijklmn", ham, ham, ham, ham, ham, ham ) if pars["symmetry_tensors"]: cls, dim, qim = TensorZ2, [1, 1], [0, 1] A_0 = cls.from_ndarray( A_0, shape=[dim] * 6, qhape=[qim] * 6, dirs=[1, 1, -1, -1, 1, -1] ) else: A_0 = Tensor.from_ndarray(A_0) return A_0
def get_initial_dilute_sixvertex_tensor(pars): # Copied and adapted from Roman # 1 # | # 4 -- A -- 2 # | # 3 # "dilute six-vertex model", # states : 0:empty, 1:top arrow, 1:bot arrow. Time flows toward N-E w = np.exp(1j * np.pi / 8.0) z = 0.57 # Close to critical # z = 1.0 # XXZ universality class A = np.zeros((3, 3, 3, 3), dtype=np.complex) A[1, 1, 1, 1] = 1.0 A[2, 1, 1, 2] = z * w A[1, 2, 2, 1] = z / w A[0, 1, 1, 0] = z / w A[1, 0, 0, 1] = z * w A[2, 0, 1, 1] = z / w A[0, 2, 1, 1] = z * w A[1, 1, 2, 0] = z * w A[1, 1, 0, 2] = z / w A[2, 2, 2, 2] = z ** 2 A[0, 0, 0, 0] = z ** 2 A[2, 0, 2, 0] = z ** 2 A[0, 2, 0, 2] = z ** 2 A[2, 0, 0, 2] = (z ** 2) * (w ** 2 + 1.0 / w ** 2) A[0, 2, 2, 0] = (z ** 2) * (w ** 2 + 1.0 / w ** 2) # U(1) charge : Q=(-1,0,+1) Q1+Q2=Q3+Q4 if pars["symmetry_tensors"]: dim = [1, 1, 1] qim = [-1, 0, 1] A = TensorU1.from_ndarray( A, shape=[dim] * 4, qhape=[qim] * 4, dirs=[1, 1, -1, -1] ) else: A = Tensor.from_ndarray(A) # To translate between Roman's convention and mine. A = A.transpose((3, 0, 1, 2)) return A
def get_initial_tensor(pars, **kwargs): if kwargs: pars = pars.copy() pars.update(kwargs) model_name = pars["model"].strip().lower() if model_name == "dilute_sixvertex": return get_initial_dilute_sixvertex_tensor(pars) elif model_name == "sixvertex": return get_initial_sixvertex_tensor(pars) elif model_name == "ising3d": return get_initial_tensor_ising_3d(pars) elif model_name == "potts33d": return get_initial_tensor_potts33d(pars) elif model_name == "complexion_qising": ham = get_ham(pars, model="qising") complexion = build_complexion(ham, pars) return complexion elif model_name == "complexion_qising_tricrit": ham = get_ham(pars, model="qising_tricrit") complexion = build_complexion(ham, pars) return complexion elif model_name == "complexion_sq_qising": ham = get_ham(pars, model="qising") complexion = build_complexion(ham, pars, square_hamiltonian=True) return complexion else: ham = hamiltonians[model_name](pars) boltz = np.exp(-pars["beta"] * ham) A_0 = np.einsum("ab,bc,cd,da->abcd", boltz, boltz, boltz, boltz) u = symmetry_bases[model_name] u_dg = u.T.conjugate() A_0 = ncon( (A_0, u, u, u_dg, u_dg), ([1, 2, 3, 4], [-1, 1], [-2, 2], [3, -3], [4, -4]), ) if pars["symmetry_tensors"]: cls, dim, qim = symmetry_classes_dims_qims[model_name] A_0 = cls.from_ndarray( A_0, shape=[dim] * 4, qhape=[qim] * 4, dirs=[1, 1, -1, -1] ) else: A_0 = Tensor.from_ndarray(A_0) return A_0
def get_initial_tensor_potts33d(pars): beta = pars["beta"] Q = potts_Q(beta, 3) A = np.einsum( "ai,aj,ak,al,am,an -> ijklmn", Q, Q, Q.conjugate(), Q.conjugate(), Q, Q.conjugate(), ) if np.linalg.norm(np.imag(A)) < 1e-12: A = np.real(A) if pars["symmetry_tensors"]: cls, dim, qim = symmetry_classes_dims_qims["potts3"] A = cls.from_ndarray( A, shape=[dim] * 6, qhape=[qim] * 6, dirs=[1, 1, -1, -1, 1, -1] ) else: A = Tensor.from_ndarray(A) return A
def get_KW_tensor(pars): """ The Kramers-Wannier duality defect of the classical 2D square lattice Ising model. """ eye = np.eye(2, dtype=np.complex_) ham = hamiltonians["ising"](pars) B = np.exp(-pars["beta"] * ham) H = np.array([[1, 1], [1, -1]], dtype=np.complex_) / np.sqrt(2) y_trigged = np.ndarray((2, 2, 2), dtype=np.complex_) y_trigged[:, :, 0] = eye y_trigged[:, :, 1] = sigma("y") D_sigma = np.sqrt(2) * np.einsum( "ab,abi,ic,ad,adk,kc->abcd", B, y_trigged, H, B, y_trigged.conjugate(), H, ) u = symmetry_bases["ising"] u_dg = u.T.conjugate() D_sigma = ncon( (D_sigma, u, u, u_dg, u_dg), ([1, 2, 3, 4], [-1, 1], [-2, 2], [3, -3], [4, -4]), ) if pars["symmetry_tensors"]: D_sigma = TensorZ2.from_ndarray( D_sigma, shape=[[1, 1]] * 4, qhape=[[0, 1]] * 4, dirs=[1, 1, -1, -1], ) else: D_sigma = Tensor.from_ndarray(D_sigma, dirs=[1, 1, -1, -1]) return D_sigma