import main main.initializeLog(logging.DEBUG) datapath = '../data/RMG_database/' logging.debug('General database: ' + os.path.abspath(datapath)) species.thermoDatabase = species.ThermoDatabaseSet() species.thermoDatabase.load(datapath) thermo.forbiddenStructures = data.Dictionary() thermo.forbiddenStructures.load(datapath + 'forbiddenStructure.txt') thermo.forbiddenStructures.toStructure() #reaction.kineticsDatabase = reaction.ReactionFamilySet() #reaction.kineticsDatabase.load(datapath) structure = chem.Structure(); structure.fromSMILES('C') CH4 = species.makeNewSpecies(structure) structure = chem.Structure(); structure.fromSMILES('[H]') H = species.makeNewSpecies(structure) structure = chem.Structure(); structure.fromSMILES('[CH3]') CH3 = species.makeNewSpecies(structure) forward = reaction.Reaction([CH3, H], [CH4]) reverse = reaction.Reaction([CH4], [CH3, H]) forward.reverse = reverse reverse.reverse = forward kinetics = reaction.ArrheniusEPKinetics() kinetics.fromDatabase([300, 2000, 1.93E14, 0, 0, 0.27, 0, 0, 0, 0, 3], '', 2) forward.kinetics = [kinetics]
def loadSeedMechanism(self, path): """ Loads a seed mechanism from the folder indicated by `path` into the core-edge reaction model. """ import os.path import quantities as pq import data import species import kinetics import reaction # Load the species data from the file species.txt # This file has the format of a standard RMG dictionary d = data.Dictionary() d.load(os.path.join(path, 'species.txt')) d.toStructure(addH=True) # Load the thermo data from the file thermo.txt # This file has the format of a standard RMG thermo library thermoData = species.ThermoDatabase() thermoData.load(os.path.join(path, 'species.txt'), '', os.path.join(path, 'thermo.txt')) # Populate the main primary thermo library with this thermo data # This will overwrite keys (but not values), so the order that the # seed mechanisms are loaded matters! for key, value in d.iteritems(): species.thermoDatabase.primaryDatabase.dictionary[key] = value for key, value in thermoData.library.iteritems(): species.thermoDatabase.primaryDatabase.library[key] = value # Create new species based on items in species.txt speciesDict = {}; speciesList = [] for label, struct in d.iteritems(): spec = species.makeNewSpecies(struct, label, reactive=True) speciesDict[label] = spec speciesList.append(spec) # Load the reactions from the file reaction.txt reactionList = [] f = open(os.path.join(path, 'reactions.txt'), 'r') for line in f: line = data.removeCommentFromLine(line) line.strip() if len(line) > 0: items = line.split() if len(items) > 0: rxn = items[0:-6] # Extract reactants and products if '<=>' in rxn: arrow = rxn.index('<=>') elif '=>' in rxn: arrow = rxn.index('=>') else: raise IOError('No arrow found in reaction equation from line %s' % line) reactants = rxn[0:arrow:2] products = rxn[arrow+1::2] # Remove third body 'M' if present thirdBody = False if 'M' in reactants and 'M' in products: thirdBody = True reactants.remove('M') products.remove('M') # Convert strings to species objects reactants = [speciesDict[r] for r in reactants] products = [speciesDict[r] for r in products] # Process Arrhenius parameters order = len(reactants) if (thirdBody): order += 1 Aunits = 'cm^%i/(mol^%i*s)' % (3*(order-1), order-1) A = float(pq.Quantity(float(items[-6]), Aunits).simplified) n = float(items[-5]) # dimensionless Ea = float(pq.Quantity(float(items[-4]), 'cal/mol').simplified) kin = [kinetics.ArrheniusKinetics(A=A, n=n, Ea=Ea)] # Create reaction object and add to list rxn = reaction.Reaction(reactants, products, 'seed', kin, thirdBody=thirdBody) reaction.processNewReaction(rxn) reactionList.append(rxn) f.close() # Add species to core for spec in speciesList: self.addSpeciesToCore(spec) # Add reactions to core for rxn in reactionList: self.addReactionToCore(rxn)
def readInputFile(fstr): """ Parse an RMG input file at the location `fstr`. If successful, this function returns a :class:`rmg.model.CoreEdgeReactionModel` object and a list of one or more :class:`rmg.model.ReactionSystem` objects. """ try: # Parse the RMG input XML file into a DOM tree xml0 = XML(path=fstr) # Make sure root element is a <rmginput> element rootElement = xml0.getRootElement() if rootElement.tagName != 'rmginput': raise InvalidInputFileException('Incorrect root element; should be <rmginput>.') # Process units units = xml0.getChildElementText(rootElement, 'units', required=False, default='si') pq.set_default_units(units) # Read draw molecules option drawMolecules = xml0.getChildElementText(rootElement, 'drawMolecules', required=False, default='off') drawMolecules = drawMolecules.lower() settings.drawMolecules = (drawMolecules == 'on' or drawMolecules == 'true' or drawMolecules == 'yes') # Read generate plots option generatePlots = xml0.getChildElementText(rootElement, 'generatePlots', required=False, default='off') generatePlots = generatePlots.lower() settings.generatePlots = (generatePlots == 'on' or generatePlots == 'true' or generatePlots == 'yes') # Process databases databases = [] databaseElements = xml0.getChildElements(rootElement, 'database') for element in databaseElements: # Get database type databaseType = xml0.getAttribute(element, 'type', required=True) databaseType = databaseType.lower() if databaseType != 'general': raise InvalidInputFileException('Invalid database type "' + databaseType + '"; valid types are "general".') # Get database name and form path databaseName = xml0.getElementText(element) databasePath = os.path.dirname(__file__) databasePath = os.path.join(databasePath, '..') databasePath = os.path.join(databasePath, '..') databasePath = os.path.join(databasePath, 'data') databasePath = os.path.join(databasePath, databaseName) if not os.path.exists(databasePath): raise InvalidInputFileException('Database "%s" not found.' % databaseName) databases.append([databaseName, databaseType, databasePath]) # Output info about databases logging.info('Found %s database%s' % (len(databases), 's' if len(databases) > 1 else '')) # Check that exactly one general database was specified generalDatabaseCount = sum([1 for database in databases if database[1] == 'general']) if generalDatabaseCount == 0: raise InvalidInputFileException('No general database specified; one must be present.') elif generalDatabaseCount > 1: raise InvalidInputFileException('Multiple general databases specified; only one is allowed.') # Load databases for database in databases: if database[1] == 'general': logging.debug('General database: ' + database[2]) # Load thermo databases species.thermoDatabase = species.ThermoDatabaseSet() species.thermoDatabase.load(database[2] + os.sep) # Load forbidden structures thermo.forbiddenStructures = data.Dictionary() thermo.forbiddenStructures.load(database[2] + os.sep + 'forbiddenStructure.txt') thermo.forbiddenStructures.toStructure() # Load kinetic databases (reaction families) reaction.kineticsDatabase = reaction.ReactionFamilySet() reaction.kineticsDatabase.load(database[2] + os.sep) logging.debug('') # Process species coreSpecies = []; speciesDict = {} speciesElements = xml0.getChildElements(rootElement, 'species') logging.info('Found ' + str(len(speciesElements)) + ' species') for element in speciesElements: # Attributes of the species element sid = xml0.getAttribute(element, 'id') label = xml0.getAttribute(element, 'label') reactive = xml0.getAttribute(element, 'reactive', required=False, default='yes') reactive = reactive.lower() reactive = not (reactive == 'no' or reactive == 'false' or reactive == 'n') # Load structure struct = structure.Structure() cml = xml0.getChildElement(element, 'cml', required=False) inchi = xml0.getChildElement(element, 'inchi', required=False) smiles = xml0.getChildElement(element, 'smiles', required=False) if cml is not None: cmlstr = str(xml0.getChildElement(cml, 'molecule', required=True).toxml()) struct.fromCML(cmlstr) elif inchi is not None: inchistr = str(xml0.getElementText(inchi)) struct.fromInChI(inchistr) elif smiles is not None: smilesstr = str(xml0.getElementText(smiles)) struct.fromSMILES(smilesstr) else: raise InvalidInputFileException('Species "%s" missing structure information.' % label) # Create a new species and append the species to the core spec = species.makeNewSpecies(struct, label, reactive) coreSpecies.append(spec) # Add to local species dictionary (for matching with other parts of file) speciesDict[sid] = spec logging.debug('') # Create an empty reaction model reactionModel = model.CoreEdgeReactionModel() # Read model flux tolerance fluxTolerance = xml0.getChildElement(rootElement, 'fluxTolerance') reactionModel.fluxToleranceKeepInEdge = float(xml0.getChildElementText(fluxTolerance, 'keepInEdge')) reactionModel.fluxToleranceMoveToCore = float(xml0.getChildElementText(fluxTolerance, 'moveToCore')) reactionModel.fluxToleranceInterrupt = float(xml0.getChildElementText(fluxTolerance, 'interruptSimulation')) logging.debug('Model flux tolerances set to:') logging.debug('\tKeep in edge: %s' % (reactionModel.fluxToleranceKeepInEdge) ) logging.debug('\tMove to core: %s' % (reactionModel.fluxToleranceMoveToCore) ) logging.debug('\tInterrupt simulation: %s' % (reactionModel.fluxToleranceInterrupt) ) logging.debug('') # Read maximum model size maxModelSize = xml0.getChildElement(rootElement, 'maximumModelSize') if maxModelSize is None: logging.debug('Maximum model size is not set') else: reactionModel.maximumEdgeSpecies = int(xml0.getChildElementText(maxModelSize, 'edgeSpecies')) logging.debug('Maximum model size set to:') logging.debug('\tEdge species: %s' % (reactionModel.maximumEdgeSpecies) ) logging.debug('') # Read dynamic simulator element = xml0.getChildElement(rootElement, 'simulator') reactionModel.absoluteTolerance = float(xml0.getAttribute(element, 'atol')) reactionModel.relativeTolerance = float(xml0.getAttribute(element, 'rtol')) logging.info('Read dynamic simulator') logging.debug('Simulator:') logging.debug('\tAbsolute tolerance set to %s' % (reactionModel.absoluteTolerance)) logging.debug('\tRelative tolerance set to %s' % (reactionModel.relativeTolerance)) logging.debug('') # Read termination targets termination = xml0.getChildElement(rootElement, 'termination') targetElements = xml0.getChildElements(termination, 'target') for element in targetElements: targetType = xml0.getAttribute(element, 'type') if targetType == 'conversion': sid = xml0.getAttribute(element, 'speciesID') spec = speciesDict[sid] conv = float(xml0.getElementText(element)) if conv < 0.0 or conv > 1.0: raise InvalidInputFileException('Invalid value for termination fractional conversion.') reactionModel.termination.append(model.TerminationConversion(spec, conv)) elif targetType == 'time': units = str(xml0.getAttribute(element, 'units')) time = float(xml0.getElementText(element)) time = pq.Quantity(time, units); time = float(time.simplified) if time < 0.0: raise InvalidInputFileException('Invalid value for termination time.') reactionModel.termination.append(model.TerminationTime(time)) else: raise InvalidInputFileException('Invalid termination target type "'+targetType+'".') if len(reactionModel.termination) == 0: raise InvalidInputFileException('No termination targets specified.') # Output info about termination targets if len(reactionModel.termination) == 1: logging.info('Found ' + str(len(reactionModel.termination)) + ' termination target') else: logging.info('Found ' + str(len(reactionModel.termination)) + ' termination targets') for index, target in enumerate(reactionModel.termination): string = '\tTermination target #' + str(index+1) + ': ' if target.__class__ == model.TerminationConversion: string += 'conversion ' + str(target.species) + ' ' + str(target.conversion) elif target.__class__ == model.TerminationTime: string += 'time ' + str(target.time) logging.debug(string) logging.debug('') # Process reaction systems reactionSystems = [] systemElements = xml0.getChildElements(rootElement, 'reactionSystem') for element in systemElements: # Create a new reaction system rsType = xml0.getAttribute(element, 'type') if rsType == 'batch': reactionSystem = model.BatchReactor() else: raise InvalidInputFileException('Invalid reaction system type "' + rsType + '".') # Temperature model temperatureModel = xml0.getChildElement(element, 'temperatureModel') tempModelType = xml0.getAttribute(temperatureModel, 'type') if tempModelType == 'isothermal': # Read the (constant) temperature from the file temperature = xml0.getChildElement(temperatureModel, 'temperature') value = float(xml0.getElementText(temperature)) units = str(xml0.getAttribute(temperature, 'units')) T = pq.Quantity(value, units); T = float(T.simplified) # Set the reaction system's temperature model to isothermal reactionSystem.temperatureModel = model.TemperatureModel() reactionSystem.temperatureModel.setIsothermal(T) else: raise InvalidInputFileException('Invalid temperature model type "' + tempModelType + '".') # Pressure model pressureModel = xml0.getChildElement(element, 'pressureModel') pressModelType = xml0.getAttribute(pressureModel, 'type') if pressModelType == 'isobaric': # Read the (constant) pressure from the file pressure = xml0.getChildElement(pressureModel, 'pressure') value = float(xml0.getElementText(pressure)) units = str(xml0.getAttribute(pressure, 'units')) P = pq.Quantity(value, units); P = float(P.simplified) # Set the reaction system's pressure model to isobaric reactionSystem.pressureModel = model.PressureModel() reactionSystem.pressureModel.setIsobaric(P) else: raise InvalidInputFileException('Invalid pressure model type "' + pressModelType + '".') # Physical property model propModel = xml0.getChildElement(element, 'physicalPropertyModel') propModelType = xml0.getAttribute(propModel, 'type') if propModelType.lower() == 'idealgas': # Set the reaction system's pressure model to isobaric reactionSystem.equationOfState = model.IdealGas() elif propModelType.lower() == 'incompressibleliquid': molarVolume = xml0.getFirstChildElement(element, 'molarVolume') value = float(xml0.getElementText(molarVolume)) units = str(xml0.getAttribute(molarVolume, 'units')) Vmol = float(pq.Quantity(value, units).simplified); reactionSystem.equationOfState = model.IncompressibleLiquid( P = reactionSystem.pressureModel.getPressure(), T = reactionSystem.temperatureModel.getTemperature(), Vmol = Vmol ) else: raise InvalidInputFileException('Invalid physical property model type "' + propModelType + '".') # Get total concentration T = reactionSystem.temperatureModel.getTemperature(0) P = reactionSystem.pressureModel.getPressure(0) totalConc = 1.0 / reactionSystem.equationOfState.getVolume(T, P, [1.0]) # Initialize all initial concentrations to zero for spec in coreSpecies: reactionSystem.initialConcentration[spec] = 0.0 # List of initial concentrations moleFractions = xml0.getChildElements(element, 'moleFraction') for moleFraction in moleFractions: # Read the concentration from the file value = float(xml0.getElementText(moleFraction)) sid = xml0.getAttribute(moleFraction, 'speciesID') reactionSystem.initialConcentration[speciesDict[sid]] = value * totalConc # Append to list of reaction systems reactionSystems.append(reactionSystem) # Output info about reaction system if len(reactionSystems) == 1: logging.info('Found ' + str(len(reactionSystems)) + ' reaction system') else: logging.info('Found ' + str(len(reactionSystems)) + ' reaction systems') for index, reactionSystem in enumerate(reactionSystems): logging.debug('Reaction system #' + str(index+1) + ':') logging.debug('\t' + str(reactionSystem.temperatureModel)) logging.debug('\t' + str(reactionSystem.pressureModel)) for spec, conc in reactionSystem.initialConcentration.iteritems(): if spec.reactive: logging.debug('\tInitial concentration of ' + str(spec) + ': ' + str(conc)) else: logging.debug('\tConstant concentration of ' + str(spec) + ': ' + str(conc)) logging.debug('') # Cleanup the DOM tree when finished xml0.cleanup() except InvalidInputFileException, e: logging.exception(str(e)) raise e