def Qs2Kc(ltemp,QA,QB,VA,VB,nR=1,nP=1): ''' Qi; partition function per unit volume Kc = [B]/[A] ''' term_V = pc.VOL0**(nP-nR) return [term_V*QB[idx]/QA[idx]*exp128(-(VB-VA)/pc.KB/T) for idx,T in enumerate(ltemp)]
def get_contributions(ctc, dall, dctc, ltemp): if ctc not in dctc.keys(): return None # Only one conformer? if len(dctc[ctc]._itcs) == 1: itc, weight = dctc[ctc]._itcs[0] dchi = {itc: [1.0 for T in ltemp]} return dchi # Get total partition function V0, V1, PFN = dall["pfn"]["%s.msho" % ctc] # Get ratios dchi = {} for itc, weight in dctc[ctc]._itcs: # Get individual partition functions try: V0i, V1i, PFNi = dall["pfn"][PN.struckey(ctc, itc)] # Calculate contribution dE = (V1i - V1) exp_arg = [-dE / pc.KB / T for T in ltemp] ratio_pfn = [weight * pfi / pftot for pfi, pftot in zip(PFNi, PFN)] chi_i = [ aa * fncs.exp128(bb) for aa, bb in zip(ratio_pfn, exp_arg) ] dchi[itc] = np.array(chi_i) except: exception = Exc.LostConformer(Exception) exception._var = PN.struckey(ctc, itc) raise exception # Return data return dchi
def calc_cag(ltemp, VadiSpl, lscvt=None): # calculate dE sAG, VAG = VadiSpl.get_max() if lscvt is None: Ediff = [VAG - VadiSpl(0.0) for T in ltemp] else: Ediff = [VAG - VadiSpl(s_i) for s_i in lscvt] # get cag cag = [fncs.exp128(-dE / pc.KB / T) for T, dE in zip(ltemp, Ediff)] return Ediff, cag
def pfnder_ele(les, Tlist): pfn_ele = [0.0 for T in Tlist] fd_ele = [0.0 for T in Tlist] sd_ele = [0.0 for T in Tlist] for idx, T in enumerate(Tlist): beta = 1.0 / pc.KB / T for mtp, relE in les: pfn_ele[idx] += mtp * exp128(-beta * relE) fd_ele[idx] += (relE) * mtp * exp128(-beta * relE) sd_ele[idx] += (relE**2) * mtp * exp128(-beta * relE) # convert to array pfn_ele = np.array(pfn_ele) fd_ele = np.array(fd_ele) sd_ele = np.array(sd_ele) # we care about derivatives of logQ fdln_ele = fd_ele / pfn_ele sdln_ele = sd_ele / pfn_ele - (fd_ele / pfn_ele)**2 return pfn_ele, fdln_ele, sdln_ele
def pm_dsoverdt(t, gp, lamb): ''' returns ds/dt ''' nelements = lamb.shape[0] dsdt = 0.0 for i in range(nelements): dsdt += ( gp[i,0] * fncs.exp128( -lamb[i,i] * t) )**2 dsdt = np.sqrt( dsdt) return dsdt
def fit2anarc(tlist,rclist,log=True): # initialize dictionary dfit = {} # number of points npts = len(tlist) if npts != len(rclist): return dfit #---------# # Guesses # #---------# # Get guesses for each type if npts < 2: return dfit x1 = 1.0/tlist[ 0] x2 = 1.0/tlist[-1] y1 = np.log(rclist[ 0]) y2 = np.log(rclist[-1]) B = (y1-y2)/(x2-x1) lnA = y1+B*x1 A = exp128(lnA) A,B = float(A),float(B) # curve fit DOES NOT admit float128 # dictionary of guesses for each type of rate constant GUESSES = {} GUESSES[1] = [A,B] GUESSES[2] = [A,B,0.0] GUESSES[3] = [A,B,0.0] GUESSES[4] = [A,B,0.0,100.0] # A, B, n, T0 GUESSES[5] = [A,B,0.0,100.0] # A, B, n, T0 # log is True or False?? if log: FNCS = LOGANFNC rclist = [float(np.log(k)) for k in rclist] else: FNCS = ANFNC rclist = [float(ki) for ki in rclist] #-----------------------# # Fitting and r^2 # #-----------------------# for atype in sorted(FNCS.keys()): function, nparams = FNCS[atype] guess = GUESSES[atype] if npts < nparams: continue # fitting try : popt, pcov = curve_fit(function, tlist, rclist, p0=guess, maxfev=10000) except: continue # calculate r^2 if len(popt) != nparams: continue r2 = get_r2(tlist,rclist,function,popt) # add Tr to return if atype in [3,4,5]: popt = list(popt)+[TR_DEFAULT] # save data dfit[atype] = (popt,r2) # save analytic3 for analytic4 guesses if atype == 3: GUESSES[4][0:3] = popt[0:3] if atype == 4: GUESSES[5][0:4] = popt[0:4] return dfit
def conformer_contributions(ltemp, dpfn, ctc, itcs): # get contributions dchi = {} for itc, weight in itcs: V0i, V1i, Qi = dpfn[PN.struckey(ctc, itc)] V0, V1, Q = dpfn[PN.struckey(ctc, "msho")] # calculate contribution expvec = [exp128(-(V1i - V1) / KB / T) for T in ltemp] chi = weight * np.array(Qi) / np.array(Q) * np.array(expvec) # save data dchi[itc] = chi return dchi
def get_sct_part4(svals, lmueff, VadiSpl, E0): ''' Calculation of tunnelling probabilities if mueff is float (=mu) --> ZCT if mueff is a list --> SCT ''' sAG, VAG = VadiSpl.get_max() # List of energies for Gaussian quadrature E_list, weights = gauquad_pointsweights(80, E0, VAG) # Calculate theta_ZCT or theta_SCT (T-independent) thetuple = [get_theta(E, svals, lmueff, VadiSpl) for E in E_list] thetas = [theta for theta, rps, diff in thetuple] rpoints = [rps for theta, rps, diff in thetuple] diffs = [diff for theta, rps, diff in thetuple] # Probabilities probs = [1.0 / (1.0 + fncs.exp128(2.0 * theta)) for theta in thetas] # Calculate theta also at E=E0 theta0, rps0, diff0 = get_theta(E0, svals, lmueff, VadiSpl) prob0 = 1.0 / (1.0 + fncs.exp128(2.0 * theta0)) # return data return weights, E_list, probs, rpoints, diffs, (prob0, rps0)
def anarc1(T,A,B): ''' Arrhenius: k = A*exp(-B/T); * A in cm^3/molecule/s * B in K. ''' # to avoid "RuntimeWarning: invalid value encountered in power" if A < 0.0: return np.inf # Calculate rate constant k = A * exp128(-B/T) # Return k return k
def get_ratecons(rcs,dchem,dall,idx,temp): drcons = dall.get("rcons",{}) processes = [] for key,(rctype,weight,coefs) in sorted(rcs.items()): rctype = rctype.lower() # reaction name and direction if "." in key: rcname, direction = key.split(".") else : rcname, direction = key, "both" # elements in reaction Rs,TS,Ps = dchem[rcname] nR,nP = len(Rs),len(Ps) # read/calculate rate constant if "analytic" not in rctype: key_fw = "%s.%s.%s"%(rctype,rcname,"fw") key_bw = "%s.%s.%s"%(rctype,rcname,"bw") # get rate constants kfw = drcons.get(key_fw,None) kbw = drcons.get(key_bw,None) if kfw is not None: kfw = kfw[idx] if kbw is not None: kbw = kbw[idx] # any non-desired rate constants if direction == "fw": kbw = None if direction == "bw": kfw = None # none if kbw is None and kfw is None: exception =Exc.NoRateCons(Exception) exception._var = (rctype,key) raise exception else: if rctype.lower() == "analytic1": k = log_anarc1(temp,*coefs) elif rctype.lower() == "analytic2": k = log_anarc2(temp,*coefs) elif rctype.lower() == "analytic3": k = log_anarc3(temp,*coefs) elif rctype.lower() == "analytic4": k = log_anarc4(temp,*coefs) elif rctype.lower() == "analytic5": k = log_anarc5(temp,*coefs) else : k = None # log --> exp if k is not None: k = exp128(k) # save data properly if direction in ["fw","both"]: kfw, kbw = k , None elif direction in ["bw" ]: kfw, kbw = None, k else : kfw, kbw = None, None # in atomic units hunitsFW = ML**(nR-1.0) / SECOND hunitsBW = ML**(nP-1.0) / SECOND if kfw is not None: kfw /= hunitsFW if kbw is not None: kbw /= hunitsBW # ignore reactions giving rise to bimolecular products if len(Ps) > 1 and direction != "bw": kbw = None # save in processes if kfw is not None: processes.append( (Rs,Ps,weight*kfw) ) if kbw is not None: processes.append( (Ps,Rs,weight*kbw) ) return processes
def anarc2(T,A,B,n): ''' Van't Hoff type 1: k = A*T^n*exp(-B/T) * A*T^n in cm^3/molecule/s. * B in K. * n (adimensional) ''' # to avoid "RuntimeWarning: invalid value encountered in power" if A < 0.0: return np.inf # Calculate rate constant k = A * (T**n) * exp128(-B/T) # Return k return k
def obtain_pfns(self): # (a) reactants for target in self._reacts: self.calculate_chi0(target) V0, V1, pfns, anh = self.return_pfns(target) self._V0R += V0 self._V1R += V1 self._QtR *= pfns self._ANHR *= anh self._FMSQH *= self._chi0[target][1] # (b) products for target in self._prods: V0, V1, pfns, anh = self.return_pfns(target) self._V0P += V0 self._V1P += V1 self._QtP *= pfns self._ANHP *= anh # (c) transition state if self._ts is None: return # (c.1) get partition functions self.calculate_chi0(self._ts) self._V0TS, self._V1TS, self._QtTS, self._ANHTS = self.return_pfns( self._ts) # (c.2) Conversion betweem SS-QH and MS-QH rate constants self._FMSQH /= self._chi0[self._ts][1] # (c.2) get individual contributions of TS and itc of min(V0) ctc, itcs, ms = self._itcs[self._ts] if ms: V0, V1, PFN = self._dall["pfn"][PN.struckey(ctc, "msho")] # save most stable conformer self._tsitc0 = self._chi0[self._ts][0] # calculate chi for each conformer of the ts for itc, weight in itcs: # see pfn V0i, V1i, PFNi = self._dall["pfn"][PN.struckey(ctc, itc)] dE = (V1i - V1) exp_arg = [-dE / KB / T for T in self._ltemp] ratio_pfn = [ weight * pfi / pftot for pfi, pftot in zip(PFNi, PFN) ] chi_i = [ aa * fncs.exp128(bb) for aa, bb in zip(ratio_pfn, exp_arg) ] # save data self._tschi["tst"][itc] = np.array(chi_i) else: itc, weight = itcs[0] self._tschi["tst"][itc] = np.array([1.0 for T in self._ltemp]) self._tsitc0 = None
def kappa_integral1(E_list, probs, weights, beta, VAG): ''' integral from E0 to VAG ''' integral = 0.0 INTGRND = [] for idx in range(len(E_list)): E_i = E_list[idx] w_i = weights[idx] pE = probs[idx] integrand = pE * fncs.exp128(-beta * (E_i - VAG)) * beta INTGRND.append(integrand) integral += w_i * integrand del integrand return integral, INTGRND
def kappa_integral2(E_list, probs, weights, beta, VAG): integral = 0.0 INTGRNDX = [] INTGRNDY = [] for idx in range(len(E_list)): E_i = E_list[idx] w_i = weights[idx] pE = probs[idx] integrand = (1.0 - pE) * fncs.exp128(-beta * (2 * VAG - E_i - VAG)) * beta INTGRNDX.append(2 * VAG - E_i) INTGRNDY.append(integrand) integral += w_i * integrand del integrand return integral, INTGRNDX[::-1], INTGRNDY[::-1]
def get_sct_part3(svals, lmueff, VadiSpl, afreq, lEquant, E0, VAG, temps): ''' discrete sum from E0 to VAG Surface Science, 164, 558-588 (1985) ''' lCOEF = [] # Only energies between E0 and VAG lEquant = [E for E in lEquant if E0 - EPS_MEPE <= E <= VAG + EPS_MEPE] # calculate theta and p(E) for each energies thetuple = [get_theta(En, svals, lmueff, VadiSpl) for En in lEquant] thetas = [theta for theta, rps, diff in thetuple] rpoints = [rps for theta, rps, diff in thetuple] diffs = [diff for theta, rps, diff in thetuple] # Probability probs = [1.0 / (1.0 + fncs.exp128(2.0 * theta)) for theta in thetas] # calculate coefficient dEndn = pc.HBAR * afreq for idx, T in enumerate(temps): beta = 1.0 / (pc.KB * T) kappa = 0.0 for En, pE in zip(lEquant, probs): kappa += dEndn * pE * fncs.exp128(-beta * (En - VAG)) * beta lCOEF.append(kappa) return lCOEF, lEquant, probs, rpoints, diffs
def anarc3(T,A,B,n,Tr=TR_DEFAULT): ''' Van't Hoff type 2: k = A*(T/Tr)^n*exp(-B/T) * A in cm^3/molecule/s. * B in K. * n (adimensional) * Tr in Kelvin ''' # to avoid "RuntimeWarning: invalid value encountered in power" if A < 0.0: return np.inf if Tr < 0.0: return np.inf # Calculate rate constant k = A * ((T/Tr)**n) * exp128(-B/T) # Return k return k
def pm_nextxms(xms,ds,gms,Fms,t0=None): ''' Calculate next geometry using page-mciver method If fail in calculating t parameter, quadratic Taylor expasion is used. ''' tmethod = "quad" # ("quad" or "trap") natoms = fncs.howmanyatoms(xms) # to numpy arrays if xms is not None: xms = np.matrix(np.array([xms]).transpose()) if gms is not None: gms = np.matrix(np.array([gms]).transpose()) if Fms is not None: Fms = np.matrix(np.array(Fms)) # Get Hessian eigenvalues and eigenvectors alpha, U = np.linalg.eigh(Fms) # Get projection of gradient gp = U.transpose() * gms # Put eigenvectors in diagonal matrix alpha = np.diag(alpha) # check dimensions if gms.shape != (3*natoms, 1): exit("Problems in 'pm_nextxms'") if gp.shape != (3*natoms, 1): exit("Problems in 'pm_nextxms'") if U.shape != (3*natoms,3*natoms): exit("Problems in 'pm_nextxms'") # get t if t0 is None: t = pm_gett(ds,gp,alpha,tmethod) else : t = t0 # apply taylor? if t is None: xms = np.array(xms.transpose().tolist()[0]) gms = np.array(gms.transpose().tolist()[0]) Fms = np.array(Fms.tolist() ) return sd_taylor(xms,ds,gms,Fms), None # Get Mn matrix M = np.identity(3*natoms) for i in range(3*natoms): M[i,i] = (fncs.exp128(- alpha[i,i] * t) - 1.0) / alpha[i,i] # Get D(t) D = U * M * U.transpose() # Get dx vector dx_vector = D * gms # to normal array xms = np.array( xms.transpose().tolist()[0]) dx_vector = np.array(dx_vector.transpose().tolist()[0]) # Get new geom xms_next = xms + dx_vector return xms_next, t
def contrib_tr_rv_el_tor(chemreacH,chemreacD,dirH,dirD): # get data QtrH_R, QrvH_R, QelH_R, V1H_R,\ QtrD_R, QrvD_R, QelD_R, V1D_R,\ anh_kH, dkH,\ anh_kD, dkD,\ QtrH_TS, QrvH_TS, QelH_TS, V1H_TS,\ QtrD_TS, QrvD_TS, QelD_TS, V1D_TS = main_data(chemreacH,chemreacD,dirH,dirD) # calculate contributions ltemp = chemreacH._ltemp dE = (V1H_TS-V1H_R)-(V1D_TS-V1D_R) vE = np.array([exp128(-dE/KB/T) for T in ltemp]) kies_tr = (QtrH_TS/QtrH_R) / (QtrD_TS/QtrD_R) kies_rv = (QrvH_TS/QrvH_R) / (QrvD_TS/QrvD_R) * vE kies_el = (QelH_TS/QelH_R) / (QelD_TS/QelD_R) kies_tor = anh_kH/anh_kD return kies_tr,kies_rv,kies_el,kies_tor
def calculate_chi0(self, target): ctc, itcs, ms = self._itcs[target] # Get total partition function key = PN.struckey(ctc, "msho") V0, V1, PFN = self._dall["pfn"][key] # Get contribution of each conformer itc0, V0_0, V1_0, PFN_0 = None, float("inf"), float("inf"), None for itc, weight_i in itcs: # individual partition function key_i = PN.struckey(ctc, itc) V0_i, V1_i, PFN_i = self._dall["pfn"][key_i] if V0_i < V0_0: itc0, V0_0, V1_0, PFN_0 = itc, V0_i, V1_i, PFN_i # contribution of most stable conformer (wo considering weight) dE = (V1_0 - V1) exp_arg = [-dE / KB / T for T in self._ltemp] ratio_pfn = [pfi / pftot for pfi, pftot in zip(PFN_0, PFN)] chi_i = [aa * fncs.exp128(bb) for aa, bb in zip(ratio_pfn, exp_arg)] self._chi0[target] = (itc0, np.array(chi_i))
def anarc5(T,A,B,n,T0,Tr=TR_DEFAULT): ''' Truhlar: k = A*((T+T0)/Tr)^n*exp(-B*(T+T0)/(T^2+T0^2)) * A in cm^3/molecule/s. * B in K. * n (adimensional) * Tr in Kelvin * T0 in Kelvin ''' # to avoid "RuntimeWarning: invalid value encountered in power" if A < 0.0: return np.inf if Tr < 0.0: return np.inf # avoid negative values if T0 < 0.0: return np.inf # Calculate rate constant tfrac1 = (T+T0)/Tr tfrac2 = (T+T0)/(T**2 + T0**2) k = A * (tfrac1**n) * exp128(-B*tfrac2) # Return k return k
def relative_gamma(xvals, yvals, T): # better values in kcal/mol yvals = [yi * pc.KCALMOL for yi in yvals] # find maximum spl = Spline(xvals, yvals, tan="findiff", tension=0.0) spl.find_xtr("max") CVT_s, CVT_gibbs = spl.get_max() # undo kcal/mol CVT_gibbs = CVT_gibbs / pc.KCALMOL # CVT values CVT_s = float(CVT_s) CVT_gamma = fncs.exp128(-(CVT_gibbs / pc.KB / T)) # Correct value, just in case if CVT_gamma > 1.0: CVT_gamma = 1.0 # data with more points (for plotting) npts = 20 * len(xvals) dx = (xvals[-1] - xvals[0]) / (npts) new_xx = [xvals[0] + ii * dx for ii in range(npts + 1)] new_yy = [spl(x) / pc.KCALMOL for x in new_xx] # return return float(CVT_s), float(CVT_gamma), (new_xx, new_yy)
def obtain_pfns(self): # (a) reactants for target in self._reacts: V0, V1, pfns, anh = self.return_pfns(target) self._V0R += V0 self._V1R += V1 self._QtR *= pfns self._ANHR *= anh # (b) products for target in self._prods: V0, V1, pfns, anh = self.return_pfns(target) self._V0P += V0 self._V1P += V1 self._QtP *= pfns self._ANHP *= anh # (c) transition state if self._ts is None: return self._V0TS, self._V1TS, self._QtTS, self._ANHTS = self.return_pfns(self._ts) # (c.1) get individual contributions of TS and itc of min(V0) ctc, itcs, ms = self._itcs[self._ts] if ms: minV0 = float("inf") V0,V1,PFN = self._dall["pfn"][PN.struckey(ctc,"msho")] for itc,weight in itcs: # see pfn V0i,V1i,PFNi = self._dall["pfn"][PN.struckey(ctc,itc)] dE = (V1i-V1) exp_arg = [-dE/KB/T for T in self._ltemp] ratio_pfn = [weight*pfi/pftot for pfi,pftot in zip(PFNi,PFN)] chi_i = [aa*fncs.exp128(bb) for aa,bb in zip(ratio_pfn,exp_arg)] # see most stable if V0i < minV0: minV0, self._tsitc0 = V0i, itc # save data self._tschi["tst"][itc] = np.array(chi_i) else : itc,weight = itcs[0] self._tschi["tst"][itc] = np.array( [1.0 for T in self._ltemp] ) self._tsitc0 = None
def pf_harmosc1D(angfreq, T, imag=1E10): if angfreq < 0.0: return imag elif angfreq == 0.0: return 1.0 exp = exp128(-pc.HBAR * angfreq / pc.KB / T) qHO = 1.0 / (1.0 - exp) return qHO
def pf_electr(eslist, T): pf, beta = 0.0, 1.0 / pc.KB / T for deg, relE in eslist: pf += deg * exp128(-relE * beta) return pf
def kappa_integral3(E0, VAG, beta): return fncs.exp128(-beta * (2 * VAG - E0 - VAG))
def readout_pfn(pof): with open(pof, 'r') as asdf: lines = asdf.readlines() data = {} data["all"] = {} for idx, line in enumerate(lines): # weight for each itc if "| weight |" in line: idx2 = idx + 2 while True: if "------" in lines[idx2]: break itc, relV0, relV1, zpe, mass, weight = lines[idx2].replace( "|", " ").split()[0:6] data[itc] = {} data[itc]["weight"] = weight data[itc]["relV0"] = relV0 data[itc]["relV1"] = relV1 idx2 += 1 # Conformer if "Conformation:" in line: itc = line.split()[-1] #data[itc] = {} # V0, V1 and ZPE if "Electronic energy " in line: data[itc]["V0"] = line.split()[-2] data[itc]["V1"] = line.split()[-2] if "V0 + zero-point en" in line: data[itc]["V1"] = line.split()[-2] if "zero-point energy:" in line: data[itc]["zpe"] = line.split()[-3] # part fncs if "| Partition functions (pfns):" in line: data[itc]["T"] = [] data[itc]["Qtr"] = [] data[itc]["Qrot"] = [] data[itc]["Qvib(V1)"] = [] data[itc]["Qel"] = [] data[itc]["Qtot(V1)"] = [] idx2 = idx + 4 while True: if "------" in lines[idx2]: break the_line = lines[idx2].replace("|", " ") T, Qtr, Qtr_ml, Qrot, Qvib_V0, Qvib_V1, Qel = the_line.split() data[itc]["T"].append(T) data[itc]["Qtr"].append(Qtr) data[itc]["Qrot"].append(Qrot) data[itc]["Qvib(V1)"].append(Qvib_V1) data[itc]["Qel"].append(Qel) #data[itc]["Qtot(V1)" ].append(Qtot) idx2 += 1 idx2 += 9 while True: if "------" in lines[idx2]: break the_line = lines[idx2].replace("|", " ") T, Qtot_V0_au, Qtot_V1_au, Qtot_V0_ml, Qtot_V1_ml = the_line.split( ) data[itc]["Qtot(V1)"].append(Qtot_V1_au) idx2 += 1 # Gibbs if "| Gibbs free energy (hartree):" in line: data[itc]["G(v)"] = [] data[itc]["G(p)"] = [] idx2 = idx + 4 while True: if "------" in lines[idx2]: break T, GV0, Gp0 = lines[idx2].replace("|", " ").split() GV0 = "%.3f" % ( (float(GV0) - float(data[itc]["V0"])) * KCALMOL) Gp0 = "%.3f" % ( (float(Gp0) - float(data[itc]["V0"])) * KCALMOL) data[itc]["G(v)"].append(GV0) data[itc]["G(p)"].append(Gp0) idx2 += 1 # min(V0), min(V1) if "min(V0) =" in line: data["all"]["V0"] = line.split()[-2] if "min(V1) =" in line: data["all"]["V1"] = line.split()[-2] # total part fncs if "Total multi-structural HO" in line: data["all"]["T"] = [] data["all"]["Qtot(V1)"] = [] idx2 = idx + 4 while True: if "------" in lines[idx2]: break the_line = lines[idx2].replace("|", " ") T, QMSHO_V0_au, QMSHO_V1_au, QMSHO_V0_ml, QMSHO_V1_ml = the_line.split( ) data["all"]["T"].append(T) data["all"]["Qtot(V1)"].append(QMSHO_V1_au) idx2 += 1 # total Gibbs free energies if "Total HO Gibbs free energies" in line: data["all"]["G(v)"] = [] data["all"]["G(p)"] = [] idx2 = idx + 4 while True: if "------" in lines[idx2]: break the_line = lines[idx2].replace("|", " ") T, GV0, Gp0 = the_line.split() GV0 = "%.3f" % ( (float(GV0) - float(data["all"]["V0"])) * KCALMOL) Gp0 = "%.3f" % ( (float(Gp0) - float(data["all"]["V0"])) * KCALMOL) data["all"]["G(v)"].append(GV0) data["all"]["G(p)"].append(Gp0) idx2 += 1 # Anharmonicity if " ZPE_MSHO:" in line: data["all"]["ZPE_MSHO"] = line.split()[-2] if " ZPE_ANH :" in line: data["all"]["ZPE_ANH"] = line.split()[-2] if "Calculating anh. ratio" in line: data["all"]["ANH. RATIO"] = [] idx2 = idx + 5 while True: if "------" in lines[idx2]: break T, anh = lines[idx2].replace("|", " ").split() data["all"]["ANH. RATIO"].append(anh) idx2 += 1 # Rovibrational itc for itc in data.keys(): if itc == "all": continue Qrot = np.array([np.float128(v) for v in data[itc]["Qrot"]]) Qvib = np.array([np.float128(v) for v in data[itc]["Qvib(V1)"]]) Qrv = ["%.3E" % v for v in Qrot * Qvib] data[itc]["Qrv(V1)"] = Qrv # Rovibrational all try: Qtot = np.array([np.float128(v) for v in data["all"]["Qtot(V1)"]]) Qtr = np.array([float(v) for v in data[itc]["Qtr"]]) Qel = np.array([float(v) for v in data[itc]["Qel"]]) Qrv = ["%.3E" % v for v in Qtot / (Qtr * Qel)] data["all"]["Qrv(V1)"] = Qrv data["all"]["Qtr"] = list(data[itc]["Qtr"]) data["all"]["Qel"] = list(data[itc]["Qel"]) except: pass # vib with regards to V0 for itc in data.keys(): try: # correction factor from V1 to V0 V0, V1 = float(data[itc]["V0"]), float(data[itc]["V1"]) V1toV0 = np.array([exp128((V0-V1)/KB/float(T)) \ for T in data[itc]["T"]]) # correct Qvib if itc != "all": Qvib = np.array( [np.float128(v) for v in data[itc]["Qvib(V1)"]]) data[itc]["Qvib"] = [eformat(v, 3) for v in Qvib * V1toV0] # correct Qrv Qrv = np.array([np.float128(v) for v in data[itc]["Qrv(V1)"]]) data[itc]["Qrv"] = [eformat(v, 3) for v in Qrv * V1toV0] # correct Qtot Qtot = np.array([np.float128(v) for v in data[itc]["Qtot(V1)"]]) data[itc]["Qtot"] = [eformat(v, 3) for v in Qtot * V1toV0] except: pass # ANH partition function try: Qar = np.array([float(v) for v in data["all"]["ANH. RATIO"]]) Qtot = np.array([np.float128(v) for v in data["all"]["Qtot"]]) T = np.array([float(v) for v in data["all"]["T"]]) Gcor = -(np.log(Qar) * T * KB) * KCALMOL GV = np.array([float(v) for v in data["all"]["G(v)"]]) Gp = np.array([float(v) for v in data["all"]["G(p)"]]) data["all"]["Qanh"] = [eformat(v, 3) for v in Qar * Qtot] data["all"]["Ganh(v)"] = ["%.3f" % v for v in GV + Gcor] data["all"]["Ganh(p)"] = ["%.3f" % v for v in Gp + Gcor] except: pass # return all return data
def calculate_QMSHO_for_ctc(Cluster, ltemp, dimasses={}, tupleHL=None): global WARNINGS # expand data ctc = Cluster._ctc itcs = Cluster._itcs eslist = Cluster._es sptype = Cluster._type fscal = Cluster._fscal diso = Cluster._diso if tupleHL is None: dlevel, dhighlvl = False, {} else: dlevel, dhighlvl = tupleHL # get list of gts files and check existency gtsfiles = Cluster.gtsfiles() exception = Exc.LackOfGts(Exception) for gts in gtsfiles: if not os.path.exists(gts): exception._var = gts raise exception # Generate Molecule instances molecules = [] mass = None V0LLs = [] for idx, gts in enumerate(gtsfiles): itc, weight = itcs[idx] # tuple with isotopic if itc in diso.keys(): iso = diso[itc] elif "*" in diso.keys(): iso = diso["*"] else: iso = None tiso = (iso, dimasses) # prepare and add molecule molecule = molecule_prep(gts, eslist, tiso, fscal) # save low-level V0LLs.append(float(molecule._V0)) # save molecule molecules.append(molecule) # String string = "" #----------------------------------------------------# # APPLY DUAL LEVEL (DLEVEL) # #----------------------------------------------------# if dlevel: # get HL energies V0HLs = get_V0HL_list(Cluster, dhighlvl) # only one conformer?? Keep LL relative energy num_nones = V0HLs.count(None) if len(V0HLs) == num_nones + 1: dlevel_ok = True IDX = [ idx for idx, V0HL_i in enumerate(V0HLs) if V0HL_i is not None ][0] deltaE = V0HLs[IDX] - V0LLs[IDX] V0HLs = [V0LL_i + deltaE for V0LL_i in V0LLs] elif num_nones == 0: dlevel_ok, IDX = True, None else: dlevel_ok, IDX = False, None # add to string string += " keyword --dlevel activated: applying High-Level energies to this STRUC\n" string += "\n" string += " * Low-level (LL) and high-level (HL) energies (in hartree):\n" string += "\n" string += " ---------------------------------------------------\n" string += " conformer | LL energy | HL energy \n" string += " ---------------------------------------------------\n" for idx, (itc, weight) in enumerate(itcs): if V0HLs[idx] is None: V0HL = " - " else: V0HL = "%+17.8f" % V0HLs[idx] string += " %-9s | %+17.8f | %s " % (itc, V0LLs[idx], V0HL) if idx == IDX: string += "*" string += "\n" string += " ---------------------------------------------------\n" if IDX is not None: string += " * conformer for which the HL energy was found\n" string += "\n" # apply HL to each conformer if dlevel_ok: for idx, molecule in enumerate(molecules): molecule._V0 = float(V0HLs[idx]) molecule._ccV1 = molecule._V0 + float(molecule._cczpe) else: string += " * FAIL!! Not enough data... DUAL-LEVEL will be omitted!\n" string += "\n" WARNINGS.append("Dual-level was not applied to %s..." % ctc) #----------------------------------------------------# # Get min of V0 and V1 V0 = min([molecule._V0 for molecule in molecules]) V1 = min([molecule._ccV1 for molecule in molecules]) string += add_iblank(PS.getstring_ctc(sptype, molecules, itcs, V0, V1), 4) # Compare masses for molecule in molecules: if mass is None: mass = molecule._mass # compare masses if abs(mass - molecule._mass) * AMU > EPS_AMU: WARNINGS.append("Mass inconsistences in %s" % ctc) exception = Exc.DiffMassConf(Exception) exception._var = string raise exception # get partition functions for each molecule (and for CTC) dctr = {} dpfn = {} dgibbs1cm3 = {} dgibbs1bar = {} pfn_tot = [0.0 for T in ltemp] #pfn_gibbs = [0.0 for T in ltemp] # goes without sigma_rot for idx, molecule in enumerate(molecules): itc, weight = itcs[idx] V0_i, V1_i, pf_i, tuple_i = molecule_pfns(molecule, ltemp, sptype) key = PN.struckey(ctc, itc) # save individual pfn and gibbs free energy rotsigma = molecule._rotsigma # Considering volume --> 1 particle per cc gibbs1cm3_i = [ V1_i - KB * T * np.log(q_j * VOL0) for T, q_j in zip(ltemp, pf_i) ] # Considering pression --> 1bar gibbs1bar_i = [ V1_i - KB * T * np.log(q_j * pressure2vol(PRE0, T)) for T, q_j in zip(ltemp, pf_i) ] # save data dpfn[key] = (V0_i, V1_i, pf_i) dgibbs1cm3[key] = gibbs1cm3_i dgibbs1bar[key] = gibbs1bar_i # update MSHO values rel_V1 = V1_i - V1 for idx, T in enumerate(ltemp): beta = 1.0 / (T * KB) pfn_tot[idx] += weight * pf_i[idx] * exp128(-rel_V1 * beta) #pfn_gibbs[idx] += weight*pf_i[idx]*exp128(-rel_V1*beta)*rotsigma # add to string pf_PIB, pf_RR, pf_HO, pf_ele = tuple_i pf_RRHO = [aa * bb for aa, bb in zip(pf_RR, pf_HO)] dctr[key] = (pf_PIB, pf_RRHO, pf_ele) string += " " + "-" * len("Conformation: %s " % itc) + "\n" string += " Conformation: %s\n" % itc string += " " + "-" * len("Conformation: %s " % itc) + "\n" for line in molecule.info_string().split("\n"): string += " | " + line + "\n" #string += add_iblank(molecule.info_string(),5) string += " | Partition functions (pfns):\n" table_1a = PS.getstring_pfn1a(ltemp, pf_PIB, pf_RR, pf_HO, pf_ele, V0_i, V1_i) table_1b = PS.getstring_pfn1b(ltemp, pf_i, V0_i, V1_i) for line in table_1a.split("\n") + table_1b.split("\n"): string += " | " + line + "\n" #string += add_iblank(PS.getstring_pfn1(ltemp,pf_i,pf_PIB,pf_RR,pf_HO,pf_ele),7) string += " | Gibbs free energy (hartree):\n" for line in PS.spfn_igibbs(ltemp, gibbs1cm3_i, gibbs1bar_i).split("\n"): string += " | " + line + "\n" #string += add_iblank(PS.spfn_igibbs(ltemp,gibbs1cm3_i,gibbs1bar_i),7) # generate molden file molden = PN.get_gtsmolden(ctc, itc) if not os.path.exists(molden): if not os.path.exists(PN.DIR5): os.mkdir(PN.DIR5) #molecule.genfile_xyz(molden) molecule.genfile_molden(molden) string += " | file %s was generated\n" % molden string += "\n" string += "\n" # save Q_MSHO dpfn[PN.struckey(ctc, "msho")] = (V0, V1, pfn_tot) pf_PIBele = [aa * bb for aa, bb in zip(pf_PIB, pf_ele)] pf_RRHO = [aa / bb for aa, bb in zip(pfn_tot, pf_PIBele)] dctr[ctc] = (pf_PIB, pf_RRHO, pf_ele) # save Gibbs_MSHO gibbs1cm3_tot = [ V1 - KB * T * np.log(q_j * VOL0) for T, q_j in zip(ltemp, pfn_tot) ] gibbs1bar_tot = [ V1 - KB * T * np.log(q_j * pressure2vol(PRE0, T)) for T, q_j in zip(ltemp, pfn_tot) ] dgibbs1cm3[PN.struckey(ctc, "msho")] = gibbs1cm3_tot dgibbs1bar[PN.struckey(ctc, "msho")] = gibbs1bar_tot # Add to string nconfs = sum([weight for name, weight in itcs]) if nconfs > 1: dchi = conformer_contributions(ltemp, dpfn, ctc, itcs) string += "\n" string += " Total multi-structural HO pfn (QMS_HO):\n" string += add_iblank(PS.getstring_pfn2a(ltemp, pfn_tot, V0, V1), 5) string += " Total HO Gibbs free energies (GFE):\n" string += add_iblank( PS.getstring_pfn2b(ltemp, gibbs1cm3_tot, gibbs1bar_tot), 5) string += " Individual contributions to the partition function:\n" string += add_iblank(PS.string_contributions(itcs, ltemp, dchi), 5) else: dchi = {} return dpfn, dgibbs1cm3, dgibbs1bar, string, dchi, dctr
def kappa_int(VAG, E, theta, beta): pE = 1.0 / (1.0 + fncs.exp128(2.0 * theta)) kappa_integrand = pE * np.sinh(beta * (VAG - E)) return kappa_integrand
#-------------------------------# # calculation of effective mass # #-------------------------------# lfs = [] # f(s) tsidx = None for idx, s_i in enumerate(svals): kappa = lkappa[idx] tbar = ltbar[idx] dtbar = ldtbar[idx] if s_i == 0.0: tsidx = idx # Calculare f(s) according to eq (14) - JAmChemSoc(1993)_115_2408 if idx in toignore: lfs.append(None) else: exparg = -2 * kappa * tbar - (kappa * tbar)**2 + dtbar**2 fs = min(fncs.exp128(exparg), 1.0) lfs.append(fs) # Interpolate Nones lfs = intrpl.interpolate_nones(svals, lfs, mode=intrplmode) # set to zero possible negative values due to interpolation for idx in toignore: lfs[idx] = max(0.0, lfs[idx]) # effective mu in au lmueff = [mu * fs for fs in lfs] return svals, lkappa, ltbar, ldtbar, mu, lmueff, toignore #-----------------------------------------------# def get_sct_part3(svals, lmueff, VadiSpl, afreq, lEquant, E0, VAG, temps): '''
def deal_with_anh(anhfile, ltemp, ZPEMSHO, QMSHO): RATIO = None DZPE = None string = "" while True: if anhfile is None: break anhfile = PN.ANHDIR + anhfile if not os.path.exists(anhfile): string += "Anharmonicity file '%s' NOT FOUND!\n" % anhfile string += "\n" break string += "Anharmonicity file '%s' FOUND!\n" % anhfile string += "\n" # read lines in file lines = read_file(anhfile) # type of file?? itisq2dtor = False itismstor = False for line in lines[::-1]: if "End of Q2DTor output" in line: itisq2dtor = True break if "End of MSTor output" in line: itismstor = True break # get data if itisq2dtor: Tlist, ZPE_MSHO, Q_MSHO, ZPE_ANH, Q_ANH = read_q2dtorout(anhfile) elif itismstor: Tlist, ZPE_MSHO, Q_MSHO, ZPE_ANH, Q_ANH = read_mstorout(anhfile) else: string += " * unable to identify the program where this file come from...\n" string += "\n" break # print info if None in (ZPE_MSHO, Q_MSHO, ZPE_ANH, Q_ANH): string += " * unable to read the file properly...\n" string += "\n" break # print zpe string += " * Data in file:\n" string += "\n" string += " ZPE_MSHO: %.8f hartree\n" % ZPE_MSHO string += " ZPE_ANH : %.8f hartree\n" % ZPE_ANH string += "\n" # compare list of temperatures string += " * checking list of temperatures\n" common = [] for idxT1, T1 in enumerate(Tlist): for idxT2, T2 in enumerate(ltemp): if abs(T1 - T2) < EPS_TEMP: common.append(idxT1) string += " num_temps(%s) = %i\n" % (PN.IFILE2, len(ltemp)) string += " num_temps(%s) = %i\n" % (anhfile, len(Tlist)) string += " in common --> %i\n" % (len(common)) if len(common) != len(ltemp): string += " differences in temperatures detected [FAIL]\n" break elif len(common) != len(Tlist): Tlist = [Tlist[idxT] for idxT in common] Q_MSHO = [Q_MSHO[idxT] for idxT in common] Q_ANH = [Q_ANH[idxT] for idxT in common] string += " temperatures match! [OK]\n" string += "\n" # print partition functions thead = " T (K) | Q_MSHO | Q_ANH " tdivi = "-" * len(thead) string += " " + tdivi + "\n" string += " " + thead + "\n" string += " " + tdivi + "\n" for idx, T in enumerate(Tlist): tline = " %8.2f | %10.3E | %10.3E " % (T, Q_MSHO[idx], Q_ANH[idx]) string += " " + tline + "\n" string += " " + tdivi + "\n" string += "\n" # compare ZPE of MSHO string += " * checking MSHO data...\n" maxdiff = abs(ZPE_MSHO - ZPEMSHO) * KCALMOL if maxdiff < 0.1: string += " abs. diff. in ZPE is %.1E kcal/mol [OK]\n" % maxdiff else: string += " abs. diff. in ZPE is %.1E kcal/mol [FAIL]\n" % maxdiff break # compare pfn of MSHO maxdiff = 100 * max( [abs(pi - pj) / pi for pi, pj in zip(QMSHO, Q_MSHO)]) if maxdiff < 2.0: string += " max. rel. diff in MSHO partition function is %.1E%% [OK]\n" % maxdiff else: string += " max. rel. diff in MSHO partition function is %.1E%% [FAIL]\n" % maxdiff break string += "\n" # calculate ratio string += " * Calculating anh. ratio = Q_ANH/Q_MSHO * exp(-(ZPE_ANH-ZPE_MSHO)*beta)\n" string += "\n" DZPE = ZPE_ANH - ZPE_MSHO RATIO = [(Q_ANH[idx] / Q_MSHO[idx]) * exp128(-DZPE / KB / T) for idx, T in enumerate(ltemp)] # print partition functions thead = " T (K) | ANH. RATIO " tdivi = "-" * len(thead) string += " " + tdivi + "\n" string += " " + thead + "\n" string += " " + tdivi + "\n" for idx, T in enumerate(ltemp): tline = " %8.2f | %10.3E " % (T, RATIO[idx]) string += " " + tline + "\n" string += " " + tdivi + "\n" string += "\n" break return RATIO, string