Ejemplo n.º 1
0
def _save_unique_conformer(ret,
                           thy_info,
                           cnf_save_fs,
                           locs,
                           saddle=False,
                           zma_locs=(0, )):
    """ Save the conformer in the filesystem
    """

    # Set the path to the conformer save filesystem
    cnf_save_path = cnf_save_fs[-1].path(locs)

    # Unpack the ret object and obtain the prog and method
    inf_obj, inp_str, out_str = ret
    prog = inf_obj.prog
    method = inf_obj.method

    # Read the energy and geom from the output
    ene = elstruct.reader.energy(prog, method, out_str)
    geo = elstruct.reader.opt_geometry(prog, out_str)
    zma = elstruct.reader.opt_zmatrix(prog, out_str)

    # Read the tra and graph
    if saddle:
        ts_min_cnf_locs, ts_min_path = filesys.mincnf.min_energy_conformer_locators(
            cnf_save_fs, thy_info)
        ts_min_zma_fs = fs.zmatrix(ts_min_path)
        print('ts_min_path test:', ts_min_path)
        tra = ts_min_zma_fs[-1].file.transformation.read(zma_locs)
        print('zma_locs test:', zma_locs)
        rct_gra = ts_min_zma_fs[-1].file.reactant_graph.read(zma_locs)

    # Build the conformer filesystem and save the structural info
    print(" - Geometry is unique. Saving...")
    print(" - Save path: {}".format(cnf_save_path))
    cnf_save_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)

    # Build the zma filesystem and save the z-matrix
    zma_save_fs = fs.zmatrix(cnf_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)

    # Save the tra and gra for a saddle
    if saddle:
        zma_save_fs[-1].file.transformation.write(tra, zma_locs)
        zma_save_fs[-1].file.reactant_graph.write(rct_gra, zma_locs)

    # Saving the energy to a SP filesystem
    print(" - Saving energy of unique geometry...")
    sp_save_fs = autofile.fs.single_point(cnf_save_path)
    sp_save_fs[-1].create(thy_info[1:4])
    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])
Ejemplo n.º 2
0
def zma_fs_from_prefix(prefix, zma_idxs=(0, )):
    """ Build a zma filesys object
    """

    zma_fs = fs.zmatrix(prefix)
    zma_fs[-1].create(zma_idxs)
    zma_path = zma_fs[-1].path(zma_idxs)

    return zma_fs, zma_path
Ejemplo n.º 3
0
def _ts_geo_viable(zma, zrxn, cnf_save_fs, mod_thy_info, zma_locs=(0, )):
    """ Perform a series of checks to assess the viability
        of a transition state geometry prior to saving
    """

    # Obtain the min-ene zma and bond keys
    _, cnf_save_path = filesys.mincnf.min_energy_conformer_locators(
        cnf_save_fs, mod_thy_info)
    zma_save_fs = fs.zmatrix(cnf_save_path)
    ref_zma = zma_save_fs[-1].file.zmatrix.read(zma_locs)

    return automol.reac.similar_saddle_point_structure(zma, ref_zma, zrxn)
Ejemplo n.º 4
0
def all_rxn_bnd_keys(cnf_fs, cnf_locs, zma_locs=(0,)):
    """ get bond broken and formed keys for a transition state
    """

    cnf_path = cnf_fs[-1].path(cnf_locs)
    zma_fs = fs.zmatrix(cnf_path)
    tra = zma_fs[-1].file.transformation.read(zma_locs)
    frm_bnd_keys, brk_bnd_keys = tra
    print('rxn keys')
    print(frm_bnd_keys)
    print(brk_bnd_keys)

    return frm_bnd_keys, brk_bnd_keys
Ejemplo n.º 5
0
def rxn_bnd_keys2(path, zma_locs=(0,)):
    """ get bond broken and formed keys for a transition state
    """

    print('zma path', path)
    zma_fs = fs.zmatrix(path)
    tra = zma_fs[-1].file.transformation.read(zma_locs)
    frm_bnd_keys, brk_bnd_keys = tra
    if frm_bnd_keys:
        frm_bnd_keys = next(iter(frm_bnd_keys))
    if brk_bnd_keys:
        brk_bnd_keys = next(iter(brk_bnd_keys))

    return frm_bnd_keys, brk_bnd_keys
