Beispiel #1
0
    def getKinetics(self):
        """
        Extracts the kinetic data from the chemkin file for plotting purposes.
        """
        from rmgpy.chemkin import loadChemkinFile
        from rmgpy.kinetics import ArrheniusEP, Chebyshev
        from rmgpy.reaction import Reaction
        from rmgpy.data.base import Entry

        kineticsDataList = []
        chemkinPath = self.path + "/chemkin/chem.inp"
        dictionaryPath = self.path + "RMG_Dictionary.txt"
        speciesList, reactionList = loadChemkinFile(chemkinPath, dictionaryPath)

        for reaction in reactionList:
            # If the kinetics are ArrheniusEP, replace them with Arrhenius
            if isinstance(reaction.kinetics, ArrheniusEP):
                reaction.kinetics = reaction.kinetics.toArrhenius(reaction.getEnthalpyOfReaction(298))

            reactants = " + ".join([moleculeToInfo(reactant) for reactant in reaction.reactants])
            arrow = "⇔" if reaction.reversible else "→"
            products = " + ".join([moleculeToInfo(reactant) for reactant in reaction.products])

            source = str(reaction).replace("<=>", "=")
            href = reaction.getURL()
            entry = Entry()
            entry.result = reactionList.index(reaction) + 1
            forwardKinetics = reaction.kinetics
            forward = True
            chemkin = reaction.toChemkin(speciesList)

            reverseKinetics = reaction.generateReverseRateCoefficient()
            reverseKinetics.comment = "Fitted reverse reaction. " + reaction.kinetics.comment

            rev_reaction = Reaction(reactants=reaction.products, products=reaction.reactants, kinetics=reverseKinetics)
            chemkin_rev = rev_reaction.toChemkin(speciesList)

            kineticsDataList.append(
                [
                    reactants,
                    arrow,
                    products,
                    entry,
                    forwardKinetics,
                    source,
                    href,
                    forward,
                    chemkin,
                    reverseKinetics,
                    chemkin_rev,
                ]
            )

        return kineticsDataList
Beispiel #2
0
    def getKinetics(self):
        """
        Extracts the kinetic data from the chemkin file for plotting purposes.
        """
        from rmgpy.chemkin import loadChemkinFile
        from rmgpy.kinetics import ArrheniusEP, Chebyshev
        from rmgpy.reaction import Reaction
        from rmgpy.data.base import Entry
        
        kineticsDataList = []    
        chemkinPath= self.path + '/chemkin/chem.inp'
        dictionaryPath = self.path + 'RMG_Dictionary.txt' 
        if self.Foreign:
            readComments = False
        else:
            readComments = True
        if os.path.exists(dictionaryPath):
            speciesList, reactionList = loadChemkinFile(chemkinPath, dictionaryPath, readComments=readComments)
        else:
            speciesList, reactionList = loadChemkinFile(chemkinPath, readComments=readComments)
            
        for reaction in reactionList:            
            # If the kinetics are ArrheniusEP, replace them with Arrhenius
            if isinstance(reaction.kinetics, ArrheniusEP):
                reaction.kinetics = reaction.kinetics.toArrhenius(reaction.getEnthalpyOfReaction(298))

            if os.path.exists(dictionaryPath):
                reactants = ' + '.join([moleculeToInfo(reactant) for reactant in reaction.reactants])
                arrow = '&hArr;' if reaction.reversible else '&rarr;'
                products = ' + '.join([moleculeToInfo(product) for product in reaction.products])
                href = reaction.getURL()
            else:
                reactants = ' + '.join([reactant.label for reactant in reaction.reactants])
                arrow = '&hArr;' if reaction.reversible else '&rarr;'
                products = ' + '.join([product.label for product in reaction.products])
                href = ''
                
            source = str(reaction).replace('<=>','=')
            entry = Entry()   
            entry.result = reactionList.index(reaction)+1
            forwardKinetics = reaction.kinetics     
            forward = True
            chemkin = reaction.toChemkin(speciesList)
            
            reverseKinetics = reaction.generateReverseRateCoefficient()
            reverseKinetics.comment = 'Fitted reverse reaction. ' + reaction.kinetics.comment
            
            rev_reaction = Reaction(reactants = reaction.products, products = reaction.reactants, kinetics = reverseKinetics)
            chemkin_rev = rev_reaction.toChemkin(speciesList)
            
            kineticsDataList.append([reactants, arrow, products, entry, forwardKinetics, source, href, forward, chemkin, reverseKinetics, chemkin_rev])

        return kineticsDataList
