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

Multi-Dimensional Rotors #1640

Merged
merged 34 commits into from
Aug 8, 2019
Merged

Multi-Dimensional Rotors #1640

merged 34 commits into from
Aug 8, 2019

Conversation

mjohnson541
Copy link
Contributor

This PR enables ND empirical and semi-empirical rotor calculations along with 2D quantum mechanical rotor calculations.

ND empirical and semi-empirical rotors rely on scipy integration and interpolation algorithms. Frequencies are estimated by finding the hessian of a polynomial fit around the origin point of the rotor scans.

This PR enables 2D dimensional coupled rotor calculations using the 2D-NS approximation within Arkane using the external software Q2DTor written by David Ferro Costas and Antonio Fernandez Ramos. It adds a wrapper class in Arkane for computing the statistical mechanical properties of 2D coupled rotors using Q2DTor and adds rotor processing for 2D coupled rotors.

Installing my fork of Q2DTor:

git clone https://github.com/mjohnson541/Q2DTor.git
git checkout arkane

add to your .bashrc or .bash_profile (as appropriate):
export Q2DTor=/.../Q2DTor/src/Q2DTor.py (replacing ... with appropriate absolute path)

I've added an example for calculating the thermo of CH2CHOOH. However the full example takes ~5-8 hours of time to run. The wrapper (HinderedRotor2D) automatically checks for the presence of the .evals output file from Q2DTor that contains the eigenvalues of the Hamiltonian. If it finds this file it automatically skips the calculations and uses the eigenvalues to compute statistical mechanical properties. To shorten the example I've added all of the Q2DTor output files to the example allowing it to find the .evals file and finish rapidly.

@alongd alongd self-requested a review July 11, 2019 18:38
@alongd
Copy link
Member

alongd commented Jul 11, 2019

@mjohnson541, a reminder to squash and rebase.

@mjohnson541
Copy link
Contributor Author

There's a reason I hadn't made a request for review on this one yet. There a tests issue that I need to resolve.

@mjohnson541
Copy link
Contributor Author

I'll try to have it ready soon.

@mjohnson541 mjohnson541 force-pushed the classicalrotors branch 2 times, most recently from 8f20ac1 to ec28610 Compare July 18, 2019 15:58
@mjohnson541
Copy link
Contributor Author

Ok, this should be ready for review!

@mjohnson541 mjohnson541 self-assigned this Jul 19, 2019
@mjohnson541
Copy link
Contributor Author

@alongd are you going to be able to review this?

@alongd
Copy link
Member

alongd commented Jul 29, 2019

Sure, it's just 1,400 files. I'm counting on the Hackathon...
I assume the comments from #1585 were addressed?
Meanwhile, do you mind rebasing?

@mjohnson541
Copy link
Contributor Author

I think I forgot those, I'll take a look tonight and get it setup by tomorrow.

@mjohnson541
Copy link
Contributor Author

Don't worry 99.9% of those files are Gaussian files

@codecov
Copy link

codecov bot commented Jul 29, 2019

Codecov Report

Merging #1640 into master will decrease coverage by 0.15%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1640      +/-   ##
==========================================
- Coverage   41.87%   41.71%   -0.16%     
==========================================
  Files         176      176              
  Lines       29369    29359      -10     
  Branches     6059     6053       -6     
