• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

materialsproject / pymatgen / 4075885785

pending completion
4075885785

push

github

Shyue Ping Ong
Merge branch 'master' of github.com:materialsproject/pymatgen

96 of 96 new or added lines in 27 files covered. (100.0%)

81013 of 102710 relevant lines covered (78.88%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.72
/pymatgen/electronic_structure/tests/test_bandstructure.py
1
# Copyright (c) Pymatgen Development Team.
2
# Distributed under the terms of the MIT License.
3

4

5
from __future__ import annotations
1✔
6

7
import json
1✔
8
import os
1✔
9
import unittest
1✔
10
import warnings
1✔
11

12
import numpy
1✔
13
import pytest
1✔
14
from monty.serialization import loadfn
1✔
15
from pytest import approx
1✔
16

17
from pymatgen.core.lattice import Lattice
1✔
18
from pymatgen.electronic_structure.bandstructure import (
1✔
19
    BandStructureSymmLine,
20
    Kpoint,
21
    LobsterBandStructureSymmLine,
22
    get_reconstructed_band_structure,
23
)
24
from pymatgen.electronic_structure.core import Orbital, Spin
1✔
25
from pymatgen.electronic_structure.plotter import BSPlotterProjected
1✔
26
from pymatgen.io.vasp import BSVasprun
1✔
27
from pymatgen.util.testing import PymatgenTest
1✔
28

29

30
class KpointTest(unittest.TestCase):
1✔
31
    def setUp(self):
1✔
32
        self.lattice = Lattice.cubic(10.0)
1✔
33
        self.kpoint = Kpoint([0.1, 0.4, -0.5], self.lattice, label="X")
1✔
34

35
    def test_properties(self):
1✔
36
        assert self.kpoint.frac_coords[0] == 0.1
1✔
37
        assert self.kpoint.frac_coords[1] == 0.4
1✔
38
        assert self.kpoint.frac_coords[2] == -0.5
1✔
39
        assert self.kpoint.a == 0.1
1✔
40
        assert self.kpoint.b == 0.4
1✔
41
        assert self.kpoint.c == -0.5
1✔
42
        assert self.lattice == Lattice.cubic(10.0)
1✔
43
        assert self.kpoint.cart_coords[0] == 1.0
1✔
44
        assert self.kpoint.cart_coords[1] == 4.0
1✔
45
        assert self.kpoint.cart_coords[2] == -5.0
1✔
46
        assert self.kpoint.label == "X"
1✔
47

48
    def test_as_dict(self):
1✔
49
        assert isinstance(self.kpoint.as_dict()["fcoords"], list)
1✔
50
        assert isinstance(self.kpoint.as_dict()["ccoords"], list)
1✔
51
        assert not isinstance(self.kpoint.as_dict()["fcoords"][0], numpy.float64)
1✔
52
        assert not isinstance(self.kpoint.as_dict()["ccoords"][0], numpy.float64)
1✔
53
        assert self.kpoint.as_dict()["fcoords"] == [0.1, 0.4, -0.5]
1✔
54
        assert self.kpoint.as_dict()["ccoords"] == [1.0, 4.0, -5.0]
1✔
55

56
    def test_from_dict(self):
1✔
57
        d = self.kpoint.as_dict()
1✔
58

59
        kpoint = Kpoint.from_dict(d)
1✔
60

61
        assert kpoint.frac_coords[0] == 0.1
1✔
62
        assert kpoint.frac_coords[1] == 0.4
1✔
63
        assert kpoint.frac_coords[2] == -0.5
1✔
64
        assert kpoint.a == 0.1
1✔
65
        assert kpoint.b == 0.4
1✔
66
        assert kpoint.c == -0.5
1✔
67
        assert kpoint.lattice == Lattice.cubic(10.0)
1✔
68
        assert kpoint.cart_coords[0] == 1.0
1✔
69
        assert kpoint.cart_coords[1] == 4.0
1✔
70
        assert kpoint.cart_coords[2] == -5.0
1✔
71
        assert kpoint.label == "X"
1✔
72

73

74
class BandStructureSymmLineTest(PymatgenTest):
1✔
75
    def setUp(self):
1✔
76
        self.bs = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "Cu2O_361_bandstructure.json"))
