Exemplo n.º 1
0
    def write_output(self):
        """
        Save the results of the ThermoJob to the `output.py` file located
        in `output_directory`.
        """
        output_file = os.path.join(self.output_directory, 'output.py')
        logging.info(
            'Saving statistical mechanics parameters for {0}...'.format(
                self.label))
        f = open(output_file, 'a')

        conformer = self.conformer
        coordinates = conformer.coordinates.value_si * 1e10

        f.write(
            '# Coordinates for {0} in Input Orientation (angstroms):\n'.format(
                self.label))
        for i in range(coordinates.shape[0]):
            x = coordinates[i, 0]
            y = coordinates[i, 1]
            z = coordinates[i, 2]
            f.write('#   {0} {1:9.4f} {2:9.4f} {3:9.4f}\n'.format(
                self.symbols[i], x, y, z))
        f.write('\n')

        result = 'conformer(label={0!r}, E0={1!r}, modes={2!r}, spin_multiplicity={3:d}, optical_isomers={4:d}'.format(
            self.label,
            conformer.E0,
            conformer.modes,
            conformer.spin_multiplicity,
            conformer.optical_isomers,
        )
        try:
            result += ', frequency={0!r}'.format(
                self.sampling.imaginary_frequency)
        except AttributeError:
            pass
        result += ')'
        f.write('{0}\n\n'.format(prettify(result)))

        if self.coordinate_system in ["E-Optimized", "E'-Optimized"]:
            from rmgpy.statmech.vibration import HarmonicOscillator
            vib_freq = [
                round((self.mode_dict[key]['K']**0.5) /
                      (2 * np.pi * constants.c * 100), 2)
                for key in self.mode_dict.keys()
            ]
            vibration = HarmonicOscillator(frequencies=(sorted(vib_freq),
                                                        "cm^-1"))
            f.write((
                '# {0}: Vibrational frequencies of optimal vibrational modes\n'
                .format(self.coordinate_system)))
            f.write(prettify('{0!r}\n'.format(vibration)))

        for line in self.result_info:
            line = line + '\n'
            f.write(line)
        f.write('\n')
        f.close()
Exemplo n.º 2
0
    def write_output(self, output_directory):
        """
        Save the results of the thermodynamics job to the `output.py` file located
        in `output_directory`.
        """
        species = self.species
        outputFile = os.path.join(output_directory, 'output.py')
        logging.info('Saving thermo for {0}...'.format(species.label))

        with open(outputFile, 'a') as f:
            f.write('# Thermodynamics for {0}:\n'.format(species.label))
            H298 = species.getThermoData().getEnthalpy(298) / 4184.
            S298 = species.getThermoData().getEntropy(298) / 4.184
            f.write('#   Enthalpy of formation (298 K)   = {0:9.3f} kcal/mol\n'.format(H298))
            f.write('#   Entropy of formation (298 K)    = {0:9.3f} cal/(mol*K)\n'.format(S298))
            f.write('#    =========== =========== =========== =========== ===========\n')
            f.write('#    Temperature Heat cap.   Enthalpy    Entropy     Free energy\n')
            f.write('#    (K)         (cal/mol*K) (kcal/mol)  (cal/mol*K) (kcal/mol)\n')
            f.write('#    =========== =========== =========== =========== ===========\n')
            for T in [300, 400, 500, 600, 800, 1000, 1500, 2000, 2400]:
                try:
                    Cp = species.getThermoData().getHeatCapacity(T) / 4.184
                    H = species.getThermoData().getEnthalpy(T) / 4184.
                    S = species.getThermoData().getEntropy(T) / 4.184
                    G = species.getThermoData().getFreeEnergy(T) / 4184.
                    f.write('#    {0:11g} {1:11.3f} {2:11.3f} {3:11.3f} {4:11.3f}\n'.format(T, Cp, H, S, G))
                except ValueError:
                    logging.debug("Valid thermo for {0} is outside range for temperature {1}".format(species, T))
            f.write('#    =========== =========== =========== =========== ===========\n')

            thermo_string = 'thermo(label={0!r}, thermo={1!r})'.format(species.label, species.getThermoData())
            f.write('{0}\n\n'.format(prettify(thermo_string)))
