Ejemplo n.º 1
0
def wfnPropagation(iMPS, HMPO, nsteps, dt, ephtable, thresh=0, \
        cleanexciton=None, prop_method="C_RK4", compress_method="svd", QNargs=None):
    '''
    simple wavefunction propagation through Runge-Kutta methods
    '''
    tableau = RK.runge_kutta_explicit_tableau(prop_method)
    propagation_c = RK.runge_kutta_explicit_coefficient(tableau)

    ketMPS = mpslib.add(iMPS, None, QNargs=QNargs)
    Hset = []  # energy
    Vset = []  # overlap
    for isteps in xrange(nsteps):
        if isteps != 0:
            ketMPS = tMPS(ketMPS, HMPO, dt, ephtable, propagation_c, thresh=thresh, \
                cleanexciton=cleanexciton, compress_method=compress_method, \
                QNargs=QNargs)

        Hset.append(mpslib.dot(mpslib.conj(ketMPS,QNargs=QNargs), \
                mpslib.mapply(HMPO, ketMPS, QNargs=QNargs), QNargs=QNargs))
        Vset.append(mpslib.dot(mpslib.conj(ketMPS,QNargs=QNargs), \
                ketMPS, QNargs=QNargs))

    return Hset, Vset
Ejemplo n.º 2
0
def ApproxPropagatorMPO(HMPO, dt, ephtable, propagation_c, thresh=0, \
        compress_method="svd", QNargs=None):
    '''
    e^-iHdt : approximate propagator MPO from Runge-Kutta methods
    '''

    # Identity operator
    if QNargs is not None:
        nmpo = len(HMPO[0])
    else:
        nmpo = len(HMPO)

    MPOdim = [1] * (nmpo + 1)
    MPOQN = [[0]] * (nmpo + 1)
    MPOQNidx = nmpo - 1
    MPOQNtot = 0

    IMPO = []
    for impo in xrange(nmpo):
        if QNargs is not None:
            mpo = np.ones([1, HMPO[0][impo].shape[1], 1], dtype=np.complex128)
        else:
            mpo = np.ones([1, HMPO[impo].shape[1], 1], dtype=np.complex128)
        IMPO.append(mpo)
    IMPO = hilbert_to_liouville(IMPO)

    QNargslocal = copy.deepcopy(QNargs)

    if QNargs is not None:
        IMPO = [IMPO, MPOQN, MPOQNidx, MPOQNtot]
        # a real MPO compression
        QNargslocal[1] = True

    approxMPO = tMPS(IMPO, HMPO, dt, ephtable, propagation_c, thresh=thresh, \
        compress_method=compress_method, QNargs=QNargslocal)

    print "approx propagator thresh:", thresh
    if QNargs is not None:
        print "approx propagator dim:", [mpo.shape[0] for mpo in approxMPO[0]]
    else:
        print "approx propagator dim:", [mpo.shape[0] for mpo in approxMPO]

    chkIden = mpslib.mapply(mpslib.conj(approxMPO, QNargs=QNargs),
                            approxMPO,
                            QNargs=QNargs)
    print "approx propagator Identity error", np.sqrt(mpslib.distance(chkIden, IMPO, QNargs=QNargs) /\
        mpslib.dot(IMPO, IMPO, QNargs=QNargs))

    return approxMPO
