Skip to content

API

The TMDybinidng package consists of several base lattices, objects to store the parameters for these lattices, functions to build the matrices associated to the hoppings of that model and classes that help user in defining new lattices with (rotational) symmetric aspects for orbitals of non-zero ml-quantum number.

Base lattices

Tight-binding lattices for TMDs for the Pybinding-package.

AbstractLattice

Bases: ABC

Abstract class for a tmd-lattice

Source code in tmdybinding/tmd_abstract_lattice.py
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
class AbstractLattice(ABC):
    """Abstract class for a tmd-lattice"""

    def __init__(self, orbital: LatticeOrbitals, params: ParametersList, soc: bool = False,
                 soc_eo_flip: bool = False, lat4: bool = False, single_orbital: bool = False, soc_sz_part: bool = True,
                 soc_polarized: bool = False, soc_sz: float = 1.,
                 n_v: int = 0, n_b: int = 0, lattice_name: str = "Abstract Lattice"):
        """Make an AbstractLattice object with the given parameters.

        Parameters:
            orbital (LatticeOrbitals): The orbitals for the lattice model.
            params (ParametersList): The parameters for the lattice model.
            soc (bool): If True, the spin-orbit coupling is considere.
            soc_eo_flip (bool): If True, the spin-flip term is included.
            lat4 (bool): If True, the lattice is a 4-atom lattice for use with the armchair direction.
            single_orbital (bool): If True, the lattice is a combination of suborbitals (slower as no matrices are used)
            soc_sz_part (bool): If False, the hamiltonian will not include the Sz part of the spin-orbit coupling.
            soc_polarized (bool): If True, the spin-orbit coupling is polarized (only spin-up part, given by `soc_sz`).
            soc_sz (float): The Sz part of the spin-orbit coupling.
            n_v (int): The index of the highest valence band (in the unitcell).
            n_b (int): The number of bands (in the unitcell).
            lattice_name (str): The name of the lattice. The name of the matrial is obtained from `params`.
        """
        self.lattice_params = VariableStorage()
        self.orbital: LatticeOrbitals = orbital
        self.__n_valence_band: int = n_v
        self.__n_bands: int = n_b
        self.__name: str = "MoS2"
        self.__x_name: str = "S"
        self.__x_type: str = "X"
        self.__m_name: str = "Mo"
        self.__m_type: str = "M"
        self.__params: ParametersList = ParametersList()
        self.__soc_eo_flip: bool = False
        self.__lattice_name: str = lattice_name
        self._lat4: bool = lat4
        self.single_orbital: bool = single_orbital
        self.soc: bool = soc
        self.soc_polarized: bool = soc_polarized
        self.soc_sz_part: bool = soc_sz_part
        self.sz: float = soc_sz
        self.params = params
        self.soc_eo_flip = soc_eo_flip

    @property
    def soc_eo_flip(self) -> bool:
        """If True, the spin-flip term is included.
        The structure is checked for the right shape and properties that it supports a spin-flip term.
        """
        return self.__soc_eo_flip

    @soc_eo_flip.setter
    def soc_eo_flip(self, pol_bool: bool):
        if pol_bool:
            if self.lattice_params.h_0_m is not None:
                assert len(self.orbital.l_number[self.orb_type(self.m_name)]) == 5, \
                    "the metal doesn't have the right shape for spin-flip term"
                assert sorted(self.orbital.l_number[self.orb_type(self.m_name)]) == sorted([0, 2, -2, 1, -1]), \
                    "the metal l is wrong for spin-flip"
            if self.lattice_params.h_0_c is not None:
                assert len(self.orbital.l_number[self.orb_type(self.x_name)]) == 6, \
                    "the chal. doesn't have the right shape for spin-flip term"
                assert sorted(self.orbital.l_number[self.orb_type(self.x_name)]) == sorted([1, -1, 0, 1, -1, 0]), \
                    "the chal. l is wrong for spin-flip"
        self.__soc_eo_flip = pol_bool

    @property
    def params(self) -> ParametersList:
        """The parameters for the lattice model."""
        return self.__params

    @params.setter
    def params(self, params: ParametersList):
        self.__params = params
        self.name = self.params["material"]

    @property
    def lattice_name(self) -> str:
        """The name of the lattice. This is not the name of the material."""
        return self.__lattice_name

    @lattice_name.setter
    def lattice_name(self, lattice_name: str):
        self.__lattice_name = lattice_name

    @property
    def name(self) -> str:
        """The name of the material."""
        return self.__name

    @property
    def m_name(self) -> str:
        """The name of the metal atom."""
        return self.__m_name

    def orb_type(self, z_name: str) -> Optional[str]:
        """Return the orbital type of the atom with the given name. Usefull for the case when `lat4` is True.
        Returns `"M"` for the metal atom and `"X"` for the chalcogen atom.
        """
        if z_name == self.m_name or (self.lat4 and z_name == self.m_name + "2"):
            return self.__m_type
        elif z_name == self.x_name or (self.lat4 and z_name == self.x_name + "2"):
            return self.__x_type
        else:
            return None

    def z_name(self, orb_type: str) -> Optional[str]:
        """Return the name of the atom with the given orbital type, for example, obtain `"S"` from `"X"` in the case
        the material is `"MoS2"`.
        """
        if orb_type == self.__m_type:
            return self.m_name
        elif orb_type == self.__x_type:
            return self.x_name
        else:
            return None

    @property
    def x_name(self) -> str:
        """The name of the chalcogen atom."""
        return self.__x_name

    @name.setter
    def name(self, name: str):
        self.__name = name
        self.__m_name, self.__x_name = re.findall("[A-Z][a-z]*", self.name)
        self._generate_matrices()

    @property
    def lat4(self) -> bool:
        """If True, the lattice is a 4-atom lattice for use with the armchair direction."""
        return self._lat4

    @lat4.setter
    def lat4(self, lat4: bool):
        self._lat4 = lat4
        self._generate_matrices()

    @property
    def a1(self) -> np.ndarray:
        """The first lattice vector. Corrected if `lat4` is True."""
        return np.array([1, 0]) * self.lattice_params.a

    @property
    def a2(self) -> np.ndarray:
        """The second lattice vector. Corrected if `lat4` is True."""
        return (np.array([0, np.sqrt(3)]) if self.lat4 else np.array([-1 / 2, np.sqrt(3) / 2])) * self.lattice_params.a

    @property
    def soc_doubled_ham(self) -> bool:
        """If True, the hamiltonian is doubled for the spin-orbit coupling."""
        return not self.soc_polarized if self.soc else False

    @property
    def soc_eo_flip_used(self) -> bool:
        """If True, the spin-flip term is used."""
        return self.soc and self.soc_eo_flip and not self.soc_polarized

    @property
    def n_valence_band(self) -> int:
        """The index of the highest valence band. Corrected for the SOC and `lat4`."""
        return (self.__n_valence_band + 1) * 2 - 1 if self.soc_doubled_ham else self.__n_valence_band

    @property
    def n_bands(self) -> int:
        """The total number of bands. Corrected for the SOC and `lat4`."""
        return self.__n_bands * (2 if self.soc_doubled_ham else 1)

    @property
    def _m_orbs(self) -> List[str]:
        m_orbs = [self.m_name + mi for mi in self.orbital.orbs[self.orb_type(self.m_name)]]
        if self.soc_doubled_ham:
            m_orbs = [mi + "u" for mi in m_orbs] + [mi + "d" for mi in m_orbs]
        return m_orbs

    @property
    def _m2_orbs(self) -> List[str]:
        m2_orbs = [self.m_name + "2" + mi for mi in self.orbital.orbs[self.orb_type(self.m_name)]]
        if self.soc_doubled_ham:
            m2_orbs = [mi + "u" for mi in m2_orbs] + [mi + "d" for mi in m2_orbs]
        return m2_orbs

    @property
    def _c_orbs(self) -> List[str]:
        c_orbs = [self.x_name + ci for ci in self.orbital.orbs[self.orb_type(self.x_name)]]
        if self.soc_doubled_ham:
            c_orbs = [ci + "u" for ci in c_orbs] + [ci + "d" for ci in c_orbs]
        return c_orbs

    @property
    def _c2_orbs(self) -> List[str]:
        c2_orbs = [self.x_name + "2" + ci for ci in self.orbital.orbs[self.orb_type(self.x_name)]]
        if self.soc_doubled_ham:
            c2_orbs = [ci + "u" for ci in c2_orbs] + [ci + "d" for ci in c2_orbs]
        return c2_orbs

    @staticmethod
    def _make_name(h_name: str, n_i: int, nfi: str, ntj: str) -> str:
        return h_name + "-" + str(n_i) + "-" + nfi + "-" + ntj

    @staticmethod
    def _separate_name(h_name_i) -> Tuple[str, int, str, str]:
        out = re.findall("[^-]+(?:[^-]*)*", h_name_i)
        assert len(out) == 4, "The given string isn't generated by the right function, the length isn't 4"
        out[1] = int(out[1])
        return str(out[0]), int(out[1]), str(out[2]), str(out[3])

    @abstractmethod
    def _generate_matrices(self):
        """Generate the matrices for the lattice model.
        This function should be implemented in the child class.
        """
        pass

    @staticmethod
    def _ham(h: np.ndarray, ur_l: np.ndarray, ur_r: np.ndarray) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
        return h, ur_l.dot(h.dot(ur_r.T)), ur_l.T.dot(h.dot(ur_r))

    @staticmethod
    def _reorder(matrix: np.ndarray, keys: Tuple[List[int], List[int]]) -> np.ndarray:
        return np.array([[matrix[xi, yi] for yi in keys[1]] for xi in keys[0]])

    def block_diag(self, *matrices) -> np.ndarray:
        """Make a block diagonal matrix from the given matrices."""
        if len(matrices) == 1:
            return matrices[0]
        else:
            matrix0 = matrices[0]
            matrix1 = self.block_diag(*matrices[1:])
            shape_0 = np.shape(matrix0)
            shape_1 = np.shape(matrix1)
            z_1 = [shape_0[-2], shape_1[-1]]
            z_2 = [shape_1[-2], shape_0[-1]]
            nd = len(shape_0)
            assert nd == len(shape_1), "The matrices don't have the right sizes in the additional dimensions"
            if nd > 2:
                for sh in shape_1[:-2]:
                    z_1.insert(0, sh)
                    z_2.insert(0, sh)
            return np.concatenate((np.concatenate((matrix0, np.zeros(z_1)), axis=nd - 1),
                                   np.concatenate((np.zeros(z_2), matrix1), axis=nd - 1)), axis=nd - 2)

    def _make_onsite(self, matrix, name, lamb):
        def ham_sz(sz):
            if self.soc_sz_part:
                s_part = sz * lamb * 1j * self.orbital.s_h[self.orb_type(name)]
                return matrix + s_part
            else:
                return np.array(matrix, dtype=complex)

        if self.soc:
            if self.soc_polarized:
                return ham_sz(self.sz)
            else:
                return self.block_diag(ham_sz(self.sz), ham_sz(-self.sz))
        else:
            return ham_sz(0.)

    def _make_h(self, matrix, from_name, to_name):
        (h_1, h_2, h_3) = self._ham(matrix,
                                    self.orbital.ur[self.orb_type(to_name)],
                                    self.orbital.ur[self.orb_type(from_name)])
        if self.soc_doubled_ham:
            h_1 = np.kron(np.eye(2), h_1)
            h_2 = np.kron(np.eye(2), h_2)
            h_3 = np.kron(np.eye(2), h_3)
        return h_1, h_2, h_3

    def _make_h_angle(self, matrix, from_name, to_name, angle):
        (h_1, h_2, h_3) = self._ham(matrix,
                                    self.orbital.ur_angle(angle)[self.orb_type(to_name)],
                                    self.orbital.ur_angle(angle)[self.orb_type(from_name)])
        return h_1, h_2, h_3

    def _add_hopping(self, lat, mat, f_n, t_n, cos, fnl, tnl, h_name):
        hn = self._make_h(mat, f_n, t_n)
        n_n_n = [0, 1, 2]
        if self.lat4:
            hn = [hn[int(ih / 2)] for ih in range(6)]
            n_n_n = [0, 0, 1, 1, 2, 2]
        # n_n = 6 if self.lat4 else 3
        if self.single_orbital:
            for f_i, nf_i in enumerate(fnl):
                for t_j, nt_j in enumerate(tnl):
                    h_names = [self._make_name(h_name, n_i, nfi, ntj) for n_i, nfi, ntj in zip(n_n_n, nf_i, nt_j)]
                    lat.register_hopping_energies(dict([(h_n_i, h.conj().T[f_i, t_j]) for h_n_i, h in zip(h_names, hn)]))
                    lat.add_hoppings(*[(co, nfi, ntj, h_n_i) for co, h_n_i, nfi, ntj in zip(cos, h_names, nf_i, nt_j)])
        else:
            h_names = [self._make_name(h_name, n_i, nfi, ntj) for n_i, nfi, ntj in zip(n_n_n, fnl, tnl)]
            lat.register_hopping_energies(dict([(h_n_i, h.conj().T) for h_n_i, h in zip(h_names, hn)]))
            lat.add_hoppings(*[(co, nfi, ntj, h_n_i) for co, h_n_i, nfi, ntj in zip(cos, h_names, fnl, tnl)])
        return lat

    def lattice(self) -> pb.Lattice:
        """Make the lattice model. It returns a `pybinding.Lattice` object."""
        lat = pb.Lattice(a1=self.a1, a2=self.a2)
        m_orbs, m2_orbs = 0, 0
        c_orbs, c2_orbs = 0, 0
        if self.lattice_params.h_0_m is not None:
            m_orbs = self._m_orbs
            m2_orbs = self._m2_orbs
            h_0_m = self._make_onsite(self.lattice_params.h_0_m, self.m_name, self.lattice_params.lamb_m)
            n_m, n_c = 0, 0
            if self.soc_eo_flip_used:
                soc_part_m = np.zeros((5, 5)) * 1j
                soc_part_m[3:, :3] = self.sz * self.lattice_params.lamb_m * np.array(
                    [[np.sqrt(3) / 2, -1 / 2, 1j / 2],
                     [-1j / 2 * np.sqrt(3), -1j / 2, -1 / 2]])
                soc_part_m[:3, 3:] = -soc_part_m[3:, :3].T
                reorder_keys = [np.abs(np.array([0, 2, -2, 1, -1]) - key).argmin()
                                for key in self.orbital.l_number[self.orb_type(self.m_name)]]
                soc_part_m = self._reorder(soc_part_m, (reorder_keys, reorder_keys))
                h_0_m[:5, 5:] = soc_part_m
                h_0_m[5:, :5] = soc_part_m.conj().T

            pos_m = np.array([0, 0])
            if self.single_orbital:
                n_m = len(m_orbs)
                for i_m in range(n_m):
                    lat.add_one_sublattice(m_orbs[i_m], pos_m, np.real(h_0_m[i_m, i_m]))
                for i_m in range(n_m):
                    for j_m in np.arange(i_m + 1, n_m):
                        h_name = self._make_name("h_0_m", 0, m_orbs[i_m], m_orbs[j_m])
                        lat.register_hopping_energies(dict([(h_name, h_0_m[i_m, j_m])]))
                        lat.add_one_hopping([0, 0], m_orbs[i_m], m_orbs[j_m], h_name)
            else:
                lat.add_one_sublattice(self.m_name, pos_m, h_0_m)
            if self.lat4:
                pos_m2 = np.array([self.lattice_params.a / 2, self.lattice_params.a * np.sqrt(3) / 2])
                if self.single_orbital:
                    for i_m in range(n_m):
                        lat.add_one_sublattice(m2_orbs[i_m], pos_m2, np.real(h_0_m[i_m, i_m]))
                    for i_m in range(n_m):
                        for j_m in np.arange(i_m + 1, n_m):
                            h_name = self._make_name("h_0_m", 0, m2_orbs[i_m], m2_orbs[j_m])
                            lat.register_hopping_energies(dict([(h_name, h_0_m[i_m, j_m])]))
                            lat.add_one_hopping([0, 0], m2_orbs[i_m], m2_orbs[j_m], h_name)
                else:
                    lat.add_one_sublattice(self.m_name + "2", pos_m2, h_0_m)

        if self.lattice_params.h_0_c is not None:
            h_0_c = self._make_onsite(self.lattice_params.h_0_c, self.x_name, self.lattice_params.lamb_c)
            c_orbs = self._c_orbs
            c2_orbs = self._c2_orbs
            n_c = len(c_orbs)
            if self.soc_eo_flip_used:
                soc_part_c = np.zeros((6, 6)) * 1j
                soc_part_c[:3, 3:] = self.sz * self.lattice_params.lamb_c * np.array(
                    [[0, 0, 1 / 2],
                     [0, 0, -1j / 2],
                     [-1 / 2, 1j / 2, 0]])
                soc_part_c[3:, :3] = -soc_part_c[:3, 3:].T
                reorder_keys1 = [np.abs(np.array([1, -1, 0]) - key).argmin()
                                 for key in self.orbital.l_number[self.orb_type(self.x_name)][:3]]
                reorder_keys2 = [3 + np.abs(np.array([1, -1, 0]) - key).argmin()
                                 for key in self.orbital.l_number[self.orb_type(self.x_name)][3:]]
                soc_part_c = self._reorder(soc_part_c, (reorder_keys1 + reorder_keys2, reorder_keys1 + reorder_keys2))
                h_0_c[:6, 6:] = soc_part_c
                h_0_c[6:, :6] = soc_part_c.conj().T
            pos_c = np.array([self.lattice_params.a / 2, self.lattice_params.a * np.sqrt(3) / 6])
            if self.single_orbital:
                for i_c in range(n_c):
                    lat.add_one_sublattice(c_orbs[i_c],pos_c, np.real(h_0_c[i_c, i_c]))
                for i_c in range(n_c):
                    for j_c in np.arange(i_c + 1, n_c):
                        h_name = self._make_name("h_0_c", 0, c_orbs[i_c], c_orbs[j_c])
                        lat.register_hopping_energies(dict([(h_name, h_0_c[i_c, j_c])]))
                        lat.add_one_hopping([0, 0], c_orbs[i_c], c_orbs[j_c], h_name)
            else:
                lat.add_one_sublattice(self.x_name, pos_c, h_0_c)

            if self.lat4:
                pos_c2 = np.array([0, self.lattice_params.a * 2 * np.sqrt(3) / 6])
                if self.single_orbital:
                    for i_c in range(n_c):
                        lat.add_one_sublattice(c2_orbs[i_c], pos_c2, np.real(h_0_c[i_c, i_c]))
                    for i_c in range(n_c):
                        for j_c in np.arange(i_c + 1, n_c):
                            h_name = self._make_name("h_0_c", 0, c2_orbs[i_c], c2_orbs[j_c])
                            lat.register_hopping_energies(dict([(h_name, h_0_c[i_c, j_c])]))
                            lat.add_one_hopping([0, 0], c2_orbs[i_c], c2_orbs[j_c], h_name)
                else:
                    lat.add_one_sublattice(self.x_name + "2", pos_c2, h_0_c)

        if self.lattice_params.h_1_m is not None:
            cos = [[-1, -1], [0, 0], [-1, 0]] if not self.lat4 else [[0, -1], [0, 0], [0, 0], [1, 0], [-1, 0], [0, 0]]
            fnl = (
                (
                    [[m_i] * 3 for m_i in m_orbs]
                    if not self.lat4 else
                    [mi * 3 for mi in zip(m_orbs, m2_orbs)]
                ) if self.single_orbital else (
                    [self.m_name] * 3
                    if not self.lat4 else
                    [self.m_name, self.m_name + "2"] * 3
                )
            )
            tnl = (
                (
                    [[c_i] * 3 for c_i in c_orbs]
                    if not self.lat4 else
                    [[c2, c1, c1, c2, c1, c2] for (c1, c2) in zip(c_orbs, c2_orbs)]
                ) if self.single_orbital else (
                    [self.x_name] * 3
                    if not self.lat4 else
                    [self.x_name + "2", self.x_name, self.x_name, self.x_name + "2", self.x_name, self.x_name + "2"]
                )
            )
            lat = self._add_hopping(lat=lat,
                                    mat=self.lattice_params.h_1_m,
                                    f_n=self.m_name,
                                    t_n=self.x_name,
                                    cos=cos,
                                    fnl=fnl,
                                    tnl=tnl,
                                    h_name="h_1_m")

        if self.lattice_params.h_2_m is not None:
            cos = [[1, 0], [0, 1], [-1, -1]] if not self.lat4 else [[1, 0], [1, 0], [-1, 0], [0, 1], [-1, -1], [0, 0]]
            fnl = (
                (
                    [[m_i] * 3 for m_i in m_orbs]
                    if not self.lat4 else
                    [mi * 3 for mi in zip(m_orbs, m2_orbs)]
                ) if self.single_orbital else (
                    [self.m_name] * 3
                    if not self.lat4 else
                    [self.m_name, self.m_name + "2"] * 3
                )
            )
            tnl = (
                (
                    [[m_i] * 3 for m_i in m_orbs]
                    if not self.lat4 else
                    [[m1, m2, m2, m1, m2, m1] for (m1, m2) in zip(m_orbs, m2_orbs)]
                ) if self.single_orbital else (
                    [self.m_name] * 3
                    if not self.lat4 else
                    [self.m_name, self.m_name + "2", self.m_name + "2", self.m_name, self.m_name + "2", self.m_name]
                )
            )
            lat = self._add_hopping(lat=lat,
                                    mat=self.lattice_params.h_2_m,
                                    f_n=self.m_name,
                                    t_n=self.m_name,
                                    cos=cos,
                                    fnl=fnl,
                                    tnl=tnl,
                                    h_name="h_2_m")

        if self.lattice_params.h_2_c is not None:
            cos = [[1, 0], [0, 1], [-1, -1]] if not self.lat4 else [[1, 0], [1, 0], [0, 0], [-1, 1], [0, -1], [-1, 0]]
            fnl = (
                (
                    [[c_i] * 3 for c_i in c_orbs]
                    if not self.lat4 else
                    [ci * 3 for ci in zip(c_orbs, c2_orbs)]
                ) if self.single_orbital else (
                    [self.x_name] * 3
                    if not self.lat4 else
                    [self.x_name, self.x_name + "2"] * 3
                )
            )
            tnl = (
                (
                    [[c_i] * 3 for c_i in c_orbs]
                    if not self.lat4 else
                    [[c1, c2, c2, c1, c2, c1] for (c1, c2) in zip(c_orbs, c2_orbs)]
                ) if self.single_orbital else (
                    [self.x_name] * 3
                    if not self.lat4 else
                    [self.x_name, self.x_name + "2", self.x_name + "2", self.x_name, self.x_name + "2", self.x_name]
                )
            )
            lat = self._add_hopping(lat=lat,
                                    mat=self.lattice_params.h_2_c,
                                    f_n=self.x_name,
                                    t_n=self.x_name,
                                    cos=cos,
                                    fnl=fnl,
                                    tnl=tnl,
                                    h_name="h_2_c")

        if self.lattice_params.h_3_m is not None:
            cos = [[0, 1], [-2, -1], [0, -1]] if not self.lat4 else [[0, 0], [0, 1], [-1, -1], [-1, 0], [1, -1], [1, 0]]
            fnl = (
                (
                    [[m_i] * 3 for m_i in m_orbs]
                    if not self.lat4 else
                    [mi * 3 for mi in zip(m_orbs, m2_orbs)]
                ) if self.single_orbital else (
                    [self.m_name] * 3
                    if not self.lat4 else
                    [self.m_name, self.m_name + "2"] * 3
                )
            )
            tnl = (
                (
                    [[c_i] * 3 for c_i in c_orbs]
                    if not self.lat4 else
                    [ci * 3 for ci in zip(c2_orbs, c_orbs)]
                ) if self.single_orbital else (
                    [self.x_name] * 3
                    if not self.lat4 else
                    [self.x_name + "2", self.x_name] * 3
                )
            )
            lat = self._add_hopping(lat=lat,
                                    mat=self.lattice_params.h_3_m,
                                    f_n=self.m_name,
                                    t_n=self.x_name,
                                    cos=cos,
                                    fnl=fnl,
                                    tnl=tnl,
                                    h_name="h_3_m")

        if self.lattice_params.h_4_m is not None:
            _, h_4_ma, h_4_mb = self._make_h_angle(
                self.lattice_params.h_4_m, self.m_name, self.x_name, np.arctan(np.sqrt(3) / 5)
            )
            cosa = [[-1, -2], [1, 1], [-2, 0]] \
                if not self.lat4 else [[0, -1], [1, -1], [1, 0], [1, 1], [-2, 0], [-1, 0]]
            cosb = [[-2, -2], [1, 0], [-1, 1]] \
                if not self.lat4 else [[-1, -1], [0, -1], [1, 0], [2, 0], [-1, 0], [-1, 1]]
            fnl = (
                (
                    [[m_i] * 3 for m_i in m_orbs]
                    if not self.lat4 else
                    [mi * 3 for mi in zip(m_orbs, m2_orbs)]
                ) if self.single_orbital else (
                    [self.m_name] * 3
                    if not self.lat4 else
                    [self.m_name, self.m_name + "2"] * 3
                )
            )
            tnla = (
                (
                    [[c_i] * 3 for c_i in c_orbs]
                    if not self.lat4 else
                    [[c1, c2, c2, c1, c1, c2] for (c1, c2) in zip(c_orbs, c2_orbs)]
                ) if self.single_orbital else (
                    [self.x_name] * 3
                    if not self.lat4 else
                    [self.x_name, self.x_name + "2", self.x_name + "2", self.x_name, self.x_name, self.x_name + "2"] * 3
                )
            )
            tnlb = (
                (
                    [[c_i] * 3 for c_i in c_orbs]
                    if not self.lat4 else
                    [[c1, c2, c1, c2, c2, c1] for (c1, c2) in zip(c_orbs, c2_orbs)]
                ) if self.single_orbital else (
                    [self.x_name] * 3
                    if not self.lat4 else
                    [self.x_name, self.x_name + "2", self.x_name, self.x_name + "2", self.x_name + "2", self.x_name] * 3
                )
            )
            lat = self._add_hopping(lat=lat,
                                    mat=h_4_ma,
                                    f_n=self.m_name,
                                    t_n=self.x_name,
                                    cos=cosa,
                                    fnl=fnl,
                                    tnl=tnla,
                                    h_name="h_4_ma")
            lat = self._add_hopping(lat=lat,
                                    mat=h_4_mb,
                                    f_n=self.m_name,
                                    t_n=self.x_name,
                                    cos=cosb,
                                    fnl=fnl,
                                    tnl=tnlb,
                                    h_name="h_4_mb")

        if self.lattice_params.h_5_m is not None:
            cos = [[1, 2], [-2, -1], [1, -1]] if not self.lat4 else [[0, 1], [0, 1], [-2, -1], [-1, 0], [1, -1], [2, 0]]
            fnl = (
                (
                    [[m_i] * 3 for m_i in m_orbs]
                    if not self.lat4 else
                    [mi * 3 for mi in zip(m_orbs, m2_orbs)]
                ) if self.single_orbital else (
                    [self.m_name] * 3
                    if not self.lat4 else
                    [self.m_name, self.m_name + "2"] * 3
                )
            )
            tnl = (
                (
                    [[m_i] * 3 for m_i in m_orbs]
                    if not self.lat4 else
                    [[m1, m2, m2, m1, m2, m1] for (m1, m2) in zip(m_orbs, m2_orbs)]
                ) if self.single_orbital else (
                    [self.m_name] * 3
                    if not self.lat4 else
                    [self.m_name, self.m_name + "2", self.m_name + "2", self.m_name, self.m_name + "2", self.m_name]
                )
            )
            lat = self._add_hopping(lat=lat,
                                    mat=self.lattice_params.h_5_m,
                                    f_n=self.m_name,
                                    t_n=self.m_name,
                                    cos=cos,
                                    fnl=fnl,
                                    tnl=tnl,
                                    h_name="h_5_m")

        if self.lattice_params.h_5_c is not None:
            cos = [[1, 2], [-2, -1], [1, -1]] if not self.lat4 else [[0, 1], [0, 1], [-1, -1], [-2, 0], [2, -1], [1, 0]]
            fnl = (
                (
                    [[c_i] * 3 for c_i in c_orbs]
                    if not self.lat4 else
                    [ci * 3 for ci in zip(c_orbs, c2_orbs)]
                ) if self.single_orbital else (
                    [self.x_name] * 3
                    if not self.lat4 else
                    [self.x_name, self.x_name + "2"] * 3
                )
            )
            tnl = (
                (
                    [[c_i] * 3 for c_i in c_orbs]
                    if not self.lat4 else
                    [[c1, c2, c2, c1, c2, c1] for (c1, c2) in zip(c_orbs, c2_orbs)]
                ) if self.single_orbital else (
                    [self.x_name] * 3
                    if not self.lat4 else
                    [self.x_name, self.x_name + "2", self.x_name + "2", self.x_name, self.x_name + "2", self.x_name]
                )
            )
            lat = self._add_hopping(lat=lat,
                                    mat=self.lattice_params.h_5_c,
                                    f_n=self.x_name,
                                    t_n=self.x_name,
                                    cos=cos,
                                    fnl=fnl,
                                    tnl=tnl,
                                    h_name="h_5_c")

        if self.lattice_params.h_6_m is not None:
            cos = [[2, 0], [0, 2], [-2, -2]] \
                if not self.lat4 else [[2, 0], [2, 0], [-1, 1], [-1, 1], [-1, -1], [-1, -1]]
            fnl = (
                (
                    [[m_i] * 3 for m_i in m_orbs]
                    if not self.lat4 else
                    [mi * 3 for mi in zip(m_orbs, m2_orbs)]
                ) if self.single_orbital else (
                    [self.m_name] * 3
                    if not self.lat4 else
                    [self.m_name, self.m_name + "2"] * 3
                )
            )
            tnl = fnl
            lat = self._add_hopping(lat=lat,
                                    mat=self.lattice_params.h_6_m,
                                    f_n=self.m_name,
                                    t_n=self.m_name,
                                    cos=cos,
                                    fnl=fnl,
                                    tnl=tnl,
                                    h_name="h_6_m")

        if self.lattice_params.h_6_c is not None:
            cos = [[2, 0], [0, 2], [-2, -2]] \
                if not self.lat4 else [[2, 0], [2, 0], [-1, 1], [-1, 1], [-1, -1], [-1, -1]]
            fnl = (
                (
                    [[c_i] * 3 for c_i in c_orbs]
                    if not self.lat4 else
                    [ci * 3 for ci in zip(c_orbs, c2_orbs)]
                ) if self.single_orbital else (
                    [self.x_name] * 3
                    if not self.lat4 else
                    [self.x_name, self.x_name + "2"] * 3
                )
            )
            tnl = (
                (
                    [[c_i] * 3 for c_i in c_orbs]
                    if not self.lat4 else
                    [[c1, c2, c2, c1, c2, c1] for (c1, c2) in zip(c_orbs, c2_orbs)]
                ) if self.single_orbital else (
                    [self.x_name] * 3
                    if not self.lat4 else
                    [self.x_name, self.x_name + "2"] * 3
                )
            )
            lat = self._add_hopping(lat=lat,
                                    mat=self.lattice_params.h_6_c,
                                    f_n=self.x_name,
                                    t_n=self.x_name,
                                    cos=cos,
                                    fnl=fnl,
                                    tnl=tnl,
                                    h_name="h_6_c")
        return lat

