Beispiel #1
0
    def read_geometry(self):
        """ Read geometry from the contained file """

        # First we read in the geometry
        sc = self.read_supercell()

        # Try and go to the first model record
        in_model, l = self._step_record('MODEL')

        idx = []
        tags = []
        xyz = []
        Z = []
        if in_model:
            l = self.readline()
            def is_atom(line):
                return l.startswith('ATOM') or l.startswith('HETATM')
            def is_end_model(line):
                return l.startswith('ENDMDL') or l == ''
            while not is_end_model(l):
                if is_atom(l):
                    idx.append(int(l[6:11]))
                    tags.append(l[12:16].strip())
                    xyz.append([float(l[30:38]), float(l[38:46]), float(l[46:54])])
                    Z.append(l[76:78].strip())
                l = self.readline()

        # First sort all atoms according to the idx array
        idx = np.array(idx)
        idx = np.argsort(idx)
        xyz = np.array(xyz)[idx, :]
        tags = [tags[i] for i in idx]
        Z = [Z[i] for i in idx]

        # Create the atom list
        atoms = Atoms(Atom(Z[0], tag=tags[0]), na=len(Z))
        for i, a in enumerate(map(Atom, Z, tags)):
            try:
                s = atoms.index(a)
            except:
                s = len(atoms.atom)
                atoms._atom.append(a)
            atoms._specie[i] = s

        return Geometry(xyz, atoms, sc=sc)
Beispiel #2
0
    def _r_basis_fdf(self):
        # Read basis from fdf file
        spcs = self.get('ChemicalSpeciesLabel')
        if spcs is None:
            # We haven't found the chemical and species label
            # so return nothing
            return None

        # Now spcs contains the block of the chemicalspecieslabel
        atom = [None] * len(spcs)
        for spc in spcs:
            idx, Z, lbl = spc.split()[:3]
            idx = int(idx) - 1  # F-indexing
            Z = int(Z)
            lbl = lbl.strip()

            atom[idx] = Atom(Z=Z, tag=lbl)
        return atom
Beispiel #3
0
    def test_repeat3(self):
        R, param = [0.1, 1.1, 2.1, 3.1], [1., 2., 3., 4.]

        # Create reference
        g = Geometry([[0] * 3], Atom('H', R=[4.]), sc=[1.] * 3)
        g.set_nsc([7] * 3)

        # Now create bigger geometry
        G = g.repeat(2, 0).repeat(2, 1).repeat(2, 2)

        HG = Hamiltonian(G.repeat(2, 0).repeat(2, 1).repeat(2, 2))
        HG.construct([R, param])
        HG.finalize()
        H = Hamiltonian(G)
        H.construct([R, param])
        H.finalize()
        H = H.repeat(2, 0).repeat(2, 1).repeat(2, 2)
        assert_true(HG.spsame(H))
Beispiel #4
0
def test_yield_manifolds_eigenvalues():
    g = Geometry([[i, 0, 0] for i in range(10)],
                 Atom(6, R=1.01),
                 sc=SuperCell([10, 1, 5.], nsc=[3, 3, 1]))
    H = Hamiltonian(g, dtype=np.float64)
    H.construct([(0.1, 1.5), (1., 0.1)])

    all_manifolds = []
    for manifold in yield_manifolds(H.eigh()):
        all_manifolds.extend(manifold)

    assert np.allclose(all_manifolds, np.arange(len(H)))

    all_manifolds = []
    for manifold in yield_manifolds(H.tile(2, 0).eigh()):
        all_manifolds.extend(manifold)

    assert np.allclose(all_manifolds, np.arange(len(H) * 2))
Beispiel #5
0
    def test_untile_segment_three(self, axis):
        # one should not untile
        nsc = [3] * 3
        nsc[axis] = 1
        geometry = Geometry([0] * 3, Atom(1, R=1.001), SuperCell(1, nsc=nsc))
        geometry = geometry.tile(4, axis)
        s = SparseAtom(geometry)
        s.construct([[0.1, 1.01], [1, 2]])
        s[0, 3] = 2
        s[3, 0] = 2

        # check that untiling twice is not the same as untiling 4 times and coupling it
        s4 = s.untile(4, axis).tile(2, axis)
        for seg in range(1, 4):
            sx = s.untile(4, axis, segment=seg).tile(2, axis)
            ds = s4 - sx
            ds.finalize()
            assert np.absolute(ds)._csr._D.sum() == pytest.approx(0.)
