def generateConditions(self, reactorTypeList, reactionTimeList, molFracList, Tlist=None, Plist=None, Vlist=None): """ Creates a list of conditions from from the lists provided. ======================= ==================================================== Argument Description ======================= ==================================================== `reactorTypeList` A list of strings of the cantera reactor type. List of supported types below: IdealGasReactor: A constant volume, zero-dimensional reactor for ideal gas mixtures IdealGasConstPressureReactor: A homogeneous, constant pressure, zero-dimensional reactor for ideal gas mixtures `reactionTimeList` A tuple object giving the ([list of reaction times], units) `molFracList` A list of molfrac dictionaries with species object keys and mole fraction values To specify the system for an ideal gas, you must define 2 of the following 3 parameters: `T0List` A tuple giving the ([list of initial temperatures], units) 'P0List' A tuple giving the ([list of initial pressures], units) 'V0List' A tuple giving the ([list of initial specific volumes], units) This saves all the reaction conditions into both the old and new cantera jobs. """ # Store the conditions in the observables test case, for bookkeeping self.conditions = generateCanteraConditions(reactorTypeList, reactionTimeList, molFracList, Tlist=Tlist, Plist=Plist, Vlist=Vlist) # Map the mole fractions dictionaries to species objects from the old and new models oldMolFracList = [] newMolFracList = [] for molFracCondition in molFracList: oldCondition = {} newCondition = {} oldSpeciesDict = getRMGSpeciesFromUserSpecies(molFracCondition.keys(), self.oldSim.speciesList) newSpeciesDict = getRMGSpeciesFromUserSpecies(molFracCondition.keys(), self.newSim.speciesList) for smiles, molfrac in molFracCondition.iteritems(): if oldSpeciesDict[smiles] is None: raise Exception('SMILES {0} was not found in the old model!'.format(smiles)) if newSpeciesDict[smiles] is None: raise Exception('SMILES {0} was not found in the new model!'.format(smiles)) oldCondition[oldSpeciesDict[smiles]] = molfrac newCondition[newSpeciesDict[smiles]] = molfrac oldMolFracList.append(oldCondition) newMolFracList.append(newCondition) # Generate the conditions in each simulation self.oldSim.generateConditions(reactorTypeList, reactionTimeList, oldMolFracList, Tlist=Tlist, Plist=Plist, Vlist=Vlist) self.newSim.generateConditions(reactorTypeList, reactionTimeList, newMolFracList, Tlist=Tlist, Plist=Plist, Vlist=Vlist)
def compare(self, tol, plot=False): """ Compare the old and new model 'tol': average error acceptable between old and new model for variables `plot`: if set to True, it will comparison plots of the two models comparing their species. Returns a list of variables failed in a list of tuples in the format: (CanteraCondition, variable label, variableOld, variableNew) """ # Ignore Inerts inertList = ['[Ar]','[He]','[N#N]','[Ne]'] oldConditionData, newConditionData = self.runSimulations() conditionsBroken=[] variablesFailed=[] print '' print '{0} Comparison'.format(self) print '================' # Check the species profile observables if 'species' in self.observables: oldSpeciesDict = getRMGSpeciesFromUserSpecies(self.observables['species'], self.oldSim.speciesList) newSpeciesDict = getRMGSpeciesFromUserSpecies(self.observables['species'], self.newSim.speciesList) # Check state variable observables implementedVariables = ['temperature','pressure'] if 'variable' in self.observables: for item in self.observables['variable']: if item.lower() not in implementedVariables: print 'Observable variable {0} not yet implemented'.format(item) failHeader='\nThe following observables did not match:\n' failHeaderPrinted=False for i in range(len(oldConditionData)): timeOld, dataListOld = oldConditionData[i] timeNew, dataListNew = newConditionData[i] # Compare species observables if 'species' in self.observables: smilesList=[] #This is to make sure we don't have species with duplicate smiles multiplicityList=['','(S)','(D)','(T)','(Q)'] #list ot add multiplcity for species in self.observables['species']: smiles=species.molecule[0].toSMILES() #For purpose of naming the plot only if smiles in smilesList: smiles=smiles+multiplicityList[species.molecule[0].multiplicity] smilesList.append(smiles) fail = False oldRmgSpecies = oldSpeciesDict[species] newRmgSpecies = newSpeciesDict[species] if oldRmgSpecies: variableOld = next((data for data in dataListOld if data.species == oldRmgSpecies), None) else: print 'No RMG species found for observable species {0} in old model.'.format(smiles) fail = True if newRmgSpecies: variableNew = next((data for data in dataListNew if data.species == newRmgSpecies), None) else: print 'No RMG species found for observable species {0} in new model.'.format(smiles) fail = True if fail is False: if not curvesSimilar(timeOld.data, variableOld.data, timeNew.data, variableNew.data, tol): fail = True # Try plotting only when species are found in both models if plot: oldSpeciesPlot = SimulationPlot(xVar=timeOld, yVar=variableOld) newSpeciesPlot = SimulationPlot(xVar=timeNew, yVar=variableNew) oldSpeciesPlot.comparePlot(newSpeciesPlot, title='Observable Species {0} Comparison'.format(smiles), ylabel='Mole Fraction', filename='condition_{0}_species_{1}.png'.format(i+1,smiles)) # Append to failed variables or conditions if this test failed if fail: if not failHeaderPrinted: print failHeader failHeaderPrinted=True if i not in conditionsBroken: conditionsBroken.append(i) print "Observable species {0} varied by more than {1:.3f} on average between old model {2} and \ new model {3} in condition {4:d}.".format(smiles, tol, variableOld.label, variableNew.label, i+1) variablesFailed.append((self.conditions[i], smiles, variableOld, variableNew)) # Compare state variable observables if 'variable' in self.observables: for varName in self.observables['variable']: variableOld = next((data for data in dataListOld if data.label == varName), None) variableNew = next((data for data in dataListNew if data.label == varName), None) if not curvesSimilar(timeOld.data, variableOld.data, timeNew.data, variableNew.data, 0.05): if i not in conditionsBroken: conditionsBroken.append(i) if not failHeaderPrinted: failHeaderPrinted=True print failHeader print "Observable variable {0} varied by more than {1:.3f} on average between old model and \ new model in condition {2:d}.".format(variableOld.label, i+1) variablesFailed.append((self.conditions[i], tol, varName, variableOld, variableNew)) if plot: oldVarPlot = GenericPlot(xVar=timeOld, yVar=variableOld) newVarPlot = GenericPlot(xVar=timeNew, yVar=variableNew) oldVarPlot.comparePlot(newSpeciesPlot, title='Observable Variable {0} Comparison'.format(varName), filename='condition_{0}_variable_{1}.png'.format(i+1, varName)) # Compare ignition delay observables if 'ignitionDelay' in self.observables: print 'Ignition delay observable comparison not implemented yet.' if failHeaderPrinted: print '' print 'The following reaction conditions were had some discrepancies:' print '' for index in conditionsBroken: print "Condition {0:d}:".format(index+1) print str(self.conditions[index]) print '' return variablesFailed else: print '' print 'All Observables varied by less than {0:.3f} on average between old model and \ new model in all conditions!'.format(tol) print ''
def run_cantera_job( smiles_dictionary, specie_initial_mol_frac, final_time, temp_initial, initial_p, chemkin_file='', species_dictionary_file='', transport_file=None, reactor_type='IdealGasConstPressureTemperatureReactor', time_units='s', temp_units='K', p_units='atm', species_list=None, reaction_list=None, ): """General function for running Cantera jobs from chemkin files with common defaults =========================== ======================================================================= Input (Required) Description =========================== ======================================================================= smiles_dictionary A dictionary with user names as keys and SMILES strings as values specie_initial_mol_frac A dictionary with user specie names as keys and mol fractions as values final_time Termination time for the simulation temp_initial Initial temperature for the simulation initial_p Initial pressure for the simulation =========================== ======================================================================= Inputs with Defaults Description =========================== ======================================================================= chemkin_file String relative path of the chem.inp or chem_annotated.inp file species_dictionary_file String relative path of species_dictionary file reactor_type String with Cantera reactor type time_units Default is s (min and h are also supported) temp_units Default is K (C is also supported) p_units Default is atm (bar and Pa are also supported) =========================== ======================================================================= Optional Inputs Description =========================== ======================================================================= transport_file String relative path of trans.dat file species_list Output from loadChemkinFile for faster simulation (otherwise generated) reaction_list Output from loadChemkinFile for faster simulation (otherwise generated) =================================================================================================== =========================== ======================================================================= Output Description =========================== ======================================================================= all_data Cantera Simulation Data Object [time, [temp, pressure, spc1, spc2,..]] =================================================================================================== """ logging.info( 'Running a cantera job using the chemkin file {}'.format(chemkin_file)) logging.debug('loading chemkin and species dictionary file') cwd = os.getcwd() if chemkin_file == '': chemkin_file = os.path.join(cwd, 'chem_annotated.inp') if species_dictionary_file == '': species_dictionary_file = os.path.join(cwd, 'species_dictionary.txt') user_species_dictionary = create_species_from_smiles(smiles_dictionary) specie_initial_mol_frac = set_species_mol_fractions( specie_initial_mol_frac, user_species_dictionary) if (not species_list) or (not reaction_list): (species_list, reaction_list) = loadChemkinFile(chemkin_file, species_dictionary_file) name_dictionary = getRMGSpeciesFromUserSpecies( user_species_dictionary.values(), species_list) mol_fractions = {} for (user_name, chemkin_name) in name_dictionary.iteritems(): try: mol_fractions[chemkin_name] = specie_initial_mol_frac[user_name] except KeyError: logging.debug( '{} initial mol fractions set to 0'.format(user_name)) if temp_units == 'C': temp_initial += 273.0 temp_initial = ([temp_initial], 'K') initial_p = ([initial_p], p_units) job = Cantera(speciesList=species_list, reactionList=reaction_list, outputDirectory='') job.loadChemkinModel(chemkin_file, transportFile=transport_file) job.generateConditions([reactor_type], ([final_time], time_units), [mol_fractions], temp_initial, initial_p) logging.debug('Starting Cantera Simulation') all_data = job.simulate() all_data = all_data[0] logging.info('Cantera Simulation Complete') logging.debug('Setting labels to user defined species labels') species_index = {} for i in range(len(species_list)): species_index[species_list[i]] = i + 2 user_index = {} for (user_name, specie) in user_species_dictionary.iteritems(): try: user_index[species_index[name_dictionary[specie]]] = user_name except KeyError: logging.info('{0} is not in the model for {1}'.format( user_name, chemkin_file)) for (indices, user_label) in user_index.iteritems(): try: all_data[1][indices].label = user_label except KeyError: pass return all_data
def compare(self, tol, plot=False): """ Compare the old and new model 'tol': average error acceptable between old and new model for variables `plot`: if set to True, it will comparison plots of the two models comparing their species. Returns a list of variables failed in a list of tuples in the format: (CanteraCondition, variable label, variableOld, variableNew) """ # Ignore Inerts inertList = ['[Ar]', '[He]', '[N#N]', '[Ne]'] oldConditionData, newConditionData = self.runSimulations() conditionsBroken = [] variablesFailed = [] print '' print '{0} Comparison'.format(self) print '================' # Check the species profile observables if 'species' in self.observables: oldSpeciesDict = getRMGSpeciesFromUserSpecies( self.observables['species'], self.oldSim.speciesList) newSpeciesDict = getRMGSpeciesFromUserSpecies( self.observables['species'], self.newSim.speciesList) # Check state variable observables implementedVariables = ['temperature', 'pressure'] if 'variable' in self.observables: for item in self.observables['variable']: if item.lower() not in implementedVariables: print 'Observable variable {0} not yet implemented'.format( item) failHeader = '\nThe following observables did not match:\n' failHeaderPrinted = False for i in range(len(oldConditionData)): timeOld, dataListOld = oldConditionData[i] timeNew, dataListNew = newConditionData[i] # Compare species observables if 'species' in self.observables: smilesList = [ ] #This is to make sure we don't have species with duplicate smiles multiplicityList = ['', '(S)', '(D)', '(T)', '(Q)'] #list ot add multiplcity for species in self.observables['species']: smiles = species.molecule[0].toSMILES( ) #For purpose of naming the plot only if smiles in smilesList: smiles = smiles + multiplicityList[ species.molecule[0].multiplicity] smilesList.append(smiles) fail = False oldRmgSpecies = oldSpeciesDict[species] newRmgSpecies = newSpeciesDict[species] if oldRmgSpecies: variableOld = next((data for data in dataListOld if data.species == oldRmgSpecies), None) else: print 'No RMG species found for observable species {0} in old model.'.format( smiles) fail = True if newRmgSpecies: variableNew = next((data for data in dataListNew if data.species == newRmgSpecies), None) else: print 'No RMG species found for observable species {0} in new model.'.format( smiles) fail = True if fail is False: if not curvesSimilar(timeOld.data, variableOld.data, timeNew.data, variableNew.data, tol): fail = True # Try plotting only when species are found in both models if plot: oldSpeciesPlot = SimulationPlot(xVar=timeOld, yVar=variableOld) newSpeciesPlot = SimulationPlot(xVar=timeNew, yVar=variableNew) oldSpeciesPlot.comparePlot( newSpeciesPlot, title='Observable Species {0} Comparison'. format(smiles), ylabel='Mole Fraction', filename='condition_{0}_species_{1}.png'. format(i + 1, smiles)) # Append to failed variables or conditions if this test failed if fail: if not failHeaderPrinted: print failHeader failHeaderPrinted = True if i not in conditionsBroken: conditionsBroken.append(i) print "Observable species {0} varied by more than {1:.3f} on average between old model {2} and \ new model {3} in condition {4:d}.".format(smiles, tol, variableOld.label, variableNew.label, i + 1) variablesFailed.append((self.conditions[i], smiles, variableOld, variableNew)) # Compare state variable observables if 'variable' in self.observables: for varName in self.observables['variable']: variableOld = next( (data for data in dataListOld if data.label == varName), None) variableNew = next( (data for data in dataListNew if data.label == varName), None) if not curvesSimilar(timeOld.data, variableOld.data, timeNew.data, variableNew.data, 0.05): if i not in conditionsBroken: conditionsBroken.append(i) if not failHeaderPrinted: failHeaderPrinted = True print failHeader print "Observable variable {0} varied by more than {1:.3f} on average between old model and \ new model in condition {2:d}.".format(variableOld.label, i + 1) variablesFailed.append( (self.conditions[i], tol, varName, variableOld, variableNew)) if plot: oldVarPlot = GenericPlot(xVar=timeOld, yVar=variableOld) newVarPlot = GenericPlot(xVar=timeNew, yVar=variableNew) oldVarPlot.comparePlot( newSpeciesPlot, title='Observable Variable {0} Comparison'.format( varName), filename='condition_{0}_variable_{1}.png'.format( i + 1, varName)) # Compare ignition delay observables if 'ignitionDelay' in self.observables: print 'Ignition delay observable comparison not implemented yet.' if failHeaderPrinted: print '' print 'The following reaction conditions were had some discrepancies:' print '' for index in conditionsBroken: print "Condition {0:d}:".format(index + 1) print str(self.conditions[index]) print '' return variablesFailed else: print '' print 'All Observables varied by less than {0:.3f} on average between old model and \ new model in all conditions!'.format(tol) print ''