Ejemplo n.º 3
0
def FiniteT_emi(mol, pbond, iMPO, HMPO, dipoleMPO, nsteps, dt, \
        ephtable, insteps, thresh=0, temperature=298, prop_method="C_RK4", compress_method="svd",
        QNargs=None):
    '''
    Finite temperature emission, already included in FiniteT_spectra
    '''
    tableau = RK.runge_kutta_explicit_tableau(prop_method)
    propagation_c = RK.runge_kutta_explicit_coefficient(tableau)

    beta = constant.T2beta(temperature)
    ketMPO = thermal_prop(iMPO,
                          HMPO,
                          insteps,
                          ephtable,
                          prop_method=prop_method,
                          thresh=thresh,
                          temperature=temperature,
                          compress_method=compress_method,
                          QNargs=QNargs)

    braMPO = mpslib.add(ketMPO, None, QNargs=QNargs)

    #\Psi e^{\-beta H} \Psi
    Z = mpslib.dot(mpslib.conj(braMPO, QNargs=QNargs), ketMPO, QNargs=QNargs)
    print "partition function Z(beta)/Z(0)", Z

    AketMPO = mpslib.mapply(dipoleMPO, ketMPO, QNargs=QNargs)

    autocorr = []
    t = 0.0
    ketpropMPO, ketpropMPOdim = ExactPropagatorMPO(mol,
                                                   pbond,
                                                   -1.0j * dt,
                                                   QNargs=QNargs)

    dipoleMPOdagger = mpslib.conjtrans(dipoleMPO, QNargs=QNargs)

    if compress_method == "variational":
        braMPO = mpslib.canonicalise(braMPO, 'l', QNargs=QNargs)

    for istep in xrange(nsteps):
        if istep != 0:
            t += dt
            AketMPO = mpslib.mapply(ketpropMPO, AketMPO, QNargs=QNargs)
            braMPO = tMPS(braMPO,
                          HMPO,
                          dt,
                          ephtable,
                          propagation_c,
                          thresh=thresh,
                          cleanexciton=1,
                          compress_method=compress_method,
                          QNargs=QNargs)

        AAketMPO = mpslib.mapply(dipoleMPOdagger, AketMPO, QNargs=QNargs)
        ft = mpslib.dot(mpslib.conj(braMPO, QNargs=QNargs),
                        AAketMPO,
                        QNargs=QNargs)
        autocorr.append(ft / Z)
        autocorr_store(autocorr, istep)

    return autocorr
Ejemplo n.º 4
0
def FiniteT_spectra(spectratype, mol, pbond, iMPO, HMPO, dipoleMPO, nsteps, dt,\
        ephtable, insteps=0, thresh=0, temperature=298,\
        algorithm=2, prop_method="C_RK4", compress_method="svd", QNargs=None, \
        approxeiHt=None, GSshift=0.0, cleanexciton=None, scheme="P&C"):
    '''
    finite temperature propagation
    only has algorithm 2, two way propagator
    '''
    assert algorithm == 2
    assert spectratype in ["abs", "emi"]
    tableau = RK.runge_kutta_explicit_tableau(prop_method)
    propagation_c = RK.runge_kutta_explicit_coefficient(tableau)

    beta = constant.T2beta(temperature)
    print "beta=", beta

    # e^{\-beta H/2} \Psi
    if spectratype == "emi":
        ketMPO = thermal_prop(iMPO, HMPO, insteps, ephtable,\
                prop_method=prop_method, thresh=thresh,\
                temperature=temperature, compress_method=compress_method,\
                QNargs=QNargs, approxeiHt=approxeiHt)
    elif spectratype == "abs":
        thermalMPO, thermalMPOdim = ExactPropagatorMPO(mol, pbond, -beta/2.0,\
                QNargs=QNargs, shift=GSshift)
        ketMPO = mpslib.mapply(thermalMPO, iMPO, QNargs=QNargs)

    #\Psi e^{\-beta H} \Psi
    Z = mpslib.dot(mpslib.conj(ketMPO, QNargs=QNargs), ketMPO, QNargs=QNargs)
    print "partition function Z(beta)/Z(0)", Z

    autocorr = []
    t = 0.0
    exacteiHpt, exacteiHptdim = ExactPropagatorMPO(mol, pbond, -1.0j*dt,\
            QNargs=QNargs, shift=GSshift)
    exacteiHmt, exacteiHmtdim = ExactPropagatorMPO(mol, pbond, 1.0j*dt,\
            QNargs=QNargs, shift=GSshift)

    if spectratype == "abs":
        ketMPO = mpslib.mapply(dipoleMPO, ketMPO, QNargs=QNargs)
    else:
        dipoleMPOdagger = mpslib.conjtrans(dipoleMPO, QNargs=QNargs)
        if QNargs is not None:
            dipoleMPOdagger[1] = [[0] * len(impsdim)
                                  for impsdim in dipoleMPO[1]]
            dipoleMPOdagger[3] = 0
        ketMPO = mpslib.mapply(ketMPO, dipoleMPOdagger, QNargs=QNargs)

    braMPO = mpslib.add(ketMPO, None, QNargs=QNargs)

    if compress_method == "variational":
        ketMPO = mpslib.canonicalise(ketMPO, 'l', QNargs=QNargs)
        braMPO = mpslib.canonicalise(braMPO, 'l', QNargs=QNargs)

    if approxeiHt is not None:
        approxeiHpt = ApproxPropagatorMPO(HMPO, dt, ephtable, propagation_c,\
                thresh=approxeiHt, compress_method=compress_method, QNargs=QNargs)
        approxeiHmt = ApproxPropagatorMPO(HMPO, -dt, ephtable, propagation_c,\
                thresh=approxeiHt, compress_method=compress_method, QNargs=QNargs)
    else:
        approxeiHpt = None
        approxeiHmt = None

    for istep in xrange(nsteps):
        if istep != 0:
            t += dt
            # for emi bra and ket is conjugated
            if istep % 2 == 0:
                braMPO = mpslib.mapply(braMPO, exacteiHpt, QNargs=QNargs)
                braMPO = tMPS(braMPO, HMPO, -dt, ephtable, propagation_c,\
                       thresh=thresh, cleanexciton=1, compress_method=compress_method, \
                       QNargs=QNargs, approxeiHt=approxeiHmt, scheme=scheme,\
                       prefix=scheme+"2")
            else:
                ketMPO = mpslib.mapply(ketMPO, exacteiHmt, QNargs=QNargs)
                ketMPO = tMPS(ketMPO, HMPO, dt, ephtable, propagation_c, \
                       thresh=thresh, cleanexciton=1, compress_method=compress_method, \
                       QNargs=QNargs, approxeiHt=approxeiHpt, scheme=scheme,\
                       prefix=scheme+"1")

        ft = mpslib.dot(mpslib.conj(braMPO, QNargs=QNargs),
                        ketMPO,
                        QNargs=QNargs)
        if spectratype == "emi":
            ft = np.conj(ft)

        wfn_store(braMPO, istep, "braMPO.pkl")
        wfn_store(ketMPO, istep, "ketMPO.pkl")
        autocorr.append(ft / Z)
        autocorr_store(autocorr, istep)

    return autocorr
