def make_band_edge_states(orbital_infos: BandEdgeOrbitalInfos,
                          p_edge_state: PerfectBandEdgeState,
                          defect_charge_info: DefectChargeInfo = None
                          ) -> BandEdgeStates:
    vbm_k_idx = orbital_infos.kpt_idx(p_edge_state.vbm_info.kpt_coord)
    cbm_k_idx = orbital_infos.kpt_idx(p_edge_state.cbm_info.kpt_coord)
    vbm_info = p_edge_state.vbm_info
    cbm_info = p_edge_state.cbm_info

    states = []
    lowest_idx = orbital_infos.lowest_band_index
    for spin_idx, orb_info_by_spin in enumerate(orbital_infos.orbital_infos):
        if defect_charge_info:
            localized_orbs = defect_charge_info.localized_orbitals()[spin_idx]
            localized_orbs = [i - lowest_idx for i in localized_orbs]
        else:
            localized_orbs = None

        vbm_idx, vbm_diff = get_similar_orb_idx(orb_info_by_spin[vbm_k_idx],
                                                vbm_info, localized_orbs,
                                                _reversed=True)
        vbm_info = EdgeInfo(band_idx=vbm_idx + lowest_idx,
                            kpt_coord=vbm_info.kpt_coord,
                            orbital_info=orb_info_by_spin[vbm_k_idx][vbm_idx])

        cbm_idx, cbm_diff = get_similar_orb_idx(orb_info_by_spin[cbm_k_idx],
                                                cbm_info, localized_orbs)
        cbm_info = EdgeInfo(band_idx=cbm_idx + lowest_idx,
                            kpt_coord=cbm_info.kpt_coord,
                            orbital_info=orb_info_by_spin[cbm_k_idx][cbm_idx])

        loc_idx_range = [vbm_info.band_idx + 1, cbm_info.band_idx - 1]
        localized_orbs = get_localized_orbs(orb_info_by_spin,
                                            loc_idx_range,
                                            orbital_infos.lowest_band_index,
                                            orbital_infos.kpt_weights)

        vbm_hole = num_hole_in_vbm(orb_info_by_spin,
                                   vbm_idx=vbm_idx,
                                   weights=orbital_infos.kpt_weights)
        cbm_electron = num_electron_in_cbm(orb_info_by_spin,
                                           cbm_idx=cbm_idx,
                                           weights=orbital_infos.kpt_weights)

        states.append(BandEdgeState(vbm_info=vbm_info,
                                    cbm_info=cbm_info,
                                    vbm_orbital_diff=vbm_diff,
                                    cbm_orbital_diff=cbm_diff,
                                    localized_orbitals=localized_orbs,
                                    vbm_hole_occupation=vbm_hole,
                                    cbm_electron_occupation=cbm_electron))

    return BandEdgeStates(states=states)
Beispiel #2
0
def test_plot_wo_spin():
    be_orbital_info = BandEdgeOrbitalInfos(orbital_infos=[orb],
                                           kpt_coords=[(0.0, 0.0, 0.0),
                                                       (0.25, 0.0, 0.0)],
                                           kpt_weights=[0.5, 0.5],
                                           lowest_band_index=10,
                                           fermi_level=0.5)
    plotter = EigenvalueMplPlotter(title="test",
                                   band_edge_orb_infos=be_orbital_info,
                                   supercell_vbm=0.1,
                                   supercell_cbm=0.9)
    plotter.construct_plot()
    plotter.plt.show()
