PLaSK library
Loading...
Searching...
No Matches
diffusion3d.py
Go to the documentation of this file.
1# This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
2# Copyright (c) 2023 Lodz University of Technology
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, version 3.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12
13import unittest
14
15from numpy import *
16from numpy.testing import assert_allclose
17
18from plask import *
19from plask import material, geometry, mesh
20
21from plask.flow import CurrentDensityProvider3D
22
23from electrical.diffusion import Diffusion3D
24
27np.set_printoptions(linewidth=132)
28
29A = 3e7 # [1/s]
30B = 1.7e-10 # [cm³/s]
31C = 6e-27 # [cm⁶/s]
32D = 10. # [cm²/s]
33
34L = 4.0
35
36
37@material.simple('GaAs')
39
40 def A(self, T=300):
41 return A
42
43 def B(self, T=300):
44 return B
45
46 def C(self, T=300):
47 return C
48
49 def D(self, T=300):
50 return D
51
52
54
55 def setUp(self):
56 # clad = geometry.Cuboid(L, L, 0.100, 'GaAs')
57 # qw = geometry.Cuboid(L, L, 0.002, 'GaAsQW')
58 # ba = geometry.Cuboid(L, L, 0.001, 'GaAs')
59 clad = geometry.Cylinder(L, 0.100, 'GaAs')
60 qw = geometry.Cylinder(L, 0.002, 'GaAsQW')
61 ba = geometry.Cylinder(L, 0.001, 'GaAs')
62 qw.role = 'QW'
63 active = geometry.Stack3D(x=0, y=0)
64 active.role = 'active'
70 stack = geometry.Stack3D(x=0, y=0)
71 stack.prepend(clad)
72 stack.prepend(active)
73 stack.prepend(clad)
74 clip = geometry.Clip3D(stack, left=0., back=0.)
75 self.geometry = geometry.Cartesian3D(clip, left='mirror', right='air', back='mirror', front='air')
76 self.solver = Diffusion3D("diffusion3d")
77 # self.solver.algorithm = 'iterative'
78 self.solver.geometry = self.geometry
79 self.solver.mesh = mesh.Rectangular3D.RegularGenerator(0.01 * L, 0.01 * L, 0.01)
80 self.solver.maxerr = 0.0001
82 self.test_mesh = mesh.Rectangular3D(linspace(-0.8 * L, 0.8 * L, 5), linspace(-0.8 * L, 0.8 * L, 5), [0.104])
83
84 def filter(self, values, x, y):
85 mask = x**2 + y**2 <= L**2
86 values[~mask] = 0.
87 return values
88
89 def test_uniform(self):
90 n = 1.0e19
91 j = 1e-7 * (self.qwm.A() * n + self.qwm.B() * n**2 + self.qwm.C() * n**3) * (phys.qe * 0.006)
92 self.solver.inCurrentDensity = vec(0., 0., j)
93 self.solver.compute()
94 res = self.solver.outCarriersConcentration(self.test_mesh).array[:, :, 0]
95 ref = n * ones_like(res)
96 y, x = meshgrid(self.test_mesh.axis0, self.test_mesh.axis1)
97 assert_allclose(res, self.filter(ref, x, y), 1e-5)
98
99 def n(self, p):
100 x, y, z = p.T
101 return self.filter(1e19 * (exp(-x**2) * exp(-y**2) + 0.5), x, y)
102
103 def d2nx(self, p):
104 x, y, z = p.T
105 return self.filter(2e19 * (2 * x**2 - 1) * exp(-x**2) * exp(-y**2), x, y)
106
107 def d2ny(self, p):
108 x, y, z = p.T
109 return self.filter(2e19 * exp(-x**2) * (2 * y**2 - 1) * exp(-y**2), x, y)
110
111 def j(self, p):
112 x, y, z = p.T
113 n = self.n(p)
114 nj = 1e8 * D * (self.d2nx(p) + self.d2ny(p)) - A * n - B * n**2 - C * n**3
115 return self.filter(-1e-7 * (phys.qe * 0.006) * nj, x, y)
116
117 def test_gaussian(self):
118 self.solver.inCurrentDensity = CurrentDensityProvider3D(
119 lambda m, _: array([zeros(len(m)), zeros(len(m)), self.j(array(m))]).T
120 )
121 self.solver.compute()
122 n = array(self.solver.outCarriersConcentration(self.test_mesh))
123 assert_allclose(n, self.n(array(self.test_mesh)), 0.5e-3)
124
125
126if __name__ == '__main__':
128 test.setUp()
129
130 x = linspace(-1.1 * L, 1.1 * L, 5001)
131 xm = mesh.Rectangular3D(x, [0.25 * L], [0.104])
132
133 axhline(0., lw=0.7, color='k')
134 plot(x, test.j(array(xm)), color='C0', label='current')
135 xlabel(f"${config.axes[1]}$ [µm]")
136 ylabel("$j$ [kA/cm]")
137 legend(loc='upper left')
138 twinx()
139
140 test.solver.inCurrentDensity = CurrentDensityProvider3D(lambda m, _: array([zeros(len(m)), zeros(len(m)), test.j(array(m))]).T)
142 plot_profile(test.solver.outCarriersConcentration(xm), color='C2', label='concentration (numeric)')
143
144 plot(x, test.n(array(xm)), 'C1', ls='--', label='concentration (analytic)')
145
146 xlabel(f"${config.axes[1]}$ [µm]")
147 ylabel("$n$ [cm$^{-3}$]")
148 legend(loc='upper right')
149
150 show()