Exemplo n.º 3
0
    def save(self, outputFile):
        """
        Save the results of the thermodynamics job to the file located
        at `path` on disk.
        """
        species = self.species
        logging.info('Saving thermo for {0}...'.format(species.label))
        
        f = open(outputFile, 'a')
    
        f.write('# Thermodynamics for {0}:\n'.format(species.label))
        H298 = species.getThermoData().getEnthalpy(298) / 4184.
        S298 = species.getThermoData().getEntropy(298) / 4.184
        f.write('#   Enthalpy of formation (298 K)   = {0:9.3f} kcal/mol\n'.format(H298))
        f.write('#   Entropy of formation (298 K)    = {0:9.3f} cal/(mol*K)\n'.format(S298))
        f.write('#    =========== =========== =========== =========== ===========\n')
        f.write('#    Temperature Heat cap.   Enthalpy    Entropy     Free energy\n')
        f.write('#    (K)         (cal/mol*K) (kcal/mol)  (cal/mol*K) (kcal/mol)\n')
        f.write('#    =========== =========== =========== =========== ===========\n')
        for T in [300,400,500,600,800,1000,1500,2000,2400]:
            try:
                Cp = species.getThermoData().getHeatCapacity(T) / 4.184
                H = species.getThermoData().getEnthalpy(T) / 4184.
                S = species.getThermoData().getEntropy(T) / 4.184
                G = species.getThermoData().getFreeEnergy(T) / 4184.
                f.write('#    {0:11g} {1:11.3f} {2:11.3f} {3:11.3f} {4:11.3f}\n'.format(T, Cp, H, S, G))
            except ValueError:
                logging.debug("Valid thermo for {0} is outside range for temperature {1}".format(species,T))
        f.write('#    =========== =========== =========== =========== ===========\n')

        thermo_string = 'thermo(label={0!r}, thermo={1!r})'.format(species.label, species.getThermoData())
        f.write('{0}\n\n'.format(prettify(thermo_string)))
        
        f.close()
        # write chemkin file
        f = open(os.path.join(os.path.dirname(outputFile), 'chem.inp'), 'a')
        if isinstance(species, Species):
            if species.molecule and isinstance(species.molecule[0], Molecule):
                elementCounts = retrieveElementCount(species.molecule[0])
            else:
                try:
                    elementCounts = species.props['elementCounts']
                except KeyError:
                    elementCounts = {'C': 0, 'H': 0}
        else:
            elementCounts = {'C': 0, 'H': 0}
        chemkin_thermo_string = writeThermoEntry(species, elementCounts=elementCounts, verbose=True)
        f.write('{0}\n'.format(chemkin_thermo_string))
        f.close()

        # write species dictionary
        if isinstance(species, Species):
            if species.molecule and isinstance(species.molecule[0], Molecule):
                with open(os.path.join(os.path.dirname(outputFile), 'species_dictionary.txt'), 'a') as f:
                    f.write(species.molecule[0].toAdjacencyList(removeH=False, label=species.label))
                    f.write('\n')
        return chemkin_thermo_string
Exemplo n.º 4
0
    def test_prettify(self):
        """Test that ``prettify`` returns the expected result"""
        input_str = (
            "conformer(label='C7H7', E0=(193.749,'kJ/mol'), modes=[IdealGasTranslation(mass=(91.0548,'amu')), "
            "NonlinearRotor(inertia=([91.0567,186.675,277.733],'amu*angstrom^2'), symmetry=2), "
            "HarmonicOscillator(frequencies=([199.381,360.536,413.795,480.347,536.285,630.723,687.118,709.613,"
            "776.662,830.404,834.386,901.841,973.498,975.148,993.349,998.606,1040.14,1120.69,1179.22,1189.07,"
            "1292.86,1332.91,1357.18,1479.46,1495.36,1507.91,1583.14,1604.63,3156.85,3170.22,3172.78,3185.05,"
            "3189.8,3203.23,3253.99],'cm^-1')), HinderedRotor(inertia=(1.70013,'amu*angstrom^2'), symmetry=2, "
            "fourier=([[-0.315923,-27.7665,0.177678,3.2437,0.0509515],[-0.00164953,-0.0021925,-0.00386396,"
            "-0.000912068,0.00274206]],'kJ/mol'), quantum=True, semiclassical=False)], spin_multiplicity=2, "
            "optical_isomers=1)")
        expected_output = """conformer(
    label = 'C7H7',
    E0 = (193.749, 'kJ/mol'),
    modes = [
        IdealGasTranslation(mass=(91.0548, 'amu')),
        NonlinearRotor(
            inertia = ([91.0567, 186.675, 277.733], 'amu*angstrom^2'),
            symmetry = 2,
        ),
        HarmonicOscillator(
            frequencies = ([199.381, 360.536, 413.795, 480.347, 536.285, 630.723, 687.118, 709.613, 776.662, 830.404, 834.386, 901.841, 973.498, 975.148, 993.349, 998.606, 1040.14, 1120.69, 1179.22, 1189.07, 1292.86, 1332.91, 1357.18, 1479.46, 1495.36, 1507.91, 1583.14, 1604.63, 3156.85, 3170.22, 3172.78, 3185.05, 3189.8, 3203.23, 3253.99], 'cm^-1'),
        ),
        HinderedRotor(
            inertia = (1.70013, 'amu*angstrom^2'),
            symmetry = 2,
            fourier = (
                [
                    [-0.315923, -27.7665, 0.177678, 3.2437, 0.0509515],
                    [-0.00164953, -0.0021925, -0.00386396, -0.000912068, 0.00274206],
                ],
                'kJ/mol',
            ),
            quantum = None,
            semiclassical = None,
        ),
    ],
    spin_multiplicity = 2,
    optical_isomers = 1,
)"""
        self.assertEqual(prettify(input_str), expected_output)
Exemplo n.º 5
0
    def write_output(self):
        """
        Save the results of the ThermoJob to the `output.py` file located
        in `output_directory`.
        """
        output_file = os.path.join(self.output_directory, 'output.py')
        logging.info('Saving statistical mechanics parameters for {0}...'.format(self.label))
        f = open(output_file, 'a')

        conformer = self.conformer
        coordinates = conformer.coordinates.value_si * 1e10
        number = conformer.number.value_si

        f.write('# Coordinates for {0} in Input Orientation (angstroms):\n'.format(self.label))
        for i in range(coordinates.shape[0]):
            x = coordinates[i, 0]
            y = coordinates[i, 1]
            z = coordinates[i, 2]
            f.write('#   {0} {1:9.4f} {2:9.4f} {3:9.4f}\n'.format(self.symbols[i], x, y, z))
        f.write('\n')

        result = 'conformer(label={0!r}, E0={1!r}, modes={2!r}, spin_multiplicity={3:d}, optical_isomers={4:d}'.format(
            self.label,
            conformer.E0,
            conformer.modes,
            conformer.spin_multiplicity,
            conformer.optical_isomers,
        )
        try:
            result += ', frequency={0!r}'.format(self.sampling.imaginary_frequency)
        except AttributeError:
            pass
        result += ')'
        f.write('{0}\n\n'.format(prettify(result)))

        for line in self.result_info:
            line = line + '\n'
            f.write(line)
        f.write('\n')
        f.close()