Beispiel #6
0
def test_sparse_orbital_sub_orbital():
    atom = Atom(1, (1, 2, 3))
    g = fcc(1., atom) * 2
    s = SparseOrbital(g)

    # take out some orbitals
    s1 = s.sub_orbital(atom, 1)
    assert s1.geometry.no == s1.geometry.na

    s2 = s.sub_orbital(atom, atom.orbitals[1])
    assert s1 == s2

    s2 = s.sub_orbital(atom, [atom.orbitals[1]])
    assert s1 == s2

    s2 = s.sub_orbital(atom, [atom.orbitals[1], atom.orbitals[0]])
    assert s2.geometry.atoms[0].orbitals[0] == atom.orbitals[0]
    assert s2.geometry.atoms[0].orbitals[1] == atom.orbitals[1]
Beispiel #7
0
        def __init__(self):
            bond = 1.42
            sq3h = 3.**.5 * 0.5
            self.sc = SuperCell(
                np.array([[1.5, sq3h, 0.], [1.5, -sq3h, 0.], [0., 0., 10.]],
                         np.float64) * bond,
                nsc=[3, 3, 1])

            n = 60
            rf = np.linspace(0, bond * 1.01, n)
            rf = (rf, rf)
            orb = SphericalOrbital(1, rf, 2.)
            C = Atom(6, orb.toAtomicOrbital())
            self.g = Geometry(
                np.array([[0., 0., 0.], [1., 0., 0.]], np.float64) * bond,
                atoms=C,
                sc=self.sc)
            self.S = Overlap(self.g)
Beispiel #8
0
    def read_hamiltonian(self, **kwargs):
        """ Returns the electronic structure from the siesta.TSHS file """

        # Now read the sizes used...
        Gamma, spin, no, no_s, nnz = _siesta.read_hsx_sizes(self.file)
        ncol, col, dH, dS, dxij = _siesta.read_hsx_hsx(self.file, Gamma, spin, no, no_s, nnz)

        # Try and immediately attach a geometry
        geom = kwargs.get('geometry', kwargs.get('geom', None))
        if geom is None:
            # We have *no* clue about the
            if np.allclose(dxij, 0.):
                # We truly, have no clue,
                # Just generate a boxed system
                xyz = [[x, 0, 0] for x in range(no)]
                geom = Geometry(xyz, Atom(1), sc=[no, 1, 1])
            else:
                # Try to figure out the supercell
                warn(self.__class__.__name__ + '.read_hamiltonian '
                     '(currently we can not calculate atomic positions from xij array)')
        if geom.no != no:
            raise SileError(self.__class__.__name__ + '.read_hamiltonian could not use the '
                            'passed geometry as the number of atoms or orbitals is '
                            'inconsistent with HSX file.')

        # Create the Hamiltonian container
        H = Hamiltonian(geom, spin, nnzpr=1, dtype=np.float32, orthogonal=False)

        # Create the new sparse matrix
        H._csr.ncol = ncol.astype(np.int32, copy=False)
        H._csr.ptr = np.insert(np.cumsum(ncol, dtype=np.int32), 0, 0)
        # Correct fortran indices
        H._csr.col = col.astype(np.int32, copy=False) - 1
        H._csr._nnz = len(col)

        H._csr._D = np.empty([nnz, spin+1], np.float32)
        H._csr._D[:, :spin] = dH[:, :]
        H._csr._D[:, spin] = dS[:]

        # Convert the supercells to sisl supercells
        if no_s // no == np.product(geom.nsc):
            _csr_from_siesta(geom, H._csr)

        return H
