Skip to content

Commit af0ef48

Browse files
authored
RMG-Py v2.4.1 release
2 parents caebd48 + 62db25f commit af0ef48

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+3042
-1509
lines changed

arkane/common.py

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
from rmgpy.statmech.vibration import HarmonicOscillator
5353
from rmgpy.pdep.collision import SingleExponentialDown
5454
from rmgpy.transport import TransportData
55-
from rmgpy.thermo import NASA, Wilhoit
55+
from rmgpy.thermo import NASA, Wilhoit, ThermoData, NASAPolynomial
5656
from rmgpy.species import Species, TransitionState
5757
import rmgpy.constants as constants
5858

@@ -180,16 +180,19 @@ def update_species_attributes(self, species=None):
180180
self.energy_transfer_model = species.energyTransferModel
181181
if species.thermo is not None:
182182
self.thermo = species.thermo.as_dict()
183-
thermo_data = species.getThermoData()
184-
h298 = thermo_data.getEnthalpy(298) / 4184.
185-
s298 = thermo_data.getEntropy(298) / 4.184
186-
cp = dict()
187-
for t in [300, 400, 500, 600, 800, 1000, 1500, 2000, 2400]:
188-
temp_str = '{0} K'.format(t)
189-
cp[temp_str] = '{0:.2f}'.format(thermo_data.getHeatCapacity(t) / 4.184)
190-
self.thermo_data = {'H298': '{0:.2f} kcal/mol'.format(h298),
191-
'S298': '{0:.2f} cal/mol*K'.format(s298),
192-
'Cp (cal/mol*K)': cp}
183+
data = species.getThermoData()
184+
h298 = data.getEnthalpy(298) / 4184.
185+
s298 = data.getEntropy(298) / 4.184
186+
temperatures = numpy.array([300, 400, 500, 600, 800, 1000, 1500, 2000, 2400])
187+
cp = []
188+
for t in temperatures:
189+
cp.append(data.getHeatCapacity(t) / 4.184)
190+
191+
self.thermo_data = ThermoData(H298=(h298, 'kcal/mol'),
192+
S298=(s298, 'cal/(mol*K)'),
193+
Tdata=(temperatures, 'K'),
194+
Cpdata=(cp, 'cal/(mol*K)'),
195+
)
193196

