Exemple #1
0
 def testNewRingDihedrals(self):
     """
     Test the calculation of new dihedrals necessary for the update
     """
     smi = 'CCCC'
     mol = StationaryPoint(smi, 0, 1, smiles=smi)
     mol.characterize()
     ins = [0, 1, 2, 3]  # change the C-C-C-C dihedral
     step_nr = 0  # This corresponds to the first dihedral update
     # there are 12 steps done in total, this means that the dihedral
     # angle should be changed by 1/10 of the total change
     total_nr_of_steps = 10
     # final dihedral value we are shooting for after 10 updates
     # this is a default value for a instance of 5 or less atoms
     final_val = 15.
     # initial dihedral
     ini = geometry.calc_dihedral(mol.geom[ins[0]],
                                  mol.geom[ins[1]],
                                  mol.geom[ins[2]],
                                  mol.geom[ins[3]])[0]
     # this is the new dihedral angle after one step
     update = geometry.new_ring_dihedrals(mol, ins, step_nr,
                                          total_nr_of_steps)
     exp = ini - (ini - final_val) / 10
     cal = update[0]
     warn = 'Dihedral update is not correct: '
     warn += 'expected {}, calculated {}'.format(exp, cal)
     self.assertEqual(exp, cal, msg=warn)
Exemple #2
0
    def find_dihedral(self): 
        """ 
        Identify unique rotatable bonds in the structure 
        No rotation around ring bonds and double and triple bonds.
        """
        self.calc_chemid()
        if not hasattr(self,'cycle_chain'):
            self.find_cycle()
        if len(self.bonds) == 0:
            self.bonds = [self.bond]
        
        self.dihed = []
        hit = 0

        if self.natom < 4: return 0

        # a-b-c-d, rotation around b-c
        for b in range(self.natom):
            if hit == 1: hit = 0
            for c in range(b, self.natom):
                if hit == 1: hit = 0
                if all([bi[b][c]==1 for bi in self.bonds]) and self.cycle[b] * self.cycle[c] == 0:
                    for a in range(self.natom):
                        if hit == 1: break
                        if self.bond[a][b] == 1 and a != c:
                            for d in range(self.natom):
                                if hit == 1: break
                                if self.bond[c][d] == 1 and d != b:
                                    dihedral_angle, warning = geometry.calc_dihedral(self.geom[a], self.geom[b], self.geom[c], self.geom[d])
                                    if warning == 0:
                                        self.dihed.append([a, b, c, d])
                                        hit = 1 

        return 0
Exemple #3
0
 def __init__(self, species, qc, par, instance, instance_name):  # special
     GeneralReac.__init__(self, species, qc, par, instance, instance_name)
     self.cistrans = self.instance[-1]  # (nominal) cis -1, trans -2
     self.double = self.instance[0]  # the dangling atom with double bond
     self.instance = self.instance[1:-1]  # cut off both
     self.dih0, _ = calc_dihedral(
         self.species.geom[self.double],  # the original dihedral
         self.species.geom[self.instance[0]],
         self.species.geom[self.instance[1]],
         self.species.geom[self.instance[2]])
Exemple #4
0
def add(j,list,zmat,zmat_atom,zmatorder,zmat_ref,atom,cart):
    """
    add an atom on the jth position of the zmat according to the four atoms in the list
    """
    zmat_atom[j] = atom[list[0]]
    zmatorder[j] = list[0]
    zmat_ref[j][0] = zmatorder.index(list[1])+1
    zmat[j][0] = np.linalg.norm(cart[list[0]] - cart[list[1]])
    zmat_ref[j][1] = zmatorder.index(list[2])+1
    zmat[j][1] = np.degrees(geometry.calc_angle(cart[list[0]], cart[list[1]], cart[list[2]]))
    zmat_ref[j][2] = zmatorder.index(list[3])+1
    zmat[j][2], collin = geometry.calc_dihedral(cart[list[0]], cart[list[1]], cart[list[2]], cart[list[3]])
Exemple #5
0
def add(j, list, zmat, zmat_atom, zmatorder, zmat_ref, atom, cart):
    """
    add an atom on the jth position of the zmat according to the four atoms in the list
    """
    zmat_atom[j] = atom[list[0]]
    zmatorder[j] = list[0]
    zmat_ref[j][0] = zmatorder.index(list[1]) + 1
    zmat[j][0] = np.linalg.norm(cart[list[0]] - cart[list[1]])
    zmat_ref[j][1] = zmatorder.index(list[2]) + 1
    zmat[j][1] = np.degrees(geometry.calc_angle(cart[list[0]], cart[list[1]], cart[list[2]]))
    zmat_ref[j][2] = zmatorder.index(list[3]) + 1
    zmat[j][2], collin = geometry.calc_dihedral(cart[list[0]], cart[list[1]], cart[list[2]], cart[list[3]])