Beispiel #9
0
    def test_so1(self):
        g = Geometry([[i, 0, 0] for i in range(10)], Atom(6, R=1.01), sc=[100])
        H = Hamiltonian(g, dtype=np.float64, spin=8)
        for i in range(10):
            j = range(i * 4, i * 4 + 3)
            H[i, i, 0] = 0.
            H[i, i, 1] = 0.
            H[i, i, 2] = 0.1
            H[i, i, 3] = 0.1
            H[i, i, 4] = 0.1
            H[i, i, 5] = 0.1
            H[i, i, 6] = 0.1
            H[i, i, 7] = 0.1
            if i > 0:
                H[i, i - 1, 0] = 1.
                H[i, i - 1, 1] = 1.
            if i < 9:
                H[i, i + 1, 0] = 1.
                H[i, i + 1, 1] = 1.
        eig1 = H.eigh()
        # Check TimeSelector
        for i in range(2):
            assert_true(np.allclose(H.eigh(), eig1))
        assert_true(len(H.eigh()) == len(H))

        H1 = Hamiltonian(g, dtype=np.float64, spin=Spin('spin-orbit'))
        for i in range(10):
            j = range(i * 4, i * 4 + 3)
            H1[i, i, 0] = 0.
            H1[i, i, 1] = 0.
            H1[i, i, 2] = 0.1
            H1[i, i, 3] = 0.1
            if i > 0:
                H1[i, i - 1, 0] = 1.
                H1[i, i - 1, 1] = 1.
            if i < 9:
                H1[i, i + 1, 0] = 1.
                H1[i, i + 1, 1] = 1.
        assert_true(H1.spsame(H))
        eig1 = H1.eigh()
        # Check TimeSelector
        for i in range(2):
            assert_true(np.allclose(H1.eigh(), eig1))
        assert_true(np.allclose(H.eigh(), H1.eigh()))
Beispiel #10
0
    def test_op3(self, setup):
        g = Geometry([[i, 0, 0] for i in range(100)],
                     Atom(6, R=1.01),
                     sc=[100])
        H = Hamiltonian(g, dtype=np.int32)
        Hc = H.copy()
        del Hc

        # Create initial stuff
        for i in range(10):
            j = range(i * 4, i * 4 + 3)
            H[0, j] = i

        for op in ['add', 'sub', 'mul', 'pow']:
            func = getattr(H, '__{}__'.format(op))
            h = func(1)
            assert h.dtype == np.int32
            h = func(1.)
            assert h.dtype == np.float64
            if op != 'pow':
                h = func(1.j)
                assert h.dtype == np.complex128

        H = H.copy(dtype=np.float64)
        for op in ['add', 'sub', 'mul', 'pow']:
            func = getattr(H, '__{}__'.format(op))
            h = func(1)
            assert h.dtype == np.float64
            h = func(1.)
            assert h.dtype == np.float64
            if op != 'pow':
                h = func(1.j)
                assert h.dtype == np.complex128

        H = H.copy(dtype=np.complex128)
        for op in ['add', 'sub', 'mul', 'pow']:
            func = getattr(H, '__{}__'.format(op))
            h = func(1)
            assert h.dtype == np.complex128
            h = func(1.)
            assert h.dtype == np.complex128
            if op != 'pow':
                h = func(1.j)
                assert h.dtype == np.complex128
Beispiel #11
0
    def read_geometry(self):
        """ Returns `Geometry` object from the CUBE file """
        na, sc = self.read_supercell(na=True)

        if na == 0:
            return None

        # Start reading the geometry
        xyz = np.empty([na, 3], np.float64)
        atom = []
        for ia in range(na):
            tmp = self.readline().split()
            atom.append(Atom(int(tmp[0])))
            xyz[ia, 0] = float(tmp[2])
            xyz[ia, 1] = float(tmp[3])
            xyz[ia, 2] = float(tmp[4])

        xyz /= Ang2Bohr
        return Geometry(xyz, atom, sc=sc)
