def resistivity(mat, Na, Ea, Nd, Ed, T): """Вычисляет сопротивление по концентрациям в функции irwin написано тоже самое но *немного* оптимальнее""" A = mat.mobility_const_a B = mat.mobility_const_b sem = DopedSemiconductor(mat.semiconductor, Na, Ea, Nd, Ed) return 1 / conductivity(0, 0, sem.p_concentration(T=T), mobility(sem, T, A, B))
def conductivity(mat, type, Na, Ea, Nd, Ed, T): """Вычисляет проводимость по концентрациям в функции""" a = mat.mobility_const_a b = mat.mobility_const_b sem = DopedSemiconductor(mat.semiconductor, Na, Ea, Nd, Ed) n = sem.p_concentration(T=T) if type == 'p' else sem.n_concentration(T=T) mob = mobility(sem, T, a, b) return models.conductivity(n, mob)
def test_intrinsic_concentrations(self): mat = DopedSemiconductor(Si, 1e15, 0, 1e17, Si.Eg) # random parameters self.assertAlmostEqual(Si.n_concentration(), Si.p_concentration(), delta=1e7) self.assertAlmostEqual(Si.n_concentration(), Si.i_concentration(), delta=1e7) self.assertAlmostEqual(mat.i_concentration(), Si.i_concentration(), delta=1e7)
def irwin(mat, Ea, Nd, Ed, T, Nas): """ То же что и выше но бес постоянного создания объектов (хотя это совсем не критично) Мне даже больше нравится первый вариант """ A = mat.mobility_const_a B = mat.mobility_const_b sem = DopedSemiconductor(mat.semiconductor, -1, Ea, Nd, Ed) res = [] for na in Nas: sem.Na = na cond = conductivity(0, 0, sem.p_concentration(T=T), mobility(sem, T, A, B)) res.append(1 / cond) return np.array(res)
def test_full_depletion_width(self): # The parameters are selected to comply with the condition delta_phi = 0.5 volt c = MSJunction(Metal(4.65 * eV), DopedSemiconductor(Si, 0, 0, 1e17, Si.Eg)) self.assertAlmostEqual(c.delta_phi() / volt, 0.5, delta=0.001) self.assertAlmostEqual(c.full_depletion_width() / unit('nm'), 81, delta=1)
def test_contact_type(self): with self.assertRaises(NotImplementedError): c = MSJunction(Metal(4.1 * eV), Si) c.contact_type() # Al -- p-Si c = MSJunction(Metal(4.1 * eV), DopedSemiconductor(Si, 1e17, 0.045 * eV, 0, Si.Eg)) self.assertEqual(c.contact_type(), ContactType.INVERSION) # Pt -- n-Si c = MSJunction(Metal(5.2 * eV), DopedSemiconductor(Si, 0, 0, 1e18, Si.Eg)) self.assertEqual(c.contact_type(), ContactType.INVERSION) # Cs -- n-Si c = MSJunction(Metal(2.14 * eV), DopedSemiconductor(Si, 0, 0, 1e18, Si.Eg)) self.assertEqual(c.contact_type(), ContactType.AUGMENTATION) # Imaginary -- p-Si c = MSJunction(Metal(4.8 * eV), DopedSemiconductor(Si, 1e17, 0.045 * eV, 0, Si.Eg)) self.assertEqual(c.contact_type(), ContactType.DEPLETION)
def test_from_materials(self): # КДБ-100 res = DopedSemiconductor.from_materials( Si, from_unit(500, 'cm^2 / V s'), # Mobility for holes 'B', from_unit(100, 'Ohm cm')) self.assertEqual(res.Nd, 0) self.assertAlmostEqual(res.Na, 1.2e14, delta=0.1e14) # КЭМ-100 res = DopedSemiconductor.from_materials( Si, from_unit(1500, 'cm^2 / V s'), # Mobility for electrons 'As', from_unit(100, 'Ohm cm')) self.assertEqual(res.Na, 0) self.assertAlmostEqual(res.Nd, 4.1e13, delta=0.1e13) with self.assertRaises(KeyError): DopedSemiconductor.from_materials(Si, 1, 'UNKNOWN', 1)
def test_schottky_barrier(self): c = MSJunction(Metal(4.1 * eV), DopedSemiconductor(Si, 1e18, 0.045 * eV, 0, Si.Eg)) self.assertAlmostEqual(c.schottky_barrier() / volt, 0.05, delta=0.001)
import matplotlib.pyplot as plt import numpy as np from fompy.constants import eV from fompy.materials import Si from fompy.models import DopedSemiconductor if __name__ == '__main__': mat1 = DopedSemiconductor(Si, 1e18, 0.045 * eV, 1e20, Si.Eg - 0.045 * eV) mat2 = DopedSemiconductor(Si, 0, 0.045 * eV, 1e15, Si.Eg - 0.045 * eV) mat3 = DopedSemiconductor(Si, 1e20, 0.4 * eV, 1e20, Si.Eg - 0.4 * eV) mat4 = DopedSemiconductor(Si, 2e20, 0.045 * eV, 0, Si.Eg) min_e = -0.1 * Si.Eg max_e = 1.1 * Si.Eg xs = np.linspace(min_e, max_e, 1000) func = np.vectorize(DopedSemiconductor._charge_imbalance) ys1 = func(mat1, xs, T=300) ys2 = func(mat2, xs, T=300) ys3 = func(mat3, xs, T=300) ys4 = func(mat4, xs, T=300) plt.plot(xs / eV, ys1, 'r', label='1') plt.plot(xs / eV, ys2, 'g', label='2') plt.plot(xs / eV, ys3, 'b', label='3') plt.plot(xs / eV, ys4, 'y', label='4') plt.title('Charge carrier imbalance') plt.xlabel('$E_f, eV$') plt.ylabel(r'$\Delta N$') plt.axvline(x=0) plt.axvline(x=Si.Eg / eV)
def test_intrinsic_fermi_level(self): mat = DopedSemiconductor(Si, 1e15, 0, 1e17, Si.Eg) # random parameters self.assertAlmostEqual(mat.intrinsic_fermi_level(), 0.57 * eV, delta=0.01 * eV) self.assertEqual(mat.intrinsic_fermi_level(), Si.fermi_level())
def test_degenerate_fermi_level(self): mat = DopedSemiconductor(Si, 1e21, 0.045 * eV, 0, Si.Eg) self.assertAlmostEqual(mat.fermi_level() / eV, -0.04, delta=0.001) # Note the negative value mat = DopedSemiconductor(Si, 10, 0, 1e20, Si.Eg - 0.045 * eV) self.assertAlmostEqual(mat.fermi_level() / eV, 1.142, delta=0.001)
class TestDopedSemiconductor(unittest.TestCase): def setUp(self): self.mat_a = DopedSemiconductor(Si, 1e18, 0.045 * eV, 0, 0) self.mat_d = DopedSemiconductor(Si, 0, 0, 1e18, Si.Eg - 0.045 * eV) def test_n_acceptor(self): self.assertAlmostEqual(self.mat_a.n_acceptor_concentration(0.04 * eV), 4.5e17, delta=1e16) self.assertAlmostEqual(self.mat_a.n_acceptor_concentration(0.04 * eV, T=200), 4.2e17, delta=1e16) def test_p_donor(self): self.assertAlmostEqual(self.mat_d.p_donor_concentration(Si.Eg - 0.04 * eV), 4.5e17, delta=1e17) self.assertAlmostEqual(self.mat_d.p_donor_concentration(Si.Eg - 0.04 * eV, T=200), 4.2e17, delta=1e17) def test_fermi_level(self): self.assertAlmostEqual(self.mat_a.fermi_level(T=200), 0.047 * eV, delta=0.001 * eV) self.assertAlmostEqual(self.mat_d.fermi_level(T=200), Si.Eg - 0.035 * eV, delta=0.001 * eV) def test_conductivity_type(self): with self.assertRaises(ValueError): self.mat_a.conductivity_type(T=300, Ef=1 * eV) self.assertEqual(self.mat_a.conductivity_type(), 'p') self.assertEqual(self.mat_d.conductivity_type(), 'n') def test_from_materials(self): # КДБ-100 res = DopedSemiconductor.from_materials( Si, from_unit(500, 'cm^2 / V s'), # Mobility for holes 'B', from_unit(100, 'Ohm cm')) self.assertEqual(res.Nd, 0) self.assertAlmostEqual(res.Na, 1.2e14, delta=0.1e14) # КЭМ-100 res = DopedSemiconductor.from_materials( Si, from_unit(1500, 'cm^2 / V s'), # Mobility for electrons 'As', from_unit(100, 'Ohm cm')) self.assertEqual(res.Na, 0) self.assertAlmostEqual(res.Nd, 4.1e13, delta=0.1e13) with self.assertRaises(KeyError): DopedSemiconductor.from_materials(Si, 1, 'UNKNOWN', 1)
def test_issue_11(self): # Should not raise OverflowError m = DopedSemiconductor(Si, 1e12, 0, 0, Si.Eg) m.fermi_level(T=11) self.assertEqual(functions.fermi(Si.Eg, 0, 11), 0)
def test_debye_length(self): c = MSJunction(Metal(4.1 * eV), DopedSemiconductor(Si, 0, 0, 1e18, Si.Eg)) self.assertAlmostEqual(c.debye_length() / unit('nm'), 4.4, delta=0.1)
plt.plot(line.xs, line.ys, line.description.style) def complete_plot(): plt.legend() plt.xscale('log') plt.yscale('log') plt.show() descriptions = { 'Si_n': FileDescription( 'Si electrons (Si_n)', ['3', '4'], { '1': LineDescription(DopedSemiconductor(Si, 0, 0, 1e12, Si.Eg), 'k', '1'), '2': LineDescription(DopedSemiconductor(Si, 0, 0, 1e13, Si.Eg), 'r', '2'), '3': LineDescription(DopedSemiconductor(Si, 1.48e15, 0, 1.75e16, Si.Eg), 'g', '3'), '4': LineDescription(DopedSemiconductor(Si, 2.2e15, 0, 1.3e17, Si.Eg), 'b', '4'), }), 'Si_p': FileDescription( 'Si holes (Si_p)', ['3', '4'], { '1':
def setUp(self): self.mat_a = DopedSemiconductor(Si, 1e18, 0.045 * eV, 0, 0) self.mat_d = DopedSemiconductor(Si, 0, 0, 1e18, Si.Eg - 0.045 * eV)
def test_delta_phi(self): c = MSJunction(Metal(4.1 * eV), DopedSemiconductor(Si, 1e18, 0.045 * eV, 0, Si.Eg)) self.assertAlmostEqual(c.delta_phi(300), -0.98 * volt, delta=0.1 * volt)
def handle_two(l1, l2, title): start_plot(lines, title) mean_ps = fit_two_curves(l1, l2) print_params(mean_ps, title) handle_line(l1, mean_ps) handle_line(l2, mean_ps) complete_plot() if __name__ == '__main__': print('=== electrons ===') desc = [ ('1', DopedSemiconductor(Si, 0, 0, 1e12, Si.Eg), 'k', '1'), ('2', DopedSemiconductor(Si, 0, 0, 1e13, Si.Eg), 'r', '2'), ('3', DopedSemiconductor(Si, 1.48e15, 0, 1.75e16, Si.Eg), 'g', '3'), ('4', DopedSemiconductor(Si, 2.2e15, 0, 1.3e17, Si.Eg), 'b', '4'), ] lines = get_lines('../data/Si_n/mobility.csv', desc) handle_independent(lines, 'Константы вчсиляются для каждой кривой') print('==========') handle_two(lines[2], lines[3], 'Константы усреднены для кривых 3 и 4') print('=== holes ===') desc = [ ('1', DopedSemiconductor(Si, 1e12, 0, 0, Si.Eg), 'k', '1'), ('2', DopedSemiconductor(Si, 1e14, 0, 0, Si.Eg), 'r', '2'), ('3', DopedSemiconductor(Si, 2.4e16, 0, 2.3e15, Si.Eg), 'g', '3'),
import numpy as np from fompy.constants import eV from fompy.materials import Si from fompy.models import DopedSemiconductor if __name__ == '__main__': # Хотя материалы 1 и 2 имеют разные концентрации и донорные уровни, # разницы между концентрациями доноров и акцепторов одинаковы. # Поэтому кривые дисбаланса, а следовательно и уровни ферми, почти совпадают. # При совпадении донорных уровней уровни ферми становятся еще ближе. # Для вырожденного полупроводника это приближение уже не работает. # Это связанно с тем что интеграл Ферми-Дирака не обладает # основным функциональным свойством экспоненты exp(a+b) = exp(a)*exp(b). # А в выровжденном мы как раз больше не можем приближать интеграл Ферми-Дирака экспонентой. mat1 = DopedSemiconductor(Si, 2e17, 0.045 * eV, 1e17, Si.Eg - 0.045 * eV) mat2 = DopedSemiconductor(Si, 1e17, 0, 0, Si.Eg) mat3 = DopedSemiconductor(Si, 2e17, 0.045 * eV, 0, Si.Eg - 0.045 * eV) print('E_f_1 =', mat1.fermi_level() / eV, 'eV') print('E_f_2 =', mat2.fermi_level() / eV, 'eV') min_e = 0.1 * Si.Eg max_e = 0.9 * Si.Eg xs = np.linspace(min_e, max_e, 1000) func = np.vectorize(DopedSemiconductor._charge_imbalance) ys1 = func(mat1, xs, T=300) ys2 = func(mat2, xs, T=300) ys3 = func(mat3, xs, T=300) plt.plot(xs / eV, ys1, 'r', label='1') plt.plot(xs / eV, ys2, 'g', label='2') plt.plot(xs / eV, ys3, 'b', label='3')