Beispiel #1
0
def test__ts_hydrogen_abstraction():
    """ test zmatrix.ts.hydrogen_abstraction
    """

    rct_zmas = [CH4_ZMA, OH_ZMA]
    prd_zmas = [CH3_ZMA, H2O_ZMA]
    rct_zmas, rct_gras = shifted_standard_zmas_graphs(rct_zmas,
                                                      remove_stereo=True)
    prd_zmas, prd_gras = shifted_standard_zmas_graphs(prd_zmas,
                                                      remove_stereo=True)

    tras, _, _, rtyp = automol.graph.reac.classify(rct_gras, prd_gras)
    print('\nrtyp', rtyp)

    zma_ret = hydrogen_abstraction(rct_zmas, prd_zmas, tras)
    print('zma\n', automol.zmatrix.string(zma_ret['ts_zma']))
    print('bnd keys\n', zma_ret['bnd_keys'])
    print('const keys\n', zma_ret['const_keys'])
Beispiel #2
0
def test__ts_insertion():
    """ test zmatrix.ts.insertion
    """

    rct_zmas = [C2H6_ZMA, CH2_ZMA]
    prd_zmas = [C3H8_ZMA]
    rct_zmas, rct_gras = shifted_standard_zmas_graphs(rct_zmas,
                                                      remove_stereo=True)
    prd_zmas, prd_gras = shifted_standard_zmas_graphs(prd_zmas,
                                                      remove_stereo=True)

    tras, _, _, rtyp = automol.graph.reac.classify(rct_gras, prd_gras)
    print('\nrtyp', rtyp)

    zma_ret = insertion(rct_zmas, prd_zmas, tras)
    print('zma\n', automol.zmatrix.string(zma_ret['ts_zma']))
    print('bnd keys\n', zma_ret['bnd_keys'])
    print('const keys\n', zma_ret['const_keys'])
Beispiel #3
0
def test__ts_elimination():
    """ test zmatrix.ts.elimination
    """

    rct_zmas = [CH3CH2OO_ZMA]
    prd_zmas = [C2H4_ZMA, HO2_ZMA]
    rct_zmas, rct_gras = shifted_standard_zmas_graphs(rct_zmas,
                                                      remove_stereo=True)
    prd_zmas, prd_gras = shifted_standard_zmas_graphs(prd_zmas,
                                                      remove_stereo=True)
    rct_zmas = [rct_zmas]
    prd_zmas = [prd_zmas]

    tras, _, _, rtyp = automol.graph.reac.classify(rct_gras, prd_gras)
    print('\nrtyp', rtyp)

    zma_ret = concerted_unimol_elimination(rct_zmas, prd_zmas, tras)
    print('zma\n', automol.zmatrix.string(zma_ret['ts_zma']))
    print('bnd keys\n', zma_ret['bnd_keys'])
    print('const keys\n', zma_ret['const_keys'])
Beispiel #4
0
def test__ts_ring_forming_scission():
    """ test zmatrix.ts.ring_forming_scission
    """

    rct_zmas = [CH2CH2OOH_ZMA]
    prd_zmas = [cCH2OCH2_ZMA, OH_ZMA]
    rct_zmas, rct_gras = shifted_standard_zmas_graphs(rct_zmas,
                                                      remove_stereo=True)
    prd_zmas, prd_gras = shifted_standard_zmas_graphs(prd_zmas,
                                                      remove_stereo=True)
    rct_zmas = [rct_zmas]
    prd_zmas = [prd_zmas]

    tras, _, _, rtyp = automol.graph.reac.classify(rct_gras, prd_gras)
    print('\nrtyp', rtyp)

    zma_ret = ring_forming_scission(rct_zmas, prd_zmas, tras)
    print('zma\n', automol.zmatrix.string(zma_ret['ts_zma']))
    print('bnd keys\n', zma_ret['bnd_keys'])
    print('const keys\n', zma_ret['const_keys'])
