PLaSK library

Loading...
Searching...
No Matches
layers.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
14 import unittest
15
16 from numpy import *
17 from numpy.testing import assert_array_almost_equal
18
19 from plask import *
20 from plask import material, geometry, mesh
21 from optical.modal import Fourier2D
22
23
24 class LayerSetTest(unittest.TestCase):
25
26 def setUp(self):
27 plask.config.axes = 'rz'
28 self.manager = plask.Manager()
29 self.manager.load('''
30 <plask>
31 <materials>
32 <material name="GaAs" base="semiconductor">
33 <nr>3.53</nr>
34 </material>
35 <material name="AlGaAs" base="semiconductor">
36 <nr>3.08</nr>
37 </material>
38 <material name="AlAs" base="semiconductor">
39 <nr>2.95</nr>
40 </material>
41 <material name="InGaAs" base="semiconductor">
42 <nr>3.53</nr>
43 <absp>1000</absp>
44 </material>
45 </materials>
46 <geometry>
47 <cartesian2d axes="rz" name="vcsel" left="mirror" right="extend" bottom="GaAs">
48 <stack name="layers">
49 <block dr="10" dz="0.06949" material="GaAs"/>
50 <stack name="top-dbr" repeat="24">
51 <block dr="10" dz="0.07955" material="AlGaAs"/>
52 <block dr="10" dz="0.06949" material="GaAs"/>
53 </stack>
54 <block name="x1" dr="10" dz="0.06371" material="AlGaAs"/>
55 <shelf name="oxide-layer">
56 <block dr="4" dz="0.01593" material="AlAs"/><block dr="6" dz="0.01593" material="AlOx"/>
57 </shelf>
58 <block dr="10" dz="0.13649" material="GaAs" role="opt-cavity,interface"/>
59 <shelf name="QW">
60 <block name="active" dr="4" dz="0.00500" material="InGaAs"/><block dr="6" dz="0.00500" material="InGaAs"/>
61 </shelf>
62 <block dr="10" dz="0.13649" material="GaAs" role="opt-cavity"/>
63 <zero/>
64 <stack name="bottom-dbr" repeat="29">
65 <block dr="10" dz="0.07955" material="AlGaAs"/>
66 <block dr="10" dz="0.06949" material="GaAs"/>
67 </stack>
68 <block dr="10" dz="0.07955" material="AlGaAs"/>
69 </stack>
70 </cartesian2d>
71 </geometry>
72 <solvers>
73 <optical name="pwrt" solver="Fourier2D">
74 <geometry ref="vcsel"/>
75 </optical>
76 </solvers>
77 </plask>''')
78 self.solver = self.manager.solvers.pwrt
79 self.solver.wavelength = 1000.
80 self.mat = self.manager.geo.vcsel.get_material
81
82 def testInterface(self):
83 self.assertEqual(self.solver.interface, 62)
84 self.solver.set_interface(0.)
85 self.assertEqual(self.solver.interface, 60)
86 self.solver.set_interface(self.manager.geo.QW)
87 self.assertEqual(self.solver.interface, 61)
88
89 def testLayers(self):
90 self.solver.initialize()
91 #layers = [ ' '.join(set([ "%s/%s" % (self.mat(2,z), self.mat(7,z)) for z in l ])) for l in self.solver.layer_sets ]
92 stack = list(self.solver.stack)[-1::-1]
93 #for i in enumerate(layers):
94 #print("%d: %s" % i)
95 #self.assertEqual(layers, ['GaAs/GaAs', 'AlGaAs/AlGaAs', 'GaAs/GaAs', 'InGaAs/InGaAs', 'AlAs/AlOx', 'air/air'])
96 print(stack)
97 self.assertEqual(stack, [5] + 25*[0,1] + [4,2,3,2] + 30*[1,0])
98
99
100 class MergeTest(unittest.TestCase):
101
102 def setUp(self):
103 rect = geometry.Rectangle(1., 1., 'GaAs')
104 stack = geometry.Stack2D()
105 stack.prepend(rect)
106 stack.prepend(rect)
107 path = stack.prepend(rect)
108 stack.prepend(rect)
109 stack.prepend(rect)
110 self.solver = Fourier2D('solver')
111 self.solver.geometry = geometry.Cartesian2D(stack)
112 self.solver.set_interface(rect, path)
113
114 def testMerge(self):
115 self.solver.initialize()
116 stack = list(self.solver.stack)
117 print(stack)
118 self.assertEqual(stack, [0, 1, 1, 0])
119
120
121 class TestAnisotropic(unittest.TestCase):
122
123 def setUp(self):
124 plask.config.axes = 'xyz'
125 self.manager = plask.Manager()
126 self.manager.load('''
127 <plask>
128 <materials>
129 <material name="Anisotropic" base="semiconductor">
130 <Eps>1, 4, 9</Eps>
131 </material>
132 </materials>
133 <geometry>
134 <cartesian2d axes="yz" name="test" left="mirror" right="periodic">
135 <block dy="10" dz="10" material="Anisotropic"/>
136 </cartesian2d>
137 </geometry>
138 <solvers>
139 <optical name="solver" solver="Fourier2D">
140 <geometry ref="test"/>
141 </optical>
142 </solvers>
143 </plask>''')
144 self.solver = self.manager.solvers.solver
145 self.solver.wavelength = 1000.
146 self.mesh = mesh.Rectangular2D([5.0], [5.0])
147
148 def testEpsilon(self):
149 assert_array_almost_equal(diag([1.,4.,9.]), self.solver.outEpsilon(self.mesh)[0])
150
151 def testRefractiveIndex(self):
152 self.assertAlmostEqual(3., self.solver.outRefractiveIndex(self.mesh)[0])
153 self.assertAlmostEqual(1., self.solver.outRefractiveIndex('ll', self.mesh)[0])
154 self.assertAlmostEqual(2., self.solver.outRefractiveIndex('tt', self.mesh, 'default')[0])
155 self.assertAlmostEqual(3., self.solver.outRefractiveIndex('vv', self.mesh)[0])
156 self.assertAlmostEqual(1., self.solver.outRefractiveIndex('xx', self.mesh)[0])
157 self.assertAlmostEqual(2., self.solver.outRefractiveIndex('yy', self.mesh)[0])
158 self.assertAlmostEqual(3., self.solver.outRefractiveIndex('zz', self.mesh)[0])
159
160
161 class ProviderTest(unittest.TestCase):
162
163 @staticmethod
164 def value(msh, lam, interp):
165 return np.array(len(msh) * [lam.imag], dtype=complex)
166
167 def setUp(self):
168 plask.config.axes = 'xyz'
169 self.manager = plask.Manager()
170 self.manager.load('''
171 <plask>
172 <geometry>
173 <cartesian2d axes="yz" name="test2" left="mirror" right="periodic">
174 <stack>
175 <block dy="2" dz="2" material="air"/>
176 <block dy="2" dz="2" material="air" role="inEpsilon"/>
177 <block dy="2" dz="2" material="air"/>
178 </stack>
179 </cartesian2d>
180 <cartesian3d axes="xyz" name="test3" back="mirror" front="periodic" left="mirror" right="periodic">
181 <stack>
182 <block dx="2" dy="2" dz="2" material="air"/>
183 <block dx="2" dy="2" dz="2" material="air" role="inEpsilon"/>
184 <block dx="2" dy="2" dz="2" material="air"/>
185 </stack>
186 </cartesian3d>
187 </geometry>
188 <solvers>
189 <optical name="solver2" solver="Fourier2D">
190 <geometry ref="test2"/>
191 </optical>
192 <optical name="solver3" solver="Fourier3D">
193 <geometry ref="test3"/>
194 </optical>
195 </solvers>
196 </plask>''')
197 self.solver2 = self.manager.solvers.solver2
198 self.solver2.wavelength = 1000 + 4j
199 self.mesh2 = mesh.Rectangular2D([1.0], [3.0])
200 self.solver3 = self.manager.solvers.solver3
201 self.solver3.wavelength = 1000 + 9j
202 self.mesh3 = mesh.Rectangular3D([1.0], [1.0], [3.0])
203 self.solver2.inEpsilon = flow.EpsilonProvider2D(self.value)
204 self.solver3.inEpsilon = flow.EpsilonProvider3D(self.value)
205
206 def test2D(self):
207 self.assertAlmostEqual(2., self.solver2.outRefractiveIndex(self.mesh2)[0])
208
209 def test3D(self):
210 self.assertAlmostEqual(3., self.solver3.outRefractiveIndex(self.mesh3)[0])