예제 #1
0
 def ph_onsite(cls, mol_list: MolList, opera: str, mol_idx:int, ph_idx=0):
     assert opera in ["b", r"b^\dagger", r"b^\dagger b"]
     mpo = cls()
     mpo.mol_list = mol_list
     for imol, mol in enumerate(mol_list):
         if mol_list.scheme < 4:
             mpo.append(xp.eye(2).reshape(1, 2, 2, 1))
         elif mol_list.scheme == 4:
             if len(mpo) == mol_list.e_idx():
                 n = mol_list.mol_num
                 mpo.append(xp.eye(n).reshape(1, n, n, 1))
         else:
             assert False
         iph = 0
         for ph in mol.dmrg_phs:
             for iqph in range(ph.nqboson):
                 ph_pbond = ph.pbond[iqph]
                 if imol == mol_idx and iph == ph_idx:
                     mt = ph_op_matrix(opera, ph_pbond)
                 else:
                     mt = ph_op_matrix("Iden", ph_pbond)
                 mpo.append(mt.reshape(1, ph_pbond, ph_pbond, 1))
                 iph += 1
     mpo.build_empty_qn()
     return mpo
예제 #2
0
    def exact_propagator(cls, mol_list: MolList, x, space="GS", shift=0.0):
        """
        construct the GS space propagator e^{xH} exact MPO
        H=\\sum_{in} \\omega_{in} b^\\dagger_{in} b_{in}
        fortunately, the H is local. so e^{xH} = e^{xh1}e^{xh2}...e^{xhn}
        the bond dimension is 1
        shift is the a constant for H+shift
        """
        assert space in ["GS", "EX"]

        mpo = cls()
        if np.iscomplex(x):
            mpo.to_complex(inplace=True)
        mpo.mol_list = mol_list

        for imol, mol in enumerate(mol_list):
            if mol_list.scheme < 4:
                mo = np.eye(2).reshape(1, 2, 2, 1)
                mpo.append(mo)
            elif mol_list.scheme == 4:
                if len(mpo) == mol_list.e_idx():
                    n = mol_list.mol_num
                    mpo.append(np.eye(n).reshape(1, n, n, 1))
            else:
                assert False

            for ph in mol.dmrg_phs:

                if space == "EX":
                    # for the EX space, with quasiboson algorithm, the b^\dagger + b
                    # operator is not local anymore.
                    assert ph.nqboson == 1
                    ph_pbond = ph.pbond[0]
                    # construct the matrix exponential by diagonalize the matrix first
                    phop = construct_ph_op_dict(ph_pbond)

                    h_mo = (
                        phop[r"b^\dagger b"] * ph.omega[0]
                        + phop[r"(b^\dagger + b)^3"] * ph.term30
                        + phop[r"b^\dagger + b"] * (ph.term10 + ph.term11)
                        + phop[r"(b^\dagger + b)^2"] * (ph.term20 + ph.term21)
                        + phop[r"(b^\dagger + b)^3"] * (ph.term31 - ph.term30)
                    )

                    w, v = scipy.linalg.eigh(h_mo)
                    h_mo = np.diag(np.exp(x * w))
                    h_mo = v.dot(h_mo)
                    h_mo = h_mo.dot(v.T)
                    mo = h_mo.reshape(1, ph_pbond, ph_pbond, 1)

                    mpo.append(mo)

                elif space == "GS":
                    anharmo = False
                    # for the ground state space, yet doesn't support 3rd force
                    # potential quasiboson algorithm
                    ph_pbond = ph.pbond[0]
                    for i in range(len(ph.force3rd)):
                        anharmo = not np.allclose(
                            ph.force3rd[i] * ph.dis[i] / ph.omega[i], 0.0
                        )
                        if anharmo:
                            break
                    if not anharmo:
                        for iboson in range(ph.nqboson):
                            d = np.exp(
                                    x
                                    * ph.omega[0]
                                    * ph.base ** (ph.nqboson - iboson - 1)
                                    * np.arange(ph_pbond)
                                )
                            mo = np.diag(d).reshape(1, ph_pbond, ph_pbond, 1)
                            mpo.append(mo)
                    else:
                        assert ph.nqboson == 1
                        # construct the matrix exponential by diagonalize the matrix first
                        phop = construct_ph_op_dict(ph_pbond)
                        h_mo = (
                            phop[r"b^\dagger b"] * ph.omega[0]
                            + phop[r"(b^\dagger + b)^3"] * ph.term30
                        )
                        w, v = scipy.linalg.eigh(h_mo)
                        h_mo = np.diag(np.exp(x * w))
                        h_mo = v.dot(h_mo)
                        h_mo = h_mo.dot(v.T)

                        mo = np.zeros([1, ph_pbond, ph_pbond, 1])
                        mo[0, :, :, 0] = h_mo

                        mpo.append(mo)
                else:
                    assert False
        # shift the H by plus a constant

        mpo.qn = [[0]] * (len(mpo) + 1)
        mpo.qnidx = len(mpo) - 1
        mpo.qntot = 0

        # np.exp(shift * x) is usually very large
        mpo = mpo.scale(np.exp(shift * x), inplace=True)

        return mpo