예제 #1
0
def layer(structure, direction, tolerance=1e-12):
  """ Iterates over layers and atoms in a layer. 

      :param structure: 
          :class:`Structure` for which to iterator over atoms.
      :param direction:
          3d-vector defining the growth direction, e.g. vector perpendicular to
          the layers.  Defaults to the first column vector of the structure.
          It is important that two cell-vectors of the structure are (or can be
          transformed to be) perpendicular to the growth direction. Otherwise
          it cannot be assured that layers are well defined, i.e. that each
          atom belongs to a single (as in periodic) layer. This condition is
          *not* enforced (no assertion) since it is not necessary, only
          sufficient.  Note that the third vector need not be parallel to the
          growth direction.
      :param tolerance: 
          Maximum difference between two atoms in the same layer.

      :returns: Yields iterators over atoms in a single epitaxial layer.
  """
  from operator import itemgetter
  from numpy import array, dot
  from . import into_cell, into_voronoi

  direction = array(direction)
  if len(structure) <= 1: yield list(structure); return

  # orders position with respect to direction.
  positions = array([into_cell(atom.pos, structure.cell) for atom in structure])
  projs = [(i, dot(pos, direction)) for i, pos in enumerate(positions)]
  projs = sorted(projs, key=itemgetter(1))

  # creates classes of positions.
  result = [[projs[0]]]
  for i, proj in projs[1:]:
    if abs(proj - result[-1][-1][-1]) < tolerance: result[-1].append((i,proj))
    else: result.append([(i,proj)])

  # only one layer.
  if len(result) == 1: yield structure; return
  # Finds if first and last have atoms in common through periodicity
  first, last = result[0], result[-1]
  centered                                                                     \
    = into_voronoi( positions[[i for i, d in last]] - positions[first[0][0]],
                    structure.cell )
  for j, pos in enumerate(centered[::-1]):
    a0 = dot(pos, direction)
    if any(abs(u[1]-a0) >= tolerance for u in first): continue
    first.append( last.pop(len(centered)-j-1) )

  # last layer got depleted.
  if len(last) == 0: result.pop(-1) 
  # only one layer.
  if len(result) == 1: yield structure; return
  # yield layer iterators.
  for layer in result:
    def inner_layer_iterator():
      """ Iterates over atoms in a single layer. """
      for index, norm in layer: yield structure[index]
    yield inner_layer_iterator ()
예제 #2
0
def shell(structure, center, direction, thickness=0.05):
    """ Iterates over cylindrical shells of atoms.

        It allows to rapidly create core-shell nanowires.

        :param structure:
            :class:`Structure` over which to iterate.

        :param center:
            3d-vector defining the growth direction of the nanowire.

        :param thickness:
            Thickness in units of ``structure.scale`` of an individual shell.

        :returns:
            Yields iterators over atoms in a single shell.
    """
    from operator import itemgetter
    from numpy import array, dot
    from numpy.linalg import norm
    from operator import into_voronoi

    direction = array(direction) / norm(array(direction))
    if len(structure) <= 1:
        yield structure
        return

    # orders position with respect to cylindrical coordinates
    positions = array([atom.pos - center for atom in structure])
    positions = into_voronoi(positions, structure.cell)
    projs = [(i, norm(pos - dot(pos, direction) * direction))
             for i, pos in enumerate(positions)]
    projs = sorted(projs, key=itemgetter(1))

    # creates classes of positions.
    result = {}
    for i, r in projs:
        index = int(r / thickness + 1e-12)
        if index in result:
            result[index].append(i)
        else:
            result[index] = [i]

    for key, layer in sorted(result.items(), key=itemgetter(0)):

        def inner_layer_iterator():
            """ Iterates over atoms in a single layer. """
            for index in layer:
                yield structure[index]

        yield inner_layer_iterator()
예제 #3
0
def shell(structure, center, direction, thickness=0.05):
    """ Iterates over cylindrical shells of atoms.

        It allows to rapidly create core-shell nanowires.

        :param structure:
            :class:`Structure` over which to iterate.

        :param center:
            3d-vector defining the growth direction of the nanowire.

        :param thickness:
            Thickness in units of ``structure.scale`` of an individual shell.

        :returns:
            Yields iterators over atoms in a single shell.
    """
    from operator import itemgetter
    from numpy import array, dot
    from numpy.linalg import norm
    from operator import into_voronoi

    direction = array(direction) / norm(array(direction))
    if len(structure) <= 1:
        yield structure
        return

    # orders position with respect to cylindrical coordinates
    positions = array([atom.pos - center for atom in structure])
    positions = into_voronoi(positions, structure.cell)
    projs = [(i, norm(pos - dot(pos, direction) * direction))
             for i, pos in enumerate(positions)]
    projs = sorted(projs, key=itemgetter(1))

    # creates classes of positions.
    result = {}
    for i, r in projs:
        index = int(r / thickness + 1e-12)
        if index in result:
            result[index].append(i)
        else:
            result[index] = [i]

    for key, layer in sorted(result.items(), key=itemgetter(0)):
        def inner_layer_iterator():
            """ Iterates over atoms in a single layer. """
            for index in layer:
                yield structure[index]
        yield inner_layer_iterator()