示例#1
0
def get_targets(targets, dctc):
    # No targets selected
    if targets == [] or targets == "*":
        targets = [
            PN.struckey(ctc, itc) for ctc in dctc.keys()
            for itc, weight in dctc[ctc]._itcs
        ]
        targets.sort()
        return targets
    # Check targets
    itargets = []
    for target in targets:
        np = target.count(".")
        # a whole ctc is selected
        if np == 0:
            ctc = target
            if ctc not in dctc.keys(): continue
            itargets += [
                PN.struckey(ctc, itc) for itc, weight in dctc[ctc]._itcs
            ]
        # a specific itc
        elif np == 1:
            ctc, itc = target.split(".")
            if ctc not in dctc.keys(): continue
            itcs = [itc_i for itc_i, weight_i in dctc[ctc]._itcs]
            if itc not in itcs: continue
            itargets += [target]
    return itargets
示例#2
0
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
示例#3
0
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():
            fncs.print_string("* '%s' not in '%s'" % (target, PN.IFILE1), 3)
            print("")
            continue
        if ctc not in dpath.keys():
            fncs.print_string("* '%s' not in '%s'" % (target, PN.IFILE3), 3)
            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)
示例#4
0
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
示例#5
0
    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
示例#6
0
 def return_pfns(self,target):
     ctc,itcs,ms = self._itcs[target]
     itc0,weight0 = itcs[0]
     # key for partition functions & anharmonicity
     if ms:
        key = PN.struckey(ctc,"msho")
        anh = self._dall["anh"].get(ctc,None)
     else:
        key = PN.struckey(ctc,itc0)
        anh = None
     V0,V1,pfns = self._dall["pfn"][key]
     if anh is None: anh = np.array([1.0 for t in self._ltemp])
     else          : self._anhctcs.add(ctc)
     return V0, V1, pfns, anh
示例#7
0
 def return_pfns(self, target):
     ctc, itcs, ms = self._itcs[target]
     # key for partition functions
     if ms: key = PN.struckey(ctc, "msho")
     else: key = PN.struckey(ctc, itcs[0][0])
     # Energies and partition functions from data
     V0, V1, pfns = self._dall["pfn"][key]
     # anharmonicity (if commented in pif.struc --> not include it)
     anh = None
     if ms and self._anhfile[ctc] is not None:
         anh = self._dall["anh"].get(ctc, None)
     # Save data
     if anh is None: anh = np.array([1.0 for t in self._ltemp])
     else: self._anhctcs.add(ctc)
     return V0, V1, pfns, anh
示例#8
0
def get_V0HL_list(ctc, itcs, dhighlvl):
    list_V0HL = []
    for itc, weight in itcs:
        key = PN.struckey(ctc, itc)
        V0HL = dhighlvl.get(key, None)
        list_V0HL.append(V0HL)
    return list_V0HL
示例#9
0
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"
示例#10
0
    def calculate_transcoeffs(self):
        if self._ts is None: return
        ctc, itcs, ms = self._itcs[self._ts]
        # Get individual transmission coefficients
        for itc, weight in itcs:
            tsname = PN.struckey(ctc, itc)
            cvt = self._dall.get("cvt", {}).get(tsname, None)
            zct = self._dall.get("zct", {}).get(tsname, None)
            sct = self._dall.get("sct", {}).get(tsname, None)
            cagtst = self._dall.get("cagtst", {}).get(tsname, None)
            cagcvt = self._dall.get("cagcvt", {}).get(tsname, None)
            # now total transmission coefficients
            try:
                tc_tstzct = np.array(fncs.prod_list((zct, cagtst)))
            except:
                tc_tstzct = None
            try:
                tc_tstsct = np.array(fncs.prod_list((sct, cagtst)))
            except:
                tc_tstsct = None
            try:
                tc_cvt = np.array(fncs.prod_list((cvt, )))
            except:
                tc_cvt = None
            try:
                tc_cvtzct = np.array(fncs.prod_list((zct, cvt, cagcvt)))
            except:
                tc_cvtzct = None
            try:
                tc_cvtsct = np.array(fncs.prod_list((sct, cvt, cagcvt)))
            except:
                tc_cvtsct = None
            # save
            self._dtcoef["tstzct"][itc] = tc_tstzct
            self._dtcoef["tstsct"][itc] = tc_tstsct
            self._dtcoef["cvt"][itc] = tc_cvt
            self._dtcoef["cvtzct"][itc] = tc_cvtzct
            self._dtcoef["cvtsct"][itc] = tc_cvtsct

        # Calculate contributions to other methods
        for X in self._dtcoef.keys():
            # calculate numerator of contribution
            for itc, weight in itcs:
                chi_i = self._tschi["tst"][itc]
                tc_i = self._dtcoef[X][itc]
                if tc_i is not None: self._tschi[X][itc] = chi_i * tc_i
                else: self._tschi[X][itc] = None
            # averaged transmission coefficient
            chis_X = [chi_i_X for chi_i_X in self._tschi[X].values()]
            try:
                self._dtcoef[X]["averaged"] = sum(chis_X)
            except:
                self._dtcoef[X]["averaged"] = None
            # calculate contribution
            averaged = self._dtcoef[X]["averaged"]
            for itc, weight in itcs:
                chi_i = self._tschi["tst"][itc]
                tc_i = self._dtcoef[X][itc]
                if averaged is None or tc_i is None: self._tschi[X][itc] = None
                else: self._tschi[X][itc] /= averaged
