def highlevel_mep(ctc, itc, keyHL_sp, software, dtesHL, dhighlvl, points): # key for dhighlvl keyHL_path = "%s.%s.path" % (ctc, itc) # initialize dictE dictE = {} # folder for calculation and file name TMP = PN.TMPHLi % PN.struckey(ctc, itc) # template and function for calculation tes = dtesHL.get(software, {}).get(ctc, None) spc_fnc = get_spc_fnc(software) # extra-arguments for spc_fnc clean = False # do not delete files bhess = False # do not calculate hessian (no needed actually) eargs = (tes, TMP, clean) # rst file rstfile = PN.get_rst(ctc, itc) tpath2, tcommon2, drst = ff.read_rst(rstfile) if drst == {}: yield None, keyHL_path, (None, None), None, "emptyrst" return ch, mtp, atonums, masses, mu = tcommon2 symbols = fncs.atonums2symbols(atonums) # define points allpoints = sorted_points(drst, hess=False) for point in points: if point.startswith("auto"): auto, nbw, nfw = point.split("_") points = auto_points(drst, allpoints, int(nbw), int(nfw)) break # loop in points for point_i in points: # name for files mname = "%s.%s.%s" % (ctc, itc, point_i) # get label label_i, s_i = find_label_in_rst(point_i, drst) # tuple for identify tuple_ID = (s_i, label_i) # not in drst? if label_i is None: yield point_i, keyHL_path, tuple_ID, None, "noinrst" # already calculated elif label_i in dhighlvl.get(keyHL_path, {}).keys(): yield point_i, keyHL_path, tuple_ID, dhighlvl[keyHL_path][ label_i], "already" # HL-calculation else: if s_i == 0.0: Ehl_sp = dhighlvl.get(keyHL_sp, None) if Ehl_sp is not None: yield point_i, keyHL_path, tuple_ID, Ehl_sp, "saddlefromsp" continue # get xcc from rst xms = drst[label_i][2] xcc = fncs.ms2cc_x(xms, masses, mu) # calculation try: out_spc = spc_fnc(xcc, symbols, bhess, mname, eargs) yield point_i, keyHL_path, tuple_ID, out_spc[4], "calculated" except: yield point_i, keyHL_path, tuple_ID, None, "fail"
def calc_mep(itarget, gtsTS, pathvars, tsoftware, TMP): # data in name ctc, itc = PN.name2data(itarget) # Low-Level if pathvars._dlevel is None: tcommon, drst, pathvars = obtain_mep(itarget, gtsTS, pathvars, tsoftware, TMP) fncs.print_string(PS.smep_table(drst, pathvars._eref), 4) # Dual-Level else: rstfile = PN.get_rst(ctc, itc) xyzfile = PN.get_rstxyz(ctc, itc) software, tes = tsoftware fncs.print_string(PS.smep_init(itarget,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) # read rst tpath, tcommon, drst = ff.read_rst(rstfile) fncs.print_string(PS.smep_rst(rstfile, drst), 4) fncs.print_string("Applying Dual-Level...", 4) 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] fncs.print_string( "%+8.4f bohr (%-6s) --> %.7f hartree" % (s_i, xx_i, yy_i), 13) 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) return tcommon, drst, pathvars
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) # rotational symmetry moleculeTS = Molecule() moleculeTS.set_from_gts(gtsTS) symmetry = str(moleculeTS._pgroup), int(moleculeTS._rotsigma) # temporal folder TMP = PN.TMPi % (target) # if exists,remove content (unless keeptmp is activated) # (to avoid reading old files from different levels of calculation) if os.path.exists(TMP) and not pathvars._keeptmp: 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 if itc in dctc[ctc]._dics.keys(): ics = dctc[ctc]._dics[itc] elif "*" in dctc[ctc]._dics.keys(): ics = dctc[ctc]._dics["*"] else: ics = None if itc in dctc[ctc]._dicsbw.keys(): icsbw = dctc[ctc]._dicsbw[itc] elif "*" in dctc[ctc]._dicsbw.keys(): icsbw = dctc[ctc]._dicsbw["*"] else: icsbw = None if itc in dctc[ctc]._dicsfw.keys(): icsfw = dctc[ctc]._dicsfw[itc] elif "*" in dctc[ctc]._dicsfw.keys(): icsfw = dctc[ctc]._dicsfw["*"] else: icsfw = None # path variables pathvars.set_ics(ics, icsbw, icsfw) # 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._scterr = None 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) sys.stdout.writeinfile(PS.init_txt()) #string fncs.print_string(PS.smep_title(target, pathvars, pof), 2) # Was previously converged??? ffloat = "%.3f" drstconv = RW.read_rstconv() if target in drstconv.keys() and not dlevel and os.path.exists(rstfile): lowtemp, useics, scterr, converged = drstconv[target] b0 = (converged == "yes") b1 = (pathvars._useics == useics) b2 = (ffloat % pathvars._scterr == ffloat % scterr) b3 = (ffloat % min(ltemp) == ffloat % lowtemp) if b0 and b1 and b2 and b3: pathvars._scterr = None fncs.print_string("THIS PATH IS STORED AS CONVERGED!\n", 4) tpath, tcommon, drst = ff.read_rst(rstfile) lbw, lfw, sbw, sfw, V0bw, V0fw = sd.rstlimits(drst) pathvars._sbw = sbw pathvars._sfw = sfw del drst #----------------# # calculate path # #----------------# # 1. Only MEP if not pathvars._beyondmep: common, drst, pathvars = calc_mep(target, gtsTS, pathvars, tsoftw, TMP) dcoefs = {} del drst # raise error raise Exc.OnlyMEP(Exception) # 2. MEP expanded till SCT convergence elif pathvars.sct_convergence(): dcoefs, converged = get_path_sctconv(target, gtsTS, pathvars, tsoftw, ltemp, TMP, symmetry, plotfile) # save convergence in file! drstconv = RW.read_rstconv() if converged: drstconv[target] = (min(ltemp), pathvars._useics, pathvars._scterr, "yes") else: drstconv[target] = (min(ltemp), pathvars._useics, pathvars._scterr, "no") RW.write_rstconv(drstconv) # 3. Coefs with the current MEP extension else: tcommon, drst, pathvars = calc_mep(target, gtsTS, pathvars, tsoftw, TMP) dcoefs, pathvars, palpha, pomega = calc_coefs(target, tcommon, drst, pathvars, ltemp, symmetry, 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) # create folder now and not in the parallel process if not os.path.exists(TMP): try: os.mkdir(TMP) except: pass # 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) # read rst try: tpath2, tcommon2, drst = ff.read_rst(rstfile) except: exception = Exc.RstReadProblem(Exception) exception._var = rstfile raise exception 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]): fncs.print_string( "'fwdir' variable differs from MEP direction in rst file!", 4) fncs.print_string("* modifying rst internal dictionary...", 8) 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 fncs.print_string("* rewriting rst file...", 8) ff.write_rst(rstfile, tpath2, tcommon2, drst) # Extension of MEP in rst is bigger if drst != {}: lbw, lfw, sbw, sfw, V0bw, V0fw = 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.setvar(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) # data for single-point calculation frozen = RW.read_frozen(gtsTS + ".frozen") oniom_layers = (list(pathvars._oniomh), list(pathvars._oniomm), list(pathvars._onioml)) spc_args = (tes, TMP, False, frozen, oniom_layers) spc_fnc = get_spc_fnc(software) #------------# # First step # #------------# print("") fncs.print_string("Performing first step of MEP...", 4) 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) # oniom layers? oniom_ok = pathvars.isONIOMok(ts._natoms, software) layers = pathvars.get_layers() fncs.print_string(PS.smep_oniom(layers, ts._natoms, software), 8) if not oniom_ok: raise Exc.WrongONIOMlayers(Exception) # Print MEP info fncs.print_string(PS.smep_first(ts._symbols, ts._xms, v0, v1, layers), 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("") fncs.print_string("Calculating MEP...", 4) print("") fncs.print_string( "* REMEMBER: data of each step will be saved at %s" % rstfile, 7) fncs.print_string(" a summary will be printed when finished", 7) # 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 fncs.print_string("* FINISHED!", 7) print("") drst.update(drstbw) drst.update(drstfw) points = [TSLABEL] + pointsbw + pointsfw # empty variables del drstbw, pointsbw del drstfw, pointsfw # Rewrite rst fncs.print_string("* (re)writing file: %s (sorted version)" % rstfile, 7) 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, V0bw, V0fw = sd.rstlimits(drst) convbw, l1bw, l2bw = convbw convfw, l1fw, l2fw = convfw if l1bw + l1fw != "": fncs.print_string("* MEP convergence criteria (epse and epsg):", 7) print("") if l1bw != "": fncs.print_string("%s" % l1bw, 9) if l2bw != "": fncs.print_string("%s" % l2bw, 9) if l1fw != "": fncs.print_string("%s" % l1fw, 9) if l2fw != "": fncs.print_string("%s" % l2fw, 9) print("") if convbw: pathvars.converged_in_bw(sbw) fncs.print_string("CRITERIA FULFILLED in backward dir.!", 9) fncs.print_string("path stopped at sbw = %+8.4f bohr" % sbw, 9) print("") if convfw: pathvars.converged_in_fw(sfw) fncs.print_string("CRITERIA FULFILLED in forward dir.!", 9) fncs.print_string("path stopped at sfw = %+8.4f bohr" % sfw, 9) print("") # write molden file fncs.print_string("* writing file: %s" % xyzfile, 7) ff.rst2xyz(rstfile, xyzfile, onlyhess=True) print("") # reference energy if pathvars._eref is None: pathvars._eref = V0bw # return data return tcommon, drst, pathvars