ElectroMagneticPython 1.3.0__tar.gz → 2.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/EMpy/RCWA.py +242 -146
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/EMpy/__init__.py +16 -8
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/EMpy/constants.py +3 -3
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/EMpy/devices.py +228 -161
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/EMpy/materials.py +77 -52
- ElectroMagneticPython-2.1.4/EMpy/modesolvers/FD.py +2536 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/EMpy/modesolvers/FMM.py +1121 -808
- ElectroMagneticPython-2.1.4/EMpy/modesolvers/__init__.py +13 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/EMpy/modesolvers/geometries.py +74 -72
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/EMpy/modesolvers/interface.py +28 -27
- ElectroMagneticPython-2.1.4/EMpy/scattering.py +236 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/EMpy/transfer_matrix.py +179 -136
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/EMpy/utils.py +387 -265
- ElectroMagneticPython-2.1.4/EMpy/version.py +1 -0
- ElectroMagneticPython-2.1.4/ElectroMagneticPython.egg-info/PKG-INFO +92 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/ElectroMagneticPython.egg-info/SOURCES.txt +3 -0
- ElectroMagneticPython-2.1.4/ElectroMagneticPython.egg-info/requires.txt +3 -0
- ElectroMagneticPython-2.1.4/LICENSE +21 -0
- ElectroMagneticPython-2.1.4/PKG-INFO +92 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/README.rst +6 -10
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/examples/ex_APRR.py +5 -5
- ElectroMagneticPython-2.1.4/examples/ex_NRR.py +38 -0
- ElectroMagneticPython-2.1.4/examples/ex_RCWA.py +96 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/examples/ex_RCWA_2.py +19 -19
- ElectroMagneticPython-2.1.4/examples/ex_RCWA_3.py +58 -0
- ElectroMagneticPython-2.1.4/examples/ex_SRR.py +21 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/examples/ex_laser_etch_monitor.py +63 -43
- ElectroMagneticPython-2.1.4/examples/ex_modesolver.py +67 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/examples/ex_modesolver_2.py +25 -17
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/examples/ex_modesolver_3.py +8 -7
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/examples/ex_modesolver_4.py +11 -8
- ElectroMagneticPython-2.1.4/examples/ex_modesolver_dch.py +296 -0
- ElectroMagneticPython-2.1.4/examples/ex_modesolver_dch_anis.py +318 -0
- ElectroMagneticPython-2.1.4/examples/ex_transfer_matrix.py +81 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/examples/ex_transfer_matrix_2.py +18 -11
- ElectroMagneticPython-2.1.4/examples/ex_transfer_matrix_3.py +59 -0
- ElectroMagneticPython-2.1.4/examples/nk.py +1474 -0
- ElectroMagneticPython-2.1.4/requirements.txt +36 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/setup.cfg +2 -1
- ElectroMagneticPython-2.1.4/setup.py +42 -0
- ElectroMagneticPython-2.1.4/tests/__init__.py +1 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/tests/materials_test.py +3 -6
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/tests/utils_test.py +0 -1
- ElectroMagneticPython-1.3.0/EMpy/modesolvers/FD.py +0 -1428
- ElectroMagneticPython-1.3.0/EMpy/modesolvers/__init__.py +0 -15
- ElectroMagneticPython-1.3.0/EMpy/scattering.py +0 -191
- ElectroMagneticPython-1.3.0/EMpy/version.py +0 -1
- ElectroMagneticPython-1.3.0/ElectroMagneticPython.egg-info/PKG-INFO +0 -97
- ElectroMagneticPython-1.3.0/ElectroMagneticPython.egg-info/requires.txt +0 -4
- ElectroMagneticPython-1.3.0/PKG-INFO +0 -97
- ElectroMagneticPython-1.3.0/examples/ex_NRR.py +0 -31
- ElectroMagneticPython-1.3.0/examples/ex_RCWA.py +0 -85
- ElectroMagneticPython-1.3.0/examples/ex_RCWA_3.py +0 -44
- ElectroMagneticPython-1.3.0/examples/ex_SRR.py +0 -23
- ElectroMagneticPython-1.3.0/examples/ex_modesolver.py +0 -42
- ElectroMagneticPython-1.3.0/examples/ex_transfer_matrix.py +0 -46
- ElectroMagneticPython-1.3.0/examples/ex_transfer_matrix_3.py +0 -48
- ElectroMagneticPython-1.3.0/examples/nk.py +0 -1036
- ElectroMagneticPython-1.3.0/requirements.txt +0 -15
- ElectroMagneticPython-1.3.0/setup.py +0 -46
- ElectroMagneticPython-1.3.0/tests/__init__.py +0 -1
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/ElectroMagneticPython.egg-info/dependency_links.txt +0 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/ElectroMagneticPython.egg-info/top_level.txt +0 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/MANIFEST.in +0 -0
- {ElectroMagneticPython-1.3.0 → ElectroMagneticPython-2.1.4}/examples/lc_data.dat +0 -0
|
@@ -12,16 +12,19 @@ for every diffraction order and layer thickness, and an anisotropic
|
|
|
12
12
|
one, only stable for low diffraction orders and thin layers.
|
|
13
13
|
|
|
14
14
|
"""
|
|
15
|
-
from builtins import range
|
|
16
|
-
from builtins import object
|
|
17
|
-
|
|
18
15
|
__author__ = "Lorenzo Bolla"
|
|
19
16
|
|
|
20
17
|
import scipy as S
|
|
21
18
|
from scipy.linalg import toeplitz, inv, eig, solve as linsolve
|
|
22
19
|
from numpy import pi
|
|
23
20
|
|
|
24
|
-
from EMpy.utils import
|
|
21
|
+
from EMpy.utils import (
|
|
22
|
+
cond,
|
|
23
|
+
warning,
|
|
24
|
+
BinaryGrating,
|
|
25
|
+
SymmetricDoubleGrating,
|
|
26
|
+
AsymmetricDoubleGrating,
|
|
27
|
+
)
|
|
25
28
|
|
|
26
29
|
|
|
27
30
|
def dispersion_relation_ordinary(kx, ky, k, nO):
|
|
@@ -35,9 +38,9 @@ def dispersion_relation_ordinary(kx, ky, k, nO):
|
|
|
35
38
|
"""
|
|
36
39
|
|
|
37
40
|
if kx.shape != ky.shape:
|
|
38
|
-
raise ValueError(
|
|
41
|
+
raise ValueError("kx and ky must have the same length")
|
|
39
42
|
|
|
40
|
-
delta = (k * nO) ** 2 - (kx
|
|
43
|
+
delta = (k * nO) ** 2 - (kx**2 + ky**2)
|
|
41
44
|
kz = S.sqrt(delta)
|
|
42
45
|
|
|
43
46
|
# Adjust sign of real/imag part
|
|
@@ -59,19 +62,26 @@ def dispersion_relation_extraordinary(kx, ky, k, nO, nE, c):
|
|
|
59
62
|
|
|
60
63
|
if kx.shape != ky.shape or c.size != 3:
|
|
61
64
|
raise ValueError(
|
|
62
|
-
|
|
65
|
+
"kx and ky must have the same length and c must have 3 components"
|
|
66
|
+
)
|
|
63
67
|
|
|
64
68
|
kz = S.empty_like(kx)
|
|
65
69
|
|
|
66
70
|
for ii in range(0, kx.size):
|
|
67
71
|
|
|
68
|
-
alpha = nE
|
|
72
|
+
alpha = nE**2 - nO**2
|
|
69
73
|
beta = kx[ii] / k * c[0] + ky[ii] / k * c[1]
|
|
70
74
|
|
|
71
75
|
# coeffs
|
|
72
|
-
C = S.array(
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
C = S.array(
|
|
77
|
+
[
|
|
78
|
+
nO**2 + c[2] ** 2 * alpha,
|
|
79
|
+
2.0 * c[2] * beta * alpha,
|
|
80
|
+
nO**2 * (kx[ii] ** 2 + ky[ii] ** 2) / k**2
|
|
81
|
+
+ alpha * beta**2
|
|
82
|
+
- nO**2 * nE**2,
|
|
83
|
+
]
|
|
84
|
+
)
|
|
75
85
|
|
|
76
86
|
# two solutions of type +x or -x, purely real or purely imag
|
|
77
87
|
tmp_kz = k * S.roots(C)
|
|
@@ -85,7 +95,7 @@ def dispersion_relation_extraordinary(kx, ky, k, nO, nE, c):
|
|
|
85
95
|
return kz
|
|
86
96
|
|
|
87
97
|
|
|
88
|
-
class RCWA
|
|
98
|
+
class RCWA:
|
|
89
99
|
|
|
90
100
|
"""Class to handle the RCWA solvers.
|
|
91
101
|
|
|
@@ -136,9 +146,16 @@ class RCWA(object):
|
|
|
136
146
|
def get_pitch(self):
|
|
137
147
|
"""Inspect the multilayer to check that all the binary
|
|
138
148
|
gratings present have the same pitch, and return it."""
|
|
139
|
-
idx = S.where(
|
|
140
|
-
|
|
141
|
-
|
|
149
|
+
idx = S.where(
|
|
150
|
+
[
|
|
151
|
+
(
|
|
152
|
+
isinstance(m, BinaryGrating)
|
|
153
|
+
| isinstance(m, SymmetricDoubleGrating)
|
|
154
|
+
| isinstance(m, AsymmetricDoubleGrating)
|
|
155
|
+
)
|
|
156
|
+
for m in self.multilayer
|
|
157
|
+
]
|
|
158
|
+
)[0]
|
|
142
159
|
if idx.size == 0:
|
|
143
160
|
# warning('no BinaryGratings: better use a simple transfer matrix.')
|
|
144
161
|
return 1.0 # return LAMBDA: any value will do
|
|
@@ -146,8 +163,7 @@ class RCWA(object):
|
|
|
146
163
|
# check that all the pitches are the same!
|
|
147
164
|
l = S.asarray([self.multilayer[i].pitch for i in idx])
|
|
148
165
|
if not S.all(l == l[0]):
|
|
149
|
-
raise ValueError(
|
|
150
|
-
'All the BinaryGratings must have the same pitch.')
|
|
166
|
+
raise ValueError("All the BinaryGratings must have the same pitch.")
|
|
151
167
|
else:
|
|
152
168
|
return l[0]
|
|
153
169
|
|
|
@@ -194,15 +210,14 @@ class IsotropicRCWA(RCWA):
|
|
|
194
210
|
|
|
195
211
|
# grating vector (on the xz plane)
|
|
196
212
|
# grating on the xy plane
|
|
197
|
-
K = 2 * pi / LAMBDA *
|
|
198
|
-
S.array([S.sin(phi), 0., S.cos(phi)], dtype=complex)
|
|
213
|
+
K = 2 * pi / LAMBDA * S.array([S.sin(phi), 0.0, S.cos(phi)], dtype=complex)
|
|
199
214
|
|
|
200
215
|
DE1 = S.zeros((nood, self.wls.size))
|
|
201
216
|
DE3 = S.zeros_like(DE1)
|
|
202
217
|
|
|
203
|
-
dirk1 = S.array(
|
|
204
|
-
|
|
205
|
-
|
|
218
|
+
dirk1 = S.array(
|
|
219
|
+
[S.sin(alpha) * S.cos(delta), S.sin(alpha) * S.sin(delta), S.cos(alpha)]
|
|
220
|
+
)
|
|
206
221
|
|
|
207
222
|
# usefull matrices
|
|
208
223
|
I = S.eye(i.size)
|
|
@@ -250,24 +265,22 @@ class IsotropicRCWA(RCWA):
|
|
|
250
265
|
|
|
251
266
|
Kx = S.diag(kx / k)
|
|
252
267
|
Ky = ky / k * I
|
|
253
|
-
Z1 = S.diag(k1i[2, :] / (k * n1
|
|
268
|
+
Z1 = S.diag(k1i[2, :] / (k * n1**2))
|
|
254
269
|
Y1 = S.diag(k1i[2, :] / k)
|
|
255
|
-
Z3 = S.diag(k3i[2, :] / (k * n3
|
|
270
|
+
Z3 = S.diag(k3i[2, :] / (k * n3**2))
|
|
256
271
|
Y3 = S.diag(k3i[2, :] / k)
|
|
257
272
|
# Fc = S.diag(S.cos(phi_i))
|
|
258
273
|
fc = S.cos(phi_i)
|
|
259
274
|
# Fs = S.diag(S.sin(phi_i))
|
|
260
275
|
fs = S.sin(phi_i)
|
|
261
276
|
|
|
262
|
-
MR = S.asarray(
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
[ZERO, -1j * Z1]]))
|
|
277
|
+
MR = S.asarray(
|
|
278
|
+
S.bmat([[I, ZERO], [-1j * Y1, ZERO], [ZERO, I], [ZERO, -1j * Z1]])
|
|
279
|
+
)
|
|
266
280
|
|
|
267
|
-
MT = S.asarray(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
[ZERO, 1j * Z3]]))
|
|
281
|
+
MT = S.asarray(
|
|
282
|
+
S.bmat([[I, ZERO], [1j * Y3, ZERO], [ZERO, I], [ZERO, 1j * Z3]])
|
|
283
|
+
)
|
|
271
284
|
|
|
272
285
|
# internal layers (grating or layer)
|
|
273
286
|
X.fill(0.0)
|
|
@@ -278,8 +291,7 @@ class IsotropicRCWA(RCWA):
|
|
|
278
291
|
layer = multilayer[nlayer]
|
|
279
292
|
d = layer.thickness
|
|
280
293
|
|
|
281
|
-
EPS2, EPS21 = layer.getEPSFourierCoeffs(
|
|
282
|
-
wl, n, anisotropic=False)
|
|
294
|
+
EPS2, EPS21 = layer.getEPSFourierCoeffs(wl, n, anisotropic=False)
|
|
283
295
|
|
|
284
296
|
E = toeplitz(EPS2[hmax::-1], EPS2[hmax:])
|
|
285
297
|
E1 = toeplitz(EPS21[hmax::-1], EPS21[hmax:])
|
|
@@ -296,7 +308,7 @@ class IsotropicRCWA(RCWA):
|
|
|
296
308
|
# non sono invertibili --> cambio leggermente i kx... ma dovrei invece
|
|
297
309
|
# trattare separatamente (analiticamente) questi casi
|
|
298
310
|
if cond(A) > 1e10:
|
|
299
|
-
warning(
|
|
311
|
+
warning("BAD CONDITIONING: randomization of kx")
|
|
300
312
|
while cond(A) > 1e10:
|
|
301
313
|
Kx = Kx * (1 + 1e-9 * S.rand())
|
|
302
314
|
B = kx[:, S.newaxis] / k * linsolve(E, Kx) - I
|
|
@@ -305,7 +317,8 @@ class IsotropicRCWA(RCWA):
|
|
|
305
317
|
if S.absolute(K[2] / k) > 1e-10:
|
|
306
318
|
|
|
307
319
|
raise ValueError(
|
|
308
|
-
|
|
320
|
+
"First Order Helmholtz Operator not implemented, yet!"
|
|
321
|
+
)
|
|
309
322
|
|
|
310
323
|
elif ky == 0 or S.allclose(S.diag(Ky / ky * k), 1):
|
|
311
324
|
|
|
@@ -313,8 +326,11 @@ class IsotropicRCWA(RCWA):
|
|
|
313
326
|
# H_U_reduced = S.dot(Ky, Ky) + A
|
|
314
327
|
H_U_reduced = (ky / k) ** 2 * I + A
|
|
315
328
|
# H_S_reduced = S.dot(Ky, Ky) + S.dot(Kx, linsolve(E, S.dot(Kx, E11))) - E11
|
|
316
|
-
H_S_reduced = (
|
|
317
|
-
|
|
329
|
+
H_S_reduced = (
|
|
330
|
+
(ky / k) ** 2 * I
|
|
331
|
+
+ kx[:, S.newaxis] / k * linsolve(E, kx[:, S.newaxis] / k * E11)
|
|
332
|
+
- E11
|
|
333
|
+
)
|
|
318
334
|
|
|
319
335
|
q1, W1 = eig(H_U_reduced)
|
|
320
336
|
q1 = S.sqrt(q1)
|
|
@@ -347,10 +363,16 @@ class IsotropicRCWA(RCWA):
|
|
|
347
363
|
# Vps = S.dot(Fs, V11)
|
|
348
364
|
Vps = fs[:, S.newaxis] * V11
|
|
349
365
|
|
|
350
|
-
Mc2bar = S.asarray(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
366
|
+
Mc2bar = S.asarray(
|
|
367
|
+
S.bmat(
|
|
368
|
+
[
|
|
369
|
+
[Vss, Vsp, Vss, Vsp],
|
|
370
|
+
[Wss, Wsp, -Wss, -Wsp],
|
|
371
|
+
[Wps, Wpp, -Wps, -Wpp],
|
|
372
|
+
[Vps, Vpp, Vps, Vpp],
|
|
373
|
+
]
|
|
374
|
+
)
|
|
375
|
+
)
|
|
354
376
|
|
|
355
377
|
x = S.r_[S.exp(-k * q1 * d), S.exp(-k * q2 * d)]
|
|
356
378
|
|
|
@@ -361,28 +383,29 @@ class IsotropicRCWA(RCWA):
|
|
|
361
383
|
X[:, :, nlayer] = S.diag(x)
|
|
362
384
|
|
|
363
385
|
MTp = linsolve(Mc2bar, MT)
|
|
364
|
-
MTp1[:, :, nlayer] = MTp[0:2 * nood, :]
|
|
365
|
-
MTp2 = MTp[2 * nood:, :]
|
|
386
|
+
MTp1[:, :, nlayer] = MTp[0 : 2 * nood, :]
|
|
387
|
+
MTp2 = MTp[2 * nood :, :]
|
|
366
388
|
|
|
367
389
|
MT = S.dot(
|
|
368
|
-
Mc1,
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
390
|
+
Mc1,
|
|
391
|
+
S.r_[
|
|
392
|
+
I2,
|
|
393
|
+
S.dot(MTp2, linsolve(MTp1[:, :, nlayer], X[:, :, nlayer])),
|
|
394
|
+
],
|
|
395
|
+
)
|
|
374
396
|
|
|
375
397
|
else:
|
|
376
398
|
|
|
377
|
-
ValueError(
|
|
378
|
-
'Second Order Helmholtz Operator not implemented, yet!')
|
|
399
|
+
ValueError("Second Order Helmholtz Operator not implemented, yet!")
|
|
379
400
|
|
|
380
401
|
# M = S.asarray(S.bmat([-MR, MT]))
|
|
381
402
|
M = S.c_[-MR, MT]
|
|
382
|
-
b = S.r_[
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
403
|
+
b = S.r_[
|
|
404
|
+
S.sin(psi) * dlt,
|
|
405
|
+
1j * S.sin(psi) * n1 * S.cos(alpha) * dlt,
|
|
406
|
+
-1j * S.cos(psi) * n1 * dlt,
|
|
407
|
+
S.cos(psi) * S.cos(alpha) * dlt,
|
|
408
|
+
]
|
|
386
409
|
|
|
387
410
|
x = linsolve(M, b)
|
|
388
411
|
R, T = S.split(x, 2)
|
|
@@ -391,12 +414,12 @@ class IsotropicRCWA(RCWA):
|
|
|
391
414
|
T = S.dot(linsolve(MTp1[:, :, ii], X[:, :, ii]), T)
|
|
392
415
|
Ts, Tp = S.split(T, 2)
|
|
393
416
|
|
|
394
|
-
DE1[:, iwl] = (k1i[2, :] / (k1[2])).real * S.absolute(Rs) ** 2 +
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
DE3[:, iwl] = (k3i[2, :] / (k1[2])).real * S.absolute(Ts) ** 2 +
|
|
398
|
-
|
|
399
|
-
|
|
417
|
+
DE1[:, iwl] = (k1i[2, :] / (k1[2])).real * S.absolute(Rs) ** 2 + (
|
|
418
|
+
k1i[2, :] / (k1[2] * n1**2)
|
|
419
|
+
).real * S.absolute(Rp) ** 2
|
|
420
|
+
DE3[:, iwl] = (k3i[2, :] / (k1[2])).real * S.absolute(Ts) ** 2 + (
|
|
421
|
+
k3i[2, :] / (k1[2] * n3**2)
|
|
422
|
+
).real * S.absolute(Tp) ** 2
|
|
400
423
|
|
|
401
424
|
# save the results
|
|
402
425
|
self.DE1 = DE1
|
|
@@ -416,14 +439,18 @@ class IsotropicRCWA(RCWA):
|
|
|
416
439
|
# raw_input('press enter to close the graph...')
|
|
417
440
|
|
|
418
441
|
def __str__(self):
|
|
419
|
-
return
|
|
420
|
-
|
|
442
|
+
return (
|
|
443
|
+
"ISOTROPIC RCWA SOLVER\n\n%s\n\nLAMBDA = %g\nalpha = %g\ndelta = %g\npsi = %g\nphi = %g\nn = %d"
|
|
444
|
+
% (
|
|
445
|
+
self.multilayer.__str__(),
|
|
421
446
|
self.LAMBDA,
|
|
422
447
|
self.alpha,
|
|
423
448
|
self.delta,
|
|
424
449
|
self.psi,
|
|
425
450
|
self.phi,
|
|
426
|
-
self.n
|
|
451
|
+
self.n,
|
|
452
|
+
)
|
|
453
|
+
)
|
|
427
454
|
|
|
428
455
|
|
|
429
456
|
class AnisotropicRCWA(RCWA):
|
|
@@ -461,20 +488,22 @@ class AnisotropicRCWA(RCWA):
|
|
|
461
488
|
DEE1 = S.zeros_like(DEO1)
|
|
462
489
|
DEE3 = S.zeros_like(DEO1)
|
|
463
490
|
|
|
464
|
-
c1 = S.array([1
|
|
465
|
-
c3 = S.array([1
|
|
491
|
+
c1 = S.array([1.0, 0.0, 0.0])
|
|
492
|
+
c3 = S.array([1.0, 0.0, 0.0])
|
|
466
493
|
# grating on the xy plane
|
|
467
|
-
K = 2 * pi / LAMBDA *
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
S.cos(alpha)])
|
|
494
|
+
K = 2 * pi / LAMBDA * S.array([S.sin(phi), 0.0, S.cos(phi)], dtype=complex)
|
|
495
|
+
dirk1 = S.array(
|
|
496
|
+
[S.sin(alpha) * S.cos(delta), S.sin(alpha) * S.sin(delta), S.cos(alpha)]
|
|
497
|
+
)
|
|
472
498
|
|
|
473
499
|
# D polarization vector
|
|
474
|
-
u = S.array(
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
500
|
+
u = S.array(
|
|
501
|
+
[
|
|
502
|
+
S.cos(psi) * S.cos(alpha) * S.cos(delta) - S.sin(psi) * S.sin(delta),
|
|
503
|
+
S.cos(psi) * S.cos(alpha) * S.sin(delta) + S.sin(psi) * S.cos(delta),
|
|
504
|
+
-S.cos(psi) * S.sin(alpha),
|
|
505
|
+
]
|
|
506
|
+
)
|
|
478
507
|
|
|
479
508
|
kO1i = S.zeros((3, i.size), dtype=complex)
|
|
480
509
|
kE1i = S.zeros_like(kO1i)
|
|
@@ -508,39 +537,26 @@ class AnisotropicRCWA(RCWA):
|
|
|
508
537
|
|
|
509
538
|
kO1i[0, :] = k1[0] - i * K[0]
|
|
510
539
|
kO1i[1, :] = k1[1] * S.ones_like(i)
|
|
511
|
-
kO1i[2, :] = -
|
|
512
|
-
dispersion_relation_ordinary(kO1i[0, :], kO1i[1, :], k, nO1)
|
|
540
|
+
kO1i[2, :] = -dispersion_relation_ordinary(kO1i[0, :], kO1i[1, :], k, nO1)
|
|
513
541
|
|
|
514
542
|
kE1i[0, :] = kO1i[0, :]
|
|
515
543
|
kE1i[1, :] = kO1i[1, :]
|
|
516
|
-
kE1i[2,
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
kE1i[1,
|
|
520
|
-
:],
|
|
521
|
-
k,
|
|
522
|
-
nO1,
|
|
523
|
-
nE1,
|
|
524
|
-
c1)
|
|
544
|
+
kE1i[2, :] = -dispersion_relation_extraordinary(
|
|
545
|
+
kE1i[0, :], kE1i[1, :], k, nO1, nE1, c1
|
|
546
|
+
)
|
|
525
547
|
|
|
526
548
|
kO3i[0, :] = kO1i[0, :]
|
|
527
549
|
kO3i[1, :] = kO1i[1, :]
|
|
528
|
-
kO3i[
|
|
529
|
-
2, :] = dispersion_relation_ordinary(
|
|
530
|
-
kO3i[
|
|
531
|
-
0, :], kO3i[
|
|
532
|
-
1, :], k, nO3)
|
|
550
|
+
kO3i[2, :] = dispersion_relation_ordinary(kO3i[0, :], kO3i[1, :], k, nO3)
|
|
533
551
|
|
|
534
552
|
kE3i[0, :] = kO1i[0, :]
|
|
535
553
|
kE3i[1, :] = kO1i[1, :]
|
|
536
|
-
kE3i[
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
0, :], kE3i[
|
|
540
|
-
1, :], k, nO3, nE3, c3)
|
|
554
|
+
kE3i[2, :] = dispersion_relation_extraordinary(
|
|
555
|
+
kE3i[0, :], kE3i[1, :], k, nO3, nE3, c3
|
|
556
|
+
)
|
|
541
557
|
|
|
542
558
|
# k2i = S.r_[[k1[0] - i * K[0]], [k1[1] - i * K[1]], [k1[2] - i * K[2]]]
|
|
543
|
-
k2i = S.r_[[k1[0] - i * K[0]], [k1[1] - i * K[1]], [-
|
|
559
|
+
k2i = S.r_[[k1[0] - i * K[0]], [k1[1] - i * K[1]], [-i * K[2]]]
|
|
544
560
|
|
|
545
561
|
# aliases for constant wavevectors
|
|
546
562
|
kx = kO1i[0, :] # o kE1i(1,;), tanto e' lo stesso
|
|
@@ -581,8 +597,12 @@ class AnisotropicRCWA(RCWA):
|
|
|
581
597
|
ETE = c3[2] * Kx - c3[0] * KE3z
|
|
582
598
|
FTE = c3[0] * Ky - c3[1] * Kx
|
|
583
599
|
|
|
584
|
-
b = S.r_[
|
|
585
|
-
|
|
600
|
+
b = S.r_[
|
|
601
|
+
u[0] * dlt,
|
|
602
|
+
u[1] * dlt,
|
|
603
|
+
(k1[1] / k * u[2] - k1[2] / k * u[1]) * dlt,
|
|
604
|
+
(k1[2] / k * u[0] - k1[0] / k * u[2]) * dlt,
|
|
605
|
+
]
|
|
586
606
|
Ky_CRO_1 = ky / k * CRO_1
|
|
587
607
|
Ky_CRE_1 = ky / k * CRE_1
|
|
588
608
|
Kx_CRO_1 = kx[:, S.newaxis] / k * CRO_1
|
|
@@ -595,10 +615,16 @@ class AnisotropicRCWA(RCWA):
|
|
|
595
615
|
MR42 = S.dot(Kx_CRO_1, BRO)
|
|
596
616
|
MR43 = S.dot(Kx_CRE_1, ARE) + KE1z
|
|
597
617
|
MR44 = S.dot(Kx_CRE_1, BRE)
|
|
598
|
-
MR = S.asarray(
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
618
|
+
MR = S.asarray(
|
|
619
|
+
S.bmat(
|
|
620
|
+
[
|
|
621
|
+
[I, ZERO, I, ZERO],
|
|
622
|
+
[ZERO, I, ZERO, I],
|
|
623
|
+
[MR31, MR32, MR33, MR34],
|
|
624
|
+
[MR41, MR42, MR43, MR44],
|
|
625
|
+
]
|
|
626
|
+
)
|
|
627
|
+
)
|
|
602
628
|
|
|
603
629
|
Ky_CTO_1 = ky / k * CTO_1
|
|
604
630
|
Ky_CTE_1 = ky / k * CTE_1
|
|
@@ -612,10 +638,16 @@ class AnisotropicRCWA(RCWA):
|
|
|
612
638
|
MT42 = S.dot(Kx_CTO_1, BTO)
|
|
613
639
|
MT43 = S.dot(Kx_CTE_1, ATE) + KE3z
|
|
614
640
|
MT44 = S.dot(Kx_CTE_1, BTE)
|
|
615
|
-
MT = S.asarray(
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
641
|
+
MT = S.asarray(
|
|
642
|
+
S.bmat(
|
|
643
|
+
[
|
|
644
|
+
[I, ZERO, I, ZERO],
|
|
645
|
+
[ZERO, I, ZERO, I],
|
|
646
|
+
[MT31, MT32, MT33, MT34],
|
|
647
|
+
[MT41, MT42, MT43, MT44],
|
|
648
|
+
]
|
|
649
|
+
)
|
|
650
|
+
)
|
|
619
651
|
|
|
620
652
|
Mp.fill(0.0)
|
|
621
653
|
M.fill(0.0)
|
|
@@ -625,32 +657,31 @@ class AnisotropicRCWA(RCWA):
|
|
|
625
657
|
layer = multilayer[nlayer]
|
|
626
658
|
thickness = layer.thickness
|
|
627
659
|
|
|
628
|
-
EPS2, EPS21 = layer.getEPSFourierCoeffs(
|
|
629
|
-
wl, n, anisotropic=True)
|
|
660
|
+
EPS2, EPS21 = layer.getEPSFourierCoeffs(wl, n, anisotropic=True)
|
|
630
661
|
|
|
631
662
|
# Exx = S.squeeze(EPS2[0, 0, :])
|
|
632
663
|
# Exx = toeplitz(S.flipud(Exx[0:hmax + 1]), Exx[hmax:])
|
|
633
664
|
Exy = S.squeeze(EPS2[0, 1, :])
|
|
634
|
-
Exy = toeplitz(S.flipud(Exy[0:hmax + 1]), Exy[hmax:])
|
|
665
|
+
Exy = toeplitz(S.flipud(Exy[0 : hmax + 1]), Exy[hmax:])
|
|
635
666
|
Exz = S.squeeze(EPS2[0, 2, :])
|
|
636
|
-
Exz = toeplitz(S.flipud(Exz[0:hmax + 1]), Exz[hmax:])
|
|
667
|
+
Exz = toeplitz(S.flipud(Exz[0 : hmax + 1]), Exz[hmax:])
|
|
637
668
|
|
|
638
669
|
Eyx = S.squeeze(EPS2[1, 0, :])
|
|
639
|
-
Eyx = toeplitz(S.flipud(Eyx[0:hmax + 1]), Eyx[hmax:])
|
|
670
|
+
Eyx = toeplitz(S.flipud(Eyx[0 : hmax + 1]), Eyx[hmax:])
|
|
640
671
|
Eyy = S.squeeze(EPS2[1, 1, :])
|
|
641
|
-
Eyy = toeplitz(S.flipud(Eyy[0:hmax + 1]), Eyy[hmax:])
|
|
672
|
+
Eyy = toeplitz(S.flipud(Eyy[0 : hmax + 1]), Eyy[hmax:])
|
|
642
673
|
Eyz = S.squeeze(EPS2[1, 2, :])
|
|
643
|
-
Eyz = toeplitz(S.flipud(Eyz[0:hmax + 1]), Eyz[hmax:])
|
|
674
|
+
Eyz = toeplitz(S.flipud(Eyz[0 : hmax + 1]), Eyz[hmax:])
|
|
644
675
|
|
|
645
676
|
Ezx = S.squeeze(EPS2[2, 0, :])
|
|
646
|
-
Ezx = toeplitz(S.flipud(Ezx[0:hmax + 1]), Ezx[hmax:])
|
|
677
|
+
Ezx = toeplitz(S.flipud(Ezx[0 : hmax + 1]), Ezx[hmax:])
|
|
647
678
|
Ezy = S.squeeze(EPS2[2, 1, :])
|
|
648
|
-
Ezy = toeplitz(S.flipud(Ezy[0:hmax + 1]), Ezy[hmax:])
|
|
679
|
+
Ezy = toeplitz(S.flipud(Ezy[0 : hmax + 1]), Ezy[hmax:])
|
|
649
680
|
Ezz = S.squeeze(EPS2[2, 2, :])
|
|
650
|
-
Ezz = toeplitz(S.flipud(Ezz[0:hmax + 1]), Ezz[hmax:])
|
|
681
|
+
Ezz = toeplitz(S.flipud(Ezz[0 : hmax + 1]), Ezz[hmax:])
|
|
651
682
|
|
|
652
683
|
Exx_1 = S.squeeze(EPS21[0, 0, :])
|
|
653
|
-
Exx_1 = toeplitz(S.flipud(Exx_1[0:hmax + 1]), Exx_1[hmax:])
|
|
684
|
+
Exx_1 = toeplitz(S.flipud(Exx_1[0 : hmax + 1]), Exx_1[hmax:])
|
|
654
685
|
Exx_1_1 = inv(Exx_1)
|
|
655
686
|
|
|
656
687
|
# lalanne
|
|
@@ -675,11 +706,16 @@ class AnisotropicRCWA(RCWA):
|
|
|
675
706
|
H42 = -S.dot(Kx, Ky) - Eyx + S.dot(Eyz_Ezz_1, Ezx)
|
|
676
707
|
H43 = -1j * S.dot(Eyz_Ezz_1, Kx)
|
|
677
708
|
H44 = 1j * S.dot(Eyz_Ezz_1, Ky)
|
|
678
|
-
H = 1j * S.diag(S.repeat(S.diag(Kz), 4)) +
|
|
679
|
-
S.
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
709
|
+
H = 1j * S.diag(S.repeat(S.diag(Kz), 4)) + S.asarray(
|
|
710
|
+
S.bmat(
|
|
711
|
+
[
|
|
712
|
+
[H11, H12, H13, H14],
|
|
713
|
+
[H21, H22, H23, H24],
|
|
714
|
+
[H31, H32, H33, H34],
|
|
715
|
+
[H41, H42, H43, H44],
|
|
716
|
+
]
|
|
717
|
+
)
|
|
718
|
+
)
|
|
683
719
|
|
|
684
720
|
q, W = eig(H)
|
|
685
721
|
W1, W2, W3, W4 = S.split(W, 4)
|
|
@@ -721,20 +757,56 @@ class AnisotropicRCWA(RCWA):
|
|
|
721
757
|
|
|
722
758
|
Mtot = S.eye(4 * nood, dtype=complex)
|
|
723
759
|
for nlayer in range(1, nlayers - 1):
|
|
724
|
-
Mtot = S.dot(
|
|
725
|
-
S.dot(Mtot, Mp[:, :, nlayer]), inv(M[:, :, nlayer]))
|
|
760
|
+
Mtot = S.dot(S.dot(Mtot, Mp[:, :, nlayer]), inv(M[:, :, nlayer]))
|
|
726
761
|
|
|
727
762
|
BC_b = S.r_[b, S.zeros_like(b)]
|
|
728
763
|
BC_A1 = S.c_[-MR, S.dot(Mtot, MT)]
|
|
729
|
-
BC_A2 = S.asarray(
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
764
|
+
BC_A2 = S.asarray(
|
|
765
|
+
S.bmat(
|
|
766
|
+
[
|
|
767
|
+
[
|
|
768
|
+
(c1[0] * I - c1[2] * S.dot(CRO_1, ARO)),
|
|
769
|
+
(c1[1] * I - c1[2] * S.dot(CRO_1, BRO)),
|
|
770
|
+
ZERO,
|
|
771
|
+
ZERO,
|
|
772
|
+
ZERO,
|
|
773
|
+
ZERO,
|
|
774
|
+
ZERO,
|
|
775
|
+
ZERO,
|
|
776
|
+
],
|
|
777
|
+
[
|
|
778
|
+
ZERO,
|
|
779
|
+
ZERO,
|
|
780
|
+
(DRE - S.dot(S.dot(FRE, CRE_1), ARE)),
|
|
781
|
+
(ERE - S.dot(S.dot(FRE, CRE_1), BRE)),
|
|
782
|
+
ZERO,
|
|
783
|
+
ZERO,
|
|
784
|
+
ZERO,
|
|
785
|
+
ZERO,
|
|
786
|
+
],
|
|
787
|
+
[
|
|
788
|
+
ZERO,
|
|
789
|
+
ZERO,
|
|
790
|
+
ZERO,
|
|
791
|
+
ZERO,
|
|
792
|
+
(c3[0] * I - c3[2] * S.dot(CTO_1, ATO)),
|
|
793
|
+
(c3[1] * I - c3[2] * S.dot(CTO_1, BTO)),
|
|
794
|
+
ZERO,
|
|
795
|
+
ZERO,
|
|
796
|
+
],
|
|
797
|
+
[
|
|
798
|
+
ZERO,
|
|
799
|
+
ZERO,
|
|
800
|
+
ZERO,
|
|
801
|
+
ZERO,
|
|
802
|
+
ZERO,
|
|
803
|
+
ZERO,
|
|
804
|
+
(DTE - S.dot(S.dot(FTE, CTE_1), ATE)),
|
|
805
|
+
(ETE - S.dot(S.dot(FTE, CTE_1), BTE)),
|
|
806
|
+
],
|
|
807
|
+
]
|
|
808
|
+
)
|
|
809
|
+
)
|
|
738
810
|
|
|
739
811
|
BC_A = S.r_[BC_A1, BC_A2]
|
|
740
812
|
|
|
@@ -748,14 +820,34 @@ class AnisotropicRCWA(RCWA):
|
|
|
748
820
|
TEz = -S.dot(CTE_1, (S.dot(ATE, TEx) + S.dot(BTE, TEy)))
|
|
749
821
|
|
|
750
822
|
denom = (k1[2] - S.dot(u, k1) * u[2]).real
|
|
751
|
-
DEO1[:, iwl] =
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
823
|
+
DEO1[:, iwl] = (
|
|
824
|
+
-(
|
|
825
|
+
(S.absolute(ROx) ** 2 + S.absolute(ROy) ** 2 + S.absolute(ROz) ** 2)
|
|
826
|
+
* S.conj(kO1i[2, :])
|
|
827
|
+
- (ROx * kO1i[0, :] + ROy * kO1i[1, :] + ROz * kO1i[2, :])
|
|
828
|
+
* S.conj(ROz)
|
|
829
|
+
).real
|
|
830
|
+
/ denom
|
|
831
|
+
)
|
|
832
|
+
DEE1[:, iwl] = (
|
|
833
|
+
-(
|
|
834
|
+
(S.absolute(REx) ** 2 + S.absolute(REy) ** 2 + S.absolute(REz) ** 2)
|
|
835
|
+
* S.conj(kE1i[2, :])
|
|
836
|
+
- (REx * kE1i[0, :] + REy * kE1i[1, :] + REz * kE1i[2, :])
|
|
837
|
+
* S.conj(REz)
|
|
838
|
+
).real
|
|
839
|
+
/ denom
|
|
840
|
+
)
|
|
841
|
+
DEO3[:, iwl] = (
|
|
842
|
+
(S.absolute(TOx) ** 2 + S.absolute(TOy) ** 2 + S.absolute(TOz) ** 2)
|
|
843
|
+
* S.conj(kO3i[2, :])
|
|
844
|
+
- (TOx * kO3i[0, :] + TOy * kO3i[1, :] + TOz * kO3i[2, :]) * S.conj(TOz)
|
|
845
|
+
).real / denom
|
|
846
|
+
DEE3[:, iwl] = (
|
|
847
|
+
(S.absolute(TEx) ** 2 + S.absolute(TEy) ** 2 + S.absolute(TEz) ** 2)
|
|
848
|
+
* S.conj(kE3i[2, :])
|
|
849
|
+
- (TEx * kE3i[0, :] + TEy * kE3i[1, :] + TEz * kE3i[2, :]) * S.conj(TEz)
|
|
850
|
+
).real / denom
|
|
759
851
|
|
|
760
852
|
# save the results
|
|
761
853
|
self.DEO1 = DEO1
|
|
@@ -779,11 +871,15 @@ class AnisotropicRCWA(RCWA):
|
|
|
779
871
|
# raw_input('press enter to close the graph...')
|
|
780
872
|
|
|
781
873
|
def __str__(self):
|
|
782
|
-
return
|
|
783
|
-
|
|
874
|
+
return (
|
|
875
|
+
"ANISOTROPIC RCWA SOLVER\n\n%s\n\nLAMBDA = %g\nalpha = %g\ndelta = %g\npsi = %g\nphi = %g\nn = %d"
|
|
876
|
+
% (
|
|
877
|
+
self.multilayer.__str__(),
|
|
784
878
|
self.LAMBDA,
|
|
785
879
|
self.alpha,
|
|
786
880
|
self.delta,
|
|
787
881
|
self.psi,
|
|
788
882
|
self.phi,
|
|
789
|
-
self.n
|
|
883
|
+
self.n,
|
|
884
|
+
)
|
|
885
|
+
)
|
|
@@ -10,13 +10,19 @@ The package contains some useful routines to study electromagnetic problems with
|
|
|
10
10
|
It is based on U{numpy<http://numpy.scipy.org>} and U{scipy<http://www.scipy.org>}.
|
|
11
11
|
|
|
12
12
|
"""
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
__all__ = [
|
|
14
|
+
"constants",
|
|
15
|
+
"devices",
|
|
16
|
+
"materials",
|
|
17
|
+
"modesolvers",
|
|
18
|
+
"RCWA",
|
|
19
|
+
"scattering",
|
|
20
|
+
"transfer_matrix",
|
|
21
|
+
"utils",
|
|
22
|
+
]
|
|
23
|
+
__author__ = "Lorenzo Bolla"
|
|
24
|
+
|
|
25
|
+
from numpy.testing import Tester # type: ignore
|
|
20
26
|
|
|
21
27
|
from . import constants
|
|
22
28
|
from . import devices
|
|
@@ -26,6 +32,8 @@ from . import RCWA
|
|
|
26
32
|
from . import scattering
|
|
27
33
|
from . import transfer_matrix
|
|
28
34
|
from . import utils
|
|
29
|
-
from .version import version
|
|
35
|
+
from .version import version
|
|
36
|
+
|
|
37
|
+
__version__ = version
|
|
30
38
|
|
|
31
39
|
test = Tester().test
|