コード例 #1
0
def main():
    # Get user input.
    args = parse_user_input()
    # Start timer.
    click()
    # Run single point calculation to determine bond order matrix.
    QCSP = QChem(args.initial,
                 charge=args.charge,
                 mult=args.mult,
                 method=args.method,
                 basis=args.basis)
    QCSP.make_stable()
    QCSP.jobtype = 'sp'
    QCSP.remextra = OrderedDict([('scf_final_print', '1')])
    QCSP.calculate()
    # Rebuild bond list using the bond order matrix.
    M = QCSP.load_qcout()
    InitE = M.qm_energies[0]
    M.bonds = []
    # Determined from an incredibly small # of data points.
    # In example_1.xyz, an O-H distance of 1.89 Angstrom had a BO of 0.094 (so it should be > 0.1)
    # In example_1.xyz, a C-H distance of 1.39 Angstrom had a BO of 0.305 (so it should be < 0.3)
    bo_thresh = 0.2
    numbonds = 0
    bondfactor = 0.0
    print("Atoms  QM-BO  Distance")
    for i in range(M.na):
        for j in range(i + 1, M.na):
            # Print out the ones that are "almost" bonds.
            if M.qm_bondorder[i, j] > 0.1:
                print("%s%i%s%s%i % .3f % .3f" %
                      (M.elem[i], i, '-' if M.qm_bondorder[i, j] > bo_thresh
                       else ' ', M.elem[j], j, M.qm_bondorder[i, j],
                       np.linalg.norm(M.xyzs[-1][i] - M.xyzs[-1][j])))
            if M.qm_bondorder[i, j] > bo_thresh:
                M.bonds.append((i, j))
                numbonds += 1
                if M.qm_bondorder[i, j] <= 1:
                    bondfactor += M.qm_bondorder[i, j]
                else:
                    # Count double bonds as 1
                    bondfactor += 1
    bondfactor /= numbonds
    M.build_topology()
    subxyz = []
    subef = []
    subna = []
    subchg = []
    submult = []
    subvalid = []
    SumFrags = []
    # Divide calculation into subsystems.
    for subg in M.molecules:
        matoms = subg.nodes()
        frag = M.atom_select(matoms)
        # Determine output file name.
        fout = os.path.splitext(
            args.initial)[0] + '.sub_%i' % len(subxyz) + '.xyz'
        # Assume we are getting the Mulliken charges from the last frame, it's safer.
        # Write the output .xyz file.
        Chg = sum(M.qm_mulliken_charges[-1][matoms])
        SpnZ = sum(M.qm_mulliken_spins[-1][matoms])
        Spn2 = sum([i**2 for i in M.qm_mulliken_spins[-1][matoms]])
        frag.comms = [
            "Molecular formula %s atoms %s from %s charge %+.3f sz %+.3f sz^2 %.3f"
            %
            (subg.ef(), commadash(subg.nodes()), args.initial, Chg, SpnZ, Spn2)
        ]
        frag.write(fout)
        subxyz.append(fout)
        subef.append(subg.ef())
        subna.append(frag.na)
        # Determine integer charge and multiplicity.
        ichg, chgpass = extract_int(np.array([Chg]), 0.5, 1.0, label="charge")
        ispn, spnpass = extract_int(np.array([abs(SpnZ)]),
                                    0.5,
                                    1.0,
                                    label="spin-z")
        nproton = sum([Elements.index(i) for i in frag.elem])
        nelectron = nproton + ichg
        # If calculation is valid, append to the list of xyz/chg/mult to be calculated.
        if (not chgpass or not spnpass):
            print("Cannot determine charge and spin for fragment %s\n" %
                  subg.ef())
            subchg.append(None)
            submult.append(None)
            subvalid.append(False)
        elif ((nelectron - ispn) / 2) * 2 != (nelectron - ispn):
            print("Inconsistent charge and spin-z for fragment %s\n" %
                  subg.ef())
            subchg.append(None)
            submult.append(None)
            subvalid.append(False)
        else:
            subchg.append(ichg)
            submult.append(ispn + 1)
            subvalid.append(True)
    print("%i/%i subcalculations are valid" % (len(subvalid), sum(subvalid)))
    for i in range(len(subxyz)):
        print("%s formula %-12s charge %i mult %i %s" %
              (subxyz[i], subef[i], subchg[i], submult[i],
               "valid" if subvalid[i] else "invalid"))
    fragid = open('fragmentid.txt', 'w')
    for formula in subef:
        fragid.write(formula + " ")
    fragid.write("\nBondfactor: " + str(bondfactor))
    if not all(subvalid): fragid.write("\ninvalid")
    fragid.close()
    # Archive and exit
    tarexit()