Beispiel #12
0
def test_sparse_orbital_append_scale(n0, n1, n2, axis):
    g = fcc(1., Atom(1, R=1.98)) * 2
    dists = np.insert(g.distance(0, R=g.maxR()) + 0.001, 0, 0.001)
    connect = np.arange(dists.size, dtype=np.float64) / 5
    s = SparseOrbital(g)
    s.construct([dists, connect])
    s = s.tile(2, 0).tile(2, 1).tile(2, 2)
    s1 = s.tile(n0, 0).tile(n1, 1).tile(n2, 2)
    s2 = s1.copy()
    # Resulting full sparse-geometry
    sf = s1.tile(2, axis)
    for i in range(sf.shape[0]):
        sf._csr._extend_empty(i, 11)

    # Now perform some appends and randomizations
    idx1 = np.arange(s1.na)
    idx2 = np.arange(s2.na)

    np.random.seed(42)
    shuffle = np.random.shuffle

    # Test 4 permutations
    for _ in range(3):
        shuffle(idx1)
        shuffle(idx2)

        s = sf.sub(np.concatenate([idx1, s1.na + idx2]))
        s.finalize()

        sout = s1.sub(idx1).append(s2.sub(idx2), axis, scale=(2., 0))
        sout = (sout + sout.transpose()) * 0.5
        assert sout.spsame(s)
        sout.finalize()
        assert np.allclose(s._csr._D, sout._csr._D)

        sout = s1.sub(idx1).append(s2.sub(idx2), axis, scale=(0., 2.))
        sout.finalize()
        # Ensure that some elements are not the same!
        assert not np.allclose(s._csr._D, sout._csr._D)
        sout = (sout + sout.transpose()) * 0.5
        assert sout.spsame(s)
        sout.finalize()
        assert np.allclose(s._csr._D, sout._csr._D)
Beispiel #13
0
def test_real_space_HS_SE_unfold_with_k():
    # check that calculating the real-space Green function is equivalent for two equivalent systems
    sq = Geometry([0] * 3, Atom(1, 1.01), [1])
    sq.set_nsc([3] * 3)
    H = Hamiltonian(sq)
    H.construct([(0.1, 1.1), (4, -1)])

    RSE = RealSpaceSE(H, 0, 1, (3, 4, 1), dk=100, trs=False)

    k1 = [0, 0, 0.2]
    k2 = [0, 0, 0.3]
    for E in [0.1, 1.5]:
        G1 = RSE.green(E, k1)
        G2 = RSE.green(E, k2)
        assert not np.allclose(G1, G2)

        SE1 = RSE.self_energy(E, k1)
        SE2 = RSE.self_energy(E, k2)
        assert not np.allclose(SE1, SE2)
Beispiel #14
0
    def test_orbital_momentum(self, setup):
        bond = 1.42
        sq3h = 3.**.5 * 0.5
        sc = SuperCell(np.array(
            [[1.5, sq3h, 0.], [1.5, -sq3h, 0.], [0., 0., 10.]], np.float64) *
                       bond,
                       nsc=[3, 3, 1])

        orb = AtomicOrbital('px', R=bond * 1.001)
        C = Atom(6, orb)
        g = Geometry(np.array([[0., 0., 0.], [1., 0., 0.]], np.float64) * bond,
                     atom=C,
                     sc=sc)
        D = DensityMatrix(g, spin=Spin('SO'))
        D.construct([[0.1, bond + 0.01],
                     [(1., 0.5, 0.01, 0.01, 0.01, 0.01, 0., 0.),
                      (0.1, 0.1, 0.1, 0.1, 0., 0., 0., 0.)]])
        D.orbital_momentum("atom")
        D.orbital_momentum("orbital")
Beispiel #15
0
    def test_spin_rotate_so(self, setup):
        bond = 1.42
        sq3h = 3.**.5 * 0.5
        sc = SuperCell(np.array([[1.5, sq3h, 0.],
                                      [1.5, -sq3h, 0.],
                                      [0., 0., 10.]], np.float64) * bond, nsc=[3, 3, 1])

        orb = AtomicOrbital('px', R=bond * 1.001)
        C = Atom(6, orb)
        g = Geometry(np.array([[0., 0., 0.],
                                    [1., 0., 0.]], np.float64) * bond,
                        atoms=C, sc=sc)
        D = DensityMatrix(g, spin=Spin('SO'))
        D.construct([[0.1, bond + 0.01], [(1., 0.5, 0.01, 0.01, 0.01, 0.01, 0.2, 0.2), (0.1, 0.2, 0.1, 0.1, 0., 0.1, 0.2, 0.3)]])
        D_mull = D.mulliken()
        d = D.spin_rotate([45, 60, 90], rad=False)
        d_mull = d.mulliken()
        assert not np.allclose(D_mull, d_mull)
        assert np.allclose(D_mull[:, 0], d_mull[:, 0])