a1: np.ndarray property

The first lattice vector. Corrected if lat4 is True.

a2: np.ndarray property

The second lattice vector. Corrected if lat4 is True.

lat4: bool property writable

If True, the lattice is a 4-atom lattice for use with the armchair direction.

lattice_name: str property writable

The name of the lattice. This is not the name of the material.

m_name: str property

The name of the metal atom.

n_bands: int property

The total number of bands. Corrected for the SOC and lat4.

n_valence_band: int property

The index of the highest valence band. Corrected for the SOC and lat4.

name: str property writable

The name of the material.

params: ParametersList property writable

The parameters for the lattice model.

soc_doubled_ham: bool property

If True, the hamiltonian is doubled for the spin-orbit coupling.

soc_eo_flip: bool property writable

If True, the spin-flip term is included. The structure is checked for the right shape and properties that it supports a spin-flip term.

soc_eo_flip_used: bool property

If True, the spin-flip term is used.

x_name: str property

The name of the chalcogen atom.

__init__(orbital, params, soc=False, soc_eo_flip=False, lat4=False, single_orbital=False, soc_sz_part=True, soc_polarized=False, soc_sz=1.0, n_v=0, n_b=0, lattice_name='Abstract Lattice')

Make an AbstractLattice object with the given parameters.

Parameters:

Name Type Description Default
orbital LatticeOrbitals

The orbitals for the lattice model.

required
params ParametersList

The parameters for the lattice model.

required
soc bool

If True, the spin-orbit coupling is considere.

False
soc_eo_flip bool

If True, the spin-flip term is included.

False
lat4 bool

If True, the lattice is a 4-atom lattice for use with the armchair direction.

False
single_orbital bool

If True, the lattice is a combination of suborbitals (slower as no matrices are used)

False
soc_sz_part bool

If False, the hamiltonian will not include the Sz part of the spin-orbit coupling.

True
soc_polarized bool

If True, the spin-orbit coupling is polarized (only spin-up part, given by soc_sz).

False
soc_sz float

The Sz part of the spin-orbit coupling.

1.0
n_v int

The index of the highest valence band (in the unitcell).

0
n_b int

The number of bands (in the unitcell).

0
lattice_name str

The name of the lattice. The name of the matrial is obtained from params.

'Abstract Lattice'
Source code in tmdybinding/tmd_abstract_lattice.py
def __init__(self, orbital: LatticeOrbitals, params: ParametersList, soc: bool = False,
             soc_eo_flip: bool = False, lat4: bool = False, single_orbital: bool = False, soc_sz_part: bool = True,
             soc_polarized: bool = False, soc_sz: float = 1.,
             n_v: int = 0, n_b: int = 0, lattice_name: str = "Abstract Lattice"):
    """Make an AbstractLattice object with the given parameters.

    Parameters:
        orbital (LatticeOrbitals): The orbitals for the lattice model.
        params (ParametersList): The parameters for the lattice model.
        soc (bool): If True, the spin-orbit coupling is considere.
        soc_eo_flip (bool): If True, the spin-flip term is included.
        lat4 (bool): If True, the lattice is a 4-atom lattice for use with the armchair direction.
        single_orbital (bool): If True, the lattice is a combination of suborbitals (slower as no matrices are used)
        soc_sz_part (bool): If False, the hamiltonian will not include the Sz part of the spin-orbit coupling.
        soc_polarized (bool): If True, the spin-orbit coupling is polarized (only spin-up part, given by `soc_sz`).
        soc_sz (float): The Sz part of the spin-orbit coupling.
        n_v (int): The index of the highest valence band (in the unitcell).
        n_b (int): The number of bands (in the unitcell).
        lattice_name (str): The name of the lattice. The name of the matrial is obtained from `params`.
    """
    self.lattice_params = VariableStorage()
    self.orbital: LatticeOrbitals = orbital
    self.__n_valence_band: int = n_v
    self.__n_bands: int = n_b
    self.__name: str = "MoS2"
    self.__x_name: str = "S"
    self.__x_type: str = "X"
    self.__m_name: str = "Mo"
    self.__m_type: str = "M"
    self.__params: ParametersList = ParametersList()
    self.__soc_eo_flip: bool = False
    self.__lattice_name: str = lattice_name
    self._lat4: bool = lat4
    self.single_orbital: bool = single_orbital
    self.soc: bool = soc
    self.soc_polarized: bool = soc_polarized
    self.soc_sz_part: bool = soc_sz_part
    self.sz: float = soc_sz
    self.params = params
    self.soc_eo_flip = soc_eo_flip

block_diag(*matrices)

Make a block diagonal matrix from the given matrices.

Source code in tmdybinding/tmd_abstract_lattice.py
def block_diag(self, *matrices) -> np.ndarray:
    """Make a block diagonal matrix from the given matrices."""
    if len(matrices) == 1:
        return matrices[0]
    else:
        matrix0 = matrices[0]
        matrix1 = self.block_diag(*matrices[1:])
        shape_0 = np.shape(matrix0)
        shape_1 = np.shape(matrix1)
        z_1 = [shape_0[-2], shape_1[-1]]
        z_2 = [shape_1[-2], shape_0[-1]]
        nd = len(shape_0)
        assert nd == len(shape_1), "The matrices don't have the right sizes in the additional dimensions"
        if nd > 2:
            for sh in shape_1[:-2]:
                z_1.insert(0, sh)
                z_2.insert(0, sh)
        return np.concatenate((np.concatenate((matrix0, np.zeros(z_1)), axis=nd - 1),
                               np.concatenate((np.zeros(z_2), matrix1), axis=nd - 1)), axis=nd - 2)

lattice()

Make the lattice model. It returns a pybinding.Lattice object.

Source code in tmdybinding/tmd_abstract_lattice.py
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
def lattice(self) -> pb.Lattice:
    """Make the lattice model. It returns a `pybinding.Lattice` object."""
    lat = pb.Lattice(a1=self.a1, a2=self.a2)
    m_orbs, m2_orbs = 0, 0
    c_orbs, c2_orbs = 0, 0
    if self.lattice_params.h_0_m is not None:
        m_orbs = self._m_orbs
        m2_orbs = self._m2_orbs
        h_0_m = self._make_onsite(self.lattice_params.h_0_m, self.m_name, self.lattice_params.lamb_m)
        n_m, n_c = 0, 0
        if self.soc_eo_flip_used:
            soc_part_m = np.zeros((5, 5)) * 1j
            soc_part_m[3:, :3] = self.sz * self.lattice_params.lamb_m * np.array(
                [[np.sqrt(3) / 2, -1 / 2, 1j / 2],
                 [-1j / 2 * np.sqrt(3), -1j / 2, -1 / 2]])
            soc_part_m[:3, 3:] = -soc_part_m[3:, :3].T
            reorder_keys = [np.abs(np.array([0, 2, -2, 1, -1]) - key).argmin()
                            for key in self.orbital.l_number[self.orb_type(self.m_name)]]
            soc_part_m = self._reorder(soc_part_m, (reorder_keys, reorder_keys))
            h_0_m[:5, 5:] = soc_part_m
            h_0_m[5:, :5] = soc_part_m.conj().T

        pos_m = np.array([0, 0])
        if self.single_orbital:
            n_m = len(m_orbs)
            for i_m in range(n_m):
                lat.add_one_sublattice(m_orbs[i_m], pos_m, np.real(h_0_m[i_m, i_m]))
            for i_m in range(n_m):
                for j_m in np.arange(i_m + 1, n_m):
                    h_name = self._make_name("h_0_m", 0, m_orbs[i_m], m_orbs[j_m])
                    lat.register_hopping_energies(dict([(h_name, h_0_m[i_m, j_m])]))
                    lat.add_one_hopping([0, 0], m_orbs[i_m], m_orbs[j_m], h_name)
        else:
            lat.add_one_sublattice(self.m_name, pos_m, h_0_m)
        if self.lat4:
            pos_m2 = np.array([self.lattice_params.a / 2, self.lattice_params.a * np.sqrt(3) / 2])
            if self.single_orbital:
                for i_m in range(n_m):
                    lat.add_one_sublattice(m2_orbs[i_m], pos_m2, np.real(h_0_m[i_m, i_m]))
                for i_m in range(n_m):
                    for j_m in np.arange(i_m + 1, n_m):
                        h_name = self._make_name("h_0_m", 0, m2_orbs[i_m], m2_orbs[j_m])
                        lat.register_hopping_energies(dict([(h_name, h_0_m[i_m, j_m])]))
                        lat.add_one_hopping([0, 0], m2_orbs[i_m], m2_orbs[j_m], h_name)
            else:
                lat.add_one_sublattice(self.m_name + "2", pos_m2, h_0_m)

    if self.lattice_params.h_0_c is not None:
        h_0_c = self._make_onsite(self.lattice_params.h_0_c, self.x_name, self.lattice_params.lamb_c)
        c_orbs = self._c_orbs
        c2_orbs = self._c2_orbs
        n_c = len(c_orbs)
        if self.soc_eo_flip_used:
            soc_part_c = np.zeros((6, 6)) * 1j
            soc_part_c[:3, 3:] = self.sz * self.lattice_params.lamb_c * np.array(
                [[0, 0, 1 / 2],
                 [0, 0, -1j / 2],
                 [-1 / 2, 1j / 2, 0]])
            soc_part_c[3:, :3] = -soc_part_c[:3, 3:].T
            reorder_keys1 = [np.abs(np.array([1, -1, 0]) - key).argmin()
                             for key in self.orbital.l_number[self.orb_type(self.x_name)][:3]]
            reorder_keys2 = [3 + np.abs(np.array([1, -1, 0]) - key).argmin()
                             for key in self.orbital.l_number[self.orb_type(self.x_name)][3:]]
            soc_part_c = self._reorder(soc_part_c, (reorder_keys1 + reorder_keys2, reorder_keys1 + reorder_keys2))
            h_0_c[:6, 6:] = soc_part_c
            h_0_c[6:, :6] = soc_part_c.conj().T
        pos_c = np.array([self.lattice_params.a / 2, self.lattice_params.a * np.sqrt(3) / 6])
        if self.single_orbital:
            for i_c in range(n_c):
                lat.add_one_sublattice(c_orbs[i_c],pos_c, np.real(h_0_c[i_c, i_c]))
            for i_c in range(n_c):
                for j_c in np.arange(i_c + 1, n_c):
                    h_name = self._make_name("h_0_c", 0, c_orbs[i_c], c_orbs[j_c])
                    lat.register_hopping_energies(dict([(h_name, h_0_c[i_c, j_c])]))
                    lat.add_one_hopping([0, 0], c_orbs[i_c], c_orbs[j_c], h_name)
        else:
            lat.add_one_sublattice(self.x_name, pos_c, h_0_c)

        if self.lat4:
            pos_c2 = np.array([0, self.lattice_params.a * 2 * np.sqrt(3) / 6])
            if self.single_orbital:
                for i_c in range(n_c):
                    lat.add_one_sublattice(c2_orbs[i_c], pos_c2, np.real(h_0_c[i_c, i_c]))
                for i_c in range(n_c):
                    for j_c in np.arange(i_c + 1, n_c):
                        h_name = self._make_name("h_0_c", 0, c2_orbs[i_c], c2_orbs[j_c])
                        lat.register_hopping_energies(dict([(h_name, h_0_c[i_c, j_c])]))
                        lat.add_one_hopping([0, 0], c2_orbs[i_c], c2_orbs[j_c], h_name)
            else:
                lat.add_one_sublattice(self.x_name + "2", pos_c2, h_0_c)

    if self.lattice_params.h_1_m is not None:
        cos = [[-1, -1], [0, 0], [-1, 0]] if not self.lat4 else [[0, -1], [0, 0], [0, 0], [1, 0], [-1, 0], [0, 0]]
        fnl = (
            (
                [[m_i] * 3 for m_i in m_orbs]
                if not self.lat4 else
                [mi * 3 for mi in zip(m_orbs, m2_orbs)]
            ) if self.single_orbital else (
                [self.m_name] * 3
                if not self.lat4 else
                [self.m_name, self.m_name + "2"] * 3
            )
        )
        tnl = (
            (
                [[c_i] * 3 for c_i in c_orbs]
                if not self.lat4 else
                [[c2, c1, c1, c2, c1, c2] for (c1, c2) in zip(c_orbs, c2_orbs)]
            ) if self.single_orbital else (
                [self.x_name] * 3
                if not self.lat4 else
                [self.x_name + "2", self.x_name, self.x_name, self.x_name + "2", self.x_name, self.x_name + "2"]
            )
        )
        lat = self._add_hopping(lat=lat,
                                mat=self.lattice_params.h_1_m,
                                f_n=self.m_name,
                                t_n=self.x_name,
                                cos=cos,
                                fnl=fnl,
                                tnl=tnl,
                                h_name="h_1_m")

    if self.lattice_params.h_2_m is not None:
        cos = [[1, 0], [0, 1], [-1, -1]] if not self.lat4 else [[1, 0], [1, 0], [-1, 0], [0, 1], [-1, -1], [0, 0]]
        fnl = (
            (
                [[m_i] * 3 for m_i in m_orbs]
                if not self.lat4 else
                [mi * 3 for mi in zip(m_orbs, m2_orbs)]
            ) if self.single_orbital else (
                [self.m_name] * 3
                if not self.lat4 else
                [self.m_name, self.m_name + "2"] * 3
            )
        )
        tnl = (
            (
                [[m_i] * 3 for m_i in m_orbs]
                if not self.lat4 else
                [[m1, m2, m2, m1, m2, m1] for (m1, m2) in zip(m_orbs, m2_orbs)]
            ) if self.single_orbital else (
                [self.m_name] * 3
                if not self.lat4 else
                [self.m_name, self.m_name + "2", self.m_name + "2", self.m_name, self.m_name + "2", self.m_name]
            )
        )
        lat = self._add_hopping(lat=lat,
                                mat=self.lattice_params.h_2_m,
                                f_n=self.m_name,
                                t_n=self.m_name,
                                cos=cos,
                                fnl=fnl,
                                tnl=tnl,
                                h_name="h_2_m")

    if self.lattice_params.h_2_c is not None:
        cos = [[1, 0], [0, 1], [-1, -1]] if not self.lat4 else [[1, 0], [1, 0], [0, 0], [-1, 1], [0, -1], [-1, 0]]
        fnl = (
            (
                [[c_i] * 3 for c_i in c_orbs]
                if not self.lat4 else
                [ci * 3 for ci in zip(c_orbs, c2_orbs)]
            ) if self.single_orbital else (
                [self.x_name] * 3
                if not self.lat4 else
                [self.x_name, self.x_name + "2"] * 3
            )
        )
        tnl = (
            (
                [[c_i] * 3 for c_i in c_orbs]
                if not self.lat4 else
                [[c1, c2, c2, c1, c2, c1] for (c1, c2) in zip(c_orbs, c2_orbs)]
            ) if self.single_orbital else (
                [self.x_name] * 3
                if not self.lat4 else
                [self.x_name, self.x_name + "2", self.x_name + "2", self.x_name, self.x_name + "2", self.x_name]
            )
        )
        lat = self._add_hopping(lat=lat,
                                mat=self.lattice_params.h_2_c,
                                f_n=self.x_name,
                                t_n=self.x_name,
                                cos=cos,
                                fnl=fnl,
                                tnl=tnl,
                                h_name="h_2_c")

    if self.lattice_params.h_3_m is not None:
        cos = [[0, 1], [-2, -1], [0, -1]] if not self.lat4 else [[0, 0], [0, 1], [-1, -1], [-1, 0], [1, -1], [1, 0]]
        fnl = (
            (
                [[m_i] * 3 for m_i in m_orbs]
                if not self.lat4 else
                [mi * 3 for mi in zip(m_orbs, m2_orbs)]
            ) if self.single_orbital else (
                [self.m_name] * 3
                if not self.lat4 else
                [self.m_name, self.m_name + "2"] * 3
            )
        )
        tnl = (
            (
                [[c_i] * 3 for c_i in c_orbs]
                if not self.lat4 else
                [ci * 3 for ci in zip(c2_orbs, c_orbs)]
            ) if self.single_orbital else (
                [self.x_name] * 3
                if not self.lat4 else
                [self.x_name + "2", self.x_name] * 3
            )
        )
        lat = self._add_hopping(lat=lat,
                                mat=self.lattice_params.h_3_m,
                                f_n=self.m_name,
                                t_n=self.x_name,
                                cos=cos,
                                fnl=fnl,
                                tnl=tnl,
                                h_name="h_3_m")

    if self.lattice_params.h_4_m is not None:
        _, h_4_ma, h_4_mb = self._make_h_angle(
            self.lattice_params.h_4_m, self.m_name, self.x_name, np.arctan(np.sqrt(3) / 5)
        )
        cosa = [[-1, -2], [1, 1], [-2, 0]] \
            if not self.lat4 else [[0, -1], [1, -1], [1, 0], [1, 1], [-2, 0], [-1, 0]]
        cosb = [[-2, -2], [1, 0], [-1, 1]] \
            if not self.lat4 else [[-1, -1], [0, -1], [1, 0], [2, 0], [-1, 0], [-1, 1]]
        fnl = (
            (
                [[m_i] * 3 for m_i in m_orbs]
                if not self.lat4 else
                [mi * 3 for mi in zip(m_orbs, m2_orbs)]
            ) if self.single_orbital else (
                [self.m_name] * 3
                if not self.lat4 else
                [self.m_name, self.m_name + "2"] * 3
            )
        )
        tnla = (
            (
                [[c_i] * 3 for c_i in c_orbs]
                if not self.lat4 else
                [[c1, c2, c2, c1, c1, c2] for (c1, c2) in zip(c_orbs, c2_orbs)]
            ) if self.single_orbital else (
                [self.x_name] * 3
                if not self.lat4 else
                [self.x_name, self.x_name + "2", self.x_name + "2", self.x_name, self.x_name, self.x_name + "2"] * 3
            )
        )
        tnlb = (
            (
                [[c_i] * 3 for c_i in c_orbs]
                if not self.lat4 else
                [[c1, c2, c1, c2, c2, c1] for (c1, c2) in zip(c_orbs, c2_orbs)]
            ) if self.single_orbital else (
                [self.x_name] * 3
                if not self.lat4 else
                [self.x_name, self.x_name + "2", self.x_name, self.x_name + "2", self.x_name + "2", self.x_name] * 3
            )
        )
        lat = self._add_hopping(lat=lat,
                                mat=h_4_ma,
                                f_n=self.m_name,
                                t_n=self.x_name,
                                cos=cosa,
                                fnl=fnl,
                                tnl=tnla,
                                h_name="h_4_ma")
        lat = self._add_hopping(lat=lat,
                                mat=h_4_mb,
                                f_n=self.m_name,
                                t_n=self.x_name,
                                cos=cosb,
                                fnl=fnl,
                                tnl=tnlb,
                                h_name="h_4_mb")

    if self.lattice_params.h_5_m is not None:
        cos = [[1, 2], [-2, -1], [1, -1]] if not self.lat4 else [[0, 1], [0, 1], [-2, -1], [-1, 0], [1, -1], [2, 0]]
        fnl = (
            (
                [[m_i] * 3 for m_i in m_orbs]
                if not self.lat4 else
                [mi * 3 for mi in zip(m_orbs, m2_orbs)]
            ) if self.single_orbital else (
                [self.m_name] * 3
                if not self.lat4 else
                [self.m_name, self.m_name + "2"] * 3
            )
        )
        tnl = (
            (
                [[m_i] * 3 for m_i in m_orbs]
                if not self.lat4 else
                [[m1, m2, m2, m1, m2, m1] for (m1, m2) in zip(m_orbs, m2_orbs)]
            ) if self.single_orbital else (
                [self.m_name] * 3
                if not self.lat4 else
                [self.m_name, self.m_name + "2", self.m_name + "2", self.m_name, self.m_name + "2", self.m_name]
            )
        )
        lat = self._add_hopping(lat=lat,
                                mat=self.lattice_params.h_5_m,
                                f_n=self.m_name,
                                t_n=self.m_name,
                                cos=cos,
                                fnl=fnl,
                                tnl=tnl,
                                h_name="h_5_m")

    if self.lattice_params.h_5_c is not None:
        cos = [[1, 2], [-2, -1], [1, -1]] if not self.lat4 else [[0, 1], [0, 1], [-1, -1], [-2, 0], [2, -1], [1, 0]]
        fnl = (
            (
                [[c_i] * 3 for c_i in c_orbs]
                if not self.lat4 else
                [ci * 3 for ci in zip(c_orbs, c2_orbs)]
            ) if self.single_orbital else (
                [self.x_name] * 3
                if not self.lat4 else
                [self.x_name, self.x_name + "2"] * 3
            )
        )
        tnl = (
            (
                [[c_i] * 3 for c_i in c_orbs]
                if not self.lat4 else
                [[c1, c2, c2, c1, c2, c1] for (c1, c2) in zip(c_orbs, c2_orbs)]
            ) if self.single_orbital else (
                [self.x_name] * 3
                if not self.lat4 else
                [self.x_name, self.x_name + "2", self.x_name + "2", self.x_name, self.x_name + "2", self.x_name]
            )
        )
        lat = self._add_hopping(lat=lat,
                                mat=self.lattice_params.h_5_c,
                                f_n=self.x_name,
                                t_n=self.x_name,
                                cos=cos,
                                fnl=fnl,
                                tnl=tnl,
                                h_name="h_5_c")

    if self.lattice_params.h_6_m is not None:
        cos = [[2, 0], [0, 2], [-2, -2]] \
            if not self.lat4 else [[2, 0], [2, 0], [-1, 1], [-1, 1], [-1, -1], [-1, -1]]
        fnl = (
            (
                [[m_i] * 3 for m_i in m_orbs]
                if not self.lat4 else
                [mi * 3 for mi in zip(m_orbs, m2_orbs)]
            ) if self.single_orbital else (
                [self.m_name] * 3
                if not self.lat4 else
                [self.m_name, self.m_name + "2"] * 3
            )
        )
        tnl = fnl
        lat = self._add_hopping(lat=lat,
                                mat=self.lattice_params.h_6_m,
                                f_n=self.m_name,
                                t_n=self.m_name,
                                cos=cos,
                                fnl=fnl,
                                tnl=tnl,
                                h_name="h_6_m")

    if self.lattice_params.h_6_c is not None:
        cos = [[2, 0], [0, 2], [-2, -2]] \
            if not self.lat4 else [[2, 0], [2, 0], [-1, 1], [-1, 1], [-1, -1], [-1, -1]]
        fnl = (
            (
                [[c_i] * 3 for c_i in c_orbs]
                if not self.lat4 else
                [ci * 3 for ci in zip(c_orbs, c2_orbs)]
            ) if self.single_orbital else (
                [self.x_name] * 3
                if not self.lat4 else
                [self.x_name, self.x_name + "2"] * 3
            )
        )
        tnl = (
            (
                [[c_i] * 3 for c_i in c_orbs]
                if not self.lat4 else
                [[c1, c2, c2, c1, c2, c1] for (c1, c2) in zip(c_orbs, c2_orbs)]
            ) if self.single_orbital else (
                [self.x_name] * 3
                if not self.lat4 else
                [self.x_name, self.x_name + "2"] * 3
            )
        )
        lat = self._add_hopping(lat=lat,
                                mat=self.lattice_params.h_6_c,
                                f_n=self.x_name,
                                t_n=self.x_name,
                                cos=cos,
                                fnl=fnl,
                                tnl=tnl,
                                h_name="h_6_c")
    return lat

orb_type(z_name)

Return the orbital type of the atom with the given name. Usefull for the case when lat4 is True. Returns "M" for the metal atom and "X" for the chalcogen atom.

Source code in tmdybinding/tmd_abstract_lattice.py
def orb_type(self, z_name: str) -> Optional[str]:
    """Return the orbital type of the atom with the given name. Usefull for the case when `lat4` is True.
    Returns `"M"` for the metal atom and `"X"` for the chalcogen atom.
    """
    if z_name == self.m_name or (self.lat4 and z_name == self.m_name + "2"):
        return self.__m_type
    elif z_name == self.x_name or (self.lat4 and z_name == self.x_name + "2"):
        return self.__x_type
    else:
        return None

z_name(orb_type)

Return the name of the atom with the given orbital type, for example, obtain "S" from "X" in the case the material is "MoS2".

Source code in tmdybinding/tmd_abstract_lattice.py
def z_name(self, orb_type: str) -> Optional[str]:
    """Return the name of the atom with the given orbital type, for example, obtain `"S"` from `"X"` in the case
    the material is `"MoS2"`.
    """
    if orb_type == self.__m_type:
        return self.m_name
    elif orb_type == self.__x_type:
        return self.x_name
    else:
        return None

FloatParameter dataclass

Bases: Parameter

Class to store one separate float parameter