1✔
77
        self.bs2 = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "CaO_2605_bandstructure.json"))
1✔
78
        self.bs_spin = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "NiO_19009_bandstructure.json"))
1✔
79
        self.bs_cbm0 = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "InN_22205_bandstructure.json"))
1✔
80
        self.bs_cu = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "Cu_30_bandstructure.json"))
1✔
81
        self.bs_diff_spins = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "VBr2_971787_bandstructure.json"))
1✔
82
        warnings.simplefilter("ignore")
1✔
83

84
    def tearDown(self):
1✔
85
        warnings.simplefilter("default")
1✔
86

87
    def test_basic(self):
1✔
88
        self.assertArrayAlmostEqual(self.bs.projections[Spin.up][10][12][0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
1✔
89
        self.assertArrayAlmostEqual(
1✔
90
            self.bs.projections[Spin.up][25][0][Orbital.dyz.value],
91
            [0.0, 0.0, 0.0011, 0.0219, 0.0219, 0.069],
92
        )
93
        assert self.bs.get_projection_on_elements()[Spin.up][25][10]["O"] == approx(0.0328)
1✔
94
        assert self.bs.get_projection_on_elements()[Spin.up][22][25]["Cu"] == approx(0.8327)
1✔
95
        proj = self.bs.get_projections_on_elements_and_orbitals({"Cu": ["s", "d"]})
1✔
96
        assert proj[Spin.up][25][0]["Cu"]["s"] == approx(0.0027)
1✔
97
        assert proj[Spin.up][25][0]["Cu"]["d"] == approx(0.8495999999999999)
1✔
98

99
        assert self.bs2.nb_bands == 16
1✔
100
        assert self.bs2.bands[Spin.up][5][10] == approx(0.5608)
1✔
101
        assert self.bs2.bands[Spin.up][5][10] == approx(0.5608)
1✔
102
        assert self.bs2.branches[5]["name"] == "L-U"
1✔
103
        assert self.bs2.branches[5]["start_index"] == 80
1✔
104
        assert self.bs2.branches[5]["end_index"] == 95
1✔
105
        assert self.bs2.distance[70] == approx(4.2335127528765737)
1✔
106

107
        assert self.bs_spin.nb_bands == 27
1✔
108
        assert self.bs_spin.bands[Spin.up][5][10] == approx(0.262)
1✔
109
        assert self.bs_spin.bands[Spin.down][5][10] == approx(1.6156)
1✔
110

111
    def test_properties(self):
1✔
112
        self.one_kpoint = self.bs2.kpoints[31]
1✔
113
        assert self.one_kpoint.frac_coords[0] == 0.5
1✔
114
        assert self.one_kpoint.frac_coords[1] == 0.25
1✔
115
        assert self.one_kpoint.frac_coords[2] == 0.75
1✔
116
        assert self.one_kpoint.cart_coords[0] == approx(0.64918757)
1✔
117
        assert self.one_kpoint.cart_coords[1] == approx(1.29837513)
1✔
118
        assert self.one_kpoint.cart_coords[2] == approx(0.0)
1✔
119
        assert self.one_kpoint.label == "W"
1✔
120

121
        assert self.bs2.efermi == approx(2.6211967), "wrong fermi energy"
1✔
122

123
    def test_get_branch(self):
1✔
124
        assert self.bs2.get_branch(110)[0]["name"] == "U-W"
1✔
125

126
    def test_get_direct_band_gap_dict(self):
1✔
127
        direct_dict = self.bs_diff_spins.get_direct_band_gap_dict()
1✔
128
        assert direct_dict[Spin.down]["value"] == 4.5365
1✔
129

130
        for bs in [self.bs2, self.bs_spin]:
1✔
131
            dg_dict = bs.get_direct_band_gap_dict()
1✔
132
            for spin, v in bs.bands.items():
1✔
133
                kpt = dg_dict[spin]["kpoint_index"]
1✔
134
                vb, cb = dg_dict[spin]["band_indices"]
1✔
135
                gap = v[cb][kpt] - v[vb][kpt]
1✔
136
                assert gap == dg_dict[spin]["value"]
1✔
137
        with pytest.raises(ValueError):
1✔
138
            self.bs_cu.get_direct_band_gap_dict()
1✔
139

140
    def test_get_direct_band_gap(self):
1✔
141
        assert self.bs2.get_direct_band_gap() == approx(4.0125999999999999)
1✔
142
        assert self.bs_diff_spins.get_direct_band_gap() > 0
1✔
143
        assert self.bs_cu.get_direct_band_gap() == 0
1✔
144

145
    def test_is_metal(self):
1✔
146
        assert not self.bs2.is_metal(), "wrong metal assignment"
1✔
147
        assert not self.bs_spin.is_metal(), "wrong metal assignment"
1✔
148
        assert self.bs_cu.is_metal(), "wrong metal assignment"
1✔
149

150
    def test_get_cbm(self):
1✔
151
        cbm = self.bs2.get_cbm()
1✔
152
        assert cbm["energy"] == approx(5.8709), "wrong CBM energy"
1✔
153
        assert cbm["band_index"][Spin.up][0] == 8, "wrong CBM band index"
1✔
154
        assert cbm["kpoint_index"][0] == 15, "wrong CBM kpoint index"
1✔
155
        assert cbm["kpoint"].frac_coords[0] == 0.5, "wrong CBM kpoint frac coords"
1✔
156
        assert cbm["kpoint"].frac_coords[1] == 0.0, "wrong CBM kpoint frac coords"
1✔
157
        assert cbm["kpoint"].frac_coords[2] == 0.5, "wrong CBM kpoint frac coords"
1✔
158
        assert cbm["kpoint"].label == "X", "wrong CBM kpoint label"
1✔
159
        cbm_spin = self.bs_spin.get_cbm()
1✔
160
        assert cbm_spin["energy"] == approx(8.0458), "wrong CBM energy"
1✔
161
        assert cbm_spin["band_index"][Spin.up][0] == 12, "wrong CBM band index"
1✔
162
        assert len(cbm_spin["band_index"][Spin.down]) == 0, "wrong CBM band index"
1✔
163
        assert cbm_spin["kpoint_index"][0] == 0, "wrong CBM kpoint index"
1✔
164
        assert cbm_spin["kpoint"].frac_coords[0] == 0.0, "wrong CBM kpoint frac coords"
1✔
165
        assert cbm_spin["kpoint"].frac_coords[1] == 0.0, "wrong CBM kpoint frac coords"
1✔
166
        assert cbm_spin["kpoint"].frac_coords[2] == 0.0, "wrong CBM kpoint frac coords"
1✔
167
        assert cbm_spin["kpoint"].label == "\\Gamma", "wrong CBM kpoint label"
1✔
168

169
    def test_get_vbm(self):
1✔
170
        vbm = self.bs2.get_vbm()
1✔
171
        assert vbm["energy"] == approx(2.2361), "wrong VBM energy"
1✔
172
        assert len(vbm["band_index"][Spin.up]) == 3, "wrong VBM number of bands"
1✔
173
        assert vbm["band_index"][Spin.up][0] == 5, "wrong VBM band index"
1✔
174
        assert vbm["kpoint_index"][0] == 0, "wrong VBM kpoint index"
1✔
175
        assert vbm["kpoint"].frac_coords[0] == 0.0, "wrong VBM kpoint frac coords"
1✔
176
        assert vbm["kpoint"].frac_coords[1] == 0.0, "wrong VBM kpoint frac coords"
1✔
177
        assert vbm["kpoint"].frac_coords[2] == 0.0, "wrong VBM kpoint frac coords"
1✔
178
        assert vbm["kpoint"].label == "\\Gamma", "wrong VBM kpoint label"
1✔
179
        vbm_spin = self.bs_spin.get_vbm()
1✔
180
        assert vbm_spin["energy"] == approx(5.731), "wrong VBM energy"
1✔
181
        assert len(vbm_spin["band_index"][Spin.up]) == 2, "wrong VBM number of bands"
1✔
182
        assert len(vbm_spin["band_index"][Spin.down]) == 0, "wrong VBM number of bands"
1✔
183
        assert vbm_spin["band_index"][Spin.up][0] == 10, "wrong VBM band index"
1✔
184
        assert vbm_spin["kpoint_index"][0] == 79, "wrong VBM kpoint index"
1✔
185
        assert vbm_spin["kpoint"].frac_coords[0] == 0.5, "wrong VBM kpoint frac coords"
1✔
186
        assert vbm_spin["kpoint"].frac_coords[1] == 0.5, "wrong VBM kpoint frac coords"
1✔
187
        assert vbm_spin["kpoint"].frac_coords[2] == 0.5, "wrong VBM kpoint frac coords"
1✔
188
        assert vbm_spin["kpoint"].label == "L", "wrong VBM kpoint label"
1✔
189

190
    def test_get_band_gap(self):
1✔
191
        bg = self.bs2.get_band_gap()
1✔
192
        assert bg["energy"] == approx(3.6348), "wrong gap energy"
1✔
193
        assert bg["transition"] == "\\Gamma-X", "wrong kpoint transition"
1✔
194
        assert not bg["direct"], "wrong nature of the gap"
1✔
195
        bg_spin = self.bs_spin.get_band_gap()
1✔
196
        assert bg_spin["energy"] == approx(2.3148), "wrong gap energy"
1✔
197
        assert bg_spin["transition"] == "L-\\Gamma", "wrong kpoint transition"
1✔
198
        assert not bg_spin["direct"], "wrong nature of the gap"
1✔
199
        bg_cbm0 = self.bs_cbm0.get_band_gap()
1✔
200
        assert bg_cbm0["energy"] == approx(0, abs=1e-3), "wrong gap energy"
1✔
201

202
    def test_get_sym_eq_kpoints_and_degeneracy(self):
1✔
203
        bs = self.bs2
1✔
204
        cbm_k = bs.get_cbm()["kpoint"].frac_coords
1✔
205
        vbm_k = bs.get_vbm()["kpoint"].frac_coords
1✔
206
        assert bs.get_kpoint_degeneracy(cbm_k) is None
1✔
207
        bs.structure = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "CaO_2605_structure.json"))