Ejemplo n.º 5
0
def ZeroTCorr(iMPS, HMPO, dipoleMPO, nsteps, dt, ephtable, thresh=0, \
        cleanexciton=None, algorithm=1, prop_method="C_RK4",\
        compress_method="svd", QNargs=None, approxeiHt=None, scheme="P&C"):
    '''
    the bra part e^iEt is negected to reduce the oscillation
    algorithm:
    algorithm 1 is the only propagte ket in 0, dt, 2dt
    algorithm 2 is propagte bra and ket in 0, dt, 2dt (in principle, with
    same calculation cost, more accurate, because the bra is also entangled,
    the entanglement is not only in ket)
    compress_method:  svd or variational
    cleanexciton: every time step propagation clean the good quantum number to
    discard the numerical error
    thresh: the svd threshold in svd or variational compress
    '''

    AketMPS = mpslib.mapply(dipoleMPO, iMPS, QNargs=QNargs)
    # store the factor and normalize the AketMPS, factor is the length of AketMPS
    factor = mpslib.dot(mpslib.conj(AketMPS, QNargs=QNargs),
                        AketMPS,
                        QNargs=QNargs)
    factor = np.sqrt(np.absolute(factor))
    print "factor", factor
    AketMPS = mpslib.scale(AketMPS, 1. / factor, QNargs=QNargs)

    if compress_method == "variational":
        AketMPS = mpslib.canonicalise(AketMPS, 'l', QNargs=QNargs)
    AbraMPS = mpslib.add(AketMPS, None, QNargs=QNargs)

    autocorr = []
    t = 0.0

    tableau = RK.runge_kutta_explicit_tableau(prop_method)
    propagation_c = RK.runge_kutta_explicit_coefficient(tableau)

    if approxeiHt is not None:
        approxeiHpt = ApproxPropagatorMPO(HMPO, dt, ephtable, propagation_c,\
                thresh=approxeiHt, compress_method=compress_method, QNargs=QNargs)
        approxeiHmt = ApproxPropagatorMPO(HMPO, -dt, ephtable, propagation_c,\
                thresh=approxeiHt, compress_method=compress_method, QNargs=QNargs)
    else:
        approxeiHpt = None
        approxeiHmt = None

    for istep in xrange(nsteps):
        if istep != 0:
            t += dt
            if algorithm == 1:
                AketMPS = tMPS(AketMPS, HMPO, dt, ephtable, propagation_c, thresh=thresh, \
                    cleanexciton=cleanexciton, compress_method=compress_method, \
                    QNargs=QNargs, approxeiHt=approxeiHpt, normalize=1., \
                    scheme=scheme, prefix=scheme)
            if algorithm == 2:
                if istep % 2 == 1:
                    AketMPS = tMPS(AketMPS, HMPO, dt, ephtable, propagation_c, thresh=thresh, \
                        cleanexciton=cleanexciton, compress_method=compress_method, QNargs=QNargs,\
                        approxeiHt=approxeiHpt, normalize=1., scheme=scheme, \
                        prefix=scheme+"1")
                else:
                    AbraMPS = tMPS(AbraMPS, HMPO, -dt, ephtable, propagation_c, thresh=thresh, \
                        cleanexciton=cleanexciton, compress_method=compress_method, QNargs=QNargs,\
                        approxeiHt=approxeiHmt, normalize=1., scheme=scheme,\
                        prefix=scheme+"2")
        ft = mpslib.dot(mpslib.conj(AbraMPS, QNargs=QNargs),
                        AketMPS,
                        QNargs=QNargs) * factor**2
        wfn_store(AbraMPS, istep, str(dt) + str(thresh) + "AbraMPS.pkl")
        wfn_store(AketMPS, istep, str(dt) + str(thresh) + "AketMPS.pkl")

        autocorr.append(ft)
        autocorr_store(autocorr, istep)

    return autocorr
