Skip to content

Commit

Permalink
RMG-Py v2.4.1 release
Browse files Browse the repository at this point in the history
  • Loading branch information
mliu49 authored Jul 23, 2019
2 parents caebd48 + 62db25f commit af0ef48
Show file tree
Hide file tree
Showing 66 changed files with 3,042 additions and 1,509 deletions.
77 changes: 51 additions & 26 deletions arkane/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
from rmgpy.statmech.vibration import HarmonicOscillator
from rmgpy.pdep.collision import SingleExponentialDown
from rmgpy.transport import TransportData
from rmgpy.thermo import NASA, Wilhoit
from rmgpy.thermo import NASA, Wilhoit, ThermoData, NASAPolynomial
from rmgpy.species import Species, TransitionState
import rmgpy.constants as constants

Expand Down Expand Up @@ -180,16 +180,19 @@ def update_species_attributes(self, species=None):
self.energy_transfer_model = species.energyTransferModel
if species.thermo is not None:
self.thermo = species.thermo.as_dict()
thermo_data = species.getThermoData()
h298 = thermo_data.getEnthalpy(298) / 4184.
s298 = thermo_data.getEntropy(298) / 4.184
cp = dict()
for t in [300, 400, 500, 600, 800, 1000, 1500, 2000, 2400]:
temp_str = '{0} K'.format(t)
cp[temp_str] = '{0:.2f}'.format(thermo_data.getHeatCapacity(t) / 4.184)
self.thermo_data = {'H298': '{0:.2f} kcal/mol'.format(h298),
'S298': '{0:.2f} cal/mol*K'.format(s298),
'Cp (cal/mol*K)': cp}
data = species.getThermoData()
h298 = data.getEnthalpy(298) / 4184.
s298 = data.getEntropy(298) / 4.184
temperatures = numpy.array([300, 400, 500, 600, 800, 1000, 1500, 2000, 2400])
cp = []
for t in temperatures:
cp.append(data.getHeatCapacity(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 update_xyz_string(self):
"""
Expand Down Expand Up @@ -228,21 +231,30 @@ def save_yaml(self, path):
yaml.dump(data=self.as_dict(), stream=f)
logging.debug('Dumping species {0} data as {1}'.format(self.label, filename))

def load_yaml(self, path, species, pdep=False):
def load_yaml(self, path, label=None, pdep=False):
"""
Load the all statMech data from the .yml file in `path` into `species`
`pdep` is a boolean specifying whether or not jobList includes a pressureDependentJob.
"""
logging.info('Loading statistical mechanics parameters for {0} from .yml file...'.format(species.label))
yml_file = os.path.basename(path)
if label:
logging.info('Loading statistical mechanics parameters for {0} from {1} file...'.format(label, yml_file))
else:
logging.info('Loading statistical mechanics parameters from {0} file...'.format(yml_file))
with open(path, 'r') as f:
data = yaml.safe_load(stream=f)
try:
if species.label != data['label']:
logging.debug('Found different labels for species: {0} in input file, and {1} in the .yml file. '
'Using the label "{0}" for this species.'.format(species.label, data['label']))
except KeyError:
# Lacking label in the YAML file is strange, but accepted
logging.debug('Did not find label for species {0} in .yml file.'.format(species.label))
if label:
# First, warn the user if the label doesn't match
try:
if label != data['label']:
logging.debug('Found different labels for species: {0} in input file, and {1} in the .yml file. '
'Using the label "{0}" for this species.'.format(label, data['label']))
except KeyError:
# Lacking label in the YAML file is strange, but accepted
logging.debug('Did not find label for species {0} in .yml file.'.format(label))

# Then, set the ArkaneSpecies label to the user supplied label
data['label'] = label
try:
class_name = data['class']
except KeyError:
Expand All @@ -265,19 +277,32 @@ def load_yaml(self, path, species, pdep=False):
'SingleExponentialDown': SingleExponentialDown,
'Wilhoit': Wilhoit,
'NASA': NASA,
'NASAPolynomial': NASAPolynomial,
'ThermoData': ThermoData,
'np_array': numpy.array,
}
freq_data = None
if 'imaginary_frequency' in data:
freq_data = data['imaginary_frequency']
del data['imaginary_frequency']
if not data['is_ts']:
if 'smiles' in data:
data['species'] = Species(SMILES=data['smiles'])
elif 'adjacency_list' in data:
data['species'] = Species().fromAdjacencyList(data['adjacency_list'])
elif 'inchi' in data:
data['species'] = Species(InChI=data['inchi'])
else:
raise ValueError('Cannot load ArkaneSpecies from YAML file {0}. Either `smiles`, `adjacency_list`, or '
'InChI must be specified'.format(path))
# Finally, set the species label so that the special attributes are updated properly
data['species'].label = data['label']

self.make_object(data=data, class_dict=class_dict)
if freq_data is not None:
self.imaginary_frequency = ScalarQuantity()
self.imaginary_frequency.make_object(data=freq_data, class_dict=dict())
self.adjacency_list = data['adjacency_list'] if 'adjacency_list' in data else None
self.inchi = data['inchi'] if 'inchi' in data else None
self.smiles = data['smiles'] if 'smiles' in data else None
self.is_ts = data['is_ts'] if 'is_ts' in data else False
self.imaginary_frequency.make_object(data=freq_data, class_dict=class_dict)

if pdep and not self.is_ts and (self.transport_data is None or self.energy_transfer_model is None):
raise ValueError('Transport data and an energy transfer model must be given if pressure-dependent '
'calculations are requested. Check file {0}'.format(path))
Expand Down Expand Up @@ -347,7 +372,7 @@ def get_element_mass(input_element, isotope=None):
else:
# no specific isotope is required
if len(mass_list[0]) == 2:
# isotop weight is unavailable, use the first entry
# isotope weight is unavailable, use the first entry
mass = mass_list[0][1]
logging.warn("Assuming isotop {0} is representative of element {1}".format(mass_list[0][0], symbol))
else:
Expand Down
57 changes: 49 additions & 8 deletions arkane/commonTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@

import rmgpy
import rmgpy.constants as constants
from rmgpy.pdep.collision import SingleExponentialDown
from rmgpy.species import Species, TransitionState
from rmgpy.quantity import ScalarQuantity
from rmgpy.thermo import NASA
from rmgpy.thermo import NASA, ThermoData

from arkane import Arkane, input
from arkane.common import ArkaneSpecies, get_element_mass
Expand Down Expand Up @@ -248,9 +249,9 @@ def testSpeciesStatmech(self):
job.includeHinderedRotors = self.useHinderedRotors
job.applyBondEnergyCorrections = self.useBondCorrections
job.load()
self.assertTrue(isinstance(job.species.props['elementCounts'], dict))
self.assertEqual(job.species.props['elementCounts']['C'], 2)
self.assertEqual(job.species.props['elementCounts']['H'], 4)
self.assertTrue(isinstance(job.species.props['element_counts'], dict))
self.assertEqual(job.species.props['element_counts']['C'], 2)
self.assertEqual(job.species.props['element_counts']['H'], 4)

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

def test_load_yaml(self):
def test_create_and_load_yaml(self):
"""
Test properly loading the ArkaneSpecies object and respective sub-objects
"""
jobList = self.arkane.loadInputFile(self.load_input_path)
# Create YAML file by running Arkane
jobList = self.arkane.loadInputFile(self.dump_input_path)
for job in jobList:
job.execute(outputFile=self.load_output_file)
arkane_spc = jobList[0].arkane_species
job.execute(outputFile=self.dump_output_file)

# Load in newly created YAML file
arkane_spc_old = jobList[0].arkane_species
arkane_spc = ArkaneSpecies.__new__(ArkaneSpecies)
arkane_spc.load_yaml(path=os.path.join(self.dump_path, 'species', arkane_spc_old.label + '.yml'))

self.assertIsInstance(arkane_spc, ArkaneSpecies) # checks make_object
self.assertIsInstance(arkane_spc.molecular_weight, ScalarQuantity)
self.assertIsInstance(arkane_spc.thermo, NASA)
self.assertNotEqual(arkane_spc.author, '')
self.assertEqual(arkane_spc.inchi, 'InChI=1S/C2H6/c1-2/h1-2H3')
self.assertEqual(arkane_spc.inchi_key, 'OTMSDBZUPAUEDD-UHFFFAOYSA-N')
self.assertEqual(arkane_spc.smiles, 'CC')
self.assertTrue('8 H u0 p0 c0 {2,S}' in arkane_spc.adjacency_list)
self.assertEqual(arkane_spc.label, 'C2H6')
self.assertEqual(arkane_spc.frequency_scale_factor, 0.99*1.014) # checks float conversion
self.assertFalse(arkane_spc.use_bond_corrections)
self.assertAlmostEqual(arkane_spc.conformer.modes[2].frequencies.value_si[0], 830.38202, 4) # HarmonicOsc.
self.assertIsInstance(arkane_spc.energy_transfer_model, SingleExponentialDown)
self.assertFalse(arkane_spc.is_ts)
self.assertEqual(arkane_spc.level_of_theory, 'cbs-qb3')
self.assertIsInstance(arkane_spc.thermo_data, ThermoData)
self.assertTrue(arkane_spc.use_hindered_rotors)
self.assertTrue('C 7.54e-14 1.193e-13 5.52e-14' in arkane_spc.xyz)
self.assertIsInstance(arkane_spc.chemkin_thermo_string, str)

def test_load_existing_yaml(self):
"""
Test that existing Arkane YAML files can still be loaded
"""
# Load in YAML file
arkane_spc = ArkaneSpecies.__new__(ArkaneSpecies)
arkane_spc.load_yaml(path=os.path.join(self.load_path, 'C2H6.yml'))

self.assertIsInstance(arkane_spc, ArkaneSpecies) # checks make_object
self.assertIsInstance(arkane_spc.molecular_weight, ScalarQuantity)
self.assertIsInstance(arkane_spc.thermo, NASA)
self.assertNotEqual(arkane_spc.author, '')
self.assertEqual(arkane_spc.inchi, 'InChI=1S/C2H6/c1-2/h1-2H3')
self.assertEqual(arkane_spc.inchi_key, 'OTMSDBZUPAUEDD-UHFFFAOYSA-N')
self.assertEqual(arkane_spc.smiles, 'CC')
self.assertTrue('8 H u0 p0 c0 {2,S}' in arkane_spc.adjacency_list)
self.assertEqual(arkane_spc.label, 'C2H6')
self.assertEqual(arkane_spc.frequency_scale_factor, 0.99) # checks float conversion
self.assertFalse(arkane_spc.use_bond_corrections)
self.assertAlmostEqual(arkane_spc.conformer.modes[2].frequencies.value_si[0], 818.91718, 4) # HarmonicOsc.
self.assertIsInstance(arkane_spc.energy_transfer_model, SingleExponentialDown)
self.assertFalse(arkane_spc.is_ts)
self.assertTrue(arkane_spc.use_hindered_rotors)
self.assertTrue('C 7.54e-14 1.193e-13 5.52e-14' in arkane_spc.xyz)
self.assertIsInstance(arkane_spc.chemkin_thermo_string, str)

@classmethod
def tearDownClass(cls):
Expand Down
33 changes: 33 additions & 0 deletions arkane/encorr/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
initialize imports
"""

###############################################################################
# #
# RMG - Reaction Mechanism Generator #
# #
# Copyright (c) 2002-2019 Prof. William H. Green (whgreen@mit.edu), #
# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) #
# #
# Permission is hereby granted, free of charge, to any person obtaining a #
# copy of this software and associated documentation files (the 'Software'), #
# to deal in the Software without restriction, including without limitation #
# the rights to use, copy, modify, merge, publish, distribute, sublicense, #
# and/or sell copies of the Software, and to permit persons to whom the #
# Software is furnished to do so, subject to the following conditions: #
# #
# The above copyright notice and this permission notice shall be included in #
# all copies or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING #
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER #
# DEALINGS IN THE SOFTWARE. #
# #
###############################################################################
Loading

0 comments on commit af0ef48

Please sign in to comment.