def active_space(info_obj, typ='ts'): """ Determine the active space for the multireference MEP scan """ def _active_space(ich, mul): """ Determine the active sapce for an InChI string """ if ich in act_space.DCT: num_act_orb = act_space.DCT[ich][0] num_act_elc = act_space.DCT[ich][1] num_states = act_space.DCT[ich][2] else: num_act_orb = (mul - 1) num_act_elc = (mul - 1) num_states = 1 return num_act_orb, num_act_elc, num_states if typ == 'spc': ich = sinfo.value(info_obj, 'inchi') mul = sinfo.value(info_obj, 'mult') num_act_orb, num_act_elec, num_states = _active_space(ich, mul) elif typ == 'ts': rct_ichs = rinfo.value(info_obj, 'inchi')[0] rct_muls = rinfo.value(info_obj, 'mult')[0] num_act_orb, num_act_elec, num_states = 0, 0, 1 for ich, mul in zip(rct_ichs, rct_muls): norb, nelec, nstat = _active_space(ich, mul) num_act_orb += norb num_act_elec += nelec num_states *= nstat return num_act_orb, num_act_elec, num_states
def ts_dct_sing_chnl(pes_idx, reaction, spc_dct, run_prefix, save_prefix, thy_info=None, ini_thy_info=None): """ build dct for single reaction """ # Unpack the reaction object chnl_idx, (reacs, prods) = reaction rxn_info = rinfo.from_dct(reacs, prods, spc_dct) print(' Preparing for reaction {} = {}'.format('+'.join(reacs), '+'.join(prods))) # Set the reacs and prods for the desired direction reacs, prods = rxnid.set_reaction_direction(reacs, prods, rxn_info, thy_info, ini_thy_info, save_prefix, direction='forw') # Obtain the reaction object for the reaction zma_locs = (0, ) zrxns, zmas, rclasses = rxnid.build_reaction(rxn_info, ini_thy_info, zma_locs, save_prefix) # Could reverse the spc dct if zrxns is not None: ts_dct = {} for idx, (zrxn, zma, cls) in enumerate(zip(zrxns, zmas, rclasses)): tsname = 'ts_{:g}_{:g}_{:g}'.format(pes_idx + 1, chnl_idx + 1, idx) ts_dct[tsname] = { 'zrxn': zrxn, 'zma': zma, 'reacs': reacs, 'prods': prods, 'rxn_info': rxn_info, 'inchi': '', 'charge': rinfo.value(rxn_info, 'charge'), 'mult': rinfo.value(rxn_info, 'tsmult'), 'elec_levels': ((0.0, rinfo.value(rxn_info, 'tsmult')), ), 'hind_inc': 30.0 * phycon.DEG2RAD, # 'sym_factor': 1.0, # remove later 'class': cls, 'rxn_fs': reaction_fs(run_prefix, save_prefix, rxn_info) } else: ts_dct = {} print('Skipping reaction as class not given/identified') # Add the ts dct to the spc dct here? return ts_dct
def _mod_class(class_typ, rxn_info): """ Create the object containing the full description of the reaction class, including its type, spin state, and whether it is a radical-radical combination. :param class_typ: reaction class type :type class_typ: str :param rxn_info: ??? :tpye rxn_info: ??? """ # Set the spin of the reaction to high/low _fake_class = (class_typ, '', '', False) if automol.par.need_spin_designation(_fake_class): ts_mul = rinfo.value(rxn_info, 'tsmult') high_mul = rinfo.ts_mult(rxn_info, rxn_mul='high') _spin = 'high-spin' if ts_mul == high_mul else 'low-spin' else: _spin = '' # Determine if it iss intersystem crossing # rxn_muls = rinfo.value(rxn_info, 'mult') # is_isc = automol.reac.intersystem_crossing(rxn_muls) return automol.par.reaction_class_from_data( class_typ, _spin, rinfo.radrad(rxn_info), False)
def _id_reaction(rxn_info): """ Identify the reaction and build the object :param rxn_info: reaction info object :type rxn_info: mechanalyzer.inf.rxn object :rtype: (tuple(automol.Reaction object), tuple(automol.zmat object)) """ rxn_ichs = rinfo.value(rxn_info, 'inchi') rct_ichs, prd_ichs = rxn_ichs[0], rxn_ichs[1] zrxn_objs = automol.reac.rxn_objs_from_inchi(rct_ichs, prd_ichs, indexing='zma') # zrxns = tuple(obj[0] for obj in zrxn_objs) # zmas = tuple(obj[1] for obj in zrxn_objs) zrxns, zmas = [], [] # for objs in zrxn_objs: # zrxn, zma, _, _ = objs # zrxns.append(zrxn) # zmas.append(zma) # print('zrxn, zma in id:', zrxn, automol.zmat.string(zma)) # for now just use first zma until we are properly producing extra zmas if zrxn_objs: zrxns.append(zrxn_objs[0][0]) zmas.append(zrxn_objs[0][1]) return zrxns, zmas
def skip_task(tsk, spc_dct, spc_name, thy_dct, es_keyword_dct, save_prefix): """ Determine if an electronic structure task should be skipped based on various parameters. :param spc_dct: species dictionary :type spc_dct: dictionary :param spc_name: name of species :type spc_name: string :rtype: bool """ # Initialize skip to be false skip = False # Set theory info needed to find information ini_method_dct = thy_dct.get(es_keyword_dct['inplvl']) ini_thy_info = tinfo.from_dct(ini_method_dct) # Perform checks if 'ts' in spc_name: # Skip all tasks except find_ts # if rad-rad TS if tsk not in ('find_ts', 'rpath_scan'): # generalize to other rpath rxn_info = spc_dct[spc_name]['rxn_info'] ts_mul = rinfo.value(rxn_info, 'tsmult') high_ts_mul = rinfo.ts_mult(rxn_info, rxn_mul='high') if rinfo.radrad(rxn_info) and ts_mul != high_ts_mul: skip = True ioprinter.info_message( f'Skipping task because {spc_name}', 'is a low-spin radical radical reaction') else: spc_natoms = len(automol.inchi.geometry(spc_dct[spc_name]['inchi'])) if spc_natoms == 1: # Skip all tasks except init_geom and conf_energy # if species is an atom if tsk not in ('init_geom', 'conf_energy'): skip = True ioprinter.info_message('Skipping task for an atom...', newline=1) else: # Skip all tasks except ini_geom # if (non-TS) species is unstable (zrxn found (i.e. is not None)) if tsk != 'init_geom': instab, path = filesys.read.instability_transformation( spc_dct, spc_name, ini_thy_info, save_prefix) skip = (instab is not None) if skip: ioprinter.info_message( f'Found instability file at path {path}', newline=1) ioprinter.info_message( 'Skipping task for unstable species...', newline=1) return skip
def _id_reaction(rxn_info, thy_info, save_prefix): """ Identify the reaction and build the object :param rxn_info: reaction info object :type rxn_info: mechanalyzer.inf.rxn object :rtype: (tuple(automol.Reaction object), tuple(automol.zmat object)) """ # Check the save filesystem for the reactant and product geometries rct_geos, prd_geos, rct_paths, prd_paths = reagent_geometries( rxn_info, thy_info, save_prefix) # Identify reactants and products from geoms or InChIs, depending # We automatically assess and add stereo to the reaction object, as needed if any(rct_geos) and any(prd_geos): print(' Reaction ID from geometries from SAVE filesys') for i, path in enumerate(rct_paths): print(f' - reactant {i+1}: {path}') for i, path in enumerate(prd_paths): print(f' - product {i+1}: {path}') zrxn_objs = automol.reac.rxn_objs_from_geometry( rct_geos, prd_geos, indexing='zma', stereo=False) # rct_geos, prd_geos, indexing='zma', stereo=True) else: print(' Reaction ID from geometries from input InChIs') rxn_ichs = rinfo.value(rxn_info, 'inchi') rct_ichs, prd_ichs = rxn_ichs[0], rxn_ichs[1] zrxn_objs = automol.reac.rxn_objs_from_inchi( rct_ichs, prd_ichs, indexing='zma', stereo=False) # rct_ichs, prd_ichs, indexing='zma', stereo=True) # Loop over the found reaction objects if zrxn_objs is not None: zrxns, zmas = (), () for obj_set in zrxn_objs: zrxn, zma, _, _ = obj_set zrxns += (zrxn,) zmas += (zma,) else: zrxns, zmas = None, None return zrxns, zmas
def _mod_class(class_typ, rxn_info): """ Create the object containing the full description of the reaction class, including its type, spin state, and whether it is a radical-radical combination. :param class_typ: reaction class type :type class_typ: str :param rxn_info: ??? :tpye rxn_info: ??? """ # Set the spin of the reaction to high/low if automol.par.need_spin_designation(class_typ): ts_mul = rinfo.value(rxn_info, 'tsmult') high_mul = rinfo.ts_mult(rxn_info, rxn_mul='high') _spin = 'high-spin' if ts_mul == high_mul else 'low-spin' else: _spin = '' return automol.par.reaction_class_from_data(class_typ, _spin, rinfo.radrad(rxn_info))
def remove_radrad_ts(obj_queue, spc_dct): """ Remove TSs who have no information from the queue and include them in the missing data lists """ ioprinter.info_message( 'Removing low-spin radical-radical TS from queue...\n') new_queue = () for obj in obj_queue: if 'ts_' in obj: rxn_info = spc_dct[obj]['rxn_info'] ts_mul = rinfo.value(rxn_info, 'tsmult') high_ts_mul = rinfo.ts_mult(rxn_info, rxn_mul='high') if rinfo.radrad(rxn_info) and ts_mul != high_ts_mul: ioprinter.info_message(f'Removing {obj} from queue.') else: new_queue += (obj, ) else: new_queue += (obj, ) return new_queue
def skip_task(spc_dct, spc_name): """ Should this task be skipped? :param spc_dct: species dictionary :type spc_dct: dictionary :param spc_name: name of species :type spc_name: string :rtype skip: boolean """ skip = False # It should be skipped if its radical radical if 'ts' in spc_name: rxn_info = spc_dct[spc_name]['rxn_info'] ts_mul = rinfo.value(rxn_info, 'tsmult') high_ts_mul = rinfo.ts_mult(rxn_info, rxn_mul='high') if rinfo.radrad(rxn_info) and ts_mul != high_ts_mul: skip = True ioprinter.info_message( 'Skipping task because {} is a low-spin radical radical reaction' .format(spc_name)) return skip
def _mod_class(cls, rxn_info): """ append additional info to the class """ full_cls_str = '' # Determine the string for radical radical reactions radrad = rinfo.radrad(rxn_info) radrad_str = 'radical-radical' if radrad else '' full_cls_str += radrad_str # Set the spin of the reaction to high/low if 'addition' in cls or 'absraction' in cls: ts_mul = rinfo.value(rxn_info, 'tsmult') high_mul = rinfo.ts_mult(rxn_info, rxn_mul='high') spin_str = 'high-spin' if ts_mul == high_mul else 'low-spin' full_cls_str += ' ' + spin_str else: spin_str = '' # Add the class label full_cls_str += ' ' + cls return full_cls_str
def ts_dct_sing_chnl(pes_idx, reaction, spc_dct, run_prefix, save_prefix, thy_info=None, ini_thy_info=None, id_missing=True, re_id=False): """ build dct for single reaction """ # Unpack the reaction object chnl_idx, (reacs, prods) = reaction rxn_info = rinfo.from_dct(reacs, prods, spc_dct) rct_str, prd_str = '+'.join(reacs), '+'.join(prods) print(f'\n Preparing for reaction {rct_str} = {prd_str}') # Set the reacs and prods for the desired direction reacs, prods = rxnid.set_reaction_direction(reacs, prods, rxn_info, thy_info, ini_thy_info, save_prefix, direction='forw') # Obtain the reaction object for the reaction zma_locs = (0, ) # is there a better way to get this hbond param out of spc_dct and does # it matter in getting the mincofs to build the reaction if we bother # to include it? # hbond_cutoffs = spc_dct[reacs[0]]['hbond_cutoffs'] zrxns, zmas, rclasses, status = rxnid.build_reaction(rxn_info, ini_thy_info, zma_locs, save_prefix, id_missing=id_missing, re_id=re_id) # , hbond_cutoffs=hbond_cutoffs) # Could reverse the spc dct if status not in ('MISSING-SKIP', 'MISSING-ADD'): ts_dct = {} for idx, (zrxn, zma, cls) in enumerate(zip(zrxns, zmas, rclasses)): tsname = f'ts_{pes_idx+1:d}_{chnl_idx+1:d}_{idx:d}' ts_dct[tsname] = { 'zrxn': zrxn, 'zma': zma, 'reacs': reacs, 'prods': prods, 'rxn_info': rxn_info, 'inchi': '', 'charge': rinfo.ts_chg(rxn_info), 'mult': rinfo.value(rxn_info, 'tsmult'), 'elec_levels': ((0.0, rinfo.value(rxn_info, 'tsmult')), ), 'hind_inc': 30.0 * phycon.DEG2RAD, 'hbond_cutoffs': (4.55, 1.92), 'class': cls, 'rxn_fs': reaction_fs(run_prefix, save_prefix, rxn_info) } elif status == 'MISSING-ADD': tsname = f'ts_{pes_idx+1:d}_{chnl_idx+1:d}_0' ts_dct = {} ts_dct[tsname] = {'missdata': ini_thy_info} elif status == 'MISSING-SKIP': ts_dct = {} print('Skipping reaction as class not given/identified') return ts_dct