Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Determine the rotor symmetry number from the potential scan #1526

Merged
merged 6 commits into from
Jan 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 4 additions & 22 deletions arkane/commonTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ def test_check_conformer_energy(self):
"""
test the check_conformer_energy function with an list of energies.
"""
Vlist = [-272.2779012225, -272.2774933703, -272.2768397635, -272.2778432059, -272.278645477, -272.2789602654,
v_list = [-272.2779012225, -272.2774933703, -272.2768397635, -272.2778432059, -272.278645477, -272.2789602654,
-272.2788749196, -272.278496709, -272.2779350675, -272.2777008843, -272.2777167286, -272.2780937643,
-272.2784838846, -272.2788050464, -272.2787865352, -272.2785091607, -272.2779977452, -272.2777957743,
-272.2779134906, -272.2781827547, -272.278443339, -272.2788244214, -272.2787748749]
Vlist = numpy.array(Vlist, numpy.float64)
Vdiff = (Vlist[0] - numpy.min(Vlist)) * constants.E_h * constants.Na / 1000
self.assertAlmostEqual(Vdiff / 2.7805169838282797, 1, 5)
v_list = numpy.array(v_list, numpy.float64)
v_diff = (v_list[0] - numpy.min(v_list)) * constants.E_h * constants.Na / 1000
self.assertAlmostEqual(v_diff / 2.7805169838282797, 1, 5)


class TestArkaneJob(unittest.TestCase):
Expand Down Expand Up @@ -270,24 +270,6 @@ def testTransitionStateStatmech(self):
job.load()


class TestStatmech(unittest.TestCase):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move this change to the next commit where you add statmechTest.py? The rest of this commit can probably be combined with one of your earlier syntax commits as well.

"""
Contains unit tests of statmech.py
"""
@classmethod
def setUp(self):
arkane = Arkane()
self.job_list = arkane.loadInputFile(os.path.join(os.path.dirname(os.path.abspath(__file__)),
'data', 'Benzyl', 'input.py'))

def test_gaussian_log_file_error(self):
"""Test that the proper error is raised if gaussian geometry and frequency file paths are the same"""
job = self.job_list[-2]
self.assertTrue(isinstance(job, StatMechJob))
with self.assertRaises(InputError):
job.load()


class TestGetMass(unittest.TestCase):
"""
Contains unit tests of common.py
Expand Down
74,462 changes: 74,462 additions & 0 deletions arkane/data/NCC_CRotor.out

Large diffs are not rendered by default.

80,771 changes: 80,771 additions & 0 deletions arkane/data/NCC_NRotor.out

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion arkane/gaussian.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ def loadScanEnergies(self):
check_conformer_energy(Vlist, self.path)

# Adjust energies to be relative to minimum energy conformer
# Also convert units from Hartree/particle to kJ/mol
# Also convert units from Hartree/particle to J/mol
Vlist -= numpy.min(Vlist)
Vlist *= constants.E_h * constants.Na

Expand Down
277 changes: 185 additions & 92 deletions arkane/statmech.py

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions arkane/statmechTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

###############################################################################
# #
# RMG - Reaction Mechanism Generator #
# #
# Copyright (c) 2002-2018 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. #
# #
###############################################################################

"""
This script contains unit tests of the :mod:`arkane.main` module.
"""

import unittest
import os

from rmgpy.exceptions import InputError

from arkane import Arkane
from arkane.statmech import StatMechJob, determine_rotor_symmetry
from arkane.qchem import QChemLog

################################################################################


class TestStatmech(unittest.TestCase):
"""
Contains unit tests of the StatmechJob class.
"""
@classmethod
def setUp(self):
arkane = Arkane()
self.job_list = arkane.loadInputFile(os.path.join(os.path.dirname(os.path.abspath(__file__)),
'data', 'Benzyl', 'input.py'))

def test_gaussian_log_file_error(self):
"""Test that the proper error is raised if gaussian geometry and frequency file paths are not the same"""
job = self.job_list[-2]
self.assertTrue(isinstance(job, StatMechJob))
with self.assertRaises(InputError):
job.load()

def test_rotor_symmetry_determination(self):
"""
Test that the correct symmetry number is determined for rotor potential scans.
"""
path1 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'NCC_NRotor.out')
path2 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'NCC_CRotor.out')
scan_log1 = QChemLog(path1)
scan_log2 = QChemLog(path2)
v_list1, angle = scan_log1.loadScanEnergies()
v_list2, angle = scan_log2.loadScanEnergies()
symmetry1 = determine_rotor_symmetry(energies=v_list1, label='NCC', pivots=[])
symmetry2 = determine_rotor_symmetry(energies=v_list2, label='NCC', pivots=[])
self.assertEqual(symmetry1, 1)
self.assertEqual(symmetry2, 3)


if __name__ == '__main__':
unittest.main(testRunner=unittest.TextTestRunner(verbosity=2))
6 changes: 4 additions & 2 deletions documentation/source/users/arkane/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,10 @@ scan in the following format::

The ``Energy`` can be in units of ``kJ/mol``, ``J/mol``, ``cal/mol``, ``kcal/mol``, ``cm^-1`` or ``hartree``.

The ``symmetry`` parameter will usually equal either 1, 2 or 3. Below are examples of internal rotor scans with these
commonly encountered symmetry numbers. First, ``symmetry = 3``:
The ``symmetry`` parameter will usually equal either 1, 2 or 3. It could be determined automatically by Arkane
(by simply not specifying it altogether), however it is always better to explicitly specify it if it is known. If it is
determined by Arkane, the log file will specify the determined value and what it was based on. Below are examples of
internal rotor scans with these commonly encountered symmetry numbers. First, ``symmetry = 3``:

.. image:: symmetry_3_example.png

Expand Down
6 changes: 4 additions & 2 deletions documentation/source/users/arkane/input_pdep.rst
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,10 @@ scan in the following format::

The ``Energy`` can be in units of ``kJ/mol``, ``J/mol``, ``cal/mol``, ``kcal/mol``, ``cm^-1`` or ``hartree``.

The ``symmetry`` parameter will usually equal either 1, 2 or 3. Below are examples of internal rotor scans with these
commonly encountered symmetry numbers. First, ``symmetry = 3``:
The ``symmetry`` parameter will usually equal either 1, 2 or 3. It could be determined automatically by Arkane
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way in .rst files to add a section of text from another file? That why, future updates to this in arkane/input.rst will automatically update the same section in input_pdep.rst. I am not sure if this is possible, but I will do some digging to find out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, I don't know

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears to be possible with the .. include :: statement, but it involves moving the text to another file. I am not sure if it is worth doing then, as it will clutter the documentation source files a little bit.

Copy link
Member Author

@alongd alongd Jan 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave it as is for now, I think we should change the pdep doc of Arkane to only include pdep stuff and avoid this repetition.

(by simply not specifying it altogether), however it is always better to explicitly specify it if it is known. If it is
determined by Arkane, the log file will specify the determined value and what it was based on. Below are examples of
internal rotor scans with these commonly encountered symmetry numbers. First, ``symmetry = 3``:

.. image:: symmetry_3_example.png

Expand Down
4 changes: 1 addition & 3 deletions examples/arkane/species/Benzyl/benzyl.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,4 @@

frequencies = Log('BenzylFreq.log')

rotors = [
HinderedRotor(scanLog=Log('BenzylRot1.log'), pivots=[12,4], top=[12,13,14], symmetry=2, fit='best'),
]
rotors = [HinderedRotor(scanLog=Log('BenzylRot1.log'), pivots=[12,4], top=[12,13,14])]
13 changes: 7 additions & 6 deletions examples/arkane/species/C2H5/ethyl.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@
'Klip_2': -78.98344186,
}

geometry = Log('ethyl_cbsqb3.log')
geometry = Log('ethyl_b3lyp.log')

frequencies = Log('ethyl_cbsqb3.log')
frequencies = Log('ethyl_b3lyp.log')

"""pivot are the two atoms that are attached to the rotor
top contains the atoms that are being rotated including one of the atoms from pivots
symmetry is the symmetry number of the scan
fit is fit of the scan data. It defaults to 'best', but can also be assigned as 'cosine' or 'fourier'"""
rotors = [
HinderedRotor(scanLog=Log('ethyl_scan_72.log'), pivots=[1,2], top=[1,3,4], symmetry=6, fit='best')
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth doing the same thing to examples/arkane/species/Toluene_Hindered_Rotor?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to leave one example in with the explicit symmetry number (although it's well documented) for users who would like to specify it. But I'm open to other thoughts.

fit is fit of the scan data. It defaults to 'best', but can also be assigned as 'cosine' or 'fourier'
Principally, the rotor symmetry can be automatically determined by Arkane, but could also be given by the user
(then the user's input overrides Arkane's determination):
rotors = [HinderedRotor(scanLog=Log('ethyl_scan_72.log'), pivots=[1,2], top=[1,3,4], symmetry=6, fit='best')]"""
rotors = [HinderedRotor(scanLog=Log('ethyl_scan_72.log'), pivots=[1,2], top=[1,3,4])]
1 change: 0 additions & 1 deletion examples/arkane/species/C2H5/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@

species('C2H5', 'ethyl.py')

statmech('C2H5')
thermo('C2H5', 'Wilhoit')
9 changes: 5 additions & 4 deletions examples/arkane/species/C2H6/C2H6.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"""pivot are the two atoms that are attached to the rotor
top contains the atoms that are being rotated including one of the atoms from pivots
symmetry is the symmetry number of the scan
fit is fit of the scan data. It defaults to 'best', but can also be assigned as 'cosine' or 'fourier'"""
rotors = [
HinderedRotor(scanLog=Log('ethane_scan_1.log'), pivots=[1,5], top=[1,2,3,4], symmetry=3, fit='best'),
]
fit is fit of the scan data. It defaults to 'best', but can also be assigned as 'cosine' or 'fourier'
Principally, the rotor symmetry can be automatically determined by Arkane, but could also be given by the user
(then the user's input overrides Arkane's determination):
rotors = [HinderedRotor(scanLog=Log('ethane_scan_1.log'), pivots=[1,5], top=[1,2,3,4], symmetry=3, fit='best')]"""
rotors = [HinderedRotor(scanLog=Log('ethane_scan_1.log'), pivots=[1,5], top=[1,2,3,4], fit='best')]