Beispiel #3
0
def test_band_edge_orbital_info_repr():
    orbital_info_1 = OrbitalInfo(energy=1.23456789,
                                 orbitals={
                                     "Mn": [0.5, 0.4, 0.0, 0.0],
                                     "Fe": [0.0, 0.0, 0.0, 0.0]
                                 },
                                 occupation=0.99998,
                                 participation_ratio=0.1111111)
    orbital_info_2 = OrbitalInfo(energy=2.34567890,
                                 orbitals={
                                     "Mn": [0.1, 0.1, 0.0, 0.0],
                                     "Fe": [0.0, 0.0, 0.0, 0.0]
                                 },
                                 occupation=0.0001,
                                 participation_ratio=0.2222222)

    band_edge_orbital_infos =  \
        BandEdgeOrbitalInfos(orbital_infos=[[[orbital_info_1, orbital_info_2]]],
                             kpt_coords=[(0.0, 0.0, 0.0)],
                             kpt_weights=[1.0],
                             lowest_band_index=10,
                             fermi_level=0.5)

    actual = band_edge_orbital_infos.__str__()
    print(actual)
    expected = """ -- band-edge orbitals info
K-points info
Index  Coords                    Weight
1      ( 0.000,  0.000,  0.000)  1.000

Band info near band edges
Index  Kpoint index  Energy  Occupation  P-ratio  Orbital
11     1             1.23    1.0         0.1      Mn-s: 0.50, Mn-p: 0.40
--
12     1             2.35    0.0         0.2
--
"""
    assert actual == expected
Beispiel #4
0
def orb_infos():
    orbital_infos = [[[
        OrbitalInfo(energy=-1.1,
                    orbitals={
                        "Mn": [0.5, 0.6, 0.0, 0.0],
                        "O": [0.0, 0.0, 0.0, 0.0]
                    },
                    occupation=1.0,
                    participation_ratio=0.1),
        OrbitalInfo(energy=-0.9,
                    orbitals={
                        "Mn": [0.5, 0.7, 0.0, 0.0],
                        "O": [0.0, 0.0, 0.0, 0.0]
                    },
                    occupation=1.0,
                    participation_ratio=0.1),  # vbm
        OrbitalInfo(energy=0.0,
                    orbitals={
                        "Mn": [0.1, 0.2, 0.0, 0.0],
                        "O": [0.3, 0.4, 0.0, 0.0]
                    },
                    occupation=1.0,
                    participation_ratio=0.1),  # in-gap
        OrbitalInfo(energy=1.0,
                    orbitals={
                        "Mn": [0.5, 0.8, 0.0, 0.0],
                        "O": [0.0, 0.0, 0.0, 0.0]
                    },
                    occupation=0.05,
                    participation_ratio=0.1),  # in-gap
        OrbitalInfo(energy=1.2,
                    orbitals={
                        "Mn": [0.0, 0.0, 0.0, 0.0],
                        "O": [0.1, 0.3, 0.0, 0.0]
                    },
                    occupation=0.02,
                    participation_ratio=0.1),
        OrbitalInfo(energy=1.2,
                    orbitals={
                        "Mn": [0.0, 0.0, 0.0, 0.0],
                        "O": [0.1, 0.3, 0.0, 0.0]
                    },
                    occupation=0.01,
                    participation_ratio=0.1)
    ]]]  # cbm
    return BandEdgeOrbitalInfos(kpt_coords=[(0.0, 0.0, 0.0)],
                                kpt_weights=[1.0],
                                orbital_infos=orbital_infos,
                                lowest_band_index=8,
                                fermi_level=0.5)