Beispiel #3
0
    def loadOld(self, path):
        """
        Load an old-style RMG kinetics library from the location `path`.
        """
        path = os.path.abspath(path)

        self.loadOldDictionary(
            os.path.join(path, 'species.txt'), pattern=False)
        species = dict([(label, Species(label=label, molecule=[entry.item]))
                        for label, entry in self.entries.iteritems()])

        # Add common bath gases (Ar, Ne, He, N2) if not already present
        for label, smiles in [('Ar', '[Ar]'), ('He', '[He]'), ('Ne', '[Ne]'),
                              ('N2', 'N#N')]:
            if label not in species:
                molecule = Molecule().fromSMILES(smiles)
                spec = Species(label=label, molecule=[molecule])
                species[label] = spec

        reactions = []
        reactions.extend(
            self.__loadOldReactions(
                os.path.join(path, 'reactions.txt'), species))
        if os.path.exists(os.path.join(path, 'pdepreactions.txt')):
            pdep_reactions = self.__loadOldReactions(
                os.path.join(path, 'pdepreactions.txt'), species)
            # RMG-Py likes otherwise equivalent PDep and non-pdep reactions to be marked as duplicates
            self.markValidDuplicates(reactions, pdep_reactions)
            reactions.extend(pdep_reactions)

        self.entries = {}
        for index, reaction in enumerate(reactions):
            entry = Entry(
                index=index + 1,
                item=reaction,
                data=reaction.kinetics,
            )
            entry.longDesc = reaction.kinetics.comment
            reaction.kinetics.comment = ''
            self.entries[index + 1] = entry
            reaction.kinetics = None

        self.checkForDuplicates()
        self.convertDuplicatesToMulti()
                                 label = species.label,
                                 molecule = species.molecule[0].toAdjacencyList(removeH = removeH),
                                 thermo = species.thermo,
                                 shortDesc = species.thermo.comment
        )                
     else:
         logging.warning('Species {0} did not contain any thermo data and was omitted from the thermo library.'.format(str(species)))
                     
 # load kinetics library entries                    
 kineticsLibrary = KineticsLibrary()
 kineticsLibrary.entries = {}
 for i in range(len(reactionList)):
     reaction = reactionList[i]        
     entry = Entry(
             index = i+1,
             item = reaction,
             data = reaction.kinetics,
         )
     entry.longDesc = reaction.kinetics.comment
     kineticsLibrary.entries[i+1] = entry
 
 kineticsLibrary.checkForDuplicates()
 kineticsLibrary.convertDuplicatesToMulti()
     
 # Assign history to all entries
 user = getUsername()    # Pulls username from current git repository
 #user = '******'.format(name, email)   # If not in git repository, then enter user information manually
 event = [time.asctime(),user,'action','{0} imported this entry from the old RMG database.'.format(user)]
 for label, entry in thermoLibrary.entries.iteritems():
     entry.history.append(event)
 for label, entry in kineticsLibrary.entries.iteritems():