コード例 #2
0
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()
コード例 #3
0
def QCOpt(initial, charge, mult, method, basis, cycles=100, gtol=600, dxtol=2400, etol=200, cart=False):
    """
    Run a Q-Chem geometry optimization.  Default tolerances for
    gradient, displacement and energy are higher than usual because we
    don't want significant nonbonded conformational changes in the
    pathway.

    Parameters
    ----------
    initial : str
        Initial XYZ file for optimization
    charge : int
        Net charge
    mult : int
        Spin multiplicity
    method : str
        Electronic structure method
    basis : str
        Basis set
    cycles : int
        Number of optimization cycles
    gtol : int
        Gradient tolerance for Q-Chem
    dxtol : int
        Displacement tolerance for Q-Chem
    etol : int
        Energy tolerance for Q-Chem
    cart : bool
        Perform the optimization in Cartesian coordinates
    """
    # Create Q-Chem object.
    QC = QChem(initial, charge=charge, mult=mult, method=method, basis=basis, qcin='optimize.in')
    # Run a stability analysis first to ensure we're in the ground state.
    QC.make_stable()
    # Set geometry optimization options.
    QC.jobtype = 'opt'
    QC.remextra = OrderedDict()
    if cart: QC.remextra['geom_opt_coords'] = 0
    QC.remextra['thresh'] = 14
    QC.remextra['geom_opt_tol_gradient'] = gtol
    QC.remextra['geom_opt_tol_displacement'] = dxtol
    QC.remextra['geom_opt_tol_energy'] = etol
    QC.remextra['geom_opt_max_cycles'] = cycles
    # Run Q-Chem.
    QC.calculate()
    # Create Molecule object from running Q-Chem.
    M = QC.load_qcout()
    return M
コード例 #4
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()
コード例 #5
0
ファイル: ts-analyze.py プロジェクト: stenczelt/nanoreactor
def main():
    # Get user input.
    args = parse_user_input()
    _exec("rm -f ts-analyze.tar.bz2 irc_transition.xyz irc_transition.vib",
          print_command=False)
    # Standardize base name to "irc_transition".
    shutil.copy2(args.ts, 'irc_transition.xyz')
    # Run Q-Chem calculations..
    QCT = QChem("irc_transition.xyz",
                charge=args.charge,
                mult=args.mult,
                method=args.method,
                basis=args.basis)
    # Ensure stability.
    QCT.make_stable()
    # Single point calculation for bond order matrix.
    QCT.jobtype = 'sp'
    QCT.remextra = OrderedDict([('scf_final_print', '1')])
    QCT.calculate()
    np.savetxt("irc_transition.bnd",
               QCT.load_qcout().qm_bondorder,
               fmt="%8.3f")
    # Frequency calculation.
    QCT.jobtype = 'freq'
    QCT.calculate()
    QCT.write_vdata('irc_transition.vib')
    tarexit()
コード例 #6
0
ファイル: qcgs.py プロジェクト: stenczelt/nanoreactor
compromise solution is to do a stability analysis every 10 string
iterations, or for any image that was unstable for the previous
string iteration.

Also, this script ensures that every image in the growing string calculation
uses the Q-Chem
"""

import os
import sys

from nanoreactor.qchem import QChem, tarexit

tarexit.tarfnm = "growing-string.tar.bz2"

QC = QChem(sys.argv[1], qcout=sys.argv[2], qcdir=sys.argv[3], qcsave=True, readsave=True)

# File that records how many calculations were done
# for this image.
calcfnm = os.path.splitext(sys.argv[1])[0] + ".num"
calcnum = -1
if os.path.exists(calcfnm):
    calcnum = int(open(calcfnm).readlines()[0].strip())
calcnum += 1
with open(calcfnm, 'w') as f: print(calcnum, file=f)

# File that records how many iterations ago we had to do a stability
# analysis.  "# of days since last accident" kind of thang.
stabfnm = "qchem.nsb"
stablast = int(open(stabfnm).readlines()[0].strip()) if os.path.exists(stabfnm) else 0