Beispiel #5
0
def make_band_edge_orbital_infos(procar: Procar,
                                 vasprun: Vasprun,
                                 vbm: float, cbm: float,
                                 str_info: DefectStructureInfo):
    eigval_range = defaults.eigval_range
    kpt_coords = [tuple(coord) for coord in vasprun.actual_kpoints]
    max_energy_by_spin, min_energy_by_spin = [], []
    neighbors = str_info.neighbor_atom_indices

    for e in vasprun.eigenvalues.values():
        max_energy_by_spin.append(np.amax(e[:, :, 0], axis=0))
        min_energy_by_spin.append(np.amin(e[:, :, 0], axis=0))

    max_energy_by_band = np.amax(np.vstack(max_energy_by_spin), axis=0)
    min_energy_by_band = np.amin(np.vstack(min_energy_by_spin), axis=0)

    lower_idx = np.argwhere(max_energy_by_band > vbm - eigval_range)[0][0]
    upper_idx = np.argwhere(min_energy_by_band < cbm + eigval_range)[-1][-1]

    orbs, s = procar.data, vasprun.final_structure
    orb_infos = []
    for spin, eigvals in vasprun.eigenvalues.items():
        orb_infos.append([])
        for k_idx in range(len(kpt_coords)):
            orb_infos[-1].append([])
            for b_idx in range(lower_idx, upper_idx + 1):
                e, occ = eigvals[k_idx, b_idx, :]
                orbitals = calc_orbital_character(orbs, s, spin, k_idx, b_idx)
                p_ratio = calc_participation_ratio(orbs, spin, k_idx, b_idx, neighbors)
                orb_infos[-1][-1].append(OrbitalInfo(e, orbitals, occ, p_ratio))

    return BandEdgeOrbitalInfos(
        orbital_infos=orb_infos,
        kpt_coords=kpt_coords,
        kpt_weights=vasprun.actual_kpoints_weights,
        # need to convert numpy.int64 to int for mongoDB.
        lowest_band_index=int(lower_idx),
        fermi_level=vasprun.efermi)
Beispiel #6
0
                       orbitals={},
                       occupation=1.0,
                       participation_ratio=0.3),
           OrbitalInfo(0.5,
                       orbitals={},
                       occupation=0.5,
                       participation_ratio=0.3),
           OrbitalInfo(1.0,
                       orbitals={},
                       occupation=0.0,
                       participation_ratio=0.3)
       ]]

orbital_infos = BandEdgeOrbitalInfos(orbital_infos=[orb, orb],
                                     kpt_coords=[(0.0, 0.0, 0.0),
                                                 (0.25, 0.0, 0.0)],
                                     kpt_weights=[0.5, 0.5],
                                     lowest_band_index=10,
                                     fermi_level=0.5)


@pytest.fixture
def eigenvalue_mpl_plotter():
    return EigenvalueMplPlotter(title="test",
                                band_edge_orb_infos=orbital_infos,
                                supercell_vbm=0.1,
                                supercell_cbm=0.9)


def test_plot(eigenvalue_mpl_plotter):
    eigenvalue_mpl_plotter.construct_plot()
    eigenvalue_mpl_plotter.plt.show()
Beispiel #7
0
def band_edge_orbital_infos(orbital_info):
    return BandEdgeOrbitalInfos(orbital_infos=[[[orbital_info]]],
                                kpt_coords=[(0.0, 0.0, 0.0)],
                                kpt_weights=[1.0],
                                lowest_band_index=10,
                                fermi_level=0.5)
