def build(self, moleculeData=None, name=None, unit='angstrom', **kwargs): if moleculeData is not None: if type(moleculeData) is list: moleculeData = np.array(moleculeData) if len(moleculeData.shape) == 1: moleculeData = np.atleast_2d(moleculeData) self.N = moleculeData.shape[0] self.Z = moleculeData[:, 0] self.R = moleculeData[:, 1:] self.type_list = [qtk.Z2n(z) for z in self.Z] self.string = ['' for i in range(self.N)] if name is None: self.name = self.stoichiometry() else: self.name = name else: assert 'Z' in kwargs assert 'R' in kwargs Z = np.array(kwargs['Z']) R = np.array(kwargs['R']) self.N = len(Z) self.Z = Z self.R = R self.type_list = [qtk.Z2n(z) for z in self.Z] self.string = ['' for i in range(self.N)] self.name = self.stoichiometry() if unit is 'bohr': self.R = self.R * 0.52917721092 return self
def stoichiometry(self, output='string', **kwargs): elements = collections.Counter(sorted(self.Z)) data = zip(elements.keys(), elements.values()) data.sort(key=lambda tup: tup[0]) if output == 'dictionary' or output == 'count': out = {} for element in data: out[qtk.Z2n(element[0])] = element[1] elif output == 'string': out = '' for element in data: out = out + qtk.Z2n(element[0]) + str(element[1]) return out
def _mutate(self, mutation): for m in xrange(len(mutation)): for i in xrange(len(mutation[m])): index = self.mutation_list[m][i] #target = self.mutation_target[m][mutation[m][i]] target = mutation[m][i] self.new_structure.Z[index] = target self.new_structure.type_list[index] = qtk.Z2n(target)
def mutateElement(self, oldZ, newZ): if oldZ != newZ: if type(oldZ) is str: oldZ = qtk.n2Z(oldZ) if type(newZ) is str: newZ = qtk.n2Z(newZ) newElem = qtk.Z2n(newZ) indices = [] for i in range(self.N): if abs(self.Z[i] - oldZ) < 0.1: indices.append(i) self.setAtoms(indices, element=newElem)
def setAtoms(self, index, **kwargs): if type(index) is int: index = [index] if 'element' in kwargs or 'Z' in kwargs: for i in index: if 'element' in kwargs: if type(kwargs['element']) is str: Z = qtk.n2Z(kwargs['element']) Zn = kwargs['element'] elif type(kwargs['element']) is int\ or type(kwargs['element']) is float: Z = kwargs['element'] Zn = qtk.Z2n(Z) elif 'Z' in kwargs: Z = kwargs['Z'] Zn = qtk.Z2n(Z) self.Z[i] = Z self.type_list[i] = Zn if 'string' in kwargs: minZ = min(min(self.Z)-1, 0) for i in index: self.string[i] = kwargs['string'] self.Z[i] = minZ
def write(self, name=None): today = datetime.date.today() out = InpContent(name) out.write('Goedecker pseudopotential for %s\n' % \ qtk.Z2n(self.param['Z'])) out.write(' %2d %2d %s ! Z, ZV, date(ddmmyy)\n' %\ (self.param['Z'], self.param['ZV'], today.strftime('%d%m%y'))) out.write(' %d %s 2 0 2002 0 ! xc:%s\n' %\ (type_dict[self.setting['type']], xc_dict[self.param['xc']], self.param['xc'])) out.write(' %12.8f %3d' % (self.param['r_loc'], self.param['Cn'])) for i in range(self.param['Cn']): out.write(' % 12.8f' % self.param['Ci'][i]) out.write(' ! rloc, #C, C[i]') out.write('\n %d\n' % self.param['l_max']) for i in range(len(self.param['r_nl'])): r_nl = self.param['r_nl'][i] h_ij = self.param['h_ij'][i] out.write(' %12.8f %3d' % (r_nl, len(h_ij))) if len(h_ij) > 0: for j in range(len(h_ij)): if j > 0: out.write('%19s' % '') for k in range(j, len(h_ij)): out.write(' % 12.8f' % h_ij[j][k]) if j == 0: out.write(' ! h_ij\n') else: out.write('\n') else: out.write(' % 12.8f\n' % 0) if self.param['r_nl'] > 0: for j in range(len(h_ij)): out.write('%19s' % '') for k in range(j, len(h_ij)): out.write(' % 12.8f' % 0.0) if j == 0: out.write(' ! abinit k_ij\n') else: out.write('\n') if self.setting['type'] == 'nlcc': out.write(' %12.8f %12.8f' %\ (self.param['rcore'], self.param['qcore'])) out.close()
def ESP(self, coord=None, **kwargs): """ method for electron density Note: CUBE file is assumed to be orthorohmbic """ data = self.data grid = self.grid if 'molecule' not in kwargs: mol = self.molecule else: try: mol = copy.deepcopy(qtk.toMolecule(kwargs['molecule'])) except: qtk.exit("error when loading molecule:%s" % \ str(kwargs['molecule'])) N = mol.N Q = self.integrate() Z_sum = sum(mol.Z) ne_diff = abs(Q - Z_sum) ve_diff = abs(Q - mol.getValenceElectrons()) if min(ne_diff, ve_diff) > 1E-2: qtk.warning("charge not conserved... ESP is wrong!") qtk.warning("charge integrate to %.2f, " % Q + \ "while nuclear charge adds to %.2f" % Z_sum) if ve_diff < ne_diff: Z = [qtk.n2ve(qtk.Z2n(z)) for z in mol.Z] Z = np.array(Z).reshape(N, 1) else: Z = mol.Z.reshape(N, 1) structure = np.hstack([Z, mol.R * 1.889725989]) if coord is not None: x, y, z = np.array(coord) * 1.889725989 V = ESP_c.esp_point(grid, structure, data, x, y, z) return V else: qtk.warning("known issue: unidentifed memory leak") out = copy.deepcopy(self) out.molecule = mol out.data = np.nan_to_num(ESP_cube_c.esp_cube( grid, structure, data)) return out
def addAtoms(self, element, coord): if type(element) is not list: element = [element] coord = [coord] if type(element[0]) is not str: element = [qtk.Z2n(int(i)) for i in element] Z = list(self.Z) for i in range(len(element)): #e = getattr(pt, element[i].title()) e = qtk.element[element[i]] r = coord[i] if self.N == 0: self.R = np.array(r) else: self.R = np.vstack([self.R, np.array(r)]) self.N = self.N + 1 self.type_list.append(e.symbol) Z.append(e.number) self.string.append('') self.Z = np.array(Z) if self.N == 1: self.R = np.array([self.R])
def getMO(self, fchk): self.program = 'gaussian' fchkfile = open(fchk) fchk = fchkfile.readlines() self.basis_name = filter(None, fchk[1].split(' '))[2] def basisList(L): N_dict = {4: 'g', 5: 'h', 6: 'k'} orbital = ['x', 'y', 'z'] base = [2 for _ in range(L)] out = [] for n in range(L + 1): b = copy.deepcopy(base) for i in range(n): b[i] = 0 orb = N_dict[L] + ''.join([orbital[j] for j in b]) out.append(orb) for i in range(n, L): b[i] = 1 orb = N_dict[L] + ''.join([orbital[j] for j in b]) out.append(orb) return out basis_list = [ ['s'], ['px', 'py', 'pz'], ['dxx', 'dyy', 'dzz', 'dxy', 'dxz', 'dyz'], [ 'fxxx', 'fyyy', 'fzzz', 'fxyy', 'fxxy', 'fxxz', 'fxzz', 'fyzz', 'fyyz', 'fxyz' ], basisList(4), basisList(5), ] def readFchk(flag, type=float): flagStr = filter(lambda x: flag in x, fchk)[0] n_entry = int(filter(None, flagStr.split(' '))[-1]) ind = fchk.index(flagStr) + 1 if type is float: factor = 5 elif type is int: factor = 6 n_lines = n_entry / factor + 1 if not n_entry % factor: n_lines = n_lines - 1 data = [] for i in range(ind, ind + n_lines): dList = list( np.array(filter(None, fchk[i].split(' '))).astype(type)) data.extend(dList) return data, n_entry self.Z, self.N = readFchk('Nuclear charges') self.type_list = [qtk.Z2n(z) for z in self.Z] _types, _n_shell = readFchk('Shell types', int) _exp, _nfn = readFchk('Primitive exponents') _cef = readFchk('Contraction coefficients')[0] _coord, _test = readFchk('Coordinates of each shell') _ng = readFchk('Number of primitives per shell', int)[0] _coord = np.array(_coord).reshape([_n_shell, 3]) self.mo_eigenvalues, self.n_mo = \ readFchk('Alpha Orbital Energies') _mo, _dim = readFchk('Alpha MO coefficients') try: self.mo_eigenvalues_beta, _ = \ readFchk('Beta Orbital Energies') _mob, _dimb = readFchk('Beta MO coefficients') except: _mob, _dimb = None, None self.mo_eigenvalues_beta = None self.n_ao = _dim / self.n_mo self.n_basis = self.n_ao self.mo_vectors = np.array(_mo).reshape([self.n_mo, self.n_ao]) if self.mo_eigenvalues_beta is not None: self.mo_vectors_beta = np.array(_mob).reshape( [self.n_mo, self.n_ao]) _map = readFchk('Shell to atom map', int)[0] _map_coord = list(np.diff(_map)) _map_coord.insert(0, 1) _R_ind = [i for i in range(_n_shell) if _map_coord[i] > 0] self.R_bohr = np.array([_coord[i] for i in _R_ind]) self.R = self.R_bohr / 1.88972613 _neStr = filter(lambda x: 'Number of electrons' in x, fchk)[0] _ne = float(filter(None, _neStr.split(' '))[-1]) self.occupation = [] warned = False for i in range(self.n_mo): if i < _ne / 2 - 1: self.occupation.append(2.0) elif i >= _ne / 2 - 1 and i < _ne / 2: if abs(_ne % 2) < 1E-5: self.occupation.append(2.0) else: self.occupation.append(_ne % 2) else: self.occupation.append(0.0) tmp = 0 shift = 0 self.basis = [] for i in range(_n_shell): _ind = _map[i] - 1 bfn_base = {} bfn_base['index'] = i bfn_base['center'] = _coord[i] bfn_base['atom'] = self.type_list[_ind] exp = [] cef = [] for g in range(_ng[i]): exp.append(_exp[i + shift + g]) cef.append(_cef[i + shift + g]) shift = shift + _ng[i] - 1 if _types[i] == 0: l_max = 1 blist = ['s'] else: if _types[i] > 0: l_max = sum(range(_types[i] + 2)) blist = basis_list[_types[i]] else: l_max = 2 * abs(_types[i]) + 1 blist = ['D0' for _ in range(l_max)] if not warned: qtk.warning("sp shell or spherical basis are used, " +\ "some functions will not work") warned = True for l in range(l_max): bfn = copy.deepcopy(bfn_base) bfn['exponents'] = copy.deepcopy(exp) bfn['coefficients'] = copy.deepcopy(cef) bfn['type'] = blist[l] tmp = tmp + 1 self.basis.append(bfn) self.basisFormat()
def getChild(): child = {} for key in parent1.iterkeys(): if key == 'mutation': # implementation for element_count constraints if self.element_count: constraint_list = [] constraint_keys = [] # tool to constuct list def _list_append(mcoord, i_list, Zc): for g in range(len(mcoord)): grp = mcoord[g] for i in range(len(grp)): Z_p = grp[i] if Z_p == Zc: i_list.append((g, i)) # construct mutation list for elem in self.element_count.iterkeys(): i_list = [] _Z = qtk.n2Z(elem) _list_append(parent1['mutation'], i_list, _Z) _list_append(parent2['mutation'], i_list, _Z) constraint_list.append(i_list) constraint_keys.append(elem) while True: selected_list = [] selected_coord = {} consistant = True for i in range(len(constraint_list)): ind_location = constraint_list[i] random.shuffle(ind_location) elem = qtk.n2Z(constraint_keys[i]) _count = self.element_count[ constraint_keys[i]][0] _end = _count while len(set(ind_location[:_end])) < _count: _end += 1 _new = list(set(ind_location[:_end])) to_select = copy.deepcopy(selected_list) to_select.extend(_new) if len(set(to_select)) == \ len(selected_list) + len(_new): selected_list.extend(_new) for coord in _new: selected_coord.update({coord: elem}) consistant = consistant & True else: consistant = False child_ind = [] for g in range(len(parent1['mutation'])): child_list = [] for i in range(len(parent1['mutation'][g])): if selected_coord.has_key((g, i)): child_list.append(selected_coord[(g, i)]) else: candidate = [] A1 = qtk.Z2n(parent1['mutation'][g][i]) A2 = qtk.Z2n(parent2['mutation'][g][i]) if not self.element_count.has_key(A1): candidate.append(qtk.n2Z(A1)) if not self.element_count.has_key(A2): candidate.append(qtk.n2Z(A2)) if len(candidate) == 0: consistant = False else: child_list.append( random.choice(candidate)) child_ind.append(child_list) if consistant: break for g in range(len(parent1['mutation'])): for i in range(len(parent1['mutation'][g])): if not selected_coord.has_key((g, i)): if random.random() < mutation_rate: child_ind[g][i] = random.choice(\ self.mutation_target[g]) elem = qtk.Z2n(child_ind[g][i]) if self.element_count.has_key(elem): coord = random.choice([tupl for tupl,targ in selected_coord.iteritems()\ if targ == qtk.n2Z(elem)]) del selected_coord[coord] selected_coord.update({ (g, i): qtk.n2Z(elem) }) [gc, ic] = list(coord) new_targ = random.choice([z for z in \ self.mutation_target[gc]\ if not self.element_count\ .has_key(qtk.Z2n(z))]) child_ind[gc][ic] = new_targ child.update({'mutation': child_ind}) else: child_mut = [] for i in range(len(parent1[key])): # mix two parent grp = parent1[key][i] index = range(len(grp)) random.shuffle(index) ind1 = index[:len(index) / 2] if len(index) % 2 == 0: ind2 = index[len(index) / 2:] append = -1 else: ind2 = index[len(index) / 2:-1] append = index[-1] new = [parent1[key][i][ind] for ind in ind1] new.extend([parent2[key][i][ind] for ind in ind2]) if append >= 0: if random.random() >= 0.5: new.append(parent1[key][i][append]) else: new.append(parent2[key][i][append]) # mutation, loop through each element for j in range(len(new)): if random.random() < mutation_rate: mut_target = [tar \ for tar in self.mutation_target[i]\ if tar != new[j]] new[j] = random.choice(mut_target) child_mut.append(new) child.update({'mutation': child_mut}) else: qtk.exit("ccs mate function is not yet implemented for "\ + key) return child
def findBonds(self, ratio=setting.bond_ratio, **kwargs): del self.segments del self.bond_types self.segments = [] self.bond_types = {} if 'no_report' not in kwargs or not kwargs['no_report']: qtk.report("Molecule", "finding bonds with cutoff ratio", ratio) def to_graph(l): G = networkx.Graph() for part in l: # each sublist is a bunch of nodes G.add_nodes_from(part) # it also imlies a number of edges: G.add_edges_from(to_edges(part)) return G def to_edges(l): """ treat `l` as a Graph and returns it's edges to_edges(['a','b','c','d']) -> [(a,b), (b,c),(c,d)] """ it = iter(l) last = next(it) for current in it: yield last, current last = current itr = 0 bond_list = [] bonded = [False for i in range(self.N)] for i in xrange(self.N): for j in xrange(i+1, self.N): d_ij = np.linalg.norm(self.R[i,:] - self.R[j,:]) atom_i = getattr(pt, self.type_list[i]) atom_j = getattr(pt, self.type_list[j]) Ri = atom_i.covalent_radius + \ atom_i.covalent_radius_uncertainty Rj = atom_j.covalent_radius + \ atom_j.covalent_radius_uncertainty Dij = (Ri+Rj) * float(ratio) if d_ij < Dij: bonded[i] = True bonded[j] = True if self.Z[i] < self.Z[j]: atom_begin = self.Z[i] atom_end = self.Z[j] index_begin = i index_end = j else: atom_begin = self.Z[j] atom_end = self.Z[i] index_begin = j index_end = i self.bonds[itr] = {'atom_begin' : atom_begin, 'index_begin' : index_begin, 'atom_end' : atom_end, 'index_end' : index_end, 'length' : d_ij} bond_list.append([i, j]) type_begin = qtk.Z2n(atom_begin) type_end = qtk.Z2n(atom_end) bond_table = qtk.data.elements.bond_table bond_keys = [] bond_keys = [ type_begin + _ + type_end for _ in ['-', '=', '#'] ] try: bond_type_ind = np.argmin( abs( np.array([ bond_table[k][0] for k in bond_keys if k in bond_table.keys() ]) - d_ij ) ) except Exception as _e: qtk.warning( "error while processing bond" +\ str(bond_keys) + "with error message %s" % str(_e)) bond_type_ind = -1 bond_type = bond_keys[bond_type_ind] self.bonds[itr]['name'] = bond_type try: bond_energy = \ bond_table[bond_keys[bond_type_ind]][1] * \ qtk.convE(1, 'kj-kcal')[0] except: bond_energy = np.nan self.bonds[itr]['energy'] = bond_energy if np.isnan(bond_energy): qtk.warning("Non-tabliated covalent bond %s" % bond_type) if bond_type in self.bond_types: self.bond_types[bond_type] += 1 else: self.bond_types[bond_type] = 1 itr += 1 segments = list(connected_components(to_graph(bond_list))) for s in range(len(segments)): segment = list(segments[s]) new_mol = self.getSegment(segment, **kwargs) ns = len(self.segments) new_mol.name = new_mol.name + '_%d' % ns self.segments.append(new_mol) for s in [i for i in range(self.N) if not bonded[i]]: segment = [s] new_mol = self.getSegment(segment, **kwargs) ns = len(self.segments) new_mol.name = new_mol.name + '_%d' % ns self.segments.append(new_mol)