Beispiel #5
0
def _hydrogen_abstraction(rct_zmas, prd_zmas, tras):
    """ standard hydrogen abstraction
    """

    ret = None
    dist_name = 'rts'
    dist_val = 3.

    # Deal with nasty cases which ruin the ordering
    rct2_gra = automol.zmatrix.graph(rct_zmas[1], remove_stereo=True)
    rad_atm_keys = automol.graph.resonance_dominant_radical_atom_keys(rct2_gra)
    # fix for O2 which is recognized as a radical
    # in the long run it would be better to put then in the
    # resonance_dominant_radical_atom_keys function
    if not rad_atm_keys:
        ich = automol.graph.inchi(rct2_gra)
        if ich == 'InChI=1S/O2/c1-2':
            rad_atm_keys = [0]
            return None
    # hno2 hack
    # rad_atm_keys = [0]
    if 0 not in rad_atm_keys:
        rct_zmas[1] = reorder_zma_for_radicals(rct_zmas[1], min(rad_atm_keys))
        rct2_gra = automol.zmatrix.graph(rct_zmas[1], remove_stereo=True)
        rad_atm_keys = automol.graph.resonance_dominant_radical_atom_keys(
            rct2_gra)
        # following assert checks to ensure that the first atom
        # in the second reactant is a radical
        # this is required for the remainder of the routine
        assert 0 in rad_atm_keys

    # Shift Graph now?
    rct_zmas, rct_gras = shifted_standard_zmas_graphs(rct_zmas,
                                                      remove_stereo=True)
    prd_zmas, prd_gras = shifted_standard_zmas_graphs(prd_zmas,
                                                      remove_stereo=True)

    # fix to put radical atom first
    # ultimately need to fix this for multiple radical centers
    # end of fix
    tra = tras[0]
    rct1_gra, rct2_gra = rct_gras
    rct1_zma, rct2_zma = rct_zmas
    rct1_natms = automol.zmatrix.count(rct1_zma)

    frm_bnd_keys, = automol.graph.trans.formed_bond_keys(tra)
    brk_bnd_keys, = automol.graph.trans.broken_bond_keys(tra)

    rct2_atm1_key = _xor(frm_bnd_keys, brk_bnd_keys)
    if not rct2_atm1_key == rct1_natms:
        rct2_gra = automol.graph.move_idx_to_top(rct2_gra, rct2_atm1_key,
                                                 rct1_natms)
        rct2_zma = automol.geom.zmatrix(automol.graph.geometry(rct2_gra))
        rct_zmas = [rct1_zma, rct2_zma]
        rct_zmas, _ = shifted_standard_zmas_graphs(rct_zmas,
                                                   remove_stereo=True)
        _, rct2_zma = rct_zmas
        new_bnd_key = []
        for key in frm_bnd_keys:
            if key == rct2_atm1_key:
                key = rct1_natms
            new_bnd_key.append(key)
        frm_bnd_keys = frozenset(new_bnd_key)
        rct_gras = (rct1_gra, rct2_gra)
    rct1_atm1_key = next(iter(frm_bnd_keys & brk_bnd_keys))

    # if rct1 and rct2 are isomorphic, we may get an atom key on rct2.
    # in that case, determine the equivalent atom from rct1
    if rct1_atm1_key in automol.graph.atom_keys(rct2_gra):
        atm_key_dct = automol.graph.full_isomorphism(rct2_gra, rct1_gra)
        assert atm_key_dct
        rct1_atm1_key = atm_key_dct[rct1_atm1_key]

    rct1_atm2_key, rct1_atm3_key, _ = join_atom_keys(rct1_zma, rct1_atm1_key)

    # Join the reactant zmas to build the TS zma
    x_atm_key = rct1_natms
    rct1_x_zma = rct1_x_join(rct1_zma, rct1_atm1_key, rct1_atm2_key,
                             rct1_atm3_key)
    ts_zma = rct1x_rct2_join(rct1_x_zma,
                             rct2_zma,
                             dist_name,
                             dist_val,
                             rct1_atm1_key,
                             x_atm_key,
                             rct1_atm2_key,
                             join_vals=(85., 85., 170., 85., 170.))

    # Standardize the ZMA
    ts_zma = automol.zmatrix.standard_form(ts_zma)

    # Generate constraints
    # tors_keys = constbuild.bimol()

    # Shift the TS bond keys
    frm_bnd_keys = shift_vals_from_dummy(frm_bnd_keys, ts_zma)
    brk_bnd_keys = shift_vals_from_dummy(brk_bnd_keys, ts_zma)

    ret = {
        'ts_zma': ts_zma,
        'bnd_keys': (frm_bnd_keys, brk_bnd_keys),
        'const_keys': (frozenset({}), frozenset({}), frozenset({}))
    }

    return ret
