def _init_geom_opt(zma_init, spc_info, mod_thy_info, run_fs, thy_run_fs, opt_script_str, overwrite, **opt_kwargs): """ Generate initial geometry via optimization from either reference geometries or from inchi """ # Set up the filesystem thy_run_fs[-1].create(mod_thy_info[1:4]) thy_run_path = thy_run_fs[-1].path(mod_thy_info[1:4]) # Call the electronic structure optimizer run_fs = autofile.fs.run(thy_run_path) es_runner.run_job( job=elstruct.Job.OPTIMIZATION, script_str=opt_script_str, run_fs=run_fs, geom=zma_init, spc_info=spc_info, thy_info=mod_thy_info, overwrite=overwrite, **opt_kwargs, ) success, ret = es_runner.read_job(job=elstruct.Job.OPTIMIZATION, run_fs=run_fs) geo, zma = None, None if success: print('Succesful reference geometry optimization') inf_obj, _, out_str = ret prog = inf_obj.prog geo = elstruct.reader.opt_geometry(prog, out_str) zma = elstruct.reader.opt_zmatrix(prog, out_str) return geo, zma
def run_irc(zma, irc_job, coord_name, run_fs, ini_scn_save_fs, ts_info, mod_ini_thy_info, overwrite, opt_script_str, **opt_kwargs): """ Run the irc job """ # Maybe check for positive coords if not _irc_ran(ini_scn_save_fs, coord_name, irc_job): print('No IRC calculation in save filesystem') opt_success, _ = es_runner.read_job( job=irc_job, run_fs=run_fs, ) need_irc = bool(not opt_success) else: print('Found IRC directory at {}'.format( ini_scn_save_fs[1].path([coord_name]))) need_irc = False if need_irc: print('Running IRC calculation') es_runner.run_job( job=irc_job, script_str=opt_script_str, run_fs=run_fs, geom=zma, spc_info=ts_info, thy_info=mod_ini_thy_info, overwrite=overwrite, **opt_kwargs, ) else: print('Skipping IRC calculation')
def save_struct(run_fs, save_fs, locs, job, mod_thy_info, zma_locs=(0, ), in_zma_fs=False, cart_to_zma=False): """ Save a geometry and associated information from some electronic structure routine into the filesystem. """ success, ret = es_runner.read_job(job=job, run_fs=run_fs) if success: # Get the geo, zma, and ene based on job type ene, zma, geo = _read(run_fs, job, cart_to_zma=cart_to_zma) # Obtain inf obj and inp str to write in filesys inf_obj, inp_str, _ = ret # Set and print the save path information save_path = save_fs[-1].path(locs) print(" - Saving...") print(" - Save path: {}".format(save_path)) # Save the geometry information save_fs[-1].create(locs) save_fs[-1].file.geometry_info.write(inf_obj, locs) save_fs[-1].file.geometry_input.write(inp_str, locs) save_fs[-1].file.geometry.write(geo, locs) save_fs[-1].file.energy.write(ene, locs) # Save zma information seperately, if required if not in_zma_fs: zma_save_fs = autofile.fs.zmatrix(save_path) zma_save_fs[-1].create(zma_locs) zma_save_fs[-1].file.geometry_info.write(inf_obj, zma_locs) zma_save_fs[-1].file.geometry_input.write(inp_str, zma_locs) zma_save_fs[-1].file.zmatrix.write(zma, zma_locs) else: save_fs[-1].file.zmatrix.write(zma, locs) # Saving the energy to an SP filesys print(" - Saving energy...") sp_save_fs = autofile.fs.single_point(save_path) sp_save_fs[-1].create(mod_thy_info[1:4]) sp_save_fs[-1].file.input.write(inp_str, mod_thy_info[1:4]) sp_save_fs[-1].file.info.write(inf_obj, mod_thy_info[1:4]) sp_save_fs[-1].file.energy.write(ene, mod_thy_info[1:4]) saved = True else: saved = False return saved
def optimize_saddle_point(guess_zmas, ts_info, mod_thy_info, run_fs, opt_script_str, overwrite, **opt_kwargs): """ Optimize the transition state structure obtained from the grid search """ if len(guess_zmas) == 1: print('\nThere is 1 guess Z-Matrix', 'to attempt to find saddle point.') else: print('\nThere are {} guess Z-Matrices'.format(len(guess_zmas)), 'to attempt to find saddle point.') # Loop over all the guess zmas to find a TS opt_ret = None for idx, zma in enumerate(guess_zmas): print('\nAttempting optimization of', 'guess Z-Matrix {}...'.format(idx + 1)) # Run the transition state optimization es_runner.run_job( job='optimization', script_str=opt_script_str, run_fs=run_fs, geom=zma, spc_info=ts_info, thy_info=mod_thy_info, saddle=True, overwrite=overwrite, **opt_kwargs, ) # Read the contents of the optimization opt_success, opt_ret = es_runner.read_job( job='optimization', run_fs=run_fs, ) # If successful, break loop. If not, try constrained opt+full opt seq if opt_success: break else: print() # es_runner.run_job( # job='optimization', # script_str=opt_script_str, # run_fs=run_fs, # geom=zma, # spc_info=ts_info, # thy_info=mod_thy_info, # frozen_coordinates=frozen_coordinates, # saddle=True, # overwrite=overwrite, # **opt_kwargs, # ) return opt_ret
def save_irc(irc_job, coord_name, run_fs, ini_scn_save_fs, mod_ini_thy_info): """ Read IRC output and store data in filesystem """ opt_success, opt_ret = es_runner.read_job( job=irc_job, run_fs=run_fs, ) if opt_success is not None: # Read the IRC output file inf_obj, inp_str, out_str = opt_ret prog = inf_obj.prog geos, gras, hessians = elstruct.reader.irc_points(prog, out_str) coord_vals, enes = elstruct.reader.irc_path(prog, out_str) # Write the data for each geom along IRC to the filesystem save_path = ini_scn_save_fs[1].path([coord_name]) print(" - Saving...") print(" - Save path: {}".format(save_path)) for idx, val in enumerate(coord_vals): # Set locs idx; for reverse, ignore SadPt and flip idx to negative locs_idx = idx if irc_job == elstruct.Job.IRCR: if locs_idx == 0: continue # val *= -1 coord vals negative from elstruct fxn for g09 # Scale the coordinates so rounding to .2f number is non-zero locs = [coord_name, [val*100.0]] print('irc locs', locs) # Save files ini_scn_save_fs[-1].create(locs) ini_scn_save_fs[-1].file.energy.write(enes[idx], locs) ini_scn_save_fs[-1].file.geometry.write(geos[idx], locs) ini_scn_save_fs[-1].file.geometry_input.write(inp_str, locs) ini_scn_save_fs[-1].file.geometry_info.write(inf_obj, locs) if gras: ini_scn_save_fs[-1].file.gradient.write(gras[idx], locs) ini_scn_save_fs[-1].file.gradient_info.write(inf_obj, locs) if hessians: ini_scn_save_fs[-1].file.hessian.write(hessians[idx], locs) ini_scn_save_fs[-1].file.hessian_info.write(inf_obj, locs) scn_save_path = ini_scn_save_fs[-1].path(locs) print('scn_save_path') sp_save_fs = autofile.fs.single_point(scn_save_path) sp_save_fs[-1].create(mod_ini_thy_info[1:4]) sp_save_fs[-1].file.input.write(inp_str, mod_ini_thy_info[1:4]) sp_save_fs[-1].file.info.write(inf_obj, mod_ini_thy_info[1:4]) sp_save_fs[-1].file.energy.write(enes[idx], mod_ini_thy_info[1:4])
def _kickoff_saddle(geo, disp_xyzs, spc_info, mod_thy_info, run_fs, thy_run_fs, opt_script_str, kickoff_size=0.1, kickoff_backward=False, opt_cart=True, **kwargs): """ kickoff from saddle to find connected minima """ # Set the filesys thy_run_fs[-1].create(mod_thy_info[1:4]) thy_run_path = thy_run_fs[-1].path(mod_thy_info[1:4]) run_fs = autofile.fs.run(thy_run_path) # Set the displacement vectors and displace geometry disp_len = kickoff_size * phycon.ANG2BOHR if kickoff_backward: disp_len *= -1 disp_xyzs = numpy.multiply(disp_xyzs, disp_len) print('geo test in kickoff_saddle:') print(automol.geom.string(geo), disp_xyzs) geo = automol.geom.displace(geo, disp_xyzs) # Optimize displaced geometry if opt_cart: geom = geo else: geom = automol.geom.zmatrix(geo) es_runner.run_job( job=elstruct.Job.OPTIMIZATION, script_str=opt_script_str, run_fs=run_fs, geom=geom, spc_info=spc_info, thy_info=mod_thy_info, overwrite=True, **kwargs, ) success, ret = es_runner.read_job(job=elstruct.Job.OPTIMIZATION, run_fs=run_fs) if success: inf_obj, _, out_str = ret prog = inf_obj.prog geo = elstruct.reader.opt_geometry(prog, out_str) return geo
def _read(run_fs, job, cart_to_zma=False): """ Read the output """ assert job in (elstruct.Job.OPTIMIZATION, elstruct.Job.ENERGY), ('Job not opt or energy') _, ret = es_runner.read_job(job=job, run_fs=run_fs) if ret: inf_obj, _, out_str = ret prog = inf_obj.prog method = inf_obj.method try: ene = elstruct.reader.energy(prog, method, out_str) except TypeError: ene = None print('No ENE') except AttributeError: ene = None print('No ENE') if job == elstruct.Job.OPTIMIZATION: # Read the optimized structs from the output file try: geo = elstruct.reader.opt_geometry(prog, out_str) except TypeError: geo = None print('No GEOM') # Read the optimized zma if cart_to_zma: zma = automol.geom.zmatrix(geo) else: try: zma = elstruct.reader.opt_zmatrix(prog, out_str) except TypeError: zma = None print('No ZMA') elif job == elstruct.Job.ENERGY: # Read the initial structs stored in the run filesys zma = run_fs[-1].file.zmatrix.read([job]) geo = run_fs[-1].file.geometry.read([job]) else: ene, zma, geo = None, None, None return ene, zma, geo
def saddle_point_hessian(opt_ret, ts_info, mod_thy_info, run_fs, script_str, overwrite, **opt_kwargs): """ run things for checking Hessian """ # Obtain geometry from optimization opt_inf_obj, _, opt_out_str = opt_ret opt_prog = opt_inf_obj.prog geo = elstruct.reader.opt_geometry(opt_prog, opt_out_str) # Run a Hessian es_runner.run_job( job='hessian', script_str=script_str, run_fs=run_fs, geom=geo, spc_info=ts_info, thy_info=mod_thy_info, overwrite=overwrite, **opt_kwargs, ) # Read the contents of the optimization hess_success, hess_ret = es_runner.read_job( job='hessian', run_fs=run_fs, ) # If successful, Read the geom and energy from the optimization if hess_success: hess_inf_obj, _, hess_out_str = hess_ret hess = elstruct.reader.hessian(hess_inf_obj.prog, hess_out_str) freq_run_path = run_fs[-1].path(['hessian']) run_fs[-1].create(['hessian']) freqs, _, imags, _ = structure.vib.projrot_freqs([geo], [hess], freq_run_path) else: freqs, imags = [], [] return hess_ret, freqs, imags
def find_vdw(ts_name, spc_dct, thy_info, ini_thy_info, vdw_params, nsamp_par, run_prefix, save_prefix, kickoff_size, kickoff_backward, overwrite): """ Find van der Waals structures for all the pairs of species in a reaction list. Fxn takes two species, performs a (random?) rotation, sticks them together and optimizes the combined geometry. Supposed to use the wells filesystem? """ new_vdws = [] _, opt_script_str, _, opt_kwargs = qchem_params(*thy_info[:2]) mul = spc_dct[ts_name]['low_mul'] vdw_names_lst = [] if vdw_params[0]: vdw_names_lst.append([sorted(spc_dct[ts_name]['reacs']), mul, 'r']) if vdw_params[1]: vdw_names_lst.append([sorted(spc_dct[ts_name]['prods']), mul, 'p']) for names, ts_mul, label in vdw_names_lst: if len(names) < 2: print('Cannot find van der Waals well for unimolecular', 'reactant or product') ichs = list(map(lambda name: spc_dct[name]['inchi'], names)) chgs = list(map(lambda name: spc_dct[name]['chg'], names)) muls = list(map(lambda name: spc_dct[name]['mul'], names)) # theory prog = thy_info[0] method = thy_info[1] _, opt_script_str, _, opt_kwargs = es_runner.qchem_params(prog, method) geos = [(), ()] ntaudof = 0. for i, (nam, ich, chg, mul) in enumerate(zip(names, ichs, chgs, muls)): spc_info = [ich, chg, mul] orb_restr = filesys.inf.orbital_restriction(spc_info, ini_thy_info) ini_g = ini_thy_info[0:3] ini_g.append(orb_restr) orb_restr = filesys.inf.orbital_restriction(spc_info, thy_info) thy_info = thy_info[0:3] thy_info.append(orb_restr) spc_run_fs = autofile.fs.species(run_prefix) spc_run_fs[-1].create(spc_info) spc_run_path = spc_run_fs[-1].path(spc_info) spc_save_fs = autofile.fs.species(save_prefix) spc_save_fs[-1].create(spc_info) spc_save_path = spc_save_fs[-1].path(spc_info) thy_run_fs = autofile.fs.theory(spc_run_path) thy_run_fs[-1].create(thy_info[1:4]) thy_run_path = thy_run_fs[-1].path(thy_info[1:4]) thy_save_fs = autofile.fs.theory(spc_save_path) thy_save_fs[-1].create(thy_info[1:4]) thy_save_path = thy_save_fs[-1].path(thy_info[1:4]) run_fs = autofile.fs.run(thy_run_path) ini_thy_save_fs = autofile.fs.theory(spc_save_path) ini_thy_save_fs[-1].create(ini_thy_info[1:4]) cnf_run_fs = autofile.fs.conformer(thy_run_path) cnf_save_fs = autofile.fs.conformer(thy_save_path) geo = geom.reference_geometry(spc_dct[nam], thy_info, ini_thy_info, thy_run_fs, thy_save_fs, ini_thy_save_fs, cnf_run_fs, cnf_save_fs, run_fs, kickoff_size=kickoff_size, kickoff_backward=kickoff_backward, overwrite=overwrite) geos[i] = geo gra = automol.geom.graph(geo) ntaudof += len( automol.graph.rotational_bond_keys(gra, with_h_rotors=False)) nsamp = util.nsamp_init(nsamp_par, ntaudof) geo1, geo2 = geos geo1 = automol.geom.mass_centered(geo1) geo2 = automol.geom.mass_centered(geo2) min_ene = 0. for idx in range(int(nsamp)): print('Optimizing vdw geometry {}/{}'.format(idx + 1, nsamp)) angs1 = numpy.multiply(numpy.random.rand(3), [1 * numpy.pi, 2 * numpy.pi, 2 * numpy.pi]) angs2 = numpy.multiply(numpy.random.rand(3), [1 * numpy.pi, 2 * numpy.pi, 2 * numpy.pi]) angs12 = numpy.multiply(numpy.random.rand(2), [1 * numpy.pi, 2 * numpy.pi]) geo1 = automol.geom.euler_rotate(geo1, *angs1) geo2 = automol.geom.euler_rotate(geo2, *angs2) dist_cutoff = 3.0 * phycon.ANG2BOHR geo = automol.geom.join(geo1, geo2, dist_cutoff, *angs12) print("Species: {}".format('+'.join(names))) print('vdw starting geometry') print(automol.geom.xyz_string(geo)) # Set up the filesystem ich = automol.inchi.recalculate(automol.inchi.join(ichs)) chg = sum(chgs) mul = ts_mul spc_info = (ich, chg, mul) spc_run_fs = autofile.fs.species(run_prefix) spc_run_fs[-1].create(spc_info) spc_run_path = spc_run_fs[-1].path(spc_info) spc_save_fs = autofile.fs.species(save_prefix) spc_save_fs[-1].create(spc_info) spc_save_path = spc_save_fs[-1].path(spc_info) orb_restr = filesys.inf.orbital_restriction(spc_info, thy_info) thy_info = thy_info[0:3] thy_info.append(orb_restr) thy_run_fs = autofile.fs.theory(spc_run_path) thy_run_fs[-1].create(thy_info[1:4]) thy_run_path = thy_run_fs[-1].path(thy_info[1:4]) thy_save_fs = autofile.fs.theory(spc_save_path) thy_save_fs[-1].create(thy_info[1:4]) thy_save_path = thy_save_fs[-1].path(thy_info[1:4]) run_fs = autofile.fs.run(thy_run_path) # Generate reference geometry # Generate the z-matrix and sampling ranges es_runner.run_job( job=elstruct.Job.OPTIMIZATION, geom=geo, spc_info=spc_info, th_info=thy_info, run_fs=run_fs, script_str=opt_script_str, overwrite=overwrite, **opt_kwargs, ) # Save info for the initial geometry (from ichi or fsave dir) success, ret = es_runner.read_job(job=elstruct.Job.OPTIMIZATION, run_fs=run_fs) if success: print('Saving reference geometry') print(" - Save path: {}".format(thy_save_path)) inf_obj, inp_str, out_str = ret prog = inf_obj.prog method = inf_obj.method geo = elstruct.reader.opt_geometry(prog, out_str) print('vdw ending geometry') print(automol.geom.xyz_string(geo)) thy_save_fs[-1].file.geometry.write(geo, thy_info[1:4]) ene = elstruct.reader.energy(prog, method, out_str) if ene < min_ene: min_ene = ene print('ene test in vdw') print(ene) thy_save_fs[-1].file.energy.write(ene, thy_info[1:4]) print('Saving reference geometry') print(" - Save path: {}".format(thy_save_path)) vdw_name = label + ts_name.replace('ts', 'vdw') spc_dct[vdw_name] = spc_dct[ts_name].copy() spc_dct[vdw_name]['inchi'] = ich spc_dct[vdw_name]['mul'] = mul spc_dct[vdw_name]['chg'] = chg spc_dct[vdw_name]['dist_info'][1] = dist_cutoff # Make a fake conformer cnf_save_fs = autofile.fs.conformer(thy_save_path) cnf_run_fs = autofile.fs.conformer(thy_run_path) cnf_save_fs[0].create() cnf_run_fs[0].create() tors_range_dct = {} cinf_obj = autofile.schema.info_objects.conformer[0]( 0, tors_range_dct) cinf_obj.nsamp = 1 cnf_save_fs[0].file.info.write(cinf_obj) locs_lst = cnf_save_fs[-1].existing() if not locs_lst: cid = autofile.schema.generate_new_conformer_id() locs = [cid] else: locs = locs_lst[0] cnf_save_fs[-1].create(locs) cnf_run_fs[-1].create(locs) cnf_save_fs[-1].file.geometry_info.write(inf_obj, locs) cnf_save_fs[-1].file.geometry_input.write(inp_str, locs) cnf_save_fs[-1].file.energy.write(ene, locs) cnf_save_fs[-1].file.geometry.write(geo, locs) if min_ene: new_vdws.append(vdw_name) return new_vdws
def run_hessian(zma, geo, spc_info, thy_info, geo_save_fs, geo_run_path, geo_save_path, locs, script_str, overwrite, retryfail=True, **kwargs): """ Determine the hessian for the geometry in the given location """ # Set the run filesystem information run_fs = autofile.fs.run(geo_run_path) # if prog == 'molpro2015': # geo = hess_geometry(out_str) # scn_save_fs[-1].file.geometry.write(geo, locs) # Set input geom # Warning using internal coordinates leads to inconsistencies with Gaussian # For this reason we only use Cartesians to generate the Hessian if geo is not None: job_geo = geo else: job_geo = automol.zmatrix.geometry(zma) is_atom = automol.geom.is_atom(job_geo) if not is_atom: if _json_database(geo_save_path): exists = geo_save_fs[-1].json.hessian.exists(locs) else: exists = geo_save_fs[-1].file.hessian.exists(locs) if not exists: print('No Hessian found in save filesys. Running Hessian...') _run = True elif overwrite: print('User specified to overwrite Hessian with new run...') _run = True else: _run = False if _run: run_fs = autofile.fs.run(geo_run_path) es_runner.run_job( job='hessian', script_str=script_str, run_fs=run_fs, geom=job_geo, spc_info=spc_info, thy_info=thy_info, overwrite=overwrite, retryfail=retryfail, **kwargs, ) success, ret = es_runner.read_job( job='hessian', run_fs=run_fs, ) if success: inf_obj, inp_str, out_str = ret print(" - Reading hessian from output...") hess = elstruct.reader.hessian(inf_obj.prog, out_str) print(" - Saving Hessian...") if _json_database(geo_save_path): geo_save_fs[-1].json.hessian_info.write(inf_obj, locs) geo_save_fs[-1].json.hessian_input.write(inp_str, locs) geo_save_fs[-1].json.hessian.write(hess, locs) else: geo_save_fs[-1].file.hessian_info.write(inf_obj, locs) geo_save_fs[-1].file.hessian_input.write(inp_str, locs) geo_save_fs[-1].file.hessian.write(hess, locs) print(" - Save path: {}".format(geo_save_path)) if thy_info[0] == 'gaussian09': _hess_grad(inf_obj.prog, out_str, geo_save_fs, geo_save_path, locs, overwrite) _hess_freqs(geo, geo_save_fs, geo_run_path, geo_save_path, locs, overwrite) else: print('Hessian found and saved previously at {}'.format( geo_save_path)) _hess_freqs(geo, geo_save_fs, geo_run_path, geo_save_path, locs, overwrite) else: print('Species is an atom. Skipping Hessian task.')
def single_conformer(zma, spc_info, mod_thy_info, cnf_run_fs, cnf_save_fs, script_str, overwrite, retryfail=True, saddle=False, **kwargs): """ generate single optimized geometry to be saved into a filesystem """ # Build the filesystem locs = [autofile.schema.generate_new_conformer_id()] cnf_run_fs[-1].create(locs) cnf_run_path = cnf_run_fs[-1].path(locs) run_fs = autofile.fs.run(cnf_run_path) # Run the optimization print('Optimizing a single conformer') es_runner.run_job(job=elstruct.Job.OPTIMIZATION, script_str=script_str, run_fs=run_fs, geom=zma, spc_info=spc_info, thy_info=mod_thy_info, overwrite=overwrite, frozen_coordinates=(), saddle=saddle, retryfail=retryfail, **kwargs) # print('Stage one success, reading for stage 2') success, ret = es_runner.read_job(job=elstruct.Job.OPTIMIZATION, run_fs=run_fs) if success: inf_obj, _, out_str = ret prog = inf_obj.prog method = inf_obj.method ene = elstruct.reader.energy(prog, method, out_str) geo = elstruct.reader.opt_geometry(prog, out_str) zma = elstruct.reader.opt_zmatrix(prog, out_str) saved_locs, saved_geos, saved_enes = _saved_cnf_info( cnf_save_fs, mod_thy_info) if _geo_unique(geo, ene, saved_geos, saved_enes, saddle): sym_id = _sym_unique(geo, ene, saved_geos, saved_enes) if sym_id is None: _save_unique_conformer(ret, mod_thy_info, cnf_save_fs, locs, saddle=saddle, zma_locs=(0, )) saved_geos.append(geo) saved_enes.append(ene) saved_locs.append(locs) # Update the conformer trajectory file print('') filesys.mincnf.traj_sort(cnf_save_fs, mod_thy_info)
def save_tau(tau_run_fs, tau_save_fs, mod_thy_info): """ save the tau dependent geometries that have been found so far """ # db_style = 'jsondb' db_style = 'directory' if db_style == 'jsondb': saved_locs = tau_save_fs[-1].json_existing() saved_geos = tau_save_fs[-1].json.geometry.read_all(saved_locs) elif db_style == 'directory': saved_geos = [ tau_save_fs[-1].file.geometry.read(locs) for locs in tau_save_fs[-1].existing() ] if not tau_run_fs[0].exists(): print("No tau geometries to save. Skipping...") else: if db_style == 'jsondb': save_info = [[], [], [], [], []] sp_save_info = [[], [], [], [], []] for locs in tau_run_fs[-1].existing(): run_path = tau_run_fs[-1].path(locs) run_fs = autofile.fs.run(run_path) save_path = tau_save_fs[-1].root.path() print("Reading from tau run at {}".format(run_path)) success, ret = es_runner.read_job(job=elstruct.Job.OPTIMIZATION, run_fs=run_fs) if success: inf_obj, inp_str, out_str = ret prog = inf_obj.prog method = inf_obj.method ene = elstruct.reader.energy(prog, method, out_str) geo = elstruct.reader.opt_geometry(prog, out_str) if db_style == 'directory': print(" - Saving...") print(" - Save path: {}".format(save_path)) tau_save_fs[-1].create(locs) tau_save_fs[-1].file.geometry_info.write(inf_obj, locs) tau_save_fs[-1].file.geometry_input.write(inp_str, locs) tau_save_fs[-1].file.energy.write(ene, locs) tau_save_fs[-1].file.geometry.write(geo, locs) # Saving the energy to a SP filesystem save_path = tau_save_fs[-1].path(locs) print(" - Saving...") print(" - Save path: {}".format(save_path)) sp_save_fs = autofile.fs.single_point(save_path) sp_save_fs[-1].create(mod_thy_info[1:4]) sp_save_fs[-1].file.input.write(inp_str, mod_thy_info[1:4]) sp_save_fs[-1].file.info.write(inf_obj, mod_thy_info[1:4]) sp_save_fs[-1].file.energy.write(ene, mod_thy_info[1:4]) elif db_style == 'jsondb': # tau_save_fs[-1].json.geometry_info.write(inf_obj, locs) # tau_save_fs[-1].json.geometry_input.write(inp_str, locs) # tau_save_fs[-1].json.energy.write(ene, locs) # tau_save_fs[-1].json.geometry.write(geo, locs) print(" - Saving energy and geo of unique geometry...") save_info[0].append(locs) save_info[1].append(inf_obj) save_info[2].append(inp_str) save_info[3].append(ene) save_info[4].append(geo) sp_save_fs = autofile.fs.single_point(save_path, json_layer=locs) sp_save_info[0].append(sp_save_fs) sp_save_info[1].append(mod_thy_info[1:4]) sp_save_info[2].append(inp_str) sp_save_info[3].append(inf_obj) sp_save_info[4].append(ene) sp_save_fs[-1].json.input.write(inp_str, mod_thy_info[1:4]) sp_save_fs[-1].json.info.write(inf_obj, mod_thy_info[1:4]) sp_save_fs[-1].json.energy.write(ene, mod_thy_info[1:4]) saved_geos.append(geo) if db_style == 'jsondb': tau_save_fs[-1].json_create() tau_save_fs[-1].json.geometry_info.write_all( save_info[1], save_info[0]) tau_save_fs[-1].json.geometry_input.write_all( save_info[2], save_info[0]) tau_save_fs[-1].json.energy.write_all(save_info[3], save_info[0]) tau_save_fs[-1].json.geometry.write_all(save_info[4], save_info[0]) for i, sp_save_fs_i in enumerate(sp_save_info[0]): sp_save_fs_i[-1].json.input.write(sp_save_info[2][i], sp_save_info[1][i]) sp_save_fs_i[-1].json.info.write(sp_save_info[3][i], sp_save_info[1][i]) sp_save_fs_i[-1].json.energy.write(sp_save_info[4][i], sp_save_info[1][i]) # update the tau trajectory file filesys.mincnf.traj_sort(tau_save_fs, mod_thy_info)
def run_conformers(zma, spc_info, thy_info, nsamp, tors_range_dct, cnf_run_fs, cnf_save_fs, script_str, overwrite, saddle, two_stage, retryfail, **kwargs): """ run sampling algorithm to find conformers """ if not tors_range_dct: print(" - No torsional coordinates. Setting nsamp to 1.") nsamp = 1 cnf_save_fs[0].create() # following check breaks; prob add checks to zmas in idv confs # kind of pain # ignoring the idea of storing multiple zmas right now # vma = automol.zmatrix.var_(zma) # if cnf_save_fs[0].file.vmatrix.exists(): # existing_vma = cnf_save_fs[0].file.vmatrix.read() # assert vma == existing_vma # cnf_save_fs[0].file.vmatrix.write(vma) nsamp0 = nsamp inf_obj = autofile.schema.info_objects.conformer_trunk(0) if cnf_save_fs[0].file.info2.exists(): inf_obj_s = cnf_save_fs[0].file.info2.read() nsampd = inf_obj_s.nsamp elif cnf_run_fs[0].file.info2.exists(): inf_obj_r = cnf_run_fs[0].file.info2.read() nsampd = inf_obj_r.nsamp else: nsampd = 0 tot_samp = nsamp - nsampd print(' - Number of samples that have been currently run:', nsampd) print(' - Number of samples requested:', nsamp) if nsamp - nsampd > 0: print('\nRunning {} samples...'.format(nsamp - nsampd)) samp_idx = 1 while True: nsamp = nsamp0 - nsampd # Break the while loop if enough sampls completed if nsamp <= 0: print('Requested number of samples have been completed. ' 'Conformer search complete.') break # Run the conformer sampling if nsampd > 0: samp_zma, = automol.zmatrix.samples(zma, 1, tors_range_dct) else: samp_zma = zma print('\nChecking if ZMA has high repulsion...') # print('zma tests:', # automol.zmatrix.string(zma), automol.zmatrix.string(zma)) bad_geom_count = 0 while (not automol.intmol.low_repulsion_struct(zma, samp_zma) and bad_geom_count < 1000): print(' ZMA has high repulsion.') # print(' Bad geometry:') # print(automol.geom.string(automol.zmatrix.geometry(samp_zma))) print('\n Generating new sample ZMA') samp_zma, = automol.zmatrix.samples(zma, 1, tors_range_dct) bad_geom_count += 1 print(' ZMA is fine...') cid = autofile.schema.generate_new_conformer_id() locs = [cid] cnf_run_fs[-1].create(locs) cnf_run_path = cnf_run_fs[-1].path(locs) run_fs = autofile.fs.run(cnf_run_path) print("Run {}/{}".format(samp_idx, tot_samp)) tors_names = list(tors_range_dct.keys()) if two_stage and tors_names: print('Stage one beginning, holding the coordinates constant', tors_names) es_runner.run_job(job=elstruct.Job.OPTIMIZATION, script_str=script_str, run_fs=run_fs, geom=samp_zma, spc_info=spc_info, thy_info=thy_info, overwrite=overwrite, frozen_coordinates=[tors_names], saddle=saddle, retryfail=retryfail, **kwargs) # print('Stage one success, reading for stage 2') success, ret = es_runner.read_job(job=elstruct.Job.OPTIMIZATION, run_fs=run_fs) if success: sinf_obj, _, out_str = ret prog = sinf_obj.prog samp_zma = elstruct.reader.opt_zmatrix(prog, out_str) print('Stage one success beginning stage two') # print('Stage one success beginning stage two on', samp_zma) es_runner.run_job(job=elstruct.Job.OPTIMIZATION, script_str=script_str, run_fs=run_fs, geom=samp_zma, spc_info=spc_info, thy_info=thy_info, overwrite=overwrite, saddle=saddle, retryfail=False, **kwargs) else: es_runner.run_job(job=elstruct.Job.OPTIMIZATION, script_str=script_str, run_fs=run_fs, geom=samp_zma, spc_info=spc_info, thy_info=thy_info, overwrite=overwrite, saddle=saddle, retryfail=retryfail, **kwargs) if cnf_save_fs[0].file.info2.exists(): inf_obj_s = cnf_save_fs[0].file.info2.read() nsampd = inf_obj_s.nsamp elif cnf_run_fs[0].file.info2.exists(): inf_obj_r = cnf_run_fs[0].file.info2.read() nsampd = inf_obj_r.nsamp nsampd += 1 samp_idx += 1 inf_obj.nsamp = nsampd cnf_save_fs[0].file.info2.write(inf_obj) cnf_run_fs[0].file.info2.write(inf_obj)
def _check_imaginary(spc_info, geo, mod_thy_info, thy_run_fs, script_str, overwrite=False, **kwargs): """ check if species has an imaginary frequency """ # Handle filesystem thy_run_fs[-1].create(mod_thy_info[1:4]) thy_run_path = thy_run_fs[-1].path(mod_thy_info[1:4]) run_fs = autofile.fs.run(thy_run_path) # Initialize info imag = False disp_xyzs = [] hess = ((), ()) # Run Hessian calculation es_runner.run_job( job=elstruct.Job.HESSIAN, spc_info=spc_info, thy_info=mod_thy_info, geom=geo, run_fs=run_fs, script_str=script_str, overwrite=overwrite, **kwargs, ) # Check for imaginary modes success, ret = es_runner.read_job(job=elstruct.Job.HESSIAN, run_fs=run_fs) if success: inf_obj, _, out_str = ret prog = inf_obj.prog hess = elstruct.reader.hessian(prog, out_str) # Calculate vibrational frequencies if hess: imag = False _, _, imag_freq, _ = structure.vib.projrot_freqs([geo], [hess], thy_run_path) if imag_freq: imag = True # Mode for now set the imaginary frequency check to -100: # Should decrease once freq projector functions properly if imag: imag = True print('Imaginary mode found:') # norm_coos = elstruct.util.normal_coordinates( # geo, hess, project=True) # im_norm_coo = numpy.array(norm_coos)[:, 0] # disp_xyzs = numpy.reshape(im_norm_coo, (-1, 3)) norm_coos = elstruct.reader.normal_coords(prog, out_str) im_norm_coo = norm_coos[0] disp_xyzs = im_norm_coo return imag, disp_xyzs
def _optimize_molecule(spc_info, zma_init, mod_thy_info, thy_run_fs, thy_save_fs, cnf_save_fs, run_fs, opt_script_str, overwrite, kickoff_size=0.1, kickoff_backward=False, **opt_kwargs): """ Optimize a proper geometry """ # Optimize the initial geometry geo, zma = _init_geom_opt(zma_init, spc_info, mod_thy_info, run_fs, thy_run_fs, opt_script_str, overwrite, **opt_kwargs) # If connected, check for imaginary modes and fix them if possible if automol.geom.connected(geo): # Remove the imaginary mode geo, imag_fix_needed = _remove_imag(spc_info, geo, mod_thy_info, thy_run_fs, run_fs, kickoff_size, kickoff_backward, overwrite=overwrite) # Recheck connectivity for imag-checked geometry if geo is not None: conf_found = True if automol.geom.connected(geo): print('\nSaving structure as the first conformer...') locs = [autofile.schema.generate_new_conformer_id()] job = elstruct.Job.OPTIMIZATION filesys.save_struct(run_fs, cnf_save_fs, locs, job, mod_thy_info, zma_locs=(0, ), in_zma_fs=False, cart_to_zma=imag_fix_needed) else: print('Saving disconnected species...') _, opt_ret = es_runner.read_job(job=elstruct.Job.OPTIMIZATION, run_fs=run_fs) structure.instab.write_instab(zma_init, zma, thy_save_fs, mod_thy_info[1:4], opt_ret, zma_locs=(0, ), save_cnf=True) else: print('\n No geom found...') conf_found = False else: print('Saving disconnected species...') conf_found = False _, opt_ret = es_runner.read_job(job=elstruct.Job.OPTIMIZATION, run_fs=run_fs) structure.instab.write_instab(zma_init, zma, thy_save_fs, mod_thy_info[1:4], opt_ret, zma_locs=(0, ), save_cnf=True) # Save geom in thy filesys if a good geom is found if conf_found: thy_save_fs[-1].create(mod_thy_info[1:4]) thy_save_path = thy_save_fs[-1].path(mod_thy_info[1:4]) thy_save_fs[-1].file.geometry.write(geo, mod_thy_info[1:4]) print('Saving reference geometry') print(" - Save path: {}".format(thy_save_path)) return conf_found
def run_prop(zma, geo, spc_info, thy_info, geo_save_fs, geo_run_path, geo_save_path, locs, script_str, overwrite, retryfail=True, **kwargs): """ Determine the properties in the given location """ # Set input geom if geo is not None: job_geo = geo else: job_geo = automol.zmatrix.geometry(zma) if _json_database(geo_save_path): dmom_exists = geo_save_fs[-1].json.dipole_moment.exists(locs) polar_exists = geo_save_fs[-1].json.polarizability.exists(locs) else: dmom_exists = geo_save_fs[-1].file.dipole_moment.exists(locs) polar_exists = geo_save_fs[-1].file.polarizability.exists(locs) if not dmom_exists or not polar_exists: print('Either no dipole moment or polarizability found in' 'in save filesys. Running properties...') _run = True elif overwrite: print('User specified to overwrite property with new run...') _run = True else: _run = False if _run: run_fs = autofile.fs.run(geo_run_path) es_runner.run_job( job='molec_properties', script_str=script_str, run_fs=run_fs, geom=job_geo, spc_info=spc_info, thy_info=thy_info, overwrite=overwrite, retryfail=retryfail, **kwargs, ) success, ret = es_runner.read_job( job='molec_properties', run_fs=run_fs, ) if success: inf_obj, inp_str, out_str = ret print(" - Reading dipole moment from output...") dmom = elstruct.reader.dipole_moment(inf_obj.prog, out_str) print(" - Reading polarizability from output...") polar = elstruct.reader.polarizability(inf_obj.prog, out_str) print('dip mom', dmom) print('polar', polar) print(" - Saving dipole moment and polarizability...") if _json_database(geo_save_path): # geo_save_fs[-1].json.property_info.write(inf_obj, locs) # geo_save_fs[-1].json.property_input.write( # inp_str, locs) geo_save_fs[-1].json.dipole_moment.write(dmom, locs) geo_save_fs[-1].json.polarizability.write(polar, locs) else: # geo_save_fs[-1].file.property_info.write(inf_obj, locs) # geo_save_fs[-1].file.property_input.write( # inp_str, locs) geo_save_fs[-1].file.dipole_moment.write(dmom, locs) geo_save_fs[-1].file.polarizability.write(polar, locs) print(" - Save path: {}".format(geo_save_path)) else: print('Dipole moment and polarizability found and', 'saved previously at {}'.format(geo_save_path))
def save_conformers(cnf_run_fs, cnf_save_fs, thy_info, saddle=False, rxn_class='', orig_ich=''): """ save the conformers that have been found so far # Only go through save procedure if conf not in save # may need to get geo, ene, etc; maybe make function """ saved_locs, saved_geos, saved_enes = _saved_cnf_info(cnf_save_fs, thy_info) if not saddle: _check_old_inchi(orig_ich, saved_geos, saved_locs, cnf_save_fs) if not cnf_run_fs[0].exists(): print(" - No conformers in run filesys to save.") else: print(" - Found conformers in run filesys to save.\n") for locs in cnf_run_fs[-1].existing(): cnf_run_path = cnf_run_fs[-1].path(locs) run_fs = autofile.fs.run(cnf_run_path) print("\nReading from conformer run at {}".format(cnf_run_path)) # Read the electronic structure optimization job success, ret = es_runner.read_job(job=elstruct.Job.OPTIMIZATION, run_fs=run_fs) # Assess the geometry and save it if so if success: inf_obj, _, out_str = ret prog = inf_obj.prog method = inf_obj.method ene = elstruct.reader.energy(prog, method, out_str) geo = elstruct.reader.opt_geometry(prog, out_str) zma = elstruct.reader.opt_zmatrix(prog, out_str) # zma = automol.geom.zmatrix(geo) # Assess if geometry is properly connected if _geo_connected(geo, saddle): if saddle: ts_viable = _ts_geo_viable(zma, cnf_save_fs, rxn_class, thy_info) if not ts_viable: continue elif not _inchi_are_same(orig_ich, geo): continue # Assess viability of transition state conformer # Determine uniqueness of conformer, save if needed if _geo_unique(geo, ene, saved_geos, saved_enes, saddle): # iso check breaks because of zma location # if _is_proper_isomer(cnf_save_fs, zma): sym_id = _sym_unique(geo, ene, saved_geos, saved_enes) if sym_id is None: _save_unique_conformer(ret, thy_info, cnf_save_fs, locs, saddle=saddle) saved_geos.append(geo) saved_enes.append(ene) saved_locs.append(locs) else: sym_locs = saved_locs[sym_id] _save_sym_indistinct_conformer( geo, cnf_save_fs, locs, sym_locs) # Update the conformer trajectory file print('') filesys.mincnf.traj_sort(cnf_save_fs, thy_info)
def run_gradient(zma, geo, spc_info, thy_info, geo_save_fs, geo_run_path, geo_save_path, locs, script_str, overwrite, retryfail=True, **kwargs): """ Determine the gradient for the geometry in the given location """ # Set input geom if geo is not None: job_geo = geo else: job_geo = automol.zmatrix.geometry(zma) is_atom = automol.geom.is_atom(job_geo) if not is_atom: if _json_database(geo_save_path): exists = geo_save_fs[-1].json.gradient.exists(locs) else: exists = geo_save_fs[-1].file.gradient.exists(locs) if not exists: print('No gradient found in save filesys. Running gradient...') _run = True elif overwrite: print('User specified to overwrite gradient with new run...') _run = True else: _run = False if _run: run_fs = autofile.fs.run(geo_run_path) es_runner.run_job( job='gradient', script_str=script_str, run_fs=run_fs, geom=job_geo, spc_info=spc_info, thy_info=thy_info, overwrite=overwrite, retryfail=retryfail, **kwargs, ) success, ret = es_runner.read_job( job='gradient', run_fs=run_fs, ) if success: inf_obj, inp_str, out_str = ret if is_atom: grad = () else: print(" - Reading gradient from output...") grad = elstruct.reader.gradient(inf_obj.prog, out_str) print(" - Saving gradient...") if _json_database(geo_save_path): geo_save_fs[-1].json.gradient_info.write(inf_obj, locs) geo_save_fs[-1].json.gradient_input.write( inp_str, locs) geo_save_fs[-1].json.gradient.write(grad, locs) else: geo_save_fs[-1].file.gradient_info.write(inf_obj, locs) geo_save_fs[-1].file.gradient_input.write( inp_str, locs) geo_save_fs[-1].file.gradient.write(grad, locs) print(" - Save path: {}".format(geo_save_path)) else: print('Gradient found and saved previously at {}'.format( geo_save_path)) else: print('Species is an atom. Skipping gradient task.')
def run_energy(zma, geo, spc_info, thy_info, geo_save_fs, geo_run_path, geo_save_path, locs, script_str, overwrite, retryfail=True, highspin=False, **kwargs): """ Find the energy for the given structure """ # geo_save_fs and locs unneeded for this _, _ = geo_save_fs, locs # Prepare unique filesystem since many energies may be under same directory if not highspin: sp_run_fs = autofile.fs.single_point(geo_run_path) sp_save_fs = autofile.fs.single_point(geo_save_path) else: sp_run_fs = autofile.fs.high_spin(geo_run_path) sp_save_fs = autofile.fs.high_spin(geo_save_path) sp_run_fs[-1].create(thy_info[1:4]) sp_run_path = sp_run_fs[-1].path(thy_info[1:4]) sp_save_fs[-1].create(thy_info[1:4]) sp_save_path = sp_save_fs[-1].path(thy_info[1:4]) run_fs = autofile.fs.run(sp_run_path) # Set input geom if geo is not None: job_geo = geo else: job_geo = zma exists = sp_save_fs[-1].file.energy.exists(thy_info[1:4]) if not exists: print('No energy found in save filesys. Running energy...') _run = True elif overwrite: print('User specified to overwrite energy with new run...') _run = True else: _run = False if _run: # Add options matrix for energy runs for molpro if thy_info[0] == 'molpro2015': errs, optmat = es_runner.molpro_opts_mat(spc_info, geo) else: errs = () optmat = () es_runner.run_job( job='energy', script_str=script_str, run_fs=run_fs, geom=job_geo, spc_info=spc_info, thy_info=thy_info, errors=errs, options_mat=optmat, overwrite=overwrite, retryfail=retryfail, **kwargs, ) success, ret = es_runner.read_job( job='energy', run_fs=run_fs, ) if success: inf_obj, inp_str, out_str = ret print(" - Reading energy from output...") ene = elstruct.reader.energy(inf_obj.prog, inf_obj.method, out_str) print("Energy: {}".format(ene)) print(" - Saving energy...") sp_save_fs[-1].file.input.write(inp_str, thy_info[1:4]) sp_save_fs[-1].file.info.write(inf_obj, thy_info[1:4]) sp_save_fs[-1].file.energy.write(ene, thy_info[1:4]) print(" - Save path: {}".format(sp_save_path)) else: print('Energy found and saved previously at {}'.format( sp_save_path)) ene = sp_save_fs[-1].file.energy.read(thy_info[1:4]) print("Energy: {}".format(ene))
def run_vpt2(zma, geo, spc_info, thy_info, geo_save_fs, geo_run_path, geo_save_path, locs, script_str, overwrite, retryfail=True, **kwargs): """ Perform vpt2 analysis for the geometry in the given location """ # Set the run filesystem information run_fs = autofile.fs.run(geo_run_path) # Assess if symmetry needs to be broken for the calculation # Add porgram check because might only be issue for gaussian if spc_info[0] in symm.HIGH: if zma is not None: disp = symm.HIGH[spc_info[0]] * phycon.ANG2BOHR vals = automol.zmatrix.values(zma) job_geo = automol.zmatrix.set_values( zma, {'R1': vals['R1'] + disp}) is_atom = automol.geom.is_atom( automol.zmatrix.geometry(job_geo)) else: print('Need a zma for high-symmetry of {}.'.format(spc_info[0]), 'Skipping task') job_geo = None is_atom = False else: if zma is not None: job_geo = zma is_atom = automol.geom.is_atom(automol.zmatrix.geometry(job_geo)) else: job_geo = geo is_atom = automol.geom.is_atom(job_geo) if is_atom: print('Species is an atom, Skipping VPT2 task.') if job_geo is not None and not is_atom: exists = geo_save_fs[-1].file.anharmonicity_matrix.exists(locs) if not exists: print('No X-Matrix found in save filesys. Running VPT2...') _run = True elif overwrite: print('User specified to overwrite VPT2 info with new run...') _run = True else: _run = False if _run: es_runner.run_job( job='vpt2', script_str=script_str, run_fs=run_fs, geom=job_geo, spc_info=spc_info, thy_info=thy_info, overwrite=overwrite, retryfail=retryfail, **kwargs, ) success, ret = es_runner.read_job( job='vpt2', run_fs=run_fs, ) if success: inf_obj, inp_str, out_str = ret # if not geo_save_fs[-1].file.hessian.exists(locs): # print(" - No Hessian in filesys.", # "Reading it from output...") # hess = elstruct.reader.hessian(inf_obj.prog, out_str) # print(" - Saving Hessian...") # print(" - Save path: {}".format(geo_save_path)) # geo_save_fs[-1].file.hessian_info.write(inf_obj, locs) # geo_save_fs[-1].file.hessian_input.write(inp_str, locs) # geo_save_fs[-1].file.hessian.write(hess, locs) print(" - Reading anharmonicities from output...") vpt2_dct = elstruct.reader.vpt2(inf_obj.prog, out_str) # hess = elstruct.reader.hessian(inf_obj.prog, out_str) # Write the VPT2 file specifying the Fermi Treatments # fermi_treatment = '{} Defaults'.format(inf_obj.prog) # vpt2_inf_obj = autofile.schema.info.vpt2( # fermi_treatment=fermi_treatment) print(" - Saving anharmonicities...") print(" - Save path: {}".format(geo_save_path)) # geo_save_fs[-1].file.vpt2_info.write(inf_obj, locs) geo_save_fs[-1].file.vpt2_input.write(inp_str, locs) geo_save_fs[-1].file.anharmonic_frequencies.write( vpt2_dct['freqs'], locs) geo_save_fs[-1].file.anharmonic_zpve.write( vpt2_dct['zpve'], locs) geo_save_fs[-1].file.vibro_rot_alpha_matrix.write( vpt2_dct['vibrot_mat'], locs) geo_save_fs[-1].file.quartic_centrifugal_dist_consts.write( vpt2_dct['cent_dist_const'], locs) geo_save_fs[-1].file.anharmonicity_matrix.write( vpt2_dct['x_mat'], locs) else: print('VPT2 information found and saved previously at {}'.format( geo_save_path))
def _run_scan(guess_zma, spc_info, mod_thy_info, thy_save_fs, coord_names, grid_vals, scn_run_fs, scn_save_fs, scn_typ, script_str, overwrite, errors=(), options_mat=(), retryfail=True, update_guess=True, saddle=False, constraint_dct=None, chkstab=False, **kwargs): """ new run function """ # Get a connected geometry from the init guess_zma for instability checks # conn_geo = automol.zmatrix.geometry(guess_zma) conn_zma = guess_zma # Set the frozen coordinates (set job at this point?) if constraint_dct is not None: frozen_coordinates = tuple(coord_names) + tuple(constraint_dct) else: frozen_coordinates = coord_names # Read the energies and Hessians from the filesystem for vals in grid_vals: # Set the locs for the scan point locs = [coord_names, vals] if constraint_dct is not None: locs = [constraint_dct] + locs # Create the filesys scn_run_fs[-1].create(locs) run_fs = autofile.fs.run(scn_run_fs[-1].path(locs)) # Build the zma zma = automol.zmatrix.set_values( guess_zma, dict(zip(coord_names, vals))) # Set the job job = _set_job(scn_typ) # Run an optimization or energy job, as needed. geo_exists = scn_save_fs[-1].file.geometry.exists(locs) if not geo_exists or overwrite: if job == elstruct.Job.OPTIMIZATION: es_runner.run_job( job=job, script_str=script_str, run_fs=run_fs, geom=zma, spc_info=spc_info, thy_info=mod_thy_info, overwrite=overwrite, frozen_coordinates=frozen_coordinates, errors=errors, options_mat=options_mat, retryfail=retryfail, saddle=saddle, **kwargs ) # Read the output for the zma and geo _, opt_zma, opt_geo = filesys.read_zma_geo(run_fs, job) if opt_zma is not None and opt_geo is not None: # Check connectivity, save instability files if needed if chkstab: connected = automol.geom.connected(opt_geo) else: connected = True # If connected and update requested: update geom # If disconnected: save instab files and break loop if connected: if update_guess: guess_zma = opt_zma else: print('WARNING: Structure seems to be unstable...') # _, opt_ret = es_runner.read_job(job=job, run_fs=run_fs) # instab.write_instab( # conn_zma, opt_zma, # thy_save_fs, mod_thy_info[1:4], # opt_ret, # zma_locs=(0,), # save_cnf=False # ) # break else: print('No output found in file') elif job == elstruct.Job.ENERGY: es_runner.run_job( job=job, script_str=script_str, run_fs=run_fs, geom=zma, spc_info=spc_info, thy_info=mod_thy_info, overwrite=overwrite, errors=errors, options_mat=options_mat, retryfail=retryfail, **kwargs ) # Run read_job to print status message _, _ = es_runner.read_job(job=job, run_fs=run_fs) # Write initial geos in run fs as they are needed later run_fs[-1].file.zmatrix.write(zma, [job]) run_fs[-1].file.geometry.write( automol.zmatrix.geometry(zma), [job])