Beispiel #5
0
def kineticsGroupEstimateEntry(
    request, family, reactant1, product1, reactant2="", reactant3="", product2="", product3=""
):
    """
    View a kinetics group estimate as an entry.
    """
    # Load the kinetics database if necessary
    loadDatabase("kinetics", "families")
    # Also load the thermo database so we can generate reverse kinetics if necessary
    loadDatabase("thermo")

    # we need 'database' to reference the top level object that we pass to generateReactions
    from tools import database

    # check the family exists
    try:
        getKineticsDatabase("families", family + "/groups")
    except ValueError:
        raise Http404

    reactantList = []
    reactantList.append(moleculeFromURL(reactant1))
    if reactant2 != "":
        reactantList.append(moleculeFromURL(reactant2))
    if reactant3 != "":
        reactantList.append(moleculeFromURL(reactant3))

    productList = []
    productList.append(moleculeFromURL(product1))
    if product2 != "":
        productList.append(moleculeFromURL(product2))
    if product3 != "":
        productList.append(moleculeFromURL(product3))

    # Search for the corresponding reaction(s)
    reactionList, empty_list = generateReactions(database, reactantList, productList, only_families=[family])

    kineticsDataList = []

    # discard all the rates from depositories and rules
    reactionList = [reaction for reaction in reactionList if isinstance(reaction, TemplateReaction)]

    # if there are still two, only keep the forward direction
    if len(reactionList) == 2:
        reactionList = [reaction for reaction in reactionList if reactionHasReactants(reaction, reactantList)]

    assert len(reactionList) == 1, "Was expecting one group estimate rate, not {0}".format(len(reactionList))
    reaction = reactionList[0]

    # Generate the thermo data for the species involved
    for reactant in reaction.reactants:
        generateSpeciesThermo(reactant, database)
    for product in reaction.products:
        generateSpeciesThermo(product, database)

    # If the kinetics are ArrheniusEP, replace them with Arrhenius
    if isinstance(reaction.kinetics, ArrheniusEP):
        reaction.kinetics = reaction.kinetics.toArrhenius(reaction.getEnthalpyOfReaction(298))

    reactants = " + ".join([moleculeToInfo(reactant) for reactant in reaction.reactants])
    arrow = "&hArr;" if reaction.reversible else "&rarr;"
    products = " + ".join([moleculeToInfo(reactant) for reactant in reaction.products])
    assert isinstance(reaction, TemplateReaction), "Expected group additive kinetics to be a TemplateReaction"

    source = "%s (RMG-Py Group additivity)" % (reaction.family.name)
    entry = Entry(
        item=reaction,
        data=reaction.kinetics,
        longDesc=reaction.kinetics.comment,
        shortDesc="Estimated by RMG-Py Group Additivity",
    )

    # Get the entry as a entry_string, to populate the New Entry form
    # first, replace the kinetics with a fitted arrhenius form with no comment
    entry.data = reaction.kinetics.toArrhenius()
    entry.data.comment = ""
    entry_buffer = StringIO.StringIO(u"")
    rmgpy.data.kinetics.saveEntry(entry_buffer, entry)
    entry_string = entry_buffer.getvalue()
    entry_buffer.close()
    # replace the kinetics with the original ones
    entry.data = reaction.kinetics
    entry_string = re.sub("^entry\(\n", "", entry_string)  # remove leading entry(
    entry_string = re.sub("\s*index = -?\d+,\n", "", entry_string)  # remove the 'index = 23,' (or -1)line
    entry_string = re.sub(
        "\s+history = \[.*", "", entry_string, flags=re.DOTALL
    )  # remove the history and everything after it (including the final ')' )
    new_entry_form = KineticsEntryEditForm(initial={"entry": entry_string})

    forwardKinetics = reaction.kinetics
    reverseKinetics = reaction.generateReverseRateCoefficient()

    forward = reactionHasReactants(reaction, reactantList)  # boolean: true if template reaction in forward direction

    reactants = " + ".join([moleculeToInfo(reactant) for reactant in reaction.reactants])
    products = " + ".join([moleculeToInfo(reactant) for reactant in reaction.products])
    reference = rmgpy.data.reference.Reference(
        url=request.build_absolute_uri(
            reverse(kinetics, kwargs={"section": "families", "subsection": family + "/groups"})
        )
    )
    referenceType = ""
    entry.index = -1

    reactionUrl = getReactionUrl(reaction)

    return render_to_response(
        "kineticsEntry.html",
        {
            "section": "families",
            "subsection": family,
            "databaseName": family,
            "entry": entry,
            "reactants": reactants,
            "arrow": arrow,
            "products": products,
            "reference": reference,
            "referenceType": referenceType,
            "kinetics": reaction.kinetics,
            "reactionUrl": reactionUrl,
            "reaction": reaction,
            "new_entry_form": new_entry_form,
        },
        context_instance=RequestContext(request),
    )
    def getLibraries(self):

        name = 'kineticsjobs'
                
        speciesList = self.speciesDict.values()
        reactionList = self.reactionDict.values()

        # remove duplicate species
        for rxn in reactionList:
            for i,rspc in enumerate(rxn.reactants):
                for spc in speciesList:
                    if spc.isIsomorphic(rspc):
                        rxn.reactants[i] = spc
                        break
            for i,rspc in enumerate(rxn.products):
                for spc in speciesList:
                    if spc.isIsomorphic(rspc):
                        rxn.products[i] = spc
                        break
        del_inds = []
        for i,spc1 in enumerate(speciesList):
            for j,spc2 in enumerate(speciesList):
                if j>i and spc1.isIsomorphic(spc2):
                    del_inds.append(j)
        
        for j in sorted(del_inds)[::-1]:
            del speciesList[j]
            
        thermoLibrary = ThermoLibrary(name=name)
        for i,species in enumerate(speciesList): 
            if species.thermo:
                thermoLibrary.loadEntry(index = i + 1,
                                        label = species.label,
                                        molecule = species.molecule[0].toAdjacencyList(),
                                        thermo = species.thermo,
                                        shortDesc = species.thermo.comment
               )                
            else:
                logging.warning('Species {0} did not contain any thermo data and was omitted from the thermo library.'.format(str(species)))

        # load kinetics library entries                    
        kineticsLibrary = KineticsLibrary(name=name,autoGenerated=True)
        kineticsLibrary.entries = {}
        for i,reaction in enumerate(reactionList):      
            entry = Entry(
                    index = i+1,
                    label = reaction.toLabeledStr(),
                    item = reaction,
                    data = reaction.kinetics,
                )

            if reaction.kinetics is not None:
                if hasattr(reaction,'library') and reaction.library:
                    entry.longDesc = 'Originally from reaction library: ' +\
                                     reaction.library + "\n" + reaction.kinetics.comment
                else:
                    entry.longDesc = reaction.kinetics.comment
            
            kineticsLibrary.entries[i+1] = entry
        
        kineticsLibrary.label = name
        
        return thermoLibrary,kineticsLibrary,speciesList
