def test_make_new_reaction(self): """ Test that CoreEdgeReactionModel.make_new_reaction method correctly works. """ procnum = 2 spcA = Species().from_smiles('[OH]') spcs = [Species().from_smiles('CC'), Species().from_smiles('[CH3]')] spc_tuples = [((spcA, spc), ['H_Abstraction']) for spc in spcs] rxns = list(itertools.chain.from_iterable(react(spc_tuples, procnum))) cerm = CoreEdgeReactionModel() for rxn in rxns: cerm.make_new_reaction(rxn) """ 3 expected H-abstraction reactions: OH + CC = H2O + C[CH2] OH + [CH3] = H2O + [CH2] OH + [CH3] = [O] + C """ # count no. of entries in reactionDict: counter = 0 for fam, v1 in cerm.reaction_dict.items(): for key2, v2 in v1.items(): for key3, rxnList in v2.items(): counter += len(rxnList) self.assertEquals(counter, 3)
def testRMGSeedWorks(self): """Test that the created seed libraries work. Note: Since this test modifies the class level RMG instance, it can cause other tests to fail if run out of order.""" # Load the seed libraries into the database self.rmg.database.load( path=self.databaseDirectory, thermoLibraries=['testSeed', 'testSeed_edge'], reactionLibraries=['testSeed', 'testSeed_edge'], seedMechanisms=['testSeed', 'testSeed_edge'], kineticsFamilies='default', kineticsDepositories=[], depository=False ) self.rmg.reactionModel = CoreEdgeReactionModel() self.rmg.reactionModel.addReactionLibraryToEdge('testSeed') # try adding seed as library self.assertTrue(len(self.rmg.reactionModel.edge.species) > 0) self.assertTrue(len(self.rmg.reactionModel.edge.reactions) > 0) self.rmg.reactionModel = CoreEdgeReactionModel() self.rmg.reactionModel.addSeedMechanismToCore('testSeed') # try adding seed as seed mech self.assertTrue(len(self.rmg.reactionModel.core.species) > 0) self.assertTrue(len(self.rmg.reactionModel.core.reactions) > 0) self.rmg.reactionModel = CoreEdgeReactionModel() self.rmg.reactionModel.addReactionLibraryToEdge('testSeed_edge') # try adding seed as library self.assertTrue(len(self.rmg.reactionModel.edge.species) > 0) self.assertTrue(len(self.rmg.reactionModel.edge.reactions) > 0) self.rmg.reactionModel = CoreEdgeReactionModel() self.rmg.reactionModel.addSeedMechanismToCore('testSeed_edge') # try adding seed as seed mech self.assertTrue(len(self.rmg.reactionModel.core.species) > 0) self.assertTrue(len(self.rmg.reactionModel.core.reactions) > 0)
def test_append_unreactive_structure(self): """ Test that CERM.make_new_species correctly recognizes a non-representative resonance structure """ cerm = CoreEdgeReactionModel() spcs = [ Species().from_smiles('CCO'), # a control species Species().from_smiles('[N]=O'), Species().from_adjacency_list( """1 O u1 p2 c0 {2,S} 2 N u0 p2 c0 {1,S}""" ), # a non-representative structure of '[N]=O' ] for spc in spcs: cerm.make_new_species(spc) self.assertEquals(len(cerm.species_dict), 2) self.assertEquals(len(cerm.index_species_dict), 2) self.assertEquals(len(cerm.index_species_dict[1].molecule), 1) self.assertTrue(cerm.index_species_dict[1].molecule[0].reactive) self.assertEquals(len(cerm.index_species_dict[2].molecule), 1) self.assertTrue(cerm.index_species_dict[2].molecule[0].reactive)
def reaction(label, reactants, products, transitionState=None, kinetics=None, tunneling=''): """Load a reaction from an input file""" global reaction_dict, species_dict, transition_state_dict if label in reaction_dict: label = label + transitionState if label in reaction_dict: raise ValueError('Multiple occurrences of reaction with label {0!r}.'.format(label)) logging.info('Loading reaction {0}...'.format(label)) reactants = sorted([species_dict[spec] for spec in reactants]) products = sorted([species_dict[spec] for spec in products]) if transitionState: transitionState = transition_state_dict[transitionState] if transitionState and (tunneling == '' or tunneling is None): transitionState.tunneling = None elif tunneling.lower() == 'wigner': transitionState.tunneling = Wigner(frequency=None) elif tunneling.lower() == 'eckart': transitionState.tunneling = Eckart(frequency=None, E0_reac=None, E0_TS=None, E0_prod=None) elif transitionState and not isinstance(tunneling, TunnelingModel): raise ValueError('Unknown tunneling model {0!r}.'.format(tunneling)) rxn = Reaction(label=label, reactants=reactants, products=products, transition_state=transitionState, kinetics=kinetics) if rxn.transition_state is None and rxn.kinetics is None: logging.info('estimating rate of reaction {0} using RMG-database') if not all([m.molecule != [] for m in rxn.reactants + rxn.products]): raise ValueError('chemical structures of reactants and products not available for RMG estimation of ' 'reaction {0}'.format(label)) db = get_db('kinetics') rxns = db.generate_reactions_from_libraries(reactants=rxn.reactants, products=rxn.products) rxns = [r for r in rxns if r.elementary_high_p] if rxns: for r in rxns: if isinstance(rxn.kinetics, PDepKineticsModel): boo = rxn.generate_high_p_limit_kinetics() if boo: rxn = r break if rxns == [] or not boo: logging.info('No library reactions tagged with elementary_high_p found for reaction {0}, generating ' 'reactions from RMG families'.format(label)) rxn = list(db.generate_reactions_from_families(reactants=rxn.reactants, products=rxn.products)) model = CoreEdgeReactionModel() model.verbose_comments = True for r in rxn: model.apply_kinetics_to_reaction(r) if isinstance(rxn, Reaction): reaction_dict[label] = rxn else: for i in range(len(rxn)): reaction_dict[label + str(i)] = rxn[i] return rxn
def reaction(label, reactants, products, transitionState=None, kinetics=None, tunneling=''): global reactionDict, speciesDict, transitionStateDict if label in reactionDict: label = label + transitionState if label in reactionDict: raise ValueError('Multiple occurrences of reaction with label {0!r}.'.format(label)) logging.info('Loading reaction {0}...'.format(label)) reactants = sorted([speciesDict[spec] for spec in reactants]) products = sorted([speciesDict[spec] for spec in products]) if transitionState: transitionState = transitionStateDict[transitionState] if tunneling.lower() == 'wigner': transitionState.tunneling = Wigner(frequency=None) elif tunneling.lower() == 'eckart': transitionState.tunneling = Eckart(frequency=None, E0_reac=None, E0_TS=None, E0_prod=None) elif transitionState and (tunneling == '' or tunneling is None): transitionState.tunneling = None elif transitionState and not isinstance(tunneling, TunnelingModel): raise ValueError('Unknown tunneling model {0!r}.'.format(tunneling)) rxn = Reaction(label=label, reactants=reactants, products=products, transitionState=transitionState, kinetics=kinetics) if rxn.transitionState is None and rxn.kinetics is None: logging.info('estimating rate of reaction {0} using RMG-database') if not all([m.molecule != [] for m in rxn.reactants+rxn.products]): raise ValueError('chemical structures of reactants and products not available for RMG estimation of reaction {0}'.format(label)) for spc in rxn.reactants+rxn.products: print spc.label print spc.molecule db = getDB('kinetics') rxns = db.generate_reactions_from_libraries(reactants=rxn.reactants,products=rxn.products) rxns = [r for r in rxns if r.elementary_high_p] if rxns != []: for r in rxns: if isinstance(rxn.kinetics, PDepKineticsModel): boo = rxn.generate_high_p_limit_kinetics() if boo: rxn = r break if rxns == [] or not boo: logging.info('No library reactions tagged with elementary_high_p found for reaction {0}, generating reactions from RMG families'.format(label)) rxn = list(db.generate_reactions_from_families(reactants=rxn.reactants,products=rxn.products)) model = CoreEdgeReactionModel() model.verboseComments = True for r in rxn: model.applyKineticsToReaction(r) if isinstance(rxn,Reaction): reactionDict[label] = rxn else: for i in xrange(len(rxn)): reactionDict[label+str(i)] = rxn[i] return rxn
def test_check_for_existing_reaction_removes_duplicates_in_opposite_directions( self): """ Test that check_for_existing_reaction removes duplicate reverse reactions """ cerm = CoreEdgeReactionModel() # make species' objects s1 = Species().from_smiles("[H]") s2 = Species().from_smiles("CC") s3 = Species().from_smiles("[H][H]") s4 = Species().from_smiles("C[CH2]") s1.label = 'H' s2.label = 'CC' s3.label = 'HH' s4.label = 'C[CH2]' rxn_f = TemplateReaction(reactants=[s1, s2], products=[s3, s4], template=['C/H3/Cs/H3', 'H_rad'], degeneracy=6, family='H_Abstraction', reverse=TemplateReaction( reactants=[s3, s4], products=[s1, s2], template=['H2', 'C_rad/H2/Cs/H3'], degeneracy=2, family='H_Abstraction')) rxn_r = TemplateReaction(reactants=[s3, s4], products=[s1, s2], template=['H2', 'C_rad/H2/Cs/H3'], degeneracy=2, family='H_Abstraction', reverse=TemplateReaction( reactants=[s1, s2], products=[s3, s4], template=['C/H3/Cs/H3', 'H_rad'], degeneracy=6, family='H_Abstraction')) rxn_f.reactants.sort() rxn_f.products.sort() cerm.add_reaction_to_core(rxn_f) cerm.register_reaction(rxn_f) reactions = cerm.search_retrieve_reactions(rxn_r) self.assertEqual( 1, len(reactions), 'cerm.search_retrieve_reactions could not identify reverse reaction' ) found, rxn = cerm.check_for_existing_reaction(rxn_r) self.assertTrue( found, 'check_for_existing_reaction failed to identify existing reaction in the reverse direction' ) self.assertEqual(rxn, rxn_f)
def test_make_new_species(self): """ Test that CoreEdgeReactionModel.make_new_species method correctly stores the unique species. """ # adding 3 unique species: cerm = CoreEdgeReactionModel() spcs = [ Species().from_smiles('[OH]'), Species().from_smiles('CC'), Species().from_smiles('[CH3]') ] for spc in spcs: cerm.make_new_species(spc) self.assertEquals(len(cerm.species_dict), len(spcs)) self.assertEquals(len(cerm.index_species_dict), len(spcs)) # adding 3 unique, and 1 already existing species: cerm = CoreEdgeReactionModel() spcs = [ Species().from_smiles('[OH]'), Species().from_smiles('CC'), Species().from_smiles('[CH3]'), Species().from_smiles('CC') ] # duplicate species for spc in spcs: cerm.make_new_species(spc) self.assertEquals(len(cerm.species_dict), len(spcs) - 1) self.assertEquals(len(cerm.index_species_dict), len(spcs) - 1)
def testAllEntriesAccessibleInSearchTargetIndex(self): butene1 = Species() butene1.fromSMILES('C=CCC') butene1.label = 'C4H8' butene2 = Species() butene2.fromSMILES('CC=CC') butene2.label = 'C4H8' species_list = [butene1, butene2] # make sure different species with same label assert not species_list[0].isIsomorphic(species_list[1]) assert species_list[0].label == species_list[1].label # make fake reactionModel object to fit in with the unittest reaction_model = CoreEdgeReactionModel() reaction_model.core.species = species_list # ensure second species index is returned when it's label is used # in `searchTargetIndex`. input_index = 1 output_index = searchTargetIndex(species_list[input_index].label, reaction_model) self.assertEqual( input_index, output_index, 'searchTargetIndex will not return the second occurance of species with the same label.' )
def testRMGExecute(self): """ This example is to test if RMG.execute increases the core reactions """ self.rmg.execute() self.assertIsInstance(self.rmg.database, RMGDatabase) self.assertTrue(self.rmg.done) self.assertTrue(len(self.rmg.reactionModel.core.reactions) > 0) self.assertTrue(len(self.rmg.reactionModel.core.species) > 1) self.assertTrue(len(self.rmg.reactionModel.edge.reactions) > 0) self.assertTrue(len(self.rmg.reactionModel.edge.species) > 0) #test seed mech generation #test seed mech made in run directory seedDir = os.path.join(originalPath,self.dir_name,'seed') self.assertTrue(os.path.exists) os.chdir(seedDir) self.assertTrue(os.path.exists(self.rmg.name+'.py')) #thermo library made self.assertTrue(os.path.exists(self.rmg.name)) #kinetics library folder made kDir = os.path.join(seedDir,self.rmg.name) os.chdir(kDir) self.assertTrue(os.path.exists('dictionary.txt')) #dictionary file made self.assertTrue(os.path.exists('reactions.py')) #reactions file made os.chdir(os.path.join(originalPath,self.dir_name)) #return to original directory #check seed mech made in database self.assertTrue(os.path.exists(self.thermoDir)) self.assertTrue(os.path.exists(self.kineticsDir)) #check seed works self.rmg.database.load(path=self.databaseDirectory,thermoLibraries=['testSeed'],reactionLibraries=['testSeed'], seedMechanisms=['testSeed'],kineticsFamilies='default',kineticsDepositories = [], depository=False) #reload the database to get the seed self.rmg.reactionModel = CoreEdgeReactionModel() self.rmg.reactionModel.addReactionLibraryToEdge('testSeed') #try adding seed as library self.assertTrue(len(self.rmg.reactionModel.edge.species)>0) self.assertTrue(len(self.rmg.reactionModel.edge.reactions)>0) self.rmg.reactionModel = CoreEdgeReactionModel() self.rmg.reactionModel.addSeedMechanismToCore('testSeed') #try adding seed as seed mech self.assertTrue(len(self.rmg.reactionModel.core.species)>0) self.assertTrue(len(self.rmg.reactionModel.core.reactions)>0)
def main(chemkin, dictionary, output, foreign): model = CoreEdgeReactionModel() model.core.species, model.core.reactions = loadChemkinFile( chemkin, dictionary, readComments=not foreign, checkDuplicates=foreign) outputPath = os.path.join(output, 'output.html') speciesPath = os.path.join(output, 'species') if not os.path.isdir(speciesPath): os.makedirs(speciesPath) saveOutputHTML(outputPath, model)
def main(chemkin, dictionary, output, foreign): model = CoreEdgeReactionModel() model.core.species, model.core.reactions = load_chemkin_file(chemkin, dictionary, read_comments=not foreign, check_duplicates=foreign) output_path = os.path.join(output, 'output.html') species_path = os.path.join(output, 'species') if not os.path.isdir(species_path): os.makedirs(species_path) save_output_html(output_path, model)
def test_check_for_existing_species_for_bi_aromatics(self): """ Test RMG check_for_existing_species can correctly check isomorphism for biaromatics. In this test, DPP is a species already stored in rmg species_dict, mol_test is a newly created molecule which has one kekulized benzene ring and one double_bond-single_bond benzene ring. """ rmg_test = RMG() rmg_test.reaction_model = CoreEdgeReactionModel() DPP = Species().from_smiles('C1=CC=C(C=C1)CCCC1C=CC=CC=1') DPP.generate_resonance_structures() formula = DPP.molecule[0].get_formula() if formula in rmg_test.reaction_model.species_dict: rmg_test.reaction_model.species_dict[formula].append(DPP) else: rmg_test.reaction_model.species_dict[formula] = [DPP] mol_test = Molecule().from_adjacency_list( """ 1 C u0 p0 c0 {2,S} {3,S} {16,S} {17,S} 2 C u0 p0 c0 {1,S} {4,S} {18,S} {19,S} 3 C u0 p0 c0 {1,S} {5,S} {20,S} {21,S} 4 C u0 p0 c0 {2,S} {6,B} {7,B} 5 C u0 p0 c0 {3,S} {8,D} {9,S} 6 C u0 p0 c0 {4,B} {10,B} {22,S} 7 C u0 p0 c0 {4,B} {12,B} {24,S} 8 C u0 p0 c0 {5,D} {14,S} {27,S} 9 C u0 p0 c0 {5,S} {15,D} {28,S} 10 C u0 p0 c0 {6,B} {11,B} {23,S} 11 C u0 p0 c0 {10,B} {12,B} {25,S} 12 C u0 p0 c0 {7,B} {11,B} {26,S} 13 C u0 p0 c0 {14,D} {15,S} {29,S} 14 C u0 p0 c0 {8,S} {13,D} {30,S} 15 C u0 p0 c0 {9,D} {13,S} {31,S} 16 H u0 p0 c0 {1,S} 17 H u0 p0 c0 {1,S} 18 H u0 p0 c0 {2,S} 19 H u0 p0 c0 {2,S} 20 H u0 p0 c0 {3,S} 21 H u0 p0 c0 {3,S} 22 H u0 p0 c0 {6,S} 23 H u0 p0 c0 {10,S} 24 H u0 p0 c0 {7,S} 25 H u0 p0 c0 {11,S} 26 H u0 p0 c0 {12,S} 27 H u0 p0 c0 {8,S} 28 H u0 p0 c0 {9,S} 29 H u0 p0 c0 {13,S} 30 H u0 p0 c0 {14,S} 31 H u0 p0 c0 {15,S} """) spec = rmg_test.reaction_model.check_for_existing_species(mol_test) self.assertIsNotNone(spec)
def main(chemkin): # Load Chemkin file reactionModel = CoreEdgeReactionModel() reactionModel.core.species, reactionModel.core.reactions = loadChemkinFile( chemkin) # Identify reactions to be removed reactionList = reactionModel.core.reactions duplicateReactionsToRemove = [] for index1 in range(len(reactionList)): reaction1 = reactionList[index1] for index2 in range(index1 + 1, len(reactionList)): reaction2 = reactionList[index2] # Check if the two reactions are identical if (reaction1.reactants == reaction2.reactants and reaction1.products == reaction2.products) or ( reaction1.reactants == reaction2.products and reaction1.products == reaction2.reactants): # Identify if exactly 1 of the reactions is a LibraryReaction if isinstance(reaction1, LibraryReaction) != isinstance( reaction2, LibraryReaction): # Mark the non-LibraryReaction to be removed if isinstance(reaction1, LibraryReaction): duplicateReactionsToRemove.append(reaction2) else: duplicateReactionsToRemove.append(reaction1) # Remove the identified reactions for reaction in duplicateReactionsToRemove: reactionList.remove(reaction) # Write new Chemkin file path = 'chem_annotated_new.inp' speciesList = reactionModel.core.species + reactionModel.outputSpeciesList rxnList = reactionModel.core.reactions + reactionModel.outputReactionList with open(chemkin, 'rb') as old, open(path, 'wb') as new: # Copy species and reactions blocks to new Chemkin file line = old.readline() while 'REACTIONS' not in line.upper(): new.write(line) line = old.readline() new.write('REACTIONS KCAL/MOLE MOLES\n\n') rmgpy.chemkin.__chemkin_reaction_count = 0 for rxn in rxnList: new.write( writeKineticsEntry(rxn, speciesList=speciesList, verbose=True)) new.write('\n') new.write('END\n\n') print "New Chemkin file contains {0} reactions.".format( rmgpy.chemkin.__chemkin_reaction_count)
def setUpClass(cls): """ A method that is run before all unit tests in this class. """ # set-up RMG object cls.rmg = RMG() cls.rmg.reaction_model = CoreEdgeReactionModel() # load kinetic database and forbidden structures cls.rmg.database = RMGDatabase() path = os.path.join(settings['test_data.directory'], 'testing_database') # kinetics family Disproportionation loading cls.rmg.database.load_kinetics(os.path.join(path, 'kinetics'), kinetics_families=['H_Abstraction', 'R_Addition_MultipleBond'], reaction_libraries=[]) # load empty forbidden structures for family in cls.rmg.database.kinetics.families.values(): family.forbidden = ForbiddenStructures() cls.rmg.database.forbidden_structures = ForbiddenStructures()
def test_save_output_html(self): """ This example is to test if an HTML file can be generated for the provided chemkin model. """ folder = os.path.join(os.path.dirname(__file__), 'test_data/saveOutputHTML/') chemkin_path = os.path.join(folder, 'eg6', 'chem_annotated.inp') dictionary_path = os.path.join(folder, 'eg6', 'species_dictionary.txt') # load_chemkin_file species, reactions = load_chemkin_file(chemkin_path, dictionary_path) # convert it into a reaction model: core = ReactionModel(species, reactions) cerm = CoreEdgeReactionModel(core) out = os.path.join(folder, 'output.html') save_output_html(out, cerm) self.assertTrue(os.path.isfile(out)) os.remove(out) shutil.rmtree(os.path.join(folder, 'species'))
def setUpClass(cls): """ A method that is run ONCE before all unit tests in this class. """ cls.dirname = os.path.abspath( os.path.join(os.path.dirname(__file__), 'temp')) os.makedirs(os.path.join(cls.dirname, 'pdep')) test_family = 'R_Recombination' cls.rmg = RMG() from rmgpy.rmg.input import set_global_rmg, pressure_dependence set_global_rmg(cls.rmg) pressure_dependence( method='modified strong collision', maximumGrainSize=(0.5, 'kcal/mol'), minimumNumberOfGrains=250, temperatures=(300, 2100, 'K', 8), pressures=(0.1, 100, 'bar', 5), interpolation=('Chebyshev', 6, 4), maximumAtoms=10, ) cls.rmg.output_directory = cls.rmg.pressure_dependence.output_file = cls.dirname cls.rmg.database = RMGDatabase() cls.rmg.database.load( path=settings['database.directory'], thermo_libraries=['primaryThermoLibrary'], kinetics_families=[test_family], reaction_libraries=[], ) cls.rmg.reaction_model = CoreEdgeReactionModel() cls.rmg.reaction_model.pressure_dependence = cls.rmg.pressure_dependence
def test_check_for_existing_reaction_eliminates_identical_reactions_without_duplicate_flag( self): """ Test that check_for_existing_reaction eliminates reactions with different templates and duplicate=false """ cerm = CoreEdgeReactionModel() # make species' objects spcA = Species().from_smiles('[H]') spcB = Species().from_smiles('C=C[CH2]C') spcC = Species().from_smiles('C=C=CC') spcD = Species().from_smiles('[H][H]') spcA.label = '[H]' spcB.label = 'C=C[CH2]C' spcC.label = 'C=C=CC' spcD.label = '[H][H]' spcB.generate_resonance_structures() cerm.add_species_to_core(spcA) cerm.add_species_to_core(spcB) cerm.add_species_to_core(spcC) cerm.add_species_to_core(spcD) reaction_in_model = TemplateReaction(reactants=[spcA, spcB], products=[spcC, spcD], family='H_Abstraction', template=['Csd', 'H'], duplicate=False) reaction_in_model.reactants.sort() reaction_in_model.products.sort() reaction_to_add = TemplateReaction(reactants=[spcA, spcB], products=[spcC, spcD], family='H_Abstraction', template=['Cs12345', 'H'], duplicate=False) cerm.add_reaction_to_core(reaction_in_model) cerm.register_reaction(reaction_in_model) found, rxn = cerm.check_for_existing_reaction(reaction_to_add) self.assertTrue( found, 'check_for_existing_reaction failed to eliminate reactions without duplicate tag' )
def test_check_for_existing_reaction_eliminates_identical_reactions(self): """ Test that check_for_existing_reaction catches identical reactions. """ cerm = CoreEdgeReactionModel() # make species' objects spcA = Species().from_smiles('[H]') spcB = Species().from_smiles('C=C[CH2]C') spcC = Species().from_smiles('C=C=CC') spcD = Species().from_smiles('[H][H]') spcA.label = '[H]' spcB.label = 'C=C[CH2]C' spcC.label = 'C=C=CC' spcD.label = '[H][H]' spcB.generate_resonance_structures() cerm.add_species_to_core(spcA) cerm.add_species_to_core(spcB) cerm.add_species_to_core(spcC) cerm.add_species_to_core(spcD) reaction_in_model = TemplateReaction(reactants=[spcA, spcB], products=[spcC, spcD], family='H_Abstraction', template=['Csd', 'H']) reaction_in_model.reactants.sort() reaction_in_model.products.sort() reaction_to_add = TemplateReaction(reactants=[spcA, spcB], products=[spcC, spcD], family='H_Abstraction', template=['Csd', 'H']) cerm.add_reaction_to_core(reaction_in_model) cerm.register_reaction(reaction_in_model) found, rxn = cerm.check_for_existing_reaction(reaction_to_add) self.assertTrue( found, 'check_for_existing_reaction failed to identify existing reaction')
def test_thermo_filter_down(self): """ test that thermo_filter_down with maximum_edge_species = 1 reduces the edge to one species """ cerm = CoreEdgeReactionModel() spcs = [ Species().from_smiles('[OH]'), Species().from_smiles('C'), Species().from_smiles('[CH3]'), Species().from_smiles('[CH2]'), Species().from_smiles('O') ] for spc in spcs: cerm.make_new_species(spc, label=spc.molecule[0].to_smiles()) spc.label = spc.molecule[0].to_smiles() thermo_dict = { '[OH]': NASA(polynomials=[ NASAPolynomial(coeffs=[ 3.51457, 2.92787e-05, -5.32168e-07, 1.0195e-09, -3.85947e-13, 3414.25, 2.10435 ], Tmin=(100, 'K'), Tmax=(1145.75, 'K')), NASAPolynomial(coeffs=[ 3.07194, 0.000604014, -1.39775e-08, -2.13448e-11, 2.48067e-15, 3579.39, 4.578 ], Tmin=(1145.75, 'K'), Tmax=(5000, 'K')) ], Tmin=(100, 'K'), Tmax=(5000, 'K'), E0=(28.3945, 'kJ/mol'), Cp0=(29.1007, 'J/(mol*K)'), CpInf=(37.4151, 'J/(mol*K)'), label="""OH(D)""", comment="""Thermo library: primaryThermoLibrary"""), 'C': NASA(polynomials=[ NASAPolynomial(coeffs=[ 4.20541, -0.00535551, 2.51121e-05, -2.1376e-08, 5.97513e-12, -10161.9, -0.921259 ], Tmin=(100, 'K'), Tmax=(1084.13, 'K')), NASAPolynomial(coeffs=[ 0.908298, 0.011454, -4.57171e-06, 8.29185e-10, -5.66309e-14, -9719.99, 13.9929 ], Tmin=(1084.13, 'K'), Tmax=(5000, 'K')) ], Tmin=(100, 'K'), Tmax=(5000, 'K'), E0=(-84.435, 'kJ/mol'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(108.088, 'J/(mol*K)'), label="""CH4""", comment="""Thermo library: primaryThermoLibrary"""), '[CH3]': NASA(polynomials=[ NASAPolynomial(coeffs=[ 3.67359, 0.00201095, 5.73022e-06, -6.87117e-09, 2.54386e-12, 16445, 1.60456 ], Tmin=(200, 'K'), Tmax=(1000, 'K')), NASAPolynomial(coeffs=[ 2.28572, 0.0072399, -2.98714e-06, 5.95685e-10, -4.67154e-14, 16775.6, 8.48007 ], Tmin=(1000, 'K'), Tmax=(3500, 'K')) ], Tmin=(200, 'K'), Tmax=(3500, 'K'), E0=(136.42, 'kJ/mol'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(83.1447, 'J/(mol*K)'), label="""CH3""", comment="""Thermo library: GRI-Mech3.0"""), '[CH2]': NASA(polynomials=[ NASAPolynomial(coeffs=[ 4.01192, -0.000154978, 3.26298e-06, -2.40422e-09, 5.69497e-13, 45867.7, 0.533201 ], Tmin=(100, 'K'), Tmax=(1104.62, 'K')), NASAPolynomial(coeffs=[ 3.14983, 0.00296674, -9.76056e-07, 1.54115e-10, -9.50338e-15, 46058.1, 4.77808 ], Tmin=(1104.62, 'K'), Tmax=(5000, 'K')) ], Tmin=(100, 'K'), Tmax=(5000, 'K'), E0=(381.37, 'kJ/mol'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(58.2013, 'J/(mol*K)'), label="""CH2(T)""", comment="""Thermo library: primaryThermoLibrary"""), 'O': NASA(polynomials=[ NASAPolynomial(coeffs=[ 4.05764, -0.000787936, 2.90877e-06, -1.47519e-09, 2.12842e-13, -30281.6, -0.311364 ], Tmin=(100, 'K'), Tmax=(1130.24, 'K')), NASAPolynomial(coeffs=[ 2.84325, 0.00275109, -7.81031e-07, 1.07244e-10, -5.79392e-15, -29958.6, 5.91042 ], Tmin=(1130.24, 'K'), Tmax=(5000, 'K')) ], Tmin=(100, 'K'), Tmax=(5000, 'K'), E0=(-251.755, 'kJ/mol'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(58.2013, 'J/(mol*K)'), label="""H2O""", comment="""Thermo library: primaryThermoLibrary"""), } for spc in spcs[:3]: cerm.add_species_to_core(spc) reaction = TemplateReaction(reactants=[spcs[0], spcs[2]], products=[spcs[-1], spcs[-2]], degeneracy=1, reversible=True, family='H_Abstraction') cerm.process_new_reactions(new_reactions=[reaction], new_species=[]) # add CH2 and O to edge for spc in cerm.core.species + cerm.edge.species: spc.thermo = thermo_dict[ spc.molecule[0].to_smiles()] # assign thermo cerm.set_thermodynamic_filtering_parameters( Tmax=300.0, thermo_tol_keep_spc_in_edge=1000.0, min_core_size_for_prune=0, maximum_edge_species=1, reaction_systems=[]) difset = set([ x.molecule[0].to_smiles() for x in cerm.edge.species ]) - set([x.molecule[0].to_smiles() for x in cerm.core.species]) self.assertEquals( len(difset), 2) # no change because toleranceThermoKeepSpeciesInEdge is high cerm.thermo_filter_down(maximum_edge_species=1) difset = set([ x.molecule[0].to_smiles() for x in cerm.edge.species ]) - set([x.molecule[0].to_smiles() for x in cerm.core.species]) self.assertEquals( len(difset), 1 ) # should be one because we thermo filtered down to one edge species
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)
def saveForm(self, posted, form): """ Save form data into input.py file specified by the path. """ # Clean past history self.rmg = RMG() # Databases #self.rmg.databaseDirectory = settings['database.directory'] self.rmg.thermoLibraries = [] if posted.thermo_libraries.all(): self.rmg.thermoLibraries = [ item.thermolib.encode() for item in posted.thermo_libraries.all() ] self.rmg.reactionLibraries = [] self.rmg.seedMechanisms = [] if posted.reaction_libraries.all(): for item in posted.reaction_libraries.all(): if not item.seedmech and not item.edge: self.rmg.reactionLibraries.append( (item.reactionlib.encode(), False)) elif not item.seedmech: self.rmg.reactionLibraries.append( (item.reactionlib.encode(), True)) else: self.rmg.seedMechanisms.append(item.reactionlib.encode()) self.rmg.statmechLibraries = [] self.rmg.kineticsDepositories = 'default' self.rmg.kineticsFamilies = 'default' self.rmg.kineticsEstimator = 'rate rules' # Species self.rmg.initialSpecies = [] speciesDict = {} initialMoleFractions = {} self.rmg.reactionModel = CoreEdgeReactionModel() for item in posted.reactor_species.all(): structure = Molecule().fromAdjacencyList(item.adjlist.encode()) spec, isNew = self.rmg.reactionModel.makeNewSpecies( structure, label=item.name.encode(), reactive=False if item.inert else True) self.rmg.initialSpecies.append(spec) speciesDict[item.name.encode()] = spec initialMoleFractions[spec] = item.molefrac # Reactor systems self.rmg.reactionSystems = [] for item in posted.reactor_systems.all(): T = Quantity(item.temperature, item.temperature_units.encode()) P = Quantity(item.pressure, item.pressure_units.encode()) termination = [] if item.conversion: termination.append( TerminationConversion(speciesDict[item.species.encode()], item.conversion)) termination.append( TerminationTime( Quantity(item.terminationtime, item.time_units.encode()))) # Sensitivity Analysis sensitiveSpecies = [] if item.sensitivity: if isinstance(item.sensitivity.encode(), str): sensitivity = item.sensitivity.encode().split(',') for spec in sensitivity: sensitiveSpecies.append(speciesDict[spec.strip()]) system = SimpleReactor(T, P, initialMoleFractions, termination, sensitiveSpecies, item.sensitivityThreshold) self.rmg.reactionSystems.append(system) # Simulator tolerances self.rmg.absoluteTolerance = form.cleaned_data['simulator_atol'] self.rmg.relativeTolerance = form.cleaned_data['simulator_rtol'] self.rmg.sensitivityAbsoluteTolerance = form.cleaned_data[ 'simulator_sens_atol'] self.rmg.sensitivityRelativeTolerance = form.cleaned_data[ 'simulator_sens_rtol'] self.rmg.fluxToleranceKeepInEdge = form.cleaned_data[ 'toleranceKeepInEdge'] self.rmg.fluxToleranceMoveToCore = form.cleaned_data[ 'toleranceMoveToCore'] self.rmg.fluxToleranceInterrupt = form.cleaned_data[ 'toleranceInterruptSimulation'] self.rmg.maximumEdgeSpecies = form.cleaned_data['maximumEdgeSpecies'] self.rmg.minCoreSizeForPrune = form.cleaned_data['minCoreSizeForPrune'] self.rmg.minSpeciesExistIterationsForPrune = form.cleaned_data[ 'minSpeciesExistIterationsForPrune'] self.rmg.filterReactions = form.cleaned_data['filterReactions'] # Pressure Dependence pdep = form.cleaned_data['pdep'].encode() if pdep != 'off': self.rmg.pressureDependence = PressureDependenceJob(network=None) self.rmg.pressureDependence.method = pdep # Process interpolation model if form.cleaned_data['interpolation'].encode() == 'chebyshev': self.rmg.pressureDependence.interpolationModel = ( form.cleaned_data['interpolation'].encode(), form.cleaned_data['temp_basis'], form.cleaned_data['p_basis']) else: self.rmg.pressureDependence.interpolationModel = ( form.cleaned_data['interpolation'].encode(), ) # Temperature and pressure range self.rmg.pressureDependence.Tmin = Quantity( form.cleaned_data['temp_low'], form.cleaned_data['temprange_units'].encode()) self.rmg.pressureDependence.Tmax = Quantity( form.cleaned_data['temp_high'], form.cleaned_data['temprange_units'].encode()) self.rmg.pressureDependence.Tcount = form.cleaned_data[ 'temp_interp'] self.rmg.pressureDependence.generateTemperatureList() self.rmg.pressureDependence.Pmin = Quantity( form.cleaned_data['p_low'], form.cleaned_data['prange_units'].encode()) self.rmg.pressureDependence.Pmax = Quantity( form.cleaned_data['p_high'], form.cleaned_data['prange_units'].encode()) self.rmg.pressureDependence.Pcount = form.cleaned_data['p_interp'] self.rmg.pressureDependence.generatePressureList() # Process grain size and count self.rmg.pressureDependence.grainSize = Quantity( form.cleaned_data['maximumGrainSize'], form.cleaned_data['grainsize_units'].encode()) self.rmg.pressureDependence.grainCount = form.cleaned_data[ 'minimumNumberOfGrains'] self.rmg.pressureDependence.maximumAtoms = form.cleaned_data[ 'maximumAtoms'] # Additional Options self.rmg.units = 'si' self.rmg.saveRestartPeriod = Quantity( form.cleaned_data['saveRestartPeriod'], form.cleaned_data['saveRestartPeriodUnits'].encode( )) if form.cleaned_data['saveRestartPeriod'] else None self.rmg.generateOutputHTML = form.cleaned_data['generateOutputHTML'] self.rmg.generatePlots = form.cleaned_data['generatePlots'] self.rmg.saveSimulationProfiles = form.cleaned_data[ 'saveSimulationProfiles'] self.rmg.saveEdgeSpecies = form.cleaned_data['saveEdgeSpecies'] self.rmg.verboseComments = form.cleaned_data['verboseComments'] # Species Constraints speciesConstraints = form.cleaned_data['speciesConstraints'] if speciesConstraints == 'on': allowed = [] if form.cleaned_data['allowed_inputSpecies']: allowed.append('input species') if form.cleaned_data['allowed_seedMechanisms']: allowed.append('seed mechanisms') if form.cleaned_data['allowed_reactionLibraries']: allowed.append('reaction libraries') self.rmg.speciesConstraints['allowed'] = allowed self.rmg.speciesConstraints[ 'maximumCarbonAtoms'] = form.cleaned_data['maximumCarbonAtoms'] self.rmg.speciesConstraints[ 'maximumOxygenAtoms'] = form.cleaned_data['maximumOxygenAtoms'] self.rmg.speciesConstraints[ 'maximumNitrogenAtoms'] = form.cleaned_data[ 'maximumNitrogenAtoms'] self.rmg.speciesConstraints[ 'maximumSiliconAtoms'] = form.cleaned_data[ 'maximumSiliconAtoms'] self.rmg.speciesConstraints[ 'maximumSulfurAtoms'] = form.cleaned_data['maximumSulfurAtoms'] self.rmg.speciesConstraints[ 'maximumHeavyAtoms'] = form.cleaned_data['maximumHeavyAtoms'] self.rmg.speciesConstraints[ 'maximumRadicalElectrons'] = form.cleaned_data[ 'maximumRadicalElectrons'] self.rmg.speciesConstraints['allowSingletO2'] = form.cleaned_data[ 'allowSingletO2'] # Quantum Calculations quantumCalc = form.cleaned_data['quantumCalc'] if quantumCalc == 'on': from rmgpy.qm.main import QMCalculator self.rmg.quantumMechanics = QMCalculator( software=form.cleaned_data['software'].encode(), method=form.cleaned_data['method'].encode(), fileStore=form.cleaned_data['fileStore'].encode(), scratchDirectory=form.cleaned_data['scratchDirectory'].encode( ), onlyCyclics=form.cleaned_data['onlyCyclics'], maxRadicalNumber=form.cleaned_data['maxRadicalNumber'], ) # Save the input.py file self.rmg.saveInput(self.savepath)
def test_add_new_surface_objects(self): """ basic test that surface movement object management works properly """ # create object with ReactionSystem behavior class rsys: pass class item: pass T = item() P = item() T.value_si = 1000.0 P.value_si = 101000.0 rsys.T = T rsys.P = P procnum = 2 cerm = CoreEdgeReactionModel() spcA = Species().from_smiles('[OH]') spcs = [Species().from_smiles('CC'), Species().from_smiles('[CH3]')] spc_tuples = [((spcA, spc), ['H_Abstraction']) for spc in spcs] rxns = list(itertools.chain.from_iterable(react(spc_tuples, procnum))) rxns += list( itertools.chain.from_iterable( react([((spcs[0], spcs[1]), ['H_Abstraction'])], procnum))) for rxn in rxns: cerm.make_new_reaction(rxn) cerm.core.species = [spcA] + spcs corerxns = [] edgerxns = [] edgespcs = set() for rxn in rxns: if set(rxn.reactants + rxn.products) <= set(cerm.core.species): corerxns.append(rxn) else: edgespcs |= set( cerm.core.species) - set(rxn.reactants + rxn.products) edgerxns.append(rxn) cerm.edge.species += list(edgespcs) cerm.core.reactions = corerxns cerm.edge.reactions = edgerxns cerm.surface.species = [] cerm.surface.reactions = [] new_surface_reactions = [cerm.edge.reactions[0]] new_surface_species = [] obj = new_surface_reactions cerm.add_new_surface_objects(obj, new_surface_species, new_surface_reactions, rsys) empty = set() self.assertEqual(cerm.new_surface_spcs_add, empty) self.assertEqual(cerm.new_surface_spcs_loss, empty) self.assertEqual(cerm.new_surface_rxns_loss, empty) self.assertEqual(cerm.new_surface_rxns_add, set([cerm.edge.reactions[0]]))
def saveForm(self, posted, form): """ Save form data into input.py file specified by the path. """ # Clean past history self.rmg = RMG() # Databases #self.rmg.databaseDirectory = settings['database.directory'] self.rmg.thermoLibraries = [] if posted.thermo_libraries.all(): self.rmg.thermoLibraries = [ item.thermolib.encode() for item in posted.thermo_libraries.all() ] self.rmg.reactionLibraries = [] self.rmg.seedMechanisms = [] if posted.reaction_libraries.all(): for item in posted.reaction_libraries.all(): if not item.seedmech and not item.edge: self.rmg.reactionLibraries.append( (item.reactionlib.encode(), False)) elif not item.seedmech: self.rmg.reactionLibraries.append( (item.reactionlib.encode(), True)) else: self.rmg.seedMechanisms.append(item.reactionlib.encode()) self.rmg.statmechLibraries = [] self.rmg.kineticsDepositories = ['training'] self.rmg.kineticsFamilies = ['!Intra_Disproportionation'] self.rmg.kineticsEstimator = 'rate rules' # Species self.rmg.initialSpecies = [] speciesDict = {} initialMoleFractions = {} self.rmg.reactionModel = CoreEdgeReactionModel() for item in posted.reactor_species.all(): structure = Molecule().fromAdjacencyList(item.adjlist.encode()) spec, isNew = self.rmg.reactionModel.makeNewSpecies( structure, label=item.name.encode(), reactive=False if item.inert else True) self.rmg.initialSpecies.append(spec) speciesDict[item.name.encode()] = spec initialMoleFractions[spec] = item.molefrac # Reactor systems self.rmg.reactionSystems = [] for item in posted.reactor_systems.all(): T = Quantity(item.temperature, item.temperature_units.encode()) P = Quantity(item.pressure, item.pressure_units.encode()) termination = [] if item.conversion: termination.append( TerminationConversion(speciesDict[item.species.encode()], item.conversion)) termination.append( TerminationTime( Quantity(item.terminationtime, item.time_units.encode()))) system = SimpleReactor(T, P, initialMoleFractions, termination) self.rmg.reactionSystems.append(system) # Simulator tolerances self.rmg.absoluteTolerance = form.cleaned_data['simulator_atol'] self.rmg.relativeTolerance = form.cleaned_data['simulator_rtol'] self.rmg.fluxToleranceKeepInEdge = form.cleaned_data[ 'toleranceKeepInEdge'] self.rmg.fluxToleranceMoveToCore = form.cleaned_data[ 'toleranceMoveToCore'] self.rmg.fluxToleranceInterrupt = form.cleaned_data[ 'toleranceInterruptSimulation'] self.rmg.maximumEdgeSpecies = form.cleaned_data['maximumEdgeSpecies'] # Pressure Dependence pdep = form.cleaned_data['pdep'].encode() if pdep != 'off': self.rmg.pressureDependence = MEASURE() self.rmg.pressureDependence.method = pdep # Temperature and pressure range interpolation = (form.cleaned_data['interpolation'].encode(), form.cleaned_data['temp_basis'], form.cleaned_data['p_basis']) self.rmg.pressureDependence.Tmin = Quantity( form.cleaned_data['temp_low'], form.cleaned_data['temprange_units'].encode()) self.rmg.pressureDependence.Tmax = Quantity( form.cleaned_data['temp_high'], form.cleaned_data['temprange_units'].encode()) self.rmg.pressureDependence.Tcount = form.cleaned_data[ 'temp_interp'] Tlist = getTemperaturesForModel( interpolation, self.rmg.pressureDependence.Tmin.value, self.rmg.pressureDependence.Tmax.value, self.rmg.pressureDependence.Tcount) self.rmg.pressureDependence.Tlist = Quantity(Tlist, "K") self.rmg.pressureDependence.Pmin = Quantity( form.cleaned_data['p_low'], form.cleaned_data['prange_units'].encode()) self.rmg.pressureDependence.Pmax = Quantity( form.cleaned_data['p_high'], form.cleaned_data['prange_units'].encode()) self.rmg.pressureDependence.Pcount = form.cleaned_data['p_interp'] Plist = getPressuresForModel( interpolation, self.rmg.pressureDependence.Pmin.value, self.rmg.pressureDependence.Pmax.value, self.rmg.pressureDependence.Pcount) self.rmg.pressureDependence.Plist = Quantity(Plist, "Pa") # Process grain size and count self.rmg.pressureDependence.grainSize = Quantity( form.cleaned_data['maximumGrainSize'], form.cleaned_data['grainsize_units'].encode()) self.rmg.pressureDependence.grainCount = form.cleaned_data[ 'minimumNumberOfGrains'] # Process interpolation model self.rmg.pressureDependence.model = interpolation # Additional Options self.rmg.units = 'si' self.rmg.saveRestartPeriod = Quantity( form.cleaned_data['saveRestartPeriod'], form.cleaned_data['saveRestartPeriodUnits'].encode( )) if form.cleaned_data['saveRestartPeriod'] else None self.rmg.drawMolecules = form.cleaned_data['drawMolecules'] self.rmg.generatePlots = form.cleaned_data['generatePlots'] self.rmg.saveConcentrationProfiles = form.cleaned_data[ 'saveConcentrationProfiles'] # Save the input.py file self.rmg.saveInput(self.savepath)
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)
# Create ignition delay calculation folder if not os.path.exists(ignitionDelayFolder): os.makedirs(ignitionDelayFolder) shutil.copy(mechFileCti, os.path.join(ignitionDelayFolder, mechFileCti)) # Create pathway calculation folder if not os.path.exists(pathwayFolder): os.makedirs(pathwayFolder) shutil.copy(mechFileCti, os.path.join(pathwayFolder, mechFileCti)) shutil.move(pathwayFile, os.path.join(pathwayFolder, pathwayFile)) # Generate HTML file if not os.path.isfile(os.path.join(mechFolder, mechHTML)): print 'create reaction model...' model = CoreEdgeReactionModel() print 'load chemkin file...' model.core.species, model.core.reactions = loadChemkinFile( os.path.join(mechFolder, mechFileInp), os.path.join(mechFolder, spcFile)) print 'save HTML file...' saveOutputHTML(os.path.join(mechFolder, mechHTML), model) print 'finished!' # Copy the 'species' folder generated during the generation of HTML file to the 'pathway' folder. Rename the copy as 'structure' structureDir = os.path.join(pathwayFolder, structureFolder) if not os.path.exists(structureDir): shutil.copytree(os.path.join(mechFolder, spcFolder), structureDir) for filename in os.listdir(structureDir): if filename.endswith(').png'): filename = os.path.join(structureDir, filename)