Ejemplo n.º 1
0
    def strain(self, atoms=None):
        """Return a fingerprint with the espected strain of the
        site atoms and the termination atoms.

        Parameters
        ----------
        atoms : object
            ASE Atoms object.

        Returns
        ----------
        features : list
            If None was passed, the elements are strings, naming the feature.
        """
        if atoms is None:
            return ['strain_site', 'strain_term']
        else:
            if ('key_value_pairs' in atoms.info and
                    'term' in atoms.info['key_value_pairs']):
                term = atoms.info['key_value_pairs']['term']
                term_numbers = [atomic_numbers[s] for s in
                                string2symbols(term)]
            elif 'termination_atoms' in atoms.subsets:
                term = atoms.subsets['termination_atoms']
                term_numbers = atoms.numbers[term]
            else:
                raise NotImplementedError("strain fingerprint.")
            if ('key_value_pairs' in atoms.info and
                    'bulk' in atoms.info['key_value_pairs']):
                bulk = atoms.info['key_value_pairs']['bulk']
                bulk_numbers = [atomic_numbers[s] for s in
                                string2symbols(bulk)]
            elif 'bulk_atoms' in atoms.subsets:
                bulk = atoms.subsets['bulk_atoms']
                bulk_numbers = atoms.numbers[bulk]
            else:
                raise NotImplementedError("strain fingerprint.")
            site = atoms.subsets['site_atoms']
            site_numbers = atoms.numbers[site]
            rbulk = []
            rterm = []
            rsite = []
            for b in bulk_numbers:
                rbulk.append(get_radius(b))
            for t in term_numbers:
                rterm.append(get_radius(t))
            for z in site_numbers:
                rsite.append(get_radius(z))
            av_term = np.average(rterm)
            av_bulk = np.average(rbulk)
            av_site = np.average(rsite)
            strain_site = (av_site - av_bulk) / av_bulk
            strain_term = (av_term - av_bulk) / av_bulk
            return [strain_site, strain_term]
Ejemplo n.º 2
0
def ase_neighborlist(atoms, cutoffs=None):
    """Make dict of neighboring atoms using ase function.

    This provides a wrapper for the ASE neighborlist generator. Currently
    default values are used.

    Parameters
    ----------
    atoms : object
        Target ase atoms object on which to get neighbor list.
    cutoffs : list
        A list of radii for each atom in atoms.
    rtol : float
        The tolerance factor to allow for small variation in the cutoff radii.

    Returns
    -------
    neighborlist : dict
        A dictionary containing the atom index and each neighbor index.
    """
    if cutoffs is None:
        cutoffs = [get_radius(a.number) for a in atoms]
    nl = NeighborList(cutoffs,
                      skin=0.,
                      sorted=False,
                      self_interaction=False,
                      bothways=True)

    nl.update(atoms)

    neighborlist = {}
    for i, _ in enumerate(atoms):
        neighborlist[i] = sorted(list(map(int, nl.get_neighbors(i)[0])))

    return neighborlist
Ejemplo n.º 3
0
 def setup_metal(self):
     """Get the atoms objects."""
     symbols = ['Ag', 'Au', 'Cu', 'Pt', 'Pd', 'Ir', 'Rh', 'Ni', 'Co']
     images = []
     for s in symbols:
         rs = get_radius(atomic_numbers[s])
         a = 2 * rs * 2**0.5
         atoms = bulk(s, crystalstructure='bcc', a=a)
         images.append(atoms)
     return images
Ejemplo n.º 4
0
def auto_layers(atoms, miller=(0, 0, 1)):
    """Returns two arrays describing which layer each atom belongs
    to and the distance between the layers and origo.
    Assumes the tolerance corresponds to the average atomic radii of the slab.

    Parameters
    ----------
    atoms : object
        The atoms object must have the following keys in atoms.subsets:

        'slab_atoms' : list
            indices of atoms belonging to the slab
    """
    radii = [get_radius(z) for z in atoms.numbers[atoms.subsets['slab_atoms']]]
    radius = np.average(radii) / 2.
    li, lz = get_layers(atoms, miller=miller, tolerance=radius)
    return li, lz
Ejemplo n.º 5
0
 def setup_metals(self, n=None):
     """Get the atoms objects."""
     adsorbates = ['H', 'O', 'C', 'N', 'S', 'Cl', 'P', 'F']
     symbols = ['Ag', 'Au', 'Cu', 'Pt', 'Pd', 'Ir', 'Rh', 'Ni', 'Co']
     if n is not None:
         symbols = symbols[:n]
         adsorbates = adsorbates[:n]
     images = []
     for i, s in enumerate(symbols):
         rs = get_radius(atomic_numbers[s])
         a = 2 * rs * 2**0.5
         for ads in adsorbates:
             atoms = fcc111(s, (2, 2, 3), a=a)
             atoms.center(vacuum=6, axis=2)
             h = (default_catlearn_radius(atomic_numbers[ads]) +
                  rs) / 2**0.5
             add_adsorbate(atoms, ads, h, 'bridge')
             images.append(atoms)
     return images
Ejemplo n.º 6
0
def catlearn_neighborlist(atoms, dx=None, max_neighbor=1, mic=True):
    """Make dict of neighboring atoms for discrete system.

    Possible to return neighbors from defined neighbor shell e.g. 1st, 2nd,
    3rd by changing the neighbor number.

    Parameters
    ----------
    atoms : object
        Target ase atoms object on which to get neighbor list.
    dx : dict
        Buffer to calculate nearest neighbor pairs in dict format:
        dx = {atomic_number: buffer}.
    max_neighbor : int or str
        Maximum neighbor shell. If int is passed this will define how many
        shells to consider. If 'full' is passed then all neighbor combinations
        will be included. This might get expensive for particularly large
        systems.

    Returns
    -------
    connection_matrix : array
        An array of the neighbor shell each atom index is located in.
    """
    atomic_numbers = atoms.get_atomic_numbers()

    # Set up buffer dict.
    if dx is None:
        dx = dict.fromkeys(set(atomic_numbers), 0)
        for i in dx:
            dx[i] = get_radius(i) / 5.

    dist = atoms.get_all_distances(mic=mic)

    r_list, b_list = [], []
    for an in atomic_numbers:
        r_list.append(get_radius(an))
        b_list.append(dx[an])

    radius_matrix = np.asarray(r_list) + np.reshape(r_list, (len(r_list), 1))
    buffer_matrix = np.asarray(b_list) + np.reshape(b_list,
                                                    (len(b_list), 1)) / 2.

    connection_matrix = np.zeros((len(atoms), len(atoms)))
    if isinstance(max_neighbor, int):
        for n in range(max_neighbor):
            dist, connection_matrix, unconnected = _neighbor_iterator(
                dist, radius_matrix, buffer_matrix, n, connection_matrix)
    elif max_neighbor == 'full':
        n, unconnected = 0, 1
        while unconnected > 0:
            dist, connection_matrix, unconnected = _neighbor_iterator(
                dist, radius_matrix, buffer_matrix, n, connection_matrix)
            n += 1
    else:
        msg = 'max_neighbor parameter {} not recognized.'.format(max_neighbor)
        raise NotImplementedError(msg)

    np.fill_diagonal(connection_matrix, 0.)

    return connection_matrix