Beispiel #7
0
    def loadEntry(
        self,
        index,
        group1=None,
        group2=None,
        group3=None,
        group4=None,
        kinetics=None,
        degeneracy=1,
        label='',
        duplicate=False,
        reversible=True,
        reference=None,
        referenceType='',
        shortDesc='',
        longDesc='',
        rank=None,
    ):

        reactants = []

        if group1[0:3].upper() == 'OR{' or group1[0:4].upper(
        ) == 'AND{' or group1[0:7].upper() == 'NOT OR{' or group1[0:8].upper(
        ) == 'NOT AND{':
            reactants.append(makeLogicNode(group1))
        else:
            reactants.append(Group().fromAdjacencyList(group1))
        if group2 is not None:
            if group2[0:3].upper() == 'OR{' or group2[0:4].upper(
            ) == 'AND{' or group2[0:7].upper(
            ) == 'NOT OR{' or group2[0:8].upper() == 'NOT AND{':
                reactants.append(makeLogicNode(group2))
            else:
                reactants.append(Group().fromAdjacencyList(group2))
        if group3 is not None:
            if group3[0:3].upper() == 'OR{' or group3[0:4].upper(
            ) == 'AND{' or group3[0:7].upper(
            ) == 'NOT OR{' or group3[0:8].upper() == 'NOT AND{':
                reactants.append(makeLogicNode(group3))
            else:
                reactants.append(Group().fromAdjacencyList(group3))
        if group4 is not None:
            if group4[0:3].upper() == 'OR{' or group4[0:4].upper(
            ) == 'AND{' or group4[0:7].upper(
            ) == 'NOT OR{' or group4[0:8].upper() == 'NOT AND{':
                reactants.append(makeLogicNode(group4))
            else:
                reactants.append(Group().fromAdjacencyList(group4))

        reaction = Reaction(reactants=reactants, products=[])

        entry = Entry(
            index=index,
            label=label,
            item=reaction,
            data=kinetics,
            reference=reference,
            referenceType=referenceType,
            shortDesc=shortDesc,
            longDesc=longDesc.strip(),
            rank=rank,
        )
        try:
            self.entries[label].append(entry)
        except KeyError:
            self.entries[label] = [entry]
        return entry
Beispiel #8
0
    def fillRulesByAveragingUp(self, rootTemplate, alreadyDone):
        """
        Fill in gaps in the kinetics rate rules by averaging child nodes.
        """
        rootLabel = ';'.join([g.label for g in rootTemplate])

        if rootLabel in alreadyDone:
            return alreadyDone[rootLabel]

        # See if we already have a rate rule for this exact template
        entry = self.getRule(rootTemplate)
        if entry is not None and entry.rank > 0:
            # We already have a rate rule for this exact template
            # If the entry has rank of zero, then we have so little faith
            # in it that we'd rather use an averaged value if possible
            # Since this entry does not have a rank of zero, we keep its
            # value
            alreadyDone[rootLabel] = entry.data
            return entry.data

        # Recursively descend to the child nodes
        childrenList = [[group] for group in rootTemplate]
        for group in childrenList:
            parent = group.pop(0)
            if len(parent.children) > 0:
                group.extend(parent.children)
            else:
                group.append(parent)

        childrenList = getAllCombinations(childrenList)
        kineticsList = []
        for template in childrenList:
            label = ';'.join([g.label for g in template])
            if template == rootTemplate:
                continue

            if label in alreadyDone:
                kinetics = alreadyDone[label]
            else:
                kinetics = self.fillRulesByAveragingUp(template, alreadyDone)

            if kinetics is not None:
                kineticsList.append([kinetics, template])

        if len(kineticsList) > 0:

            # We found one or more results! Let's average them together
            kinetics = self.__getAverageKinetics([k for k, t in kineticsList])
            kinetics.comment += 'Average of ({0}). '.format(
                ' + '.join([
                    k.comment
                    if k.comment != '' else ','.join([g.label for g in t])
                    for k, t in kineticsList
                ]), )
            entry = Entry(
                index=0,
                label=rootLabel,
                item=rootTemplate,
                data=kinetics,
                rank=10,  # Indicates this is an averaged estimate
            )
            self.entries[entry.label] = [entry]
            alreadyDone[rootLabel] = entry.data
            return entry.data

        alreadyDone[rootLabel] = None
        return None