Source code in tmdybinding/parameters/symmetry_group.py
@dataclass
class FloatParameter(Parameter):
    """Class to store one separate float parameter"""
    param: Optional[float] = None

LatticeOrbitals

Object for saving the l and s values of a lattice model.

Source code in tmdybinding/tmd_abstract_lattice.py
class LatticeOrbitals:
    """ Object for saving the l and s values of a lattice model."""

    def __init__(self, l_number: Dict[str, List[int]], orbs: Dict[str, List[str]],
                 group: Optional[Dict[str, List[int]]] = None, clockwise: bool = False):
        """Make a LatticeOrbitals object with the given combinations of l and orbs.
        The input for `l`, `orbs` and `group` must be in the format `"atom_name": variables`.


        Parameters:
            l_number (Dict[str, List[int]]): The l-values for the orbitals.
                The dictionary entries must be in the format `"atom_name": l_number`.
                The l-values must be integers.
                They must come in pairs of negative and positive values, except for zero.
                Example: `{"S": [0, 1, -1, 0, 1, -1]}
            orbs (Dict[str, List[str]]): The orbital names for the orbitals.
                The dictionary entries must be in the format `"atom_name": orbs`.
                The orbital names must be strings.
                Example: `{"S": ["pze", "pxe", pye", "pzo", "pxo", "pyo"]}`
            group (Optional[Dict[str, List[int]]): The group of orbitals with the same l-value.
                If multiple orbitals with the same `l` are present on one atom, you can group the similar orbitals.
                If all the `l`-values are unique, the group is not needed.
                The dictionary entries must be in the format `"atom_name": group`.
                Example: `{"S": [0, 1, 1, 2, 3, 3]}`
            clockwise (bool): If True, the rotation matrices are clockwise.
        """
        self.__l_number = None
        self.__orbs = None
        self.__names = None
        self.__group = None
        self.clockwise = clockwise
        self.set_params(l_number=l_number, orbs=orbs, group=group)

    def set_params(self, l_number: Optional[Dict[str, List[int]]] = None, orbs: Optional[Dict[str, List[str]]] = None,
                   group: Optional[Dict[str, List[int]]] = None):
        """Set the parameters for the lattice model.

        Parameters:
            l_number (Optional[Dict[str, List[int]]]): The l-values for the orbitals.
                The dictionary entries must be in the format `"atom_name": l_number`.
                The l-values must be integers.
                They must come in pairs of negative and positive values, except for zero.
                If None, the previous value is kept.
                Example: `{"S": [0, 1, -1, 0, 1, -1]}
            orbs (Optional[Dict[str, Dict[str]]]): The orbital names for the orbitals.
                The dictionary entries must be in the format `"atom_name": orbs`.
                The orbital names must be strings.
                If None, the previous value is kept.
                Example: `{"S": ["pze", "pxe", pye", "pzo", "pxo", "pyo"]}`
            group (Optional[Dict[str, List[int]]): The group of orbitals with the same l-value.
                If multiple orbitals with the same `l` are present on one atom, you can group the similar orbitals.
                If all the `l`-values are unique, the group is not needed.
                If None, the previous value is kept (if there).
                The dictionary entries must be in the format `"atom_name": group`.
                Example: `{"S": [0, 1, 1, 2, 3, 3]}`
        """
        l_pass = l_number or self.l_number
        orbs_pass = orbs or self.orbs
        group_pass = group or self.group
        self._check_names(l_pass, orbs_pass, group_pass)
        self._check_shape(l_pass, orbs_pass, group_pass)

    @staticmethod
    def _make_bools(l_number: Dict[str, List[int]], orbs: Dict[str, List[str]],
                    group: Optional[Dict[str, List[int]]]) -> Tuple[bool, bool, bool]:
        """Make the boolean values for the input.

        Parameters:
            l_number (Dict[str, List[int]]): The l-values for the orbitals.
            orbs (Dict[str, List[str]]): The orbital names for the orbitals.
            group (Optional[Dict[str, List[int]]): The group of orbitals with the same l-value.
        """
        l_bool = l_number is not None
        orbs_bool = orbs is not None
        group_bool = group is not None
        assert l_bool or orbs_bool, "not enough input given, at least l or orbs needed"
        return l_bool, orbs_bool, group_bool

    def _check_names(self, l_number: Dict[str, List[int]], orbs: Dict[str, List[str]],
                     group: Optional[Dict[str, List[int]]]):
        """Check if the names of the orbitals are the same."""
        (l_bool, orbs_bool, group_bool) = self._make_bools(l_number, orbs, group)
        names = None
        if l_bool:
            names_l = [str(name) for name in l_number.keys()]
            names = names_l
        if orbs_bool:
            names_orbs = [str(name) for name in orbs.keys()]
            if names is None:
                names = names_orbs
            else:
                assert names == names_orbs, f"the names of l_number and orbs are not the same, {names} != {names_orbs}"
        if group_bool:
            names_group = [str(name) for name in group.keys()]
            assert names == names_group, \
                f"the names of l_number/orbs  and group are not the same, {names} != {names_group}"
        self.__names = names

    def _check_shape(self, l_number: Dict[str, List[int]], orbs: Dict[str, List[str]],
                     group: Optional[Dict[str, List[int]]]):
        """Check if the shape of the orbitals is correct."""
        (l_bool, orbs_bool, group_bool) = self._make_bools(l_number, orbs, group)
        shape = None
        if l_bool:
            shape_l = [np.shape(l_number[name]) for name in self.names]
            shape = shape_l
        if orbs_bool:
            shape_orbs = [np.shape(orbs[name]) for name in self.names]
            if shape is None:
                shape = shape_orbs
            else:
                assert shape == shape_orbs, f"the shape of l_number and orbs are not the same, {shape} !m {shape_orbs}"
        if group_bool:
            shape_group = [np.shape(group[name]) for name in self.names]
            assert shape == shape_group, "the shape of group and l_number and/or orbs are not the same"

        # see if definition of group and l are correct. If no group is specified, but there is an l, the l is checked
        l_local = l_number if l_bool else dict([(name, np.zeros(shape[j])) for j, name in enumerate(self.names)])
        if not group_bool:
            for name in self.names:
                l_num = np.array(l_local[name])
                for lm in set(np.abs(l_num)):
                    l_b = np.abs(l_num) == lm
                    assert np.sum(l_b) < 3, \
                        f"the representation can only be given for max two parts, {np.sum(l_b)} given"
                    if np.sum(l_b) == 2:
                        assert l_num[l_b][0] == -l_num[l_b][1], \
                            f"can't have same l-number if group is not defined, for '{lm}'"
                    else:
                        assert lm == 0, \
                            f"can't have a sole l-number other than zero, '{lm}' given"
                    assert np.sum(l_b) == 1, \
                        f"can't have a sole l-number, only one '{lm}' given"
        group_local = group if group_bool else dict([(name, np.abs(l_local[name])) for name in self.names])

        # check l and group
        for name in self.names:
            group_l = np.array(group_local[name])
            l_num = np.array(l_local[name])
            for group_i in set(group_l):
                group_b = group_i == group_l
                assert np.sum(group_b) < 3, "the group for representation can only be given for max two parts"
                assert (np.sum(group_b) == 2 and l_num[group_b][0] == -l_num[group_b][1]) or np.sum(group_b) == 1, \
                    "can't have same l-number in same group"
        self.__l_number = l_local
        self.__orbs = orbs
        self.__group = group_local

    @staticmethod
    def rot_mat(phi: float = 0) -> np.ndarray:
        """Make a rotation matrix for the given angle.

        Parameters:
            phi (float): The angle of the rotation matrix.
        """
        return np.array([[np.cos(phi), -np.sin(phi)], [np.sin(phi), np.cos(phi)]])

    @property
    def l_number(self) -> Dict[str, List[int]]:
        """The l-values for the orbitals."""
        return self.__l_number

    @property
    def names(self) -> List[str]:
        """The names of the atoms."""
        return self.__names

    @property
    def orbs(self) -> Dict[str, List[str]]:
        """The orbital names for the orbitals."""
        return self.__orbs

    @property
    def group(self) -> Dict[str, List[int]]:
        """The group of orbitals with the same l-value."""
        return self.__group

    def _make_matrix(self, matrix_func, single) -> Dict[str, np.ndarray]:
        out_dict: Dict[str, np.ndarray] = {}
        for name in self.names:
            group_l = np.array(self.group[name])
            l_num = np.array(self.l_number[name])
            value = np.zeros((len(l_num), len(l_num)))
            for group_i in set(group_l):
                group_b = group_i == group_l
                lm = np.abs(l_num[group_b][0])
                sign = -1 if l_num[group_b][0] < 0 else 1
                if np.sum(group_b) == 2:
                    matrix = matrix_func(lm, sign)
                    for ik, k in enumerate(np.arange(len(l_num))[group_b]):
                        for ikk, kk in enumerate(np.arange(len(l_num))[group_b]):
                            value[k, kk] = matrix[ik, ikk]
                else:
                    value[np.arange(len(l_num))[group_b], np.arange(len(l_num))[group_b]] = single(lm, sign)
            out_dict[name] = value
        return out_dict

    @property
    def ur(self) -> Dict[str, np.ndarray]:
        """Rotation matrix for the orbitals over an angle of 2pi/3.
        Returns a dict of rotation matrices for the orbitals in the format `"atom_name": matrix`.
        """

        def matrix_func(lm, sign):
            ur_t = self.rot_mat(np.pi * 2 / 3 * lm)
            if sign == -1:
                ur_t = np.transpose(ur_t)
            if self.clockwise:
                ur_t = np.transpose(ur_t)
            return ur_t

        def single(lm, sign):
            return 1 + (lm * 0 + sign * 0)

        return self._make_matrix(matrix_func, single)

    @property
    def sr(self) -> Dict[str, np.ndarray]:
        """Mirror on yz-plane.
        Returns a dict of mirror matrices for the orbitals in the format `"atom_name": matrix`.
        """

        def matrix_func(lm, sign):
            return sign * np.diag([-1, 1]) * (1 if np.abs(lm) == 1 else -1)

        def single(lm, sign):
            return 1 + (lm * 0 + sign * 0)

        return self._make_matrix(matrix_func, single)

    def ur_angle(self, angle) -> Dict[str, np.ndarray]:
        """Rotation matrix for the orbitals over an angle of `angle`.
        Returns a dict of rotation matrices for the orbitals over an angle of `angle` in the
        format `"atom_name": matrix`.

        Parameters:
            angle (float): The angle of the rotation matrix.
        """

        def matrix_func(lm, sign):
            ur_t = self.rot_mat(angle * lm)
            if sign == -1:
                ur_t = np.transpose(ur_t)
            if self.clockwise:
                ur_t = np.transpose(ur_t)
            return ur_t

        def single(lm, sign):
            return 1 + (lm * 0 + sign * 0)

        return self._make_matrix(matrix_func, single)

    @property
    def s_h(self):
        """Spin factor for the orbitals.
        Returns a dict of spin matrices for the orbitals in the format `"atom_name": matrix`.
        """

        def matrix_func(lm, sign):
            ur_t = lm / 2 * np.array([[0, -1], [1, 0]])
            if sign == -1:
                ur_t = np.transpose(ur_t)
            return ur_t

        def single(lm, sign):
            return 0 + (lm * 0 + sign * 0)

        return self._make_matrix(matrix_func, single)

group: Dict[str, List[int]] property

The group of orbitals with the same l-value.

l_number: Dict[str, List[int]] property

The l-values for the orbitals.

names: List[str] property

The names of the atoms.

orbs: Dict[str, List[str]] property

The orbital names for the orbitals.

s_h property

Spin factor for the orbitals. Returns a dict of spin matrices for the orbitals in the format "atom_name": matrix.

sr: Dict[str, np.ndarray] property

Mirror on yz-plane. Returns a dict of mirror matrices for the orbitals in the format "atom_name": matrix.

ur: Dict[str, np.ndarray] property

Rotation matrix for the orbitals over an angle of 2pi/3. Returns a dict of rotation matrices for the orbitals in the format "atom_name": matrix.

__init__(l_number, orbs, group=None, clockwise=False)

Make a LatticeOrbitals object with the given combinations of l and orbs. The input for l, orbs and group must be in the format "atom_name": variables.

Parameters:

Name Type Description Default
l_number Dict[str, List[int]]