Beispiel #6
0
def _sigma_hydrogen_abstraction(rct_zmas, prd_zmas):
    print('323543534343422')
    ret = None
    dist_name = 'rts'
    dist_val = 3.

    # in the future, we can get the rxn_idxs directly from
    # graph.reac.hydrogen_abstraction, because it returns them now
    rxn_idxs = automol.formula.reac.argsort_hydrogen_abstraction(
        list(map(automol.convert.zmatrix.formula, rct_zmas)),
        list(map(automol.convert.zmatrix.formula, prd_zmas)))
    if rxn_idxs is not None:
        rct_idxs, prd_idxs = rxn_idxs
        rct_zmas = list(map(rct_zmas.__getitem__, rct_idxs))
        prd_zmas = list(map(prd_zmas.__getitem__, prd_idxs))
        rct_zmas, rct_gras = shifted_standard_zmas_graphs(rct_zmas,
                                                          remove_stereo=True)
        prd_zmas, prd_gras = shifted_standard_zmas_graphs(prd_zmas,
                                                          remove_stereo=True)
        tras, _, _ = automol.graph.reac.hydrogen_abstraction(
            rct_gras, prd_gras)
        if tras:
            tra = tras[0]
            rct1_gra, rct2_gra = rct_gras
            rct1_zma, rct2_zma = rct_zmas
            rct1_natms = automol.zmatrix.count(rct1_zma)
            rct2_natms = automol.zmatrix.count(rct2_zma)

            frm_bnd_keys, = automol.graph.trans.formed_bond_keys(tra)
            brk_bnd_keys, = automol.graph.trans.broken_bond_keys(tra)
            rct1_atm1_key = next(iter(frm_bnd_keys & brk_bnd_keys))
            rct2_atm1_key = next(iter(frm_bnd_keys - brk_bnd_keys))

            # if rct1 and rct2 are isomorphic, we may get an atom key on rct2.
            # in that case, determine the equivalent atom from rct1
            if rct1_atm1_key in automol.graph.atom_keys(rct2_gra):
                atm_key_dct = automol.graph.full_isomorphism(
                    rct2_gra, rct1_gra)
                assert atm_key_dct
                rct1_atm1_key = atm_key_dct[rct1_atm1_key]

            rct1_atm2_key, rct1_atm3_key, _ = join_atom_keys(
                rct1_zma, rct1_atm1_key)

            x_zma = ((('X', (None, None, None), (None, None, None)), ), {})

            x_join_val_dct = {
                'rx': 1. * qcc.conversion_factor('angstrom', 'bohr'),
                'ax': 90. * qcc.conversion_factor('degree', 'radian'),
                'dx': 180. * qcc.conversion_factor('degree', 'radian'),
            }

            x_join_keys = numpy.array(
                [[rct1_atm1_key, rct1_atm2_key, rct1_atm3_key]])
            x_join_names = numpy.array([['rx', 'ax', 'dx']],
                                       dtype=numpy.object_)
            x_join_names[numpy.equal(x_join_keys, None)] = None
            x_join_name_set = set(numpy.ravel(x_join_names)) - {None}
            x_join_val_dct = {
                name: x_join_val_dct[name]
                for name in x_join_name_set
            }
            rct1_x_zma = automol.zmatrix.join(rct1_zma, x_zma, x_join_keys,
                                              x_join_names, x_join_val_dct)

            rct1_x_atm_key = rct1_natms

            if rct2_atm1_key in automol.graph.atom_keys(rct1_gra):
                atm_key_dct = automol.graph.full_isomorphism(
                    rct1_gra, rct2_gra)
                assert atm_key_dct
                rct2_atm1_key = atm_key_dct[rct2_atm1_key]

            rct2_atm1_key -= rct1_natms
            assert rct2_atm1_key == 0
            # insert dummy atom as the second atom in reactant 2

            insert_keys = numpy.array([[0, None, None], [None, 1, None],
                                       [None, None, 2]])[:rct2_natms]
            insert_names = numpy.array([['rx2', None,
                                         None], [None, 'ax2', None],
                                        [None, None, 'dx2']])[:rct2_natms]
            insert_val_dct = {
                'rx2': 1. * qcc.conversion_factor('angstrom', 'bohr'),
                'ax2': 90. * qcc.conversion_factor('degree', 'radian'),
                'dx2': 180. * qcc.conversion_factor('degree', 'radian'),
            }
            insert_name_set = set(numpy.ravel(insert_names)) - {None}
            insert_val_dct = {
                name: insert_val_dct[name]
                for name in insert_name_set
            }
            rct2_x_zma = automol.zmatrix.insert_dummy_atom(
                rct2_zma, 1, insert_keys, insert_names, insert_val_dct)

            join_val_dct = {
                dist_name: dist_val,
                'aabs1': 85. * qcc.conversion_factor('degree', 'radian'),
                'aabs2': 85. * qcc.conversion_factor('degree', 'radian'),
                'babs1': 170. * qcc.conversion_factor('degree', 'radian'),
                'babs2': 85. * qcc.conversion_factor('degree', 'radian'),
                'babs3': 170. * qcc.conversion_factor('degree', 'radian'),
            }

            join_keys = numpy.array(
                [[rct1_atm1_key, rct1_x_atm_key, rct1_atm2_key],
                 [None, rct1_atm1_key, rct1_x_atm_key],
                 [None, None, rct1_atm1_key]])[:rct2_natms + 1]
            join_names = numpy.array([[dist_name, 'aabs1', 'babs1'],
                                      [None, 'aabs2', 'babs2'],
                                      [None, None, 'babs3']])[:rct2_natms + 1]
            join_names[numpy.equal(join_keys, None)] = None

            join_name_set = set(numpy.ravel(join_names)) - {None}
            join_val_dct = {name: join_val_dct[name] for name in join_name_set}

            ts_zma = automol.zmatrix.join(rct1_x_zma, rct2_x_zma, join_keys,
                                          join_names, join_val_dct)

            ts_name_dct = automol.zmatrix.standard_names(ts_zma)
            dist_name = ts_name_dct[dist_name]
            ts_zma = automol.zmatrix.standard_form(ts_zma)
            rct1_tors_names = automol.zmatrix.torsion_coordinate_names(
                rct1_zma)
            rct2_tors_names = automol.zmatrix.torsion_coordinate_names(
                rct2_zma)
            tors_names = (
                tuple(map(ts_name_dct.__getitem__, rct1_tors_names)) +
                tuple(map(ts_name_dct.__getitem__, rct2_tors_names)))

            if 'babs2' in ts_name_dct:
                geo1 = automol.convert.zmatrix.geometry(rct1_zma)
                if not automol.geom.is_linear(geo1):
                    tors_name = ts_name_dct['babs2']
                    tors_names += (tors_name, )

            # babs3 should only be included if there is only group
            # connected to the radical atom
            include = include_babs3(frm_bnd_keys, rct2_gra)
            if 'babs3' in ts_name_dct and include:
                tors_name = ts_name_dct['babs3']
                tors_names += (tors_name, )

            frm_bnd_keys = shift_vals_from_dummy(frm_bnd_keys, ts_zma)
            brk_bnd_keys = shift_vals_from_dummy(brk_bnd_keys, ts_zma)

            # Build reactants graph
            atom_keys2 = automol.graph.atom_keys(rct2_gra)
            natom2 = len(atom_keys2)
            atm_key_dct = dict(
                zip(
                    atom_keys2,
                    (key + natom2 for key in atom_keys2),
                ))
            new_rct2_gra = automol.graph.relabel(rct2_gra, atm_key_dct)
            rcts_gra = automol.graph.union_from_sequence(
                (rct1_gra, new_rct2_gra))

            ret = (ts_zma, dist_name, frm_bnd_keys, brk_bnd_keys, tors_names,
                   rcts_gra)

    return ret
