Skip to content

Commit

Permalink
Merge pull request #56 from ReactionMechanismGenerator/ts
Browse files Browse the repository at this point in the history
Added reactions to ARC
  • Loading branch information
alongd committed Feb 14, 2019
2 parents 1a6f02f + bee832e commit 95c9b29
Show file tree
Hide file tree
Showing 43 changed files with 15,170 additions and 4,736 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ scratch/

# csv database
*.csv

# iPython files
*.ipynb_*
17 changes: 14 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,22 @@ before_install:
cache: pip
install:
- cd ARC
- pip install -r requirements.txt
- conda install -y -c rmg rmg
- conda install -y -c rdkit rdkit
- conda env create -q -f environment.yml
- source activate arc_env
- cd ..
- git clone https://github.com/ReactionMechanismGenerator/RMG-Py
- cd RMG-Py
- export PYTHONPATH=$PYTHONPATH:$(pwd)
- make
- cd ..
- git clone https://github.com/ReactionMechanismGenerator/RMG-database
- git clone https://github.com/alongd/AutoTST
- cd AutoTST
- export PYTHONPATH=$PYTHONPATH:$(pwd)
- cd ..
- conda install -y -c conda-forge codecov
- conda list
- cd ARC

script:
- make test
Expand Down
41 changes: 20 additions & 21 deletions arc/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,60 @@

class InputError(Exception):
"""
An exception raised when parsing an input file for any module.
Pass a string describing the error.
An exception raised when parsing an input file for any module
"""
pass

class OutputError(Exception):
"""
This exception is raised whenever an error occurs while saving output
information. Pass a string describing the circumstances of the exceptional
behavior.
This exception is raised whenever an error occurs while saving output information
"""
pass

class SettingsError(Exception):
"""
An exception raised when dealing with settings.
An exception raised when dealing with settings
"""
pass

class SpeciesError(Exception):
"""
An exception class for exceptional behavior that occurs while working with
chemical species. Pass a string describing the circumstances that caused the
exceptional behavior.
An exception class for exceptional behavior that occurs while working with chemical species
"""
pass

class TSError(Exception):
"""
An exception class for exceptional behavior that occurs while working with transition states
"""
pass

class ReactionError(Exception):
"""
An exception class for exceptional behavior that occurs while working with reactions
"""
pass

class RotorError(Exception):
"""
An exception class for exceptional behavior that occurs while working with
chemical species. Pass a string describing the circumstances that caused the
exceptional behavior.
An exception class for exceptional behavior that occurs while working with rotors
"""
pass

class SchedulerError(Exception):
"""
An exception class for exceptional behavior that occurs while working with
chemical species. Pass a string describing the circumstances that caused the
exceptional behavior.
An exception class for exceptional behavior that occurs while working with the scheduler
"""
pass

class JobError(Exception):
"""
An exception class for exceptional behavior that occurs while working with
chemical species. Pass a string describing the circumstances that caused the
exceptional behavior.
An exception class for exceptional behavior that occurs while working with jobs
"""
pass