Ejemplo n.º 6
0
def rxn_bnd_keys(cnf_fs, cnf_locs, zma_locs=(0,)):
    """ get bond broken and formed keys for a transition state
    """

    print('cnf locs', cnf_locs)
    cnf_path = cnf_fs[-1].path(cnf_locs)
    zma_fs = fs.zmatrix(cnf_path)
    tra = zma_fs[-1].file.transformation.read(zma_locs)
    frm_bnd_keys, brk_bnd_keys = tra
    print('rxn keys')
    print(frm_bnd_keys)
    print(brk_bnd_keys)
    if frm_bnd_keys:
        frm_bnd_keys = next(iter(frm_bnd_keys))
    if brk_bnd_keys:
        brk_bnd_keys = next(iter(brk_bnd_keys))

    return frm_bnd_keys, brk_bnd_keys
Ejemplo n.º 7
0
def build_rotors(spc_dct_i, pf_filesystems, spc_mod_dct_i,
                 read_potentials=True):
    """ Add more rotor info
    """

    run_prefix = pf_filesystems['run_prefix']
    spc_info = sinfo.from_dct(spc_dct_i)
    spc_fml = automol.inchi.formula_string(spc_info[0])
    if spc_fml is None:
        spc_fml = 'TS'
    run_path = job_path(run_prefix, 'PROJROT', 'FREQ', spc_fml, locs_idx=None)

    # Set up tors level filesystem and model and level
    tors_model = spc_mod_dct_i['tors']['mod']
    tors_ene_info = spc_mod_dct_i['tors']['enelvl'][1][1]
    mod_tors_ene_info = tinfo.modify_orb_label(
        tors_ene_info, sinfo.from_dct(spc_dct_i))

    rotors = None
    if pf_filesystems['tors'] is not None:
        [cnf_fs, cnf_save_path, min_cnf_locs, _, _] = pf_filesystems['tors']

        # Build the rotors
        ref_ene = filesys.read.energy(cnf_fs, min_cnf_locs, mod_tors_ene_info)
        zma_fs = fs.zmatrix(cnf_fs[-1].path(min_cnf_locs))
        if (
            zma_fs[-1].file.torsions.exists([0]) and
            zma_fs[-1].file.zmatrix.exists([0]) and
            tors_model != 'rigid'
        ):
            rotors = automol.rotor.from_data(
                zma=zma_fs[-1].file.zmatrix.read([0]),
                tors_inf_dct=zma_fs[-1].file.torsions.read([0]),
                tors_names=spc_dct_i.get('tors_names', None),
                multi=bool('1d' in tors_model))

        # Read the potential grids
        if read_potentials and rotors is not None:
            rotors = _read_potentials(
                rotors, spc_dct_i, run_path, cnf_save_path,
                ref_ene, mod_tors_ene_info,
                tors_model)

    return rotors