Beispiel #16
0
    def test_rho2(self, setup):
        bond = 1.42
        sq3h = 3.**.5 * 0.5
        sc = SuperCell(np.array([[1.5, sq3h, 0.],
                                      [1.5, -sq3h, 0.],
                                      [0., 0., 10.]], np.float64) * bond, nsc=[3, 3, 1])

        n = 60
        rf = np.linspace(0, bond * 1.01, n)
        rf = (rf, rf)
        orb = SphericalOrbital(1, rf, 2.)
        C = Atom(6, orb)
        g = Geometry(np.array([[0., 0., 0.],
                                    [1., 0., 0.]], np.float64) * bond,
                        atoms=C, sc=sc)
        D = DensityMatrix(g)
        D.construct([[0.1, bond + 0.01], [1., 0.1]])
        grid = Grid(0.2, geometry=D.geometry)
        D.density(grid)

        D = DensityMatrix(g, spin=Spin('P'))
        D.construct([[0.1, bond + 0.01], [(1., 0.5), (0.1, 0.1)]])
        grid = Grid(0.2, geometry=D.geometry)
        D.density(grid)
        D.density(grid, [1., -1])
        D.density(grid, 0)
        D.density(grid, 1)

        D = DensityMatrix(g, spin=Spin('NC'))
        D.construct([[0.1, bond + 0.01], [(1., 0.5, 0.01, 0.01), (0.1, 0.1, 0.1, 0.1)]])
        grid = Grid(0.2, geometry=D.geometry)
        D.density(grid)
        D.density(grid, [[1., 0.], [0., -1]])

        D = DensityMatrix(g, spin=Spin('SO'))
        D.construct([[0.1, bond + 0.01], [(1., 0.5, 0.01, 0.01, 0.01, 0.01, 0., 0.), (0.1, 0.1, 0.1, 0.1, 0., 0., 0., 0.)]])
        grid = Grid(0.2, geometry=D.geometry)
        D.density(grid)
        D.density(grid, [[1., 0.], [0., -1]])
        D.density(grid, Spin.X)
        D.density(grid, Spin.Y)
        D.density(grid, Spin.Z)
Beispiel #17
0
def test_sparse_orbital_bz_hermitian(n0, n1, n2):
    g = geom.fcc(1., Atom(1, R=1.5)) * 2
    s = SparseOrbitalBZ(g)
    s.construct([[0.1, 1.51], [1, 2]])
    s = s.tile(n0, 0).tile(n1, 1).tile(n2, 2)
    no = s.geometry.no

    nnz = 0
    for io in range(no):
        # orbitals connecting to io
        edges = s.edges(io)
        # Figure out the transposed supercell indices of the edges
        isc = -s.geometry.o2isc(edges)
        # Convert to supercell
        IO = s.geometry.sc.sc_index(isc) * no + io
        # Figure out if 'io' is also in the back-edges
        for jo, edge in zip(IO, edges % no):
            assert jo in s.edges(edge)
            nnz += 1

    # Check that we have counted all nnz
    assert s.nnz == nnz

    # Since we are also dealing with f32 data-types we cannot go beyond 1e-7
    approx_zero = pytest.approx(0., abs=1e-5)
    for k0 in [0, 0.1]:
        for k1 in [0, -0.15]:
            for k2 in [0, 0.33333]:
                k = (k0, k1, k2)

                if np.allclose(k, 0.):
                    dtypes = [None, np.float32, np.float64]
                else:
                    dtypes = [None, np.complex64, np.complex128]

                # Also assert Pk == Pk.H for all data-types
                for dtype in dtypes:
                    Pk = s.Pk(k=k, format='csr', dtype=dtype)
                    assert abs(Pk - Pk.getH()).toarray().max() == approx_zero

                    Pk = s.Pk(k=k, format='array', dtype=dtype)
                    assert np.abs(Pk - np.conj(Pk.T)).max() == approx_zero
Beispiel #18
0
        def __init__(self):
            bond = 1.42
            sq3h = 3.**.5 * 0.5
            self.sc = SuperCell(
                np.array([[1.5, sq3h, 0.], [1.5, -sq3h, 0.], [0., 0., 10.]],
                         np.float64) * bond,
                nsc=[3, 3, 1])

            C = Atom(Z=6, R=[bond * 1.01])
            self.g = Geometry(
                np.array([[0., 0., 0.], [1., 0., 0.]], np.float64) * bond,
                atom=C,
                sc=self.sc)
            self.H = Hamiltonian(self.g)
            func = self.H.create_construct([0.1, bond + 0.1], [0., -2.7])
            self.H.construct(func)
            self.HS = Hamiltonian(self.g, orthogonal=False)
            func = self.HS.create_construct([0.1, bond + 0.1], [(0., 1.),
                                                                (-2.7, 0.)])
            self.HS.construct(func)
