Пример #1
0
 def read_supercell(self):
     """ Reads a supercell from the Sile """
     # 1st line is number of supercells
     nsc = _a.fromiteri(map(int, self.readline().split()[:3]))
     self.readline()  # natoms, nspecies
     self.readline()  # species
     cell = _a.fromiterd(map(float, self.readline().split()[:9]))
     # Typically ScaleUp uses very large unit-cells
     # so supercells will typically be restricted to [3, 3, 3]
     return SuperCell(cell * Bohr2Ang, nsc=nsc)
Пример #2
0
    def read_geometry(self, primary=False, **kwargs):
        """ Reads a geometry from the Sile """
        # 1st line is number of supercells
        nsc = _a.fromiteri(map(int, self.readline().split()[:3]))
        na, ns = map(int, self.readline().split()[:2])
        # Convert species to atom objects
        try:
            species = get_sile(self.file.rsplit('REF', 1)[0] +
                               'orbocc').read_atom()
        except:
            species = [Atom(s) for s in self.readline().split()[:ns]]

        # Total number of super-cells
        if primary:
            # Only read in the primary unit-cell
            ns = 1
        else:
            ns = np.prod(nsc)

        cell = _a.fromiterd(map(float, self.readline().split()))
        try:
            cell.shape = (3, 3)
            if primary:
                cell[0, :] /= nsc[0]
                cell[1, :] /= nsc[1]
                cell[2, :] /= nsc[2]
        except:
            c = np.empty([3, 3], np.float64)
            c[0, 0] = 1. + cell[0]
            c[0, 1] = cell[5] / 2.
            c[0, 2] = cell[4] / 2.
            c[1, 0] = cell[5] / 2.
            c[1, 1] = 1. + cell[1]
            c[1, 2] = cell[3] / 2.
            c[2, 0] = cell[4] / 2.
            c[2, 1] = cell[3] / 2.
            c[2, 2] = 1. + cell[2]
            cell = c * Ang2Bohr
        sc = SuperCell(cell * Bohr2Ang, nsc=nsc)

        # Create list of coordinates and atoms
        xyz = np.empty([na * ns, 3], np.float64)
        atoms = [None] * na * ns

        # Read the geometry
        for ia in range(na * ns):

            # Retrieve line
            #   ix  iy  iz  ia  is   x  y  z
            line = self.readline().split()

            atoms[ia] = species[int(line[4]) - 1]
            xyz[ia, :] = _a.fromiterd(map(float, line[5:8]))

        return Geometry(xyz * Bohr2Ang, atoms, sc=sc)
Пример #3
0
 def Neumann(idx_bc, idx_p1):
     # TODO check this BC
     # Set all boundary equations to 0
     s = array_arange(A.indptr[idx_bc], A.indptr[idx_bc+1])
     A.data[s] = 0
     # force the boundary cells to equal the neighbouring cell
     A[idx_bc, idx_bc] = -C # I am not sure this is correct, but setting it to 0 does NOT work
     A[idx_bc, idx_p1] = C
     # ensure the neighbouring cell doesn't connect to the boundary (no back propagation)
     A[idx_p1, idx_bc] = 0
     # Ensure the sum of the source for the neighbouring cells equals 0
     # To make it easy to figure out the diagonal elements we first
     # set it to 0, then sum off-diagonal terms, and set the diagonal
     # equal to the sum.
     A[idx_p1, idx_p1] = 0
     n = A.indptr[idx_p1+1] - A.indptr[idx_p1]
     s = array_arange(A.indptr[idx_p1], n=n)
     n = np.split(A.data[s], np.cumsum(n)[:-1])
     n = _a.fromiteri(map(np.sum, n))
     # update diagonal
     A[idx_p1, idx_p1] = -n
     del s, n
     A.eliminate_zeros()
     b[idx_bc] = 0.