Exemplo n.º 1
0
def get_geometry(atoms, index, code):
    from ase.geometry import get_distances
    from collections import defaultdict
    #get possible rings, and max rings size
    ring_sizes = get_ring_sizes(code) * 2
    max_ring = max(ring_sizes)

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

    # to find all the rings associated with a T site, we need all the rings
    # associated with each oxygen bound to that T site. We will use networkx
    # neighbors to find those oxygens
    atoms = atoms.repeat(repeat)
    import networkx as nx
    com_dists = defaultdict(list)
    for n in nx.neighbors(G, index):
        c, paths, a = get_orings(large_atoms, n, code, validation='sastre')

        atoms, trans = center(atoms, large_atoms[n].tag)
        for p in paths:
            l = int(len(p) / 2)
            ring_atoms = atoms[p]
            rp = ring_atoms.get_positions()
            com = rp.mean(axis=0)
            positions = atoms.get_positions()
            distances = get_distances(com, positions)[1][0]
            for i, d in enumerate(distances):
                if i not in p:
                    com_dists[l].append(d)
    return com_dists
Exemplo n.º 2
0
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
Exemplo n.º 3
0
Arquivo: rings.py Projeto: cwaitt/zse
def get_trings(atoms, index, code):
    '''
    Function to find all the rings asssociated with a T-site in a zeolite
    framework.

    INPUTS:
    atoms:      (ASE atoms object) the zeolite framework to be analyzed
                works best if you remove any adsorbates first
    index:      (integer) index of the atom that you want to classify
    code:       (str) IZA code for the zeolite you are using (i.e. 'CHA')

    OUTPUTS:
    ring_list:      (list) The size of rings associated with the oxygen.
    paths:      (2d array) The actual atom indices that compose found rings.
    ring_atoms: (ASE atoms object) all the rings found
    '''
    #get possible rings, and max rings size
    ring_sizes = get_ring_sizes(code) * 2
    max_ring = max(ring_sizes)

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

    # to find all the rings associated with a T site, we need all the rings
    # associated with each oxygen bound to that T site. We will use networkx
    # neighbors to find those oxygens
    import networkx as nx
    paths = []
    for n in nx.neighbors(G, index):
        paths = paths + get_paths(G, n, ring_sizes)

    # now we want to remove all the non ring paths
    paths = remove_non_rings(large_atoms, paths)

    # finally organize all outputs: list of ring sizes, atom indices that make
    # ring paths, and an atoms object that shows all those rings
    ring_list = [int(len(p) / 2) for p in paths]
    paths = [x for _, x in sorted(zip(ring_list, paths), reverse=True)]
    ring_list.sort(reverse=True)

    ring_atoms = paths_to_atoms(large_atoms, paths)

    return ring_list, paths, ring_atoms
Exemplo n.º 4
0
def monovalent(atoms,
               index,
               symbol,
               code,
               included_rings=None,
               path=None,
               bvect=None):
    '''
    This code has been updated to place the ion inside each of the rings
    associated with the T site. The rings are found using the rings module of
    ZSE.

    INPUTS:
    atoms = ASE atoms object of the zeolite framework
    index = Index of the t site that the cation will be associated with (int)
    symbol = Elemental symbol of the cation you want to use, i.e. 'Na' (str)
    code = Framework code of the zeolite you are using, i.e. 'CHA' (str)
    included_rings (optional) = List of ints for rings you want to include
                                if not specified all rings larger than 4-MR will
                                be inlcuded.
    path (optional) = Path for which you would like the structure files saved.
                      If not included, structure files will not be saved.
    bvect (optional) = Manually specify the bond length between the cation and 
                        atom index

    OUTPUTS:
    traj = ASE trajectory of all the structures generated. You can view traj
           with ase.visualize.view.
    locations = List of all the rings that the ion was placed in. Correlates to
                the images in the trajectory.
    '''

    # let's import the modules we will need to make this work
    from zse.collections import get_ring_sizes
    import networkx as nx
    from ase.data import covalent_radii, chemical_symbols

    # I will use these radii to approximate bond lengths
    radii = {
        chemical_symbols[i]: covalent_radii[i]
        for i in range(len(chemical_symbols))
    }

    # get all the rings associated with the T site
    # this follows the same steps as rings.get_trings()
    ring_sizes = get_ring_sizes(code) * 2
    max_ring = max(ring_sizes)
    G, large_atoms, repeat = atoms_to_graph(atoms, index, max_ring)
    import networkx as nx
    paths = []
    for n in nx.neighbors(G, index):
        paths = paths + get_paths(G, n, ring_sizes)
    paths = remove_non_rings(large_atoms, paths)

    # which rings should be included
    if included_rings == None:
        included_rings = []
        for p in ring_sizes:
            if p > 8:
                included_rings.append(p)
    else:
        included_rings = [x * 2 for x in included_rings]

    # get a list of all the rings and their sizes present
    Class, class_count, paths = count_rings(paths)

    # add the cation to each ring, put structure in a trajectory
    traj, locations = add_cation(atoms, large_atoms, radii, index, symbol,
                                 paths, included_rings, class_count, path,
                                 bvect)

    return traj, locations