Beispiel #19
0
def diamond(alat=3.57, atoms=None):
    """ Diamond lattice with 2 atoms in the unitcell

    Parameters
    ----------
    alat : float
        the lattice constant for the diamond
    atoms : Atom, optional
        atom in the lattice, may be one or two atoms. Default is Carbon
    """
    dist = alat * 3.**.5 / 4
    if atoms is None:
        atoms = Atom(Z=6, R=dist * 1.01)
    sc = SuperCell(np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]], np.float64) *
                   alat / 2,
                   nsc=[3, 3, 3])
    dia = Geometry(np.array([[0, 0, 0], [1, 1, 1]], np.float64) * alat / 4,
                   atoms,
                   sc=sc)
    return dia
Beispiel #20
0
def graphene(bond=1.42, atom=None, orthogonal=False):
    """ Graphene lattice with 2 or 4 atoms per unit-cell, latter orthogonal cell

    Parameters
    ----------
    bond : float
        bond length between atoms (*not* lattice constant)
    atom : Atom, optional
        the atom (or atoms) that the honeycomb lattice consists of.
        Default to Carbon atom.
    orthogonal : bool, optional
        if True returns an orthogonal lattice

    See Also
    --------
    honeycomb: the equivalent of this, but with non-default atoms
    bilayer: create bilayer honeycomb lattices
    """
    if atom is None:
        return honeycomb(bond, Atom(Z=6, R=bond * 1.01), orthogonal)
    return honeycomb(bond, atom, orthogonal)
Beispiel #21
0
    def test_tile3(self, setup):
        R, param = [0.1, 1.1, 2.1, 3.1], [1., 2., 3., 4.]

        # Create reference
        g = Geometry([[0] * 3], Atom('H', R=[4.]), sc=[1.] * 3)
        g.set_nsc([7] * 3)

        # Now create bigger geometry
        G = g.tile(2, 0).tile(2, 1).tile(2, 2)

        HG = Hamiltonian(G.tile(2, 0).tile(2, 1).tile(2, 2))
        HG.construct([R, param])
        HG.finalize()
        H = Hamiltonian(G)
        H.construct([R, param])
        H.finalize()
        H = H.tile(2, 0).tile(2, 1).tile(2, 2)
        assert HG.spsame(H)
        H.finalize()
        HG.finalize()
        assert np.allclose(H._csr._D, HG._csr._D)
Beispiel #22
0
    def test_rho_fail_nc(self, setup):
        bond = 1.42
        sq3h = 3.**.5 * 0.5
        sc = SuperCell(np.array([[1.5, sq3h, 0.],
                                      [1.5, -sq3h, 0.],
                                      [0., 0., 10.]], np.float64) * bond, nsc=[3, 3, 1])

        n = 60
        rf = np.linspace(0, bond * 1.01, n)
        rf = (rf, rf)
        orb = SphericalOrbital(1, rf, 2.)
        C = Atom(6, orb)
        g = Geometry(np.array([[0., 0., 0.],
                                    [1., 0., 0.]], np.float64) * bond,
                        atoms=C, sc=sc)

        D = DensityMatrix(g, spin=Spin('NC'))
        D.construct([[0.1, bond + 0.01], [(1., 0.5, 0.01, 0.01), (0.1, 0.1, 0.1, 0.1)]])
        grid = Grid(0.2, geometry=D.geometry)
        with pytest.raises(ValueError):
            D.density(grid, [1., 0.])
Beispiel #23
0
    def read_geometry(self):
        """ Returns Geometry object from a Siesta.nc file """

        # Read supercell
        sc = self.read_supercell()

        xyz = np.array(self._value('xa'), np.float64)
        xyz.shape = (-1, 3)

        if 'BASIS' in self.groups:
            basis = self.read_basis()
            species = self.groups['BASIS'].variables['basis'][:] - 1
            atom = Atoms([basis[i] for i in species])
        else:
            atom = Atom(1)

        xyz *= Bohr2Ang

        # Create and return geometry object
        geom = Geometry(xyz, atom, sc=sc)
        return geom
