def get_spacegroup_and_volume(self, name, icsdno, natoms):
     # get experimental volume per formula unit
     output =  commands.getoutput("grep 'space' /home/jyan/icsd/%s/icsd_%s.cif"%(name, icsdno))
     if "No such file or directory" in output:
         return None, None
     
     volume =  float(commands.getoutput("grep '_cell_volume' /home/jyan/icsd/%s/icsd_%s.cif"%(name, icsdno)).split()[1])
     formulaunit = float(commands.getoutput("grep '_cell_formula_units_Z' /home/jyan/icsd/%s/icsd_%s.cif"%(name, icsdno)).split() [1])
     chemformula = commands.getoutput("grep '_chemical_formula_sum' /home/jyan/icsd/%s/icsd_%s.cif"%(name, icsdno)).split()
     na = []
     for s in chemformula:
         x = 0
         for i in s:
             if i.isdigit():
                 x = int(i) + 10 * x
         na.append(x)
     if len(na) == 1:
         formulaunit *= na[0]
     else:
         ncell = gcd(na[0], na[1])
         if len(na) > 2:
             for i in range(2, len(na)):
                 ncell = gcd(ncell, na[i])
         formulaunit *= ncell
 
 #    try:
 #        volume = read.icsd_cif_a("/home/jyan/icsd/%s/icsd_%s.cif"%(name, icsdno)).volume.magnitude
 #    except:
 #        return None, None
 
     return output.split("'")[1], volume / formulaunit
def filter_disorder(d):
    dnew = {}
    for key, item in d.items():
        formula = item[0].replace("'",'').split()
        n = []
        for el in formula:
            for i in el:
                if not i.isdigit():
                    el = el.replace(i, '')
            n.append(int(el))

        ncell = n[0]
        if len(n) >= 2:
            ncell = gcd(n[0], n[1])
            if len(n) > 2:
                for i in range(2, len(n)):
                    ncell = gcd(ncell, n[i])

        natoms = sum(n) / ncell
        if item[2] != 0 and (item[2] % natoms == 0 or natoms % item[2] == 0):
            dnew[key] = item
        else:
            print key, formula, item[2], natoms
            
    return dnew
 def get_number_of_primitive_cell(self, Z):
     # input a list of atomic masses, and output number of primitive cells
     b = Counter(Z)
     nlist = [i[1] for i in b.items()] # number of atoms for each atom species
     if len(nlist) == 1:
         return nlist[0]
     else:
         ncell = gcd(nlist[0], nlist[1])
         if len(nlist) > 2:
             for i in range(2, len(nlist)):
                 ncell = gcd(ncell, nlist[i])
         return ncell
Exemple #4
0
def reduceindex(M):
    """Reduce Miller index to the lowest equivalent integers."""
    oldM = M
    g = gcd(M[0], M[1])
    h = gcd(g, M[2])
    while h != 1:
        M = M // h
        g = gcd(M[0], M[1])
        h = gcd(g, M[2])
    if np.dot(oldM, M) > 0:
        return M
    else:
        return -M
Exemple #5
0
 def get_number_of_primitive_cell(self, Z):
     # input a list of atomic masses, and output number of primitive cells
     b = Counter(Z)
     nlist = [i[1]
              for i in b.items()]  # number of atoms for each atom species
     if len(nlist) == 1:
         return nlist[0]
     else:
         ncell = gcd(nlist[0], nlist[1])
         if len(nlist) > 2:
             for i in range(2, len(nlist)):
                 ncell = gcd(ncell, nlist[i])
         return ncell
Exemple #6
0
def reduceindex(M):
    "Reduce Miller index to the lowest equivalent integers."
    oldM = M
    g = gcd(M[0], M[1])
    h = gcd(g, M[2])
    while h != 1:
        M = M/h
        g = gcd(M[0], M[1])
        h = gcd(g, M[2])
    if np.dot(oldM, M) > 0:
        return M
    else:
        return -M
