def toCantera(self, useChemkinIdentifier = False): """ Converts the RMG Species object to a Cantera Species object with the appropriate thermo data. If useChemkinIdentifier is set to False, the species label is used instead. Be sure that species' labels are unique when setting it False. """ import cantera as ct # Determine the number of each type of element in the molecule elementDict = {} # elementCounts = [0,0,0,0] for atom in self.molecule[0].atoms: # The atom itself symbol = atom.element.symbol if symbol not in elementDict: elementDict[symbol] = 1 else: elementDict[symbol] += 1 if useChemkinIdentifier: ctSpecies = ct.Species(self.toChemkin(), elementDict) else: ctSpecies = ct.Species(self.label, elementDict) if self.thermo: try: ctSpecies.thermo = self.thermo.toCantera() except Exception: logging.error('Could not convert thermo to create Cantera Species object. Check that thermo is a NASA polynomial.') raise if self.transportData: ctSpecies.transport = self.transportData.toCantera() return ctSpecies
def test_modify_thermo_invalid(self): S = {sp.name: sp for sp in ct.Species.listFromFile('h2o2.xml')} orig = S['H2'] thermo = orig.thermo copy = ct.Species('foobar', orig.composition) copy.thermo = thermo with self.assertRaises(ct.CanteraError): self.gas.modify_species(self.gas.species_index('H2'), copy) copy = ct.Species('H2', {'H': 3}) copy.thermo = thermo with self.assertRaises(ct.CanteraError): self.gas.modify_species(self.gas.species_index('H2'), copy) copy = ct.Species('H2', orig.composition) copy.thermo = ct.ConstantCp(thermo.min_temp, thermo.max_temp, thermo.reference_pressure, [300, 123, 456, 789]) with self.assertRaises(ct.CanteraError): self.gas.modify_species(self.gas.species_index('H2'), copy) copy = ct.Species('H2', orig.composition) copy.thermo = ct.NasaPoly2(thermo.min_temp + 200, thermo.max_temp, thermo.reference_pressure, thermo.coeffs) with self.assertRaises(ct.CanteraError): self.gas.modify_species(self.gas.species_index('H2'), copy)
def test_qss_artificial(self): """Test using four species artificial model with QSS species from 2006 DRG paper. # R \approx F / 1e3 """ R1 = ct.Reaction.fromCti('''reaction('F => R', [1.0, 0.0, 0.0])''') R2 = ct.Reaction.fromCti('''reaction('R => P', [1.0e3, 0.0, 0.0])''') R3 = ct.Reaction.fromCti('''reaction('R => Pp', [1.0, 0.0, 0.0])''') F = ct.Species('F', 'H:1') R = ct.Species('R', 'H:1') P = ct.Species('P', 'H:1') Pp = ct.Species('Pp', 'H:1') for sp in [F, R, P, Pp]: sp.thermo = ct.ConstantCp(300, 1000, 101325, (300, 1.0, 1.0, 1.0)) model = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', species=[F, R, P, Pp], reactions=[R1, R2, R3]) state = 1000, ct.one_atm, [1., 1. / 1.e3, 0., 0.] matrix = create_drg_matrix(state, model) correct = np.array([[0, 1.0, 0, 0], [0.5, 0, 0.5, 0.5 * 1e-3], [0, 1.0, 0, 0], [0, 1, 0, 0]]) assert np.allclose(correct, matrix, rtol=1e-3)
def test_pe_artificial(self): """Test using three species artificial model with PE reactions from 2006 DRG paper. """ R1 = ct.Reaction.fromCti('''reaction('F <=> R', [1.0e3, 0.0, 0.0])''') R2 = ct.Reaction.fromCti('''reaction('R <=> P', [1.0, 0.0, 0.0])''') F = ct.Species('F', 'H:1') R = ct.Species('R', 'H:1') P = ct.Species('P', 'H:1') for sp in [F, R, P]: sp.thermo = ct.ConstantCp(300, 1000, 101325, (300, 1.0, 1.0, 1.0)) model = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', species=[F, R, P], reactions=[R1, R2]) conc_R = 0.1 conc_F = ((1 + 1e-3) * conc_R - (1 / 2e3)) / (1 - (1 / 2e3)) conc_P = 1.0 - (conc_R + conc_F) state = 1000, ct.one_atm, [conc_F, conc_R, conc_P] matrix = create_drg_matrix(state, model) correct = np.array([ [0, 1.0, 0], [1. / 3., 0, 2. / 3.], [0, 1.0, 0], ]) assert np.allclose(correct, matrix, rtol=1e-3)
def test_defaults(self): s = ct.Species('H2') self.assertEqual(s.size, 1.0) self.assertEqual(s.charge, 0.0) self.assertIsNone(s.thermo) self.assertIsNone(s.transport)
def toCantera(self, speciesList=[]): """ Converts the RMG Species object to a Cantera Species object with the appropriate thermo data. """ import cantera as ct # Determine the number of each type of element in the molecule elementDict = {} # elementCounts = [0,0,0,0] for atom in self.molecule[0].atoms: # The atom itself symbol = atom.element.symbol if symbol not in elementDict: elementDict[symbol] = 1 else: elementDict[symbol] += 1 ctSpecies = ct.Species(self.toChemkin(), elementDict) if self.thermo: try: ctSpecies.thermo = self.thermo.toCantera() except Exception, e: print e raise Exception( 'Could not convert thermo to create Cantera Species object. Check that thermo is a NASA polynomial.' )
def test_standalone(self): s = ct.Species('CH4', {'C': 1, 'H': 4}) self.assertEqual(s.name, 'CH4') c = s.composition self.assertEqual(len(c), 2) self.assertEqual(c['C'], 1) self.assertEqual(c['H'], 4)
def test_dormant_modes(self): """Test using three species artificial model with dormant modes from 2006 DRG paper. """ R1 = ct.Reaction.fromCti('''reaction('A <=> B', [1.0, 0.0, 0.0])''') R2 = ct.Reaction.fromCti('''reaction('B <=> C', [1.0e-3, 0.0, 0.0])''') A = ct.Species('A', 'H:1') B = ct.Species('B', 'H:1') C = ct.Species('C', 'H:1') for sp in [A, B, C]: sp.thermo = ct.ConstantCp(300, 1000, 101325, (300, 1.0, 1.0, 1.0)) model = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', species=[A, B, C], reactions=[R1, R2]) state = 1000, ct.one_atm, [1.0, 2.0, 1.0] matrix = create_drg_matrix(state, model) correct = np.array([ [0, 1.0, 0], [1 / (1 + 1e-3), 0, 1e-3 / (1 + 1e-3)], [0, 1.0, 0], ]) assert np.allclose(correct, matrix, rtol=1e-3) conc_A = 1.370536 conc_B = 1.370480 conc_C = 1.258985 state = 1000, ct.one_atm, [conc_A, conc_B, conc_C] matrix = create_drg_matrix(state, model) correct = np.array([ [0, 1.0, 0], [ abs(conc_A - conc_B) / (abs(conc_A - conc_B) + 1e-3 * abs(conc_B - conc_C)), 0, 1e-3 * abs(conc_B - conc_C) / (abs(conc_A - conc_B) + 1e-3 * abs(conc_B - conc_C)) ], [0, 1.0, 0], ]) assert np.allclose(correct, matrix, rtol=1e-3)
def test_csp_mech5(self): """Test of simple mech 5 from 2006 DRG paper. """ R1 = ct.Reaction.fromCti('''reaction('F => P', [1.0, 0.0, 0.0])''') R2 = ct.Reaction.fromCti('''reaction('F => R', [1.0e-2, 0.0, 0.0])''') R3 = ct.Reaction.fromCti('''reaction('R => P', [1.0e2, 0.0, 0.0])''') F = ct.Species('F', 'H:1') P = ct.Species('P', 'H:1') R = ct.Species('R', 'H:1') for sp in [F, P, R]: sp.thermo = ct.ConstantCp(300, 1000, 101325, (300, 1.0, 1.0, 1.0)) model = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', species=[F, P, R], reactions=[R1, R2, R3]) state = 1000, ct.one_atm, [1.0, 1.0, 1.0e-4] matrix = create_drg_matrix(state, model) reached = trim_drg(matrix, ['F', 'P', 'R'], ['F'], 0.1) assert check_equal(reached, ['F', 'P'])
def _get_cantera_element_mw_map(cls, ctsol: ct.Solution): species_list = [ ct.Species(element_name, f'{element_name}: 1') for element_name in ctsol.element_names ] for i in range(len(species_list)): species_list[i].thermo = ct.ConstantCp(300., 3000., 101325., (300., 0., 0., 1.e4)) element_only_ctsol = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', species=species_list, reactions=[]) return { name: mw for name, mw in zip(element_only_ctsol.species_names, element_only_ctsol.molecular_weights) }
from nanoparticles.nanoparticle_units import * ################################################################################ # GAS ################################################################################ T_low = 200.00 # [K] T_mid = 1000.00 # [K] T_high = 3500.00 # [K] P_ref = 1.00 * atm ################################################################################ # CO ################################################################################ CO = ct.Species(name = 'CO') coeffs = np.zeros(15) coeffs[0] = T_mid coeffs[1:8] = [ 3.57953347E+00, -6.10353680E-04, 1.01681433E-06, 9.07005884E-10, -9.04424499E-13, 0.00000000E+00, 3.50840928E+00] coeffs[8:15] = [ 2.71518561E+00, 2.06252743E-03, -9.98825771E-07, 2.30053008E-10, -2.03647716E-14, 1.92213599E+02, 7.81868772E+00] CO.thermo = ct.NasaPoly2(T_low = T_low , T_high = T_high , P_ref = P_ref , coeffs = coeffs )
def _build_cantera_solution(cls, gdata): p_ref = gdata['ref_pressure'] species_list = list() for s in gdata['species']: spec = gdata['species'][s] ctspec = ct.Species( s, ','.join( [f'{k}:{spec["atom_map"][k]}' for k in spec['atom_map']])) if spec['cp'][0] == 'constant': Tmin, Tmax, T0, h0, s0, cp = spec['cp'][1:] ctspec.thermo = ct.ConstantCp(Tmin, Tmax, p_ref, list([T0, h0, s0, cp])) elif spec['cp'][0] == 'NASA7': Tmin, Tmid, Tmax, low_coeffs, high_coeffs = spec['cp'][1:] coeffs = [Tmid] + high_coeffs + low_coeffs ctspec.thermo = ct.NasaPoly2(Tmin, Tmax, p_ref, coeffs) species_list.append(ctspec) reaction_list = list() for rxn in gdata['reactions']: type, reactants_stoich, products_stoich, reversible = rxn[:4] fwd_pre_exp_value, fwd_temp_exponent, fwd_act_energy = rxn[4:7] fwd_rate = ct.Arrhenius(fwd_pre_exp_value, fwd_temp_exponent, fwd_act_energy) if type == 'simple' or type == 'simple-special': ctrxn = ct.ElementaryReaction(reactants_stoich, products_stoich) ctrxn.rate = fwd_rate elif type == 'three-body' or type == 'three-body-special': ctrxn = ct.ThreeBodyReaction(reactants_stoich, products_stoich) ctrxn.rate = fwd_rate ctrxn.efficiencies = rxn[7] ctrxn.default_efficiency = rxn[8] elif type == 'Lindemann' or type == 'Lindemann-special': ctrxn = ct.FalloffReaction(reactants_stoich, products_stoich) ctrxn.efficiencies = rxn[7] ctrxn.default_efficiency = rxn[8] flf_pre_exp_value, flf_temp_exponent, flf_act_energy = rxn[ 9:12] ctrxn.high_rate = fwd_rate ctrxn.low_rate = ct.Arrhenius(flf_pre_exp_value, flf_temp_exponent, flf_act_energy) ctrxn.falloff = ct.Falloff() elif type == 'Troe' or type == 'Troe-special': ctrxn = ct.FalloffReaction(reactants_stoich, products_stoich) ctrxn.efficiencies = rxn[7] ctrxn.default_efficiency = rxn[8] flf_pre_exp_value, flf_temp_exponent, flf_act_energy = rxn[ 9:12] troe_params = rxn[12] ctrxn.high_rate = fwd_rate ctrxn.low_rate = ct.Arrhenius(flf_pre_exp_value, flf_temp_exponent, flf_act_energy) if len(troe_params) == 4 and abs(troe_params[3]) < 1e-300: ctrxn.falloff = ct.TroeFalloff(troe_params[:3]) else: ctrxn.falloff = ct.TroeFalloff(troe_params) if 'special' in type: ctrxn.orders = rxn[-1] ctrxn.reversible = reversible reaction_list.append(ctrxn) return ct.Solution(thermo='IdealGas', kinetics='GasKinetics', species=species_list, reactions=reaction_list)
def set_mechanism(self, mech_dict, species_dict={}, bnds=[]): def get_Arrhenius_parameters(entry): A = entry['pre_exponential_factor'] b = entry['temperature_exponent'] Ea = entry['activation_energy'] return A, b, Ea if len(species_dict) == 0: species = self.gas.species() else: species = [] for n in range(len(species_dict)): s_dict = species_dict[n] s = ct.Species(name=s_dict['name'], composition=s_dict['composition'], charge=s_dict['charge'], size=s_dict['size']) thermo = s_dict['type'](s_dict['T_low'], s_dict['T_high'], s_dict['P_ref'], s_dict['coeffs']) s.thermo = thermo species.append(s) # Set kinetics data rxns = [] for rxnIdx in range(len(mech_dict)): if 'ElementaryReaction' == mech_dict[rxnIdx]['rxnType']: rxn = ct.ElementaryReaction(mech_dict[rxnIdx]['reactants'], mech_dict[rxnIdx]['products']) rxn.allow_negative_pre_exponential_factor = True A, b, Ea = get_Arrhenius_parameters( mech_dict[rxnIdx]['rxnCoeffs'][0]) rxn.rate = ct.Arrhenius(A, b, Ea) elif 'ThreeBodyReaction' == mech_dict[rxnIdx]['rxnType']: rxn = ct.ThreeBodyReaction(mech_dict[rxnIdx]['reactants'], mech_dict[rxnIdx]['products']) A, b, Ea = get_Arrhenius_parameters( mech_dict[rxnIdx]['rxnCoeffs'][0]) rxn.rate = ct.Arrhenius(A, b, Ea) rxn.efficiencies = mech_dict[rxnIdx]['rxnCoeffs'][0][ 'efficiencies'] elif 'PlogReaction' == mech_dict[rxnIdx]['rxnType']: rxn = ct.PlogReaction(mech_dict[rxnIdx]['reactants'], mech_dict[rxnIdx]['products']) rates = [] for plog in mech_dict[rxnIdx]['rxnCoeffs']: pressure = plog['Pressure'] A, b, Ea = get_Arrhenius_parameters(plog) rates.append((pressure, ct.Arrhenius(A, b, Ea))) rxn.rates = rates elif 'FalloffReaction' == mech_dict[rxnIdx]['rxnType']: rxn = ct.FalloffReaction(mech_dict[rxnIdx]['reactants'], mech_dict[rxnIdx]['products']) # high pressure limit A, b, Ea = get_Arrhenius_parameters( mech_dict[rxnIdx]['rxnCoeffs']['high_rate']) rxn.high_rate = ct.Arrhenius(A, b, Ea) # low pressure limit A, b, Ea = get_Arrhenius_parameters( mech_dict[rxnIdx]['rxnCoeffs']['low_rate']) rxn.low_rate = ct.Arrhenius(A, b, Ea) # falloff parameters if mech_dict[rxnIdx]['rxnCoeffs']['falloff_type'] == 'Troe': falloff_param = mech_dict[rxnIdx]['rxnCoeffs'][ 'falloff_parameters'] if falloff_param[-1] == 0.0: falloff_param = falloff_param[0:-1] rxn.falloff = ct.TroeFalloff(falloff_param) else: rxn.falloff = ct.SriFalloff( mech_dict[rxnIdx]['rxnCoeffs']['falloff_parameters']) rxn.efficiencies = mech_dict[rxnIdx]['rxnCoeffs'][ 'efficiencies'] elif 'ChebyshevReaction' == mech_dict[rxnIdx]['rxnType']: rxn = ct.ChebyshevReaction(mech_dict[rxnIdx]['reactants'], mech_dict[rxnIdx]['products']) rxn.set_parameters(Tmin=mech_dict['Tmin'], Tmax=mech_dict['Tmax'], Pmin=mech_dict['Pmin'], Pmax=mech_dict['Pmax'], coeffs=mech_dict['coeffs']) rxn.duplicate = mech_dict[rxnIdx]['duplicate'] rxn.reversible = mech_dict[rxnIdx]['reversible'] rxn.allow_negative_orders = True rxn.allow_nonreactant_orders = True rxns.append(rxn) self.gas = ct.Solution(thermo='IdealGas', kinetics='GasKinetics', species=species, reactions=rxns) self.set_rate_expression_coeffs(bnds) # set copy of coeffs self.set_thermo_expression_coeffs() # set copy of thermo coeffs
import unittest from numpy import max, abs, ones, zeros, hstack, sqrt, finfo from cantera import gas_constant from spitfire import ChemicalMechanismSpec as Mechanism import pickle import cantera as ct species_decl = list([ ct.Species('A', 'H:2'), ct.Species('B', 'H:1'), ct.Species('C', 'O:1'), ct.Species('D', 'O:2'), ct.Species('E', 'H:1, O:2'), ct.Species('N', 'H:1, O:1') ]) species_dict = dict({'const': list(), 'nasa7': list()}) for i, s in enumerate(species_decl): species_dict['const'].append(ct.Species(s.name, s.composition)) species_dict['const'][-1].thermo = ct.ConstantCp( 300., 3000., 101325., (300., 0., 0., float(i + 1) * 1.e4)) species_dict['nasa7'].append(ct.Species(s.name, s.composition)) coeffs = [ float(i + 1) * v for v in [1.e0, 1.e-2, 1.e-4, 1.e-6, 1.e-8, 1.e-10, 1.e-12] ] species_dict['nasa7'][-1].thermo = ct.NasaPoly2( 300., 3000., 101325., hstack([1200.] + coeffs + coeffs)) mechs = [('const', Mechanism.from_solution( ct.Solution(thermo='IdealGas',