def execute_pfn(itargets, dchem, idata, status, case): reactions = set([]) for target in itargets: ctc1, itc1 = PN.name2data(target) the_reaction = None for reaction, (Rs, TS, Ps) in dchem.items(): try: ctc2, itc2 = PN.name2data(TS) except: continue if ctc1 == ctc2: the_reaction = reaction if itc1 == itc2: break if the_reaction is not None: reactions.add(the_reaction) if len(reactions) == 0: return reactions = sorted(list(reactions)) print " The selected transitions states are involved in defined reactions!" pfn_targets = set([]) for reaction in reactions: print " * %s" % reaction Rs, TS, Ps = dchem[reaction] for xx in Rs + [TS] + Ps: pfn_targets.add(PN.name2data(xx)[0]) if len(pfn_targets) == 0: return pfn_targets = sorted(list(pfn_targets)) print import opt_pfn as pfn print " Calculating partition functions for the next targets:" for target in pfn_targets: print " * %s" % target print pfn.main(idata, status, case, targets=pfn_targets)
def data_target(target, dall, ltemp): # convert to list target = target2list(target) # initialize tot_V0 = 0.0 tot_V1 = 0.0 tot_Q = [1.0 for T in ltemp] tot_ANH = [1.0 for T in ltemp] trg_ANH = [] # everything ok? if target is None: return None, None, None, tot_ANH, trg_ANH # read data for trg in target: ctc, itc = PN.name2data(trg) # Get key if itc is None: key = PN.struckey(ctc, "msho") else: key = PN.struckey(ctc, itc) # look for data try: V0, V1, pfns = dall["pfn"][key] except: raise Exc.NoData # add energies to total tot_V0 += V0 tot_V1 += V1 # update total partition function tot_Q = [q_i * q_j for q_i, q_j in zip(tot_Q, pfns)] # anharmonicity if ctc in dall["anh"].keys(): anh = dall["anh"][ctc] tot_ANH = [r1 * r2 for r1, r2 in zip(tot_ANH, anh)] trg_ANH.append(trg) # return data return tot_V0, tot_V1, tot_Q, tot_ANH, trg_ANH
def get_itargets(targets, dpath, dctc): ''' get individual targets ''' # Targets? if (len(targets) == 0) or ("*" in targets): targets = dpath.keys() # generate list of individual targets itargets = [] for target in targets: ctc, itc = PN.name2data(target) # check ctc if ctc not in dctc.keys(): print " * '%s' not in '%s'" % (target, PN.IFILE1) print continue if ctc not in dpath.keys(): print " * '%s' not in '%s'" % (target, PN.IFILE3) print continue # list of itcs for the ctc itclist = [itc_i for itc_i, weight_i in dctc[ctc]._itcs] # add itc if itc is None: itargets += [ PN.struckey(ctc, itc) for itc, weight in dctc[ctc]._itcs ] elif itc in itclist: itargets += [PN.struckey(ctc, itc)] return sorted(itargets)
def calc_mep(itarget, gtsTS, pathvars, tsoftware, TMP, decrease=False): ''' if decrease = True, MEP is reduced hsteps steps ''' # data in name ctc, itc = PN.name2data(itarget) # calculate path tcommon, drst, pathvars = obtain_mep(itarget, gtsTS, pathvars, tsoftware, TMP) # decrease mep?? if decrease: sbw1, sfw1 = pathvars._sbw, pathvars._sfw pathvars.decrease_svals() sbw2, sfw2 = pathvars._sbw, pathvars._sfw print " MEP will be reduced to check SCT convergence:" print print " sbw: %+8.4f --> %+8.4f bohr" % (sbw1, sbw2) print " sfw: %+8.4f --> %+8.4f bohr" % (sfw1, sfw2) print drst = { label: data for label, data in drst.items() if in_interval(data[0], sbw2, sfw2) } # DLEVEL?? if pathvars._dlevel is not None: print " Applying Dual-Level..." print dlevel_xy = [(find_label_in_rst(x, drst)[0], y) for x, y in pathvars._dlevel.items()] dlevel_xy = [(x, y) for x, y in dlevel_xy if x is not None] # Print points (sorted by s value) dummy = [(drst[xx][0], idx) for idx, (xx, yy) in enumerate(dlevel_xy)] dummy.sort() for s_i, idx_i in dummy: xx_i, yy_i = dlevel_xy[idx_i] print " %+8.4f bohr (%-6s) --> %.7f hartree" % ( s_i, xx_i, yy_i) print # interpolation drst, points, xx, yyll, yyhl = ispe.ispe(tcommon, drst, dlevel_xy, tension=0.0) tdleveldata = (points, xx, yyll, yyhl) # table new values fncs.print_string( PS.smep_tableDLEVEL(drst, tdleveldata, pathvars._eref), 4) else: # Print table fncs.print_string(PS.smep_table(drst, pathvars._eref), 4) return tcommon, drst, pathvars
def get_masses(target, dctc, dimasses): ctc, itc = PN.name2data(target) diso = dctc[ctc]._diso if itc in diso.keys(): imod = diso[itc] elif "*" in diso.keys(): imod = diso["*"] else: imod = None if imod is None: return None gtsTS = dctc[ctc].gtsfile(itc) TS = Molecule() TS.set_from_gts(gtsTS) TS.apply_imods(imod, dimasses) masses = list(TS._masses) return masses
def set_eref_from_reaction(self, tsname, dchem, dof): thebool = self._eref in [None, "auto", "default"] ctc, itc = PN.name2data(tsname) # Get data from reactions rname, V0R, V0P, V1R, V1P, GibbsR = get_reaction_energies( tsname, dchem, dof) self._V1R = V1R self._V1P = V1P # save GibbsR for CVT gibbs self._GibbsR = GibbsR # go case by case if thebool and V0R is not None: self._eref = V0R # save reaction name and check if beyond mep self._reaction = rname if self._eref in [None, "auto", "default"]: self._beyondmep = False
def factors_from_TS(TS, V1TS, QTS, ltemp, dctc, dall): # list of itcs ctc, itc = PN.name2data(TS) if itc is None: itcs = dctc[ctc]._itcs else: itcs = [(itc, 1)] # get TST ratios tst_ratios = get_TSratios(ctc, itcs, V1TS, QTS, ltemp, dall) # print TST ratios print_string(PS.srcons_tstratios(ltemp, tst_ratios), 7) # get total correction factors corrfactors = get_corrfactors(ltemp, ctc, itcs, dall, tst_ratios) # print correction factors print_string(PS.string_corrfactors(ltemp, corrfactors), 7) # print VTST contributions print_string(PS.srcons_vtstratios(ltemp, tst_ratios, corrfactors), 7) return tst_ratios, corrfactors
def prepare_qrc(self, dchem, dctc, dimasses): # Will qrc be used? if self._reaction is None: return if self._qrc is None: return reactants = dchem[self._reaction][0] if len(reactants) != 1: return # generate Molecule instance reactant = reactants[0] ctc, itc = PN.name2data(reactant) if ctc not in dctc.keys(): return cluster = dctc[ctc] if itc is None: itc = cluster._itcs[0][0] if itc in cluster._diso.keys(): imods = cluster._diso[itc] elif "*" in cluster._diso.keys(): imods = cluster._diso["*"] else: imods = None gtsfile = PN.get_gts(ctc, itc) if not os.path.exists(gtsfile): raise Exception # Generate Molecule instance reactant = Molecule() reactant.set_from_gts(gtsfile) # apply fscal reactant.set_fscal(fscal=cluster._fscal) # apply isotopic masses if imods is not None: reactant.apply_imods(imods, dimasses) # calculate frequencies reactant.setup() mode, nE = self._qrc Vadi = reactant._V0 for idx, afreq in enumerate(reactant._ccfreqs): if idx == mode: continue Vadi += afreq2zpe(afreq) afreq = reactant._ccfreqs[mode] listE = [ Vadi + (n + 0.5) * HBAR * afreq - self._eref for n in range(nE) ] self._qrclE = listE self._qrcafreq = afreq
fstatus = ffchecking(mustexist, tocreate) if fstatus == -1: exit() # expand case (dof, hlf, plotfile), dlevel, software = case #-------------------------------------------------------# print " Selected software: %s" % software print targets = get_targets(targets, dctc) # Print targets if len(targets) != 0: print " High-level (HL) calculations will be carried out for:" ml = max([len(target) for target in targets] + [1]) for target in targets: ctc, itc = PN.name2data(target) TMP = PN.TMPHLi % PN.struckey(ctc, itc) print " %s (TMP folder: %s)" % ("%%-%is" % ml % target, TMP) print else: print " No valid target(s) for High-level (HL) calculations" print return # read high-level output file dhighlvl = RW.read_highlevelfile(hlf) # loop over each target print " Carrying out HL-calculations:" print ml = max([len(target) for target in targets])
def get_reaction_energies(TS, dchem, dof): ''' * checks the reactions which involved the target transition state (TS) in order to extract V0 and V1 for reactants and products ''' # initialize variables reaction = None Eref = None V0R = None V0P = None V1R = None V1P = None GibbsR = None # select reaction ctc, itc = PN.name2data(TS) for rname in dchem.keys(): Rs, ts, Ps = dchem[rname] ctc2, itc2 = PN.name2data(ts) if ctc == ctc2: reaction = rname if itc == itc2: break # no reaction? if reaction is None: return reaction, V0R, V0P, V1R, V1P, GibbsR # read dof dall = RW.read_alldata(dof)[0] # get energy from reaction Rs = dchem[reaction][0] Ps = dchem[reaction][2] # reactants if len(Rs) != 0: V0R, V1R = 0.0, 0.0 for R in Rs: ctc, itc = PN.name2data(R) if itc is None: key = PN.struckey(ctc, "msho") else: key = R data = dall["pfn"].get(key, None) if data is None: V0R, V1R = None, None break V0, V1, pfns = data V0R += V0 V1R += V1 # Gibbs energy if key in dall["gibbs"].keys(): gibbs = dall["gibbs"][key] if GibbsR is None: GibbsR = gibbs else: GibbsR = [gi + gj for gi, gj in zip(GibbsR, gibbs)] # products if len(Ps) != 0: V0P, V1P = 0.0, 0.0 for P in Ps: ctc, itc = PN.name2data(P) if itc is None: key = PN.struckey(ctc, "msho") else: key = P data = dall["pfn"].get(key, None) if data is None: V0P, V1P = None, None break V0, V1, pfns = data V0P += V0 V1P += V1 # Output return reaction, V0R, V0P, V1R, V1P, GibbsR
def deal_with_path(target, dlevel, software, ltemp, dctc, pathvars, dtes, dchem, dhighlvl, dimasses): dof = PN.get_dof(dlevel) plotfile = PN.get_plf(dlevel) # gts file for this TS ctc, itc = PN.name2data(target) gtsTS = dctc[ctc].gtsfile(itc) # temporal folder TMP = PN.TMPi % (target) # if exists,remove content # (to avoid reading old files from different levels of calculation) if os.path.exists(TMP): shutil.rmtree(TMP, ignore_errors=True) # split target ctc, itc = PN.name2data(target) # name of rst file rstfile = PN.get_rst(ctc, itc) # tuple software tes = dtes.get(software, {}).get(ctc, None) tsoftw = (software, tes) # internal coordinates dics = dctc[ctc]._dics if itc in dics.keys(): ics = dics[itc] elif "*" in dics.keys(): ics = dics["*"] else: ics = None # path variables pathvars.set_ics(ics) # before setup3!! pathvars.apply_specific(itc) pathvars.setup1() pathvars.setup2() pathvars.setup3() # Set Eref (from reaction) pathvars.set_eref_from_reaction(target, dchem, dof) # Quantum reaction coordinate qrc pathvars.prepare_qrc(dchem, dctc, dimasses) # frequency scaling factor pathvars._freqscal = float(dctc[ctc]._fscal) # if dlevel --> no convergence and dlevel data if dlevel: exception = Exc.NoDLEVELdata(Exception) pathvars._sctmns = 0 keydhl = "%s.%s.path" % (ctc, itc) if keydhl not in dhighlvl.keys(): # maybe only TS keydhl = "%s.%s" % (dctc[ctc]._root, itc) if keydhl in dhighlvl.keys(): dictE = {0.0: dhighlvl[keydhl]} else: global WARNINGS WARNINGS.append("No high-level data for %s" % target) raise exception else: dictE = dhighlvl[keydhl] pathvars._dlevel = dictE # LOGGER pof = PN.get_pof(dlevel, "path", target) sys.stdout = Logger(pof, "w", True) #string fncs.print_string(PS.smep_title(target, pathvars, pof), 2) #----------------# # calculate path # #----------------# # 1. MEP if not pathvars._beyondmep: common, drst, pathvars = calc_mep(target, gtsTS, pathvars, tsoftw, TMP, decrease=False) dcoefs = {} del drst # raise error raise Exc.OnlyMEP(Exception) # 2. MEP + coefs else: # 2.1 MEP expanded till SCT convergence if pathvars.sct_convergence(): dcoefs = get_path_sctconv(target, gtsTS, pathvars, tsoftw, ltemp, TMP, plotfile) # 2.2 Coefs with the current MEP extension else: tcommon, drst, pathvars = calc_mep(target, gtsTS, pathvars, tsoftw, TMP, decrease=False) dcoefs, pathvars = calc_coefs(target, tcommon, drst, pathvars, ltemp, plotfile) del drst # print summary with the coefficients fncs.print_string(PS.spath_allcoefs(ltemp, dcoefs), 3) # return data return dcoefs, pathvars
def obtain_mep(target, gtsTS, pathvars, tsoftware, TMP): ctc, itc = PN.name2data(target) # Files rstfile = PN.get_rst(ctc, itc) xyzfile = PN.get_rstxyz(ctc, itc) # print software, tes = tsoftware fncs.print_string(PS.smep_init(target,software,pathvars._paral,pathvars.tuple_first(),\ pathvars.tuple_sdbw(),pathvars.tuple_sdfw()),4) fncs.print_string(PS.smep_ff(TMP, PN.DIR4, PN.DIR5, rstfile, xyzfile), 4) # data for single-point calculation spc_args = (tes, TMP, False) spc_fnc = get_spc_fnc(software) # read rst tpath2, tcommon2, drst = ff.read_rst(rstfile) fncs.print_string(PS.smep_rst(rstfile, drst), 4) # correct MEP direction? if TSLABEL in drst.keys(): ii_s, ii_V, ii_x, ii_g, ii_F, ii_v0, ii_v1, ii_t = drst[TSLABEL] ii_ic, ii_sign = pathvars._fwdir if not intl.ics_correctdir(ii_x, ii_v0, ii_ic, ii_sign, tcommon2[3], tcommon2[4]): print " 'fwdir' variable differs from MEP direction in rst file!" print " * modifying rst internal dictionary..." new_drst = {} for key in drst.keys(): ii_s, ii_V, ii_x, ii_g, ii_F, ii_v0, ii_v1, ii_t = drst[key] ii_s = -ii_s if ii_v0 is not None: ii_v0 = [-ii for ii in ii_v0] if ii_v1 is not None: ii_v1 = [-ii for ii in ii_v1] if "bw" in key: newkey = key.replace("bw", "fw") else: newkey = key.replace("fw", "bw") new_drst[newkey] = (ii_s, ii_V, ii_x, ii_g, ii_F, ii_v0, ii_v1, ii_t) drst = new_drst del new_drst print " * rewriting rst file..." ff.write_rst(rstfile, tpath2, tcommon2, drst) # Extension of MEP in rst is bigger if drst != {}: lbw, lfw, sbw, sfw, Ebw, Efw = sd.rstlimits(drst) pathvars._sbw = min(pathvars._sbw, sbw) pathvars._sfw = max(pathvars._sfw, sfw) # Read gts ts = Molecule() ts.set_from_gts(gtsTS) # scaling of frequencies ts.set_fscal(pathvars._freqscal) # apply iso mod if pathvars._masses is not None: ts.mod_masses(pathvars._masses) # setup ts.setup(mu=pathvars._mu) ts.ana_freqs(case="cc") fncs.print_string(PS.smep_ts(ts), 4) tcommon = (ts._ch, ts._mtp, ts._atnums, ts._masses, ts._mu) compare_tpath(pathvars.tuple_rst(), tpath2, rstfile) compare_tcommon(tcommon, tcommon2, rstfile) #------------# # First step # #------------# print print " Performing first step of MEP..." print inputvars = (ts._xcc,ts._gcc,ts._Fcc,ts._symbols,ts._masses,pathvars.tuple_first(),\ spc_fnc,spc_args,drst,pathvars._paral) (xms, gms, Fms), (v0, v1), (xms_bw, xms_fw) = sd.mep_first(*inputvars) s1bw = -float(pathvars._ds) s1fw = +float(pathvars._ds) fncs.print_string(PS.smep_first(ts._symbols, ts._xms, v0, v1), 8) # write rst file if TSLABEL not in drst.keys(): drst[TSLABEL] = (0.0, ts._V0, xms, gms, Fms, v0, v1, None) ff.write_rst_head(rstfile, pathvars.tuple_rst(), tcommon) ff.write_rst_add(rstfile, TSLABEL, drst[TSLABEL]) #------------# # The MEP # #------------# print print " Calculating MEP..." print print " * REMEMBER: data of each step will be saved at %s" % rstfile print " a summary will be printed when finished" # preparation xcc_bw = fncs.ms2cc_x(xms_bw, ts._masses, pathvars._mu) xcc_fw = fncs.ms2cc_x(xms_fw, ts._masses, pathvars._mu) args_bw = ((xcc_bw,s1bw,ts._symbols,ts._masses,pathvars.tuple_sdbw(),\ spc_fnc,spc_args,drst,ts._Fms,"bw%i") , rstfile,drst) args_fw = ((xcc_fw,s1fw,ts._symbols,ts._masses,pathvars.tuple_sdfw(),\ spc_fnc,spc_args,drst,ts._Fms,"fw%i") , rstfile,drst) # execution if pathvars._paral: import multiprocessing pool = multiprocessing.Pool() out = [ pool.apply_async(onesidemep, args=args) for args in [args_bw, args_fw] ] drstbw, pointsbw, convbw = out[0].get() drstfw, pointsfw, convfw = out[1].get() del out # clean up pool pool.close() pool.join() else: drstbw, pointsbw, convbw = onesidemep(*args_bw) drstfw, pointsfw, convfw = onesidemep(*args_fw) # update drst print " * FINISHED!" print drst.update(drstbw) drst.update(drstfw) points = [TSLABEL] + pointsbw + pointsfw # empty variables del drstbw, pointsbw del drstfw, pointsfw # Rewrite rst print " * (re)writing file: %s (sorted version)" % rstfile ff.write_rst(rstfile, pathvars.tuple_rst(), tcommon, drst) print ## restrict drst to points #if restrict: drst = {point:drst[point] for point in points} # Get limits of rst lbw, lfw, sbw, sfw, Ebw, Efw = sd.rstlimits(drst) convbw, l1bw, l2bw = convbw convfw, l1fw, l2fw = convfw if l1bw + l1fw != "": print " * EPS criteria (epse and epsg):" print if l1bw != "": print " %s" % l1bw if l2bw != "": print " %s" % l2bw if l1fw != "": print " %s" % l1fw if l2fw != "": print " %s" % l2fw print if convbw: pathvars.converged_in_bw(sbw) print " CRITERIA FULFILLED in backward dir.!" print " path stopped at sbw = %+8.4f bohr" % sbw print if convfw: pathvars.converged_in_fw(sfw) print " CRITERIA FULFILLED in forward dir.!" print " path stopped at sfw = %+8.4f bohr" % sfw print # write molden file print " * writing file: %s" % xyzfile ff.rst2xyz(rstfile, xyzfile, onlyhess=True) print # reference energy if pathvars._eref is None: pathvars._eref = Ebw # return data return tcommon, drst, pathvars