def main():
    # Get user input.
    args = parse_user_input()
    if len(args.methods) > 2:
        logger.error("Unsure what to do with >2 electronic structure methods")
        raise RuntimeError
    # Delete the result from previous jobs
    _exec("rm -rf ts_result.tar.bz2", print_command=False)
    # Perform transition state search.
    # First run the TS-calculation with the smaller basis set
    QCTS1 = QChemTS(args.tsest,
                    charge=args.charge,
                    mult=args.mult,
                    method=args.methods[0],
                    basis=args.bases[0],
                    finalize=(len(args.methods) == 1),
                    qcin='qcts1.in',
                    vout='irc_transition.vib')
    QCTS1.write('ts1.xyz')
    if len(args.methods) == 2:
        print(' --== \x1b[1;92mUpgrading\x1b[0m ==--')
        QCTS2 = QChemTS("ts1.xyz",
                        charge=args.charge,
                        mult=args.mult,
                        method=args.methods[1],
                        basis=args.bases[1],
                        finalize=True,
                        qcin='qcts2.in',
                        vout='irc_transition.vib')
        QCTS2.write('ts2.xyz')
        qcdir = QCTS2.qcdir
        shutil.copy2('ts2.xyz', 'ts.xyz')
    else:
        qcdir = QCTS1.qcdir
        shutil.copy2('ts1.xyz', 'ts.xyz')
    # Intrinsic reaction coordinate calculation.
    print("Intrinsic reaction coordinate..")
    # Process and save IRC results.
    M_IRC, E_IRC = QChemIRC("ts.xyz",
                            charge=args.charge,
                            mult=args.mult,
                            method=args.methods[-1],
                            basis=args.bases[-1],
                            qcdir=qcdir,
                            xyz0=args.initpath)
    M_IRC.write("irc.xyz")
    M_IRC.get_populations().write('irc.pop', ftype='xyz')
    # Save the IRC energy as a function of arc length.
    ArcMol = arc(M_IRC, RMSD=True)
    ArcMolCumul = np.insert(np.cumsum(ArcMol), 0, 0.0)
    np.savetxt("irc.nrg",
               np.hstack((ArcMolCumul.reshape(-1, 1), E_IRC.reshape(-1, 1))),
               fmt="% 14.6f",
               header="Arclength(Ang) Energy(kcal/mol)")
    # Create IRC with equally spaced structures.
    M_IRC_EV = SpaceIRC(M_IRC, E_IRC, RMSD=True)
    M_IRC_EV.write("irc_spaced.xyz")
    # Run two final single point calculations with SCF_FINAL_PRINT set to 1
    M_IRC[0].write("irc_reactant.xyz")
    M_IRC[-1].write("irc_product.xyz")
    QCR = QChem("irc_reactant.xyz",
                charge=args.charge,
                mult=args.mult,
                method=args.methods[-1],
                basis=args.bases[-1])
    QCP = QChem("irc_product.xyz",
                charge=args.charge,
                mult=args.mult,
                method=args.methods[-1],
                basis=args.bases[-1])
    shutil.copy2("ts.xyz", "irc_transition.xyz")
    QCT = QChem("irc_transition.xyz",
                charge=args.charge,
                mult=args.mult,
                method=args.methods[-1],
                basis=args.bases[-1])

    def FinalSCF(SP):
        SP.make_stable()
        SP.jobtype = 'sp'
        SP.remextra = OrderedDict([('scf_final_print', '1')])
        SP.calculate()

    FinalSCF(QCR)
    FinalSCF(QCP)
    FinalSCF(QCT)
    np.savetxt("irc_reactant.bnd", QCR.load_qcout().qm_bondorder, fmt="%8.3f")
    np.savetxt("irc_product.bnd", QCP.load_qcout().qm_bondorder, fmt="%8.3f")
    np.savetxt("irc_transition.bnd",
               QCT.load_qcout().qm_bondorder,
               fmt="%8.3f")

    # Calculate ZPEs, entropy, enthalpy for Delta-G calcs
    # Should be able to take out freq calcs of R and P once we get can confidently get rid of this section.
    QCR.remextra = OrderedDict()
    QCP.remextra = OrderedDict()
    QCT.remextra = OrderedDict()
    QCR.freq()
    R = QCR.load_qcout()
    QCP.freq()
    P = QCP.load_qcout()
    QCT.freq()
    T = QCT.load_qcout()
    nrgfile = open('deltaG.nrg', 'w')
    deltaH = P.qm_energies[0] * Ha_to_kcalmol + P.qm_zpe[
        0] - R.qm_energies[0] * Ha_to_kcalmol - R.qm_zpe[0]
    deltaG = deltaH - P.qm_entropy[0] * 0.29815 + P.qm_enthalpy[
        0] + R.qm_entropy[0] * 0.29815 - R.qm_enthalpy[0]
    Ha = T.qm_energies[0] * Ha_to_kcalmol + T.qm_zpe[
        0] - R.qm_energies[0] * Ha_to_kcalmol - R.qm_zpe[0]
    Ga = Ha - T.qm_entropy[0] * 0.29815 + T.qm_enthalpy[
        0] + R.qm_entropy[0] * 0.29815 - R.qm_enthalpy[0]
    nrgfile.write(
        "=> ** The following data is referenced to reactant and product complexes **\n"
    )
    nrgfile.write(
        "=> ** WARNING! Data may not be accurate in cases with >1 molecule        **\n"
    )
    nrgfile.write(
        "=> ** Activation enthalpy H_a (0K) =         %.4f kcal/mol               **\n"
        % Ha)
    nrgfile.write(
        "=> ** Activation Gibbs energy G_a (STP) =    %.4f kcal/mol               **\n"
        % Ga)
    nrgfile.write(
        "=> ** Delta-H(0K) =                          %.4f kcal/mol               **\n"
        % deltaH)
    nrgfile.write(
        "=> ** Delta-G(STP) =                         %.4f kcal/mol               **\n"
        % deltaG)

    # Calculate Delta-G's based on fragment information from reactant and product
    # Get data from fragment nrg files
    if args.fragpath == None:
        fragpath = os.path.abspath('../../../../../fragments')
    else:
        fragpath = args.fragpath
    formulas = []
    nrg = []
    zpe = []
    entr = []
    enth = []
    validity = []
    for frm in os.listdir(fragpath):
        optdir = os.path.join(fragpath, frm, "opt")
        if os.path.exists(os.path.join(optdir, 'fragmentopt.nrg')):
            fragnrgfile = open(os.path.join(optdir, 'fragmentopt.nrg'))
            formulas.append(fragnrgfile.readline().strip())
            nrg.append(float(fragnrgfile.readline().split()[3]))
            zpe.append(float(fragnrgfile.readline().split()[2]))
            entr.append(float(fragnrgfile.readline().split()[3]))
            enth.append(float(fragnrgfile.readline().split()[3]))
            validity.append(fragnrgfile.readline().strip())
            fragnrgfile.close()
    # Compare list of molecules to choose right energy
    formulasR = []
    formulasP = []
    nrgR = 0.0
    nrgP = 0.0
    R.build_topology()
    for subg in R.molecules:
        formulasR.append(subg.ef())
    formulasR = sorted(formulasR)
    P.build_topology()
    for subg in P.molecules:
        formulasP.append(subg.ef())
    formulasP = sorted(formulasP)
    for i in range(len(formulas)):
        formlist = sorted(formulas[i].split())
        if formlist == formulasR and validity[i] != "invalid":
            nrgR = nrg[i]
            zpeR = zpe[i]
            entrR = entr[i]
            enthR = enth[i]
        if formlist == formulasP and validity[i] != "invalid":
            nrgP = nrg[i]
            zpeP = zpe[i]
            entrP = entr[i]
            enthP = enth[i]
    # Calculate energetics
    if nrgR != 0.0:
        Ha = T.qm_energies[0] * Ha_to_kcalmol + T.qm_zpe[
            0] - nrgR * Ha_to_kcalmol - zpeR
        Ga = Ha - T.qm_entropy[0] * 0.29815 + T.qm_enthalpy[
            0] + entrR * 0.29815 - enthR
        nrgfile.write(
            "=> ## The following data is calculated referenced to isolated reactant and product molecules:\n"
        )
        nrgfile.write(
            "=> ## Activation enthalpy H_a (0K) =         %.4f kcal/mol               ##\n"
            % Ha)
        nrgfile.write(
            "=> ## Activation Gibbs energy G_a (STP) =    %.4f kcal/mol               ##\n"
            % Ga)
    else:
        nrgfile.write(
            "=> Reactant state could not be identified among fragment calculations\n"
        )
        nrgfile.write(
            "=> No energetics referenced to isolated molecules will be calculated for this pathway\n"
        )
    if nrgR != 0.0 and nrgP != 0.0:
        deltaH = nrgP * Ha_to_kcalmol + zpeP - nrgR * Ha_to_kcalmol - zpeR
        deltaG = deltaH - entrP * 0.29815 + enthP + entrR * 0.29815 - enthR
        nrgfile.write(
            "=> ## Delta-H(0K) =                          %.4f kcal/mol               **\n"
            % deltaH)
        nrgfile.write(
            "=> ## Delta-G(STP) =                         %.4f kcal/mol               **\n"
            % deltaG)
    elif nrgP == 0.0:
        nrgfile.write(
            "=> Product state could not be identified among fragment calculations\n"
        )
        nrgfile.write(
            "=> No reaction energies referenced to isolated molecules will be calculated for this pathway\n"
        )
    nrgfile.close()
    print("\x1b[1;92mIRC Success!\x1b[0m")
    tarexit()