Exemple #7
0
def create_parsize_maxbands(nbands, world_size):
    """Safely parse command line parallel arguments for band parallel case."""
    # D: number of domains
    # B: number of band groups
    if parsize_bands is None:
        if parsize_domain is None:
            B = gcd(nbands, world_size)  # largest possible
            D = world_size // B
        else:
            D = parsize_domain
            B = gcd(nbands, world_size // np.prod(D))
    else:
        B = parsize_bands
        D = parsize_domain or world_size // B
    return D, B
Exemple #8
0
def reduceindex(M):
    """Reduce Miller index to the lowest equivalent integers."""
    oldM = M
    g = gcd(M[0], M[1])
    h = gcd(g, M[2])
    while h != 1:
        if h == 0:
            raise ValueError("Division by zero: Are the miller indices linearly dependent?")
        M = M // h
        g = gcd(M[0], M[1])
        h = gcd(g, M[2])
    if np.dot(oldM, M) > 0:
        return M
    else:
        return -M
Exemple #9
0
def reduceindex(M):
    """Reduce Miller index to the lowest equivalent integers."""
    oldM = M
    g = gcd(M[0], M[1])
    h = gcd(g, M[2])
    while h != 1:
        if h == 0:
            raise ValueError(
                "Division by zero: Are the miller indices linearly dependent?")
        M = M // h
        g = gcd(M[0], M[1])
        h = gcd(g, M[2])
    if np.dot(oldM, M) > 0:
        return M
    else:
        return -M
Exemple #10
0
def surface_from_ase(lattice, indices, layers, vacuum=None, tol=1e-10):
    """Create surface from a given lattice and Miller indices.

    lattice: Atoms object or str
        Bulk lattice structure of alloy or pure metal.  Note that the
        unit-cell must be the conventional cell - not the primitive cell.
        One can also give the chemical symbol as a string, in which case the
        correct bulk lattice will be generated automatically.
    indices: sequence of three int
        Surface normal in Miller indices (h,k,l).
    layers: int
        Number of equivalent layers of the slab.
    vacuum: float
        Amount of vacuum added on both sides of the slab.
    
    Originally from ASE v. 3.11
    """

    indices = np.asarray(indices)

    if indices.shape != (3, ) or not indices.any() or indices.dtype != int:
        raise ValueError('%s is an invalid surface type' % indices)

    if isinstance(lattice, str):
        lattice = bulk(lattice, cubic=True)

    h, k, l = indices
    h0, k0, l0 = (indices == 0)
    if h0 and k0 or h0 and l0 or k0 and l0:  # if two indices are zero
        if not h0:
            c1, c2, c3 = [(0, 1, 0), (0, 0, 1), (1, 0, 0)]
        if not k0:
            c1, c2, c3 = [(0, 0, 1), (1, 0, 0), (0, 1, 0)]
        if not l0:
            c1, c2, c3 = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]
    else:
        p, q = ext_gcd(k, l)
        a1, a2, a3 = lattice.cell

        # constants describing the dot product of basis c1 and c2:
        # dot(c1,c2) = k1+i*k2, i in Z
        k1 = np.dot(p * (k * a1 - h * a2) + q * (l * a1 - h * a3),
                    l * a2 - k * a3)
        k2 = np.dot(l * (k * a1 - h * a2) - k * (l * a1 - h * a3),
                    l * a2 - k * a3)

        if abs(k2) > tol:
            i = -int(round(k1 / k2))  # i corresponding to the optimal basis
            p, q = p + i * l, q - i * k

        a, b = ext_gcd(p * k + q * l, h)

        c1 = (p * k + q * l, -p * h, -q * h)
        c2 = np.array((0, l, -k)) // abs(gcd(l, k))
        c3 = (b, a * p, a * q)

    surf = build_from_ase(lattice, np.array([c1, c2, c3]), layers, tol)
    if vacuum is not None:
        surf.center(vacuum=vacuum, axis=2)
    return surf