Ejemplo n.º 8
0
def save_saddle_point(opt_ret,
                      hess_ret,
                      freqs,
                      imags,
                      mod_thy_info,
                      cnf_save_fs,
                      ts_save_fs,
                      ts_save_path,
                      frm_bnd_keys,
                      brk_bnd_keys,
                      rcts_gra,
                      zma_locs=(0, )):
    """ Optimize the transition state structure obtained from the grid search
    """

    # Read the geom, energy, and Hessian from output
    opt_inf_obj, opt_inp_str, opt_out_str = opt_ret
    opt_prog = opt_inf_obj.prog
    opt_method = opt_inf_obj.method
    ene = elstruct.reader.energy(opt_prog, opt_method, opt_out_str)
    geo = elstruct.reader.opt_geometry(opt_prog, opt_out_str)
    zma = elstruct.reader.opt_zmatrix(opt_prog, opt_out_str)
    print('TS Geometry:')
    print(automol.geom.string(geo))
    print()

    # Build new zma using x2z and new torsion coordinates
    # zma = automol.geometry.zmatrix(
    #     geo, ts_bnd=(frm_bnd_keys, brk_bnd_keys))

    print(" - Reading hessian from output...")
    hess_inf_obj, hess_inp_str, hess_out_str = hess_ret
    hess_prog = hess_inf_obj.prog
    hess = elstruct.reader.hessian(hess_prog, hess_out_str)
    freqs = sorted([-1.0 * val for val in imags] + freqs)
    print('TS freqs: {}'.format(' '.join(str(freq) for freq in freqs)))

    # Save the information into the filesystem
    print(" - Saving...")
    print(" - Save path: {}".format(ts_save_path))

    # Save geom in the upper theory/TS layer
    ts_save_fs[0].file.geometry.write(geo)

    # Save this structure as first conformer
    locs = [autofile.schema.generate_new_conformer_id()]
    cnf_save_fs[-1].create(locs)
    cnf_save_fs[-1].file.geometry_info.write(opt_inf_obj, locs)
    cnf_save_fs[-1].file.geometry_input.write(opt_inp_str, locs)
    cnf_save_fs[-1].file.hessian_info.write(hess_inf_obj, locs)
    cnf_save_fs[-1].file.hessian_input.write(hess_inp_str, locs)
    cnf_save_fs[-1].file.energy.write(ene, locs)
    cnf_save_fs[-1].file.geometry.write(geo, locs)
    cnf_save_fs[-1].file.hessian.write(hess, locs)
    cnf_save_fs[-1].file.harmonic_frequencies.write(freqs, locs)
    cnf_save_path = cnf_save_fs[-1].path(locs)

    # Save the zmatrix information in a zma filesystem
    cnf_save_path = cnf_save_fs[-1].path(locs)
    zma_save_fs = fs.zmatrix(cnf_save_path)
    zma_save_fs[-1].create(zma_locs)
    zma_save_fs[-1].file.geometry_info.write(opt_inf_obj, zma_locs)
    zma_save_fs[-1].file.geometry_input.write(opt_inp_str, zma_locs)
    zma_save_fs[-1].file.zmatrix.write(zma, zma_locs)

    # Save the form and break keys in the filesystem
    tra = (frozenset({frm_bnd_keys}), frozenset({brk_bnd_keys}))
    zma_save_fs[-1].file.transformation.write(tra, zma_locs)
    zma_save_fs[-1].file.reactant_graph.write(rcts_gra, zma_locs)

    # Save the energy in a single-point filesystem
    print(" - Saving energy...")
    sp_save_fs = autofile.fs.single_point(cnf_save_path)
    sp_save_fs[-1].create(mod_thy_info[1:4])
    sp_save_fs[-1].file.input.write(opt_inp_str, mod_thy_info[1:4])
    sp_save_fs[-1].file.info.write(opt_inf_obj, mod_thy_info[1:4])
    sp_save_fs[-1].file.energy.write(ene, mod_thy_info[1:4])
Ejemplo n.º 9
0
def read_hr_pot(tors_names,
                tors_grids,
                cnf_save_path,
                mod_tors_ene_info,
                ref_ene,
                constraint_dct,
                read_geom=False,
                read_grad=False,
                read_hess=False,
                read_zma=False):
    """ Get the potential for a hindered rotor
    """

    # Build initial lists for storing potential energies and Hessians
    grid_points, grid_vals = set_scan_dims(tors_grids)
    pot, geoms, grads, hessians, zmas, paths = {}, {}, {}, {}, {}, {}

    # Set up filesystem information
    zma_fs = fs.zmatrix(cnf_save_path)
    zma_path = zma_fs[-1].path([0])
    if constraint_dct is None:
        scn_fs = autofile.fs.scan(zma_path)
    else:
        scn_fs = autofile.fs.cscan(zma_path)

    # Read the energies and Hessians from the filesystem
    for point, vals in zip(grid_points, grid_vals):

        locs = [tors_names, vals]
        if constraint_dct is not None:
            locs = [constraint_dct] + locs

        ene = read_tors_ene(scn_fs, locs, mod_tors_ene_info)
        if ene is not None:
            pot[point] = (ene - ref_ene) * phycon.EH2KCAL
        else:
            pot[point] = -10.0

        # print('path test in read_hr_pot:', scn_fs[-1].path(locs))
        if read_geom:
            if scn_fs[-1].file.geometry.exists(locs):
                geoms[point] = scn_fs[-1].file.geometry.read(locs)
            else:
                geoms[point] = None

        if read_grad:
            if scn_fs[-1].file.gradient.exists(locs):
                grads[point] = scn_fs[-1].file.gradient.read(locs)
            else:
                grads[point] = None

        if read_hess:
            if scn_fs[-1].file.hessian.exists(locs):
                hessians[point] = scn_fs[-1].file.hessian.read(locs)
            else:
                hessians[point] = None

        if read_zma:
            if scn_fs[-1].file.zmatrix.exists(locs):
                zmas[point] = scn_fs[-1].file.zmatrix.read(locs)
            else:
                zmas[point] = None

        paths[point] = scn_fs[-1].path(locs)

    return pot, geoms, grads, hessians, zmas, paths
