Example #1
0
    def equilibrium_f(self, temperature, semiconductor, fermi_level_from_conduction_band,
                      electron_volts=False, use_mpmath=False, debug=False):
        """
        Calculates trap equilibrium filling for given Fermi level position
        :param temperature: Temperature, K
        :param semiconductor: Semiconductor object
        :param fermi_level_from_conduction_band: distance from Conduction band to Fermi level
        :param electron_volts: if True assume all energy values to be in eV
        :param use_mpmath: if True integration is done using mpmath.quad function instead of numpy.trapz (default)
        :param debug: if True prints out some debug information
        :return: equilibrium f between 0 and 1
        """
        if electron_volts:
            energy_coefficient = to_numeric(q)
            energy_unit = 'eV'
        else:
            energy_coefficient = 1
            energy_unit = 'J'
        energy_scale = to_numeric(k * temperature) / energy_coefficient
        conduction_band = 0
        fermi_level = conduction_band - fermi_level_from_conduction_band
        trap_energy_level = self.energy_level(temperature, semiconductor, charge_state_idx=0,
                                              electron_volts=electron_volts)
        if debug:
            print 'Et = %2.2g ' % ((conduction_band - trap_energy_level)) + energy_unit
            print 'Ef =', fermi_level, energy_unit
        g_ratio = self.charge_states[0][2] / self.charge_states[1][2]

        if self.energy_distribution_function in energy_distribution_functions['Single Level']:
            fermi_level_grid, = np.meshgrid(fermi_level)
            exp_arg = (np.float(conduction_band - trap_energy_level) - fermi_level_grid) / energy_scale
            exp_term = np.exp(exp_arg)
            f = 1 / (1 + g_ratio * exp_term)
        else:
            energy = sym.symbols('E')
            energy_distribution = self.energy_distribution.subs([('Et', trap_energy_level * energy_coefficient),
                                                                 ('Ecb', conduction_band * energy_coefficient)])
            energy_distribution = energy_distribution.subs(q, to_numeric(q))
            if not use_mpmath:
                if debug:
                    print 'Numeric integration (numpy.trapz)'
                energy_range = centered_linspace(conduction_band - trap_energy_level,
                                                 10 * to_numeric(self.energy_spread) / energy_coefficient,
                                                 to_numeric(self.energy_spread) / energy_coefficient / 1000)
                energy_range_grid, fermi_level_grid = np.meshgrid(energy_range, fermi_level)
                fermi_function = 1 / (1 + g_ratio * np.exp((energy_range_grid - fermi_level_grid) / energy_scale))
                energy_distribution_function = sym.lambdify(energy, energy_distribution, 'numpy')
                integrand_array = energy_distribution_function(energy_range_grid * energy_coefficient) * fermi_function
                f = np.trapz(integrand_array, energy_range_grid * energy_coefficient, axis=1)
            else:
                if debug:
                    print 'Numeric integration (mpmath.quad)'
                fermi_level_grid, = np.meshgrid(fermi_level)
                f = np.zeros_like(fermi_level_grid)
                for i, fermi_level_i in enumerate(fermi_level_grid):
                    fermi_function = fermi(energy, fermi_level_i * energy_coefficient, temperature, g_ratio)
                    fermi_function = fermi_function.subs(k, to_numeric(k))
                    integrand = sym.lambdify(energy, energy_distribution * fermi_function)
                    f[i] = mp.quad(integrand,
                                   [to_numeric(energy_coefficient * (conduction_band - trap_energy_level)
                                               - 10 * self.energy_spread),
                                    to_numeric(energy_coefficient * (conduction_band - trap_energy_level)
                                               - 0.5 * self.energy_spread),
                                    to_numeric(energy_coefficient * (conduction_band - trap_energy_level)
                                               + 0.5 * self.energy_spread),
                                    to_numeric(energy_coefficient * (conduction_band - trap_energy_level)
                                               + 10 * self.energy_spread)])
        if debug:
            print 'F =', f
        if f.size == 1:
            f = f[0]
        return f