def surface(lattice, indices, layers, vacuum=None, tol=1e-10):
    """Create surface from a given lattice and Miller indices.

    lattice: Atoms object or str
        Bulk lattice structure of alloy or pure metal.  Note that the
        unit-cell must be the conventional cell - not the primitive cell.
        One can also give the chemical symbol as a string, in which case the
        correct bulk lattice will be generated automatically.
    indices: sequence of three int
        Surface normal in Miller indices (h,k,l).
    layers: int
        Number of equivalent layers of the slab.
    vacuum: float
        Amount of vacuum added on both sides of the slab.
    """

    indices = np.asarray(indices)

    if indices.shape != (3,) or not indices.any() or indices.dtype != int:
        raise ValueError('%s is an invalid surface type' % indices)

    if isinstance(lattice, basestring):
        lattice = bulk(lattice, cubic=True)

    h, k, l = indices
    h0, k0, l0 = (indices == 0)
    if h0 and k0 or h0 and l0 or k0 and l0:  # if two indices are zero
        if not h0:
            c1, c2, c3 = [(0, 1, 0), (0, 0, 1), (1, 0, 0)]
        if not k0:
            c1, c2, c3 = [(0, 0, 1), (1, 0, 0), (0, 1, 0)]
        if not l0:
            c1, c2, c3 = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]
    else:
        p, q = ext_gcd(k, l)
        a1, a2, a3 = lattice.cell

        # constants describing the dot product of basis c1 and c2:
        # dot(c1,c2) = k1+i*k2, i in Z
        k1 = np.dot(p * (k * a1 - h * a2) + q * (l * a1 - h * a3),
                    l * a2 - k * a3)
        k2 = np.dot(l * (k * a1 - h * a2) - k * (l * a1 - h * a3),
                    l * a2 - k * a3)

        if abs(k2) > tol:
            i = -int(round(k1 / k2))  # i corresponding to the optimal basis
            p, q = p + i * l, q - i * k

        a, b = ext_gcd(p * k + q * l, h)

        c1 = (p * k + q * l, -p * h, -q * h)
        c2 = np.array((0, l, -k)) // abs(gcd(l, k))
        c3 = (b, a * p, a * q)

    surf = build(lattice, np.array([c1, c2, c3]), layers, tol)
    if vacuum is not None:
        surf.center(vacuum=vacuum, axis=2)
    return surf