Exemple #6
0
    def generate_ring_conformers(self, cart):
        """
        Generate the conformers of a cyclic structure
        by randomly sampling the dihedrals of the ring
        """

        # iterate the different rings in the species
        for cyc in self.species.cycle_chain:
            if len(cyc) > 3:  # three membered rings don't have conformers
                dihs = []  # list of the ring dihedrals
                for i, at in enumerate(cyc):
                    dihs.append([cyc[i - 3], cyc[i - 2], cyc[i - 1], cyc[i]])

                # define the flatness of the ring by the sum of the
                # absolute values of the dihedrals along the ring
                # divided by the number of atoms in the ring
                cycdih = 0.
                for dih in dihs:
                    val = geometry.calc_dihedral(cart[dih[0]], cart[dih[1]],
                                                 cart[dih[2]], cart[dih[3]])[0]
                    cycdih += np.abs(val)
                cycdih /= float(len(cyc))

                # randomly select N-3 dihedrals,
                # with N the number of dihedrals in the ring
                random_dihs = random.sample(dihs, len(dihs) - 3)
                # number of independent dihedrals
                nd = len(dihs) - 3
                # number of conformers for this ring:
                nc = np.power(3, nd)
                for i in range(nc):
                    self.cyc_dih_atoms.append(random_dihs)
                    # values the dihedrals will be modified to
                    values = []
                    for j in range(nd):
                        values.append(cycdih *
                                      (np.mod(i // np.power(3, j), 3) - 1))
                    self.cyc_dih_values.append(values)
                    self.cyc_conf_index.append(-1)
                    self.cyc_conf += 1
            else:
                self.cyc_conf_geoms.append(copy.deepcopy(cart))

        for ci in range(self.cyc_conf):
            self.start_ring_conformer_search(ci,
                                             copy.deepcopy(self.species.geom))
Exemple #7
0
    def generate_ring_conformers(self, cart):
        """
        Generate the conformers of a cyclic structure
        by randomly sampling the dihedrals of the ring
        """

        # iterate the different rings in the species
        for cyc in self.species.cycle_chain:
            if len(cyc) > 3:  # three membered rings don't have conformers
                dihs = []  # list of the ring dihedrals
                for i, at in enumerate(cyc):
                    dihs.append([cyc[i-3], cyc[i-2], cyc[i-1], cyc[i]])

                # define the flatness of the ring by the sum of the
                # absolute values of the dihedrals along the ring
                # divided by the number of atoms in the ring
                cycdih = 0.
                for dih in dihs:
                    val = geometry.calc_dihedral(cart[dih[0]], cart[dih[1]],
                                                 cart[dih[2]], cart[dih[3]])[0]
                    cycdih += np.abs(val)
                cycdih /= float(len(cyc))

                # randomly select N-3 dihedrals,
                # with N the number of dihedrals in the ring
                random_dihs = random.sample(dihs, len(dihs) - 3)
                # number of independent dihedrals
                nd = len(dihs) - 3
                # number of conformers for this ring:
                nc = np.power(3, nd)
                for i in range(nc):
                    self.cyc_dih_atoms.append(random_dihs)
                    # values the dihedrals will be modified to
                    values = []
                    for j in range(nd):
                        values.append(cycdih*(np.mod(i // np.power(3, j), 3) - 1))
                    self.cyc_dih_values.append(values)
                    self.cyc_conf_index.append(-1)
                    self.cyc_conf += 1
            else:
                self.cyc_conf_geoms.append(copy.deepcopy(cart))

        for ci in range(self.cyc_conf):
            self.start_ring_conformer_search(ci, copy.deepcopy(self.species.geom))
Exemple #8
0
 def testCalcDihedral(self):
     """
     Test the dihedral angle calculation
     """
     np.random.seed(1)
     a = np.random.uniform(size=3)
     b = np.random.uniform(size=3)
     c = np.random.uniform(size=3)
     d = np.random.uniform(size=3)
     cal, collinear = geometry.calc_dihedral(a, b, c, d)
     # verify the angle
     exp = -83.9898211154
     warn = 'Dihedral angle not correct: '
     warn += 'expected {}, calculated {}'.format(exp, cal)
     self.assertAlmostEqual(exp, cal, places=10, msg=warn)
     # verify the collinear boolean
     exp = 0
     cal = collinear
     warn = 'Dihedral collinear boolean is not correct: '
     warn += 'expected {}, calculated {}'.format(exp, cal)
     self.assertEqual(exp, cal, msg=warn)
Exemple #9
0
    def generate_ring_conformers(self, cart):
        """
        Generate the conformers of a cyclic structure
        by randomly sampling the dihedrals of the ring
        """
        # iterate the different rings in the species
        for cyc in self.species.cycle_chain:
            if len(cyc) > 3:  # three membered rings don't have conformers
                dihs = []  # list of the ring dihedrals
                for i, at in enumerate(cyc):
                    dihs.append([cyc[i - 3], cyc[i - 2], cyc[i - 1], cyc[i]])

                # define the flatness of the ring by the sum of the
                # absolute values of the dihedrals along the ring
                # divided by the number of atoms in the ring
                cycdih = 0.
                # list of flat sections of the ring
                flat_ring_dih = []
                for dih in dihs:
                    val = geometry.calc_dihedral(cart[dih[0]], cart[dih[1]],
                                                 cart[dih[2]], cart[dih[3]])[0]
                    if abs(val) < 5.:
                        flat_ring_dih.append(True)
                    else:
                        flat_ring_dih.append(False)
                        cycdih += np.abs(val)
                # only care about flatness for non-flat parts
                n_dih_nonflat = len(cyc) - np.sum(flat_ring_dih)
                if n_dih_nonflat > 0:
                    cycdih /= float(n_dih_nonflat)
                else:  # for instance benzene
                    self.cyc_conf_geoms.append(copy.deepcopy(cart))
                    continue

                # randomly select at most N-3 dihedrals,
                # with N the number of non-flat dihedrals in the ring
                # number of independent dihedrals
                if n_dih_nonflat < 4:
                    nd = 1
                else:
                    nd = n_dih_nonflat - 3
                random_dihs = list(
                    random.sample(
                        list(np.array(dihs)[[not f for f in flat_ring_dih]]),
                        nd))

                # number of conformers (nc) per ring conformer:
                # 4, 5, 6 member rings nc = 3 ^ nd
                # 7+ member rings = nc from (ring size - 1) + (2 ^ nd)
                # ex: 7 member ring = 6 member ring nc + 2 ^ 4 = 27 + 16 = 43
                if len(cyc) < 7:
                    nc = np.power(3, nd)
                else:
                    nc = 27  # 3 ^ (6-3)
                    exp = 4
                    while exp <= nd:
                        conf_add = np.power(2, exp)
                        nc = nc + conf_add
                        exp = exp + 1

                for i in range(nc):
                    self.cyc_dih_atoms.append(random_dihs)
                    # values the dihedrals will be modified to
                    values = []
                    for j in range(nd):
                        values.append(cycdih *
                                      (np.mod(i // np.power(3, j), 3) - 1))
                    self.cyc_dih_values.append(values)
                    self.cyc_conf_index.append(-1)
                    self.cyc_conf += 1
            else:
                self.cyc_conf_geoms.append(copy.deepcopy(cart))

        for ci in range(self.cyc_conf):
            self.start_ring_conformer_search(ci,
                                             copy.deepcopy(self.species.geom))
Exemple #10
0
    def get_constraints(self, step, geom):
        fix = []
        change = []
        release = []
        if step < self.max_step:
            self.fix_bonds(fix)

        if step < self.dihstep:
            self.set_dihedrals(change, step, cut=1)

            ldih = [
            ]  # constraint for the last dihedral, which needs to be 180 degrees
            for i in range(4):
                ldih.append(self.instance[len(self.instance) - 4 + i] + 1)
            dih = geometry.calc_dihedral(geom[ldih[0] - 1], geom[ldih[1] - 1],
                                         geom[ldih[2] - 1],
                                         geom[ldih[3] - 1])[0]
            frac = 1. / (12. - step)
            if dih < 0:
                new_dih = dih - frac * (180. + dih)
                ldih.append(new_dih)
            else:
                new_dih = dih + frac * (180. - dih)
                ldih.append(new_dih)
            change.append(ldih)

        elif step < self.max_step:
            self.release_dihedrals(release)

            fdist1 = constants.st_bond[''.join(
                sorted(self.species.atom[self.instance[0]] +
                       self.species.atom[self.instance[-2]]))] * 1.0
            if ''.join(
                    sorted(self.species.atom[self.instance[0]] +
                           self.species.atom[self.instance[-2]])) == 'CO':
                fdist1 = 1.68
            self.set_bond(0,
                          -2,
                          -999,
                          change,
                          step=step - 11,
                          stmax=10,
                          findist=fdist1,
                          geom=geom)

            fdist2 = constants.st_bond[''.join(
                sorted(self.species.atom[self.instance[-1]] +
                       self.species.atom[self.instance[-2]]))] * 1.0
            if ''.join(
                    sorted(self.species.atom[self.instance[-1]] +
                           self.species.atom[self.instance[-2]])) == 'CO':
                fdist2 = 1.68
            self.set_bond(-1,
                          -2,
                          -999,
                          change,
                          step=step - 11,
                          stmax=10,
                          findist=fdist2,
                          geom=geom)

        self.clean_constraints(change, fix)

        return step, fix, change, release
    def get_constraints(self,step, geom):
        """
        There are three types of constraints:
        1. fix a coordinate to the current value
        2. change a coordinate and fix is to the new value
        3. release a coordinate (only for gaussian)
        """
        fix = []
        change = []
        release = []
        if step < self.max_step:
            #fix all the bond lengths
            for i in range(self.species.natom - 1):
                for j in range(i+1, self.species.natom):
                    if self.species.bond[i][j] > 0:
                        fix.append([i+1,j+1])
        if step < 12:
            new_dihs = geometry.new_ring_dihedrals(self.species, self.instance, step, 12,geom)
            for dih in range(len(self.instance)-4): # do not include last atom
                constraint = []
                for i in range(4):
                    constraint.append(self.instance[dih+i] + 1)
                constraint.append(new_dihs[dih])
                change.append(constraint)
            ldih = [] # constraint for the last dihedral, which needs to be 180 degrees    
            for i in range(4):
                ldih.append(self.instance[len(self.instance)-4+i] + 1)
            dih = geometry.calc_dihedral(geom[ldih[0] - 1], geom[ldih[1] - 1], geom[ldih[2] - 1], geom[ldih[3] - 1])[0]
            frac = 1./(12. - step)
            if dih < 0:
                new_dih = dih - frac * (180. + dih) 
                ldih.append(new_dih)
            else:
                new_dih = dih + frac * (180. - dih) 
                ldih.append(new_dih)
            change.append(ldih)
        elif step < 22:
            for dih in range(len(self.instance)-3):  
                constraint = []
                for i in range(4):
                    constraint.append(self.instance[dih+i] + 1)
                release.append(constraint)

            fdist1 = constants.st_bond[''.join(sorted(self.species.atom[self.instance[0]]+self.species.atom[self.instance[-2]]))]*1.0
            if ''.join(sorted(self.species.atom[self.instance[0]]+self.species.atom[self.instance[-2]])) == 'CO':
                fdist1 = 1.68
            ndist1 = geometry.new_bond_length(self.species,self.instance[0],self.instance[-2],step - 11 ,10,fdist1,geom)
            constraint = [self.instance[0] + 1,self.instance[-2] + 1,ndist1]
            change.append(constraint)
            
            fdist2 = constants.st_bond[''.join(sorted(self.species.atom[self.instance[-1]]+self.species.atom[self.instance[-2]]))]*1.0
            if ''.join(sorted(self.species.atom[self.instance[-1]]+self.species.atom[self.instance[-2]])) == 'CO':
                fdist2 = 1.68
            ndist2 = geometry.new_bond_length(self.species,self.instance[-1],self.instance[-2],step - 11 ,10,fdist2,geom)
            constraint = [self.instance[-1] + 1,self.instance[-2] + 1,ndist2]
            change.append(constraint)

        #remove the bonds from the fix if they are in another constaint
        for c in change:
            if len(c) == 3:
                index = -1
                for i,fi in enumerate(fix):
                    if len(fi) == 2:
                        if sorted(fi) == sorted(c[:2]):
                            index = i
                if index > -1:
                    del fix[index]
        
        return step, fix, change, release
Exemple #12
0
def make_zmat_from_cart_all_dihedrals(bond, cycle, dihed, conf_dihed, natom, atom, cart, mode):
    """
    Rearrange geometry defined in Cartesian into a Z-matrix,
    with references suitable for a 1-D hindered rotor scan.
    Include all rotors which are:
    If mode = 0: all rotatable bonds
    If mode = 1: only those bonds, which generate conformers,
    i.e. no methyl bonds, t-butyl bonds, etc
    
    bond: bond matrix of the species
    cycle: atom list of species with 0 if atom is not in cycle and 1 otherwise
    dihed: total list of dihedrals
    conf_dihed: list of dihedrals without the symmetrical ones
    natom: number of atoms
    atom: symbols of all the atoms
    cart: cartesian coordinates of the species
    """
    rotors = [] #rotors to consider
    
    if mode == 0:
        for rotor in dihed:
            rotors.append(rotor[:])
    if mode == 1:
        for rotor in conf_dihed:
            rotors.append(rotor[:])

    if len(rotors) > 0:
        #order in which the atoms will be added:
        # 1. First rotor
        # 2. Smallest path between first and second rotor (if any)
        # 3. Second rotor
        # 4. Smallest path between second and third rotor (if any)
        # ...
        # n. Last rotor
        # n+1. All atoms that are not part of a rotor, 
        #      starting by the neighbors of all rotor atoms

        #order the rotors as such that the path between subsequent rotors does not 
        #cross another rotor
        rotors, connecting_list, connected_rotor, path_length = order_rotors(rotors,bond,natom, atom)
        #Add first rotor: 
        zmat_atom = ['X' for i in range(natom)]
        zmat_ref = np.zeros((natom, 3), dtype=int) - 1
        zmat = np.zeros((natom, 3)) - 1
        zmatorder = [-1 for i in range(natom)]
        
        zmat_atom[0] = atom[rotors[0][0]]
        zmatorder[0] = rotors[0][0]

        zmat_atom[1] = atom[rotors[0][1]]
        zmatorder[1] = rotors[0][1]
        zmat_ref[1][0] = 1
        zmat[1][0] = np.linalg.norm(cart[rotors[0][1]] - cart[rotors[0][0]]) 

        zmat_atom[2] = atom[rotors[0][2]]
        zmatorder[2] = rotors[0][2]
        zmat_ref[2][0] = 2
        zmat[2][0] = np.linalg.norm(cart[rotors[0][2]] - cart[rotors[0][1]])
        zmat_ref[2][1] = 1
        zmat[2][1] = np.degrees(geometry.calc_angle(cart[rotors[0][2]], cart[rotors[0][1]], cart[rotors[0][0]]))

        zmat_atom[3] = atom[rotors[0][3]]
        zmatorder[3] = rotors[0][3]
        zmat_ref[3][0] = 3
        zmat[3][0] = np.linalg.norm(cart[rotors[0][3]] - cart[rotors[0][2]])
        zmat_ref[3][1] = 2
        zmat[3][1] = np.degrees(geometry.calc_angle(cart[rotors[0][3]], cart[rotors[0][2]], cart[rotors[0][1]]))
        zmat_ref[3][2] = 1
        zmat[3][2], collin = geometry.calc_dihedral(cart[rotors[0][3]], cart[rotors[0][2]], cart[rotors[0][1]], cart[rotors[0][0]])


        #Add subsequent rotors: 
        rot_index = 1
        j = 4
        
        while rot_index < len(rotors):
            
            rotor = rotors[rot_index]
            chain_length = path_length[rot_index - 1]
            chain = connecting_list[rot_index - 1]
            conn_rotor = connected_rotor[rot_index - 1]
            
            to_add = []
            added = []
            for at in rotor:
                if not at in zmatorder:
                    to_add.append(at)
                else:
                    added.append(at)
            
            if len(to_add) == 0:
                logging.error("error, all atoms of a rotor have been added, without adding this dihedral explicitly")
            elif len(to_add) == 1:
                at = to_add[0]
                if rotor.index(at) == 1 or rotor.index(at) == 2:
                    logging.error("error, all atoms except a middle atom have been added, strange...")
                elif rotor.index(at) == 0:
                    add(j,[at,rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                elif rotor.index(at) == 3:
                    add(j,[at,rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
            elif len(to_add) == 2:
                at1 = to_add[0]
                at2 = to_add[1]
                if sorted([rotor.index(at1),rotor.index(at2)]) == [0,1]:
                    neighbor_list = get_neighbors(rotor[2],bond,natom,rotors,zmatorder)
                    #add rotor[1]
                    add(j,[rotor[1],rotor[2],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                    #add rotor[0]
                    add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                elif sorted([rotor.index(at1),rotor.index(at2)]) == [2,3]:
                    neighbor_list = get_neighbors(rotor[1],bond,natom,rotors,zmatorder)
                    #add rotor[2]
                    add(j,[rotor[2],rotor[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                    #add rotor[3]
                    add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                elif sorted([rotor.index(at1),rotor.index(at2)]) == [0,3]:
                    r1,pos1 = middle_atom(rotors,rotor[1])
                    r2,pos2 = middle_atom(rotors,rotor[2])
                    if r1 and pos1[0] in zmatorder and pos1[1] in zmatorder:
                        #add rotor[0]
                        add(j,[rotor[0],rotor[1],pos1[0],pos1[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        #add rotor[3]
                        add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                    elif r2 and pos2[0] in zmatorder and pos2[1] in zmatorder:
                        #add rotor[3]
                        add(j,[rotor[3],rotor[2],pos2[0],pos2[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        #add rotor[0]
                        add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                    else:
                        if cycle[rotor[2]] == 1:
                            neighbor_list = get_neighbors(rotor[2],bond,natom,rotors,zmatorder)
                            #add rotor[3]
                            add(j,[rotor[3],rotor[2],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            #add rotor[0]
                            add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                        else:
                            neighbor_list = get_neighbors(rotor[1],bond,natom,rotors,zmatorder)
                            #add rotor[0]
                            add(j,[rotor[0],rotor[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            #add rotor[3]
                            add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                elif sorted([rotor.index(at1),rotor.index(at2)]) == [0,2]:
                    neighbor_list = get_neighbors(rotor[1],bond,natom,rotors,zmatorder)
                    #add rotor[2]
                    add(j,[rotor[2],rotor[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    #add rotor[0]
                    add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                elif sorted([rotor.index(at1),rotor.index(at2)]) == [1,3]:
                    neighbor_list = get_neighbors(rotor[0],bond,natom,rotors,zmatorder)
                    #add rotor[1]
                    add(j,[rotor[1],rotor[0],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    #add rotor[3]
                    add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                else:
                    logging.error("error, two atoms that need to be added are not the outer atoms of a rotor, strange...")
            elif len(to_add) == 3:
                if added[0] == rotor[0]:
                    neighbor_list = get_neighbors(rotor[0],bond,natom,rotors,zmatorder)
                    add(j,[rotor[1],rotor[0],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                    add(j,[rotor[2],rotor[1],rotor[0],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                    add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                elif added[0] == rotor[1]:
                    neighbor_list = get_neighbors(rotor[1],bond,natom,rotors,zmatorder)
                    if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                        add(j,[rotor[2],rotor[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[3],rotor[2],rotor[1],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                    else:
                        add(j,[rotor[0],rotor[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[2],rotor[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                elif added[0] == rotor[2]:
                    neighbor_list = get_neighbors(rotor[2],bond,natom,rotors,zmatorder)
                    if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                        add(j,[rotor[3],rotor[2],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[1],rotor[2],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                    else:
                        add(j,[rotor[1],rotor[2],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[0],rotor[1],rotor[2],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                elif added[0] == rotor[3]:
                    neighbor_list = get_neighbors(rotor[3],bond,natom,rotors,zmatorder)
                    add(j,[rotor[2],rotor[3],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                    add(j,[rotor[1],rotor[2],rotor[3],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                    add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
                else:
                    logging.error('error')
            else:
                if len(chain) == 2: #this is the minimum chain length
                    neighbor_list=get_neighbors(chain[1],bond,natom,rotors,zmatorder)
                    if chain[0] == rotor[0]:
                        add(j,[rotor[0],chain[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[1],rotor[0],chain[1],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[2],rotor[1],rotor[0],chain[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                    elif chain[0] == rotor[1]:
                        if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                            add(j,[rotor[1],chain[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[2],rotor[1],chain[1],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[3],rotor[2],rotor[1],chain[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                        else:
                            add(j,[rotor[1],chain[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[0],rotor[1],chain[1],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[2],rotor[1],chain[1],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                    elif chain[0] == rotor[2]:
                        if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                            add(j,[rotor[2],chain[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[1],rotor[2],chain[1],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[3],rotor[2],chain[1],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                        else:
                            add(j,[rotor[2],chain[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[1],rotor[2],chain[1],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[0],rotor[1],rotor[2],chain[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                    elif chain[0] == rotor[3]:
                        add(j,[rotor[3],chain[1],neighbor_list[0],neighbor_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[2],rotor[3],chain[1],neighbor_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[1],rotor[2],rotor[3],chain[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                elif len(chain) > 2:
                    neighbor_list=get_neighbors(chain[-1],bond,natom,rotors,zmatorder)
                    #add the chain of atoms between this rotor and the closest rotor that is already in the zmatrix
                    for i in range(1,len(chain)-1): #do not consider two outer atoms, which are part of a rotor
                        ref_list = []
                        if i == 1:
                            ref_list = [chain[-1],neighbor_list[0],neighbor_list[1]]
                        elif i == 2: 
                            ref_list = [chain[-2],chain[-1],neighbor_list[0]]
                        else:
                            ref_list = [chain[-i],chain[-(i-1)],chain[-(i-2)]]
                        add(j,[chain[-(i+1)],ref_list[0],ref_list[1],ref_list[2]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                    #add the rotor itself:
                    ref_list = []
                    
                    if len(chain) == 3: #only one atom connects the two rotors:
                        ref_list = [chain[1],chain[2],neighbor_list[0]]
                    else:
                        ref_list = [chain[1],chain[2],chain[3]]
                    
                    if chain[0] == rotor[0]:
                        add(j,[rotor[0],ref_list[0],ref_list[1],ref_list[2]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[1],rotor[0],ref_list[0],ref_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[2],rotor[1],rotor[0],ref_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                    elif chain[0] == rotor[1]:
                        if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                            add(j,[rotor[1],ref_list[0],ref_list[1],ref_list[2]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[2],rotor[1],ref_list[0],ref_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[3],rotor[2],rotor[1],ref_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                        else:
                            add(j,[rotor[1],ref_list[0],ref_list[1],ref_list[2]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[0],rotor[1],ref_list[0],ref_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[2],rotor[1],ref_list[0],ref_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                    elif chain[0] == rotor[2]:
                        if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                            add(j,[rotor[2],ref_list[0],ref_list[1],ref_list[2]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[1],rotor[2],ref_list[0],ref_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[3],rotor[2],ref_list[0],ref_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                        else:
                            add(j,[rotor[2],ref_list[0],ref_list[1],ref_list[2]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[1],rotor[2],ref_list[0],ref_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[0],rotor[1],rotor[2],ref_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                            add(j,[rotor[3],rotor[2],rotor[1],rotor[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                            j += 1
                    elif chain[0] == rotor[3]:
                        add(j,[rotor[3],ref_list[0],ref_list[1],ref_list[2]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[2],rotor[3],ref_list[0],ref_list[1]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[1],rotor[2],rotor[3],ref_list[0]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                        add(j,[rotor[0],rotor[1],rotor[2],rotor[3]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                        j += 1
                else:
                    logging.error('error, chain length too small')
            rot_index += 1
    else:
        # no rotors here, add the first four atoms of the molecule
        zmat_atom = ['X' for i in range(natom)]
        zmat_ref = np.zeros((natom, 3), dtype=int) - 1
        zmat = np.zeros((natom, 3)) - 1
        zmatorder = [-1 for i in range(natom)]
        
        if len(atom) == 1:
            zmat_atom[0] = atom[0]
            zmatorder[0] = 0
        elif len(atom) == 2:
            zmat_atom[0] = atom[0]
            zmatorder[0] = 0
            
            zmat_atom[1] = atom[1]
            zmatorder[1] = 1
            zmat_ref[1][0] = 1
            zmat[1][0] = np.linalg.norm(cart[1] - cart[0]) 
        else:
            # get three atoms that are bonded to one another
            motif = ['X','X','X']
            ins = start_motif(motif, natom, bond, atom, -1, [[k] for k in range(natom)])[0]
            
            zmat_atom[0] = atom[ins[0]]
            zmatorder[0] = ins[0]
            
            zmat_atom[1] = atom[ins[1]]
            zmatorder[1] = ins[1]
            zmat_ref[1][0] = 1
            zmat[1][0] = np.linalg.norm(cart[ins[1]] - cart[ins[0]]) 

            zmat_atom[2] = atom[ins[2]]
            zmatorder[2] = ins[2]
            zmat_ref[2][0] = 2
            zmat[2][0] = np.linalg.norm(cart[ins[2]] - cart[ins[1]])
            zmat_ref[2][1] = 1
            zmat[2][1] = np.degrees(geometry.calc_angle(cart[ins[2]], cart[ins[1]], cart[ins[0]]))
            
            j = 3

        
    #add all the remaining atoms
    while -1 in zmatorder:
        for i in range(natom):
            if not i in zmatorder:
                neighbor_list = get_three_neighbors(i,bond,natom,rotors,zmatorder)
                if len(neighbor_list) > 2:
                    add(j,[i,neighbor_list[0],neighbor_list[1],neighbor_list[2]],zmat,zmat_atom,zmatorder,zmat_ref,atom,cart)
                    j += 1
    
    return zmat_atom, zmat_ref, zmat, zmatorder
Exemple #13
0
def make_zmat_from_cart(species, rotor, cart, mode):
    """
    Rearrange geometry defined in Cartesian into a Z-matrix,
    with references suitable for a 1-D hindered rotor scan.
    If mode = 0: all rotatable bonds
    If mode = 1: only those bonds, which generate conformers
    If mode = 2: suply your one rotor in rotor as a list of atom indices
    """
    natom = species.natom
    atom = species.atom
    if mode == 0:
        a = species.dihed[rotor][0]
        b = species.dihed[rotor][1]
        c = species.dihed[rotor][2]
        d = species.dihed[rotor][3]
    elif mode == 1:
        a = species.conf_dihed[rotor][0]
        b = species.conf_dihed[rotor][1]
        c = species.conf_dihed[rotor][2]
        d = species.conf_dihed[rotor][3]
    elif mode == 2:
        a = rotor[0]
        b = rotor[1]
        c = rotor[2]
        d = rotor[3]

    groupA = np.zeros(natom, dtype=int)
    groupB = np.zeros(natom, dtype=int)
    groupC = np.zeros(natom, dtype=int)
    groupD = np.zeros(natom, dtype=int)

    groupA[a] = 1
    groupB[b] = 1
    groupC[c] = 1
    groupD[d] = 1

    # get all immediate neighbors of a A, B, C, and D
    for i in range(natom):
        if species.bond[a][i] > 0 and i != b:
            groupA[i] = 1
        elif species.bond[b][i] > 0 and i != a and i != c:
            groupB[i] = 1
        elif species.bond[c][i] > 0 and i != b and i != d:
            groupC[i] = 1
        elif species.bond[d][i] > 0 and i != c:
            groupD[i] = 1

    found = 1
    while found > 0:
        found = 0
        for i in range(natom):
            if groupA[i] == 1:
                for j in range(natom):
                    if species.bond[i][j] > 0 and j != b and groupA[j] != 1:
                        groupA[j] = 1
                        found = 1
            elif groupB[i] == 1:
                for j in range(natom):
                    if species.bond[i][j] > 0 and j != a and j != c and groupB[j] != 1:
                        groupB[j] = 1
                        found = 1
            elif groupC[i] == 1:
                for j in range(natom):
                    if species.bond[i][j] > 0 and j != b and j != d and groupC[j] != 1:
                        groupC[j] = 1
                        found = 1
            elif groupD[i] == 1:
                for j in range(natom):
                    if species.bond[i][j] > 0 and j != c and groupD[j] != 1:
                        groupD[j] = 1
                        found = 1

    zmat_atom = ['X' for i in range(natom)]
    zmat_ref = np.zeros((natom, 3), dtype=int) - 1
    zmat = np.zeros((natom, 3)) - 1

    # FIXME need to take care about TS structures maybe
    zmatorder = [-1 for i in range(natom)]

    zmat_atom[0] = atom[a]
    zmatorder[0] = a

    zmat_atom[1] = atom[b]
    zmatorder[1] = b
    zmat_ref[1][0] = 1
    zmat[1][0] = np.linalg.norm(cart[b] - cart[a])

    zmat_atom[2] = atom[c]
    zmatorder[2] = c
    zmat_ref[2][0] = 2
    zmat[2][0] = np.linalg.norm(cart[c] - cart[b])
    zmat_ref[2][1] = 1
    zmat[2][1] = np.degrees(geometry.calc_angle(cart[c], cart[b], cart[a]))

    zmat_atom[3] = atom[d]
    zmatorder[3] = d
    zmat_ref[3][0] = 3
    zmat[3][0] = np.linalg.norm(cart[d] - cart[c])
    zmat_ref[3][1] = 2
    zmat[3][1] = np.degrees(geometry.calc_angle(cart[d], cart[c], cart[b]))
    zmat_ref[3][2] = 1
    zmat[3][2], collin = geometry.calc_dihedral(cart[d], cart[c], cart[b], cart[a])

    j = 4
    for i in range(natom):
        if i == a or i == b or i == c or i == d:
            continue
        zmat_atom[j] = atom[i]
        zmatorder[j] = i
        if groupA[i] == 1:
            zmat_ref[j][0] = 1
            zmat[j][0] = np.linalg.norm(cart[i] - cart[a])
            zmat_ref[j][1] = 2
            zmat[j][1] = np.degrees(geometry.calc_angle(cart[i], cart[a], cart[b]))
            zmat_ref[j][2] = 3
            zmat[j][2], collin = geometry.calc_dihedral(cart[i], cart[a], cart[b], cart[c])
        elif groupB[i] == 1:
            zmat_ref[j][0] = 2
            zmat[j][0] = np.linalg.norm(cart[i] - cart[b])
            zmat_ref[j][1] = 3
            zmat[j][1] = np.degrees(geometry.calc_angle(cart[i], cart[b], cart[c]))
            zmat_ref[j][2] = 4
            zmat[j][2], collin = geometry.calc_dihedral(cart[i], cart[b], cart[c], cart[d])
        elif groupC[i] == 1:
            zmat_ref[j][0] = 3
            zmat[j][0] = np.linalg.norm(cart[i] - cart[c])
            zmat_ref[j][1] = 2
            zmat[j][1] = np.degrees(geometry.calc_angle(cart[i], cart[c], cart[b]))
            zmat_ref[j][2] = 1
            zmat[j][2], collin = geometry.calc_dihedral(cart[i], cart[c], cart[b], cart[a])
        elif groupD[i] == 1:
            zmat_ref[j][0] = 4
            zmat[j][0] = np.linalg.norm(cart[i] - cart[d])
            zmat_ref[j][1] = 3
            zmat[j][1] = np.degrees(geometry.calc_angle(cart[i], cart[d], cart[c]))
            zmat_ref[j][2] = 2
            zmat[j][2], collin = geometry.calc_dihedral(cart[i], cart[d], cart[c], cart[b])
        j += 1

    return zmat_atom, zmat_ref, zmat, zmatorder
Exemple #14
0
def make_zmat_from_cart_all_dihedrals(bond, cycle, dihed, conf_dihed, natom, atom, cart, mode):
    """
    Rearrange geometry defined in Cartesian into a Z-matrix,
    with references suitable for a 1-D hindered rotor scan.
    Include all rotors which are:
    If mode = 0: all rotatable bonds
    If mode = 1: only those bonds, which generate conformers,
    i.e. no methyl bonds, t-butyl bonds, etc

    bond: bond matrix of the species
    cycle: atom list of species with 0 if atom is not in cycle and 1 otherwise
    dihed: total list of dihedrals
    conf_dihed: list of dihedrals without the symmetrical ones
    natom: number of atoms
    atom: symbols of all the atoms
    cart: cartesian coordinates of the species
    """
    rotors = []  # rotors to consider

    if mode == 0:
        for rotor in dihed:
            rotors.append(rotor[:])
    if mode == 1:
        for rotor in conf_dihed:
            rotors.append(rotor[:])

    if len(rotors) > 0:
        # order in which the atoms will be added:
        # 1. First rotor
        # 2. Smallest path between first and second rotor (if any)
        # 3. Second rotor
        # 4. Smallest path between second and third rotor (if any)
        # ...
        # n. Last rotor
        # n+1. All atoms that are not part of a rotor,
        #      starting by the neighbors of all rotor atoms

        # order the rotors as such that the path between subsequent rotors does not
        # cross another rotor
        rotors, connecting_list, connected_rotor, path_length = order_rotors(rotors, bond, natom, atom)
        # Add first rotor:
        zmat_atom = ['X' for i in range(natom)]
        zmat_ref = np.zeros((natom, 3), dtype=int) - 1
        zmat = np.zeros((natom, 3)) - 1
        zmatorder = [-1 for i in range(natom)]

        zmat_atom[0] = atom[rotors[0][0]]
        zmatorder[0] = rotors[0][0]

        zmat_atom[1] = atom[rotors[0][1]]
        zmatorder[1] = rotors[0][1]
        zmat_ref[1][0] = 1
        zmat[1][0] = np.linalg.norm(cart[rotors[0][1]] - cart[rotors[0][0]])

        zmat_atom[2] = atom[rotors[0][2]]
        zmatorder[2] = rotors[0][2]
        zmat_ref[2][0] = 2
        zmat[2][0] = np.linalg.norm(cart[rotors[0][2]] - cart[rotors[0][1]])
        zmat_ref[2][1] = 1
        zmat[2][1] = np.degrees(geometry.calc_angle(cart[rotors[0][2]], cart[rotors[0][1]], cart[rotors[0][0]]))

        zmat_atom[3] = atom[rotors[0][3]]
        zmatorder[3] = rotors[0][3]
        zmat_ref[3][0] = 3
        zmat[3][0] = np.linalg.norm(cart[rotors[0][3]] - cart[rotors[0][2]])
        zmat_ref[3][1] = 2
        zmat[3][1] = np.degrees(geometry.calc_angle(cart[rotors[0][3]], cart[rotors[0][2]], cart[rotors[0][1]]))
        zmat_ref[3][2] = 1
        zmat[3][2], collin = geometry.calc_dihedral(cart[rotors[0][3]], cart[rotors[0][2]], cart[rotors[0][1]], cart[rotors[0][0]])

        # Add subsequent rotors:
        rot_index = 1
        j = 4

        while rot_index < len(rotors):
            rotor = rotors[rot_index]
            chain_length = path_length[rot_index - 1]
            chain = connecting_list[rot_index - 1]
            conn_rotor = connected_rotor[rot_index - 1]
            to_add = []
            added = []
            for at in rotor:
                if at not in zmatorder:
                    to_add.append(at)
                else:
                    added.append(at)

            if len(to_add) == 0:
                logging.error("error, all atoms of a rotor have been added, without adding this dihedral explicitly")
            elif len(to_add) == 1:
                at = to_add[0]
                if rotor.index(at) == 1 or rotor.index(at) == 2:
                    logging.error("error, all atoms except a middle atom have been added, strange...")
                elif rotor.index(at) == 0:
                    add(j, [at, rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                elif rotor.index(at) == 3:
                    add(j, [at, rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
            elif len(to_add) == 2:
                at1 = to_add[0]
                at2 = to_add[1]
                if sorted([rotor.index(at1), rotor.index(at2)]) == [0, 1]:
                    neighbor_list = get_neighbors(rotor[2], bond, natom, rotors, zmatorder)
                    # add rotor[1]
                    add(j, [rotor[1], rotor[2], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                    # add rotor[0]
                    add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                elif sorted([rotor.index(at1), rotor.index(at2)]) == [2, 3]:
                    neighbor_list = get_neighbors(rotor[1], bond, natom, rotors, zmatorder)
                    # add rotor[2]
                    add(j, [rotor[2], rotor[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                    # add rotor[3]
                    add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                elif sorted([rotor.index(at1), rotor.index(at2)]) == [0, 3]:
                    r1, pos1 = middle_atom(rotors, rotor[1])
                    r2, pos2 = middle_atom(rotors, rotor[2])
                    if r1 and pos1[0] in zmatorder and pos1[1] in zmatorder:
                        # add rotor[0]
                        add(j, [rotor[0], rotor[1], pos1[0], pos1[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        # add rotor[3]
                        add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                    elif r2 and pos2[0] in zmatorder and pos2[1] in zmatorder:
                        # add rotor[3]
                        add(j, [rotor[3], rotor[2], pos2[0], pos2[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        # add rotor[0]
                        add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                    else:
                        if cycle[rotor[2]] == 1:
                            neighbor_list = get_neighbors(rotor[2], bond, natom, rotors, zmatorder)
                            # add rotor[3]
                            add(j, [rotor[3], rotor[2], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            # add rotor[0]
                            add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                        else:
                            neighbor_list = get_neighbors(rotor[1], bond, natom, rotors, zmatorder)
                            # add rotor[0]
                            add(j, [rotor[0], rotor[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            # add rotor[3]
                            add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                elif sorted([rotor.index(at1), rotor.index(at2)]) == [0, 2]:
                    neighbor_list = get_neighbors(rotor[1], bond, natom, rotors, zmatorder)
                    # add rotor[2]
                    add(j, [rotor[2], rotor[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    # add rotor[0]
                    add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                elif sorted([rotor.index(at1), rotor.index(at2)]) == [1, 3]:
                    neighbor_list = get_neighbors(rotor[0], bond, natom, rotors, zmatorder)
                    # add rotor[1]
                    add(j, [rotor[1], rotor[0], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    # add rotor[3]
                    add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                else:
                    logging.error("error, two atoms that need to be added are not the outer atoms of a rotor, strange...")
            elif len(to_add) == 3:
                if added[0] == rotor[0]:
                    neighbor_list = get_neighbors(rotor[0], bond, natom, rotors, zmatorder)
                    add(j, [rotor[1], rotor[0], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                    add(j, [rotor[2], rotor[1], rotor[0], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                    add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                elif added[0] == rotor[1]:
                    neighbor_list = get_neighbors(rotor[1], bond, natom, rotors, zmatorder)
                    if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                        add(j, [rotor[2], rotor[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[3], rotor[2], rotor[1], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                    else:
                        add(j, [rotor[0], rotor[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[2], rotor[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                elif added[0] == rotor[2]:
                    neighbor_list = get_neighbors(rotor[2], bond, natom, rotors, zmatorder)
                    if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                        add(j, [rotor[3], rotor[2], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[1], rotor[2], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                    else:
                        add(j, [rotor[1], rotor[2], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[0], rotor[1], rotor[2], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                elif added[0] == rotor[3]:
                    neighbor_list = get_neighbors(rotor[3], bond, natom, rotors, zmatorder)
                    add(j, [rotor[2], rotor[3], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                    add(j, [rotor[1], rotor[2], rotor[3], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                    add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1
                else:
                    logging.error('error')
            else:
                if len(chain) == 2:  # this is the minimum chain length
                    neighbor_list = get_neighbors(chain[1], bond, natom, rotors, zmatorder)
                    if chain[0] == rotor[0]:
                        add(j, [rotor[0], chain[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[1], rotor[0], chain[1], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[2], rotor[1], rotor[0], chain[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                    elif chain[0] == rotor[1]:
                        if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                            add(j, [rotor[1], chain[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[2], rotor[1], chain[1], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[3], rotor[2], rotor[1], chain[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                        else:
                            add(j, [rotor[1], chain[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[0], rotor[1], chain[1], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[2], rotor[1], chain[1], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                    elif chain[0] == rotor[2]:
                        if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                            add(j, [rotor[2], chain[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[1], rotor[2], chain[1], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[3], rotor[2], chain[1], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                        else:
                            add(j, [rotor[2], chain[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[1], rotor[2], chain[1], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[0], rotor[1], rotor[2], chain[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                    elif chain[0] == rotor[3]:
                        add(j, [rotor[3], chain[1], neighbor_list[0], neighbor_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[2], rotor[3], chain[1], neighbor_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[1], rotor[2], rotor[3], chain[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                elif len(chain) > 2:
                    neighbor_list = get_neighbors(chain[-1], bond, natom, rotors, zmatorder)
                    # add the chain of atoms between this rotor and the closest rotor that is already in the zmatrix
                    for i in range(1, len(chain) - 1):  # do not consider two outer atoms, which are part of a rotor
                        ref_list = []
                        if i == 1:
                            ref_list = [chain[-1], neighbor_list[0], neighbor_list[1]]
                        elif i == 2:
                            ref_list = [chain[-2], chain[-1], neighbor_list[0]]
                        else:
                            ref_list = [chain[-i], chain[-(i - 1)], chain[-(i - 2)]]
                        add(j, [chain[-(i + 1)], ref_list[0], ref_list[1], ref_list[2]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                    # add the rotor itself:
                    ref_list = []

                    if len(chain) == 3:  # only one atom connects the two rotors:
                        ref_list = [chain[1], chain[2], neighbor_list[0]]
                    else:
                        ref_list = [chain[1], chain[2], chain[3]]

                    if chain[0] == rotor[0]:
                        add(j, [rotor[0], ref_list[0], ref_list[1], ref_list[2]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[1], rotor[0], ref_list[0], ref_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[2], rotor[1], rotor[0], ref_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                    elif chain[0] == rotor[1]:
                        if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                            add(j, [rotor[1], ref_list[0], ref_list[1], ref_list[2]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[2], rotor[1], ref_list[0], ref_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[3], rotor[2], rotor[1], ref_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                        else:
                            add(j, [rotor[1], ref_list[0], ref_list[1], ref_list[2]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[0], rotor[1], ref_list[0], ref_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[2], rotor[1], ref_list[0], ref_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                    elif chain[0] == rotor[2]:
                        if cycle[rotor[3]] == 1 or cycle[rotor[2]] == 1:
                            add(j, [rotor[2], ref_list[0], ref_list[1], ref_list[2]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[1], rotor[2], ref_list[0], ref_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[3], rotor[2], ref_list[0], ref_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                        else:
                            add(j, [rotor[2], ref_list[0], ref_list[1], ref_list[2]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[1], rotor[2], ref_list[0], ref_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[0], rotor[1], rotor[2], ref_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                            add(j, [rotor[3], rotor[2], rotor[1], rotor[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                            j += 1
                    elif chain[0] == rotor[3]:
                        add(j, [rotor[3], ref_list[0], ref_list[1], ref_list[2]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[2], rotor[3], ref_list[0], ref_list[1]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[1], rotor[2], rotor[3], ref_list[0]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                        add(j, [rotor[0], rotor[1], rotor[2], rotor[3]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                        j += 1
                else:
                    logging.error('error, chain length too small')
            rot_index += 1
    else:
        # no rotors here, add the first four atoms of the molecule
        zmat_atom = ['X' for i in range(natom)]
        zmat_ref = np.zeros((natom, 3), dtype=int) - 1
        zmat = np.zeros((natom, 3)) - 1
        zmatorder = [-1 for i in range(natom)]

        if len(atom) == 1:
            zmat_atom[0] = atom[0]
            zmatorder[0] = 0
        elif len(atom) == 2:
            zmat_atom[0] = atom[0]
            zmatorder[0] = 0

            zmat_atom[1] = atom[1]
            zmatorder[1] = 1
            zmat_ref[1][0] = 1
            zmat[1][0] = np.linalg.norm(cart[1] - cart[0])
        else:
            # get three atoms that are bonded to one another
            motif = ['X', 'X', 'X']
            ins = start_motif(motif, natom, bond, atom, -1, [[k] for k in range(natom)])[0]

            zmat_atom[0] = atom[ins[0]]
            zmatorder[0] = ins[0]

            zmat_atom[1] = atom[ins[1]]
            zmatorder[1] = ins[1]
            zmat_ref[1][0] = 1
            zmat[1][0] = np.linalg.norm(cart[ins[1]] - cart[ins[0]])

            zmat_atom[2] = atom[ins[2]]
            zmatorder[2] = ins[2]
            zmat_ref[2][0] = 2
            zmat[2][0] = np.linalg.norm(cart[ins[2]] - cart[ins[1]])
            zmat_ref[2][1] = 1
            zmat[2][1] = np.degrees(geometry.calc_angle(cart[ins[2]], cart[ins[1]], cart[ins[0]]))

            j = 3

    # add all the remaining atoms
    while -1 in zmatorder:
        for i in range(natom):
            if i not in zmatorder:
                neighbor_list = get_three_neighbors(i, bond, natom, rotors, zmatorder)
                if len(neighbor_list) > 2:
                    add(j, [i, neighbor_list[0], neighbor_list[1], neighbor_list[2]], zmat, zmat_atom, zmatorder, zmat_ref, atom, cart)
                    j += 1

    return zmat_atom, zmat_ref, zmat, zmatorder
Exemple #15
0
    def get_constraints(self,step, geom):
        """
        There are three types of constraints:
        1. fix a coordinate to the current value
        2. change a coordinate and fix is to the new value
        3. release a coordinate (only for gaussian)
        """
        fix = []
        change = []
        release = []
        if step < self.max_step:
            #fix all the bond lengths
            for i in range(self.species.natom - 1):
                for j in range(i+1, self.species.natom):
                    if self.species.bond[i][j] > 0:
                        fix.append([i+1,j+1])
        if step < 12:
            
            if step < 10:
                dih = geometry.calc_dihedral(geom[self.instance[-4]], geom[self.instance[-3]], geom[self.instance[-2]], geom[self.instance[-1]])[0]
                if np.abs(dih) < 160:
                    #move the dihedral to 160 degrees in 10 steps
                    frac = 1. / (10 - step + 0.)
                    new_dih = dih + frac * (160. - dih)
                    constraint = [self.instance[-4] + 1,self.instance[-3] + 1,self.instance[-2] + 1,self.instance[-1] + 1,new_dih]
                    change.append(constraint)
            
            fval = [2.0,2.0,1.8,1.8]
            if self.species.atom[self.instance[-1]] == 'H':
                fval[2] = 1.35
                fval[3] = 1.35
            
            val = geometry.new_bond_length(self.species,self.instance[0],self.instance[1],step+1,12,fval[0],geom)
            constraint = [self.instance[0] + 1,self.instance[1] + 1,val]
            change.append(constraint)
            
            val = geometry.new_bond_length(self.species,self.instance[2],self.instance[3],step+1,12,fval[1],geom)
            constraint = [self.instance[2] + 1,self.instance[3] + 1,val]
            change.append(constraint)
            
            if self.species.bond[self.instance[-1]][self.instance[-2]] == 1:
                val = geometry.new_bond_length(self.species,self.instance[-1],self.instance[-2],step+1,12,fval[2],geom)
                constraint = [self.instance[-1] + 1,self.instance[-2] + 1,val]
                change.append(constraint)
            #else do not change this bond length, the bond needs to stay and just change in order
            
            val = geometry.new_bond_length(self.species,self.instance[-1],self.instance[3],step+1,12,fval[3],geom)
            constraint = [self.instance[-1] + 1,self.instance[3] + 1,val] #todo: larger rings, this only work for 5 membered rings
            change.append(constraint)

        
        #remove the bonds from the fix if they are in another constaint
        for c in change:
            if len(c) == 3:
                index = -1
                for i,fi in enumerate(fix):
                    if len(fi) == 2:
                        if sorted(fi) == sorted(c[:2]):
                            index = i
                if index > -1:
                    del fix[index]
        
        return step, fix, change, release
Exemple #16
0
def make_zmat_from_cart(species, rotor, cart, mode):
    """
    Rearrange geometry defined in Cartesian into a Z-matrix,
    with references suitable for a 1-D shindered rotor scan.
    If mode = 0: all rotatable bonds
    If mode = 1: only those bonds, which generate conformers
    If mode = 2: suply your one rotor in rotor as a list of atom indices
    """
    natom = species.natom
    atom = species.atom
    
    if mode == 0:
        a = species.dihed[rotor][0]
        b = species.dihed[rotor][1]
        c = species.dihed[rotor][2]
        d = species.dihed[rotor][3]
    elif mode == 1:
        a = species.conf_dihed[rotor][0]
        b = species.conf_dihed[rotor][1]
        c = species.conf_dihed[rotor][2]
        d = species.conf_dihed[rotor][3]   
    elif mode == 2:
        a = rotor[0]
        b = rotor[1]
        c = rotor[2]
        d = rotor[3]

    groupA = np.zeros(natom, dtype=int)
    groupB = np.zeros(natom, dtype=int)
    groupC = np.zeros(natom, dtype=int)
    groupD = np.zeros(natom, dtype=int)
    
    groupA[a] = 1
    groupB[b] = 1
    groupC[c] = 1
    groupD[d] = 1

    #get all immediate neighbors of a A, B, C, and D
    for i in range(natom):
        if species.bond[a][i] > 0 and i != b:
            groupA[i] = 1
        elif species.bond[b][i] > 0 and i != a and i != c:
            groupB[i] = 1
        elif species.bond[c][i] > 0 and i != b and i != d:
            groupC[i] = 1
        elif species.bond[d][i] > 0 and i != c:
            groupD[i] = 1
            
    found = 1
    while found > 0:
        found = 0
        for i in range(natom):
            if groupA[i] == 1:
                for j in range(natom):
                    if species.bond[i][j] > 0 and j != b and groupA[j] != 1:
                        groupA[j] = 1
                        found = 1
            elif groupB[i] == 1:
                for j in range(natom):
                    if species.bond[i][j] > 0 and j != a and j != c and groupB[j] != 1:
                        groupB[j] = 1
                        found = 1
            elif groupC[i] == 1:
                for j in range(natom):
                    if species.bond[i][j] > 0 and j != b and j != d and groupC[j] != 1:
                        groupC[j] = 1
                        found = 1
            elif groupD[i] == 1:
                for j in range(natom):
                    if species.bond[i][j] > 0 and j != c and groupD[j] != 1:
                        groupD[j] = 1
                        found = 1

    zmat_atom = ['X' for i in range(natom)]
    zmat_ref = np.zeros((natom, 3), dtype=int) - 1
    zmat = np.zeros((natom, 3)) - 1

    # FIXME need to take care about TS strucutres maybe
    zmatorder = [-1 for i in range(natom)]
    
    zmat_atom[0] = atom[a]
    zmatorder[0] = a

    zmat_atom[1] = atom[b]
    zmatorder[1] = b
    zmat_ref[1][0] = 1
    zmat[1][0] = np.linalg.norm(cart[b] - cart[a]) 

    zmat_atom[2] = atom[c]
    zmatorder[2] = c
    zmat_ref[2][0] = 2
    zmat[2][0] = np.linalg.norm(cart[c] - cart[b])
    zmat_ref[2][1] = 1
    zmat[2][1] = np.degrees(geometry.calc_angle(cart[c], cart[b], cart[a]))

    zmat_atom[3] = atom[d]
    zmatorder[3] = d
    zmat_ref[3][0] = 3
    zmat[3][0] = np.linalg.norm(cart[d] - cart[c])
    zmat_ref[3][1] = 2
    zmat[3][1] = np.degrees(geometry.calc_angle(cart[d], cart[c], cart[b]))
    zmat_ref[3][2] = 1
    zmat[3][2], collin = geometry.calc_dihedral(cart[d], cart[c], cart[b], cart[a])

    j = 4
    for i in range(natom):
        if i == a or i == b or i == c or i == d:
            continue
        zmat_atom[j] = atom[i]
        zmatorder[j] = i
        if groupA[i] == 1:
            zmat_ref[j][0] = 1
            zmat[j][0] = np.linalg.norm(cart[i] - cart[a])
            zmat_ref[j][1] = 2
            zmat[j][1] = np.degrees(geometry.calc_angle(cart[i], cart[a], cart[b]))
            zmat_ref[j][2] = 3
            zmat[j][2], collin = geometry.calc_dihedral(cart[i], cart[a], cart[b], cart[c])
        elif groupB[i] == 1:
            zmat_ref[j][0] = 2
            zmat[j][0] = np.linalg.norm(cart[i] - cart[b])
            zmat_ref[j][1] = 3
            zmat[j][1] = np.degrees(geometry.calc_angle(cart[i], cart[b], cart[c]))
            zmat_ref[j][2] = 4
            zmat[j][2], collin = geometry.calc_dihedral(cart[i], cart[b], cart[c], cart[d])
        elif groupC[i] == 1:
            zmat_ref[j][0] = 3
            zmat[j][0] = np.linalg.norm(cart[i] - cart[c])
            zmat_ref[j][1] = 2
            zmat[j][1] = np.degrees(geometry.calc_angle(cart[i], cart[c], cart[b]))
            zmat_ref[j][2] = 1
            zmat[j][2], collin = geometry.calc_dihedral(cart[i], cart[c], cart[b], cart[a])
        elif groupD[i] == 1:
            zmat_ref[j][0] = 4
            zmat[j][0] = np.linalg.norm(cart[i] - cart[d])
            zmat_ref[j][1] = 3
            zmat[j][1] = np.degrees(geometry.calc_angle(cart[i], cart[d], cart[c]))
            zmat_ref[j][2] = 2
            zmat[j][2], collin = geometry.calc_dihedral(cart[i], cart[d], cart[c], cart[b])
        j += 1

    return zmat_atom, zmat_ref, zmat, zmatorder
Exemple #17
0
    def get_constraints(self, step, geom):
        """
        There are three types of constraints:
        1. fix a coordinate to the current value
        2. change a coordinate and fix is to the new value
        3. release a coordinate (only for gaussian)
        """
        fix = []
        change = []
        release = []
        if step < self.max_step:
            #fix all the bond lengths
            for i in range(self.species.natom - 1):
                for j in range(i + 1, self.species.natom):
                    if self.species.bond[i][j] > 0:
                        fix.append([i + 1, j + 1])
        if step < 12:
            new_dihs = geometry.new_ring_dihedrals(self.species, self.instance,
                                                   step, 12, geom)
            for dih in range(len(self.instance) -
                             4):  # do not include last atom
                constraint = []
                for i in range(4):
                    constraint.append(self.instance[dih + i] + 1)
                constraint.append(new_dihs[dih])
                change.append(constraint)
            ldih = [
            ]  # constraint for the last dihedral, which needs to be 180 degrees
            for i in range(4):
                ldih.append(self.instance[len(self.instance) - 4 + i] + 1)
            dih = geometry.calc_dihedral(geom[ldih[0] - 1], geom[ldih[1] - 1],
                                         geom[ldih[2] - 1],
                                         geom[ldih[3] - 1])[0]
            frac = 1. / (12. - step)
            if dih < 0:
                new_dih = dih - frac * (180. + dih)
                ldih.append(new_dih)
            else:
                new_dih = dih + frac * (180. - dih)
                ldih.append(new_dih)
            change.append(ldih)
        elif step < 22:
            for dih in range(len(self.instance) - 3):
                constraint = []
                for i in range(4):
                    constraint.append(self.instance[dih + i] + 1)
                release.append(constraint)

            fdist1 = constants.st_bond[''.join(
                sorted(self.species.atom[self.instance[0]] +
                       self.species.atom[self.instance[-2]]))] * 1.0
            if ''.join(
                    sorted(self.species.atom[self.instance[0]] +
                           self.species.atom[self.instance[-2]])) == 'CO':
                fdist1 = 1.68
            ndist1 = geometry.new_bond_length(self.species, self.instance[0],
                                              self.instance[-2], step - 11, 10,
                                              fdist1, geom)
            constraint = [self.instance[0] + 1, self.instance[-2] + 1, ndist1]
            change.append(constraint)

            fdist2 = constants.st_bond[''.join(
                sorted(self.species.atom[self.instance[-1]] +
                       self.species.atom[self.instance[-2]]))] * 1.0
            if ''.join(
                    sorted(self.species.atom[self.instance[-1]] +
                           self.species.atom[self.instance[-2]])) == 'CO':
                fdist2 = 1.68
            ndist2 = geometry.new_bond_length(self.species, self.instance[-1],
                                              self.instance[-2], step - 11, 10,
                                              fdist2, geom)
            constraint = [self.instance[-1] + 1, self.instance[-2] + 1, ndist2]
            change.append(constraint)

        #remove the bonds from the fix if they are in another constaint
        for c in change:
            if len(c) == 3:
                index = -1
                for i, fi in enumerate(fix):
                    if len(fi) == 2:
                        if sorted(fi) == sorted(c[:2]):
                            index = i
                if index > -1:
                    del fix[index]

        return step, fix, change, release
Exemple #18
0
    def get_constraints(self, step, geom):
        fix = []
        change = []
        release = []
        if step < self.max_step:
            self.fix_bonds(fix)

            if step < 10:
                dih = geometry.calc_dihedral(geom[self.instance[-4]],
                                             geom[self.instance[-3]],
                                             geom[self.instance[-2]],
                                             geom[self.instance[-1]])[0]
                if abs(dih) < 160:
                    #move the dihedral to 160 degrees in 10 steps
                    frac = 1. / (10 - step + 0.)
                    new_dih = dih + frac * (160. - dih)
                    constraint = [
                        self.instance[-4] + 1, self.instance[-3] + 1,
                        self.instance[-2] + 1, self.instance[-1] + 1, new_dih
                    ]
                    change.append(constraint)

            fval = [2.0, 2.0, 1.8, 1.8]
            if self.species.atom[self.instance[-1]] == 'H':
                fval[2] = 1.35
                fval[3] = 1.35

            self.set_bond(0,
                          1,
                          -999,
                          change,
                          step=step + 1,
                          stmax=self.max_step,
                          findist=fval[0],
                          geom=geom)
            self.set_bond(2,
                          3,
                          -999,
                          change,
                          step=step + 1,
                          stmax=self.max_step,
                          findist=fval[1],
                          geom=geom)

            if self.species.bond[self.instance[-1]][self.instance[-2]] == 1:
                self.set_bond(-1,
                              -2,
                              -999,
                              change,
                              step=step + 1,
                              stmax=self.max_step,
                              findist=fval[2],
                              geom=geom)
                #else do not change this bond length, the bond needs to stay and just change in order

            self.set_bond(-1,
                          3,
                          -999,
                          change,
                          step=step + 1,
                          stmax=self.max_step,
                          findist=fval[3],
                          geom=geom)
            # TODO larger rings, this only work for 5 membered rings

        self.clean_constraints(change, fix)

        return step, fix, change, release