Пример #1
0
def get_T(pars):
    # We always get the invariant tensor here, and cast it to the
    # non-invariant if needed. This gets around the silly fact that the
    # basis of the original tensor depends on symmetry_tensors,
    # something that should be fixed.
    T = tensordispenser.get_tensor(pars, iter_count=0,
                                   symmetry_tensors=True)[0]
    if not pars["symmetry_tensors"]:
        T = Tensor.from_ndarray(T.to_ndarray())
    log_fact = 0
    Fs = []
    Ns = []
    cum = T
    for i in range(1, pars["n_normalization"]):
        cum = toolbox.contract2x2(cum)
        log_fact *= 4
        m = cum.abs().max()
        if m != 0:
            cum /= m
            log_fact += np.log(m)
        N = 4**i
        F = np.log(scon(cum, [1, 2, 1, 2]).value()) + log_fact
        Fs.append(F)
        Ns.append(N)
    A, B = np.polyfit(Ns[pars["n_discard"]:], Fs[pars["n_discard"]:], 1)
    T /= np.exp(A)
    return T
Пример #2
0
def get_KW_unitary(pars):
    eye = np.eye(2, dtype=np.complex_)
    CZ = Csigma_np("z")
    U = scon(
        (CZ, R_np(np.pi / 4, 'z'), R_np(np.pi / 4, 'x'), R_np(np.pi / 4, 'y')),
        ([-1, -2, 5, 6], [-3, 5], [3, 6], [-4, 3]))
    u = symmetry_bases["ising"]
    u_dg = u.T.conjugate()
    U = scon((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
Пример #3
0
def get_initial_tensor(pars, **kwargs):
    if kwargs:
        pars = pars.copy()
        pars.update(kwargs)
    model_name = pars["model"].strip().lower()
    ham = hamiltonians[model_name](pars)
    boltz = np.exp(-pars["beta"] * ham)
    T_0 = np.einsum('ab,bc,cd,da->abcd', boltz, boltz, boltz, boltz)
    if pars["symmetry_tensors"]:
        u = symmetry_bases[model_name]
        u_dg = u.T.conjugate()
        T_0 = scon((T_0, u, u, u_dg, u_dg),
                   ([1, 2, 3, 4], [-1, 1], [-2, 2], [3, -3], [4, -4]))
        cls, dim, qim = symmetry_classes_dims_qims[model_name]
        T_0 = cls.from_ndarray(T_0,
                               shape=[dim] * 4,
                               qhape=[qim] * 4,
                               dirs=[1, 1, -1, -1])
    else:
        T_0 = Tensor.from_ndarray(T_0)
    return T_0
Пример #4
0
def get_D(t, pars):
    ham = (-pars["J"] * np.array([[1, -1], [-1, 1]], dtype=pars["dtype"]) +
           pars["H"] * np.array([[-1, 0], [0, 1]], dtype=pars["dtype"]))
    boltz = np.exp(-pars["beta"] * ham)
    ham_g = -pars["g"] * pars["J"] * np.array([[1, -1], [-1, 1]],
                                              dtype=pars["dtype"])
    boltz_g = np.exp(-pars["beta"] * ham_g)
    ones = np.ones((2, 2), dtype=pars["dtype"])
    D = np.einsum('ab,bc,cd,da->abcd', boltz, boltz_g, boltz_g, boltz)
    u = np.array([[1, 1], [1, -1]]) / np.sqrt(2)
    u_dg = u.T.conjugate()
    D = scon((D, u, u, u_dg, u_dg),
             ([1, 2, 3, 4], [-1, 1], [-2, 2], [3, -3], [4, -4]))
    if pars["symmetry_tensors"]:
        D = TensorZ2.from_ndarray(D,
                                  shape=[[1, 1]] * 4,
                                  qhape=[[0, 1]] * 4,
                                  dirs=[1, 1, -1, -1])
    else:
        D = Tensor.from_ndarray(D)
    return D
Пример #5
0
def get_KW_tensor(pars):
    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_np('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 = scon((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
Пример #6
0
def generate_initial_tensors(pars):
    ham = (-pars["J"] * np.array([[1, -1], [-1, 1]], dtype=pars["dtype"]) +
           pars["H"] * np.array([[-1, 0], [0, 1]], dtype=pars["dtype"]))
    boltz = np.exp(-pars["beta"] * ham)
    ham_g = -pars["g"] * pars["J"] * np.array([[1, -1], [-1, 1]],
                                              dtype=pars["dtype"])
    boltz_g = np.exp(-pars["beta"] * ham_g)
    ones = np.ones((2, 2), dtype=pars["dtype"])
    D = np.einsum('ab,bc,cd,da->abcd', boltz, boltz_g, boltz_g, boltz)
    if pars["symmetry_tensors"]:
        u = np.array([[1, 1], [1, -1]]) / np.sqrt(2)
        u_dg = u.T.conjugate()
        D = scon((D, u, u, u_dg, u_dg),
                 ([1, 2, 3, 4], [-1, 1], [-2, 2], [3, -3], [4, -4]))
        D = TensorZ2.from_ndarray(D,
                                  shape=[[1, 1]] * 4,
                                  qhape=[[0, 1]] * 4,
                                  dirs=[1, 1, -1, -1])
    else:
        D = Tensor.from_ndarray(D)
    T = initialtensors.get_initial_tensor(pars, iter_count=0)
    A_list = [D, T]
    log_fact_list = [0, 0]
    return A_list, log_fact_list
Пример #7
0
def get_cft_data(pars):
    T = get_T(pars)

    scaldims_by_alpha = {}
    if pars["do_momenta"]:
        momenta_by_alpha = {}
    if pars["do_eigenvectors"]:
        evects_by_alpha = {}
    for alpha in pars["defect_angles"]:
        print("Building the matrix to diagonalize.")
        T_first = get_T_first(T, pars, alpha=alpha)

        # Get the eigenvalues and their logarithms.
        block_width = pars["block_width"]
        n_dims_do = pars["n_dims_do"]

        if pars["do_momenta"]:
            translation = list(range(1, block_width)) + [0]
        else:
            translation = range(block_width)
        scon_list = [T_first] + [T] * (block_width - 1)
        index_list = [[block_width * 2, -101, 2, -1]]
        for i in range(2, block_width + 1):
            index_list += [[2 * i - 2, -100 - i, 2 * i, -(2 * i - 1)]]
        if pars["KW"] and pars["do_momenta"]:
            U = initialtensors.get_KW_unitary(pars)
            scon_list += [U]
            for l in index_list:
                l[0] += 2
                l[2] += 2
                l[3] += -2
            index_list[0][3] *= -1
            index_list[1][3] *= -1
            U_indices = [3, 5, -1, -2]
            index_list.append(U_indices)

        if not pars["symmetry_tensors"]:
            # Cast to non-invariant tensors.
            scon_list = [
                Tensor.from_ndarray(T.to_ndarray()) for T in scon_list
            ]

        hermitian = not pars["do_momenta"]
        res = scon_sparseeig(scon_list,
                             index_list,
                             translation,
                             range(block_width),
                             hermitian=hermitian,
                             return_eigenvectors=pars["do_eigenvectors"],
                             qnums_do=pars["qnums_do"],
                             maxiter=500,
                             tol=1e-8,
                             k=pars["n_dims_do"])
        if pars["do_eigenvectors"]:
            es, evects = res
        else:
            es = res

        # Convert es to complex for taking the log.
        es = es.astype(np.complex_, copy=False)
        # Log and scale the eigenvalues.
        block_width = pars["block_width"]
        if pars["KW"]:
            block_width -= 0.5
        log_es = es.log() * block_width / (2 * np.pi)

        # Extract the central charge.
        if alpha == 0:
            if pars["KW"]:
                c = (log_es.real().max() + 0.0625) * 12
            else:
                c = log_es.real().max() * 12
        try:
            log_es -= c / 12
        except NameError:
            raise ValueError("Need to provide 0 in defect_angles to be able "
                             "to obtain the central charge.")
        log_es *= -1
        scaldims = log_es.real()
        if (not pars["symmetry_tensors"]) and pars["sep_qnums"]:
            qnums = qnums_from_eigenvectors(evects, pars)
            scaldims = separate_vector_by_qnum(scaldims, qnums, pars)
        scaldims_by_alpha[alpha] = scaldims
        if pars["do_momenta"]:
            momenta = log_es.imag()
            if (not pars["symmetry_tensors"]) and pars["sep_qnums"]:
                momenta = separate_vector_by_qnum(momenta, qnums, pars)
            momenta_by_alpha[alpha] = momenta
        if pars["do_eigenvectors"]:
            evects_by_alpha[alpha] = evects
    ret_val = (scaldims_by_alpha, c)
    if pars["do_momenta"]:
        ret_val += (momenta_by_alpha, )
    if pars["do_eigenvectors"]:
        ret_val += (evects_by_alpha, )
    return ret_val
Пример #8
0
            else:
                dirs2 = None
            T2 = rtensor(shape=shp2, qhape=qhp2, dirs=dirs2)
            T2_orig = T2.copy()
            T1_np = T1.to_ndarray()
            T2_np = T2.to_ndarray()
            T = T1.dot(T2, (i_list, j_list))
            assert ((T1 == T1_orig).all())
            assert ((T2 == T2_orig).all())
            test_internal_consistency(T)
            i_list_compl = sorted(set(range(len(shp1))) - set(i_list))
            j_list_compl = sorted(set(range(len(shp2))) - set(j_list))
            product_shp = [shp1[i] for i in i_list_compl]\
                          + [shp2[j] for j in j_list_compl]
            if type(T) == Tensor:
                product_shp = Tensor.flatten_shape(product_shp)
            assert (T.shape == product_shp)
            T_np = np.tensordot(T1_np, T2_np, (i_list, j_list))
            assert (np.allclose(T_np, T.to_ndarray()))

            # Products of non-invariant vectors.
            n1 = np.random.randint(1, 3)
            T1 = rtensor(n=n1, chilow=1, invar=(n1 != 1))

            n2 = np.random.randint(1, 3)
            shp2 = rshape(n=n2, chilow=1)
            qhp2 = rqhape(shape=shp2)
            dirs2 = rdirs(shape=shp2)
            c2 = rcharge()
            shp2[0] = T1.shape[-1]
            if T1.qhape is not None: