Skip to content

Commit fe3bf83

Browse files
committed
scheduler.py multi_species termination process
f! scheduler fixup! scheduler.py issue2 fixup! scheduler.py issue3 f! scheduler fixup! scheduler.py issue5 fixup! scheduler.py issue6 fixup! scheduler.py issue7 fixup! scheduler.py issue7.1 fixup! scheduler.py issue7.2 fixup! scheduler.py issue7.3 f! scheduler Define a new method "post_opt_geo_work" for processing
1 parent 25295b8 commit fe3bf83

File tree

1 file changed

+46
-57
lines changed

1 file changed

+46
-57
lines changed

arc/scheduler.py

+46-57
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,10 @@ def __init__(self,
422422
# conformers weren't asked for, assign initial_xyz
423423
species.initial_xyz = species.conformers[0]
424424
if species.label not in self.running_jobs:
425-
self.running_jobs[species.label] = list() # initialize before running the first job
425+
if not species.multi_species:
426+
self.running_jobs[species.label] = list()
427+
else:
428+
self.running_jobs[species.multi_species] = list()
426429
if self.output[species.label]['convergence']:
427430
continue
428431
if species.is_monoatomic():
@@ -523,7 +526,7 @@ def schedule_jobs(self):
523526
while self.running_jobs != {}:
524527
self.timer = True
525528
for label in self.unique_species_labels:
526-
if self.output[label]['convergence'] is False:
529+
if label in self.output and self.output[label]['convergence'] is False:
527530
# Skip unconverged species.
528531
if label in self.running_jobs:
529532
del self.running_jobs[label]
@@ -775,7 +778,7 @@ def run_job(self,
775778
max_job_time = max_job_time or self.max_job_time # if it's None, set to default
776779
ess_trsh_methods = ess_trsh_methods if ess_trsh_methods is not None else list()
777780
species = None
778-
if isinstance(label, str):
781+
if isinstance(label, str) and label in self.output:
779782
species = self.species_dict[label]
780783
elif isinstance(label, list):
781784
species = [spc for spc in self.species_list if spc.label in label]
@@ -976,7 +979,7 @@ def end_job(self, job: 'JobAdapter',
976979
os.makedirs(r_path)
977980
shutil.copyfile(src=check_path, dst=os.path.join(r_path, 'directed_rotor_check.chk'))
978981
self.species_dict[label].checkfile = os.path.join(r_path, 'directed_rotor_check.chk')
979-
else:
982+
elif label in self.output:
980983
self.species_dict[label].checkfile = check_path
981984
if job.job_type == 'scan' or job.directed_scan_type == 'ess':
982985
for rotors_dict in self.species_dict[label].rotors_dict.values():
@@ -1028,10 +1031,9 @@ def run_conformer_jobs(self, labels: Optional[List[str]] = None):
10281031
10291032
Args:
10301033
labels (list): Labels of specific species to run conformer jobs for.
1031-
If ``None``, conformer jobs will be spawned for all species corresponding to labels in
1032-
self.unique_species_labels.
1034+
If ``None``, conformer jobs will be spawned for all species in self.species_list.
10331035
"""
1034-
labels_to_consider = labels if labels is not None else self.unique_species_labels
1036+
labels_to_consider = labels if labels is not None else [spc.label for spc in self.species_list]
10351037
log_info_printed = False
10361038
for label in labels_to_consider:
10371039
if not self.species_dict[label].is_ts and not self.output[label]['job_types']['opt'] \
@@ -1427,12 +1429,12 @@ def spawn_post_opt_jobs(self,
14271429
return None
14281430

14291431
# Spawn IRC if requested and if relevant.
1430-
if self.job_types['irc'] and self.species_dict[label].is_ts:
1432+
if label in self.output and self.job_types['irc'] and self.species_dict[label].is_ts:
14311433
self.run_irc_job(label=label, irc_direction='forward')
14321434
self.run_irc_job(label=label, irc_direction='reverse')
14331435

14341436
# Spawn freq (or check it if this is a composite job) for polyatomic molecules.
1435-
if self.species_dict[label].number_of_atoms > 1:
1437+
if label in self.output and self.species_dict[label].number_of_atoms > 1:
14361438
if 'freq' not in job_name and self.job_types['freq']:
14371439
# This is either an opt or a composite job (not an optfreq job), spawn freq.
14381440
self.run_freq_job(label)
@@ -1446,7 +1448,7 @@ def spawn_post_opt_jobs(self,
14461448

14471449
# Perceive the Molecule from xyz.
14481450
# Useful for TS species where xyz might not be given at the outset to perceive a .mol attribute.
1449-
if self.species_dict[label].mol is None:
1451+
if label in self.output and self.species_dict[label].mol is None:
14501452
self.species_dict[label].mol_from_xyz()
14511453

14521454
# Spawn scan jobs.
@@ -1465,11 +1467,11 @@ def spawn_post_opt_jobs(self,
14651467
self.run_orbitals_job(label)
14661468

14671469
# Spawn onedmin job.
1468-
if self.job_types['onedmin'] and not self.species_dict[label].is_ts:
1470+
if label in self.output and self.job_types['onedmin'] and not self.species_dict[label].is_ts:
14691471
self.run_onedmin_job(label)
14701472

14711473
# Spawn bde jobs.
1472-
if self.job_types['bde'] and self.species_dict[label].bdes is not None:
1474+
if label in self.output and self.job_types['bde'] and self.species_dict[label].bdes is not None:
14731475
bde_species_list = self.species_dict[label].scissors()
14741476
for bde_species in bde_species_list:
14751477
if bde_species.label != 'H':
@@ -1493,7 +1495,7 @@ def spawn_post_opt_jobs(self,
14931495
if species.number_of_atoms > 1])
14941496

14951497
# Check whether any reaction was waiting for this species to spawn TS search jobs.
1496-
if not self.species_dict[label].is_ts:
1498+
if label in self.output and not self.species_dict[label].is_ts:
14971499
self.spawn_ts_jobs()
14981500

14991501
def spawn_ts_jobs(self):
@@ -2257,11 +2259,11 @@ def parse_opt_geo(self,
22572259
if job.job_status[1]['status'] == 'done':
22582260
multi_species = any(spc.multi_species == label for spc in self.species_list)
22592261
species_labels = [spc.label for spc in self.species_list if spc.multi_species == label]
2260-
if label in self.species_dict.keys():
2261-
opt_xyz = parser.parse_xyz_from_file(path=job.local_path_to_xyz or job.local_path_to_output_file)
2262-
elif multi_species:
2263-
opt_xyz_dict = parser.parse_multi_species_xyz_from_file(path=job.local_path_to_xyz or job.local_path_to_output_file,
2264-
species_name_list=species_labels)
2262+
opt_xyz = parser.parse_xyz_from_file(path=job.local_path_to_xyz or job.local_path_to_output_file) \
2263+
if label in self.species_dict.keys() else dict()
2264+
opt_xyz_dict = parser.parse_multi_species_xyz_from_file(path=job.local_path_to_xyz or job.local_path_to_output_file,
2265+
species_name_list=species_labels) \
2266+
if multi_species else list()
22652267

22662268
if not job.fine and self.job_types['fine'] \
22672269
and not job.level.method_type == 'wavefunction' \
@@ -2275,47 +2277,22 @@ def parse_opt_geo(self,
22752277
else:
22762278
self.species_dict[label].initial_xyz = opt_xyz
22772279
self.run_job(label=species_labels if multi_species else label,
2278-
xyz=opt_xyz if not multi_species else None,
2279-
species=None if not multi_species else [s for s in self.species_list if s.multi_species == label],
2280-
level_of_theory=job.level,
2281-
job_type='opt',
2282-
fine=True,
2283-
)
2280+
xyz=opt_xyz if not multi_species else None,
2281+
level_of_theory=job.level,
2282+
job_type='opt',
2283+
fine=True,
2284+
)
22842285
else:
22852286
success = True
22862287
if multi_species:
22872288
for spc in self.species_list:
22882289
if spc.multi_species == label:
22892290
# spc.final_xyz = opt_xyz_dict[spc.label]
2290-
self.species_dict[spc.label].final_xyz = opt_xyz
2291-
self.output[spc.label]['job_types']['opt'] = True
2292-
if self.job_types['fine']:
2293-
self.output[spc.label]['job_types']['fine'] = True
2294-
self.species_dict[spc.label].opt_level = self.opt_level.simple()
2295-
plotter.save_geo(species=self.species_dict[spc.label], project_directory=self.project_directory)
2296-
if self.species_dict[spc.label].is_ts:
2297-
rxn_str = f' of reaction {self.species_dict[spc.label].rxn_label}' \
2298-
if self.species_dict[spc.label].rxn_label is not None else ''
2299-
else:
2300-
rxn_str = ''
2301-
logger.info(f'\nOptimized geometry for {spc.label}{rxn_str} at {job.level.simple()}:\n'
2302-
f'{xyz_to_str(self.species_dict[spc.label].final_xyz)}\n')
2303-
self.output[spc.label]['paths']['geo'] = job.local_path_to_output_file # will be overwritten with freq
2291+
self.species_dict[spc.label].final_xyz = opt_xyz_dict[spc.label]
2292+
self.post_opt_geo_work(spc.label, job)
23042293
else:
23052294
self.species_dict[label].final_xyz = opt_xyz
2306-
self.output[label]['job_types']['opt'] = True
2307-
if self.job_types['fine']:
2308-
self.output[label]['job_types']['fine'] = True
2309-
self.species_dict[label].opt_level = self.opt_level.simple()
2310-
plotter.save_geo(species=self.species_dict[label], project_directory=self.project_directory)
2311-
if self.species_dict[label].is_ts:
2312-
rxn_str = f' of reaction {self.species_dict[label].rxn_label}' \
2313-
if self.species_dict[label].rxn_label is not None else ''
2314-
else:
2315-
rxn_str = ''
2316-
logger.info(f'\nOptimized geometry for {label}{rxn_str} at {job.level.simple()}:\n'
2317-
f'{xyz_to_str(self.species_dict[label].final_xyz)}\n')
2318-
self.output[label]['paths']['geo'] = job.local_path_to_output_file # will be overwritten with freq
2295+
self.post_opt_geo_work(label, job)
23192296
if 'optfreq' in job.job_name:
23202297
self.check_freq_job(label, job)
23212298
self.save_restart_dict()
@@ -2340,10 +2317,22 @@ def parse_opt_geo(self,
23402317
method='draw_3d')
23412318
elif self.trsh_ess_jobs:
23422319
self.troubleshoot_opt_jobs(label=label)
2343-
if success:
2344-
return True # run freq / sp / scan jobs on this optimized geometry
2320+
return success
2321+
2322+
def post_opt_geo_work(self, spc_label, job):
2323+
self.output[spc_label]['job_types']['opt'] = True
2324+
if self.job_types['fine']:
2325+
self.output[spc_label]['job_types']['fine'] = True
2326+
self.species_dict[spc_label].opt_level = self.opt_level.simple()
2327+
plotter.save_geo(species=self.species_dict[spc_label], project_directory=self.project_directory)
2328+
if self.species_dict[spc_label].is_ts:
2329+
rxn_str = f' of reaction {self.species_dict[spc_label].rxn_label}' \
2330+
if self.species_dict[spc_label].rxn_label is not None else ''
23452331
else:
2346-
return False # return ``False``, so no freq / sp / scan jobs are initiated for this unoptimized geometry
2332+
rxn_str = ''
2333+
logger.info(f'\nOptimized geometry for {spc_label}{rxn_str} at {job.level.simple()}:\n'
2334+
f'{xyz_to_str(self.species_dict[spc_label].final_xyz)}\n')
2335+
self.output[spc_label]['paths']['geo'] = job.local_path_to_output_file # will be overwritten with freq
23472336

23482337
def check_freq_job(self,
23492338
label: str,
@@ -2939,7 +2928,7 @@ def check_all_done(self, label: str):
29392928
label (str): The species label.
29402929
"""
29412930
all_converged = True
2942-
if not self.output[label]['convergence']:
2931+
if label in self.output and not self.output[label]['convergence']:
29432932
for job_type, spawn_job_type in self.job_types.items():
29442933
if spawn_job_type and not self.output[label]['job_types'][job_type] \
29452934
and not ((self.species_dict[label].is_ts and job_type in ['scan', 'conformers'])
@@ -2952,7 +2941,7 @@ def check_all_done(self, label: str):
29522941
logger.debug(f'Species {label} did not converge.')
29532942
all_converged = False
29542943
break
2955-
if all_converged:
2944+
if label in self.output and all_converged:
29562945
self.output[label]['convergence'] = True
29572946
if self.species_dict[label].is_ts:
29582947
self.species_dict[label].make_ts_report()
@@ -2981,7 +2970,7 @@ def check_all_done(self, label: str):
29812970
logger.info(f'\nAll jobs for species {label} successfully converged. '
29822971
f'Run time: {self.species_dict[label].run_time}')
29832972
# Todo: any TS which did not converged (any rxn not calculated) should be reported here with full status: Was the family identified? Were TS guesses found? IF so, what's wrong?
2984-
elif (not self.species_dict[label].is_ts or self.species_dict[label].ts_guesses_exhausted) and not label.startswith('IRC_'):
2973+
elif label in self.species_dict and (not self.species_dict[label].is_ts or self.species_dict[label].ts_guesses_exhausted) and not label.startswith('IRC_'):
29852974
job_type_status = {key: val for key, val in self.output[label]['job_types'].items()
29862975
if key in self.job_types and self.job_types[key]
29872976
and (key != 'irc' or self.species_dict[label].is_ts)}

0 commit comments

Comments
 (0)