Beispiel #9
0
                                    label = species.label,
                                    molecule = species.molecule[0].toAdjacencyList(),
                                    thermo = species.thermo,
                                    shortDesc = species.thermo.comment
           )                
        else:
            logging.warning('Species {0} did not contain any thermo data and was omitted from the thermo library.'.format(str(species)))
                        
    # load kinetics library entries                    
    kineticsLibrary = KineticsLibrary(name=name)
    kineticsLibrary.entries = {}
    for i in range(len(reactionList)):
        reaction = reactionList[i]        
        entry = Entry(
                index = i+1,
                label = str(reaction),
                item = reaction,
                data = reaction.kinetics,
            )
        try:
    	    entry.longDesc = 'Originally from reaction library: ' + reaction.library + "\n" + reaction.kinetics.comment
	except AttributeError:
    	    entry.longDesc = reaction.kinetics.comment
        kineticsLibrary.entries[i+1] = entry
    
    # Mark as duplicates where there are mixed pressure dependent and non-pressure dependent duplicate kinetics
    # Even though CHEMKIN does not require a duplicate flag, RMG needs it.
    # Using flag markDuplicates = True
    kineticsLibrary.checkForDuplicates(markDuplicates=True)
    kineticsLibrary.convertDuplicatesToMulti()

    # Save in Py format
Beispiel #10
0
def save_kinetics_lib(rxn_list, path, name, lib_long_desc):
    """
    Save an RMG kinetics library of all reactions in `rxn_list` in the supplied `path`.
    `rxn_list` is a list of ARCReaction objects.
    `name` is the library's name (or project's name).
    `long_desc` is a multiline string with level of theory description.
    """
    entries = dict()
    if rxn_list:
        for i, rxn in enumerate(rxn_list):
            if rxn.kinetics is not None:
                if len(rxn.rmg_reaction.reactants):
                    reactants = rxn.rmg_reaction.reactants
                    products = rxn.rmg_reaction.products
                elif rxn.r_species.mol_list is not None:
                    reactants = [
                        Species(molecule=arc_spc.mol_list)
                        for arc_spc in rxn.r_species
                    ]
                    products = [
                        Species(molecule=arc_spc.mol_list)
                        for arc_spc in rxn.p_species
                    ]
                elif rxn.r_species.mol is not None:
                    reactants = [
                        Species(molecule=[arc_spc.mol])
                        for arc_spc in rxn.r_species
                    ]
                    products = [
                        Species(molecule=[arc_spc.mol])
                        for arc_spc in rxn.p_species
                    ]
                else:
                    reactants = [
                        Species(molecule=[arc_spc.xyz_mol])
                        for arc_spc in rxn.r_species
                    ]
                    products = [
                        Species(molecule=[arc_spc.xyz_mol])
                        for arc_spc in rxn.p_species
                    ]
                rxn.rmg_reaction.reactants = reactants
                rxn.rmg_reaction.products = products
                entry = Entry(index=i,
                              item=rxn.rmg_reaction,
                              data=rxn.kinetics,
                              label=rxn.label)
                rxn.ts_species.make_ts_report()
                entry.longDesc = rxn.ts_species.ts_report + '\n\nOptimized TS geometry:\n' + rxn.ts_species.final_xyz
                rxn.rmg_reaction.kinetics = rxn.kinetics
                rxn.rmg_reaction.kinetics.comment = str('')
                entries[i + 1] = entry
            else:
                logger.warning(
                    'Reaction {0} did not contain any kinetic data and was omitted from the kinetics'
                    ' library.'.format(rxn.label))
        kinetics_library = KineticsLibrary(name=name,
                                           longDesc=lib_long_desc,
                                           autoGenerated=True)
        kinetics_library.entries = entries
        lib_path = os.path.join(path, 'kinetics', '')
        if os.path.exists(lib_path):
            shutil.rmtree(lib_path)
        try:
            os.makedirs(lib_path)
        except OSError:
            pass
        kinetics_library.save(os.path.join(lib_path, 'reactions.py'))
        kinetics_library.saveDictionary(
            os.path.join(lib_path, 'dictionary.txt'))
