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)
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
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]])
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]])
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]])
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))
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))
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)
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))
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
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
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
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
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
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
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
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