Example #2
0
    def emission_rate(self,
                      temperature,
                      semiconductor,
                      f,
                      poole_frenkel_e=None,
                      poole_frenkel_h=None,
                      barrier_lowering_e=None,
                      barrier_lowering_h=None,
                      use_mpmath=False,
                      debug=False):
        """
        Calculate carriers emission rate for bot electrons and holes
        :param temperature: Temperature, K
        :param semiconductor: Semiconductor object
        :param f: Trap occupation from 0.0 to 1.0
        :param poole_frenkel_e: emission rate boost due to Poole-Frenkel effect for electron
        :param poole_frenkel_h: emission rate boost due to Poole-Frenkel effect for electron
        :param barrier_lowering_e: lowering of activation energy for electrons
        :param barrier_lowering_h: lowering of activation energy for holes
        :param use_mpmath: if True integration is done using mpmath.quad function instead of numpy.trapz (default)
        :param debug: if True prints out some debug information
        :return: emission_e, emission_h
        """
        if barrier_lowering_e is None:
            barrier_lowering_e = np.zeros_like(f, dtype=np.float)
        if barrier_lowering_h is None:
            barrier_lowering_h = np.zeros_like(f, dtype=np.float)
        if poole_frenkel_e is None:
            poole_frenkel_e = np.ones_like(f, dtype=np.float)
        if poole_frenkel_h is None:
            poole_frenkel_h = np.ones_like(f, dtype=np.float)
        energy_scale = to_numeric(k * temperature)
        conduction_band = 0
        band_gap = semiconductor.band_gap(temperature,
                                          symbolic=False,
                                          electron_volts=False)
        valence_band = conduction_band - band_gap
        trap_energy_level_e = np.float(
            self.energy_level(temperature,
                              semiconductor,
                              charge_state_idx=1,
                              electron_volts=False))
        trap_energy_level_h = np.float(
            self.energy_level(temperature,
                              semiconductor,
                              charge_state_idx=0,
                              electron_volts=False))
        trap_energy_level_e_positive = conduction_band - trap_energy_level_e
        trap_energy_level_h_positive = conduction_band - trap_energy_level_h

        g_ratio_e = self.charge_states[0][2] / self.charge_states[1][2]
        g_ratio_h = self.charge_states[1][2] / self.charge_states[0][2]

        v_e = np.float(semiconductor.v_T('e', temperature, symbolic=False))
        v_h = np.float(semiconductor.v_T('h', temperature, symbolic=False))
        if debug:
            print '<v_e> =', v_e, 'm/s'
            print '<v_h> =', v_h, 'm/s'
        sigma_n, sigma_p = self.capture_cross_sections(temperature)
        fore_factor_n = np.float(
            sigma_n * v_e * semiconductor.Nc(temperature, symbolic=False) *
            g_ratio_e)
        fore_factor_p = np.float(
            sigma_p * v_h * semiconductor.Nv(temperature, symbolic=False) *
            g_ratio_h)
        fore_factor_n *= poole_frenkel_e
        fore_factor_p *= poole_frenkel_h
        if debug:
            print 'factor_n =', fore_factor_n
            print 'factor_p =', fore_factor_p

        if self.energy_distribution_function in energy_distribution_functions[
                'Single Level']:
            activation_energy_e = conduction_band - trap_energy_level_e_positive - barrier_lowering_e
            activation_energy_h = trap_energy_level_h_positive - valence_band - barrier_lowering_h
            emission_rate_e = fore_factor_n * np.exp(
                -activation_energy_e / energy_scale)
            emission_rate_h = fore_factor_p * np.exp(
                -activation_energy_h / energy_scale)
            emission_time_constant_e = 1 / emission_rate_e
            emission_time_constant_h = 1 / emission_rate_h
            emission_e = emission_rate_e * f
            emission_h = emission_rate_h * (1 - f)
        else:
            quasi_fermi_level = self.f_to_equilibrium_fermi_level(
                temperature,
                semiconductor,
                f,
                electron_volts=False,
                use_mpmath=use_mpmath,
                debug=False)
            quasi_fermi_level = conduction_band - quasi_fermi_level
            if debug:
                print 'Eqf =', quasi_fermi_level / to_numeric(q), 'eV'
            energy = sym.symbols('E')
            energy_distribution_e = self.energy_distribution.subs([
                ('Et', trap_energy_level_e), ('Ecb', conduction_band)
            ])
            energy_distribution_e = energy_distribution_e.subs(
                q, to_numeric(q))
            energy_distribution_h = self.energy_distribution.subs([
                ('Et', trap_energy_level_h), ('Ecb', conduction_band)
            ])
            energy_distribution_h = energy_distribution_h.subs(
                q, to_numeric(q))
            energy_range_e = centered_linspace(
                conduction_band - trap_energy_level_e,
                10 * to_numeric(self.energy_spread),
                to_numeric(self.energy_spread) / 1000)
            energy_range_h = centered_linspace(
                conduction_band - trap_energy_level_h,
                10 * to_numeric(self.energy_spread),
                to_numeric(self.energy_spread) / 1000)
            energy_distribution_function_e = sym.lambdify(
                energy, energy_distribution_e, 'numpy')
            energy_distribution_function_h = sym.lambdify(
                energy, energy_distribution_h, 'numpy')
            energy_range_grid_e, barrier_lowering_grid_e = np.meshgrid(
                energy_range_e, barrier_lowering_e)
            energy_range_grid_h, barrier_lowering_grid_h = np.meshgrid(
                energy_range_h, barrier_lowering_h)
            exp_term_e = np.exp(-(conduction_band - energy_range_grid_e +
                                  barrier_lowering_grid_e) / energy_scale)
            exp_term_h = np.exp(
                -(energy_range_grid_h - barrier_lowering_grid_h - valence_band)
                / energy_scale)
            emission_rate_e = energy_distribution_function_e(
                energy_range_e) * exp_term_e * fore_factor_n
            emission_rate_h = energy_distribution_function_h(
                energy_range_h) * exp_term_h * fore_factor_p
            emission_rate_e_max = np.max(emission_rate_e, axis=1)
            emission_rate_h_max = np.max(emission_rate_h, axis=1)
            emission_time_constant_e = 1 / emission_rate_e_max
            emission_time_constant_h = 1 / emission_rate_h_max
            if not use_mpmath:
                if debug:
                    print 'Numeric integration (numpy.trapz)'
                energy_range_grid_e, fermi_level_grid_e = np.meshgrid(
                    energy_range_e, quasi_fermi_level)
                energy_range_grid_h, fermi_level_grid_h = np.meshgrid(
                    energy_range_h, quasi_fermi_level)
                fermi_function_e = 1 / (1 + g_ratio_e * np.exp(
                    (energy_range_grid_e - fermi_level_grid_e) / energy_scale))
                fermi_function_h = 1 - 1 / (1 + g_ratio_h * np.exp(
                    (energy_range_grid_h - fermi_level_grid_h) / energy_scale))
                exp_term_e = np.exp(-(conduction_band - energy_range_grid_e +
                                      barrier_lowering_e) / energy_scale)
                exp_term_h = np.exp(
                    -(energy_range_grid_h - barrier_lowering_h - valence_band)
                    / energy_scale)
                emission_rate_e = energy_distribution_function_e(
                    energy_range_grid_e) * exp_term_e
                emission_rate_h = energy_distribution_function_h(
                    energy_range_grid_h) * exp_term_h
                integrand_array_e = emission_rate_e * fermi_function_e
                integrand_array_h = emission_rate_h * fermi_function_h
                emission_e = np.trapz(integrand_array_e,
                                      energy_range_grid_e,
                                      axis=1) * fore_factor_n
                emission_h = np.trapz(integrand_array_h,
                                      energy_range_grid_h,
                                      axis=1) * fore_factor_p
            else:
                if debug:
                    print 'Numeric integration (mpmath.quad)'
                exp_term_e = sym.exp(
                    -(conduction_band - energy + barrier_lowering_e) /
                    energy_scale)
                exp_term_h = sym.exp(
                    -(energy - barrier_lowering_h - valence_band) /
                    energy_scale)
                quasi_fermi_level_grid, = np.meshgrid(quasi_fermi_level)
                emission_e = np.zeros_like(quasi_fermi_level_grid)
                emission_h = np.zeros_like(quasi_fermi_level_grid)
                for i, quasi_fermi_level_i in enumerate(
                        quasi_fermi_level_grid):
                    fermi_function_e = fermi(energy, quasi_fermi_level_i,
                                             temperature, g_ratio_e)
                    fermi_function_e = fermi_function_e.subs(k, to_numeric(k))
                    fermi_function_h = fermi(quasi_fermi_level_i, energy,
                                             temperature, g_ratio_h)
                    fermi_function_h = fermi_function_h.subs(k, to_numeric(k))
                    integrand_e = sym.lambdify(
                        energy,
                        energy_distribution_e * fermi_function_e * exp_term_e)
                    integrand_h = sym.lambdify(
                        energy,
                        energy_distribution_h * fermi_function_h * exp_term_h)
                    emission_integral_e = mp.quad(integrand_e, [
                        to_numeric(trap_energy_level_e_positive -
                                   10 * self.energy_spread),
                        to_numeric(trap_energy_level_e_positive -
                                   0.5 * self.energy_spread),
                        to_numeric(trap_energy_level_e_positive +
                                   0.5 * self.energy_spread),
                        to_numeric(trap_energy_level_e_positive +
                                   10 * self.energy_spread)
                    ])
                    emission_integral_h = mp.quad(integrand_h, [
                        to_numeric(trap_energy_level_h_positive -
                                   10 * self.energy_spread),
                        to_numeric(trap_energy_level_h_positive -
                                   0.5 * self.energy_spread),
                        to_numeric(trap_energy_level_h_positive +
                                   0.5 * self.energy_spread),
                        to_numeric(trap_energy_level_h_positive +
                                   10 * self.energy_spread)
                    ])
                    emission_e[i] = np.float(emission_integral_e *
                                             fore_factor_n)
                    emission_h[i] = np.float(emission_integral_h *
                                             fore_factor_p)
        if isinstance(emission_e, np.ndarray):
            if emission_e.size == 1:
                emission_e = emission_e[0]
                emission_h = emission_h[0]
                emission_time_constant_e = emission_time_constant_e[0]
                emission_time_constant_h = emission_time_constant_h[0]
        if debug: print 'emission_e =', emission_e
        if debug: print 'emission_h =', emission_h
        if debug: print 'emission_tau_e =', emission_time_constant_e
        if debug: print 'emission_tau_h =', emission_time_constant_e
        return emission_e, emission_h, emission_time_constant_e, emission_time_constant_h
