def read_locs_harmonic_freqs(cnf_fs, cnf_locs, run_prefix, zrxn=None): """ Read the harmonic frequencies for a specific conformer Do the freqs obtain for two species for fake and pst? """ if cnf_locs is not None: geo_exists = cnf_fs[-1].file.geometry.exists(cnf_locs) hess_exists = cnf_fs[-1].file.hessian.exists(cnf_locs) if not geo_exists: ioprinter.error_message( 'No Reference geometry for harmonic frequencies at path', cnf_fs[-1].file.hessian.path(cnf_locs)) if not hess_exists: ioprinter.error_message( 'No Hessian available for harmonic frequencies at path', cnf_fs[-1].file.hessian.path(cnf_locs)) else: geo_exists, hess_exists = False, False if geo_exists and hess_exists: # Obtain geom and freqs from filesys geo = cnf_fs[-1].file.geometry.read(cnf_locs) hess = cnf_fs[-1].file.hessian.read(cnf_locs) ioprinter.reading('Hessian', cnf_fs[-1].path(cnf_locs)) # Build the run filesystem using locs fml_str = automol.geom.formula_string(geo) vib_path = job_path(run_prefix, 'PROJROT', 'FREQ', fml_str) # Obtain the frequencies ioprinter.info_message( 'Calling ProjRot to diagonalize Hessian and get freqs...') script_str = autorun.SCRIPT_DCT['projrot'] freqs, _, imag_freqs, _ = autorun.projrot.frequencies( script_str, vib_path, [geo], [[]], [hess]) # Obtain the displacements norm_coord_str, _ = autorun.projrot.displacements( script_str, vib_path, [geo], [[]], [hess]) # Calculate the zpve ioprinter.frequencies(freqs) zpe = (sum(freqs) / 2.0) * phycon.WAVEN2EH # Check imaginary frequencies and set freqs if zrxn is not None: if len(imag_freqs) > 1: ioprinter.warning_message('Saddle Point has more than', 'one imaginary frequency') imag = imag_freqs[0] else: imag = None ret = (freqs, imag, zpe, norm_coord_str) else: ret = None return ret
def _hess_freqs(geo, geo_save_fs, save_path, locs, run_prefix, overwrite): """ Calculate harmonic frequencies using Hessian """ if _json_database(save_path): exists = geo_save_fs[-1].json.harmonic_frequencies.exists(locs) else: exists = geo_save_fs[-1].file.harmonic_frequencies.exists(locs) if not exists: ioprinter.info_message( 'No harmonic frequencies found in save filesys...') _run = True elif overwrite: ioprinter.info_message( 'User specified to overwrite frequencies with new run...') _run = True else: _run = False if _run: # Read the Hessian from the filesystem if _json_database(save_path): hess = geo_save_fs[-1].json.hessian.read(locs) else: hess = geo_save_fs[-1].file.hessian.read(locs) # Calculate and save the harmonic frequencies ioprinter.info_message( " - Calculating harmonic frequencies from Hessian...") script_str = autorun.SCRIPT_DCT['projrot'] fml_str = automol.geom.formula_string(geo) vib_path = job_path(run_prefix, 'PROJROT', 'FREQ', fml_str) rt_freqs, _, rt_imags, _ = autorun.projrot.frequencies( script_str, vib_path, [geo], [[]], [hess]) rt_imags = tuple(-1 * imag_freq for imag_freq in rt_imags) freqs = sorted(rt_imags + rt_freqs) ioprinter.frequencies(freqs) ioprinter.geometry(geo) if _json_database(save_path): geo_save_fs[-1].json.harmonic_frequencies.write(freqs, locs) else: geo_save_fs[-1].file.harmonic_frequencies.write(freqs, locs) ioprinter.save_frequencies(save_path) else: ioprinter.existing_path('Harmonic frequencies', save_path) freqs = geo_save_fs[-1].file.harmonic_frequencies.read(locs) ioprinter.frequencies(freqs)
def read_locs_harmonic_freqs(cnf_fs, harm_path, cnf_locs, run_prefix, zrxn=None): """ Read the harmonic frequencies for a specific conformer """ # probably should read freqs # Do the freqs obtain for two species for fake and pst if cnf_locs is not None: # Obtain geom and freqs from filesys geo = cnf_fs[-1].file.geometry.read(cnf_locs) hess = cnf_fs[-1].file.hessian.read(cnf_locs) ioprinter.reading('Hessian', cnf_fs[-1].path(cnf_locs)) # Build the run filesystem using locs fml_str = automol.geom.formula_string(geo) vib_path = job_path(run_prefix, 'PROJROT', 'FREQ', fml_str) # Obtain the frequencies ioprinter.info_message( 'Calling ProjRot to diagonalize Hessian and get freqs...') script_str = autorun.SCRIPT_DCT['projrot'] freqs, _, imag_freqs, _ = autorun.projrot.frequencies( script_str, vib_path, [geo], [[]], [hess]) # Calculate the zpve ioprinter.frequencies(freqs) zpe = (sum(freqs) / 2.0) * phycon.WAVEN2EH # Check imaginary frequencies and set freqs if zrxn is not None: if len(imag_freqs) > 1: ioprinter.warning_message('Saddle Point has more than', 'one imaginary frequency') imag = imag_freqs[0] else: imag = None else: ioprinter.error_message( 'Reference geometry is missing for harmonic frequencies') return freqs, imag, zpe
def _assess_imags(freqs, ref_freqs, cnf_run_fs, cnf_save_fs, locs): """ Check if the frequencies signal a bad transition state """ # Initialize success variable to be changed if needed success = True # Assume first (lowest) frequency is the imaginary mode imags = tuple(x for x in freqs if x < 0.0) imag_freq, ref_imag_freq = abs(imags[0]), abs(ref_freqs[0]) print('\nChecking imaginary mode of potential saddle-point conformer ' '(frequencies below)\n' f'versus reference imaginary mode {ref_imag_freq:.1f} cm-1.') ioprinter.frequencies(freqs) print('Checking if deviation from reference mode less than 100.0 cm-1') imag_diff = abs(imag_freq - ref_imag_freq) if imag_diff <= 100.0: print(f' - Deviation = {imag_diff:.1f} cm-1. Small, likely fine.') else: print(f' - Deviation = {imag_diff:1f} cm-1. Large, could be bad') print(' - Checking if value of mode greater than 150.0 cm-1') if imag_freq >= 150.0: print(f' - Mode = {imag_freq:.1f} cm-1. Large, likely fine\n') else: print(f' - Mode = {imag_freq:.1f} cm-1. Small, likely bad\n') success = False if success: print('Frequencies appear fine. Proceeding to save Hessian info.') else: cnf_run_path = cnf_run_fs[-1].path(locs) cnf_save_path = cnf_save_fs[-1].path(locs) shutil.rmtree(cnf_run_path) shutil.rmtree(cnf_save_path) print('Based on checks, saddle-point conformer likely bad. ' 'Removing conformer from both RUN and SAVE filesystem at\n' f'{cnf_run_path}\n' f'{cnf_save_path}\n') return success
def conformer_tsk(job, spc_dct, spc_name, thy_dct, es_keyword_dct, run_prefix, save_prefix, print_debug=False): """ Prepares and executes all electronic structure tasks that generate information for species and transition state conformers. This includes sampling and optimization procedures to generate conformer structures, as well as __ calculations using some saved conformer as input. :param job(subtask): calculatiion(s) to perform for conformer :type job: str :param spc_dct: :type spc_dct: :param spc_name: name of species :type spc_name: str :param thy_dct: :type thy_dct: :param es_keyword_dct: keyword-values for electronic structure task :type es_keyword_dct: dict[str:str] :param run_prefix: root-path to the run-filesystem :type run_prefix: str :param save_prefix: root-path to the save-filesystem :type save_prefix: str """ saddle = bool('ts_' in spc_name) spc_dct_i = spc_dct[spc_name] # Set the spc_info if not saddle: spc_info = sinfo.from_dct(spc_dct_i) else: spc_info = rinfo.ts_info(spc_dct_i['rxn_info']) zrxn = spc_dct_i.get('zrxn', None) overwrite = es_keyword_dct['overwrite'] retryfail = es_keyword_dct['retryfail'] nprocs = 1 # Modify the theory method_dct = thy_dct.get(es_keyword_dct['runlvl']) ini_method_dct = thy_dct.get(es_keyword_dct['inplvl']) thy_info = tinfo.from_dct(method_dct) ini_thy_info = tinfo.from_dct(ini_method_dct) mod_thy_info = tinfo.modify_orb_label(thy_info, spc_info) mod_ini_thy_info = tinfo.modify_orb_label(ini_thy_info, spc_info) # New filesystem objects _root = root_locs(spc_dct_i, saddle=saddle, name=spc_name) ini_cnf_run_fs, ini_cnf_save_fs = build_fs(run_prefix, save_prefix, 'CONFORMER', thy_locs=mod_ini_thy_info[1:], **_root) cnf_run_fs, cnf_save_fs = build_fs(run_prefix, save_prefix, 'CONFORMER', thy_locs=mod_thy_info[1:], **_root) if job == 'samp': # Build the ini zma filesys user_conf_ids = spc_dct_i.get('conf_id') if user_conf_ids is None: ini_loc_info = filesys.mincnf.min_energy_conformer_locators( ini_cnf_save_fs, mod_ini_thy_info) ini_locs, ini_min_cnf_path = ini_loc_info else: print(f'Using user specified conformer IDs: {user_conf_ids}') ini_locs = user_conf_ids if any(ini_locs): ini_zma_save_fs = autofile.fs.zmatrix(ini_min_cnf_path) # Set up the run scripts script_str, kwargs = qchem_params(method_dct, elstruct.Job.OPTIMIZATION) # Set variables if it is a saddle two_stage = saddle mc_nsamp = spc_dct_i['mc_nsamp'] resave = es_keyword_dct['resave'] # Read the geometry and zma from the ini file system geo = ini_cnf_save_fs[-1].file.geometry.read(ini_locs) zma = ini_zma_save_fs[-1].file.zmatrix.read([0]) # Read the torsions from the ini file sys if ini_zma_save_fs[-1].file.torsions.exists([0]): tors_dct = ini_zma_save_fs[-1].file.torsions.read([0]) rotors = automol.rotor.from_data(zma, tors_dct) tors_names = automol.rotor.names(rotors, flat=True) else: tors_names = () geo_path = ini_cnf_save_fs[-1].path(ini_locs) ioprinter.initial_geom_path('Sampling started', geo_path) # Check runsystem for equal ring CONF make conf_fs # Else make new ring conf directory rid = conformer.rng_loc_for_geo(geo, cnf_save_fs) if rid is None: conformer.single_conformer(zma, spc_info, mod_thy_info, cnf_run_fs, cnf_save_fs, script_str, overwrite, retryfail=retryfail, zrxn=zrxn, **kwargs) rid = conformer.rng_loc_for_geo(geo, cnf_save_fs) # Run the sampling conformer.conformer_sampling(zma, spc_info, mod_thy_info, cnf_run_fs, cnf_save_fs, rid, script_str, overwrite, nsamp_par=mc_nsamp, tors_names=tors_names, zrxn=zrxn, two_stage=two_stage, retryfail=retryfail, resave=resave, repulsion_thresh=40.0, print_debug=print_debug, **kwargs) else: ioprinter.info_message('Missing conformers. Skipping task...') elif job == 'pucker': # Build the ini zma filesys ini_loc_info = filesys.mincnf.min_energy_conformer_locators( ini_cnf_save_fs, mod_ini_thy_info) ini_min_locs, ini_min_cnf_path = ini_loc_info ini_zma_save_fs = autofile.fs.zmatrix(ini_min_cnf_path) # Set up the run scripts script_str, kwargs = qchem_params(method_dct, elstruct.Job.OPTIMIZATION) # Set variables if it is a saddle two_stage = saddle mc_nsamp = spc_dct_i['mc_nsamp'] # Read the geometry and zma from the ini file system geo = ini_cnf_save_fs[-1].file.geometry.read(ini_min_locs) zma = ini_zma_save_fs[-1].file.zmatrix.read([0]) # Read the torsions from the ini file sys if ini_zma_save_fs[-1].file.ring_torsions.exists([0]): ring_tors_dct = ini_zma_save_fs[-1].file.ring_torsions.read([0]) else: ring_tors_dct = {} geo_path = ini_cnf_save_fs[-1].path(ini_min_locs) ioprinter.initial_geom_path('Sampling started', geo_path) # Run the sampling conformer.ring_conformer_sampling(zma, spc_info, mod_thy_info, cnf_run_fs, cnf_save_fs, script_str, overwrite, nsamp_par=mc_nsamp, ring_tors_dct=ring_tors_dct, zrxn=zrxn, two_stage=two_stage, retryfail=retryfail, **kwargs) elif job == 'opt': cnf_range = es_keyword_dct['cnf_range'] hbond_cutoffs = spc_dct_i['hbond_cutoffs'] cnf_sort_info_lst = _sort_info_lst(es_keyword_dct['sort'], thy_dct, spc_info) # Set up the run scripts script_str, kwargs = qchem_params(method_dct, elstruct.Job.OPTIMIZATION) rng_cnf_locs_lst, _ = filesys.mincnf.conformer_locators( cnf_save_fs, mod_thy_info, cnf_range='all', nprocs=nprocs) ini_rng_cnf_locs_lst, _ = filesys.mincnf.conformer_locators( ini_cnf_save_fs, mod_ini_thy_info, cnf_range=cnf_range, sort_info_lst=cnf_sort_info_lst, hbond_cutoffs=hbond_cutoffs, print_enes=True, nprocs=nprocs) # Truncate the list of the ini confs uni_rng_locs_lst, uni_cnf_locs_lst = conformer.unique_fs_ring_confs( cnf_save_fs, rng_cnf_locs_lst, ini_cnf_save_fs, ini_rng_cnf_locs_lst) # ioprinter.debug_message( # 'uni lst that has no similar ring', uni_rng_locs_lst) # ioprinter.debug_message( # 'uni lst that has similar ring', uni_cnf_locs_lst) for locs in uni_rng_locs_lst: rid, cid = locs # Obtain the zma from ini loc ini_cnf_save_path = ini_cnf_save_fs[-1].path(locs) ini_zma_save_fs = autofile.fs.zmatrix(ini_cnf_save_path) zma = ini_zma_save_fs[-1].file.zmatrix.read((0, )) # Make the ring filesystem conformer.single_conformer(zma, spc_info, mod_thy_info, cnf_run_fs, cnf_save_fs, script_str, overwrite, retryfail=retryfail, zrxn=zrxn, use_locs=locs, **kwargs) for locs in uni_cnf_locs_lst: ini_locs, rid = locs # Obtain the zma from ini loc ini_cnf_save_path = ini_cnf_save_fs[-1].path(ini_locs) ini_zma_save_fs = autofile.fs.zmatrix(ini_cnf_save_path) zma = ini_zma_save_fs[-1].file.zmatrix.read((0, )) # obtain conformer filesys associated with ring at the runlevel cid = autofile.schema.generate_new_conformer_id() conformer.single_conformer(zma, spc_info, mod_thy_info, cnf_run_fs, cnf_save_fs, script_str, overwrite, retryfail=retryfail, zrxn=zrxn, use_locs=(rid, cid), **kwargs) # print all geometres within cnfrange rng_cnf_locs_lst, _ = filesys.mincnf.conformer_locators( cnf_save_fs, mod_thy_info, cnf_range=cnf_range, sort_info_lst=cnf_sort_info_lst, hbond_cutoffs=hbond_cutoffs, nprocs=nprocs) for locs in rng_cnf_locs_lst: geo = cnf_save_fs[-1].file.geometry.read(locs) ioprinter.geometry(geo) elif job in ('energy', 'grad', 'hess', 'vpt2', 'prop'): cnf_range = es_keyword_dct['cnf_range'] hbond_cutoffs = spc_dct_i['hbond_cutoffs'] cnf_sort_info_lst = _sort_info_lst(es_keyword_dct['sort'], thy_dct, spc_info) user_conf_ids = spc_dct_i.get('conf_id') if user_conf_ids is None: ini_rng_cnf_locs_lst, _ = filesys.mincnf.conformer_locators( ini_cnf_save_fs, mod_ini_thy_info, cnf_range=cnf_range, sort_info_lst=cnf_sort_info_lst, hbond_cutoffs=hbond_cutoffs, print_enes=True, nprocs=nprocs) else: print(f'Using user specified conformer IDs: {user_conf_ids}') ini_rng_cnf_locs_lst = (user_conf_ids, ) # Check if locs exist, kill if it doesn't if not ini_rng_cnf_locs_lst: ioprinter.error_message('No min-energy conformer found for level:') else: # Set up the run scripts script_str, kwargs = qchem_params(method_dct) # Grab frequencies for the reference, print ref freqs if job == 'hess': if ini_cnf_save_fs[-1].file.harmonic_frequencies.exists( ini_rng_cnf_locs_lst[0]): frq = ini_cnf_save_fs[-1].file.harmonic_frequencies.read( ini_rng_cnf_locs_lst[0]) ref_val = frq else: ref_val = None if ref_val is not None and zrxn is not None: ref_path = cnf_save_fs[-1].path(ini_rng_cnf_locs_lst[0]) print('Found reference frequencies for saddle-point ' f'checks for conformer at\n {ref_path}') ioprinter.frequencies(ref_val) else: ref_val = None # Run the job over all the conformers requested by the user print('Going over all requested conformers for task...\n') for ini_locs in ini_rng_cnf_locs_lst: ini_cnf_run_fs[-1].create(ini_locs) geo_save_path = ini_cnf_save_fs[-1].path(ini_locs) ini_zma_save_fs = autofile.fs.zmatrix(geo_save_path) print('Running task for geometry at ', geo_save_path) geo = ini_cnf_save_fs[-1].file.geometry.read(ini_locs) zma = ini_zma_save_fs[-1].file.zmatrix.read((0, )) ES_TSKS[job](zma, geo, spc_info, mod_thy_info, ini_cnf_run_fs, ini_cnf_save_fs, ini_locs, run_prefix, script_str, overwrite, zrxn=zrxn, retryfail=retryfail, method_dct=method_dct, ref_val=ref_val, **kwargs) print('\n === FINISHED CONF ===\n')