Exemplo n.º 6
0
    def save(self, output_file):
        """Save the output of a pressure dependent job"""
        logging.info(
            'Saving pressure dependence results for network {0}...'.format(
                self.network.label))
        f = open(output_file, 'a')
        f_chemkin = open(
            os.path.join(os.path.dirname(output_file), 'chem.inp'), 'a')

        n_reac = self.network.n_isom + self.network.n_reac
        n_prod = n_reac + self.network.n_prod
        Tlist = self.Tlist.value_si
        Plist = self.Plist.value_si
        Tcount = Tlist.shape[0]
        Pcount = Plist.shape[0]

        f.write("#Thermo used:  \n")
        spcs = []
        for rxn in self.network.path_reactions:
            spcs.extend(rxn.reactants)
            spcs.extend(rxn.products)
        for spc in spcs:
            if spc.thermo:
                f.write("#" + spc.label + "  SMILES: " +
                        spc.molecule[0].to_smiles() + "\n")
                f.write("#" + spc.thermo.comment + "\n")
        f.write("\n#Path Reactions used:  \n")
        for rxn in self.network.path_reactions:
            if rxn.kinetics:
                f.write("#" + str(rxn) + "\n")
                for s in rxn.kinetics.comment.split("\n"):
                    f.write("#" + s + "\n")
        f.write("\n")

        count = 0
        printed_reactions = []  # list of rxns already printed
        for prod in range(n_prod):
            for reac in range(n_reac):
                if reac == prod:
                    continue
                reaction = self.network.net_reactions[count]
                count += 1
                # make sure we aren't double counting any reactions
                if not any([
                        reaction.is_isomorphic(other_rxn,
                                               check_only_label=True)
                        for other_rxn in printed_reactions
                ]):
                    duplicate = False
                    # add reaction to printed reaction
                    printed_reactions.append(reaction)
                else:
                    # comment out the extra reverse reaction
                    duplicate = True

                # write chemkin output.
                string = write_kinetics_entry(reaction,
                                              species_list=None,
                                              verbose=False,
                                              commented=duplicate)
                f_chemkin.write('{0}\n'.format(string))

                # write to 'output.py'
                kdata = self.K[:, :, prod, reac].copy()
                order = len(reaction.reactants)
                kdata *= 1e6**(order - 1)
                k_units = {
                    1: 's^-1',
                    2: 'cm^3/(mol*s)',
                    3: 'cm^6/(mol^2*s)'
                }[order]

                f.write('#   =========== ')
                f.write('=========== ' * Pcount)
                f.write('\n')
                f.write('#         T / P ')
                f.write(' '.join(['{0:11.3e}'.format(P * 1e-5)
                                  for P in Plist]))
                f.write('\n')
                f.write('#   =========== ')
                f.write('=========== ' * Pcount)
                f.write('\n')

                for t in range(Tcount):
                    f.write('#   {0:11g}'.format(Tlist[t]))
                    for p in range(Pcount):
                        f.write(' {0:11.3e}'.format(kdata[t, p]))
                    f.write('\n')

                f.write('#   =========== ')
                f.write('=========== ' * Pcount)
                f.write('\n')

                string = 'pdepreaction(reactants={0!r}, products={1!r}, kinetics={2!r})'.format(
                    [reactant.label for reactant in reaction.reactants],
                    [product.label for product in reaction.products],
                    reaction.kinetics,
                )
                pdep_function = '{0}\n\n'.format(prettify(string))
                if duplicate:
                    # add comments to the start of the string
                    pdep_function = '#   ' + pdep_function.replace(
                        '\n', '\n#   ')
                f.write(pdep_function)

        f.close()
        f_chemkin.close()