Example #3
0
    def emission_rate(self, temperature, semiconductor, f, poole_frenkel_e=1.0, poole_frenkel_h=1.0,
                      barrier_lowering_e=None, barrier_lowering_h=None, use_mpmath=False, debug=False):
        """
        Calculate carriers emission rate for bot electrons and holes
        :param temperature: Temperature, K
        :param semiconductor: Semiconductor object
        :param f: Trap occupation from 0.0 to 1.0
        :param poole_frenkel_e: emission rate boost due to Poole-Frenkel effect for electron
        :param poole_frenkel_h: emission rate boost due to Poole-Frenkel effect for electron
        :param barrier_lowering_e: lowering of activation energy for electrons
        :param barrier_lowering_h: lowering of activation energy for holes
        :param use_mpmath: if True integration is done using mpmath.quad function instead of numpy.trapz (default)
        :param debug: if True prints out some debug information
        :return: emission_e, emission_h
        """
        if barrier_lowering_e is None:
            barrier_lowering_e = np.zeros_like(f, dtype=np.float)
        if barrier_lowering_h is None:
            barrier_lowering_h = np.zeros_like(f, dtype=np.float)
        energy_scale = to_numeric(k * temperature)
        conduction_band = 0
        band_gap = semiconductor.band_gap(temperature, symbolic=False, electron_volts=False)
        valence_band = conduction_band - band_gap
        trap_energy_level_e = np.float(self.energy_level(temperature, semiconductor,
                                                         charge_state_idx=1, electron_volts=False))
        trap_energy_level_h = np.float(self.energy_level(temperature, semiconductor,
                                                         charge_state_idx=0, electron_volts=False))
        trap_energy_level_e_positive = conduction_band - trap_energy_level_e
        trap_energy_level_h_positive = conduction_band - trap_energy_level_h

        g_ratio_e = self.charge_states[0][2] / self.charge_states[1][2]
        g_ratio_h = self.charge_states[1][2] / self.charge_states[0][2]

        v_e = np.float(semiconductor.v_T('e', temperature, symbolic=False))
        v_h = np.float(semiconductor.v_T('h', temperature, symbolic=False))
        if debug:
            print '<v_e> =', v_e, 'm/s'
            print '<v_h> =', v_h, 'm/s'
        sigma_n, sigma_p = self.capture_cross_sections(temperature)
        fore_factor_n = np.float(sigma_n * v_e * semiconductor.Nc(temperature, symbolic=False) * g_ratio_e)
        fore_factor_p = np.float(sigma_p * v_h * semiconductor.Nv(temperature, symbolic=False) * g_ratio_h)
        fore_factor_n *= poole_frenkel_e
        fore_factor_p *= poole_frenkel_h
        if debug:
            print 'factor_n =', fore_factor_n
            print 'factor_p =', fore_factor_p

        if self.energy_distribution_function in energy_distribution_functions['Single Level']:
            activation_energy_e = conduction_band - trap_energy_level_e_positive - barrier_lowering_e
            activation_energy_h = trap_energy_level_h_positive - valence_band - barrier_lowering_h
            emission_rate_e = fore_factor_n * np.exp(-activation_energy_e / energy_scale)
            emission_rate_h = fore_factor_p * np.exp(-activation_energy_h / energy_scale)
            emission_time_constant_e = 1 / emission_rate_e
            emission_time_constant_h = 1 / emission_rate_h
            emission_e = emission_rate_e * f
            emission_h = emission_rate_h * (1 - f)
        else:
            quasi_fermi_level = self.f_to_equilibrium_fermi_level(temperature, semiconductor, f,
                                                                  electron_volts=False,
                                                                  use_mpmath=use_mpmath, debug=False)
            quasi_fermi_level = conduction_band - quasi_fermi_level
            if debug:
                print 'Eqf =', quasi_fermi_level / to_numeric(q), 'eV'
            energy = sym.symbols('E')
            energy_distribution_e = self.energy_distribution.subs([('Et', trap_energy_level_e),
                                                                   ('Ecb', conduction_band)])
            energy_distribution_e = energy_distribution_e.subs(q, to_numeric(q))
            energy_distribution_h = self.energy_distribution.subs([('Et', trap_energy_level_h),
                                                                   ('Ecb', conduction_band)])
            energy_distribution_h = energy_distribution_h.subs(q, to_numeric(q))
            energy_range_e = centered_linspace(conduction_band - trap_energy_level_e,
                                               10 * to_numeric(self.energy_spread),
                                               to_numeric(self.energy_spread) / 1000)
            energy_range_h = centered_linspace(conduction_band - trap_energy_level_h,
                                               10 * to_numeric(self.energy_spread),
                                               to_numeric(self.energy_spread) / 1000)
            energy_distribution_function_e = sym.lambdify(energy, energy_distribution_e, 'numpy')
            energy_distribution_function_h = sym.lambdify(energy, energy_distribution_h, 'numpy')
            energy_range_grid_e, barrier_lowering_grid_e = np.meshgrid(energy_range_e, barrier_lowering_e)
            energy_range_grid_h, barrier_lowering_grid_h = np.meshgrid(energy_range_h, barrier_lowering_h)
            exp_term_e = np.exp(-(conduction_band - energy_range_grid_e + barrier_lowering_grid_e) / energy_scale)
            exp_term_h = np.exp(-(energy_range_grid_h - barrier_lowering_grid_h - valence_band) / energy_scale)
            emission_rate_e = energy_distribution_function_e(energy_range_e) * exp_term_e * fore_factor_n
            emission_rate_h = energy_distribution_function_h(energy_range_h) * exp_term_h * fore_factor_p
            emission_rate_e_max = np.max(emission_rate_e, axis=1)
            emission_rate_h_max = np.max(emission_rate_h, axis=1)
            emission_time_constant_e = 1 / emission_rate_e_max
            emission_time_constant_h = 1 / emission_rate_h_max
            if not use_mpmath:
                if debug:
                    print 'Numeric integration (numpy.trapz)'
                energy_range_grid_e, fermi_level_grid_e = np.meshgrid(energy_range_e, quasi_fermi_level)
                energy_range_grid_h, fermi_level_grid_h = np.meshgrid(energy_range_h, quasi_fermi_level)
                fermi_function_e = 1 / (1 + g_ratio_e * np.exp((energy_range_grid_e - fermi_level_grid_e) / energy_scale))
                fermi_function_h = 1 - 1 / (1 + g_ratio_h * np.exp((energy_range_grid_h - fermi_level_grid_h) / energy_scale))
                exp_term_e = np.exp(-(conduction_band - energy_range_grid_e + barrier_lowering_e) / energy_scale)
                exp_term_h = np.exp(-(energy_range_grid_h - barrier_lowering_h - valence_band) / energy_scale)
                emission_rate_e = energy_distribution_function_e(energy_range_grid_e) * exp_term_e
                emission_rate_h = energy_distribution_function_h(energy_range_grid_h) * exp_term_h
                integrand_array_e = emission_rate_e * fermi_function_e
                integrand_array_h = emission_rate_h * fermi_function_h
                emission_e = np.trapz(integrand_array_e, energy_range_grid_e, axis=1) * fore_factor_n
                emission_h = np.trapz(integrand_array_h, energy_range_grid_h, axis=1) * fore_factor_p
            else:
                if debug:
                    print 'Numeric integration (mpmath.quad)'
                exp_term_e = sym.exp(-(conduction_band - energy + barrier_lowering_e) / energy_scale)
                exp_term_h = sym.exp(-(energy - barrier_lowering_h - valence_band) / energy_scale)
                quasi_fermi_level_grid, = np.meshgrid(quasi_fermi_level)
                emission_e = np.zeros_like(quasi_fermi_level_grid)
                emission_h = np.zeros_like(quasi_fermi_level_grid)
                for i, quasi_fermi_level_i in enumerate(quasi_fermi_level_grid):
                    fermi_function_e = fermi(energy, quasi_fermi_level_i, temperature, g_ratio_e)
                    fermi_function_e = fermi_function_e.subs(k, to_numeric(k))
                    fermi_function_h = fermi(quasi_fermi_level_i, energy, temperature, g_ratio_h)
                    fermi_function_h = fermi_function_h.subs(k, to_numeric(k))
                    integrand_e = sym.lambdify(energy, energy_distribution_e * fermi_function_e * exp_term_e)
                    integrand_h = sym.lambdify(energy, energy_distribution_h * fermi_function_h * exp_term_h)
                    emission_integral_e = mp.quad(integrand_e,
                                                  [to_numeric(trap_energy_level_e_positive - 10 * self.energy_spread),
                                                   to_numeric(trap_energy_level_e_positive - 0.5 * self.energy_spread),
                                                   to_numeric(trap_energy_level_e_positive + 0.5 * self.energy_spread),
                                                   to_numeric(trap_energy_level_e_positive + 10 * self.energy_spread)])
                    emission_integral_h = mp.quad(integrand_h,
                                                  [to_numeric(trap_energy_level_h_positive - 10 * self.energy_spread),
                                                   to_numeric(trap_energy_level_h_positive - 0.5 * self.energy_spread),
                                                   to_numeric(trap_energy_level_h_positive + 0.5 * self.energy_spread),
                                                   to_numeric(trap_energy_level_h_positive + 10 * self.energy_spread)])
                    emission_e[i] = np.float(emission_integral_e * fore_factor_n)
                    emission_h[i] = np.float(emission_integral_h * fore_factor_p)
        if isinstance(emission_e, np.ndarray):
            if emission_e.size == 1:
                emission_e = emission_e[0]
                emission_h = emission_h[0]
                emission_time_constant_e = emission_time_constant_e[0]
                emission_time_constant_h = emission_time_constant_h[0]
        if debug: print 'emission_e =', emission_e
        if debug: print 'emission_h =', emission_h
        if debug: print 'emission_tau_e =', emission_time_constant_e
        if debug: print 'emission_tau_h =', emission_time_constant_e
        return emission_e, emission_h, emission_time_constant_e, emission_time_constant_h