194197
def update_xyz_string(self):
195198
"""
@@ -228,21 +231,30 @@ def save_yaml(self, path):
228231
yaml.dump(data=self.as_dict(), stream=f)
229232
logging.debug('Dumping species {0} data as {1}'.format(self.label, filename))
230233

231-
def load_yaml(self, path, species, pdep=False):
234+
def load_yaml(self, path, label=None, pdep=False):
232235
"""
233236
Load the all statMech data from the .yml file in `path` into `species`
234237
`pdep` is a boolean specifying whether or not jobList includes a pressureDependentJob.
235238
"""
236-
logging.info('Loading statistical mechanics parameters for {0} from .yml file...'.format(species.label))
239+
yml_file = os.path.basename(path)
240+
if label:
241+
logging.info('Loading statistical mechanics parameters for {0} from {1} file...'.format(label, yml_file))
242+
else:
243+
logging.info('Loading statistical mechanics parameters from {0} file...'.format(yml_file))
237244
with open(path, 'r') as f:
238245
data = yaml.safe_load(stream=f)
239-
try:
240-
if species.label != data['label']:
241-
logging.debug('Found different labels for species: {0} in input file, and {1} in the .yml file. '
242-
'Using the label "{0}" for this species.'.format(species.label, data['label']))
243-
except KeyError:
244-
# Lacking label in the YAML file is strange, but accepted
245-
logging.debug('Did not find label for species {0} in .yml file.'.format(species.label))
246+
if label:
247+
# First, warn the user if the label doesn't match
248+
try:
249+
if label != data['label']:
250+
logging.debug('Found different labels for species: {0} in input file, and {1} in the .yml file. '
251+
'Using the label "{0}" for this species.'.format(label, data['label']))
252+
except KeyError:
253+
# Lacking label in the YAML file is strange, but accepted
254+
logging.debug('Did not find label for species {0} in .yml file.'.format(label))
255+
256+
# Then, set the ArkaneSpecies label to the user supplied label
257+
data['label'] = label
246258
try:
247259
class_name = data['class']
248260
except KeyError:
@@ -265,19 +277,32 @@ def load_yaml(self, path, species, pdep=False):
265277
'SingleExponentialDown': SingleExponentialDown,
266278
'Wilhoit': Wilhoit,
267279
'NASA': NASA,
280+
'NASAPolynomial': NASAPolynomial,
281+
'ThermoData': ThermoData,
282+
'np_array': numpy.array,
268283
}
269284
freq_data = None
270285
if 'imaginary_frequency' in data:
271286
freq_data = data['imaginary_frequency']
272287
del data['imaginary_frequency']
288+
if not data['is_ts']:
289+
if 'smiles' in data:
290+
data['species'] = Species(SMILES=data['smiles'])
291+
elif 'adjacency_list' in data:
292+
data['species'] = Species().fromAdjacencyList(data['adjacency_list'])
293+
elif 'inchi' in data:
294+
data['species'] = Species(InChI=data['inchi'])
295+
else:
296+
raise ValueError('Cannot load ArkaneSpecies from YAML file {0}. Either `smiles`, `adjacency_list`, or '
297+
'InChI must be specified'.format(path))
298+
# Finally, set the species label so that the special attributes are updated properly
299+
data['species'].label = data['label']
300+
273301
self.make_object(data=data, class_dict=class_dict)
274302
if freq_data is not None:
275303
self.imaginary_frequency = ScalarQuantity()
276-
self.imaginary_frequency.make_object(data=freq_data, class_dict=dict())
277-
self.adjacency_list = data['adjacency_list'] if 'adjacency_list' in data else None
278-
self.inchi = data['inchi'] if 'inchi' in data else None
279-
self.smiles = data['smiles'] if 'smiles' in data else None
280-
self.is_ts = data['is_ts'] if 'is_ts' in data else False
304+
self.imaginary_frequency.make_object(data=freq_data, class_dict=class_dict)
305+
281306
if pdep and not self.is_ts and (self.transport_data is None or self.energy_transfer_model is None):
282307
raise ValueError('Transport data and an energy transfer model must be given if pressure-dependent '
283308
'calculations are requested. Check file {0}'.format(path))
@@ -347,7 +372,7 @@ def get_element_mass(input_element, isotope=None):
347372
else:
348373
# no specific isotope is required
349374
if len(mass_list[0]) == 2:
350-
# isotop weight is unavailable, use the first entry
375+
# isotope weight is unavailable, use the first entry
351376
mass = mass_list[0][1]
352377
logging.warn("Assuming isotop {0} is representative of element {1}".format(mass_list[0][0], symbol))
353378
else:

arkane/commonTest.py

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@
4040

4141
import rmgpy
4242
import rmgpy.constants as constants
43+
from rmgpy.pdep.collision import SingleExponentialDown
4344
from rmgpy.species import Species, TransitionState
4445
from rmgpy.quantity import ScalarQuantity
45-
from rmgpy.thermo import NASA
46+
from rmgpy.thermo import NASA, ThermoData
4647

4748
from arkane import Arkane, input
4849
from arkane.common import ArkaneSpecies, get_element_mass
@@ -248,9 +249,9 @@ def testSpeciesStatmech(self):
248249
job.includeHinderedRotors = self.useHinderedRotors
249250
job.applyBondEnergyCorrections = self.useBondCorrections
250251
job.load()
251-
self.assertTrue(isinstance(job.species.props['elementCounts'], dict))
252-
self.assertEqual(job.species.props['elementCounts']['C'], 2)
253-
self.assertEqual(job.species.props['elementCounts']['H'], 4)
252+
self.assertTrue(isinstance(job.species.props['element_counts'], dict))
253+
self.assertEqual(job.species.props['element_counts']['C'], 2)
254+
self.assertEqual(job.species.props['element_counts']['H'], 4)
254255

255256
def testSpeciesThermo(self):
256257
"""Test thermo job execution for species from separate input file."""
@@ -334,25 +335,65 @@ def test_dump_yaml(self):
334335
job.execute(outputFile=self.dump_output_file)
335336
self.assertTrue(os.path.isfile(self.dump_yaml_file))
336337

337-
def test_load_yaml(self):
338+
def test_create_and_load_yaml(self):
338339
"""
339340
Test properly loading the ArkaneSpecies object and respective sub-objects
340341
"""
341-
jobList = self.arkane.loadInputFile(self.load_input_path)
342+
# Create YAML file by running Arkane
343+
jobList = self.arkane.loadInputFile(self.dump_input_path)
342344
for job in jobList:
343-
job.execute(outputFile=self.load_output_file)
344-
arkane_spc = jobList[0].arkane_species
345+
job.execute(outputFile=self.dump_output_file)
346+
347+
# Load in newly created YAML file
348+
arkane_spc_old = jobList[0].arkane_species
349+
arkane_spc = ArkaneSpecies.__new__(ArkaneSpecies)
350+
arkane_spc.load_yaml(path=os.path.join(self.dump_path, 'species', arkane_spc_old.label + '.yml'))
351+
352+
self.assertIsInstance(arkane_spc, ArkaneSpecies) # checks make_object
353+
self.assertIsInstance(arkane_spc.molecular_weight, ScalarQuantity)
354+
self.assertIsInstance(arkane_spc.thermo, NASA)
355+
self.assertNotEqual(arkane_spc.author, '')
356+
self.assertEqual(arkane_spc.inchi, 'InChI=1S/C2H6/c1-2/h1-2H3')
357+
self.assertEqual(arkane_spc.inchi_key, 'OTMSDBZUPAUEDD-UHFFFAOYSA-N')
358+
self.assertEqual(arkane_spc.smiles, 'CC')
359+
self.assertTrue('8 H u0 p0 c0 {2,S}' in arkane_spc.adjacency_list)
360+
self.assertEqual(arkane_spc.label, 'C2H6')
361+
self.assertEqual(arkane_spc.frequency_scale_factor, 0.99*1.014) # checks float conversion
362+
self.assertFalse(arkane_spc.use_bond_corrections)
363+
self.assertAlmostEqual(arkane_spc.conformer.modes[2].frequencies.value_si[0], 830.38202, 4) # HarmonicOsc.
364+
self.assertIsInstance(arkane_spc.energy_transfer_model, SingleExponentialDown)
365+
self.assertFalse(arkane_spc.is_ts)
366+
self.assertEqual(arkane_spc.level_of_theory, 'cbs-qb3')
367+
self.assertIsInstance(arkane_spc.thermo_data, ThermoData)
368+
self.assertTrue(arkane_spc.use_hindered_rotors)
369+
self.assertTrue('C 7.54e-14 1.193e-13 5.52e-14' in arkane_spc.xyz)
370+
self.assertIsInstance(arkane_spc.chemkin_thermo_string, str)
371+
372+
def test_load_existing_yaml(self):
373+
"""
374+
Test that existing Arkane YAML files can still be loaded
375+
"""
376+
# Load in YAML file
377+
arkane_spc = ArkaneSpecies.__new__(ArkaneSpecies)
378+
arkane_spc.load_yaml(path=os.path.join(self.load_path, 'C2H6.yml'))
379+
345380
self.assertIsInstance(arkane_spc, ArkaneSpecies) # checks make_object
346381
self.assertIsInstance(arkane_spc.molecular_weight, ScalarQuantity)
347382
self.assertIsInstance(arkane_spc.thermo, NASA)
348383
self.assertNotEqual(arkane_spc.author, '')
349384
self.assertEqual(arkane_spc.inchi, 'InChI=1S/C2H6/c1-2/h1-2H3')
385+
self.assertEqual(arkane_spc.inchi_key, 'OTMSDBZUPAUEDD-UHFFFAOYSA-N')
350386
self.assertEqual(arkane_spc.smiles, 'CC')
351387
self.assertTrue('8 H u0 p0 c0 {2,S}' in arkane_spc.adjacency_list)
352388
self.assertEqual(arkane_spc.label, 'C2H6')
353389
self.assertEqual(arkane_spc.frequency_scale_factor, 0.99) # checks float conversion
354390
self.assertFalse(arkane_spc.use_bond_corrections)
355391
self.assertAlmostEqual(arkane_spc.conformer.modes[2].frequencies.value_si[0], 818.91718, 4) # HarmonicOsc.
392+
self.assertIsInstance(arkane_spc.energy_transfer_model, SingleExponentialDown)
393+
self.assertFalse(arkane_spc.is_ts)
394+
self.assertTrue(arkane_spc.use_hindered_rotors)
395+
self.assertTrue('C 7.54e-14 1.193e-13 5.52e-14' in arkane_spc.xyz)
396+
self.assertIsInstance(arkane_spc.chemkin_thermo_string, str)
356397

357398
@classmethod
358399
def tearDownClass(cls):

arkane/encorr/__init__.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
"""
5+
initialize imports
6+
"""
7+
8+
###############################################################################
9+
# #
10+
# RMG - Reaction Mechanism Generator #
11+
# #
12+
# Copyright (c) 2002-2019 Prof. William H. Green ([email protected]), #
13+
# Prof. Richard H. West ([email protected]) and the RMG Team ([email protected]) #
14+
# #
15+
# Permission is hereby granted, free of charge, to any person obtaining a #
16+
# copy of this software and associated documentation files (the 'Software'), #
17+
# to deal in the Software without restriction, including without limitation #
18+
# the rights to use, copy, modify, merge, publish, distribute, sublicense, #
19+
# and/or sell copies of the Software, and to permit persons to whom the #
20+
# Software is furnished to do so, subject to the following conditions: #
21+
# #
22+
# The above copyright notice and this permission notice shall be included in #
23+
# all copies or substantial portions of the Software. #
24+
# #
25+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
26+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
27+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
28+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
29+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING #
30+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER #
31+
# DEALINGS IN THE SOFTWARE. #
32+
# #
33+
###############################################################################

0 commit comments

Comments
 (0)