Ejemplo n.º 10
0
def _ts_geo_viable(zma, cnf_save_fs, rxn_class, mod_thy_info, zma_locs=(0, )):
    """ Perform a series of checks to assess the viability
        of a transition state geometry prior to saving
    """

    # Initialize viable
    viable = True

    # Obtain the min-ene zma and bond keys
    min_cnf_locs, cnf_save_path = filesys.mincnf.min_energy_conformer_locators(
        cnf_save_fs, mod_thy_info)
    zma_save_fs = fs.zmatrix(cnf_save_path)
    ref_zma = zma_save_fs[-1].file.zmatrix.read(zma_locs)

    # Read the form and broken keys from the min conf
    # frm_bnd_keys, brk_bnd_keys = tsprep.rxn_bnd_keys(
    frm_bnd_keys, brk_bnd_keys = tsprep.all_rxn_bnd_keys(cnf_save_fs,
                                                         min_cnf_locs,
                                                         zma_locs=zma_locs)

    # Use the idxs to set the forming and breaking bond names
    #    if frm_bnd_keys:
    #      frm_name = automol.zmatrix.bond_key_from_idxs(
    #           zma, frm_bnd_keys)
    #        ts_bnd1, ts_bnd2 = min(frm_bnd_keys), max(frm_bnd_keys)
    #    else:
    #      frm_name = ''
    #        ts_bnd1, ts_bnd2 = None, None

    # if brk_bnd_keys:
    #  brk_name = automol.zmatrix.bond_key_from_idxs(
    #      zma, brk_bnd_keys)
    # else:
    #  brk_name = ''
    # print('frm_name', frm_name)
    # print('brk_name', brk_name)

    # Calculate the distance of bond being formed
    # cnf_dct = automol.zmatrix.values(zma)
    # ref_dct = automol.zmatrix.values(ref_zma)
    cnf_geo = automol.zmatrix.geometry(zma)
    ref_geo = automol.zmatrix.geometry(ref_zma)

    cnf_dist_lst = []
    ref_dist_lst = []
    bnd_key_lst = []
    cnf_ang_lst = []
    ref_ang_lst = []
    for frm_bnd_key in frm_bnd_keys:
        print('frm_bnd_key test:', frm_bnd_key)
        frm_idx1, frm_idx2 = list(frm_bnd_key)
        cnf_dist = automol.geom.distance(cnf_geo, frm_idx1, frm_idx2)
        ref_dist = automol.geom.distance(ref_geo, frm_idx1, frm_idx2)
        cnf_dist_lst.append(cnf_dist)
        ref_dist_lst.append(ref_dist)
        bnd_key_lst.append(frm_bnd_key)

    for brk_bnd_key in brk_bnd_keys:
        brk_idx1, brk_idx2 = list(brk_bnd_key)
        cnf_dist = automol.geom.distance(cnf_geo, brk_idx1, brk_idx2)
        ref_dist = automol.geom.distance(ref_geo, brk_idx1, brk_idx2)
        cnf_dist_lst.append(cnf_dist)
        ref_dist_lst.append(ref_dist)
        bnd_key_lst.append(brk_bnd_key)

    for frm_bnd_key in frm_bnd_keys:
        for brk_bnd_key in brk_bnd_keys:
            for frm_idx in frm_bnd_key:
                for brk_idx in brk_bnd_key:
                    if frm_idx == brk_idx:
                        idx2 = frm_idx
                        idx1 = list(frm_bnd_key - frozenset({idx2}))[0]
                        idx3 = list(brk_bnd_key - frozenset({idx2}))[0]
                        cnf_ang = automol.geom.central_angle(
                            cnf_geo, idx1, idx2, idx3)
                        ref_ang = automol.geom.central_angle(
                            ref_geo, idx1, idx2, idx3)
                        cnf_ang_lst.append(cnf_ang)
                        ref_ang_lst.append(ref_ang)

    #      cnf_dist = cnf_dct.get(frm_name, None)
    #      ref_dist = ref_dct.get(frm_name, None)
    #  if cnf_dist is None:
    #      cnf_dist = cnf_dct.get(brk_name, None)
    #  if ref_dist is None:
    #      ref_dist = ref_dct.get(brk_name, None)
    print('bnd_key_list', bnd_key_lst)
    print('conf_dist', cnf_dist_lst)
    print('ref_dist', ref_dist_lst)
    print('conf_angle', cnf_ang_lst)
    print('ref_angle', ref_ang_lst)

    #  # Calculate the central angle of reacting moiety of zma
    #  cnf_angle = geomprep.calc_rxn_angle(
    #      zma, frm_bnd_keys, brk_bnd_keys, rxn_class)
    #  ref_angle = geomprep.calc_rxn_angle(
    #      ref_zma, frm_bnd_keys, brk_bnd_keys, rxn_class)
    #  print('conf_angle', cnf_angle)
    #  print('ref_angle', ref_angle)

    # Set the maximum allowed displacement for a TS conformer
    max_disp = 0.6
    # would be better to check for bond forming length in bond scission with ring forming
    if 'addition' in rxn_class:
        max_disp = 0.8
    if 'abstraction' in rxn_class:
        # this was 1.4 - SJK reduced it to work for some OH abstractions
        max_disp = 1.0

    # Check forming bond angle similar to ini config
    if 'elimination' not in rxn_class:
        for ref_angle, cnf_angle in zip(ref_ang_lst, cnf_ang_lst):
            if abs(cnf_angle - ref_angle) > .44:
                print(
                    " - Transition State conformer has",
                    "diverged from original structure of",
                    "angle {:.3f} with angle {:.3f}".format(
                        ref_angle, cnf_angle))
                viable = False

    symbols = automol.geom.symbols(cnf_geo)
    lst_info = zip(ref_dist_lst, cnf_dist_lst, bnd_key_lst)
    for ref_dist, cnf_dist, bnd_key in lst_info:
        if 'add' in rxn_class or 'abst' in rxn_class:
            bnd_key1, bnd_key2 = min(list(bnd_key)), max(list(bnd_key))
            symb1 = symbols[bnd_key1]
            symb2 = symbols[bnd_key2]

            if bnd_key in frm_bnd_keys:
                # Check if radical atom is closer to some atom
                # other than the bonding atom
                cls = geomprep.is_atom_closest_to_bond_atom(
                    zma, bnd_key2, cnf_dist)
                if not cls:
                    print(
                        " - Transition State conformer has",
                        "diverged from original structure of",
                        "dist {:.3f} with dist {:.3f}".format(
                            ref_dist, cnf_dist))
                    print(' - Radical atom now has a new nearest neighbor')
                    viable = False
                # check forming bond distance
                if abs(cnf_dist - ref_dist) > max_disp:
                    print(
                        " - Transition State conformer has",
                        "diverged from original structure of",
                        "dist {:.3f} with dist {:.3f}".format(
                            ref_dist, cnf_dist))
                    viable = False

            # Check distance relative to equi. bond
            if (symb1, symb2) in bnd.LEN_DCT:
                equi_bnd = bnd.LEN_DCT[(symb1, symb2)]
            elif (symb2, symb1) in bnd.LEN_DCT:
                equi_bnd = bnd.LEN_DCT[(symb2, symb1)]
            else:
                equi_bnd = 0.0
            displace_from_equi = cnf_dist - equi_bnd
            dchk1 = abs(cnf_dist - ref_dist) > 0.1
            dchk2 = displace_from_equi < 0.2
            if dchk1 and dchk2:
                print(
                    " - Transition State conformer has", "converged to an",
                    "equilibrium structure with dist",
                    " {:.3f} comp with equil {:.3f}".format(
                        cnf_dist, equi_bnd))
                viable = False
        else:
            # check forming/breaking bond distance
            # if abs(cnf_dist - ref_dist) > 0.4:
            # max disp of 0.4 causes problems for bond scission with ring forming
            # not sure if setting it to 0.3 will cause problems for other cases
            if abs(cnf_dist - ref_dist) > 0.3:
                print(
                    " - Transition State conformer has",
                    "diverged from original structure of",
                    "dist {:.3f} with dist {:.3f}".format(ref_dist, cnf_dist))
                viable = False

    return viable
