def test_wrap_kwargs(arg): from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) bz = MonkhorstPack(H, [2, 2, 2], trs=False) assert len(bz) == 2 ** 3 def wrap_none(arg): return arg def wrap_kwargs(arg, parent, k, weight): return arg * weight E = np.linspace(-2, 2, 100) asarray1 = (bz.asarray().DOS(E, wrap=wrap_none) * bz.weight.reshape(-1, 1)).sum(0) asarray2 = bz.asarray().DOS(E, wrap=wrap_kwargs).sum(0) aslist1 = (np.array(bz.aslist().DOS(E, wrap=wrap_none)) * bz.weight.reshape(-1, 1)).sum(0) aslist2 = np.array(bz.aslist().DOS(E, wrap=wrap_kwargs)).sum(0) asyield1 = (np.array([a for a in bz.asyield().DOS(E, wrap=wrap_none)]) * bz.weight.reshape(-1, 1)).sum(0) asyield2 = np.array([a for a in bz.asyield().DOS(E, wrap=wrap_kwargs)]).sum(0) asaverage = bz.asaverage().DOS(E, wrap=wrap_none) assum = bz.assum().DOS(E, wrap=wrap_kwargs) assert np.allclose(asarray1, asaverage) assert np.allclose(asarray2, asaverage) assert np.allclose(aslist1, asaverage) assert np.allclose(aslist2, asaverage) assert np.allclose(asyield1, asaverage) assert np.allclose(asyield2, asaverage) assert np.allclose(assum, asaverage)
def test_trs(self, setup): size = [0.05, 0.5, 0.9] for x, y, z in product(np.arange(10) + 1, np.arange(20) + 1, np.arange(6) + 1): bz = MonkhorstPack(setup.s1, [x, y, z]) assert bz.weight.sum() == pytest.approx(1.) bz = MonkhorstPack(setup.s1, [x, y, z], size=size) assert bz.weight.sum() == pytest.approx(np.prod(size))
def test_mp2(self, setup): bz1 = MonkhorstPack(setup.s1, [2] * 3, centered=False, trs=False) assert len(bz1) == 8 bz2 = MonkhorstPack(setup.s1, [2] * 3, displacement=[.5] * 3, trs=False) assert len(bz2) == 8 assert np.allclose(bz1.k, bz2.k)
def test_replace_gamma_trs(self): g = geom.graphene() bz = MonkhorstPack(g, [2, 2, 2], trs=False) bz_gamma = MonkhorstPack(g, [3, 3, 3], size=[0.5] * 3, trs=True) assert len(bz) == 2 ** 3 bz.replace([0] * 3, bz_gamma) assert len(bz) == 2 ** 3 + 3 ** 3 - 3 ** 2 - 1 assert bz.weight.sum() == pytest.approx(1.)
def test_mp_asgrid_fail(self, setup): class Test(SuperCellChild): def __init__(self, sc): self.set_supercell(sc) def eigh(self, k, *args, **kwargs): return np.arange(3) bz = MonkhorstPack(Test(setup.s1), [2] * 3, displacement=[0.1] * 3).asgrid() bz.eigh(wrap=lambda eig: eig[0])
def test_as_wrap(self): from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) bz = MonkhorstPack(H, [2, 2, 2], trs=False) assert len(bz) == 2**3 # Check with a wrap function def wrap(arg): return arg[::-1] # Assert that as* all does the same asarray = bz.apply.array.eigh(wrap=wrap) aslist = np.array(bz.apply.list.eigh(wrap=wrap)) asyield = np.array([a for a in bz.apply.iter.eigh(wrap=wrap)]) asaverage = bz.apply.average.eigh(wrap=wrap) assert np.allclose(asarray, aslist) assert np.allclose(asarray, asyield) assert np.allclose((asarray / len(bz)).sum(0), asaverage) # Now we should check whether the reverse is doing its magic! mylist = [wrap(H.eigh(k=k)) for k in bz] assert np.allclose(aslist, mylist)
def test_wrap_unzip(self): from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) bz = MonkhorstPack(H, [2, 2, 2], trs=False) # Check with a wrap function E = np.linspace(-2, 2, 20) def wrap(es): return es.eig, es.DOS(E) eig0, DOS0 = zip(*bz.apply.list.eigenstate(wrap=wrap)) with bz.apply.renew(unzip=True) as k_unzip: eig1, DOS1 = k_unzip.list.eigenstate(wrap=wrap) eig2, DOS2 = k_unzip.array.eigenstate(wrap=wrap) #eig0 and DOS0 are generators, and not list's #eig1 and DOS1 are generators, and not list's assert isinstance(eig2, np.ndarray) assert isinstance(DOS2, np.ndarray) assert np.allclose(eig0, eig1) assert np.allclose(DOS0, DOS1) assert np.allclose(eig0, eig2) assert np.allclose(DOS0, DOS2)
def test_pathos(self): try: import pathos except ImportError: pytest.skip("pathos not available") from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) bz = MonkhorstPack(H, [2, 2, 2], trs=False) # We need to ensure that all functions does the same apply = bz.apply papply = bz.papply for method in ["iter", "average", "sum", "array", "list", "oplist"]: # TODO One should be careful with zip # zip will stop when it hits the final element in the first # list. # So if a generator has some clean-up code one has to use zip_longest # regardless of method for v1, v2 in zip(papply[method].eigh(), apply[method].eigh()): assert np.allclose(v1, v2)
def test_mp_gamma_centered_displ(self, setup): for x, y, z in product(np.arange(10) + 1, np.arange(20) + 1, np.arange(6) + 1): bz = MonkhorstPack(setup.s1, [x, y, z], displacement=[0.2, 0, 0], trs=False) k = bz.k.copy() k[:, 0] -= 0.2 assert len(bz) == x * y * z assert ((k == 0.).sum(1).astype(np.int32) == 3).sum() == 1
def test_mp_gamma_centered(self, setup): for x, y, z in product( np.arange(10) + 1, np.arange(20) + 1, np.arange(6) + 1): bz = MonkhorstPack(setup.s1, [x, y, z], trs=False) assert len(bz) == x * y * z assert ((bz.k == 0.).sum(1).astype(np.int32) == 3).sum() == 1
def test_fermi_level(self, setup): R, param = [0.1, 1.5], [(1., 1.), (2.1, 0.1)] H = Hamiltonian(setup.g.copy(), orthogonal=False) H.construct([R, param]) bz = MonkhorstPack(H, [10, 10, 1]) Ef = H.fermi_level(bz, q=1) H.shift(-Ef) assert H.fermi_level(bz, q=1) == pytest.approx(0., abs=1e-6)
def test_pathos(self): pytest.skip( "BrillouinZone.apply(pool=True|int) scales extremely bad and may cause stall" ) pytest.importorskip("pathos", reason="pathos not available") from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) bz = MonkhorstPack(H, [2, 2, 2], trs=False) # try and determine a sensible import os try: import psutil nprocs = len(psutil.Process().cpu_affinity()) // 2 except Exception: nprocs = os.cpu_count() // 2 omp_num_threads = os.environ.get("OMP_NUM_THREADS") # Check that the ObjectDispatcher works apply = bz.apply papply = bz.apply.renew(pool=nprocs) assert str(apply) != str(papply) for method in ["iter", "average", "sum", "array", "list", "oplist"]: # TODO One should be careful with zip # zip will stop when it hits the final element in the first # list. # So if a generator has some clean-up code one has to use zip_longest # regardless of method os.environ["OMP_NUM_THREADS"] = "1" V1 = papply[method].eigh() if omp_num_threads is None: del os.environ["OMP_NUM_THREADS"] else: os.environ["OMP_NUM_THREADS"] = omp_num_threads V2 = apply[method].eigh() for v1, v2 in zip(V1, V2): assert np.allclose(v1, v2) # Check that the MethodDispatcher works apply = bz.apply.eigh papply = bz.apply.renew(pool=True).eigh assert str(apply) != str(papply) for method in ["iter", "average", "sum", "array", "list", "oplist"]: # TODO One should be careful with zip # zip will stop when it hits the final element in the first # list. # So if a generator has some clean-up code one has to use zip_longest # regardless of method for v1, v2 in zip(papply[method](), apply[method]()): assert np.allclose(v1, v2)
def test_as_wrap_default_oplist(self): from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) bz = MonkhorstPack(H, [2, 2, 2], trs=False).asaverage() assert len(bz) == 2 ** 3 # Check with a wrap function E = np.linspace(-2, 2, 100) def wrap_sum(es, weight): PDOS = es.PDOS(E) * weight return PDOS.sum(0), PDOS DOS, PDOS = bz.assum().eigenstate(wrap=wrap_sum) assert np.allclose(bz.DOS(E), DOS) assert np.allclose(bz.PDOS(E), PDOS)
def test_as_single(self): from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) def wrap(eig): return eig[0] bz = MonkhorstPack(H, [2, 2, 2], trs=False) assert len(bz) == 2 ** 3 # Assert that as* all does the same asarray = bz.asarray().eigh(wrap=wrap) aslist = np.array(bz.aslist().eigh(wrap=wrap)) asyield = np.array([a for a in bz.asyield().eigh(wrap=wrap)]) assert np.allclose(asarray, aslist) assert np.allclose(asarray, asyield)
def test_monkhorstpack_pickle(self, setup): import pickle as p bz1 = MonkhorstPack(geom.graphene(), [10, 11, 1], centered=False) n = p.dumps(bz1) bz2 = p.loads(n) assert np.allclose(bz1.k, bz2.k) assert np.allclose(bz1.weight, bz2.weight) assert bz1.parent == bz2.parent assert bz1._centered == bz2._centered
def test_fermi_level_spin_separate(self, setup): R, param = [0.1, 1.5], [(1., 1.), (2.1, 0.1)] H = Hamiltonian(setup.g.copy(), spin=Spin('P')) H.construct([R, param]) bz = MonkhorstPack(H, [10, 10, 1]) q = [0.5, 0.3] Ef = H.fermi_level(bz, q=q) assert len(Ef) == 2 H.shift(-Ef) assert np.allclose(H.fermi_level(bz, q=q), 0.)
def test_fermi_level_spin(self, setup): R, param = [0.1, 1.5], [(1., 1.), (2.1, 0.1)] H = Hamiltonian(setup.g.copy(), spin=Spin('P')) H.construct([R, param]) bz = MonkhorstPack(H, [10, 10, 1]) q = 1.1 Ef = H.fermi_level(bz, q=q) assert np.asarray(Ef).ndim == 0 H.shift(-Ef) assert H.fermi_level(bz, q=q) == pytest.approx(0., abs=1e-6)
def test_mp_asgrid(self, setup, N, centered): class Test(SuperCellChild): def __init__(self, sc): self.set_supercell(sc) def eigh(self, k, *args, **kwargs): return np.arange(3) bz = MonkhorstPack(Test(setup.s1), [2] * 3).asgrid() # Check the shape grid = bz.eigh(wrap=lambda eig: eig[0]) assert np.allclose(grid.shape, [2] * 3) # Check the grids are different grid2 = bz.eigh(grid_unit='Bohr', wrap=lambda eig: eig[0]) assert not np.allclose(grid.cell, grid2.cell) assert np.allclose(grid.grid, grid2.grid) for i in range(3): grid = bz.eigh(data_axis=i) shape = [2] * 3 shape[i] = 3 assert np.allclose(grid.shape, shape)
def test_mp_gamma_non_centered(self, setup): for x, y, z in product(np.arange(10) + 1, np.arange(20) + 1, np.arange(6) + 1): bz = MonkhorstPack(setup.s1, [x, y, z], centered=False, trs=False) assert len(bz) == x * y * z # The gamma point will also be in the unit-cell for # non-centered has_gamma = x % 2 == 1 has_gamma &= y % 2 == 1 has_gamma &= z % 2 == 1 if has_gamma: assert ((bz.k == 0.).sum(1).astype(np.int32) == 3).sum() == 1 else: assert ((bz.k == 0.).sum(1).astype(np.int32) == 3).sum() == 0
def test_as_dataarray(self): try: import xarray except ImportError: pytest.skip('xarray not available') from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) bz = MonkhorstPack(H, [2, 2, 2], trs=False) # Assert that as* all does the same asarray = bz.asarray().eigh() asdarray = bz.asdataarray().eigh() assert np.allclose(asarray, asdarray.values) assert isinstance(asdarray.bz, MonkhorstPack) assert isinstance(asdarray.parent, Hamiltonian) assert asdarray.dims == ('k', 'v1') asdarray = bz.asdataarray().eigh(coords=['orb']) assert asdarray.dims == ('k', 'orb')
def test_pathos(self): pytest.importorskip("pathos", reason="pathos not available") from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) bz = MonkhorstPack(H, [2, 2, 2], trs=False) # Check that the ObjectDispatcher works apply = bz.apply papply = bz.apply(pool=True) assert str(apply) != str(papply) for method in ["iter", "average", "sum", "array", "list", "oplist"]: # TODO One should be careful with zip # zip will stop when it hits the final element in the first # list. # So if a generator has some clean-up code one has to use zip_longest # regardless of method for v1, v2 in zip(papply[method].eigh(), apply[method].eigh()): assert np.allclose(v1, v2) # Check that the MethodDispatcher works apply = bz.apply.eigh papply = bz.apply(pool=True).eigh assert str(apply) != str(papply) for method in ["iter", "average", "sum", "array", "list", "oplist"]: # TODO One should be careful with zip # zip will stop when it hits the final element in the first # list. # So if a generator has some clean-up code one has to use zip_longest # regardless of method for v1, v2 in zip(papply[method](), apply[method]()): assert np.allclose(v1, v2)
def test_replace_gamma(self): g = geom.graphene() bz = MonkhorstPack(g, 2, trs=False) bz_gamma = MonkhorstPack(g, [2, 2, 2], size=[0.5] * 3, trs=False) assert len(bz) == 2**3 bz.replace([0] * 3, bz_gamma) assert len(bz) == 2**3 + 2**3 - 1 assert bz.weight.sum() == pytest.approx(1.) assert np.allclose(bz.copy().k, bz.k) assert np.allclose(bz.copy().weight, bz.weight)
def test_as_simple(self): from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) bz = MonkhorstPack(H, [2, 2, 2], trs=False) assert len(bz) == 2 ** 3 # Assert that as* all does the same asarray = bz.asarray().eigh() aslist = np.array(bz.aslist().eigh()) asyield = np.array([a for a in bz.asyield().eigh()]) asaverage = bz.asaverage().eigh() assert np.allclose(asarray, aslist) assert np.allclose(asarray, asyield) # Average needs to be performed assert np.allclose((asarray / len(bz)).sum(0), asaverage) bz.asnone().eigh()
def test_wrap_oplist(self, setup): R, param = [0.1, 1.5], [1, 2.1] H = Hamiltonian(setup.g.copy()) H.construct([R, param]) bz = MonkhorstPack(H, [10, 10, 1]) E = np.linspace(-4, 4, 1000) dist = get_distribution('gaussian', smearing=0.05) def wrap(es, parent, k, weight): DOS = es.DOS(E, distribution=dist) PDOS = es.PDOS(E, distribution=dist) vel = es.velocity() * es.occupation().reshape(-1, 1) return oplist([DOS, PDOS, vel]) bz.asaverage() results = bz.eigenstate(wrap=wrap) assert np.allclose(bz.DOS(E, distribution=dist), results[0]) assert np.allclose(bz.PDOS(E, distribution=dist), results[1])
def test_class3(self, setup): class Test(SuperCellChild): def __init__(self, sc): self.set_supercell(sc) def eigh(self, k, *args, **kwargs): return np.arange(3) def eig(self, k, *args, **kwargs): return np.arange(3) - 1 bz = MonkhorstPack(Test(setup.s1), [2] * 3) # Try the yield method bz.asyield() for val in bz.eigh(): assert np.allclose(val, np.arange(3)) for val in bz.eig(): assert np.allclose(val, np.arange(3) - 1) # Average assert np.allclose(bz.asaverage().eigh(), np.arange(3))
def test_as_dataarray(self): pytest.importorskip("xarray", reason="xarray not available") from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) bz = MonkhorstPack(H, [2, 2, 2], trs=False) # Assert that as* all does the same asarray = bz.apply.array.eigh() bz_da = bz.apply.dataarray asdarray = bz_da.eigh() assert np.allclose(asarray, asdarray.values) assert isinstance(asdarray.bz, MonkhorstPack) assert isinstance(asdarray.parent, Hamiltonian) assert asdarray.dims == ('k', 'v1') asdarray = bz_da.eigh(coords=['orb']) assert asdarray.dims == ('k', 'orb')
def test_as_dataarray_unzip(self): pytest.importorskip("xarray", reason="xarray not available") from sisl import geom, Hamiltonian g = geom.graphene() H = Hamiltonian(g) H.construct([[0.1, 1.44], [0, -2.7]]) E = np.linspace(-2, 2, 20) bz = MonkhorstPack(H, [2, 2, 1], trs=False) def wrap(es): return es.eig, es.DOS(E), es.PDOS(E) with bz.apply.renew(unzip=True) as unzip: eig, DOS, PDOS = unzip.ndarray.eigenstate(wrap=wrap) ds0 = unzip.dataarray.eigenstate(wrap=wrap, name=["eig", "DOS", "PDOS"]) # explicitly create dimensions ds1 = unzip.dataarray.eigenstate(wrap=wrap, coords=[ { "orb": np.arange(len(H)) }, { "E": E }, { "orb": np.arange(len(H)), "E": E }, ], dims=(['orb'], ['E'], ['orb', 'E']), name=["eig", "DOS", "PDOS"]) for var, data in zip(["eig", "DOS", "PDOS"], [eig, DOS, PDOS]): assert np.allclose(ds0.data_vars[var].values, data) assert np.allclose(ds1.data_vars[var].values, data) assert len(ds1.coords) < len(ds0.coords)
def test_in_primitive(self): assert np.allclose(MonkhorstPack.in_primitive([[1.] * 3, [-1.] * 3]), 0)
def test_mp3(self, setup): bz1 = MonkhorstPack(setup.s1, [2] * 3, size=0.5, trs=False) assert len(bz1) == 8 assert np.all(bz1.k <= 0.25) assert bz1.weight.sum() == pytest.approx(0.5**3)
def test_mp_uneven(self, setup): bz1 = MonkhorstPack(setup.s1, [3] * 3, trs=False) bz2 = MonkhorstPack(setup.s1, [3] * 3, displacement=[.5] * 3, trs=False) assert not np.allclose(bz1.k, bz2.k)