Exemplo n.º 7
0
def saveEntry(f, entry):
    """
    Save an `entry` in the kinetics database by writing a string to
    the given file object `f`.
    """
    from arkane.output import prettify

    def sortEfficiencies(efficiencies0):
        efficiencies = {}
        for mol, eff in efficiencies0.iteritems():
            if isinstance(mol, str):
                # already in SMILES string format
                smiles = mol
            else:
                smiles = mol.toSMILES()
                
            efficiencies[smiles] = eff
        keys = efficiencies.keys()
        keys.sort()
        return [(key, efficiencies[key]) for key in keys]

    f.write('entry(\n')
    f.write('    index = {0:d},\n'.format(entry.index))
    if entry.label != '':
        f.write('    label = "{0}",\n'.format(entry.label))


    #Entries for kinetic rules, libraries, training reactions
    #and depositories will have a Reaction object for its item
    if isinstance(entry.item, Reaction):
        #Write out additional data if depository or library
        #kinetic rules would have a Group object for its reactants instead of Species
        if isinstance(entry.item.reactants[0], Species):
            # Add degeneracy if the reaction is coming from a depository or kinetics library
            f.write('    degeneracy = {0:.1f},\n'.format(entry.item.degeneracy))
            if entry.item.duplicate:
                f.write('    duplicate = {0!r},\n'.format(entry.item.duplicate))
            if not entry.item.reversible:
                f.write('    reversible = {0!r},\n'.format(entry.item.reversible))
            if entry.item.allow_pdep_route:
                f.write('    allow_pdep_route = {0!r},\n'.format(entry.item.allow_pdep_route))
            if entry.item.elementary_high_p:
                f.write('    elementary_high_p = {0!r},\n'.format(entry.item.elementary_high_p))
            if entry.item.allow_max_rate_violation:
                f.write('    allow_max_rate_violation = {0!r},\n'.format(entry.item.allow_max_rate_violation))
    #Entries for groups with have a group or logicNode for its item
    elif isinstance(entry.item, Group):
        f.write('    group = \n')
        f.write('"""\n')
        f.write(entry.item.toAdjacencyList())
        f.write('""",\n')
    elif isinstance(entry.item, LogicNode):
        f.write('    group = "{0}",\n'.format(entry.item))
    else:
        raise DatabaseError("Encountered unexpected item of type {0} while saving database.".format(entry.item.__class__))

    # Write kinetics
    if isinstance(entry.data, str):
        f.write('    kinetics = "{0}",\n'.format(entry.data))
    elif entry.data is not None:
        efficiencies = None
        if hasattr(entry.data, 'efficiencies'):
            efficiencies = entry.data.efficiencies
            entry.data.efficiencies = dict(sortEfficiencies(entry.data.efficiencies))
        kinetics = prettify(repr(entry.data))
        kinetics = '    kinetics = {0},\n'.format(kinetics.replace('\n', '\n    '))
        f.write(kinetics)
        if hasattr(entry.data, 'efficiencies'):
            entry.data.efficiencies = efficiencies
    else:
        f.write('    kinetics = None,\n')
            
    # Write reference
    if entry.reference is not None:
        reference = entry.reference.toPrettyRepr()
        lines = reference.splitlines()
        f.write('    reference = {0}\n'.format(lines[0]))
        for line in lines[1:-1]:
            f.write('    {0}\n'.format(line))
        f.write('    ),\n'.format(lines[0]))
    
    if entry.referenceType != "":
        f.write('    referenceType = "{0}",\n'.format(entry.referenceType))
    if entry.rank is not None:
        f.write('    rank = {0},\n'.format(entry.rank))
        
    if entry.shortDesc.strip() !='':
        f.write('    shortDesc = u"""')
        try:
            f.write(entry.shortDesc.encode('utf-8'))
        except:
            f.write(entry.shortDesc.strip().encode('ascii', 'ignore')+ "\n")
        f.write('""",\n')
    
    if entry.longDesc.strip() !='':
        f.write('    longDesc = \n')
        f.write('u"""\n')
        try:
            f.write(entry.longDesc.strip().encode('utf-8') + "\n")
        except:
            f.write(entry.longDesc.strip().encode('ascii', 'ignore')+ "\n")
        f.write('""",\n')

    f.write(')\n\n')
Exemplo n.º 8
0
    def save(self, outputFile):
        """
        Save the results of the kinetics job to the file located
        at `path` on disk.
        """
        reaction = self.reaction
        
        ks = []
        k0s = []
        k0revs = []
        krevs = []
        
        logging.info('Saving kinetics for {0}...'.format(reaction))
        
        order = len(self.reaction.reactants)
        factor = 1e6 ** (order-1)
        
        f = open(outputFile, 'a')

        if self.usedTST:
            # If TST is not used, eg. it was given in 'reaction', then this will throw an error.
            f.write('#   ======= =========== =========== =========== ===============\n')
            f.write('#   Temp.   k (TST)     Tunneling   k (TST+T)   Units\n')
            f.write('#   ======= =========== =========== =========== ===============\n')
            
            if self.Tlist is None:
                Tlist = numpy.array([300,400,500,600,800,1000,1500,2000])
            else:
                Tlist =self.Tlist.value_si

            for T in Tlist:  
                tunneling = reaction.transitionState.tunneling
                reaction.transitionState.tunneling = None
                try:
                    k0 = reaction.calculateTSTRateCoefficient(T) * factor
                except SpeciesError:
                    k0 = 0
                reaction.transitionState.tunneling = tunneling
                try:
                    k = reaction.calculateTSTRateCoefficient(T) * factor
                    kappa = k / k0
                except (SpeciesError,ZeroDivisionError):
                    k = reaction.getRateCoefficient(T)
                    kappa = 0
                    logging.info("The species in reaction {} do not have adequate information for TST, using default kinetics values.".format(reaction))
                tunneling = reaction.transitionState.tunneling
                ks.append(k)
                k0s.append(k0)

                f.write('#    {0:4g} K {1:11.3e} {2:11g} {3:11.3e} {4}\n'.format(T, k0, kappa, k, self.kunits))
            f.write('#   ======= =========== =========== =========== ===============\n')
            f.write('\n\n')
            
            f.write('#   ======= ============ =========== ============ ============= =========\n')
            f.write('#   Temp.    Kc (eq)        Units     krev (TST)   krev (TST+T)   Units\n')
            f.write('#   ======= ============ =========== ============ ============= =========\n')

            # Initialize Object for Converting Units
            if self.Kequnits != '       ':
                keq_unit_converter = quantity.Units(self.Kequnits).getConversionFactorFromSI()
            else:
                keq_unit_converter = 1

            for n,T in enumerate(Tlist):
                k = ks[n]
                k0 = k0s[n]
                Keq = keq_unit_converter * reaction.getEquilibriumConstant(T)  # getEquilibriumConstant returns SI units
                k0rev = k0/Keq
                krev =  k/Keq
                k0revs.append(k0rev)
                krevs.append(krev)
                f.write('#    {0:4g} K {1:11.3e}   {2}  {3:11.3e}   {4:11.3e}      {5}\n'.format(T, Keq, self.Kequnits, k0rev, krev, self.krunits))

            f.write('#   ======= ============ =========== ============ ============= =========\n')
            f.write('\n\n')

            kinetics0rev = Arrhenius().fitToData(Tlist, numpy.array(k0revs), kunits=self.krunits)
            kineticsrev = Arrhenius().fitToData(Tlist, numpy.array(krevs), kunits=self.krunits)
            
            f.write('# krev (TST) = {0} \n'.format(kinetics0rev))
            f.write('# krev (TST+T) = {0} \n\n'.format(kineticsrev))

        # Reaction path degeneracy is INCLUDED in the kinetics itself!
        string = 'kinetics(label={0!r}, kinetics={1!r})'.format(reaction.label, reaction.kinetics)
        f.write('{0}\n\n'.format(prettify(string)))
        
        f.close()
        
        # Also save the result to chem.inp
        f = open(os.path.join(os.path.dirname(outputFile), 'chem.inp'), 'a')
        
        reaction = self.reaction
        kinetics = reaction.kinetics

        string = ''
        if reaction.kinetics.comment:
            for line in reaction.kinetics.comment.split("\n"):
                string += "! {0}\n".format(line)
        string += '{0!s:51} {1:9.3e} {2:9.3f} {3:9.3f}\n'.format(
            reaction,
            kinetics.A.value_si * factor,
            kinetics.n.value_si,
            kinetics.Ea.value_si / 4184.,
        )
                
        f.write('{0}\n'.format(string))
            
        f.close()

        # We're saving a YAML file for TSs iff structures of the respective reactant/s and product/s are known
        if all ([spc.molecule is not None and len(spc.molecule)
                 for spc in self.reaction.reactants + self.reaction.products]):
            self.arkane_species.update_species_attributes(self.reaction.transitionState)
            self.arkane_species.reaction_label = reaction.label
            self.arkane_species.reactants = [{'label': spc.label, 'adjacency_list': spc.molecule[0].toAdjacencyList()}
                                             for spc in self.reaction.reactants]
            self.arkane_species.products = [{'label': spc.label, 'adjacency_list': spc.molecule[0].toAdjacencyList()}
                                             for spc in self.reaction.products]
            self.arkane_species.save_yaml(path=os.path.dirname(outputFile))
