def runge_kutta_vs_exact(Hmat, e, c0, nsteps, dt, prop_method="C_RK4",store_freq=500): ''' e, c are the eigenvalue and eigenvector of Hmat, c0 is normalized to 1 ''' # runge-kutta from ephMPS import RK tableau = RK.runge_kutta_explicit_tableau(prop_method) propagation_c = RK.runge_kutta_explicit_coefficient(tableau) ct_rk_list = [] for istep in xrange(nsteps): if istep == 0: ct_rk = c0 else: termlist = [ct_rk] for iterm in xrange(len(propagation_c)-1): termlist.append(Hmat.dot(termlist[iterm])-e[0]*termlist[iterm]) ct_rk_new = np.zeros(c0.shape, dtype=np.complex128) for iterm in xrange(len(propagation_c)): ct_rk_new += termlist[iterm]*(-1.0j*dt)**iterm*propagation_c[iterm] ct_rk = ct_rk_new ct_rk = ct_rk / np.linalg.norm(ct_rk) ct_rk_list.append(ct_rk) if (istep+1) % store_freq == 0: autocorr_store(ct_rk_list, istep+1, index=(istep+1), freq=store_freq) ct_rk_list = [] return ct_rk_list
def hybrid_TDDMRG_TDH(mol, J, MPS, WFN, dt, ephtable, thresh=0.,\ cleanexciton=None, QNargs=None, TDDMRG_prop_method="C_RK4", TDH_prop_method="unitary", normalize=1.0): ''' hybrid TDDMRG and TDH solver 1.gauge is g_k = 0 ''' # construct Hamiltonian if QNargs is None: MPO, MPOdim, MPOQN, MPOQNidx, MPOQNtot, HAM, Etot = construct_hybrid_Ham( mol, J, MPS, WFN) else: MPO, MPOdim, MPOQN, MPOQNidx, MPOQNtot, HAM, Etot = construct_hybrid_Ham( mol, J, MPS[0], WFN) MPO = [MPO, MPOQN, MPOQNidx, MPOQNtot] print "Etot", Etot # EOM of coefficient a WFN[-1] *= np.exp(Etot / 1.0j * dt) # EOM of TDDMRG tableau = RK.runge_kutta_explicit_tableau(TDDMRG_prop_method) propagation_c = RK.runge_kutta_explicit_coefficient(tableau) MPS = tMPS.tMPS(MPS, MPO, dt, ephtable, propagation_c, thresh=thresh, \ cleanexciton=cleanexciton, QNargs=QNargs, normalize=normalize) # EOM of TDH # here if TDH also use RK4, then the TDDMRG part should be changed to get # t=t_1, t=t_2... wfn and slope k if TDH_prop_method == "unitary": TDH.unitary_propagation(HAM, WFN, dt) return MPS, WFN
def thermal_prop(iMPO, HMPO, nsteps, ephtable, thresh=0, temperature=298, \ prop_method="C_RK4", compress_method="svd", QNargs=None, approxeiHt=None, normalize=None): ''' do imaginary propagation ''' tableau = RK.runge_kutta_explicit_tableau(prop_method) propagation_c = RK.runge_kutta_explicit_coefficient(tableau) beta = constant.T2beta(temperature) print "beta=", beta dbeta = beta / float(nsteps) if approxeiHt is not None: approxeiHpt = ApproxPropagatorMPO(HMPO, -0.5j*dbeta, ephtable, propagation_c,\ thresh=approxeiHt, compress_method=compress_method, QNargs=QNargs) else: approxeiHpt = None ketMPO = mpslib.add(iMPO, None, QNargs=QNargs) it = 0.0 for istep in xrange(nsteps): it += dbeta ketMPO = tMPS(ketMPO, HMPO, -0.5j*dbeta, ephtable, propagation_c,thresh=thresh,\ cleanexciton=1, compress_method=compress_method, QNargs=QNargs,\ approxeiHt=approxeiHpt, normalize=normalize) return ketMPO
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
def TDH(mol, J, nexciton, WFN, dt, fe, fv, prop_method="unitary", particle="hardcore boson"): ''' time dependent Hartree solver 1. gauge is g_k = 0 2. f = fe + fv is DOF 3. two propagation method: exact and RK, exact is unitary and is practically better than RK4. if dt_exact < 1/4 dt_RK4, exact is definitely better than RK4. ''' f = fe + fv assert (fe + fv) == (len(WFN) - 1) # EOM of wfn if prop_method == "unitary": HAM, Etot = construct_H_Ham(mol, J, nexciton, WFN, fe, fv, particle=particle) unitary_propagation(HAM, WFN, dt) else: [RK_a, RK_b, RK_c, Nstage] = RK.runge_kutta_explicit_tableau(prop_method) klist = [] for istage in xrange(Nstage): WFN_temp = copy.deepcopy(WFN) for jterm in xrange(istage): for iwfn in xrange(f): WFN_temp[ iwfn] += klist[jterm][iwfn] * RK_a[istage][jterm] * dt HAM, Etot_check = construct_H_Ham(mol, J, nexciton, WFN_temp, fe, fv, particle=particle) if istage == 0: Etot = Etot_check klist.append( [HAM[iwfn].dot(WFN_temp[iwfn]) / 1.0j for iwfn in xrange(f)]) for iwfn in xrange(f): for istage in xrange(Nstage): WFN[iwfn] += RK_b[istage] * klist[istage][iwfn] * dt # EOM of coefficient a print "Etot", Etot WFN[-1] *= np.exp(Etot / 1.0j * dt) return WFN
def test_RK(self): tableau = RK.runge_kutta_explicit_tableau("Forward_Euler") vout = RK.runge_kutta_explicit_coefficient(tableau) self.assertTrue(np.allclose(vout,[1.0,1.0])) tableau = RK.runge_kutta_explicit_tableau("Heun_RK2") vout = RK.runge_kutta_explicit_coefficient(tableau) self.assertTrue(np.allclose(vout,[1.0,1.0,0.5])) tableau = RK.runge_kutta_explicit_tableau("Ralston_RK2") vout = RK.runge_kutta_explicit_coefficient(tableau) self.assertTrue(np.allclose(vout,[1.0,1.0,0.5])) tableau = RK.runge_kutta_explicit_tableau("midpoint_RK2") vout = RK.runge_kutta_explicit_coefficient(tableau) self.assertTrue(np.allclose(vout,[1.0,1.0,0.5])) tableau = RK.runge_kutta_explicit_tableau("Kutta_RK3") vout = RK.runge_kutta_explicit_coefficient(tableau) self.assertTrue(np.allclose(vout,[1.,1.,0.5,0.16666667])) tableau = RK.runge_kutta_explicit_tableau("C_RK4") vout = RK.runge_kutta_explicit_coefficient(tableau) self.assertTrue(np.allclose(vout,[1.,1.,0.5,0.16666667,0.04166667])) tableau = RK.runge_kutta_explicit_tableau("38rule_RK4") vout = RK.runge_kutta_explicit_coefficient(tableau) self.assertTrue(np.allclose(vout,[1.,1.,0.5,0.16666667,0.04166667]))
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
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
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