Beispiel #7
0
def addition(rct_zmas, prd_zmas, tras):
    """ z-matrix for an addition reaction
    """

    dist_name = 'rts'
    dist_val = 3.

    # Old sort procedure (maybe move?)
    count1 = automol.zmatrix.count(rct_zmas[0])
    if len(rct_zmas) == 2:
        count2 = automol.zmatrix.count(rct_zmas[1])
        if count1 == 1 or count1 < count2:
            rct2_zma, rct1_zma = rct_zmas
            rct_zmas = [rct1_zma, rct2_zma]
    rct1_zma, rct2_zma = rct_zmas
    rct1_gra = automol.zmatrix.graph(rct1_zma)
    rct2_gra = automol.zmatrix.graph(rct2_zma)
    rct2_natms = automol.zmatrix.count(rct2_zma)
    rct1_natms = automol.zmatrix.count(rct1_zma)

    tra = tras[0]
    frm_bnd_keyss, = automol.graph.trans.formed_bond_keys(tra)
    rct1_atm1_key, rct2_atm_key = sorted(frm_bnd_keyss)

    # Shift rct2_zma so that it's forming site is the first atom
    if rct2_atm_key != rct1_natms:
        rct2_geo = automol.zmatrix.geometry(rct2_zma)
        rct2_geo = automol.geom.swap_coordinates(rct2_geo,
                                                 rct2_atm_key - rct1_natms, 0)
        rct2_zma = automol.geom.zmatrix(rct2_geo)
        rct_zmas, rct_gras = shifted_standard_zmas_graphs([rct1_zma, rct2_zma],
                                                          remove_stereo=True)
        _, rct2_zma = rct_zmas
        rct2_atm_key = rct1_natms
        frm_bnd_keys = frozenset({rct1_atm1_key, rct2_atm_key})

    # Replace old routine with new one based on unsaturated atoms
    # Start of new routine
    rct1_unsat_keys = automol.graph.unsaturated_atom_keys(rct1_gra)
    # get neighbor keys for rct1_atm1_key
    neighbor_dct = automol.graph.atom_neighbor_keys(rct1_gra)
    atm1_nghbr_keys = neighbor_dct[rct1_atm1_key]
    # shift keys for unsaturated atoms and for atm1_nghbr keys
    # to include dummy atoms

    # second atom key
    # choose rct1_atm2 as first unsaturated neighbor to rct1_atm1
    rct1_atm2_key = None
    for key in atm1_nghbr_keys:
        if key in rct1_unsat_keys:
            rct1_atm2_key = key
            break

    # if no unsaturated neighbor, choose any atm1_nghbr
    if rct1_atm2_key is None:
        for key in atm1_nghbr_keys:
            rct1_atm2_key = key
            break

    # third atom key
    # if atm1 has two neighbors choose third atom key as second neighbor
    rct1_atm3_key = []
    for key in atm1_nghbr_keys:
        if key != rct1_atm2_key:
            rct1_atm3_key = key
            break

    # else choose it as second neighbor to atm 2
    if not rct1_atm3_key:
        atm2_nghbr_keys = neighbor_dct[rct1_atm2_key]
        for key in atm2_nghbr_keys:
            if key != rct1_atm1_key:
                rct1_atm3_key = key
                break

    # check if rct1_atm1, rct1_atm2, rct1_atm3 are colinear
    # if they are choose a dummy atom
    rct1_geo = automol.zmatrix.geometry(rct1_zma)
    if rct1_atm3_key:
        rct1_sub_geo = (rct1_geo[rct1_atm1_key], rct1_geo[rct1_atm2_key],
                        rct1_geo[rct1_atm3_key])
    else:
        rct1_sub_geo = (rct1_geo[rct1_atm1_key], rct1_geo[rct1_atm2_key])
    if automol.geom.is_linear(rct1_sub_geo) or not rct1_atm3_key:
        # have to regenerate atm2_nghbr_keys to include dummy atom keys!
        rct1_key_mat = automol.zmatrix.key_matrix(rct1_zma)
        rct1_keys = [row[0] for row in rct1_key_mat]
        if rct1_keys[rct1_atm2_key] is not None:
            atm2_nghbr_keys = [rct1_keys[rct1_atm2_key]]
        else:
            atm2_nghbr_keys = []
        for idx, rct1_key in enumerate(rct1_keys):
            if rct1_key == rct1_atm2_key:
                atm2_nghbr_keys.append(idx)
        new_atm3 = False
        for atm_key in atm2_nghbr_keys:
            if atm_key not in (rct1_atm3_key, rct1_atm1_key):
                rct1_atm3_key = atm_key
                new_atm3 = True
                break
        if not new_atm3:
            # if there are no dummy atoms connected to the rct1_atm2 then
            # search for dummy atom keys connected to rct1_atm1
            # now regenerate atm1_nghbr_keys to include dummy atom keys!
            if rct1_keys[rct1_atm1_key] is not None:
                atm1_nghbr_keys = [rct1_keys[rct1_atm1_key]]
            else:
                atm1_nghbr_keys = []
            for idx, rct1_key in enumerate(rct1_keys):
                if rct1_key == rct1_atm1_key:
                    atm1_nghbr_keys.append(idx)
            new_atm3 = False
            for atm_key in atm1_nghbr_keys:
                if atm_key not in (rct1_atm3_key, rct1_atm2_key):
                    rct1_atm3_key = atm_key
                    new_atm3 = True
                    break

    join_val_dct = {
        dist_name: dist_val,
        'aabs1': 85. * qcc.conversion_factor('degree', 'radian'),
        'aabs2': 85. * qcc.conversion_factor('degree', 'radian'),
        'babs1': 85. * qcc.conversion_factor('degree', 'radian'),
        'babs2': 85. * qcc.conversion_factor('degree', 'radian'),
        'babs3': 85. * qcc.conversion_factor('degree', 'radian'),
    }

    rct1_natom = automol.zmatrix.count(rct1_zma)
    rct2_natom = automol.zmatrix.count(rct2_zma)

    if rct1_natom == 1 and rct2_natom == 1:
        raise NotImplementedError
    if rct1_natom == 2 and rct2_natom == 1:
        join_keys = numpy.array([[rct1_atm1_key, rct1_atm2_key, None]])
        join_names = numpy.array([[dist_name, 'aabs1', None]])
    elif rct1_natom == 2 and rct2_natom == 2:
        join_keys = numpy.array([[rct1_atm1_key, rct1_atm2_key, rct1_atm3_key],
                                 [None, rct1_atm1_key, rct1_atm2_key]])
        join_names = numpy.array([[dist_name, 'aabs1', None],
                                  [None, 'aabs2', 'babs2']])
    else:
        join_keys = numpy.array([[rct1_atm1_key, rct1_atm2_key, rct1_atm3_key],
                                 [None, rct1_atm1_key, rct1_atm2_key],
                                 [None, None, rct1_atm1_key]])[:rct2_natms]
        join_names = numpy.array([[dist_name, 'aabs1', 'babs1'],
                                  [None, 'aabs2', 'babs2'],
                                  [None, None, 'babs3']])[:rct2_natms]

    join_name_set = set(numpy.ravel(join_names)) - {None}
    join_val_dct = {name: join_val_dct[name] for name in join_name_set}

    ts_zma = automol.zmatrix.join(rct1_zma, rct2_zma, join_keys, join_names,
                                  join_val_dct)

    ts_name_dct = automol.zmatrix.standard_names(ts_zma)
    dist_name = ts_name_dct[dist_name]
    ts_zma = automol.zmatrix.standard_form(ts_zma)

    # bimol_tors_names = constbuild.bimol()
    frm_bnd_keys = shift_vals_from_dummy(frm_bnd_keyss, ts_zma)

    # Build return
    ret = {
        'ts_zma': ts_zma,
        'bnd_keys': (frm_bnd_keys, frozenset({})),
        'const_keys': (frozenset({}), frozenset({}), frozenset({}))
    }

    return ret