Beispiel #24
0
    def _SpGeom_replace_geom(spgeom, geom):
        """ Replace all atoms in spgeom with the atom in geom while retaining the number of orbitals

        Currently we need some way of figuring out whether the number of atoms and orbitals are
        consistent.

        Parameters
        ----------
        spgeom : SparseGeometry
           the sparse object with attached geometry
        geom : Geometry
           geometry to grab atoms from
        full_replace : bool, optional
           whether the full geometry may be replaced in case ``spgeom.na != geom.na && spgeom.no == geom.no``.
           This is required when `spgeom` does not contain information about atoms.
        """
        if spgeom.na != geom.na and spgeom.no == geom.no:
            # In this case we cannot compare individiual atoms # of orbitals.
            # I.e. we suspect the incoming geometry to be correct.
            spgeom._geometry = geom
            return True

        elif spgeom.na != geom.na:
            warn(
                'cannot replace geometry due to insufficient information regarding number of '
                'atoms and orbitals, ensuring correct geometry failed...')

        no_no = spgeom.no == geom.no
        # Loop and make sure the number of orbitals is consistent
        for a, idx in geom.atom.iter(True):
            if len(idx) == 0:
                continue
            Sa = spgeom.geom.atom[idx[0]]
            if Sa.no != a.no:
                # Make sure the atom we replace with retains the same information
                # *except* the number of orbitals.
                a = Atom(a.Z, Sa.orbital, mass=a.mass, tag=a.tag)
            spgeom.geom.atom.replace(idx, a)
            spgeom.geom.reduce()
        return no_no
Beispiel #25
0
    def read_geometry(self):
        """ Returns Geometry object from a siesta.TSHS file """

        # Read supercell
        sc = self.read_supercell()

        na = _siesta.read_tshs_sizes(self.file)[1]
        _bin_check(self, 'read_geometry', 'could not read sizes.')
        arr = _siesta.read_tshs_geom(self.file, na)
        _bin_check(self, 'read_geometry', 'could not read geometry.')
        xyz = np.array(arr[0].T, np.float64)
        xyz.shape = (-1, 3)
        lasto = np.array(arr[1], np.int32)

        # Create all different atoms...
        # The TSHS file does not contain the
        # atomic numbers, so we will just
        # create them individually
        orbs = np.diff(lasto)

        # Get unique orbitals
        uorb = np.unique(orbs)
        # Create atoms
        atoms = []
        for Z, orb in enumerate(uorb):
            atoms.append(Atom(Z + 1, [-1] * orb))

        def get_atom(atoms, orbs):
            for atom in atoms:
                if atom.no == orbs:
                    return atom

        atom = []
        for orb in orbs:
            atom.append(get_atom(atoms, orb))

        # Create and return geometry object
        geom = Geometry(xyz, atom, sc=sc)

        return geom
Beispiel #26
0
    def read_energy_density_matrix(self, **kwargs):
        """ Returns the energy density matrix from the siesta.DM file """

        # Now read the sizes used...
        spin, no, nnz = _siesta.read_tsde_sizes(self.file)
        ncol, col, dEDM = _siesta.read_tsde_edm(self.file, spin, no, nnz)

        # Try and immediately attach a geometry
        geom = kwargs.get('geometry', kwargs.get('geom', None))
        if geom is None:
            # We truly, have no clue,
            # Just generate a boxed system
            xyz = [[x, 0, 0] for x in range(no)]
            geom = Geometry(xyz, Atom(1), sc=[no, 1, 1])

        if geom.no != no:
            raise ValueError(
                "Reading EDM files requires the input geometry to have the "
                "correct number of orbitals.")

        # Create the energy density matrix container
        EDM = EnergyDensityMatrix(geom,
                                  spin,
                                  nnzpr=1,
                                  dtype=np.float32,
                                  orthogonal=False)

        # Create the new sparse matrix
        EDM._csr.ncol = ncol.astype(np.int32, copy=False)
        EDM._csr.ptr = np.insert(np.cumsum(ncol, dtype=np.int32), 0, 0)
        # Correct fortran indices
        EDM._csr.col = col.astype(np.int32, copy=False) - 1
        EDM._csr._nnz = len(col)

        EDM._csr._D = np.empty([nnz, spin + 1], np.float32)
        EDM._csr._D[:, :spin] = dEDM[:, :]
        # EDM file does not contain overlap matrix... so neglect it for now.
        EDM._csr._D[:, spin] = 0.

        return EDM