def generateAdditionalRateRules(family, database):
    """
    For a given reaction `family` label, generate additional rate rules from
    the corresponding depository training set. This function does automatically
    what users used to do by hand to construct a rate rule from reaction
    kinetics found in the literature, i.e. determine the groups involved,
    adjust to a per-site basis, etc.
    """
    
    # Find the database components we will need
    rules = database.kinetics.depository['{0}/rules'.format(family)]
    groups = database.kinetics.groups[family]
    
    index = max([entry.index for entry in rules.entries.values()]) + 1
    
    for depositoryLabel in ['training']:
        depository = database.kinetics.depository['{0}/{1}'.format(family, depositoryLabel)]
        
        entries = depository.entries.values()
        entries.sort(key=lambda x: (x.index, x.label))
        
        for entry0 in entries:
            
            reaction, template = database.kinetics.getForwardReactionForFamilyEntry(entry=entry0, family=family, thermoDatabase=database.thermo)
            
            # We must convert the kinetics to ArrheniusEP to finish our rate rule
            kinetics = reaction.kinetics
            # If kinetics are KineticsData, then first convert to Arrhenius
            if isinstance(kinetics, KineticsData):
                kinetics = Arrhenius().fitToData(
                    Tdata=kinetics.Tdata.values,
                    kdata=kinetics.kdata.values,
                    kunits=kinetics.kdata.units,
                    T0=1,
                )
            
            # Now convert from Arrhenius to ArrheniusEP
            # If not Arrhenius (or KineticsData), then skip this entry
            if isinstance(kinetics, Arrhenius):
                if kinetics.T0.value != 1:
                    kinetics.changeT0(1)
                kinetics = ArrheniusEP(
                    A = kinetics.A,
                    n = kinetics.n,
                    alpha = 0,
                    E0 = kinetics.Ea,
                    Tmin = kinetics.Tmin,
                    Tmax = kinetics.Tmax,
                )
            else:
                break
            
            # Put the kinetics on a per-site basis
            kinetics.A.value /= reaction.degeneracy
                
            # Construct a new entry for the new rate rule
            label = ';'.join([group.label for group in template])
            item = Reaction(
                reactants = template[:],
                products = None,
            )
            entry = Entry(
                index = index,
                label = label,
                item = item,
                data = kinetics,
                reference = entry0.reference,
                rank = entry0.rank,
                shortDesc = entry0.shortDesc,
                longDesc = entry0.longDesc,
                history = entry0.history,
            )

            # Add the new rate rule to the depository of rate rules
            rules.entries[entry.index] = entry
            
            index += 1