1✔
208
        assert bs.get_kpoint_degeneracy(cbm_k) == 3
1✔
209
        assert bs.get_kpoint_degeneracy(vbm_k) == 1
1✔
210
        cbm_eqs = bs.get_sym_eq_kpoints(cbm_k)
1✔
211
        assert [0.5, 0.0, 0.5] in cbm_eqs
1✔
212
        assert [0.0, 0.5, 0.5] in cbm_eqs
1✔
213
        assert [0.5, 0.5, 0.0] in cbm_eqs
1✔
214
        vbm_eqs = bs.get_sym_eq_kpoints(vbm_k)
1✔
215
        assert [0.0, 0.0, 0.0] in vbm_eqs
1✔
216

217
    def test_as_dict(self):
1✔
218
        expected_keys = {
1✔
219
            "@module",
220
            "@class",
221
            "lattice_rec",
222
            "efermi",
223
            "kpoints",
224
            "bands",
225
            "is_metal",
226
            "vbm",
227
            "cbm",
228
            "band_gap",
229
            "labels_dict",
230
            "is_spin_polarized",
231
            "projections",
232
            # "structure",  # not always present
233
            "branches",
234
        }
235
        d1 = self.bs.as_dict()
1✔
236
        assert set(d1) >= expected_keys, f"{expected_keys - set(d1)=}"