Exemplo n.º 9
0
    def save(self, outputFile):

        logging.info(
            'Saving pressure dependence results for network {0}...'.format(
                self.network.label))
        f = open(outputFile, 'a')
        f_chemkin = open(os.path.join(os.path.dirname(outputFile), 'chem.inp'),
                         'a')

        Nreac = self.network.Nisom + self.network.Nreac
        Nprod = Nreac + self.network.Nprod
        Tlist = self.Tlist.value_si
        Plist = self.Plist.value_si
        Tcount = Tlist.shape[0]
        Pcount = Plist.shape[0]

        count = 0
        printed_reactions = []  # list of rxns already printed
        for prod in range(Nprod):
            for reac in range(Nreac):
                if reac == prod: continue
                reaction = self.network.netReactions[count]
                count += 1
                # make sure we aren't double counting any reactions
                if not any([reaction.isIsomorphic(other_rxn,checkOnlyLabel=True) \
                            for other_rxn in printed_reactions]):
                    duplicate = False
                    # add reaction to printed reaction
                    printed_reactions.append(reaction)
                else:
                    # comment out the extra reverse reaction
                    duplicate = True

                # write chemkin output.
                string = writeKineticsEntry(reaction,
                                            speciesList=None,
                                            verbose=False,
                                            commented=duplicate)
                f_chemkin.write('{0}\n'.format(string))

                # write to 'output.py'
                kdata = self.K[:, :, prod, reac].copy()
                order = len(reaction.reactants)
                kdata *= 1e6**(order - 1)
                kunits = {
                    1: 's^-1',
                    2: 'cm^3/(mol*s)',
                    3: 'cm^6/(mol^2*s)'
                }[order]

                f.write('#   =========== ')
                f.write('=========== ' * Pcount)
                f.write('\n')
                f.write('#         T \ P ')
                f.write(' '.join(['{0:11.3e}'.format(P * 1e-5)
                                  for P in Plist]))
                f.write('\n')
                f.write('#   =========== ')
                f.write('=========== ' * Pcount)
                f.write('\n')

                for t in range(Tcount):
                    f.write('#   {0:11g}'.format(Tlist[t]))
                    for p in range(Pcount):
                        f.write(' {0:11.3e}'.format(kdata[t, p]))
                    f.write('\n')

                f.write('#   =========== ')
                f.write('=========== ' * Pcount)
                f.write('\n')

                string = 'pdepreaction(reactants={0!r}, products={1!r}, kinetics={2!r})'.format(
                    [reactant.label for reactant in reaction.reactants],
                    [product.label for product in reaction.products],
                    reaction.kinetics,
                )
                pdep_function = '{0}\n\n'.format(prettify(string))
                if duplicate:
                    # add comments to the start of the string
                    pdep_function = '#   ' + pdep_function.replace(
                        '\n', '\n#   ')
                f.write(pdep_function)

        f.close()
        f_chemkin.close()
