def execute(self, output_file, plot, file_format='pdf', print_summary=True, species_list=None, thermo_library=None, kinetics_library=None): """Execute an ExplorerJob""" logging.info('Exploring network...') rmg = RMG() rmg.species_constraints = { 'allowed': ['input species', 'seed mechanisms', 'reaction libraries'], 'maximumRadicalElectrons': self.maximum_radical_electrons, 'explicitlyAllowedMolecules': [] } rmgpy.rmg.input.rmg = rmg reaction_model = CoreEdgeReactionModel() reaction_model.pressure_dependence = self.pdepjob reaction_model.pressure_dependence.rmgmode = True if output_file: reaction_model.pressure_dependence.output_file = os.path.dirname( output_file) kinetics_database = get_db('kinetics') thermo_database = get_db('thermo') thermo_database.libraries['thermojobs'] = thermo_library thermo_database.library_order.insert(0, 'thermojobs') kinetics_database.libraries['kineticsjobs'] = kinetics_library kinetics_database.library_order.insert( 0, ('kineticsjobs', 'Reaction Library')) self.job_rxns = [rxn for rxn in reaction_model.core.reactions] if output_file is not None: if not os.path.exists( os.path.join( reaction_model.pressure_dependence.output_file, 'pdep')): os.mkdir( os.path.join( reaction_model.pressure_dependence.output_file, 'pdep')) else: shutil.rmtree( os.path.join( reaction_model.pressure_dependence.output_file, 'pdep')) os.mkdir( os.path.join( reaction_model.pressure_dependence.output_file, 'pdep')) # get the molecular formula for the network mmol = None for spc in self.source: if mmol: mmol = mmol.merge(spc.molecule[0]) else: mmol = spc.molecule[0].copy(deep=True) form = mmol.get_formula() for spec in list(self.bath_gas.keys()) + self.source: nspec, is_new = reaction_model.make_new_species(spec, reactive=False) flags = np.array([ s.molecule[0].get_formula() == form for s in reaction_model.core.species ]) reaction_model.enlarge(nspec, react_edge=False, unimolecular_react=flags, bimolecular_react=np.zeros( (len(reaction_model.core.species), len(reaction_model.core.species)))) reaction_model.add_seed_mechanism_to_core('kineticsjobs') for lib in kinetics_database.library_order: if lib[0] != 'kineticsjobs': reaction_model.add_reaction_library_to_edge(lib[0]) for spc in reaction_model.core.species: for i, item in enumerate(self.source): if spc.is_isomorphic(item): self.source[i] = spc # react initial species if len(self.source) == 1: flags = np.array([ s.molecule[0].get_formula() == form for s in reaction_model.core.species ]) biflags = np.zeros((len(reaction_model.core.species), len(reaction_model.core.species))) elif len(self.source) == 2: flags = np.array([False for s in reaction_model.core.species]) biflags = np.array( [[False for i in range(len(reaction_model.core.species))] for j in range(len(reaction_model.core.species))]) biflags[reaction_model.core.species.index(self.source[0]), reaction_model.core.species.index(self.source[1])] = True else: raise ValueError( "Reactant channels with greater than 2 reactants not supported" ) reaction_model.enlarge(react_edge=True, unimolecular_react=flags, bimolecular_react=biflags) # find the networks we're interested in networks = [] for nwk in reaction_model.network_list: if set(nwk.source) == set(self.source): self.source = nwk.source networks.append(nwk) if len(networks) == 0: raise ValueError( 'Did not generate a network with the requested source. This usually means no unimolecular ' 'reactions were generated for the source. Note that library reactions that are not ' 'properly flagged as elementary_high_p can replace RMG generated reactions that would ' 'otherwise be part of networks.') for network in networks: network.bath_gas = self.bath_gas self.networks = networks # determine T and P combinations if self.pdepjob.Tlist: t_list = self.pdepjob.Tlist.value_si else: t_list = np.linspace(self.pdepjob.Tmin.value_si, self.pdepjob.Tmax.value_si, self.pdepjob.Tcount) if self.pdepjob.Plist: p_list = self.pdepjob.Plist.value_si else: p_list = np.linspace(self.pdepjob.Pmin.value_si, self.pdepjob.Pmax.value_si, self.pdepjob.Pcount) # generate the network forbidden_structures = get_db('forbidden') incomplete = True checked_species = [] while incomplete: incomplete = False for temperature in t_list: for pressure in p_list: for network in self.networks: # compute the characteristic rate coefficient by summing all rate coefficients # from the reactant channel for spc in reaction_model.edge.species: if spc in checked_species: continue if forbidden_structures.is_molecule_forbidden( spc.molecule[0]): reaction_model.remove_species_from_edge( reaction_model.reaction_systems, spc) reaction_model.remove_empty_pdep_networks() else: checked_species.append(spc) kchar = 0.0 for rxn in network.net_reactions: # reaction_model.core.reactions+reaction_model.edge.reactions if (set(rxn.reactants) == set(self.source) and rxn.products[0].molecule[0].get_formula() == form): kchar += rxn.kinetics.get_rate_coefficient( T=temperature, P=pressure) elif (set(rxn.products) == set(self.source) and rxn.reactants[0].molecule[0].get_formula() == form): kchar += rxn.generate_reverse_rate_coefficient( network_kinetics=True ).get_rate_coefficient(T=temperature, P=pressure) if network.get_leak_coefficient( T=temperature, P=pressure) > self.explore_tol * kchar: incomplete = True spc = network.get_maximum_leak_species( T=temperature, P=pressure) logging.info( 'adding new isomer {0} to network'.format(spc)) flags = np.array([ s.molecule[0].get_formula() == form for s in reaction_model.core.species ]) reaction_model.enlarge( (network, spc), react_edge=False, unimolecular_react=flags, bimolecular_react=np.zeros( (len(reaction_model.core.species), len(reaction_model.core.species)))) flags = np.array([ s.molecule[0].get_formula() == form for s in reaction_model.core.species ]) reaction_model.enlarge( react_edge=True, unimolecular_react=flags, bimolecular_react=np.zeros( (len(reaction_model.core.species), len(reaction_model.core.species)))) for network in self.networks: rm_rxns = [] for rxn in network.path_reactions: # remove reactions with forbidden species for r in rxn.reactants + rxn.products: if forbidden_structures.is_molecule_forbidden( r.molecule[0]): rm_rxns.append(rxn) for rxn in rm_rxns: logging.info('Removing forbidden reaction: {0}'.format(rxn)) network.path_reactions.remove(rxn) # clean up output files if output_file is not None: path = os.path.join( reaction_model.pressure_dependence.output_file, 'pdep') for name in os.listdir(path): if name.endswith('.py') and '_' in name: if name.split('_')[-1].split('.')[0] != str( len(network.isomers)): os.remove(os.path.join(path, name)) else: os.rename( os.path.join(path, name), os.path.join( path, 'network_full{}.py'.format( self.networks.index(network)))) warns = [] for rxn in self.job_rxns: if rxn not in network.path_reactions: warns.append( 'Reaction {0} in the input file was not explored during network expansion and was ' 'not included in the full network. This is likely because your explore_tol value is ' 'too high.'.format(rxn)) # reduction process for network in self.networks: if self.energy_tol != np.inf or self.flux_tol != 0.0: rxn_set = None product_set = None for temperature in t_list: if self.energy_tol != np.inf: rxns = network.get_energy_filtered_reactions( temperature, self.energy_tol) if rxn_set is not None: rxn_set &= set(rxns) else: rxn_set = set(rxns) for pressure in p_list: if self.flux_tol != 0.0: products = network.get_rate_filtered_products( temperature, pressure, self.flux_tol) products = [tuple(x) for x in products] if product_set is not None: product_set &= set(products) else: product_set = set(products) if rxn_set: logging.info('removing reactions during reduction:') for rxn in rxn_set: logging.info(rxn) rxn_set = list(rxn_set) if product_set: logging.info('removing products during reduction:') for prod in product_set: logging.info([x.label for x in prod]) product_set = list(product_set) network.remove_reactions(reaction_model, rxns=rxn_set, prods=product_set) for rxn in self.job_rxns: if rxn not in network.path_reactions: warns.append( 'Reaction {0} in the input file was not included in the reduced model.' .format(rxn)) self.networks = networks for p, network in enumerate(self.networks): self.pdepjob.network = network if len(self.networks) > 1: root, file_name = os.path.split(output_file) s1, s2 = file_name.split(".") ind = str(self.networks.index(network)) stot = os.path.join(root, s1 + "{}.".format(ind) + s2) else: stot = output_file self.pdepjob.execute(stot, plot, file_format='pdf', print_summary=True) if os.path.isfile('network.pdf'): os.rename('network.pdf', 'network' + str(p) + '.pdf') if warns: logging.info('\nOUTPUT WARNINGS:\n') for w in warns: logging.warning(w)
def execute(self, outputFile, plot, format='pdf', print_summary=True, speciesList=None, thermoLibrary=None, kineticsLibrary=None): logging.info('Exploring network...') rmg = RMG() rmg.speciesConstraints = { 'allowed': ['input species', 'seed mechanisms', 'reaction libraries'], 'maximumRadicalElectrons': self.maximumRadicalElectrons, 'explicitlyAllowedMolecules': [] } rmgpy.rmg.input.rmg = rmg reaction_model = CoreEdgeReactionModel() reaction_model.pressureDependence = self.pdepjob reaction_model.pressureDependence.rmgmode = True if outputFile: reaction_model.pressureDependence.outputFile = os.path.dirname( outputFile) kineticsDatabase = getDB('kinetics') thermoDatabase = getDB('thermo') thermoDatabase.libraries['thermojobs'] = thermoLibrary thermoDatabase.libraryOrder.insert(0, 'thermojobs') kineticsDatabase.libraries['kineticsjobs'] = kineticsLibrary kineticsDatabase.libraryOrder.insert( 0, ('kineticsjobs', 'Reaction Library')) jobRxns = [rxn for rxn in reaction_model.core.reactions] self.jobRxns = jobRxns if outputFile is not None: if not os.path.exists( os.path.join(reaction_model.pressureDependence.outputFile, 'pdep')): os.mkdir( os.path.join(reaction_model.pressureDependence.outputFile, 'pdep')) else: shutil.rmtree( os.path.join(reaction_model.pressureDependence.outputFile, 'pdep')) os.mkdir( os.path.join(reaction_model.pressureDependence.outputFile, 'pdep')) # get the molecular formula for the network mmol = None for spc in self.source: if mmol: mmol.merge(spc.molecule[0]) else: mmol = spc.molecule[0] form = mmol.getFormula() for spec in self.bathGas.keys() + self.source: nspec, isNew = reaction_model.makeNewSpecies(spec, reactive=False) flags = np.array([ s.molecule[0].getFormula() == form for s in reaction_model.core.species ]) reaction_model.enlarge(nspec, reactEdge=False, unimolecularReact=flags, bimolecularReact=np.zeros( (len(reaction_model.core.species), len(reaction_model.core.species)))) reaction_model.addSeedMechanismToCore('kineticsjobs') for lib in kineticsDatabase.libraryOrder: if lib[0] != 'kineticsjobs': reaction_model.addReactionLibraryToEdge(lib[0]) for spc in reaction_model.core.species: for i, item in enumerate(self.source): if spc.isIsomorphic(item): self.source[i] = spc # react initial species flags = np.array([ s.molecule[0].getFormula() == form for s in reaction_model.core.species ]) reaction_model.enlarge(reactEdge=True, unimolecularReact=flags, bimolecularReact=np.zeros( (len(reaction_model.core.species), len(reaction_model.core.species)))) # find the network we're interested in for nwk in reaction_model.networkList: if set(nwk.source) == set(self.source): self.source = nwk.source network = nwk break else: raise ValueError( 'Did not generate a network with the requested source. This usually means no unimolecular' 'reactions were generated for the source. Note that library reactions that are not' ' properly flagged as elementary_high_p can replace RMG generated reactions that would' ' otherwise be part of networks.') network.bathGas = self.bathGas self.network = network # determine T and P combinations if self.pdepjob.Tlist: Tlist = self.pdepjob.Tlist.value_si else: Tlist = np.linspace(self.pdepjob.Tmin.value_si, self.pdepjob.Tmax.value_si, self.pdepjob.Tcount) if self.pdepjob.Plist: Plist = self.pdepjob.Plist.value_si else: Plist = np.linspace(self.pdepjob.Pmin.value_si, self.pdepjob.Pmax.value_si, self.pdepjob.Pcount) # generate the network forbiddenStructures = getDB('forbidden') incomplete = True while incomplete: incomplete = False for T in Tlist: for P in Plist: if network.getLeakCoefficient(T=T, P=P) > self.explore_tol: incomplete = True spc = network.getMaximumLeakSpecies(T=T, P=P) if forbiddenStructures.isMoleculeForbidden( spc.molecule[0]): reaction_model.removeSpeciesFromEdge( reaction_model.reactionSystems, spc) reaction_model.removeEmptyPdepNetworks() logging.error(spc.label) else: logging.info( 'adding new isomer {0} to network'.format(spc)) flags = np.array([ s.molecule[0].getFormula() == form for s in reaction_model.core.species ]) reaction_model.enlarge( (network, spc), reactEdge=False, unimolecularReact=flags, bimolecularReact=np.zeros( (len(reaction_model.core.species), len(reaction_model.core.species)))) flags = np.array([ s.molecule[0].getFormula() == form for s in reaction_model.core.species ]) reaction_model.enlarge( reactEdge=True, unimolecularReact=flags, bimolecularReact=np.zeros( (len(reaction_model.core.species), len(reaction_model.core.species)))) rmRxns = [] for rxn in network.pathReactions: # remove reactions with forbidden species for r in rxn.reactants + rxn.products: if forbiddenStructures.isMoleculeForbidden(r.molecule[0]): rmRxns.append(rxn) for rxn in rmRxns: logging.info('Removing forbidden reaction: {0}'.format(rxn)) network.pathReactions.remove(rxn) # clean up output files if outputFile is not None: path = os.path.join(reaction_model.pressureDependence.outputFile, 'pdep') for name in os.listdir(path): if name.endswith('.py') and '_' in name: if name.split('_')[-1].split('.')[0] != str( len(network.isomers)): os.remove(os.path.join(path, name)) else: os.rename(os.path.join(path, name), os.path.join(path, 'network_full.py')) warns = [] for rxn in jobRxns: if rxn not in network.pathReactions: warns.append( 'Reaction {0} in the input file was not explored during network expansion and was not included in the full network. This is likely because your explore_tol value is too high.' .format(rxn)) # reduction process if self.energy_tol != np.inf or self.flux_tol != 0.0: rxnSet = None for T in Tlist: if self.energy_tol != np.inf: rxns = network.get_energy_filtered_reactions( T, self.energy_tol) if rxnSet is not None: rxnSet &= set(rxns) else: rxnSet = set(rxns) for P in Plist: if self.flux_tol != 0.0: rxns = network.get_rate_filtered_reactions( T, P, self.flux_tol) if rxnSet is not None: rxnSet &= set(rxns) else: rxnSet = set(rxns) logging.info('removing reactions during reduction:') for rxn in rxnSet: logging.info(rxn) network.remove_reactions(reaction_model, list(rxnSet)) for rxn in jobRxns: if rxn not in network.pathReactions: warns.append( 'Reaction {0} in the input file was not included in the reduced model.' .format(rxn)) self.network = network self.pdepjob.network = network self.pdepjob.execute(outputFile, plot, format='pdf', print_summary=True) if warns != []: logging.info('\nOUTPUT WARNINGS:\n') for w in warns: logging.warning(w)
def execute(self, outputFile, plot, format='pdf', print_summary=True, speciesList=None, thermoLibrary=None, kineticsLibrary=None): logging.info('Exploring network...') rmg = RMG() rmg.speciesConstraints = {'allowed' : ['input species', 'seed mechanisms', 'reaction libraries'], 'maximumRadicalElectrons' : self.maximumRadicalElectrons, 'explicitlyAllowedMolecules': []} rmgpy.rmg.input.rmg = rmg reaction_model = CoreEdgeReactionModel() reaction_model.pressureDependence = self.pdepjob reaction_model.pressureDependence.rmgmode = True if outputFile: reaction_model.pressureDependence.outputFile = os.path.dirname(outputFile) kineticsDatabase = getDB('kinetics') thermoDatabase = getDB('thermo') thermoDatabase.libraries['thermojobs'] = thermoLibrary thermoDatabase.libraryOrder.insert(0,'thermojobs') kineticsDatabase.libraries['kineticsjobs'] = kineticsLibrary kineticsDatabase.libraryOrder.insert(0,('kineticsjobs','Reaction Library')) jobRxns = [rxn for rxn in reaction_model.core.reactions] self.jobRxns = jobRxns if outputFile is not None: if not os.path.exists(os.path.join(reaction_model.pressureDependence.outputFile,'pdep')): os.mkdir(os.path.join(reaction_model.pressureDependence.outputFile,'pdep')) else: shutil.rmtree(os.path.join(reaction_model.pressureDependence.outputFile,'pdep')) os.mkdir(os.path.join(reaction_model.pressureDependence.outputFile,'pdep')) # get the molecular formula for the network mmol = None for spc in self.source: if mmol: mmol = mmol.merge(spc.molecule[0]) else: mmol = spc.molecule[0].copy(deep=True) form = mmol.getFormula() for spec in self.bathGas.keys()+self.source: nspec,isNew = reaction_model.makeNewSpecies(spec,reactive=False) flags = np.array([s.molecule[0].getFormula()==form for s in reaction_model.core.species]) reaction_model.enlarge(nspec,reactEdge=False,unimolecularReact=flags, bimolecularReact=np.zeros((len(reaction_model.core.species),len(reaction_model.core.species)))) reaction_model.addSeedMechanismToCore('kineticsjobs') for lib in kineticsDatabase.libraryOrder: if lib[0] != 'kineticsjobs': reaction_model.addReactionLibraryToEdge(lib[0]) for spc in reaction_model.core.species: for i,item in enumerate(self.source): if spc.isIsomorphic(item): self.source[i] = spc # react initial species if len(self.source) == 1: flags = np.array([s.molecule[0].getFormula()==form for s in reaction_model.core.species]) biflags = np.zeros((len(reaction_model.core.species),len(reaction_model.core.species))) elif len(self.source) == 2: flags = np.array([False for s in reaction_model.core.species]) biflags = np.array([[False for i in xrange(len(reaction_model.core.species))] for j in xrange(len(reaction_model.core.species))]) biflags[reaction_model.core.species.index(self.source[0]),reaction_model.core.species.index(self.source[1])] = True else: raise ValueError("Reactant channels with greater than 2 reactants not supported") reaction_model.enlarge(reactEdge=True,unimolecularReact=flags, bimolecularReact=biflags) # find the networks we're interested in networks = [] for nwk in reaction_model.networkList: if set(nwk.source) == set(self.source): self.source = nwk.source networks.append(nwk) if len(networks) == 0: raise ValueError('Did not generate a network with the requested source. This usually means no unimolecular' 'reactions were generated for the source. Note that library reactions that are not' ' properly flagged as elementary_high_p can replace RMG generated reactions that would' ' otherwise be part of networks.') for network in networks: network.bathGas = self.bathGas self.networks = networks # determine T and P combinations if self.pdepjob.Tlist: Tlist = self.pdepjob.Tlist.value_si else: Tlist = np.linspace(self.pdepjob.Tmin.value_si,self.pdepjob.Tmax.value_si,self.pdepjob.Tcount) if self.pdepjob.Plist: Plist = self.pdepjob.Plist.value_si else: Plist = np.linspace(self.pdepjob.Pmin.value_si,self.pdepjob.Pmax.value_si,self.pdepjob.Pcount) # generate the network forbiddenStructures = getDB('forbidden') incomplete = True while incomplete: incomplete = False for T in Tlist: for P in Plist: for network in self.networks: kchar = 0.0 #compute the characteristic rate coefficient by summing all rate coefficients from the reactant channel for rxn in network.netReactions:#reaction_model.core.reactions+reaction_model.edge.reactions: if set(rxn.reactants) == set(self.source) and rxn.products[0].molecule[0].getFormula() == form: kchar += rxn.kinetics.getRateCoefficient(T=T,P=P) elif set(rxn.products) == set(self.source) and rxn.reactants[0].molecule[0].getFormula() == form: kchar += rxn.generateReverseRateCoefficient(network_kinetics=True).getRateCoefficient(T=T,P=P) if network.getLeakCoefficient(T=T,P=P) > self.explore_tol*kchar: incomplete = True spc = network.getMaximumLeakSpecies(T=T,P=P) if forbiddenStructures.isMoleculeForbidden(spc.molecule[0]): reaction_model.removeSpeciesFromEdge(reaction_model.reactionSystems,spc) reaction_model.removeEmptyPdepNetworks() logging.error(spc.label) else: logging.info('adding new isomer {0} to network'.format(spc)) flags = np.array([s.molecule[0].getFormula()==form for s in reaction_model.core.species]) reaction_model.enlarge((network,spc),reactEdge=False,unimolecularReact=flags, bimolecularReact=np.zeros((len(reaction_model.core.species),len(reaction_model.core.species)))) flags = np.array([s.molecule[0].getFormula()==form for s in reaction_model.core.species]) reaction_model.enlarge(reactEdge=True,unimolecularReact=flags, bimolecularReact=np.zeros((len(reaction_model.core.species),len(reaction_model.core.species)))) for network in self.networks: rmRxns = [] for rxn in network.pathReactions: # remove reactions with forbidden species for r in rxn.reactants+rxn.products: if forbiddenStructures.isMoleculeForbidden(r.molecule[0]): rmRxns.append(rxn) for rxn in rmRxns: logging.info('Removing forbidden reaction: {0}'.format(rxn)) network.pathReactions.remove(rxn) # clean up output files if outputFile is not None: path = os.path.join(reaction_model.pressureDependence.outputFile,'pdep') for name in os.listdir(path): if name.endswith('.py') and '_' in name: if name.split('_')[-1].split('.')[0] != str(len(network.isomers)): os.remove(os.path.join(path,name)) else: os.rename(os.path.join(path,name),os.path.join(path,'network_full{}.py'.format(self.networks.index(network)))) warns = [] for rxn in jobRxns: if rxn not in network.pathReactions: warns.append('Reaction {0} in the input file was not explored during network expansion and was not included in the full network. This is likely because your explore_tol value is too high.'.format(rxn)) # reduction process for network in self.networks: if self.energy_tol != np.inf or self.flux_tol != 0.0: rxnSet = None for T in Tlist: if self.energy_tol != np.inf: rxns = network.get_energy_filtered_reactions(T,self.energy_tol) if rxnSet is not None: rxnSet &= set(rxns) else: rxnSet = set(rxns) for P in Plist: if self.flux_tol != 0.0: rxns = network.get_rate_filtered_reactions(T,P,self.flux_tol) if rxnSet is not None: rxnSet &= set(rxns) else: rxnSet = set(rxns) logging.info('removing reactions during reduction:') for rxn in rxnSet: logging.info(rxn) network.remove_reactions(reaction_model,list(rxnSet)) for rxn in jobRxns: if rxn not in network.pathReactions: warns.append('Reaction {0} in the input file was not included in the reduced model.'.format(rxn)) self.networks = networks for p,network in enumerate(self.networks): self.pdepjob.network = network if len(self.networks) > 1: s1,s2 = outputFile.split(".") ind = str(self.networks.index(network)) stot = s1+"{}.".format(ind)+s2 else: stot = outputFile self.pdepjob.execute(stot, plot, format='pdf', print_summary=True) if os.path.isfile('network.pdf'): os.rename('network.pdf','network'+str(p)+'.pdf') if warns != []: logging.info('\nOUTPUT WARNINGS:\n') for w in warns: logging.warning(w)