==========================================
- Hits        12297    12246      -51     
- Misses      16192    16244      +52     
+ Partials      880      869      -11
Impacted Files Coverage Δ
rmgpy/tools/merge_models.py 14.28% <0%> (-32.63%) ⬇️
rmgpy/rmg/model.py 38.46% <0%> (-3.25%) ⬇️
rmgpy/data/kinetics/groups.py 15.15% <0%> (-0.26%) ⬇️
rmgpy/data/thermo.py 61.86% <0%> (-0.07%) ⬇️
rmgpy/reaction.py 0% <0%> (ø) ⬆️
rmgpy/quantity.py 0% <0%> (ø) ⬆️
rmgpy/molecule/molecule.py 0% <0%> (ø) ⬆️
rmgpy/data/kinetics/family.py 52.9% <0%> (+0.23%) ⬆️
rmgpy/rmg/react.py 87.03% <0%> (+0.24%) ⬆️
rmgpy/rmg/input.py 35.77% <0%> (+0.38%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 69122e6...2ae9005. Read the comment docs.

@codecov
Copy link

codecov bot commented Jul 29, 2019

Codecov Report

Merging #1640 into master will increase coverage by 0.22%.
The diff coverage is 59.51%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1640      +/-   ##
==========================================
+ Coverage   41.56%   41.78%   +0.22%     
==========================================
  Files         176      177       +1     
  Lines       29840    30207     +367     
  Branches     6192     6252      +60     
==========================================
+ Hits        12403    12622     +219     
- Misses      16529    16661     +132     
- Partials      908      924      +16
Impacted Files Coverage Δ
rmgpy/quantity.py 0% <0%> (ø) ⬆️
rmgpy/statmech/ndTorsions.py 59.67% <59.67%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 114bd34...912f7b7. Read the comment docs.

@mjohnson541 mjohnson541 force-pushed the classicalrotors branch 2 times, most recently from dcf0db8 to d79ae2f Compare July 29, 2019 23:12
@mjohnson541
Copy link
Contributor Author

This should be ready for review now.

Copy link
Member

@alongd alongd left a comment

Choose a reason for hiding this comment

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

Thanks for this PR!
Please see my comments below

rmgpy/statmech/conformer.pyx Show resolved Hide resolved
arkane/statmech.py Outdated Show resolved Hide resolved
@@ -1135,3 +1136,58 @@ def determine_rotor_symmetry(energies, label, pivots):
logging.info('Determined a symmetry number of {0} for rotor of species {1} between pivots {2}'
' based on the {3}.'.format(symmetry, label, pivots, reason))
return symmetry

class HinderedRotor2D(Mode):
Copy link
Member

Choose a reason for hiding this comment

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

Seems more natural to have this in rmgpy/statmech/torsion.pyx
We can think whether we want it to inherit from Torsion or not (and if not, drop a line explaining why)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I invested a lot of time trying to get this to work in torsion.pyx, but there's a circular import that occurs because HinderedRotor2D and HinderedRotorClassicalND unlike the other rotor functions both need quantum file reading related imports so I decided to locate them in statmech.py where this didn't create a circular import.

Copy link
Member

Choose a reason for hiding this comment

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

OK, let's try to make this move as we discussed offline

@@ -1135,3 +1136,58 @@ def determine_rotor_symmetry(energies, label, pivots):
logging.info('Determined a symmetry number of {0} for rotor of species {1} between pivots {2}'
' based on the {3}.'.format(symmetry, label, pivots, reason))
return symmetry

class HinderedRotor2D(Mode):
Copy link
Member

Choose a reason for hiding this comment

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

Do we have tests for this class?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added


def getTorsions(self):
"""
determine torsions, not entirely necessary for 2D-NS, but important for E2DT
Copy link
Member

Choose a reason for hiding this comment

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

please add (in parentheses?) the definitions of NS ans E2DT

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added

arkane/statmech.py Outdated Show resolved Hide resolved
@@ -1175,6 +1175,32 @@ def determine_rotor_symmetry(energies, label, pivots):
' based on the {3}.'.format(symmetry, label, pivots, reason))
return symmetry

def is_linear(coordinates):
Copy link
Member

Choose a reason for hiding this comment

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

We already had the is_linear function in Arkane. I think it got deleted somewhere in this PR, and from briefly looking at it the added function seems extremely similar if not identical. Please change the PR so the function doesn't get deleted and re-added

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We did, it got deleted in a prior PR and I had to recreate it after I rebased.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(It's deleted on master)

Copy link
Member

@alongd alongd Aug 5, 2019

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was incorrect, but I've squashed them so it shouldn't show up as deleted and created in a different commit

rmgpy/statmech/torsion.pyx Show resolved Hide resolved
@@ -55,6 +56,11 @@ def setUpClass(cls):
cls.base_path = os.path.join(os.path.dirname(os.path.dirname(rmgpy.__file__)), 'examples', 'arkane')
cls.failed = []
cls.example_types = ['species', 'reactions', 'explorer', 'networks']
ch2ooh_path = os.path.join(cls.base_path,'species','CH2CHOOH','CH2CHOOHscans')
Copy link
Member

Choose a reason for hiding this comment

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

space between arguments? (below as well)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

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 take a second look?
It's minor, but I don't think its resolved.
It should be os.path.join(cls.base_path, 'species', 'CH2CHOOH', 'CH2CHOOHscans'),
but I still see os.path.join(cls.base_path,'species','CH2CHOOH','CH2CHOOHscans').

same thing below, and possibly other places in this PR

arkane/mainTest.py Show resolved Hide resolved
@alongd alongd added Arkane Before Py3 Should be merged before Python 3 transition labels Aug 1, 2019
Copy link
Member

@alongd alongd left a comment

Choose a reason for hiding this comment

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

I went over just a couple of changes, but didn't see the changes in the code. Were the changes pushed? Am I not looking at it correctly? Let's resolve it offline and I'll continue reviewing. Thanks!

@@ -55,6 +56,11 @@ def setUpClass(cls):
cls.base_path = os.path.join(os.path.dirname(os.path.dirname(rmgpy.__file__)), 'examples', 'arkane')
cls.failed = []
cls.example_types = ['species', 'reactions', 'explorer', 'networks']
ch2ooh_path = os.path.join(cls.base_path,'species','CH2CHOOH','CH2CHOOHscans')
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 take a second look?
It's minor, but I don't think its resolved.
It should be os.path.join(cls.base_path, 'species', 'CH2CHOOH', 'CH2CHOOHscans'),
but I still see os.path.join(cls.base_path,'species','CH2CHOOH','CH2CHOOHscans').

same thing below, and possibly other places in this PR

elif pivots[1] in top:
pivot1 = pivots[1]
pivot2 = pivots[0]
else: raise Exception('Could not determine pivot atom.')
Copy link
Member

Choose a reason for hiding this comment

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

I still see else: raise Exception('Could not determine pivot atom.'), all in one line. Were the changes pushed?

@mjohnson541
Copy link
Contributor Author

Sorry I'll let you know once I've pushed. I haven't finished the documentation and then I need to pack everything into commits. I just wanted to check off things so I knew I fixed them.

@mjohnson541
Copy link
Contributor Author

Okay, I've pushed the changes!

@mjohnson541
Copy link
Contributor Author

It isn't packaged, so it can't be install with pip or conda. I can add it to the travis build though.

Copy link
Member

@alongd alongd left a comment

Choose a reason for hiding this comment

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

I added a few more comment

@@ -1135,3 +1136,58 @@ def determine_rotor_symmetry(energies, label, pivots):
logging.info('Determined a symmetry number of {0} for rotor of species {1} between pivots {2}'
' based on the {3}.'.format(symmetry, label, pivots, reason))
return symmetry

class HinderedRotor2D(Mode):
Copy link
Member

Choose a reason for hiding this comment

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

OK, let's try to make this move as we discussed offline

"""
use Q2DTor to generate a .ics file
"""
out = subprocess.check_call(['python2',os.environ['Q2DTor'],self.name,'--init'],
Copy link
Member

Choose a reason for hiding this comment

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

OK, let me know where to look once it's up (or is it already?)

@@ -1618,6 +1622,17 @@ def readScan(self):
Es.append(Es[j])
xyzs.append(xyzs[j])

q = len(phis)
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 double check the fix for the duplicate loops?
I still see two instances of

            for i in xrange(N):  # add the negative values to improve fit near 0.0
                for j in xrange(q):

at the same level

@@ -0,0 +1,74 @@
# Coordinates for Toluene in Input Orientation (angstroms):
Copy link
Member

Choose a reason for hiding this comment

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

let me know the status of this comment

@@ -405,7 +405,7 @@ def __str__(self):
uncertainty = '[{0}]'.format(','.join(uncertainty))

result = '{0}'.format(value)
if any(self.uncertainty != 0.0):
if (self.uncertainty>0).any():
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 teach me what this did and what it does now?
I'm used to the format if any([a, b, c]):, but here it looks like we're checking whether [a, b, c] > 0 instead of entry >0 for entry in [a, b, c]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Basically this gave me an error related to comparing an array with a value whenever it was actually called. I think it just never got called in normal operation until I was trying to log stuff. Essentially the line is suppose to display uncertainties if they aren't all zero, but it resulted in an error until I fixed it.

Copy link
Contributor

Choose a reason for hiding this comment

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

This seems odd to me. You're still comparing an array to a value, so it doesn't make sense why this would work any differently...

Copy link
Contributor Author

@mjohnson541 mjohnson541 Aug 6, 2019

Choose a reason for hiding this comment

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

You're right, but I can tell you for certain that the first one crashed everytime and the second one displays properly

@@ -262,6 +262,8 @@ cdef class Conformer(RMGObject):
N += 1
elif type(mode) == SphericalTopRotor:
N += 3
elif hasattr(mode,'dof'):
Copy link
Member

Choose a reason for hiding this comment

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

please add a space between mode and 'dof'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@mjohnson541
Copy link
Contributor Author

@alongd Here's the problem with moving I need to calculate Internal reduced moment of inertia at each point in HR multi D (this improves the accuracy of the calculation relative to Arkane's original HR software) However Arkane is designed to have this computed through the Conformer object (which makes sense), and the Conformer object imports torsion.pyx.

Essentially in order to make this possible I either need to write a file of independent code that duplicates a lot of Conformer functionality and then redesign how HR multi D gets conformer information and sends it to the independent code or Arkane needs redesigned.

…rtition functions

fit the partition function to a spline and generate first and second derivatives
for semiclassical correct using rotor frequencies
get the hessian by fitting a ND quadratic polynomial around the minimum
add omnia to conda channels list
add numdifftools to dependencies
unzip CH2CHOOH zip file if necessary before running tests
don't delete key directories for arkane test jobs
Copy link
Member

@alongd alongd left a comment

Choose a reason for hiding this comment

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

Thanks for this awesome contribution!

@alongd alongd merged commit fabc165 into master Aug 8, 2019
@alongd alongd deleted the classicalrotors branch August 8, 2019 00:32
@mliu49 mliu49 mentioned this pull request Dec 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Arkane Before Py3 Should be merged before Python 3 transition
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants