Example #1
0
	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]
Example #2
0
	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)
Example #3
0
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