示例#11
0
def get_V0HL_list(Cluster, dhighlvl):
    list_V0HL = []
    for itc, weight in Cluster._itcs:
        key = PN.struckey(Cluster._root, itc)
        V0HL = dhighlvl.get(key, None)
        list_V0HL.append(V0HL)
    return list_V0HL
示例#12
0
 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))
示例#13
0
def get_transmissioncoeffs(ctc, dall, dctc, ltemp):
    # Get contributions
    dchi = get_contributions(ctc, dall, dctc, ltemp)
    if ctc not in dctc.keys(): return None, dchi
    # Get individual transmission coefficients
    dtc = {X: {} for X in "tst,tstzct,tstsct,cvt,cvtzct,cvtsct".split(",")}
    # Get transmission coefficients
    for itc, weight in dctc[ctc]._itcs:
        tsname = PN.struckey(ctc, itc)
        cvt = dall.get("cvt", {}).get(tsname, None)
        zct = dall.get("zct", {}).get(tsname, None)
        sct = dall.get("sct", {}).get(tsname, None)
        cagtst = dall.get("cagtst", {}).get(tsname, None)
        cagcvt = dall.get("cagcvt", {}).get(tsname, None)
        # now total transmission coefficients
        try:
            tc_tstzct = np.array(fncs.prod_list((zct, cagtst)))
        except:
            tc_tstzct = None
        try:
            tc_tstsct = np.array(fncs.prod_list((sct, cagtst)))
        except:
            tc_tstsct = None
        try:
            tc_cvt = np.array(fncs.prod_list((cvt, )))
        except:
            tc_cvt = None
        try:
            tc_cvtzct = np.array(fncs.prod_list((zct, cvt, cagcvt)))
        except:
            tc_cvtzct = None
        try:
            tc_cvtsct = np.array(fncs.prod_list((sct, cvt, cagcvt)))
        except:
            tc_cvtsct = None
        # save
        dtc["tst"][itc] = np.array([1.0 for T in ltemp])
        dtc["tstzct"][itc] = tc_tstzct
        dtc["tstsct"][itc] = tc_tstsct
        dtc["cvt"][itc] = tc_cvt
        dtc["cvtzct"][itc] = tc_cvtzct
        dtc["cvtsct"][itc] = tc_cvtsct
    # Get averaged transmission coefficient
    for X in dtc.keys():
        # Initializing averaged value
        dtc[X]["averaged"] = np.array([0.0 for T in ltemp])
        # Calculating averaged coef
        for itc, weight in dctc[ctc]._itcs:
            # No data for this method?
            if dtc[X][itc] is None:
                dtc[X]["averaged"] = None
                break
            # update averaged transmission coeff
            else:
                dtc[X]["averaged"] += dchi[itc] * dtc[X][itc]
    return dtc, dchi
示例#14
0
 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
示例#15
0
 except Exception as exception:
     WARNINGS.append("Problem with %s" % ctc)
     if type(exception) == Exc.DiffMassConf:
         print_string(exception._var, NBS)
         continue
     if type(exception) == Exc.LackOfGts:
         error_line = "ERROR: Unable to find '%s'" % exception._var
         print_string(error_line, 7)
         print("")
         continue
     raise exception
 # print info
 print_string(string, NBS)
 # anharmonicity??
 anhfile = dctc[ctc]._anh
 V0, V1, QMSHO = dpfn_i[PN.struckey(ctc, "msho")]
 ZPEMSHO = V1 - V0
 RATIO, string = deal_with_anh(anhfile, ltemp, ZPEMSHO, QMSHO)
 if string != "":
     print_string(string, 7)
     if RATIO is None:
         WARNINGS.append("Anharmonicity IGNORED for %s" % ctc)
 # add data of weights to plot
 if plotfile is not None and dchi != {}:
     plotdata = {}
     plotdata.update(manage_data_for_plot_weights(ctc, ltemp, dchi))
     write_plotfile(plotfile, plotdata)
 # update dictionary
 dpfn.update(dpfn_i)
 dgibbs1cm3.update(dgibbs1cm3_i)
 dgibbs1bar.update(dgibbs1bar_i)
示例#16
0
 def return_V0V1(self, ctc, itc):
     key = PN.struckey(ctc, itc)
     V0, V1, pfns = self._dall["pfn"][key]
     return V0, V1
示例#17
0
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["gibbs1cm3"].keys():
               gibbs = dall["gibbs1cm3"][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
示例#18
0
    # 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])
    cols = ("target","point identifier","s value (bohr)","E_HL (hartree)")
示例#19
0
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