Calculate all the properties w.r.t. the doping levels in input.

        Args:
            doping: numpy array specifing the doping levels

        When executed, it add the following variable at the BztTransportProperties
        object:
            Conductivity_doping, Seebeck_doping, Kappa_doping, Power_Factor_doping,
            cond_Effective_mass_doping are dictionaries with 'n' and 'p' keys and
            arrays of dim (len(temp_r),len(doping),3,3) as values
        doping_carriers: number of carriers for each doping level
        mu_doping_eV: the chemical potential corrispondent to each doping level

def compute_properties_doping(self, doping, temp_r=None):
        """
        Calculate all the properties w.r.t. the doping levels in input.

        Args:
            doping: numpy array specifing the doping levels

        When executed, it add the following variable at the BztTransportProperties
        object:
            Conductivity_doping, Seebeck_doping, Kappa_doping, Power_Factor_doping,
            cond_Effective_mass_doping are dictionaries with 'n' and 'p' keys and
            arrays of dim (len(temp_r),len(doping),3,3) as values
        doping_carriers: number of carriers for each doping level
        mu_doping_eV: the chemical potential corrispondent to each doping level
        """

        if temp_r is None:
            temp_r = self.temp_r

        self.Conductivity_doping, self.Seebeck_doping, self.Kappa_doping = {}, {}, {}
        # self.Hall_doping = {}

        self.Power_Factor_doping, self.Effective_mass_doping = {}, {}

        mu_doping = {}
        doping_carriers = [dop * (self.volume / (units.Meter / 100.) ** 3) for dop in doping]

        for dop_type in ['n', 'p']:
            sbk = np.zeros((len(temp_r), len(doping), 3, 3))
            cond = np.zeros((len(temp_r), len(doping), 3, 3))
            kappa = np.zeros((len(temp_r), len(doping), 3, 3))
            hall = np.zeros((len(temp_r), len(doping), 3, 3, 3))
            if dop_type == 'p':
                doping_carriers = [-dop for dop in doping_carriers]

            mu_doping[dop_type] = np.zeros((len(temp_r), len(doping)))
            for t, temp in enumerate(temp_r):
                for i, dop_car in enumerate(doping_carriers):
                    mu_doping[dop_type][t, i] = self.find_mu_doping(self.epsilon, self.dos, self.nelect + dop_car, temp,
                                                                    self.dosweight)

                N, L0, L1, L2, Lm11 = BL.fermiintegrals(self.epsilon, self.dos, self.vvdos, mur=mu_doping[dop_type][t],
                                                        Tr=np.array([temp]), dosweight=self.dosweight)
                cond[t], sbk[t], kappa[t], hall[t] = BL.calc_Onsager_coefficients(L0, L1, L2, mu_doping[dop_type][t],
                                                                                  np.array([temp]), self.volume, Lm11)

            self.Conductivity_doping[dop_type] = cond * self.CRTA  # S / m
            self.Seebeck_doping[dop_type] = sbk * 1e6  # microVolt / K
            self.Kappa_doping[dop_type] = kappa * self.CRTA  # W / (m K)
            # self.Hall_doping[dop_type] = hall

            self.Power_Factor_doping[dop_type] = (sbk @ sbk) @ cond * self.CRTA * 1e3

            cond_eff_mass = np.zeros((len(temp_r), len(doping), 3, 3))
            for t in range(len(temp_r)):
                for i, dop in enumerate(doping):
                    try:
                        cond_eff_mass[t, i] = np.linalg.inv(cond[t, i]) * dop * units.qe_SI ** 2 / units.me_SI * 1e6
                    except np.linalg.LinAlgError:
                        pass

            self.Effective_mass_doping[dop_type] = cond_eff_mass

        self.doping_carriers = doping_carriers
        self.doping = doping
        self.mu_doping = mu_doping
        self.mu_doping_eV = {k: v / units.eV - self.efermi for k, v in mu_doping.items()}