Beispiel #12
0
    def get_libraries(self):
        """Get RMG kinetics and thermo libraries"""
        name = 'kineticsjobs'

        species_list = list(self.species_dict.values())
        reaction_list = list(self.reaction_dict.values())

        # remove duplicate species
        for rxn in reaction_list:
            for i, rspc in enumerate(rxn.reactants):
                for spc in species_list:
                    if spc.is_isomorphic(rspc):
                        rxn.reactants[i] = spc
                        break
            for i, rspc in enumerate(rxn.products):
                for spc in species_list:
                    if spc.is_isomorphic(rspc):
                        rxn.products[i] = spc
                        break
        del_inds = []
        for i, spc1 in enumerate(species_list):
            for j, spc2 in enumerate(species_list):
                if j > i and spc1.is_isomorphic(spc2):
                    del_inds.append(j)

        for j in sorted(del_inds)[::-1]:
            del species_list[j]

        thermo_library = ThermoLibrary(name=name)
        for i, species in enumerate(species_list):
            if species.thermo:
                thermo_library.load_entry(
                    index=i + 1,
                    label=species.label,
                    molecule=species.molecule[0].to_adjacency_list(),
                    thermo=species.thermo,
                    shortDesc=species.thermo.comment)
            else:
                logging.warning(
                    'Species {0} did not contain any thermo data and was omitted from the thermo library.'
                    .format(str(species)))

        # load kinetics library entries
        kinetics_library = KineticsLibrary(name=name, auto_generated=True)
        kinetics_library.entries = {}
        for i, reaction in enumerate(reaction_list):
            entry = Entry(index=i + 1,
                          label=reaction.to_labeled_str(),
                          item=reaction,
                          data=reaction.kinetics)

            if reaction.kinetics is not None:
                if hasattr(reaction, 'library') and reaction.library:
                    entry.long_desc = 'Originally from reaction library: ' + \
                                      reaction.library + "\n" + reaction.kinetics.comment
                else:
                    entry.long_desc = reaction.kinetics.comment

            kinetics_library.entries[i + 1] = entry

        kinetics_library.label = name

        return thermo_library, kinetics_library, species_list
    def fillRulesByAveragingUp(self, rootTemplate, alreadyDone, verbose=False):
        """
        Fill in gaps in the kinetics rate rules by averaging child nodes.
        If verbose is set to True, then exact sources of kinetics are saved in the kinetics comments
        (warning: this uses up a lot of memory due to the extensively long comments)
        """
        rootLabel = ';'.join([g.label for g in rootTemplate])

        if rootLabel in alreadyDone:
            return alreadyDone[rootLabel]

        # Generate the distance 1 pairings which must be averaged for this root template.
        # The distance 1 template is created by taking the parent node from one or more trees
        # and creating the combinations with children from a single remaining tree.
        # i.e. for some node (A,B), we want to fetch all combinations for the pairing of (A,B's children) and
        # (A's children, B).  For node (A,B,C), we would retrieve all combinations of (A,B,C's children)
        # (A,B's children,C) etc...
        # If a particular node has no children, it is skipped from the children expansion altogether.

        childrenList = []
        distanceList = []
        for i, parent in enumerate(rootTemplate):
            # Start with the root template, and replace the ith member with its children
            if parent.children:
                childrenSet = [[group] for group in rootTemplate]
                childrenSet[i] = parent.children
                childrenList.extend(getAllCombinations(childrenSet))
                distanceList.extend([k.nodalDistance for k in parent.children])

        if distanceList != []:  #average the minimum distance neighbors
            minDist = min(distanceList)
            closeChildrenList = [
                childrenList[i] for i in xrange(len(childrenList))
                if distanceList[i] == minDist
            ]
        else:
            closeChildrenList = []

        kineticsList = []
        for template in childrenList:
            label = ';'.join([g.label for g in template])

            if label in alreadyDone:
                kinetics = alreadyDone[label]
            else:
                kinetics = self.fillRulesByAveragingUp(template, alreadyDone,
                                                       verbose)

            if template in closeChildrenList and kinetics is not None:
                kineticsList.append([kinetics, template])

        # See if we already have a rate rule for this exact template instead
        # and return it now that we have finished searching its children
        entry = self.getRule(rootTemplate)

        if entry is not None and entry.rank > 0:
            # We already have a rate rule for this exact template
            # If the entry has rank of zero, then we have so little faith
            # in it that we'd rather use an averaged value if possible
            # Since this entry does not have a rank of zero, we keep its
            # value
            alreadyDone[rootLabel] = entry.data
            return entry.data

        if len(kineticsList) > 0:

            if len(kineticsList) > 1:
                # We found one or more results! Let's average them together
                kinetics = self.__getAverageKinetics(
                    [k for k, t in kineticsList])

                if verbose:
                    kinetics.comment = 'Average of [{0}]'.format(' + '.join(
                        k.comment if k.comment != '' else ';'.join(g.label
                                                                   for g in t)
                        for k, t in kineticsList))

                else:
                    kinetics.comment = 'Average of [{0}]'.format(' + '.join(
                        ';'.join(g.label for g in t) for k, t in kineticsList))

            else:
                k, t = kineticsList[0]
                kinetics = deepcopy(k)
                # Even though we are using just a single set of kinetics, it's still considered
                # an average.  It just happens that the other distance 1 children had no data.

                if verbose:
                    kinetics.comment = 'Average of [{0}]'.format(
                        k.comment if k.comment != '' else ';'.join(g.label
                                                                   for g in t))
                else:
                    kinetics.comment = 'Average of [{0}]'.format(';'.join(
                        g.label for g in t))

            entry = Entry(
                index=0,
                label=rootLabel,
                item=rootTemplate,
                data=kinetics,
                rank=10,  # Indicates this is an averaged estimate
            )
            self.entries[entry.label] = [entry]
            alreadyDone[rootLabel] = entry.data
            return entry.data

        alreadyDone[rootLabel] = None
        return None
def generateRules(family, database):
    """
    For a given reaction `family` label, generate additional rate rules from
    the corresponding depository training set. This function does automatically
    what users used to do by hand to construct a rate rule from reaction
    kinetics found in the literature, i.e. determine the groups involved,
    adjust to a per-site basis, etc.
    """

    # Load rules and determine starting index
    rules = family.rules
    index = max([entry.index for entry in rules.entries.values()] or [0]) + 1

    # Load training entries
    for depository in family.depositories:
        if 'training' in depository.name:
            entries = sorted(depository.entries.values(),
                             key=lambda entry: (entry.index, entry.label))
            break

    # Generate a rate rule for each training entry
    for entry in entries:

        # Load entry's reaction, template, and kinetics
        reaction, template = database.kinetics.getForwardReactionForFamilyEntry(
            entry=entry, family=family.name, thermoDatabase=database.thermo)
        kinetics = reaction.kinetics

        # Convert KineticsData to Arrhenius
        if isinstance(kinetics, KineticsData):
            kinetics = Arrhenius().fitToData(Tdata=kinetics.Tdata.values,
                                             kdata=kinetics.kdata.values,
                                             kunits=kinetics.kdata.units,
                                             T0=1)

        # Ignore other kinetics types
        if not isinstance(kinetics, Arrhenius):
            continue

        # Change reference temperature to 1 K if necessary
        if kinetics.T0.value != 1:
            kinetics = kinetics.changeT0(1)

        # Convert kinetics to a per-site basis
        kinetics.A.value /= reaction.degeneracy

        # Convert to ArrheniusEP
        kinetics = ArrheniusEP(A=kinetics.A,
                               n=kinetics.n,
                               alpha=0,
                               E0=kinetics.Ea,
                               Tmin=kinetics.Tmin,
                               Tmax=kinetics.Tmax)

        # Add new rate rule
        rules.entries[index] = Entry(index=index,
                                     label=';'.join(
                                         [group.label for group in template]),
                                     item=Reaction(reactants=template[:],
                                                   products=None),
                                     data=kinetics,
                                     reference=entry.reference,
                                     rank=entry.rank,
                                     shortDesc=entry.shortDesc,
                                     longDesc=entry.longDesc,
                                     history=entry.history)
        index += 1