Ejemplo n.º 6
0
def Exact_Spectra(spectratype, mol, pbond, iMPS, dipoleMPO, nsteps, dt,\
        temperature, GSshift=0.0, EXshift=0.0):
    '''
    0T emission spectra exact propagator
    the bra part e^iEt is negected to reduce the osillation
    and 
    for single molecule, the EX space propagator e^iHt is local, and so exact
    
    GS/EXshift is the ground/excited state space energy shift
    the aim is to reduce the oscillation of the correlation fucntion

    support:
    all cases: 0Temi
    1mol case: 0Temi, TTemi, 0Tabs, TTabs
    '''

    assert spectratype in ["emi", "abs"]

    if spectratype == "emi":
        space1 = "EX"
        space2 = "GS"
        shift1 = EXshift
        shift2 = GSshift

        if temperature != 0:
            assert len(mol) == 1
    else:
        assert len(mol) == 1
        space1 = "GS"
        space2 = "EX"
        shift1 = GSshift
        shift2 = EXshift

    if temperature != 0:
        beta = constant.T2beta(temperature)
        print "beta=", beta
        thermalMPO, thermalMPOdim = ExactPropagatorMPO(mol,
                                                       pbond,
                                                       -beta / 2.0,
                                                       space=space1,
                                                       shift=shift1)
        ketMPS = mpslib.mapply(thermalMPO, iMPS)
        Z = mpslib.dot(mpslib.conj(ketMPS), ketMPS)
        print "partition function Z(beta)/Z(0)", Z
    else:
        ketMPS = iMPS
        Z = 1.0

    AketMPS = mpslib.mapply(dipoleMPO, ketMPS)

    if temperature != 0:
        braMPS = mpslib.add(ketMPS, None)
    else:
        AbraMPS = mpslib.add(AketMPS, None)

    t = 0.0
    autocorr = []
    propMPO1, propMPOdim1 = ExactPropagatorMPO(mol,
                                               pbond,
                                               -1.0j * dt,
                                               space=space1,
                                               shift=shift1)
    propMPO2, propMPOdim2 = ExactPropagatorMPO(mol,
                                               pbond,
                                               -1.0j * dt,
                                               space=space2,
                                               shift=shift2)

    # we can reconstruct the propagator each time if there is accumulated error

    for istep in xrange(nsteps):
        if istep != 0:
            AketMPS = mpslib.mapply(propMPO2, AketMPS)
            if temperature != 0:
                braMPS = mpslib.mapply(propMPO1, braMPS)

        if temperature != 0:
            AbraMPS = mpslib.mapply(dipoleMPO, braMPS)

        ft = mpslib.dot(mpslib.conj(AbraMPS), AketMPS)
        autocorr.append(ft / Z)
        autocorr_store(autocorr, istep)

    return autocorr