Exemplo n.º 10
0
    def write_output(self, output_directory):
        """
        Save the results of the kinetics job to the `output.py` file located
        in `output_directory`.
        """
        reaction = self.reaction

        ks, k0s, k0_revs, k_revs = [], [], [], []

        logging.info('Saving kinetics for {0}...'.format(reaction))

        order = len(self.reaction.reactants)

        factor = 1e6**(order - 1)

        f = open(os.path.join(output_directory, 'output.py'), 'a')

        if self.usedTST:
            # If TST is not used, eg. it was given in 'reaction', then this will throw an error.
            f.write(
                '#   ======= =========== =========== =========== ===============\n'
            )
            f.write('#   Temp.   k (TST)     Tunneling   k (TST+T)   Units\n')
            f.write(
                '#   ======= =========== =========== =========== ===============\n'
            )

            if self.Tlist is None:
                t_list = np.array([300, 400, 500, 600, 800, 1000, 1500, 2000])
            else:
                t_list = self.Tlist.value_si

            for T in t_list:
                tunneling = reaction.transition_state.tunneling
                reaction.transition_state.tunneling = None
                try:
                    k0 = reaction.calculate_tst_rate_coefficient(T) * factor
                except SpeciesError:
                    k0 = 0
                reaction.transition_state.tunneling = tunneling
                try:
                    k = reaction.calculate_tst_rate_coefficient(T) * factor
                    kappa = k / k0
                except (SpeciesError, ZeroDivisionError):
                    k = reaction.get_rate_coefficient(T)
                    kappa = 0
                    logging.info(
                        "The species in reaction {0} do not have adequate information for TST, "
                        "using default kinetics values.".format(reaction))
                tunneling = reaction.transition_state.tunneling
                ks.append(k)
                k0s.append(k0)

                f.write(
                    '#    {0:4g} K {1:11.3e} {2:11g} {3:11.3e} {4}\n'.format(
                        T, k0, kappa, k, self.k_units))
            f.write(
                '#   ======= =========== =========== =========== ===============\n'
            )
            f.write('\n\n')

            f.write(
                '#   ======= ============ =========== ============ ============= =========\n'
            )
            f.write(
                '#   Temp.    Kc (eq)        Units     k_rev (TST) k_rev (TST+T)   Units\n'
            )
            f.write(
                '#   ======= ============ =========== ============ ============= =========\n'
            )

            # Initialize Object for Converting Units
            if self.K_eq_units != '       ':
                keq_unit_converter = quantity.Units(
                    self.K_eq_units).get_conversion_factor_from_si()
            else:
                keq_unit_converter = 1

            for n, T in enumerate(t_list):
                k = ks[n]
                k0 = k0s[n]
                K_eq = keq_unit_converter * reaction.get_equilibrium_constant(
                    T)  # returns SI units
                k0_rev = k0 / K_eq
                k_rev = k / K_eq
                k0_revs.append(k0_rev)
                k_revs.append(k_rev)
                f.write(
                    '#    {0:4g} K {1:11.3e}   {2}  {3:11.3e}   {4:11.3e}      {5}\n'
                    .format(T, K_eq, self.K_eq_units, k0_rev, k_rev,
                            self.k_r_units))

            f.write(
                '#   ======= ============ =========== ============ ============= =========\n'
            )
            f.write('\n\n')

            kinetics_0_rev = Arrhenius().fit_to_data(t_list,
                                                     np.array(k0_revs),
                                                     kunits=self.k_r_units)
            kinetics_rev = Arrhenius().fit_to_data(t_list,
                                                   np.array(k_revs),
                                                   kunits=self.k_r_units)

            f.write('# k_rev (TST) = {0} \n'.format(kinetics_0_rev))
            f.write('# k_rev (TST+T) = {0} \n\n'.format(kinetics_rev))
        # Reaction path degeneracy is INCLUDED in the kinetics itself!
        rxn_str = 'kinetics(label={0!r}, kinetics={1!r})'.format(
            reaction.label, reaction.kinetics)
        f.write('{0}\n\n'.format(prettify(rxn_str)))

        f.close()
Exemplo n.º 11
0
def saveEntry(f, entry):
    """
    Save an `entry` in the kinetics database by writing a string to
    the given file object `f`.
    """
    from arkane.output import prettify

    def sortEfficiencies(efficiencies0):
        efficiencies = {}
        for mol, eff in efficiencies0.iteritems():
            if isinstance(mol, str):
                # already in SMILES string format
                smiles = mol
            else:
                smiles = mol.toSMILES()
                
            efficiencies[smiles] = eff
        keys = efficiencies.keys()
        keys.sort()
        return [(key, efficiencies[key]) for key in keys]

    f.write('entry(\n')
    f.write('    index = {0:d},\n'.format(entry.index))
    if entry.label != '':
        f.write('    label = "{0}",\n'.format(entry.label))


    #Entries for kinetic rules, libraries, training reactions
    #and depositories will have a Reaction object for its item
    if isinstance(entry.item, Reaction):
        #Write out additional data if depository or library
        #kinetic rules would have a Group object for its reactants instead of Species
        if isinstance(entry.item.reactants[0], Species):
            # Add degeneracy if the reaction is coming from a depository or kinetics library
            f.write('    degeneracy = {0:.1f},\n'.format(entry.item.degeneracy))
            if entry.item.duplicate:
                f.write('    duplicate = {0!r},\n'.format(entry.item.duplicate))
            if not entry.item.reversible:
                f.write('    reversible = {0!r},\n'.format(entry.item.reversible))
            if entry.item.allow_pdep_route:
                f.write('    allow_pdep_route = {0!r},\n'.format(entry.item.allow_pdep_route))
            if entry.item.elementary_high_p:
                f.write('    elementary_high_p = {0!r},\n'.format(entry.item.elementary_high_p))
            if entry.item.allow_max_rate_violation:
                f.write('    allow_max_rate_violation = {0!r},\n'.format(entry.item.allow_max_rate_violation))
    #Entries for groups with have a group or logicNode for its item
    elif isinstance(entry.item, Group):
        f.write('    group = \n')
        f.write('"""\n')
        f.write(entry.item.toAdjacencyList())
        f.write('""",\n')
    elif isinstance(entry.item, LogicNode):
        f.write('    group = "{0}",\n'.format(entry.item))
    else:
        raise DatabaseError("Encountered unexpected item of type {0} while saving database.".format(entry.item.__class__))

    # Write kinetics
    if isinstance(entry.data, str):
        f.write('    kinetics = "{0}",\n'.format(entry.data))
    elif entry.data is not None:
        efficiencies = None
        if hasattr(entry.data, 'efficiencies'):
            efficiencies = entry.data.efficiencies
            entry.data.efficiencies = dict(sortEfficiencies(entry.data.efficiencies))
        kinetics = prettify(repr(entry.data))
        kinetics = '    kinetics = {0},\n'.format(kinetics.replace('\n', '\n    '))
        f.write(kinetics)
        if hasattr(entry.data, 'efficiencies'):
            entry.data.efficiencies = efficiencies
    else:
        f.write('    kinetics = None,\n')
            
    # Write reference
    if entry.reference is not None:
        reference = entry.reference.toPrettyRepr()
        lines = reference.splitlines()
        f.write('    reference = {0}\n'.format(lines[0]))
        for line in lines[1:-1]:
            f.write('    {0}\n'.format(line))
        f.write('    ),\n'.format(lines[0]))
    
    if entry.referenceType != "":
        f.write('    referenceType = "{0}",\n'.format(entry.referenceType))
    if entry.rank is not None:
        f.write('    rank = {0},\n'.format(entry.rank))
        
    if entry.shortDesc.strip() !='':
        f.write('    shortDesc = u"""')
        try:
            f.write(entry.shortDesc.encode('utf-8'))
        except:
            f.write(entry.shortDesc.strip().encode('ascii', 'ignore')+ "\n")
        f.write('""",\n')
    
    if entry.longDesc.strip() !='':
        f.write('    longDesc = \n')
        f.write('u"""\n')
        try:
            f.write(entry.longDesc.strip().encode('utf-8') + "\n")
        except:
            f.write(entry.longDesc.strip().encode('ascii', 'ignore')+ "\n")
        f.write('""",\n')

    f.write(')\n\n')
