@@ -422,7 +422,10 @@ def __init__(self,
422
422
# conformers weren't asked for, assign initial_xyz
423
423
species .initial_xyz = species .conformers [0 ]
424
424
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 ()
426
429
if self .output [species .label ]['convergence' ]:
427
430
continue
428
431
if species .is_monoatomic ():
@@ -523,7 +526,7 @@ def schedule_jobs(self):
523
526
while self .running_jobs != {}:
524
527
self .timer = True
525
528
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 :
527
530
# Skip unconverged species.
528
531
if label in self .running_jobs :
529
532
del self .running_jobs [label ]
@@ -775,7 +778,7 @@ def run_job(self,
775
778
max_job_time = max_job_time or self .max_job_time # if it's None, set to default
776
779
ess_trsh_methods = ess_trsh_methods if ess_trsh_methods is not None else list ()
777
780
species = None
778
- if isinstance (label , str ):
781
+ if isinstance (label , str ) and label in self . output :
779
782
species = self .species_dict [label ]
780
783
elif isinstance (label , list ):
781
784
species = [spc for spc in self .species_list if spc .label in label ]
@@ -976,7 +979,7 @@ def end_job(self, job: 'JobAdapter',
976
979
os .makedirs (r_path )
977
980
shutil .copyfile (src = check_path , dst = os .path .join (r_path , 'directed_rotor_check.chk' ))
978
981
self .species_dict [label ].checkfile = os .path .join (r_path , 'directed_rotor_check.chk' )
979
- else :
982
+ elif label in self . output :
980
983
self .species_dict [label ].checkfile = check_path
981
984
if job .job_type == 'scan' or job .directed_scan_type == 'ess' :
982
985
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):
1028
1031
1029
1032
Args:
1030
1033
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.
1033
1035
"""
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 ]
1035
1037
log_info_printed = False
1036
1038
for label in labels_to_consider :
1037
1039
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,
1427
1429
return None
1428
1430
1429
1431
# 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 :
1431
1433
self .run_irc_job (label = label , irc_direction = 'forward' )
1432
1434
self .run_irc_job (label = label , irc_direction = 'reverse' )
1433
1435
1434
1436
# 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 :
1436
1438
if 'freq' not in job_name and self .job_types ['freq' ]:
1437
1439
# This is either an opt or a composite job (not an optfreq job), spawn freq.
1438
1440
self .run_freq_job (label )
@@ -1446,7 +1448,7 @@ def spawn_post_opt_jobs(self,
1446
1448
1447
1449
# Perceive the Molecule from xyz.
1448
1450
# 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 :
1450
1452
self .species_dict [label ].mol_from_xyz ()
1451
1453
1452
1454
# Spawn scan jobs.
@@ -1465,11 +1467,11 @@ def spawn_post_opt_jobs(self,
1465
1467
self .run_orbitals_job (label )
1466
1468
1467
1469
# 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 :
1469
1471
self .run_onedmin_job (label )
1470
1472
1471
1473
# 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 :
1473
1475
bde_species_list = self .species_dict [label ].scissors ()
1474
1476
for bde_species in bde_species_list :
1475
1477
if bde_species .label != 'H' :
@@ -1493,7 +1495,7 @@ def spawn_post_opt_jobs(self,
1493
1495
if species .number_of_atoms > 1 ])
1494
1496
1495
1497
# 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 :
1497
1499
self .spawn_ts_jobs ()
1498
1500
1499
1501
def spawn_ts_jobs (self ):
@@ -2257,11 +2259,11 @@ def parse_opt_geo(self,
2257
2259
if job .job_status [1 ]['status' ] == 'done' :
2258
2260
multi_species = any (spc .multi_species == label for spc in self .species_list )
2259
2261
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 ( )
2265
2267
2266
2268
if not job .fine and self .job_types ['fine' ] \
2267
2269
and not job .level .method_type == 'wavefunction' \
@@ -2275,47 +2277,22 @@ def parse_opt_geo(self,
2275
2277
else :
2276
2278
self .species_dict [label ].initial_xyz = opt_xyz
2277
2279
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
+ )
2284
2285
else :
2285
2286
success = True
2286
2287
if multi_species :
2287
2288
for spc in self .species_list :
2288
2289
if spc .multi_species == label :
2289
2290
# 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'\n Optimized 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 )
2304
2293
else :
2305
2294
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'\n Optimized 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 )
2319
2296
if 'optfreq' in job .job_name :
2320
2297
self .check_freq_job (label , job )
2321
2298
self .save_restart_dict ()
@@ -2340,10 +2317,22 @@ def parse_opt_geo(self,
2340
2317
method = 'draw_3d' )
2341
2318
elif self .trsh_ess_jobs :
2342
2319
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 ''
2345
2331
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'\n Optimized 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
2347
2336
2348
2337
def check_freq_job (self ,
2349
2338
label : str ,
@@ -2939,7 +2928,7 @@ def check_all_done(self, label: str):
2939
2928
label (str): The species label.
2940
2929
"""
2941
2930
all_converged = True
2942
- if not self .output [label ]['convergence' ]:
2931
+ if label in self . output and not self .output [label ]['convergence' ]:
2943
2932
for job_type , spawn_job_type in self .job_types .items ():
2944
2933
if spawn_job_type and not self .output [label ]['job_types' ][job_type ] \
2945
2934
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):
2952
2941
logger .debug (f'Species { label } did not converge.' )
2953
2942
all_converged = False
2954
2943
break
2955
- if all_converged :
2944
+ if label in self . output and all_converged :
2956
2945
self .output [label ]['convergence' ] = True
2957
2946
if self .species_dict [label ].is_ts :
2958
2947
self .species_dict [label ].make_ts_report ()
@@ -2981,7 +2970,7 @@ def check_all_done(self, label: str):
2981
2970
logger .info (f'\n All jobs for species { label } successfully converged. '
2982
2971
f'Run time: { self .species_dict [label ].run_time } ' )
2983
2972
# 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_' ):
2985
2974
job_type_status = {key : val for key , val in self .output [label ]['job_types' ].items ()
2986
2975
if key in self .job_types and self .job_types [key ]
2987
2976
and (key != 'irc' or self .species_dict [label ].is_ts )}
0 commit comments