Beispiel #27
0
    def test_spin_align_nc(self, setup):
        bond = 1.42
        sq3h = 3.**.5 * 0.5
        sc = SuperCell(np.array(
            [[1.5, sq3h, 0.], [1.5, -sq3h, 0.], [0., 0., 10.]], np.float64) *
                       bond,
                       nsc=[3, 3, 1])

        orb = AtomicOrbital('px', R=bond * 1.001)
        C = Atom(6, orb)
        g = Geometry(np.array([[0., 0., 0.], [1., 0., 0.]], np.float64) * bond,
                     atom=C,
                     sc=sc)
        D = DensityMatrix(g, spin=Spin('nc'))
        D.construct([[0.1, bond + 0.01],
                     [(1., 0.5, 0.01, 0.01), (0.1, 0.2, 0.1, 0.1)]])
        D_mull = D.mulliken()
        v = np.array([1, 2, 3])
        d = D.spin_align(v)
        d_mull = d.mulliken()
        assert not np.allclose(D_mull, d_mull)
        assert np.allclose(D_mull[:, 0], d_mull[:, 0])
Beispiel #28
0
def test_sparse_orbital_symmetric(n0, n1, n2):
    g = fcc(1., Atom(1, R=1.5)) * 2
    s = SparseOrbital(g)
    s.construct([[0.1, 1.51], [1, 2]])
    s = s.tile(n0, 0).tile(n1, 1).tile(n2, 2)
    no = s.geometry.no

    nnz = no
    for io in range(no):
        # orbitals connecting to io
        edges = s.edges(io)
        # Figure out the transposed supercell indices of the edges
        isc = -s.geometry.o2isc(edges)
        # Convert to supercell
        IO = s.geometry.sc.sc_index(isc) * no + io
        # Figure out if 'io' is also in the back-edges
        for jo, edge in zip(IO, edges % no):
            assert jo in s.edges(edge)
            nnz += 1

    # Check that we have counted all nnz
    assert s.nnz == nnz
def test_sparse_atom_symmetric(n0, n1, n2):
    g = fcc(1., Atom(1, R=1.5)) * 2
    s = SparseAtom(g)
    s.construct([[0.1, 1.51], [1, 2]])
    s = s.tile(n0, 0).tile(n1, 1).tile(n2, 2)
    na = s.geometry.na

    nnz = 0
    for ia in range(na):
        # orbitals connecting to ia
        edges = s.edges(ia)
        # Figure out the transposed supercell indices of the edges
        isc = -s.geometry.a2isc(edges)
        # Convert to supercell
        IA = s.geometry.sc.sc_index(isc) * na + ia
        # Figure out if 'ia' is also in the back-edges
        for ja, edge in zip(IA, edges % na):
            assert ja in s.edges(edge)
            nnz += 1

    # Check that we have counted all nnz
    assert s.nnz == nnz
Beispiel #30
0
    def test_spin_align_pol(self, setup):
        bond = 1.42
        sq3h = 3.**.5 * 0.5
        sc = SuperCell(np.array([[1.5, sq3h, 0.],
                                      [1.5, -sq3h, 0.],
                                      [0., 0., 10.]], np.float64) * bond, nsc=[3, 3, 1])

        orb = AtomicOrbital('px', R=bond * 1.001)
        C = Atom(6, orb)
        g = Geometry(np.array([[0., 0., 0.],
                                    [1., 0., 0.]], np.float64) * bond,
                        atoms=C, sc=sc)
        D = DensityMatrix(g, spin=Spin('p'))
        D.construct([[0.1, bond + 0.01], [(1., 0.5), (0.1, 0.2)]])
        D_mull = D.mulliken()
        v = np.array([1, 2, 3])
        d = D.spin_align(v)
        d_mull = d.mulliken()
        assert D_mull.shape == (len(D), 2)
        assert d_mull.shape == (len(D), 4)
        assert not np.allclose(-np.diff(D_mull, axis=1), d_mull[:, 3])
        assert np.allclose(D_mull.sum(1), d_mull[:, 0])