Example #4
0
    def d_equilibrium_f_d_fermi_energy(self,
                                       temperature,
                                       semiconductor,
                                       fermi_level_from_conduction_band,
                                       electron_volts=False,
                                       use_mpmath=False,
                                       debug=False):
        """
        Calculates trap equilibrium filling derivative for given Fermi level position
        on small Fermi level change
        :param temperature: Temperature, K
        :param semiconductor: Semiconductor object
        :param fermi_level_from_conduction_band: distance from Conduction band to Fermi level
        :param electron_volts: if True assume all energy values to be in eV
        :param use_mpmath: if True integration is done using mpmath.quad function instead of numpy.trapz (default)
        :param debug: if True prints out some debug information
        :return: equilibrium f between 0 and 1
        """
        if electron_volts:
            energy_coefficient = to_numeric(q)
            energy_unit = 'eV'
        else:
            energy_coefficient = 1
            energy_unit = 'J'
        energy_scale = to_numeric(k * temperature) / energy_coefficient
        conduction_band = 0
        fermi_level = conduction_band - fermi_level_from_conduction_band
        trap_energy_level = self.energy_level(temperature,
                                              semiconductor,
                                              charge_state_idx=0,
                                              electron_volts=electron_volts)
        if debug:
            print 'Et = %2.2g ' % (
                (conduction_band - trap_energy_level)) + energy_unit
            print 'Ef =,', fermi_level, energy_unit
        g_ratio = self.charge_states[0][2] / self.charge_states[1][2]

        if self.energy_distribution_function in energy_distribution_functions[
                'Single Level']:
            fermi_level_grid, = np.meshgrid(fermi_level)
            exp_arg = (np.float(conduction_band - trap_energy_level) -
                       fermi_level_grid) / energy_scale
            exp_term = np.exp(exp_arg)
            exp_term = np.array(map(mp.exp, exp_arg))
            a = g_ratio / (energy_coefficient * energy_scale)
            #print exp_term #/ (1 + g_ratio * exp_term)
            b = exp_term / (1 + g_ratio * exp_term)**2
            d_f = a * b
            # d_f = g_ratio / (energy_coefficient * energy_scale) * exp_term / (1 + g_ratio * exp_term) ** 2
            d_f[np.where(d_f == np.nan)] = 0
        else:
            energy = sym.symbols('E')
            energy_distribution = self.energy_distribution.subs([
                ('Et', trap_energy_level * energy_coefficient),
                ('Ecb', conduction_band * energy_coefficient)
            ])
            energy_distribution = energy_distribution.subs(q, to_numeric(q))
            if not use_mpmath:
                if debug:
                    print 'Numeric integration (numpy.trapz)'
                energy_range = centered_linspace(
                    conduction_band - trap_energy_level,
                    10 * to_numeric(self.energy_spread) / energy_coefficient,
                    to_numeric(self.energy_spread) / energy_coefficient / 1000)
                energy_range_grid, fermi_level_grid = np.meshgrid(
                    energy_range, fermi_level)
                exp_term = np.exp(
                    (energy_range_grid - fermi_level_grid) / energy_scale)
                fore_factor = g_ratio / (energy_coefficient * energy_scale)
                d_fermi_function = fore_factor * exp_term / (
                    1 + g_ratio * exp_term)**2
                d_fermi_function[np.where(d_fermi_function == np.nan)] = 0
                energy_distribution_function = sym.lambdify(
                    energy, energy_distribution, 'numpy')
                integrand_array = energy_distribution_function(
                    energy_range_grid * energy_coefficient) * d_fermi_function
                d_f = np.trapz(integrand_array,
                               energy_range_grid * energy_coefficient,
                               axis=1)
            else:
                if debug:
                    print 'Numeric integration (mpmath.quad)'
                fermi_level_grid, = np.meshgrid(fermi_level)
                d_f = np.zeros_like(fermi_level_grid)
                for i, fermi_level_i in enumerate(fermi_level_grid):
                    d_fermi_function = d_fermi_d_delta_fermi_energy(
                        energy, fermi_level_i * energy_coefficient,
                        temperature, g_ratio)
                    d_fermi_function = d_fermi_function.subs(k, to_numeric(k))
                    integrand = sym.lambdify(
                        energy, energy_distribution * d_fermi_function)
                    d_f[i] = mp.quad(integrand, [
                        to_numeric(energy_coefficient *
                                   (conduction_band - trap_energy_level) -
                                   10 * self.energy_spread),
                        to_numeric(energy_coefficient *
                                   (conduction_band - trap_energy_level) -
                                   0.5 * self.energy_spread),
                        to_numeric(energy_coefficient *
                                   (conduction_band - trap_energy_level) +
                                   0.5 * self.energy_spread),
                        to_numeric(energy_coefficient *
                                   (conduction_band - trap_energy_level) +
                                   10 * self.energy_spread)
                    ])
        if debug:
            print 'dF =', d_f
        if d_f.size == 1:
            d_f = d_f[0]
        return d_f