Exemplo n.º 5
0
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
Exemplo n.º 6
0
def get_trings(atoms, index, code, validation='cross_distance', cutoff=3.15):
    '''
    Function to find all the rings asssociated with a T-site in a zeolite
    framework.

    INPUTS:
    atoms:      (ASE atoms object) the zeolite framework to be analyzed
                works best if you remove any adsorbates first
    index:      (integer) index of the atom that you want to classify
    code:       (str) IZA code for the zeolite you are using (i.e. 'CHA')
    validation: (str) Method in which to determin valid rings.
                cross_distance: uses cross ring Si-Si distances
                d2:             ensures each ring can't be decomposed into two
                                smaller rings
                sphere:         Checks that no non ring atoms are within some
                                cutoff radius of the center of mass of the
                                ring.
                                Cutoff input is required for this method
                sp:             Custum shortest path method, not very reliable
    cutoff:     (float) Value required for the sphere validation method

    OUTPUTS:
    ring_list:      (list) The size of rings associated with the oxygen.
    paths:      (2d array) The actual atom indices that compose found rings.
    ring_atoms: (ASE atoms object) all the rings found
    '''
    #get possible rings, and max rings size
    ring_sizes = get_ring_sizes(code) * 2
    max_ring = max(ring_sizes)

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

    # to find all the rings associated with a T site, we need all the rings
    # associated with each oxygen bound to that T site. We will use networkx
    # neighbors to find those oxygens
    import networkx as nx
    paths = []
    for n in nx.neighbors(G, index):
        paths = paths + get_paths(G, n, ring_sizes)

    # Since we found the rings for each oxygen attached to the T-site,
    # there will be duplicate rings. Let's remove those.
    paths = remove_dups(paths)

    # now we want to remove all the non ring paths, the method for determining
    # valid rings is designated with the validation input variable.
    if validation == 'sp':
        paths = sp(G, paths)
    if validation == 'd2':
        paths = d2(G, paths)
    if validation == 'sphere':
        if cutoff == None:
            print(
                'INPUT ERROR: Validation with geometry requires cutoff in Å, however, cutoff not set.'
            )
            return
        paths = sphere(large_atoms, paths, cutoff)
    if validation == 'cross_distance':
        paths = cross_distance(large_atoms, paths)

    # finally organize all outputs: list of ring sizes, atom indices that make
    # ring paths, and an atoms object that shows all those rings
    ring_list = [int(len(p) / 2) for p in paths]
    paths2 = [x for _, x in sorted(zip(ring_list, paths), reverse=True)]
    tmp_paths = [x for _, x in sorted(zip(ring_list, paths), reverse=True)]
    paths = []
    for p in tmp_paths:
        temp = []
        for i in p:
            temp.append(large_atoms[i].tag)
        paths.append(temp)
    ring_list.sort(reverse=True)

    ring_atoms = paths_to_atoms(large_atoms, paths2)

    return ring_list, paths, ring_atoms