Ejemplo n.º 7
0
def Quasi_Boson_MPO(opera, nqb, trunc, base=2, C1=1.0, C2=1.0):
    '''
    nqb : # of quasi boson sites
    opera : operator to be decomposed
            "b + b^\dagger"
    '''
    assert opera in ["b + b^\dagger","b^\dagger b", "b", "b^\dagger", \
            "C1(b + b^\dagger) + C2(b + b^\dagger)^2"]

    # the structure is [bra_highest_bit, ket_highest_bit,..., bra_lowest_bit,
    # ket_lowest_bit]
    mat = np.zeros([
        base,
    ] * nqb * 2)

    if opera == "b + b^\dagger" or opera == "b^\dagger" or opera == "b":
        if opera == "b + b^\dagger" or opera == "b^\dagger":
            for i in xrange(1, base**nqb):
                # b^+
                lstring = np.array(map(int, baseConvert(i, base).zfill(nqb)))
                rstring = np.array(
                    map(int,
                        baseConvert(i - 1, base).zfill(nqb)))
                pos = tuple(roundrobin(lstring, rstring))
                mat[pos] = np.sqrt(i)

        if opera == "b + b^\dagger" or opera == "b":
            for i in xrange(0, base**nqb - 1):
                # b
                lstring = np.array(map(int, baseConvert(i, base).zfill(nqb)))
                rstring = np.array(
                    map(int,
                        baseConvert(i + 1, base).zfill(nqb)))
                pos = tuple(roundrobin(lstring, rstring))
                mat[pos] = np.sqrt(i + 1)

    elif opera == "C1(b + b^\dagger) + C2(b + b^\dagger)^2":
        # b^+
        for i in xrange(1, base**nqb):
            lstring = np.array(map(int, baseConvert(i, base).zfill(nqb)))
            rstring = np.array(map(int, baseConvert(i - 1, base).zfill(nqb)))
            pos = tuple(roundrobin(lstring, rstring))
            mat[pos] = C1 * np.sqrt(i)
        # b
        for i in xrange(0, base**nqb - 1):
            lstring = np.array(map(int, baseConvert(i, base).zfill(nqb)))
            rstring = np.array(map(int, baseConvert(i + 1, base).zfill(nqb)))
            pos = tuple(roundrobin(lstring, rstring))
            mat[pos] = C1 * np.sqrt(i + 1)
        # bb
        for i in xrange(0, base**nqb - 2):
            lstring = np.array(map(int, baseConvert(i, base).zfill(nqb)))
            rstring = np.array(map(int, baseConvert(i + 2, base).zfill(nqb)))
            pos = tuple(roundrobin(lstring, rstring))
            mat[pos] = C2 * np.sqrt(i + 2) * np.sqrt(i + 1)
        # b^\dagger b^\dagger
        for i in xrange(2, base**nqb):
            lstring = np.array(map(int, baseConvert(i, base).zfill(nqb)))
            rstring = np.array(map(int, baseConvert(i - 2, base).zfill(nqb)))
            pos = tuple(roundrobin(lstring, rstring))
            mat[pos] = C2 * np.sqrt(i) * np.sqrt(i - 1)
        # b^\dagger b + b b^\dagger
        for i in xrange(0, base**nqb):
            lstring = np.array(map(int, baseConvert(i, base).zfill(nqb)))
            rstring = np.array(map(int, baseConvert(i, base).zfill(nqb)))
            pos = tuple(roundrobin(lstring, rstring))
            mat[pos] = C2 * float(i * 2 + 1)

    elif opera == "b^\dagger b":
        # actually Identity operator can be constructed directly
        for i in xrange(0, base**nqb):
            # I
            lstring = np.array(map(int, baseConvert(i, base).zfill(nqb)))
            rstring = np.array(map(int, baseConvert(i, base).zfill(nqb)))
            pos = tuple(roundrobin(lstring, rstring))
            mat[pos] = float(i)

    # check the original mat
    # mat = np.moveaxis(mat,range(1,nqb*2,2),range(nqb,nqb*2))
    # print mat.reshape(base**nqb,base**nqb)

    # decompose canonicalise
    MPO = []
    mat = mat.reshape(1, -1)
    for idx in xrange(nqb - 1):
        U, S, Vt = scipy.linalg.svd(mat.reshape(mat.shape[0]*base**2,-1), \
                full_matrices=False)
        U = U.reshape(mat.shape[0], base, base, -1)
        MPO.append(U)
        mat = np.einsum("i, ij -> ij", S, Vt)

    MPO.append(mat.reshape(-1, base, base, 1))
    print "original MPO shape:", [i.shape[0] for i in MPO] + [1]

    # compress
    MPOnew = mpslib.compress(MPO, 'l', trunc=trunc)
    print "trunc", trunc, "distance", mpslib.distance(MPO, MPOnew)
    fidelity = mpslib.dot(mpslib.conj(MPOnew), MPO) / mpslib.dot(
        mpslib.conj(MPO), MPO)
    print "compression fidelity:: ", fidelity
    print "compressed MPO shape", [i.shape[0] for i in MPOnew] + [1]

    return MPOnew