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 calculate_QMSHO_for_ctc(Cluster, ltemp, dimasses={}, tupleHL=None): # 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 # DLEVEL if dlevel: V0HLs = get_V0HL_list(Cluster._root, itcs, dhighlvl) else: V0HLs = [None for itc, weight in itcs] # 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)) # apply dlevel if V0HLs[idx] is not None: molecule._V0 = V0HLs[idx] molecule._ccV1 = molecule._V0 + molecule._cczpe # save molecule molecules.append(molecule) # Get min of V0 and V1 V0 = min([molecule._V0 for molecule in molecules]) V1 = min([molecule._ccV1 for molecule in molecules]) # String string = "" if dlevel: 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 \n" % (itc, V0LLs[idx], V0HL) string += " ---------------------------------------------------\n" string += "\n" if None in V0HLs: string += " * FAIL!! Not enough data... DUAL-LEVEL will be omitted!\n" string += "\n" global WARNINGS WARNINGS.append("Dual-level was not applied to %s..." % ctc) 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: global WARNINGS 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) dpfn = {} dgibbs = {} 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 gibbs_i = [ V1_i - KB * T * np.log(q_j * rotsigma) for T, q_j in zip(ltemp, pf_i) ] dpfn[key] = (V0_i, V1_i, pf_i) dgibbs[key] = gibbs_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] * np.exp(-rel_V1 * beta) pfn_gibbs[idx] += weight * pf_i[idx] * np.exp( -rel_V1 * beta) * rotsigma # add to string pf_PIB, pf_RR, pf_HO, pf_ele = tuple_i string += " Conformation: %s\n" % itc string += add_iblank(molecule.info_string(), 7) string += " partition functions (with regards electronic energy + ZPE):\n" string += add_iblank( PS.getstring_pfn1(ltemp, pf_i, pf_PIB, pf_RR, pf_HO, pf_ele), 7) # save Q_MSHO dpfn[PN.struckey(ctc, "msho")] = (V0, V1, pfn_tot) # save Gibbs_MSHO gibbs_tot = [V1 - KB * T * np.log(q_j) for T, q_j in zip(ltemp, pfn_gibbs)] dgibbs[PN.struckey(ctc, "msho")] = gibbs_tot # Add to string nconfs = sum([weight for name, weight in itcs]) if nconfs > 1: dchi = conformer_contributions(ltemp, dpfn, ctc, itcs) string += " MSHO partition function (QMSHO) with regard to min(V1):\n" string += "\n" string += add_iblank(PS.getstring_pfn2(ltemp, pfn_tot), 10) string += " Individual contributions to QMSHO:\n" string += "\n" string += add_iblank(PS.string_contributions(itcs, ltemp, dchi), 10) else: dchi = {} return dpfn, dgibbs, string, dchi