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)
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
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))
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))
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.)
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]
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)
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
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()))
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
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)
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)
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)
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")
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])
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)
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
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)
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
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)
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)
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.])
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
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
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
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
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])
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
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])