Skip to content

Commit

Permalink
Merge pull request #125 from ReactionMechanismGenerator/restart
Browse files Browse the repository at this point in the history
 Save conformer jobs in the restart file
  • Loading branch information
alongd committed May 1, 2019
2 parents 5b39b88 + e3216a4 commit 6738253
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 25 deletions.
55 changes: 34 additions & 21 deletions arc/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ class Scheduler(object):
`rmgdb` ``RMGDatabase`` The RMG database object
`allow_nonisomorphic_2d` ``bool`` Whether to optimize species even if they do not have a 3D conformer that is
isomorphic to the 2D graph representation
`memory` ``int`` The allocated job memory (1500 MB by default)
`job_types` ``dict`` A dictionary of job types to execute. Keys are job types, values are boolean
`bath_gas` ``str`` A bath gas. Currently used in OneDMin to calc L-J parameters.
`dont_gen_confs` ``list`` A list of species labels for which conformer jobs were loaded from a restart file,
and additional conformer generation should be avoided
`memory` ``int`` The allocated job memory (1500 MB by default)
`job_types` ``dict`` A dictionary of job types to execute. Keys are job types, values are boolean
`bath_gas` ``str`` A bath gas. Currently used in OneDMin to calc L-J parameters.
Allowed values are He, Ne, Ar, Kr, H2, N2, O2
======================= ========= ==================================================================================
Expand Down Expand Up @@ -133,6 +135,7 @@ def __init__(self, project, ess_settings, species_list, composite_method, confor
self.memory = memory
self.bath_gas = bath_gas
self.adaptive_levels = adaptive_levels
self.dont_gen_confs = list()
if self.restart_dict is not None:
self.output = self.restart_dict['output']
if 'running_jobs' in self.restart_dict:
Expand Down Expand Up @@ -554,18 +557,18 @@ def run_job(self, label, xyz, level_of_theory, job_type, fine=False, software=No
self.job_dict[label][job_type] = dict()
self.job_dict[label][job_type][job.job_name] = job
self.job_dict[label][job_type][job.job_name].run()
self.save_restart_dict()
else:
# Running a conformer job. Append differently to job_dict.
self.running_jobs[label].append('conformer{0}'.format(conformer)) # mark as a running job
self.job_dict[label]['conformers'][conformer] = job # save job object
self.job_dict[label]['conformers'][conformer].run() # run the job
self.save_restart_dict()
if job.server not in self.servers:
self.servers.append(job.server)

def end_job(self, job, label, job_name):
"""
A helper function for checking job status, saving in cvs file, and downloading output files.
A helper function for checking job status, saving in csv file, and downloading output files.
Returns ``True`` if job terminated successfully on the server, ``False`` otherwise
"""
try:
Expand Down Expand Up @@ -611,7 +614,7 @@ def run_conformer_jobs(self):
if not self.species_dict[label].is_ts and 'opt converged' not in self.output[label]['status'] \
and 'opt' not in self.job_dict[label] and 'composite' not in self.job_dict[label] \
and all([e is None for e in self.species_dict[label].conformer_energies]) \
and self.species_dict[label].number_of_atoms > 1:
and self.species_dict[label].number_of_atoms > 1 and label not in self.dont_gen_confs:
# This is not a TS, opt (/composite) did not converged nor running, and conformer energies were not set
self.save_conformers_file(label)
if self.species_dict[label].initial_xyz is None and self.species_dict[label].final_xyz is None \
Expand Down Expand Up @@ -1040,14 +1043,7 @@ def check_freq_job(self, label, job):
if job.job_status[1] == 'done':
if not os.path.isfile(job.local_path_to_output_file):
raise SchedulerError('Called check_freq_job with no output file')
ccparser = cclib.io.ccopen(str(job.local_path_to_output_file))
try:
data = ccparser.parse()
vibfreqs = data.vibfreqs
except AssertionError:
# In cclib/parser/qchemparser.py there's an assertion of `assert 'Beta MOs' in line`
# which sometimes fails (CClib issue https://github.com/cclib/cclib/issues/678)
vibfreqs = parser.parse_frequencies(path=str(job.local_path_to_output_file), software=job.software)
vibfreqs = parser.parse_frequencies(path=str(job.local_path_to_output_file), software=job.software)
freq_ok = self.check_negative_freq(label=label, job=job, vibfreqs=vibfreqs)
if not self.species_dict[label].is_ts and not freq_ok:
self.troubleshoot_negative_freq(label=label, job=job)
Expand Down Expand Up @@ -1751,7 +1747,10 @@ def restore_running_jobs(self):
if spc_label not in self.running_jobs:
self.running_jobs[spc_label] = list()
for job_description in jobs[spc_label]:
self.running_jobs[spc_label].append(job_description['job_name'])
if 'conformer' not in job_description or job_description['conformer'] < 0:
self.running_jobs[spc_label].append(job_description['job_name'])
else:
self.running_jobs[spc_label].append('conformer{0}'.format(job_description['conformer']))
for species in self.species_list:
if species.label == spc_label:
break
Expand All @@ -1776,16 +1775,28 @@ def restore_running_jobs(self):
if spc_label not in self.job_dict:
self.job_dict[spc_label] = dict()
if job_description['job_type'] not in self.job_dict[spc_label]:
self.job_dict[spc_label][job_description['job_type']] = dict()
self.job_dict[spc_label][job_description['job_type']][job_description['job_name']] = job
if 'conformer' not in job_description or job_description['conformer'] < 0:
self.job_dict[spc_label][job_description['job_type']] = dict()
elif 'conformers' not in self.job_dict[spc_label]:
self.job_dict[spc_label]['conformers'] = dict()
if 'conformer' not in job_description or job_description['conformer'] < 0:
self.job_dict[spc_label][job_description['job_type']][job_description['job_name']] = job
else:
self.job_dict[spc_label]['conformers'][int(job_description['conformer'])] = job
# don't generate additional conformers for this species
self.dont_gen_confs.append(spc_label)
self.servers_jobs_ids.append(job.job_id)
if self.job_dict:
content = 'Restarting ARC, tracking the following jobs spawned in a previous session:'
for spc_label in self.job_dict.keys():
content += '\n' + spc_label + ': '
for tob_type in self.job_dict[spc_label].keys():
for job_name in self.job_dict[spc_label][tob_type].keys():
content += job_name + ', '
for job_type in self.job_dict[spc_label].keys():
for job_name in self.job_dict[spc_label][job_type].keys():
if job_type != 'conformers':
content += job_name + ', '
else:
content += self.job_dict[spc_label][job_type][job_name].job_name\
+ ' (conformer' + str(job_name) + ')' + ', '
content += '\n\n'
logging.info(content)

Expand All @@ -1804,7 +1815,9 @@ def save_restart_dict(self):
if spc.label in self.running_jobs:
self.restart_dict['running_jobs'][spc.label] =\
[self.job_dict[spc.label][job_name.split('_')[0]][job_name].as_dict()
for job_name in self.running_jobs[spc.label] if 'conformer' not in job_name]
for job_name in self.running_jobs[spc.label] if 'conformer' not in job_name]\
+ [self.job_dict[spc.label]['conformers'][int(job_name.split('mer')[1])].as_dict()
for job_name in self.running_jobs[spc.label] if 'conformer' in job_name]
content = yaml.dump(data=self.restart_dict, encoding='utf-8', allow_unicode=True)
with open(self.restart_path, 'w') as f:
f.write(content)
Expand Down
4 changes: 2 additions & 2 deletions arc/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,11 @@
default_levels_of_theory = {'conformer': 'b3lyp/6-31+g(d,p)',
'ts_guesses': 'b3lyp/6-31+g(d,p)', # used for IRC as well
'opt': 'wb97xd/6-311++g(d,p)',
'freq': 'wb97xd/6-311++g(d,p)', # should be the same level as opt
'freq': 'wb97xd/6-311++g(d,p)', # should be the same level as opt (to calc freq at min E)
'scan': 'wb97xd/6-311++g(d,p)', # should be the same level as freq (to project out rotors)
'sp': 'ccsd(t)-f12/cc-pvtz-f12', # This should be a level for which BAC is available
# 'sp': 'b3lyp/6-311+g(3df,2p)',
'orbitals': 'b3lyp/6-311+g(d,p)', # save orbitals for visualization
'scan': 'b3lyp/6-311+g(d,p)',
'scan_for_composite': 'B3LYP/CBSB7', # This is the frequency level of the CBS-QB3 method
'freq_for_composite': 'B3LYP/CBSB7', # This is the frequency level of the CBS-QB3 method
}
Expand Down
2 changes: 1 addition & 1 deletion arc/species/species.py
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ def set_transport_data(self, lj_path, opt_path, bath_gas, opt_level, freq_path='
"""
original_comment = self.transport_data.comment
comment = 'L-J coefficients calculated by OneDMin using a DF-MP2/aug-cc-pVDZ potential energy surface ' \
'with {0} as the collider'.format(bath_gas)
'with {0} as the bath gas'.format(bath_gas)
epsilon, sigma = None, None
with open(lj_path, 'r') as f:
lines = f.readlines()
Expand Down
2 changes: 1 addition & 1 deletion arc/species/speciesTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ def test_set_transport_data(self):
self.assertEqual(self.spc1.transport_data.rotrelaxcollnum, 2)
self.assertEqual(self.spc1.transport_data.comment, 'L-J coefficients calculated by OneDMin using a '
'DF-MP2/aug-cc-pVDZ potential energy surface with N2 as '
'the collider; Dipole moment was calculated at the CBS-QB3 '
'the bath gas; Dipole moment was calculated at the CBS-QB3 '
'level of theory; Polarizability was calculated at the '
'CBS-QB3 level of theory; Rotational Relaxation Collision '
'Number was not determined, default value is 2')
Expand Down

0 comments on commit 6738253

Please sign in to comment.