Ejemplo n.º 11
0
def build_rotors(spc_dct_i,
                 pf_filesystems,
                 pf_models,
                 pf_levels,
                 rxn_class='',
                 frm_bnd_keys=(),
                 brk_bnd_keys=()):
    """ Add more rotor info
    """

    saddle = bool(rxn_class and (frm_bnd_keys or brk_bnd_keys))

    # Set up tors level filesystem and model and level
    print('pflvls', pf_levels)
    tors_model = pf_models['tors']
    tors_ene_info = pf_levels['tors'][1][0]
    mod_tors_ene_info = filesys.inf.modify_orb_restrict(
        filesys.inf.get_spc_info(spc_dct_i), tors_ene_info)
    [cnf_fs, cnf_save_path, min_cnf_locs, _, _] = pf_filesystems['tors']

    # Grab the zmatrix
    if min_cnf_locs is not None:
        zma_fs = fs.zmatrix(cnf_fs[-1].path(min_cnf_locs))
        zma = zma_fs[-1].file.zmatrix.read([0])
        remdummy = geomprep.build_remdummy_shift_lst(zma)
        geo = cnf_fs[-1].file.geometry.read(min_cnf_locs)

        # Read the reference energy
        ref_ene = torsprep.read_tors_ene(cnf_fs, min_cnf_locs,
                                         mod_tors_ene_info)

    # Set the tors names
    rotor_inf = _rotor_info(zma,
                            spc_dct_i,
                            cnf_fs,
                            min_cnf_locs,
                            tors_model,
                            frm_bnd_keys=frm_bnd_keys,
                            brk_bnd_keys=brk_bnd_keys)

    # Read the potential energy surface for the rotors
    num_rotors = len(rotor_inf[0])
    rotors = []
    for tors_names, tors_grids, tors_syms in zip(*rotor_inf):

        # Initialize dct to hold info for each torsion of rotor
        rotor_dct = {}

        # Read the potential along the rotors
        if tors_model in ('mdhr', 'mdhrv'):

            # Set to read additional info for vibrational adiabaticity
            if tors_model == 'mdhrv':
                read_geom, read_grad, read_hess = True, True, True
            else:
                read_geom, read_grad, read_hess = False, False, False

            # Read and MDHR potential for single MDHR rotor
            # Could be MDHR mod for sys w/ 1 Rotor
            if ((num_rotors > 1 and len(tors_names) > 1) or num_rotors == 1):
                pot, geoms, grads, hessians, _, _ = torsprep.read_hr_pot(
                    tors_names,
                    tors_grids,
                    cnf_save_path,
                    mod_tors_ene_info,
                    ref_ene,
                    constraint_dct=None,  # No extra frozen treatments
                    read_geom=read_geom,
                    read_grad=read_grad,
                    read_hess=read_hess)
                rotor_dct['mdhr_pot_data'] = (pot, geoms, grads, hessians)

        for tname, tgrid, tsym in zip(tors_names, tors_grids, tors_syms):

            # Build constraint dct
            if tors_model == '1dhrf':
                tname_tup = tuple([tname])
                const_names = tuple(itertools.chain(*rotor_inf[0]))
                constraint_dct = torsprep.build_constraint_dct(
                    zma, const_names, tname_tup)
            elif tors_model == '1dhrfa':
                coords = list(automol.zmatrix.coordinates(zma))
                const_names = tuple(coord for coord in coords)
                tname_tup = tuple([tname])
                constraint_dct = torsprep.build_constraint_dct(
                    zma, const_names, tname_tup)
            else:
                constraint_dct = None

            # Call read pot for 1DHR
            pot, _, _, _, _, _ = torsprep.read_hr_pot([tname], [tgrid],
                                                      cnf_save_path,
                                                      mod_tors_ene_info,
                                                      ref_ene, constraint_dct)
            pot = _hrpot_spline_fitter(pot,
                                       min_thresh=-0.0001,
                                       max_thresh=50.0)

            # Get the HR groups and axis for the rotor
            group, axis, pot, sym_num = torsprep.set_tors_def_info(
                zma,
                tname,
                tsym,
                pot,
                frm_bnd_keys,
                brk_bnd_keys,
                rxn_class,
                saddle=saddle)
            remdummy = geomprep.build_remdummy_shift_lst(zma)

            # Get the indices for the torsion
            mode_idxs = automol.zmatrix.coord_idxs(zma, tname)
            mode_idxs = tuple((idx + 1 for idx in mode_idxs))

            # Determine the flux span using the symmetry number
            mode_span = 360.0 / tsym

            # Build dictionary for the torsion
            keys = [
                'group', 'axis', 'sym_num', 'remdummy', 'pot', 'atm_idxs',
                'span', 'hrgeo'
            ]
            vals = [
                group, axis, sym_num, remdummy, pot, mode_idxs, mode_span, geo
            ]
            rotor_dct[tname] = dict(zip(keys, vals))

        # print('rotors pot test:', pot)
        # Append to lst
        rotors.append(rotor_dct)

    return rotors