The l-values for the orbitals. The dictionary entries must be in the format "atom_name": l_number. The l-values must be integers. They must come in pairs of negative and positive values, except for zero. Example: `{"S": [0, 1, -1, 0, 1, -1]}

required
orbs Dict[str, List[str]]

The orbital names for the orbitals. The dictionary entries must be in the format "atom_name": orbs. The orbital names must be strings. Example: {"S": ["pze", "pxe", pye", "pzo", "pxo", "pyo"]}

required
group Optional[Dict[str, List[int]]

The group of orbitals with the same l-value. If multiple orbitals with the same l are present on one atom, you can group the similar orbitals. If all the l-values are unique, the group is not needed. The dictionary entries must be in the format "atom_name": group. Example: {"S": [0, 1, 1, 2, 3, 3]}

None
clockwise bool

If True, the rotation matrices are clockwise.

False
Source code in tmdybinding/tmd_abstract_lattice.py
def __init__(self, l_number: Dict[str, List[int]], orbs: Dict[str, List[str]],
             group: Optional[Dict[str, List[int]]] = None, clockwise: bool = False):
    """Make a LatticeOrbitals object with the given combinations of l and orbs.
    The input for `l`, `orbs` and `group` must be in the format `"atom_name": variables`.


    Parameters:
        l_number (Dict[str, List[int]]): The l-values for the orbitals.
            The dictionary entries must be in the format `"atom_name": l_number`.
            The l-values must be integers.
            They must come in pairs of negative and positive values, except for zero.
            Example: `{"S": [0, 1, -1, 0, 1, -1]}
        orbs (Dict[str, List[str]]): The orbital names for the orbitals.
            The dictionary entries must be in the format `"atom_name": orbs`.
            The orbital names must be strings.
            Example: `{"S": ["pze", "pxe", pye", "pzo", "pxo", "pyo"]}`
        group (Optional[Dict[str, List[int]]): The group of orbitals with the same l-value.
            If multiple orbitals with the same `l` are present on one atom, you can group the similar orbitals.
            If all the `l`-values are unique, the group is not needed.
            The dictionary entries must be in the format `"atom_name": group`.
            Example: `{"S": [0, 1, 1, 2, 3, 3]}`
        clockwise (bool): If True, the rotation matrices are clockwise.
    """
    self.__l_number = None
    self.__orbs = None
    self.__names = None
    self.__group = None
    self.clockwise = clockwise
    self.set_params(l_number=l_number, orbs=orbs, group=group)

rot_mat(phi=0) staticmethod

Make a rotation matrix for the given angle.

Parameters:

Name Type Description Default
phi float

The angle of the rotation matrix.

0
Source code in tmdybinding/tmd_abstract_lattice.py
@staticmethod
def rot_mat(phi: float = 0) -> np.ndarray:
    """Make a rotation matrix for the given angle.

    Parameters:
        phi (float): The angle of the rotation matrix.
    """
    return np.array([[np.cos(phi), -np.sin(phi)], [np.sin(phi), np.cos(phi)]])

set_params(l_number=None, orbs=None, group=None)

Set the parameters for the lattice model.

Parameters:

Name Type Description Default
l_number Optional[Dict[str, List[int]]]

The l-values for the orbitals. The dictionary entries must be in the format "atom_name": l_number. The l-values must be integers. They must come in pairs of negative and positive values, except for zero. If None, the previous value is kept. Example: `{"S": [0, 1, -1, 0, 1, -1]}

None
orbs Optional[Dict[str, Dict[str]]]

The orbital names for the orbitals. The dictionary entries must be in the format "atom_name": orbs. The orbital names must be strings. If None, the previous value is kept. Example: {"S": ["pze", "pxe", pye", "pzo", "pxo", "pyo"]}

None
group Optional[Dict[str, List[int]]

The group of orbitals with the same l-value. If multiple orbitals with the same l are present on one atom, you can group the similar orbitals. If all the l-values are unique, the group is not needed. If None, the previous value is kept (if there). The dictionary entries must be in the format "atom_name": group. Example: {"S": [0, 1, 1, 2, 3, 3]}

None
Source code in tmdybinding/tmd_abstract_lattice.py
def set_params(self, l_number: Optional[Dict[str, List[int]]] = None, orbs: Optional[Dict[str, List[str]]] = None,
               group: Optional[Dict[str, List[int]]] = None):
    """Set the parameters for the lattice model.

    Parameters:
        l_number (Optional[Dict[str, List[int]]]): The l-values for the orbitals.
            The dictionary entries must be in the format `"atom_name": l_number`.
            The l-values must be integers.
            They must come in pairs of negative and positive values, except for zero.
            If None, the previous value is kept.
            Example: `{"S": [0, 1, -1, 0, 1, -1]}
        orbs (Optional[Dict[str, Dict[str]]]): The orbital names for the orbitals.
            The dictionary entries must be in the format `"atom_name": orbs`.
            The orbital names must be strings.
            If None, the previous value is kept.
            Example: `{"S": ["pze", "pxe", pye", "pzo", "pxo", "pyo"]}`
        group (Optional[Dict[str, List[int]]): The group of orbitals with the same l-value.
            If multiple orbitals with the same `l` are present on one atom, you can group the similar orbitals.
            If all the `l`-values are unique, the group is not needed.
            If None, the previous value is kept (if there).
            The dictionary entries must be in the format `"atom_name": group`.
            Example: `{"S": [0, 1, 1, 2, 3, 3]}`
    """
    l_pass = l_number or self.l_number
    orbs_pass = orbs or self.orbs
    group_pass = group or self.group
    self._check_names(l_pass, orbs_pass, group_pass)
    self._check_shape(l_pass, orbs_pass, group_pass)

ur_angle(angle)

Rotation matrix for the orbitals over an angle of angle. Returns a dict of rotation matrices for the orbitals over an angle of angle in the format "atom_name": matrix.

Parameters:

Name Type Description Default
angle float

The angle of the rotation matrix.

required
Source code in tmdybinding/tmd_abstract_lattice.py
def ur_angle(self, angle) -> Dict[str, np.ndarray]:
    """Rotation matrix for the orbitals over an angle of `angle`.
    Returns a dict of rotation matrices for the orbitals over an angle of `angle` in the
    format `"atom_name": matrix`.

    Parameters:
        angle (float): The angle of the rotation matrix.
    """

    def matrix_func(lm, sign):
        ur_t = self.rot_mat(angle * lm)
        if sign == -1:
            ur_t = np.transpose(ur_t)
        if self.clockwise:
            ur_t = np.transpose(ur_t)
        return ur_t

    def single(lm, sign):
        return 1 + (lm * 0 + sign * 0)

    return self._make_matrix(matrix_func, single)

Parameter dataclass

Class to store one separate parameter

Source code in tmdybinding/parameters/symmetry_group.py
@dataclass
class Parameter:
    """Class to store one separate parameter"""
    name: str = ""

ParametersList

Class to save the parameters

Source code in tmdybinding/parameters/symmetry_group.py
class ParametersList:
    """Class to save the parameters"""

    def __init__(self, input_dict: Optional[Dict[str, Union[float, str]]] = None):
        """Initialize the parameters for the TMD lattice.

        Parameters:
            input_dict (Optional[Dict[str, Union[float, str]]]): The parameters for the TMD lattice.
                The keys are the names of the parameters and the values are the values of the parameters.
                The keys are:
                `a`,            `lamb_m`,       `lamb_x`,       `material`,
                `eps_0_x_e`, `eps_1_x_e`, `eps_0_m_e`, `eps_1_m_e`,
                `u_1_0_m_e`, `u_1_1_m_e`, `u_1_2_m_e`, `u_1_3_m_e`, `u_1_4_m_e`,
                `u_2_0_m_e`, `u_2_1_m_e`, `u_2_2_m_e`, `u_2_3_m_e`, `u_2_4_m_e`, `u_2_5_m_e`,
                `u_2_0_x_e`, `u_2_1_x_e`, `u_2_2_x_e`, `u_2_3_x_e`, `u_2_4_x_e`, `u_2_5_x_e`,
                `u_3_0_m_e`, `u_3_1_m_e`, `u_3_2_m_e`, `u_3_3_m_e`, `u_3_4_m_e`,
                `u_4_0_m_e`, `u_4_1_m_e`, `u_4_2_m_e`, `u_4_3_m_e`, `u_4_4_m_e`,
                `u_5_0_m_e`, `u_5_1_m_e`, `u_5_3_m_e`, `u_5_5_m_e`, `u_5_6_m_e`,
                `u_5_0_x_e`, `u_5_2_x_e`, `u_5_3_x_e`, `u_5_5_x_e`, `u_5_6_x_e`,
                `u_6_0_m_e`, `u_6_1_m_e`, `u_6_2_m_e`, `u_6_3_m_e`, `u_6_4_m_e`, `u_6_5_m_e`,
                `u_6_0_x_e`, `u_6_1_x_e`, `u_6_2_x_e`, `u_6_3_x_e`, `u_6_4_x_e`, `u_6_5_x_e`,
                `eps_0_x_o`, `eps_1_x_o`, `eps_0_m_o`,
                `u_1_0_m_o`, `u_1_1_m_o`, `u_1_2_m_o`,
                `u_2_0_m_o`, `u_2_1_m_o`, `u_2_2_m_o`,
                `u_2_0_x_o`, `u_2_1_x_o`, `u_2_2_x_o`, `u_2_3_x_o`, `u_2_4_x_o`, `u_2_5_x_o`,
                `u_3_0_m_o`, `u_3_1_m_o`, `u_3_2_m_o`,
                `u_4_0_m_o`, `u_4_1_m_o`, `u_4_2_m_o`,
                `u_5_0_m_o`, `u_5_2_m_o`,
                `u_5_0_x_o`, `u_5_2_x_o`, `u_5_3_x_o`, `u_5_5_x_o`, `u_5_6_x_o`,
                `u_6_0_m_o`, `u_6_1_m_o`, `u_6_2_m_o`,
                `u_6_0_x_o`, `u_6_1_x_o`, `u_6_2_x_o`, `u_6_3_x_o`, `u_6_4_x_o` and `u_6_5_x_o`
        """
        energy_params = [
            *[f"eps_{i}_x_{r}" for i in range(2) for r in ("e", "o")],
            *[f"eps_{i}_m_{r}" for i in "0" for r in ("e", "o")],
            *[f"eps_{i}_m_{r}" for i in "1" for r in "e"],
            *[f"u_{u}_{i}_m_e" for u in ("1", "3", "4") for i in range(5)],
            *[f"u_{u}_{i}_m_o" for u in ("1", "3", "4") for i in range(3)],
            *[f"u_{u}_{i}_{m}_e" for u in ("2", "6") for i in range(6) for m in ("m", "x")],
            *[f"u_{u}_{i}_x_o" for u in ("2", "6") for i in range(6)],
            *[f"u_{u}_{i}_m_o" for u in ("2", "6") for i in range(3)],
            *[f"u_{u}_{i}_m_e" for u in "5" for i in ("0", "1", "3", "5", "6")],
            *[f"u_{u}_{i}_x_{r}" for u in "5" for i in ("0", "2", "3", "5", "6") for r in ("e", "o")],
            *[f"u_{u}_{i}_m_o" for u in "5" for i in ("0", "2")],
        ]

        energy_params_names = [
            *[rf"$\epsilon_{i}^{{X,{r}}}$" for i in range(2) for r in ("e", "o")],
            *[rf"$\epsilon_{i}^{{M,{r}}}$" for i in "0" for r in ("e", "o")],
            *[rf"$\epsilon_{i}^{{M,{r}}}$" for i in "1" for r in "e"],
            *[rf"$u_{u}^{{{i},e}}$" for u in ("1", "3", "4") for i in range(5)],
            *[rf"$u_{u}^{{{i},o}}$" for u in ("1", "3", "4") for i in range(3)],
            *[rf"$u_{u}^{{{i},{m}e}}$" for u in ("2", "6") for i in range(6) for m in ("M", "X")],
            *[rf"$u_{u}^{{{i},Xo}}$" for u in ("2", "6") for i in range(6)],
            *[rf"$u_{u}^{{{i},Mo}}$" for u in ("2", "6") for i in range(3)],
            *[rf"$u_{u}^{{{i},Me}}$" for u in "5" for i in ("0", "1", "3", "5", "6")],
            *[rf"$u_{u}^{{{i},X{r}}}$" for u in "5" for i in ("0", "2", "3", "5", "6") for r in ("e", "o")],
            *[rf"$u_{u}^{{{i},Mo}}$" for u in "5" for i in ("0", "2")],
        ]

        self._energy_params_dict: Dict[str, FloatParameter] = dict(zip(
            energy_params,
            [FloatParameter(name=p_name) for p_name in energy_params_names]
        ))

        self._general_params_dict: Dict[str, Union[FloatParameter, StringParameter]] = dict(zip(
            ["a", "lamb_m", "lamb_x", "material"],
            [
                FloatParameter(param=1., name=r"$a$"),
                FloatParameter(name=r"$\lambda_M$"),
                FloatParameter(name=r"$\lambda_X$"),
                StringParameter(name="material")
            ]
        ))
        if input_dict is not None:
            self.from_dict(input_dict)

    @property
    def _unique_params_dict(self) -> List[dict]:
        return [self._general_params_dict, self._energy_params_dict]

    @property
    def _protected_params_dict(self) -> Optional[List[dict]]:
        return None

    @property
    def _all_params_dict(self) -> List[dict]:
        return self._unique_params_dict + (self._protected_params_dict or [])

    @property
    def _allowed_params(self):
        return [param_key for param_dict in self._all_params_dict for param_key in param_dict.keys()]

    def _check_key(self, key) -> bool:
        if key not in self._allowed_params:
            warnings.warn(f"Variable {key} is not an expected variable, it is ignored", UserWarning, stacklevel=2)
        return True

    def __setitem__(self, key, value):
        if self._check_key(key):
            for param_dict in self._unique_params_dict:
                if key in param_dict.keys():
                    param_dict[key].param = value
                    return
            if self._protected_params_dict is not None:
                for param_dict in self._protected_params_dict:
                    if key in param_dict.keys():
                        param_dict[key].param = value
                        warnings.warn(f"The variable {key} is read-only, you should not change it.", UserWarning, stacklevel=2)
                        return
            warnings.warn(f"This should not happen, {key} should be a valid key.", UserWarning, stacklevel=2)

    def __getitem__(self, item) -> Union[float, str]:
        return self.get_param(item) or 0.0

    def t_m(self) -> dict:
        """Function to get the variables as a dict."""
        out_dict = {}
        for param_dict in self._unique_params_dict:
            for key, item in param_dict.items():
                if item.param is not None:
                    out_dict[key] = item.param
        return out_dict

    def get_param(self, key):
        """Function to get the specific variable"""
        if self._check_key(key):
            for param_dict in self._all_params_dict:
                if key in param_dict.keys():
                    return param_dict[key].param
            warnings.warn(f"This should not happen, {key} should be a valid key.", UserWarning, stacklevel=2)

    def get_name(self, key) -> str:
        """Function to get the name (in LaTeX) of the specific variable"""
        if self._check_key(key):
            for param_dict in self._all_params_dict:
                if key in param_dict.keys():
                    return param_dict[key].name
            warnings.warn(f"This should not happen, {key} should be a valid key.", UserWarning, stacklevel=2)

    def from_dict(self, input_dict: Dict[str, Union[float, str]]):
        """Function to set the variables with a dict.

        Parameters:
            input_dict (dict): The dictionary containing the parameters for the TMD lattice.
                The allowed keys are:
                `a`,            `lamb_m`,       `lamb_x`,       `material`,
                `eps_0_x_e`, `eps_1_x_e`, `eps_0_m_e`, `eps_1_m_e`,
                `u_1_0_m_e`, `u_1_1_m_e`, `u_1_2_m_e`, `u_1_3_m_e`, `u_1_4_m_e`,
                `u_2_0_m_e`, `u_2_1_m_e`, `u_2_2_m_e`, `u_2_3_m_e`, `u_2_4_m_e`, `u_2_5_m_e`,
                `u_2_0_x_e`, `u_2_1_x_e`, `u_2_2_x_e`, `u_2_3_x_e`, `u_2_4_x_e`, `u_2_5_x_e`,
                `u_3_0_m_e`, `u_3_1_m_e`, `u_3_2_m_e`, `u_3_3_m_e`, `u_3_4_m_e`,
                `u_4_0_m_e`, `u_4_1_m_e`, `u_4_2_m_e`, `u_4_3_m_e`, `u_4_4_m_e`,
                `u_5_0_m_e`, `u_5_1_m_e`, `u_5_3_m_e`, `u_5_5_m_e`, `u_5_6_m_e`,
                `u_5_0_x_e`, `u_5_2_x_e`, `u_5_3_x_e`, `u_5_5_x_e`, `u_5_6_x_e`,
                `u_6_0_m_e`, `u_6_1_m_e`, `u_6_2_m_e`, `u_6_3_m_e`, `u_6_4_m_e`, `u_6_5_m_e`,
                `u_6_0_x_e`, `u_6_1_x_e`, `u_6_2_x_e`, `u_6_3_x_e`, `u_6_4_x_e`, `u_6_5_x_e`,
                `eps_0_x_o`, `eps_1_x_o`, `eps_0_m_o`,
                `u_1_0_m_o`, `u_1_1_m_o`, `u_1_2_m_o`,
                `u_2_0_m_o`, `u_2_1_m_o`, `u_2_2_m_o`,
                `u_2_0_x_o`, `u_2_1_x_o`, `u_2_2_x_o`, `u_2_3_x_o`, `u_2_4_x_o`, `u_2_5_x_o`,
                `u_3_0_m_o`, `u_3_1_m_o`, `u_3_2_m_o`,
                `u_4_0_m_o`, `u_4_1_m_o`, `u_4_2_m_o`,
                `u_5_0_m_o`, `u_5_2_m_o`,
                `u_5_0_x_o`, `u_5_2_x_o`, `u_5_3_x_o`, `u_5_5_x_o`, `u_5_6_x_o`,
                `u_6_0_m_o`, `u_6_1_m_o`, `u_6_2_m_o`,
                `u_6_0_x_o`, `u_6_1_x_o`, `u_6_2_x_o`, `u_6_3_x_o`, `u_6_4_x_o` and `u_6_5_x_o`
        """
        for param_name, value in input_dict.items():
            self[param_name] = value

__init__(input_dict=None)

Initialize the parameters for the TMD lattice.

Parameters:

Name Type Description Default
input_dict Optional[Dict[str, Union[float, str]]]

The parameters for the TMD lattice. The keys are the names of the parameters and the values are the values of the parameters. The keys are: a, lamb_m, lamb_x, material, eps_0_x_e, eps_1_x_e, eps_0_m_e, eps_1_m_e, u_1_0_m_e, u_1_1_m_e, u_1_2_m_e, u_1_3_m_e, u_1_4_m_e, u_2_0_m_e, u_2_1_m_e, u_2_2_m_e, u_2_3_m_e, u_2_4_m_e, u_2_5_m_e, u_2_0_x_e, u_2_1_x_e, u_2_2_x_e, u_2_3_x_e, u_2_4_x_e, u_2_5_x_e, u_3_0_m_e, u_3_1_m_e, u_3_2_m_e, u_3_3_m_e, u_3_4_m_e, u_4_0_m_e, u_4_1_m_e, u_4_2_m_e, u_4_3_m_e, u_4_4_m_e, u_5_0_m_e, u_5_1_m_e, u_5_3_m_e, u_5_5_m_e, u_5_6_m_e, u_5_0_x_e, u_5_2_x_e, u_5_3_x_e, u_5_5_x_e, u_5_6_x_e, u_6_0_m_e, u_6_1_m_e, u_6_2_m_e, u_6_3_m_e, u_6_4_m_e, u_6_5_m_e, u_6_0_x_e, u_6_1_x_e, u_6_2_x_e, u_6_3_x_e, u_6_4_x_e, u_6_5_x_e, eps_0_x_o, eps_1_x_o, eps_0_m_o, u_1_0_m_o, u_1_1_m_o, u_1_2_m_o, u_2_0_m_o, u_2_1_m_o, u_2_2_m_o, u_2_0_x_o, u_2_1_x_o, u_2_2_x_o, u_2_3_x_o, u_2_4_x_o, u_2_5_x_o, u_3_0_m_o, u_3_1_m_o, u_3_2_m_o, u_4_0_m_o, u_4_1_m_o, u_4_2_m_o, u_5_0_m_o, u_5_2_m_o, u_5_0_x_o, u_5_2_x_o, u_5_3_x_o, u_5_5_x_o, u_5_6_x_o, u_6_0_m_o, u_6_1_m_o, u_6_2_m_o, u_6_0_x_o, u_6_1_x_o, u_6_2_x_o, u_6_3_x_o, u_6_4_x_o and u_6_5_x_o

None
Source code in tmdybinding/parameters/symmetry_group.py
def __init__(self, input_dict: Optional[Dict[str, Union[float, str]]] = None):
    """Initialize the parameters for the TMD lattice.

    Parameters:
        input_dict (Optional[Dict[str, Union[float, str]]]): The parameters for the TMD lattice.
            The keys are the names of the parameters and the values are the values of the parameters.
            The keys are:
            `a`,            `lamb_m`,       `lamb_x`,       `material`,
            `eps_0_x_e`, `eps_1_x_e`, `eps_0_m_e`, `eps_1_m_e`,
            `u_1_0_m_e`, `u_1_1_m_e`, `u_1_2_m_e`, `u_1_3_m_e`, `u_1_4_m_e`,
            `u_2_0_m_e`, `u_2_1_m_e`, `u_2_2_m_e`, `u_2_3_m_e`, `u_2_4_m_e`, `u_2_5_m_e`,
            `u_2_0_x_e`, `u_2_1_x_e`, `u_2_2_x_e`, `u_2_3_x_e`, `u_2_4_x_e`, `u_2_5_x_e`,
            `u_3_0_m_e`, `u_3_1_m_e`, `u_3_2_m_e`, `u_3_3_m_e`, `u_3_4_m_e`,
            `u_4_0_m_e`, `u_4_1_m_e`, `u_4_2_m_e`, `u_4_3_m_e`, `u_4_4_m_e`,
            `u_5_0_m_e`, `u_5_1_m_e`, `u_5_3_m_e`, `u_5_5_m_e`, `u_5_6_m_e`,
            `u_5_0_x_e`, `u_5_2_x_e`, `u_5_3_x_e`, `u_5_5_x_e`, `u_5_6_x_e`,
            `u_6_0_m_e`, `u_6_1_m_e`, `u_6_2_m_e`, `u_6_3_m_e`, `u_6_4_m_e`, `u_6_5_m_e`,
            `u_6_0_x_e`, `u_6_1_x_e`, `u_6_2_x_e`, `u_6_3_x_e`, `u_6_4_x_e`, `u_6_5_x_e`,
            `eps_0_x_o`, `eps_1_x_o`, `eps_0_m_o`,
            `u_1_0_m_o`, `u_1_1_m_o`, `u_1_2_m_o`,
            `u_2_0_m_o`, `u_2_1_m_o`, `u_2_2_m_o`,
            `u_2_0_x_o`, `u_2_1_x_o`, `u_2_2_x_o`, `u_2_3_x_o`, `u_2_4_x_o`, `u_2_5_x_o`,
            `u_3_0_m_o`, `u_3_1_m_o`, `u_3_2_m_o`,
            `u_4_0_m_o`, `u_4_1_m_o`, `u_4_2_m_o`,
            `u_5_0_m_o`, `u_5_2_m_o`,
            `u_5_0_x_o`, `u_5_2_x_o`, `u_5_3_x_o`, `u_5_5_x_o`, `u_5_6_x_o`,
            `u_6_0_m_o`, `u_6_1_m_o`, `u_6_2_m_o`,
            `u_6_0_x_o`, `u_6_1_x_o`, `u_6_2_x_o`, `u_6_3_x_o`, `u_6_4_x_o` and `u_6_5_x_o`
    """
    energy_params = [
        *[f"eps_{i}_x_{r}" for i in range(2) for r in ("e", "o")],
        *[f"eps_{i}_m_{r}" for i in "0" for r in ("e", "o")],
        *[f"eps_{i}_m_{r}" for i in "1" for r in "e"],
        *[f"u_{u}_{i}_m_e" for u in ("1", "3", "4") for i in range(5)],
        *[f"u_{u}_{i}_m_o" for u in ("1", "3", "4") for i in range(3)],
        *[f"u_{u}_{i}_{m}_e" for u in ("2", "6") for i in range(6) for m in ("m", "x")],
        *[f"u_{u}_{i}_x_o" for u in ("2", "6") for i in range(6)],
        *[f"u_{u}_{i}_m_o" for u in ("2", "6") for i in range(3)],
        *[f"u_{u}_{i}_m_e" for u in "5" for i in ("0", "1", "3", "5", "6")],
        *[f"u_{u}_{i}_x_{r}" for u in "5" for i in ("0", "2", "3", "5", "6") for r in ("e", "o")],
        *[f"u_{u}_{i}_m_o" for u in "5" for i in ("0", "2")],
    ]

    energy_params_names = [
        *[rf"$\epsilon_{i}^{{X,{r}}}$" for i in range(2) for r in ("e", "o")],
        *[rf"$\epsilon_{i}^{{M,{r}}}$" for i in "0" for r in ("e", "o")],
        *[rf"$\epsilon_{i}^{{M,{r}}}$" for i in "1" for r in "e"],
        *[rf"$u_{u}^{{{i},e}}$" for u in ("1", "3", "4") for i in range(5)],
        *[rf"$u_{u}^{{{i},o}}$" for u in ("1", "3", "4") for i in range(3)],
        *[rf"$u_{u}^{{{i},{m}e}}$" for u in ("2", "6") for i in range(6) for m in ("M", "X")],
        *[rf"$u_{u}^{{{i},Xo}}$" for u in ("2", "6") for i in range(6)],
        *[rf"$u_{u}^{{{i},Mo}}$" for u in ("2", "6") for i in range(3)],
        *[rf"$u_{u}^{{{i},Me}}$" for u in "5" for i in ("0", "1", "3", "5", "6")],
        *[rf"$u_{u}^{{{i},X{r}}}$" for u in "5" for i in ("0", "2", "3", "5", "6") for r in ("e", "o")],
        *[rf"$u_{u}^{{{i},Mo}}$" for u in "5" for i in ("0", "2")],
    ]

    self._energy_params_dict: Dict[str, FloatParameter] = dict(zip(
        energy_params,
        [FloatParameter(name=p_name) for p_name in energy_params_names]
    ))

    self._general_params_dict: Dict[str, Union[FloatParameter, StringParameter]] = dict(zip(
        ["a", "lamb_m", "lamb_x", "material"],
        [
            FloatParameter(param=1., name=r"$a$"),
            FloatParameter(name=r"$\lambda_M$"),
            FloatParameter(name=r"$\lambda_X$"),
            StringParameter(name="material")
        ]
    ))
    if input_dict is not None:
        self.from_dict(input_dict)

from_dict(input_dict)

Function to set the variables with a dict.

Parameters:

Name Type Description Default
input_dict dict

The dictionary containing the parameters for the TMD lattice. The allowed keys are: a, lamb_m, lamb_x, material, eps_0_x_e, eps_1_x_e, eps_0_m_e, eps_1_m_e, u_1_0_m_e, u_1_1_m_e, u_1_2_m_e, u_1_3_m_e, u_1_4_m_e, u_2_0_m_e, u_2_1_m_e, u_2_2_m_e, u_2_3_m_e, u_2_4_m_e, u_2_5_m_e, u_2_0_x_e, u_2_1_x_e, u_2_2_x_e, u_2_3_x_e, u_2_4_x_e, u_2_5_x_e, u_3_0_m_e, u_3_1_m_e, u_3_2_m_e, u_3_3_m_e, u_3_4_m_e, u_4_0_m_e, u_4_1_m_e, u_4_2_m_e, u_4_3_m_e, u_4_4_m_e, u_5_0_m_e, u_5_1_m_e, u_5_3_m_e, u_5_5_m_e, u_5_6_m_e, u_5_0_x_e, u_5_2_x_e, u_5_3_x_e, u_5_5_x_e, u_5_6_x_e, u_6_0_m_e, u_6_1_m_e, u_6_2_m_e, u_6_3_m_e, u_6_4_m_e, u_6_5_m_e, u_6_0_x_e, u_6_1_x_e, u_6_2_x_e, u_6_3_x_e, u_6_4_x_e, u_6_5_x_e, eps_0_x_o, eps_1_x_o, eps_0_m_o, u_1_0_m_o, u_1_1_m_o, u_1_2_m_o, u_2_0_m_o, u_2_1_m_o, u_2_2_m_o, u_2_0_x_o, u_2_1_x_o, u_2_2_x_o, u_2_3_x_o, u_2_4_x_o, u_2_5_x_o, u_3_0_m_o, u_3_1_m_o, u_3_2_m_o, u_4_0_m_o, u_4_1_m_o, u_4_2_m_o, u_5_0_m_o, u_5_2_m_o, u_5_0_x_o, u_5_2_x_o, u_5_3_x_o, u_5_5_x_o, u_5_6_x_o, u_6_0_m_o, u_6_1_m_o, u_6_2_m_o, u_6_0_x_o, u_6_1_x_o, u_6_2_x_o, u_6_3_x_o, u_6_4_x_o and u_6_5_x_o

required
Source code in tmdybinding/parameters/symmetry_group.py
def from_dict(self, input_dict: Dict[str, Union[float, str]]):
    """Function to set the variables with a dict.

    Parameters:
        input_dict (dict): The dictionary containing the parameters for the TMD lattice.
            The allowed keys are:
            `a`,            `lamb_m`,       `lamb_x`,       `material`,
            `eps_0_x_e`, `eps_1_x_e`, `eps_0_m_e`, `eps_1_m_e`,
            `u_1_0_m_e`, `u_1_1_m_e`, `u_1_2_m_e`, `u_1_3_m_e`, `u_1_4_m_e`,
            `u_2_0_m_e`, `u_2_1_m_e`, `u_2_2_m_e`, `u_2_3_m_e`, `u_2_4_m_e`, `u_2_5_m_e`,
            `u_2_0_x_e`, `u_2_1_x_e`, `u_2_2_x_e`, `u_2_3_x_e`, `u_2_4_x_e`, `u_2_5_x_e`,
            `u_3_0_m_e`, `u_3_1_m_e`, `u_3_2_m_e`, `u_3_3_m_e`, `u_3_4_m_e`,
            `u_4_0_m_e`, `u_4_1_m_e`, `u_4_2_m_e`, `u_4_3_m_e`, `u_4_4_m_e`,
            `u_5_0_m_e`, `u_5_1_m_e`, `u_5_3_m_e`, `u_5_5_m_e`, `u_5_6_m_e`,
            `u_5_0_x_e`, `u_5_2_x_e`, `u_5_3_x_e`, `u_5_5_x_e`, `u_5_6_x_e`,
            `u_6_0_m_e`, `u_6_1_m_e`, `u_6_2_m_e`, `u_6_3_m_e`, `u_6_4_m_e`, `u_6_5_m_e`,
            `u_6_0_x_e`, `u_6_1_x_e`, `u_6_2_x_e`, `u_6_3_x_e`, `u_6_4_x_e`, `u_6_5_x_e`,
            `eps_0_x_o`, `eps_1_x_o`, `eps_0_m_o`,
            `u_1_0_m_o`, `u_1_1_m_o`, `u_1_2_m_o`,
            `u_2_0_m_o`, `u_2_1_m_o`, `u_2_2_m_o`,
            `u_2_0_x_o`, `u_2_1_x_o`, `u_2_2_x_o`, `u_2_3_x_o`, `u_2_4_x_o`, `u_2_5_x_o`,
            `u_3_0_m_o`, `u_3_1_m_o`, `u_3_2_m_o`,
            `u_4_0_m_o`, `u_4_1_m_o`, `u_4_2_m_o`,
            `u_5_0_m_o`, `u_5_2_m_o`,
            `u_5_0_x_o`, `u_5_2_x_o`, `u_5_3_x_o`, `u_5_5_x_o`, `u_5_6_x_o`,
            `u_6_0_m_o`, `u_6_1_m_o`, `u_6_2_m_o`,
            `u_6_0_x_o`, `u_6_1_x_o`, `u_6_2_x_o`, `u_6_3_x_o`, `u_6_4_x_o` and `u_6_5_x_o`
    """
    for param_name, value in input_dict.items():
        self[param_name] = value

get_name(key)

Function to get the name (in LaTeX) of the specific variable

Source code in tmdybinding/parameters/symmetry_group.py
def get_name(self, key) -> str:
    """Function to get the name (in LaTeX) of the specific variable"""
    if self._check_key(key):
        for param_dict in self._all_params_dict:
            if key in param_dict.keys():
                return param_dict[key].name
        warnings.warn(f"This should not happen, {key} should be a valid key.", UserWarning, stacklevel=2)

get_param(key)

Function to get the specific variable

Source code in tmdybinding/parameters/symmetry_group.py
def get_param(self, key):
    """Function to get the specific variable"""
    if self._check_key(key):
        for param_dict in self._all_params_dict:
            if key in param_dict.keys():
                return param_dict[key].param
        warnings.warn(f"This should not happen, {key} should be a valid key.", UserWarning, stacklevel=2)

t_m()

Function to get the variables as a dict.

Source code in tmdybinding/parameters/symmetry_group.py
def t_m(self) -> dict:
    """Function to get the variables as a dict."""
    out_dict = {}
    for param_dict in self._unique_params_dict:
        for key, item in param_dict.items():
            if item.param is not None:
                out_dict[key] = item.param
    return out_dict

SKParametersList

Bases: ParametersList

Class to store the parameters for SK e/o model

Source code in tmdybinding/parameters/slater_koster.py
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
class SKParametersList(ParametersList):
    """Class to store the parameters for SK e/o model"""

    def __init__(self, input_dict: Optional[Dict[str, Union[str, Optional[float]]]] = None):
        """Initialize the SK parameters

        Parameters:
            input_dict (dict): The dictionary containing the SK parameters. The keys are the parameter names and the
                values are the parameter values. The keys are:
                `a`, `lamb_x`, `lamb_m`, `material`, `theta`,
                `delta_p`, `delta_z`, `delta_0`, `delta_1`, `delta_2`,
                `v_0_pps`, `v_0_ppp`,
                `v_1_e_pds`, `v_1_e_pdp`, `v_1_o_pds`, `v_1_o_pdp`,
                `v_2_e_pps`, `v_2_e_ppp`, `v_2_e_pps_tb`, `v_2_e_ppp_tb`,
                `v_2_o_pps`, `v_2_o_ppp`, `v_2_o_pps_tb`, `v_2_o_ppp_tb`,
                `v_2_e_dds`, `v_2_e_ddp`, `v_2_e_ddd`,
                `v_2_o_ddp`, `v_2_o_ddd`,
                `v_3_e_pds`, `v_3_e_pdp`, `v_3_o_pds`, `v_3_o_pdp`,
                `v_4_e_pds`, `v_4_e_pdp`, `v_4_o_pds`, `v_4_o_pdp`,
                `v_5_e_pps`, `v_5_e_ppp`, `v_5_e_pps_tb`, `v_5_e_ppp_tb`,
                `v_5_o_pps`, `v_5_o_ppp`, `v_5_o_pps_tb`, `v_5_o_ppp_tb`,
                `v_5_e_dds`, `v_5_e_ddp`, `v_5_e_ddd`,
                `v_5_o_ddp`, `v_5_o_ddd`,
                `v_6_e_pps`, `v_6_e_ppp`, `v_6_e_pps_tb`, `v_6_e_ppp_tb`,
                `v_6_o_pps`, `v_6_o_ppp`, `v_6_o_pps_tb`, `v_6_o_ppp_tb`,
                `v_6_e_dds`, `v_6_e_ddp`, `v_6_e_ddd`,
                `v_6_o_ddp` and `v_6_o_ddd`"""
        super().__init__(None)
        self._recalculate_params_bool: bool = True
        self._tan_theta: Optional[float] = None

        onsite_sk_params = [
            "theta",
            *[f"delta_{r}" for r in ("p", "z", "0", "1", "2")],
            *[f"v_0_pp{r}" for r in ("s", "p")]
        ]
        onsite_sk_params_names = [
            r"$\theta$",
            *[rf"$\delta_{r}$" for r in ("p", "z", "0", "1", "2")],
            *[rf"$V^0_{{pp{r}}}$" for r in (r"\sigma", r"\pi")],
        ]

        self._onsite_sk_params_dict: dict = dict(zip(
            onsite_sk_params,
            [FloatParameter(name=p_name) for p_name in onsite_sk_params_names]
        ))

        sk_params = [
            *[f"v_{n}_{r}_pd{i}" for n in ("1", "3", "4") for r in ("e", "o") for i in ("s", "p")],
            *[f"v_{n}_{r}_pp{i}{t}" for n in ("2", "5", "6")
              for r in ("e", "o") for i in ("s", "p") for t in ("", "_tb")],
            *[f"v_{n}_e_dds" for n in ("2", "5", "6")],
            *[f"v_{n}_{r}_dd{i}" for n in ("2", "5", "6") for r in ("e", "o") for i in ("p", "d")]
        ]

        sk_params_names = [
            *[rf"$V^{{{n}_{r}}}_{{pd{i}}}$" for n in ("1", "3", "4") for r in ("e", "o") for i in (r"\sigma", r"\pi")],
            *[rf"$V^{{{n}_{r}}}_{{pp{i}{t}}}$" for n in ("2", "5", "6")
              for r in ("e", "o") for i in (r"\sigma", r"\pi") for t in ("", ",tb")],
            *[rf"$V^{{{n}_e}}_{{dd\sigmas}}$" for n in ("2", "5", "6")],
            *[rf"$V^{{{n}_{r}}}_{{dd{i}}}$" for n in ("2", "5", "6") for r in ("e", "o") for i in (r"\pi", r"\delta")]
        ]
        self._sk_params_dict: dict = dict(zip(
            sk_params,
            [FloatParameter(name=p_name) for p_name in sk_params_names]
        ))

        if input_dict is not None:
            self.from_dict(input_dict)

    @property
    def _unique_params_dict(self) -> List[dict]:
        return [self._general_params_dict, self._onsite_sk_params_dict, self._sk_params_dict]

    @property
    def _protected_params_dict(self) -> Optional[List[dict]]:
        return [self._energy_params_dict]

    def __setitem__(self, key, value):
        """Set the value of a parameter and recalculate the parameters."""
        super().__setitem__(key, value)
        self._recalculate_params()

    def from_dict(self, input_dict: Dict[str, Union[float, str]]):
        """Set the parameters from a dictionary and recalculate the parameters.

        Parameters:
            input_dict (dict): The dictionary containing the SK parameters. The keys are the parameter names and the
                values are the parameter values. The keys are:
                `a`, `lamb_x`, `lamb_m`, `material`, `theta`,
                `delta_p`, `delta_z`, `delta_0`, `delta_1`, `delta_2`,
                `v_0_pps`, `v_0_ppp`,
                `v_1_e_pds`, `v_1_e_pdp`, `v_1_o_pds`, `v_1_o_pdp`,
                `v_2_e_pps`, `v_2_e_ppp`, `v_2_e_pps_tb`, `v_2_e_ppp_tb`,
                `v_2_o_pps`, `v_2_o_ppp`, `v_2_o_pps_tb`, `v_2_o_ppp_tb`,
                `v_2_e_dds`, `v_2_e_ddp`, `v_2_e_ddd`,
                `v_2_o_ddp`, `v_2_o_ddd`,
                `v_3_e_pds`, `v_3_e_pdp`, `v_3_o_pds`, `v_3_o_pdp`,
                `v_4_e_pds`, `v_4_e_pdp`, `v_4_o_pds`, `v_4_o_pdp`,
                `v_5_e_pps`, `v_5_e_ppp`, `v_5_e_pps_tb`, `v_5_e_ppp_tb`,
                `v_5_o_pps`, `v_5_o_ppp`, `v_5_o_pps_tb`, `v_5_o_ppp_tb`,
                `v_5_e_dds`, `v_5_e_ddp`, `v_5_e_ddd`,
                `v_5_o_ddp`, `v_5_o_ddd`,
                `v_6_e_pps`, `v_6_e_ppp`, `v_6_e_pps_tb`, `v_6_e_ppp_tb`,
                `v_6_o_pps`, `v_6_o_ppp`, `v_6_o_pps_tb`, `v_6_o_ppp_tb`,
                `v_6_e_dds`, `v_6_e_ddp`, `v_6_e_ddd`,
                `v_6_o_ddp` and `v_6_o_ddd`"""
        self._recalculate_params_bool = False
        super().from_dict(input_dict)
        self._recalculate_params_bool = True
        self._recalculate_params()

    def _recalculate_params(self):
        if self._recalculate_params_bool:
            self._tan_theta = np.tan(self["theta"]) if self["theta"] is not None else np.sqrt(3 / 4)
            # Onsite elements
            # X
            self._energy_params_dict["eps_0_x_e"].param = self._comb_nonefloat([self["delta_p"], self["v_0_ppp"]])
            self._energy_params_dict["eps_1_x_e"].param = self._subtract_param(self["delta_z"], self["v_0_pps"])
            self._energy_params_dict["eps_0_x_o"].param = self._subtract_param(self["delta_p"], self["v_0_ppp"])
            self._energy_params_dict["eps_1_x_o"].param = self._comb_nonefloat([self["delta_z"], self["v_0_pps"]])
            # M
            self._energy_params_dict["eps_0_m_e"].param = self["delta_0"]
            self._energy_params_dict["eps_1_m_e"].param = self["delta_2"]
            self._energy_params_dict["eps_0_m_o"].param = self["delta_1"]
            # h1
            [
                self._energy_params_dict["u_1_0_m_e"].param,
                self._energy_params_dict["u_1_1_m_e"].param,
                self._energy_params_dict["u_1_2_m_e"].param,
                self._energy_params_dict["u_1_3_m_e"].param,
                self._energy_params_dict["u_1_4_m_e"].param
            ] = self._h_mx_e(r=-1, vpds=self["v_1_e_pds"], vpdp=self["v_1_e_pdp"])
            [
                self._energy_params_dict["u_1_0_m_o"].param,
                self._energy_params_dict["u_1_1_m_o"].param,
                self._energy_params_dict["u_1_2_m_o"].param
            ] = self._h_mx_o(r=-1, vpds=self["v_1_o_pds"], vpdp=self["v_1_o_pdp"])
            # h2
            [
                self._energy_params_dict["u_2_0_m_e"].param,
                self._energy_params_dict["u_2_1_m_e"].param,
                self._energy_params_dict["u_2_2_m_e"].param,
                self._energy_params_dict["u_2_3_m_e"].param,
                self._energy_params_dict["u_2_4_m_e"].param,
                self._energy_params_dict["u_2_5_m_e"].param
            ] = self._h_mm_x_e(vdds=self["v_2_e_dds"], vddp=self["v_2_e_ddp"], vddd=self["v_2_e_ddd"])
            [
                self._energy_params_dict["u_2_0_m_o"].param,
                self._energy_params_dict["u_2_1_m_o"].param,
                self._energy_params_dict["u_2_2_m_o"].param
            ] = self._h_mm_x_o(vddp=self["v_2_o_ddp"], vddd=self["v_2_o_ddd"])
            [
                self._energy_params_dict["u_2_0_x_e"].param,
                self._energy_params_dict["u_2_1_x_e"].param,
                self._energy_params_dict["u_2_2_x_e"].param,
                self._energy_params_dict["u_2_3_x_e"].param,
                self._energy_params_dict["u_2_4_x_e"].param,
                self._energy_params_dict["u_2_5_x_e"].param
            ] = self._h_xx_x_e(r=np.sqrt(3), vpps=self["v_2_e_pps"], vppp=self["v_2_e_ppp"],
                               vppstb=self["v_2_e_pps_tb"], vppptb=self["v_2_e_ppp_tb"])
            [
                self._energy_params_dict["u_2_0_x_o"].param,
                self._energy_params_dict["u_2_1_x_o"].param,
                self._energy_params_dict["u_2_2_x_o"].param,
                self._energy_params_dict["u_2_3_x_o"].param,
                self._energy_params_dict["u_2_4_x_o"].param,
                self._energy_params_dict["u_2_5_x_o"].param
            ] = self._h_xx_x_o(r=np.sqrt(3), vpps=self["v_2_o_pps"], vppp=self["v_2_o_ppp"],
                               vppstb=self["v_2_o_pps_tb"], vppptb=self["v_2_o_ppp_tb"])
            # h3
            [
                self._energy_params_dict["u_3_0_m_e"].param,
                self._energy_params_dict["u_3_1_m_e"].param,
                self._energy_params_dict["u_3_2_m_e"].param,
                self._energy_params_dict["u_3_3_m_e"].param,
                self._energy_params_dict["u_3_4_m_e"].param
            ] = self._h_mx_e(r=2, vpds=self["v_3_e_pds"], vpdp=self["v_3_e_pdp"])
            [
                self._energy_params_dict["u_3_0_m_o"].param,
                self._energy_params_dict["u_3_1_m_o"].param,
                self._energy_params_dict["u_3_2_m_o"].param
            ] = self._h_mx_o(r=2, vpds=self["v_3_o_pds"], vpdp=self["v_3_o_pdp"])
            # h4
            [
                self._energy_params_dict["u_4_0_m_e"].param,
                self._energy_params_dict["u_4_1_m_e"].param,
                self._energy_params_dict["u_4_2_m_e"].param,
                self._energy_params_dict["u_4_3_m_e"].param,
                self._energy_params_dict["u_4_4_m_e"].param
            ] = self._h_mx_e(r=-np.sqrt(7), vpds=self["v_4_e_pds"], vpdp=self["v_4_e_pdp"])
            [
                self._energy_params_dict["u_4_0_m_o"].param,
                self._energy_params_dict["u_4_1_m_o"].param,
                self._energy_params_dict["u_4_2_m_o"].param
            ] = self._h_mx_o(r=-np.sqrt(7), vpds=self["v_4_o_pds"], vpdp=self["v_4_o_pdp"])
            # h5
            [
                self._energy_params_dict["u_5_0_m_e"].param,
                self._energy_params_dict["u_5_1_m_e"].param,
                self._energy_params_dict["u_5_3_m_e"].param,
                self._energy_params_dict["u_5_5_m_e"].param,
                self._energy_params_dict["u_5_6_m_e"].param
            ] = self._h_mm_y_e(vdds=self["v_5_e_dds"], vddp=self["v_5_e_ddp"], vddd=self["v_5_e_ddd"])
            [
                self._energy_params_dict["u_5_0_m_o"].param,
                self._energy_params_dict["u_5_2_m_o"].param
            ] = self._h_mm_y_o(vddp=self["v_5_o_ddp"], vddd=self["v_5_o_ddd"])
            [
                self._energy_params_dict["u_5_0_x_e"].param,
                self._energy_params_dict["u_5_2_x_e"].param,
                self._energy_params_dict["u_5_3_x_e"].param,
                self._energy_params_dict["u_5_5_x_e"].param,
                self._energy_params_dict["u_5_6_x_e"].param
            ] = self._h_xx_y_e(r=3, vpps=self["v_5_e_pps"], vppp=self["v_5_e_ppp"],
                               vppstb=self["v_5_e_pps_tb"], vppptb=self["v_5_e_ppp_tb"])
            [
                self._energy_params_dict["u_5_0_x_o"].param,
                self._energy_params_dict["u_5_2_x_o"].param,
                self._energy_params_dict["u_5_3_x_o"].param,
                self._energy_params_dict["u_5_5_x_o"].param,
                self._energy_params_dict["u_5_6_x_o"].param
            ] = self._h_xx_y_o(r=3, vpps=self["v_5_o_pps"], vppp=self["v_5_o_ppp"],
                               vppstb=self["v_5_e_pps_tb"], vppptb=self["v_5_o_ppp_tb"])
            # h6
            [
                self._energy_params_dict["u_6_0_m_e"].param,
                self._energy_params_dict["u_6_1_m_e"].param,
                self._energy_params_dict["u_6_2_m_e"].param,
                self._energy_params_dict["u_6_3_m_e"].param,
                self._energy_params_dict["u_6_4_m_e"].param,
                self._energy_params_dict["u_6_5_m_e"].param
            ] = self._h_mm_x_e(vdds=self["v_6_e_dds"], vddp=self["v_6_e_ddp"], vddd=self["v_6_e_ddd"])
            [
                self._energy_params_dict["u_6_0_m_o"].param,
                self._energy_params_dict["u_6_1_m_o"].param,
                self._energy_params_dict["u_6_2_m_o"].param
            ] = self._h_mm_x_o(vddp=self["v_6_o_ddp"], vddd=self["v_6_o_ddd"])
            [
                self._energy_params_dict["u_6_0_x_e"].param,
                self._energy_params_dict["u_6_1_x_e"].param,
                self._energy_params_dict["u_6_2_x_e"].param,
                self._energy_params_dict["u_6_3_x_e"].param,
                self._energy_params_dict["u_6_4_x_e"].param,
                self._energy_params_dict["u_6_5_x_e"].param
            ] = self._h_xx_x_e(r=np.sqrt(3), vpps=self["v_6_e_pps"], vppp=self["v_6_e_ppp"],
                               vppstb=self["v_6_e_pps_tb"], vppptb=self["v_6_e_ppp_tb"])
            [
                self._energy_params_dict["u_6_0_x_o"].param,
                self._energy_params_dict["u_6_1_x_o"].param,
                self._energy_params_dict["u_6_2_x_o"].param,
                self._energy_params_dict["u_6_3_x_o"].param,
                self._energy_params_dict["u_6_4_x_o"].param,
                self._energy_params_dict["u_6_5_x_o"].param
            ] = self._h_xx_x_o(r=np.sqrt(3), vpps=self["v_6_o_pps"], vppp=self["v_6_o_ppp"],
                               vppstb=self["v_6_o_pps_tb"], vppptb=self["v_6_o_ppp_tb"])

    def _subtract_param(self, p1: Optional[float], p2: Optional[float]):
        return self._comb_nonefloat([p1, -p2 if p2 is not None else None])

    @staticmethod
    def _h_mm_x_e(vdds: Optional[float], vddp: Optional[float], vddd: Optional[float]) -> List[Optional[float]]:
        vddsd_bool = (vdds is not None) and (vddd is not None)
        vddp_bool = vddp is not None
        u_0: Optional[float] = 1 / 4 * (vdds + 3 * vddd) if vddsd_bool else None
        u_1: Optional[float] = np.sqrt(3) / 4 * (-vdds + vddd) if vddsd_bool else None
        u_2: Optional[float] = 0 if (vddsd_bool or vddp_bool) else None
        u_3: Optional[float] = 1 / 4 * (3 * vdds + vddd) if vddsd_bool else None
        u_4: Optional[float] = 0 if (vddsd_bool or vddp_bool) else None
        u_5: Optional[float] = vddp if vddp_bool else None
        return [u_0, u_1, u_2, u_3, u_4, u_5]

    @staticmethod
    def _h_mm_y_e(vdds: Optional[float], vddp: Optional[float], vddd: Optional[float]) -> List[Optional[float]]:
        vddsd_bool = (vdds is not None) and (vddd is not None)
        vddp_bool = vddp is not None
        u_0: Optional[float] = 1 / 4 * (vdds + 3 * vddd) if vddsd_bool else None
        u_1: Optional[float] = np.sqrt(3) / 4 * (-vdds + vddd) if vddsd_bool else None
        u_3: Optional[float] = 1 / 4 * (3 * vdds + vddd) if vddsd_bool else None
        u_5: Optional[float] = vddp if vddp_bool else None
        u_6: Optional[float] = np.sqrt(3) / 4 * (-vdds + vddd) if vddsd_bool else None
        return [u_0, u_1, u_3, u_5, u_6]

    @staticmethod
    def _h_mm_x_o(vddp: Optional[float], vddd: Optional[float]) -> List[Optional[float]]:
        vddd_bool = vddd is not None
        vddp_bool = vddp is not None
        u_0: Optional[float] = vddp if vddp_bool else None
        u_1: Optional[float] = 0 if (vddd_bool or vddp_bool) else None
        u_2: Optional[float] = vddd if vddd_bool else None
        return [u_0, u_1, u_2]

    @staticmethod
    def _h_mm_y_o(vddp: Optional[float], vddd: Optional[float]) -> List[Optional[float]]:
        vddd_bool = vddd is not None
        vddp_bool = vddp is not None
        u_0: Optional[float] = vddp if vddp_bool else None
        u_2: Optional[float] = vddd if vddd_bool else None
        return [u_0, u_2]

    @staticmethod
    def _comb_nonefloat(u_list: List[Optional[float]]) -> Optional[float]:
        bl = [ul is not None for ul in u_list]
        return None if np.all(np.logical_not(bl)) else np.sum([u_list[li] for li in np.arange(len(u_list))[bl]])

    def _h_xx_x_e(self, r: float, vpps: Optional[float], vppp: Optional[float],
                  vppstb: Optional[float] = None, vppptb: Optional[float] = None) -> List[Optional[float]]:
        vpps_bool = vpps is not None
        vppp_bool = vppp is not None
        vptb_bool = vppstb is not None
        vstb_bool = vppptb is not None
        u_0_0: Optional[float] = vpps if vpps_bool else None
        u_0_1: Optional[float] = vppptb if vptb_bool else None
        u_0_2: Optional[float] = -r ** 2 * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_0: Optional[float] = self._comb_nonefloat([u_0_0, u_0_1, u_0_2])
        u_1: Optional[float] = 0 if (vpps_bool or vppp_bool or vstb_bool or vptb_bool) else None
        u_2: Optional[float] = -2 * self._tan_theta * r * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_3_0: Optional[float] = vppp if vppp_bool else None
        u_3_1: Optional[float] = vppptb if vptb_bool else None
        u_3: Optional[float] = self._comb_nonefloat([u_3_0, u_3_1])
        u_4: Optional[float] = 0 if (vpps_bool or vppp_bool or vstb_bool or vptb_bool) else None
        u_5_0: Optional[float] = vppp if vppp_bool else None
        u_5_1: Optional[float] = -vppstb if vstb_bool else None
        u_5_2: Optional[float] = -r ** 2 * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_5: Optional[float] = self._comb_nonefloat([u_5_0, u_5_1, u_5_2])
        return [u_0, u_1, u_2, u_3, u_4, u_5]

    def _h_xx_y_e(self, r: float, vpps: Optional[float], vppp: Optional[float],
                  vppstb: Optional[float] = None, vppptb: Optional[float] = None) -> List[Optional[float]]:
        vpps_bool = vpps is not None
        vppp_bool = vppp is not None
        vptb_bool = vppstb is not None
        vstb_bool = vppptb is not None
        u_0_0: Optional[float] = vpps if vpps_bool else None
        u_0_1: Optional[float] = vppptb if vptb_bool else None
        u_0_2: Optional[float] = -r ** 2 * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_0: Optional[float] = self._comb_nonefloat([u_0_0, u_0_1, u_0_2])
        u_2: Optional[float] = -2 * self._tan_theta * r * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_3_0: Optional[float] = vppp if vppp_bool else None
        u_3_1: Optional[float] = vppptb if vptb_bool else None
        u_3: Optional[float] = self._comb_nonefloat([u_3_0, u_3_1])
        u_5_0: Optional[float] = vppp if vppp_bool else None
        u_5_1: Optional[float] = -vppstb if vstb_bool else None
        u_5_2: Optional[float] = -r ** 2 * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_5: Optional[float] = self._comb_nonefloat([u_5_0, u_5_1, u_5_2])
        u_6: Optional[float] = 2 * self._tan_theta * r * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        return [u_0, u_2, u_3, u_5, u_6]

    def _h_xx_x_o(self, r: float, vpps: Optional[float], vppp: Optional[float],
                  vppstb: Optional[float] = None, vppptb: Optional[float] = None) -> List[Optional[float]]:
        vpps_bool = vpps is not None
        vppp_bool = vppp is not None
        vptb_bool = vppstb is not None
        vstb_bool = vppptb is not None
        u_0_0: Optional[float] = vpps if vpps_bool else None
        u_0_1: Optional[float] = -vppptb if vptb_bool else None
        u_0_2: Optional[float] = r ** 2 * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_0: Optional[float] = self._comb_nonefloat([u_0_0, u_0_1, u_0_2])
        u_1: Optional[float] = 0 if (vpps_bool or vppp_bool or vstb_bool or vptb_bool) else None
        u_2: Optional[float] = -2 * self._tan_theta * r * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_3_0: Optional[float] = vppp if vppp_bool else None
        u_3_1: Optional[float] = -vppptb if vptb_bool else None
        u_3: Optional[float] = self._comb_nonefloat([u_3_0, u_3_1])
        u_4: Optional[float] = 0 if (vpps_bool or vppp_bool or vstb_bool or vptb_bool) else None
        u_5_0: Optional[float] = vppp if vppp_bool else None
        u_5_1: Optional[float] = vppstb if vstb_bool else None
        u_5_2: Optional[float] = r ** 2 * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_5: Optional[float] = self._comb_nonefloat([u_5_0, u_5_1, u_5_2])
        return [u_0, u_1, u_2, u_3, u_4, u_5]

    def _h_xx_y_o(self, r: float, vpps: Optional[float], vppp: Optional[float],
                  vppstb: Optional[float] = None, vppptb: Optional[float] = None) -> List[Optional[float]]:
        vpps_bool = vpps is not None
        vppp_bool = vppp is not None
        vptb_bool = vppstb is not None
        vstb_bool = vppptb is not None
        u_0_0: Optional[float] = vpps if vpps_bool else None
        u_0_1: Optional[float] = -vppptb if vptb_bool else None
        u_0_2: Optional[float] = r ** 2 * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_0: Optional[float] = self._comb_nonefloat([u_0_0, u_0_1, u_0_2])
        u_2: Optional[float] = 2 * self._tan_theta * r * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_3_0: Optional[float] = vppp if vppp_bool else None
        u_3_1: Optional[float] = -vppptb if vptb_bool else None
        u_3: Optional[float] = self._comb_nonefloat([u_3_0, u_3_1])
        u_5_0: Optional[float] = vppp if vppp_bool else None
        u_5_1: Optional[float] = vppstb if vstb_bool else None
        u_5_2: Optional[float] = r ** 2 * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        u_5: Optional[float] = self._comb_nonefloat([u_5_0, u_5_1, u_5_2])
        u_6: Optional[float] = -2 * self._tan_theta * r * (vppptb - vppstb) / (r ** 2 + 4 * self._tan_theta ** 2)\
            if vstb_bool and vptb_bool else None
        return [u_0, u_2, u_3, u_5, u_6]

    def _h_mx_e(self, r: float, vpds: Optional[float], vpdp: Optional[float]) -> List[Optional[float]]:
        if (vpds is not None) and (vpdp is not None):
            u_0 = np.sqrt(2) * r * vpdp / (np.sqrt(r ** 2 + self._tan_theta ** 2))
            u_1 = -r * (
                    2 * np.sqrt(3) * self._tan_theta ** 2 * vpdp + (r ** 2 - 2 * self._tan_theta ** 2) * vpds
            ) / (np.sqrt(2) * ((r ** 2 + self._tan_theta ** 2) ** (3 / 2)))
            u_2 = -r * (
                    2 * self._tan_theta ** 2 * vpdp + np.sqrt(3) * r ** 2 * vpds
            ) / (np.sqrt(2) * ((r ** 2 + self._tan_theta ** 2) ** (3 / 2)))
            u_3 = self._tan_theta * (
                    r ** 2 * 2 * np.sqrt(3) * vpdp + (2 * self._tan_theta ** 2 - r ** 2) * vpds
            ) / (np.sqrt(2) * ((r ** 2 + self._tan_theta ** 2) ** (3 / 2)))
            u_4 = r ** 2 * self._tan_theta * (
                    2 * vpdp - np.sqrt(3) * vpds
            ) / (np.sqrt(2) * ((r ** 2 + self._tan_theta ** 2) ** (3 / 2)))
            return [u_0, u_1, u_2, u_3, u_4]
        else:
            return [None, None, None, None, None]

    def _h_mx_o(self, r: float, vpds: Optional[float], vpdp: Optional[float]) -> List[Optional[float]]:
        if (vpds is not None) and (vpdp is not None):
            u_0 = np.sqrt(2) * self._tan_theta * vpdp / np.sqrt(r ** 2 + self._tan_theta ** 2)
            u_1 = np.sqrt(2) * self._tan_theta * (
                    (self._tan_theta ** 2 - r ** 2) * vpdp + r ** 2 * np.sqrt(3) * vpds
            ) / ((r ** 2 + self._tan_theta ** 2) ** (3 / 2))
            u_2 = np.sqrt(2) * r * (
                    (r ** 2 - self._tan_theta ** 2) * vpdp + self._tan_theta ** 2 * np.sqrt(3) * vpds
            ) / ((r ** 2 + self._tan_theta ** 2) ** (3 / 2))
            return [u_0, u_1, u_2]
        else:
            return [None, None, None]

__init__(input_dict=None)

Initialize the SK parameters

Parameters:

Name Type Description Default
input_dict dict

The dictionary containing the SK parameters. The keys are the parameter names and the values are the parameter values. The keys are: a, lamb_x, lamb_m, material, theta, delta_p, delta_z, delta_0, delta_1, delta_2, v_0_pps, v_0_ppp, v_1_e_pds, v_1_e_pdp, v_1_o_pds, v_1_o_pdp, v_2_e_pps, v_2_e_ppp, v_2_e_pps_tb, v_2_e_ppp_tb, v_2_o_pps, v_2_o_ppp, v_2_o_pps_tb, v_2_o_ppp_tb, v_2_e_dds, v_2_e_ddp, v_2_e_ddd, v_2_o_ddp, v_2_o_ddd, v_3_e_pds, v_3_e_pdp, v_3_o_pds, v_3_o_pdp, v_4_e_pds, v_4_e_pdp, v_4_o_pds, v_4_o_pdp, v_5_e_pps, v_5_e_ppp, v_5_e_pps_tb, v_5_e_ppp_tb, v_5_o_pps, v_5_o_ppp, v_5_o_pps_tb, v_5_o_ppp_tb, v_5_e_dds, v_5_e_ddp, v_5_e_ddd, v_5_o_ddp, v_5_o_ddd, v_6_e_pps, v_6_e_ppp, v_6_e_pps_tb, v_6_e_ppp_tb, v_6_o_pps, v_6_o_ppp, v_6_o_pps_tb, v_6_o_ppp_tb, v_6_e_dds, v_6_e_ddp, v_6_e_ddd, v_6_o_ddp and v_6_o_ddd

None
Source code in tmdybinding/parameters/slater_koster.py
def __init__(self, input_dict: Optional[Dict[str, Union[str, Optional[float]]]] = None):
    """Initialize the SK parameters

    Parameters:
        input_dict (dict): The dictionary containing the SK parameters. The keys are the parameter names and the
            values are the parameter values. The keys are:
            `a`, `lamb_x`, `lamb_m`, `material`, `theta`,
            `delta_p`, `delta_z`, `delta_0`, `delta_1`, `delta_2`,
            `v_0_pps`, `v_0_ppp`,
            `v_1_e_pds`, `v_1_e_pdp`, `v_1_o_pds`, `v_1_o_pdp`,
            `v_2_e_pps`, `v_2_e_ppp`, `v_2_e_pps_tb`, `v_2_e_ppp_tb`,
            `v_2_o_pps`, `v_2_o_ppp`, `v_2_o_pps_tb`, `v_2_o_ppp_tb`,
            `v_2_e_dds`, `v_2_e_ddp`, `v_2_e_ddd`,
            `v_2_o_ddp`, `v_2_o_ddd`,
            `v_3_e_pds`, `v_3_e_pdp`, `v_3_o_pds`, `v_3_o_pdp`,
            `v_4_e_pds`, `v_4_e_pdp`, `v_4_o_pds`, `v_4_o_pdp`,
            `v_5_e_pps`, `v_5_e_ppp`, `v_5_e_pps_tb`, `v_5_e_ppp_tb`,
            `v_5_o_pps`, `v_5_o_ppp`, `v_5_o_pps_tb`, `v_5_o_ppp_tb`,
            `v_5_e_dds`, `v_5_e_ddp`, `v_5_e_ddd`,
            `v_5_o_ddp`, `v_5_o_ddd`,
            `v_6_e_pps`, `v_6_e_ppp`, `v_6_e_pps_tb`, `v_6_e_ppp_tb`,
            `v_6_o_pps`, `v_6_o_ppp`, `v_6_o_pps_tb`, `v_6_o_ppp_tb`,
            `v_6_e_dds`, `v_6_e_ddp`, `v_6_e_ddd`,
            `v_6_o_ddp` and `v_6_o_ddd`"""
    super().__init__(None)
    self._recalculate_params_bool: bool = True
    self._tan_theta: Optional[float] = None

    onsite_sk_params = [
        "theta",
        *[f"delta_{r}" for r in ("p", "z", "0", "1", "2")],
        *[f"v_0_pp{r}" for r in ("s", "p")]
    ]
    onsite_sk_params_names = [
        r"$\theta$",
        *[rf"$\delta_{r}$" for r in ("p", "z", "0", "1", "2")],
        *[rf"$V^0_{{pp{r}}}$" for r in (r"\sigma", r"\pi")],
    ]

    self._onsite_sk_params_dict: dict = dict(zip(
        onsite_sk_params,
        [FloatParameter(name=p_name) for p_name in onsite_sk_params_names]
    ))

    sk_params = [
        *[f"v_{n}_{r}_pd{i}" for n in ("1", "3", "4") for r in ("e", "o") for i in ("s", "p")],
        *[f"v_{n}_{r}_pp{i}{t}" for n in ("2", "5", "6")
          for r in ("e", "o") for i in ("s", "p") for t in ("", "_tb")],
        *[f"v_{n}_e_dds" for n in ("2", "5", "6")],
        *[f"v_{n}_{r}_dd{i}" for n in ("2", "5", "6") for r in ("e", "o") for i in ("p", "d")]
    ]

    sk_params_names = [
        *[rf"$V^{{{n}_{r}}}_{{pd{i}}}$" for n in ("1", "3", "4") for r in ("e", "o") for i in (r"\sigma", r"\pi")],
        *[rf"$V^{{{n}_{r}}}_{{pp{i}{t}}}$" for n in ("2", "5", "6")
          for r in ("e", "o") for i in (r"\sigma", r"\pi") for t in ("", ",tb")],
        *[rf"$V^{{{n}_e}}_{{dd\sigmas}}$" for n in ("2", "5", "6")],
        *[rf"$V^{{{n}_{r}}}_{{dd{i}}}$" for n in ("2", "5", "6") for r in ("e", "o") for i in (r"\pi", r"\delta")]
    ]
    self._sk_params_dict: dict = dict(zip(
        sk_params,
        [FloatParameter(name=p_name) for p_name in sk_params_names]
    ))

    if input_dict is not None:
        self.from_dict(input_dict)

__setitem__(key, value)

Set the value of a parameter and recalculate the parameters.

Source code in tmdybinding/parameters/slater_koster.py
def __setitem__(self, key, value):
    """Set the value of a parameter and recalculate the parameters."""
    super().__setitem__(key, value)
    self._recalculate_params()

from_dict(input_dict)

Set the parameters from a dictionary and recalculate the parameters.

Parameters:

Name Type Description Default
input_dict dict

The dictionary containing the SK parameters. The keys are the parameter names and the values are the parameter values. The keys are: a, lamb_x, lamb_m, material, theta, delta_p, delta_z, delta_0, delta_1, delta_2, v_0_pps, v_0_ppp, v_1_e_pds, v_1_e_pdp, v_1_o_pds, v_1_o_pdp, v_2_e_pps, v_2_e_ppp, v_2_e_pps_tb, v_2_e_ppp_tb, v_2_o_pps, v_2_o_ppp, v_2_o_pps_tb, v_2_o_ppp_tb, v_2_e_dds, v_2_e_ddp, v_2_e_ddd, v_2_o_ddp, v_2_o_ddd, v_3_e_pds, v_3_e_pdp, v_3_o_pds, v_3_o_pdp, v_4_e_pds, v_4_e_pdp, v_4_o_pds, v_4_o_pdp, v_5_e_pps, v_5_e_ppp, v_5_e_pps_tb, v_5_e_ppp_tb, v_5_o_pps, v_5_o_ppp, v_5_o_pps_tb, v_5_o_ppp_tb, v_5_e_dds, v_5_e_ddp, v_5_e_ddd, v_5_o_ddp, v_5_o_ddd, v_6_e_pps, v_6_e_ppp, v_6_e_pps_tb, v_6_e_ppp_tb, v_6_o_pps, v_6_o_ppp, v_6_o_pps_tb, v_6_o_ppp_tb, v_6_e_dds, v_6_e_ddp, v_6_e_ddd, v_6_o_ddp and v_6_o_ddd

required
Source code in tmdybinding/parameters/slater_koster.py
def from_dict(self, input_dict: Dict[str, Union[float, str]]):
    """Set the parameters from a dictionary and recalculate the parameters.

    Parameters:
        input_dict (dict): The dictionary containing the SK parameters. The keys are the parameter names and the
            values are the parameter values. The keys are:
            `a`, `lamb_x`, `lamb_m`, `material`, `theta`,
            `delta_p`, `delta_z`, `delta_0`, `delta_1`, `delta_2`,
            `v_0_pps`, `v_0_ppp`,
            `v_1_e_pds`, `v_1_e_pdp`, `v_1_o_pds`, `v_1_o_pdp`,
            `v_2_e_pps`, `v_2_e_ppp`, `v_2_e_pps_tb`, `v_2_e_ppp_tb`,
            `v_2_o_pps`, `v_2_o_ppp`, `v_2_o_pps_tb`, `v_2_o_ppp_tb`,
            `v_2_e_dds`, `v_2_e_ddp`, `v_2_e_ddd`,
            `v_2_o_ddp`, `v_2_o_ddd`,
            `v_3_e_pds`, `v_3_e_pdp`, `v_3_o_pds`, `v_3_o_pdp`,
            `v_4_e_pds`, `v_4_e_pdp`, `v_4_o_pds`, `v_4_o_pdp`,
            `v_5_e_pps`, `v_5_e_ppp`, `v_5_e_pps_tb`, `v_5_e_ppp_tb`,
            `v_5_o_pps`, `v_5_o_ppp`, `v_5_o_pps_tb`, `v_5_o_ppp_tb`,
            `v_5_e_dds`, `v_5_e_ddp`, `v_5_e_ddd`,
            `v_5_o_ddp`, `v_5_o_ddd`,
            `v_6_e_pps`, `v_6_e_ppp`, `v_6_e_pps_tb`, `v_6_e_ppp_tb`,
            `v_6_o_pps`, `v_6_o_ppp`, `v_6_o_pps_tb`, `v_6_o_ppp_tb`,
            `v_6_e_dds`, `v_6_e_ddp`, `v_6_e_ddd`,
            `v_6_o_ddp` and `v_6_o_ddd`"""
    self._recalculate_params_bool = False
    super().from_dict(input_dict)
    self._recalculate_params_bool = True
    self._recalculate_params()

SKSimpleParametersList

Bases: SKParametersList

Class to store the simplified SK paramters (no even/odd).

Source code in tmdybinding/parameters/slater_koster.py
class SKSimpleParametersList(SKParametersList):
    """Class to store the simplified SK paramters (no even/odd)."""
    def __init__(self, input_dict: Optional[Dict[str, Union[str, Optional[float]]]] = None):
        """Initializes the SKSimpleParametersList object.

        Parameters:
            input_dict (dict): Dictionary with the SK paramters. The keus are the parameter names and the values are the
                parameter values. The parameter names are:
                `a`, `material`, `lamb_x`, `lamb_m`, `theta`,
                `delta_p`, `delta_z`, `delta_0`, `delta_1`, `delta_2`,
                `v_0_pps`, `v_0_ppp`,
                `v_1_pds`, `v_1_pdp`,
                `v_2_dds`, `v_2_ddp`, `v_2_ddd`, `v_2_pps`, `v_2_ppp`, `v_2_pps_tb`, `v_2_ppp_tb`,
                `v_3_pds`, `v_3_pdp`,
                `v_4_pds`, `v_4_pdp`,
                `v_5_dds`, `v_5_ddp`, `v_5_ddd`, `v_5_pps`, `v_5_ppp`, `v_5_pps_tb`, `v_5_ppp_tb`,
                `v_6_dds`, `v_6_ddp`, `v_6_ddd`, `v_6_pps`, `v_6_ppp`, `v_6_pps_tb` and `v_6_ppp_tb`."""
        super().__init__(None)
        sk_simple_params = [
            *[f"v_{n}_pd{i}" for n in ("1", "3", "4") for i in ("s", "p")],
            *[f"v_{n}_pp{i}{t}" for n in ("2", "5", "6") for i in ("s", "p") for t in ("", "_tb")],
            *[f"v_{n}_dd{i}" for n in ("2", "5", "6") for i in ("s", "p", "d")]
        ]

        sk_simple_params_names = [
            *[rf"$V^{{{n}}}_{{pd{i}}}$" for n in ("1", "3", "4") for i in (r"\sigma", r"\pi")],
            *[rf"$V^{{{n}}}_{{pp{i}{t}}}$" for n in ("2", "5", "6") for i in (r"\sigma", r"\pi") for t in ("", ",tb")],
            *[rf"$V^{{{n}}}_{{dd{i}}}$" for n in ("2", "5", "6") for i in (r"\sigmas", r"\pi", r"\delta")]
        ]
        self._sk_simple_params_dict: dict = dict(zip(
            sk_simple_params,
            [FloatParameter(name=p_name) for p_name in sk_simple_params_names]
        ))

        if input_dict is not None:
            self.from_dict(input_dict)

    def _recalculate_params(self):
        if self._recalculate_params_bool:
            # h1
            self._sk_params_dict["v_1_e_pds"].param = self["v_1_pds"]
            self._sk_params_dict["v_1_o_pds"].param = self["v_1_pds"]
            self._sk_params_dict["v_1_e_pdp"].param = self["v_1_pdp"]
            self._sk_params_dict["v_1_o_pdp"].param = self["v_1_pdp"]
            # h2
            self._sk_params_dict["v_2_e_dds"].param = self["v_2_dds"]
            self._sk_params_dict["v_2_e_ddp"].param = self["v_2_ddp"]
            self._sk_params_dict["v_2_o_ddp"].param = self["v_2_ddp"]
            self._sk_params_dict["v_2_e_ddd"].param = self["v_2_ddd"]
            self._sk_params_dict["v_2_o_ddd"].param = self["v_2_ddd"]
            self._sk_params_dict["v_2_e_pps"].param = self["v_2_pps"]
            self._sk_params_dict["v_2_o_pps"].param = self["v_2_pps"]
            self._sk_params_dict["v_2_e_ppp"].param = self["v_2_ppp"]
            self._sk_params_dict["v_2_o_ppp"].param = self["v_2_ppp"]
            self._sk_params_dict["v_2_e_pps_tb"].param = self["v_2_pps_tb"]
            self._sk_params_dict["v_2_o_pps_tb"].param = self["v_2_pps_tb"]
            self._sk_params_dict["v_2_e_ppp_tb"].param = self["v_2_ppp_tb"]
            self._sk_params_dict["v_2_o_ppp_tb"].param = self["v_2_ppp_tb"]
            # h3
            self._sk_params_dict["v_3_e_pds"].param = self["v_3_pds"]
            self._sk_params_dict["v_3_o_pds"].param = self["v_3_pds"]
            self._sk_params_dict["v_3_e_pdp"].param = self["v_3_pdp"]
            self._sk_params_dict["v_3_o_pdp"].param = self["v_3_pdp"]
            # h4
            self._sk_params_dict["v_4_e_pds"].param = self["v_4_pds"]
            self._sk_params_dict["v_4_o_pds"].param = self["v_4_pds"]
            self._sk_params_dict["v_4_e_pdp"].param = self["v_4_pdp"]
            self._sk_params_dict["v_4_o_pdp"].param = self["v_4_pdp"]
            # h5
            self._sk_params_dict["v_5_e_dds"].param = self["v_5_dds"]
            self._sk_params_dict["v_5_e_ddp"].param = self["v_5_ddp"]
            self._sk_params_dict["v_5_o_ddp"].param = self["v_5_ddp"]
            self._sk_params_dict["v_5_e_ddd"].param = self["v_5_ddd"]
            self._sk_params_dict["v_5_o_ddd"].param = self["v_5_ddd"]
            self._sk_params_dict["v_5_e_pps"].param = self["v_5_pps"]
            self._sk_params_dict["v_5_o_pps"].param = self["v_5_pps"]
            self._sk_params_dict["v_5_e_ppp"].param = self["v_5_ppp"]
            self._sk_params_dict["v_5_o_ppp"].param = self["v_5_ppp"]
            self._sk_params_dict["v_5_e_pps_tb"].param = self["v_5_pps_tb"]
            self._sk_params_dict["v_5_o_pps_tb"].param = self["v_5_pps_tb"]
            self._sk_params_dict["v_5_e_ppp_tb"].param = self["v_5_ppp_tb"]
            self._sk_params_dict["v_5_o_ppp_tb"].param = self["v_5_ppp_tb"]
            # h6
            self._sk_params_dict["v_6_e_dds"].param = self["v_6_dds"]
            self._sk_params_dict["v_6_e_ddp"].param = self["v_6_ddp"]
            self._sk_params_dict["v_6_o_ddp"].param = self["v_6_ddp"]
            self._sk_params_dict["v_6_e_ddd"].param = self["v_6_ddd"]
            self._sk_params_dict["v_6_o_ddd"].param = self["v_6_ddd"]
            self._sk_params_dict["v_6_e_pps"].param = self["v_6_pps"]
            self._sk_params_dict["v_6_o_pps"].param = self["v_6_pps"]
            self._sk_params_dict["v_6_e_ppp"].param = self["v_6_ppp"]
            self._sk_params_dict["v_6_o_ppp"].param = self["v_6_ppp"]
            self._sk_params_dict["v_6_e_pps_tb"].param = self["v_6_pps_tb"]
            self._sk_params_dict["v_6_o_pps_tb"].param = self["v_6_pps_tb"]
            self._sk_params_dict["v_6_e_ppp_tb"].param = self["v_6_ppp_tb"]
            self._sk_params_dict["v_6_o_ppp_tb"].param = self["v_6_ppp_tb"]
            super()._recalculate_params()

    @property
    def _unique_params_dict(self) -> List[dict]:
        return [self._general_params_dict, self._onsite_sk_params_dict, self._sk_simple_params_dict]

    @property
    def _protected_params_dict(self) -> Optional[List[dict]]:
        return [self._sk_params_dict, self._energy_params_dict]

__init__(input_dict=None)

Initializes the SKSimpleParametersList object.

Parameters:

Name Type Description Default
input_dict dict

Dictionary with the SK paramters. The keus are the parameter names and the values are the parameter values. The parameter names are: a, material, lamb_x, lamb_m, theta, delta_p, delta_z, delta_0, delta_1, delta_2, v_0_pps, v_0_ppp, v_1_pds, v_1_pdp, v_2_dds, v_2_ddp, v_2_ddd, v_2_pps, v_2_ppp, v_2_pps_tb, v_2_ppp_tb, v_3_pds, v_3_pdp, v_4_pds, v_4_pdp, v_5_dds, v_5_ddp, v_5_ddd, v_5_pps, v_5_ppp, v_5_pps_tb, v_5_ppp_tb, v_6_dds, v_6_ddp, v_6_ddd, v_6_pps, v_6_ppp, v_6_pps_tb and v_6_ppp_tb.

None
Source code in tmdybinding/parameters/slater_koster.py
def __init__(self, input_dict: Optional[Dict[str, Union[str, Optional[float]]]] = None):
    """Initializes the SKSimpleParametersList object.

    Parameters:
        input_dict (dict): Dictionary with the SK paramters. The keus are the parameter names and the values are the
            parameter values. The parameter names are:
            `a`, `material`, `lamb_x`, `lamb_m`, `theta`,
            `delta_p`, `delta_z`, `delta_0`, `delta_1`, `delta_2`,
            `v_0_pps`, `v_0_ppp`,
            `v_1_pds`, `v_1_pdp`,
            `v_2_dds`, `v_2_ddp`, `v_2_ddd`, `v_2_pps`, `v_2_ppp`, `v_2_pps_tb`, `v_2_ppp_tb`,
            `v_3_pds`, `v_3_pdp`,
            `v_4_pds`, `v_4_pdp`,
            `v_5_dds`, `v_5_ddp`, `v_5_ddd`, `v_5_pps`, `v_5_ppp`, `v_5_pps_tb`, `v_5_ppp_tb`,
            `v_6_dds`, `v_6_ddp`, `v_6_ddd`, `v_6_pps`, `v_6_ppp`, `v_6_pps_tb` and `v_6_ppp_tb`."""
    super().__init__(None)
    sk_simple_params = [
        *[f"v_{n}_pd{i}" for n in ("1", "3", "4") for i in ("s", "p")],
        *[f"v_{n}_pp{i}{t}" for n in ("2", "5", "6") for i in ("s", "p") for t in ("", "_tb")],
        *[f"v_{n}_dd{i}" for n in ("2", "5", "6") for i in ("s", "p", "d")]
    ]

    sk_simple_params_names = [
        *[rf"$V^{{{n}}}_{{pd{i}}}$" for n in ("1", "3", "4") for i in (r"\sigma", r"\pi")],
        *[rf"$V^{{{n}}}_{{pp{i}{t}}}$" for n in ("2", "5", "6") for i in (r"\sigma", r"\pi") for t in ("", ",tb")],
        *[rf"$V^{{{n}}}_{{dd{i}}}$" for n in ("2", "5", "6") for i in (r"\sigmas", r"\pi", r"\delta")]
    ]
    self._sk_simple_params_dict: dict = dict(zip(
        sk_simple_params,
        [FloatParameter(name=p_name) for p_name in sk_simple_params_names]
    ))

    if input_dict is not None:
        self.from_dict(input_dict)

StrainParametersList

Bases: ParametersList

List of strain parameters.

Source code in tmdybinding/parameters/strain.py
class StrainParametersList(ParametersList):
    """List of strain parameters."""

    def __init__(self, input_dict: Optional[Dict[str, Union[float, List[float]]]] = None, max_order: int = 1):
        super().__init__(None)
        self.max_order = max_order
        strain_params = []
        strain_params_names = []

        # biaxial and uniaxial strain parameters
        for strain_type in ("b", "u", "s"):
            for order_idx in range(1, self.max_order+1):
                strain_part = f"{strain_type}_{str(order_idx)}"
                strain_part_name = rf"{strain_type},{str(order_idx)}"
                if not strain_type == "s":
                    for param_key, param_float in self._energy_params_dict.items():
                        strain_params.append(rf"{param_key}_{strain_part}")
                        check_for = r"$\epsilon_" if "eps_" in param_key else r"$u_"
                        split_idx, split_len = len(check_for), 1
                        param_name = param_float.name
                        pre_name = param_name[:split_idx]
                        idx_name = param_name[split_idx:split_idx+split_len]
                        pst_name = param_name[split_idx+split_len:]
                        assert pre_name == check_for, f"Expected {check_for}, got {pre_name}"
                        strain_params_names.append(rf"{pre_name}{{{idx_name},{strain_part_name}}}{pst_name}")
                else:
                    params_shear = [
                        *[f"u_{u}_{i}_m_e_{strain_part}" for u in ("1", "3", "4") for i in range(5, 9)],
                        *[f"u_{u}_{i}_m_o_{strain_part}" for u in ("1", "3", "4") for i in range(3, 6)],
                        *[f"u_{u}_{i}_{m}_e_{strain_part}" for u in ("2", "6") for i in ("1", "2", "4") for m in ("m", "x")],
                        *[f"u_{u}_{i}_x_o_{strain_part}" for u in ("2", "6") for i in ("1", "2", "4")],
                        *[f"u_{u}_{i}_m_o_{strain_part}" for u in ("2", "6") for i in range(1, 2)],
                        *[f"u_{u}_{i}_m_e_{strain_part}" for u in "5" for i in ("2", "4", "7", "8")],
                        *[f"u_{u}_{i}_x_{r}_{strain_part}" for u in "5" for i in ("1", "4", "7", "8") for r in ("e", "o")],
                        *[f"u_{u}_{i}_m_o_{strain_part}" for u in "5" for i in ("1", "3")],
                    ]
                    params_names_shear = [
                        *[rf"$u_{{{u},{strain_part_name}}}^{{{i},e}}$" for u in ("1", "3", "4") for i in range(5, 9)],
                        *[rf"$u_{{{u},{strain_part_name}}}^{{{i},o}}$" for u in ("1", "3", "4") for i in range(3, 6)],
                        *[rf"$u_{{{u},{strain_part_name}}}^{{{i},{m}e}}$" for u in ("2", "6") for i in ("1", "2", "4") for m in ("M", "X")],
                        *[rf"$u_{{{u},{strain_part_name}}}^{{{i},Xo}}$" for u in ("2", "6") for i in ("1", "2", "4")],
                        *[rf"$u_{{{u},{strain_part_name}}}^{{{i},Mo}}$" for u in ("2", "6") for i in range(1, 2)],
                        *[rf"$u_{{{u},{strain_part_name}}}^{{{i},Me}}$" for u in "5" for i in ("2", "4", "7", "8")],
                        *[rf"$u_{{{u},{strain_part_name}}}^{{{i},X{r}}}$" for u in "5" for i in ("2", "4", "7", "8") for r in ("e", "o")],
                        *[rf"$u_{{{u},{strain_part_name}}}^{{{i},Mo}}$" for u in "5" for i in ("1", "3")],
                    ]
                    strain_params.extend(params_shear)
                    strain_params_names.extend(params_names_shear)


        # shear strain parameters, only hoppings as onsite are given by the uniaxial parameters
        self._strain_params_dict: dict = dict(zip(
            strain_params,
            [FloatParameter(name=p_name) for p_name in strain_params_names]
        ))


        if input_dict is not None:
            self.from_dict(input_dict)

    @property
    def _unique_params_dict(self) -> List[dict]:
        return [self._general_params_dict, self._energy_params_dict, self._strain_params_dict]

StringParameter dataclass

Bases: Parameter

Class to store one separate string parameter

Source code in tmdybinding/parameters/symmetry_group.py
@dataclass
class StringParameter(Parameter):
    """Class to store one separate string parameter"""
    param: Optional[str] = None

TmdMatrices

Construct the TMD hopping matrices

Source code in tmdybinding/tmd_hopping_matrices.py
class TmdMatrices:
    """Construct the TMD hopping matrices"""
    def __init__(self, params: ParametersList):
        """Initialize the TMD hopping matrices

        Parameters:
            params (ParametersList): The parameters for the TMD lattice."""
        self.params = params

    @staticmethod
    def _t_n_e(u_0, u_1, u_2, u_3, u_4) -> np.ndarray:
        """The hopping matrices for the first-, third- and fourth-nearest neighbours from the even metal orbitals"""
        return np.array([[0, 0, u_0], [u_1, u_2, 0], [u_3, u_4, 0]])

    @staticmethod
    def _t_n_o(u_0, u_1, u_2) -> np.ndarray:
        """The hopping matrices for the first-, third- and fourth-nearest neighbours from the odd metal orbitals"""
        return np.array([[u_0, 0], [0, u_1], [0, u_2]])

    @staticmethod
    def _t_m_xr(u_0, u_1, u_2, u_3, u_4, u_5) -> np.ndarray:
        """The hopping matrices for the second- and sixth-nearest neighbours from the chalcogen orbitals"""
        return np.array([[u_0, u_1, u_2], [-u_1, u_3, u_4], [-u_2, u_4, u_5]])

    @staticmethod
    def _t_m_me(u_0, u_1, u_2, u_3, u_4, u_5) -> np.ndarray:
        """The hopping matrices for the second-, fifth- and sixth-nearest neighbours from the even metal orbitals"""
        return np.array([[u_0, u_1, u_2], [u_1, u_3, u_4], [-u_2, -u_4, u_5]])

    @staticmethod
    def _t_m_mo(u_0, u_1, u_2) -> np.ndarray:
        """The hopping matrices for the second-, fifth- and sixth-nearest neighbours from the odd metal orbitals"""
        return np.array([[u_0, u_1], [-u_1, u_2]])

    @staticmethod
    def _t_5_me(u_0, u_1, u_3, u_5, u_6) ->np.ndarray:
        """The hopping matrix for the fifth-nearest neighbours from the even metal orbitals"""
        return np.array([[u_0, -u_1, 0.0], [-u_6, u_3, 0.0], [0.0, 0.0, u_5]])

    @staticmethod
    def _t_5_mo(u_0, u_2) -> np.ndarray:
        """The hopping matrix for the fifth-nearest neighbours from the odd metal orbitals"""
        return np.diag((u_2, u_0))

    @staticmethod
    def _t_5_xr(u_0, u_2, u_3, u_5, u_6) -> np.ndarray:
        """The hopping matrices for the fifth-nearest neighbours from the chalcogen orbitals"""
        return np.array([[u_3, 0, 0], [0, u_0, u_2], [0, u_6, u_5]])

    @property
    def e_xe(self) -> np.ndarray:
        """The hopping matrix for the even chalcogen orbitals"""
        return np.diag((self.params["eps_0_x_e"], self.params["eps_0_x_e"], self.params["eps_1_x_e"]))

    @property
    def e_xo(self) -> np.ndarray:
        """The hopping matrix for the odd chalcogen orbitals"""
        return np.diag((self.params["eps_0_x_o"], self.params["eps_0_x_o"], self.params["eps_1_x_o"]))

    @property
    def e_me(self) -> np.ndarray:
        """The hopping matrix for the even metal orbitals"""
        return np.diag((self.params["eps_0_m_e"], self.params["eps_1_m_e"], self.params["eps_1_m_e"]))

    @property
    def e_mo(self) -> np.ndarray:
        """The hopping matrix for the odd metal orbitals"""
        return np.diag((self.params["eps_0_m_o"], self.params["eps_0_m_o"]))

    @property
    def t_1_me(self) -> np.ndarray:
        """The first-nearest neighbour hopping matrix from the even metal orbitals"""
        return self._t_n_e(*[self.params[f"u_1_{i}_m_e"] for i in range(5)])

    @property
    def t_1_mo(self) -> np.ndarray:
        """The first-nearest neighbour hopping matrix from the odd metal orbitals"""
        return self._t_n_o(*[self.params[f"u_1_{i}_m_o"] for i in range(3)])

    @property
    def t_2_me(self) -> np.ndarray:
        """The second-nearest neighbour hopping matrix from the even metal orbitals"""
        return self._t_m_me(*[self.params[f"u_2_{i}_m_e"] for i in range(6)])

    @property
    def t_2_mo(self) -> np.ndarray:
        """The second-nearest neighbour hopping matrix from the odd metal orbitals"""
        return self._t_m_mo(*[self.params[f"u_2_{i}_m_o"] for i in range(3)])

    @property
    def t_2_xe(self) -> np.ndarray:
        """The second-nearest neighbour hopping matrix from the even chalcogen orbitals"""
        return self._t_m_xr(*[self.params[f"u_2_{i}_x_e"] for i in range(6)])

    @property
    def t_2_xo(self) -> np.ndarray:
        """The second-nearest neighbour hopping matrix from the odd chalcogen orbitals"""
        return self._t_m_xr(*[self.params[f"u_2_{i}_x_o"] for i in range(6)])

    @property
    def t_3_me(self) -> np.ndarray:
        """The third-nearest neighbour hopping matrix from the even metal orbitals"""
        return self._t_n_e(*[self.params[f"u_3_{i}_m_e"] for i in range(5)])

    @property
    def t_3_mo(self) -> np.ndarray:
        """The third-nearest neighbour hopping matrix from the odd metal orbitals"""
        return self._t_n_o(*[self.params[f"u_3_{i}_m_o"] for i in range(3)])

    @property
    def t_4_me(self) -> np.ndarray:
        """The fourth-nearest neighbour hopping matrix from the even metal orbitals"""
        return self._t_n_e(*[self.params[f"u_4_{i}_m_e"] for i in range(5)])

    @property
    def t_4_mo(self) -> np.ndarray:
        """The fourth-nearest neighbour hopping matrix from the odd metal orbitals"""
        return self._t_n_o(*[self.params[f"u_4_{i}_m_o"] for i in range(3)])

    @property
    def t_5_me(self) -> np.ndarray:
        """The fifth-nearest neighbour hopping matrix from the even metal orbitals"""
        return self._t_5_me(*[self.params[f"u_5_{i}_m_e"] for i in ("0", "1", "3", "5", "6")])

    @property
    def t_5_mo(self) -> np.ndarray:
        """The fifth-nearest neighbour hopping matrix from the odd metal orbitals"""
        return self._t_5_mo(*[self.params[f"u_5_{i}_m_o"] for i in ("0", "2")])

    @property
    def t_5_xe(self) -> np.ndarray:
        """The fifth-nearest neighbour hopping matrix from the even chalcogen orbitals"""
        return self._t_5_xr(*[self.params[f"u_5_{i}_x_e"] for i in ("0", "2", "3", "5", "6")])

    @property
    def t_5_xo(self) -> np.ndarray:
        """The fifth-nearest neighbour hopping matrix from the odd chalcogen orbitals"""
        return self._t_5_xr(*[self.params[f"u_5_{i}_x_o"] for i in ("0", "2", "3", "5", "6")])

    @property
    def t_6_me(self) -> np.ndarray:
        """The sixth-nearest neighbour hopping matrix from the even metal orbitals"""
        return self._t_m_me(*[self.params[f"u_6_{i}_m_e"] for i in range(6)])

    @property
    def t_6_mo(self) -> np.ndarray:
        """The sixth-nearest neighbour hopping matrix from the odd metal orbitals"""
        return self._t_m_mo(*[self.params[f"u_6_{i}_m_o"] for i in range(3)])

    @property
    def t_6_xe(self) -> np.ndarray:
        """The sixth-nearest neighbour hopping matrix from the even chalcogen orbitals"""
        return self._t_m_xr(*[self.params[f"u_6_{i}_x_e"] for i in range(6)])

    @property
    def t_6_xo(self) -> np.ndarray:
        """The sixth-nearest neighbour hopping matrix from the odd chalcogen orbitals"""
        return self._t_m_xr(*[self.params[f"u_6_{i}_x_o"] for i in range(6)])

e_me: np.ndarray property

The hopping matrix for the even metal orbitals

e_mo: np.ndarray property

The hopping matrix for the odd metal orbitals

e_xe: np.ndarray property

The hopping matrix for the even chalcogen orbitals

e_xo: np.ndarray property

The hopping matrix for the odd chalcogen orbitals

t_1_me: np.ndarray property

The first-nearest neighbour hopping matrix from the even metal orbitals

t_1_mo: np.ndarray property

The first-nearest neighbour hopping matrix from the odd metal orbitals

t_2_me: np.ndarray property

The second-nearest neighbour hopping matrix from the even metal orbitals

t_2_mo: np.ndarray property

The second-nearest neighbour hopping matrix from the odd metal orbitals

t_2_xe: np.ndarray property

The second-nearest neighbour hopping matrix from the even chalcogen orbitals

t_2_xo: np.ndarray property

The second-nearest neighbour hopping matrix from the odd chalcogen orbitals

t_3_me: np.ndarray property

The third-nearest neighbour hopping matrix from the even metal orbitals

t_3_mo: np.ndarray property

The third-nearest neighbour hopping matrix from the odd metal orbitals

t_4_me: np.ndarray property

The fourth-nearest neighbour hopping matrix from the even metal orbitals

t_4_mo: np.ndarray property

The fourth-nearest neighbour hopping matrix from the odd metal orbitals

t_5_me: np.ndarray property

The fifth-nearest neighbour hopping matrix from the even metal orbitals

t_5_mo: np.ndarray property

The fifth-nearest neighbour hopping matrix from the odd metal orbitals

t_5_xe: np.ndarray property

The fifth-nearest neighbour hopping matrix from the even chalcogen orbitals

t_5_xo: np.ndarray property

The fifth-nearest neighbour hopping matrix from the odd chalcogen orbitals

t_6_me: np.ndarray property

The sixth-nearest neighbour hopping matrix from the even metal orbitals

t_6_mo: np.ndarray property

The sixth-nearest neighbour hopping matrix from the odd metal orbitals

t_6_xe: np.ndarray property

The sixth-nearest neighbour hopping matrix from the even chalcogen orbitals

t_6_xo: np.ndarray property

The sixth-nearest neighbour hopping matrix from the odd chalcogen orbitals

__init__(params)

Initialize the TMD hopping matrices

Parameters:

Name Type Description Default
params ParametersList

The parameters for the TMD lattice.

required
Source code in tmdybinding/tmd_hopping_matrices.py
def __init__(self, params: ParametersList):
    """Initialize the TMD hopping matrices

    Parameters:
        params (ParametersList): The parameters for the TMD lattice."""
    self.params = params

TmdNN123456MeoXeo

Bases: AbstractLattice

11 bands model for metal and chalcogen orbitals with all the hoppings up to sixth nearest-neighbor hopping

Source code in tmdybinding/tmd_lattice.py
class TmdNN123456MeoXeo(AbstractLattice):
    """11 bands model for metal and chalcogen orbitals with all the hoppings up to sixth nearest-neighbor hopping"""
    def __init__(self, **kwargs):
        orbital = LatticeOrbitals(
            l_number={"M": [0, 2, -2, 1, -1], "X": [1, -1, 0, 1, -1, 0]},
            orbs={"M": ["dz2", "dx2y2", "dxy", "dxz", "dyz"], "X": ["pxe", "pye", "pze", "pxo", "pyo", "pzo"]},
            group={"M": [0, 1, 1, 2, 2], "X": [0, 0, 1, 2, 2, 3]}
        )
        super().__init__(orbital=orbital, params=all["MoS2"], lattice_name="11 bands 6NN model",
                         n_v=6, n_b=11)
        [setattr(self, var, kwargs[var]) for var in [*kwargs]]

    def _generate_matrices(self):
        t_m = TmdMatrices(self.params)
        h_0_m = self.block_diag(t_m.e_me, t_m.e_mo)
        h_0_x = self.block_diag(t_m.e_xe, t_m.e_xo)
        h_1_m = self.block_diag(t_m.t_1_me, t_m.t_1_mo)
        h_2_m = self.block_diag(t_m.t_2_me, t_m.t_2_mo)
        h_2_x = self.block_diag(t_m.t_2_xe, t_m.t_2_xo)
        h_3_m = self.block_diag(t_m.t_3_me, t_m.t_3_mo)
        h_4_m = self.block_diag(t_m.t_4_me, t_m.t_4_mo)
        h_5_m = self.block_diag(t_m.t_5_me, t_m.t_5_mo)
        h_5_x = self.block_diag(t_m.t_5_xe, t_m.t_5_xo)
        h_6_m = self.block_diag(t_m.t_6_me, t_m.t_6_mo)
        h_6_x = self.block_diag(t_m.t_6_xe, t_m.t_6_xo)
        keys = ["h_0_m", "h_0_c", "h_1_m", "h_2_m", "h_2_c", "h_3_m", "h_4_m", "h_5_m", "h_5_c", "h_6_m", "h_6_c",
                "a", "lamb_m", "lamb_c"]
        values = [h_0_m, h_0_x, h_1_m, h_2_m, h_2_x, h_3_m, h_4_m, h_5_m, h_5_x, h_6_m, h_6_x,
                  self.params["a"], self.params["lamb_m"], self.params["lamb_x"]]
        self.lattice_params.set_params(dict([(key, value) for key, value in zip(keys, values)]))

TmdNN123MeoXeo

Bases: AbstractLattice

11 bands model for metal and chalcogen orbitals with the first-, second- and third-nearest-neighbor hopping

Source code in tmdybinding/tmd_lattice.py
class TmdNN123MeoXeo(AbstractLattice):
    """11 bands model for metal and chalcogen orbitals with the first-, second- and third-nearest-neighbor hopping"""
    def __init__(self, **kwargs):
        orbital = LatticeOrbitals(
            l_number={"M": [0, 2, -2, 1, -1], "X": [1, -1, 0, 1, -1, 0]},
            orbs={"M": ["dz2", "dx2y2", "dxy", "dxz", "dyz"], "X": ["pxe", "pye", "pze", "pxo", "pyo", "pzo"]},
            group={"M": [0, 1, 1, 2, 2], "X": [0, 0, 1, 2, 2, 3]}
        )
        super().__init__(orbital=orbital, params=fang["MoS2"], lattice_name="11 bands 3NN model",
                         n_v=6, n_b=11)
        [setattr(self, var, kwargs[var]) for var in [*kwargs]]

    def _generate_matrices(self):
        t_m = TmdMatrices(self.params)
        h_0_m = self.block_diag(t_m.e_me, t_m.e_mo)
        h_0_x = self.block_diag(t_m.e_xe, t_m.e_xo)
        h_1_m = self.block_diag(t_m.t_1_me, t_m.t_1_mo)
        h_2_m = self.block_diag(t_m.t_2_me, t_m.t_2_mo)
        h_2_x = self.block_diag(t_m.t_2_xe, t_m.t_2_xo)
        h_3_m = self.block_diag(t_m.t_3_me, t_m.t_1_mo * 0)
        keys = ["h_0_m", "h_0_c", "h_1_m", "h_2_m", "h_2_c", "h_3_m",
                "a", "lamb_m", "lamb_c"]
        values = [h_0_m, h_0_x, h_1_m, h_2_m, h_2_x, h_3_m,
                  self.params["a"], self.params["lamb_m"], self.params["lamb_x"]]
        self.lattice_params.set_params(dict([(key, value) for key, value in zip(keys, values)]))

TmdNN125MeoXeo

Bases: AbstractLattice

11 bands model for metal and chalcogen orbitals with the first-, second- and fifth- nearest-neighbor hopping

Source code in tmdybinding/tmd_lattice.py
class TmdNN125MeoXeo(AbstractLattice):
    """11 bands model for metal and chalcogen orbitals with the first-, second- and fifth- nearest-neighbor hopping"""
    def __init__(self, **kwargs):
        orbital = LatticeOrbitals(
            l_number={"M": [0, 2, -2, 1, -1], "X": [1, -1, 0, 1, -1, 0]},
            orbs={"M": ["dz2", "dx2y2", "dxy", "dxz", "dyz"], "X": ["pxe", "pye", "pze", "pxo", "pyo", "pzo"]},
            group={"M": [0, 1, 1, 2, 2], "X": [0, 0, 1, 2, 2, 3]}
        )
        super().__init__(orbital=orbital, params=dias["MoS2"], lattice_name="11 bands 5NN model",
                         n_v=6, n_b=11)
        [setattr(self, var, kwargs[var]) for var in [*kwargs]]

    def _generate_matrices(self):
        t_m = TmdMatrices(self.params)
        h_0_m = self.block_diag(t_m.e_me, t_m.e_mo)
        h_0_x = self.block_diag(t_m.e_xe, t_m.e_xo)
        h_1_m = self.block_diag(t_m.t_1_me, t_m.t_1_mo)
        h_2_m = self.block_diag(t_m.t_2_me, t_m.t_2_mo)
        h_2_x = self.block_diag(t_m.t_2_xe, t_m.t_2_xo)
        h_5_m = self.block_diag(t_m.t_5_me, t_m.t_5_mo)
        h_5_x = self.block_diag(t_m.t_5_xe, t_m.t_5_xo)
        keys = ["h_0_m", "h_0_c", "h_1_m", "h_2_m", "h_2_c", "h_5_m", "h_5_c",
                "a", "lamb_m", "lamb_c"]
        values = [h_0_m, h_0_x, h_1_m, h_2_m, h_2_x, h_5_m, h_5_x,
                  self.params["a"], self.params["lamb_m"], self.params["lamb_x"]]
        self.lattice_params.set_params(dict([(key, value) for key, value in zip(keys, values)]))

TmdNN12MeXe

Bases: AbstractLattice

6 bands model for even metal and chalcogen orbitals with the first- and second-nearest-neighbor hopping

Source code in tmdybinding/tmd_lattice.py
class TmdNN12MeXe(AbstractLattice):
    """6 bands model for even metal and chalcogen orbitals with the first- and second-nearest-neighbor hopping"""
    def __init__(self, **kwargs):
        orbital = LatticeOrbitals(
            l_number={"M": [0, 2, -2], "X": [1, -1, 0]},
            orbs={"M": ["dz2", "dx2y2", "dxy"], "X": ["pxe", "pye", "pze"]},
            group={"M": [0, 2, 2], "X": [0, 0, 1]}
        )
        super().__init__(orbital=orbital, params=jorissen["MoS2"], lattice_name="6 bands 2NN model",
                         n_v=3, n_b=6)
        [setattr(self, var, kwargs[var]) for var in [*kwargs]]

    def _generate_matrices(self):
        t_m = TmdMatrices(self.params)
        h_0_m = t_m.e_me
        h_0_x = t_m.e_xe
        h_1_m = t_m.t_1_me
        h_2_m = t_m.t_2_me
        h_2_x = t_m.t_2_xe
        keys = ["h_0_m", "h_0_c", "h_1_m", "h_2_m", "h_2_c", "a", "lamb_m", "lamb_c"]
        values = [h_0_m, h_0_x, h_1_m, h_2_m, h_2_x, self.params["a"], self.params["lamb_m"], self.params["lamb_x"]]
        self.lattice_params.set_params(dict([(key, value) for key, value in zip(keys, values)]))

TmdNN12MeoXeo

Bases: AbstractLattice

3 bands model for metal and chalocogen orbitals with the first- and second-nearest-neighbor hopping

Source code in tmdybinding/tmd_lattice.py
class TmdNN12MeoXeo(AbstractLattice):
    """3 bands model for metal and chalocogen orbitals with the first- and second-nearest-neighbor hopping"""
    def __init__(self, **kwargs):
        orbital = LatticeOrbitals(
            l_number={"M": [0, 2, -2, 1, -1], "X": [1, -1, 0, 1, -1, 0]},
            orbs={"M": ["dz2", "dx2y2", "dxy", "dxz", "dyz"], "X": ["pxe", "pye", "pze", "pxo", "pyo", "pzo"]},
            group={"M": [0, 1, 1, 2, 2], "X": [0, 0, 1, 2, 2, 3]}
        )
        super().__init__(orbital=orbital, params=cappelluti["MoS2"], lattice_name="11 bands 2NN model",
                         n_v=6, n_b=11)
        [setattr(self, var, kwargs[var]) for var in [*kwargs]]
    def _generate_matrices(self):
        t_m = TmdMatrices(self.params)
        h_0_m = self.block_diag(t_m.e_me, t_m.e_mo)
        h_0_x = self.block_diag(t_m.e_xe, t_m.e_xo)
        h_1_m = self.block_diag(t_m.t_1_me, t_m.t_1_mo)
        h_2_m = self.block_diag(t_m.t_2_me, t_m.t_2_mo)
        h_2_x = self.block_diag(t_m.t_2_xe, t_m.t_2_xo)
        keys = ["h_0_m", "h_0_c", "h_1_m", "h_2_m", "h_2_c", "a", "lamb_m", "lamb_c"]
        values = [h_0_m, h_0_x, h_1_m, h_2_m, h_2_x, self.params["a"], self.params["lamb_m"], self.params["lamb_x"]]
        self.lattice_params.set_params(dict([(key, value) for key, value in zip(keys, values)]))

TmdNN256Me

Bases: AbstractLattice

3 bands model for even metal orbitals with the second-, fifth- and sixth-nearest-neighbor hopping

Source code in tmdybinding/tmd_lattice.py
class TmdNN256Me(AbstractLattice):
    """3 bands model for even metal orbitals with the second-, fifth- and sixth-nearest-neighbor hopping"""

    def __init__(self, **kwargs):
        orbital = LatticeOrbitals(
            l_number={"M": [0, 2, -2]},
            orbs={"M": ["dz2", "dx2y2", "dxy"]},
            group={"M": [0, 1, 1]}
        )
        super().__init__(orbital=orbital, params=liu6["MoS2"], lattice_name="3 bands 6NN model",
                         n_v=0, n_b=3)
        [setattr(self, var, kwargs[var]) for var in [*kwargs]]
    def _generate_matrices(self):
        t_m = TmdMatrices(self.params)
        h_0_m = t_m.e_me
        h_2_m = t_m.t_2_me
        h_5_m = t_m.t_5_me
        h_6_m = t_m.t_6_me
        keys = ["h_0_m", "h_2_m", "h_5_m", "h_6_m", "a", "lamb_m"]
        values = [h_0_m, h_2_m, h_5_m, h_6_m, self.params["a"], self.params["lamb_m"]]
        self.lattice_params.set_params(dict([(key, value) for key, value in zip(keys, values)]))

TmdNN256Meo

Bases: AbstractLattice

5 bands model for metal orbitals with the second-, fifth- and sixth-nearest-neighbor hopping

Source code in tmdybinding/tmd_lattice.py
class TmdNN256Meo(AbstractLattice):
    """5 bands model for metal orbitals with the second-, fifth- and sixth-nearest-neighbor hopping"""
    def __init__(self, **kwargs):
        orbital = LatticeOrbitals(
            l_number={"M": [0, 2, -2, 1, -1]},
            orbs={"M": ["dz2", "dx2y2", "dxy", "dxz", "dyz"]},
            group={"M": [0, 1, 1, 2, 2]}
        )
        super().__init__(orbital=orbital, params=wu["MoS2"], lattice_name="5 bands 6NN model",
                         n_v=0, n_b=5)
        [setattr(self, var, kwargs[var]) for var in [*kwargs]]

    def _generate_matrices(self):
        t_m = TmdMatrices(self.params)
        h_0_m = self.block_diag(t_m.e_me, t_m.e_mo)
        h_2_m = self.block_diag(t_m.t_2_me, t_m.t_2_mo)
        h_5_m = self.block_diag(t_m.t_5_me, t_m.t_5_mo)
        h_6_m = self.block_diag(t_m.t_6_me, t_m.t_6_mo)
        keys = ["h_0_m", "h_2_m", "h_5_m", "h_6_m", "a", "lamb_m"]
        values = [h_0_m, h_2_m, h_5_m, h_6_m, self.params["a"], self.params["lamb_m"]]
        self.lattice_params.set_params(dict([(key, value) for key, value in zip(keys, values)]))

TmdNN2Me

Bases: AbstractLattice

3 bands model for even metal orbitals with the second nearest-neighbor hopping

Source code in tmdybinding/tmd_lattice.py
class TmdNN2Me(AbstractLattice):
    """3 bands model for even metal orbitals with the second nearest-neighbor hopping"""
    def __init__(self, **kwargs):
        orbital = LatticeOrbitals(
            l_number={"M": [0, 2, -2]},
            orbs={"M": ["dz2", "dx2y2", "dxy"]},
            group={"M": [0, 1, 1]}
        )
        super().__init__(orbital=orbital, params=liu2["MoS2"], lattice_name="3 bands 2NN model",
                         n_v=0, n_b=3)
        [setattr(self, var, kwargs[var]) for var in [*kwargs]]

    def _generate_matrices(self):
        t_m = TmdMatrices(self.params)
        h_0_m = t_m.e_me
        h_2_m = t_m.t_2_me
        keys = ["h_0_m", "h_2_m", "a", "lamb_m"]
        values = [h_0_m, h_2_m, self.params["a"], self.params["lamb_m"]]
        self.lattice_params.set_params(dict([(key, value) for key, value in zip(keys, values)]))

TmdStrainMatrices

Bases: TmdMatrices

Construct the strained TMD hopping matrices

Source code in tmdybinding/tmd_strain.py
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
class TmdStrainMatrices(TmdMatrices):
    """Construct the strained TMD hopping matrices"""

    def __init__(self, params: StrainParametersList):
        """Initialize the strained TMD hopping matrices

        Parameters:
            params (StrainParametersList): The parameters for the strained TMD lattice."""
        super().__init__(params)
        self.params: StrainParametersList = params

    @staticmethod
    def _e_xr_u(u_0, u_1) -> np.ndarray:
        """The onsite matrix for the chalcogen orbitals under uniaxial strain"""
        return np.array([[u_0, 0, 0], [0, -u_0, u_1], [0, u_1, 0]])

    @staticmethod
    def _e_me_u(u_0, u_1) -> np.ndarray:
        """The onsite matrix for the even metal orbitals under uniaxial strain"""
        return np.array([[0, u_0, 0], [u_0, -u_1, 0], [0, 0, u_1]])

    @staticmethod
    def _e_mo_u(u_0) -> np.ndarray:
        """The onsite matrix for the odd metal orbitals under uniaxial strain"""
        return np.array([[u_0, 0], [0, -u_0]])

    @staticmethod
    def _e_xr_s(u_0, u_1) -> np.ndarray:
        """The onsite matrix for the chalcogen orbitals under shear strain"""
        return np.array([[0, -u_0, -u_1], [-u_0, 0, 0], [-u_1, 0, 0]])

    @staticmethod
    def _e_me_s(u_0, u_1) -> np.ndarray:
        """The onsite matrix for the even metal orbitals under shear strain"""
        return np.array([[0, 0, -u_0], [0, 0, -u_1], [-u_0, -u_1, 0]])

    @staticmethod
    def _e_mo_s(u_0) -> np.ndarray:
        """The onsite matrix for the odd metal orbitals under shear strain"""
        return np.array([[0, -u_0], [-u_0, 0]])

    @staticmethod
    def _t_n_e_s(u_5, u_6, u_7, u_8) -> np.ndarray:
        """The hopping matrices for the first-, third- and fourth-nearest neighbours from the even metal orbitals under shear strain"""
        return np.array([[u_5, u_6, 0], [0, 0, u_7], [0, 0, u_8]])

    @staticmethod
    def _t_n_o_s(u_3, u_4, u_5) -> np.ndarray:
        """The hopping matrices for the first-, third- and fourth-nearest neighbours from the odd metal orbitals under shear strain"""
        return np.array([[0, u_3], [u_4, 0], [u_5, 0]])

    @staticmethod
    def _t_m_xr_s(u_1, u_2, u_4) -> np.ndarray:
        """The hopping matrices for the second- and sixth-nearest neighbours from the chalcogen orbitals under shear strain"""
        return np.array([[0, u_1, u_2], [u_1, 0, u_4], [u_2, -u_4, 0]])

    @staticmethod
    def _t_m_me_s(u_1, u_2, u_4) -> np.ndarray:
        """The hopping matrices for the second-, fifth- and sixth-nearest neighbours from the even metal orbitals under shear strain"""
        return np.array([[0, u_1, u_2], [-u_1, 0, u_4], [u_2, u_4, 0]])

    @staticmethod
    def _t_m_mo_s(u_1) -> np.ndarray:
        """The hopping matrices for the second-, fifth- and sixth-nearest neighbours from the odd metal orbitals under shear strain"""
        return np.array([[0, u_1], [u_1, 0]])

    @staticmethod
    def _t_5_me_s(u_2, u_4, u_7, u_8) -> np.ndarray:
        """The hopping matrix for the fifth-nearest neighbours from the even metal orbitals under shear strain"""
        return np.array([[0, 0, u_2], [0, 0, u_4], [u_7, u_8, 0]])

    @staticmethod
    def _t_5_mo_s(u_1, u_3) -> np.ndarray:
        """The hopping matrix for the fifth-nearest neighbours from the odd metal orbitals under shear strain"""
        return np.array([[0, u_1], [u_3, 0]])

    @staticmethod
    def _t_5_xr_s(u_1, u_4, u_7, u_8) -> np.ndarray:
        """The hopping matrices for the fifth-nearest neighbours from the chalcogen orbitals under shear strain"""
        return np.array([[0, u_1, u_4], [u_7, 0, 0], [u_8, 0, 0]])

    @property
    def e_xe_b(self) -> list[np.ndarray]:
        """The hopping matrix for the even chalcogen orbitals under biaxial strain"""
        return [
            np.diag((
                self.params[f"eps_0_x_e_b_{order_idx}"],
                self.params[f"eps_0_x_e_b_{order_idx}"],
                self.params[f"eps_1_x_e_b_{order_idx}"]
            ))
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_xo_b(self) -> list[np.ndarray]:
        """The hopping matrix for the odd chalcogen orbitals under biaxial strain"""
        return [
            np.diag((
                self.params[f"eps_0_x_o_b_{order_idx}"],
                self.params[f"eps_0_x_o_b_{order_idx}"],
                self.params[f"eps_1_x_o_b_{order_idx}"]
            ))
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_me_b(self) -> list[np.ndarray]:
        """The hopping matrix for the even metal orbitals under biaxial strain"""
        return [
            np.diag((
                self.params[f"eps_0_m_e_b_{order_idx}"],
                self.params[f"eps_1_m_e_b_{order_idx}"],
                self.params[f"eps_1_m_e_b_{order_idx}"]
            ))
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_mo_b(self) -> list[np.ndarray]:
        """The hopping matrix for the odd metal orbitals under biaxial strain"""
        return [
            np.diag((
                self.params[f"eps_0_m_e_b_{order_idx}"],
                self.params[f"eps_0_m_e_b_{order_idx}"]
            ))
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_xe_u(self) -> list[np.ndarray]:
        """The hopping matrix for the even chalcogen orbitals under uniaxial strain"""
        return [self._e_xr_u(
            self.params[f"eps_0_x_e_u_{order_idx}"],
            self.params[f"eps_1_x_e_u_{order_idx}"]
        ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_xo_u(self) -> list[np.ndarray]:
        """The hopping matrix for the odd chalcogen orbitals under uniaxial strain"""
        return [
            self._e_xr_u(
                self.params[f"eps_0_x_o_u_{order_idx}"],
                self.params[f"eps_1_x_o_u_{order_idx}"]
            )
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_me_u(self) -> list[np.ndarray]:
        """The hopping matrix for the even metal orbitals under uniaxial strain"""
        return [
            self._e_me_u(
                self.params[f"eps_0_m_e_u_{order_idx}"],
                self.params[f"eps_1_m_e_u_{order_idx}"]
            )
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_mo_u(self) -> list[np.ndarray]:
        """The hopping matrix for the odd metal orbitals under uniaxial strain"""
        return [
            self._e_mo_u(
                self.params[f"eps_0_m_o_u_{order_idx}"]
            )
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_xe_s(self) -> list[np.ndarray]:
        """The hopping matrix for the even chalcogen orbitals under shear strain"""
        return [
            self._e_xr_s(
                self.params[f"eps_0_x_e_u_{order_idx}"],
                self.params[f"eps_1_x_e_u_{order_idx}"]
            )
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_xo_s(self) -> list[np.ndarray]:
        """The hopping matrix for the odd chalcogen orbitals under shear strain"""
        return [
            self._e_xr_s(
                self.params[f"eps_0_x_o_u_{order_idx}"],
                self.params[f"eps_1_x_o_u_{order_idx}"]
            )
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_me_s(self) -> list[np.ndarray]:
        """The hopping matrix for the even metal orbitals under shear strain"""
        return [
            self._e_me_s(
                self.params[f"eps_0_m_e_u_{order_idx}"],
                self.params[f"eps_1_m_e_u_{order_idx}"]
            )
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def e_mo_s(self) -> list[np.ndarray]:
        """The hopping matrix for the odd metal orbitals under shear strain"""
        return [
            self._e_mo_s(
                self.params[f"eps_0_m_o_u_{order_idx}"]
            )
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_1_me_b(self) -> list[np.ndarray]:
        """The first-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain"""
        return [
            self._t_n_e(*[self.params[f"u_1_{i}_m_e_b_{order_idx}"] for i in range(5)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_1_mo_b(self) -> list[np.ndarray]:
        """The first-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain"""
        return [
            self._t_n_o(*[self.params[f"u_1_{i}_m_o_b_{order_idx}"] for i in range(3)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_me_b(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain"""
        return [
            self._t_m_me(*[self.params[f"u_2_{i}_m_e_b_{order_idx}"] for i in range(6)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_mo_b(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain"""
        return [
            self._t_m_mo(*[self.params[f"u_2_{i}_m_o_b_{order_idx}"] for i in range(3)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_xe_b(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the even chalcogen orbitals under biaxial strain"""
        return [
            self._t_m_xr(*[self.params[f"u_2_{i}_x_e_b_{order_idx}"] for i in range(6)]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_xo_b(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the odd chalcogen orbitals under biaxial strain"""
        return [
            self._t_m_xr(*[self.params[f"u_2_{i}_x_o_b_{order_idx}"] for i in range(6)]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_3_me_b(self) -> list[np.ndarray]:
        """The third-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain"""
        return [
            self._t_n_e(*[self.params[f"u_3_{i}_m_e_b_{order_idx}"] for i in range(5)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_3_mo_b(self) -> list[np.ndarray]:
        """The third-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain"""
        return [
            self._t_n_o(*[self.params[f"u_3_{i}_m_o_b_{order_idx}"] for i in range(3)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_4_me_b(self) -> list[np.ndarray]:
        """The fourth-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain"""
        return [
            self._t_n_e(*[self.params[f"u_4_{i}_m_e_b_{order_idx}"] for i in range(5)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_4_mo_b(self) -> list[np.ndarray]:
        """The fourth-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain"""
        return [
            self._t_n_o(*[self.params[f"u_4_{i}_m_o_b_{order_idx}"] for i in range(3)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_me_b(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain"""
        return [
            self._t_5_me(*[self.params[f"u_5_{i}_m_e_b_{order_idx}"] for i in ("0", "1", "3", "5", "6")])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_mo_b(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain"""
        return [
            self._t_5_mo(*[self.params[f"u_5_{i}_m_o_b_{order_idx}"] for i in ("0", "2")])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_xe_b(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the even chalcogen orbitals under biaxial strain"""
        return [
            self._t_5_xr(*[self.params[f"u_5_{i}_x_e_b_{order_idx}"] for i in ("0", "2", "3", "5", "6")])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_xo_b(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the odd chalcogen orbitals under biaxial strain"""
        return [
            self._t_5_xr(*[self.params[f"u_5_{i}_x_o_b_{order_idx}"] for i in ("0", "2", "3", "5", "6")])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_me_b(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain"""
        return [
            self._t_m_me(*[self.params[f"u_6_{i}_m_e_b_{order_idx}"] for i in range(6)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_mo_b(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain"""
        return [
            self._t_m_mo(*[self.params[f"u_6_{i}_m_o_b_{order_idx}"] for i in range(3)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_xe_b(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the even chalcogen orbitals under biaxial strain"""
        return [
            self._t_m_xr(*[self.params[f"u_6_{i}_x_e_b_{order_idx}"] for i in range(6)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_xo_b(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the odd chalcogen orbitals under biaxial strain"""
        return [
            self._t_m_xr(*[self.params[f"u_6_{i}_x_o_b_{order_idx}"] for i in range(6)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_1_me_u(self) -> list[np.ndarray]:
        """The first-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain"""
        return [
            self._t_n_e(*[self.params[f"u_1_{i}_m_e_u_{order_idx}"] for i in range(5)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_1_mo_u(self) -> list[np.ndarray]:
        """The first-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain"""
        return [
            self._t_n_o(*[self.params[f"u_1_{i}_m_o_u_{order_idx}"] for i in range(3)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_me_u(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain"""
        return [
            self._t_m_me(*[self.params[f"u_2_{i}_m_e_u_{order_idx}"] for i in range(6)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_mo_u(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain"""
        return [
            self._t_m_mo(*[self.params[f"u_2_{i}_m_o_u_{order_idx}"] for i in range(3)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_xe_u(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the even chalcogen orbitals under uniaxial strain"""
        return [
            self._t_m_xr(*[self.params[f"u_2_{i}_x_e_u_{order_idx}"] for i in range(6)]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_xo_u(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the odd chalcogen orbitals under uniaxial strain"""
        return [
            self._t_m_xr(*[self.params[f"u_2_{i}_x_o_u_{order_idx}"] for i in range(6)]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_3_me_u(self) -> list[np.ndarray]:
        """The third-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain"""
        return [
            self._t_n_e(*[self.params[f"u_3_{i}_m_e_u_{order_idx}"] for i in range(5)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_3_mo_u(self) -> list[np.ndarray]:
        """The third-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain"""
        return [
            self._t_n_o(*[self.params[f"u_3_{i}_m_o_u_{order_idx}"] for i in range(3)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_4_me_u(self) -> list[np.ndarray]:
        """The fourth-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain"""
        return [
            self._t_n_e(*[self.params[f"u_4_{i}_m_e_u_{order_idx}"] for i in range(5)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_4_mo_u(self) -> list[np.ndarray]:
        """The fourth-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain"""
        return [
            self._t_n_o(*[self.params[f"u_4_{i}_m_o_u_{order_idx}"] for i in range(3)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_me_u(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain"""
        return [
            self._t_5_me(*[self.params[f"u_5_{i}_m_e_u_{order_idx}"] for i in ("0", "1", "3", "5", "6")])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_mo_u(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain"""
        return [
            self._t_5_mo(*[self.params[f"u_5_{i}_m_o_u_{order_idx}"] for i in ("0", "2")])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_xe_u(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the even chalcogen orbitals under uniaxial strain"""
        return [
            self._t_5_xr(*[self.params[f"u_5_{i}_x_e_u_{order_idx}"] for i in ("0", "2", "3", "5", "6")])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_xo_u(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the odd chalcogen orbitals under uniaxial strain"""
        return [
            self._t_5_xr(*[self.params[f"u_5_{i}_x_o_u_{order_idx}"] for i in ("0", "2", "3", "5", "6")])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_me_u(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain"""
        return [
            self._t_m_me(*[self.params[f"u_6_{i}_m_e_u_{order_idx}"] for i in range(6)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_mo_u(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain"""
        return [
            self._t_m_mo(*[self.params[f"u_6_{i}_m_o_u_{order_idx}"] for i in range(3)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_xe_u(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the even chalcogen orbitals under uniaxial strain"""
        return [
            self._t_m_xr(*[self.params[f"u_6_{i}_x_e_u_{order_idx}"] for i in range(6)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_xo_u(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the odd chalcogen orbitals under uniaxial strain"""
        return [
            self._t_m_xr(*[self.params[f"u_6_{i}_x_o_u_{order_idx}"] for i in range(6)])
            for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_1_me_s(self) -> list[np.ndarray]:
        """The first-nearest neighbour hopping matrix from the even metal orbitals under shear strain"""
        return [
            self._t_n_e_s(*[self.params[f"u_1_{i}_m_e_s_{order_idx}"] for i in range(5, 9)]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_1_mo_s(self) -> list[np.ndarray]:
        """The first-nearest neighbour hopping matrix from the odd metal orbitals under shear strain"""
        return [
            self._t_n_o_s(*[self.params[f"u_1_{i}_m_o_s_{order_idx}"] for i in range(3, 6)]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_me_s(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the even metal orbitals under shear strain"""
        return [
            self._t_m_me_s(*[self.params[f"u_2_{i}_m_e_s_{order_idx}"] for i in [1, 2, 4]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_mo_s(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the odd metal orbitals under shear strain"""
        return [
            self._t_m_mo_s(*[self.params[f"u_2_{i}_m_o_s_{order_idx}"] for i in [1]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_xe_s(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the even chalcogen orbitals under shear strain"""
        return [
            self._t_m_xr_s(*[self.params[f"u_2_{i}_x_e_s_{order_idx}"] for i in [1, 2, 4]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_2_xo_s(self) -> list[np.ndarray]:
        """The second-nearest neighbour hopping matrix from the odd chalcogen orbitals under shear strain"""
        return [
            self._t_m_xr_s(*[self.params[f"u_2_{i}_x_o_s_{order_idx}"] for i in [1, 2, 4]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_3_me_s(self) -> list[np.ndarray]:
        """The third-nearest neighbour hopping matrix from the even metal orbitals under shear strain"""
        return [
            self._t_n_e_s(*[self.params[f"u_3_{i}_m_e_s_{order_idx}"] for i in range(5, 9)]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_3_mo_s(self) -> list[np.ndarray]:
        """The third-nearest neighbour hopping matrix from the odd metal orbitals under shear strain"""
        return [
            self._t_n_o_s(*[self.params[f"u_3_{i}_m_o_s_{order_idx}"] for i in range(3, 6)]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_4_me_s(self) -> list[np.ndarray]:
        """The fourth-nearest neighbour hopping matrix from the even metal orbitals under shear strain"""
        return [
            self._t_n_e_s(*[self.params[f"u_4_{i}_m_e_s_{order_idx}"] for i in range(5, 9)]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_4_mo_s(self) -> list[np.ndarray]:
        """The fourth-nearest neighbour hopping matrix from the odd metal orbitals under shear strain"""
        return [
            self._t_n_o_s(*[self.params[f"u_4_{i}_m_o_s_{order_idx}"] for i in range(3, 6)]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_me_s(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the even metal orbitals under shear strain"""
        return [
            self._t_5_me_s(*[self.params[f"u_5_{i}_m_e_s_{order_idx}"] for i in [2, 4, 7, 8]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_mo_s(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the odd metal orbitals under shear strain"""
        return [
            self._t_5_mo_s(*[self.params[f"u_5_{i}_m_o_s_{order_idx}"] for i in [1, 3]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_xe_s(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the even chalcogen orbitals under shear strain"""
        return [
            self._t_5_xr_s(*[self.params[f"u_5_{i}_x_e_s_{order_idx}"] for i in [1, 4, 7, 8]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_5_xo_s(self) -> list[np.ndarray]:
        """The fifth-nearest neighbour hopping matrix from the odd chalcogen orbitals under shear strain"""
        return [
            self._t_5_xr_s(*[self.params[f"u_5_{i}_x_o_s_{order_idx}"] for i in [1, 4, 7, 8]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_me_s(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the even metal orbitals under shear strain"""
        return [
            self._t_m_me_s(*[self.params[f"u_6_{i}_m_e_s_{order_idx}"] for i in [1, 2, 4]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_mo_s(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the odd metal orbitals under shear strain"""
        return [
            self._t_m_mo_s(*[self.params[f"u_6_{i}_m_o_s_{order_idx}"] for i in [1]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_xe_s(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the even chalcogen orbitals under shear strain"""
        return [
            self._t_m_xr_s(*[self.params[f"u_6_{i}_x_e_s_{order_idx}"] for i in [1, 2, 4]]
            ) for order_idx in range(1, self.params.max_order+1)]

    @property
    def t_6_xo_s(self) -> list[np.ndarray]:
        """The sixth-nearest neighbour hopping matrix from the odd chalcogen orbitals under shear strain"""
        return [
            self._t_m_xr_s(*[self.params[f"u_6_{i}_x_o_s_{order_idx}"] for i in [1, 2, 4]]
            ) for order_idx in range(1, self.params.max_order+1)]

e_me_b: list[np.ndarray] property

The hopping matrix for the even metal orbitals under biaxial strain

e_me_s: list[np.ndarray] property

The hopping matrix for the even metal orbitals under shear strain

e_me_u: list[np.ndarray] property

The hopping matrix for the even metal orbitals under uniaxial strain

e_mo_b: list[np.ndarray] property

The hopping matrix for the odd metal orbitals under biaxial strain

e_mo_s: list[np.ndarray] property

The hopping matrix for the odd metal orbitals under shear strain

e_mo_u: list[np.ndarray] property

The hopping matrix for the odd metal orbitals under uniaxial strain

e_xe_b: list[np.ndarray] property

The hopping matrix for the even chalcogen orbitals under biaxial strain

e_xe_s: list[np.ndarray] property

The hopping matrix for the even chalcogen orbitals under shear strain

e_xe_u: list[np.ndarray] property

The hopping matrix for the even chalcogen orbitals under uniaxial strain

e_xo_b: list[np.ndarray] property

The hopping matrix for the odd chalcogen orbitals under biaxial strain

e_xo_s: list[np.ndarray] property

The hopping matrix for the odd chalcogen orbitals under shear strain

e_xo_u: list[np.ndarray] property

The hopping matrix for the odd chalcogen orbitals under uniaxial strain

t_1_me_b: list[np.ndarray] property

The first-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain

t_1_me_s: list[np.ndarray] property

The first-nearest neighbour hopping matrix from the even metal orbitals under shear strain

t_1_me_u: list[np.ndarray] property

The first-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain

t_1_mo_b: list[np.ndarray] property

The first-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain

t_1_mo_s: list[np.ndarray] property

The first-nearest neighbour hopping matrix from the odd metal orbitals under shear strain

t_1_mo_u: list[np.ndarray] property

The first-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain

t_2_me_b: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain

t_2_me_s: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the even metal orbitals under shear strain

t_2_me_u: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain

t_2_mo_b: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain

t_2_mo_s: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the odd metal orbitals under shear strain

t_2_mo_u: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain

t_2_xe_b: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the even chalcogen orbitals under biaxial strain

t_2_xe_s: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the even chalcogen orbitals under shear strain

t_2_xe_u: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the even chalcogen orbitals under uniaxial strain

t_2_xo_b: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the odd chalcogen orbitals under biaxial strain

t_2_xo_s: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the odd chalcogen orbitals under shear strain

t_2_xo_u: list[np.ndarray] property

The second-nearest neighbour hopping matrix from the odd chalcogen orbitals under uniaxial strain

t_3_me_b: list[np.ndarray] property

The third-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain

t_3_me_s: list[np.ndarray] property

The third-nearest neighbour hopping matrix from the even metal orbitals under shear strain

t_3_me_u: list[np.ndarray] property

The third-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain

t_3_mo_b: list[np.ndarray] property

The third-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain

t_3_mo_s: list[np.ndarray] property

The third-nearest neighbour hopping matrix from the odd metal orbitals under shear strain

t_3_mo_u: list[np.ndarray] property

The third-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain

t_4_me_b: list[np.ndarray] property

The fourth-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain

t_4_me_s: list[np.ndarray] property

The fourth-nearest neighbour hopping matrix from the even metal orbitals under shear strain

t_4_me_u: list[np.ndarray] property

The fourth-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain

t_4_mo_b: list[np.ndarray] property

The fourth-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain

t_4_mo_s: list[np.ndarray] property

The fourth-nearest neighbour hopping matrix from the odd metal orbitals under shear strain

t_4_mo_u: list[np.ndarray] property

The fourth-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain

t_5_me_b: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain

t_5_me_s: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the even metal orbitals under shear strain

t_5_me_u: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain

t_5_mo_b: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain

t_5_mo_s: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the odd metal orbitals under shear strain

t_5_mo_u: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain

t_5_xe_b: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the even chalcogen orbitals under biaxial strain

t_5_xe_s: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the even chalcogen orbitals under shear strain

t_5_xe_u: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the even chalcogen orbitals under uniaxial strain

t_5_xo_b: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the odd chalcogen orbitals under biaxial strain

t_5_xo_s: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the odd chalcogen orbitals under shear strain

t_5_xo_u: list[np.ndarray] property

The fifth-nearest neighbour hopping matrix from the odd chalcogen orbitals under uniaxial strain

t_6_me_b: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the even metal orbitals under biaxial strain

t_6_me_s: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the even metal orbitals under shear strain

t_6_me_u: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the even metal orbitals under uniaxial strain

t_6_mo_b: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the odd metal orbitals under biaxial strain

t_6_mo_s: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the odd metal orbitals under shear strain

t_6_mo_u: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the odd metal orbitals under uniaxial strain

t_6_xe_b: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the even chalcogen orbitals under biaxial strain

t_6_xe_s: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the even chalcogen orbitals under shear strain

t_6_xe_u: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the even chalcogen orbitals under uniaxial strain

t_6_xo_b: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the odd chalcogen orbitals under biaxial strain

t_6_xo_s: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the odd chalcogen orbitals under shear strain

t_6_xo_u: list[np.ndarray] property

The sixth-nearest neighbour hopping matrix from the odd chalcogen orbitals under uniaxial strain

__init__(params)

Initialize the strained TMD hopping matrices

Parameters:

Name Type Description Default
params StrainParametersList

The parameters for the strained TMD lattice.

required
Source code in tmdybinding/tmd_strain.py
def __init__(self, params: StrainParametersList):
    """Initialize the strained TMD hopping matrices

    Parameters:
        params (StrainParametersList): The parameters for the strained TMD lattice."""
    super().__init__(params)
    self.params: StrainParametersList = params

VariableStorage

Class for saving the matrices and variables in the AbstractLattice-class. There are also checks for a consistent model, where the sizes of the matrices, the included hoppings and the onsite matrices are checked.

Source code in tmdybinding/tmd_abstract_lattice.py
class VariableStorage:
    """
    Class for saving the matrices and variables in the AbstractLattice-class.
    There are also checks for a consistent model, where the sizes of the matrices, the included hoppings and the onsite
    matrices are checked.
    """

    def __init__(self, params_dict: Optional[dict] = None):
        """Make a VariableStorage object with the given parameters. If no parameters are given, the parameters are None.

        Parameters:
            params_dict (Optional[dict]): The parameters for the lattice model.
                The dictionary entries must be in the format `"name": parameter`.
                The possible parameters are `"h_0_m"`, `"h_0_c"`, `"h_1_m"`, `"h_2_m"`, `"h_2_c"`, `"h_3_m"`, `"h_4_m"`,
                `"h_5_m"`, `"h_5_c"`, `"h_6_m"`, `"h_6_c"`, `"a"`, `"lamb_m"` and `"lamb_c"`.
        """
        self.__h_0_m = None
        self.__h_0_c = None
        self.__h_1_m = None
        self.__h_2_m = None
        self.__h_2_c = None
        self.__h_3_m = None
        self.__h_4_m = None
        self.__h_5_m = None
        self.__h_5_c = None
        self.__h_6_m = None
        self.__h_6_c = None
        self.__a = None
        self.__lamb_m = None
        self.__lamb_c = None
        self.__keys = [
            "h_0_m", "h_0_c",
            "h_1_m",
            "h_2_m", "h_2_c",
            "h_3_m",
            "h_4_m",
            "h_5_m", "h_5_c",
            "h_6_m", "h_6_c",
            "a", "lamb_m", "lamb_c"
        ]
        if params_dict is not None:
            self.set_params(params_dict)

    @staticmethod
    def _params_check(params_dict: dict, param_name: str) -> Optional[np.ndarray]:
        if param_name in params_dict.keys():
            if params_dict[param_name] is not None:
                return np.array(params_dict[param_name])
        return None

    def set_params(self, params_dict: dict, keep: bool = True):
        """Set the parameters for the lattice model.

        Parameters:
            params_dict (dict): The parameters for the lattice model.
                The dictionary entries must be in the format `"name": parameter`.
                The possible parameters are `"h_0_m"`, `"h_0_c"`, `"h_1_m"`, `"h_2_m"`, `"h_2_c"`, `"h_3_m"`, `"h_4_m"`,
                `"h_5_m"`, `"h_5_c"`, `"h_6_m"`, `"h_6_c"`, `"a"`, `"lamb_m"` and `"lamb_c"`.
            keep (bool): If True, the parameters that are not included in the `param_dict`are kept as they are.
                If False, the parameters that are not given are set to None.
        """
        params = self.to_dict() if keep else {}
        for name in params_dict.keys():
            assert str(name) in self.__keys, f"key {name} not in expected hoppings, possible wrong name"
            params[name] = params_dict[name]
        self._component_check(params)
        self._shape_check(params)
        self.__h_0_m = self._params_check(params, "h_0_m")
        self.__h_0_c = self._params_check(params, "h_0_c")
        self.__h_1_m = self._params_check(params, "h_1_m")
        self.__h_2_m = self._params_check(params, "h_2_m")
        self.__h_2_c = self._params_check(params, "h_2_c")
        self.__h_3_m = self._params_check(params, "h_3_m")
        self.__h_4_m = self._params_check(params, "h_4_m")
        self.__h_5_m = self._params_check(params, "h_5_m")
        self.__h_5_c = self._params_check(params, "h_5_c")
        self.__h_6_m = self._params_check(params, "h_6_m")
        self.__h_6_c = self._params_check(params, "h_6_c")
        self.__a = self._params_check(params, "a")
        self.__lamb_m = self._params_check(params, "lamb_m")
        self.__lamb_c = self._params_check(params, "lamb_c")

    def _make_bools(self, params_dict: dict):
        return [self._attr_check(name, params_dict) for name in self.__keys]

    def _component_check(self, params_dict: dict):
        (m_bool, c_bool,
         h_1_m_bool,
         h_2_m_bool, h_2_c_bool,
         h_3_m_bool,
         h_4_m_bool,
         h_5_m_bool, h_5_c_bool,
         h_6_m_bool, h_6_c_bool) = self._make_bools(params_dict)[:-3]
        assert m_bool or c_bool, "not X nor M in model"
        assert not (not m_bool and h_1_m_bool), "not M in model and 1st hopping from M"
        assert not (not c_bool and h_1_m_bool), "not M in model and 1st hopping to X"
        assert not (not m_bool and h_2_m_bool), "not M in model and 2nd hopping from/to M"
        assert not (not c_bool and h_2_c_bool), "not M in model and 2nd hopping from/to X"
        assert not (not m_bool and h_3_m_bool), "not M in model and 3rd hopping from M"
        assert not (not c_bool and h_3_m_bool), "not M in model and 3rd hopping to X"
        assert not (not m_bool and h_4_m_bool), "not M in model and 4rd hopping from M"
        assert not (not c_bool and h_4_m_bool), "not M in model and 4rd hopping to X"
        assert not (not m_bool and h_5_m_bool), "not M in model and 5th hopping from/to M"
        assert not (not c_bool and h_5_c_bool), "not M in model and 5th hopping from/to X"
        assert not (not m_bool and h_6_m_bool), "not M in model and 6th hopping from/to M"
        assert not (not c_bool and h_6_c_bool), "not M in model and 6th hopping from/to X"
        assert h_1_m_bool or h_2_c_bool or h_2_m_bool or h_3_m_bool or h_4_m_bool or h_5_c_bool or h_5_m_bool or \
               h_6_c_bool or h_6_m_bool, "no hoppings specified in the model"

    def _shape_check(self, params_dict: dict):
        (m_bool, c_bool,
         h_1_m_bool,
         h_2_m_bool, h_2_c_bool,
         h_3_m_bool,
         h_4_m_bool,
         h_5_m_bool, h_5_c_bool,
         h_6_m_bool, h_6_c_bool) = self._make_bools(params_dict)[:-3]
        if m_bool:
            m_shape = self._check_shape(params_dict["h_0_m"])
            if h_1_m_bool:
                assert np.shape(params_dict["h_1_m"])[1] == m_shape, "shape 1st hopping from M not correct"
            if h_2_m_bool:
                assert np.shape(params_dict["h_2_m"])[0] == m_shape, "shape 2nd hopping to M not correct"
                assert np.shape(params_dict["h_2_m"])[1] == m_shape, "shape 2nd hopping from M not correct"
            if h_3_m_bool:
                assert np.shape(params_dict["h_3_m"])[1] == m_shape, "shape 3rd hopping from M not correct"
            if h_4_m_bool:
                assert np.shape(params_dict["h_4_m"])[1] == m_shape, "shape 4rd hopping from M not correct"
            if h_5_m_bool:
                assert np.shape(params_dict["h_5_m"])[0] == m_shape, "shape 5th hopping to M not correct"
                assert np.shape(params_dict["h_5_m"])[1] == m_shape, "shape 5th hopping from M not correct"
            if h_6_m_bool:
                assert np.shape(params_dict["h_6_m"])[0] == m_shape, "shape 6th hopping to M not correct"
                assert np.shape(params_dict["h_6_m"])[1] == m_shape, "shape 6th hopping from M not correct"
        if c_bool:
            c_shape = self._check_shape(params_dict["h_0_c"])
            if h_1_m_bool:
                assert np.shape(params_dict["h_1_m"])[0] == c_shape, "shape 1st hopping to X not correct"
            if h_2_c_bool:
                assert np.shape(params_dict["h_2_c"])[0] == c_shape, "shape 2nd hopping to X not correct"
                assert np.shape(params_dict["h_2_c"])[1] == c_shape
            if h_3_m_bool:
                assert np.shape(params_dict["h_3_m"])[0] == c_shape, "shape 3rd hopping to X not correct"
            if h_4_m_bool:
                assert np.shape(params_dict["h_4_m"])[0] == c_shape, "shape 4rd hopping to X not correct"
            if h_5_c_bool:
                assert np.shape(params_dict["h_5_c"])[0] == c_shape, "shape 5th hopping to X not correct"
                assert np.shape(params_dict["h_5_c"])[1] == c_shape, "shape 5th hopping from X not correct"
            if h_6_c_bool:
                assert np.shape(params_dict["h_6_c"])[0] == c_shape, "shape 6th hopping to X not correct"
                assert np.shape(params_dict["h_6_c"])[1] == c_shape, "shape 6th hopping from X not correct"

    @staticmethod
    def _attr_check(name, params_dict: dict):
        if name in params_dict.keys():
            return params_dict[name] is not None
        else:
            return False

    @staticmethod
    def _check_shape(h_0):
        h_0_shape = np.shape(h_0)
        assert len(h_0_shape) < 3, "onsite energy too many dims (max 2 as matrix)"
        if len(h_0_shape) == 2:
            assert h_0_shape[0] == h_0_shape[1] or h_0_shape[0] == 1, "shape of x and y not the same for onsite energy"
            return h_0_shape[1]
        else:
            return h_0_shape[0]

    def to_dict(self) -> dict:
        """Return the parameters as a dictionary in the format `"name": parameter`."""
        dict_list = []
        for name in self.__keys:
            value = getattr(self, name)
            if value is not None:
                dict_list.append((name, value))
        return dict(dict_list)

    @property
    def h_0_m(self) -> np.ndarray:
        """The onsite energy for the metal atom."""
        return self.__h_0_m

    @h_0_m.setter
    def h_0_m(self, value: np.ndarray):
        self.set_params({"h_0_m": value})

    @property
    def h_0_c(self) -> np.ndarray:
        """The onsite energy for the chalcogen atom."""
        return self.__h_0_c

    @h_0_c.setter
    def h_0_c(self, value: np.ndarray):
        self.set_params({"h_0_c": value})

    @property
    def h_1_m(self) -> np.ndarray:
        """The first nearest neighbour hopping from the metal atom."""
        return self.__h_1_m

    @h_1_m.setter
    def h_1_m(self, value: np.ndarray):
        self.set_params({"h_1_m": value})

    @property
    def h_2_m(self) -> np.ndarray:
        """The second-nearest neighbour hopping from the metal atom."""
        return self.__h_2_m

    @h_2_m.setter
    def h_2_m(self, value: np.ndarray):
        self.set_params({"h_2_m": value})

    @property
    def h_2_c(self) -> np.ndarray:
        """The second-nearest neighbour hopping from the chalcogen atom."""
        return self.__h_2_c

    @h_2_c.setter
    def h_2_c(self, value: np.ndarray):
        self.set_params({"h_2_c": value})

    @property
    def h_3_m(self) -> np.ndarray:
        """The third-nearest neighbour hopping from the metal atom."""
        return self.__h_3_m

    @h_3_m.setter
    def h_3_m(self, value: np.ndarray):
        self.set_params({"h_3_m": value})

    @property
    def h_4_m(self) -> np.ndarray:
        """The fourth-nearest neighbour hopping from the metal atom."""
        return self.__h_4_m

    @h_4_m.setter
    def h_4_m(self, value: np.ndarray):
        self.set_params({"h_4_m": value})

    @property
    def h_5_m(self) -> np.ndarray:
        """The fifth-nearest neighbour hopping from the metal atom."""
        return self.__h_5_m

    @h_5_m.setter
    def h_5_m(self, value: np.ndarray):
        self.set_params({"h_5_m": value})

    @property
    def h_5_c(self) -> np.ndarray:
        """The fifth-nearest neighbour hopping from the chalcogen atom."""
        return self.__h_5_c

    @h_5_c.setter
    def h_5_c(self, value: np.ndarray):
        self.set_params({"h_5_c": value})

    @property
    def h_6_m(self) -> np.ndarray:
        """The sixth-nearest neighbour hopping from the metal atom."""
        return self.__h_6_m

    @h_6_m.setter
    def h_6_m(self, value: np.ndarray):
        self.set_params({"h_6_m": value})

    @property
    def h_6_c(self) -> np.ndarray:
        """The sixth-nearest neighbour hopping from the chalcogen atom."""
        return self.__h_6_c

    @h_6_c.setter
    def h_6_c(self, value: np.ndarray):
        self.set_params({"h_6_c": value})

    @property
    def a(self) -> float:
        """The lattice constant."""
        return self.__a

    @a.setter
    def a(self, value: float):
        self.set_params({"a": value})

    @property
    def lamb_m(self) -> float:
        """The spin-orbit coupling for the metal atom."""
        return self.__lamb_m

    @lamb_m.setter
    def lamb_m(self, value: float):
        self.set_params({"lamb_m": value})

    @property
    def lamb_c(self) -> float:
        """The spin-orbit coupling for the chalcogen atom."""
        return self.__lamb_c

    @lamb_c.setter
    def lamb_c(self, value: float):
        self.set_params({"lamb_c": value})

a: float property writable

The lattice constant.

h_0_c: np.ndarray property writable

The onsite energy for the chalcogen atom.

h_0_m: np.ndarray property writable

The onsite energy for the metal atom.

h_1_m: np.ndarray property writable

The first nearest neighbour hopping from the metal atom.

h_2_c: np.ndarray property writable

The second-nearest neighbour hopping from the chalcogen atom.

h_2_m: np.ndarray property writable

The second-nearest neighbour hopping from the metal atom.

h_3_m: np.ndarray property writable

The third-nearest neighbour hopping from the metal atom.

h_4_m: np.ndarray property writable

The fourth-nearest neighbour hopping from the metal atom.

h_5_c: np.ndarray property writable

The fifth-nearest neighbour hopping from the chalcogen atom.

h_5_m: np.ndarray property writable

The fifth-nearest neighbour hopping from the metal atom.

h_6_c: np.ndarray property writable

The sixth-nearest neighbour hopping from the chalcogen atom.

h_6_m: np.ndarray property writable

The sixth-nearest neighbour hopping from the metal atom.

lamb_c: float property writable

The spin-orbit coupling for the chalcogen atom.

lamb_m: float property writable

The spin-orbit coupling for the metal atom.

__init__(params_dict=None)

Make a VariableStorage object with the given parameters. If no parameters are given, the parameters are None.

Parameters:

Name Type Description Default
params_dict Optional[dict]

The parameters for the lattice model. The dictionary entries must be in the format "name": parameter. The possible parameters are "h_0_m", "h_0_c", "h_1_m", "h_2_m", "h_2_c", "h_3_m", "h_4_m", "h_5_m", "h_5_c", "h_6_m", "h_6_c", "a", "lamb_m" and "lamb_c".

None
Source code in tmdybinding/tmd_abstract_lattice.py
def __init__(self, params_dict: Optional[dict] = None):
    """Make a VariableStorage object with the given parameters. If no parameters are given, the parameters are None.

    Parameters:
        params_dict (Optional[dict]): The parameters for the lattice model.
            The dictionary entries must be in the format `"name": parameter`.
            The possible parameters are `"h_0_m"`, `"h_0_c"`, `"h_1_m"`, `"h_2_m"`, `"h_2_c"`, `"h_3_m"`, `"h_4_m"`,
            `"h_5_m"`, `"h_5_c"`, `"h_6_m"`, `"h_6_c"`, `"a"`, `"lamb_m"` and `"lamb_c"`.
    """
    self.__h_0_m = None
    self.__h_0_c = None
    self.__h_1_m = None
    self.__h_2_m = None
    self.__h_2_c = None
    self.__h_3_m = None
    self.__h_4_m = None
    self.__h_5_m = None
    self.__h_5_c = None
    self.__h_6_m = None
    self.__h_6_c = None
    self.__a = None
    self.__lamb_m = None
    self.__lamb_c = None
    self.__keys = [
        "h_0_m", "h_0_c",
        "h_1_m",
        "h_2_m", "h_2_c",
        "h_3_m",
        "h_4_m",
        "h_5_m", "h_5_c",
        "h_6_m", "h_6_c",
        "a", "lamb_m", "lamb_c"
    ]
    if params_dict is not None:
        self.set_params(params_dict)

set_params(params_dict, keep=True)

Set the parameters for the lattice model.

Parameters:

Name Type Description Default
params_dict dict

The parameters for the lattice model. The dictionary entries must be in the format "name": parameter. The possible parameters are "h_0_m", "h_0_c", "h_1_m", "h_2_m", "h_2_c", "h_3_m", "h_4_m", "h_5_m", "h_5_c", "h_6_m", "h_6_c", "a", "lamb_m" and "lamb_c".

required
keep bool

If True, the parameters that are not included in the param_dictare kept as they are. If False, the parameters that are not given are set to None.

True
Source code in tmdybinding/tmd_abstract_lattice.py
def set_params(self, params_dict: dict, keep: bool = True):
    """Set the parameters for the lattice model.

    Parameters:
        params_dict (dict): The parameters for the lattice model.
            The dictionary entries must be in the format `"name": parameter`.
            The possible parameters are `"h_0_m"`, `"h_0_c"`, `"h_1_m"`, `"h_2_m"`, `"h_2_c"`, `"h_3_m"`, `"h_4_m"`,
            `"h_5_m"`, `"h_5_c"`, `"h_6_m"`, `"h_6_c"`, `"a"`, `"lamb_m"` and `"lamb_c"`.
        keep (bool): If True, the parameters that are not included in the `param_dict`are kept as they are.
            If False, the parameters that are not given are set to None.
    """
    params = self.to_dict() if keep else {}
    for name in params_dict.keys():
        assert str(name) in self.__keys, f"key {name} not in expected hoppings, possible wrong name"
        params[name] = params_dict[name]
    self._component_check(params)
    self._shape_check(params)
    self.__h_0_m = self._params_check(params, "h_0_m")
    self.__h_0_c = self._params_check(params, "h_0_c")
    self.__h_1_m = self._params_check(params, "h_1_m")
    self.__h_2_m = self._params_check(params, "h_2_m")
    self.__h_2_c = self._params_check(params, "h_2_c")
    self.__h_3_m = self._params_check(params, "h_3_m")
    self.__h_4_m = self._params_check(params, "h_4_m")
    self.__h_5_m = self._params_check(params, "h_5_m")
    self.__h_5_c = self._params_check(params, "h_5_c")
    self.__h_6_m = self._params_check(params, "h_6_m")
    self.__h_6_c = self._params_check(params, "h_6_c")
    self.__a = self._params_check(params, "a")
    self.__lamb_m = self._params_check(params, "lamb_m")
    self.__lamb_c = self._params_check(params, "lamb_c")

to_dict()

Return the parameters as a dictionary in the format "name": parameter.

Source code in tmdybinding/tmd_abstract_lattice.py
def to_dict(self) -> dict:
    """Return the parameters as a dictionary in the format `"name": parameter`."""
    dict_list = []
    for name in self.__keys:
        value = getattr(self, name)
        if value is not None:
            dict_list.append((name, value))
    return dict(dict_list)

tests()

Run the package tests.

Source code in tmdybinding/__init__.py
def tests():
    """Run the package tests."""
    import pytest
    import pathlib
    import os
    from pybinding.utils.misc import cd
    import pybinding as pb

    module_path = pathlib.Path(__file__).parent

    args = []
    if (module_path / 'tests').exists():
        # tests are inside installed package -> use read-only mode
        args.append('--failpath=' + os.getcwd() + '/failed')
        with cd(module_path):
            args += ['-c', str(module_path / 'tests/local.cfg'), str(module_path)]
            error_code = pytest.main(args)
    else:
        # tests are in dev environment -> use development mode
        with cd(module_path.parent):
            error_code = pytest.main(args)

    return error_code or None