Beispiel #15
0
                molecule=species.molecule[0].toAdjacencyList(removeH=removeH),
                thermo=species.thermo,
                shortDesc=species.thermo.comment)
        else:
            logging.warning(
                'Species {0} did not contain any thermo data and was omitted from the thermo library.'
                .format(str(species)))

    # load kinetics library entries
    kineticsLibrary = KineticsLibrary()
    kineticsLibrary.entries = {}
    for i in range(len(reactionList)):
        reaction = reactionList[i]
        entry = Entry(
            index=i + 1,
            item=reaction,
            data=reaction.kinetics,
        )
        entry.longDesc = reaction.kinetics.comment
        kineticsLibrary.entries[i + 1] = entry

    kineticsLibrary.checkForDuplicates()
    kineticsLibrary.convertDuplicatesToMulti()

    # Assign history to all entries
    user = getUsername()  # Pulls username from current git repository
    #user = '******'.format(name, email)   # If not in git repository, then enter user information manually
    event = [
        time.asctime(), user, 'action',
        '{0} imported this entry from the old RMG database.'.format(user)
    ]
Beispiel #16
0
    def getKinetics(self):
        """
        Extracts the kinetic data from the chemkin file for plotting purposes.
        """
        from rmgpy.chemkin import loadChemkinFile
        from rmgpy.kinetics import ArrheniusEP, Chebyshev
        from rmgpy.reaction import Reaction
        from rmgpy.data.base import Entry

        kineticsDataList = []
        chemkinPath = self.path + '/chemkin/chem.inp'
        dictionaryPath = self.path + 'RMG_Dictionary.txt'
        if self.Foreign:
            readComments = False
        else:
            readComments = True
        if os.path.exists(dictionaryPath):
            speciesList, reactionList = loadChemkinFile(
                chemkinPath, dictionaryPath, readComments=readComments)
        else:
            speciesList, reactionList = loadChemkinFile(
                chemkinPath, readComments=readComments)

        for reaction in reactionList:
            # If the kinetics are ArrheniusEP, replace them with Arrhenius
            if isinstance(reaction.kinetics, ArrheniusEP):
                reaction.kinetics = reaction.kinetics.toArrhenius(
                    reaction.getEnthalpyOfReaction(298))

            if os.path.exists(dictionaryPath):
                reactants = ' + '.join([
                    moleculeToInfo(reactant) for reactant in reaction.reactants
                ])
                arrow = '&hArr;' if reaction.reversible else '&rarr;'
                products = ' + '.join(
                    [moleculeToInfo(product) for product in reaction.products])
                href = reaction.getURL()
            else:
                reactants = ' + '.join(
                    [reactant.label for reactant in reaction.reactants])
                arrow = '&hArr;' if reaction.reversible else '&rarr;'
                products = ' + '.join(
                    [product.label for product in reaction.products])
                href = ''

            source = str(reaction).replace('<=>', '=')
            entry = Entry()
            entry.result = reactionList.index(reaction) + 1
            forwardKinetics = reaction.kinetics
            forward = True
            chemkin = reaction.toChemkin(speciesList)

            reverseKinetics = reaction.generateReverseRateCoefficient()
            reverseKinetics.comment = 'Fitted reverse reaction. ' + reaction.kinetics.comment

            rev_reaction = Reaction(reactants=reaction.products,
                                    products=reaction.reactants,
                                    kinetics=reverseKinetics)
            chemkin_rev = rev_reaction.toChemkin(speciesList)

            kineticsDataList.append([
                reactants, arrow, products, entry, forwardKinetics, source,
                href, forward, chemkin, reverseKinetics, chemkin_rev
            ])

        return kineticsDataList