Beispiel #8
0
def hydrogen_migration(rct_zmas_lst, prd_zmas_lst, tras):
    """ z-matrix for a hydrogen migration reaction

        tras in the ZMATRIX coordinate system
    """

    # Find the zma and traj pair that has min dist among rxn coord
    init_zma, min_tra = min_dist(rct_zmas_lst, tras)
    _ = prd_zmas_lst  # unneeded for TS build
    frm_bnd_keys, = automol.graph.trans.formed_bond_keys(min_tra)
    brk_bnd_keys, = automol.graph.trans.broken_bond_keys(min_tra)

    # Build a properly ordered zma
    count = 0
    while True:

        # figure out which idx in frm_bnd_keys corresponds to the hydrogen
        symbols = automol.vmatrix.symbols(automol.zmatrix.var_(init_zma))
        dist_coo_key = tuple(reversed(sorted(frm_bnd_keys)))
        for idx in dist_coo_key:
            if symbols[idx] == 'H':
                h_idx = idx
            else:
                a1_idx = idx

        brk_dist_coo_key = tuple(reversed(sorted(brk_bnd_keys)))
        for idx in brk_dist_coo_key:
            if symbols[idx] != 'H':
                a2_idx = idx

        # determine if the zmatrix needs to be rebuilt by x2z
        # determines if the hydrogen atom is used to define other atoms
        init_keys = automol.zmatrix.key_matrix(init_zma)
        rebuild = False
        for i, _ in enumerate(init_keys):
            if i > h_idx and any(idx == h_idx for idx in init_keys[i]):
                rebuild = True
                break

        # rebuild zmat and go through while loop again if needed
        # shifts order of cartesian coords and rerun x2z to get a new zmat
        # else go to next stage
        if rebuild:
            re_zma, frm_bnd_keys, brk_bnd_keys = reorder_zmatrix_for_redef(
                init_zma, a1_idx, h_idx, frm_bnd_keys, brk_bnd_keys)
            rct_zma = [re_zma]
            count += 1
            if count == 6:
                break
        else:
            rct_zma = init_zma
            break

    if not rct_zma:
        return None

    # Determine the backbone atoms to redefine the z-matrix entry
    _, gras = shifted_standard_zmas_graphs([rct_zma], remove_stereo=True)
    gra = functools.reduce(automol.graph.union, gras)
    xgr1, = automol.graph.connected_components(gra)
    chains_dct = automol.graph.atom_longest_chains(xgr1)

    idx_found = True
    a3_idx = chains_dct[a2_idx][1]
    if a3_idx in (h_idx, a1_idx):
        idx_found = False
        a2_neighbors = _atom_neighbor_keys(xgr1)[a2_idx]
        for idx in a2_neighbors:
            if idx not in (h_idx, a1_idx):
                a3_idx = idx
                idx_found = True

    if not idx_found:
        a3_idx = chains_dct[a1_idx][1]
        if a3_idx in (h_idx, a2_idx):
            a1_neighbors = _atom_neighbor_keys(xgr1)[a1_idx]
            for idx in a1_neighbors:
                if idx not in (h_idx, a2_idx):
                    a3_idx = idx

    # Set the values of the coordinates of the migrating H atom
    rct_geo = automol.zmatrix.geometry(rct_zma)
    distance = automol.geom.distance(rct_geo, h_idx, a1_idx)
    angle = automol.geom.central_angle(rct_geo, h_idx, a1_idx, a2_idx)
    dihedral = automol.geom.dihedral_angle(rct_geo, h_idx, a1_idx, a2_idx,
                                           a3_idx)

    dihed_is_180 = numpy.isclose(abs(dihedral), (numpy.pi),
                                 rtol=(5.0 * numpy.pi / 180.))
    dihed_is_0 = numpy.isclose(dihedral, (0.0), rtol=(5.0 * numpy.pi / 180.))
    dihed_is_360 = numpy.isclose(abs(dihedral), (2 * numpy.pi),
                                 rtol=(5.0 * numpy.pi / 180.))

    if dihed_is_180 or dihed_is_0 or dihed_is_360:
        dihedral -= (15.0 * numpy.pi / 180.)

    # Reset the keys for the migrating H atom
    new_idxs = (a1_idx, a2_idx, a3_idx)
    key_dct = {h_idx: new_idxs}
    ts_zma = automol.zmatrix.set_keys(rct_zma, key_dct)
    h_names = automol.zmatrix.name_matrix(ts_zma)[h_idx]
    ts_zma = automol.zmatrix.set_values(ts_zma, {
        h_names[0]: distance,
        h_names[1]: angle,
        h_names[2]: dihedral
    })

    # standardize the ts zmat and get tors and dist coords
    coo_dct = automol.zmatrix.coordinates(ts_zma)
    for coo_name, coo_key in coo_dct.items():
        dist_coo_key_rev = dist_coo_key[::-1]
        if coo_key[0] in (dist_coo_key, dist_coo_key_rev):
            dist_name = coo_name
            break

    # if migrating H atom is not the final zmat entry, shift it to the end (if
    # needed)
    if h_idx != automol.zmatrix.count(ts_zma) - 1:
        ts_zma, h_idx, frm_bnd_keys, brk_bnd_keys = shift_row_to_end(
            ts_zma, h_idx, frm_bnd_keys, brk_bnd_keys)

    ts_name_dct = automol.zmatrix.standard_names(ts_zma)
    dist_name = ts_name_dct[dist_name]
    ts_zma = automol.zmatrix.standard_form(ts_zma)

    # Build the torsional coordinates
    const_bnd_keys, _, _ = constbuild.hydrogen_migration(
        ts_zma, rct_zma, h_idx, frm_bnd_keys, brk_bnd_keys)
    # tors_bnd_keys = [coord_idxs(ts_zma, name) for name in tors_names]

    # Build the bond coordinates
    frm_bnd_keys = shift_vals_from_dummy(frm_bnd_keys, ts_zma)
    brk_bnd_keys = shift_vals_from_dummy(brk_bnd_keys, ts_zma)
    const_bnd_keys = shift_vals_from_dummy(const_bnd_keys, ts_zma)

    # Set the return
    ret = {
        'ts_zma': ts_zma,
        'bnd_keys': (frm_bnd_keys, brk_bnd_keys),
        'const_keys': (const_bnd_keys, frozenset({}), frozenset({}))
    }

    return ret