Example #2
0
def main():
    # Get user input.
    args = parse_user_input()
    # Start timer.
    click()

    subxyz = []
    subna = []
    subchg = []
    submult = []
    subvalid = []
    subefstart = []
    subeffinal = []
    SumFrags = []
    fragfiles = []

    # Pick out the files in the tarfile that have the structure "example*.sub_*.xyz"
    idhome = os.path.abspath('..')
    tar = tarfile.open(os.path.join(idhome, 'fragmentid.tar.bz2'), 'r')
    for tarinfo in tar:
        splitlist = tarinfo.name.split(".")
        if len(splitlist) > 2:
            if splitlist[2] == "xyz":
                subxyz.append(tarinfo.name)
                fragfiles.append(tarinfo)
    # Extract these files from the tarfile
    tar.extractall(members=fragfiles)
    tar.close()

    # Load files as molecules
    for frag in subxyz:
        M = Molecule(frag)
        M.read_comm_charge_mult()
        subchg.append(M.charge)
        submult.append(M.mult)
        subna.append(M.na)
        efstart = re.search('(?<=Molecular formula )\w+', M.comms[0]).group(0)
        subefstart.append(efstart)

    print("Running individual optimizations.")
    # Run individual geometry optimizations.
    FragE = 0.0
    FragZPE = 0.0
    FragEntr = 0.0
    FragEnth = 0.0
    for i in range(len(subxyz)):
        if subna[i] > 1:
            M = QCOptIC(subxyz[i],
                        subchg[i],
                        submult[i],
                        args.method,
                        args.basis,
                        cycles=args.cycles,
                        qcin='%s.opt.in' % os.path.splitext(subxyz[i])[0])
            # Select frames where the energy is monotonically decreasing.
            M = M[monotonic_decreasing(M.qm_energies)]
        else:
            # Special case of a single atom
            QCSP = QChem(subxyz[i],
                         charge=subchg[i],
                         mult=submult[i],
                         method=args.method,
                         basis=args.basis,
                         qcin='%s.sp.in' % os.path.splitext(subxyz[i])[0])
            QCSP.make_stable()
            QCSP.jobtype = 'sp'
            QCSP.calculate()
            M = QCSP.load_qcout()
        # Write optimization final result to file.
        M = M[-1]
        fragoptfile = os.path.splitext(subxyz[i])[0] + ".opt.xyz"
        M.write(fragoptfile)
        QCFR = QChem(fragoptfile,
                     charge=subchg[i],
                     mult=submult[i],
                     method=args.method,
                     basis=args.basis,
                     qcin='%s.freq.in' % os.path.splitext(fragoptfile)[0])
        QCFR.freq()
        M = QCFR.load_qcout()
        # Print out new molecular formulas.
        # This time we should be able to use covalent radii.
        M.build_topology(force_bonds=True)
        optformula = ' '.join([m.ef() for m in M.molecules])
        subeffinal.append(optformula)
        print(("%s.opt.xyz : formula %s; charge %i; mult %i; energy %f Ha;"
               "ZPE %f kcal/mol; entropy %f cal/mol.K; enthalpy %f kcal/mol" %
               (os.path.splitext(subxyz[i])[0], optformula, subchg[i],
                submult[i], M.qm_energies[0], M.qm_zpe[0], M.qm_entropy[0],
                M.qm_enthalpy[0])))
        FragE += M.qm_energies[0]
        FragZPE += M.qm_zpe[0]
        FragEntr += M.qm_entropy[0]
        FragEnth += M.qm_enthalpy[0]
        SumFrags.append(M[0])
    for fragment in SumFrags:
        fragment.write('fragmentopt.xyz', append=True)
    if subefstart != subeffinal:
        print("Fragments changed during optimization, calculation invalid")
    print("Final electronic energy (Ha) of optimized frags: % 18.10f" % FragE)
    print("Final ZPE (kcal/mol) of optimized frags: % 18.10f" % FragZPE)
    print("Final entropy (cal/mol.K) of optimized frags: % 18.10f" % FragEntr)
    print("Final enthalpy (kcal/mol) of optimized frags: % 18.10f" % FragEnth)
    nrg = open('fragmentopt.nrg', 'w')
    for subef in subeffinal:
        nrg.write(subef + " ")
    nrg.write("\nTotal electronic energy: %f Ha\n" % FragE)
    nrg.write("Total ZPE: %f kcal/mol\n" % FragZPE)
    nrg.write("Total entropy (STP): %f cal/mol.K\n" % FragEntr)
    nrg.write("Total enthalpy (STP): %f kcal/mol\n" % FragEnth)
    if subefstart != subeffinal: nrg.write("invalid")
    nrg.close()
    # Archive and exit.
    tarexit()