1✔
237
        d2 = self.bs2.as_dict()
1✔
238
        assert set(d2) >= expected_keys, f"{expected_keys - set(d2)=}"
1✔
239
        d3 = self.bs_spin.as_dict()
1✔
240
        assert set(d3) >= expected_keys, f"{expected_keys - set(d3)=}"
1✔
241

242
    def test_old_format_load(self):
1✔
243
        with open(os.path.join(PymatgenTest.TEST_FILES_DIR, "bs_ZnS_old.json")) as f:
1✔
244
            d = json.load(f)
1✔
245
            bs_old = BandStructureSymmLine.from_dict(d)
1✔
246
            assert bs_old.get_projection_on_elements()[Spin.up][0][0]["Zn"] == 0.0971
1✔
247

248

249
class ReconstructBandStructureTest(PymatgenTest):
1✔
250
    def setUp(self):
1✔
251
        self.bs_cu = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "Cu_30_bandstructure.json"))
1✔
252
        self.bs_cu2 = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "Cu_30_bandstructure.json"))
1✔
253
        warnings.simplefilter("ignore")
1✔
254

255
    def tearDown(self):
1✔
256
        warnings.simplefilter("default")
1✔
257

258
    def test_reconstruct_band_structure(self):
1✔
259
        bs = get_reconstructed_band_structure([self.bs_cu, self.bs_cu2])
