def removeSpeciesFromEdge(self, spec): """ Remove species `spec` from the reaction model edge. """ # remove the species self.edge.species.remove(spec) # identify any reactions it's involved in rxnList = [] for rxn in self.edge.reactions: if spec in rxn.reactants or spec in rxn.products: rxnList.append(rxn) # remove those reactions for rxn in rxnList: self.edge.reactions.remove(rxn) # Remove the species from any unirxn networks it is in if settings.unimolecularReactionNetworks: networksToDelete = [] for network in self.unirxnNetworks: if spec in network.getSpeciesList(): # Delete all path reactions involving the species rxnList = [] for rxn in network.pathReactions: if spec in rxn.reactants or spec in rxn.products: rxnList.append(rxn) for rxn in rxnList: network.pathReactions.remove(rxn) # Delete all net reactions involving the species rxnList = [] for rxn in network.netReactions: if spec in rxn.reactants or spec in rxn.products: rxnList.append(rxn) for rxn in rxnList: network.netReactions.remove(rxn) # Delete all isomers involving the species isomerList = [] for isomer in network.isomers: if spec in isomer.species: isomerList.append(isomer) for isomer in isomerList: network.isomers.remove(isomer) # If no remaining reactions, delete the network (actually # add to list of networks to be deleted in a subsequent # step) if len(network.pathReactions) == 0 and len(network.netReactions) == 0: networksToDelete.append(network) # Complete deletion of empty networks for network in networksToDelete: logging.debug('Deleting empty unirxn network %s' % network.id) self.unirxnNetworks.remove(network) # remove from the global list of species, to free memory species.speciesList.remove(spec)
def updateUnimolecularReactionNetworks(self): """ Iterate through all of the currently-existing unimolecular reaction networks, updating those that have been marked as invalid. In each update, the phenomonological rate coefficients :math:`k(T,P)` are computed for each net reaction in the network, and the resulting reactions added or updated. """ from unirxn.network import Isomer, UnirxnNetworkException from reaction import PDepReaction from kinetics import ChebyshevKinetics, PDepArrheniusKinetics count = sum([1 for network in self.unirxnNetworks if not network.valid]) logging.info('Updating %i modified unimolecular reaction networks...' % count) for network in self.unirxnNetworks: if not network.valid: logging.verbose('Updating unimolecular reaction network %s' % network.id) # Other inputs method, Tlist, Plist, grainSize, numGrains, model = settings.unimolecularReactionNetworks network.bathGas = [spec for spec in self.core.species if not spec.reactive][0] network.bathGas.expDownParam = 4.86 * 4184 # Generate isomers for reaction in network.pathReactions: # Create isomer for the reactant isomer = None for isom in network.isomers: if all([spec in isom.species for spec in reaction.reactants]): isomer = isom if isomer is None: isomer = Isomer(reaction.reactants) network.isomers.append(isomer) reaction.reactant = isomer # Create isomer for the product isomer = None for isom in network.isomers: if all([spec in isom.species for spec in reaction.products]): isomer = isom if isomer is None: isomer = Isomer(reaction.products) network.isomers.append(isomer) reaction.product = isomer # Update list of explored isomers to include all species in core for isom in network.isomers: if isom.isUnimolecular(): spec = isom.species[0] if spec not in network.explored: if spec in self.core.species: network.explored.append(spec) # Remove any isomers that aren't found in any path reactions # Ideally this block of code wouldn't be needed, but it's here # just in case isomerList = [] for isomer in network.isomers: found = False for reaction in network.pathReactions: if reaction.reactant is isomer or reaction.product is isomer: found = True break if not found: isomerList.append(isomer) if len(isomerList) > 0: logging.debug('Removed %i isomer(s) from network %i.' % (len(isomerList), network.id)) for isomer in isomerList: network.isomers.remove(isomer) # Sort isomers so that all unimolecular isomers come first isomers = [isom for isom in network.isomers if isom.isUnimolecular()] isomers.extend([isom for isom in network.isomers if isom.isMultimolecular()]) network.isomers = isomers # Get list of species in network speciesList = network.getSpeciesList() # Calculate ground-state energy of all species in network # For now we assume that this is equal to the enthalpy of formation # of the species for spec in speciesList: spec.E0 = spec.getEnthalpy(T=298) # Determine isomer ground-state energies for isomer in network.isomers: isomer.E0 = sum([spec.E0 for spec in isomer.species]) # Determine transition state ground-state energies of the reactions for reaction in network.pathReactions: E0 = sum([spec.E0 for spec in reaction.reactants]) reaction.E0 = E0 + reaction.kinetics[0].getActivationEnergy(reaction.getEnthalpyOfReaction(T=298)) # Shift network such that lowest-energy isomer has a ground state of 0.0 network.shiftToZeroEnergy() # Determine energy grains Elist = network.determineEnergyGrains(grainSize, numGrains, max(Tlist)) # Calculate density of states for all isomers in network network.calculateDensitiesOfStates(Elist) # Determine phenomenological rate coefficients K = network.calculateRateCoefficients(Tlist, Plist, Elist, method) # Generate PDepReaction objects for i, product in enumerate(network.isomers): for j, reactant in enumerate(network.isomers[0:i]): if numpy.any(K[:,:,i,j]): if not numpy.all(K[:,:,i,j]): raise UnirxnNetworkException('Zero rate coefficient encountered while updating network %s.' % network) # Find the path reaction netReaction = None for r in network.netReactions: if r.hasTemplate(reactant.species, product.species): netReaction = r # If path reaction does not already exist, make a new one if netReaction is None: netReaction = PDepReaction(reactant.species, product.species, network, None) network.netReactions.append(netReaction) self.addReactionToEdge(netReaction) # Set its kinetics using interpolation model if model[0].lower() == 'chebyshev': modelType, degreeT, degreeP = model chebyshev = ChebyshevKinetics() chebyshev.fitToData(Tlist, Plist, K[:,:,i,j], degreeT, degreeP) netReaction.kinetics = chebyshev elif model.lower() == 'pdeparrhenius': pDepArrhenius = PDepArrheniusKinetics() pDepArrhenius.fitToData(Tlist, Plist, K[:,:,i,j]) netReaction.kinetics = pDepArrhenius else: pass # Update cantera if this is a core reaction if netReaction in self.core.reactions: netReaction.toCantera() for spec in speciesList: del spec.E0 for reaction in network.pathReactions: del reaction.reactant del reaction.product del reaction.E0 network.valid = True