def test_compute_derivative(self): rxnList = [] rxnList.append(Reaction(reactants=[self.C2H6], products=[self.CH3,self.CH3], kinetics=Arrhenius(A=(686.375e6,'1/s'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[self.C2H6,self.CH3], products=[self.C2H5,self.CH4], kinetics=Arrhenius(A=(46.375*6,'m^3/(mol*s)'), n=3.40721, Ea=(6.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[self.C2H6,self.CH3,self.CH3], products=[self.C2H5,self.C2H5,self.H2], kinetics=Arrhenius(A=(146.375*6,'m^6/(mol^2*s)'), n=2.40721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K')))) coreSpecies = [self.CH4,self.CH3,self.C2H6,self.C2H5, self.H2] edgeSpecies = [] coreReactions = rxnList edgeReactions = [] numCoreSpecies = len(coreSpecies) c0={self.CH4:0.2,self.CH3:0.1,self.C2H6:0.35,self.C2H5:0.15, self.H2:0.2} rxnSystem0 = LiquidReactor(self.T, c0,termination=[]) rxnSystem0.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions) dfdt0 = rxnSystem0.residual(0.0, rxnSystem0.y, numpy.zeros(rxnSystem0.y.shape))[0] solver_dfdk = rxnSystem0.computeRateDerivative() #print 'Solver d(dy/dt)/dk' #print solver_dfdk integrationTime = 1e-8 modelSettings = ModelSettings(toleranceKeepInEdge = 0,toleranceMoveToCore=1,toleranceInterruptSimulation=0) simulatorSettings = SimulatorSettings() rxnSystem0.termination.append(TerminationTime((integrationTime,'s'))) rxnSystem0.simulate(coreSpecies, coreReactions, [], [], [],[], modelSettings=modelSettings,simulatorSettings=simulatorSettings) y0 = rxnSystem0.y dfdk = numpy.zeros((numCoreSpecies,len(rxnList))) # d(dy/dt)/dk c0={self.CH4:0.2,self.CH3:0.1,self.C2H6:0.35,self.C2H5:0.15, self.H2:0.2} for i in xrange(len(rxnList)): k0 = rxnList[i].getRateCoefficient(self.T) rxnList[i].kinetics.A.value_si = rxnList[i].kinetics.A.value_si*(1+1e-3) dk = rxnList[i].getRateCoefficient(self.T) - k0 rxnSystem = LiquidReactor(self.T, c0,termination=[]) rxnSystem.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions) dfdt = rxnSystem.residual(0.0, rxnSystem.y, numpy.zeros(rxnSystem.y.shape))[0] dfdk[:,i]=(dfdt-dfdt0)/dk rxnSystem.termination.append(TerminationTime((integrationTime,'s'))) modelSettings = ModelSettings(toleranceKeepInEdge = 0,toleranceMoveToCore=1,toleranceInterruptSimulation=0) simulatorSettings = SimulatorSettings() rxnSystem.simulate(coreSpecies, coreReactions,[],[],[],[], modelSettings=modelSettings,simulatorSettings=simulatorSettings) rxnList[i].kinetics.A.value_si = rxnList[i].kinetics.A.value_si/(1+1e-3) # reset A factor for i in xrange(numCoreSpecies): for j in xrange(len(rxnList)): self.assertAlmostEqual(dfdk[i,j], solver_dfdk[i,j], delta=abs(1e-3*dfdk[i,j]))
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.sensitivity import plotSensitivity 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, P, initialMoleFractions, termination, sensitiveSpecies, 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, ) plotSensitivity(self.outputDirectory, reactionSystemIndex, reactionSystem.sensitiveSpecies, number=number, fileformat=fileformat)
def testListen(self): """ Test that data can be retrieved from an attached ReactionSystem listener. """ #create observable reactionSystem = self.rmg.reactionSystems[0] reactionSystem.attach(self.listener) reactionModel = self.rmg.reactionModel self.assertEqual(self.listener.data, []) modelSettings = ModelSettings(toleranceMoveToCore=1, toleranceKeepInEdge=0, toleranceInterruptSimulation=1) simulatorSettings = SimulatorSettings() # run simulation: terminated, obj, sspcs, srxns = reactionSystem.simulate( coreSpecies=reactionModel.core.species, coreReactions=reactionModel.core.reactions, edgeSpecies=reactionModel.edge.species, edgeReactions=reactionModel.edge.reactions, surfaceSpecies=[], surfaceReactions=[], modelSettings=modelSettings, simulatorSettings=simulatorSettings, ) self.assertNotEqual(self.listener.data, [])
def test_listen(self): """ Test that data can be retrieved from an attached ReactionSystem listener. """ # create observable reaction_system = self.rmg.reaction_systems[0] reaction_system.attach(self.listener) reaction_model = self.rmg.reaction_model self.assertEqual(self.listener.data, []) model_settings = ModelSettings(tol_move_to_core=1, tol_keep_in_edge=0, tol_interrupt_simulation=1) simulator_settings = SimulatorSettings() # run simulation: terminated, resurrected, obj, sspcs, srxns, t, conv = reaction_system.simulate( core_species=reaction_model.core.species, core_reactions=reaction_model.core.reactions, edge_species=reaction_model.edge.species, edge_reactions=reaction_model.edge.reactions, surface_species=[], surface_reactions=[], model_settings=model_settings, simulator_settings=simulator_settings, ) self.assertNotEqual(self.listener.data, [])
def simulateOne(reactionModel, atol, rtol, reactionSystem): """ Simulates one reaction system, listener registers results, which are returned at the end. The returned data consists of a array of the species names, and the concentration data. The concentration data consists of a number of elements for each timestep the solver took to reach the end time of the batch reactor simulation. Each element consists of the time and the concentration data of the species at that particular timestep in the order of the species names. """ #register as a listener listener = ConcentrationListener() coreSpecies = reactionModel.core.species regex = r'\([0-9]+\)' #cut of '(one or more digits)' speciesNames = [] for spc in coreSpecies: name = getSpeciesIdentifier(spc) name_cutoff = re.split(regex, name)[0] speciesNames.append(name_cutoff) listener.speciesNames = speciesNames reactionSystem.attach(listener) pdepNetworks = [] for source, networks in reactionModel.networkDict.items(): pdepNetworks.extend(networks) simulatorSettings = SimulatorSettings(atol, rtol) modelSettings = ModelSettings(toleranceKeepInEdge=0, toleranceMoveToCore=1, toleranceInterruptSimulation=1) terminated, obj, sspcs, srxns = reactionSystem.simulate( coreSpecies=reactionModel.core.species, coreReactions=reactionModel.core.reactions, edgeSpecies=reactionModel.edge.species, edgeReactions=reactionModel.edge.reactions, surfaceSpecies=[], surfaceReactions=[], pdepNetworks=pdepNetworks, modelSettings=modelSettings, simulatorSettings=simulatorSettings, ) assert terminated #unregister as a listener reactionSystem.detach(listener) return listener.speciesNames, listener.data
def model(toleranceMoveToCore=None, toleranceMoveEdgeReactionToCore=numpy.inf, toleranceKeepInEdge=0.0, toleranceInterruptSimulation=1.0, toleranceMoveEdgeReactionToSurface=numpy.inf, toleranceMoveSurfaceSpeciesToCore=numpy.inf, toleranceMoveSurfaceReactionToCore=numpy.inf, toleranceMoveEdgeReactionToSurfaceInterrupt=None, toleranceMoveEdgeReactionToCoreInterrupt=None, maximumEdgeSpecies=1000000, minCoreSizeForPrune=50, minSpeciesExistIterationsForPrune=2, filterReactions=False, ignoreOverallFluxCriterion=False, maxNumSpecies=None, maxNumObjsPerIter=1, terminateAtMaxObjects=False, toleranceThermoKeepSpeciesInEdge=numpy.inf, dynamicsTimeScale=(0.0, 'sec')): """ How to generate the model. `toleranceMoveToCore` must be specified. toleranceMoveReactionToCore and toleranceReactionInterruptSimulation refers to an additional criterion for forcing an edge reaction to be included in the core by default this criterion is turned off Other parameters are optional and control the pruning. ignoreOverallFluxCriterion=True will cause the toleranceMoveToCore to be only applied to the pressure dependent network expansion and not movement of species from edge to core """ if toleranceMoveToCore is None: raise InputError( "You must provide a toleranceMoveToCore value. It should be less than or equal to toleranceInterruptSimulation which is currently {0}" .format(toleranceInterruptSimulation)) if toleranceMoveToCore > toleranceInterruptSimulation: raise InputError( "toleranceMoveToCore must be less than or equal to toleranceInterruptSimulation, which is currently {0}" .format(toleranceInterruptSimulation)) rmg.modelSettingsList.append( ModelSettings(toleranceMoveToCore, toleranceMoveEdgeReactionToCore, toleranceKeepInEdge, toleranceInterruptSimulation, toleranceMoveEdgeReactionToSurface, toleranceMoveSurfaceSpeciesToCore, toleranceMoveSurfaceReactionToCore, toleranceMoveEdgeReactionToSurfaceInterrupt, toleranceMoveEdgeReactionToCoreInterrupt, maximumEdgeSpecies, minCoreSizeForPrune, minSpeciesExistIterationsForPrune, filterReactions, ignoreOverallFluxCriterion, maxNumSpecies, maxNumObjsPerIter, terminateAtMaxObjects, toleranceThermoKeepSpeciesInEdge, Quantity(dynamicsTimeScale)))
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, P, initialMoleFractions, termination, sensitiveSpecies, 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 testSolve(self): """ Test the simple batch reactor with a simple kinetic model. Here we choose a kinetic model consisting of the hydrogen abstraction reaction CH4 + C2H5 <=> CH3 + C2H6. """ CH4 = Species( molecule=[Molecule().fromSMILES("C")], thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([ 8.615, 9.687,10.963,12.301,14.841,16.976,20.528],"cal/(mol*K)"), H298=(-17.714,"kcal/mol"), S298=(44.472,"cal/(mol*K)")) ) CH3 = Species( molecule=[Molecule().fromSMILES("[CH3]")], thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([ 9.397,10.123,10.856,11.571,12.899,14.055,16.195],"cal/(mol*K)"), H298=( 9.357,"kcal/mol"), S298=(45.174,"cal/(mol*K)")) ) C2H6 = Species( molecule=[Molecule().fromSMILES("CC")], thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([12.684,15.506,18.326,20.971,25.500,29.016,34.595],"cal/(mol*K)"), H298=(-19.521,"kcal/mol"), S298=(54.799,"cal/(mol*K)")) ) C2H5 = Species( molecule=[Molecule().fromSMILES("C[CH2]")], thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([11.635,13.744,16.085,18.246,21.885,24.676,29.107],"cal/(mol*K)"), H298=( 29.496,"kcal/mol"), S298=(56.687,"cal/(mol*K)")) ) rxn1 = Reaction(reactants=[C2H6,CH3], products=[C2H5,CH4], kinetics=Arrhenius(A=(686.375*6,'m^3/(mol*s)'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K'))) coreSpecies = [CH4,CH3,C2H6,C2H5] edgeSpecies = [] coreReactions = [rxn1] edgeReactions = [] T = 1000; P = 1.0e5 rxnSystem = SimpleReactor(T, P, initialMoleFractions={C2H5: 0.1, CH3: 0.1, CH4: 0.4, C2H6: 0.4}, termination=[]) rxnSystem.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions) tlist = numpy.array([10**(i/10.0) for i in range(-130, -49)], numpy.float64) # Integrate to get the solution at each time point t = []; y = []; reactionRates = []; speciesRates = [] for t1 in tlist: rxnSystem.advance(t1) t.append(rxnSystem.t) # You must make a copy of y because it is overwritten by DASSL at # each call to advance() y.append(rxnSystem.y.copy()) reactionRates.append(rxnSystem.coreReactionRates.copy()) speciesRates.append(rxnSystem.coreSpeciesRates.copy()) # Convert the solution vectors to numpy arrays t = numpy.array(t, numpy.float64) y = numpy.array(y, numpy.float64) reactionRates = numpy.array(reactionRates, numpy.float64) speciesRates = numpy.array(speciesRates, numpy.float64) V = constants.R * rxnSystem.T.value_si * numpy.sum(y) / rxnSystem.P.value_si # Check that we're computing the species fluxes correctly for i in range(t.shape[0]): self.assertAlmostEqual(reactionRates[i,0], speciesRates[i,0], delta=1e-6*reactionRates[i,0]) self.assertAlmostEqual(reactionRates[i,0], -speciesRates[i,1], delta=1e-6*reactionRates[i,0]) self.assertAlmostEqual(reactionRates[i,0], -speciesRates[i,2], delta=1e-6*reactionRates[i,0]) self.assertAlmostEqual(reactionRates[i,0], speciesRates[i,3], delta=1e-6*reactionRates[i,0]) # Check that we've reached equilibrium self.assertAlmostEqual(reactionRates[-1,0], 0.0, delta=1e-2) ####### # Unit test for the jacobian function: # Solve a reaction system and check if the analytical jacobian matches the finite difference jacobian H2 = Species( molecule=[Molecule().fromSMILES("[H][H]")], thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([6.89,6.97,6.99,7.01,7.08,7.22,7.72],"cal/(mol*K)"), H298=( 0,"kcal/mol"), S298=(31.23,"cal/(mol*K)")) ) rxnList = [] rxnList.append(Reaction(reactants=[C2H6], products=[CH3,CH3], kinetics=Arrhenius(A=(686.375*6,'1/s'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[CH3,CH3], products=[C2H6], kinetics=Arrhenius(A=(686.375*6,'m^3/(mol*s)'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[C2H6,CH3], products=[C2H5,CH4], kinetics=Arrhenius(A=(46.375*6,'m^3/(mol*s)'), n=3.40721, Ea=(6.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[C2H5,CH4], products=[C2H6,CH3], kinetics=Arrhenius(A=(46.375*6,'m^3/(mol*s)'), n=3.40721, Ea=(6.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[C2H5,CH4], products=[CH3,CH3,CH3], kinetics=Arrhenius(A=(246.375*6,'m^3/(mol*s)'), n=1.40721, Ea=(3.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[CH3,CH3,CH3], products=[C2H5,CH4], kinetics=Arrhenius(A=(246.375*6,'m^6/(mol^2*s)'), n=1.40721, Ea=(3.82799,'kcal/mol'), T0=(298.15,'K'))))# rxnList.append(Reaction(reactants=[C2H6,CH3,CH3], products=[C2H5,C2H5,H2], kinetics=Arrhenius(A=(146.375*6,'m^6/(mol^2*s)'), n=2.40721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[C2H5,C2H5,H2], products=[C2H6,CH3,CH3], kinetics=Arrhenius(A=(146.375*6,'m^6/(mol^2*s)'), n=2.40721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[C2H6,C2H6], products=[CH3,CH4,C2H5], kinetics=Arrhenius(A=(1246.375*6,'m^3/(mol*s)'), n=0.40721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[CH3,CH4,C2H5], products=[C2H6,C2H6], kinetics=Arrhenius(A=(46.375*6,'m^6/(mol^2*s)'), n=0.10721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K')))) for rxn in rxnList: coreSpecies = [CH4,CH3,C2H6,C2H5,H2] edgeSpecies = [] coreReactions = [rxn] rxnSystem0 = SimpleReactor(T,P,initialMoleFractions={CH4:0.2,CH3:0.1,C2H6:0.35,C2H5:0.15, H2:0.2},termination=[]) rxnSystem0.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions) dydt0 = rxnSystem0.residual(0.0, rxnSystem0.y, numpy.zeros(rxnSystem0.y.shape))[0] numCoreSpecies = len(coreSpecies) dN = .000001*sum(rxnSystem0.y) dN_array = dN*numpy.eye(numCoreSpecies) dydt = [] for i in range(numCoreSpecies): rxnSystem0.y[i] += dN dydt.append(rxnSystem0.residual(0.0, rxnSystem0.y, numpy.zeros(rxnSystem0.y.shape))[0]) rxnSystem0.y[i] -= dN # reset y to original y0 # Let the solver compute the jacobian solverJacobian = rxnSystem0.jacobian(0.0, rxnSystem0.y, dydt0, 0.0) # Compute the jacobian using finite differences jacobian = numpy.zeros((numCoreSpecies, numCoreSpecies)) for i in range(numCoreSpecies): for j in range(numCoreSpecies): jacobian[i,j] = (dydt[j][i]-dydt0[i])/dN self.assertAlmostEqual(jacobian[i,j], solverJacobian[i,j], delta=abs(1e-4*jacobian[i,j])) #print 'Solver jacobian' #print solverJacobian #print 'Numerical jacobian' #print jacobian ### # Unit test for the compute rate derivative rxnList = [] rxnList.append(Reaction(reactants=[C2H6], products=[CH3,CH3], kinetics=Arrhenius(A=(686.375e6,'1/s'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[C2H6,CH3], products=[C2H5,CH4], kinetics=Arrhenius(A=(46.375*6,'m^3/(mol*s)'), n=3.40721, Ea=(6.82799,'kcal/mol'), T0=(298.15,'K')))) rxnList.append(Reaction(reactants=[C2H6,CH3,CH3], products=[C2H5,C2H5,H2], kinetics=Arrhenius(A=(146.375*6,'m^6/(mol^2*s)'), n=2.40721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K')))) coreSpecies = [CH4,CH3,C2H6,C2H5,H2] edgeSpecies = [] coreReactions = rxnList rxnSystem0 = SimpleReactor(T,P,initialMoleFractions={CH4:0.2,CH3:0.1,C2H6:0.35,C2H5:0.15, H2:0.2},termination=[]) rxnSystem0.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions) dfdt0 = rxnSystem0.residual(0.0, rxnSystem0.y, numpy.zeros(rxnSystem0.y.shape))[0] solver_dfdk = rxnSystem0.computeRateDerivative() #print 'Solver d(dy/dt)/dk' #print solver_dfdk integrationTime = 1e-8 rxnSystem0.termination.append(TerminationTime((integrationTime,'s'))) modelSettings = ModelSettings(toleranceKeepInEdge = 0,toleranceMoveToCore=1,toleranceInterruptSimulation=0) simulatorSettings = SimulatorSettings() rxnSystem0.simulate(coreSpecies, coreReactions, [], [], [],[], modelSettings = modelSettings, simulatorSettings=simulatorSettings) y0 = rxnSystem0.y dfdk = numpy.zeros((numCoreSpecies,len(rxnList))) # d(dy/dt)/dk for i in range(len(rxnList)): k0 = rxnList[i].getRateCoefficient(T,P) rxnList[i].kinetics.A.value_si = rxnList[i].kinetics.A.value_si*(1+1e-3) dk = rxnList[i].getRateCoefficient(T,P) - k0 rxnSystem = SimpleReactor(T,P,initialMoleFractions={CH4:0.2,CH3:0.1,C2H6:0.35,C2H5:0.15, H2:0.2},termination=[]) rxnSystem.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions) dfdt = rxnSystem.residual(0.0, rxnSystem.y, numpy.zeros(rxnSystem.y.shape))[0] dfdk[:,i]=(dfdt-dfdt0)/dk rxnSystem.termination.append(TerminationTime((integrationTime,'s'))) modelSettings = ModelSettings(toleranceKeepInEdge=0,toleranceMoveToCore=1,toleranceInterruptSimulation=0) simulatorSettings = SimulatorSettings() rxnSystem.simulate(coreSpecies, coreReactions, [], [], [], [], modelSettings=modelSettings, simulatorSettings=simulatorSettings) rxnList[i].kinetics.A.value_si = rxnList[i].kinetics.A.value_si/(1+1e-3) # reset A factor for i in range(numCoreSpecies): for j in range(len(rxnList)): self.assertAlmostEqual(dfdk[i,j], solver_dfdk[i,j], delta=abs(1e-3*dfdk[i,j]))
def sensitivity_analysis(self, initial_mole_fractions, sensitive_species, T, P, termination_time, sensitivity_threshold=1e-3, number=10, fileformat='.png'): """ Run sensitivity analysis using the RMG solver in a single ReactionSystem object initial_mole_fractions is a dictionary with Species objects as keys and mole fraction initial conditions sensitive_species 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.rmg.listener import SimulationProfileWriter, SimulationProfilePlotter from rmgpy.rmg.settings import ModelSettings, SimulatorSettings T = Quantity(T) P = Quantity(P) termination = [TerminationTime(Quantity(termination_time))] reaction_system = SimpleReactor( T=T, P=P, initial_mole_fractions=initial_mole_fractions, termination=termination, sensitive_species=sensitive_species, sensitivity_threshold=sensitivity_threshold) # Create the csv worksheets for logging sensitivity util.make_output_subdirectory(self.output_directory, 'solver') sens_worksheet = [] reaction_system_index = 0 for spec in reaction_system.sensitive_species: csvfile_path = os.path.join( self.output_directory, 'solver', 'sensitivity_{0}_SPC_{1}.csv'.format(reaction_system_index + 1, spec.index)) sens_worksheet.append(csvfile_path) reaction_system.attach( SimulationProfileWriter(self.output_directory, reaction_system_index, self.species_list)) reaction_system.attach( SimulationProfilePlotter(self.output_directory, reaction_system_index, self.species_list)) simulator_settings = SimulatorSettings() # defaults model_settings = ModelSettings() # defaults model_settings.tol_move_to_core = 0.1 model_settings.tol_interrupt_simulation = 1.0 model_settings.tol_keep_in_edge = 0.0 reaction_system.simulate( core_species=self.species_list, core_reactions=self.reaction_list, edge_species=[], edge_reactions=[], surface_species=[], surface_reactions=[], model_settings=model_settings, simulator_settings=simulator_settings, sensitivity=True, sens_worksheet=sens_worksheet, ) plot_sensitivity(self.output_directory, reaction_system_index, reaction_system.sensitive_species, number=number, fileformat=fileformat)
def simulate(rmg, diffusionLimited=True): """ Simulate the RMG job and run the sensitivity analysis if it is on, generating output csv files diffusionLimited=True implies that if it is a liquid reactor diffusion limitations will be enforced otherwise they will not be in a liquid reactor """ util.makeOutputSubdirectory(rmg.outputDirectory, 'solver') for index, reactionSystem in enumerate(rmg.reactionSystems): if reactionSystem.sensitiveSpecies: logging.info( 'Conducting simulation and sensitivity analysis of reaction system %s...' % (index + 1)) else: logging.info('Conducting simulation of reaction system %s...' % (index + 1)) if rmg.saveSimulationProfiles: reactionSystem.attach( SimulationProfileWriter(rmg.outputDirectory, index, rmg.reactionModel.core.species)) reactionSystem.attach( SimulationProfilePlotter(rmg.outputDirectory, index, rmg.reactionModel.core.species)) sensWorksheet = [] for spec in reactionSystem.sensitiveSpecies: csvfilePath = os.path.join( rmg.outputDirectory, 'solver', 'sensitivity_{0}_SPC_{1}.csv'.format(index + 1, spec.index)) sensWorksheet.append(csvfilePath) pdepNetworks = [] for source, networks in rmg.reactionModel.networkDict.items(): pdepNetworks.extend(networks) modelSettings = ModelSettings(toleranceKeepInEdge=0, toleranceMoveToCore=1, toleranceInterruptSimulation=1) simulatorSettings = rmg.simulatorSettingsList[-1] if isinstance(reactionSystem, LiquidReactor): if diffusionLimited: rmg.loadDatabase() solventData = rmg.database.solvation.getSolventData( rmg.solvent) diffusionLimiter.enable(solventData, rmg.database.solvation) # Store constant species indices if reactionSystem.constSPCNames is not None: reactionSystem.get_constSPCIndices( rmg.reactionModel.core.species) reactionSystem.simulate( coreSpecies=rmg.reactionModel.core.species, coreReactions=rmg.reactionModel.core.reactions, edgeSpecies=rmg.reactionModel.edge.species, edgeReactions=rmg.reactionModel.edge.reactions, surfaceSpecies=[], surfaceReactions=[], pdepNetworks=pdepNetworks, sensitivity=True if reactionSystem.sensitiveSpecies else False, sensWorksheet=sensWorksheet, modelSettings=modelSettings, simulatorSettings=simulatorSettings, ) if reactionSystem.sensitiveSpecies: plotSensitivity(rmg.outputDirectory, index, reactionSystem.sensitiveSpecies)
def simulate(rmg, diffusion_limited=True): """ Simulate the RMG job and run the sensitivity analysis if it is on, generating output csv files diffusion_limited=True implies that if it is a liquid reactor diffusion limitations will be enforced otherwise they will not be in a liquid reactor """ util.make_output_subdirectory(rmg.output_directory, 'solver') for index, reaction_system in enumerate(rmg.reaction_systems): if reaction_system.sensitive_species: logging.info( 'Conducting simulation and sensitivity analysis of reaction system %s...' % (index + 1)) if reaction_system.sensitive_species == ['all']: reaction_system.sensitive_species = rmg.reaction_model.core.species else: logging.info('Conducting simulation of reaction system %s...' % (index + 1)) reaction_system.attach( SimulationProfileWriter(rmg.output_directory, index, rmg.reaction_model.core.species)) reaction_system.attach( SimulationProfilePlotter(rmg.output_directory, index, rmg.reaction_model.core.species)) sens_worksheet = [] for spec in reaction_system.sensitive_species: csvfile_path = os.path.join( rmg.output_directory, 'solver', 'sensitivity_{0}_SPC_{1}.csv'.format(index + 1, spec.index)) sens_worksheet.append(csvfile_path) pdep_networks = [] for source, networks in rmg.reaction_model.network_dict.items(): pdep_networks.extend(networks) model_settings = ModelSettings(tol_keep_in_edge=0, tol_move_to_core=1, tol_interrupt_simulation=1) simulator_settings = rmg.simulator_settings_list[-1] if isinstance(reaction_system, LiquidReactor): if diffusion_limited: rmg.load_database() solvent_data = rmg.database.solvation.get_solvent_data( rmg.solvent) diffusion_limiter.enable(solvent_data, rmg.database.solvation) # Store constant species indices if reaction_system.const_spc_names is not None: reaction_system.get_const_spc_indices( rmg.reaction_model.core.species) elif rmg.uncertainty is not None: rmg.verbose_comments = True rmg.load_database() reaction_system.simulate( core_species=rmg.reaction_model.core.species, core_reactions=rmg.reaction_model.core.reactions, edge_species=rmg.reaction_model.edge.species, edge_reactions=rmg.reaction_model.edge.reactions, surface_species=[], surface_reactions=[], pdep_networks=pdep_networks, sensitivity=True if reaction_system.sensitive_species else False, sens_worksheet=sens_worksheet, model_settings=model_settings, simulator_settings=simulator_settings, ) if reaction_system.sensitive_species: plot_sensitivity(rmg.output_directory, index, reaction_system.sensitive_species) rmg.run_uncertainty_analysis()
def simulate(rmg): """ Simulate the RMG job and run the sensitivity analysis if it is on, generating output csv files """ util.makeOutputSubdirectory(rmg.outputDirectory, 'solver') for index, reactionSystem in enumerate(rmg.reactionSystems): if reactionSystem.sensitiveSpecies: logging.info( 'Conducting simulation and sensitivity analysis of reaction system %s...' % (index + 1)) else: logging.info('Conducting simulation of reaction system %s...' % (index + 1)) if rmg.saveSimulationProfiles: reactionSystem.attach( SimulationProfileWriter(rmg.outputDirectory, index, rmg.reactionModel.core.species)) reactionSystem.attach( SimulationProfilePlotter(rmg.outputDirectory, index, rmg.reactionModel.core.species)) else: worksheet = None sensWorksheet = [] for spec in reactionSystem.sensitiveSpecies: csvfilePath = os.path.join( rmg.outputDirectory, 'solver', 'sensitivity_{0}_SPC_{1}.csv'.format(index + 1, spec.index)) sensWorksheet.append(csvfilePath) pdepNetworks = [] for source, networks in rmg.reactionModel.networkDict.items(): pdepNetworks.extend(networks) modelSettings = ModelSettings(toleranceKeepInEdge=0, toleranceMoveToCore=1, toleranceInterruptSimulation=1) simulatorSettings = rmg.simulatorSettingsList[-1] terminated, obj, sspcs, srxns = reactionSystem.simulate( coreSpecies=rmg.reactionModel.core.species, coreReactions=rmg.reactionModel.core.reactions, edgeSpecies=rmg.reactionModel.edge.species, edgeReactions=rmg.reactionModel.edge.reactions, surfaceSpecies=[], surfaceReactions=[], pdepNetworks=pdepNetworks, sensitivity=True if reactionSystem.sensitiveSpecies else False, sensWorksheet=sensWorksheet, modelSettings=modelSettings, simulatorSettings=simulatorSettings, ) if reactionSystem.sensitiveSpecies: plotSensitivity(rmg.outputDirectory, index, reactionSystem.sensitiveSpecies)