1✔
260
        assert bs.bands[Spin.up].shape == (20, 700), "wrong number of bands or kpoints"
1✔
261

262
    def test_vasprun_bs(self):
1✔
263
        bsv = BSVasprun(
1✔
264
            os.path.join(PymatgenTest.TEST_FILES_DIR, "vasprun.xml"),
265
            parse_projected_eigen=True,
266
            parse_potcar_file=True,
267
        )
268
        bs = bsv.get_band_structure(
1✔
269
            kpoints_filename=os.path.join(PymatgenTest.TEST_FILES_DIR, "KPOINTS.band"), line_mode=True
270
        )
271
        bs.get_projection_on_elements()
1✔
272

273

274
class LobsterBandStructureSymmLineTest(PymatgenTest):
1✔
275
    def setUp(self):
1✔
276
        warnings.simplefilter("ignore")
1✔
277
        with open(
1✔
278
            os.path.join(PymatgenTest.TEST_FILES_DIR, "cohp/Fatband_SiO2/Test_p/lobster_band_structure_spin.json"),
279
        ) as f:
280
            bs_spin_dict = json.load(f)
1✔
281
        self.bs_spin = LobsterBandStructureSymmLine.from_dict(bs_spin_dict)
1✔
282

283
        with open(
1✔
284
            os.path.join(PymatgenTest.TEST_FILES_DIR, "cohp/Fatband_SiO2/Test_p/lobster_band_structure.json"),
285
        ) as f:
286
            bs_dict = json.load(f)
1✔
287
        self.bs_p = LobsterBandStructureSymmLine.from_dict(bs_dict)
1✔
288

289
    def tearDown(self):
1✔
290
        warnings.simplefilter("default")
1✔
291

292
    def test_basic(self):
1✔
293
        bs_p = self.bs_p
1✔
294
        bs_spin = self.bs_spin
1✔
295
        assert bs_p.structure[0].frac_coords[0] == approx(0.0)
1✔
296
        assert bs_p.structure[0].frac_coords[1] == approx(0.47634315)
1✔
297
        assert bs_p.structure[0].frac_coords[2] == approx(0.666667)
1✔
298
        assert bs_p.structure[0].species_string == "Si"
1✔
299
        assert bs_p.structure[0].coords[0] == approx(-1.19607309)
1✔
300
        assert bs_p.structure[0].coords[1] == approx(2.0716597)
1✔
301
        assert bs_p.structure[0].coords[2] == approx(3.67462144)
1✔
302
        assert bs_p.efermi == approx(1.06470288)
1✔
303

304
        lattice = bs_p.lattice_rec.as_dict()
1✔
305
        assert lattice["matrix"][0][0] == approx(1.2511575194890285)
1✔
306
        assert lattice["matrix"][0][1] == approx(0.7223560132915973)
1✔
307
        assert lattice["matrix"][0][2] == approx(0.0)
1✔
308
        assert lattice["matrix"][1][0] == approx(0.0)
1✔
309
        assert lattice["matrix"][1][1] == approx(1.4447123171425553)
1✔
310
        assert lattice["matrix"][1][2] == approx(0.0)
1✔
311
        assert lattice["matrix"][2][0] == approx(0.0)
1✔
312
        assert lattice["matrix"][2][1] == approx(0.0)
1✔
313
        assert lattice["matrix"][2][2] == approx(1.1399248502312707)
1✔
314
        assert bs_p.kpoints[8].frac_coords[0] == approx(0.09090909)
1✔
315
        assert bs_p.kpoints[8].frac_coords[1] == approx(0.0)
1✔
316
        assert bs_p.kpoints[8].frac_coords[2] == approx(0.0)
1✔
317
        assert bs_p.kpoints[8].cart_coords[0] == approx(0.11374159)
