Example #1
0
def test_coordination_shells():
    from random import random
    from numpy import array
    from numpy.random import randint, random
    from pylada.crystal import supercell, Structure

    lattice = Structure([[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) \
        .add_atom(0, 0, 0, "Si")                                      \
        .add_atom(0.25, 0.25, 0.25, "Ge")
    for atom in lattice:
        check(lattice, atom)

    structure = supercell(lattice, [[1, 1, 0], [-5, 2, 0], [0, 0, 1]])
    for index in randint(len(structure), size=4):
        check(structure, structure[index])

    for atom in lattice:
        atom.pos += random(3) * 1e-4 - 5e-5
    for atom in lattice:
        check(lattice, atom, 1e-2)

    for atom in structure:
        atom.pos += random(3) * 1e-4 - 5e-5
    for index in randint(len(structure), size=4):
        check(structure, structure[index], 1e-2)

    check_against_neighbors(structure, 1e-8)

    lattice = Structure([[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) \
        .add_atom(0, 0, 0, "Si")
    check_against_neighbors(structure, 1e-8)
    lattice = Structure([[-0.5, 0.5, 0.5], [0.5, -0.5, 0.5], [0.5, 0.5, -0.5]]) \
        .add_atom(0, 0, 0, "Si")
    check_against_neighbors(structure, 1e-8)
Example #2
0
def mix_atoms(s1, s2, roll=True):
  """ Randomly mix cell and atoms from parents.

      Mating operation on two parent structures s1 and s2.
      Done by mixing randomly atoms from s1 and s2 into the 
      cell coming from one of them. Returns two offspring 
      structures.
  """
  from random import choice
  from itertools import chain
  from numpy.linalg import det
  from numpy import dot, abs
  from ..crystal import Structure

  # swap structures randomly.
  if choice([True, False]): s1, s2 = s2, s1

  # chem. symbols and scaled positions of the two parents
  sc_pos1 = zip([atom.type for atom in s1], fractional_pos(s1, roll))
  sc_pos2 = zip([atom.type for atom in s2], fractional_pos(s2, roll))

  result = Structure(s1.cell)

  for pos, type in chain(sc_pos1, sc_pos2):
    if choice([True, False]):
      result.add_atom(*dot(result.cell, pot), type=type)

  result.scale =  s1.scale * (float(len(result)) / float(len(s1)))**(1./3.)

  return result
Example #3
0
def str_template(name, scale, cell):
  from pylada.crystal import Structure
  structure = Structure()
  structure.name   = name
  structure.scale  = scale
  structure.cell = cell
  return structure
Example #4
0
def test_system():
    from pylada.crystal import Structure
    from pylada.vasp import Vasp
    a = Vasp()
    b = Structure()

    assert a.system is None
    assert a._input['system'].keyword == 'system'
    assert a._input['system'].output_map(vasp=a, structure=b) is None

    a.system = 'system'
    assert a.system == 'system'
    assert 'system' in a._input['system'].output_map(vasp=a, structure=b)
    assert a._input['system'].output_map(vasp=a,
                                         structure=b)['system'] == 'system'

    b.name = 'hello'
    assert 'system' in a._input['system'].output_map(vasp=a, structure=b)
    assert a._input['system'].output_map(
        vasp=a, structure=b)['system'] == 'system: hello'

    a.system = None
    assert a.system is None
    assert 'system' in a._input['system'].output_map(vasp=a, structure=b)
    assert a._input['system'].output_map(vasp=a,
                                         structure=b)['system'] == 'hello'

    a.system = None
    assert a.system is None
    assert 'system' in a._input['system'].output_map(vasp=a, structure=b)
    assert a._input['system'].output_map(vasp=a,
                                         structure=b)['system'] == 'hello'
Example #5
0
def test_ewald():
    """ Ewald Rydberg test """
    from numpy import all, abs, sqrt
    from pylada.crystal import Structure
    from pylada.ewald import ewald
    from quantities import angstrom, a0, Ry

    structure = Structure([[1, 0, 0],
                           [0, 1, 0],
                           [0, 0, 1] ], scale=50 )             \
        .add_atom(0, 0, 0, 'A', charge=1e0)                     \
        .add_atom(float(a0.rescale(angstrom) / 50.0), 0, 0, 'A', charge=-1e0)

    result = ewald(structure, cutoff=80)
    assert abs(result.energy + 2e0 * Ry) < 1e-3
    assert all(abs(abs(result[0].force) - [2e0, 0, 0] * Ry / a0) < 1e-3)
    assert all(abs(abs(result[1].force) - [2e0, 0, 0] * Ry / a0) < 1e-3)

    a = float(a0.rescale(angstrom) / 50.0) / sqrt(2.)
    structure = Structure([[1, 0, 0],
                           [0, 1, 0],
                           [0, 0, 1] ], scale=50 )              \
        .add_atom(0, 0, 0, 'A', charge=1e0)                     \
        .add_atom(0, a, a, 'A', charge=-1e0)

    result = ewald(structure, cutoff=80)
    assert abs(result.energy + 2e0 * Ry) < 1e-3
    assert all(
        abs(abs(result[0].force) -
            [0, 2. / sqrt(2), 2. / sqrt(2)] * Ry / a0) < 1e-3)
    assert all(
        abs(abs(result[1].force) -
            [0, 2. / sqrt(2), 2. / sqrt(2)] * Ry / a0) < 1e-3)
Example #6
0
def test_system():
    from pylada.crystal import Structure
    from pylada.vasp import Vasp
    a = Vasp()
    b = Structure()

    assert a.system is None
    assert a._input['system'].keyword == 'system'
    assert a._input['system'].output_map(vasp=a, structure=b) is None

    a.system = 'system'
    assert a.system == 'system'
    assert 'system' in a._input['system'].output_map(vasp=a, structure=b)
    assert a._input['system'].output_map(vasp=a, structure=b)['system'] == 'system'

    b.name = 'hello'
    assert 'system' in a._input['system'].output_map(vasp=a, structure=b)
    assert a._input['system'].output_map(vasp=a, structure=b)['system'] == 'system: hello'

    a.system = None
    assert a.system is None
    assert 'system' in a._input['system'].output_map(vasp=a, structure=b)
    assert a._input['system'].output_map(vasp=a, structure=b)['system'] == 'hello'

    a.system = None
    assert a.system is None
    assert 'system' in a._input['system'].output_map(vasp=a, structure=b)
    assert a._input['system'].output_map(vasp=a, structure=b)['system'] == 'hello'
Example #7
0
def icsd_cif_b(filename):
    from os.path import basename
    from numpy import dot, transpose
    from pylada.crystal import Structure, primitive
    from . import readCif

    rdr = readCif.CifReader(0, filename)    # buglevel = 0
    vaspMap = rdr.getVaspMap()
    cellBasis = vaspMap['cellBasis']

    structure = Structure(
        transpose(cellBasis),
        scale=1,
        name=basename(filename))

    usyms = vaspMap['uniqueSyms']
    posVecs = vaspMap['posVecs']

    # multiplicities = num atoms of each type.
    mults = [len(x) for x in posVecs]

    # For each unique type of atom ...
    for ii in range(len(usyms)):
        # For each atom of that type ...
        for jj in range(mults[ii]):
            atpos = dot(transpose(cellBasis), posVecs[ii][jj])
            structure.add_atom(atpos[0], atpos[1], atpos[2], usyms[ii])


    prim = primitive(structure)
    logger.info("  crystal/read: icsd_cif_b: structure: %s" % structure)

    return prim
Example #8
0
def icsd_cif_b(filename):
    from os.path import basename
    from numpy import dot, transpose
    from pylada.crystal import Structure, primitive
    from . import readCif

    rdr = readCif.CifReader(0, filename)    # buglevel = 0
    vaspMap = rdr.getVaspMap()
    cellBasis = vaspMap['cellBasis']

    structure = Structure(
        transpose(cellBasis),
        scale=1,
        name=basename(filename))

    usyms = vaspMap['uniqueSyms']
    posVecs = vaspMap['posVecs']

    # multiplicities = num atoms of each type.
    mults = [len(x) for x in posVecs]

    # For each unique type of atom ...
    for ii in range(len(usyms)):
        # For each atom of that type ...
        for jj in range(mults[ii]):
            atpos = dot(transpose(cellBasis), posVecs[ii][jj])
            structure.add_atom(atpos[0], atpos[1], atpos[2], usyms[ii])


    prim = primitive(structure)
    logger.info("  crystal/read: icsd_cif_b: structure: %s" % structure)

    return prim
Example #9
0
def mix_poscars(s1,s2, roll=True):
  """ Crossover operations where atoms are from one and cell from other.

      Mating operation on two parent structures s1 and s2.
      Done on scaled atomic positions (cubic systems) by
      interchanging their cells and scaled positions.
      Returns two offspring structures each with the same 
      number of atoms as the parent from which the atoms 
      are inhereted.
  """
  from random import choice
  from numpy import dot
  from numpy.linalg import det
  from ..crystal import Structure

  # swap structures randomly.
  if choice([True, False]): s1, s2 = s2, s1

  # chem. symbols and scaled positions of the two parents
  sc_pos2 = zip([atom.type for atom in s2],fractional_pos(s2, roll))

  # cell from s1
  result = Structure(s1.cell, scal=s1.scale)

  # atoms from s2
  for type, pos in sc_pos2:
    result.add_atom(*dot(result.cell, pos), type=type)

  result.scale =  s1.scale * (float(len(result)) / float(len(s1)))**(1./3.)
  return result
Example #10
0
def icsd_cif_b( filename):
  from os.path import basename
  from numpy import dot, transpose
  from pylada.crystal import Structure, primitive
  from pylada.misc import bugLev
  from . import readCif

  rdr = readCif.CifReader( 0, filename)    # buglevel = 0
  vaspMap = rdr.getVaspMap()
  cellBasis = vaspMap['cellBasis']

  structure = Structure(
    transpose( cellBasis),
    scale = 1,
    name = basename( filename))

  usyms = vaspMap['uniqueSyms']
  posVecs = vaspMap['posVecs']

  # multiplicities = num atoms of each type.
  mults = [len(x) for x in posVecs]
  if bugLev >= 5:
    print "    crystal/read: len(usyms): %d  usyms: %s" \
      % (len( usyms), usyms,)
    print "    crystal/read: len(posVecs): %d" % (len(posVecs),)
    print "    crystal/read: len(mults):   %d  mults:   %s" \
      % (len( mults), mults,)

  # For each unique type of atom ...
  for ii in range( len( usyms)):
    if bugLev >= 5:
      print "    crystal/read: icsd_cif_b: ii: ", ii, \
        "  usym: ", usyms[ii], \
        "  mult: ", mults[ii], \
        "  posVecs: ", posVecs[ii]
    # crystal/read: i:  0   symbol:  Mo   len position:  2

    # For each atom of that type ...
    for jj in range( mults[ii]):
      atpos = dot( transpose( cellBasis), posVecs[ii][jj])
      if bugLev >= 5:
        print "      jj: ", jj, "  pos: ", posVecs[ii][jj]
        print "        atpos: ", atpos
      #  j:  0   pos:  [0.3333, 0.6666000000000001, 0.25]
      #  atpos:  [  6.32378655e-16   1.81847148e+00   3.07500000e+00]

      structure.add_atom( atpos[0], atpos[1], atpos[2], usyms[ii])

  if bugLev >= 2:
    print "  crystal/read: icsd_cif_b: structure:\n", structure
  
  prim = primitive( structure)
  if bugLev >= 2:
    print "  crystal/read: icsd_cif_b: primitive structure:\n", prim
  
  return prim
Example #11
0
def pmg_to_pyl(pmg : Structure):
    from pylada.crystal import Structure as Pyl_Structure
    from pylada.crystal import Atom
    pyl = Pyl_Structure(np.transpose(pmg.lattice.matrix))
    for i in range(len(pmg)):
        if pmg.site_properties:
            kwargs = {x: pmg.site_properties[x][i] for x in pmg.site_properties}
        else:
            kwargs = {}
        coords = pmg[i].coords
        specie = str(pmg[i].specie)
        pyl_atom = Atom(coords[0], coords[1], coords[2], specie, **kwargs)
        pyl.add_atom(pyl_atom)
    return pyl
Example #12
0
def test_ediff():
    from pickle import loads, dumps
    from pylada.crystal import Structure, supercell
    from pylada.vasp.incar._params import Ediff, Ediffg

    structure = Structure([[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]])\
        .add_atom(0, 0, 0, 'Si')\
        .add_atom(0.25, 0.25, 0.25, 'Si')
    assert Ediff(None).incar_string(structure=structure) is None
    a = loads(dumps(Ediff(1e-4))).incar_string(structure=structure).split()
    assert a[0] == 'EDIFF' and a[1] == '=' and abs(float(a[2]) - 1e-4 * 2.) < 1e-8
    a = loads(dumps(Ediff(-1e-4))).incar_string(structure=structure).split()
    assert a[0] == 'EDIFF' and a[1] == '=' and abs(float(a[2]) - 1e-4) < 1e-8 and float(a[2]) > 0e0

    assert Ediffg(None).incar_string(structure=structure) is None
    a = loads(dumps(Ediffg(1e-4))).incar_string(structure=structure).split()
    assert a[0] == 'EDIFFG' and a[1] == '=' and abs(float(a[2]) - 1e-4 * 2.) < 1e-8
    a = loads(dumps(Ediffg(-1e-4))).incar_string(structure=structure).split()
    assert a[0] == 'EDIFFG' and a[1] == '=' and abs(float(a[2]) + 1e-4) < 1e-8

    structure = supercell(structure, [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
    a = loads(dumps(Ediff(1e-4))).incar_string(structure=structure).split()
    assert a[0] == 'EDIFF' and a[1] == '=' and abs(float(a[2]) - 1e-4 * 8.) < 1e-8
    a = loads(dumps(Ediff(-1e-4))).incar_string(structure=structure).split()
    assert a[0] == 'EDIFF' and a[1] == '=' and abs(float(a[2]) - 1e-4) < 1e-8 and float(a[2]) > 0e0

    a = loads(dumps(Ediffg(1e-4))).incar_string(structure=structure).split()
    assert a[0] == 'EDIFFG' and a[1] == '=' and abs(float(a[2]) - 1e-4 * 8.) < 1e-8
    a = loads(dumps(Ediffg(-1e-4))).incar_string(structure=structure).split()
    assert a[0] == 'EDIFFG' and a[1] == '=' and abs(float(a[2]) + 1e-4) < 1e-8
Example #13
0
def test_encut(EncutClass):
    from pickle import loads, dumps
    from collections import namedtuple
    from pylada.crystal import Structure, supercell
    from quantities import eV, hartree

    Vasp = namedtuple('Vasp', ['species'])
    Specie = namedtuple('Specie', ['enmax'])
    vasp = Vasp({'Si': Specie(1. * eV), 'Ge': Specie(10.), 'C': Specie(100. * eV)})
    name = EncutClass.__name__.upper()

    structure = Structure([[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]])\
        .add_atom(0, 0, 0, 'Si')\
        .add_atom(0.25, 0.25, 0.25, 'Ge')
    assert EncutClass(None).incar_string(vasp=vasp, structure=structure) is None
    a = loads(dumps(EncutClass(50))).incar_string(vasp=vasp, structure=structure).split()
    assert a[0] == name and a[1] == '=' and abs(float(a[2]) - 50) < 1e-8
    a = loads(dumps(EncutClass(1.0))).incar_string(vasp=vasp, structure=structure).split()
    assert a[0] == name and a[1] == '=' and abs(float(a[2]) - 10.) < 1e-8
    structure[0].type = 'C'
    a = loads(dumps(EncutClass(2.0))).incar_string(vasp=vasp, structure=structure).split()
    assert a[0] == name and a[1] == '=' and abs(float(a[2]) - 2. * 100.) < 1e-8
    a = loads(dumps(EncutClass(50. * eV))).incar_string(vasp=vasp, structure=structure).split()
    assert a[0] == name and a[1] == '=' and abs(float(a[2]) - 50.) < 1e-8
    a = loads(dumps(EncutClass((50. * eV).rescale(hartree)))
              ).incar_string(vasp=vasp, structure=structure).split()
    assert a[0] == name and a[1] == '=' and abs(float(a[2]) - 50.) < 1e-8
    assert EncutClass(-50).incar_string(vasp=vasp, structure=structure) is None
    assert EncutClass(-50 * eV).incar_string(vasp=vasp, structure=structure) is None
Example #14
0
def test_primitive(cell):
    """ Tests whether primitivization works. """
    from numpy import abs, dot
    from numpy.linalg import inv
    from pylada.crystal import supercell, Structure, are_periodic_images as api, primitive, \
        is_primitive

    lattice = Structure(0.0, 0.5, 0.5,
                        0.5, 0.0, 0.5,
                        0.5, 0.5, 0.0, scale=2.0, m=True ) \
        .add_atom(0, 0, 0, "As")                           \
        .add_atom(0.25, 0.25, 0.25, ['In', 'Ga'], m=True)

    structure = supercell(lattice, dot(lattice.cell, cell))
    assert not is_primitive(structure)
    structure = primitive(structure, 1e-8)
    assert is_primitive(structure)
    assert abs(structure.volume - lattice.volume) < 1e-8
    assert len(structure) == len(lattice)
    assert is_integer(dot(structure.cell, inv(lattice.cell)))
    assert is_integer(dot(lattice.cell, inv(structure.cell)))
    invcell = inv(lattice.cell)
    for atom in structure:
        assert api(lattice[atom.site].pos, atom.pos, invcell)
        assert atom.type == lattice[atom.site].type
        assert getattr(lattice[atom.site], 'm',
                       False) == getattr(atom, 'm', False)
        assert (getattr(atom, 'm', False) or atom.site == 0)
Example #15
0
def test(path):
  from shutil import rmtree
  from tempfile import mkdtemp
  from pylada.crystal import Structure
  from pylada.vasp import Vasp
  from epirelax import epitaxial
  from pylada import default_comm

  structure = Structure([[0, 0.5, 0.5],[0.5, 0, 0.5], [0.5, 0.5, 0]], scale=5.55, name='has a name')\
                       .add_atom(0,0,0, "Si")\
                       .add_atom(0.25,0.25,0.25, "Si")

  vasp = Vasp()
  vasp.kpoints    = "Automatic generation\n0\nMonkhorst\n2 2 2\n0 0 0"
  vasp.prec       = "accurate"
  vasp.ediff      = 1e-5
  vasp.encut      = 1.4
  vasp.ismear     = "fermi"
  vasp.sigma      = 0.01
  vasp.relaxation = "volume"
  vasp.add_specie = "Si", "{0}/pseudos/Si".format(path)
  directory = mkdtemp()
  try: 
    result = epitaxial(vasp, structure, outdir=directory, epiconv=1e-4, comm=default_comm)
    assert result.success
  finally: 
    rmtree(directory)
    pass
Example #16
0
    def __init__(self, vasp, dft, gw, outdir="nlep_fit", comm=None, units=None):
        from os import makedirs
        from os.path import exists
        from shutil import rmtree
        from boost.mpi import world
        from pylada.crystal import Structure

        self.gw = gw
        self.dft = dft
        self.gw.comm = comm
        self.dft.comm = comm
        # since comm has changed, makes sure there are no issues with caching
        self.gw.uncache()
        self.dft.uncache()

        self.vasp = vasp
        self.system = Structure(dft.structure)
        self._nbcalls = 0
        self.outdir = outdir
        self.comm = comm if comm != None else world
        self.units = units if units != None else 1e0

        self.use_syscall = True

        if self.comm.rank == 0 and exists(self.outdir):
            rmtree(self.outdir)
            makedirs(self.outdir)
        self.comm.barrier()
Example #17
0
def s28():
    """ s28 lattice """
    from pylada.crystal import Structure
    return Structure( 7.342, -3.671, 0,\
                      0, 6.35836, 0,\
                      0, 0, 7.218,\
                      scale=1, name='s28' )\
             .add_atom(1.55419, 2.47041, 1.8045, 'A')\
             .add_atom(4.42546, 0.110763, 1.8045, 'A')\
             .add_atom(5.03334, 3.77718, 1.8045, 'A')\
             .add_atom(1.36234, 2.58118, 5.4135, 'A')\
             .add_atom(-2.11681, 3.88795, 5.4135, 'A')\
             .add_atom(0.754464, 6.2476, 5.4135, 'A')\
             .add_atom(-3.671e-08, 4.23891, 0.241153, 'B')\
             .add_atom(-3.671e-08, 4.23891, 3.36785, 'B')\
             .add_atom(3.671, 2.11945, 3.85015, 'B')\
             .add_atom(3.671, 2.11945, 6.97685, 'B')\
             .add_atom(0, 0, 1.8045, 'B')\
             .add_atom(0, 0, 5.4135, 'B')\
             .add_atom(2.67983, 4.6416, 0, 'X')\
             .add_atom(1.98234, 0, 0, 'X')\
             .add_atom(-0.99117, 1.71676, 0, 'X')\
             .add_atom(2.67983, 4.6416, 3.609, 'X')\
             .add_atom(1.98234, 0, 3.609, 'X')\
             .add_atom(-0.99117, 1.71676, 3.609, 'X')
Example #18
0
def s18():
    """ s18 lattice """
    from pylada.crystal import Structure
    return Structure( 9.296, -4.648, 0,\
                      0, 8.05057, 0,\
                      0, 0, 7.346,\
                      scale=1.1, name='s18' )\
             .add_atom(4.648, 5.24897, 4.99528, 'A')\
             .add_atom(2.42626, 1.4008, 4.99528, 'A')\
             .add_atom(6.86974, 1.4008, 4.99528, 'A')\
             .add_atom(0, 2.8016, 1.32228, 'A')\
             .add_atom(2.22174, 6.64977, 1.32228, 'A')\
             .add_atom(-2.22174, 6.64977, 1.32228, 'A')\
             .add_atom(4.64846, 2.68326, 2.29195, 'A')\
             .add_atom(-0.0004648, 5.36732, 5.96495, 'A')\
             .add_atom(0, 7.76075, 3.673, 'B')\
             .add_atom(-2.07301, 4.1702, 3.673, 'B')\
             .add_atom(2.07301, 4.1702, 3.673, 'B')\
             .add_atom(4.648, 0.289821, 0, 'B')\
             .add_atom(6.72101, 3.88038, 0, 'B')\
             .add_atom(2.57499, 3.88038, 0, 'B')\
             .add_atom(0, 0, 3.673, 'B')\
             .add_atom(0, 0, 0, 'B')\
             .add_atom(4.648, 5.31338, 1.89527, 'X')\
             .add_atom(2.37048, 1.3686, 1.89527, 'X')\
             .add_atom(6.92552, 1.3686, 1.89527, 'X')\
             .add_atom(0, 2.73719, 5.56827, 'X')\
             .add_atom(2.27752, 6.68197, 5.56827, 'X')\
             .add_atom(-2.27752, 6.68197, 5.56827, 'X')\
             .add_atom(4.64846, 2.68326, 5.28177, 'X')\
             .add_atom(-0.0004648, 5.36732, 1.60877, 'X')
Example #19
0
def test_b5(u):
    """ Test b5 space-group and equivalents """
    from numpy import dot
    from numpy.random import randint
    from pylada.crystal import Structure, which_site

    x, y = u, 0.25 - u
    lattice = Structure([[0,0.5,0.5],[0.5,0,0.5],[0.5,0.5,0]]) \
                       .add_atom(5.000000e-01, 5.000000e-01, 5.000000e-01, "A") \
                       .add_atom(5.000000e-01, 2.500000e-01, 2.500000e-01, "A") \
                       .add_atom(2.500000e-01, 5.000000e-01, 2.500000e-01, "A") \
                       .add_atom(2.500000e-01, 2.500000e-01, 5.000000e-01, "A") \
                       .add_atom(8.750000e-01, 8.750000e-01, 8.750000e-01, "B") \
                       .add_atom(1.250000e-01, 1.250000e-01, 1.250000e-01, "B") \
                       .add_atom(     x,     x,     x, "X") \
                       .add_atom(     x,     y,     y, "X") \
                       .add_atom(     y,     x,     y, "X") \
                       .add_atom(     y,     y,     x, "X") \
                       .add_atom(    -x,    -x,    -x, "X") \
                       .add_atom(    -x,    -y,    -y, "X") \
                       .add_atom(    -y,    -x,    -y, "X") \
                       .add_atom(    -y,    -y,    -x, "X")
    assert which_site(lattice[6].pos + [0.5, -0.5, 2], lattice) == 6
    for i, atom in enumerate(lattice):
        assert which_site(atom.pos, lattice) == i
        for j in xrange(10):
            newpos = dot(lattice.cell, randint(10, size=(3, )) - 5)
            assert which_site(atom.pos + newpos,
                              lattice) == i, (atom.pos, newpos, i)
Example #20
0
def s26():
    """ s26 lattice """
    from pylada.crystal import Structure
    return Structure( 6.997, 0, 3.4985,\
                      0, 10.83, 5.415,\
                      0, 0, 3.1435,\
                      scale=1.1, name='s26' )\
             .add_atom(5.24775, 8.65967, 1.86347, 'A')\
             .add_atom(8.74625, 13.0003, 1.86347, 'A')\
             .add_atom(5.24775, 13.2202, 1.70189, 'A')\
             .add_atom(8.74625, 8.43982, 1.70189, 'A')\
             .add_atom(8.74625, 5.43774, 2.62671, 'A')\
             .add_atom(5.24775, 5.39226, 2.62671, 'A')\
             .add_atom(3.70491, 6.75359, 0.75444, 'B')\
             .add_atom(3.29209, 4.07641, 0.75444, 'B')\
             .add_atom(6.79059, 6.75359, 0.75444, 'B')\
             .add_atom(7.20341, 4.07641, 0.75444, 'B')\
             .add_atom(3.4985, 10.83, 1.57238, 'B')\
             .add_atom(6.997, 10.83, 1.57238, 'B')\
             .add_atom(7.03898, 14.431, 3.11395, 'X')\
             .add_atom(6.95502, 7.22903, 3.11395, 'X')\
             .add_atom(10.4535, 14.431, 3.11395, 'X')\
             .add_atom(3.54048, 7.22903, 3.11395, 'X')\
             .add_atom(1.74925, 5.689, 0.0345785, 'X')\
             .add_atom(5.24775, 5.141, 0.0345785, 'X')
Example #21
0
def s13():
    """ s13 lattice """
    from pylada.crystal import Structure
    return Structure( 14.462, 7.231, -2.12564,\
                      0, 2.785, 0,\
                      0, 0, 9.23657,\
                      scale=1.1, name='s13' )\
             .add_atom(12.2089, 1.30839, 5.17802, 'A')\
             .add_atom(13.5267, 1.30839, 8.67683, 'A')\
             .add_atom(7.35851, 1.47661, 4.05855, 'A')\
             .add_atom(6.04068, 1.47661, 0.559736, 'A')\
             .add_atom(9.78368, 1.3925, 4.61828, 'A')\
             .add_atom(3.6155, 1.3925, 0, 'A')\
             .add_atom(10.1658, 1.31619, 8.0469, 'B')\
             .add_atom(15.5698, 1.31619, 5.80795, 'B')\
             .add_atom(9.40159, 1.46881, 1.18967, 'B')\
             .add_atom(3.9976, 1.46881, 3.42861, 'B')\
             .add_atom(5.63677, 1.22429, 6.92742, 'B')\
             .add_atom(13.9306, 1.56071, 2.30914, 'B')\
             .add_atom(10.8767, 2.56777, 5.62507, 'X')\
             .add_atom(14.8588, 2.56777, 8.22978, 'X')\
             .add_atom(8.69066, 0.21723, 3.6115, 'X')\
             .add_atom(4.70852, 0.21723, 1.00679, 'X')\
             .add_atom(-1.06282, 0, 4.61828, 'X')\
             .add_atom(0, 0, 0, 'X')
Example #22
0
def s41():
    """ s41 lattice """
    from pylada.crystal import Structure
    return Structure( 5.81, 0, 0,\
                      0, 5.96, 0,\
                      0, 0, 11.71,\
                      scale=1.2, name='s41' )\
             .add_atom(5.03146, 1.79992, 0.74944, 'A')\
             .add_atom(2.12646, 1.18008, 10.9606, 'A')\
             .add_atom(0.77854, 4.77992, 5.10556, 'A')\
             .add_atom(3.68354, 4.16008, 6.60444, 'A')\
             .add_atom(0.77854, 4.16008, 10.9606, 'A')\
             .add_atom(3.68354, 4.77992, 0.74944, 'A')\
             .add_atom(5.03146, 1.18008, 6.60444, 'A')\
             .add_atom(2.12646, 1.79992, 5.10556, 'A')\
             .add_atom(3.59058, 0.298, 3.7472, 'B')\
             .add_atom(0.68558, 2.682, 7.9628, 'B')\
             .add_atom(2.21942, 3.278, 2.1078, 'B')\
             .add_atom(5.12442, 5.662, 9.6022, 'B')\
             .add_atom(2.21942, 5.662, 7.9628, 'B')\
             .add_atom(5.12442, 3.278, 3.7472, 'B')\
             .add_atom(3.59058, 2.682, 9.6022, 'B')\
             .add_atom(0.68558, 0.298, 2.1078, 'B')\
             .add_atom(2.98634, 1.03108, 1.33494, 'X')\
             .add_atom(0.08134, 1.94892, 10.3751, 'X')\
             .add_atom(2.82366, 4.01108, 4.52006, 'X')\
             .add_atom(5.72866, 4.92892, 7.18994, 'X')\
             .add_atom(2.82366, 4.92892, 10.3751, 'X')\
             .add_atom(5.72866, 4.01108, 1.33494, 'X')\
             .add_atom(2.98634, 1.94892, 7.18994, 'X')\
             .add_atom(0.08134, 1.03108, 4.52006, 'X')
Example #23
0
def s29():
    """ s29 lattice """
    from pylada.crystal import Structure
    return Structure( 4.308, 0, 0,\
                      0, 13.912, 0,\
                      0, 0, 7.431,\
                      scale=1.1, name='s29' )\
             .add_atom(3.231, 8.93276, 6.85658, 'A')\
             .add_atom(3.231, 11.9352, 6.85658, 'A')\
             .add_atom(1.077, 4.97924, 0.574416, 'A')\
             .add_atom(1.077, 1.97676, 0.574416, 'A')\
             .add_atom(3.231, 1.32039, 4.32023, 'A')\
             .add_atom(3.231, 5.63561, 4.32023, 'A')\
             .add_atom(1.077, 12.5916, 3.11077, 'A')\
             .add_atom(1.077, 8.27639, 3.11077, 'A')\
             .add_atom(3.231, 6.97603, 1.55828, 'B')\
             .add_atom(3.231, 13.892, 1.55828, 'B')\
             .add_atom(1.077, 6.93597, 5.87272, 'B')\
             .add_atom(1.077, 0.0200333, 5.87272, 'B')\
             .add_atom(3.231, 3.478, 2.16688, 'B')\
             .add_atom(1.077, 10.434, 5.26412, 'B')\
             .add_atom(3.231, 10.434, 2.22484, 'B')\
             .add_atom(1.077, 3.478, 5.20616, 'B')\
             .add_atom(3.231, 8.39728, 4.39321, 'X')\
             .add_atom(3.231, 12.4707, 4.39321, 'X')\
             .add_atom(1.077, 5.51472, 3.03779, 'X')\
             .add_atom(1.077, 1.44128, 3.03779, 'X')\
             .add_atom(3.231, 2.18001, 6.76072, 'X')\
             .add_atom(3.231, 4.77599, 6.76072, 'X')\
             .add_atom(1.077, 11.732, 0.670276, 'X')\
             .add_atom(1.077, 9.13601, 0.670276, 'X')
Example #24
0
def test(path):
    from os import makedirs
    from os.path import exists
    from shutil import rmtree
    from tempfile import mkdtemp
    from pylada.crystal import Structure
    from pylada.vasp import Vasp
    from pylada import default_comm

    structure = Structure([[0, 0.5, 0.5],[0.5, 0, 0.5], [0.5, 0.5, 0]], scale=5.43, name='has a name')\
                         .add_atom(0,0,0, "Si")\
                         .add_atom(0.25,0.25,0.25, "Si")

    vasp = Vasp()
    vasp.kpoints = "Automatic generation\n0\nMonkhorst\n2 2 2\n0 0 0"
    vasp.prec = "accurate"
    vasp.ediff = 1e-5
    vasp.encut = 1
    vasp.ismear = "fermi"
    vasp.sigma = 0.01
    vasp.relaxation = "volume"
    vasp.add_specie = "Si", "{0}/pseudos/Si".format(path)
    directory = mkdtemp()
    if directory == '/tmp/test' or directory == '/tmp/test/':
        if exists(directory): rmtree(directory)
        makedirs(directory)
    try:
        result = vasp(structure, outdir=directory, comm=default_comm)
        assert result.success
    finally:
        if directory != '/tmp/test' and directory != '/tmp/test/':
            rmtree(directory)
Example #25
0
def test(tmpdir, path):
    from numpy import abs
    from pylada.crystal import Structure
    from pylada.vasp import Vasp
    from pylada.vasp.relax import epitaxial
    from pylada import default_comm

    structure = Structure([[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], scale=5.55, name='has a name')\
        .add_atom(0, 0, 0, "Si")\
        .add_atom(0.25, 0.25, 0.25, "Si")

    vasp = Vasp()
    vasp.kpoints = "Automatic generation\n0\nMonkhorst\n2 2 2\n0 0 0"
    vasp.prec = "accurate"
    vasp.ediff = 1e-5
    vasp.encut = 1.4
    vasp.ismear = "fermi"
    vasp.sigma = 0.01
    vasp.relaxation = "volume"
    vasp.add_specie = "Si", "{0}/pseudos/Si".format(path)
    result = epitaxial(vasp,
                       structure,
                       outdir=str(tmpdir),
                       epiconv=1e-5,
                       comm=default_comm)
    assert result.success
    assert abs(result.stress[2, 2]) < 1.0
Example #26
0
def test_nelect():
    from os.path import dirname
    from pickle import loads, dumps
    from pylada.vasp import Vasp
    from pylada.crystal import Structure

    structure = Structure([[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]],
                          scale=5.43, name='has a name')\
        .add_atom(0, 0, 0, "Si")\
        .add_atom(0.25, 0.25, 0.25, "Si")
    a = Vasp()
    a.add_specie = "Si", "{0}/pseudos/Si".format(dirname(__file__))
    assert a.extraelectron is None
    assert a._input['extraelectron'].output_map() is None
    assert a._input['nelect'].output_map() is None
    a.extraelectron = 0
    assert a.extraelectron == 0
    assert a.nelect is None
    assert a._input['extraelectron'].output_map() is None
    assert a._input['nelect'].output_map() is None
    a.extraelectron = 1
    assert a.extraelectron == 1
    assert a.nelect is None
    assert 'nelect' in a._input['extraelectron'].output_map(
        vasp=a, structure=structure)
    assert abs(
        float(a._input['extraelectron'].output_map(vasp=a, structure=structure)
              ['nelect']) - 9.0) < 1e-8
    assert a._input['nelect'].output_map() is None
    a.nelect = 1
    a.extraelectron = -1
    assert a.extraelectron == -1
    assert a.nelect is None
    assert 'nelect' in a._input['extraelectron'].output_map(
        vasp=a, structure=structure)
    assert abs(
        float(a._input['extraelectron'].output_map(vasp=a, structure=structure)
              ['nelect']) - 7.0) < 1e-8
    assert a._input['nelect'].output_map() is None
    o = a._input['extraelectron']
    d = {'ExtraElectron': o.__class__}
    assert repr(eval(repr(o), d)) == repr(o)
    assert abs(
        float(
            eval(repr(o), d).output_map(vasp=a, structure=structure)['nelect'])
        - 7.0) < 1e-8
    assert repr(loads(dumps(o))) == repr(o)

    a.nelect = 8
    assert a.nelect == 8
    assert a.extraelectron is None
    assert 'nelect' in a._input['nelect'].output_map()
    assert abs(float(a._input['nelect'].output_map()['nelect']) - 8.0) < 1e-8
    assert a._input['extraelectron'].output_map() is None
    o = a._input['nelect']
    d = {'NElect': o.__class__}
    assert repr(eval(repr(o), d)) == repr(o)
    assert abs(float(eval(repr(o), d).output_map()['nelect']) - 8.0) < 1e-8
    assert repr(loads(dumps(o))) == repr(o)
Example #27
0
def bcc():
    """ Creates a BCC lattice with a single site. """
    from pylada.crystal import Structure
    return Structure(-0.5, 0.5, 0.5,
                     0.5, -0.5, 0.5,
                     0.5, 0.5, -0.5,
                     scale=1, name='bcc' )\
        .add_atom(0, 0, 0, 'A')
Example #28
0
def fcc():
  """ Creates an FCC lattice with a single site. """
  from pylada.crystal import Structure
  return Structure( 0, 0.5, 0.5,\
                    0.5, 0, 0.5,\
                    0.5, 0.5, 0,\
                    scale=1, name='fcc' )\
           .add_atom(0, 0, 0, 'A')
Example #29
0
def test(path):
  from shutil import rmtree
  from tempfile import mkdtemp
  from os.path import join
  from quantities import eV
  from pylada.vasp import Vasp, read_incar
  from pylada.crystal import Structure
  structure = Structure([[0, 0.5, 0.5],[0.5, 0, 0.5], [0.5, 0.5, 0]], scale=5.43, name='has a name')\
                       .add_atom(0,0,0, "Si")\
                       .add_atom(0.25,0.25,0.25, "Si")

  vasp = Vasp()
  vasp.kpoints    = "Automatic generation\n0\nMonkhorst\n2 2 2\n0 0 0"
  vasp.precision  = "accurate"
  vasp.ediff      = 1e-5
  vasp.encut      = 1
  vasp.ismear     = "metal"
  vasp.sigma      = 0.06
  vasp.relaxation = "volume"
  vasp.add_specie = "Si", "{0}/pseudos/Si".format(path)

  directory = mkdtemp()
  try: 
    vasp.write_incar(path=join(directory, 'INCAR'), structure=structure)
    other = read_incar(join(directory, 'INCAR'))
    assert abs(other.ediff - 1e-5)  < 1e-8
    assert abs(other.encut - 245.345) < 1e-8
    assert abs(other.sigma - 0.06 * eV) < 1e-8
    assert other.ibrion     == 2
    assert other.icharg     == 'atomic'
    assert other.isif       == 7
    assert other.ismear     == 'metal'
    assert other.istart     == 'scratch'
    assert other.lcharg     == False
    assert other.nsw        == 50
    assert other.relaxation == 'volume'
    assert other.system     == 'has a name'
    with open(join(directory, 'INCAR'), 'a') as file:
      file.write('\nSOMETHing = 0.5\n')
    other = read_incar(join(directory, 'INCAR'))
    assert abs(other.ediff - 1e-5)  < 1e-8
    assert abs(other.encut - 245.345) < 1e-8
    assert abs(other.sigma - 0.06 * eV) < 1e-8
    assert other.ibrion     == 2
    assert other.icharg     == 'atomic'
    assert other.isif       == 7
    assert other.ismear     == 'metal'
    assert other.istart     == 'scratch'
    assert other.lcharg     == False
    assert other.nsw        == 50
    assert other.relaxation == 'volume'
    assert other.system     == 'has a name'
    assert 'something' in other._input
    assert isinstance(other.something, float)
    assert abs(other.something - 0.5) < 1e-8
  finally: 
    rmtree(directory)
    pass
Example #30
0
def rock_salt():
    """ rock_salt lattice """
    from pylada.crystal import Structure
    return Structure(1, 0, 0,
                     0, 1, 0,
                     0, 0, 1,
                     scale=1, name='Rock-Salt' )\
        .add_atom(0, 0, 0, 'A')\
        .add_atom(0.5, 0.5, 0.5, 'B')
Example #31
0
def zinc_blende():
    """ zinc_blende lattice """
    from pylada.crystal import Structure
    return Structure(0, 0.5, 0.5,
                     0.5, 0, 0.5,
                     0.5, 0.5, 0,
                     scale=1, name='Zinc-Blende' )\
        .add_atom(0, 0, 0, 'A')\
        .add_atom(0.25, 0.25, 0.25, 'B')
Example #32
0
def crystal(file='fort.34'):
  """ Reads CRYSTAL's external format. """
  from numpy import array, abs, zeros, any, dot
  from numpy.linalg import inv
  from ..crystal import which_site
  from ..misc import RelativePath
  from ..error import IOError
  from ..periodic_table import find as find_specie
  from . import Structure

  if isinstance(file, str):
    if file.find('\n') == -1:
      with open(RelativePath(file).path, 'r') as file: return crystal(file)
    else: file = file.splitlines().__iter__()
  # read first line
  try: line = file.next()
  except StopIteration: raise IOError('Premature end of stream.')
  else: dimensionality, centering, type = [int(u) for u in line.split()[:3]]
  # read cell
  try: cell = array( [file.next().split()[:3] for i in xrange(3)],
                     dtype='float64' ).T
  except StopIteration: raise IOError('Premature end of stream.')
  result = Structure( cell=cell, centering=centering,
                      dimensionality=dimensionality, type=type, scale=1e0 )
  # read symmetry operators
  result.spacegroup = []
  try: N = int(file.next())
  except StopIteration: raise IOError('Premature end of stream.')
  for i in xrange(N):
    try: op = array( [file.next().split()[:3] for j in xrange(4)],
                     dtype='float64' )
    except StopIteration: raise IOError('Premature end of stream.')
    else: op[:3] = op[:3].copy().T
    result.spacegroup.append(op)
  result.spacegroup = array(result.spacegroup)

  # read atoms.
  try: N = int(file.next())
  except StopIteration: raise IOError('Premature end of stream.')

  for i in xrange(N):
    try: line = file.next().split()
    except StopIteration: raise IOError('Premature end of stream.')
    else: type, pos = int(line[0]), array(line[1:4], dtype='float64')
    if type < 100: type = find_specie(atomic_number=type).symbol
    result.add_atom(pos=pos, type=type, asymmetric=True)

  # Adds symmetrically equivalent structures.
  identity = zeros((4, 3), dtype='float64')
  for i in xrange(3): identity[i, i] == 1
  symops = [u for u in result.spacegroup if any(abs(u - identity) > 1e-8)]
  invcell = inv(result.cell)
  for atom in [u for u in result]:
    for op in symops:
      pos = dot(op[:3], atom.pos) + op[3]
      if which_site(pos, result, invcell=invcell) == -1:
        result.add_atom(pos=pos, type=atom.type, asymmetric=False)

  return result
Example #33
0
def s1():
    """ s1 lattice """
    from pylada.crystal import Structure
    return Structure( 0, 3.1, 3.1,\
                      3.1, 0, 3.1,\
                      3.1, 3.1, 0,\
                      scale=1, name='s1' )\
             .add_atom(3.1, 3.1, 3.1, 'A')\
             .add_atom(0, 0, 0, 'B')\
             .add_atom(1.55, 1.55, 1.55, 'X')
Example #34
0
def test_lattice_is_primitive():
    from pylada.crystal import Structure, is_primitive

    lattice = Structure(0.0, 0.5, 0.5,
                        0.5, 0.0, 0.5,
                        0.5, 0.5, 0.0, scale=2.0, m=True ) \
        .add_atom(0, 0, 0, "As")                           \
        .add_atom(0.25, 0.25, 0.25, ['In', 'Ga'], m=True)

    assert is_primitive(lattice)
Example #35
0
def s17():
    """ s17 lattice """
    from pylada.crystal import Structure
    return Structure( 4.244, -2.122, 0,\
                      0, 3.67541, 0,\
                      0, 0, 4.563,\
                      scale=1, name='s17' )\
             .add_atom(0, 0, 0, 'A')\
             .add_atom(2.122, 1.22514, 2.2815, 'B')\
             .add_atom(-2.122e-08, 2.45027, 2.2815, 'X')
Example #36
0
def wurtzite():
    """ wurtzite lattice """
    from pylada.crystal import Structure
    return Structure(0.5, 0.5, 0,
                     -0.866025, 0.866025, 0,
                     0, 0, 1,
                     scale=1, name='Wurtzite' )\
        .add_atom(0.5, 0.288675, 0, 'A')\
        .add_atom(0.5, -0.288675, 0.5, 'A')\
        .add_atom(0.5, 0.288675, 0.25, 'B')\
        .add_atom(0.5, -0.288675, 0.75, 'B')
def get_madelungenergy(latt_vec_array, charge, epsilon, cutoff):
    """ Function returns leading first order correction term, i.e.,
        screened Madelung-like lattice energy of point charge
    Reference: M. Leslie and M. J. Gillan, J. Phys. C: Solid State Phys. 18 (1985) 973

    Parameters
        defect = pylada.vasp.Extract object
        charge = charge of point defect. Default 1e0 elementary charge
        epsilon = dimensionless relative permittivity, SKW: isotropic average of dielectric constant
        cutoff = Ewald cutoff parameter

    Returns
        Madelung (electrostatic) energy in eV                                                                                                                

    Note:
        1. Units in this function are either handled by the module Quantities, or\
        defaults to Angstrom and elementary charges
        2. Function is adopted from Haowei Peng's version in pylada.defects modules
    """

    ewald_cutoff = cutoff * Ry

    cell_scale = 1.0  # SKW: In notebook workflow cell parameters are converted to Cartesians and units of Angstroms
    # SKW: Create point charge in pylada.crystal.structure class (used for charge model)
    # http://pylada.github.io/pylada/userguide/crystal.html
    struc = Structure()
    struc.cell = latt_vec_array
    struc.scale = cell_scale
    struc.add_atom(0., 0., 0., "P", charge=charge)

    #Anuj_05/22/18: added "cutoff" in ewald syntax
    result = ewald(struc, cutoff=ewald_cutoff).energy / epsilon
    return -1 * result.rescale(eV)
Example #38
0
def first_order_charge_correction(structure, charge=None, epsilon=1e0, cutoff=20.0, **kwargs):
    """ First order charge correction of +1 charge in given supercell. 

        Units in this function are either handled by the module Quantities, or
        defaults to Angstroems and elementary charges.

        :Parameters:
          structure : `pylada.crystal.Structure`
            Defect supercell, with cartesian positions in angstrom.
          charge 
            Charge of the point-defect. Defaults to 1e0 elementary charge. If no
            units are attached, expects units of elementary charges.
          epsilon 
            dimensionless relative permittivity.
          cutoff 
            Ewald cutoff parameter.

        :return: Electrostatic energy in eV.
    """
    from quantities import elementary_charge, eV
    from pylada.crystal import Structure
    from pylada.physics import Ry
    from pylada.ewald import ewald

    if charge is None:
        charge = 1
    elif charge == 0:
        return 0e0 * eV
    if hasattr(charge, "units"):
        charge = float(charge.rescale(elementary_charge))

    ewald_cutoff = cutoff * Ry

    struc = Structure()
    struc.cell = structure.cell
    struc.scale = structure.scale
    struc.add_atom(0e0, 0, 0, "A", charge=charge)

    result = ewald(struc, ewald_cutoff).energy / epsilon
    return -result.rescale(eV)
Example #39
0
def cut_and_splice(s1, s2, roll=True):
  """ Cut-n-splice GSGO crossover operation

      Mating operation on two parent structures s1 and s2.
      Done on scaled atomic positions (cubic systems) by
      cutting them in half and mixing their upper and 
      lower parts.
  """
  from random import choice, random
  from numpy import dot, abs
  from numpy.linalg import det
  from pylada.crystal import Structure

  # swap structures randomly.
  if choice([True, False]): s1, s2 = s2, s1

  # chem. symbols and scaled positions of the two parents
  sc_pos1 = zip([atom.type for atom in s1],fractional_pos(s1, roll=True))
  sc_pos2 = zip([atom.type for atom in s2],fractional_pos(s2, roll=True))

  result = Structure(s1.cell, scale=s1.scale)

  # choose random positions of split-plane
  xsep = 0.5 - (random() * 0.45 + 0.15)
  # choose direction of split-plane randomly from cell-vectors.
  direction = choice(range(3))

  for type, pos in sc_pos1:
    if pos[direction] >= xsep: result.add_atom(*dot(result.cell, pos), type=type)

  for type, pos in sc_pos2:
    if pos[direction] < xsep: result.add_atom(*dot(result.cell, pos), type=type)

  result.scale =  s1.scale * (float(len(result)) / float(len(s1)))**(1./3.)

  return result
Example #40
0
###############################

from sys import exit
from shutil import rmtree
from os.path import exists, join
from math import ceil, sqrt
from numpy import dot, array, matrix
from numpy.linalg import norm
from boost.mpi import world
from pylada.vff import Vff
from pylada.crystal import Structure, Lattice, fill_structure
from pylada.escan import read_input

input = read_input("input.py")

structure = Structure()
structure.set_cell = (4, 0, 0.5),\
                     (0, 1,   0),\
                     (0, 0, 0.5)
structure = fill_structure(structure.cell)
for i, atom in enumerate(structure.atoms):
  atom.type = "Si" if i < len(structure.atoms)/2 else "Ge"


result_str = Structure()
result_str.scale = 5.450000e+00
result_str.set_cell = (4.068890e+00, -4.235770e-18, 5.083297e-01),\
                     (-1.694308e-17, 1.016103e+00, 2.238072e-18),\
                     (-2.252168e-03, 8.711913e-18, 5.083297e-01)
result_str.weight = 1.000000e+00
result_str.name = ""
Example #41
0
# Structure definition.
from pylada.crystal import Structure
from pylada.crystal.defects import third_order_charge_correction
from quantities import eV

structure = Structure()
structure.name   = 'Ga2CdO4: b5'
structure.scale  = 1.0
structure.energy = -75.497933000000003
structure.weight = 1.0
structure.set_cell = (-0.0001445, 4.3538020, 4.3537935),\
                     (4.3538700, -0.0001445, 4.3538615),\
                     (4.3538020, 4.3537935, -0.0001445)
structure.add_atoms = [(7.61911540668, 7.61923876219, 7.61912846850), 'Cd'],\
                      [(1.08833559332, 1.08834823781, 1.08832253150), 'Cd'],\
                      [(4.35372550000, 4.35379350000, 4.35372550000), 'Ga'],\
                      [(4.35379775000, 2.17685850000, 2.17682450000), 'Ga'],\
                      [(2.17682450000, 4.35386575000, 2.17682875000), 'Ga'],\
                      [(2.17682875000, 2.17686275000, 4.35379775000), 'Ga'],\
                      [(2.32881212361, 2.32884849688, 2.32881647755),  'O'],\
                      [(2.32887187256, 4.20174404476, 4.20169148188),  'O'],\
                      [(4.20168277385, 2.32891695560, 4.20168347161),  'O'],\
                      [(4.20168782554, 4.20174474241, 2.32887622633),  'O'],\
                      [(6.37863887654, 6.37873414925, 6.37863016865),  'O'],\
                      [(6.37857477364, 4.50584295539, 4.50575516433),  'O'],\
                      [(4.50576822615, 6.37867004441, 4.50576752839),  'O'],\
                      [(4.50576317445, 4.50584225759, 6.37857477367),  'O']

# this is converged to less than 1meV
third = third_order_charge_correction(structure, epsilon=10.0, n=20)
assert abs(third - 0.11708438633232088*eV) < 1e-12
Example #42
0
#  <http://www.gnu.org/licenses/>.
###############################

from pylada.crystal import Structure
from pylada.pcm import Clj, bond_name
from pylada.physics import a0, Ry
from quantities import angstrom, eV, hartree

clj  = Clj()
""" Point charge + r^12 + r^6 model. """
clj.ewald_cutoff = 80 * Ry

clj.charges["A"] = -1.0
clj.charges["B"] =  1.0

structure = Structure()
structure.set_cell = (1,0,0),\
                     (0,1,0),\
                     (0,0,1)
structure.scale = 50
structure.add_atom = (0,0,0), "A"
structure.add_atom = (a0.rescale(angstrom)/structure.scale,0,0), "B"

print clj.ewald(structure).energy, hartree.rescale(eV)


from pylada.crystal.A2BX4 import b5
from pylada.crystal import fill_structure
from numpy import array
clj.ewald_cutoff = 20 * Ry
lattice = b5()
Example #43
0
def make_surface(structure=None, miller=None, nlayers=5, vacuum=15, acc=5):
    """Returns a slab from the 3D structure 

       Takes a structure and makes a slab defined by the miller indices 
       with nlayers number of layers and vacuum defining the size 
       of the vacuum thickness. Variable acc determines the number of 
       loops used to get the direct lattice vectors perpendicular 
       and parallel to miller. For high index surfaces use larger acc value 
       .. warning: (1) cell is always set such that miller is alogn z-axes
                   (2) nlayers and vacuum are always along z-axes.

       :param structure: LaDa structure
       :param miller: 3x1 float64 array
           Miller indices defining the slab    
       :param nlayers: integer
           Number of layers in the slab
       :param vacuum: real
           Vacuum thicness in angstroms
       :param acc: integer
           number of loops for finding the cell vectors of the slab structure
    """
    direct_cell = transpose(structure.cell)
    reciprocal_cell = 2 * pi * transpose(inv(direct_cell))

    orthogonal = []  # lattice vectors orthogonal to miller

    for n1 in arange(-acc, acc + 1):
        for n2 in arange(-acc, acc + 1):
            for n3 in arange(-acc, acc + 1):

                pom = array([n1, n2, n3])
                if dot(pom, miller) == 0 and dot(pom, pom) != 0:
                    orthogonal.append(array([n1, n2, n3]))

    # chose the shortest parallel and set it to be a3 lattice vector
    norm_orthogonal = [sqrt(dot(dot(x, direct_cell), dot(x, direct_cell))) for x in orthogonal]
    a1 = orthogonal[norm_orthogonal.index(min(norm_orthogonal))]

    # chose the shortest orthogonal to miller and not colinear with a1 and set it as a2
    in_plane = []

    for x in orthogonal:
        if dot(x, x) > 1e-3:
            v = cross(dot(x, direct_cell), dot(a1, direct_cell))
            v = sqrt(dot(v, v))
            if v > 1e-3:
                in_plane.append(x)

    norm_in_plane = [sqrt(dot(dot(x, direct_cell), dot(x, direct_cell))) for x in in_plane]
    a2 = in_plane[norm_in_plane.index(min(norm_in_plane))]

    a1 = dot(a1, direct_cell)
    a2 = dot(a2, direct_cell)

    # new cartesian axes z-along miller, x-along a1, and y-to define the right-hand orientation
    e1 = a1 / sqrt(dot(a1, a1))
    e2 = a2 - dot(e1, a2) * e1
    e2 = e2 / sqrt(dot(e2, e2))
    e3 = cross(e1, e2)

    # find vectors parallel to miller and set the shortest to be a3
    parallel = []

    for n1 in arange(-acc, acc + 1):
        for n2 in arange(-acc, acc + 1):
            for n3 in arange(-acc, acc + 1):
                pom = dot(array([n1, n2, n3]), direct_cell)
                if sqrt(dot(pom, pom)) - dot(e3, pom) < 1e-8 and sqrt(dot(pom, pom)) > 1e-3:
                    parallel.append(pom)

    # if there are no lattice vectors parallel to miller
    if len(parallel) == 0:
        for n1 in arange(-acc, acc + 1):
            for n2 in arange(-acc, acc + 1):
                for n3 in arange(-acc, acc + 1):
                    pom = dot(array([n1, n2, n3]), direct_cell)
                    if dot(e3, pom) > 1e-3:
                        parallel.append(pom)

    parallel = [x for x in parallel if sqrt(
        dot(x - dot(e1, x) * e1 - dot(e2, x) * e2, x - dot(e1, x) * e1 - dot(e2, x) * e2)) > 1e-3]
    norm_parallel = [sqrt(dot(x, x)) for x in parallel]

    assert len(norm_parallel) != 0, "Increase acc, found no lattice vectors parallel to (hkl)"

    a3 = parallel[norm_parallel.index(min(norm_parallel))]

    # making a structure in the new unit cell - defined by the a1,a2,a3
    new_direct_cell = array([a1, a2, a3])

    assert abs(det(new_direct_cell)) > 1e-5, "Something is wrong your volume is equal to zero"

    # make sure determinant is positive
    if det(new_direct_cell) < 0.:
        new_direct_cell = array([-a1, a2, a3])

    #structure = fill_structure(transpose(new_direct_cell),structure.to_lattice())
    structure = supercell(lattice=structure, supercell=transpose(new_direct_cell))

    # transformation matrix to new coordinates x' = dot(m,x)
    m = array([e1, e2, e3])

    # seting output structure
    out_structure = Structure()
    out_structure.scale = structure.scale
    out_structure.cell = transpose(dot(new_direct_cell, transpose(m)))

    for atom in structure:
        p = dot(m, atom.pos)
        out_structure.add_atom(p[0], p[1], p[2], atom.type)

    # repaeting to get nlayers and vacuum
    repeat_cell = dot(out_structure.cell, array([[1., 0., 0.], [0., 1., 0.], [0., 0., nlayers]]))
    out_structure = supercell(lattice=out_structure, supercell=repeat_cell)

    # checking whether there are atoms close to the cell faces and putting them back to zero
    for i in range(len(out_structure)):
        scaled_pos = dot(out_structure[i].pos, inv(transpose(out_structure.cell)))
        for j in range(3):
            if abs(scaled_pos[j] - 1.) < 1e-5:
                scaled_pos[j] = 0.
        out_structure[i].pos = dot(scaled_pos, transpose(out_structure.cell))

    # adding vaccum to the cell
    out_structure.cell = out_structure.cell + \
        array([[0., 0., 0.], [0., 0., 0.], [0., 0., float(vacuum) / float(out_structure.scale)]])

    # translating atoms so that center of the slab and the center of the cell along z-axes coincide
    max_z = max([x.pos[2] for x in out_structure])
    min_z = min([x.pos[2] for x in out_structure])
    center_atoms = 0.5 * (max_z + min_z)
    center_cell = 0.5 * out_structure.cell[2][2]

    for i in range(len(out_structure)):
        out_structure[i].pos = out_structure[i].pos + array([0., 0., center_cell - center_atoms])

    # exporting the final structure
    return out_structure
Example #44
0
def icsd_cif_a(filename, make_primitive=True):
    """ Reads lattice from the ICSD \*cif files.

        It will not work in the case of other \*cif.
        It is likely to produce wrong output if the site occupations are fractional.
        If the occupation is > 0.5 it will treat it as 1 and
        in the case occupation < 0.5 it will treat it as 0 and
        it will accept all occupation = 0.5 as 1 and create a mess!
    """
    from pylada import logger
    import re
    from copy import deepcopy
    from os.path import basename
    from numpy.linalg import norm
    from numpy import array, transpose
    from numpy import pi, sin, cos, sqrt, dot

    lines = open(filename, 'r').readlines()
    logger.info("crystal/read: icsd_cif_a: %s" % filename)

    sym_big = 0
    sym_end = 0
    pos_big = 0
    pos_end = 0

    for l in lines:
        x = l.split()
        if len(x) > 0:
                    # CELL
            if x[0] == '_cell_length_a':
                if '(' in x[-1]:
                    index = x[-1].index('(')
                else:
                    index = len(x[-1])
                a = float(x[-1][:index])

            if x[0] == '_cell_length_b':
                if '(' in x[-1]:
                    index = x[-1].index('(')
                else:
                    index = len(x[-1])
                b = float(x[-1][:index])

            if x[0] == '_cell_length_c':
                if '(' in x[-1]:
                    index = x[-1].index('(')
                else:
                    index = len(x[-1])
                c = float(x[-1][:index])

            if x[0] == '_cell_angle_alpha':
                if '(' in x[-1]:
                    index = x[-1].index('(')
                else:
                    index = len(x[-1])
                alpha = float(x[-1][:index])

            if x[0] == '_cell_angle_beta':
                if '(' in x[-1]:
                    index = x[-1].index('(')
                else:
                    index = len(x[-1])
                beta = float(x[-1][:index])

            if x[0] == '_cell_angle_gamma':
                if '(' in x[-1]:
                    index = x[-1].index('(')
                else:
                    index = len(x[-1])
                gamma = float(x[-1][:index])

        # SYMMETRY OPERATIONS

        if len(x) > 0 and x[0] == '_symmetry_equiv_pos_as_xyz':
            sym_big = lines.index(l)

        if len(x) > 0 and x[0] == '_atom_type_symbol':
            sym_end = lines.index(l)

        # WYCKOFF POSITIONS

        if len(x) > 0 and x[0] == '_atom_site_attached_hydrogens':
            pos_big = lines.index(l)

        if len(x) > 0 and x[0] == '_atom_site_B_iso_or_equiv':
            pos_big = lines.index(l)

        if len(x) > 0 and x[0] == '_atom_site_U_iso_or_equiv':
            pos_big = lines.index(l)

        if len(x) > 0 and x[0] == '_atom_site_0_iso_or_equiv':
            pos_big = lines.index(l)

        # if pos_end == 0 and l in ['\n', '\r\n'] and lines.index(l) > pos_big:
        if pos_end == 0 and pos_big > 0 \
                and (l in ['\n', '\r\n'] or l.startswith('#')) \
                and lines.index(l) > pos_big:
            pos_end = lines.index(l)

    # _symmetry_equiv_pos_* lines are like:
    #     1     'x, x-y, -z+1/2'
    logger.debug("crystal/read: icsd_cif_a: sym_big: %s" % sym_big)
    logger.debug("crystal/read: icsd_cif_a: sym_end: %s" % sym_end)

    symm_ops = ['(' + x.split()[1][1:] + x.split()[2] + x.split()[3][:-1] + ')'
                for x in lines[sym_big + 1:sym_end - 1]]
    logger.debug("crystal/read: icsd_cif_a: symm_ops a: %s" % symm_ops)
    # ['(x,x-y,-z+1/2)', '(-x+y,y,-z+1/2)', ...]

    # Insert decimal points after integers
    symm_ops = [re.sub(r'(\d+)', r'\1.', x) for x in symm_ops]
    logger.debug("crystal/read: icsd_cif_a: symm_ops b: %s" % symm_ops)
    # ['(x,x-y,-z+1./2.)', '(-x+y,y,-z+1./2.)', ...]

    # _atom_site_* lines are like:
    #   Mo1 Mo4+ 2 c 0.3333 0.6667 0.25 1. 0
    logger.debug("crystal/read: icsd_cif_a: pos_big: %s" % pos_big)
    logger.debug("crystal/read: icsd_cif_a: pos_end: %s" % pos_end)
    wyckoff = [[x.split()[0], [x.split()[4], x.split()[5], x.split()[6]], x.split()[7]]
               for x in lines[pos_big + 1:pos_end]]
    logger.debug("crystal/read: icsd_cif_a: wyckoff a: %s" % wyckoff)
    # [['Mo1', ['0.3333', '0.6667', '0.25'], '1.'], ['S1', ['0.3333', '0.6667', '0.621(4)'], '1.']]

    wyckoff = [w for w in wyckoff if int(float(w[-1][:4]) + 0.5) != 0]
    logger.debug("crystal/read: icsd_cif_a: wyckoff b: %s" % wyckoff)
    # [['Mo1', ['0.3333', '0.6667', '0.25'], '1.'], ['S1', ['0.3333', '0.6667', '0.621(4)'], '1.']]

    # Setting up a good wyckoff list

    for w in wyckoff:
        # Strip trailing numerals from w[0] == 'Mo1'
        pom = 0
        for i in range(len(w[0])):
            try:
                int(w[0][i])
                if pom == 0:
                    pom = i
            except:
                pass

        w[0] = w[0][:pom]

        # Strip trailing standard uncertainty, if any, from w[1], ..., w[3]
        for i in range(3):
            if '(' in w[1][i]:
                index = w[1][i].index('(')
            else:
                index = len(w[1][i])
            w[1][i] = float(w[1][i][:index])

        # Delete w[4]
        del w[-1]
    ##########################################

    # List of unique symbols ["Mo", "S"]
    symbols = list({w[0] for w in wyckoff})
    logger.debug("crystal/read: icsd_cif_a: symbols: %s" % symbols)

    # List of position vectors for each symbol
    positions = [[] for i in range(len(symbols))]

    for w in wyckoff:
        symbol = w[0]
        x, y, z = w[1][0], w[1][1], w[1][2]
        logger.debug("symbol: %s  x: %s   y: %s  z: %s" % (symbol, x, y, z))
        for i in range(len(symm_ops)):
            # Set pom = new position based on symmetry transform
            pom = list(eval(symm_ops[i]))
            logger.debug("i: %s  pom a: %s" % (i, pom))
            # [0.3333, -0.3334, 0.25]

            # Move positions to range [0,1]:
            for j in range(len(pom)):
                if pom[j] < 0.:
                    pom[j] = pom[j] + 1.
                if pom[j] >= 0.999:
                    pom[j] = pom[j] - 1.
            logger.debug("i: %s   pom b: %s" % (i, pom))
            # [0.3333, 0.6666, 0.25]

            # If pom is not in positions[symbol], append pom
            if not any(norm(array(u) - array(pom)) < 0.01 for u in positions[symbols.index(symbol)]):
                ix = symbols.index(symbol)
                positions[ix].append(pom)
                logger.debug("new positions for %s: %s" % (symbol, repr(positions[ix])))

    ################ CELL ####################

    a1 = a * array([1., 0., 0.])
    a2 = b * array([cos(gamma * pi / 180.), sin(gamma * pi / 180.), 0.])
    c1 = c * cos(beta * pi / 180.)
    c2 = c / sin(gamma * pi / 180.) * (-cos(beta * pi / 180.) *
                                       cos(gamma * pi / 180.) + cos(alpha * pi / 180.))
    a3 = array([c1, c2, sqrt(c**2 - (c1**2 + c2**2))])
    cell = array([a1, a2, a3])
    logger.debug("crystal/read: icsd_cif_a: a1: %s" % a1)
    logger.debug("crystal/read: icsd_cif_a: a2: %s" % a2)
    logger.debug("crystal/read: icsd_cif_a: a3: %s" % a3)
    ##########################################

    from pylada.crystal import Structure, primitive
    logger.debug("crystal/read: icsd_cif_a: cell: %s" % cell)

    structure = Structure(
        transpose(cell),
        scale=1,
        name=basename(filename))

    for i in range(len(symbols)):
        logger.debug("crystal/read: icsd_cif_a: i: %s  symbol: %s  len(position): %i" % (
            i,  symbols[i], len(positions[i])
        ))
        # crystal/read: i:  0   symbol:  Mo   len position:  2

        for j in range(len(positions[i])):
            atpos = dot(transpose(cell), positions[i][j])
            logger.debug("j: %s  pos: %s" % (j, positions[i][j]))
            logger.debug("atpos: " % atpos)
            #  j:  0   pos:  [0.3333, 0.6666000000000001, 0.25]
            #  atpos:  [  6.32378655e-16   1.81847148e+00   3.07500000e+00]

            structure.add_atom(atpos[0], atpos[1], atpos[2], symbols[i])

    logger.info("crystal/read: icsd_cif_a: structure: %s" % structure)

    if make_primitive:
        prim = primitive(structure)
    else:
        prim = deepcopy(structure)
    logger.info("crystal/read: icsd_cif_a: primitive structure: %s" % prim)

    return prim
Example #45
0
def test_istruc():
  from collections import namedtuple
  from pickle import loads, dumps
  from os import remove
  from os.path import join, exists
  from shutil import rmtree
  from tempfile import mkdtemp
  from pylada.vasp.files import POSCAR, CONTCAR
  from pylada.vasp import Vasp
  from pylada.crystal import Structure, read, specieset, write
  from pylada.error import ValueError

  structure = Structure([[0, 0.5, 0.5],[0.5, 0, 0.5], [0.5, 0.5, 0]], scale=5.43, name='has a name')\
                       .add_atom(0,0,0, "Si")\
                       .add_atom(0.25,0.25,0.25, "Si")

  Extract = namedtuple("Extract", ['directory', 'success', 'structure'])
  a = Vasp()
  o = a._input['istruc']
  d = {'IStruc': o.__class__}

  directory = mkdtemp()
  try: 
    assert a.istruc == 'auto'
    assert o.output_map(vasp=a, outdir=directory, structure=structure) is None
    assert eval(repr(o), d).value == 'auto'
    assert loads(dumps(o)).value == 'auto'
    assert exists(join(directory, POSCAR))
    remove(join(directory, POSCAR))

    # check reading from outcar but only on success.
    a.restart = Extract(directory, False, structure.copy())
    a.restart.structure[1].pos[0] += 0.02
    assert a.istruc == 'auto'
    assert o.output_map(vasp=a, outdir=directory, structure=structure) is None
    assert exists(join(directory, POSCAR))
    other = read.poscar(join(directory, POSCAR), types=specieset(structure))
    assert abs(other[1].pos[0] - 0.25) < 1e-8
    assert abs(other[1].pos[0] - 0.27) > 1e-8
    # check reading from outcar but only on success.
    a.restart = Extract(directory, True, structure.copy())
    a.restart.structure[1].pos[0] += 0.02
    assert a.istruc == 'auto'
    assert o.output_map(vasp=a, outdir=directory, structure=structure) is None
    assert exists(join(directory, POSCAR))
    other = read.poscar(join(directory, POSCAR), types=specieset(structure))
    assert abs(other[1].pos[0] - 0.25) > 1e-8
    assert abs(other[1].pos[0] - 0.27) < 1e-8

    # Now check CONTCAR
    write.poscar(structure, join(directory, CONTCAR))
    assert a.istruc == 'auto'
    assert o.output_map(vasp=a, outdir=directory, structure=structure) is None
    assert exists(join(directory, POSCAR))
    other = read.poscar(join(directory, POSCAR), types=specieset(structure))
    assert abs(other[1].pos[0] - 0.25) < 1e-8
    assert abs(other[1].pos[0] - 0.27) > 1e-8

    # Check some failure modes.
    write.poscar(structure, join(directory, CONTCAR))
    structure[0].type = 'Ge'
    a.restart = None
    try: o.output_map(vasp=a, outdir=directory, structure=structure)
    except ValueError: pass
    else: raise Exception()
    structure[0].type = 'Si'
    structure.add_atom(0.25,0,0, 'Si')
    try: o.output_map(vasp=a, outdir=directory, structure=structure)
    except ValueError: pass
    else: raise Exception()

  finally: rmtree(directory)
Example #46
0
vff.lattice.set_types = ("In", "Ga"), ("As",)
vff.lattice.scale = 6.5
vff.add_bond = "In", "As", (2.62332, 21.6739, -112.0, 150.0)
vff.add_bond = "Ga", "As", (2.44795, 32.1530, -105.0, 150.0)
vff.add_angle = "As", "Ga", "As", ("tet", -4.099, 9.3703)
vff.add_angle = "Ga", "As", "Ga", ("tet", -4.099, 9.3703)
vff.add_angle = "In", "As", "In", ("tet", -5.753, 5.7599)
vff.add_angle = "As", "In", "As", ("tet", -5.753, 5.7599)
vff.add_angle = "Ga", "As", "In", (-0.35016, -4.926, 7.5651)
vff.minimizer.verbose = True
vff.minimizer.type = "gsl_bfgs2"
vff.minimizer.itermax = 1
vff.minimizer.tolerance = 1e-5
vff.minimizer.uncertainties = 1e-3

structure = Structure()
# structure.set_cell = (00.0, 0.5, 0.5),\
#                      (0.50, 0.0, 0.5),\
#                      (0.50, 0.5, 0.0)
# structure.add_atoms = ((0.00, 0.00, 0.00), "In"),\
#                       ((0.25, 0.25, 0.25), "As")
structure.set_cell = (10.0, 0.5, 0.5),\
                     (0.00, 0.0, 0.5),\
                     (0.00, 0.5, 0.0)
structure.add_atoms = ((0.00, 0.00, 0.00), "Ga"),\
                      ((0.25, 0.25, 0.25), "As"),\
                      ((1.00, 0.00, 0.00), "Ga"),\
                      ((1.25, 0.25, 0.25), "As"),\
                      ((2.00, 0.00, 0.00), "In"),\
                      ((2.25, 0.25, 0.25), "As"),\
                      ((3.00, 0.00, 0.00), "In"),\
Example #47
0
def test_ingaas():
  from numpy import abs, all, dot, array
  from quantities import eV, angstrom
  from pylada.crystal import Structure

  vff = functional()

  structure = Structure( 10.0, 0.5, 0.5, 
                         0.00, 0.0, 0.5,
                         0.00, 0.5, 0.0, scale=6.5 )\
                       .add_atom(pos=(0.00, 0.00, 0.00), type="Ga") \
                       .add_atom(pos=(0.25, 0.25, 0.25), type="As") \
                       .add_atom(pos=(1.00, 0.00, 0.00), type="Ga") \
                       .add_atom(pos=(1.25, 0.25, 0.25), type="As") \
                       .add_atom(pos=(2.00, 0.00, 0.00), type="In") \
                       .add_atom(pos=(2.25, 0.25, 0.25), type="As") \
                       .add_atom(pos=(3.00, 0.00, 0.00), type="In") \
                       .add_atom(pos=(3.25, 0.25, 0.25), type="As") \
                       .add_atom(pos=(4.00, 0.00, 0.00), type="Ga") \
                       .add_atom(pos=(4.25, 0.25, 0.25), type="As") \
                       .add_atom(pos=(5.00, 0.00, 0.00), type="In") \
                       .add_atom(pos=(5.25, 0.25, 0.25), type="As") \
                       .add_atom(pos=(6.00, 0.00, 0.00), type="In") \
                       .add_atom(pos=(6.25, 0.25, 0.25), type="As") \
                       .add_atom(pos=(7.00, 0.00, 0.00), type="Ga") \
                       .add_atom(pos=(7.25, 0.25, 0.25), type="As") \
                       .add_atom(pos=(8.00, 0.00, 0.00), type="Ga") \
                       .add_atom(pos=(8.25, 0.25, 0.25), type="As") \
                       .add_atom(pos=(9.00, 0.00, 0.00), type="Ga") \
                       .add_atom(pos=(9.25, 0.25, 0.25), type="As")  

  epsilon = array([[1e0, 0.1, 0], [0.1, 1e0, 0], [0, 0, 1e0]])
  structure.cell = dot(epsilon, structure.cell)
  for atom in structure: atom.pos = dot(epsilon, atom.pos)
  out = vff._pyeval(structure)
  assert abs(out.energy - 12.7962141476*eV) < 1e-8
  assert abs(vff.energy(structure) - 12.7962141476*eV) < 1e-8
  stress = array([[ 0.07050804,  0.04862879,  0.00025269],
                  [ 0.04862879,  0.07050804, -0.00025269],
                  [ 0.00025269, -0.00025269,  0.06073765]]) * eV/angstrom**3
  assert all(abs(out.stress - stress) < 1e-6)
  assert all(abs(vff.jacobian(structure)[0] - stress) < 1e-6)
  gradients = array([u.gradient for u in out])
  check_gradients = array( [[  9.15933995e-16,  -5.96744876e-15,   1.12373933e+00],
                            [  2.22044605e-16,  -9.43689571e-15,  -1.12373933e+00],
                            [  6.19921859e-02,  -6.19921859e-02,   1.00514227e+00],
                            [ -5.99520433e-15,   2.19269047e-15,  -1.12373933e+00],
                            [  7.66544525e-02,  -7.66544525e-02,   1.02138259e+00],
                            [  3.82409256e-01,  -3.82409256e-01,  -1.65478066e+00],
                            [ -1.89756333e-02,   1.89756333e-02,   1.15847492e+00],
                            [ -4.16333634e-17,   8.81239526e-16,  -1.09205526e+00],
                            [ -7.54665596e-02,   7.54665596e-02,   1.14107325e+00],
                            [ -3.64621516e-01,   3.64621516e-01,  -5.74094841e-01],
                            [  7.66544525e-02,  -7.66544525e-02,   1.02138259e+00],
                            [  3.82409256e-01,  -3.82409256e-01,  -1.65478066e+00],
                            [ -1.89756333e-02,   1.89756333e-02,   1.15847492e+00],
                            [ -1.19973476e-14,  -2.32591724e-14,  -1.09205526e+00],
                            [ -1.37458746e-01,   1.37458746e-01,   1.25967031e+00],
                            [ -3.64621516e-01,   3.64621516e-01,  -5.74094841e-01],
                            [ -7.77156117e-16,  -3.10862447e-15,   1.12373933e+00],
                            [  8.29891711e-15,   0.00000000e+00,  -1.12373933e+00],
                            [  3.33066907e-15,   7.16093851e-15,   1.12373933e+00],
                            [ -4.44089210e-16,   7.85482790e-15,  -1.12373933e+00]])
  assert all(abs(gradients - check_gradients) < 1e-8)
  assert all(abs(vff.jacobian(structure)[1].magnitude - check_gradients) < 1e-8)
Example #48
0
def castep(file):
  """ Tries to read a castep structure file. """
  from numpy import array, dot
  from ..periodic_table import find as find_specie
  from ..error import IOError, NotImplementedError, input as InputError
  from ..misc import RelativePath
  from . import Structure
  if isinstance(file, str):
    if file.find('\n') == -1:
      with open(RelativePath(file).path, 'r') as file: return castep(file)
    else: file = file.splitlines()

  file = [l for l in file]

  def parse_input(input):
    """ Retrieves blocks from CASTEP input file. """
    current_block = None
    result = {}
    for line in file:
      if '#' in line: line = line[:line.find('#')]
      if current_block is not None:
        if line.split()[0].lower() == '%endblock':
          current_block = None
          continue
        result[current_block] += line
      elif len(line.split()) == 0: continue
      elif len(line.split()[0]) == 0: continue
      elif line.split()[0].lower() == '%block':
        name = line.split()[1].lower().replace('.', '').replace('_', '')
        if name in result:
          raise InputError('Found two {0} blocks in input.'.format(name))
        result[name] = ""
        current_block = name
      else:
        name = line.split()[0].lower().replace('.', '').replace('_', '')
        if name[-1] in ['=' or ':']: name = name[:-1]
        if name in result:
          raise InputError('Found two {0} tags in input.'.format(name))
        data = line.split()[1:]
        if len(data) == 0: result[name] = None; continue
        if data[0] in [':', '=']: data = data[1:]
        result[name] = ' '.join(data)
    return result

  def parse_units(line):
    from quantities import a0, meter, centimeter, millimeter, angstrom, emass, \
                           amu, second, millisecond, microsecond, nanosecond,  \
                           picosecond, femtosecond, elementary_charge, coulomb,\
                           hartree, eV, meV, Ry, joule, cal, erg, hertz,       \
                           megahertz, gigahertz, tera, kelvin, newton, dyne,   \
                           h_bar, UnitQuantity, pascal, megapascal, gigapascal,\
                           bar, atm, milli, mol

    auv = UnitQuantity('auv', a0*Ry/h_bar) # velocity
    units = { 'a0': a0, 'bohr': a0, 'm': meter, 'cm': centimeter,
              'mm': millimeter, 'ang': angstrom, 'me': emass, 'amu': amu,
              's': second, 'ms': millisecond, 'mus': microsecond,
              'ns': nanosecond, 'ps': picosecond, 'fs': femtosecond,
              'e': elementary_charge, 'c': coulomb, 'hartree': hartree,
              'ha': hartree, 'mha': 1e-3*hartree, 'ev': eV, 'mev': meV,
              'ry': Ry, 'mry': 1e-3*Ry, 'kj': 1e3*joule, 'mol': mol,
              'kcal': 1e3*cal, 'j': joule, 'erg': erg, 'hz': hertz,
              'mhz': megahertz, 'ghz': gigahertz, 'thz': tera*hertz,
              'k': kelvin, 'n': newton, 'dyne': dyne, 'auv': auv, 'pa': pascal,
              'mpa': megapascal, 'gpa': gigapascal, 'atm': atm, 'bar': bar,
              'atm': atm, 'mbar': milli*bar }
    line = line.replace('cm-1', '1/cm')
    return eval(line, units)


  input = parse_input(file)
  if 'latticecart' in input:
    data = input['latticecart'].splitlines()
    if len(data) == 4:
      units = parse_units(data[0])
      data = data[1:]
    else: units = 1
    cell = array([l.split() for l in data], dtype='float64')
  elif 'latticeabc' in input:
    raise NotImplementedError('Cannot read lattice in ABC format yet.')
  else:
    raise InputError('Could not find lattice block in input.')

  # create structure
  result = Structure(cell, scale=units)

  # now look for position block.
  units = None
  if 'positionsfrac' in input:
    posdata, isfrac = input['positionsfrac'].splitlines(), True
  elif 'positionsabs' in input:
    posdata, isfrac = input['positionsabs'].splitlines(), False
    try: units = parse_units(posdata[0])
    except: units = None
    else: posdata = posdata[1:]
  else: raise InputError('Could not find position block in input.')
  # and parse it
  for line in posdata:
    line = line.split()
    if len(line) < 2:
      raise IOError( 'Wrong file format: line with less '                      \
                     'than two items in positions block.')
    pos = array(line[1:4], dtype='float64')
    if isfrac: pos = dot(result.cell, pos)
    try: dummy = int(line[0])
    except: type = line[0]
    else: type = find_specie(atomic_number=dummy).symbol
    result.add_atom(pos=pos, type=type)
    if len(line) == 5: result[-1].magmom = float(line[4])
  return result
Example #49
0
def poscar(path="POSCAR", types=None):
  """ Tries to read a VASP POSCAR file.

       :param path: Path to the POSCAR file. Can also be an object with
         file-like behavior.
       :type path: str or file object
       :param types: Species in the POSCAR.
       :type types: None or sequence of str

      :return: `pylada.crystal.Structure` instance.
  """
  import re
  from os.path import join, exists, isdir
  from copy import deepcopy
  from numpy import array, dot, transpose
  from numpy.linalg import det
  from quantities import angstrom
  from . import Structure

  # if types is not none, converts to a list of strings.
  if types is not None:
    if isinstance(types, str): types = [types] # can't see another way of doing this...
    elif not hasattr(types, "__iter__"): types = [str(types)] # single lone vasp.specie.Specie
    else: types = [str(s) for s in types]

  if path is None: path = "POSCAR"
  if not hasattr(path, 'read'):
    assert exists(path), IOError("Could not find path %s." % (path))
    if isdir(path):
      assert exists(join(path, "POSCAR")), IOError("Could not find POSCAR in %s." % (path))
      path = join(path, "POSCAR")
  result = Structure()
  poscar = path if hasattr(path, "read") else open(path, 'r')

  try:
    # gets name of structure
    result.name = poscar.readline().strip()
    if len(result.name) > 0:
      if result.name[0] == "#": result.name = result.name[1:].strip()
    # reads scale
    scale = float(poscar.readline().split()[0])
    # gets cell vectors.
    cell = []
    for i in range(3):
      line = poscar.readline()
      assert len(line.split()) >= 3,\
             RuntimeError("Could not read column vector from poscar: %s." % (line))
      cell.append( [float(f) for f in line.split()[:3]] )
    result.cell = transpose(array(cell))
    vol = det(cell)
    if scale < 1.E-8 : scale = abs(scale/vol) **(1.0/3)
    result.scale = scale * angstrom
    # checks for vasp 5 input.
    is_vasp_5 = True
    line = poscar.readline().split()
    for i in line:
      if not re.match(r"[A-Z][a-z]?", i):
        is_vasp_5 = False
        break
    if is_vasp_5:
      text_types = deepcopy(line)
      if types is not None and not set(text_types).issubset(set(types)):
        raise RuntimeError( "Unknown species in poscar: {0} not in {1}."\
                            .format(text_types, types) )
      types = text_types
      line = poscar.readline().split()
    assert types is not None, RuntimeError("No atomic species given in POSCAR or input.")
    #  checks/reads for number of each specie
    assert len(types) >= len(line), RuntimeError("Too many atomic species in POSCAR.")
    nb_atoms = [int(u) for u in line]
    # Check whether selective dynamics, cartesian, or direct.
    first_char = poscar.readline().strip().lower()[0]
    selective_dynamics = False
    if first_char == 's':
      selective_dynamics = True
      first_char = poscar.readline().strip().lower()[0]
    # Checks whether cartesian or direct.
    is_direct = first_char not in ['c', 'k']
    # reads atoms.
    for n, specie in zip(nb_atoms, types):
      for i in range(n):
        line = poscar.readline().split()
        pos = array([float(u) for u in line[:3]], dtype="float64")
        if is_direct: pos = dot(result.cell, pos)
        result.add_atom(pos=pos, type=specie)
        if selective_dynamics:
          for which, freeze in zip(line[3:], ['x', 'y', 'z']):
            if which.lower()[0] == 't':
              result[-1].freeze = getattr(result[-1], 'freeze', '') + freeze
  finally: poscar.close()

  return result
Example #50
0
def icsd_cif_a( filename):
  """ Reads lattice from the ICSD \*cif files.

      It will not work in the case of other \*cif.
      It is likely to produce wrong output if the site occupations are fractional.
      If the occupation is > 0.5 it will treat it as 1 and
      in the case occupation < 0.5 it will treat it as 0 and
      it will accept all occupation = 0.5 as 1 and create a mess!
  """
  import re
  from os.path import basename
  from numpy.linalg import norm
  from numpy import array, transpose
  from numpy import pi, sin, cos, sqrt, dot
  from pylada.misc import bugLev

  lines = open(filename,'r').readlines()
  if bugLev >= 2:
    print "  crystal/read: icsd_cif_a: filename: ", filename

  sym_big = 0
  sym_end = 0
  pos_big = 0
  pos_end = 0

  for l in lines:
      x = l.split()
      if len(x)>0:
          # CELL
          if x[0] == '_cell_length_a':
              if '(' in x[-1]:
                  index = x[-1].index('(')
              else:
                  index = len(x[-1])
              a = float(x[-1][:index])

          if x[0] == '_cell_length_b':
              if '(' in x[-1]:
                  index = x[-1].index('(')
              else:
                  index = len(x[-1])
              b = float(x[-1][:index])

          if x[0] == '_cell_length_c':
              if '(' in x[-1]:
                  index = x[-1].index('(')
              else:
                  index = len(x[-1])
              c = float(x[-1][:index])

          if x[0] == '_cell_angle_alpha':
              if '(' in x[-1]:
                  index = x[-1].index('(')
              else:
                  index = len(x[-1])
              alpha = float(x[-1][:index])

          if x[0] == '_cell_angle_beta':
              if '(' in x[-1]:
                  index = x[-1].index('(')
              else:
                  index = len(x[-1])
              beta = float(x[-1][:index])

          if x[0] == '_cell_angle_gamma':
              if '(' in x[-1]:
                  index = x[-1].index('(')
              else:
                  index = len(x[-1])
              gamma = float(x[-1][:index])

      # SYMMETRY OPERATIONS

      if len(x)>0 and x[0] == '_symmetry_equiv_pos_as_xyz':
          sym_big = lines.index(l)

      if len(x)>0 and x[0] == '_atom_type_symbol':
          sym_end = lines.index(l)

      # WYCKOFF POSITIONS

      if len(x)>0 and x[0] == '_atom_site_attached_hydrogens':
          pos_big = lines.index(l)

      if len(x)>0 and x[0] == '_atom_site_B_iso_or_equiv':
          pos_big = lines.index(l)

      if len(x)>0 and x[0] == '_atom_site_U_iso_or_equiv':
          pos_big = lines.index(l)

      if len(x)>0 and x[0] == '_atom_site_0_iso_or_equiv':
          pos_big = lines.index(l)

      #if pos_end == 0 and l in ['\n', '\r\n'] and lines.index(l) > pos_big:
      if pos_end == 0 and pos_big > 0 \
        and (l in ['\n', '\r\n'] or l.startswith('#')) \
        and lines.index(l) > pos_big:
          pos_end = lines.index(l)


  # _symmetry_equiv_pos_* lines are like:
  #     1     'x, x-y, -z+1/2'
  if bugLev >= 5:
    print "  crystal/read: icsd_cif_a: sym_big: ", sym_big
    print "  crystal/read: icsd_cif_a: sym_end: ", sym_end

  symm_ops = [ '(' + x.split()[1][1:] + x.split()[2] + x.split()[3][:-1] + ')'\
               for x in lines[sym_big+1:sym_end-1] ]
  if bugLev >= 5:
    print "  crystal/read: icsd_cif_a: symm_ops a: ", symm_ops
  # ['(x,x-y,-z+1/2)', '(-x+y,y,-z+1/2)', ...]

  # Insert decimal points after integers
  symm_ops = [re.sub(r'(\d+)', r'\1.', x) for x in symm_ops]
  if bugLev >= 5:
    print "  crystal/read: icsd_cif_a: symm_ops b: ", symm_ops
  # ['(x,x-y,-z+1./2.)', '(-x+y,y,-z+1./2.)', ...]

  # _atom_site_* lines are like:
  #   Mo1 Mo4+ 2 c 0.3333 0.6667 0.25 1. 0
  if bugLev >= 5:
    print "  crystal/read: icsd_cif_a: pos_big: ", pos_big
    print "  crystal/read: icsd_cif_a: pos_end: ", pos_end
  wyckoff = [ [x.split()[0],[x.split()[4],x.split()[5],x.split()[6]],x.split()[7]]\
              for x in lines[pos_big+1:pos_end] ]
  if bugLev >= 5:
    print "  crystal/read: icsd_cif_a: wyckoff a: ", wyckoff
  # [['Mo1', ['0.3333', '0.6667', '0.25'], '1.'], ['S1', ['0.3333', '0.6667', '0.621(4)'], '1.']]

  wyckoff = [w for w in wyckoff if int(float(w[-1][:4])+0.5) != 0]
  if bugLev >= 5:
    print "  crystal/read: icsd_cif_a: wyckoff b: ", wyckoff
  # [['Mo1', ['0.3333', '0.6667', '0.25'], '1.'], ['S1', ['0.3333', '0.6667', '0.621(4)'], '1.']]

  ############## Setting up a good wyckoff list

  for w in wyckoff:
      # Strip trailing numerals from w[0] == 'Mo1'
      pom = 0
      for i in range(len(w[0])):
          try:
              int(w[0][i])
              if pom ==0: pom=i
          except:
              pass

      w[0] = w[0][:pom]

      # Strip trailing standard uncertainty, if any, from w[1], ..., w[3]
      for i in range(3):
          if '(' in w[1][i]:
              index = w[1][i].index('(')
          else:
              index = len(w[1][i])
          w[1][i] = float(w[1][i][:index])

      # Delete w[4]
      del w[-1]
  ##########################################

  # List of unique symbols ["Mo", "S"]
  symbols = list(set([w[0] for w in wyckoff]))
  if bugLev >= 5:
    print "  crystal/read: icsd_cif_a: symbols: ", symbols

  # List of position vectors for each symbol
  positions = [[] for i in range(len(symbols))]

  for w in wyckoff:
      symbol = w[0]
      x,y,z = w[1][0],w[1][1],w[1][2]
      if bugLev >= 5:
        print "    symbol: ", symbol, "  x: ", x, "  y: ", y, "  z: ", z
      for i in range(len(symm_ops)):
          # Set pom = new position based on symmetry transform
          pom = list(eval(symm_ops[i]))
          if bugLev >= 5:
            print "      i: ", i, "  pom a: ", pom
          # [0.3333, -0.3334, 0.25]

          # Move positions to range [0,1]:
          for j in range(len(pom)):
              if pom[j] <  0.: pom[j] = pom[j]+1.
              if pom[j] >= 0.999: pom[j] = pom[j]-1.
          if bugLev >= 5:
            print "      i: ", i, "  pom b: ", pom
          # [0.3333, 0.6666, 0.25]

          # If pom is not in positions[symbol], append pom
          if not any(norm(array(u)-array(pom)) < 0.01 for u in positions[symbols.index(symbol)]):
              ix = symbols.index(symbol)
              positions[ix].append(pom)
              if bugLev >= 5:
                print "      new positions for ", symbol, ": ", positions[ix]

  ################ CELL ####################

  a1 = a*array([1.,0.,0.])
  a2 = b*array([cos(gamma*pi/180.),sin(gamma*pi/180.),0.])
  c1 = c*cos(beta*pi/180.)
  c2 = c/sin(gamma*pi/180.)*(-cos(beta*pi/180.)*cos(gamma*pi/180.) + cos(alpha*pi/180.))
  a3 = array([c1, c2, sqrt(c**2-(c1**2+c2**2))])
  cell = array([a1,a2,a3])
  if bugLev >= 2:
    print "  crystal/read: icsd_cif_a: a1: ", a1
    print "  crystal/read: icsd_cif_a: a2: ", a2
    print "  crystal/read: icsd_cif_a: a3: ", a3
  #  a1:  [ 3.15  0.    0.  ]
  #  a2:  [-1.575       2.72798002  0.        ]
  #  a3:  [  7.53157781e-16   1.30450754e-15   1.23000000e+01]
  ##########################################


  from pylada.crystal import Structure, primitive
  if bugLev >= 2:
    print "  crystal/read: icsd_cif_a: cell: ", cell
  #  [[  3.15000000e+00   0.00000000e+00   0.00000000e+00]
  #   [ -1.57500000e+00   2.72798002e+00   0.00000000e+00]
  #   [  7.53157781e-16   1.30450754e-15   1.23000000e+01]]

  structure = Structure(
    transpose( cell),
    scale = 1,
    name = basename( filename))

  for i in range(len(symbols)):
    if bugLev >= 5:
      print "    crystal/read: icsd_cif_a: i: ", i, \
        "  symbol: ", symbols[i], \
        "  len position: ", len(positions[i])
    # crystal/read: i:  0   symbol:  Mo   len position:  2

    for j in range(len(positions[i])):
      atpos = dot( transpose(cell), positions[i][j])
      if bugLev >= 5:
        print "      j: ", j, "  pos: ", positions[i][j]
        print "        atpos: ", atpos
      #  j:  0   pos:  [0.3333, 0.6666000000000001, 0.25]
      #  atpos:  [  6.32378655e-16   1.81847148e+00   3.07500000e+00]

      structure.add_atom( atpos[0], atpos[1], atpos[2], symbols[i])

  if bugLev >= 2:
    print "  crystal/read: icsd_cif_a: structure:\n", structure
  
  prim = primitive( structure)
  if bugLev >= 2:
    print "  crystal/read: icsd_cif_a: primitive structure:\n", prim
  
  return prim