def setUp(self): """ Here we choose a kinetic model consisting of the hydrogen abstraction reaction CH4 + C2H5 <=> CH3 + C2H6. Reset the loaded database """ import rmgpy.data.rmg rmgpy.data.rmg.database = None Tlist = [300,400,500,600,800,1000,1500] self.CH4 = Species( molecule=[Molecule().fromSMILES("C")], thermo=ThermoData(Tdata=(Tlist,"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)")) ) self.CH3 = Species( molecule=[Molecule().fromSMILES("[CH3]")], thermo=ThermoData(Tdata=(Tlist,"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)")) ) self.C2H6 = Species( molecule=[Molecule().fromSMILES("CC")], thermo=ThermoData(Tdata=(Tlist,"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)")) ) self.C2H5 = Species( molecule=[Molecule().fromSMILES("C[CH2]")], thermo=ThermoData(Tdata=(Tlist,"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)")) ) self.H2 = Species( molecule=[Molecule().fromSMILES("[H][H]")], thermo=ThermoData(Tdata=(Tlist,"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)")) ) self.T = 1000
def update_species_attributes(self, species=None): """ Update the object with a new species/TS (while keeping non-species-dependent attributes unchanged) """ if species is None: raise ValueError('No species was passed to ArkaneSpecies') # Don't overwrite the label if it already exists self.label = self.label or species.label if isinstance(species, TransitionState): self.imaginary_frequency = species.frequency if species.conformer is not None: self.conformer = species.conformer self.xyz = self.update_xyz_string() elif species.molecule is not None and len(species.molecule) > 0: self.smiles = species.molecule[0].to_smiles() self.adjacency_list = species.molecule[0].to_adjacency_list() self.charge = species.molecule[0].get_net_charge() self.multiplicity = species.molecule[0].multiplicity self.formula = species.molecule[0].get_formula() try: inchi = to_inchi(species.molecule[0], backend='try-all', aug_level=0) except ValueError: inchi = '' try: inchi_key = to_inchi_key(species.molecule[0], backend='try-all', aug_level=0) except ValueError: inchi_key = '' self.inchi = inchi self.inchi_key = inchi_key if species.conformer is not None: self.conformer = species.conformer self.xyz = self.update_xyz_string() self.molecular_weight = species.molecular_weight if species.symmetry_number != -1: self.symmetry_number = species.symmetry_number if species.transport_data is not None: self.transport_data = species.transport_data # called `collisionModel` in Arkane if species.energy_transfer_model is not None: self.energy_transfer_model = species.energy_transfer_model if species.thermo is not None: self.thermo = species.thermo.as_dict() data = species.get_thermo_data() h298 = data.get_enthalpy(298) / 4184. s298 = data.get_entropy(298) / 4.184 temperatures = np.array( [300, 400, 500, 600, 800, 1000, 1500, 2000, 2400]) cp = [] for t in temperatures: cp.append(data.get_heat_capacity(t) / 4.184) self.thermo_data = ThermoData( H298=(h298, 'kcal/mol'), S298=(s298, 'cal/(mol*K)'), Tdata=(temperatures, 'K'), Cpdata=(cp, 'cal/(mol*K)'), )
def setUp(self): """ A method that is run before each unit test in this class. """ self.species = Species( index=1, label='C2H4', thermo=ThermoData( Tdata=([300.0,400.0,500.0,600.0,800.0,1000.0,1500.0],'K'), Cpdata=([3.0,4.0,5.0,6.0,8.0,10.0,15.0],'cal/(mol*K)'), H298=(-20.0,'kcal/mol'), S298=(50.0,'cal/(mol*K)'), Tmin=(300.0,'K'), Tmax=(2000.0,'K'), ), conformer=Conformer( E0=(0.0,'kJ/mol'), modes=[ IdealGasTranslation(mass=(28.03,'amu')), NonlinearRotor(inertia=([5.6952e-47, 2.7758e-46, 3.3454e-46],'kg*m^2'), symmetry=1), HarmonicOscillator(frequencies=([834.50, 973.31, 975.37, 1067.1, 1238.5, 1379.5, 1472.3, 1691.3, 3121.6, 3136.7, 3192.5, 3221.0],'cm^-1')), ], spinMultiplicity=1, opticalIsomers=1, ), molecule=[Molecule().fromSMILES('C=C')], transportData=TransportData(sigma=(1, 'angstrom'), epsilon=(100, 'K')), molecularWeight=(28.03,'amu'), reactive=True, )
def get_thermo_data(self, molecule: Union[Molecule, str]) -> ThermoData: """ Return thermodynamic parameters corresponding to a given :class:`Molecule` object `molecule` or a SMILES string. Returns: ThermoData """ molecule = Molecule( smiles=molecule) if isinstance(molecule, str) else molecule hf298 = self.hf298_estimator(molecule.smiles)[0][0] s298_cp = self.s298_cp_estimator(molecule.smiles)[0] s298, cp = s298_cp[0], s298_cp[1:] cp0 = molecule.calculate_cp0() cpinf = molecule.calculate_cpinf() # Set uncertainties to 0 because the current model cannot estimate them thermo = ThermoData(Tdata=(self.temps, 'K'), Cpdata=(cp, 'cal/(mol*K)', np.zeros(len(self.temps))), H298=(hf298, 'kcal/mol', 0), S298=(s298, 'cal/(mol*K)', 0), Cp0=(cp0, 'J/(mol*K)'), CpInf=(cpinf, 'J/(mol*K)'), Tmin=(300.0, 'K'), Tmax=(2000.0, 'K'), comment='ML Estimation') return thermo
def setUpClass(cls): cls.methane = Species(smiles='C') cls.ethane = Species(smiles='CC') cls.propane = Species(smiles='CCC') cls.thermo_data = ThermoData(H298=(100.0, 'kJ/mol'), S298=(100.0, 'J/(mol*K)')) cls.xyz_dict = {'symbols': ('H', 'H'), 'isotopes': (1, 1), 'coords': ((0.0, 0.0, 0.0), (0.708, 0.0, 0.0))} cls.t1_diagnostic = 0.101
def calculateThermoData(self): """ Calculate the thermodynamic properties. Stores and returns a ThermoData object as self.thermo. self.qmData and self.pointGroup need to be generated before this method is called. """ assert self.qmData, "Need QM Data first in order to calculate thermo." assert self.pointGroup, "Need Point Group first in order to calculate thermo." trans = rmgpy.statmech.IdealGasTranslation( mass=self.qmData.molecularMass) if self.pointGroup.linear: # there should only be one rotational constant for a linear rotor rotationalConstant = rmgpy.quantity.Frequency( max(self.qmData.rotationalConstants.value), self.qmData.rotationalConstants.units) rot = rmgpy.statmech.LinearRotor( rotationalConstant=rotationalConstant, symmetry=self.pointGroup.symmetryNumber, ) else: rot = rmgpy.statmech.NonlinearRotor( rotationalConstant=self.qmData.rotationalConstants, symmetry=self.pointGroup.symmetryNumber, ) # @todo: should we worry about spherical top rotors? vib = rmgpy.statmech.HarmonicOscillator( frequencies=self.qmData.frequencies) # @todo: We need to extract or calculate E0 somehow from the qmdata E0 = (0, "kJ/mol") self.statesmodel = rmgpy.statmech.Conformer( E0=E0, modes=[trans, rot, vib], spinMultiplicity=self.qmData.groundStateDegeneracy) #we will use number of atoms from above (alternatively, we could use the chemGraph); this is needed to test whether the species is monoatomic # SI units are J/mol, but converted to kJ/mol for generating the thermo. Hf298 = self.qmData.energy.value_si / 1000 S298 = self.statesmodel.getEntropy(298.0) Tdata = [300.0, 400.0, 500.0, 600.0, 800.0, 1000.0, 1500.0] Cp = [self.statesmodel.getHeatCapacity(T) for T in Tdata] S298 = S298 + self.calculateChiralityCorrection() comment = self.qmData.source or "QM calculation of some sort." thermo = ThermoData(Tdata=(Tdata, "K"), Cpdata=(Cp, "J/(mol*K)"), H298=(Hf298, "kJ/mol"), S298=(S298, "J/(mol*K)"), Tmin=(300.0, "K"), Tmax=(2000.0, "K"), comment=comment) self.thermo = thermo return thermo
def test_extract_level_of_theory(self): """ Test that a given level of theory can be extracted from the reference set database """ # Create a quick example database ref_data_1 = ReferenceDataEntry(ThermoData(H298=(100, 'kJ/mol', '+|-', 2))) ref_data_2 = ReferenceDataEntry(ThermoData(H298=(25, 'kcal/mol', '+|-', 1))) calc_data_1 = CalculatedDataEntry(ThermoData(H298=(110, 'kJ/mol'))) calc_data_2 = CalculatedDataEntry(ThermoData(H298=(120, 'kJ/mol'))) ethane = ReferenceSpecies(smiles='CC', reference_data={'precise': ref_data_1, 'less_precise': ref_data_2}, calculated_data={LevelOfTheory('good_chem'): calc_data_1, LevelOfTheory('bad_chem'): calc_data_2}, preferred_reference='less_precise') propane = ReferenceSpecies(smiles='CCC', reference_data={'precise': ref_data_1, 'less_precise': ref_data_2}, calculated_data={LevelOfTheory('good_chem'): calc_data_1, LevelOfTheory('bad_chem'): calc_data_2}) butane = ReferenceSpecies(smiles='CCCC', reference_data={'precise': ref_data_1, 'less_precise': ref_data_2}, calculated_data={LevelOfTheory('bad_chem'): calc_data_2}) database = ReferenceDatabase() database.reference_sets = {'testing_1': [ethane, butane], 'testing_2': [propane]} model_chem_list = database.extract_level_of_theory(LevelOfTheory('good_chem')) self.assertEqual(len(model_chem_list), 2) self.assertIsInstance(model_chem_list[0], ErrorCancelingSpecies) for spcs in model_chem_list: smiles = spcs.molecule.to_smiles() self.assertNotIn(smiles, ['CCCC']) self.assertIn(smiles, ['CC', 'CCC']) if smiles == 'CC': # Test that `less_precise` is the source since it was set manually as preferred self.assertAlmostEqual(spcs.high_level_hf298.value_si, 25.0*4184.0) if smiles == 'CCC': # Test that `precise` is the source since it has the lowest uncertainty self.assertAlmostEqual(spcs.high_level_hf298.value_si, 100.0*1000.0)
def processOldLibraryEntry(data): """ Process a list of parameters `data` as read from an old-style RMG thermo database, returning the corresponding thermodynamics object. """ return ThermoData( Tdata = ([300,400,500,600,800,1000,1500],"K"), Cpdata = ([float(d) for d in data[2:9]],"cal/(mol*K)","+|-",float(data[11])), H298 = (float(data[0]),"kcal/mol","+|-",float(data[9])), S298 = (float(data[1]),"cal/(mol*K)","+|-",float(data[10])), )
def setUp(self): """ A function run before each unit test in this class. """ self.wilhoit = Wilhoit( Cp0=(4.0 * constants.R, "J/(mol*K)"), CpInf=(21.5 * constants.R, "J/(mol*K)"), a0=0.0977518, a1=-16.3067, a2=26.2524, a3=-12.6785, B=(1068.68, "K"), H0=(-94.088 * constants.R, "kJ/mol"), S0=(-118.46 * constants.R, "J/(mol*K)"), Tmin=(10, "K"), Tmax=(3000, "K"), comment='C2H6', ) self.nasa = NASA( polynomials=[ NASAPolynomial(coeffs=[ 4.03055, -0.00214171, 4.90611e-05, -5.99027e-08, 2.38945e-11, -11257.6, 3.5613 ], Tmin=(10, "K"), Tmax=(650.73, "K")), NASAPolynomial(coeffs=[ -0.307954, 0.0245269, -1.2413e-05, 3.07724e-09, -3.01467e-13, -10693, 22.628 ], Tmin=(650.73, "K"), Tmax=(3000, "K")), ], Tmin=(10, "K"), Tmax=(3000, "K"), E0=(-93.6077, 'kJ/mol'), Cp0=(4.0 * constants.R, "J/(mol*K)"), CpInf=(21.5 * constants.R, "J/(mol*K)"), comment='C2H6', ) self.thermodata = ThermoData( Tdata=([300, 400, 500, 600, 800, 1000, 1500], "K"), Cpdata=(numpy.array([ 6.38268, 7.80327, 9.22175, 10.5528, 12.8323, 14.6013, 17.40890 ]) * constants.R, "J/(mol*K)"), H298=(-81.7, "kJ/mol"), S298=(27.5727 * constants.R, "J/(mol*K)"), Cp0=(4.0 * constants.R, "J/(mol*K)"), CpInf=(21.5 * constants.R, "J/(mol*K)"), Tmin=(10, "K"), Tmax=(3000, "K"), E0=(-93.6077, 'kJ/mol'), comment='C2H6', )
def setUp(self): """ A method that is run before each unit test in this class. """ self.species = Species( index=1, label='C2H4', thermo=ThermoData( Tdata=([300.0, 400.0, 500.0, 600.0, 800.0, 1000.0, 1500.0], 'K'), Cpdata=([3.0, 4.0, 5.0, 6.0, 8.0, 10.0, 15.0], 'cal/(mol*K)'), H298=(-20.0, 'kcal/mol'), S298=(50.0, 'cal/(mol*K)'), Tmin=(300.0, 'K'), Tmax=(2000.0, 'K'), ), conformer=Conformer( E0=(0.0, 'kJ/mol'), modes=[ IdealGasTranslation(mass=(28.03, 'amu')), NonlinearRotor( inertia=([5.6952e-47, 2.7758e-46, 3.3454e-46], 'kg*m^2'), symmetry=1), HarmonicOscillator(frequencies=([ 834.50, 973.31, 975.37, 1067.1, 1238.5, 1379.5, 1472.3, 1691.3, 3121.6, 3136.7, 3192.5, 3221.0 ], 'cm^-1')), ], spin_multiplicity=1, optical_isomers=1, ), molecule=[Molecule().from_smiles('C=C')], transport_data=TransportData(sigma=(1, 'angstrom'), epsilon=(100, 'K')), molecular_weight=(28.03, 'amu'), reactive=True, ) self.species2 = Species().from_adjacency_list(""" 1 C u0 p0 c0 {2,D} {6,S} {7,S} 2 C u0 p0 c0 {1,D} {3,S} {8,S} 3 C u0 p0 c0 {2,S} {4,D} {9,S} 4 C u0 p0 c0 {3,D} {5,S} {10,S} 5 C u0 p0 c0 {4,S} {6,D} {11,S} 6 C u0 p0 c0 {1,S} {5,D} {12,S} 7 H u0 p0 c0 {1,S} 8 H u0 p0 c0 {2,S} 9 H u0 p0 c0 {3,S} 10 H u0 p0 c0 {4,S} 11 H u0 p0 c0 {5,S} 12 H u0 p0 c0 {6,S} """)
def get_thermo_data(self, molecule): """ Return thermodynamic parameters corresponding to a given :class:`Molecule` object `molecule`. Also set the uncertainties estimated by the ML model if available. Returns: ThermoData """ # These should correspond to the temperatures that the ML model was # trained on for Cp. temps = [300.0, 400.0, 500.0, 600.0, 800.0, 1000.0, 1500.0] hf298 = self.hf298_estimator.predict(molecule=molecule, sigma=self.hf298_uncertainty) s298 = self.s298_estimator.predict(molecule=molecule, sigma=self.s298_uncertainty) cp = self.cp_estimator.predict(molecule=molecule, sigma=self.cp_uncertainty) # If uncertainty is available for the ML model, a tuple of predicted # value and estimated uncertainty is returned. An uncertainty of None # gets set to a valua of 0 by :class:`Quantity`. hf298, hf298u = hf298 if isinstance(hf298, tuple) else (hf298, None) s298, s298u = s298 if isinstance(s298, tuple) else (s298, None) cp, cpu = cp if isinstance(cp, tuple) else (cp, None) cp = [np.float64(cp_i) for cp_i in cp] if cpu is not None: cpu = [np.float64(cpu_i) for cpu_i in cpu] cp0 = molecule.calculateCp0() cpinf = molecule.calculateCpInf() thermo = ThermoData(Tdata=(temps, 'K'), Cpdata=(cp, 'cal/(mol*K)', cpu), H298=(hf298, 'kcal/mol', hf298u), S298=(s298, 'cal/(mol*K)', s298u), Cp0=(cp0, 'J/(mol*K)'), CpInf=(cpinf, 'J/(mol*K)'), Tmin=(300.0, 'K'), Tmax=(2000.0, 'K'), comment='ML Estimation') return thermo
def estimateThermoViaGroupAdditivity(self, molecule): """ Return the set of thermodynamic parameters corresponding to a given :class:`Molecule` object `molecule` by estimation using the group additivity values. If no group additivity values are loaded, a :class:`DatabaseError` is raised. """ # For thermo estimation we need the atoms to already be sorted because we # iterate over them; if the order changes during the iteration then we # will probably not visit the right atoms, and so will get the thermo wrong molecule.sortVertices() # Create the ThermoData object thermoData = ThermoData( Tdata=([300, 400, 500, 600, 800, 1000, 1500], "K"), Cpdata=([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], "J/(mol*K)"), H298=(0.0, "kJ/mol"), S298=(0.0, "J/(mol*K)"), ) if molecule.isRadical(): # radical species return self.estimateRadicalThermoViaHBI( molecule, self. estimateThermoViaGroupAdditivityForSaturatedStructWithoutSymmetryCorrection ) else: # non-radical species thermoData = self.estimateThermoViaGroupAdditivityForSaturatedStructWithoutSymmetryCorrection( molecule) # Correct entropy for symmetry number molecule.calculateSymmetryNumber() thermoData.S298.value_si -= constants.R * math.log( molecule.symmetryNumber) return thermoData
def loadFAMEInput(path, moleculeDict=None): """ Load the contents of a FAME input file into the MEASURE object. FAME is an early version of MEASURE written in Fortran and used by RMG-Java. This script enables importing FAME input files into MEASURE so we can use the additional functionality that MEASURE provides. Note that it is mostly designed to load the FAME input files generated automatically by RMG-Java, and may not load hand-crafted FAME input files. If you specify a `moleculeDict`, then this script will use it to associate the species with their structures. """ def readMeaningfulLine(f): line = f.readline() while line != '': line = line.strip() if len(line) > 0 and line[0] != '#': return line else: line = f.readline() return '' moleculeDict = moleculeDict or {} logging.info('Loading file "{0}"...'.format(path)) f = open(path) job = PressureDependenceJob(network=None) # Read method method = readMeaningfulLine(f).lower() if method == 'modifiedstrongcollision': job.method = 'modified strong collision' elif method == 'reservoirstate': job.method = 'reservoir state' # Read temperatures Tcount, Tunits, Tmin, Tmax = readMeaningfulLine(f).split() job.Tmin = Quantity(float(Tmin), Tunits) job.Tmax = Quantity(float(Tmax), Tunits) job.Tcount = int(Tcount) Tlist = [] for i in range(int(Tcount)): Tlist.append(float(readMeaningfulLine(f))) job.Tlist = Quantity(Tlist, Tunits) # Read pressures Pcount, Punits, Pmin, Pmax = readMeaningfulLine(f).split() job.Pmin = Quantity(float(Pmin), Punits) job.Pmax = Quantity(float(Pmax), Punits) job.Pcount = int(Pcount) Plist = [] for i in range(int(Pcount)): Plist.append(float(readMeaningfulLine(f))) job.Plist = Quantity(Plist, Punits) # Read interpolation model model = readMeaningfulLine(f).split() if model[0].lower() == 'chebyshev': job.interpolationModel = ('chebyshev', int(model[1]), int(model[2])) elif model[0].lower() == 'pdeparrhenius': job.interpolationModel = ('pdeparrhenius',) # Read grain size or number of grains job.minimumGrainCount = 0 job.maximumGrainSize = None for i in range(2): data = readMeaningfulLine(f).split() if data[0].lower() == 'numgrains': job.minimumGrainCount = int(data[1]) elif data[0].lower() == 'grainsize': job.maximumGrainSize = (float(data[2]), data[1]) # A FAME file is almost certainly created during an RMG job, so use RMG mode job.rmgmode = True # Create the Network job.network = Network() # Read collision model data = readMeaningfulLine(f) assert data.lower() == 'singleexpdown' alpha0units, alpha0 = readMeaningfulLine(f).split() T0units, T0 = readMeaningfulLine(f).split() n = readMeaningfulLine(f) energyTransferModel = SingleExponentialDown( alpha0 = Quantity(float(alpha0), alpha0units), T0 = Quantity(float(T0), T0units), n = float(n), ) speciesDict = {} # Read bath gas parameters bathGas = Species(label='bath_gas', energyTransferModel=energyTransferModel) molWtunits, molWt = readMeaningfulLine(f).split() if molWtunits == 'u': molWtunits = 'amu' bathGas.molecularWeight = Quantity(float(molWt), molWtunits) sigmaLJunits, sigmaLJ = readMeaningfulLine(f).split() epsilonLJunits, epsilonLJ = readMeaningfulLine(f).split() assert epsilonLJunits == 'J' bathGas.transportData = TransportData( sigma = Quantity(float(sigmaLJ), sigmaLJunits), epsilon = Quantity(float(epsilonLJ) / constants.kB, 'K'), ) job.network.bathGas = {bathGas: 1.0} # Read species data Nspec = int(readMeaningfulLine(f)) for i in range(Nspec): species = Species() species.conformer = Conformer() species.energyTransferModel = energyTransferModel # Read species label species.label = readMeaningfulLine(f) speciesDict[species.label] = species if species.label in moleculeDict: species.molecule = [moleculeDict[species.label]] # Read species E0 E0units, E0 = readMeaningfulLine(f).split() species.conformer.E0 = Quantity(float(E0), E0units) species.conformer.E0.units = 'kJ/mol' # Read species thermo data H298units, H298 = readMeaningfulLine(f).split() S298units, S298 = readMeaningfulLine(f).split() Cpcount, Cpunits = readMeaningfulLine(f).split() Cpdata = [] for i in range(int(Cpcount)): Cpdata.append(float(readMeaningfulLine(f))) if S298units == 'J/mol*K': S298units = 'J/(mol*K)' if Cpunits == 'J/mol*K': Cpunits = 'J/(mol*K)' species.thermo = ThermoData( H298 = Quantity(float(H298), H298units), S298 = Quantity(float(S298), S298units), Tdata = Quantity([300,400,500,600,800,1000,1500], "K"), Cpdata = Quantity(Cpdata, Cpunits), Cp0 = (Cpdata[0], Cpunits), CpInf = (Cpdata[-1], Cpunits), ) # Read species collision parameters molWtunits, molWt = readMeaningfulLine(f).split() if molWtunits == 'u': molWtunits = 'amu' species.molecularWeight = Quantity(float(molWt), molWtunits) sigmaLJunits, sigmaLJ = readMeaningfulLine(f).split() epsilonLJunits, epsilonLJ = readMeaningfulLine(f).split() assert epsilonLJunits == 'J' species.transportData = TransportData( sigma = Quantity(float(sigmaLJ), sigmaLJunits), epsilon = Quantity(float(epsilonLJ) / constants.kB, 'K'), ) # Read species vibrational frequencies freqCount, freqUnits = readMeaningfulLine(f).split() frequencies = [] for j in range(int(freqCount)): frequencies.append(float(readMeaningfulLine(f))) species.conformer.modes.append(HarmonicOscillator( frequencies = Quantity(frequencies, freqUnits), )) # Read species external rotors rotCount, rotUnits = readMeaningfulLine(f).split() if int(rotCount) > 0: raise NotImplementedError('Cannot handle external rotational modes in FAME input.') # Read species internal rotors freqCount, freqUnits = readMeaningfulLine(f).split() frequencies = [] for j in range(int(freqCount)): frequencies.append(float(readMeaningfulLine(f))) barrCount, barrUnits = readMeaningfulLine(f).split() barriers = [] for j in range(int(barrCount)): barriers.append(float(readMeaningfulLine(f))) if barrUnits == 'cm^-1': barrUnits = 'J/mol' barriers = [barr * constants.h * constants.c * constants.Na * 100. for barr in barriers] elif barrUnits in ['Hz', 's^-1']: barrUnits = 'J/mol' barriers = [barr * constants.h * constants.Na for barr in barriers] elif barrUnits != 'J/mol': raise Exception('Unexpected units "{0}" for hindered rotor barrier height.'.format(barrUnits)) inertia = [V0 / 2.0 / (nu * constants.c * 100.)**2 / constants.Na for nu, V0 in zip(frequencies, barriers)] for I, V0 in zip(inertia, barriers): species.conformer.modes.append(HinderedRotor( inertia = Quantity(I,"kg*m^2"), barrier = Quantity(V0,barrUnits), symmetry = 1, semiclassical = False, )) # Read overall symmetry number species.conformer.spinMultiplicity = int(readMeaningfulLine(f)) # Read isomer, reactant channel, and product channel data Nisom = int(readMeaningfulLine(f)) Nreac = int(readMeaningfulLine(f)) Nprod = int(readMeaningfulLine(f)) for i in range(Nisom): data = readMeaningfulLine(f).split() assert data[0] == '1' job.network.isomers.append(speciesDict[data[1]]) for i in range(Nreac): data = readMeaningfulLine(f).split() assert data[0] == '2' job.network.reactants.append([speciesDict[data[1]], speciesDict[data[2]]]) for i in range(Nprod): data = readMeaningfulLine(f).split() if data[0] == '1': job.network.products.append([speciesDict[data[1]]]) elif data[0] == '2': job.network.products.append([speciesDict[data[1]], speciesDict[data[2]]]) # Read path reactions Nrxn = int(readMeaningfulLine(f)) for i in range(Nrxn): # Read and ignore reaction equation equation = readMeaningfulLine(f) reaction = Reaction(transitionState=TransitionState(), reversible=True) job.network.pathReactions.append(reaction) reaction.transitionState.conformer = Conformer() # Read reactant and product indices data = readMeaningfulLine(f).split() reac = int(data[0]) - 1 prod = int(data[1]) - 1 if reac < Nisom: reaction.reactants = [job.network.isomers[reac]] elif reac < Nisom+Nreac: reaction.reactants = job.network.reactants[reac-Nisom] else: reaction.reactants = job.network.products[reac-Nisom-Nreac] if prod < Nisom: reaction.products = [job.network.isomers[prod]] elif prod < Nisom+Nreac: reaction.products = job.network.reactants[prod-Nisom] else: reaction.products = job.network.products[prod-Nisom-Nreac] # Read reaction E0 E0units, E0 = readMeaningfulLine(f).split() reaction.transitionState.conformer.E0 = Quantity(float(E0), E0units) reaction.transitionState.conformer.E0.units = 'kJ/mol' # Read high-pressure limit kinetics data = readMeaningfulLine(f) assert data.lower() == 'arrhenius' Aunits, A = readMeaningfulLine(f).split() if '/' in Aunits: index = Aunits.find('/') Aunits = '{0}/({1})'.format(Aunits[0:index], Aunits[index+1:]) Eaunits, Ea = readMeaningfulLine(f).split() n = readMeaningfulLine(f) reaction.kinetics = Arrhenius( A = Quantity(float(A), Aunits), Ea = Quantity(float(Ea), Eaunits), n = Quantity(float(n)), ) reaction.kinetics.Ea.units = 'kJ/mol' f.close() job.network.isomers = [Configuration(isomer) for isomer in job.network.isomers] job.network.reactants = [Configuration(*reactants) for reactants in job.network.reactants] job.network.products = [Configuration(*products) for products in job.network.products] return job
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'))) rxnSystem0.simulate(coreSpecies, coreReactions, [], [], 0, 1, 0) 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'))) 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 range(numCoreSpecies): for j in range(len(rxnList)): self.assertAlmostEqual(dfdk[i, j], solver_dfdk[i, j], delta=abs(1e-3 * dfdk[i, j]))
keyend = match.group(3) inchi = match.group(4) inchidict[keystart] = inchi keydict[inchi] = keystart match = re.match('Thermo for ([A-Z]{14})-([A-Z]{10}):\s+(.*)',line) if match: keystart = match.group(1) keyend = match.group(2) thermo = match.group(3).split() thermo = [float(t) for t in thermo] td = ThermoData( Tdata = ([300,400,500,600,800,1000,1500],"K"), Cpdata = (thermo[2:9],"cal/(mol*K)"), H298 = (thermo[0],"kcal/mol"), S298 = (thermo[1],"cal/(mol*K)"), Tmin = (300.0,"K"), Tmax = (2000.0,"K"), comment = "from RMG-Java TDE" ) thermodict[keystart] = td for f in os.listdir(folder): f = os.path.join(folder,f) stem, ext = os.path.splitext(f) if ext != '.thermo': continue with open(f) as thermofile:
def estimateThermoViaGroupAdditivity(self, molecule): """ Return the set of thermodynamic parameters corresponding to a given :class:`Molecule` object `molecule` by estimation using the group additivity values. If no group additivity values are loaded, a :class:`DatabaseError` is raised. """ # For thermo estimation we need the atoms to already be sorted because we # iterate over them; if the order changes during the iteration then we # will probably not visit the right atoms, and so will get the thermo wrong molecule.sortVertices() # Create the ThermoData object thermoData = ThermoData( Tdata = ([300,400,500,600,800,1000,1500],"K"), Cpdata = ([0.0,0.0,0.0,0.0,0.0,0.0,0.0],"J/(mol*K)"), H298 = (0.0,"kJ/mol"), S298 = (0.0,"J/(mol*K)"), ) if molecule.getRadicalCount() > 0: # radical species return self.estimateRadicalThermoViaHBI(molecule, self.estimateThermoViaGroupAdditivity ) else: # non-radical species cyclic = molecule.isCyclic() # Generate estimate of thermodynamics for atom in molecule.atoms: # Iterate over heavy (non-hydrogen) atoms if atom.isNonHydrogen(): # Get initial thermo estimate from main group database try: self.__addGroupThermoData(thermoData, self.groups['group'], molecule, {'*':atom}) except KeyError: logging.error("Couldn't find in main thermo database:") logging.error(molecule) logging.error(molecule.toAdjacencyList()) raise # Correct for gauche and 1,5- interactions if not cyclic: try: self.__addGroupThermoData(thermoData, self.groups['gauche'], molecule, {'*':atom}) except KeyError: pass try: self.__addGroupThermoData(thermoData, self.groups['int15'], molecule, {'*':atom}) except KeyError: pass try: self.__addGroupThermoData(thermoData, self.groups['other'], molecule, {'*':atom}) except KeyError: pass # Do ring corrections separately because we only want to match # each ring one time if cyclic: if molecule.getAllPolycyclicVertices(): # If the molecule has fused ring atoms, this implies that we are dealing # with a polycyclic ring system, for which separate ring strain corrections may not # be adequate. Therefore, we search the polycyclic thermo group corrections # instead of adding single ring strain corrections within the molecule. # For now, assume only one polycyclic RSC can be found per molecule try: self.__addGroupThermoData(thermoData, self.groups['polycyclic'], molecule, {}) except: logging.error("Couldn't find in polycyclic ring database:") logging.error(molecule) logging.error(molecule.toAdjacencyList()) raise else: rings = molecule.getSmallestSetOfSmallestRings() for ring in rings: # Make a temporary structure containing only the atoms in the ring # NB. if any of the ring corrections depend on ligands not in the ring, they will not be found! try: self.__addGroupThermoData(thermoData, self.groups['ring'], molecule, {}) except KeyError: logging.error("Couldn't find in ring database:") logging.error(ring) logging.error(ring.toAdjacencyList()) raise # Correct entropy for symmetry number molecule.calculateSymmetryNumber() thermoData.S298.value_si -= constants.R * math.log(molecule.symmetryNumber) return thermoData
def test_solve_h2(self): """ Test the surface batch reactor with a dissociative adsorption of H2 Here we choose a kinetic model consisting of the dissociative adsorption reaction H2 + 2X <=> 2 HX We use a SurfaceArrhenius for the rate expression. """ h2 = Species( molecule=[Molecule().from_smiles("[H][H]")], thermo=ThermoData(Tdata=([300, 400, 500, 600, 800, 1000, 1500], "K"), Cpdata=([6.955, 6.955, 6.956, 6.961, 7.003, 7.103, 7.502], "cal/(mol*K)"), H298=(0, "kcal/mol"), S298=(31.129, "cal/(mol*K)"))) x = Species( molecule=[Molecule().from_adjacency_list("1 X u0 p0")], thermo=ThermoData(Tdata=([300, 400, 500, 600, 800, 1000, 1500], "K"), Cpdata=([0., 0., 0., 0., 0., 0., 0.], "cal/(mol*K)"), H298=(0.0, "kcal/mol"), S298=(0.0, "cal/(mol*K)"))) hx = Species( molecule=[Molecule().from_adjacency_list("1 H u0 p0 {2,S} \n 2 X u0 p0 {1,S}")], thermo=ThermoData(Tdata=([300, 400, 500, 600, 800, 1000, 1500], "K"), Cpdata=([1.50, 2.58, 3.40, 4.00, 4.73, 5.13, 5.57], "cal/(mol*K)"), H298=(-11.26, "kcal/mol"), S298=(0.44, "cal/(mol*K)"))) rxn1 = Reaction(reactants=[h2, x, x], products=[hx, hx], kinetics=SurfaceArrhenius(A=(9.05e18, 'cm^5/(mol^2*s)'), n=0.5, Ea=(5.0, 'kJ/mol'), T0=(1.0, 'K'))) core_species = [h2, x, hx] edge_species = [] core_reactions = [rxn1] edge_reactions = [] T = 1000 P_initial = 1.0e5 rxn_system = SurfaceReactor( T, P_initial, n_sims=1, initial_gas_mole_fractions={h2: 1.0}, initial_surface_coverages={x: 1.0}, surface_volume_ratio=(1e1, 'm^-1'), surface_site_density=(2.72e-9, 'mol/cm^2'), termination=[]) rxn_system.initialize_model(core_species, core_reactions, edge_species, edge_reactions) tlist = np.logspace(-13, -5, 81, dtype=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) y = np.array(y, np.float64) reaction_rates = np.array(reaction_rates, np.float64) species_rates = np.array(species_rates, np.float64) V = constants.R * rxn_system.T.value_si * np.sum(y) / rxn_system.P_initial.value_si # Check that we're computing the species fluxes correctly for i in range(t.shape[0]): self.assertAlmostEqual(reaction_rates[i, 0], -1.0 * species_rates[i, 0], delta=1e-6 * reaction_rates[i, 0]) self.assertAlmostEqual(reaction_rates[i, 0], -0.5 * species_rates[i, 1], delta=1e-6 * reaction_rates[i, 0]) self.assertAlmostEqual(reaction_rates[i, 0], 0.5 * species_rates[i, 2], delta=1e-6 * reaction_rates[i, 0]) # Check that we've reached equilibrium self.assertAlmostEqual(reaction_rates[-1, 0], 0.0, delta=1e-2) # # Visualize the simulation results # import pylab # fig = pylab.figure(figsize=(6, 6)) # pylab.subplot(2, 1, 1) # pylab.semilogx(t, y[:, 2]) # pylab.ylabel('Concentration (mol/m$^\\mathdefault{3 or 2}$)') # pylab.legend(['HX'], loc=4) # pylab.subplot(2, 1, 2) # pylab.semilogx(t, species_rates) # pylab.legend(['H2', 'X', 'HX'], loc=4) # pylab.xlabel('Time (s)') # pylab.ylabel('Rate (mol/m$^\\mathdefault{3 or 2}$*s)') # # fig.subplots_adjust(left=0.21, bottom=0.10, right=0.95, top=0.95, wspace=0.20, hspace=0.35) # pylab.tight_layout() # # pylab.show() # pylab.savefig('surfaceTestH2.pdf') return
def setUp(self): self.A = 1e14 self.sar = sar self.ipropyl_mol = Molecule(SMILES='C[CH]C') self.ipropyl_ip = 7.37 self.methyl_ip = 9.84 # breakdown forming benzyl radical (though not as primary resonance structure) self.resonance_reaction = 0 #ethyoxy breakdown self.reaction = TemplateReaction(reactants=[ Species( label="", thermo=ThermoData( Tdata=([300, 400, 500, 600, 800, 1000, 1500], 'K'), Cpdata=([ 35.4385, 39.2459, 43.7646, 48.1997, 55.9401, 61.965, 61.965 ], 'J/(mol*K)'), H298=(-108.575, 'kJ/mol'), S298=(218.834, 'J/(mol*K)'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(83.1447, 'J/(mol*K)'), comment= """Thermo group additivity estimation: group(Cds-OdHH)"""), molecule=[ Molecule().fromAdjacencyList( """1 *1 C u0 p0 c0 {2,S} {3,S} {4,D} 2 H u0 p0 c0 {1,S} 3 H u0 p0 c0 {1,S} 4 *2 O u0 p2 c0 {1,D} """) ]), Species( label="", thermo=ThermoData( Tdata=([300, 400, 500, 600, 800, 1000, 1500], 'K'), Cpdata=([ 9.331, 9.988, 10.611, 11.274, 12.457, 13.427, 15.105 ], 'cal/(mol*K)'), H298=(34.893, 'kcal/mol'), S298=(46.3704, 'cal/(mol*K)'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(108.088, 'J/(mol*K)'), comment= """Thermo library: primaryThermoLibrary + radical(CH3)"""), molecule=[ Molecule().fromAdjacencyList("""multiplicity 2 1 *3 C u1 p0 c0 {2,S} {3,S} {4,S} 2 H u0 p0 c0 {1,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} """) ]) ], products=[ Species(label="", thermo=ThermoData( Tdata=([ 300, 400, 500, 600, 800, 1000, 1500 ], 'K'), Cpdata=([ 61.879, 72.3026, 83.2296, 93.9954, 112.876, 127.558, 150.145 ], 'J/(mol*K)'), H298=(-17.2758, 'kJ/mol'), S298=(284.871, 'J/(mol*K)'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(178.761, 'J/(mol*K)'), comment= """Thermo group additivity estimation: group(Cs-CsOsHH) + group(Cs-CsHHH) + group(Os-CsH) + radical(CCOJ)""" ), molecule=[ Molecule(). fromAdjacencyList( """multiplicity 2 1 *3 C u0 p0 c0 {2,S} {4,S} {5,S} {6,S} 2 *1 C u0 p0 c0 {1,S} {3,S} {7,S} {8,S} 3 *2 O u1 p2 c0 {2,S} 4 H u0 p0 c0 {1,S} 5 H u0 p0 c0 {1,S} 6 H u0 p0 c0 {1,S} 7 H u0 p0 c0 {2,S} 8 H u0 p0 c0 {2,S} """) ]) ], pairs=[[ Species(label="", thermo=ThermoData( Tdata=([ 300, 400, 500, 600, 800, 1000, 1500 ], 'K'), Cpdata=([ 35.4385, 39.2459, 43.7646, 48.1997, 55.9401, 61.965, 61.965 ], 'J/(mol*K)'), H298=(-108.575, 'kJ/mol'), S298=(218.834, 'J/(mol*K)'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(83.1447, 'J/(mol*K)'), comment= """Thermo group additivity estimation: group(Cds-OdHH)""" ), molecule=[ Molecule(). fromAdjacencyList( """1 *1 C u0 p0 c0 {2,S} {3,S} {4,D} 2 H u0 p0 c0 {1,S} 3 H u0 p0 c0 {1,S} 4 *2 O u0 p2 c0 {1,D} """) ]), Species(label="", thermo=ThermoData( Tdata=([ 300, 400, 500, 600, 800, 1000, 1500 ], 'K'), Cpdata=([ 61.879, 72.3026, 83.2296, 93.9954, 112.876, 127.558, 150.145 ], 'J/(mol*K)'), H298=(-17.2758, 'kJ/mol'), S298=(284.871, 'J/(mol*K)'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(178.761, 'J/(mol*K)'), comment= """Thermo group additivity estimation: group(Cs-CsOsHH) + group(Cs-CsHHH) + group(Os-CsH) + radical(CCOJ)""" ), molecule=[ Molecule(). fromAdjacencyList( """multiplicity 2 1 *3 C u0 p0 c0 {2,S} {4,S} {5,S} {6,S} 2 *1 C u0 p0 c0 {1,S} {3,S} {7,S} {8,S} 3 *2 O u1 p2 c0 {2,S} 4 H u0 p0 c0 {1,S} 5 H u0 p0 c0 {1,S} 6 H u0 p0 c0 {1,S} 7 H u0 p0 c0 {2,S} 8 H u0 p0 c0 {2,S} """) ]) ], [ Species( label="", thermo=ThermoData( Tdata=([ 300, 400, 500, 600, 800, 1000, 1500 ], 'K'), Cpdata=([ 9.331, 9.988, 10.611, 11.274, 12.457, 13.427, 15.105 ], 'cal/(mol*K)'), H298=(34.893, 'kcal/mol'), S298=( 46.3704, 'cal/(mol*K)'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=( 108.088, 'J/(mol*K)'), comment= """Thermo library: primaryThermoLibrary + radical(CH3)""" ), molecule=[ Molecule(). fromAdjacencyList( """multiplicity 2 1 *3 C u1 p0 c0 {2,S} {3,S} {4,S} 2 H u0 p0 c0 {1,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} """) ]), Species( label="", thermo=ThermoData( Tdata=([ 300, 400, 500, 600, 800, 1000, 1500 ], 'K'), Cpdata=([ 61.879, 72.3026, 83.2296, 93.9954, 112.876, 127.558, 150.145 ], 'J/(mol*K)'), H298=(-17.2758, 'kJ/mol'), S298=(284.871, 'J/(mol*K)'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=( 178.761, 'J/(mol*K)'), comment= """Thermo group additivity estimation: group(Cs-CsOsHH) + group(Cs-CsHHH) + group(Os-CsH) + radical(CCOJ)""" ), molecule=[ Molecule(). fromAdjacencyList( """multiplicity 2 1 *3 C u0 p0 c0 {2,S} {4,S} {5,S} {6,S} 2 *1 C u0 p0 c0 {1,S} {3,S} {7,S} {8,S} 3 *2 O u1 p2 c0 {2,S} 4 H u0 p0 c0 {1,S} 5 H u0 p0 c0 {1,S} 6 H u0 p0 c0 {1,S} 7 H u0 p0 c0 {2,S} 8 H u0 p0 c0 {2,S} """) ]) ]], family='R_Addition_MultipleBond', template=['Cd_R', 'CsJ']) self.degenerate_reaction = TemplateReaction(reactants=[ Species( label="", thermo=ThermoData( Tdata=([300, 400, 500, 600, 800, 1000, 1500], 'K'), Cpdata=([51.55, 63.29, 74.38, 84.19, 100.1, 112.02, 130.2], 'J/(mol*K)'), H298=(-166.3, 'kJ/mol'), S298=(263.446, 'J/(mol*K)'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(153.818, 'J/(mol*K)'), comment= """Thermo group additivity estimation: group(Cs-(Cds-Od)HHH) + group(Cds-OdCsH)""" ), molecule=[ Molecule().fromAdjacencyList( """1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S} 2 *1 C u0 p0 c0 {1,S} {6,D} {7,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} 5 H u0 p0 c0 {1,S} 6 *2 O u0 p2 c0 {2,D} 7 H u0 p0 c0 {2,S} """) ]), Species( label="", thermo=ThermoData( Tdata=([300, 400, 500, 600, 800, 1000, 1500], 'K'), Cpdata=([ 9.331, 9.988, 10.611, 11.274, 12.457, 13.427, 15.105 ], 'cal/(mol*K)'), H298=(34.893, 'kcal/mol'), S298=(46.3704, 'cal/(mol*K)'), Cp0=(33.2579, 'J/(mol*K)'), CpInf=(108.088, 'J/(mol*K)'), comment= """Thermo library: primaryThermoLibrary + radical(CH3)"""), molecule=[ Molecule().fromAdjacencyList("""multiplicity 2 1 *3 C u1 p0 c0 {2,S} {3,S} {4,S} 2 H u0 p0 c0 {1,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} """) ]) ], products=[ Species( label="", thermo=ThermoData( Tdata=([ 300, 400, 500, 600, 800, 1000, 1500 ], 'K'), Cpdata=([ 87.5579, 108.135, 126.429, 141.841, 165.681, 183.615, 211.679 ], 'J/(mol*K)' ), H298=( -46.0526, 'kJ/mol'), S298=( 302.672, 'J/(mol*K)' ), Cp0=( 33.2579, 'J/(mol*K)' ), CpInf=( 249.434, 'J/(mol*K)' ), comment= """Thermo group additivity estimation: group(Cs-CsCsOsH) + group(Cs-CsHHH) + group(Cs-CsHHH) + group(Os-CsH) + radical(CC(C)OJ)""" ), molecule=[ Molecule(). fromAdjacencyList( """multiplicity 2 1 *1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S} 2 C u0 p0 c0 {1,S} {6,S} {7,S} {8,S} 3 *3 C u0 p0 c0 {1,S} {9,S} {10,S} {11,S} 4 *2 O u1 p2 c0 {1,S} 5 H u0 p0 c0 {1,S} 6 H u0 p0 c0 {2,S} 7 H u0 p0 c0 {2,S} 8 H u0 p0 c0 {2,S} 9 H u0 p0 c0 {3,S} 10 H u0 p0 c0 {3,S} 11 H u0 p0 c0 {3,S} """) ]) ], degeneracy=2.0, pairs=[[ Species( label="", thermo=ThermoData( Tdata=([ 300, 400, 500, 600, 800, 1000, 1500 ], 'K'), Cpdata=([ 51.55, 63.29, 74.38, 84.19, 100.1, 112.02, 130.2 ], 'J/(mol*K)' ), H298=( -166.3, 'kJ/mol'), S298=( 263.446, 'J/(mol*K)' ), Cp0=( 33.2579, 'J/(mol*K)' ), CpInf=( 153.818, 'J/(mol*K)' ), comment= """Thermo group additivity estimation: group(Cs-(Cds-Od)HHH) + group(Cds-OdCsH)""" ), molecule=[ Molecule(). fromAdjacencyList( """1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S} 2 *1 C u0 p0 c0 {1,S} {6,D} {7,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} 5 H u0 p0 c0 {1,S} 6 *2 O u0 p2 c0 {2,D} 7 H u0 p0 c0 {2,S} """) ]), Species( label="", thermo=ThermoData( Tdata=([ 300, 400, 500, 600, 800, 1000, 1500 ], 'K'), Cpdata=([ 87.5579, 108.135, 126.429, 141.841, 165.681, 183.615, 211.679 ], 'J/(mol*K)' ), H298=( -46.0526, 'kJ/mol'), S298=( 302.672, 'J/(mol*K)' ), Cp0=( 33.2579, 'J/(mol*K)' ), CpInf=( 249.434, 'J/(mol*K)' ), comment= """Thermo group additivity estimation: group(Cs-CsCsOsH) + group(Cs-CsHHH) + group(Cs-CsHHH) + group(Os-CsH) + radical(CC(C)OJ)""" ), molecule=[ Molecule(). fromAdjacencyList( """multiplicity 2 1 *1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S} 2 C u0 p0 c0 {1,S} {6,S} {7,S} {8,S} 3 *3 C u0 p0 c0 {1,S} {9,S} {10,S} {11,S} 4 *2 O u1 p2 c0 {1,S} 5 H u0 p0 c0 {1,S} 6 H u0 p0 c0 {2,S} 7 H u0 p0 c0 {2,S} 8 H u0 p0 c0 {2,S} 9 H u0 p0 c0 {3,S} 10 H u0 p0 c0 {3,S} 11 H u0 p0 c0 {3,S} """) ]) ], [ Species( label="", thermo= ThermoData( Tdata=([ 300, 400, 500, 600, 800, 1000, 1500 ], 'K'), Cpdata=([ 9.331, 9.988, 10.611, 11.274, 12.457, 13.427, 15.105 ], 'cal/(mol*K)' ), H298= (34.893, 'kcal/mol' ), S298= (46.3704, 'cal/(mol*K)' ), Cp0= (33.2579, 'J/(mol*K)' ), CpInf= (108.088, 'J/(mol*K)' ), comment= """Thermo library: primaryThermoLibrary + radical(CH3)""" ), molecule=[ Molecule( ). fromAdjacencyList( """multiplicity 2 1 *3 C u1 p0 c0 {2,S} {3,S} {4,S} 2 H u0 p0 c0 {1,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} """) ]), Species( label="", thermo= ThermoData( Tdata=([ 300, 400, 500, 600, 800, 1000, 1500 ], 'K'), Cpdata=([ 87.5579, 108.135, 126.429, 141.841, 165.681, 183.615, 211.679 ], 'J/(mol*K)' ), H298= (-46.0526, 'kJ/mol' ), S298= (302.672, 'J/(mol*K)' ), Cp0= (33.2579, 'J/(mol*K)' ), CpInf= (249.434, 'J/(mol*K)' ), comment= """Thermo group additivity estimation: group(Cs-CsCsOsH) + group(Cs-CsHHH) + group(Cs-CsHHH) + group(Os-CsH) + radical(CC(C)OJ)""" ), molecule=[ Molecule( ). fromAdjacencyList( """multiplicity 2 1 *1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S} 2 C u0 p0 c0 {1,S} {6,S} {7,S} {8,S} 3 *3 C u0 p0 c0 {1,S} {9,S} {10,S} {11,S} 4 *2 O u1 p2 c0 {1,S} 5 H u0 p0 c0 {1,S} 6 H u0 p0 c0 {2,S} 7 H u0 p0 c0 {2,S} 8 H u0 p0 c0 {2,S} 9 H u0 p0 c0 {3,S} 10 H u0 p0 c0 {3,S} 11 H u0 p0 c0 {3,S} """) ]) ]], family= 'R_Addition_MultipleBond', template=['Cd_R', 'CsJ'])