Beispiel #1
0
def waves_particle_hole(config, m):
    m_ph = m.copy()

    m_ph[:m.shape[0] // 2, :m.shape[1] // 2] = models.apply_TBC(
        config,
        config.twist,
        deepcopy(m_ph[:m.shape[0] // 2, :m.shape[1] // 2]),
        inverse=False)
    m_ph[m.shape[0] // 2:, m.shape[1] // 2:] = -models.apply_TBC(
        config,
        config.twist,
        deepcopy(m_ph[m.shape[0] // 2:, m.shape[1] // 2:]).T,
        inverse=True)
    return m_ph
    def __init__(self, config, K_up=None, K_down=None):
        self.config = config
        t = time()
        K_matrix_up = K_up if K_up is not None else models.apply_TBC(
            self.config,
            self.config.twist,
            deepcopy(self.config.K_0),
            inverse=False)
        K_matrix_down = K_down if K_down is not None else models.apply_TBC(
            self.config,
            self.config.twist,
            deepcopy(self.config.K_0).T,
            inverse=True)
        print('apply pbc takes {:.15f}'.format(time() - t))

        self.edges_quadratic = scipy.linalg.block_diag(K_matrix_up,
                                                       -K_matrix_down)
Beispiel #3
0
def test_BC_twist(config):
    twist = np.exp(2.0j * np.pi * np.random.uniform(0, 1, size=2))
    print('Testing BC twist is invertable, with twist ' + str(twist), flush=True)
    for name, gap in zip(config.pairings_list_names, config.pairings_list_unwrapped):
        assert np.allclose(gap, models.apply_TBC(config, twist, models.apply_TBC(config, twist, deepcopy(gap), inverse = False), inverse=True))
        print('Passed {:s}'.format(name))

    twist_2 = np.exp(2.0j * np.pi * np.random.uniform(0, 1, size=2))
    print('Testing BC twist is U(1) representation, with twists ' + str(twist) + ' ' + str(twist_2), flush=True)
    for name, gap in zip(config.pairings_list_names, config.pairings_list_unwrapped):
        assert np.allclose(models.apply_TBC(config, twist_2, models.apply_TBC(config, twist, deepcopy(gap), inverse = False), inverse=False), \
                models.apply_TBC(config, twist, models.apply_TBC(config, twist_2, deepcopy(gap), inverse = False), inverse=False))
        print('Passed {:s}'.format(name))
    print('Passed', flush=True)
    return True
Beispiel #4
0
def test_FT_BC_twist(config):
    K0 = config.K_0

    nbands = config.n_orbitals * config.n_sublattices

    for _ in range(100):
        #twist = np.array([0.5, 0.5]) #
        twist = np.random.uniform(0, 1, size=2) 
        fft_plus = get_fft(config.Ls, nbands // 2, twist)
        fft_minus = get_fft(config.Ls, nbands // 2, np.array([-twist[0], -twist[1]]))
        
        K0_twisted = models.apply_TBC(config, np.exp(1.0j * 2.0 * np.pi * twist), deepcopy(K0), inverse = False)
        K0_twisted_plus = K0_twisted[np.arange(0, K0_twisted.shape[0], 2), :]; K0_twisted_plus = K0_twisted_plus[:, np.arange(0, K0_twisted.shape[0], 2)]
        K0_twisted_minus = K0_twisted[np.arange(1, K0_twisted.shape[0], 2), :]; K0_twisted_minus = K0_twisted_minus[:, np.arange(1, K0_twisted.shape[0], 2)]

        K0_twisted_plus = fft_plus.conj().T.dot(K0_twisted_plus.dot(fft_plus))
        K0_twisted_minus = fft_minus.conj().T.dot(K0_twisted_minus.dot(fft_minus))

        K0_check = K0_twisted_plus.copy()


        for i in range(K0.shape[0] // nbands):
            K0_check[i * nbands // 2:i * nbands // 2 + nbands // 2,i * nbands // 2:i * nbands // 2 + nbands // 2] = 0.0
        if not np.isclose(np.sum(np.abs(K0_check)), 0.0):
            print('plus valley twist BC test failed with twist', twist)
            exit(-1)
            return False


        K0_check = K0_twisted_minus.copy()
        for i in range(K0.shape[0] // nbands):
            K0_check[i * nbands // 2:i * nbands // 2 + nbands // 2,i * nbands // 2:i * nbands // 2 + nbands // 2] = 0.0
        if not np.isclose(np.sum(np.abs(K0_check)), 0.0):
            print('minus valley twist BC test failed with twist', twist)
            exit(-1)
            return False

    print('Passed', flush=True)
    return True
Beispiel #5
0
def get_kinetic_orbitals(config, filling):
    Ls = config.Ls
    K0 = config.K_0
    assert config.twist_mesh == 'PBC'

    Tx, Ty = pairings.Tx_symmetry_map, pairings.Ty_symmetry_map
    C3z = np.argmax(np.abs(pairings.C3z_symmetry_map_chiral), axis=0)
    C2y = np.argmax(np.abs(pairings.C2y_symmetry_map_chiral), axis=0)
    tx, ty = [], []

    for i in range(Tx.shape[0]):
        assert len(np.where(Tx[i, :] == 1)[0]) == 1
        assert len(np.where(Ty[i, :] == 1)[0]) == 1

        tx.append(np.where(Tx[i, :] == 1)[0][0])
        ty.append(np.where(Ty[i, :] == 1)[0][0])

    tx, ty = np.array(tx), np.array(ty)
    np.save('tx.npy', tx)
    np.save('ty.npy', ty)
    assert np.allclose(tx[ty], ty[tx])

    tx_valley = tx[::2] // 2
    ty_valley = ty[::2] // 2
    assert np.allclose(tx_valley[ty_valley], ty_valley[tx_valley])
    valley = np.concatenate(
        [np.array([2 * i + 1, 2 * i]) for i in range(config.Ls**2 * 2)])

    path = '/home/astronaut/Documents/all_Imada_formats/'

    ########### writing the spin locations (none) ##########
    f = open(os.path.join(path, 'locspn_{:d}.def'.format(Ls)), 'w')
    f.write('================================\n')
    f.write('NlocalSpin     0\n')
    f.write('================================\n')
    f.write('========i_0LocSpn_1IteElc ======\n')
    f.write('================================\n')
    for i in range(Ls**2 * 4):
        f.write('    {:d}      0\n'.format(i))
    f.close()

    symmetries = [np.arange(Ls**2 * 4)]
    ########### writing the translational symmetries ##########
    f = open(os.path.join(path, 'qptransidx_{:d}.def'.format(Ls)), 'w')
    f.write('=============================================\n')
    f.write('NQPTrans          {:d}\n'.format(len(symmetries)))
    f.write('=============================================\n')
    f.write('======== TrIdx_TrWeight_and_TrIdx_i_xi ======\n')
    f.write('=============================================\n')

    for i in range(len(symmetries)):
        f.write('{:d}    1.00000\n'.format(i))

    for i, symm in enumerate(symmetries):
        for i_from in range(symm.shape[0]):
            f.write('    {:d}      {:d}      {:d}\n'.format(
                i, i_from, symm[i_from]))
    f.close()

    from copy import deepcopy
    ########### writing the jastrows ##########
    all_translations = [np.arange(Ls**2 * 4)]
    curr_trans = tx.copy()
    all_new_translations = []
    for kx in range(config.Ls - 1):
        new_translations = [symm[curr_trans] for symm in all_translations]
        all_new_translations.append(deepcopy(new_translations))
        curr_trans = curr_trans[tx]
    for d in all_new_translations:
        all_translations += d

    curr_trans = ty.copy()
    all_new_translations = []
    for kx in range(config.Ls - 1):
        new_translations = [symm[curr_trans] for symm in all_translations]
        all_new_translations.append(deepcopy(new_translations))
        curr_trans = curr_trans[ty]
    for d in all_new_translations:
        all_translations += d

    f = open(os.path.join(path, 'jastrowidx_TRSbroken_{:d}.def'.format(Ls)),
             'w')
    jastrow_ij, jastrow_k, n_jastrows, matrix_jastrows = get_jastrow_fromshift(
        all_translations,
        config.Ls,
        np.around(np.array(config.all_distances), decimals=5),
        dist_threshold=5.)
    np.save('check.npy', matrix_jastrows)
    # G)

    assert np.allclose(matrix_jastrows, matrix_jastrows.T)

    matrix_jastrows_trans = matrix_jastrows.copy()
    matrix_jastrows_trans = matrix_jastrows_trans[:, tx]
    matrix_jastrows_trans = matrix_jastrows_trans[tx, :]
    assert np.allclose(matrix_jastrows_trans, matrix_jastrows)

    matrix_jastrows_trans = matrix_jastrows.copy()
    matrix_jastrows_trans = matrix_jastrows_trans[:, ty]
    matrix_jastrows_trans = matrix_jastrows_trans[ty, :]
    assert np.allclose(matrix_jastrows_trans, matrix_jastrows)

    f.write('=============================================\n')
    f.write('NJastrowIdx         {:d}\n'.format(n_jastrows + 1))
    f.write('ComplexType          {:d}\n'.format(0))
    f.write('=============================================\n')
    f.write('=============================================\n')

    uniques = []
    for i in range(config.Ls**2 * 4):
        for j in range(config.Ls**2 * 4):
            if i == j:
                continue
            f.write('    {:d}      {:d}      {:d}\n'.format(
                i, j, matrix_jastrows[i, j]))

    for i in range(n_jastrows + 1):
        f.write('    {:d}      1\n'.format(i))
    f.close()

    f = open(os.path.join(path, 'InJastrow_TRSbroken_{:d}.def'.format(Ls)),
             'w')
    f.write('======================\n')
    f.write('NJastrowIdx  {:d}\n'.format(n_jastrows + 1))
    f.write('======================\n')
    f.write('== i_j_JastrowIdx  ===\n')
    f.write('======================\n')
    for i in range(n_jastrows):
        f.write('{:d} {:.10f}  {:.10f}\n'.format(i, \
                np.random.uniform(0.0, 1.0) * 0, np.random.uniform(0.0, 1.0) * 0))
    f.write('{:d} {:.10f}  {:.10f}\n'.format(n_jastrows, 0, 0))
    f.close()

    f = open(os.path.join(path, 'gutzwilleridx_{:d}.def'.format(Ls)), 'w')

    f.write('=============================================\n')
    f.write('NGutzwillerIdx          {:d}\n'.format(1))
    f.write('ComplexType          {:d}\n'.format(0))
    f.write('=============================================\n')
    f.write('=============================================\n')

    for i in range(4 * Ls**2):
        f.write('    {:d}      {:d}\n'.format(i, 0))  #idx))
    for i in range(1):
        f.write('    {:d}      1\n'.format(i))
    f.close()

    f = open(os.path.join(path, 'InGutzwiller.def'), 'w')
    f.write('======================\n')
    f.write('NGutzwillerIdx  {:d}\n'.format(1))
    f.write('======================\n')
    f.write('== i_j_GutzwillerIdx  ===\n')
    f.write('======================\n')
    for i in range(1):
        f.write('{:d} {:.10f}  {:.10f}\n'.format(
            i,
            np.random.uniform(0.0, 1.0) * 0,
            np.random.uniform(0.0, 1.0) * 0))
    f.close()

    ########### writing the modpara ##########
    f = open(os.path.join(path, 'modpara_{:d}_{:d}.def'.format(Ls, filling)),
             'w')

    f.write('--------------------\n')
    f.write('Model_Parameters   0\n')
    f.write('--------------------\n')
    f.write('VMC_Cal_Parameters\n')
    f.write('--------------------\n')
    f.write('CDataFileHead  zvo\n')
    f.write('CParaFileHead  zqp\n')
    f.write('--------------------\n')
    f.write('NVMCCalMode    0\n')
    f.write('--------------------\n')
    f.write('NDataIdxStart  1\n')
    f.write('NDataQtySmp    1\n')
    f.write('--------------------\n')
    f.write('Nsite          {:d}\n'.format(Ls**2 * 4))
    f.write('Ncond          {:d}\n'.format(filling))
    f.write('2Sz            0\n')
    f.write('NSPGaussLeg    8\n')
    f.write('NSPStot        0\n')
    f.write('NMPTrans       {:d}\n'.format(1))
    f.write('NSROptItrStep  400\n')
    f.write('NSROptItrSmp   40\n')
    f.write('DSROptRedCut   0.0000001000\n')
    f.write('DSROptStaDel   0.0200000000\n')
    f.write('DSROptStepDt   0.0000020000\n')
    f.write('NVMCWarmUp     400\n')
    f.write('NVMCInterval   1\n')
    f.write('NVMCSample     4000\n')
    f.write('NExUpdatePath  0\n')
    f.write('RndSeed        1\n')
    f.write('NSplitSize     1\n')
    f.write('NStore         0\n')
    f.write('NSRCG          1\n')
    f.close()

    twist = (0, 0.5)
    twist_exp = [
        np.exp(2 * np.pi * 1.0j * twist[0]),
        np.exp(2 * np.pi * 1.0j * twist[1])
    ]
    fft = get_fft_APBCy(config.Ls)
    for gap_idx in [40, 9, 36, 14]:
        #[0, 32, 43, 17, 11, 19]:  # 40, 43, 9, 36[!!]
        print('gap_idx = ', gap_idx)
        #if config.idx_map[gap_idx] != 13:
        #    continue

        for gap_val in [0.0, 0.003, 0.02]:
            #g = gap_val * np.load('the_wave_extended_{:d}.npy'.format(config.Ls))
            g = gap_val * np.load(
                '/home/astronaut/Documents/DQMC_TBG/gaps_8x8/gap_{:d}.npy'.
                format(gap_idx))
            # = gap_val * np.load('/home/astronaut/Documents/XQMC/gaps_6x6_extended/twist_0/gap_{:d}.npy'.format(gap_idx))
            #gap_val * np.load('/home/astronaut/Documents/DQMC_TBG/gaps_8x8/gap_{:d}.npy'.format(gap_idx))
            if config.Ls == 6:
                g = models.xy_to_chiral(g, 'pairing', config, True)

            TRS = np.concatenate(
                [np.array([2 * i + 1, 2 * i]) for i in range(g.shape[0] // 2)])
            g_TRS = g[:, TRS]
            g_TRS = g_TRS[TRS, :]
            g = g + g_TRS  # * (0.1 if gap_val == 0.02 else 1.)
            #np.save('sheck.npy', g)
            if gap_idx in [11, 19]:
                g = g / 1.0j

            # g = (g + g.conj()) / np.sqrt(2)
            print(g[0], 'g[0]')
            print(g[1], 'g[1]')

            assert np.allclose(g, g.T)
            swave = 1e-5 * models.xy_to_chiral(
                pairings.combine_product_terms(
                    config, pairings.twoorb_hex_all[1]), 'pairing', config,
                True)
            assert np.allclose(swave, swave.T)
            print(swave[0], swave[1], 'swave in chiral basis')

            g = g + swave
            gap = models.apply_TBC(config,
                                   twist_exp,
                                   deepcopy(g),
                                   inverse=False)
            #np.save('the_wave_extended_twisted_{:d}.npy'.format(config.Ls), models.apply_TBC(config, twist_exp, deepcopy(np.load('the_wave_extended_{:d}.npy'.format(config.Ls))), inverse = False))
            #exit(-1)
            gapT = models.apply_TBC(config,
                                    twist_exp,
                                    deepcopy(g).T,
                                    inverse=True)

            gap_fft = fft.T.conj().dot(gap).dot(fft)
            gap_check = gap_fft.copy()
            for i in range(gap_check.shape[0] // 4):
                #print(i % 4, i // 4)
                #(np.abs(np.linalg.eig(gap_check[i * 4:i * 4 + 4,i * 4:i * 4 + 4])[0]), i)
                # print(gap_check[i * 4:i * 4 + 4,i * 4:i * 4 + 4])
                #assert np.allclose(gap_check[i * 4:i * 4 + 4,i * 4:i * 4 + 4], gap_check[i * 4:i * 4 + 4,i * 4:i * 4 + 4].conj().T)
                gap_check[i * 4:i * 4 + 4, i * 4:i * 4 + 4] = 0.0
            assert np.isclose(np.sum(np.abs(gap_check)), 0.0)

            ############ determine required mu_BCS to start ################
            K0_up = models.apply_TBC(config,
                                     twist_exp,
                                     deepcopy(K0),
                                     inverse=False)
            K0_down = models.apply_TBC(config,
                                       twist_exp,
                                       deepcopy(K0),
                                       inverse=True)
            K0_downT = models.apply_TBC(config,
                                        twist_exp,
                                        deepcopy(K0),
                                        inverse=True).T
            K0_upT = models.apply_TBC(config,
                                      twist_exp,
                                      deepcopy(K0),
                                      inverse=False).T
            #print('energies {:d}'.format(config.Ls), np.linalg.eigh(K0_up)[0])
            #exit(-1)

            #### check twist is correct ###
            K0_fft_plus = fft.conj().T.dot(K0_up).dot(fft)
            K0_fft_minus = fft.T.dot(K0_up).dot(fft.conj())

            K0_check = K0_fft_plus.copy()
            for i in range(K0_check.shape[0] // 4):
                K0_check[i * 4:i * 4 + 4, i * 4:i * 4 + 4] = 0.0
            assert np.isclose(np.sum(np.abs(K0_check)), 0.0)

            K0_check = K0_fft_minus.copy()
            for i in range(K0_check.shape[0] // 4):
                K0_check[i * 4:i * 4 + 4, i * 4:i * 4 + 4] = 0.0
            assert np.isclose(np.sum(np.abs(K0_check)), 0.0)

            assert np.allclose(K0_up, K0_up.conj().T)
            assert np.allclose(K0_down, K0_down.conj().T)

            L = K0.shape[0]
            totalM = np.zeros((4 * L, 4 * L), dtype=np.complex128)

            totalM[:L, :L] = K0_up
            totalM[L:2 * L, L:2 * L] = K0_down
            totalM[2 * L:3 * L, 2 * L:3 * L] = -K0_upT
            totalM[3 * L:, 3 * L:] = -K0_downT
            totalM[:L, 3 * L:] = gap
            totalM[L:2 * L, 2 * L:3 * L] = -gapT
            totalM[2 * L:3 * L, L:2 * L] = -gapT.conj().T
            totalM[3 * L:, :L] = gap.conj().T
            energies = np.linalg.eigh(totalM)[
                0]  # energies with BC twist and gap

            #print(energies)
            mu_BCS = (energies[filling * 2] + energies[filling * 2 - 1]) / 2.
            print(energies[filling * 2], energies[filling * 2 - 1])
            #assert not np.isclose(energies[filling * 2], energies[filling * 2 - 1])
            print('mu_BCS = ', mu_BCS)

            K0_up = K0_up - np.eye(K0_up.shape[0]) * mu_BCS
            K0_upT = K0_upT - np.eye(K0_upT.shape[0]) * mu_BCS
            K0_down = K0_down - np.eye(K0_down.shape[0]) * mu_BCS
            K0_downT = K0_downT - np.eye(K0_downT.shape[0]) * mu_BCS

            L = K0.shape[0]
            totalM = np.zeros((4 * L, 4 * L), dtype=np.complex128)

            totalM[:L, :L] = K0_up
            totalM[L:2 * L, L:2 * L] = K0_down
            totalM[2 * L:3 * L, 2 * L:3 * L] = -K0_upT
            totalM[3 * L:, 3 * L:] = -K0_downT
            totalM[:L, 3 * L:] = gap
            totalM[L:2 * L, 2 * L:3 * L] = -gapT
            totalM[2 * L:3 * L, L:2 * L] = -gapT.conj().T
            totalM[3 * L:, :L] = gap.conj().T

            selected_idxs = np.concatenate(
                [np.arange(0, L), np.arange(3 * L, 4 * L)])
            totalM_updown = totalM[:, selected_idxs]
            totalM_updown = totalM_updown[selected_idxs, ...]

            #totalM_updown = np.zeros((2 * L, 2 * L), dtype=np.complex128)
            #totalM_updown[:L, :L] = K0; totalM_updown[L:, L:] = -K0.T;
            #totalM_updown[:L, L:] = gap; totalM_updown[L:, :L] = gap.conj().T;

            selected_idxs = np.arange(L, 3 * L)
            totalM_downup = totalM[:, selected_idxs]
            totalM_downup = totalM_downup[selected_idxs, ...]

            TRS = np.concatenate([
                np.array([2 * i + 1, 2 * i], dtype=np.int64) for i in range(L)
            ])

            #totalM_downup = np.zeros((2 * L, 2 * L), dtype=np.complex128)
            #totalM_downup[:L, :L] = K0; totalM_downup[L:, L:] = -K0.T;
            #totalM_downup[:L, L:] = -gap.T; totalM_downup[L:, :L] = -gap.conj();

            en_updown, W_updown = np.linalg.eigh(totalM_updown)

            totalM_updown_TRS = totalM_updown[TRS, ...]
            totalM_updown_TRS = totalM_updown_TRS[..., TRS]
            totalM_updown_TRS = totalM_updown_TRS.conj()

            print('after TRS, discrepancy',
                  np.sum(np.abs(totalM_updown_TRS - totalM_updown)))

            en_downup, W_downup = np.linalg.eigh(totalM_downup)
            assert np.allclose(en_updown, np.sort(-en_updown))
            assert np.allclose(en_downup, np.sort(-en_downup))
            en_total, W = np.linalg.eigh(totalM)
            #print('energies with gap', gap_val, en_total)
            #print('updown energies', en_updown)
            #print('downup energies', en_downup)

            #for en, state in zip(en_downup, W_downup.T):
            #    if np.abs(en + 0.03085819) < 1e-6:
            #        print(en, state)
            #exit(-1)

            for i in range(W_updown.shape[1] // 2):
                v = W_updown[:, i]
                en = en_updown[i]

                v_conj = v * 0.0
                v_conj[:len(v) // 2] = v[len(v) // 2:].conj()
                v_conj[len(v) // 2:] = v[:len(v) // 2].conj()

                en_conj = np.dot(v_conj.conj(),
                                 totalM_updown.dot(v_conj)) / np.dot(
                                     v_conj.conj(), v_conj)
                #print(en_conj, en, np.dot(v_conj.conj(), v_conj), np.dot(v.conj(), totalM_updown.dot(v)))
                #W_conj.append(v_conj)
                #assert np.isclose(en_conj, -en)
            #exit(-1)

            W_conj = []

            for i in range(W.shape[1] // 2):
                v = W[:, i]
                en = en_total[i]

                v_conj = v * 0.0
                v_conj[:len(v) // 2] = v[len(v) // 2:].conj()
                v_conj[len(v) // 2:] = v[:len(v) // 2].conj()

                en_conj = np.dot(v_conj.conj(), totalM.dot(v_conj))
                #print(en_conj, en)
                W_conj.append(v_conj)
                assert np.isclose(en_conj, -en)

            W_conj = np.array(W_conj).T

            W[:, W.shape[1] //
              2:] = W_conj  # make the right form -- but this makes no difference: this is only rearrangement of 2nd part of the array, while we only use the 1st part
            # why W does not protect that block form? -- or do we even need this form?

            assert np.allclose(
                np.diag(W.conj().T.dot(totalM).dot(W)).real,
                np.diag(W.conj().T.dot(totalM).dot(W)))
            assert np.allclose(
                np.sort(np.diag(W.conj().T.dot(totalM).dot(W)).real),
                np.linalg.eigh(totalM)[0])

            # with gap 6, W_pieces does not diagonalize totalM! why?
            W_pieces = np.zeros((4 * L, 4 * L), dtype=np.complex128)
            W_pieces[:L, :L] = W_updown[:L, :L]
            W_pieces[3 * L:, 3 * L:] = W_updown[L:, L:]
            W_pieces[3 * L:, :L] = W_updown[L:, :L]
            W_pieces[:L, 3 * L:] = W_updown[:L, L:]

            W_pieces[L:2 * L, L:2 * L] = W_downup[:L, :L]
            W_pieces[2 * L:3 * L, 2 * L:3 * L] = W_downup[L:, L:]
            W_pieces[2 * L:3 * L, L:2 * L] = W_downup[L:, :L]
            W_pieces[L:2 * L, 2 * L:3 * L] = W_downup[:L, L:]

            #assert np.allclose(np.sort(np.diag(W_pieces.conj().T.dot(totalM).dot(W_pieces)).real), np.sort(np.diag(W_pieces.conj().T.dot(totalM).dot(W_pieces))))
            #assert np.isclose(np.sum(np.abs(W_pieces.conj().T.dot(totalM).dot(W_pieces) - np.diag(np.diag(W_pieces.conj().T.dot(totalM).dot(W_pieces))))), 0.0)
            assert np.isclose(
                np.sum(
                    np.abs(W.conj().T.dot(totalM).dot(W) -
                           np.diag(np.diag(W.conj().T.dot(totalM).dot(W))))),
                0.0)

            #print(np.sort(np.diag(W.conj().T.dot(totalM).dot(W)).real) - np.sort(np.diag(W_pieces.conj().T.dot(totalM).dot(W_pieces)).real))
            #assert np.allclose(np.sort(np.diag(W.conj().T.dot(totalM).dot(W)).real), \
            #                   np.sort(np.diag(W_pieces.conj().T.dot(totalM).dot(W_pieces)).real))

            #print(np.linalg.det(W_updown), np.linalg.det(W_downup), np.linalg.det(W_updown) * np.linalg.det(W_downup))
            #print(np.linalg.det(W_pieces))
            #print(np.linalg.det(W))

            for i in range(W_updown.shape[1]):
                v = W_updown[:, i]
                en = en_updown[i]

                v_conj = v * 0.0
                v_conj[:len(v) // 2] = v[len(v) // 2:].conj()
                v_conj[len(v) // 2:] = v[:len(v) // 2].conj()

                en_conj = np.dot(v_conj.conj(), totalM_updown.dot(v_conj))
                # print(en_conj, en)
                #assert en_conj == -en

            mask = np.zeros((4 * L, 4 * L), dtype=np.complex128)
            mask[:L, :L] = np.ones((L, L))
            mask[L:2 * L, L:2 * L] = np.ones((L, L))
            mask[2 * L:3 * L, 2 * L:3 * L] = np.ones((L, L))
            mask[3 * L:, 3 * L:] = np.ones((L, L))
            mask[3 * L:, :L] = np.ones((L, L))
            mask[2 * L:3 * L, L:2 * L] = np.ones((L, L))
            mask[L:2 * L, 2 * L:3 * L] = np.ones((L, L))
            mask[:L, 3 * L:] = np.ones((L, L))

            #totalM[:L, :L] = K0; totalM[L:2 * L, L:2 * L] = K0; totalM[2 * L:3 * L, 2 * L:3 * L] = -K0.T; totalM[3 * L:, 3 * L:] = -K0.T
            #totalM[:L, 2 * L:3 * L] = gap; totalM[L: 2 * L, 3 * L:] = -gap.T; totalM[3 * L:, L: 2 * L] = -gap.conj(); totalM[2 * L:3 * L, :L] = gap.conj().T;

            assert np.allclose(totalM, totalM.conj().T)

            # W = np.linalg.eigh(totalM / 2.)[1]
            #print(np.linalg.eigh(totalM / 2.)[0])
            #assert np.sum(np.abs(W - W * mask)) == 0

            #assert np.allclose(W[:W.shape[0] // 2, :W.shape[0] // 2], W[W.shape[0] // 2:, W.shape[0] // 2:].conj())
            #assert np.allclose(W[W.shape[0] // 2:, :W.shape[0] // 2], W[:W.shape[0] // 2, W.shape[0] // 2:].conj())

            Q, V = W[:W.shape[0] // 2, :W.shape[0] // 2], \
                   W[W.shape[0] // 2:, :W.shape[0] // 2]
            Z = (Q.dot(np.linalg.inv(V)))
            print('max U^{-1} = ', np.max(np.abs(np.linalg.inv(Q))), gap_val,
                  gap_idx)

            np.save('Z_fast.npy', Z)
            result = Z[Z.shape[0] // 2:, :Z.shape[0] // 2]

            Z = Z / np.max(np.abs(Z))
            print(
                np.sum(
                    np.abs(Z[Z.shape[0] // 2:, :Z.shape[0] // 2] +
                           Z[:Z.shape[0] // 2, Z.shape[0] // 2:].T)))
            print(
                np.sum(
                    np.abs(
                        np.real(Z[Z.shape[0] // 2:, :Z.shape[0] // 2] +
                                Z[:Z.shape[0] // 2, Z.shape[0] // 2:].T))))
            print(
                np.sum(
                    np.abs(
                        np.imag(Z[Z.shape[0] // 2:, :Z.shape[0] // 2] +
                                Z[:Z.shape[0] // 2, Z.shape[0] // 2:].T))))

            assert np.allclose(Z[Z.shape[0] // 2:, :Z.shape[0] // 2],
                               -Z[:Z.shape[0] // 2, Z.shape[0] // 2:].T)
            assert np.allclose(Z[Z.shape[0] // 2:, Z.shape[0] // 2:],
                               Z[Z.shape[0] // 2:, Z.shape[0] // 2:] * 0.0)
            assert np.allclose(Z[:Z.shape[0] // 2, :Z.shape[0] // 2],
                               Z[:Z.shape[0] // 2, :Z.shape[0] // 2] * 0.0)

            ##### preparing orbital idxs and teir initial values ####
            vol = 4 * Ls**2
            orbital_idxs = -np.ones((vol, vol), dtype=np.int64)

            f_ij = result
            f_ij = f_ij / np.abs(np.max(f_ij))
            np.save('f_ij_fast.npy', f_ij)

            current_orb_idx = 0
            for xshift in range(Ls):
                for yshift in range(Ls):
                    for iorb in range(4):
                        for jorb in range(4):
                            if yshift > 0:
                                for ipos in range(Ls**2):
                                    i = ipos * 4 + iorb
                                    oi, si, xi, yi = models.from_linearized_index(
                                        i, config.Ls, config.n_orbitals,
                                        config.n_sublattices)
                                    j = models.to_linearized_index(
                                        (xi + xshift) % Ls, (yi + yshift) % Ls,
                                        jorb % 2, jorb // 2, Ls, 2, 2)
                                    if yi + yshift > Ls - 1:
                                        orbital_idxs[i, j] = current_orb_idx
                                current_orb_idx += 1

                            for ipos in range(Ls**2):
                                i = ipos * 4 + iorb
                                oi, si, xi, yi = models.from_linearized_index(
                                    i, config.Ls, config.n_orbitals,
                                    config.n_sublattices)
                                j = models.to_linearized_index(
                                    (xi + xshift) % Ls, (yi + yshift) % Ls,
                                    jorb % 2, jorb // 2, Ls, 2, 2)
                                if yi + yshift <= Ls - 1:
                                    orbital_idxs[i, j] = current_orb_idx
                            current_orb_idx += 1
            print('FAST: orbitals after enforcing APBCy remaining:',
                  current_orb_idx)
            for i in range(current_orb_idx):
                values = f_ij.flatten()[orbital_idxs.flatten() == i]
                assert np.isclose(np.std(values - values.mean()), 0.0)

            if np.allclose(f_ij, f_ij.T):
                print(
                    'FAST: symmetric f_ij = f_ji (singlet): restricting su(2) parameters'
                )

                for i in range(vol):
                    for j in range(vol):
                        orb_ij = orbital_idxs[i, j]
                        orb_ji = orbital_idxs[j, i]
                        orbital_idxs[i, j] = np.min([orb_ij, orb_ji])
                        orbital_idxs[j, i] = np.min([orb_ij, orb_ji])
                new_orbitals = np.unique(orbital_idxs.flatten())
                mapping = list(np.sort(new_orbitals))

                for i in range(vol):
                    for j in range(vol):
                        orbital_idxs[i, j] = mapping.index(orbital_idxs[i, j])

                for i in range(len(mapping)):
                    values = f_ij.flatten()[orbital_idxs.flatten() == i]
                    assert np.isclose(np.std(values - values.mean()), 0.0)
                print('FAST: total orbitals su(2) with APBCy', len(mapping))
                current_orb_idx = len(mapping)

            TRS = np.concatenate([[2 * i + 1, 2 * i] for i in range(vol // 2)])
            f_trs = f_ij[:, TRS]
            f_trs = f_trs[TRS, :]
            if np.allclose(f_trs, f_ij):
                print('FAST: f_ij = TRS f_ij: resticting TRS parameters')

                for i in range(vol):
                    for j in range(vol):
                        orb_ij = orbital_idxs[i, j]
                        i_trs = ((i // 2) * 2) + (((i % 2) + 1) % 2)
                        j_trs = ((j // 2) * 2) + (((j % 2) + 1) % 2)
                        orb_ij_trs = orbital_idxs[i_trs, j_trs]
                        #print(f_ij[i, j], f_ij[i_trs, j_trs])
                        assert np.isclose(f_ij[i, j], f_ij[i_trs, j_trs])

                        orbital_idxs[i, j] = np.min([orb_ij, orb_ij_trs])
                        orbital_idxs[i_trs,
                                     j_trs] = np.min([orb_ij, orb_ij_trs])

                #for i in range(current_orb_idx):
                #    if np.sum(orbital_idxs.flatten() == i) == 0:
                #        print('orbital', i, 'is missing')
                new_orbitals = np.unique(orbital_idxs.flatten())
                mapping = list(np.sort(new_orbitals))

                for i in range(vol):
                    for j in range(vol):
                        orbital_idxs[i, j] = mapping.index(orbital_idxs[i, j])

                for i in range(len(mapping)):
                    values = f_ij.flatten()[orbital_idxs.flatten() == i]
                    assert np.isclose(np.std(values - values.mean()), 0.0)
                print('FAST: total orbitals su(2) with APBCy and TRS!',
                      len(mapping) + 1)
                current_orb_idx = len(mapping)

            np.save('orbital_idxs_fast.npy', orbital_idxs)

            f = open(
                os.path.join(
                    path,
                    'InOrbital_extended_{:d}_{:d}_{:d}_{:.4f}.def'.format(
                        Ls, gap_idx, filling, gap_val)), 'w')
            f.write('======================\n')
            f.write('NOrbitalIdx  {:d}\n'.format(current_orb_idx))
            f.write('======================\n')
            f.write('== i_j_OrbitalIdx  ===\n')
            f.write('======================\n')
            for k in range(current_orb_idx):
                mask = (orbital_idxs == k)
                val = np.sum(f_ij * mask) / np.sum(mask)
                f.write('{:d} {:.20f}  {:.20f}\n'.format(
                    k, val.real, val.imag))
            f.close()

            ########### writing the orbitals indexes ##########
            f = open(
                os.path.join(
                    path, 'orbitalidx_extended_{:d}_{:d}_{:d}.def'.format(
                        Ls, gap_idx, filling)), 'w')

            f.write('=============================================\n')
            f.write('NOrbitalIdx         {:d}\n'.format(current_orb_idx))
            f.write('ComplexType          {:d}\n'.format(1))
            f.write('=============================================\n')
            f.write('=============================================\n')

            for i in range(config.Ls**2 * 4):
                for j in range(config.Ls**2 * 4):
                    f.write('    {:d}      {:d}      {:d}\n'.format(
                        i, j, orbital_idxs[i, j]))

            for i in range(current_orb_idx):
                f.write('    {:d}      1\n'.format(i))
            f.close()

            twist_exp = [
                np.exp(2.0j * np.pi * twist[0]),
                np.exp(2.0j * np.pi * twist[1])
            ]
            K_0_twisted = models.apply_TBC(config,
                                           twist_exp,
                                           deepcopy(K0),
                                           inverse=False)

            ########### writing the K--matrix ##########
            K0_up_int = K0_up - np.diag(np.diag(K0_up))
            K0_down_int = K0_down - np.diag(np.diag(K0_down))

            f = open(
                os.path.join(path,
                             'trans_{:d}_{:.3f}_{:.3f}.def'.format(Ls,
                                                                   *twist)),
                'w')

            f.write('========================\n')
            f.write('NTransfer      {:d}\n'.format(
                2 * np.sum(np.abs(K0_up_int) > 1e-7)))
            f.write('========================\n')
            f.write('========i_j_s_tijs======\n')
            f.write('========================\n')

            for i in range(K_0_twisted.shape[0]):
                for j in range(K_0_twisted.shape[1]):
                    if np.abs(K0_up_int[i, j]) > 1e-7:
                        f.write(
                            '    {:d}     0     {:d}     0   {:.6f}  {:.6f}\n'.
                            format(i, j, np.real(-K0_up_int[i, j]),
                                   np.imag(-K0_up_int[i, j])))
                        f.write(
                            '    {:d}     1     {:d}     1   {:.6f}  {:.6f}\n'.
                            format(i, j, np.real(-K0_down_int[i, j]),
                                   np.imag(-K0_down_int[i, j])))
            f.close()
    return
def run_simulation(delta_reg, previous_params):
    config_vmc_file = import_config(sys.argv[1])
    config_vmc_import = config_vmc_file.MC_parameters(int(sys.argv[2]),
                                                      int(sys.argv[3]), rank)

    config_vmc = cv_module.MC_parameters(int(sys.argv[2]), int(sys.argv[3]),
                                         rank)
    config_vmc.__dict__ = config_vmc_import.__dict__.copy()

    print_model_summary(config_vmc)

    if previous_params is not None:
        config_vmc.initial_parameters = previous_params

    config_vmc.workdir = config_vmc.workdir + '/irrep_{:d}_Ne_{:d}/'.format(
        rank, int(sys.argv[3]))

    os.makedirs(config_vmc.workdir, exist_ok=True)
    with open(os.path.join(config_vmc.workdir, 'config.py'), 'w') as target, \
         open(sys.argv[1], 'r') as source:  # save config file to workdir (to remember!!)
        target.write(source.read())

    if config_vmc.visualisation:
        # config_vmc.twist = [np.exp(2.0j * np.pi * 0.1904), np.exp(2.0j * np.pi * (0.1904 + 0.1))]
        visualisation.plot_levels_evolution_mu(config_vmc)
        visualisation.plot_all_waves(config_vmc)
        visualisation.plot_DOS(config_vmc)
        visualisation.plot_fermi_surface(config_vmc)
        visualisation.plot_all_waves(config_vmc)
        visualisation.plot_all_Jastrow(config_vmc)
        visualisation.plot_MF_spectrum_profile(config_vmc)

    config_vmc.twist = [
        1, 1
    ]  #[np.exp(2.0j * np.pi * 0.1904), np.exp(2.0j * np.pi * (0.1904 + 0.10))]
    if config_vmc.tests:
        if rank == 0:
            if tests.perform_all_tests(config_vmc):
                print('\033[92m All tests passed successfully \033[0m',
                      flush=True)
            else:
                print('\033[91m Warning: some of the tests failed! \033[0m',
                      flush=True)
    comm.Barrier()

    n_cpus_max = psutil.cpu_count(logical=True)
    print('max available CPUs:', n_cpus_max)
    n_cpus = config_vmc.n_cpus
    if config_vmc.n_cpus == -1:
        n_cpus = n_cpus_max
    print('performing simulation at', n_cpus, 'CPUs')

    ### generate twists once and for all (Sandro's suggestion) ###

    if config_vmc.twist_mesh == 'Baldereschi':
        print('Working with the Baldereschi mesh')
        if config_vmc.n_sublattices == 2:
            twists = [[
                np.exp(2.0j * np.pi * 0.1904),
                np.exp(2.0j * np.pi * (0.1904 + 0.1))
            ] for _ in range(config_vmc.n_chains)]
        if config_vmc.n_sublattices == 1:
            twists = [[1., -1.] for _ in range(config_vmc.n_chains)]  # FIXME
        twists_per_cpu = config_vmc.n_chains / n_cpus
    elif config_vmc.twist_mesh == 'PBC':
        twists = [[1., 1.] for _ in range(config_vmc.n_chains)]
        twists_per_cpu = config_vmc.n_chains / n_cpus
    elif config_vmc.twist_mesh == 'APBCy':
        twists = [[1., -1.] for _ in range(config_vmc.n_chains)]
        twists_per_cpu = config_vmc.n_chains / n_cpus
    elif config_vmc.twist_mesh == 'reals':
        assert config_vmc.n_chains == 4
        twists = [[1, 1], [1, -1], [-1, 1], [-1, -1]]
        twists_per_cpu = config_vmc.n_chains / n_cpus
        assert twists_per_cpu == 1
    elif config_vmc.twist_mesh == 'uniform':
        L = config_vmc.L_twists_uniform
        twists = []
        for i_x in range(L):
            for i_y in range(L):
                twists.append([
                    np.exp(1.0j * np.pi * (-1. + 1. / L + 2. * i_x / L)),
                    np.exp(1.0j * np.pi * (-1. + 1. / L + 2. * i_y / L))
                ])
        twists_per_cpu = len(twists) // n_cpus
        if twists_per_cpu * n_cpus < len(twists):
            twists_per_cpu += 1
    else:
        print('Twist {:s} is not supported'.format(config_vmc.twist_mesh))
        exit(-1)
    print(twists)
    print(
        'Number of twists: {:d}, number of chains {:d}, twists per cpu {:2f}'.
        format(len(twists), config_vmc.n_chains, twists_per_cpu))
    K_matrices_up = [
        models.apply_TBC(config_vmc,
                         twist,
                         deepcopy(config_vmc.K_0),
                         inverse=False) for twist in twists
    ]
    print(repr(K_matrices_up[0]))
    print(config_vmc.K_0)
    #exit(-1)
    K_matrices_down = [
        models.apply_TBC(config_vmc,
                         twist,
                         deepcopy(config_vmc.K_0).T,
                         inverse=True) for twist in twists
    ]
    reg_terms = [models.apply_TBC(config_vmc, twist, deepcopy(config_vmc.reg_gap_term), inverse = False) * \
                 config_vmc.reg_gap_val for twist in twists]

    config_vmc.MC_chain = config_vmc.MC_chain // len(
        twists)  # the MC_chain contains the total required number of samples

    pairings_list = config_vmc.pairings_list
    pairings_names = config_vmc.pairings_list_names

    # template = 'e_{:.2f}_Ne_{:d}'.format(config_vmc.epsilon, config_vmc.Ne) if config_vmc.PN_projection else \
    #            'e_{:.2f}_mu_{:.2f}'.format(config_vmc.epsilon, config_vmc.mu)

    local_workdir = config_vmc.workdir

    obs_files = []
    loaded_from_external = False
    if config_vmc.load_parameters:
        if config_vmc.load_parameters_path is not None:
            loaded_from_external = True
            filename = config_vmc.load_parameters_path
            parameters, last_step = load_parameters(filename)
        elif os.path.isfile(os.path.join(local_workdir, 'last_opt_params.p')):
            filename = os.path.join(local_workdir, 'last_opt_params.p')
            parameters, last_step = load_parameters(filename)
        else:
            parameters = config_vmc.initial_parameters
            last_step = 0
    else:
        parameters = config_vmc.initial_parameters
        last_step = 0

    if config_vmc.condensation_energy_check_regime:
        parameters[config_vmc.layout[:3].sum():config_vmc.layout[:4].sum(
        )] = 0.

    log_file = open(os.path.join(local_workdir, 'general_log.dat'), 'a+')
    force_file = open(os.path.join(local_workdir, 'force_log.dat'), 'a+')
    gaps_file = open(os.path.join(local_workdir, 'gaps_log.dat'), 'a+')
    force_SR_file = open(os.path.join(local_workdir, 'force_SR_log.dat'), 'a+')

    spectral_file = open(os.path.join(local_workdir, 'spectral_log.dat'), 'a+')
    final_states = [False] * len(twists)
    orbitals_in_use = [None] * len(twists)

    ### write log header only if we start from some random parameters ###
    if last_step == 0 or loaded_from_external:
        write_initial_logs(log_file, force_file, force_SR_file, config_vmc)

    #for n_step in range(last_step, config_vmc.optimisation_steps):
    n_step = last_step
    while n_step < config_vmc.optimisation_steps:
        t = time()
        if twists_per_cpu > 1:
            with parallel_backend("loky", inner_max_num_threads=1):
                results_batched = Parallel(n_jobs=n_cpus)(delayed(get_MC_chain_result)( \
                        n_step, \
                        deepcopy(config_vmc), \
                        pairings_list, \
                        parameters, \
                        twists = twists[i * twists_per_cpu:np.min([(i + 1) * twists_per_cpu, len(twists)])], \
                        final_states = final_states[i * twists_per_cpu:np.min([(i + 1) * twists_per_cpu, len(twists)])], \
                        orbitals_in_use = orbitals_in_use[i * twists_per_cpu:np.min([(i + 1) * twists_per_cpu, len(twists)])], \
                        K_matrices_up = K_matrices_up[i * twists_per_cpu:np.min([(i + 1) * twists_per_cpu, len(twists)])], \
                        K_matrices_down = K_matrices_down[i * twists_per_cpu:np.min([(i + 1) * twists_per_cpu, len(twists)])], \
                        regs = reg_terms[i * twists_per_cpu:np.min([(i + 1) * twists_per_cpu, len(twists)])], \
                    ) for i in range(n_cpus))
                #for i in range(n_cpus):
                #    print(i * twists_per_cpu, np.min([(i + 1) * twists_per_cpu, len(twists)]))
                results = []
                for i, r in enumerate(results_batched):
                    results = results + r
                    print('obtained {:d} results from {:d} cpu'.format(
                        len(r), i))
                print('obtained in total {:d} results'.format(len(results)))
                #print(len(twists))
        else:
            with parallel_backend("loky", inner_max_num_threads=1):
                results = Parallel(n_jobs=config_vmc.n_chains)(delayed(_get_MC_chain_result)( \
                        n_step, \
                        deepcopy(config_vmc), \
                        pairings_list, \
                        parameters, \
                        twists[i], \
                        final_states[i], \
                        orbitals_in_use[i], \
                        K_matrices_up[i], \
                        K_matrices_down[i], \
                        reg_terms[i], \
                    ) for i in range(config_vmc.n_chains))
        print('MC chain generationof {:d} no {:d} took {:f}'.format(
            rank, n_step,
            time() - t))
        t = time()

        ### print-out current energy levels ###
        E = results[0][7]
        spectral_file.write(
            str(n_step) + ' ' + ("{:.7f} " * len(E) + '\n').format(*E))
        spectral_file.flush()
        ### MC chains data extraction ###
        gaps, gap, energies, mean_variance, Os, acceptance, \
            final_states, densities, orbitals_in_use, occupied_numbers = \
            extract_MC_data(results, config_vmc, config_vmc.n_chains)
        energies_merged = np.concatenate(energies)

        n_above_FS = len(
            np.setdiff1d(occupied_numbers[0],
                         np.arange(config_vmc.total_dof // 2)))
        ### gradient step ###
        if config_vmc.generator_mode:  # evolve parameters only if it's necessary
            mask = np.ones(np.sum(config_vmc.layout))
            factor_stages = 1
            if n_step < 100:  # jastrows and mu_BCS have not converged yet
                mask = np.zeros(np.sum(config_vmc.layout))
                mask[-config_vmc.layout[4]:] = 1.
                factor_stages = 30.
            #    # mask[:config_vmc.layout[0]] = 1.
            #    mask[config_vmc.layout[0] + config_vmc.layout[1] + config_vmc.layout[2]:config_vmc.layout[0] + \
            #         config_vmc.layout[1] + config_vmc.layout[2] + config_vmc.layout[3]] = 0.
            #mask[1] = 0.0  # fugacity is not optimized in the meantime

            # Os = [np.einsum('ik,k->ik', Os_theta, config_vmc.mask) for Os_theta in Os]

            step, forces = make_SR_step(Os, energies, config_vmc, twists, gaps,
                                        n_step, mask)

            write_intermediate_log(log_file, force_file, force_SR_file, n_step, config_vmc.total_dof // 2, energies, densities, \
                                   mean_variance, acceptance, forces, step, gap, n_above_FS, parameters)  # write parameters before step not to lose the initial values

            write_gaps_log(gaps_file, gaps, n_step)

            #if np.abs(gap) < 1e-4:  # if the gap is too small, SR will make gradient just 0
            #    step = forces
            #step = forces * config_vmc.opt_parameters[1]
            step = step * config_vmc.opt_parameters[1]
            #step = clip_forces(config_vmc.all_clips, step)

            parameters += step * mask * factor_stages  # lr better be ~0.01..0.1

            #if parameters[0] < config_vmc.mu_BCS_min:
            #    parameters[0] = config_vmc.mu_BCS_min
            #if parameters[0] > config_vmc.mu_BCS_max:
            #    parameters[0] = config_vmc.mu_BCS_max

            save_parameters(parameters, config_vmc.workdir, n_step)
        ### END SR STEP ###

        observables = np.concatenate([np.array(x[4]) for x in results], axis=0)
        observables_names = results[0][5]
        n_step += 1
        if len(observables_names) == 0:
            continue

        if n_step == config_vmc.thermalization + 1:
            create_obs_files(observables_names, config_vmc)

        write_observables(n_step, obs_files, observables, config_vmc)
        if rank == 0:
            print('SR and logging {:d} took {:f}'.format(n_step, time() - t))

    log_file.close()
    force_file.close()
    force_SR_file.close()
    spectral_file.close()

    [file.close() for file in obs_files]
    return parameters
Beispiel #7
0
    def select_initial_muBCS_Koshino(self, Ne, parameters=[]):
        if len(parameters) == 0:
            parameters = self.initial_parameters
        #_, _, waves, gap, _ = self.unpack_parameters(parameters, mode_setting = True)
        # T = wfv.construct_HMF(self, self.K_0, self.K_0.T, self.pairings_list_unwrapped, gap, waves, self.reg_gap_term)

        # assert np.allclose(T, T.conj().T)
        if self.twist_mesh == 'Baldereschi':
            twist = [
                np.exp(2.0j * np.pi * 0.1904),
                np.exp(2.0j * np.pi * (0.1904 + 0.1))
            ]
        elif self.twist_mesh == 'APBCy':
            twist = [1, -1]
        else:
            twist = [1, 1]
        #twist = [1.0j, -1.0j]
        print(twist)

        #if twist[0] != 1 or twist[1] != 1:
        K_0_twisted = models.apply_TBC(self,
                                       twist,
                                       deepcopy(self.K_0),
                                       inverse=False)
        energies = np.linalg.eigh(K_0_twisted)[0]
        #print(energies)
        print(twist)
        print(
            'energy_free_theory = ',
            np.sum(
                np.sort(energies)[:self.total_dof // 2 // 2] * 2 /
                (self.total_dof // 2)))
        assert np.allclose(K_0_twisted, K_0_twisted.T.conj())
        print('energy_free_theory = ',
              np.sum(energies[:self.Ne // 2] * 2) / 16.)

        K_0_twisted_holes = -models.apply_TBC(
            self, twist, deepcopy(self.K_0).T, inverse=True)
        assert np.allclose(K_0_twisted, K_0_twisted.conj().T)
        assert np.allclose(K_0_twisted_holes, K_0_twisted_holes.conj().T)
        assert np.allclose(
            np.linalg.eigh(K_0_twisted_holes)[0],
            np.sort(-np.linalg.eigh(K_0_twisted)[0]))

        for i in range(K_0_twisted.shape[0]):
            for j in range(K_0_twisted.shape[1]):
                if (i + j) % 2 == 1 and np.abs(K_0_twisted[i, j]) > 1e-12:
                    print(i, j)
                    exit(-1)  # chiral basis check failed

        K_0_plus = K_0_twisted[:, np.arange(0, self.total_dof // 2, 2)]
        K_0_plus = K_0_plus[np.arange(0, self.total_dof // 2, 2), :]
        K_0_minus = K_0_twisted[:, np.arange(1, self.total_dof // 2, 2)]
        K_0_minus = K_0_minus[np.arange(1, self.total_dof // 2, 2), :]

        assert np.allclose(np.conj(K_0_plus), K_0_minus)
        print(np.linalg.eigh(K_0_plus)[0])
        print(np.linalg.eigh(K_0_minus)[0])
        #

        K_0_plus_holes = K_0_twisted_holes[:,
                                           np.arange(0, self.total_dof //
                                                     2, 2)]
        K_0_plus_holes = K_0_plus_holes[np.arange(0, self.total_dof //
                                                  2, 2), :]

        K_0_minus_holes = K_0_twisted_holes[:,
                                            np.arange(1, self.total_dof //
                                                      2, 2)]
        K_0_minus_holes = K_0_minus_holes[np.arange(1, self.total_dof //
                                                    2, 2), :]

        #print(np.linalg.eigh(K_0_plus)[0] -  np.sort(-np.linalg.eigh(K_0_minus_holes)[0]))
        assert np.allclose(
            np.linalg.eigh(K_0_plus)[0],
            np.sort(-np.linalg.eigh(K_0_minus_holes)[0]))
        assert np.allclose(
            np.linalg.eigh(K_0_minus)[0],
            np.sort(-np.linalg.eigh(K_0_plus_holes)[0]))
        #exit(-1)

        nu = self.valley_imbalance // 4
        delta = (self.total_dof // 2 - Ne) // 4

        Ep, _ = np.linalg.eigh(K_0_plus)  # particle energies
        Ep = np.sort(Ep)
        Em, _ = np.linalg.eigh(K_0_minus)  # particle energies
        Em = np.sort(Em)

        N_particles_plus_below = np.sum(
            Ep < 0)  # current number of + particle energies below zero
        xi = N_particles_plus_below - (
            self.total_dof // 8 - delta + nu
        )  # this many levels must be put up above FS
        print('xi_plus = {:d}'.format(xi))
        dEp = (Ep[N_particles_plus_below - xi - 1] * 0.5 +
               Ep[N_particles_plus_below - xi] * 0.5) / 1
        mu_BCS_min = (Ep[N_particles_plus_below - xi - 1] * 0.999 +
                      Ep[N_particles_plus_below - xi] * 0.001)
        mu_BCS_max = (Ep[N_particles_plus_below - xi - 1] * 0.001 +
                      Ep[N_particles_plus_below - xi] * 0.999)

        print(Ep, Ep[N_particles_plus_below - xi - 1],
              Ep[N_particles_plus_below - xi])
        print('initial mu_BCS = {:.10f}'.format(dEp))
        #exit(-1)
        print('N_particles_plus_below before = {:d}'.format(
            N_particles_plus_below))
        #print(Ep)
        #print('N_holes_minus_below before = {:d}'.format(np.sum(np.linalg.eigh(K_0_minus_holes)[0] < 0)))
        Ep, _ = np.linalg.eigh(
            K_0_plus - np.eye(K_0_plus.shape[0]) * dEp)  # particle energies
        N_particles_plus_below = np.sum(
            Ep < 0)  # number after proper mu_BCS subtraction
        print('N_particles_plus_below after = {:d}'.format(
            N_particles_plus_below))
        #print('N_holes_minus_below after = {:d}'.format(np.sum(np.linalg.eigh(K_0_minus_holes + np.eye(K_0_plus.shape[0]) * dEp)[0] < 0)))
        # print('holes', np.linalg.eigh(-K_0_plus_holes.T + np.eye(K_0_plus.shape[0]) * dEp)[0])
        # print('particles', Ep)

        #N_particles_minus_below = np.sum(Em < 0)  # current number of + particle energies below zero
        #xi = N_particles_minus_below - (self.total_dof // 8 - delta - nu)  # this many levels must be put up above FS
        #dEm = (Em[N_particles_minus_below - xi - 1] * 0.49 + Em[N_particles_minus_below - xi] * 0.51) / 1
        #print(Em, Em[N_particles_minus_below - xi - 1], Em[N_particles_minus_below - xi])
        #print('initial mu_BCS_2 = {:.10f}'.format(dEm))
        #print('N_particles_minus_below before = {:d}'.format(N_particles_minus_below))
        #print('N_holes_minus_below before = {:d}'.format(np.sum(np.linalg.eigh(K_0_plus_holes)[0] < 0)))
        #Em, _ = np.linalg.eigh(K_0_minus - np.eye(K_0_minus.shape[0]) * dEm)  # particle energies
        #N_particles_minus_below = np.sum(Em < 0)  # number after proper mu_BCS subtraction
        #print('N_particles_minus_below after = {:d}'.format(N_particles_minus_below))
        #print('N_holes_plus_below after = {:d}'.format(np.sum(np.linalg.eigh(K_0_plus_holes + np.eye(K_0_minus.shape[0]) * dEm)[0] < 0)))

        #print('!!!!', np.sort(np.concatenate([Em, Ep])))

        #print('but I wanted particles_+ {:d}, holes_+ {:d}, particles_-{:d}, holes_- {:d}'.format(self.total_dof // 8 - delta + nu, self.total_dof // 8 + delta - nu, self.total_dof // 8 - delta - nu, self.total_dof // 8 + delta + nu))

        print(dEp)
        return dEp, mu_BCS_min, mu_BCS_max
Beispiel #8
0
        #assert config.mu == 0

        #assert np.allclose(K_matrix.imag, K_matrix * 0.)
        assert np.allclose(K_matrix, K_matrix.conj().T)

        K_matrix = -K_matrix  # this is to agree with ED, this is just unitary transform in terms of particle-hole transformation

        print(repr(K_matrix))

        energies = np.linalg.eigh(K_matrix)[0]
        print(energies)
        print(np.sum(energies[energies < 0]) / 16.)

        K_matrix = models.apply_TBC(config,
                                    twist,
                                    deepcopy(K_matrix),
                                    inverse=False)
        config.pairings_list_unwrapped = [
            models.apply_TBC(config, twist, deepcopy(gap), inverse=False)
            for gap in config.pairings_list_unwrapped
        ]

        ### creating precomputed exponents ###
        K_operator = scipy.linalg.expm(config.dt * K_matrix)
        K_operator_inverse = scipy.linalg.expm(-config.dt * K_matrix)
        assert np.allclose(np.linalg.inv(K_operator), K_operator_inverse)
        K_operator_half = scipy.linalg.expm(0.5 * config.dt * K_matrix)
        K_operator_half_inverse = scipy.linalg.expm(-0.5 * config.dt *
                                                    K_matrix)

        local_workdir = config.workdir  #,#os.path.join(config.workdir, 'U_{:.2f}_V_{:.2f}_mu_{:.2f}_Nt_{:d}_c_{:d}'.format(U, V, mu, int(Nt), rank + config.offset))
Beispiel #9
0
def get_MFH(config, mu_given=None, gap_given=None, only_free=False):
    K_up = config.model(config, config.mu, spin=+1.0)[0]
    K_up = models.xy_to_chiral(K_up, 'K_matrix', config, config.chiral_basis)
    K_up = models.apply_TBC(config,
                            config.twist,
                            deepcopy(K_up),
                            inverse=False)

    K_down = config.model(config, config.mu, spin=-1.0)[0].T
    K_down = models.xy_to_chiral(K_down, 'K_matrix', config,
                                 config.chiral_basis)
    K_down = models.apply_TBC(config,
                              config.twist,
                              deepcopy(K_down),
                              inverse=True)

    mu, fugacity, waves, gap, jastrow = config.unpack_parameters(
        config.initial_parameters)

    C2y = pairings.C2y_symmetry_map_chiral
    C2y = np.kron(np.eye(2), C2y)

    C3z = pairings.C3z_symmetry_map_chiral
    C3z = np.kron(np.eye(2), C3z)

    if mu_given is not None:
        Deltas_twisted = [
            models.apply_TBC(config,
                             config.twist,
                             deepcopy(gap),
                             inverse=False)
            for gap in config.pairings_list_unwrapped
        ]
        Delta = pairings.get_total_pairing_upwrapped(config, Deltas_twisted,
                                                     gap)
        reg = models.apply_TBC(
            config, config.twist, deepcopy(
                config.reg_gap_term), inverse=False) * config.reg_gap_val
        Ts = []

        for dmu in mu_given:
            T = scipy.linalg.block_diag(
                K_up - np.eye(K_up.shape[0]) *
                (mu + dmu), -(K_down - np.eye(K_down.shape[0]) *
                              (mu + dmu))) + 0.0j
            T[:config.total_dof // 2, config.total_dof // 2:] = Delta + reg
            T[config.total_dof // 2:, :config.total_dof //
              2] = Delta.conj().T + reg.conj().T

            Ts.append(T.copy() * 1.)

            Deltaonly = T * 0.0
            Deltaonly[:config.total_dof // 2, config.total_dof // 2:] = Delta
            Deltaonly[config.total_dof // 2:, :config.total_dof //
                      2] = Delta.conj().T

            eigenvalues, eigenvectors = np.linalg.eigh(Ts[-1])
            idxs = np.argsort(np.abs(eigenvalues))[:2]
            # print(eigenvalues[idxs])
            vplus = eigenvectors[:, idxs[0]]
            vminus = eigenvectors[:, idxs[1]]

            print(np.dot(vplus.conj(), C3z.dot(vplus)))
            print(np.dot(vminus.conj(), C3z.dot(vminus)))
            #print(C3z.shape)
            #print(Deltaonly.shape)
            print(np.trace(Delta.T.conj().dot(pairings.C3z_symmetry_map_chiral.dot(Delta.dot(pairings.C3z_symmetry_map_chiral.T)))) \
                / np.trace(np.dot(Delta, Delta.conj().T)))

            print(np.abs(np.dot(vplus.conj(), np.dot(Deltaonly, vminus))), np.abs(np.dot(vplus.conj(), vminus)), eigenvalues[idxs], idxs, dmu, \
                  np.trace(np.dot(Deltaonly, Deltaonly.T.conj())))
        #exit(-1)
        return Ts

    K_up -= np.eye(K_up.shape[0]) * mu
    K_down -= np.eye(K_down.shape[0]) * mu

    T = scipy.linalg.block_diag(K_up, -K_down) + 0.0j
    if only_free:
        return T

    if gap_given is None:
        Delta = pairings.get_total_pairing_upwrapped(
            config, config.pairings_list_unwrapped, gap)

        T[:config.total_dof // 2, config.total_dof // 2:] = Delta
        T[config.total_dof // 2:, :config.total_dof // 2] = Delta.conj().T
        return T

    else:
        Ts = []
        Delta = pairings.get_total_pairing_upwrapped(
            config, config.pairings_list_unwrapped, [1])
        for gap in gap_given:
            T_gap = T.copy() * 1.0

            T_gap[:config.total_dof // 2, config.total_dof // 2:] = Delta * gap
            T_gap[config.total_dof // 2:, :config.total_dof //
                  2] = Delta.conj().T * gap
            Ts.append(T_gap.copy() * 1.0)
        return Ts