def loadDatabase(self, kineticsFamilies='all',kineticsDepositories=None,thermoLibraries=None, reactionLibraries=None): """ This function loads a single copy of the RMGDatabase with full verbose averaging of the rate rule to trace kinetics sources. By default, this function loads all the kinetics families, only the training kinetics depository, the primaryThermoLibrary, and no reaction libraries. """ from rmgpy.data.rmg import RMGDatabase from rmgpy import settings if not kineticsDepositories: kineticsDepositories = ['training'] if not thermoLibraries: thermoLibraries = ['primaryThermoLibrary'] if not reactionLibraries: reactionLibraries = [] self.database = RMGDatabase() self.database.load(settings['database.directory'], kineticsFamilies=kineticsFamilies, kineticsDepositories=kineticsDepositories, thermoLibraries=thermoLibraries, reactionLibraries=reactionLibraries, ) # Prepare the database by loading training reactions but not averaging the rate rules for familyLabel, family in self.database.kinetics.families.iteritems(): family.addKineticsRulesFromTrainingSet(thermoDatabase=self.database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True)
def setUpModule(): """A function that is run ONCE before all unit tests in this module.""" global database database = RMGDatabase() database.load( path=os.path.join(settings['test_data.directory'], 'testing_database'), thermoLibraries=['primaryThermoLibrary'], reactionLibraries=['GRI-Mech3.0'], kineticsFamilies=[ 'R_Recombination', 'Disproportionation', 'R_Addition_MultipleBond', 'H_Abstraction', 'intra_H_migration', ], testing=True, depository=False, solvation=False, ) #load empty forbidden structures to avoid any dependence on forbidden structures #for these tests for family in database.kinetics.families.values(): family.forbidden = ForbiddenStructures() database.forbiddenStructures = ForbiddenStructures() # Prepare the database by loading training reactions and averaging the rate rules for family in database.kinetics.families.values(): family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True)
def convertPrIMe(family): print 'Loading kinetics families...' database = RMGDatabase() database.kinetics = KineticsDatabase() database.kinetics.loadFamilies('input/kinetics/families') database.loadForbiddenStructures('input/forbiddenStructures.py') for depository in database.kinetics.families[family].depositories: if depository.label == '{0}/PrIMe'.format(family): break else: raise Exception( 'Could not find PrIMe depository in {0} family.'.format(family)) entries = [] print 'Determining unique list of reactions...' for entry0 in depository.entries.values(): for entry in entries: if entry.item.isIsomorphic(entry0.item): break else: entries.append(entry0) print 'Found {0:d} unique reactions out of {1:d} entries.'.format( len(entries), len(depository.entries)) print 'Sorting unique reactions...' entries.sort(key=lambda entry: sum([ 1 for r in entry.item.reactants for a in r.atoms if a.isNonHydrogen() ])) print 'Saving reactions...' for index, entry in enumerate(entries): label = entry.label reaction = entry.item # Determine degeneracy in both directions reactions = database.kinetics.generateReactionsFromFamilies( reaction.reactants, reaction.products, only_families=[family]) if len(reactions) != 1: print 'Warning: could not determine forward degeneracy for reaction #{0:d}.'.format( index + 1) forwardDegeneracy = 1 else: forwardDegeneracy = reactions[0].degeneracy reactions = database.kinetics.generateReactionsFromFamilies( reaction.products, reaction.reactants, only_families=[family]) if len(reactions) != 1: print 'Warning: could not determine reverse degeneracy for reaction #{0:d}.'.format( index + 1) reverseDegeneracy = 1 else: reverseDegeneracy = reactions[0].degeneracy saveReaction( 'input/kinetics/families/{0}/training/{0}.py'.format( family, index + 1), index + 1, label, reaction, forwardDegeneracy, reverseDegeneracy)
def setUpModule(): """A function that is run ONCE before all unit tests in this module.""" global database database = RMGDatabase() database.load( path=os.path.join(settings['test_data.directory'], 'testing_database'), thermoLibraries=['primaryThermoLibrary'], reactionLibraries=['GRI-Mech3.0'], kineticsFamilies=[ 'R_Recombination', 'Disproportionation', 'R_Addition_MultipleBond', 'H_Abstraction' ], testing=True, depository=False, solvation=False, ) #load empty forbidden structures to avoid any dependence on forbidden structures #for these tests for family in database.kinetics.families.values(): family.forbidden = ForbiddenStructures() database.forbiddenStructures = ForbiddenStructures() # Prepare the database by loading training reactions and averaging the rate rules for family in database.kinetics.families.values(): family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True)
def main(): initialize_log(logging.INFO, 'treegen.log') dbdir = settings['database.directory'] family_name = parse_arguments() database = RMGDatabase() database.load( path=dbdir, thermo_libraries=['Klippenstein_Glarborg2016', 'BurkeH2O2', 'thermo_DFT_CCSDTF12_BAC', 'DFT_QCI_thermo', 'primaryThermoLibrary', 'primaryNS', 'NitrogenCurran', 'NOx2018', 'FFCM1(-)', 'SulfurLibrary', 'SulfurGlarborgH2S', 'SABIC_aromatics'], transport_libraries=[], reaction_libraries=[], seed_mechanisms=[], kinetics_families=[family_name], kinetics_depositories=['training'], # frequenciesLibraries = self.statmechLibraries, depository=False, # Don't bother loading the depository information, as we don't use it ) family = database.kinetics.families[family_name] num_training_rxns = len(family.get_training_depository().entries) max_batch_size = 800 family.clean_tree() if (num_training_rxns/max_batch_size > 1) and (num_training_rxns/max_batch_size <= 1.3): family.generate_tree(thermo_database=database.thermo, nprocs=1, max_batch_size=num_training_rxns) else: family.generate_tree(thermo_database=database.thermo, nprocs=1) family.check_tree() family.regularize() template_rxn_map = family.get_reaction_matches(thermo_database=database.thermo, remove_degeneracy=True, get_reverse=True, fix_labels=True) family.make_bm_rules_from_template_rxn_map(template_rxn_map, nprocs=1) family.check_tree() family.save(os.path.join(dbdir, 'kinetics', 'families', family_name))
def load_families_only(rmgdb: RMGDatabase, kinetics_families: Union[str, list] = 'default'): """ A helper function for loading kinetic families from RMG's database. Args: rmgdb (RMGDatabase): The RMG database instance. kinetics_families (Union[str, list], optional): Specific kinetics families to load. """ if kinetics_families not in ('default', 'all', 'none') and not isinstance( kinetics_families, list): raise InputError( f"kinetics families should be either 'default', 'all', 'none', or a list of names, e.g.," f" ['H_Abstraction','R_Recombination'] or ['!Intra_Disproportionation']. " f"Got:\n{kinetics_families}") logger.debug('\n\nLoading only kinetic families from the RMG database...') rmgdb.load( path=db_path, thermo_libraries=list(), transport_libraries='none', reaction_libraries=list(), seed_mechanisms=list(), kinetics_families=kinetics_families, kinetics_depositories=['training'], depository=False, )
def main(): initializeLog(logging.INFO,'treegen.log') dbdir = settings['database.directory'] familyName, nprocs = parse_arguments() database = RMGDatabase() database.load( path=dbdir, thermoLibraries=['Klippenstein_Glarborg2016', 'BurkeH2O2', 'thermo_DFT_CCSDTF12_BAC', 'DFT_QCI_thermo', 'primaryThermoLibrary', 'primaryNS', 'NitrogenCurran', 'NOx2018', 'FFCM1(-)', 'SulfurLibrary', 'SulfurGlarborgH2S'], transportLibraries=[], reactionLibraries=[], seedMechanisms=[], kineticsFamilies=[familyName], kineticsDepositories=['training'], # frequenciesLibraries = self.statmechLibraries, depository=False, # Don't bother loading the depository information, as we don't use it ) family = database.kinetics.families[familyName] family.cleanTree(database.thermo) family.generateTree(thermoDatabase=database.thermo, nprocs=min(4, nprocs)) family.checkTree() family.regularize() templateRxnMap = family.getReactionMatches(thermoDatabase=database.thermo, removeDegeneracy=True, getReverse=True, fixLabels=True) family.makeBMRulesFromTemplateRxnMap(templateRxnMap, nprocs=min(6, nprocs)) family.checkTree() family.save(os.path.join(dbdir,'kinetics','families',familyName))
def simple_react(n_cp, n_iter): # load RMG database to create reactions database = RMGDatabase() database.load( path=settings['database.directory'], thermoLibraries=['primaryThermoLibrary' ], # can add others if necessary kineticsFamilies='all', reactionLibraries=[], kineticsDepositories='') kinetics_db = database.kinetics mol0 = Molecule().fromSMILES('CCCCCCCCC1CCCc2ccccc21') mol1 = Molecule().fromSMILES('CCCCCCCCC1CCCC2C=CC=CC=21') mol_tuple = (mol0, mol1) reactions = [] for i in range(n_iter): mol_tuples = [mol_tuple] * n_cp results = map_(react_molecules_wrapper, mol_tuples) reactions_iter = itertools.chain.from_iterable(results) print "{0} iter: {1} reactions.".format(i, len(list(reactions_iter)))
def setUp(self): rmg_database = RMGDatabase() rmg_database.load( rmgpy.settings['database.directory'], kinetics_families=[ "R_Addition_MultipleBond", "H_Abstraction", "intra_H_migration" ], transport_libraries=[], reaction_libraries=[], seed_mechanisms=[], thermo_libraries=[ 'primaryThermoLibrary', 'thermo_DFT_CCSDTF12_BAC', 'CBS_QB3_1dHR'], solvation=False, ) self.rmg_database = rmg_database ts_database = TransitionStates() path = os.path.join(autotst.settings["tst_database_path"], "H_Abstraction") global_context = {'__builtins__': None} local_context = {'DistanceData': DistanceData} family = self.rmg_database.kinetics.families["H_Abstraction"] ts_database.family = family ts_database.load(path, local_context, global_context) self.ts_database = ts_database
def loadDatabase(): print 'Loading RMG database...' from rmgpy.data.rmg import RMGDatabase database = RMGDatabase() database.load(settings['database.directory'], kineticsFamilies='all', kineticsDepositories='all') return database
def TS_Database_Update(families, path=None, auto_save=False): """ Expects list of reaction families Loads RMG Databse, Creaes instance of TS_updater for each reaction family in families, Return dictionary of family:family's instance of the updater """ assert isinstance( families, list ), "Families must be a list. If singular family, still keep it in list" acceptable_families = os.listdir( os.path.join(os.path.expandvars("$RMGpy"), "..", "AutoTST", "database")) for family in families: assert isinstance(family, str), "Family names must be provided as strings" if family.upper() not in (family.upper() for family in acceptable_families): logging.warning( '"{}" is not a known Kinetics Family'.format(family)) families.remove(family) logging.info("Loading RMG Database...") rmg_database = RMGDatabase() database_path = os.path.join(os.path.expandvars('$RMGpy'), "..", 'RMG-database', 'input') try: rmg_database.load( database_path, # kineticsFamilies=['H_Abstraction'], kineticsFamilies=families, transportLibraries=[], reactionLibraries=[], seedMechanisms=[], thermoLibraries=[ 'primaryThermoLibrary', 'thermo_DFT_CCSDTF12_BAC', 'CBS_QB3_1dHR' ], solvation=False, ) except: logging.error( "Failed to Load RMG Database at {}".format(database_path)) Databases = { family: TS_Updater(family, rmg_database, path=path) for family in families } if auto_save == True: save_all_individual_databases(Databases) return Databases
def main(dictionary): database = RMGDatabase() database.loadTransport(path=os.path.join(settings['database.directory'], 'transport'), transportLibraries=None) speciesDict = loadSpeciesDictionary(dictionary) saveTransportFile('tran.dat', speciesDict.values())
def __init__(self): self.database = RMGDatabase() self.database.kinetics = KineticsDatabase() self.database.thermo = ThermoDatabase() self.database.transport = TransportDatabase() self.database.statmech = StatmechDatabase() self.database.solvation = SolvationDatabase() self.database.load_forbidden_structures( os.path.join(rmgweb.settings.DATABASE_PATH, 'forbiddenStructures.py')) self.timestamps = {}
def loadDatabase(args): print 'Loading RMG database...' from rmgpy.data.rmg import RMGDatabase rmgDatabase = RMGDatabase() rmgDatabase.load('/Users/belinda/Code/RMG-database/input', kineticsFamilies=args.family) rxnFamily = rmgDatabase.kinetics.families[args.family[0]] database = rxnFamily.solvationCorrections return database, rmgDatabase
def export(input, output, database=None): print 'Loading the new RMG-Py database...' if not database: database = RMGDatabase() database.load(input) print 'Constructing additional rate rules from kinetics depository...' for family in database.kinetics.families.values(): generateRules(family, database) print 'Saving old RMG-Java database...' database.saveOld(output)
def database_setup(): # load RMG database to create reactions database = RMGDatabase() database.load( path = settings['database.directory'], thermoLibraries = ['primaryThermoLibrary'], # can add others if necessary kineticsFamilies = 'all', reactionLibraries = [], kineticsDepositories = '' ) thermodb = database.thermo print thermodb.libraries.keys()
def load(): tearDown() rmg = RMG()#for solvent database = RMGDatabase() database.loadThermo(os.path.join(settings['database.directory'], 'thermo')) database.loadTransport(os.path.join(settings['database.directory'], 'transport')) database.loadSolvation(os.path.join(settings['database.directory'], 'solvation'))
def convertPrIMe(family): print 'Loading kinetics families...' database = RMGDatabase() database.kinetics = KineticsDatabase() database.kinetics.loadFamilies('input/kinetics/families') database.loadForbiddenStructures('input/forbiddenStructures.py') for depository in database.kinetics.families[family].depositories: if depository.label == '{0}/PrIMe'.format(family): break else: raise Exception('Could not find PrIMe depository in {0} family.'.format(family)) entries = [] print 'Determining unique list of reactions...' for entry0 in depository.entries.values(): for entry in entries: if entry.item.isIsomorphic(entry0.item): break else: entries.append(entry0) print 'Found {0:d} unique reactions out of {1:d} entries.'.format(len(entries), len(depository.entries)) print 'Sorting unique reactions...' entries.sort(key=lambda entry: sum([1 for r in entry.item.reactants for a in r.atoms if a.isNonHydrogen()])) print 'Saving reactions...' for index, entry in enumerate(entries): label = entry.label reaction = entry.item # Determine degeneracy in both directions reactions = database.kinetics.generateReactionsFromFamilies(reaction.reactants, reaction.products, only_families=[family]) if len(reactions) != 1: print 'Warning: could not determine forward degeneracy for reaction #{0:d}.'.format(index+1) forwardDegeneracy = 1 else: forwardDegeneracy = reactions[0].degeneracy reactions = database.kinetics.generateReactionsFromFamilies(reaction.products, reaction.reactants, only_families=[family]) if len(reactions) != 1: print 'Warning: could not determine reverse degeneracy for reaction #{0:d}.'.format(index+1) reverseDegeneracy = 1 else: reverseDegeneracy = reactions[0].degeneracy saveReaction('input/kinetics/families/{0}/training/{0}.py'.format(family, index+1), index+1, label, reaction, forwardDegeneracy, reverseDegeneracy)
def setUpClass(cls): """A function run ONCE before all unit tests in this class.""" # Set up a dummy database cls.database = RMGDatabase() cls.database.load( path=os.path.join(settings['test_data.directory'], 'testing_database'), thermoLibraries=[], reactionLibraries=[], kineticsFamilies=[], depository=False, solvation=False, testing=True, ) cls.database.loadForbiddenStructures() cls.thermoDatabase = ThermoDatabase() #the real full Thermo Database cls.thermoDatabase.load(path=os.path.join( settings['database.directory'], 'thermo'), libraries=['primaryThermoLibrary']) cls.kineticsDatabase = KineticsDatabase() cls.kineticsDatabase.loadFamilies( path=os.path.join(settings['test_data.directory'], 'testing_database/kinetics/families'), families=[ 'Singlet_Carbene_Intra_Disproportionation', ], ) cls.family = cls.kineticsDatabase.families[ 'Singlet_Carbene_Intra_Disproportionation']
def setUpClass(cls): """ Load the database before running the tests. """ databaseDirectory = settings['database.directory'] cls.database = RMGDatabase() cls.database.load(databaseDirectory, kineticsFamilies='all')
def export(input, output, database=None): print 'Loading the new RMG-Py database...' if not database: database = RMGDatabase() database.load(input, kineticsFamilies='all', kineticsDepositories='all') print 'Constructing additional rate rules from kinetics depository...' for family in database.kinetics.families.values(): family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) print "Deleting thermo library entries with atoms RMG-Java can't understand..." database.thermo.pruneHeteroatoms(allowed=['C','H','O','S']) print 'Saving old RMG-Java database...' database.saveOld(output) print "Done!"
def setUpClass(cls): """This method is run once before all tests in this class.""" test_dir = rmgpy.settings['test_data.directory'] data_dir = os.path.join(test_dir, 'testing_database') chem_dir = os.path.join(test_dir, 'parsing_data') chemkin_file = os.path.join(chem_dir, 'chem_annotated.inp') spc_dict = os.path.join(chem_dir, 'species_dictionary.txt') cls.uncertainty = Uncertainty(outputDirectory='chemDir') cls.uncertainty.loadModel(chemkin_file, spc_dict) # load database properly cls.uncertainty.database = RMGDatabase() cls.uncertainty.database.load( data_dir, kineticsFamilies='all', kineticsDepositories=['training'], thermoLibraries=['primaryThermoLibrary'], reactionLibraries=['GRI-Mech3.0'], ) # Prepare the database by loading training reactions and averaging the rate rules verbosely for family in cls.uncertainty.database.kinetics.families.itervalues(): family.addKineticsRulesFromTrainingSet( thermoDatabase=cls.uncertainty.database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True)
def testGetRingGroupsFromComments(self): """ Test that getRingGroupsFromComments method works for fused polycyclics. """ from rmgpy.thermo.thermoengine import generateThermoData # set-up RMG object rmg = RMG() # load kinetic database and forbidden structures rmg.database = RMGDatabase() path = os.path.join(settings['database.directory']) # forbidden structure loading rmg.database.loadThermo(os.path.join(path, 'thermo')) smi = 'C12C(C3CCC2C3)C4CCC1C4' #two norbornane rings fused together spc = Species().fromSMILES(smi) spc.thermo = generateThermoData(spc) thermodb = rmg.database.thermo thermodb.getRingGroupsFromComments(spc.thermo) import rmgpy.data.rmg rmgpy.data.rmg.database = None
def setUpClass(cls): """A function run ONCE before all unit tests in this class.""" # Set up a dummy database cls.database = RMGDatabase() cls.database.load( path=os.path.join(settings['test_data.directory'], 'testing_database'), thermo_libraries=[], reaction_libraries=[], kinetics_families=[], depository=False, solvation=False, testing=True, ) cls.database.load_forbidden_structures() cls.thermoDatabase = ThermoDatabase() # the real full Thermo Database cls.thermoDatabase.load(path=os.path.join(settings['database.directory'], 'thermo'), libraries=['primaryThermoLibrary']) cls.kineticsDatabase = KineticsDatabase() cls.kineticsDatabase.load_families( path=os.path.join(settings['test_data.directory'], 'testing_database/kinetics/families'), families=[ 'Singlet_Carbene_Intra_Disproportionation', ], ) cls.family = cls.kineticsDatabase.families['Singlet_Carbene_Intra_Disproportionation'] cls.treerxns = cls.family.get_training_set(thermo_database=cls.thermoDatabase, remove_degeneracy=True, estimate_thermo=True, fix_labels=True, get_reverse=True)
def setUpClass(cls): """This method is run once before all tests in this class.""" test_dir = rmgpy.settings['test_data.directory'] data_dir = os.path.join(test_dir, 'testing_database') chem_dir = os.path.join(test_dir, 'parsing_data') chemkin_file = os.path.join(chem_dir, 'chem_annotated.inp') spc_dict = os.path.join(chem_dir, 'species_dictionary.txt') cls.uncertainty = Uncertainty(outputDirectory='chemDir') cls.uncertainty.loadModel(chemkin_file, spc_dict) # load database properly cls.uncertainty.database = RMGDatabase() cls.uncertainty.database.load( data_dir, kineticsFamilies=[ '1,2_shiftC', '6_membered_central_C-C_shift', 'Disproportionation', 'H_Abstraction', 'Intra_ene_reaction', 'intra_H_migration', 'Intra_R_Add_Exo_scission', 'intra_substitutionS_isomerization', 'R_Addition_MultipleBond', 'R_Recombination' ], kineticsDepositories=['training'], thermoLibraries=['primaryThermoLibrary'], reactionLibraries=['GRI-Mech3.0'], ) # Prepare the database by loading training reactions and averaging the rate rules verbosely for family in cls.uncertainty.database.kinetics.families.itervalues(): family.addKineticsRulesFromTrainingSet( thermoDatabase=cls.uncertainty.database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True)
def loadDatabase(component='', section=''): """ Load the requested `component` of the RMG database if modified since last loaded. """ global database if not database: database = RMGDatabase() database.thermo = ThermoDatabase() database.kinetics = KineticsDatabase() database.loadForbiddenStructures(os.path.join(settings.DATABASE_PATH, 'forbiddenStructures.py')) if component in ['thermo', '']: if section in ['depository', '']: dirpath = os.path.join(settings.DATABASE_PATH, 'thermo', 'depository') if isDirModified(dirpath): database.thermo.loadDepository(dirpath) resetDirTimestamps(dirpath) if section in ['libraries', '']: dirpath = os.path.join(settings.DATABASE_PATH, 'thermo', 'libraries') if isDirModified(dirpath): database.thermo.loadLibraries(dirpath) # put them in our preferred order, so that when we look up thermo in order to estimate kinetics, # we use our favourite values first. preferred_order = ['primaryThermoLibrary','DFT_QCI_thermo','GRI-Mech3.0','CBS_QB3_1dHR','KlippensteinH2O2'] new_order = [i for i in preferred_order if i in database.thermo.libraryOrder] for i in database.thermo.libraryOrder: if i not in new_order: new_order.append(i) database.thermo.libraryOrder = new_order resetDirTimestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(settings.DATABASE_PATH, 'thermo', 'groups') if isDirModified(dirpath): database.thermo.loadGroups(dirpath) resetDirTimestamps(dirpath) if component in ['kinetics', '']: if section in ['libraries', '']: dirpath = os.path.join(settings.DATABASE_PATH, 'kinetics', 'libraries') if isDirModified(dirpath): database.kinetics.loadLibraries(dirpath) resetDirTimestamps(dirpath) if section in ['families', '']: dirpath = os.path.join(settings.DATABASE_PATH, 'kinetics', 'families') if isDirModified(dirpath): database.kinetics.loadFamilies(dirpath) resetDirTimestamps(dirpath) return database
def database( thermoLibraries = None, transportLibraries = None, reactionLibraries = None, frequenciesLibraries = None, kineticsFamilies = 'default', kineticsDepositories = 'default', kineticsEstimator = 'rate rules', ): if isinstance(thermoLibraries, str): thermoLibraries = [thermoLibraries] if isinstance(transportLibraries, str): transportLibraries = [transportLibraries] if isinstance(reactionLibraries, str): reactionLibraries = [reactionLibraries] if isinstance(frequenciesLibraries, str): frequenciesLibraries = [frequenciesLibraries] databaseDirectory = settings['database.directory'] thermoLibraries = thermoLibraries or [] transportLibraries = transportLibraries reactionLibraries = reactionLibraries or [] kineticsEstimator = kineticsEstimator if kineticsDepositories == 'default': kineticsDepositories = ['training'] elif kineticsDepositories == 'all': kineticsDepositories = None else: if not isinstance(kineticsDepositories,list): raise InputError("kineticsDepositories should be either 'default', 'all', or a list of names eg. ['training','PrIMe'].") kineticsDepositories = kineticsDepositories if kineticsFamilies in ('default', 'all', 'none'): kineticsFamilies = kineticsFamilies else: if not isinstance(kineticsFamilies,list): raise InputError("kineticsFamilies should be either 'default', 'all', 'none', or a list of names eg. ['H_Abstraction','R_Recombination'] or ['!Intra_Disproportionation'].") kineticsFamilies = kineticsFamilies database = getDB() or RMGDatabase() database.load( path = databaseDirectory, thermoLibraries = thermoLibraries, transportLibraries = transportLibraries, reactionLibraries = reactionLibraries, seedMechanisms = [], kineticsFamilies = kineticsFamilies, kineticsDepositories = kineticsDepositories, depository = False, # Don't bother loading the depository information, as we don't use it ) for family in database.kinetics.families.values(): #load training family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) for family in database.kinetics.families.values(): family.fillKineticsRulesByAveragingUp(verbose=True)
def __init__(self): self.database = RMGDatabase() self.database.kinetics = KineticsDatabase() self.database.thermo = ThermoDatabase() self.database.transport = TransportDatabase() self.database.statmech = StatmechDatabase() self.database.solvation = SolvationDatabase() self.database.loadForbiddenStructures(os.path.join(rmgweb.settings.DATABASE_PATH, 'forbiddenStructures.py')) self.timestamps = {}
def make_rmg_database_object(): """ Make a clean RMGDatabase object. Returns: RMGDatabase A clean RMG database object. """ rmgdb = RMGDatabase() return rmgdb
def loadNecessaryDatabases(): """ loads transport and statmech databases """ from rmgpy.data.statmech import StatmechDatabase from rmgpy.data.transport import TransportDatabase #only load if they are not there already. try: getDB('transport') getDB('statmech') except DatabaseError: logging.info("Databases not found. Making databases") db = RMGDatabase() db.statmech = StatmechDatabase() db.statmech.load(os.path.join(settings['database.directory'],'statmech')) db.transport = TransportDatabase() db.transport.load(os.path.join(settings['database.directory'],'transport'))
def simple_react(): # load RMG database to create reactions database = RMGDatabase() database.load( path = settings['database.directory'], thermoLibraries = ['primaryThermoLibrary'], # can add others if necessary kineticsFamilies = 'all', reactionLibraries = [], kineticsDepositories = '' ) kinetics_db = database.kinetics mol = Molecule().fromSMILES('CC') reactants = [mol] return kinetics_db.react_molecules(reactants, only_families=['R_Recombination'], prod_resonance=False)
def setUp(self): """ A function run before each unit test in this class. """ # load kinetics database db_path = settings['database.directory'] self.database = RMGDatabase() # forbidden structure loading self.database.loadForbiddenStructures( os.path.join(db_path, 'forbiddenStructures.py')) # kinetics family loading self.database.loadKinetics(os.path.join(db_path, 'kinetics'), kineticsFamilies=[ 'R_Recombination', 'H_Abstraction', '1,2_Insertion_carbene' ], reactionLibraries=[])
def setUpModule(): """A function that is run ONCE before all unit tests in this module.""" global database database = RMGDatabase() database.load( path=os.path.join(settings['test_data.directory'], 'testing_database'), kineticsFamilies=[ 'H_Abstraction','intra_H_migration' ], testing=True, depository=False, solvation=False, ) database.loadForbiddenStructures() # Prepare the database by loading training reactions and averaging the rate rules for family in database.kinetics.families.values(): family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True)
def database(thermoLibraries=None, transportLibraries=None, reactionLibraries=None, frequenciesLibraries=None, kineticsFamilies='default', kineticsDepositories='default', kineticsEstimator='rate rules'): """Load the RMG database""" thermo_libraries = as_list(thermoLibraries, default=[]) transport_libraries = as_list(transportLibraries, default=None) reaction_libraries = as_list(reactionLibraries, default=[]) database_directory = settings['database.directory'] if kineticsDepositories == 'default': kinetics_depositories = ['training'] elif kineticsDepositories == 'all': kinetics_depositories = None else: if not isinstance(kineticsDepositories, list): raise InputError( "kinetics_depositories should be either 'default', 'all', or a list of names eg. ['training','PrIMe']." ) kinetics_depositories = kineticsDepositories if kineticsFamilies in ('default', 'all', 'none'): kinetics_families = kineticsFamilies else: if not isinstance(kineticsFamilies, list): raise InputError( "kineticsFamilies should be either 'default', 'all', 'none', or a list of names eg. " "['H_Abstraction','R_Recombination'] or ['!Intra_Disproportionation']." ) kinetics_families = kineticsFamilies rmg_database = get_db() or RMGDatabase() rmg_database.load( path=database_directory, thermo_libraries=thermo_libraries, transport_libraries=transport_libraries, reaction_libraries=reaction_libraries, seed_mechanisms=[], kinetics_families=kinetics_families, kinetics_depositories=kinetics_depositories, depository= False, # Don't bother loading the depository information, as we don't use it ) for family in rmg_database.kinetics.families.values(): # load training if not family.auto_generated: family.add_rules_from_training(thermo_database=rmg_database.thermo) for family in rmg_database.kinetics.families.values(): family.fill_rules_by_averaging_up(verbose=True)
def loadDatabase(self): self.database = RMGDatabase() self.database.load( path = self.databaseDirectory, thermoLibraries = self.thermoLibraries, reactionLibraries = [library for library, option in self.reactionLibraries], seedMechanisms = self.seedMechanisms, kineticsDepositories = self.kineticsDepositories, #frequenciesLibraries = self.statmechLibraries, depository = False, # Don't bother loading the depository information, as we don't use it )
def setUpClass(cls): """ A method that is run before each unit test in this class. """ # set-up RMG object cls.rmg = RMG() # load kinetic database and forbidden structures cls.rmg.database = RMGDatabase() path = os.path.join(settings['database.directory']) # forbidden structure loading cls.rmg.database.load_thermo(os.path.join(path, 'thermo'))
def testToWilhoit(self): """ Test if the entropy computed from other thermo implementations is close to what Wilhoit computes. """ from rmgpy import settings from rmgpy.data.rmg import RMGDatabase, database from rmgpy.species import Species # Load databases database = RMGDatabase() database.loadThermo(os.path.join(settings['database.directory'], 'thermo'), thermoLibraries=['Narayanaswamy']) database.loadSolvation( os.path.join(settings['database.directory'], 'solvation')) spc = Species().fromSMILES('CC') spc.getThermoData() T = 1350. # not 298K! # nasa to wilhoit nasa = spc.thermo Snasa = nasa.getEntropy(T) nasaToWh = nasa.toWilhoit() SnasaToWh = nasaToWh.getEntropy(T) self.assertAlmostEqual(Snasa, SnasaToWh, -1) self.assertEqual(nasa.comment, nasaToWh.comment) # wilhoit to nasa conversion done in nasaTest.py # thermo data to wilhoit: td = nasa.toThermoData() Std = td.getEntropy(T) wilhoit = td.toWilhoit(B=1000.) Swh = wilhoit.getEntropy(T) self.assertAlmostEqual(Std, Swh, -1) self.assertEqual(td.comment, wilhoit.comment) # wilhoit back to thermodata td = wilhoit.toThermoData() Std = td.getEntropy(T) self.assertAlmostEqual(Std, Swh, -1) self.assertEqual(td.comment, wilhoit.comment)
def setUpClass(cls): """A function run ONCE before all unit tests in this class.""" # Set up a dummy database cls.database = RMGDatabase() cls.database.load( path=os.path.join(settings['test_data.directory'], 'testing_database'), thermoLibraries=[], reactionLibraries=[], kineticsFamilies=['H_Abstraction'], depository=False, solvation=False, testing=True, ) cls.database.loadForbiddenStructures()
def loadDatabase(self): self.database = RMGDatabase() self.database.load( path = self.databaseDirectory, thermoLibraries = self.thermoLibraries, reactionLibraries = [library for library, option in self.reactionLibraries], seedMechanisms = self.seedMechanisms, kineticsFamilies = self.kineticsFamilies, kineticsDepositories = self.kineticsDepositories, #frequenciesLibraries = self.statmechLibraries, depository = False, # Don't bother loading the depository information, as we don't use it ) if self.kineticsEstimator == 'rate rules': logging.info('Adding rate rules from training set in kinetics families...') for family in self.database.kinetics.families.values(): family.addKineticsRulesFromTrainingSet(thermoDatabase=self.database.thermo) logging.info('Filling in rate rules in kinetics families by averaging...') for family in self.database.kinetics.families.values(): family.fillKineticsRulesByAveragingUp()
data = kinetics, reference = entry0.reference, rank = entry0.rank, shortDesc = entry0.shortDesc, longDesc = entry0.longDesc, history = entry0.history, ) # Add the new rate rule to the depository of rate rules rules.entries[entry.index] = entry index += 1 ################################################################################ if __name__ == '__main__': oldPath = 'output/RMG_database' newPath = 'input' print 'Loading the new RMG-Py database...' database = RMGDatabase() database.load(newPath) print 'Constructing additional rate rules from kinetics depository...' for family in database.kinetics.groups: generateAdditionalRateRules(family, database) print 'Saving old RMG-Java database...' database.saveOld(oldPath)
def loadDatabase(): print 'Loading RMG database...' from rmgpy.data.rmg import RMGDatabase database = RMGDatabase() database.load('input') return database
# copy of this software and associated documentation files (the 'Software'), # # to deal in the Software without restriction, including without limitation # # the rights to use, copy, modify, merge, publish, distribute, sublicense, # # and/or sell copies of the Software, and to permit persons to whom the # # Software is furnished to do so, subject to the following conditions: # # # # The above copyright notice and this permission notice shall be included in # # all copies or substantial portions of the Software. # # # # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # # DEALINGS IN THE SOFTWARE. # # # ############################################################################### """ This script machine writes all the families and groups (no libraries) so that RMG-database looks cleaner and does not have duplicate indexes """ from rmgpy import settings from rmgpy.data.rmg import RMGDatabase database = RMGDatabase() database.load(settings['database.directory'], kineticsFamilies = 'all') database.save(settings['database.directory'])
for label, entry in library.entries.iteritems(): entry.history.append(event) groups = database.states.groups for label, entry in groups.entries.iteritems(): entry.history.append(event) for label, entry in database.forbiddenStructures.entries.iteritems(): entry.history.append(event) ################################################################################ if __name__ == '__main__': #figure out the username user = getUsername() # Set the import and export paths oldPath = 'output/RMG_database' newPath = 'input' print 'Loading old RMG-Java database...' database = RMGDatabase() database.loadOld(oldPath) print 'Setting history of all entries in database...' setHistory(database, user=user) print 'Saving the new RMG-Py database...' database.save(newPath)
class Uncertainty: """ This class contains functions associated with running uncertainty analyses for a single RMG-generated mechanism. """ def __init__(self, speciesList=None, reactionList=None, outputDirectory=''): """ `speciesList`: list of RMG species objects `reactionList`: list of RMG reaction objects `outputDirectoy`: directory path for saving output files from the analyses """ self.database = None self.speciesList = speciesList self.reactionList = reactionList self.speciesSourcesDict = None self.reactionSourcesDict = None self.allThermoSources = None self.allKineticSources = None self.thermoInputUncertainties = None self.kineticInputUncertainties = None self.outputDirectory = outputDirectory if outputDirectory else os.getcwd() # Make output directory if it does not yet exist: if not os.path.exists(self.outputDirectory): try: os.makedirs(self.outputDirectory) except: raise Exception('Uncertainty output directory could not be created.') def loadDatabase(self, kineticsFamilies='all',kineticsDepositories=None,thermoLibraries=None, reactionLibraries=None): """ This function loads a single copy of the RMGDatabase with full verbose averaging of the rate rule to trace kinetics sources. By default, this function loads all the kinetics families, only the training kinetics depository, the primaryThermoLibrary, and no reaction libraries. """ from rmgpy.data.rmg import RMGDatabase from rmgpy import settings if not kineticsDepositories: kineticsDepositories = ['training'] if not thermoLibraries: thermoLibraries = ['primaryThermoLibrary'] if not reactionLibraries: reactionLibraries = [] self.database = RMGDatabase() self.database.load(settings['database.directory'], kineticsFamilies=kineticsFamilies, kineticsDepositories=kineticsDepositories, thermoLibraries=thermoLibraries, reactionLibraries=reactionLibraries, ) # Prepare the database by loading training reactions but not averaging the rate rules for familyLabel, family in self.database.kinetics.families.iteritems(): family.addKineticsRulesFromTrainingSet(thermoDatabase=self.database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True) def loadModel(self, chemkinPath, dictionaryPath, transportPath=None): """ Load a RMG-generated model into the Uncertainty class `chemkinPath`: path to the chem_annotated.inp CHEMKIN mechanism `dictionaryPath`: path to the species_dictionary.txt file `transportPath`: path to the tran.dat file (optional) Then create dictionaries stored in self.thermoGroups and self.rateRules containing information about the source of the thermodynamic and kinetic parameters """ from rmgpy.chemkin import loadChemkinFile self.speciesList, self.reactionList = loadChemkinFile(chemkinPath, dictionaryPath=dictionaryPath, transportPath=transportPath) def extractSourcesFromModel(self): """ Extract the source data from the model using its comments. Must be done after loading model and database to work. """ self.speciesSourcesDict = {} for species in self.speciesList: source = self.database.thermo.extractSourceFromComments(species) # Now prep the source data # Do not alter the GAV information, but reassign QM and Library sources to the species indices that they came from if len(source.keys()) == 1: # The thermo came from a single source, so we know it comes from a value describing the exact species if 'Library' in source: source['Library'] = self.speciesList.index(species) # Use just the species index in self.speciesList, for better shorter printouts when debugging if 'QM' in source: source['QM'] = self.speciesList.index(species) elif len(source.keys()) == 2: # The thermo has two sources, which indicates it's an HBI correction on top of a library or QM value. We must retrieve the original # saturated molecule's thermo instead of using the radical species as the source of thermo saturatedSpecies = retrieveSaturatedSpeciesFromList(species,self.speciesList) if 'Library' in source: source['Library'] = self.speciesList.index(saturatedSpecies) if 'QM' in source: source['QM'] = self.speciesList.index(saturatedSpecies) else: raise Exception('Source of thermo should not use more than two sources out of QM, Library, or GAV.') self.speciesSourcesDict[species] = source self.reactionSourcesDict = {} for reaction in self.reactionList: source = self.database.kinetics.extractSourceFromComments(reaction) # Prep the source data # Consider any library or PDep reaction to be an independent parameter for now and assign the source to the index of the # reaction within self.reactionList if 'Library' in source: source['Library'] = self.reactionList.index(reaction) elif 'PDep' in source: source['PDep'] = self.reactionList.index(reaction) elif 'Training' in source: # Do nothing here because training source already saves the entry from the training reaction pass elif 'Rate Rules' in source: # Do nothing pass else: raise Exception('Source of kinetics must be either Library, PDep, Training, or Rate Rules') self.reactionSourcesDict[reaction] = source # Account for all the thermo sources allThermoSources = {'GAV':{}, 'Library':set(), 'QM':set()} for source in self.speciesSourcesDict.values(): if 'GAV' in source: for groupType in source['GAV'].keys(): groupEntries = [groupTuple[0] for groupTuple in source['GAV'][groupType]] if not groupType in allThermoSources['GAV']: allThermoSources['GAV'][groupType] = set(groupEntries) else: allThermoSources['GAV'][groupType].update(groupEntries) if 'Library' in source: allThermoSources['Library'].add(source['Library']) if 'QM' in source: allThermoSources['QM'].add(source['QM']) # Convert to lists self.allThermoSources = {} self.allThermoSources['Library'] = list(allThermoSources['Library']) self.allThermoSources['QM'] = list(allThermoSources['QM']) self.allThermoSources['GAV'] = {} for groupType in allThermoSources['GAV'].keys(): self.allThermoSources['GAV'][groupType] = list(allThermoSources['GAV'][groupType]) # Account for all the kinetics sources allKineticSources = {'Rate Rules':{}, 'Training':{}, 'Library':[], 'PDep':[]} for source in self.reactionSourcesDict.values(): if 'Training' in source: familyLabel = source['Training'][0] trainingEntry = source['Training'][1] if not familyLabel in allKineticSources['Training']: allKineticSources['Training'][familyLabel] = set([trainingEntry]) else: allKineticSources['Training'][familyLabel].add(trainingEntry) elif 'Library' in source: allKineticSources['Library'].append(source['Library']) elif 'PDep' in source: allKineticSources['PDep'].append(source['PDep']) elif 'Rate Rules' in source: familyLabel = source['Rate Rules'][0] sourceDict = source['Rate Rules'][1] rules = sourceDict['rules'] training = sourceDict['training'] if rules: ruleEntries = [ruleTuple[0] for ruleTuple in rules] if not familyLabel in allKineticSources['Rate Rules']: allKineticSources['Rate Rules'][familyLabel] = set(ruleEntries) else: allKineticSources['Rate Rules'][familyLabel].update(ruleEntries) if training: # Even though they are from training reactions, we consider the rate rules derived from the training # reactions to be noncorrelated, due to the fact that some may be reversed. trainingRules = [trainingTuple[0] for trainingTuple in training] # Pick the rate rule entries if not familyLabel in allKineticSources['Rate Rules']: allKineticSources['Rate Rules'][familyLabel] = set(trainingRules) else: allKineticSources['Rate Rules'][familyLabel].update(trainingRules) self.allKineticSources = {} self.allKineticSources['Library'] = allKineticSources['Library'] self.allKineticSources['PDep'] = allKineticSources['PDep'] # Convert to lists self.allKineticSources['Rate Rules'] = {} for familyLabel in allKineticSources['Rate Rules'].keys(): self.allKineticSources['Rate Rules'][familyLabel] = list(allKineticSources['Rate Rules'][familyLabel]) self.allKineticSources['Training'] = {} for familyLabel in allKineticSources['Training'].keys(): self.allKineticSources['Training'][familyLabel] = list(allKineticSources['Training'][familyLabel]) def assignParameterUncertainties(self, gParamEngine = ThermoParameterUncertainty(), kParamEngine = KineticParameterUncertainty()): """ Assign uncertainties based on the sources of the species thermo and reaction kinetics. """ self.thermoInputUncertainties = [] self.kineticInputUncertainties = [] for species in self.speciesList: dG = gParamEngine.getUncertaintyValue(self.speciesSourcesDict[species]) self.thermoInputUncertainties.append(dG) for reaction in self.reactionList: dlnk = kParamEngine.getUncertaintyValue(self.reactionSourcesDict[reaction]) self.kineticInputUncertainties.append(dlnk)
# Save to csv file csvwriter.writerow([familyName, QDict[familyName]]) return if __name__ == '__main__': from rmgpy import settings # Create the data evaluation directory trialDir = os.path.join(settings['database.directory'],'..','testing','eval') if not os.path.exists(trialDir): os.makedirs(trialDir) print 'Loading the RMG database...' FullDatabase=RMGDatabase() FullDatabase.load(settings['database.directory'], kineticsFamilies='all', kineticsDepositories='all', thermoLibraries=['primaryThermoLibrary'], # Use just the primary thermo library, which contains necessary small molecular thermo reactionLibraries=[], ) # Prepare the database by loading training reactions but not averaging the rate rules for family in FullDatabase.kinetics.families.values(): family.addKineticsRulesFromTrainingSet(thermoDatabase=FullDatabase.thermo) print '--------------------------------------------' print 'Obtaining statistics for the families...' obtainKineticsFamilyStatistics(FullDatabase, trialDir)
class RMG: """ A representation of a Reaction Mechanism Generator (RMG) job. The attributes are: =========================== ================================================ Attribute Description =========================== ================================================ `inputFile` The path to the input file `logFile` The path to the log file --------------------------- ------------------------------------------------ `databaseDirectory` The directory containing the RMG database `thermoLibraries` The thermodynamics libraries to load `reactionLibraries` The kinetics libraries to load `statmechLibraries` The statistical mechanics libraries to load `seedMechanisms` The seed mechanisms included in the model `kineticsFamilies` The kinetics families to use for reaction generation `kineticsDepositories` The kinetics depositories to use for looking up kinetics in each family `kineticsEstimator` The method to use to estimate kinetics: 'group additivity' or 'rate rules' --------------------------- ------------------------------------------------ `reactionModel` The core-edge reaction model generated by this job `reactionSystems` A list of the reaction systems used in this job `database` The RMG database used in this job --------------------------- ------------------------------------------------ `absoluteTolerance` The absolute tolerance used in the ODE/DAE solver `relativeTolerance` The relative tolerance used in the ODE/DAE solver `fluxToleranceKeepInEdge` The relative species flux below which species are discarded from the edge `fluxToleranceMoveToCore` The relative species flux above which species are moved from the edge to the core `fluxToleranceInterrupt` The relative species flux above which the simulation will halt `maximumEdgeSpecies` The maximum number of edge species allowed at any time `termination` A list of termination targets (i.e :class:`TerminationTime` and :class:`TerminationConversion` objects) --------------------------- ------------------------------------------------ `outputDirectory` The directory used to save output files `scratchDirectory` The directory used to save temporary files `verbosity` The level of logging verbosity for console output `loadRestart` ``True`` if restarting a previous job, ``False`` otherwise `saveRestartPeriod` The time period to periodically save a restart file (:class:`Quantity`), or ``None`` for never. `units` The unit system to use to save output files (currently must be 'si') `drawMolecules` ``True`` to draw pictures of the species in the core, ``False`` otherwise `generatePlots` ``True`` to generate plots of the job execution statistics after each iteration, ``False`` otherwise `pressureDependence` Whether to process unimolecular (pressure-dependent) reaction networks `wallTime` The maximum amount of CPU time in seconds to expend on this job; used to stop gracefully so we can still get profiling information --------------------------- ------------------------------------------------ `initializationTime` The time at which the job was initiated, in seconds since the epoch (i.e. from time.time()) `done` Whether the job has completed (there is nothing new to add) =========================== ================================================ """ def __init__(self, inputFile=None, logFile=None, outputDirectory=None, scratchDirectory=None): self.inputFile = inputFile self.logFile = logFile self.outputDirectory = outputDirectory self.scratchDirectory = scratchDirectory self.clear() def clear(self): """ Clear all loaded information about the job (except the file paths). """ self.databaseDirectory = None self.thermoLibraries = None self.reactionLibraries = None self.statmechLibraries = None self.seedMechanisms = None self.kineticsFamilies = None self.kineticsDepositories = None self.kineticsEstimator = 'group additivity' self.reactionModel = None self.reactionSystems = None self.database = None self.fluxToleranceKeepInEdge = 0.0 self.fluxToleranceMoveToCore = 1.0 self.fluxToleranceInterrupt = 1.0 self.absoluteTolerance = 1.0e-8 self.relativeTolerance = 1.0e-4 self.maximumEdgeSpecies = 1000000 self.termination = [] self.done = False self.verbosity = logging.INFO self.loadRestart = None self.saveRestartPeriod = None self.units = 'si' self.drawMolecules = None self.generatePlots = None self.saveConcentrationProfiles = None self.pressureDependence = None self.wallTime = 0 self.initializationTime = 0 def loadInput(self, path=None): """ Load an RMG job from the input file located at `inputFile`, or from the `inputFile` attribute if not given as a parameter. """ from input import readInputFile if path is None: path = self.inputFile readInputFile(path, self) self.reactionModel.kineticsEstimator = self.kineticsEstimator if self.pressureDependence: # If the output directory is not yet set, then set it to the same # directory as the input file by default if not self.outputDirectory: self.outputDirectory = os.path.dirname(path) self.pressureDependence.outputFile = self.outputDirectory self.reactionModel.pressureDependence = self.pressureDependence def checkInput(self): """ Check for a few common mistakes in the input file. """ if self.pressureDependence: for index, reactionSystem in enumerate(self.reactionSystems): assert (reactionSystem.T.value_si < self.pressureDependence.Tmax.value_si), "Reaction system T is above pressureDependence range." assert (reactionSystem.T.value_si > self.pressureDependence.Tmin.value_si), "Reaction system T is below pressureDependence range." assert (reactionSystem.P.value_si < self.pressureDependence.Pmax.value_si), "Reaction system P is above pressureDependence range." assert (reactionSystem.P.value_si > self.pressureDependence.Pmin.value_si), "Reaction system P is below pressureDependence range." assert any([not s.reactive for s in reactionSystem.initialMoleFractions.keys()]), \ "Pressure Dependence calculations require at least one inert (nonreacting) species for the bath gas." def saveInput(self, path=None): """ Save an RMG job to the input file located at `path`, or from the `outputFile` attribute if not given as a parameter. """ from input import saveInputFile if path is None: path = self.outputFile saveInputFile(path, self) def loadDatabase(self): self.database = RMGDatabase() self.database.load( path = self.databaseDirectory, thermoLibraries = self.thermoLibraries, reactionLibraries = [library for library, option in self.reactionLibraries], seedMechanisms = self.seedMechanisms, kineticsFamilies = self.kineticsFamilies, kineticsDepositories = self.kineticsDepositories, #frequenciesLibraries = self.statmechLibraries, depository = False, # Don't bother loading the depository information, as we don't use it ) if self.kineticsEstimator == 'rate rules': logging.info('Adding rate rules from training set in kinetics families...') for family in self.database.kinetics.families.values(): family.addKineticsRulesFromTrainingSet(thermoDatabase=self.database.thermo) logging.info('Filling in rate rules in kinetics families by averaging...') for family in self.database.kinetics.families.values(): family.fillKineticsRulesByAveragingUp() def initialize(self, args): """ Initialize an RMG job using the command-line arguments `args` as returned by the :mod:`argparse` package. """ # Save initialization time self.initializationTime = time.time() # Log start timestamp logging.info('RMG execution initiated at ' + time.asctime() + '\n') # Print out RMG header self.logHeader() # Set directories self.outputDirectory = args.output_directory self.scratchDirectory = args.scratch_directory # Read input file self.loadInput(args.file[0]) # Check input file self.checkInput() # See if memory profiling package is available try: import os import psutil except ImportError: logging.info('Optional package dependency "psutil" not found; memory profiling information will not be saved.') # See if spreadsheet writing package is available if self.saveConcentrationProfiles: try: xlwt except NameError: logging.warning('Package dependency "xlwt" not loaded; reaction system concentration profiles will not be saved, despite saveConcentrationProfiles = True option.') self.saveConcentrationProfiles = False # Make output subdirectories self.makeOutputSubdirectory('plot') self.makeOutputSubdirectory('species') self.makeOutputSubdirectory('pdep') self.makeOutputSubdirectory('chemkin') self.makeOutputSubdirectory('solver') # Load databases self.loadDatabase() # Set wall time if args.walltime == '0': self.wallTime = 0 else: data = args.walltime[0].split(':') if len(data) == 1: self.wallTime = int(data[-1]) elif len(data) == 2: self.wallTime = int(data[-1]) + 60 * int(data[-2]) elif len(data) == 3: self.wallTime = int(data[-1]) + 60 * int(data[-2]) + 3600 * int(data[-3]) elif len(data) == 4: self.wallTime = int(data[-1]) + 60 * int(data[-2]) + 3600 * int(data[-3]) + 86400 * int(data[-4]) else: raise ValueError('Invalid format for wall time; should be HH:MM:SS.') # Delete previous HTML file from rmgpy.rmg.output import saveOutputHTML saveOutputHTML(os.path.join(self.outputDirectory, 'output.html'), self.reactionModel) # Initialize reaction model if args.restart: self.loadRestartFile(os.path.join(self.outputDirectory,'restart.pkl')) else: # Seed mechanisms: add species and reactions from seed mechanism # DON'T generate any more reactions for the seed species at this time for seedMechanism in self.seedMechanisms: self.reactionModel.addSeedMechanismToCore(seedMechanism, react=False) # Reaction libraries: add species and reactions from reaction library to the edge so # that RMG can find them if their rates are large enough for library, option in self.reactionLibraries: self.reactionModel.addReactionLibraryToEdge(library) # Add nonreactive species (e.g. bath gases) to core first # This is necessary so that the PDep algorithm can identify the bath gas self.reactionModel.enlarge([spec for spec in self.initialSpecies if not spec.reactive]) # Then add remaining reactive species for spec in self.initialSpecies: spec.generateThermoData(self.database) self.reactionModel.enlarge([spec for spec in self.initialSpecies if spec.reactive]) # Save a restart file if desired if self.saveRestartPeriod: self.saveRestartFile(os.path.join(self.outputDirectory,'restart.pkl'), self.reactionModel) def execute(self, args): """ Execute an RMG job using the command-line arguments `args` as returned by the :mod:`argparse` package. """ self.initialize(args) # RMG execution statistics coreSpeciesCount = [] coreReactionCount = [] edgeSpeciesCount = [] edgeReactionCount = [] execTime = [] restartSize = [] memoryUse = [] self.done = False self.saveEverything() # Main RMG loop while not self.done: if self.saveConcentrationProfiles: # self.saveConcentrationProfiles should have been set to false if xlwt cannot be loaded workbook = xlwt.Workbook() self.done = True objectsToEnlarge = [] allTerminated = True for index, reactionSystem in enumerate(self.reactionSystems): if self.saveConcentrationProfiles: worksheet = workbook.add_sheet('#{0:d}'.format(index+1)) else: worksheet = None # Conduct simulation pdepNetworks = [] for source, networks in self.reactionModel.networkDict.items(): pdepNetworks.extend(networks) logging.info('Conducting simulation of reaction system %s...' % (index+1)) terminated, obj = reactionSystem.simulate( coreSpecies = self.reactionModel.core.species, coreReactions = self.reactionModel.core.reactions, edgeSpecies = self.reactionModel.edge.species, edgeReactions = self.reactionModel.edge.reactions, toleranceKeepInEdge = self.fluxToleranceKeepInEdge, toleranceMoveToCore = self.fluxToleranceMoveToCore, toleranceInterruptSimulation = self.fluxToleranceInterrupt, pdepNetworks = pdepNetworks, worksheet = worksheet, absoluteTolerance = self.absoluteTolerance, relativeTolerance = self.relativeTolerance, ) allTerminated = allTerminated and terminated logging.info('') # If simulation is invalid, note which species should be added to # the core if obj: if isinstance(obj, PDepNetwork): # Determine which species in that network has the highest leak rate # We do this here because we need a temperature and pressure # Store the maximum leak species along with the associated network obj = (obj, obj.getMaximumLeakSpecies(reactionSystem.T.value_si, reactionSystem.P.value_si)) objectsToEnlarge.append(obj) self.done = False if self.saveConcentrationProfiles: workbook.save(os.path.join(self.outputDirectory, 'solver', 'simulation_{0:d}.xls'.format(len(self.reactionModel.core.species)))) if not self.done: # There is something that needs exploring/enlarging # If we reached our termination conditions, then try to prune # species from the edge if allTerminated: self.reactionModel.prune(self.reactionSystems, self.fluxToleranceKeepInEdge, self.maximumEdgeSpecies) # Enlarge objects identified by the simulation for enlarging # These should be Species or Network objects logging.info('') objectsToEnlarge = list(set(objectsToEnlarge)) self.reactionModel.enlarge(objectsToEnlarge) self.saveEverything() # Update RMG execution statistics logging.info('Updating RMG execution statistics...') coreSpec, coreReac, edgeSpec, edgeReac = self.reactionModel.getModelSize() coreSpeciesCount.append(coreSpec) coreReactionCount.append(coreReac) edgeSpeciesCount.append(edgeSpec) edgeReactionCount.append(edgeReac) execTime.append(time.time() - self.initializationTime) elapsed = execTime[-1] seconds = elapsed % 60 minutes = (elapsed - seconds) % 3600 / 60 hours = (elapsed - seconds - minutes * 60) % (3600 * 24) / 3600 days = (elapsed - seconds - minutes * 60 - hours * 3600) / (3600 * 24) logging.info(' Execution time (DD:HH:MM:SS): ' '{0:02}:{1:02}:{2:02}:{3:02}'.format(int(days), int(hours), int(minutes), int(seconds))) try: import psutil process = psutil.Process(os.getpid()) rss, vms = process.get_memory_info() memoryUse.append(rss / 1.0e6) logging.info(' Memory used: %.2f MB' % (memoryUse[-1])) except ImportError: memoryUse.append(0.0) if os.path.exists(os.path.join(self.outputDirectory,'restart.pkl.gz')): restartSize.append(os.path.getsize(os.path.join(self.outputDirectory,'restart.pkl.gz')) / 1.0e6) logging.info(' Restart file size: %.2f MB' % (restartSize[-1])) else: restartSize.append(0.0) self.saveExecutionStatistics(execTime, coreSpeciesCount, coreReactionCount, edgeSpeciesCount, edgeReactionCount, memoryUse, restartSize) if self.generatePlots: self.generateExecutionPlots(execTime, coreSpeciesCount, coreReactionCount, edgeSpeciesCount, edgeReactionCount, memoryUse, restartSize) logging.info('') # Consider stopping gracefully if the next iteration might take us # past the wall time if self.wallTime > 0 and len(execTime) > 1: t = execTime[-1] dt = execTime[-1] - execTime[-2] if t + 3 * dt > self.wallTime: logging.info('MODEL GENERATION TERMINATED') logging.info('') logging.info('There is not enough time to complete the next iteration before the wall time is reached.') logging.info('The output model may be incomplete.') logging.info('') coreSpec, coreReac, edgeSpec, edgeReac = self.reactionModel.getModelSize() logging.info('The current model core has %s species and %s reactions' % (coreSpec, coreReac)) logging.info('The current model edge has %s species and %s reactions' % (edgeSpec, edgeReac)) return # Write output file logging.info('') logging.info('MODEL GENERATION COMPLETED') logging.info('') coreSpec, coreReac, edgeSpec, edgeReac = self.reactionModel.getModelSize() logging.info('The final model core has %s species and %s reactions' % (coreSpec, coreReac)) logging.info('The final model edge has %s species and %s reactions' % (edgeSpec, edgeReac)) self.finish() def saveEverything(self): """ Saves the output HTML, the Chemkin file, and the Restart file (if appropriate). The restart file is only saved if self.saveRestartPeriod or self.done. """ # If the user specifies it, add unused reaction library reactions to # an additional output species and reaction list which is written to the ouput HTML # file as well as the chemkin file self.reactionModel.outputSpeciesList = [] self.reactionModel.outputReactionList = [] for library, option in self.reactionLibraries: if option: self.reactionModel.addReactionLibraryToOutput(library) # Save the current state of the model core to a pretty HTML file self.saveOutputHTML() # Save a Chemkin file containing the current model core self.saveChemkinFile() # Save the restart file if desired if self.saveRestartPeriod or self.done: self.saveRestartFile( os.path.join(self.outputDirectory,'restart.pkl'), self.reactionModel, delay=0 if self.done else self.saveRestartPeriod.value_si ) def finish(self): """ Complete the model generation. """ # Log end timestamp logging.info('') logging.info('RMG execution terminated at ' + time.asctime()) def getGitCommit(self): import subprocess from rmgpy import getPath try: return subprocess.check_output(['git', 'log', '--format=%H%n%cd', '-1'], cwd=getPath()).splitlines() except: return '', '' def logHeader(self, level=logging.INFO): """ Output a header containing identifying information about RMG to the log. """ logging.log(level, '#################################################') logging.log(level, '# RMG - Reaction Mechanism Generator #') logging.log(level, '# Version: 0.1.0 (14 May 2009) #') logging.log(level, '# Authors: RMG Developers ([email protected]) #') logging.log(level, '# P.I.: William H. Green ([email protected]) #') logging.log(level, '# Website: http://rmg.sourceforge.net/ #') logging.log(level, '#################################################\n') import os head, date = self.getGitCommit() if head != '' and date != '': logging.log(level, 'The current git HEAD is:') logging.log(level, '\t%s' % head) logging.log(level, '\t%s' % date) logging.log(level, '') def makeOutputSubdirectory(self, folder): """ Create a subdirectory `folder` in the output directory. If the folder already exists (e.g. from a previous job) its contents are deleted. """ dir = os.path.join(self.outputDirectory, folder) if os.path.exists(dir): # The directory already exists, so delete it (and all its content!) shutil.rmtree(dir) os.mkdir(dir) def loadRestartFile(self, path): """ Load a restart file at `path` on disk. """ import cPickle # Unpickle the reaction model from the specified restart file logging.info('Loading previous restart file...') f = open(path, 'rb') self.reactionModel = cPickle.load(f) f.close() # A few things still point to the species in the input file, so update # those to point to the equivalent species loaded from the restart file # The termination conversions still point to the old species from rmgpy.solver.base import TerminationConversion for reactionSystem in self.reactionSystems: for term in reactionSystem.termination: if isinstance(term, TerminationConversion): term.species, isNew = self.reactionModel.makeNewSpecies(term.species.molecule[0], term.species.label, term.species.reactive) # The initial mole fractions in the reaction systems still point to the old species for reactionSystem in self.reactionSystems: initialMoleFractions = {} for spec0, moleFrac in reactionSystem.initialMoleFractions.iteritems(): spec, isNew = self.reactionModel.makeNewSpecies(spec0.molecule[0], spec0.label, spec0.reactive) initialMoleFractions[spec] = moleFrac reactionSystem.initialMoleFractions = initialMoleFractions # The reactions and reactionDict still point to the old reaction families reactionDict = {} oldFamilies = self.reactionModel.reactionDict.keys() for family0 in self.reactionModel.reactionDict: # Find the equivalent library or family in the newly-loaded kinetics database family = None if isinstance(family0, KineticsLibrary): for label, database in self.database.kinetics.libraries.iteritems(): if database.label == family0.label: family = database break elif isinstance(family0, KineticsFamily): for label, database in self.database.kinetics.families.iteritems(): if database.label == family0.label: family = database break else: import pdb; pdb.set_trace() if family is None: raise Exception("Unable to find matching reaction family for %s" % family0.label) # Update each affected reaction to point to that new family # Also use that new family in a duplicate reactionDict reactionDict[family] = {} for reactant1 in self.reactionModel.reactionDict[family0]: reactionDict[family][reactant1] = {} for reactant2 in self.reactionModel.reactionDict[family0][reactant1]: reactionDict[family][reactant1][reactant2] = [] if isinstance(family0, KineticsLibrary): for rxn in self.reactionModel.reactionDict[family0][reactant1][reactant2]: assert isinstance(rxn, LibraryReaction) rxn.library = family reactionDict[family][reactant1][reactant2].append(rxn) elif isinstance(family0, KineticsFamily): for rxn in self.reactionModel.reactionDict[family0][reactant1][reactant2]: assert isinstance(rxn, TemplateReaction) rxn.family = family reactionDict[family][reactant1][reactant2].append(rxn) self.reactionModel.reactionDict = reactionDict def saveOutputHTML(self): """ Save the current reaction model to a pretty HTML file. """ logging.info('Saving current model to HTML file...') from rmgpy.rmg.output import saveOutputHTML saveOutputHTML(os.path.join(self.outputDirectory, 'output.html'), self.reactionModel) def saveChemkinFile(self): """ Save the current reaction model to a Chemkin file. """ logging.info('Saving current model to Chemkin file...') this_chemkin_path = os.path.join(self.outputDirectory, 'chemkin', 'chem%04i.inp' % len(self.reactionModel.core.species)) latest_chemkin_path = os.path.join(self.outputDirectory, 'chemkin','chem.inp') latest_dictionary_path = os.path.join(self.outputDirectory, 'chemkin','species_dictionary.txt') self.reactionModel.saveChemkinFile(this_chemkin_path, latest_dictionary_path) if os.path.exists(latest_chemkin_path): os.unlink(latest_chemkin_path) shutil.copy2(this_chemkin_path,latest_chemkin_path) def saveRestartFile(self, path, reactionModel, delay=0): """ Save a restart file to `path` on disk containing the contents of the provided `reactionModel`. The `delay` parameter is a time in seconds; if the restart file is not at least that old, the save is aborted. (Use the default value of 0 to force the restart file to be saved.) """ import cPickle # Saving of a restart file is very slow (likely due to all the Quantity objects) # Therefore, to save it less frequently, don't bother if the restart file is less than an hour old if os.path.exists(path) and time.time() - os.path.getmtime(path) < delay: logging.info('Not saving restart file in this iteration.') return # Pickle the reaction model to the specified file # We also compress the restart file to save space (and lower the disk read/write time) logging.info('Saving restart file...') f = open(path, 'wb') cPickle.dump(reactionModel, f, cPickle.HIGHEST_PROTOCOL) f.close() def saveExecutionStatistics(self, execTime, coreSpeciesCount, coreReactionCount, edgeSpeciesCount, edgeReactionCount, memoryUse, restartSize): """ Save the statistics of the RMG job to an Excel spreadsheet for easy viewing after the run is complete. The statistics are saved to the file `statistics.xls` in the output directory. The ``xlwt`` package is used to create the spreadsheet file; if this package is not installed, no file is saved. """ # Attempt to import the xlwt package; return if not installed try: xlwt except NamerError: logging.warning('Package xlwt not loaded. Unable to save execution statistics.') return # Create workbook and sheet for statistics to be places workbook = xlwt.Workbook() sheet = workbook.add_sheet('Statistics') # First column is execution time sheet.write(0,0,'Execution time (s)') for i, etime in enumerate(execTime): sheet.write(i+1,0,etime) # Second column is number of core species sheet.write(0,1,'Core species') for i, count in enumerate(coreSpeciesCount): sheet.write(i+1,1,count) # Third column is number of core reactions sheet.write(0,2,'Core reactions') for i, count in enumerate(coreReactionCount): sheet.write(i+1,2,count) # Fourth column is number of edge species sheet.write(0,3,'Edge species') for i, count in enumerate(edgeSpeciesCount): sheet.write(i+1,3,count) # Fifth column is number of edge reactions sheet.write(0,4,'Edge reactions') for i, count in enumerate(edgeReactionCount): sheet.write(i+1,4,count) # Sixth column is memory used sheet.write(0,5,'Memory used (MB)') for i, memory in enumerate(memoryUse): sheet.write(i+1,5,memory) # Seventh column is restart file size sheet.write(0,6,'Restart file size (MB)') for i, memory in enumerate(restartSize): sheet.write(i+1,6,memory) # Save workbook to file fstr = os.path.join(self.outputDirectory, 'statistics.xls') workbook.save(fstr) def generateExecutionPlots(self, execTime, coreSpeciesCount, coreReactionCount, edgeSpeciesCount, edgeReactionCount, memoryUse, restartSize): """ Generate a number of plots describing the statistics of the RMG job, including the reaction model core and edge size and memory use versus execution time. These will be placed in the output directory in the plot/ folder. """ logging.info('Generating plots of execution statistics...') import matplotlib.pyplot as plt fig = plt.figure() ax1 = fig.add_subplot(111) ax1.semilogx(execTime, coreSpeciesCount, 'o-b') ax1.set_xlabel('Execution time (s)') ax1.set_ylabel('Number of core species') ax2 = ax1.twinx() ax2.semilogx(execTime, coreReactionCount, 'o-r') ax2.set_ylabel('Number of core reactions') plt.savefig(os.path.join(self.outputDirectory, 'plot/coreSize.svg')) plt.clf() fig = plt.figure() ax1 = fig.add_subplot(111) ax1.loglog(execTime, edgeSpeciesCount, 'o-b') ax1.set_xlabel('Execution time (s)') ax1.set_ylabel('Number of edge species') ax2 = ax1.twinx() ax2.loglog(execTime, edgeReactionCount, 'o-r') ax2.set_ylabel('Number of edge reactions') plt.savefig(os.path.join(self.outputDirectory, 'plot/edgeSize.svg')) plt.clf() fig = plt.figure() ax1 = fig.add_subplot(111) ax1.semilogx(execTime, memoryUse, 'o-k') ax1.semilogx(execTime, restartSize, 'o-g') ax1.set_xlabel('Execution time (s)') ax1.set_ylabel('Memory (MB)') ax1.legend(['RAM', 'Restart file'], loc=2) plt.savefig(os.path.join(self.outputDirectory, 'plot/memoryUse.svg')) plt.clf() def loadRMGJavaInput(self, path): """ Load an RMG-Java job from the input file located at `inputFile`, or from the `inputFile` attribute if not given as a parameter. """ # NOTE: This function is currently incomplete! # It only loads a subset of the available information. self.reactionModel = CoreEdgeReactionModel() self.initialSpecies = [] self.reactionSystems = [] Tlist = []; Plist = []; concentrationList = []; speciesDict = {} termination = []; atol=1e-16; rtol=1e-8 with open(path, 'r') as f: line = self.readMeaningfulLineJava(f) while line != '': if line.startswith('TemperatureModel:'): tokens = line.split() units = tokens[2][1:-1] assert units in ['C', 'F', 'K'] if units == 'C': Tlist = [float(T)+273.15 for T in tokens[3:]] elif units == 'F': Tlist = [(float(T)+459.67)*5./9. for T in tokens[3:]] else: Tlist = [float(T) for T in tokens[3:]] elif line.startswith('PressureModel:'): tokens = line.split() units = tokens[2][1:-1] assert units in ['atm', 'bar', 'Pa', 'torr'] if units == 'atm': Plist = [float(P)*101325. for P in tokens[3:]] elif units == 'bar': Plist = [float(P)*100000. for P in tokens[3:]] elif units == 'torr': Plist = [float(P)/760.*101325. for P in tokens[3:]] else: Plist = [float(P) for P in tokens[3:]] elif line.startswith('InitialStatus:'): label = ''; concentrations = []; adjlist = '' line = self.readMeaningfulLineJava(f) while line != 'END': if line == '' and label != '': species = Species(label=label, molecule=[Molecule().fromAdjacencyList(adjlist)]) self.initialSpecies.append(species) speciesDict[label] = species concentrationList.append(concentrations) label = ''; concentrations = []; adjlist = '' elif line != '' and label == '': tokens = line.split() label = tokens[0] units = tokens[1][1:-1] if tokens[-1] in ['Unreactive', 'ConstantConcentration']: tokens.pop(-1) assert units in ['mol/cm3', 'mol/m3', 'mol/l'] if units == 'mol/cm3': concentrations = [float(C)*1.0e6 for C in tokens[2:]] elif units == 'mol/l': concentrations = [float(C)*1.0e3 for C in tokens[2:]] else: concentrations = [float(C) for C in tokens[2:]] elif line != '': adjlist += line + '\n' line = f.readline().strip() if '//' in line: line = line[0:line.index('//')] elif line.startswith('InertGas:'): line = self.readMeaningfulLineJava(f) while line != 'END': tokens = line.split() label = tokens[0] assert label in ['N2', 'Ar', 'He', 'Ne'] if label == 'Ne': smiles = '[Ne]' elif label == 'Ar': smiles = '[Ar]' elif label == 'He': smiles = '[He]' else: smiles = 'N#N' units = tokens[1][1:-1] assert units in ['mol/cm3', 'mol/m3', 'mol/l'] if units == 'mol/cm3': concentrations = [float(C)*1.0e6 for C in tokens[2:]] elif units == 'mol/l': concentrations = [float(C)*1.0e3 for C in tokens[2:]] else: concentrations = [float(C) for C in tokens[2:]] species = Species(label=label, reactive=False, molecule=[Molecule().fromSMILES(smiles)]) self.initialSpecies.append(species) speciesDict[label] = species concentrationList.append(concentrations) line = self.readMeaningfulLineJava(f) elif line.startswith('FinishController:'): # First meaningful line is a termination time or conversion line = self.readMeaningfulLineJava(f) tokens = line.split() if tokens[2].lower() == 'conversion:': label = tokens[3] conversion = float(tokens[4]) termination.append(TerminationConversion(spec=speciesDict[label], conv=conversion)) elif tokens[2].lower() == 'reactiontime:': time = float(tokens[3]) units = tokens[4][1:-1] assert units in ['sec', 'min', 'hr', 'day'] if units == 'min': time *= 60. elif units == 'hr': time *= 60. * 60. elif units == 'day': time *= 60. * 60. * 24. termination.append(TerminationTime(time=time)) # Second meaningful line is the error tolerance # We're not doing anything with this information yet! line = self.readMeaningfulLineJava(f) elif line.startswith('Atol:'): tokens = line.split() atol = float(tokens[1]) elif line.startswith('Rtol:'): tokens = line.split() rtol = float(tokens[1]) line = self.readMeaningfulLineJava(f) assert len(Tlist) > 0 assert len(Plist) > 0 concentrationList = numpy.array(concentrationList) assert concentrationList.shape[1] == 1 or concentrationList.shape[1] == len(Tlist) * len(Plist) # Make a reaction system for each (T,P) combination systemCounter = 0 for T in Tlist: for P in Plist: if concentrationList.shape[1] == 1: concentrations = concentrationList[:,0] else: concentrations = concentrationList[:,systemCounter] totalConc = numpy.sum(concentrations) initialMoleFractions = dict([(self.initialSpecies[i], concentrations[i] / totalConc) for i in range(len(self.initialSpecies))]) reactionSystem = SimpleReactor(T, P, initialMoleFractions=initialMoleFractions, termination=termination) self.reactionSystems.append(reactionSystem) systemCounter += 1 def readMeaningfulLineJava(self, f): """ Read a meaningful line from an RMG-Java condition file object `f`, returning the line with any comments removed. """ line = f.readline() if line != '': line = line.strip() if '//' in line: line = line[0:line.index('//')] while line == '': line = f.readline() if line == '': break line = line.strip() if '//' in line: line = line[0:line.index('//')] return line
connection_id = fig.canvas.mpl_connect('pick_event', onpick) pylab.show() ################################################################################ if __name__ == '__main__': import argparse parser = argparse.ArgumentParser() parser.add_argument('depository', metavar='<depository>', type=str, nargs=1, help='the depository to use') args = parser.parse_args() print 'Loading RMG database...' from rmgpy.data.rmg import RMGDatabase database = RMGDatabase() database.load('input') try: depositories = [database.kinetics.depository[label] for label in args.depository] except KeyError: print e print 'The specified depository "{0}" was invalid.'.format(label) quit() print 'Generating Evans-Polanyi data...' for depository in depositories: generateEvansPolanyiPlot(depository, database)
class Uncertainty: """ This class contains functions associated with running uncertainty analyses for a single RMG-generated mechanism. """ def __init__(self, speciesList=None, reactionList=None, outputDirectory=''): """ `speciesList`: list of RMG species objects `reactionList`: list of RMG reaction objects `outputDirectoy`: directory path for saving output files from the analyses """ self.database = None self.speciesList = speciesList self.reactionList = reactionList self.speciesSourcesDict = None self.reactionSourcesDict = None self.allThermoSources = None self.allKineticSources = None self.thermoInputUncertainties = None self.kineticInputUncertainties = None self.outputDirectory = outputDirectory if outputDirectory else os.getcwd() # Make output directory if it does not yet exist: if not os.path.exists(self.outputDirectory): try: os.makedirs(self.outputDirectory) except: raise Exception('Uncertainty output directory could not be created.') def loadDatabase(self, kineticsFamilies='all',kineticsDepositories=None,thermoLibraries=None, reactionLibraries=None): """ This function loads a single copy of the RMGDatabase with full verbose averaging of the rate rule to trace kinetics sources. By default, this function loads all the kinetics families, only the training kinetics depository, the primaryThermoLibrary, and no reaction libraries. """ from rmgpy.data.rmg import RMGDatabase from rmgpy import settings if not kineticsDepositories: kineticsDepositories = ['training'] if not thermoLibraries: thermoLibraries = ['primaryThermoLibrary'] if not reactionLibraries: reactionLibraries = [] self.database = RMGDatabase() self.database.load(settings['database.directory'], kineticsFamilies=kineticsFamilies, kineticsDepositories=kineticsDepositories, thermoLibraries=thermoLibraries, reactionLibraries=reactionLibraries, ) # Prepare the database by loading training reactions but not averaging the rate rules for familyLabel, family in self.database.kinetics.families.iteritems(): family.addKineticsRulesFromTrainingSet(thermoDatabase=self.database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True) def loadModel(self, chemkinPath, dictionaryPath, transportPath=None): """ Load a RMG-generated model into the Uncertainty class `chemkinPath`: path to the chem_annotated.inp CHEMKIN mechanism `dictionaryPath`: path to the species_dictionary.txt file `transportPath`: path to the tran.dat file (optional) Then create dictionaries stored in self.thermoGroups and self.rateRules containing information about the source of the thermodynamic and kinetic parameters """ from rmgpy.chemkin import loadChemkinFile self.speciesList, self.reactionList = loadChemkinFile(chemkinPath, dictionaryPath=dictionaryPath, transportPath=transportPath) def retrieveSaturatedSpeciesFromList(self,species): """ Given a radical `species`, this function retrieves the saturated species objects from a list of species objects and returns the saturated species object along with a boolean that indicates if the species is not part of the model (True->not in the model, False->in the model) """ molecule = species.molecule[0] assert molecule.isRadical(), "Method only valid for radicals." saturatedStruct = molecule.copy(deep=True) saturatedStruct.saturate_radicals() for otherSpecies in self.speciesList: if otherSpecies.isIsomorphic(saturatedStruct): return otherSpecies, False #couldn't find saturated species in the model, try libraries newSpc = Species(molecule=[saturatedStruct]) thermo = self.database.thermo.getThermoDataFromLibraries(newSpc) if thermo is not None: newSpc.thermo = thermo self.speciesList.append(newSpc) return newSpc, True else: raise Exception('Could not retrieve saturated species form of {0} from the species list'.format(species)) def extractSourcesFromModel(self): """ Extract the source data from the model using its comments. Must be done after loading model and database to work. """ self.speciesSourcesDict = {} ignoreSpcs = [] for species in self.speciesList: if not species in ignoreSpcs: source = self.database.thermo.extractSourceFromComments(species) # Now prep the source data # Do not alter the GAV information, but reassign QM and Library sources to the species indices that they came from if len(source.keys()) == 1: # The thermo came from a single source, so we know it comes from a value describing the exact species if 'Library' in source: source['Library'] = self.speciesList.index(species) # Use just the species index in self.speciesList, for better shorter printouts when debugging if 'QM' in source: source['QM'] = self.speciesList.index(species) elif len(source.keys()) == 2: # The thermo has two sources, which indicates it's an HBI correction on top of a library or QM value. We must retrieve the original # saturated molecule's thermo instead of using the radical species as the source of thermo saturatedSpecies,ignoreSpc = self.retrieveSaturatedSpeciesFromList(species) if ignoreSpc: #this is saturated species that isn't in the actual model ignoreSpcs.append(saturatedSpecies) if 'Library' in source: source['Library'] = self.speciesList.index(saturatedSpecies) if 'QM' in source: source['QM'] = self.speciesList.index(saturatedSpecies) else: raise Exception('Source of thermo should not use more than two sources out of QM, Library, or GAV.') self.speciesSourcesDict[species] = source self.reactionSourcesDict = {} for reaction in self.reactionList: source = self.database.kinetics.extractSourceFromComments(reaction) # Prep the source data # Consider any library or PDep reaction to be an independent parameter for now and assign the source to the index of the # reaction within self.reactionList if 'Library' in source: source['Library'] = self.reactionList.index(reaction) elif 'PDep' in source: source['PDep'] = self.reactionList.index(reaction) elif 'Training' in source: # Do nothing here because training source already saves the entry from the training reaction pass elif 'Rate Rules' in source: # Do nothing pass else: raise Exception('Source of kinetics must be either Library, PDep, Training, or Rate Rules') self.reactionSourcesDict[reaction] = source for spc in ignoreSpcs: self.speciesList.remove(spc) def compileAllSources(self): """ Compile two dictionaries composed of all the thermo and kinetic sources. Must be performed after extractSourcesFromModel function """ # Account for all the thermo sources allThermoSources = {'GAV':{}, 'Library':set(), 'QM':set()} for source in self.speciesSourcesDict.values(): if 'GAV' in source: for groupType in source['GAV'].keys(): groupEntries = [groupTuple[0] for groupTuple in source['GAV'][groupType]] if not groupType in allThermoSources['GAV']: allThermoSources['GAV'][groupType] = set(groupEntries) else: allThermoSources['GAV'][groupType].update(groupEntries) if 'Library' in source: allThermoSources['Library'].add(source['Library']) if 'QM' in source: allThermoSources['QM'].add(source['QM']) # Convert to lists self.allThermoSources = {} self.allThermoSources['Library'] = list(allThermoSources['Library']) self.allThermoSources['QM'] = list(allThermoSources['QM']) self.allThermoSources['GAV'] = {} for groupType in allThermoSources['GAV'].keys(): self.allThermoSources['GAV'][groupType] = list(allThermoSources['GAV'][groupType]) # Account for all the kinetics sources allKineticSources = {'Rate Rules':{}, 'Training':{}, 'Library':[], 'PDep':[]} for source in self.reactionSourcesDict.values(): if 'Training' in source: familyLabel = source['Training'][0] trainingEntry = source['Training'][1] if not familyLabel in allKineticSources['Training']: allKineticSources['Training'][familyLabel] = set([trainingEntry]) else: allKineticSources['Training'][familyLabel].add(trainingEntry) elif 'Library' in source: allKineticSources['Library'].append(source['Library']) elif 'PDep' in source: allKineticSources['PDep'].append(source['PDep']) elif 'Rate Rules' in source: familyLabel = source['Rate Rules'][0] sourceDict = source['Rate Rules'][1] rules = sourceDict['rules'] training = sourceDict['training'] if rules: ruleEntries = [ruleTuple[0] for ruleTuple in rules] if not familyLabel in allKineticSources['Rate Rules']: allKineticSources['Rate Rules'][familyLabel] = set(ruleEntries) else: allKineticSources['Rate Rules'][familyLabel].update(ruleEntries) if training: # Even though they are from training reactions, we consider the rate rules derived from the training # reactions to be noncorrelated, due to the fact that some may be reversed. trainingRules = [trainingTuple[0] for trainingTuple in training] # Pick the rate rule entries if not familyLabel in allKineticSources['Rate Rules']: allKineticSources['Rate Rules'][familyLabel] = set(trainingRules) else: allKineticSources['Rate Rules'][familyLabel].update(trainingRules) self.allKineticSources = {} self.allKineticSources['Library'] = allKineticSources['Library'] self.allKineticSources['PDep'] = allKineticSources['PDep'] # Convert to lists self.allKineticSources['Rate Rules'] = {} for familyLabel in allKineticSources['Rate Rules'].keys(): self.allKineticSources['Rate Rules'][familyLabel] = list(allKineticSources['Rate Rules'][familyLabel]) self.allKineticSources['Training'] = {} for familyLabel in allKineticSources['Training'].keys(): self.allKineticSources['Training'][familyLabel] = list(allKineticSources['Training'][familyLabel]) def assignParameterUncertainties(self, gParamEngine = ThermoParameterUncertainty(), kParamEngine = KineticParameterUncertainty(), correlated=False): """ Assign uncertainties based on the sources of the species thermo and reaction kinetics. """ self.thermoInputUncertainties = [] self.kineticInputUncertainties = [] for species in self.speciesList: if not correlated: dG = gParamEngine.getUncertaintyValue(self.speciesSourcesDict[species]) self.thermoInputUncertainties.append(dG) else: source = self.speciesSourcesDict[species] dG = {} if 'Library' in source: pdG = gParamEngine.getPartialUncertaintyValue(source, 'Library', corrParam=source['Library']) label = 'Library {}'.format(self.speciesList[source['Library']].toChemkin()) dG[label] = pdG if 'QM' in source: pdG = gParamEngine.getPartialUncertaintyValue(source, 'QM',corrParam=source['QM']) label = 'QM {}'.format(self.speciesList[source['QM']].toChemkin()) dG[label] = pdG if 'GAV' in source: for groupType, groupList in source['GAV'].iteritems(): for group, weight in groupList: pdG = gParamEngine.getPartialUncertaintyValue(source, 'GAV', group, groupType) label = 'Group({}) {}'.format(groupType, group.label) dG[label] = pdG # We also know if there is group additivity used, there will be uncorrelated estimation error est_pdG = gParamEngine.getPartialUncertaintyValue(source, 'Estimation') if est_pdG: label = 'Estimation {}'.format(species.toChemkin()) dG[label] = est_pdG self.thermoInputUncertainties.append(dG) for reaction in self.reactionList: if not correlated: dlnk = kParamEngine.getUncertaintyValue(self.reactionSourcesDict[reaction]) self.kineticInputUncertainties.append(dlnk) else: source = self.reactionSourcesDict[reaction] dlnk = {} if 'Rate Rules' in source: family = source['Rate Rules'][0] sourceDict = source['Rate Rules'][1] rules = sourceDict['rules'] training = sourceDict['training'] for ruleEntry, weight in rules: dplnk = kParamEngine.getPartialUncertaintyValue(source, 'Rate Rules', corrParam=ruleEntry, corrFamily=family) label = '{} {}'.format(family, ruleEntry) dlnk[label]=dplnk for ruleEntry, trainingEntry, weight in training: dplnk = kParamEngine.getPartialUncertaintyValue(source, 'Rate Rules', corrParam=ruleEntry, corrFamily=family) label = '{} {}'.format(family, ruleEntry) dlnk[label]=dplnk # There is also estimation error if rate rules are used est_dplnk = kParamEngine.getPartialUncertaintyValue(source, 'Estimation') if est_dplnk: label = 'Estimation {}'.format(reaction.toChemkin(self.speciesList, kinetics=False)) dlnk[label]=est_dplnk elif 'PDep' in source: dplnk = kParamEngine.getPartialUncertaintyValue(source, 'PDep', source['PDep']) label = 'PDep {}'.format(reaction.toChemkin(self.speciesList, kinetics=False)) dlnk[label]=dplnk elif 'Library' in source: dplnk = kParamEngine.getPartialUncertaintyValue(source, 'Library', source['Library']) label = 'Library {}'.format(reaction.toChemkin(self.speciesList, kinetics=False)) dlnk[label]=dplnk elif 'Training' in source: dplnk = kParamEngine.getPartialUncertaintyValue(source, 'Training', source['Training']) family = source['Training'][0] label = 'Training {} {}'.format(family, reaction.toChemkin(self.speciesList, kinetics=False)) dlnk[label]=dplnk self.kineticInputUncertainties.append(dlnk) def sensitivityAnalysis(self, initialMoleFractions, sensitiveSpecies, T, P, terminationTime, sensitivityThreshold=1e-3, number=10, fileformat='.png'): """ Run sensitivity analysis using the RMG solver in a single ReactionSystem object initialMoleFractions is a dictionary with Species objects as keys and mole fraction initial conditions sensitiveSpecies is a list of sensitive Species objects number is the number of top species thermo or reaction kinetics desired to be plotted """ from rmgpy.solver import SimpleReactor, TerminationTime from rmgpy.quantity import Quantity from rmgpy.tools.simulate import plot_sensitivity from rmgpy.rmg.listener import SimulationProfileWriter, SimulationProfilePlotter from rmgpy.rmg.settings import ModelSettings, SimulatorSettings T = Quantity(T) P = Quantity(P) termination=[TerminationTime(Quantity(terminationTime))] reactionSystem = SimpleReactor(T=T, P=P, initialMoleFractions=initialMoleFractions, termination=termination, sensitiveSpecies=sensitiveSpecies, sensitivityThreshold=sensitivityThreshold) # Create the csv worksheets for logging sensitivity util.makeOutputSubdirectory(self.outputDirectory, 'solver') sensWorksheet = [] reactionSystemIndex = 0 for spec in reactionSystem.sensitiveSpecies: csvfilePath = os.path.join(self.outputDirectory, 'solver', 'sensitivity_{0}_SPC_{1}.csv'.format(reactionSystemIndex+1, spec.index)) sensWorksheet.append(csvfilePath) reactionSystem.attach(SimulationProfileWriter( self.outputDirectory, reactionSystemIndex, self.speciesList)) reactionSystem.attach(SimulationProfilePlotter( self.outputDirectory, reactionSystemIndex, self.speciesList)) simulatorSettings = SimulatorSettings() #defaults modelSettings = ModelSettings() #defaults modelSettings.fluxToleranceMoveToCore = 0.1 modelSettings.fluxToleranceInterrupt = 1.0 modelSettings.fluxToleranceKeepInEdge = 0.0 reactionSystem.simulate( coreSpecies = self.speciesList, coreReactions = self.reactionList, edgeSpecies = [], edgeReactions = [], surfaceSpecies = [], surfaceReactions = [], modelSettings = modelSettings, simulatorSettings = simulatorSettings, sensitivity = True, sensWorksheet = sensWorksheet, ) plot_sensitivity(self.outputDirectory, reactionSystemIndex, reactionSystem.sensitiveSpecies, number=number, fileformat=fileformat) def localAnalysis(self, sensitiveSpecies, correlated=False, number=10, fileformat='.png'): """ Conduct local uncertainty analysis on the reaction model. sensitiveSpecies is a list of sensitive Species objects number is the number of highest contributing uncertain parameters desired to be plotted fileformat can be either .png, .pdf, or .svg """ for sensSpecies in sensitiveSpecies: csvfilePath = os.path.join(self.outputDirectory, 'solver', 'sensitivity_{0}_SPC_{1}.csv'.format(1, sensSpecies.index)) time, dataList = parseCSVData(csvfilePath) # Assign uncertainties thermoDataList = [] reactionDataList = [] for data in dataList: if data.species: for species in self.speciesList: if species.toChemkin() == data.species: index = self.speciesList.index(species) break else: raise Exception('Chemkin name {} of species in the CSV file does not match anything in the species list.'.format(data.species)) data.uncertainty = self.thermoInputUncertainties[index] thermoDataList.append(data) if data.reaction: rxnIndex = int(data.index) - 1 data.uncertainty = self.kineticInputUncertainties[rxnIndex] reactionDataList.append(data) if correlated: correlatedThermoData = {} correlatedReactionData = {} for data in thermoDataList: for label, dpG in data.uncertainty.iteritems(): if label in correlatedThermoData: # Unpack the labels and partial uncertainties correlatedThermoData[label].data[-1] += data.data[-1]*dpG # Multiply the sensitivity with the partial uncertainty else: correlatedThermoData[label] = GenericData(data=[data.data[-1]*dpG], uncertainty=1, label=label, species='dummy') for data in reactionDataList: for label, dplnk in data.uncertainty.iteritems(): if label in correlatedReactionData: correlatedReactionData[label].data[-1] += data.data[-1]*dplnk else: correlatedReactionData[label] = GenericData(data=[data.data[-1]*dplnk], uncertainty=1, label=label, reaction='dummy') thermoDataList = correlatedThermoData.values() reactionDataList = correlatedReactionData.values() # Compute total variance totalVariance = 0.0 for data in thermoDataList: totalVariance += (data.data[-1]*data.uncertainty)**2 for data in reactionDataList: totalVariance += (data.data[-1]*data.uncertainty)**2 if not correlated: # Add the reaction index to the data label of the reaction uncertainties for data in reactionDataList: data.label = 'k'+str(data.index) + ': ' + data.label.split()[-1] thermoUncertaintyPlotPath = os.path.join(self.outputDirectory, 'thermoLocalUncertainty_{0}'.format(sensSpecies.toChemkin()) + fileformat) reactionUncertaintyPlotPath = os.path.join(self.outputDirectory, 'kineticsLocalUncertainty_{0}'.format(sensSpecies.toChemkin()) + fileformat) ReactionSensitivityPlot(xVar=time,yVar=reactionDataList,numReactions=number).uncertaintyPlot(totalVariance, filename=reactionUncertaintyPlotPath) ThermoSensitivityPlot(xVar=time,yVar=thermoDataList,numSpecies=number).uncertaintyPlot(totalVariance, filename=thermoUncertaintyPlotPath)
################################################################################ if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('inputPath', metavar='INPUT', type=str, nargs=1, help='the input path of the RMG-Java database directory') parser.add_argument('outputPath', metavar='OUTPUT', type=str, nargs=1, help='output path for the desired RMG-Py database directory') args = parser.parse_args() inputPath = args.inputPath[0] outputPath = args.outputPath[0] newPath = 'input' print 'Loading old RMG-Java database...' database = RMGDatabase() database.loadOld(inputPath) try: os.makedirs(outputPath) except: pass print 'Saving the new RMG-Py database...' database.save(outputPath) print "Done!"
import argparse from rmgpy.data.rmg import RMGDatabase from rmgpy.chemkin import saveChemkinFile, saveSpeciesDictionary from rmgpy.rmg.model import Species ################################################################################ if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('library', metavar='LIBRARYNAME', type=str, nargs=1, help='the name of the kinetic library to be exported') args = parser.parse_args() libraryName = args.library[0] print 'Loading RMG-Py database...' database = RMGDatabase() database.load('input/', kineticsFamilies='all', kineticsDepositories='all') print 'Loading {0} library'.format(libraryName) kineticLibrary = database.kinetics.libraries[libraryName] reactionList = [] for index, entry in kineticLibrary.entries.iteritems(): reaction = entry.item reaction.kinetics = entry.data reactionList.append(reaction) speciesList = [] index = 0 for spec in kineticLibrary.getSpecies().values():
################################################################################ if __name__ == '__main__': #figure out the username user = getUsername() # Comment out the line above and uncomment the one below, filling in user information manually if # it cannot be obtained from git or you do not want to extract user info from git. # user = "******" # Set the import and export paths oldPath = 'output/RMG_database' newPath = 'input' print 'Loading old RMG-Java database...' database = RMGDatabase() database.loadOld(oldPath) print 'Loading the current database to look for changes...' current_database = RMGDatabase() current_database.load(newPath) print 'Setting history of all entries in database...' setHistory(database, current_database, user=user) print 'Saving the new RMG-Py database...' database.save(newPath) print "Done!"
from rmgpy import settings from rmgpy.data.rmg import RMGDatabase def checkFamilies(FullDatabase): databaseLog=logging.getLogger('databaseLog') familyStatus={} for family in FullDatabase.kinetics.families: databaseLog.error('\nChecking ' + family + "...") print 'Checking ' + family + "..." familyStatus[family]=FullDatabase.kinetics.families[family].checkWellFormed() if __name__ == '__main__': # Set up paths for database and logger databaseDirectory = settings['database.directory'] # RMG-database/input logPath = os.path.join(databaseDirectory, '..', 'database.log') #clear logger if it exists if os.path.exists(logPath): with open(logPath, 'w'): pass databaseLog=logging.getLogger('databaseLog') fh=logging.FileHandler(logPath) fh.setLevel(logging.DEBUG) databaseLog.addHandler(fh) databaseLog.propagate=False #prevents these logging messages to being sent to ancestors (so that it doesn't print on console) # logging.basicConfig(filename=logpath, level=logging.ERROR) FullDatabase=RMGDatabase() FullDatabase.load(databaseDirectory, kineticsFamilies='all') checkFamilies(FullDatabase)
for group, parent in problems[4].iteritems(): outputFile.write('Child: ' + group + ', Parent: ' + parent + '\n') if problemsExist[5]: outputFile.write('\n' + 'These groups are probably products, but you should check them anyway' + '\n') for group in problems[5]: outputFile.write(group + '\n') outputFile.write('\n\n') if __name__ == '__main__': #Thermo stuff # ThermoDatabase=ThermoDatabase() # ThermoDatabase.load(path) # ThermoDatabase.save(r'C:\RMG-database\input\thermo_test') # ThermoDatabase.save(path) FullDatabase=RMGDatabase() # path=r'C:\RMG-database\input\thermo' path='C:\RMG-database\input' # FullDatabase.load(thermoLibraries=) FullDatabase.load(path) checkFamilies(FullDatabase) # trialDir=r'C:\Users\User1\Dropbox\Research\RMG\kinetics\LeaveOneOut\test' # trialDir=r'C:\RMG-database\input_test' # family=FullDatabase.kinetics.families['Disproportionation'] # entryKey='Y_1centerbirad;O_Cdrad' # # test=getKineticsFromRules(family, entryKey) # # print test.comment # print test
class RMGWebDatabase(object): """Wrapper class for RMGDatabase that provides loading functionality.""" def __init__(self): self.database = RMGDatabase() self.database.kinetics = KineticsDatabase() self.database.thermo = ThermoDatabase() self.database.transport = TransportDatabase() self.database.statmech = StatmechDatabase() self.database.solvation = SolvationDatabase() self.database.loadForbiddenStructures(os.path.join(rmgweb.settings.DATABASE_PATH, 'forbiddenStructures.py')) self.timestamps = {} @property def kinetics(self): """Get the kinetics database.""" return self.database.kinetics @property def thermo(self): """Get the thermo database.""" return self.database.thermo @property def transport(self): """Get the transport database.""" return self.database.transport @property def statmech(self): """Get the statmech database.""" return self.database.statmech @property def solvation(self): """Get the solvation database.""" return self.database.solvation def reset_timestamp(self, path): """ Reset the files timestamp in the dictionary of timestamps. """ mtime = os.stat(path).st_mtime self.timestamps[path] = mtime def reset_dir_timestamps(self, dirpath): """ Walk the directory tree from dirpath, calling reset_timestamp(file) on each file. """ print "Resetting 'last loaded' timestamps for {0} in process {1}".format(dirpath, os.getpid()) for root, dirs, files in os.walk(dirpath): for name in files: self.reset_timestamp(os.path.join(root, name)) def is_file_modified(self, path): """ Return True if the file at `path` has been modified since `reset_timestamp(path)` was last called. """ # If path doesn't denote a file and were previously # tracking it, then it has been removed or the file type # has changed, so return True. if not os.path.isfile(path): return path in self.timestamps # If path wasn't being tracked then it's new, so return True elif path not in self.timestamps: return True # Force restart when modification time has changed, even # if time now older, as that could indicate older file # has been restored. elif os.stat(path).st_mtime != self.timestamps[path]: return True # All the checks have been passed, so the file was not modified else: return False def is_dir_modified(self, dirpath): """ Returns True if anything in the directory at dirpath has been modified since reset_dir_timestamps(dirpath). """ to_check = set([path for path in self.timestamps if path.startswith(dirpath)]) for root, dirs, files in os.walk(dirpath): for name in files: path = os.path.join(root, name) if self.is_file_modified(path): return True to_check.remove(path) # If there's anything left in to_check, it's probably now gone and this will return True: for path in to_check: if self.is_file_modified(path): return True # Passed all tests. return False ################################################################################ def load(self, component='', section=''): """ Load the requested `component` of the RMG database if modified since last loaded. """ if component in ['thermo', '']: if section in ['depository', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'depository') if self.is_dir_modified(dirpath): self.database.thermo.loadDepository(dirpath) self.reset_dir_timestamps(dirpath) if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'libraries') if self.is_dir_modified(dirpath): self.database.thermo.loadLibraries(dirpath) # put them in our preferred order, so that when we look up thermo in order to estimate kinetics, # we use our favorite values first. preferred_order = [ 'primaryThermoLibrary', 'DFT_QCI_thermo', 'GRI-Mech3.0', 'CBS_QB3_1dHR', 'KlippensteinH2O2', ] new_order = [i for i in preferred_order if i in self.database.thermo.libraryOrder] for i in self.database.thermo.libraryOrder: if i not in new_order: new_order.append(i) self.database.thermo.libraryOrder = new_order self.reset_dir_timestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'groups') if self.is_dir_modified(dirpath): self.database.thermo.loadGroups(dirpath) self.reset_dir_timestamps(dirpath) if component in ['transport', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'libraries') if self.is_dir_modified(dirpath): self.database.transport.loadLibraries(dirpath) self.reset_dir_timestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'groups') if self.is_dir_modified(dirpath): self.database.transport.loadGroups(dirpath) self.reset_dir_timestamps(dirpath) if component in ['solvation', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'solvation') if self.is_dir_modified(dirpath): self.database.solvation.load(dirpath) self.reset_dir_timestamps(dirpath) if component in ['kinetics', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'libraries') if self.is_dir_modified(dirpath): self.database.kinetics.loadLibraries(dirpath) self.reset_dir_timestamps(dirpath) if section in ['families', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'families') if self.is_dir_modified(dirpath): self.database.kinetics.loadFamilies(dirpath, families='all', depositories='all') self.reset_dir_timestamps(dirpath) # Make sure to load the entire thermo database prior to adding training values to the rules self.load('thermo', '') for family in self.database.kinetics.families.values(): oldentries = len(family.rules.entries) family.addKineticsRulesFromTrainingSet(thermoDatabase=self.database.thermo) newentries = len(family.rules.entries) if newentries != oldentries: print '{0} new entries added to {1} family after adding rules from training set.'.format( newentries - oldentries, family.label) # Filling in rate rules in kinetics families by averaging... family.fillKineticsRulesByAveragingUp() if component in ['statmech', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'statmech') if self.is_dir_modified(dirpath): self.database.statmech.load(dirpath) self.reset_dir_timestamps(dirpath) def get_transport_database(self, section, subsection): """ Return the component of the transport database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == 'libraries': db = self.database.transport.libraries[subsection] elif section == 'groups': db = self.database.transport.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_solvation_database(self, section, subsection): """ Return the component of the solvation database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == '': db = self.database.solvation # return general SolvationDatabase elif section == 'libraries': db = self.database.solvation.libraries[subsection] elif section == 'groups': db = self.database.solvation.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_statmech_database(self, section, subsection): """ Return the component of the statmech database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == 'depository': db = self.database.statmech.depository[subsection] elif section == 'libraries': db = self.database.statmech.libraries[subsection] elif section == 'groups': db = self.database.statmech.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_thermo_database(self, section, subsection): """ Return the component of the thermodynamics database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == 'depository': db = self.database.thermo.depository[subsection] elif section == 'libraries': db = self.database.thermo.libraries[subsection] elif section == 'groups': db = self.database.thermo.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_kinetics_database(self, section, subsection): """ Return the component of the kinetics database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ db = None try: if section == 'libraries': db = self.database.kinetics.libraries[subsection] elif section == 'families': subsection = subsection.split('/') if subsection[0] != '' and len(subsection) == 2: family = self.database.kinetics.families[subsection[0]] if subsection[1] == 'groups': db = family.groups elif subsection[1] == 'rules': db = family.rules else: label = '{0}/{1}'.format(family.label, subsection[1]) db = (d for d in family.depositories if d.label == label).next() else: raise ValueError('Invalid value "%s" for section parameter.' % section) except (KeyError, StopIteration): raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db
gotit = [] for rxnFamily in rxnFamiles: for k, line in enumerate(mechLines): if line.startswith('! {0} estimate:'.format(rxnFamily)) or line.startswith('! {0} exact:'.format(rxnFamily)): reaction = mechLines[k+1].split()[0] if reaction not in gotit: gotit.append(reaction) rxnList.append((rxnFamily, mechLines[k+1])) elif '{0} estimate:'.format(rxnFamily) in line or '{0} exact:'.format(rxnFamily) in line: reaction = mechLines[k+1].split()[0] if reaction not in gotit: gotit.append(reaction) rxnList.append((rxnFamily, mechLines[k+1])) print 'Loading RMG Database ...' rmgDatabase = RMGDatabase() rmgDatabase.load(os.path.abspath(os.path.join(os.getenv('RMGpy'), '..', 'RMG-database', 'input')), kineticsFamilies='default') print 'Finished loading RMG Database ...' reactionTuple = rxnList[i-1] rxnFamily, reactionLine = reactionTuple rxnFormula, A, n, Ea = reactionLine.split() reactants, products = rxnFormula.split('=') if rxnFamily in ['H_Abstraction', 'Disproportionation']: reactant1, reactant2 = [moleculeDict[j] for j in reactants.split('+')] product1, product2 = [moleculeDict[j] for j in products.split('+')] rSpecies1 = Species(molecule=[reactant1]) rSpecies2 = Species(molecule=[reactant2]) pSpecies1 = Species(molecule=[product1]) pSpecies2 = Species(molecule=[product2]) rSpecies1.generateResonanceIsomers()
def loadDatabase(component='', section=''): """ Load the requested `component` of the RMG database if modified since last loaded. """ global database if not database: database = RMGDatabase() database.solvation = SolvationDatabase() database.thermo = ThermoDatabase() database.kinetics = KineticsDatabase() database.transport = TransportDatabase() database.statmech = StatmechDatabase() database.loadForbiddenStructures(os.path.join(rmgweb.settings.DATABASE_PATH, 'forbiddenStructures.py')) if component == 'initialize': return database if component in ['thermo', '']: if section in ['depository', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'depository') if isDirModified(dirpath): database.thermo.loadDepository(dirpath) resetDirTimestamps(dirpath) if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'libraries') if isDirModified(dirpath): database.thermo.loadLibraries(dirpath) # put them in our preferred order, so that when we look up thermo in order to estimate kinetics, # we use our favorite values first. preferred_order = ['primaryThermoLibrary','DFT_QCI_thermo','GRI-Mech3.0','CBS_QB3_1dHR','KlippensteinH2O2'] new_order = [i for i in preferred_order if i in database.thermo.libraryOrder] for i in database.thermo.libraryOrder: if i not in new_order: new_order.append(i) database.thermo.libraryOrder = new_order resetDirTimestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'groups') if isDirModified(dirpath): database.thermo.loadGroups(dirpath) resetDirTimestamps(dirpath) if component in ['transport', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'libraries') if isDirModified(dirpath): database.transport.loadLibraries(dirpath) resetDirTimestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'groups') if isDirModified(dirpath): database.transport.loadGroups(dirpath) resetDirTimestamps(dirpath) if component in ['solvation', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'solvation') if isDirModified(dirpath): database.solvation.load(dirpath) resetDirTimestamps(dirpath) if component in ['kinetics', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'libraries') if isDirModified(dirpath): database.kinetics.loadLibraries(dirpath) resetDirTimestamps(dirpath) if section in ['families', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'families') if isDirModified(dirpath): database.kinetics.loadFamilies(dirpath, families = 'all', depositories = 'all') resetDirTimestamps(dirpath) # Make sure to load the entire thermo database prior to adding training values to the rules loadDatabase('thermo','') for family in database.kinetics.families.values(): oldentries = len(family.rules.entries) family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) newentries = len(family.rules.entries) if newentries != oldentries: print '{0} new entries added to {1} family after adding rules from training set.'.format(newentries-oldentries, family.label) # Filling in rate rules in kinetics families by averaging... family.fillKineticsRulesByAveragingUp() if component in ['statmech', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'statmech') if isDirModified(dirpath): database.statmech.load(dirpath) resetDirTimestamps(dirpath) return database