def assess_pf_convergence(tau_save_fs, ref_ene, temps=(300., 500., 750., 1000., 1500.)): """ Determine how much the partition function has converged """ # Calculate sigma values at various temperatures for the PF for temp in temps: sumq = 0. sum2 = 0. idx = 0 ioprinter.debug_message('integral convergence for T = ', temp) inf_obj_s = tau_save_fs[0].file.info.read() nsamp = inf_obj_s.nsamp saved_locs = tau_save_fs[-1].existing() ratio = float(nsamp) / len(saved_locs) for locs in tau_save_fs[-1].existing(): idx += 1 ene = tau_save_fs[-1].file.energy.read(locs) ene = (ene - ref_ene) * phycon.EH2KCAL tmp = numpy.exp(-ene*349.7/(0.695*temp)) sumq = sumq + tmp sum2 = sum2 + tmp**2 sigma = numpy.sqrt( (abs(sum2/float(idx)-(sumq/float(idx))**2))/float(idx)) ioprinter.debug_message( sumq/float(idx), sigma, 100.*sigma*float(idx)/sumq, idx) inf_obj_s = tau_save_fs[0].file.info.read() nsamp = inf_obj_s.nsamp saved_locs = tau_save_fs[-1].existing() ratio = len(saved_locs) / float(nsamp) ioprinter.info_message('Ratio of good to sampled geometries: ', ratio)
def scale_rotor_pots(rotors, scale_factor=((), None)): """ scale the pots """ # Count numbers numtors = 0 for rotor in rotors: numtors += len(rotor) # Calculate the scaling factors scale_indcs, factor = scale_factor nscale = numtors - len(scale_indcs) if nscale > 0: sfactor = factor**(2.0/nscale) ioprinter.debug_message( 'scale_coeff test:', factor, nscale, sfactor) # test # sfactor = 1 # test for tidx, rotor in enumerate(rotors): for torsion in rotor: if tidx not in scale_indcs and factor is not None: torsion.pot = automol.pot.scale(torsion.pot, sfactor) # following is being used in a test to see how effective # a scaling of fixed scan torsional pots can be # torsion.pot = automol.pot.relax_scale(torsion.pot) return rotors
def make_pes_label_dct(rxn_lst, pes_idx, spc_dct, spc_mod_dct_i): """ Builds a dictionary that matches the mechanism name to the labels used in the MESS input and output files for the whole PES """ print('spc dct_names', list(spc_dct.keys())) pes_label_dct = {} for rxn in rxn_lst: # Get the wells models rwell_mod = spc_mod_dct_i['ts']['rwells'] pwell_mod = spc_mod_dct_i['ts']['pwells'] # Get thhe name and class chnl_idx, (reacs, prods) = rxn tsname = 'ts_{:g}_{:g}'.format(pes_idx+1, chnl_idx+1) sub_tsname = '{}_{:g}'.format(tsname, 0) rclass = spc_dct[sub_tsname]['zrxn'].class_ # Build labels pes_label_dct.update( _make_channel_label_dct( tsname, rclass, pes_label_dct, chnl_idx, reacs, prods, rwell_mod, pwell_mod)) ioprinter.debug_message('pes_label dct', pes_label_dct) return pes_label_dct
def read_energy(spc_dct_i, pf_filesystems, spc_model_dct_i, run_prefix, read_ene=True, read_zpe=True, conf=None, saddle=False): """ Get the energy for a species on a channel """ # Read the electronic energy and ZPVE e_elec = None if read_ene: e_elec = electronic_energy( spc_dct_i, pf_filesystems, spc_model_dct_i, conf=conf) ioprinter.debug_message('e_elec in models ene ', e_elec) e_zpe = None if read_zpe: e_zpe = zero_point_energy( spc_dct_i, pf_filesystems, spc_model_dct_i, run_prefix, saddle=saddle) ioprinter.debug_message('zpe in models ene ', e_zpe) # Return the total energy requested ene = None if read_ene and read_zpe: if e_elec is not None and e_zpe is not None: ene = e_elec + e_zpe elif read_ene and not read_zpe: ene = e_elec elif read_ene and not read_zpe: ene = e_zpe return ene
def scale_1d(spc_mod_dct_i): """ determine if we need to scale the potential """ ioprinter.debug_message('tors model in scale set', spc_mod_dct_i['tors']['mod']) return (bool(spc_mod_dct_i['tors']['mod'] in ('1dhrfa', '1dhrf', '1dhr')) and spc_mod_dct_i['tors']['scale'] == 'on')
def rpath_ref_idx(ts_dct, scn_vals, coord_name, scn_prefix, ene_info1, ene_info2): """ Get the reference energy along a reaction path """ # Set up the filesystem zma_fs = autofile.fs.zmatrix(scn_prefix) zma_path = zma_fs[-1].path([0]) scn_fs = autofile.fs.scan(zma_path) ene_info1 = ene_info1[1][0][1] ene_info2 = ene_info2[0] ioprinter.debug_message('mod_eneinf1', ene_info1) ioprinter.debug_message('mod_eneinf2', ene_info2) mod_ene_info1 = tinfo.modify_orb_label(sinfo.from_dct(ts_dct), ene_info1) mod_ene_info2 = tinfo.modify_orb_label(sinfo.from_dct(ts_dct), ene_info2) ene1, ene2, ref_val = None, None, None for val in reversed(scn_vals): locs = [[coord_name], [val]] path = scn_fs[-1].path(locs) hs_fs = autofile.fs.high_spin(path) if hs_fs[-1].file.energy.exists(mod_ene_info1[1:4]): ene1 = hs_fs[-1].file.energy.read(mod_ene_info1[1:4]) if hs_fs[-1].file.energy.exists(mod_ene_info2[1:4]): ene2 = hs_fs[-1].file.energy.read(mod_ene_info2[1:4]) if ene1 is not None and ene2 is not None: ref_val = val break if ref_val is not None: scn_idx = scn_vals.index(ref_val) return scn_idx, ene1, ene2
def saddle_point_checker(imags): """ run things for checking Hessian """ big_imag, kick_imag = 0, 0 ioprinter.checking('the imaginary frequencies of the saddle point...') if len(imags) < 1: ioprinter.warning_message('No imaginary modes for geometry') status = 'fail' else: if len(imags) > 1: ioprinter.warning_message('More than one imaginary mode for geometry') for idx, imag in enumerate(imags): if imag <= 50.0: ioprinter.warning_message('Mode {} {} cm-1 is low,'.format(str(idx+1), imag)) elif 50.0 < imag <= 200.0: lowstr = 'Mode {} {} cm-1 is low,'.format(str(idx+1), imag) ioprinter.warning_message(lowstr + 'need a kickoff procedure to remove') kick_imag += 1 else: ioprinter.debug_message('Mode {} {} cm-1 likely fine,'.format(str(idx+1), imag)) big_imag += 1 if big_imag > 1: ioprinter.warning_message('WARNING: More than one imaginary mode for geometry') if kick_imag >= 1: ioprinter.debug_message('Will kickoff to get saddle point') status = 'kickoff' elif big_imag == 1: status = 'success' return status
def make_pes_label_dct(rxn_lst, pes_idx, spc_dct, spc_mod_dct_i): """ Loop over all of the reaction channels of the PES to build a dictionary that systematically maps the mechanism names of all species and transition states to formatted labels used to designate each as a well, bimol, or barrier component in a MESS input file. """ pes_label_dct = {} for rxn in rxn_lst: # Get the wells models rwell_mod = spc_mod_dct_i['ts']['rwells'] pwell_mod = spc_mod_dct_i['ts']['pwells'] # Get thhe name and class chnl_idx, (reacs, prods) = rxn tsname = 'ts_{:g}_{:g}'.format(pes_idx + 1, chnl_idx + 1) sub_tsname = '{}_{:g}'.format(tsname, 0) rclass = spc_dct[sub_tsname]['class'] # Build labels pes_label_dct.update( _make_channel_label_dct(tsname, rclass, pes_label_dct, chnl_idx, reacs, prods, rwell_mod, pwell_mod)) ioprinter.debug_message('pes_label dct', pes_label_dct) return pes_label_dct
def _read_basis_energy(ich_name_dct, spc_dct, uni_refs_dct, spc_model_dct_i, run_prefix, save_prefix, ichs, output_queue=None): h_basis_dct = {} print(f'Process {os.getpid()} reading energy for species: {ichs}') for ich in ichs: name = ich_name_dct[ich] if name in spc_dct: spc_dct_i = spc_dct[name] prname = name elif name in uni_refs_dct: spc_dct_i = uni_refs_dct[name] prname = name if 'ts' in name or 'TS' in name: reacs, prods = ich.split('PRODS') reacs = reacs.replace('REACS', '') reacs = reacs.split('REAC') prods = prods.split('PROD') reac_lbl = 'r0' if len(reacs) > 1: reac_lbl += '+r1' prod_lbl = 'p0' if len(prods) > 1: prod_lbl += '+p1' ioprinter.info_message( f'Basis Reaction: {reac_lbl}={prod_lbl} 1 1 1 ') for i, reac in enumerate(reacs): ioprinter.info_message( f'r{i},{reac},{automol.inchi.smiles(reac)},1') for i, prod in enumerate(prods): ioprinter.info_message( f'p{i},{prod},{automol.inchi.smiles(prod)},1') ioprinter.debug_message('bases energies test:', ich, name) pf_filesystems = filesys.models.pf_filesys( spc_dct_i, spc_model_dct_i, run_prefix, save_prefix, saddle=('ts' in name or 'TS' in name), name=name) ioprinter.info_message(f'Calculating energy for basis {prname}...', newline=1) h_basis_dct[ich] = read_energy(spc_dct_i, pf_filesystems, spc_model_dct_i, run_prefix, read_ene=True, read_zpe=True, saddle='ts' in name or 'TS' in name) output_queue.put((h_basis_dct, ))
def run_tsk(tsk, spc_dct, spc_name, thy_dct, es_keyword_dct, run_prefix, save_prefix): """ run an electronic structure task for generating a list of conformer or tau sampling geometries """ # Print the head of the task ioprinter.task_header(tsk, spc_name) ioprinter.keyword_list(es_keyword_dct, thy_dct) # If species is unstable, set task to 'none' ini_method_dct = thy_dct.get(es_keyword_dct['inplvl']) ini_thy_info = tinfo.from_dct(ini_method_dct) stable = True if 'ts' not in spc_name and tsk != 'init_geom': zrxn, path = filesys.read.instability_transformation( spc_dct, spc_name, ini_thy_info, save_prefix) stable = bool(zrxn is None) if stable: ioprinter.debug_message('- Proceeding with requested task...') # Get stuff from task job = tsk.split('_', 1)[1] # Run the task if an initial geom exists if 'init' in tsk and not skip_task(spc_dct, spc_name): _ = geom_init(spc_dct, spc_name, thy_dct, es_keyword_dct, run_prefix, save_prefix) elif 'conf' in tsk and not skip_task(spc_dct, spc_name): conformer_tsk(job, spc_dct, spc_name, thy_dct, es_keyword_dct, run_prefix, save_prefix) elif 'tau' in tsk and not skip_task(spc_dct, spc_name): tau_tsk(job, spc_dct, spc_name, thy_dct, es_keyword_dct, run_prefix, save_prefix) elif 'hr' in tsk and not skip_task(spc_dct, spc_name): hr_tsk(job, spc_dct, spc_name, thy_dct, es_keyword_dct, run_prefix, save_prefix) elif 'rpath' in tsk and not skip_task(spc_dct, spc_name): pass elif 'irc' in tsk and not skip_task(spc_dct, spc_name): irc_tsk(job, spc_dct, spc_name, thy_dct, es_keyword_dct, run_prefix, save_prefix) elif 'find' in tsk: findts(job, spc_dct, spc_name, thy_dct, es_keyword_dct, run_prefix, save_prefix) else: ioprinter.info_message('Skipping task for unstable species...', newline=1)
def _kickoff_saddle(geo, norm_coords, size=0.1, backward=False, mode=0): """ kickoff from saddle to find connected minima """ # Choose the displacement xyzs and set kickoff direction and size kickoff = size if not backward else -1.0*size disp_xyzs = norm_coords[mode] disp_xyzs = numpy.multiply(disp_xyzs, kickoff) disp_geo = automol.geom.translate_along_matrix(geo, disp_xyzs) ioprinter.debug_message( f'Creating displacement geometry with kickoff size of {kickoff}' f'\ninitial geometry:\n{automol.geom.string(geo)}' f'\ndisplaced geometry:\n{automol.geom.string(disp_geo)}' ) return disp_geo
def _kickoff_saddle(geo, norm_coords, spc_info, mod_thy_info, run_fs, opt_script_str, kickoff_size=0.1, kickoff_backward=False, kickoff_mode=0, opt_cart=True, **kwargs): """ kickoff from saddle to find connected minima """ # Choose the displacement xyzs disp_xyzs = norm_coords[kickoff_mode] # 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) ioprinter.debug_message( 'geo test in kickoff_saddle:', 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) success, ret = es_runner.execute_job( job=elstruct.Job.OPTIMIZATION, script_str=opt_script_str, run_fs=run_fs, geo=geom, spc_info=spc_info, thy_info=mod_thy_info, overwrite=True, **kwargs, ) if success: inf_obj, _, out_str = ret prog = inf_obj.prog geo = elstruct.reader.opt_geometry(prog, out_str) return geo, ret
def get_matching_tors_locs(spc_model_dct_i, spc_dct_i, harm_filesys, run_prefix, save_prefix, saddle=False, nprocs=1): """get a list of locations in at the scan level filesystem that match the conformer locations at the vib level filesystem """ cnf_save_fs, cnf_path, cnf_locs, _, _ = harm_filesys if spc_model_dct_i['tors']['geolvl'] != spc_model_dct_i['vib']['geolvl']: tors_run_fs, tors_save_fs, tors_locs_lst = get_all_tors_locs_lst( spc_dct_i, spc_model_dct_i, run_prefix, save_prefix, saddle, nprocs=nprocs) match_dct = fs_confs_dict(tors_save_fs, tors_locs_lst, cnf_save_fs, [cnf_locs]) if match_dct[tuple(cnf_locs)] is not None: match_tors_locs = tuple(match_dct[tuple(cnf_locs)]) match_path = tors_save_fs[-1].path(match_tors_locs) ioprinter.info_message( f'Using {cnf_path} as the parent conformer location') ioprinter.info_message(f'and {match_path} for torsional profiles') else: cnf_zma_save_fs = autofile.fs.zmatrix(cnf_path) zma = cnf_zma_save_fs[-1].file.zmatrix.read((0, )) save_locs = tors_save_fs[-1].existing() _, sym_locs_lst = this_conformer_was_run_in_run(zma, tors_run_fs) for sym_locs in sym_locs_lst: if sym_locs in save_locs: match_tors_locs = sym_locs match_path = tors_save_fs[-1].path(match_tors_locs) ioprinter.debug_message( 'this conformer had converged to another conformer at' f'{match_path}') else: match_tors_locs = cnf_locs return match_tors_locs
def _obtain_ini_geom(spc_dct_i, ini_cnf_save_fs, mod_ini_thy_info, overwrite): """ Obtain an initial geometry to be optimized. Checks a hieratchy of places to obtain the initial geom. (1) Geom dict which is the input from the user (2) Geom from inchi """ geo_init = None # Obtain geom from thy fs or remove the conformer filesystem if needed if not overwrite: ini_min_locs, ini_path = filesys.mincnf.min_energy_conformer_locators( ini_cnf_save_fs, mod_ini_thy_info) if ini_path: geo_init = ini_cnf_save_fs[-1].file.geometry.read(ini_min_locs) ioprinter.info_message( 'Getting inital geometry from inplvl at path', '{}'.format(ini_cnf_save_fs[-1].path(ini_min_locs))) else: ioprinter.debug_message( 'Removing original conformer save data for instability') for locs in ini_cnf_save_fs[-1].existing(): cnf_path = ini_cnf_save_fs[-1].path(locs) ioprinter.debug_message('Removing {}'.format(cnf_path)) shutil.rmtree(cnf_path) if geo_init is None: if 'geo_inp' in spc_dct_i: geo_init = spc_dct_i['geo_inp'] ioprinter.info_message( 'Getting initial geometry from geom dictionary') if geo_init is None: geo_init = automol.inchi.geometry(spc_dct_i['inchi']) ioprinter.info_message('Getting initial geometry from inchi') # Check if the init geometry is connected if geo_init is not None: if not automol.geom.connected(geo_init): geo_init = None return geo_init
def make_messrate_str(pes_idx, rxn_lst, pes_model, spc_model, spc_dct, thy_dct, pes_model_dct, spc_model_dct, label_dct, mess_path, run_prefix, save_prefix): """ Combine various MESS strings together to combined MESS rates spc model could become a list for channel combinations """ pes_model_dct_i = pes_model_dct[pes_model] spc_model_dct_i = spc_model_dct[spc_model] # Write the strings for the MESS input file globkey_str = make_header_str( spc_dct, temps=pes_model_dct_i['rate_temps'], pressures=pes_model_dct_i['pressures']) # Write the energy transfer section strings for MESS file etransfer = pes_model_dct_i['glob_etransfer'] energy_trans_str = make_global_etrans_str( rxn_lst, spc_dct, etransfer) # Write the MESS strings for all the PES channels rxn_chan_str, dats, _, _ = make_pes_mess_str( spc_dct, rxn_lst, pes_idx, run_prefix, save_prefix, label_dct, pes_model_dct_i, spc_model_dct_i, spc_model, thy_dct) # Combine strings together mess_inp_str = mess_io.writer.messrates_inp_str( globkey_str, energy_trans_str, rxn_chan_str) # Write the MESS file into the filesystem ioprinter.obj('line_plus') ioprinter.writing('MESS input file', mess_path) ioprinter.debug_message(mess_inp_str) return mess_inp_str, dats
def make_header_str(spc_dct, temps, pressures): """ makes the standard header and energy transfer sections for MESS input file """ ioprinter.messpf('global_header') keystr1 = ( 'EnergyStepOverTemperature, ExcessEnergyOverTemperature, ' + 'ModelEnergyLimit' ) keystr2 = ( 'CalculationMethod, WellCutoff, ' + 'ChemicalEigenvalueMax, ReductionMethod, AtomDistanceMin' ) ioprinter.debug_message(' {}'.format(keystr1)) ioprinter.debug_message(' {}'.format(keystr2)) if is_abstraction(spc_dct): well_extend = None else: well_extend = 'auto' ioprinter.debug_message('Including WellExtend in MESS input') header_str = mess_io.writer.global_rates_input( temps, pressures, excess_ene_temp=None, well_extend=well_extend) return header_str
def _calc_nsamp(tors_names, nsamp_par, zma, zrxn=None): """ Determine the number of samples to od """ tors_ranges = tuple((0, 2 * numpy.pi) for tors in tors_names) tors_range_dct = dict(zip(tors_names, tors_ranges)) if zrxn is None: gra = automol.zmat.graph(zma) ntaudof = len( automol.graph.rotational_bond_keys(gra, with_h_rotors=False)) ioprinter.info_message( " - Nonmethyl torsional coordinates {}".format(ntaudof)) else: ntaudof = len(tors_names) nsamp = util.nsamp_init(nsamp_par, ntaudof) ioprinter.debug_message('tors_names', tors_names) ioprinter.debug_message('tors_range_dct', tors_range_dct) if not tors_range_dct: ioprinter.info_message( " - No torsional coordinates. Setting nsamp to 1.") nsamp = 1 return nsamp, tors_range_dct
def _this_conformer_is_running(zma, cnf_run_fs): """ Check the RUN filesystem for similar geometry submissions that are currently running """ running = False job = elstruct.Job.OPTIMIZATION cnf_run_path = cnf_run_fs[0].path() ioprinter.debug_message('cnf path ' + cnf_run_path) for locs in cnf_run_fs[-1].existing(ignore_bad_formats=True): cnf_run_path = cnf_run_fs[-1].path(locs) run_fs = autofile.fs.run(cnf_run_path) run_path = run_fs[-1].path([job]) inf_obj = run_fs[-1].file.info.read([job]) status = inf_obj.status if status == autofile.schema.RunStatus.RUNNING: start_time = inf_obj.utc_start_time current_time = autofile.schema.utc_time() if (current_time - start_time).total_seconds() < 3000000: subrun_fs = autofile.fs.subrun(run_path) inp_str = subrun_fs[0].file.input.read([0, 0]) inp_str = inp_str.replace('=', '') prog = inf_obj.prog inp_zma = elstruct.reader.inp_zmatrix(prog, inp_str) if automol.zmat.almost_equal(inp_zma, zma, dist_rtol=0.018, ang_atol=.2): ioprinter.info_message( 'This conformer was started in the last ' + '{:3.4f} hours in {}.'.format( (current_time - start_time).total_seconds() / 3600., run_path)) running = True break return running
def make_header_str(spc_dct, rxn_lst, pes_idx, pesgrp_num, pes_param_dct, hot_enes_dct, label_dct, temps, pressures, float_type): """ Built the head of the MESS input file that contains various global keywords used for running rate calculations. Function determines certain input parameters for the well-extension methodology based on the reaction type stored in spc_dct. :param spc_dct: :type spc_dct: dict[] :param temps: temperatures for the rate calculations (in K) :type temps: tuple(float) :param pressures: pressures for the rate calculations (in atm) :type pressures: tuple(float) :rtype: str """ ioprinter.messpf('global_header') keystr1 = ('EnergyStepOverTemperature, ExcessEnergyOverTemperature, ' + 'ModelEnergyLimit') keystr2 = ('CalculationMethod, WellCutoff, ' + 'ChemicalEigenvalueMax, ReductionMethod, AtomDistanceMin') ioprinter.debug_message(f' {keystr1}') ioprinter.debug_message(f' {keystr2}') # Set the well extension energy thresh if is_abstraction_pes(spc_dct, rxn_lst, pes_idx): well_extend = None else: well_extend = 'auto' ioprinter.debug_message('Including WellExtend in MESS input') # Set other parameters # Need the PES number to pull the correct params out of lists ped_spc_lst, hot_enes_dct, micro_out_params = energy_dist_params( pesgrp_num, pes_param_dct, hot_enes_dct, label_dct) header_str = mess_io.writer.global_rates_input( temps, pressures, calculation_method='direct', well_extension=well_extend, ped_spc_lst=ped_spc_lst, hot_enes_dct=hot_enes_dct, excess_ene_temp=None, micro_out_params=micro_out_params, float_type=float_type) return header_str
def saddle_point_checker(imags): """ run things for checking Hessian """ big_imag, kick_imag = 0, 0 ioprinter.checking('the imaginary frequencies of the saddle point...') if len(imags) < 1: ioprinter.warning_message('No imaginary modes for geometry') status = 'fail' else: if len(imags) > 1: ioprinter.warning_message( 'More than one imaginary mode for geometry') status = 'fail' for idx, imag in enumerate(imags): if imag <= 50.0: ioprinter.warning_message( f'Mode {str(idx+1)} {imag} cm-1 is low,') elif 50.0 < imag <= 200.0: lowstr = f'Mode {str(idx+1)} {imag} cm-1 is low,' ioprinter.debug_message( lowstr + ' check mode and see if it should be corrected') big_imag += 1 # Adding to the kick counter kills code for good TSs # Some addditions of big species have low mode of this # ioprinter.warning_message( # lowstr + 'need a kickoff procedure to remove') # kick_imag += 1 else: ioprinter.debug_message( f'Mode {str(idx+1)} {imag} cm-1 likely fine') big_imag += 1 if big_imag > 1: ioprinter.warning_message( 'More than one imaginary mode for geometry') if kick_imag >= 1: ioprinter.debug_message('Will kickoff to get saddle point') status = 'kickoff' else: status = 'failure' elif big_imag == 1: status = 'success' elif big_imag == 0: status = 'failure' ioprinter.warning_message('Did not find any appropriate modes') return status
def _check_freqs(imags): """ Check the magnitude of the imaginary modes. """ big_imag, kick_imag = 0, 0 ioprinter.checking('the imaginary frequencies of the saddle point...') if len(imags) < 1: ioprinter.warning_message('No imaginary modes for geometry') status = 'fail' else: if len(imags) > 1: ioprinter.warning_message( 'More than one imaginary mode for geometry') status = 'fail' for idx, imag in enumerate(imags): if imag <= 50.0: ioprinter.warning_message(f'Mode {idx+1} {imag} cm-1 is low,') elif 50.0 < imag <= 200.0: lowstr = f'Mode {idx+1} {imag} cm-1 is low,' ioprinter.debug_message( lowstr + ' check mode and see if it should be corrected') big_imag += 1 # Adding to the kick counter kills code for good TSs # Some addditions of big species have low mode of this # ioprinter.warning_message( # lowstr + 'need a kickoff procedure to remove') # kick_imag += 1 else: ioprinter.debug_message( f'Mode {idx+1} {imag} cm-1 is likely fine,') big_imag += 1 if big_imag > 1: ioprinter.warning_message( 'More than one imaginary mode for geometry') if kick_imag >= 1: ioprinter.debug_message('Will kickoff to get saddle point') status = 'kick' else: status = False elif big_imag == 1: status = True elif big_imag == 0: status = False return status
def make_header_str(spc_dct, temps, pressures): """ Built the head of the MESS input file that contains various global keywords used for running rate calculations. Function determines certain input parameters for the well-extension methodology based on the reaction type stored in spc_dct. :param spc_dct: :type spc_dct: dict[] :param temps: temperatures for the rate calculations (in K) :type temps: tuple(float) :param pressures: pressures for the rate calculations (in atm) :type pressures: tuple(float) :rtype: str """ ioprinter.messpf('global_header') keystr1 = ('EnergyStepOverTemperature, ExcessEnergyOverTemperature, ' + 'ModelEnergyLimit') keystr2 = ('CalculationMethod, WellCutoff, ' + 'ChemicalEigenvalueMax, ReductionMethod, AtomDistanceMin') ioprinter.debug_message(' {}'.format(keystr1)) ioprinter.debug_message(' {}'.format(keystr2)) if is_abstraction_pes(spc_dct): well_extend = None else: well_extend = 'auto' ioprinter.debug_message('Including WellExtend in MESS input') header_str = mess_io.writer.global_rates_input(temps, pressures, excess_ene_temp=None, well_extend=well_extend) return header_str
def run_prop(zma, geo, spc_info, thy_info, geo_run_fs, geo_save_fs, locs, run_prefix, script_str, overwrite, zrxn=None, retryfail=True, method_dct=None, ref_val=None, **kwargs): """ Determine the properties in the given location """ # Set unneeded vals _, _, _, _ = zrxn, method_dct, ref_val, run_prefix # Set input geom geo_run_path = geo_run_fs[-1].path(locs) geo_save_path = geo_save_fs[-1].path(locs) if geo is not None: job_geo = geo else: job_geo = automol.zmat.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: ioprinter.info_message( 'Either no dipole moment or polarizability found in' 'in save filesys. Running properties...') _run = True elif overwrite: ioprinter.info_message( 'User specified to overwrite property with new run...') _run = True else: _run = False if _run: run_fs = autofile.fs.run(geo_run_path) success, ret = es_runner.execute_job( job=elstruct.Job.MOLPROP, script_str=script_str, run_fs=run_fs, geo=job_geo, spc_info=spc_info, thy_info=thy_info, zrxn=zrxn, overwrite=overwrite, retryfail=retryfail, **kwargs, ) if success: inf_obj, _, out_str = ret ioprinter.info_message(" - Reading dipole moment from output...") dmom = elstruct.reader.dipole_moment(inf_obj.prog, out_str) ioprinter.info_message(" - Reading polarizability from output...") polar = elstruct.reader.polarizability(inf_obj.prog, out_str) ioprinter.debug_message('dip mom', dmom) ioprinter.debug_message('polar', polar) ioprinter.info_message( " - 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) ioprinter.save_geo(geo_save_path) else: ioprinter.existing_path('Dipole moment and polarizability', geo_save_path)
def sum_channel_enes(channel_infs, ref_ene, ene_lvl='ene_chnlvl'): """ sum the energies """ # Initialize sum ene dct sum_ene = {} # Calculate energies for species reac_ene = 0.0 reac_ref_ene = 0.0 for rct in channel_infs['reacs']: reac_ene += rct[ene_lvl] reac_ref_ene += rct['ene_tsref'] ioprinter.info_message('reac ene', rct[ene_lvl], rct['ene_tsref']) sum_ene.update({'reacs': reac_ene}) prod_ene = 0.0 prod_ref_ene = 0.0 for prd in channel_infs['prods']: prod_ene += prd[ene_lvl] prod_ref_ene += prd['ene_tsref'] ioprinter.info_message('prod ene', prd[ene_lvl], prd['ene_tsref']) sum_ene.update({'prods': prod_ene}) # Calculate energies for fake entrance- and exit-channel wells if 'fake_vdwr' in channel_infs: vdwr_ene = reac_ene - (1.0 * phycon.KCAL2EH) sum_ene.update({'fake_vdwr': vdwr_ene, 'fake_vdwr_ts': reac_ene}) if 'fake_vdwp' in channel_infs: vdwp_ene = prod_ene - (1.0 * phycon.KCAL2EH) sum_ene.update({'fake_vdwp': vdwp_ene, 'fake_vdwp_ts': prod_ene}) ioprinter.debug_message('REAC HoF (0 K) spc lvl kcal/mol: ', reac_ene * phycon.EH2KCAL) ioprinter.debug_message('REAC HoF (0 K) ts lvl kcal/mol: ', reac_ref_ene * phycon.EH2KCAL) ioprinter.debug_message('PROD HoF (0 K) spc lvl kcal/mol: ', prod_ene * phycon.EH2KCAL) ioprinter.debug_message('PROD HoF (0 K) ts lvl kcal/mol: ', prod_ref_ene * phycon.EH2KCAL) # Scale all of the current energies in the dict for spc, ene in sum_ene.items(): sum_ene[spc] = (ene - ref_ene) * phycon.EH2KCAL # Set the inner TS ene and scale them if channel_infs['ts'][0]['writer'] in ('pst_block', 'vrctst_block'): if len(channel_infs['reacs']) == 2: ts_enes = [sum(inf['ene_chnlvl'] for inf in channel_infs['reacs'])] else: ts_enes = [sum(inf['ene_chnlvl'] for inf in channel_infs['prods'])] channel_infs['ts'][0].update({'ene_chnlvl': ts_enes}) else: if 'rpath' in channel_infs['ts']: ts_enes = [dct[ene_lvl] for dct in channel_infs['ts']['rpath']] else: ts_enes = [dct[ene_lvl] for dct in channel_infs['ts']] # ts_enes = [channel_infs['ts'][ene_lvl]] ioprinter.debug_message('TS HoF (0 K) ts lvl kcal/mol: ', ts_enes[0] * phycon.EH2KCAL) if reac_ref_ene: if abs(ts_enes[0] - reac_ref_ene) < abs(ts_enes[0] - prod_ref_ene): ts_enes = [ene - reac_ref_ene + reac_ene for ene in ts_enes] else: ts_enes = [ene - prod_ref_ene + prod_ene for ene in ts_enes] ioprinter.debug_message('TS HoF (0 K) approx spc lvl kcal/mol: ', ts_enes[0] * phycon.EH2KCAL) ts_enes = [(ene - ref_ene) * phycon.EH2KCAL for ene in ts_enes] sum_ene.update({'ts': ts_enes}) return sum_ene
def squash_tors_pot(spc_mod_dct_i): """ determine if we need to scale the potential """ ioprinter.debug_message('tors model in scale set', spc_mod_dct_i['tors']['mod']) return bool(spc_mod_dct_i['tors']['mod'] in ('1dhrfa', 'tau-1dhrfa'))
def enthalpy_calculation(spc_dct, spc_name, ene_chnlvl, chn_basis_ene_dct, pes_mod_dct_i, spc_mod_dct_i, run_prefix, save_prefix, pforktp='ktp', zrxn=None): """ Calculate the Enthalpy. """ ref_scheme = pes_mod_dct_i['therm_fit']['ref_scheme'] ref_enes = pes_mod_dct_i['therm_fit']['ref_enes'] basis_dct = thermfit.prepare_basis(ref_scheme, spc_dct, (spc_name, ), zrxn=zrxn) uniref_dct = thermfit.unique_basis_species(basis_dct, spc_dct) # Get the basis info for the spc of interest spc_basis, coeff_basis = basis_dct[spc_name] ene_spc = ene_chnlvl ene_basis = [] energy_missing = False for spc_basis_i in spc_basis: if not isinstance(spc_basis_i, str): basreacs, basprods = spc_basis_i spc_basis_i = ''.join(basreacs) spc_basis_i += ''.join(basprods) if spc_basis_i in chn_basis_ene_dct: ioprinter.debug_message('Energy already found for basis species: ', spc_basis_i) ene_basis.append(chn_basis_ene_dct[spc_basis_i]) else: ioprinter.debug_message( 'Energy will be determined for basis species: ', spc_basis_i) energy_missing = True # Get the energies for the spc and its basis if energy_missing: _, ene_basis = basis_energy(spc_name, spc_basis, uniref_dct, spc_dct, spc_mod_dct_i, run_prefix, save_prefix, read_species=False) for spc_basis_i, ene_basis_i in zip(spc_basis, ene_basis): if not isinstance(spc_basis_i, str): basreacs, basprods = spc_basis_i spc_basis_i = ''.join(basreacs) spc_basis_i += ''.join(basprods) chn_basis_ene_dct[spc_basis_i] = ene_basis_i # Calculate and store the 0 K Enthalpy hf0k = thermfit.heatform.calc_hform_0k(ene_spc, ene_basis, spc_basis, coeff_basis, ref_set=ref_enes) if pforktp == 'ktp': if 'basic' in ref_scheme: ts_ref_scheme = 'basic' else: ts_ref_scheme = 'cbh0' if '_' in ref_scheme: ts_ref_scheme = 'cbh' + ref_scheme.split('_')[1] if zrxn is None: if ref_scheme != ts_ref_scheme: basis_dct_trs = thermfit.prepare_basis(ts_ref_scheme, spc_dct, (spc_name, ), zrxn=zrxn) uniref_dct_trs = thermfit.unique_basis_species( basis_dct_trs, spc_dct) spc_basis_trs, coeff_basis_trs = basis_dct_trs[spc_name] ene_basis_trs = [] energy_missing = False for spc_basis_i in spc_basis_trs: if spc_basis_i in chn_basis_ene_dct: ioprinter.info_message( 'Energy already found for basis species: ', spc_basis_i) ene_basis_trs.append(chn_basis_ene_dct[spc_basis_i]) else: ioprinter.info_message( 'Energy will be determined for basis species: ', spc_basis_i) energy_missing = True if energy_missing: _, ene_basis_trs = basis_energy(spc_name, spc_basis_trs, uniref_dct_trs, spc_dct, spc_mod_dct_i, run_prefix, save_prefix, read_species=False) for spc_basis_i, ene_basis_i in zip( spc_basis_trs, ene_basis_trs): chn_basis_ene_dct[spc_basis_i] = ene_basis_i ene_spc_trs = ene_chnlvl hf0k_trs = thermfit.heatform.calc_hform_0k(ene_spc_trs, ene_basis_trs, spc_basis_trs, coeff_basis_trs, ref_set=ref_enes) else: hf0k_trs = hf0k else: hf0k_trs = 0.0 else: hf0k_trs = None ioprinter.info_message('ABS Energy (hart): ', ene_chnlvl) ioprinter.info_message('Hf0K Energy (hart): ', hf0k * phycon.KCAL2KJ) return hf0k, hf0k_trs, chn_basis_ene_dct, basis_dct
def rpvtst_data(ts_dct, reac_dcts, spc_mod_dct_i, run_prefix, save_prefix, sadpt=False): """ Pull all of the neccessary information from the filesystem for a species """ zrxn = ts_dct['zrxn'] # Set up all the filesystem objects using models and levels if sadpt: # Set up filesystems and coordinates for saddle point # Scan along RxnCoord is under THY/TS/CONFS/cid/Z pf_filesystems = filesys.models.pf_filesys(ts_dct, spc_mod_dct_i, run_prefix, save_prefix, True) tspaths = pf_filesystems['harm'] [_, cnf_save_path, min_locs, _, cnf_run_fs] = tspaths ts_run_path = cnf_run_fs[-1].path(min_locs) # Set TS reaction coordinate frm_name = 'IRC' scn_vals = filesys.models.get_rxn_scn_coords(cnf_save_path, frm_name) scn_vals.sort() scn_ene_info = spc_mod_dct_i['ene'][1][0][1] # fix to be ene lvl scn_prefix = cnf_save_path else: # Set up filesystems and coordinates for reaction path # Scan along RxnCoord is under THY/TS/Z tspaths = filesys.models.set_rpath_filesys(ts_dct, spc_mod_dct_i['rpath'][1]) ts_run_path, _, _, thy_save_path = tspaths # Set TS reaction coordinate scn_vals = filesys.models.get_rxn_scn_coords(thy_save_path, frm_name) scn_vals.sort() scn_ene_info = spc_mod_dct_i['rpath'][1][0] scn_prefix = thy_save_path # Modify the scn thy info ioprinter.debug_message('scn thy info', scn_ene_info) ioprinter.info_message('scn vals', scn_vals) mod_scn_ene_info = filesys.inf.modify_orb_restrict( filesys.inf.get_spc_info(ts_dct), scn_ene_info) # scn thy info [[1.0, ['molpro2015', 'ccsd(t)', 'cc-pvdz', 'RR']]] # Need to read the sp vals along the scan. add to read ref_ene = 0.0 enes, geoms, grads, hessians, _, _ = filesys.read.potential( [frm_name], [scn_vals], scn_prefix, mod_scn_ene_info, ref_ene, constraint_dct=None, # No extra frozen treatments read_geom=True, read_grad=True, read_hess=True) script_str = autorun.SCRIPT_DCT['projrot'] freqs = autorun.projrot.pot_frequencies(script_str, geoms, grads, hessians, ts_run_path) # Get the energies and zpes at R_ref if not sadpt: _, ene_hs_sr_ref, ene_hs_mr_ref = ene.rpath_ref_idx( ts_dct, scn_vals, frm_name, scn_prefix, spc_mod_dct_i['ene'], spc_mod_dct_i['rpath'][1]) fr_idx = len(scn_vals) - 1 zpe_ref = (sum(freqs[(fr_idx, )]) / 2.0) * phycon.WAVEN2KCAL # Get the reactants and infinite seperation energy reac_ene = 0.0 ene_hs_sr_inf = 0.0 for dct in reac_dcts: pf_filesystems = filesys.models.pf_filesys(dct, spc_mod_dct_i, run_prefix, save_prefix, False) new_spc_dct_i = { 'ene': spc_mod_dct_i['ene'], 'harm': spc_mod_dct_i['harm'], 'tors': spc_mod_dct_i['tors'] } reac_ene += ene.read_energy(dct, pf_filesystems, new_spc_dct_i, run_prefix, read_ene=True, read_zpe=True, saddle=sadpt) ioprinter.debug_message('rpath', spc_mod_dct_i['rpath'][1]) new_spc_dct_i = { 'ene': ['mlvl', [[1.0, spc_mod_dct_i['rpath'][1][2]]]], 'harm': spc_mod_dct_i['harm'], 'tors': spc_mod_dct_i['tors'] } ene_hs_sr_inf += ene.read_energy(dct, pf_filesystems, new_spc_dct_i, run_prefix, read_ene=True, read_zpe=False) # Scale the scn values if sadpt: scn_vals = [val / 100.0 for val in scn_vals] # scn_vals = [val * phycon.BOHR2ANG for val in scn_vals] # Grab the values from the read inf_dct = {} inf_dct['rpath'] = [] pot_info = zip(scn_vals, enes.values(), geoms.values(), freqs.values()) for rval, pot, geo, frq in pot_info: # Scale the r-values # Get the relative energy (edit for radrad scans) zpe = (sum(frq) / 2.0) * phycon.WAVEN2KCAL if sadpt: zero_ene = (pot + zpe) * phycon.KCAL2EH else: ioprinter.debug_message('enes') ioprinter.debug_message('reac ene', reac_ene) ioprinter.debug_message('hs sr', ene_hs_sr_ref) ioprinter.debug_message('inf', ene_hs_sr_inf) ioprinter.debug_message('hs mr', ene_hs_mr_ref) ioprinter.debug_message('pot R', pot * phycon.KCAL2EH) ioprinter.debug_message('zpe', zpe) ioprinter.debug_message('zpe ref', zpe_ref) elec_ene = (ene_hs_sr_ref - ene_hs_sr_inf - ene_hs_mr_ref + pot * phycon.KCAL2EH) zpe_pt = zpe - zpe_ref zero_ene = reac_ene + (elec_ene + zpe_pt * phycon.KCAL2EH) ioprinter.info_message('elec ene', elec_ene) ioprinter.info_message('zero ene', zero_ene) # ENE # ene = (reac_ene + # ene_hs_sr(R_ref) - ene_hs_sr(inf) + # ene_ls_mr(R_ref) - ene_hs_mr(R_ref) + # ene_ls_mr(R) - ene_ls_mr(R_ref)) # ene = (reac_ene + # ene_hs_sr(R_ref) - ene_hs_sr(inf) - # ene_hs_mr(R_ref) + ene_ls_mr(R)) # inf_sep_ene = reac_ene + hs_sr_ene - hs_mr_ene # inf_sep_ene_p = (reac_ene + # hs_sr_ene(R_ref) - ene_hs_sr(inf) + # ls_mr_ene(R_ref) - hs_mr_ene(R_ref)) # ene = inf_sep_ene_p + ene_ls_mr(R) - ene_ls_mr(R_ref) # ZPE # zpe = zpe(R) - zpe(inf) # or # zpe = zpe_ls_mr(R) - zpe_ls_mr(R_ref) # Set values constant across the scan elec_levels = ts_dct['elec_levels'] # Create info dictionary and append to lst keys = ['rval', 'geom', 'freqs', 'elec_levels', 'ene_chnlvl'] vals = [rval, geo, frq, elec_levels, zero_ene] inf_dct['rpath'].append(dict(zip(keys, vals))) # Calculate and store the imaginary mode if sadpt: _, imag, _ = vib.read_harmonic_freqs(pf_filesystems, run_prefix, zrxn=zrxn) ts_idx = scn_vals.index(0.00) else: imag = None ts_idx = 0 inf_dct.update({'imag': imag}) inf_dct.update({'ts_idx': ts_idx}) return inf_dct
def run_tau(zma, spc_info, thy_info, nsamp, tors_range_dct, tau_run_fs, tau_save_fs, script_str, overwrite, saddle, **kwargs): """ run sampling algorithm to find tau dependent geometries """ if not tors_range_dct: ioprinter.info_message( "No torsional coordinates. Setting nsamp to 1.") nsamp = 1 tau_save_fs[0].create() vma = automol.zmat.var_(zma) if tau_save_fs[0].file.vmatrix.exists(): existing_vma = tau_save_fs[0].file.vmatrix.read() assert vma == existing_vma tau_save_fs[0].file.vmatrix.write(vma) idx = 0 nsamp0 = nsamp inf_obj = autofile.schema.info_objects.tau_trunk(0, tors_range_dct) while True: if tau_save_fs[0].file.info.exists(): inf_obj_s = tau_save_fs[0].file.info.read() nsampd = inf_obj_s.nsamp elif tau_run_fs[0].file.info.exists(): inf_obj_r = tau_run_fs[0].file.info.read() nsampd = inf_obj_r.nsamp else: nsampd = 0 nsamp = nsamp0 - nsampd if nsamp <= 0: ioprinter.info_message( 'Reached requested number of samples. ', 'Tau sampling complete.') break ioprinter.info_message("New nsamp is {:d}.".format(nsamp), indent=1) samp_zma, = automol.zmat.samples(zma, 1, tors_range_dct) tid = autofile.schema.generate_new_tau_id() locs = [tid] tau_run_fs[-1].create(locs) tau_run_prefix = tau_run_fs[-1].path(locs) run_fs = autofile.fs.run(tau_run_prefix) idx += 1 ioprinter.info_message("Run {}/{}".format(idx, nsamp0)) ioprinter.debug_message( 'Checking if ZMA has high repulsion...', newline=1) geo = automol.zmat.geometry(zma) samp_geo = automol.zmat.geometry(samp_zma) if automol.pot.low_repulsion_struct(geo, samp_geo): ioprinter.debug_message('ZMA fine.') es_runner.run_job( job=elstruct.Job.OPTIMIZATION, script_str=script_str, run_fs=run_fs, geo=samp_zma, spc_info=spc_info, thy_info=thy_info, saddle=saddle, overwrite=overwrite, frozen_coordinates=tors_range_dct.keys(), **kwargs ) else: ioprinter.warning_message('repulsive ZMA:') inp_str = elstruct.writer.optimization( geo=samp_zma, charge=spc_info[1], mult=spc_info[2], method=thy_info[1], basis=thy_info[2], prog=thy_info[0], orb_type=thy_info[3], mol_options=['nosym'], frozen_coordinates=tors_range_dct.keys(), ) tau_run_fs[-1].file.geometry_input.write(inp_str, locs) ioprinter.warning_message( 'geometry for bad ZMA at', tau_run_fs[-1].path(locs)) # nsampd += 1 # inf_obj.nsamp = nsampd # tau_save_fs[0].file.info.write(inf_obj) # tau_run_fs[0].file.info.write(inf_obj) if tau_save_fs[0].file.info.exists(): inf_obj_s = tau_save_fs[0].file.info.read() nsampd = inf_obj_s.nsamp elif tau_run_fs[0].file.info.exists(): inf_obj_r = tau_run_fs[0].file.info.read() nsampd = inf_obj_r.nsamp nsampd += 1 inf_obj.nsamp = nsampd tau_save_fs[0].file.info.write(inf_obj) tau_run_fs[0].file.info.write(inf_obj)
def _make_fake_mess_strs(chnl, side, fake_inf_dcts, chnl_enes, label_dct, side_label): """ write the MESS strings for the fake wells and TSs """ # Set vars based on the reacs/prods reacs, prods = chnl if side == 'reacs': well_key = 'fake_vdwr' ts_key = 'fake_vdwr_ts' prepend_key = 'FRB' side_idx = 0 elif side == 'prods': well_key = 'fake_vdwp' ts_key = 'fake_vdwp_ts' side_idx = 1 if reacs in (prods, prods[::-1]): prepend_key = 'FRB' else: prepend_key = 'FPB' # Initialize well and ts strs and data dcts fake_dat_dct = {} well_str, ts_str = '', '' # Build a fake TS dct ts_inf_dct = { 'n_pst': 6.0, 'cn_pst': 10.0 } # MESS string for the fake reactant side well well_dct_key = make_rxn_str(chnl[side_idx], prepend='F') well_dct_key_rev = make_rxn_str(chnl[side_idx][::-1], prepend='F') if well_dct_key in label_dct: fake_well_label = label_dct[well_dct_key] elif well_dct_key_rev in label_dct: fake_well_label = label_dct[well_dct_key_rev] else: ioprinter.warning_message( 'No label {} in label dict'.format(well_dct_key)) # well_str += mess_io.writer.species_separation_str() well_str += '\n! Fake Well for {}\n'.format( '+'.join(chnl[side_idx])) fake_well, well_dat = blocks.fake_species_block(*fake_inf_dcts) well_str += mess_io.writer.well( fake_well_label, fake_well, chnl_enes[well_key]) # MESS PST TS string for fake reactant side well -> reacs pst_dct_key = make_rxn_str(chnl[side_idx], prepend=prepend_key) pst_dct_key_rev = make_rxn_str(chnl[side_idx][::-1], prepend=prepend_key) if pst_dct_key in label_dct: pst_label = label_dct[pst_dct_key] elif pst_dct_key_rev in label_dct: pst_label = label_dct[pst_dct_key_rev] else: ioprinter.debug_message( 'No label {} in label dict'.format(pst_dct_key)) pst_ts_str, pst_ts_dat = blocks.pst_block(ts_inf_dct, *fake_inf_dcts) ts_str += '\n' + mess_io.writer.ts_sadpt( pst_label, side_label, fake_well_label, pst_ts_str, chnl_enes[ts_key], tunnel='') # Build the data dct if well_dat: fake_dat_dct.update(well_dat) if pst_ts_dat: fake_dat_dct.update(pst_ts_dat) return well_str, ts_str, fake_well_label, fake_dat_dct
def make_pes_mess_str(spc_dct, rxn_lst, pes_idx, run_prefix, save_prefix, label_dct, pes_model_dct_i, spc_model_dct_i, spc_model, thy_dct): """ Write all the MESS input file strings for the reaction channels """ ioprinter.messpf('channel_section') # Initialize empty MESS strings full_well_str, full_bi_str, full_ts_str = '', '', '' full_dat_str_dct = {} pes_ene_dct = {} conn_lst = tuple() # Set the energy and model for the first reference species ioprinter.info_message('\nCalculating reference energy for PES') ref_ene = set_reference_ene( rxn_lst, spc_dct, thy_dct, pes_model_dct_i, spc_model_dct_i, run_prefix, save_prefix, ref_idx=0) # Loop over all the channels and write the MESS strings written_labels = [] basis_energy_dct = {} for rxn in rxn_lst: chnl_idx, (reacs, prods) = rxn ioprinter.obj('vspace') ioprinter.reading('PES electrion structure data') ioprinter.channel(chnl_idx, reacs, prods) # Set the TS name and channel model tsname = 'ts_{:g}_{:g}'.format(pes_idx+1, chnl_idx+1) # Obtain all of the species data if spc_model not in basis_energy_dct: basis_energy_dct[spc_model] = {} # Pass in full ts class chnl_infs, chn_basis_ene_dct = get_channel_data( reacs, prods, tsname, spc_dct, basis_energy_dct[spc_model], pes_model_dct_i, spc_model_dct_i, run_prefix, save_prefix) basis_energy_dct[spc_model].update(chn_basis_ene_dct) # Calculate the relative energies of all spc on the channel chnl_enes = sum_channel_enes(chnl_infs, ref_ene) # Write the mess strings for all spc on the channel mess_strs, dat_str_dct, written_labels = _make_channel_mess_strs( tsname, reacs, prods, spc_dct, label_dct, written_labels, chnl_infs, chnl_enes, spc_model_dct_i) # Append to full MESS strings [well_str, bi_str, ts_str] = mess_strs full_well_str += well_str full_bi_str += bi_str full_ts_str += ts_str full_dat_str_dct.update(dat_str_dct) ioprinter.debug_message('rxn', rxn) ioprinter.debug_message('enes', chnl_enes) ioprinter.debug_message('label dct', label_dct) ioprinter.debug_message('written labels', written_labels) # Combine all the reaction channel strings rxn_chan_str = '\n'.join([full_well_str, full_bi_str, full_ts_str]) return rxn_chan_str, full_dat_str_dct, pes_ene_dct, conn_lst