class ServerError(Exception):
"""
An exception class for exceptional behavior that occurs while working with
chemical species. Pass a string describing the circumstances that caused the
exceptional behavior.
An exception class for exceptional behavior that occurs while working with servers
"""
pass
8 changes: 4 additions & 4 deletions arc/job/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@
'scf=(tight,direct) int=finegrid irc=(rcfc,forward,maxpoints=100,stepsize=10) geom=check' for irc f
'scf=(tight,direct) int=finegrid irc=(rcfc,reverse,maxpoints=100,stepsize=10) geom=check' for irc r
scan: '\nD 3 1 5 8 S 36 10.000000' (with the line break)
restricted: '' or 'u' or restricted / unrestricted
restricted: '' or 'u' for restricted / unrestricted
qchem:
job_type_1: 'opt', 'ts', 'sp'
job_type_2: 'freq'.
fine: '\n GEOM_OPT_TOL_GRADIENT 15\n GEOM_OPT_TOL_DISPLACEMENT 60\n GEOM_OPT_TOL_ENERGY 5'
restricted: 'false' or 'true' or restricted / unrestricted
fine: '\n GEOM_OPT_TOL_GRADIENT 15\n GEOM_OPT_TOL_DISPLACEMENT 60\n GEOM_OPT_TOL_ENERGY 5\n XC_GRID SG-3'
restricted: 'false' or 'true' for restricted / unrestricted
"""

input_files = {
'gaussian': """%chk=check.chk
%mem={memory}mb
%nproc=8
# {job_type_1} {restricted}{method}{slash}{basis} {job_type_2} {fine} {trsh}
#P {job_type_1} {restricted}{method}{slash}{basis} {job_type_2} {fine} {trsh}
name
Expand Down
29 changes: 18 additions & 11 deletions arc/job/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ def __init__(self, project, settings, species_name, xyz, job_type, level_of_theo
self.ess_trsh_methods = ess_trsh_methods if ess_trsh_methods is not None else list()
self.trsh = trsh
self.initial_trsh = initial_trsh if initial_trsh is not None else dict()
job_types = ['conformer', 'opt', 'freq', 'optfreq', 'sp', 'composite', 'scan', 'gsm', 'irc']
job_types = ['conformer', 'opt', 'freq', 'optfreq', 'sp', 'composite', 'scan', 'gsm', 'irc', 'ts_guess']
# the 'conformer' job type is identical to 'opt', but we differentiate them to be identifiable in Scheduler
if job_type not in job_types:
raise ValueError("Job type {0} not understood. Must be on of the following: {1}".format(
raise ValueError("Job type {0} not understood. Must be one of the following:\n{1}".format(
job_type, job_types))
self.job_type = job_type
if self.job_num < 0:
Expand Down Expand Up @@ -134,6 +134,11 @@ def __init__(self, project, settings, species_name, xyz, job_type, level_of_theo
self.software = 'qchem'
elif self.settings['molpro']:
self.software = 'molpro'
elif 'wb97xd' in self.method:
if not self.settings['gaussian']:
raise JobError('Could not find the Gaussian software to run {0}/{1}'.format(
self.method, self.basis_set))
self.software = 'gaussian'
elif 'b97' in self.method or 'm06-2x' in self.method or 'def2' in self.basis_set:
if not self.settings['qchem']:
raise JobError('Could not find the QChem software to run {0}/{1}'.format(
Expand Down Expand Up @@ -318,7 +323,6 @@ def write_input_file(self):
Write a software-specific job-specific input file.
Saves the file locally and also uploads it to the server.
"""

if self.initial_trsh and not self.trsh:
# use the default trshs defined by the user in the initial_trsh dictionary
if self.software in self.initial_trsh:
Expand Down Expand Up @@ -383,6 +387,11 @@ def write_input_file(self):
job_type_1 = 'opt'
if self.fine:
fine = '\n GEOM_OPT_TOL_GRADIENT 15\n GEOM_OPT_TOL_DISPLACEMENT 60\n GEOM_OPT_TOL_ENERGY 5'
if 'b' in self.level_of_theory:
# Try to capture DFT levels (containing the letter 'b'?), and det a fine DFT grid
# See 4.4.5.2 Standard Quadrature Grids, S in
# http://www.q-chem.com/qchem-website/manual/qchem50_manual/sect-DFT.html
fine += '\n XC_GRID 3'
elif self.software == 'molpro':
if self.is_ts:
job_type_1 = "\noptg,root=2,method=qsd,readhess,savexyz='geometry.xyz'"
Expand Down Expand Up @@ -484,7 +493,7 @@ def write_input_file(self):
if self.software != 'molpro':
raise JobError('Can only run MRCI on Molpro, not {0}'.format(self.software))
if self.occ > 16:
raise JobError('Will not excecute an MRCI calculation with more than 16 occupied orbitals.'
raise JobError('Will not execute an MRCI calculation with more than 16 occupied orbitals.'
'Selective occ, closed, core, frozen keyword still not implemented.')
else:
try:
Expand Down Expand Up @@ -639,11 +648,6 @@ def _check_job_ess_status(self):
for line in lines[::-1]:
if 'Thank you very much for using Q-Chem' in line:
done = True
elif 'opt' in self.job_type or 'conformer' in self.job_type or 'ts' in self.job_type:
if 'MAXIMUM OPTIMIZATION CYCLES REACHED' in line:
return 'errored: unconverged, max opt cycles reached'
elif 'OPTIMIZATION CONVERGED' in line and done: # `done` should already be assigned
return 'done'
elif 'SCF failed' in line:
return 'errored: {0}'.format(line)
elif 'error' in line and 'DIIS' not in line:
Expand All @@ -653,6 +657,11 @@ def _check_job_ess_status(self):
elif 'Invalid charge/multiplicity combination' in line:
raise SpeciesError('The multiplicity and charge combination for species {0} are wrong.'.format(
self.species_name))
if 'opt' in self.job_type or 'conformer' in self.job_type or 'ts' in self.job_type:
if 'MAXIMUM OPTIMIZATION CYCLES REACHED' in line:
return 'errored: unconverged, max opt cycles reached'
elif 'OPTIMIZATION CONVERGED' in line and done: # `done` should already be assigned
return 'done'
if done:
return 'done'
else:
Expand All @@ -661,7 +670,6 @@ def _check_job_ess_status(self):
else:
return 'errored: Unknown reason'
elif self.software == 'molpro':
prev_line = ''
for line in lines[::-1]:
if 'molpro calculation terminated' in line.lower()\
or 'variable memory released' in line.lower():
Expand All @@ -677,7 +685,6 @@ def _check_job_ess_status(self):
# the request was for real words`
# add_mem = (float(line.split()[-2]) - float(prev_line.split()[0])) / 1e6
return 'errored: additional memory (mW) required: {0}'.format(float(line.split()[-2]) / 1e6)
prev_line = line
for line in lines[::-1]:
if 'the problem occurs' in line:
return 'errored: ' + line
Expand Down
64 changes: 64 additions & 0 deletions arc/job/jobTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
This module contains unit tests of the arc.job.job module
"""

from __future__ import (absolute_import, division, print_function, unicode_literals)
import unittest
import os

from arc.job.job import Job
from arc.settings import arc_path

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


class TestJob(unittest.TestCase):
"""
Contains unit tests for the Job class
"""

@classmethod
def setUpClass(cls):
"""
A method that is run before all unit tests in this class.
"""
cls.maxDiff = None
settings = {'gaussian': 'server1', 'molpro': 'server2', 'qchem': 'server1', 'ssh': False}
cls.job1 = Job(project='project_test', settings=settings, species_name='tst_spc', xyz='C 0.0 0.0 0.0',
job_type='opt', level_of_theory='b3lyp/6-31+g(d)', multiplicity=1,
project_directory=os.path.join(arc_path, 'Projects', 'project_test'), fine=True, job_num=100)

def test_as_dict(self):
"""Test Job.as_dict()"""
job_dict = self.job1.as_dict()
dt = job_dict['date_time']
expected_dict = {u'date_time': dt,
u'ess_trsh_methods': [],
u'fine': True,
u'job_id': 0,
u'job_name': u'opt_a100',
u'job_num': 100,
u'job_server_name': u'a100',
u'job_status': [u'initializing', u'initializing'],
u'job_type': u'opt',
u'level_of_theory': u'b3lyp/6-31+g(d)',
u'memory': 1500,
u'occ': None,
u'pivots': [],
u'project_directory': os.path.join(arc_path, 'Projects', 'project_test'),
u'run_time': u'',
u'scan': u'',
u'server': None,
u'shift': u'',
u'trsh': u'',
u'xyz': u'C 0.0 0.0 0.0'}
self.assertEqual(job_dict, expected_dict)


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

if __name__ == '__main__':
unittest.main(testRunner=unittest.TextTestRunner(verbosity=2))

0 comments on commit 95c9b29

Please sign in to comment.