Beispiel #8
0
def test_make_band_edge_orbital_infos(mocker):
    mock_procar = mocker.Mock(spec=Procar, autospec=True)
    mock_vasprun = mocker.Mock(spec=Vasprun, autospec=True)
    mock_str_info = mocker.Mock(spec=DefectStructureInfo, autospec=True)

    mock_vasprun.actual_kpoints = [[0.0, 0.0, 0.0]]
    mock_vasprun.actual_kpoints_weights = [1.0]
    mock_vasprun.final_structure = Structure(Lattice.cubic(1),
                                             species=["H", "H", "He"],
                                             coords=[[0] * 3] * 3)
    mock_vasprun.eigenvalues = {
        Spin.up:
        np.array([
            [
                [-3.01, 1.],
                [-2.90, 1.],  # vbm
                [8.01, 0.]
            ],
            [[-3.01, 1.], [-2.99, 1.], [7.90, 0.]]
        ]),  # cbm
        # shift one band for testing magnetization
        Spin.down:
        np.array([[[-2.99, 1.], [7.99, 0.], [10.00, 0.]],
                  [[-3.01, 1.], [8.00, 0.], [10.00, 0.]]])
    }
    mock_vasprun.efermi = 20.0
    # s: 1, p: 3, d: 5, f: 7 = 16 orbitals
    mock_procar.data = {
        Spin.up:
        np.array([
            [
                [
                    [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                     0.0],  # 1st kpt, 0th band, 1st atom
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                     0.0],  # 1st kpt, 0th band, 2nd atom
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
                ],  # 1st kpt, 0th band, 3rd atom
                [
                    [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                     0.0],  # 1st kpt, 1st band, 1st atom
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
                ],
                [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
            ],
            [
                [
                    [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                     0.0],  # 2nd kpt, 0th band, 1st atom
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
                ],
                [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]],
                [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
            ]
        ]),
        Spin.down:
        np.array([
            [
                [
                    [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                     0.0],  # 1st kpt, 0th band, 1st atom
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                     0.0],  # 1st kpt, 0th band, 2nd atom
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
                ],  # 1st kpt, 0th band, 3rd atom
                [
                    [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                     0.0],  # 1st kpt, 1st band, 1st atom
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
                ],
                [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
            ],
            [
                [
                    [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                     0.0],  # 2nd kpt, 0th band, 1st atom
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
                ],
                [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]],
                [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
                 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
            ]
        ]),
    }

    mock_str_info.neighbor_atom_indices = [0]
    actual = make_band_edge_orbital_infos(mock_procar,
                                          mock_vasprun,
                                          vbm=0.0,
                                          cbm=5.0,
                                          str_info=mock_str_info)

    expected = BandEdgeOrbitalInfos(
        orbital_infos=[[[
            OrbitalInfo(energy=-2.9,
                        orbitals={
                            "H": [1.0, 0.0, 0.0, 0.0],
                            "He": [0.0, 0.0, 0.0, 0.0]
                        },
                        occupation=1.0,
                        participation_ratio=1.0),
            OrbitalInfo(energy=8.01,
                        orbitals={
                            "H": [1.0, 0.0, 0.0, 0.0],
                            "He": [0.0, 0.0, 0.0, 0.0]
                        },
                        occupation=0.0,
                        participation_ratio=1.0)
        ],
                        [
                            OrbitalInfo(energy=-2.99,
                                        orbitals={
                                            "H": [1.0, 0.0, 0.0, 0.0],
                                            "He": [0.0, 0.0, 0.0, 0.0]
                                        },
                                        occupation=1.0,
                                        participation_ratio=1.0),
                            OrbitalInfo(energy=7.90,
                                        orbitals={
                                            "H": [1.0, 0.0, 0.0, 0.0],
                                            "He": [0.0, 0.0, 0.0, 0.0]
                                        },
                                        occupation=0.0,
                                        participation_ratio=1.0)
                        ]],
                       [[
                           OrbitalInfo(energy=7.99,
                                       orbitals={
                                           "H": [1.0, 0.0, 0.0, 0.0],
                                           "He": [0.0, 0.0, 0.0, 0.0]
                                       },
                                       occupation=0.0,
                                       participation_ratio=1.0),
                           OrbitalInfo(energy=10.00,
                                       orbitals={
                                           "H": [1.0, 0.0, 0.0, 0.0],
                                           "He": [0.0, 0.0, 0.0, 0.0]
                                       },
                                       occupation=0.0,
                                       participation_ratio=1.0)
                       ],
                        [
                            OrbitalInfo(energy=8.00,
                                        orbitals={
                                            "H": [1.0, 0.0, 0.0, 0.0],
                                            "He": [0.0, 0.0, 0.0, 0.0]
                                        },
                                        occupation=0.0,
                                        participation_ratio=1.0),
                            OrbitalInfo(energy=10.00,
                                        orbitals={
                                            "H": [1.0, 0.0, 0.0, 0.0],
                                            "He": [0.0, 0.0, 0.0, 0.0]
                                        },
                                        occupation=0.0,
                                        participation_ratio=1.0)
                        ]]],
        kpt_coords=[(0.0, 0.0, 0.0)],
        kpt_weights=[1.0],
        lowest_band_index=1,
        fermi_level=20.0)
    assert_dataclass_almost_equal(actual, expected)