1✔
318
        assert bs_p.kpoints[8].cart_coords[1] == approx(0.06566873)
1✔
319
        assert bs_p.kpoints[8].cart_coords[2] == approx(0.0)
1✔
320
        assert bs_p.kpoints[50].frac_coords[0] == approx(0.46153846)
1✔
321
        assert bs_p.kpoints[50].frac_coords[1] == approx(0.07692308)
1✔
322
        assert bs_p.kpoints[50].frac_coords[2] == approx(0.0)
1✔
323
        assert bs_p.kpoints[50].cart_coords[0] == approx(0.57745732)
1✔
324
        assert bs_p.kpoints[50].cart_coords[1] == approx(0.4445268)
1✔
325
        assert bs_p.kpoints[50].cart_coords[2] == approx(0.0)
1✔
326
        assert bs_p.distance[30] == approx(0.49251552363382556)
1✔
327
        assert bs_p.branches[0]["name"], "\\Gamma-K"
1✔
328
        assert bs_p.get_band_gap()["energy"] == approx(5.6739999999999995)
1✔
329
        assert bs_p.get_projection_on_elements()[Spin.up][0][0]["Si"] == approx(3 * (0.001 + 0.064))
1✔
330
        assert bs_p.get_projections_on_elements_and_orbitals({"Si": ["3p"]})[Spin.up][0][0]["Si"]["3p"] == approx(0.003)
1✔
331
        assert bs_p.get_projections_on_elements_and_orbitals({"O": ["2p"]})[Spin.up][0][0]["O"]["2p"] == approx(
1✔
332
            0.002 * 3 + 0.003 * 3
333
        )
334
        dict_here = bs_p.get_projections_on_elements_and_orbitals({"Si": ["3s", "3p"], "O": ["2s", "2p"]})[Spin.up][0][
1✔
335
            0
336
        ]
337
        assert dict_here["Si"]["3s"] == approx(0.192)
1✔
338
        assert dict_here["Si"]["3p"] == approx(0.003)
1✔
339
        assert dict_here["O"]["2s"] == approx(0.792)
1✔
340
        assert dict_here["O"]["2p"] == approx(0.015)
1✔
341

342
        assert bs_spin.get_projection_on_elements()[Spin.up][0][0]["Si"] == approx(3 * (0.001 + 0.064))
1✔
343
        assert bs_spin.get_projections_on_elements_and_orbitals({"Si": ["3p"]})[Spin.up][0][0]["Si"]["3p"] == approx(
1✔
344
            0.003
345
        )
346
        assert bs_spin.get_projections_on_elements_and_orbitals({"O": ["2p"]})[Spin.up][0][0]["O"]["2p"] == approx(
1✔
347
            0.002 * 3 + 0.003 * 3
348
        )
349

350
        dict_here = bs_spin.get_projections_on_elements_and_orbitals({"Si": ["3s", "3p"], "O": ["2s", "2p"]})[Spin.up][
1✔
351
            0
352
        ][0]
353
        assert dict_here["Si"]["3s"] == approx(0.192)
1✔
354
        assert dict_here["Si"]["3p"] == approx(0.003)
1✔
355
        assert dict_here["O"]["2s"] == approx(0.792)
1✔
356
        assert dict_here["O"]["2p"] == approx(0.015)
1✔
357
        assert bs_spin.get_projection_on_elements()[Spin.up][0][0]["Si"] == approx(3 * (0.001 + 0.064))
1✔
358
        assert bs_spin.get_projections_on_elements_and_orbitals({"Si": ["3p"]})[Spin.down][0][0]["Si"]["3p"] == approx(
1✔
359
            0.003
360
        )
361
        assert bs_spin.get_projections_on_elements_and_orbitals({"O": ["2p"]})[Spin.down][0][0]["O"]["2p"] == approx(
1✔
362
            0.002 * 3 + 0.003 * 3
363
        )
364
        dict_here = bs_spin.get_projections_on_elements_and_orbitals({"Si": ["3s", "3p"], "O": ["2s", "2p"]})[
1✔
365
            Spin.down
366
        ][0][0]
367
        assert dict_here["Si"]["3s"] == approx(0.192)
