PLaSK library
Loading...
Searching...
No Matches
gaas3d.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3# Copyright (c) 2022 Lodz University of Technology
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, version 3.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13
14import unittest
15
16from numpy import *
17from numpy.testing import assert_allclose
18
19from plask import *
20from plask import material, geometry, mesh, flow
21
22from gain.freecarrier import FreeCarrier3D
23
25
26@material.simple('GaAs')
28 lattC = 5.654
29 Dso = 0.3548
30 Me = 0.103
31 Mhh = 0.6
32 Mlh = 0.14
33 D = 10
34 def VB(self, T=300., e=0., point=None, hole=None):
35 return -0.75
36 def A(self, T=300.):
37 return 7e7 + (T-300) * 1.4e5
38 def B(self, T=300.):
39 return 1.1e-10 - (T-300) * -2.2e-13
40 def C(self, T=300.):
41 return 1.130976e-28 - (T-300) * 1.028743e-30 + (T-300)**2 * 8.694142e-32
42 def Eg(self, T=300., e=0., point=None):
43 return 1.30 - 0.0003 * (T-300)
44 def nr(self, wl, T=300., n=0.):
45 return 3.3 + (wl-1310) * 5.00e-4 + (T-300) * 7e-4
46 def absp(self, wl, T=300.):
47 return 50. + (T-300) * 7e-2
48
49
50@material.simple('Barrier')
52 Me = 0.052
53 Mhh = 0.477
54 Mlh = 0.103
55 absp = 1000.
56 def VB(self, T=300., e=0., point=None, hole=None):
57 return 0.14676 + 0.000033 * (T-300) - 0.75
58 def Eg(self, T=300., e=0., point=None):
59 return 0.87 - 0.0002 * (T-300) - 100. * e
60 def nr(self, wl, T=300., n=0.):
61 return 3.6 + (wl-1310) * 5.00e-4 + (T-300) * 7e-4
62
63
64@material.simple('Barrier')
66 def VB(self, T=300., e=0., point=None, hole=None):
67 return -0.5
68 def Eg(self, T=300., e=0., point=None):
69 return 0.9
70
71
72@material.simple('Well')
74 def VB(self, T=300., e=0., point=None, hole=None):
75 return -0.2
76 def Eg(self, T=300., e=0., point=None):
77 return 0.1
78
79
81
82 def build_geometry(self, well_material, barrier_material):
83 substrate = geometry.Cylinder(20., 1000., 'GaAs')
84 substrate.role = 'substrate'
85 well = geometry.Cylinder(20., 0.0060, well_material)
86 well.role = 'QW'
87 barrier = geometry.Cylinder(20., 0.0067, barrier_material)
88 stack = geometry.Stack3D(x=0, y=0)
89 stack.prepend(substrate)
90 active = geometry.Stack3D(x=0, y=0)
91 active.role = 'active'
92 for i in range(4):
93 active.prepend(barrier)
94 active.prepend(well)
95 active.prepend(barrier)
96 stack.prepend(active)
97 stack.prepend(substrate)
98 return geometry.Cartesian3D(stack), active, well
99
100 def setUp(self):
101 self.mesh = mesh.Rectangular3D([-17., 0., 17.], [-17., 0., 17.], [1000.0100])
102 self.geometry, self.active, well = self.build_geometry('Well', 'Barrier')
104 self.concentration[well] = 3.5e18
105
106 def get_bands(self, band, dest_mesh, interp=None):
107 if band == 'CONDUCTION':
108 return array([self.geometry.get_material(p).CB() for p in dest_mesh])
109 elif band == 'VALENCE_LIGHT':
110 return array([self.geometry.get_material(p).VB(hole='L') for p in dest_mesh])
111 elif band == 'VALENCE_HEAVY':
112 return array([self.geometry.get_material(p).VB(hole='H') for p in dest_mesh])
113 elif band == 'SPINOFF':
114 return array([self.geometry.get_material(p).Dso() for p in dest_mesh])
115
116 def get_fermi_level(self, which, dest_mesh, interp=None):
117 value = {'ELECTRONS': 0.4290875146658184, 'HOLES': -0.5893720196570111}[which]
118 return array([value] * len(dest_mesh))
119
120 def plot_bands(self):
121 box = self.geometry.get_object_bboxes(self.active)[0]
122 zz = linspace(box.lower.z-0.002, box.upper.z+0.002, 1001)
123 msh = mesh.Rectangular3D([0.], [0.], zz)
124 CC = self.get_bands('CONDUCTION', msh)
125 VV = self.get_bands('VALENCE_HEAVY', msh)
126 plot(1e3*zz, CC)
127 plot(1e3*zz, VV)
128 xlim(1e3*zz[0], 1e3*zz[-1])
129 xlabel("$z$ (nm)")
130 ylabel("Band Edges (eV)")
131 window_title("Band Edges")
132 tight_layout(pad=0.5)
133
134 def test_gain(self):
135 solver = FreeCarrier3D("self.solver")
137 solver.inCarriersConcentration = self.concentration.outCarriersConcentration
138 solver.strained = True
139 g = 1314.
140 assert_allclose(array(solver.outGain(self.mesh, 1275.))[:,0], [0., g, 0., g, g, g, 0., g, 0.], rtol=1e-3)
141 msh = mesh.Rectangular3D([0.], [0.], [100.])
142 self.assertEqual(len(solver.outEnergyLevels('ELECTRONS', msh)[0]), 0)
143
145 solver = FreeCarrier3D("self.solver")
146 geom, _, _ = self.build_geometry('Well0', 'Barrier0')
147 solver.geometry = geom
149 solver.inCarriersConcentration = self.concentration.outCarriersConcentration
150 self.assertAlmostEqual(solver.outGain(self.mesh, 1275.)[4][0], 1254., 0)
151 assert_allclose(
152 solver.outEnergyLevels('ELECTRONS', self.mesh)[4],
153 [0.3337, 0.3337, 0.3337, 0.3337, 0.5259, 0.5259, 0.5263, 0.5263, 0.5979, 0.5987],
154 rtol=1e-3)
155 assert_allclose(
156 solver.outEnergyLevels('HEAVY_HOLES', self.mesh)[4],
157 [-0.6166, -0.6166, -0.6166, -0.6166, -0.6561, -0.6561, -0.6562, -0.6562, -0.7174, -0.7174, -0.7174,
158 -0.7174, -0.7978, -0.7916, -0.7859, -0.7813, -0.7788, -0.7651, -0.7627, -0.7606, -0.7591, -0.7586],
159 rtol=1e-3)
160 assert_allclose(
161 solver.outEnergyLevels('LIGHT_HOLES', self.mesh)[4],
162 [-0.6415, -0.6415, -0.6415, -0.6415, -0.7386, -0.7386, -0.7390, -0.7390, -0.7997, -0.7844, -0.7833],
163 rtol=1e-3)
164
166 solver = FreeCarrier3D("self.solver")
170 self.assertAlmostEqual(solver.outGain(self.mesh, 1275.)[4][0], 1254., 0)
171
172
173if __name__ == '__main__':
174 test = unittest.main(exit=False)
175 instance = TestStructureGain('plot_bands')
178 show()