def get_fwrings(code, validation='cross_distance', cutoff=3.15): ''' Function to find all the unique rings in a zeolite framework. INPUTS: code: (str) IZA code for the zeolite you are using (i.e. 'CHA') OUTPUTS: index_paths: (dictionary) {ring length : indices of atoms in ring} label_paths: (dictionary) {ring length : site labels of atoms in ring} trajectories: (dictionary of atoms objects) - {ring length : [atoms objects for that size ring]} ''' # First, get some basic info we will need about the framework # atoms object, possible ring sizes, and the index of each o-site type atoms = framework(code) ring_sizes = get_ring_sizes(code) osites, omults, oinds = get_osites(code) # now we find all the rings associated with each oxygen type in the fw # this in theory should find us every possible type of ring in the fw paths = [] for o in oinds: paths += get_orings(atoms, o, code, validation=validation, cutoff=cutoff)[1] paths = remove_dups(paths) # now we want to get the t-site and o-site labels repeat = atoms_to_graph(atoms, 0, max(ring_sizes) * 2)[2] atoms = atoms.repeat(repeat) labels = site_labels(atoms, code) # now convert all the paths from index form into site label form index_paths = paths label_paths = [] for path in index_paths: l = [] for p in path: l.append(labels[p]) label_paths.append(l) # now we want to remove duplicate rings based on the label_paths # this will also give us the paths in a conveinent dictionary # we will check the labels and geometry to remove duplicates index_paths, label_paths = remove_labeled_dups(index_paths, label_paths, ring_sizes, atoms) # last but not least, let's make an atoms object for each ring type so that # we can visualize them later # this will be a dictionary of trajectories trajectories = dict_to_atoms(index_paths, atoms) return index_paths, label_paths, trajectories
def site_labels(atoms, code): ''' This function will get the atom site labels (as defined by the IZA) for your atoms object. Be sure to remove any adsorbates from your zeolite framework before using this function or else it won't work. This function will work with T sites that have been exchanged for Al (or any atom). atoms: atoms object containing a zeolite you want labels for code: the zeolite framework code of your atoms object (i.e. 'CHA') ''' tdict = label_tsites(atoms, code) odict = label_osites(atoms, code) all_labels = {**tdict, **odict} z = framework(code) zcell = z.cell.cellpar()[:3] acell = atoms.cell.cellpar()[:3] repeat = [] for zc, ac in zip(zcell, acell): repeat.append(int(round(ac / zc))) z = z.repeat(repeat) zo_inds = [atom.index for atom in z if atom.symbol == 'O'] zt_inds = [atom.index for atom in z if atom.symbol != 'O'] #z.set_tags(z_inds) poszo = z[zo_inds].get_scaled_positions() poszt = z[zt_inds].get_scaled_positions() scaledp = atoms.get_scaled_positions() Dict = {} for a in atoms: pa = scaledp[a.index] sym = a.symbol if sym == 'O': diffp = poszo - pa mags = [] for d in diffp: mags.append(np.linalg.norm(d)) ind = mags.index(min(mags)) ind = zo_inds[ind] label = all_labels[ind] if sym != 'O': diffp = poszt - pa mags = [] for d in diffp: mags.append(np.linalg.norm(d)) ind = mags.index(min(mags)) ind = zt_inds[ind] label = all_labels[ind] Dict[a.index] = label return Dict
def get_tsites(code): from zse.collections import get_tsites z = framework(code) tsites, tmult = get_tsites(code) tinds = [atom.index for atom in z if atom.symbol != 'O'] index = 0 first_ts = [] for i, m in enumerate(tmult): first_ts.append(tinds[index]) index += m return tsites, tmult, first_ts
def get_osites(code): from zse.collections import get_osites z = framework(code) osites, omult = get_osites(code) oinds = [atom.index for atom in z if atom.symbol == 'O'] index = 0 first_os = [] for i, m in enumerate(omult): first_os.append(oinds[index]) index += m return osites, omult, first_os
def label_tsites(atoms, code): z = framework(code) tsites, tmult, first = get_tsites(code) tinds = [atom.index for atom in z if atom.symbol != 'O'] zcell = z.cell.cellpar()[:3] acell = atoms.cell.cellpar()[:3] repeat = [] for zc, ac in zip(zcell, acell): repeat.append(int(round(ac / zc))) z = z.repeat(repeat) tinds = [atom.index for atom in z if atom.symbol != 'O'] rp = np.prod(repeat) Dict = {} j = 0 for i in range(rp): for s, t in enumerate(tsites): for q in range(tmult[s]): Dict[tinds[j]] = t j += 1 return Dict
def label_osites(atoms, code): z = framework(code) osites, omult, first = get_osites(code) zcell = z.get_cell_lengths_and_angles()[:3] acell = atoms.get_cell_lengths_and_angles()[:3] repeat = [] for zc, ac in zip(zcell, acell): repeat.append(int(round(ac / zc))) z = z.repeat(repeat) oinds = [atom.index for atom in z if atom.symbol == 'O'] rp = np.prod(repeat) Dict = {} j = 0 for i in range(rp): for s, t in enumerate(osites): for q in range(omult[s]): Dict[oinds[j]] = t j += 1 return Dict
def get_unique_trings(code, ring_size): z = framework(code) pr = get_fwrings(code) tsites, tmult = get_tsites(code) tinds = [atom.index for atom in z if atom.symbol != 'O'] index = 0 firstts = [] for i, m in enumerate(tmult): firstts.append(tinds[index]) index += m allrings = [] for f in firstts: c, r, ringatoms, repeat = tring_driver(z, f, pr, delete=False) for ring in r: allrings.append(ring) tinds = [atom.index for atom in ringatoms if atom.symbol != 'O'] rp = np.prod(repeat) Dict = {} j = 0 for i in range(rp): for s, t in enumerate(tsites): for q in range(tmult[s]): Dict[tinds[j]] = t j += 1 ring_tsites = [] for ring in allrings: tmp = [] for i in ring: if ringatoms[i].symbol != 'O': tmp.append(Dict[i]) ring_tsites.append(tmp) desired_rings_tsites = [] desired_rings_full = [] for i, r in enumerate(ring_tsites): if len(r) == ring_size: desired_rings_tsites.append(r) desired_rings_full.append(allrings[i]) unique_tsites = [] unique_full = [] d = [] for i in range(len(desired_rings_tsites)): for j in range((i + 1), len(desired_rings_tsites)): if i != j: st1 = ' '.join(map(str, desired_rings_tsites[i])) st2 = ' '.join(map(str, desired_rings_tsites[j])) st2_2 = ' '.join(map(str, reversed(desired_rings_tsites[j]))) # st1 = set(desired_rings_tsites[i]) # st2 = set(desired_rings_tsites[j]) # if st1 == st2: if st2 in st1 + ' ' + st1 or st2_2 in st1 + ' ' + st1: d.append(int(j)) for i in range(len(desired_rings_tsites)): if i not in d: unique_tsites.append(desired_rings_tsites[i]) unique_full.append(desired_rings_full[i]) traj = [] com = ringatoms.get_center_of_mass() for ring in unique_full: keepers = [] atoms = ringatoms.copy() for i in ring: if i not in keepers: keepers.append(i) d = [atom.index for atom in atoms if atom.index not in keepers] del atoms[d] position = atoms[0].position trans = com - position atoms.translate(trans) atoms.wrap() traj += [atoms] return traj, unique_tsites
def get_all_rings(code): ''' For developmental testing only. ''' z = framework(code) pr = get_fwrings(code) tsites, tmult, first = get_tsites(code) tinds = [atom.index for atom in z if atom.symbol != 'O'] index = 0 firstts = [] for i, m in enumerate(tmult): firstts.append(tinds[index]) index += m allrings = [] for f in firstts: c, r, ringatoms, repeat = all_trings(z, f, pr, delete=False) for ring in r: allrings.append(ring) tinds = [atom.index for atom in ringatoms if atom.symbol != 'O'] rp = np.prod(repeat) Dict = {} j = 0 for i in range(rp): for s, t in enumerate(tsites): for q in range(tmult[s]): Dict[tinds[j]] = t j += 1 ring_tsites = [] for ring in allrings: tmp = [] for i in ring: if ringatoms[i].symbol != 'O': tmp.append(Dict[i]) ring_tsites.append(tmp) unique_tsites = {} unique_full = {} for i, r in enumerate(ring_tsites): length = len(r) if length not in unique_tsites: unique_tsites[length] = [r] unique_full[length] = [allrings[i]] else: unique_tsites[length].append(r) unique_full[length].append(allrings[i]) trajectories = {} com = ringatoms.get_center_of_mass() for length in pr: ring_tlist = unique_tsites[length] ring_full = unique_full[length] d = [] for i in range(len(ring_tlist)): for j in range((i + 1), len(ring_tlist)): st1 = ' '.join(map(str, ring_tlist[i])) st2 = ' '.join(map(str, ring_tlist[j])) st2_2 = ' '.join(map(str, reversed(ring_tlist[j]))) if st2 in st1 + ' ' + st1 or st2_2 in st1 + ' ' + st1: d.append(int(j)) tmp1 = [] tmp2 = [] for i in range(len(ring_tlist)): if i not in d: tmp1.append(ring_tlist[i]) tmp2.append(ring_full[i]) unique_tsites[length] = tmp1 unique_full[length] = tmp2 traj = [] for ring in tmp2: keepers = [] atoms = ringatoms.copy() for i in ring: if i not in keepers: keepers.append(i) d = [atom.index for atom in atoms if atom.index not in keepers] del atoms[d] position = atoms[0].position trans = com - position atoms.translate(trans) atoms.wrap() traj += [atoms] trajectories[length] = traj return unique_tsites, unique_full, trajectories
def get_vertex_symbols(code, index): ''' Function to find all the the shortest rings connecting each oxygen-oxygen pair associated with a T-site INPUTS: code: (str) IZA code for the zeolite you are using (i.e. 'CHA') index: (integer) index of the T-site that you want to classify OUTPUTS: vertex_symbols: (dictionary) keys are the O-site labels, and values are the indices of the atoms connecting those oxygens trajectory: (ASE atoms objects) that include the rings for each oxygen-oxygen pair ''' # get the possible rings of this framework from the IZA # the maximum ring size determines how many times to repeat the unit cell ring_sizes = get_ring_sizes(code) * 2 max_ring = max(ring_sizes) # get an atoms object of the framework atoms = framework(code) # repeat the unit cell so it is large enough to capture the max ring size # also turn this new larger unit cell into a graph G, large_atoms, repeat = atoms_to_graph(atoms, index, max_ring) index = [atom.index for atom in large_atoms if atom.tag == index][0] # get the T-site and O-site labels for each atom in the framework atoms = atoms.repeat(repeat) labels = site_labels(atoms, code) # get each o-o pair for the T-site vertices = get_vertices(G, index) # set up a dictionary to stare results vertex_symbols = {} # got through each o-o pair and find the shortest paths traj = [] for i, v in enumerate(vertices): o1 = v[0] o2 = v[1] v_label = '{0}-{1}'.format(labels[large_atoms[o1].tag], labels[large_atoms[o2].tag]) # this finds the shortest path between the two path, l = shortest_valid_path(G, o1, o2, index) # this finds all valid paths of that length between the two paths = [p for p in all_paths(G, o1, o2, index, l)] traj += [paths_to_atoms(large_atoms, paths)] tmp_paths = [] for p in paths: temp = [] for x in p: temp.append(large_atoms[x].tag) tmp_paths.append(temp) vertex_symbols['{0}:{1}'.format( i + 1, v_label)] = [path for path in tmp_paths] return vertex_symbols, traj