Exemplo n.º 12
0
    def parse(self):
        """
        Parse QChem output file and crate the variables the sampling job needed.
        """
        Log = QChemLog(self.input_file)

        # Load force constant matrix
        self.hessian = Log.load_force_constant_matrix()

        # Load cartesian coordinate
        coordinates, number, mass = Log.load_geometry()

        # Create conformer class
        self.conformer, unscaled_frequencies = Log.load_conformer()

        # Define the sampling protocol
        if self.protocol is None:
            self.protocol = 'UMN'

        # Extract spin miltiplicity and number of optical isomers
        if self.spin_multiplicity is None:
            self.spin_multiplicity = self.conformer.spin_multiplicity

        # Extract net charge from QChem output file
        if self.charge is None:
            self.charge = Log.charge

        # Determine wheteher `UNRESTRICTED` variable should be used or not in QChem calculation
        self.unrestricted = Log.is_unrestricted()

        # Log some information related to QM/MM system
        self.is_QM_MM_INTERFACE = Log.is_QM_MM_INTERFACE()
        if self.is_QM_MM_INTERFACE:
            self.QM_ATOMS = Log.get_QM_ATOMS()
            self.ISOTOPES = Log.get_ISOTOPES()
            self.nHcap = len(self.ISOTOPES)
            self.force_field_params = Log.get_force_field_params()
            self.opt = Log.get_opt()
            self.fixed_molecule_string = Log.get_fixed_molecule()
            self.QM_USER_CONNECT = Log.get_QM_USER_CONNECT()
            self.QM_mass = Log.QM_mass
            self.QM_coord = Log.QM_coord
            self.natom = len(self.QM_ATOMS) + len(self.ISOTOPES)
            self.symbols = Log.QM_atom
            self.cart_coords = self.QM_coord.reshape(-1, )
            self.conformer.coordinates = (self.QM_coord, "angstroms")
            self.conformer.number = number[:self.natom]
            self.conformer.mass = (self.QM_mass, "amu")
            xyz = ''
            for i in range(len(self.QM_ATOMS)):
                if self.QM_USER_CONNECT[i].endswith('0  0  0  0'):
                    xyz += '{}\t{}\t\t{}\t\t{}'.format(
                        self.symbols[i], self.cart_coords[3 * i],
                        self.cart_coords[3 * i + 1],
                        self.cart_coords[3 * i + 2])
                    if i != self.natom - 1: xyz += '\n'
            self.xyz = xyz
            if self.ncpus is None:
                raise InputError('Lack of defining the number of cpu used.')
            self.zpe = Log.load_zero_point_energy()
            if self.addcart is None and self.addtr is None and self.add_interfragment_bonds is None:
                self.addtr = True
        else:
            self.nHcap = 0
            self.natom = Log.get_number_of_atoms()
            self.symbols = [symbol_by_number[i] for i in number]
            self.cart_coords = coordinates.reshape(-1, )
            self.conformer.coordinates = (coordinates, "angstroms")
            self.conformer.number = number
            self.conformer.mass = (mass, "amu")
            self.xyz = getXYZ(self.symbols, self.cart_coords)
            if self.ncpus is None:
                raise InputError('Lack of defining the number of cpu used.')
            self.zpe = Log.load_zero_point_energy()

        # Determine whether or not the species is linear from its 3D coordinates
        self.linearity = is_linear(self.conformer.coordinates.value)

        # Determine hindered rotors information
        if self.protocol == 'UMVT':
            if self.rotors is not None:
                logging.info('Find user defined rotors...')
                self.rotors_dict = self.rotors
            else:
                logging.info('Determing the rotors of {}...'.format(
                    self.label))
                self.rotors_dict = self.get_rotors_dict()
            if self.rotors_dict == {}:
                logging.info(
                    'No internal rotations are found for {label}'.format(
                        label=self.label))
            else:
                logging.info('==========================================')
                logging.info('              Hindered Rotors             ')
                logging.info('==========================================')
                logging.info(prettify(str(self.rotors_dict)))
                logging.info('-----------------------------------------\n')
            self.n_rotors = len(self.rotors_dict)
        elif self.protocol == 'UMN':
            self.rotors_dict = []
            self.n_rotors = 0
        else:
            raise InputError(
                'The protocol of {protocol} is invalid. Please use UMVT or UMN.'
                .format(protocol=self.protocol))

        # Determine whether this system is QM/MM system
        if self.is_QM_MM_INTERFACE:
            self.nmode = 3 * len(Log.get_QM_ATOMS()) - (1 if self.is_ts else 0)
            self.n_vib = 3 * len(Log.get_QM_ATOMS()) - self.n_rotors - (
                1 if self.is_ts else 0)
        else:
            self.nmode = 3 * self.natom - (5 if self.linearity else
                                           6) - (1 if self.is_ts else 0)
            self.n_vib = 3 * self.natom - (
                5 if self.linearity else 6) - self.n_rotors - (1 if self.is_ts
                                                               else 0)

        # Create RedundantCoords object
        if self.is_ts and self.addcart is None and self.addtr is None and self.add_interfragment_bonds is None:
            self.addcart = True
        self.internal = get_RedundantCoords(
            self.label,
            self.symbols,
            self.cart_coords / BOHR2ANG,
            self.bond_factor,
            nHcap=self.nHcap,
            add_hrdrogen_bonds=False,
            addcart=self.addcart,
            addtr=self.addtr,
            add_interfragment_bonds=self.add_interfragment_bonds)

        # Create RedundantCoords object for torsional mode
        if self.protocol == 'UMVT':
            self.torsion_internal = get_RedundantCoords(
                self.label,
                self.symbols,
                self.cart_coords / BOHR2ANG,
                self.bond_factor,
                self.rotors_dict,
                self.nHcap,
                add_hrdrogen_bonds=False,
                addcart=False,
                addtr=False,
                add_interfragment_bonds=True)

        # Extract imaginary frequency from transition state
        if self.is_ts:
            self.imaginary_frequency = Log.load_negative_frequency()

        # Determine max_loop
        if self.nnl is not None:
            self.max_nloop = int(1 / self.step_size_factor) * self.nnl
        else:
            self.max_nloop = 200

        # The basis used in freq job, which will be used in OptVib job
        self.freq_basis, self.freq_gen_basis = Log.get_basis()
