def test_storeConstantSpeciesNames(self): "Test if (i) constant species names are stored in reactor attributes and (ii) if attributes are not mix/equal for multiple conditions generation" c0 = {self.C2H5: 0.1, self.CH3: 0.1, self.CH4: 0.4, self.C2H6: 0.4} Temp = 1000 # #set up the liquid phase reactor 1 terminationConversion = [] terminationTime = None sensitivity = [] sensitivityThreshold = 0.001 constantSpecies = ["CH4", "C2H6"] rxnSystem1 = LiquidReactor(Temp, c0, terminationConversion, sensitivity, sensitivityThreshold, constantSpecies) #set up the liquid phase reactor 2 constantSpecies = ["O2", "H2O"] rxnSystem2 = LiquidReactor(Temp, c0, terminationConversion, sensitivity, sensitivityThreshold, constantSpecies) for reactor in [rxnSystem1, rxnSystem2]: self.assertIsNotNone(reactor.constSPCNames) #check if Constant species are different in each liquid system for spc in rxnSystem1.constSPCNames: for spc2 in rxnSystem2.constSPCNames: self.assertIsNot( spc, spc2, "Constant species declared in two different reactors seem mixed. Species \"{0}\" appears in both systems and should be." .format(spc))
def testComputeFlux(self): """ Test the liquid batch reactor with a simple kinetic model. """ rxn1 = Reaction( reactants=[self.C2H6, self.CH3], products=[self.C2H5, self.CH4], kinetics=Arrhenius(A=(686.375*6, 'm^3/(mol*s)'), n=4.40721, Ea=(7.82799, 'kcal/mol'), T0=(298.15, 'K')) ) coreSpecies = [self.CH4, self.CH3, self.C2H6, self.C2H5] edgeSpecies = [] coreReactions = [rxn1] edgeReactions = [] c0 = {self.C2H5: 0.1, self.CH3: 0.1, self.CH4: 0.4, self.C2H6: 0.4} rxnSystem = LiquidReactor(self.T, c0, 1, termination=[]) rxnSystem.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions) tlist = numpy.array([10**(i/10.0) for i in xrange(-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) reactionRates = numpy.array(reactionRates, numpy.float64) speciesRates = numpy.array(speciesRates, numpy.float64) # Check that we're computing the species fluxes correctly for i in xrange(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)
def liquidReactor(temperature, initialConcentrations, terminationConversion=None, terminationTime=None, sensitivity=None, sensitivityThreshold=1e-3): logging.debug('Found LiquidReactor reaction system') T = Quantity(temperature) for spec, conc in initialConcentrations.iteritems(): concentration = Quantity(conc) # check the dimensions are ok # convert to mol/m^3 (or something numerically nice? or must it be SI) initialConcentrations[spec] = concentration.value_si termination = [] if terminationConversion is not None: for spec, conv in terminationConversion.iteritems(): termination.append(TerminationConversion(speciesDict[spec], conv)) if terminationTime is not None: termination.append(TerminationTime(Quantity(terminationTime))) if len(termination) == 0: raise InputError( 'No termination conditions specified for reaction system #{0}.'. format(len(rmg.reactionSystems) + 2)) sensitiveSpecies = [] if sensitivity: for spec in sensitivity: sensitiveSpecies.append(speciesDict[spec]) system = LiquidReactor(T, initialConcentrations, termination, sensitiveSpecies, sensitivityThreshold) rmg.reactionSystems.append(system)
def test_corespeciesRate(self): "Test if a specific core species rate is equal to 0 over time" c0={self.C2H5: 0.1, self.CH3: 0.1, self.CH4: 0.4, self.C2H6: 0.4} rxn1 = Reaction(reactants=[self.C2H6,self.CH3], products=[self.C2H5,self.CH4], kinetics=Arrhenius(A=(686.375*6,'m^3/(mol*s)'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K'))) coreSpecies = [self.CH4,self.CH3,self.C2H6,self.C2H5] edgeSpecies = [] coreReactions = [rxn1] edgeReactions = [] sensitivity=[] terminationConversion = [] sensitivityThreshold=0.001 ConstSpecies = ["CH4"] rxnSystem = LiquidReactor(self.T, c0, terminationConversion, sensitivity,sensitivityThreshold,ConstSpecies) ##The test regarding the writting of constantSPCindices from input file is check with the previous test. rxnSystem.constSPCIndices=[0] 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) self.assertEqual(rxnSystem.coreSpeciesRates[0], 0,"Core species rate has to be equal to 0 for species hold constant. Here it is equal to {0}".format(rxnSystem.coreSpeciesRates[0]))
def test_jacobian(self): """ Unit test for the jacobian function: Solve a reaction system and check if the analytical jacobian matches the finite difference jacobian """ coreSpecies = [self.CH4,self.CH3,self.C2H6,self.C2H5] edgeSpecies = [] rxn1 = Reaction(reactants=[self.C2H6,self.CH3], products=[self.C2H5,self.CH4], kinetics=Arrhenius(A=(686.375*6,'m^3/(mol*s)'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K'))) coreReactions = [rxn1] edgeReactions = [] numCoreSpecies = len(coreSpecies) rxnList = [] rxnList.append(Reaction(reactants=[self.C2H6], products=[self.CH3,self.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=[self.CH3,self.CH3], products=[self.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=[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.C2H5,self.CH4], products=[self.C2H6,self.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=[self.C2H5,self.CH4], products=[self.CH3,self.CH3,self.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=[self.CH3,self.CH3,self.CH3], products=[self.C2H5,self.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=[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')))) rxnList.append(Reaction(reactants=[self.C2H5,self.C2H5,self.H2], products=[self.C2H6,self.CH3,self.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=[self.C2H6,self.C2H6], products=[self.CH3,self.CH4,self.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=[self.CH3,self.CH4,self.C2H5], products=[self.C2H6,self.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 = [self.CH4,self.CH3,self.C2H6,self.C2H5,self.H2] edgeSpecies = [] coreReactions = [rxn] 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) dydt0 = rxnSystem0.residual(0.0, rxnSystem0.y, numpy.zeros(rxnSystem0.y.shape))[0] dN = .000001*sum(rxnSystem0.y) dN_array = dN*numpy.eye(numCoreSpecies) dydt = [] for i in xrange(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 xrange(numCoreSpecies): for j in xrange(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]))
def test_compute_flux(self): """ Test the liquid batch reactor with a simple kinetic model. """ rxn1 = Reaction(reactants=[self.C2H6, self.CH3], products=[self.C2H5, self.CH4], kinetics=Arrhenius(A=(686.375 * 6, 'm^3/(mol*s)'), n=4.40721, Ea=(7.82799, 'kcal/mol'), T0=(298.15, 'K'))) core_species = [self.CH4, self.CH3, self.C2H6, self.C2H5] edge_species = [] core_reactions = [rxn1] edge_reactions = [] c0 = {self.C2H5: 0.1, self.CH3: 0.1, self.CH4: 0.4, self.C2H6: 0.4} rxn_system = LiquidReactor(self.T, c0, 1, termination=[]) rxn_system.initialize_model(core_species, core_reactions, edge_species, edge_reactions) tlist = np.array([10**(i / 10.0) for i in range(-130, -49)], np.float64) # Integrate to get the solution at each time point t, y, reaction_rates, species_rates = [], [], [], [] for t1 in tlist: rxn_system.advance(t1) t.append(rxn_system.t) # You must make a copy of y because it is overwritten by DASSL at # each call to advance() y.append(rxn_system.y.copy()) reaction_rates.append(rxn_system.core_reaction_rates.copy()) species_rates.append(rxn_system.core_species_rates.copy()) # Convert the solution vectors to np arrays t = np.array(t, np.float64) reaction_rates = np.array(reaction_rates, np.float64) species_rates = np.array(species_rates, np.float64) # Check that we're computing the species fluxes correctly for i in range(t.shape[0]): self.assertAlmostEqual(reaction_rates[i, 0], species_rates[i, 0], delta=1e-6 * reaction_rates[i, 0]) self.assertAlmostEqual(reaction_rates[i, 0], -species_rates[i, 1], delta=1e-6 * reaction_rates[i, 0]) self.assertAlmostEqual(reaction_rates[i, 0], -species_rates[i, 2], delta=1e-6 * reaction_rates[i, 0]) self.assertAlmostEqual(reaction_rates[i, 0], species_rates[i, 3], delta=1e-6 * reaction_rates[i, 0]) # Check that we've reached equilibrium self.assertAlmostEqual(reaction_rates[-1, 0], 0.0, delta=1e-2)
def test_corespeciesRate(self): """ Test if a specific core species rate is equal to 0 over time. """ c0 = {self.C2H5: 0.1, self.CH3: 0.1, self.CH4: 0.4, self.C2H6: 0.4} rxn1 = Reaction( reactants=[self.C2H6, self.CH3], products=[self.C2H5, self.CH4], kinetics=Arrhenius(A=(686.375*6, 'm^3/(mol*s)'), n=4.40721, Ea=(7.82799, 'kcal/mol'), T0=(298.15, 'K')) ) coreSpecies = [self.CH4, self.CH3, self.C2H6, self.C2H5] edgeSpecies = [] coreReactions = [rxn1] edgeReactions = [] sensitivity = [] terminationConversion = [] sensitivityThreshold = 0.001 ConstSpecies = ["CH4"] rxnSystem = LiquidReactor(self.T, c0, terminationConversion, sensitivity, sensitivityThreshold, ConstSpecies) # The test regarding the writing of constantSPCindices from input file is check with the previous test. rxnSystem.constSPCIndices = [0] 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) self.assertEqual(rxnSystem.coreSpeciesRates[0], 0, "Core species rate has to be equal to 0 for species hold constant. Here it is equal to {0}".format(rxnSystem.coreSpeciesRates[0]))
def test_store_constant_species_names(self): """ Test if (i) constant species names are stored in reactor attributes and (ii) if attributes are not mix/equal for multiple conditions generation. """ c0 = {self.C2H5: 0.1, self.CH3: 0.1, self.CH4: 0.4, self.C2H6: 0.4} temp = 1000 # set up the liquid phase reactor 1 termination_conversion = [] termination_time = None sensitivity = [] sensitivity_threshold = 0.001 constant_species = ["CH4", "C2H6"] sens_conds = None rxn_system1 = LiquidReactor(temp, c0, 4, termination_conversion, sensitivity, sensitivity_threshold, sens_conds, constant_species) # set up the liquid phase reactor 2 constant_species = ["O2", "H2O"] rxn_system2 = LiquidReactor(temp, c0, 4, termination_conversion, sensitivity, sensitivity_threshold, sens_conds, constant_species) for reactor in [rxn_system1, rxn_system2]: self.assertIsNotNone(reactor.const_spc_names) # check if Constant species are different in each liquid system for spc in rxn_system1.const_spc_names: for spc2 in rxn_system2.const_spc_names: self.assertIsNot( spc, spc2, 'Constant species declared in two different reactors seem mixed. ' 'Species "{0}" appears in both systems and should be.'. format(spc))
def test_compute_derivative(self): rxn_list = [ 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'))), 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'))), 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'))), ] core_species = [self.CH4, self.CH3, self.C2H6, self.C2H5, self.H2] edge_species = [] core_reactions = rxn_list edge_reactions = [] num_core_species = len(core_species) c0 = { self.CH4: 0.2, self.CH3: 0.1, self.C2H6: 0.35, self.C2H5: 0.15, self.H2: 0.2 } rxn_system0 = LiquidReactor(self.T, c0, 1, termination=[]) rxn_system0.initialize_model(core_species, core_reactions, edge_species, edge_reactions) dfdt0 = rxn_system0.residual(0.0, rxn_system0.y, np.zeros(rxn_system0.y.shape))[0] solver_dfdk = rxn_system0.compute_rate_derivative() # print 'Solver d(dy/dt)/dk' # print solver_dfdk integration_time = 1e-8 model_settings = ModelSettings(tol_keep_in_edge=0, tol_move_to_core=1, tol_interrupt_simulation=0) simulator_settings = SimulatorSettings() rxn_system0.termination.append(TerminationTime( (integration_time, 's'))) rxn_system0.simulate(core_species, core_reactions, [], [], [], [], model_settings=model_settings, simulator_settings=simulator_settings) y0 = rxn_system0.y dfdk = np.zeros((num_core_species, len(rxn_list))) # 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 range(len(rxn_list)): k0 = rxn_list[i].get_rate_coefficient(self.T) rxn_list[i].kinetics.A.value_si = rxn_list[ i].kinetics.A.value_si * (1 + 1e-3) dk = rxn_list[i].get_rate_coefficient(self.T) - k0 rxn_system = LiquidReactor(self.T, c0, 1, termination=[]) rxn_system.initialize_model(core_species, core_reactions, edge_species, edge_reactions) dfdt = rxn_system.residual(0.0, rxn_system.y, np.zeros(rxn_system.y.shape))[0] dfdk[:, i] = (dfdt - dfdt0) / dk rxn_system.termination.append( TerminationTime((integration_time, 's'))) model_settings = ModelSettings(tol_keep_in_edge=0, tol_move_to_core=1, tol_interrupt_simulation=0) simulator_settings = SimulatorSettings() rxn_system.simulate(core_species, core_reactions, [], [], [], [], model_settings=model_settings, simulator_settings=simulator_settings) rxn_list[i].kinetics.A.value_si = rxn_list[ i].kinetics.A.value_si / (1 + 1e-3) # reset A factor for i in range(num_core_species): for j in range(len(rxn_list)): self.assertAlmostEqual(dfdk[i, j], solver_dfdk[i, j], delta=abs(1e-3 * dfdk[i, j]))
def test_jacobian(self): """ Unit test for the jacobian function: Solve a reaction system and check if the analytical jacobian matches the finite difference jacobian. """ core_species = [self.CH4, self.CH3, self.C2H6, self.C2H5, self.H2] edge_species = [] num_core_species = len(core_species) c0 = { self.CH4: 0.2, self.CH3: 0.1, self.C2H6: 0.35, self.C2H5: 0.15, self.H2: 0.2 } edge_reactions = [] rxn_list = [ Reaction(reactants=[self.C2H6], products=[self.CH3, self.CH3], kinetics=Arrhenius(A=(686.375 * 6, '1/s'), n=4.40721, Ea=(7.82799, 'kcal/mol'), T0=(298.15, 'K'))), Reaction(reactants=[self.CH3, self.CH3], products=[self.C2H6], kinetics=Arrhenius(A=(686.375 * 6, 'm^3/(mol*s)'), n=4.40721, Ea=(7.82799, 'kcal/mol'), T0=(298.15, 'K'))), 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'))), Reaction(reactants=[self.C2H5, self.CH4], products=[self.C2H6, self.CH3], kinetics=Arrhenius(A=(46.375 * 6, 'm^3/(mol*s)'), n=3.40721, Ea=(6.82799, 'kcal/mol'), T0=(298.15, 'K'))), Reaction(reactants=[self.C2H5, self.CH4], products=[self.CH3, self.CH3, self.CH3], kinetics=Arrhenius(A=(246.375 * 6, 'm^3/(mol*s)'), n=1.40721, Ea=(3.82799, 'kcal/mol'), T0=(298.15, 'K'))), Reaction(reactants=[self.CH3, self.CH3, self.CH3], products=[self.C2H5, self.CH4], kinetics=Arrhenius(A=(246.375 * 6, 'm^6/(mol^2*s)'), n=1.40721, Ea=(3.82799, 'kcal/mol'), T0=(298.15, 'K'))), 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'))), Reaction(reactants=[self.C2H5, self.C2H5, self.H2], products=[self.C2H6, self.CH3, self.CH3], kinetics=Arrhenius(A=(146.375 * 6, 'm^6/(mol^2*s)'), n=2.40721, Ea=(8.82799, 'kcal/mol'), T0=(298.15, 'K'))), Reaction(reactants=[self.C2H6, self.C2H6], products=[self.CH3, self.CH4, self.C2H5], kinetics=Arrhenius(A=(1246.375 * 6, 'm^3/(mol*s)'), n=0.40721, Ea=(8.82799, 'kcal/mol'), T0=(298.15, 'K'))), Reaction(reactants=[self.CH3, self.CH4, self.C2H5], products=[self.C2H6, self.C2H6], kinetics=Arrhenius(A=(46.375 * 6, 'm^6/(mol^2*s)'), n=0.10721, Ea=(8.82799, 'kcal/mol'), T0=(298.15, 'K'))), ] # Analytical Jacobian for reaction 6 def jacobian_rxn6(c, kf, kr, s): c1, c2, c3, c4 = c[s[1]], c[s[2]], c[s[3]], c[s[4]] jaco = np.zeros((5, 5)) jaco[1, 1] = -4 * kf * c1 * c2 jaco[1, 2] = -2 * kf * c1 * c1 jaco[1, 3] = 4 * kr * c3 * c4 jaco[1, 4] = 2 * kr * c3 * c3 jaco[2, 1:] = 0.5 * jaco[1, 1:] jaco[3, 1:] = -jaco[1, 1:] jaco[4, 1:] = -0.5 * jaco[1, 1:] return jaco # Analytical Jacobian for reaction 7 def jacobian_rxn7(c, kf, kr, s): c1, c2, c3, c4 = c[s[1]], c[s[2]], c[s[3]], c[s[4]] jaco = np.zeros((5, 5)) jaco[1, 1] = -4 * kr * c1 * c2 jaco[1, 2] = -2 * kr * c1 * c1 jaco[1, 3] = 4 * kf * c3 * c4 jaco[1, 4] = 2 * kf * c3 * c3 jaco[2, 1:] = 0.5 * jaco[1, 1:] jaco[3, 1:] = -jaco[1, 1:] jaco[4, 1:] = -0.5 * jaco[1, 1:] return jaco for rxn_num, rxn in enumerate(rxn_list): core_reactions = [rxn] rxn_system0 = LiquidReactor(self.T, c0, 1, termination=[]) rxn_system0.initialize_model(core_species, core_reactions, edge_species, edge_reactions) dydt0 = rxn_system0.residual(0.0, rxn_system0.y, np.zeros(rxn_system0.y.shape))[0] dN = .000001 * sum(rxn_system0.y) # Let the solver compute the jacobian solver_jacobian = rxn_system0.jacobian(0.0, rxn_system0.y, dydt0, 0.0) if rxn_num not in (6, 7): dydt = [] for i in range(num_core_species): rxn_system0.y[i] += dN dydt.append( rxn_system0.residual(0.0, rxn_system0.y, np.zeros(rxn_system0.y.shape))[0]) rxn_system0.y[i] -= dN # reset y # Compute the jacobian using finite differences jacobian = np.zeros((num_core_species, num_core_species)) for i in range(num_core_species): for j in range(num_core_species): jacobian[i, j] = (dydt[j][i] - dydt0[i]) / dN self.assertAlmostEqual(jacobian[i, j], solver_jacobian[i, j], delta=abs(1e-4 * jacobian[i, j])) # The forward finite difference is very unstable for reactions # 6 and 7. Use Jacobians calculated by hand instead. elif rxn_num == 6: kforward = rxn.get_rate_coefficient(self.T) kreverse = kforward / rxn.get_equilibrium_constant(self.T) jacobian = jacobian_rxn6(c0, kforward, kreverse, core_species) for i in range(num_core_species): for j in range(num_core_species): self.assertAlmostEqual(jacobian[i, j], solver_jacobian[i, j], delta=abs(1e-4 * jacobian[i, j])) elif rxn_num == 7: kforward = rxn.get_rate_coefficient(self.T) kreverse = kforward / rxn.get_equilibrium_constant(self.T) jacobian = jacobian_rxn7(c0, kforward, kreverse, core_species) for i in range(num_core_species): for j in range(num_core_species): self.assertAlmostEqual(jacobian[i, j], solver_jacobian[i, j], delta=abs(1e-4 * jacobian[i, j]))
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, 1, 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, 1, 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 test_jacobian(self): """ Unit test for the jacobian function: Solve a reaction system and check if the analytical jacobian matches the finite difference jacobian. """ coreSpecies = [self.CH4, self.CH3, self.C2H6, self.C2H5, self.H2] edgeSpecies = [] numCoreSpecies = len(coreSpecies) c0 = {self.CH4: 0.2, self.CH3: 0.1, self.C2H6: 0.35, self.C2H5: 0.15, self.H2: 0.2} edgeReactions = [] rxnList = [] rxnList.append(Reaction( reactants=[self.C2H6], products=[self.CH3, self.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=[self.CH3, self.CH3], products=[self.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=[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.C2H5, self.CH4], products=[self.C2H6, self.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=[self.C2H5, self.CH4], products=[self.CH3, self.CH3, self.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=[self.CH3, self.CH3, self.CH3], products=[self.C2H5, self.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=[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')) )) rxnList.append(Reaction( reactants=[self.C2H5, self.C2H5, self.H2], products=[self.C2H6, self.CH3, self.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=[self.C2H6, self.C2H6], products=[self.CH3, self.CH4, self.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=[self.CH3, self.CH4, self.C2H5], products=[self.C2H6, self.C2H6], kinetics=Arrhenius(A=(46.375*6, 'm^6/(mol^2*s)'), n=0.10721, Ea=(8.82799, 'kcal/mol'), T0=(298.15, 'K')) )) # Analytical Jacobian for reaction 6 def jacobian_rxn6(c, kf, kr, s): c1, c2, c3, c4 = c[s[1]], c[s[2]], c[s[3]], c[s[4]] J = numpy.zeros((5, 5)) J[1, 1] = -4 * kf * c1 * c2 J[1, 2] = -2 * kf * c1 * c1 J[1, 3] = 4 * kr * c3 * c4 J[1, 4] = 2 * kr * c3 * c3 J[2, 1:] = 0.5 * J[1, 1:] J[3, 1:] = -J[1, 1:] J[4, 1:] = -0.5 * J[1, 1:] return J # Analytical Jacobian for reaction 7 def jacobian_rxn7(c, kf, kr, s): c1, c2, c3, c4 = c[s[1]], c[s[2]], c[s[3]], c[s[4]] J = numpy.zeros((5, 5)) J[1, 1] = -4 * kr * c1 * c2 J[1, 2] = -2 * kr * c1 * c1 J[1, 3] = 4 * kf * c3 * c4 J[1, 4] = 2 * kf * c3 * c3 J[2, 1:] = 0.5 * J[1, 1:] J[3, 1:] = -J[1, 1:] J[4, 1:] = -0.5 * J[1, 1:] return J for rxn_num, rxn in enumerate(rxnList): coreReactions = [rxn] rxnSystem0 = LiquidReactor(self.T, c0, 1, termination=[]) rxnSystem0.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions) dydt0 = rxnSystem0.residual(0.0, rxnSystem0.y, numpy.zeros(rxnSystem0.y.shape))[0] dN = .000001*sum(rxnSystem0.y) # Let the solver compute the jacobian solverJacobian = rxnSystem0.jacobian(0.0, rxnSystem0.y, dydt0, 0.0) if rxn_num not in (6, 7): dydt = [] for i in xrange(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 # Compute the jacobian using finite differences jacobian = numpy.zeros((numCoreSpecies, numCoreSpecies)) for i in xrange(numCoreSpecies): for j in xrange(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])) # The forward finite difference is very unstable for reactions # 6 and 7. Use Jacobians calculated by hand instead. elif rxn_num == 6: kforward = rxn.getRateCoefficient(self.T) kreverse = kforward / rxn.getEquilibriumConstant(self.T) jacobian = jacobian_rxn6(c0, kforward, kreverse, coreSpecies) for i in xrange(numCoreSpecies): for j in xrange(numCoreSpecies): self.assertAlmostEqual(jacobian[i, j], solverJacobian[i, j], delta=abs(1e-4*jacobian[i, j])) elif rxn_num == 7: kforward = rxn.getRateCoefficient(self.T) kreverse = kforward / rxn.getEquilibriumConstant(self.T) jacobian = jacobian_rxn7(c0, kforward, kreverse, coreSpecies) for i in xrange(numCoreSpecies): for j in xrange(numCoreSpecies): self.assertAlmostEqual(jacobian[i, j], solverJacobian[i, j], delta=abs(1e-4*jacobian[i, j]))
def liquidReactor(temperature, initialConcentrations, terminationConversion=None, nSimsTerm = 4, terminationTime=None, terminationRateRatio=None, sensitivity=None, sensitivityThreshold=1e-3, sensitivityTemperature=None, sensitivityConcentrations=None, constantSpecies=None): logging.debug('Found LiquidReactor reaction system') if not isinstance(temperature,list): T = Quantity(temperature) else: if len(temperature) != 2: raise InputError('Temperature and pressure ranges can either be in the form of (number,units) or a list with 2 entries of the same format') T = [Quantity(t) for t in temperature] for spec,conc in initialConcentrations.iteritems(): if not isinstance(conc,list): concentration = Quantity(conc) # check the dimensions are ok # convert to mol/m^3 (or something numerically nice? or must it be SI) initialConcentrations[spec] = concentration.value_si else: if len(conc) != 2: raise InputError("Concentration values must either be in the form of (number,units) or a list with 2 entries of the same format") initialConcentrations[spec] = [Quantity(conc[0]),Quantity(conc[1])] if not isinstance(temperature,list) and all([not isinstance(x,list) for x in initialConcentrations.itervalues()]): nSimsTerm=1 termination = [] if terminationConversion is not None: for spec, conv in terminationConversion.iteritems(): termination.append(TerminationConversion(speciesDict[spec], conv)) if terminationTime is not None: termination.append(TerminationTime(Quantity(terminationTime))) if terminationRateRatio is not None: termination.append(TerminationRateRatio(terminationRateRatio)) if len(termination) == 0: raise InputError('No termination conditions specified for reaction system #{0}.'.format(len(rmg.reactionSystems)+2)) sensitiveSpecies = [] if sensitivity: for spec in sensitivity: sensitiveSpecies.append(speciesDict[spec]) ##chatelak: check the constant species exist if constantSpecies is not None: logging.debug(' Generation with constant species:') for constantSpecie in constantSpecies: logging.debug(" {0}".format(constantSpecie)) if not speciesDict.has_key(constantSpecie): raise InputError('Species {0} not found in the input file'.format(constantSpecie)) if not isinstance(T,list): sensitivityTemperature = T if not any([isinstance(x,list) for x in initialConcentrations.itervalues()]): sensitivityConcentrations = initialConcentrations if sensitivityConcentrations is None or sensitivityTemperature is None: sensConditions = None else: sensConditions = sensitivityConcentrations sensConditions['T'] = Quantity(sensitivityTemperature).value_si system = LiquidReactor(T, initialConcentrations, nSimsTerm, termination, sensitiveSpecies, sensitivityThreshold, sensConditions, constantSpecies) rmg.reactionSystems.append(system)
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 rxnSystem0.termination.append(TerminationTime((integrationTime,'s'))) rxnSystem0.simulate(coreSpecies, coreReactions, [], [], 0, 1, 0) 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'))) rxnSystem.simulate(coreSpecies, coreReactions, [], [], 0, 1, 0) 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]))