Beispiel #9
0
def concerted_unimol_elimination(rct_zmas, prd_zmas, tras):
    """ z-matrix for a concerted unimolecular elimination reaction
    """

    # Find the zma and traj pair that has min dist among rxn coord
    _ = prd_zmas  # Unneeded
    rct_zma, min_tra = min_dist(rct_zmas, tras)
    frm_bnd_keys, = automol.graph.trans.formed_bond_keys(min_tra)
    brk_bnd_keys = automol.graph.trans.broken_bond_keys(min_tra)
    brk_bnd_key1, brk_bnd_key2 = brk_bnd_keys

    count = 1
    while True:

        init_zma = rct_zma
        print('init_zma\n', automol.zmatrix.string(init_zma))
        # print('init_geo\n', automol.geom.string(automol.zmatrix.geometry(init_zma)))

        # Get index for migrating atom (or bond-form atom in group)
        brk_bnd_key1, brk_bnd_key2 = brk_bnd_keys
        for bnd_key in (brk_bnd_key1, brk_bnd_key2):
            if bnd_key & frm_bnd_keys:
                mig_key = next(iter(bnd_key & frm_bnd_keys))
        for key in frm_bnd_keys:
            if key != mig_key:
                a1_idx = key

        # Get chain for redefining the rc1_atm1_key z-matrix entries
        _, gras = shifted_standard_zmas_graphs([init_zma], remove_stereo=True)
        gra = functools.reduce(automol.graph.union, gras)
        xgr1, = automol.graph.connected_components(gra)
        atm1_neighbors = _atom_neighbor_keys(xgr1)[a1_idx]
        for idx in atm1_neighbors:
            num_keys = len(_atom_neighbor_keys(xgr1)[idx])
            if idx != mig_key and num_keys > 1:
                a2_idx = idx
        atm2_neighbors = _atom_neighbor_keys(xgr1)[a2_idx]
        for idx in atm2_neighbors:
            if idx not in (mig_key, a1_idx):
                a3_idx = idx

        mig_redef_keys = (a1_idx, a2_idx, a3_idx)
        print('mig key', mig_key)
        print('mig redef keys', mig_redef_keys)
        print('frm keys', frm_bnd_keys)
        print('brk keys', brk_bnd_keys)
        # determine if the zmatrix needs to be rebuilt by x2z
        # determines if the hydrogen atom is used to define other atoms
        rebuild = False
        if any(idx > mig_key for idx in mig_redef_keys):
            rebuild = True

        # rebuild zmat and go through while loop again if needed
        # shift order of cartesian coords & rerun x2z to get a new zmat
        # else go to next stage
        if rebuild:
            # multiple bond keys need to be passed
            reord_zma, frm_bnd_keys, brk_bnd_keys = reorder_zmatrix_for_redef(
                init_zma, a1_idx, mig_key, frm_bnd_keys, brk_bnd_keys)
            rct_zma = reord_zma
            count += 1
            if count == 3:
                finish_build = False
                break
            print('rebuild')
        else:
            rct_zma = init_zma
            finish_build = True
            print('no rebuild')
            break

    # If z-mat with good order not found, exit function
    if not finish_build:
        return None

    # determine the new coordinates
    rct_geo = automol.zmatrix.geometry(rct_zma)
    distance = automol.geom.distance(rct_geo, mig_key, a1_idx)
    angle = automol.geom.central_angle(rct_geo, mig_key, a1_idx, a2_idx)
    dihedral = automol.geom.dihedral_angle(rct_geo, mig_key, a1_idx, a2_idx,
                                           a3_idx)

    # Reset the keys for the migrating H atom
    new_idxs = (a1_idx, a2_idx, a3_idx)
    key_dct = {mig_key: new_idxs}
    ts_zma = automol.zmatrix.set_keys(rct_zma, key_dct)

    # Reset the values in the value dict
    mig_names = automol.zmatrix.name_matrix(ts_zma)[mig_key]
    ts_zma = automol.zmatrix.set_values(ts_zma, {
        mig_names[0]: distance,
        mig_names[1]: angle,
        mig_names[2]: dihedral
    })

    # standardize the ts zmat and get tors and dist coords
    coo_dct = automol.zmatrix.coordinates(ts_zma)
    dist_coo_key = tuple(reversed(sorted(frm_bnd_keys)))
    dist_name = next(coo_name for coo_name, coo_keys in coo_dct.items()
                     if dist_coo_key in coo_keys)
    ts_name_dct = automol.zmatrix.standard_names(ts_zma)
    dist_name = ts_name_dct[dist_name]
    ts_zma = automol.zmatrix.standard_form(ts_zma)

    brk_bnd_keys = frozenset({
        shift_vals_from_dummy(brk_bnd_key1, ts_zma),
        shift_vals_from_dummy(brk_bnd_key2, ts_zma)
    })
    frm_bnd_keys = shift_vals_from_dummy(frm_bnd_keys, ts_zma)

    # Set the return
    ret = {
        'ts_zma': ts_zma,
        'bnd_keys': (frm_bnd_keys, brk_bnd_keys),
        'const_keys': (frozenset({}), frozenset({}), frozenset({}))
    }

    return ret