Exemplo n.º 13
0
    def save(self, outputFile):
        
        logging.info('Saving pressure dependence results for network {0}...'.format(self.network.label))
        f = open(outputFile, 'a')
        f_chemkin = open(os.path.join(os.path.dirname(outputFile), 'chem.inp'), 'a')
    
        Nreac = self.network.Nisom + self.network.Nreac
        Nprod = Nreac + self.network.Nprod
        Tlist = self.Tlist.value_si
        Plist = self.Plist.value_si
        Tcount = Tlist.shape[0]
        Pcount = Plist.shape[0]

        f.write("#Thermo used:  \n")
        spcs = []
        for rxn in self.network.pathReactions:
            spcs.extend(rxn.reactants)
            spcs.extend(rxn.products)
        for spc in spcs:
            if spc.thermo:
                f.write("#"+spc.label+"  SMILES: "+spc.molecule[0].toSMILES()+"\n")
                f.write("#"+spc.thermo.comment+"\n")
        f.write("\n#Path Reactions used:  \n")
        for rxn in self.network.pathReactions:
            if rxn.kinetics:
                f.write("#"+str(rxn)+"\n")
                for s in rxn.kinetics.comment.split("\n"):
                    f.write("#"+s+"\n")
        f.write("\n")

        count = 0
        printed_reactions = [] # list of rxns already printed
        for prod in range(Nprod):
            for reac in range(Nreac):
                if reac == prod: continue
                reaction = self.network.netReactions[count]
                count += 1
                # make sure we aren't double counting any reactions
                if not any([reaction.isIsomorphic(other_rxn,checkOnlyLabel=True) \
                            for other_rxn in printed_reactions]):
                    duplicate = False
                    # add reaction to printed reaction
                    printed_reactions.append(reaction)
                else:
                    # comment out the extra reverse reaction
                    duplicate = True

                # write chemkin output.
                string = writeKineticsEntry(reaction, speciesList=None, verbose=False, commented = duplicate)
                f_chemkin.write('{0}\n'.format(string))

                # write to 'output.py'
                kdata = self.K[:,:,prod,reac].copy()
                order = len(reaction.reactants)
                kdata *= 1e6 ** (order-1)
                kunits = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[order]
                
                f.write('#   =========== ')
                f.write('=========== ' * Pcount)
                f.write('\n')
                f.write('#         T \ P ')
                f.write(' '.join(['{0:11.3e}'.format(P*1e-5) for P in Plist]))
                f.write('\n')
                f.write('#   =========== ')
                f.write('=========== ' * Pcount)
                f.write('\n')
                
                for t in range(Tcount):
                    f.write('#   {0:11g}'.format(Tlist[t]))
                    for p in range(Pcount):
                        f.write(' {0:11.3e}'.format(kdata[t,p]))
                    f.write('\n')
                
                f.write('#   =========== ')
                f.write('=========== ' * Pcount)
                f.write('\n')
                
                string = 'pdepreaction(reactants={0!r}, products={1!r}, kinetics={2!r})'.format(
                    [reactant.label for reactant in reaction.reactants],
                    [product.label for product in reaction.products],
                    reaction.kinetics,
                )
                pdep_function = '{0}\n\n'.format(prettify(string))
                if duplicate:
                    # add comments to the start of the string
                    pdep_function = '#   ' + pdep_function.replace('\n','\n#   ')
                f.write(pdep_function)

        f.close()
        f_chemkin.close()