1✔
368
        assert dict_here["Si"]["3p"] == approx(0.003)
1✔
369
        assert dict_here["O"]["2s"] == approx(0.792)
1✔
370
        assert dict_here["O"]["2p"] == approx(0.015)
1✔
371

372
    def test_proj_bandstructure_plot(self):
1✔
373
        # make sure that it can be plotted!
374
        BSPlotterProjected(self.bs_spin).get_elt_projected_plots()
1✔
375
        BSPlotterProjected(self.bs_spin).get_projected_plots_dots({"Si": ["3s"]})
1✔
376

377
    def test_get_branch(self):
1✔
378
        branch = self.bs_p.get_branch(0)[0]
1✔
379
        assert branch["name"] == "\\Gamma-K"
1✔
380
        assert branch["start_index"] == 0
1✔
381
        assert branch["end_index"] == 70
1✔
382
        assert branch["index"] == 0
1✔
383

384
    def test_get_direct_band_gap_dict(self):
1✔
385
        direct_dict = self.bs_p.get_direct_band_gap_dict()
1✔
386
        assert direct_dict[Spin.up]["value"] == approx(6.005999999999999)
1✔
387
        assert direct_dict[Spin.up]["kpoint_index"] == 0
1✔
388
        assert direct_dict[Spin.up]["band_indices"] == [22, 24]
1✔
389

390
        direct_dict = self.bs_spin.get_direct_band_gap_dict()
1✔
391
        assert direct_dict[Spin.up]["value"] == approx(6.005999999999999)
1✔
392
        assert direct_dict[Spin.up]["kpoint_index"] == 0
1✔
393
        assert direct_dict[Spin.up]["band_indices"] == [22, 24]
1✔
394
        assert direct_dict[Spin.down]["value"] == approx(6.005999999999999)
1✔
395
        assert direct_dict[Spin.down]["kpoint_index"] == 0
1✔
396
        assert direct_dict[Spin.down]["band_indices"] == [22, 24]
1✔
397

398
    def test_get_direct_band_gap(self):
1✔
399
        assert self.bs_p.get_direct_band_gap() == approx(6.005999999999999)
1✔
400
        assert self.bs_spin.get_direct_band_gap() == approx(6.005999999999999)
1✔
401

402
    def test_is_metal(self):
1✔
403
        assert not self.bs_p.is_metal(), "wrong metal assignment"
1✔
404
        assert not self.bs_spin.is_metal(), "wrong metal assignment"
1✔
405

406
    def test_get_cbm(self):
1✔
407
        cbm = self.bs_p.get_cbm()
1✔
408
        assert cbm["energy"] == approx(6.3037028799999995), "wrong CBM energy"
1✔
409
        assert cbm["band_index"][Spin.up][0] == 24, "wrong CBM band index"
1✔
410
        assert cbm["kpoint_index"][0] == 0, "wrong CBM kpoint index"
1✔
411
        assert cbm["kpoint"].frac_coords[0] == 0.0, "wrong CBM kpoint frac coords"
1✔
412
        assert cbm["kpoint"].frac_coords[1] == 0.0, "wrong CBM kpoint frac coords"
1✔
413
        assert cbm["kpoint"].frac_coords[2] == 0.0, "wrong CBM kpoint frac coords"
1✔
414
        assert cbm["kpoint"].label == "\\Gamma", "wrong CBM kpoint label"
1✔
415
        cbm_spin = self.bs_spin.get_cbm()
1✔
416
        assert cbm_spin["energy"] == approx(6.30370274), "wrong CBM energy"
1✔
417
        assert cbm_spin["band_index"][Spin.up][0] == 24, "wrong CBM band index"
1✔
418
        assert len(cbm_spin["band_index"][Spin.down]) == 1, "wrong CBM band index"
1✔
419
        assert cbm_spin["kpoint_index"][0] == 0, "wrong CBM kpoint index"
1✔
420
        assert cbm_spin["kpoint"].frac_coords[0] == 0.0, "wrong CBM kpoint frac coords"
1✔
421
        assert cbm_spin["kpoint"].frac_coords[1] == 0.0, "wrong CBM kpoint frac coords"
1✔
422
        assert cbm_spin["kpoint"].frac_coords[2] == 0.0, "wrong CBM kpoint frac coords"