Exemple #12
0
 def _reduce(self):
     N = 0
     for n in self._count.values():
         if N == 0:
             N = n
         else:
             N = gcd(n, N)
     dct = {symb: n // N for symb, n in self._count.items()}
     return dct, N
Exemple #13
0
def frac(f, n=2 * 3 * 4 * 5, tol=1e-6):
    if not isinstance(f, (int, float)):
        return np.array([frac(a, n, tol) for a in f]).T
    if f == 0:
        return 0, 1
    x = n * f
    if abs(x - round(x)) > n * tol:
        raise ValueError
    x = int(round(x))
    d = gcd(x, n)
    return x // d, n // d
Exemple #14
0
    def get_spacegroup_and_volume(self, name, icsdno, natoms):
        # get experimental volume per formula unit
        output = commands.getoutput(
            "grep 'space' /home/jyan/icsd/%s/icsd_%s.cif" % (name, icsdno))
        if "No such file or directory" in output:
            return None, None

        volume = float(
            commands.getoutput(
                "grep '_cell_volume' /home/jyan/icsd/%s/icsd_%s.cif" %
                (name, icsdno)).split()[1])
        formulaunit = float(
            commands.getoutput(
                "grep '_cell_formula_units_Z' /home/jyan/icsd/%s/icsd_%s.cif" %
                (name, icsdno)).split()[1])
        chemformula = commands.getoutput(
            "grep '_chemical_formula_sum' /home/jyan/icsd/%s/icsd_%s.cif" %
            (name, icsdno)).split()
        na = []
        for s in chemformula:
            x = 0
            for i in s:
                if i.isdigit():
                    x = int(i) + 10 * x
            na.append(x)
        if len(na) == 1:
            formulaunit *= na[0]
        else:
            ncell = gcd(na[0], na[1])
            if len(na) > 2:
                for i in range(2, len(na)):
                    ncell = gcd(ncell, na[i])
            formulaunit *= ncell

    #    try:
    #        volume = read.icsd_cif_a("/home/jyan/icsd/%s/icsd_%s.cif"%(name, icsdno)).volume.magnitude
    #    except:
    #        return None, None

        return output.split("'")[1], volume / formulaunit
Exemple #15
0
def distribute_cpus(parsize_domain, parsize_bands,
                    nspins, nibzkpts, comm=world,
                    idiotproof=True, mode='fd'):
    nsk = nspins * nibzkpts
    if mode in ['fd', 'lcao']:
        if parsize_bands is None:
            parsize_bands = 1
    else:
        # Plane wave mode:
        if parsize_bands is None:
            parsize_bands = comm.size // gcd(nsk, comm.size)

    p = Parallelization(comm, nsk)
    return p.build_communicators(domain=np.prod(parsize_domain),
                                 band=parsize_bands)
Exemple #16
0
def surface(lattice, indices, layers, vacuum=None, tol=1e-10, termination=0):
    """Create surface from a given lattice and Miller indices.

    lattice: Atoms object or str
        Bulk lattice structure of alloy or pure metal.  Note that the
        unit-cell must be the conventional cell - not the primitive cell.
        One can also give the chemical symbol as a string, in which case the
        correct bulk lattice will be generated automatically.
    indices: sequence of three int
        Surface normal in Miller indices (h,k,l).
    layers: int
        Number of equivalent layers of the slab.
    vacuum: float
        Amount of vacuum added on both sides of the slab.
    termination: int
        The termination "number" for your crystal. The same value will not
        produce the same termination for different symetrically identical
        bulk structures, but changing this value allows your to explore all
        the possible terminations for the bulk structure you provide it.
        note: this code is not well tested
    """

    indices = np.asarray(indices)

    if indices.shape != (3,) or not indices.any() or indices.dtype != int:
        raise ValueError('%s is an invalid surface type' % indices)

    if isinstance(lattice, basestring):
        lattice = bulk(lattice, cubic=True)

    h, k, l = indices
    h0, k0, l0 = (indices == 0)
    
    if termination != 0:  #changing termination
        import warnings
        warnings.warn('Work on changing terminations is currently in '
                      'progress.  Code may not behave as expected.')
        lattice1 = deepcopy(lattice)
        cell = lattice1.get_cell()
        pt = [0,0,0]
        millers = list(indices)
        for index,item in enumerate(millers):
            if item == 0:
                millers[index] = 10**9 #make zeros large numbers
            elif pt == [0,0,0]:        #for numerical stability
                pt = list(cell[index]/float(item)/np.linalg.norm(cell[index]))
        h1,k1,l1 = millers
        N = np.array(cell[0]/h1+cell[1]/k1+cell[2]/l1)
        n = N/np.linalg.norm(N)# making a unit vector normal to cut plane
        d = [np.round(np.dot(n,(a-pt)),4) for a in lattice.get_scaled_positions()]
        d = set(d)
        d = sorted(list(d))
        d = [0]+d #distances of atoms from cut plane
        displacement = (h*cell[0]+k*cell[1]+l*cell[2])*d[termination]
        lattice1.positions += displacement
        lattice = lattice1
       
    if h0 and k0 or h0 and l0 or k0 and l0:  # if two indices are zero
        if not h0:
            c1, c2, c3 = [(0, 1, 0), (0, 0, 1), (1, 0, 0)]
        if not k0:
            c1, c2, c3 = [(0, 0, 1), (1, 0, 0), (0, 1, 0)]
        if not l0:
            c1, c2, c3 = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]
    else:
        p, q = ext_gcd(k, l)
        a1, a2, a3 = lattice.cell

        # constants describing the dot product of basis c1 and c2:
        # dot(c1,c2) = k1+i*k2, i in Z
        k1 = np.dot(p * (k * a1 - h * a2) + q * (l * a1 - h * a3),
                    l * a2 - k * a3)
        k2 = np.dot(l * (k * a1 - h * a2) - k * (l * a1 - h * a3),
                    l * a2 - k * a3)

        if abs(k2) > tol:
            i = -int(round(k1 / k2))  # i corresponding to the optimal basis
            p, q = p + i * l, q - i * k

        a, b = ext_gcd(p * k + q * l, h)

        c1 = (p * k + q * l, -p * h, -q * h)
        c2 = np.array((0, l, -k)) // abs(gcd(l, k))
        c3 = (b, a * p, a * q)

    surf = build(lattice, np.array([c1, c2, c3]), layers, tol)
    if vacuum is not None:
        surf.center(vacuum=vacuum, axis=2)
    return surf
Exemple #17
0
N = 2000  # number of bands
repeats = 20

try:
    N = int(sys.argv[1])
    K = int(sys.argv[2])
except (IndexError, ValueError):
    N = 6
    K = 3
    repeats = 3

# B: number of band groups
# D: number of domains
if parsize_bands is None:
    if parsize_domain is None:
        B = gcd(N, world.size)
        D = world.size // B
    else:
        B = world.size // np.prod(parsize_domain)
        D = parsize_domain
else:
    B = parsize_bands
    D = world.size // B

M = N // B     # number of bands per group
assert M * B == N, 'M=%d, B=%d, N=%d' % (M,B,N)

h = 0.2        # grid spacing
a = h * G      # side length of box
assert np.prod(D) * B == world.size, 'D=%s, B=%d, W=%d' % (D,B,world.size)
Exemple #18
0
def nanotube(n, m, length=1, bond=1.42, symbol='C', verbose=False):
    if n < m:
        m, n = n, m
        sign = -1
    else:
        sign = 1

    nk = 6000
    sq3 = sqrt(3.0)
    a = sq3 * bond
    l2 = n * n + m * m + n * m
    l = sqrt(l2)

    nd = gcd(n, m)
    if (n - m) % (3 * nd) == 0:
        ndr = 3 * nd
    else:
        ndr = nd

    nr = (2 * m + n) / ndr
    ns = -(2 * n + m) / ndr
    nn = 2 * l2 / ndr

    ichk = 0
    if nr == 0:
        n60 = 1
    else:
        n60 = nr * 4

    absn = abs(n60)
    nnp = []
    nnq = []
    for i in range(-absn, absn + 1):
        for j in range(-absn, absn + 1):
            j2 = nr * j - ns * i
            if j2 == 1:
                j1 = m * i - n * j
                if j1 > 0 and j1 < nn:
                    ichk += 1
                    nnp.append(i)
                    nnq.append(j)

    if ichk == 0:
        raise RuntimeError('not found p, q strange!!')
    if ichk >= 2:
        raise RuntimeError('more than 1 pair p, q strange!!')

    nnnp = nnp[0]
    nnnq = nnq[0]

    if verbose:
        print 'the symmetry vector is', nnnp, nnnq

    lp = nnnp * nnnp + nnnq * nnnq + nnnp * nnnq
    r = a * sqrt(lp)
    c = a * l
    t = sq3 * c / ndr

    if 2 * nn > nk:
        raise RuntimeError('parameter nk is too small!')

    rs = c / (2.0 * np.pi)

    if verbose:
        print 'radius=', rs, t

    q1 = np.arctan((sq3 * m) / (2 * n + m))
    q2 = np.arctan((sq3 * nnnq) / (2 * nnnp + nnnq))
    q3 = q1 - q2

    q4 = 2.0 * np.pi / nn
    q5 = bond * np.cos((np.pi / 6.0) - q1) / c * 2.0 * np.pi

    h1 = abs(t) / abs(np.sin(q3))
    h2 = bond * np.sin((np.pi / 6.0) - q1)

    ii = 0
    x, y, z = [], [], []
    for i in range(nn):
        x1, y1, z1 = 0, 0, 0

        k = np.floor(i * abs(r) / h1)
        x1 = rs * np.cos(i * q4)
        y1 = rs * np.sin(i * q4)
        z1 = (i * abs(r) - k * h1) * np.sin(q3)
        kk2 = abs(np.floor((z1 + 0.0001) / t))
        if z1 >= t - 0.0001:
            z1 -= t * kk2
        elif z1 < 0:
            z1 += t * kk2
        ii += 1

        x.append(x1)
        y.append(y1)
        z.append(z1)
        z3 = (i * abs(r) - k * h1) * np.sin(q3) - h2
        ii += 1

        if z3 >= 0 and z3 < t:
            x2 = rs * np.cos(i * q4 + q5)
            y2 = rs * np.sin(i * q4 + q5)
            z2 = (i * abs(r) - k * h1) * np.sin(q3) - h2
            x.append(x2)
            y.append(y2)
            z.append(z2)
        else:
            x2 = rs * np.cos(i * q4 + q5)
            y2 = rs * np.sin(i * q4 + q5)
            z2 = (i * abs(r) - (k + 1) * h1) * np.sin(q3) - h2
            kk = abs(np.floor(z2 / t))
            if z2 >= t - 0.0001:
                z2 -= t * kk
            elif z2 < 0:
                z2 += t * kk
            x.append(x2)
            y.append(y2)
            z.append(z2)

    ntotal = 2 * nn
    X = []
    for i in range(ntotal):
        X.append([x[i], y[i], sign * z[i]])

    if length > 1:
        xx = X[:]
        for mnp in range(2, length + 1):
            for i in range(len(xx)):
                X.append(xx[i][:2] + [xx[i][2] + (mnp - 1) * t])

    TransVec = t
    NumAtom = ntotal * length
    Diameter = rs * 2
    ChiralAngle = np.arctan((sq3 * n) / (2 * m + n)) / (np.pi * 180)

    cell = [Diameter * 2, Diameter * 2, length * t]
    atoms = Atoms(symbol + str(NumAtom),
                  positions=X,
                  cell=cell,
                  pbc=[False, False, True])
    atoms.center()
    if verbose:
        print 'translation vector =', TransVec
        print 'diameter = ', Diameter
        print 'chiral angle = ', ChiralAngle
    return atoms
Exemple #19
0
def nanotube(n, m, length=1, bond=1.42, symbol="C", verbose=False):
    if n < m:
        m, n = n, m
        sign = -1
    else:
        sign = 1

    nk = 6000
    sq3 = sqrt(3.0)
    a = sq3 * bond
    l2 = n * n + m * m + n * m
    l = sqrt(l2)
    dt = a * l / np.pi

    nd = gcd(n, m)
    if (n - m) % (3 * nd) == 0:
        ndr = 3 * nd
    else:
        ndr = nd

    nr = (2 * m + n) / ndr
    ns = -(2 * n + m) / ndr
    nt2 = 3 * l2 / ndr / ndr
    nt = np.floor(sqrt(nt2))
    nn = 2 * l2 / ndr

    ichk = 0
    if nr == 0:
        n60 = 1
    else:
        n60 = nr * 4

    absn = abs(n60)
    nnp = []
    nnq = []
    for i in range(-absn, absn + 1):
        for j in range(-absn, absn + 1):
            j2 = nr * j - ns * i
            if j2 == 1:
                j1 = m * i - n * j
                if j1 > 0 and j1 < nn:
                    ichk += 1
                    nnp.append(i)
                    nnq.append(j)

    if ichk == 0:
        raise RuntimeError("not found p, q strange!!")
    if ichk >= 2:
        raise RuntimeError("more than 1 pair p, q strange!!")

    nnnp = nnp[0]
    nnnq = nnq[0]

    if verbose:
        print "the symmetry vector is", nnnp, nnnq

    lp = nnnp * nnnp + nnnq * nnnq + nnnp * nnnq
    r = a * sqrt(lp)
    c = a * l
    t = sq3 * c / ndr

    if 2 * nn > nk:
        raise RuntimeError("parameter nk is too small!")

    rs = c / (2.0 * np.pi)

    if verbose:
        print "radius=", rs, t

    q1 = np.arctan((sq3 * m) / (2 * n + m))
    q2 = np.arctan((sq3 * nnnq) / (2 * nnnp + nnnq))
    q3 = q1 - q2

    q4 = 2.0 * np.pi / nn
    q5 = bond * np.cos((np.pi / 6.0) - q1) / c * 2.0 * np.pi

    h1 = abs(t) / abs(np.sin(q3))
    h2 = bond * np.sin((np.pi / 6.0) - q1)

    ii = 0
    x, y, z = [], [], []
    for i in range(nn):
        x1, y1, z1 = 0, 0, 0

        k = np.floor(i * abs(r) / h1)
        x1 = rs * np.cos(i * q4)
        y1 = rs * np.sin(i * q4)
        z1 = (i * abs(r) - k * h1) * np.sin(q3)
        kk2 = abs(np.floor((z1 + 0.0001) / t))
        if z1 >= t - 0.0001:
            z1 -= t * kk2
        elif z1 < 0:
            z1 += t * kk2
        ii += 1

        x.append(x1)
        y.append(y1)
        z.append(z1)
        z3 = (i * abs(r) - k * h1) * np.sin(q3) - h2
        ii += 1

        if z3 >= 0 and z3 < t:
            x2 = rs * np.cos(i * q4 + q5)
            y2 = rs * np.sin(i * q4 + q5)
            z2 = (i * abs(r) - k * h1) * np.sin(q3) - h2
            x.append(x2)
            y.append(y2)
            z.append(z2)
        else:
            x2 = rs * np.cos(i * q4 + q5)
            y2 = rs * np.sin(i * q4 + q5)
            z2 = (i * abs(r) - (k + 1) * h1) * np.sin(q3) - h2
            kk = abs(np.floor(z2 / t))
            if z2 >= t - 0.0001:
                z2 -= t * kk
            elif z2 < 0:
                z2 += t * kk
            x.append(x2)
            y.append(y2)
            z.append(z2)

    ntotal = 2 * nn
    X = []
    for i in range(ntotal):
        X.append([x[i], y[i], sign * z[i]])

    if length > 1:
        xx = X[:]
        for mnp in range(2, length + 1):
            for i in range(len(xx)):
                X.append(xx[i][:2] + [xx[i][2] + (mnp - 1) * t])

    TransVec = t
    NumAtom = ntotal * length
    Diameter = rs * 2
    ChiralAngle = np.arctan((sq3 * n) / (2 * m + n)) / (np.pi * 180)

    cell = [Diameter * 2, Diameter * 2, length * t]
    atoms = Atoms(symbol + str(NumAtom), positions=X, cell=cell, pbc=[False, False, True])
    atoms.center()
    if verbose:
        print "translation vector =", TransVec
        print "diameter = ", Diameter
        print "chiral angle = ", ChiralAngle
    return atoms
Exemple #20
0
def oriented_surface(lattice,
                     indices,
                     layers,
                     vacuum=None,
                     tol=1e-10,
                     orient=(1, 0)):
    """Create surface from a given lattice and Miller indices.

    lattice: Atoms object or str
        Bulk lattice structure of alloy or pure metal.  Note that the
        unit-cell must be the conventional cell - not the primitive cell.
        One can also give the chemical symbol as a string, in which case the
        correct bulk lattice will be generated automatically.
    indices: sequence of three int
        Surface normal in Miller indices (h,k,l).
    layers: int
        Number of equivalent layers of the slab.
    vacuum: float
        Amount of vacuum added on both sides of the slab.
    """

    orient = np.asarray(orient)
    if orient.shape != (2, ) or not orient.any() or orient.dtype != int:
        raise ValueError('%s is an invalid orientation type' % orient)

    indices = np.asarray(indices)
    if indices.shape != (3, ) or not indices.any() or indices.dtype != int:
        raise ValueError('%s is an invalid surface type' % indices)

    if isinstance(lattice, basestring):
        lattice = bulk(lattice, cubic=True)

    h, k, l = indices
    m, n = orient
    h0, k0, l0 = (indices == 0)
    if h0 and k0 or h0 and l0 or k0 and l0:  # if two indices are zero
        if not h0:
            c1, c2, c3 = [(0, 1, 0), (0, 0, 1), (1, 0, 0)]
        if not k0:
            c1, c2, c3 = [(0, 0, 1), (1, 0, 0), (0, 1, 0)]
        if not l0:
            c1, c2, c3 = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]
    else:
        a1, a2, a3 = lattice.cell

        # RZK: determine two surface vectors
        p, q = ext_gcd(k, l)
        # dot(c1,c2) = k1+i*k2, i in Z
        # RZK: k1 = (p*t1 + q.t2).t3
        k1 = np.dot(p * (k * a1 - h * a2) + q * (l * a1 - h * a3),
                    l * a2 - k * a3)
        # RZK: k2 = (l*t1 + k.t2).t3
        k2 = np.dot(l * (k * a1 - h * a2) - k * (l * a1 - h * a3),
                    l * a2 - k * a3)

        if abs(k2) > tol:
            i = -int(round(
                k1 /
                k2))  # RZK: i -- c in the PDF -- determines the optimal basis
            p, q = p + i * l, q - i * k

        # RZK: determine the vacuum vector
        a, b = ext_gcd(p * k + q * l, h)

        c1 = (p * k + q * l, -p * h, -q * h)  # RZK: optimal surface vector 1
        c2 = np.array((0, l, -k)) // abs(gcd(
            l, k))  # RZK: surface vector 2 = normalized(t3)
        c3 = (b, a * p, a * q)  # RZK: vacuum vector

        # RZK!!: the following lines are modified
        print("c1 =", c1, ", c2 =", c2, ", c3 =", c3)
        c1n = (m * c1[0] + n * c2[0], m * c1[1] + n * c2[1],
               m * c1[2] + n * c2[2])
        c2n = (-n * c1[0] + m * c2[0], -n * c1[1] + m * c2[1],
               -n * c1[2] + m * c2[2])
        print("c1n=", c1n, ", c2n=", c2n)

    surf = build(lattice, np.array([c1n, c2n, c3]), layers, tol)
    if vacuum is not None:
        surf.center(vacuum=vacuum, axis=2)
    return surf
Exemple #21
0
    def find_k_along_path(self, plot_BZ=True):
        """Finds the k-points along the bandpath present in the
           original calculation"""
        kd = self.kd
        acell_cv = self.acell_cv
        bcell_cv = self.bcell_cv
        kpoints = self.kpoints

        if plot_BZ:
            """Plotting the points in the Brillouin Zone"""
            kp_1bz = to1bz(kd.bzk_kc, acell_cv)

            bzk_kcv = np.dot(kd.bzk_kc, bcell_cv)
            kp_1bz_v = np.dot(kp_1bz, bcell_cv)

            import matplotlib.pyplot as plt
            plt.plot(bzk_kcv[:, 0], bzk_kcv[:, 1], 'xg')
            plt.plot(kp_1bz_v[:, 0], kp_1bz_v[:, 1], 'ob')
            for ik in range(1, len(kpoints)):
                kpoint1_v = np.dot(kpoints[ik], bcell_cv)
                kpoint2_v = np.dot(kpoints[ik - 1], bcell_cv)
                plt.plot([kpoint1_v[0], kpoint2_v[0]], [kpoint1_v[1],
                                                        kpoint2_v[1]], '--vr')

        """Finding the points along given directions"""
        print('Finding the kpoints along the path')
        N_c = kd.N_c
        wpts_xc = kpoints

        x_x = []
        k_xc = []
        k_x = []
        x = 0.
        X = []
        for nwpt in range(1, len(wpts_xc)):
            X.append(x)
            to_c = wpts_xc[nwpt]
            from_c = wpts_xc[nwpt - 1]
            vec_c = to_c - from_c
            print('From ', from_c, ' to ', to_c)
            Nv_c = (vec_c * N_c).round().astype(int)
            Nv = abs(gcd(gcd(Nv_c[0], Nv_c[1]), Nv_c[2]))
            print(Nv, ' points found')
            dv_c = vec_c / Nv
            dv_v = np.dot(dv_c, bcell_cv)
            dx = np.linalg.norm(dv_v)
            if nwpt == len(wpts_xc) - 1:
                # X.append(Nv * dx)
                Nv += 1
            for n in range(Nv):
                k_c = from_c + n * dv_c
                bzk_c = to1bz(np.array([k_c]), acell_cv)[0]
                ikpt = kd.where_is_q(bzk_c, kd.bzk_kc)
                x_x.append(x)
                k_xc.append(k_c)
                k_x.append(ikpt)
                x += dx
        X.append(x_x[-1])
        if plot_BZ is True:
            for ik in range(len(k_xc)):
                ktemp_xcv = np.dot(k_xc[ik], bcell_cv)
                plt.plot(ktemp_xcv[0], ktemp_xcv[1], 'xr', markersize=10)
            plt.show()

        return x_x, k_xc, k_x, X
Exemple #22
0
    def prune_symmetries_atoms(self, spos_ac):
        """Remove symmetries that are not satisfied by the atoms."""

        if len(spos_ac) == 0:
            return

        # Build lists of atom numbers for each type of atom - one
        # list for each combination of atomic number, setup type,
        # magnetic moment and basis set:
        a_ij = {}
        for a, id in enumerate(self.id_a):
            if id in a_ij:
                a_ij[id].append(a)
            else:
                a_ij[id] = [a]

        a_j = a_ij[self.id_a[0]]  # just pick the first species

        # if supercell disable fractional translations:
        if not self.symmorphic:
            op_cc = np.identity(3, int)
            ftrans_sc = spos_ac[a_j[1:]] - spos_ac[a_j[0]]
            ftrans_sc -= np.rint(ftrans_sc)
            for ft_c in ftrans_sc:
                a_a = self.check_one_symmetry(spos_ac, op_cc, ft_c, a_ij)
                if a_a is not None:
                    self.symmorphic = True
                    break

        symmetries = []
        ftsymmetries = []

        # go through all possible symmetry operations
        for op_cc in self.op_scc:
            # first ignore fractional translations
            a_a = self.check_one_symmetry(spos_ac, op_cc, [0, 0, 0], a_ij)
            if a_a is not None:
                symmetries.append((op_cc, [0, 0, 0], a_a))
            elif not self.symmorphic:
                # check fractional translations
                sposrot_ac = np.dot(spos_ac, op_cc)
                ftrans_jc = sposrot_ac[a_j] - spos_ac[a_j[0]]
                ftrans_jc -= np.rint(ftrans_jc)
                for ft_c in ftrans_jc:
                    try:
                        nom_c, denom_c = frac(ft_c, tol=self.tol)
                    except ValueError:
                        continue
                    ft_c = nom_c / denom_c
                    a_a = self.check_one_symmetry(spos_ac, op_cc, ft_c, a_ij)
                    if a_a is not None:
                        ftsymmetries.append((op_cc, ft_c, a_a))
                        for c, d in enumerate(denom_c):
                            self.gcd_c[c] = gcd(self.gcd_c[c] * d, d)

        # Add symmetry operations with fractional translations at the end:
        symmetries.extend(ftsymmetries)
        self.op_scc = np.array([sym[0] for sym in symmetries])
        self.ft_sc = np.array([sym[1] for sym in symmetries])
        self.a_sa = np.array([sym[2] for sym in symmetries])

        inv_cc = -np.eye(3, dtype=int)
        self.has_inversion = (self.op_scc == inv_cc).all(2).all(1).any()