1✔
423
        assert cbm_spin["kpoint"].label == "\\Gamma", "wrong CBM kpoint label"
1✔
424

425
    def test_get_vbm(self):
1✔
426
        vbm = self.bs_p.get_vbm()
1✔
427
        assert vbm["energy"] == approx(0.62970288), "wrong VBM energy"
1✔
428
        assert len(vbm["band_index"][Spin.up]) == 1, "wrong VBM number of bands"
1✔
429
        assert vbm["band_index"][Spin.up][0] == 23, "wrong VBM band index"
1✔
430
        assert vbm["kpoint_index"][0] == 68, "wrong VBM kpoint index"
1✔
431
        assert vbm["kpoint"].frac_coords[0] == approx(0.34615384615385), "wrong VBM kpoint frac coords"
1✔
432
        assert vbm["kpoint"].frac_coords[1] == approx(0.30769230769231), "wrong VBM kpoint frac coords"
1✔
433
        assert vbm["kpoint"].frac_coords[2] == approx(0.0), "wrong VBM kpoint frac coords"
1✔
434
        assert vbm["kpoint"].label is None, "wrong VBM kpoint label"
1✔
435
        vbm_spin = self.bs_spin.get_vbm()
1✔
436
        assert vbm_spin["energy"] == approx(0.6297027399999999), "wrong VBM energy"
1✔
437
        assert len(vbm_spin["band_index"][Spin.up]) == 1, "wrong VBM number of bands"
1✔
438
        assert len(vbm_spin["band_index"][Spin.down]) == 1, "wrong VBM number of bands"
1✔
439
        assert vbm_spin["band_index"][Spin.up][0] == 23, "wrong VBM band index"
1✔
440
        assert vbm_spin["kpoint_index"][0] == 68, "wrong VBM kpoint index"
1✔
441
        assert vbm_spin["kpoint"].frac_coords[0] == approx(0.34615384615385), "wrong VBM kpoint frac coords"
1✔
442
        assert vbm_spin["kpoint"].frac_coords[1] == approx(0.30769230769231), "wrong VBM kpoint frac coords"
1✔
443
        assert vbm_spin["kpoint"].frac_coords[2] == approx(0.0), "wrong VBM kpoint frac coords"
1✔
444
        assert vbm_spin["kpoint"].label is None, "wrong VBM kpoint label"
1✔
445

446
    def test_get_band_gap(self):
1✔
447
        bg = self.bs_p.get_band_gap()
1✔
448
        assert bg["energy"] == approx(5.6739999999999995), "wrong gap energy"
1✔
449
        assert bg["transition"] == "(0.346,0.308,0.000)-\\Gamma", "wrong kpoint transition"
1✔
450
        assert not bg["direct"], "wrong nature of the gap"
1✔
451
        bg_spin = self.bs_spin.get_band_gap()
1✔
452
        assert bg_spin["energy"] == approx(5.674), "wrong gap energy"
1✔
453
        assert bg_spin["transition"] == "(0.346,0.308,0.000)-\\Gamma", "wrong kpoint transition"
1✔
454
        assert not bg_spin["direct"], "wrong nature of the gap"
1✔
455

456
    def test_get_sym_eq_kpoints_and_degeneracy(self):
1✔
457
        bs = self.bs_p
1✔
458
        cbm_k = bs.get_cbm()["kpoint"].frac_coords
1✔
459
        vbm_k = bs.get_vbm()["kpoint"].frac_coords
1✔
460
        assert bs.get_kpoint_degeneracy(cbm_k) == 1
1✔
461
        assert bs.get_kpoint_degeneracy(vbm_k) == 3
1✔
462

463
    def test_as_dict(self):
1✔
464
        s = json.dumps(self.bs_p.as_dict())
1✔
465
        assert s is not None
1✔
466
        s = json.dumps(self.bs_spin.as_dict())
1✔
467
        assert s is not None
1✔
468

469
    def test_old_format_load(self):
1✔
470
        # this method will use the loading from the old dict
471
        self.bs_spin.apply_scissor(3.0)
1✔
472

473

474
if __name__ == "__main__":
1✔
475
    unittest.main()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc