ElectroMagneticPython 2.1.5__py3-none-any.whl → 2.2.3__py3-none-any.whl
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.
- EMpy/RCWA.py +291 -271
- EMpy/__init__.py +10 -2
- EMpy/_version.py +34 -0
- EMpy/devices.py +10 -33
- EMpy/materials.py +1 -6
- EMpy/modesolvers/FD.py +34 -72
- EMpy/modesolvers/FMM.py +24 -23
- EMpy/modesolvers/__init__.py +1 -0
- EMpy/modesolvers/geometries.py +8 -9
- EMpy/transfer_matrix.py +83 -83
- EMpy/utils.py +12 -24
- electromagneticpython-2.2.3.dist-info/METADATA +99 -0
- electromagneticpython-2.2.3.dist-info/RECORD +44 -0
- {ElectroMagneticPython-2.1.5.dist-info → electromagneticpython-2.2.3.dist-info}/WHEEL +1 -1
- electromagneticpython-2.2.3.dist-info/top_level.txt +4 -0
- examples/ex_APRR.py +18 -0
- examples/ex_NRR.py +40 -0
- examples/ex_RCWA.py +95 -0
- examples/ex_RCWA_2.py +52 -0
- examples/ex_RCWA_3.py +58 -0
- examples/ex_SRR.py +23 -0
- examples/ex_laser_etch_monitor.py +241 -0
- examples/ex_modesolver.py +68 -0
- examples/ex_modesolver_2.py +58 -0
- examples/ex_modesolver_3.py +48 -0
- examples/ex_modesolver_4.py +43 -0
- examples/ex_modesolver_dch.py +296 -0
- examples/ex_modesolver_dch_anis.py +318 -0
- examples/ex_transfer_matrix.py +82 -0
- examples/ex_transfer_matrix_2.py +44 -0
- examples/ex_transfer_matrix_2.py.png +0 -0
- examples/ex_transfer_matrix_3.py +60 -0
- examples/lc_data.dat +27 -0
- examples/nk.py +1468 -0
- scripts/FDTD.py +741 -0
- tests/devices_test.py +31 -0
- tests/materials_test.py +1 -1
- tests/modesolvers_test.py +36 -0
- tests/utils_test.py +9 -5
- EMpy/version.py +0 -1
- ElectroMagneticPython-2.1.5.dist-info/METADATA +0 -95
- ElectroMagneticPython-2.1.5.dist-info/RECORD +0 -22
- ElectroMagneticPython-2.1.5.dist-info/top_level.txt +0 -2
- {ElectroMagneticPython-2.1.5.dist-info → electromagneticpython-2.2.3.dist-info/licenses}/LICENSE +0 -0
EMpy/RCWA.py
CHANGED
|
@@ -12,9 +12,10 @@ 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
|
+
|
|
15
16
|
__author__ = "Lorenzo Bolla"
|
|
16
17
|
|
|
17
|
-
import
|
|
18
|
+
import numpy as np
|
|
18
19
|
from scipy.linalg import toeplitz, inv, eig, solve as linsolve
|
|
19
20
|
from numpy import pi
|
|
20
21
|
|
|
@@ -41,7 +42,7 @@ def dispersion_relation_ordinary(kx, ky, k, nO):
|
|
|
41
42
|
raise ValueError("kx and ky must have the same length")
|
|
42
43
|
|
|
43
44
|
delta = (k * nO) ** 2 - (kx**2 + ky**2)
|
|
44
|
-
kz =
|
|
45
|
+
kz = np.sqrt(delta)
|
|
45
46
|
|
|
46
47
|
# Adjust sign of real/imag part
|
|
47
48
|
kz.real = abs(kz.real)
|
|
@@ -65,14 +66,14 @@ def dispersion_relation_extraordinary(kx, ky, k, nO, nE, c):
|
|
|
65
66
|
"kx and ky must have the same length and c must have 3 components"
|
|
66
67
|
)
|
|
67
68
|
|
|
68
|
-
kz =
|
|
69
|
+
kz = np.empty_like(kx)
|
|
69
70
|
|
|
70
71
|
for ii in range(0, kx.size):
|
|
71
72
|
alpha = nE**2 - nO**2
|
|
72
73
|
beta = kx[ii] / k * c[0] + ky[ii] / k * c[1]
|
|
73
74
|
|
|
74
75
|
# coeffs
|
|
75
|
-
C =
|
|
76
|
+
C = np.array(
|
|
76
77
|
[
|
|
77
78
|
nO**2 + c[2] ** 2 * alpha,
|
|
78
79
|
2.0 * c[2] * beta * alpha,
|
|
@@ -83,19 +84,18 @@ def dispersion_relation_extraordinary(kx, ky, k, nO, nE, c):
|
|
|
83
84
|
)
|
|
84
85
|
|
|
85
86
|
# two solutions of type +x or -x, purely real or purely imag
|
|
86
|
-
tmp_kz = k *
|
|
87
|
+
tmp_kz = k * np.roots(C)
|
|
87
88
|
|
|
88
89
|
# get the negative imaginary part or the positive real one
|
|
89
|
-
if
|
|
90
|
-
kz[ii] =
|
|
90
|
+
if np.any(np.isreal(tmp_kz)):
|
|
91
|
+
kz[ii] = np.absolute(tmp_kz[0])
|
|
91
92
|
else:
|
|
92
|
-
kz[ii] = -1j *
|
|
93
|
+
kz[ii] = -1j * np.absolute(tmp_kz[0])
|
|
93
94
|
|
|
94
95
|
return kz
|
|
95
96
|
|
|
96
97
|
|
|
97
98
|
class RCWA:
|
|
98
|
-
|
|
99
99
|
"""Class to handle the RCWA solvers.
|
|
100
100
|
|
|
101
101
|
NOTE
|
|
@@ -145,7 +145,7 @@ class RCWA:
|
|
|
145
145
|
def get_pitch(self):
|
|
146
146
|
"""Inspect the multilayer to check that all the binary
|
|
147
147
|
gratings present have the same pitch, and return it."""
|
|
148
|
-
idx =
|
|
148
|
+
idx = np.where(
|
|
149
149
|
[
|
|
150
150
|
(
|
|
151
151
|
isinstance(m, BinaryGrating)
|
|
@@ -160,15 +160,14 @@ class RCWA:
|
|
|
160
160
|
return 1.0 # return LAMBDA: any value will do
|
|
161
161
|
else:
|
|
162
162
|
# check that all the pitches are the same!
|
|
163
|
-
l =
|
|
164
|
-
if not
|
|
163
|
+
l = np.asarray([self.multilayer[i].pitch for i in idx])
|
|
164
|
+
if not np.all(l == l[0]):
|
|
165
165
|
raise ValueError("All the BinaryGratings must have the same pitch.")
|
|
166
166
|
else:
|
|
167
167
|
return l[0]
|
|
168
168
|
|
|
169
169
|
|
|
170
170
|
class IsotropicRCWA(RCWA):
|
|
171
|
-
|
|
172
171
|
"""Isotropic RCWA solver."""
|
|
173
172
|
|
|
174
173
|
def solve(self, wls):
|
|
@@ -192,7 +191,7 @@ class IsotropicRCWA(RCWA):
|
|
|
192
191
|
matrix approach", JOSA A, 12(5), 1995
|
|
193
192
|
"""
|
|
194
193
|
|
|
195
|
-
self.wls =
|
|
194
|
+
self.wls = np.atleast_1d(wls)
|
|
196
195
|
|
|
197
196
|
LAMBDA = self.LAMBDA
|
|
198
197
|
n = self.n
|
|
@@ -203,32 +202,36 @@ class IsotropicRCWA(RCWA):
|
|
|
203
202
|
phi = self.phi
|
|
204
203
|
|
|
205
204
|
nlayers = len(multilayer)
|
|
206
|
-
i =
|
|
205
|
+
i = np.arange(-n, n + 1)
|
|
207
206
|
nood = 2 * n + 1
|
|
208
207
|
hmax = nood - 1
|
|
209
208
|
|
|
210
209
|
# grating vector (on the xz plane)
|
|
211
210
|
# grating on the xy plane
|
|
212
|
-
K = 2 * pi / LAMBDA *
|
|
211
|
+
K = 2 * pi / LAMBDA * np.array([np.sin(phi), 0.0, np.cos(phi)], dtype=complex)
|
|
213
212
|
|
|
214
|
-
DE1 =
|
|
215
|
-
DE3 =
|
|
213
|
+
DE1 = np.zeros((nood, self.wls.size))
|
|
214
|
+
DE3 = np.zeros_like(DE1)
|
|
216
215
|
|
|
217
|
-
dirk1 =
|
|
218
|
-
[
|
|
216
|
+
dirk1 = np.array(
|
|
217
|
+
[
|
|
218
|
+
np.sin(alpha) * np.cos(delta),
|
|
219
|
+
np.sin(alpha) * np.sin(delta),
|
|
220
|
+
np.cos(alpha),
|
|
221
|
+
]
|
|
219
222
|
)
|
|
220
223
|
|
|
221
224
|
# usefull matrices
|
|
222
|
-
I =
|
|
223
|
-
I2 =
|
|
224
|
-
ZERO =
|
|
225
|
+
I = np.eye(i.size)
|
|
226
|
+
I2 = np.eye(i.size * 2)
|
|
227
|
+
ZERO = np.zeros_like(I)
|
|
225
228
|
|
|
226
|
-
X =
|
|
227
|
-
MTp1 =
|
|
228
|
-
MTp2 =
|
|
229
|
+
X = np.zeros((2 * nood, 2 * nood, nlayers), dtype=complex)
|
|
230
|
+
MTp1 = np.zeros((2 * nood, 2 * nood, nlayers), dtype=complex)
|
|
231
|
+
MTp2 = np.zeros_like(MTp1)
|
|
229
232
|
|
|
230
|
-
EPS2 =
|
|
231
|
-
EPS21 =
|
|
233
|
+
EPS2 = np.zeros(2 * hmax + 1, dtype=complex)
|
|
234
|
+
EPS21 = np.zeros_like(EPS2)
|
|
232
235
|
|
|
233
236
|
dlt = (i == 0).astype(int)
|
|
234
237
|
|
|
@@ -244,40 +247,40 @@ class IsotropicRCWA(RCWA):
|
|
|
244
247
|
|
|
245
248
|
# all the other wavevectors
|
|
246
249
|
tmp_x = k1[0] - i * K[0]
|
|
247
|
-
tmp_y = k1[1] *
|
|
250
|
+
tmp_y = k1[1] * np.ones_like(i)
|
|
248
251
|
tmp_z = dispersion_relation_ordinary(tmp_x, tmp_y, k, n1)
|
|
249
|
-
k1i =
|
|
252
|
+
k1i = np.r_[[tmp_x], [tmp_y], [tmp_z]]
|
|
250
253
|
|
|
251
|
-
# k2i =
|
|
254
|
+
# k2i = np.r_[[k1[0] - i*K[0]], [k1[1] - i * K[1]], [-i * K[2]]]
|
|
252
255
|
|
|
253
256
|
tmp_z = dispersion_relation_ordinary(tmp_x, tmp_y, k, n3)
|
|
254
|
-
k3i =
|
|
257
|
+
k3i = np.r_[[k1i[0, :]], [k1i[1, :]], [tmp_z]]
|
|
255
258
|
|
|
256
259
|
# aliases for constant wavevectors
|
|
257
260
|
kx = k1i[0, :]
|
|
258
261
|
ky = k1[1]
|
|
259
262
|
|
|
260
263
|
# angles of reflection
|
|
261
|
-
# phi_i =
|
|
262
|
-
phi_i =
|
|
264
|
+
# phi_i = np.arctan2(ky,kx)
|
|
265
|
+
phi_i = np.arctan2(ky, kx.real) # OKKIO
|
|
263
266
|
|
|
264
|
-
Kx =
|
|
267
|
+
Kx = np.diag(kx / k)
|
|
265
268
|
Ky = ky / k * I
|
|
266
|
-
Z1 =
|
|
267
|
-
Y1 =
|
|
268
|
-
Z3 =
|
|
269
|
-
Y3 =
|
|
270
|
-
# Fc =
|
|
271
|
-
fc =
|
|
272
|
-
# Fs =
|
|
273
|
-
fs =
|
|
274
|
-
|
|
275
|
-
MR =
|
|
276
|
-
|
|
269
|
+
Z1 = np.diag(k1i[2, :] / (k * n1**2))
|
|
270
|
+
Y1 = np.diag(k1i[2, :] / k)
|
|
271
|
+
Z3 = np.diag(k3i[2, :] / (k * n3**2))
|
|
272
|
+
Y3 = np.diag(k3i[2, :] / k)
|
|
273
|
+
# Fc = np.diag(np.cos(phi_i))
|
|
274
|
+
fc = np.cos(phi_i)
|
|
275
|
+
# Fs = np.diag(np.sin(phi_i))
|
|
276
|
+
fs = np.sin(phi_i)
|
|
277
|
+
|
|
278
|
+
MR = np.asarray(
|
|
279
|
+
np.bmat([[I, ZERO], [-1j * Y1, ZERO], [ZERO, I], [ZERO, -1j * Z1]])
|
|
277
280
|
)
|
|
278
281
|
|
|
279
|
-
MT =
|
|
280
|
-
|
|
282
|
+
MT = np.asarray(
|
|
283
|
+
np.bmat([[I, ZERO], [1j * Y3, ZERO], [ZERO, I], [ZERO, 1j * Z3]])
|
|
281
284
|
)
|
|
282
285
|
|
|
283
286
|
# internal layers (grating or layer)
|
|
@@ -293,10 +296,10 @@ class IsotropicRCWA(RCWA):
|
|
|
293
296
|
E = toeplitz(EPS2[hmax::-1], EPS2[hmax:])
|
|
294
297
|
E1 = toeplitz(EPS21[hmax::-1], EPS21[hmax:])
|
|
295
298
|
E11 = inv(E1)
|
|
296
|
-
# B =
|
|
297
|
-
B = kx[:,
|
|
298
|
-
# A =
|
|
299
|
-
A =
|
|
299
|
+
# B = np.dot(Kx, linsolve(E,Kx)) - I
|
|
300
|
+
B = kx[:, np.newaxis] / k * linsolve(E, Kx) - I
|
|
301
|
+
# A = np.dot(Kx, Kx) - E
|
|
302
|
+
A = np.diag((kx / k) ** 2) - E
|
|
300
303
|
|
|
301
304
|
# Note: solution bug alfredo
|
|
302
305
|
# randomizzo Kx un po' a caso finche' cond(A) e' piccolo (<1e10)
|
|
@@ -307,59 +310,61 @@ class IsotropicRCWA(RCWA):
|
|
|
307
310
|
if cond(A) > 1e10:
|
|
308
311
|
warning("BAD CONDITIONING: randomization of kx")
|
|
309
312
|
while cond(A) > 1e10:
|
|
310
|
-
Kx = Kx * (1 + 1e-9 *
|
|
311
|
-
B = kx[:,
|
|
312
|
-
A =
|
|
313
|
+
Kx = Kx * (1 + 1e-9 * np.rand())
|
|
314
|
+
B = kx[:, np.newaxis] / k * linsolve(E, Kx) - I
|
|
315
|
+
A = np.diag((kx / k) ** 2) - E
|
|
313
316
|
|
|
314
|
-
if
|
|
317
|
+
if np.absolute(K[2] / k) > 1e-10:
|
|
315
318
|
raise ValueError(
|
|
316
319
|
"First Order Helmholtz Operator not implemented, yet!"
|
|
317
320
|
)
|
|
318
321
|
|
|
319
|
-
elif ky == 0 or
|
|
322
|
+
elif ky == 0 or np.allclose(np.diag(Ky / ky * k), 1):
|
|
320
323
|
# lalanne
|
|
321
|
-
# H_U_reduced =
|
|
324
|
+
# H_U_reduced = np.dot(Ky, Ky) + A
|
|
322
325
|
H_U_reduced = (ky / k) ** 2 * I + A
|
|
323
|
-
# H_S_reduced =
|
|
326
|
+
# H_S_reduced = np.dot(Ky, Ky) + np.dot(Kx, linsolve(E, np.dot(Kx, E11))) - E11
|
|
324
327
|
H_S_reduced = (
|
|
325
328
|
(ky / k) ** 2 * I
|
|
326
|
-
+ kx[:,
|
|
329
|
+
+ kx[:, np.newaxis]
|
|
330
|
+
/ k
|
|
331
|
+
* linsolve(E, kx[:, np.newaxis] / k * E11)
|
|
327
332
|
- E11
|
|
328
333
|
)
|
|
329
334
|
|
|
330
335
|
q1, W1 = eig(H_U_reduced)
|
|
331
|
-
q1 =
|
|
336
|
+
q1 = np.sqrt(q1)
|
|
332
337
|
q2, W2 = eig(H_S_reduced)
|
|
333
|
-
q2 =
|
|
338
|
+
q2 = np.sqrt(q2)
|
|
334
339
|
|
|
335
340
|
# boundary conditions
|
|
336
341
|
|
|
337
|
-
# V11 =
|
|
338
|
-
V11 = linsolve(A, W1) * q1[
|
|
339
|
-
V12 = (ky / k) *
|
|
340
|
-
V21 = (ky / k) *
|
|
341
|
-
# V22 =
|
|
342
|
-
V22 = linsolve(B, W2) * q2[
|
|
343
|
-
|
|
344
|
-
# Vss =
|
|
345
|
-
Vss = fc[:,
|
|
346
|
-
# Wss =
|
|
347
|
-
Wss = fc[:,
|
|
348
|
-
# Vsp =
|
|
349
|
-
Vsp = fc[:,
|
|
350
|
-
# Wsp =
|
|
351
|
-
Wsp = fs[:,
|
|
352
|
-
# Wpp =
|
|
353
|
-
Wpp = fc[:,
|
|
354
|
-
# Vpp =
|
|
355
|
-
Vpp = fc[:,
|
|
356
|
-
# Wps =
|
|
357
|
-
Wps = fc[:,
|
|
358
|
-
# Vps =
|
|
359
|
-
Vps = fs[:,
|
|
360
|
-
|
|
361
|
-
Mc2bar =
|
|
362
|
-
|
|
342
|
+
# V11 = np.dot(linsolve(A, W1), np.diag(q1))
|
|
343
|
+
V11 = linsolve(A, W1) * q1[np.newaxis, :]
|
|
344
|
+
V12 = (ky / k) * np.dot(linsolve(A, Kx), W2)
|
|
345
|
+
V21 = (ky / k) * np.dot(linsolve(B, Kx), linsolve(E, W1))
|
|
346
|
+
# V22 = np.dot(linsolve(B, W2), np.diag(q2))
|
|
347
|
+
V22 = linsolve(B, W2) * q2[np.newaxis, :]
|
|
348
|
+
|
|
349
|
+
# Vss = np.dot(Fc, V11)
|
|
350
|
+
Vss = fc[:, np.newaxis] * V11
|
|
351
|
+
# Wss = np.dot(Fc, W1) + np.dot(Fs, V21)
|
|
352
|
+
Wss = fc[:, np.newaxis] * W1 + fs[:, np.newaxis] * V21
|
|
353
|
+
# Vsp = np.dot(Fc, V12) - np.dot(Fs, W2)
|
|
354
|
+
Vsp = fc[:, np.newaxis] * V12 - fs[:, np.newaxis] * W2
|
|
355
|
+
# Wsp = np.dot(Fs, V22)
|
|
356
|
+
Wsp = fs[:, np.newaxis] * V22
|
|
357
|
+
# Wpp = np.dot(Fc, V22)
|
|
358
|
+
Wpp = fc[:, np.newaxis] * V22
|
|
359
|
+
# Vpp = np.dot(Fc, W2) + np.dot(Fs, V12)
|
|
360
|
+
Vpp = fc[:, np.newaxis] * W2 + fs[:, np.newaxis] * V12
|
|
361
|
+
# Wps = np.dot(Fc, V21) - np.dot(Fs, W1)
|
|
362
|
+
Wps = fc[:, np.newaxis] * V21 - fs[:, np.newaxis] * W1
|
|
363
|
+
# Vps = np.dot(Fs, V11)
|
|
364
|
+
Vps = fs[:, np.newaxis] * V11
|
|
365
|
+
|
|
366
|
+
Mc2bar = np.asarray(
|
|
367
|
+
np.bmat(
|
|
363
368
|
[
|
|
364
369
|
[Vss, Vsp, Vss, Vsp],
|
|
365
370
|
[Wss, Wsp, -Wss, -Wsp],
|
|
@@ -369,51 +374,51 @@ class IsotropicRCWA(RCWA):
|
|
|
369
374
|
)
|
|
370
375
|
)
|
|
371
376
|
|
|
372
|
-
x =
|
|
377
|
+
x = np.r_[np.exp(-k * q1 * d), np.exp(-k * q2 * d)]
|
|
373
378
|
|
|
374
|
-
# Mc1 =
|
|
375
|
-
xx =
|
|
376
|
-
Mc1 = Mc2bar * xx[
|
|
379
|
+
# Mc1 = np.dot(Mc2bar, np.diag(np.r_[np.ones_like(x), x]))
|
|
380
|
+
xx = np.r_[np.ones_like(x), x]
|
|
381
|
+
Mc1 = Mc2bar * xx[np.newaxis, :]
|
|
377
382
|
|
|
378
|
-
X[:, :, nlayer] =
|
|
383
|
+
X[:, :, nlayer] = np.diag(x)
|
|
379
384
|
|
|
380
385
|
MTp = linsolve(Mc2bar, MT)
|
|
381
386
|
MTp1[:, :, nlayer] = MTp[0 : 2 * nood, :]
|
|
382
387
|
MTp2 = MTp[2 * nood :, :]
|
|
383
388
|
|
|
384
|
-
MT =
|
|
389
|
+
MT = np.dot(
|
|
385
390
|
Mc1,
|
|
386
|
-
|
|
391
|
+
np.r_[
|
|
387
392
|
I2,
|
|
388
|
-
|
|
393
|
+
np.dot(MTp2, linsolve(MTp1[:, :, nlayer], X[:, :, nlayer])),
|
|
389
394
|
],
|
|
390
395
|
)
|
|
391
396
|
|
|
392
397
|
else:
|
|
393
398
|
ValueError("Second Order Helmholtz Operator not implemented, yet!")
|
|
394
399
|
|
|
395
|
-
# M =
|
|
396
|
-
M =
|
|
397
|
-
b =
|
|
398
|
-
|
|
399
|
-
1j *
|
|
400
|
-
-1j *
|
|
401
|
-
|
|
400
|
+
# M = np.asarray(np.bmat([-MR, MT]))
|
|
401
|
+
M = np.c_[-MR, MT]
|
|
402
|
+
b = np.r_[
|
|
403
|
+
np.sin(psi) * dlt,
|
|
404
|
+
1j * np.sin(psi) * n1 * np.cos(alpha) * dlt,
|
|
405
|
+
-1j * np.cos(psi) * n1 * dlt,
|
|
406
|
+
np.cos(psi) * np.cos(alpha) * dlt,
|
|
402
407
|
]
|
|
403
408
|
|
|
404
409
|
x = linsolve(M, b)
|
|
405
|
-
R, T =
|
|
406
|
-
Rs, Rp =
|
|
410
|
+
R, T = np.split(x, 2)
|
|
411
|
+
Rs, Rp = np.split(R, 2)
|
|
407
412
|
for ii in range(1, nlayers - 1):
|
|
408
|
-
T =
|
|
409
|
-
Ts, Tp =
|
|
413
|
+
T = np.dot(linsolve(MTp1[:, :, ii], X[:, :, ii]), T)
|
|
414
|
+
Ts, Tp = np.split(T, 2)
|
|
410
415
|
|
|
411
|
-
DE1[:, iwl] = (k1i[2, :] / (k1[2])).real *
|
|
416
|
+
DE1[:, iwl] = (k1i[2, :] / (k1[2])).real * np.absolute(Rs) ** 2 + (
|
|
412
417
|
k1i[2, :] / (k1[2] * n1**2)
|
|
413
|
-
).real *
|
|
414
|
-
DE3[:, iwl] = (k3i[2, :] / (k1[2])).real *
|
|
418
|
+
).real * np.absolute(Rp) ** 2
|
|
419
|
+
DE3[:, iwl] = (k3i[2, :] / (k1[2])).real * np.absolute(Ts) ** 2 + (
|
|
415
420
|
k3i[2, :] / (k1[2] * n3**2)
|
|
416
|
-
).real *
|
|
421
|
+
).real * np.absolute(Tp) ** 2
|
|
417
422
|
|
|
418
423
|
# save the results
|
|
419
424
|
self.DE1 = DE1
|
|
@@ -448,7 +453,6 @@ class IsotropicRCWA(RCWA):
|
|
|
448
453
|
|
|
449
454
|
|
|
450
455
|
class AnisotropicRCWA(RCWA):
|
|
451
|
-
|
|
452
456
|
"""Anisotropic RCWA solver."""
|
|
453
457
|
|
|
454
458
|
def solve(self, wls):
|
|
@@ -462,7 +466,7 @@ class AnisotropicRCWA(RCWA):
|
|
|
462
466
|
and transmitted.
|
|
463
467
|
"""
|
|
464
468
|
|
|
465
|
-
self.wls =
|
|
469
|
+
self.wls = np.atleast_1d(wls)
|
|
466
470
|
|
|
467
471
|
LAMBDA = self.LAMBDA
|
|
468
472
|
n = self.n
|
|
@@ -473,39 +477,45 @@ class AnisotropicRCWA(RCWA):
|
|
|
473
477
|
phi = self.phi
|
|
474
478
|
|
|
475
479
|
nlayers = len(multilayer)
|
|
476
|
-
i =
|
|
480
|
+
i = np.arange(-n, n + 1)
|
|
477
481
|
nood = 2 * n + 1
|
|
478
482
|
hmax = nood - 1
|
|
479
483
|
|
|
480
|
-
DEO1 =
|
|
481
|
-
DEO3 =
|
|
482
|
-
DEE1 =
|
|
483
|
-
DEE3 =
|
|
484
|
+
DEO1 = np.zeros((nood, self.wls.size))
|
|
485
|
+
DEO3 = np.zeros_like(DEO1)
|
|
486
|
+
DEE1 = np.zeros_like(DEO1)
|
|
487
|
+
DEE3 = np.zeros_like(DEO1)
|
|
484
488
|
|
|
485
|
-
c1 =
|
|
486
|
-
c3 =
|
|
489
|
+
c1 = np.array([1.0, 0.0, 0.0])
|
|
490
|
+
c3 = np.array([1.0, 0.0, 0.0])
|
|
487
491
|
# grating on the xy plane
|
|
488
|
-
K = 2 * pi / LAMBDA *
|
|
489
|
-
dirk1 =
|
|
490
|
-
[
|
|
492
|
+
K = 2 * pi / LAMBDA * np.array([np.sin(phi), 0.0, np.cos(phi)], dtype=complex)
|
|
493
|
+
dirk1 = np.array(
|
|
494
|
+
[
|
|
495
|
+
np.sin(alpha) * np.cos(delta),
|
|
496
|
+
np.sin(alpha) * np.sin(delta),
|
|
497
|
+
np.cos(alpha),
|
|
498
|
+
]
|
|
491
499
|
)
|
|
492
500
|
|
|
493
501
|
# D polarization vector
|
|
494
|
-
u =
|
|
502
|
+
u = np.array(
|
|
495
503
|
[
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
504
|
+
np.cos(psi) * np.cos(alpha) * np.cos(delta)
|
|
505
|
+
- np.sin(psi) * np.sin(delta),
|
|
506
|
+
np.cos(psi) * np.cos(alpha) * np.sin(delta)
|
|
507
|
+
+ np.sin(psi) * np.cos(delta),
|
|
508
|
+
-np.cos(psi) * np.sin(alpha),
|
|
499
509
|
]
|
|
500
510
|
)
|
|
501
511
|
|
|
502
|
-
kO1i =
|
|
503
|
-
kE1i =
|
|
504
|
-
kO3i =
|
|
505
|
-
kE3i =
|
|
512
|
+
kO1i = np.zeros((3, i.size), dtype=complex)
|
|
513
|
+
kE1i = np.zeros_like(kO1i)
|
|
514
|
+
kO3i = np.zeros_like(kO1i)
|
|
515
|
+
kE3i = np.zeros_like(kO1i)
|
|
506
516
|
|
|
507
|
-
Mp =
|
|
508
|
-
M =
|
|
517
|
+
Mp = np.zeros((4 * nood, 4 * nood, nlayers), dtype=complex)
|
|
518
|
+
M = np.zeros((4 * nood, 4 * nood, nlayers), dtype=complex)
|
|
509
519
|
|
|
510
520
|
dlt = (i == 0).astype(int)
|
|
511
521
|
|
|
@@ -516,20 +526,20 @@ class AnisotropicRCWA(RCWA):
|
|
|
516
526
|
# wavevectors
|
|
517
527
|
k = 2 * pi / wl
|
|
518
528
|
|
|
519
|
-
eps1 =
|
|
520
|
-
eps3 =
|
|
529
|
+
eps1 = np.diag(np.asarray([nE1, nO1, nO1]) ** 2)
|
|
530
|
+
eps3 = np.diag(np.asarray([nE3, nO3, nO3]) ** 2)
|
|
521
531
|
|
|
522
532
|
# ordinary wave
|
|
523
533
|
abskO1 = k * nO1
|
|
524
534
|
# abskO3 = k * nO3
|
|
525
535
|
# extraordinary wave
|
|
526
|
-
# abskE1 = k * nO1 *nE1 /
|
|
527
|
-
# abskE3 = k * nO3 *nE3 /
|
|
536
|
+
# abskE1 = k * nO1 *nE1 / np.sqrt(nO1**2 + (nE1**2 - nO1**2) * np.dot(-c1, dirk1)**2)
|
|
537
|
+
# abskE3 = k * nO3 *nE3 / np.sqrt(nO3**2 + (nE3**2 - nO3**2) * np.dot(-c3, dirk1)**2)
|
|
528
538
|
|
|
529
539
|
k1 = abskO1 * dirk1
|
|
530
540
|
|
|
531
541
|
kO1i[0, :] = k1[0] - i * K[0]
|
|
532
|
-
kO1i[1, :] = k1[1] *
|
|
542
|
+
kO1i[1, :] = k1[1] * np.ones_like(i)
|
|
533
543
|
kO1i[2, :] = -dispersion_relation_ordinary(kO1i[0, :], kO1i[1, :], k, nO1)
|
|
534
544
|
|
|
535
545
|
kE1i[0, :] = kO1i[0, :]
|
|
@@ -548,23 +558,23 @@ class AnisotropicRCWA(RCWA):
|
|
|
548
558
|
kE3i[0, :], kE3i[1, :], k, nO3, nE3, c3
|
|
549
559
|
)
|
|
550
560
|
|
|
551
|
-
# k2i =
|
|
552
|
-
k2i =
|
|
561
|
+
# k2i = np.r_[[k1[0] - i * K[0]], [k1[1] - i * K[1]], [k1[2] - i * K[2]]]
|
|
562
|
+
k2i = np.r_[[k1[0] - i * K[0]], [k1[1] - i * K[1]], [-i * K[2]]]
|
|
553
563
|
|
|
554
564
|
# aliases for constant wavevectors
|
|
555
565
|
kx = kO1i[0, :] # o kE1i(1,;), tanto e' lo stesso
|
|
556
566
|
ky = k1[1]
|
|
557
567
|
|
|
558
568
|
# matrices
|
|
559
|
-
I =
|
|
560
|
-
ZERO =
|
|
561
|
-
Kx =
|
|
569
|
+
I = np.eye(nood, dtype=complex)
|
|
570
|
+
ZERO = np.zeros((nood, nood), dtype=complex)
|
|
571
|
+
Kx = np.diag(kx / k)
|
|
562
572
|
Ky = ky / k * I
|
|
563
|
-
Kz =
|
|
564
|
-
KO1z =
|
|
565
|
-
KE1z =
|
|
566
|
-
KO3z =
|
|
567
|
-
KE3z =
|
|
573
|
+
Kz = np.diag(k2i[2, :] / k)
|
|
574
|
+
KO1z = np.diag(kO1i[2, :] / k)
|
|
575
|
+
KE1z = np.diag(kE1i[2, :] / k)
|
|
576
|
+
KO3z = np.diag(kO3i[2, :] / k)
|
|
577
|
+
KE3z = np.diag(kE3i[2, :] / k)
|
|
568
578
|
|
|
569
579
|
ARO = Kx * eps1[0, 0] + Ky * eps1[1, 0] + KO1z * eps1[2, 0]
|
|
570
580
|
BRO = Kx * eps1[0, 1] + Ky * eps1[1, 1] + KO1z * eps1[2, 1]
|
|
@@ -590,7 +600,7 @@ class AnisotropicRCWA(RCWA):
|
|
|
590
600
|
ETE = c3[2] * Kx - c3[0] * KE3z
|
|
591
601
|
FTE = c3[0] * Ky - c3[1] * Kx
|
|
592
602
|
|
|
593
|
-
b =
|
|
603
|
+
b = np.r_[
|
|
594
604
|
u[0] * dlt,
|
|
595
605
|
u[1] * dlt,
|
|
596
606
|
(k1[1] / k * u[2] - k1[2] / k * u[1]) * dlt,
|
|
@@ -598,18 +608,18 @@ class AnisotropicRCWA(RCWA):
|
|
|
598
608
|
]
|
|
599
609
|
Ky_CRO_1 = ky / k * CRO_1
|
|
600
610
|
Ky_CRE_1 = ky / k * CRE_1
|
|
601
|
-
Kx_CRO_1 = kx[:,
|
|
602
|
-
Kx_CRE_1 = kx[:,
|
|
603
|
-
MR31 = -
|
|
604
|
-
MR32 = -
|
|
605
|
-
MR33 = -
|
|
606
|
-
MR34 = -
|
|
607
|
-
MR41 =
|
|
608
|
-
MR42 =
|
|
609
|
-
MR43 =
|
|
610
|
-
MR44 =
|
|
611
|
-
MR =
|
|
612
|
-
|
|
611
|
+
Kx_CRO_1 = kx[:, np.newaxis] / k * CRO_1
|
|
612
|
+
Kx_CRE_1 = kx[:, np.newaxis] / k * CRE_1
|
|
613
|
+
MR31 = -np.dot(Ky_CRO_1, ARO)
|
|
614
|
+
MR32 = -np.dot(Ky_CRO_1, BRO) - KO1z
|
|
615
|
+
MR33 = -np.dot(Ky_CRE_1, ARE)
|
|
616
|
+
MR34 = -np.dot(Ky_CRE_1, BRE) - KE1z
|
|
617
|
+
MR41 = np.dot(Kx_CRO_1, ARO) + KO1z
|
|
618
|
+
MR42 = np.dot(Kx_CRO_1, BRO)
|
|
619
|
+
MR43 = np.dot(Kx_CRE_1, ARE) + KE1z
|
|
620
|
+
MR44 = np.dot(Kx_CRE_1, BRE)
|
|
621
|
+
MR = np.asarray(
|
|
622
|
+
np.bmat(
|
|
613
623
|
[
|
|
614
624
|
[I, ZERO, I, ZERO],
|
|
615
625
|
[ZERO, I, ZERO, I],
|
|
@@ -621,18 +631,18 @@ class AnisotropicRCWA(RCWA):
|
|
|
621
631
|
|
|
622
632
|
Ky_CTO_1 = ky / k * CTO_1
|
|
623
633
|
Ky_CTE_1 = ky / k * CTE_1
|
|
624
|
-
Kx_CTO_1 = kx[:,
|
|
625
|
-
Kx_CTE_1 = kx[:,
|
|
626
|
-
MT31 = -
|
|
627
|
-
MT32 = -
|
|
628
|
-
MT33 = -
|
|
629
|
-
MT34 = -
|
|
630
|
-
MT41 =
|
|
631
|
-
MT42 =
|
|
632
|
-
MT43 =
|
|
633
|
-
MT44 =
|
|
634
|
-
MT =
|
|
635
|
-
|
|
634
|
+
Kx_CTO_1 = kx[:, np.newaxis] / k * CTO_1
|
|
635
|
+
Kx_CTE_1 = kx[:, np.newaxis] / k * CTE_1
|
|
636
|
+
MT31 = -np.dot(Ky_CTO_1, ATO)
|
|
637
|
+
MT32 = -np.dot(Ky_CTO_1, BTO) - KO3z
|
|
638
|
+
MT33 = -np.dot(Ky_CTE_1, ATE)
|
|
639
|
+
MT34 = -np.dot(Ky_CTE_1, BTE) - KE3z
|
|
640
|
+
MT41 = np.dot(Kx_CTO_1, ATO) + KO3z
|
|
641
|
+
MT42 = np.dot(Kx_CTO_1, BTO)
|
|
642
|
+
MT43 = np.dot(Kx_CTE_1, ATE) + KE3z
|
|
643
|
+
MT44 = np.dot(Kx_CTE_1, BTE)
|
|
644
|
+
MT = np.asarray(
|
|
645
|
+
np.bmat(
|
|
636
646
|
[
|
|
637
647
|
[I, ZERO, I, ZERO],
|
|
638
648
|
[ZERO, I, ZERO, I],
|
|
@@ -651,55 +661,55 @@ class AnisotropicRCWA(RCWA):
|
|
|
651
661
|
|
|
652
662
|
EPS2, EPS21 = layer.getEPSFourierCoeffs(wl, n, anisotropic=True)
|
|
653
663
|
|
|
654
|
-
# Exx =
|
|
655
|
-
# Exx = toeplitz(
|
|
656
|
-
Exy =
|
|
657
|
-
Exy = toeplitz(
|
|
658
|
-
Exz =
|
|
659
|
-
Exz = toeplitz(
|
|
660
|
-
|
|
661
|
-
Eyx =
|
|
662
|
-
Eyx = toeplitz(
|
|
663
|
-
Eyy =
|
|
664
|
-
Eyy = toeplitz(
|
|
665
|
-
Eyz =
|
|
666
|
-
Eyz = toeplitz(
|
|
667
|
-
|
|
668
|
-
Ezx =
|
|
669
|
-
Ezx = toeplitz(
|
|
670
|
-
Ezy =
|
|
671
|
-
Ezy = toeplitz(
|
|
672
|
-
Ezz =
|
|
673
|
-
Ezz = toeplitz(
|
|
674
|
-
|
|
675
|
-
Exx_1 =
|
|
676
|
-
Exx_1 = toeplitz(
|
|
664
|
+
# Exx = np.squeeze(EPS2[0, 0, :])
|
|
665
|
+
# Exx = toeplitz(np.flipud(Exx[0:hmax + 1]), Exx[hmax:])
|
|
666
|
+
Exy = np.squeeze(EPS2[0, 1, :])
|
|
667
|
+
Exy = toeplitz(np.flipud(Exy[0 : hmax + 1]), Exy[hmax:])
|
|
668
|
+
Exz = np.squeeze(EPS2[0, 2, :])
|
|
669
|
+
Exz = toeplitz(np.flipud(Exz[0 : hmax + 1]), Exz[hmax:])
|
|
670
|
+
|
|
671
|
+
Eyx = np.squeeze(EPS2[1, 0, :])
|
|
672
|
+
Eyx = toeplitz(np.flipud(Eyx[0 : hmax + 1]), Eyx[hmax:])
|
|
673
|
+
Eyy = np.squeeze(EPS2[1, 1, :])
|
|
674
|
+
Eyy = toeplitz(np.flipud(Eyy[0 : hmax + 1]), Eyy[hmax:])
|
|
675
|
+
Eyz = np.squeeze(EPS2[1, 2, :])
|
|
676
|
+
Eyz = toeplitz(np.flipud(Eyz[0 : hmax + 1]), Eyz[hmax:])
|
|
677
|
+
|
|
678
|
+
Ezx = np.squeeze(EPS2[2, 0, :])
|
|
679
|
+
Ezx = toeplitz(np.flipud(Ezx[0 : hmax + 1]), Ezx[hmax:])
|
|
680
|
+
Ezy = np.squeeze(EPS2[2, 1, :])
|
|
681
|
+
Ezy = toeplitz(np.flipud(Ezy[0 : hmax + 1]), Ezy[hmax:])
|
|
682
|
+
Ezz = np.squeeze(EPS2[2, 2, :])
|
|
683
|
+
Ezz = toeplitz(np.flipud(Ezz[0 : hmax + 1]), Ezz[hmax:])
|
|
684
|
+
|
|
685
|
+
Exx_1 = np.squeeze(EPS21[0, 0, :])
|
|
686
|
+
Exx_1 = toeplitz(np.flipud(Exx_1[0 : hmax + 1]), Exx_1[hmax:])
|
|
677
687
|
Exx_1_1 = inv(Exx_1)
|
|
678
688
|
|
|
679
689
|
# lalanne
|
|
680
690
|
Ezz_1 = inv(Ezz)
|
|
681
691
|
Ky_Ezz_1 = ky / k * Ezz_1
|
|
682
|
-
Kx_Ezz_1 = kx[:,
|
|
683
|
-
Exz_Ezz_1 =
|
|
684
|
-
Eyz_Ezz_1 =
|
|
685
|
-
H11 = 1j *
|
|
686
|
-
H12 = 1j *
|
|
687
|
-
H13 =
|
|
688
|
-
H14 = I -
|
|
689
|
-
H21 = 1j *
|
|
690
|
-
H22 = 1j *
|
|
691
|
-
H23 =
|
|
692
|
-
H24 = -
|
|
693
|
-
H31 =
|
|
694
|
-
H32 = Exx_1_1 -
|
|
695
|
-
H33 = 1j *
|
|
696
|
-
H34 = -1j *
|
|
697
|
-
H41 =
|
|
698
|
-
H42 = -
|
|
699
|
-
H43 = -1j *
|
|
700
|
-
H44 = 1j *
|
|
701
|
-
H = 1j *
|
|
702
|
-
|
|
692
|
+
Kx_Ezz_1 = kx[:, np.newaxis] / k * Ezz_1
|
|
693
|
+
Exz_Ezz_1 = np.dot(Exz, Ezz_1)
|
|
694
|
+
Eyz_Ezz_1 = np.dot(Eyz, Ezz_1)
|
|
695
|
+
H11 = 1j * np.dot(Ky_Ezz_1, Ezy)
|
|
696
|
+
H12 = 1j * np.dot(Ky_Ezz_1, Ezx)
|
|
697
|
+
H13 = np.dot(Ky_Ezz_1, Kx)
|
|
698
|
+
H14 = I - np.dot(Ky_Ezz_1, Ky)
|
|
699
|
+
H21 = 1j * np.dot(Kx_Ezz_1, Ezy)
|
|
700
|
+
H22 = 1j * np.dot(Kx_Ezz_1, Ezx)
|
|
701
|
+
H23 = np.dot(Kx_Ezz_1, Kx) - I
|
|
702
|
+
H24 = -np.dot(Kx_Ezz_1, Ky)
|
|
703
|
+
H31 = np.dot(Kx, Ky) + Exy - np.dot(Exz_Ezz_1, Ezy)
|
|
704
|
+
H32 = Exx_1_1 - np.dot(Ky, Ky) - np.dot(Exz_Ezz_1, Ezx)
|
|
705
|
+
H33 = 1j * np.dot(Exz_Ezz_1, Kx)
|
|
706
|
+
H34 = -1j * np.dot(Exz_Ezz_1, Ky)
|
|
707
|
+
H41 = np.dot(Kx, Kx) - Eyy + np.dot(Eyz_Ezz_1, Ezy)
|
|
708
|
+
H42 = -np.dot(Kx, Ky) - Eyx + np.dot(Eyz_Ezz_1, Ezx)
|
|
709
|
+
H43 = -1j * np.dot(Eyz_Ezz_1, Kx)
|
|
710
|
+
H44 = 1j * np.dot(Eyz_Ezz_1, Ky)
|
|
711
|
+
H = 1j * np.diag(np.repeat(np.diag(Kz), 4)) + np.asarray(
|
|
712
|
+
np.bmat(
|
|
703
713
|
[
|
|
704
714
|
[H11, H12, H13, H14],
|
|
705
715
|
[H21, H22, H23, H24],
|
|
@@ -710,7 +720,7 @@ class AnisotropicRCWA(RCWA):
|
|
|
710
720
|
)
|
|
711
721
|
|
|
712
722
|
q, W = eig(H)
|
|
713
|
-
W1, W2, W3, W4 =
|
|
723
|
+
W1, W2, W3, W4 = np.split(W, 4)
|
|
714
724
|
|
|
715
725
|
#
|
|
716
726
|
# boundary conditions
|
|
@@ -727,38 +737,38 @@ class AnisotropicRCWA(RCWA):
|
|
|
727
737
|
# [b] = [-MR Mtot.MT] [R]
|
|
728
738
|
# [0] [...........] [T]
|
|
729
739
|
|
|
730
|
-
z =
|
|
731
|
-
z[
|
|
732
|
-
D =
|
|
733
|
-
Sy0 = W1 * D[
|
|
734
|
-
Sx0 = W2 * D[
|
|
735
|
-
Uy0 = W3 * D[
|
|
736
|
-
Ux0 = W4 * D[
|
|
737
|
-
|
|
738
|
-
z = thickness *
|
|
739
|
-
z[
|
|
740
|
-
D =
|
|
741
|
-
D1 =
|
|
742
|
-
Syd = D1[:,
|
|
743
|
-
Sxd = D1[:,
|
|
744
|
-
Uyd = D1[:,
|
|
745
|
-
Uxd = D1[:,
|
|
746
|
-
|
|
747
|
-
Mp[:, :, nlayer] =
|
|
748
|
-
M[:, :, nlayer] =
|
|
749
|
-
|
|
750
|
-
Mtot =
|
|
740
|
+
z = np.zeros_like(q)
|
|
741
|
+
z[np.where(q.real > 0)] = -thickness
|
|
742
|
+
D = np.exp(k * q * z)
|
|
743
|
+
Sy0 = W1 * D[np.newaxis, :]
|
|
744
|
+
Sx0 = W2 * D[np.newaxis, :]
|
|
745
|
+
Uy0 = W3 * D[np.newaxis, :]
|
|
746
|
+
Ux0 = W4 * D[np.newaxis, :]
|
|
747
|
+
|
|
748
|
+
z = thickness * np.ones_like(q)
|
|
749
|
+
z[np.where(q.real > 0)] = 0
|
|
750
|
+
D = np.exp(k * q * z)
|
|
751
|
+
D1 = np.exp(-1j * k2i[2, :] * thickness)
|
|
752
|
+
Syd = D1[:, np.newaxis] * W1 * D[np.newaxis, :]
|
|
753
|
+
Sxd = D1[:, np.newaxis] * W2 * D[np.newaxis, :]
|
|
754
|
+
Uyd = D1[:, np.newaxis] * W3 * D[np.newaxis, :]
|
|
755
|
+
Uxd = D1[:, np.newaxis] * W4 * D[np.newaxis, :]
|
|
756
|
+
|
|
757
|
+
Mp[:, :, nlayer] = np.r_[Sx0, Sy0, -1j * Ux0, -1j * Uy0]
|
|
758
|
+
M[:, :, nlayer] = np.r_[Sxd, Syd, -1j * Uxd, -1j * Uyd]
|
|
759
|
+
|
|
760
|
+
Mtot = np.eye(4 * nood, dtype=complex)
|
|
751
761
|
for nlayer in range(1, nlayers - 1):
|
|
752
|
-
Mtot =
|
|
762
|
+
Mtot = np.dot(np.dot(Mtot, Mp[:, :, nlayer]), inv(M[:, :, nlayer]))
|
|
753
763
|
|
|
754
|
-
BC_b =
|
|
755
|
-
BC_A1 =
|
|
756
|
-
BC_A2 =
|
|
757
|
-
|
|
764
|
+
BC_b = np.r_[b, np.zeros_like(b)]
|
|
765
|
+
BC_A1 = np.c_[-MR, np.dot(Mtot, MT)]
|
|
766
|
+
BC_A2 = np.asarray(
|
|
767
|
+
np.bmat(
|
|
758
768
|
[
|
|
759
769
|
[
|
|
760
|
-
(c1[0] * I - c1[2] *
|
|
761
|
-
(c1[1] * I - c1[2] *
|
|
770
|
+
(c1[0] * I - c1[2] * np.dot(CRO_1, ARO)),
|
|
771
|
+
(c1[1] * I - c1[2] * np.dot(CRO_1, BRO)),
|
|
762
772
|
ZERO,
|
|
763
773
|
ZERO,
|
|
764
774
|
ZERO,
|
|
@@ -769,8 +779,8 @@ class AnisotropicRCWA(RCWA):
|
|
|
769
779
|
[
|
|
770
780
|
ZERO,
|
|
771
781
|
ZERO,
|
|
772
|
-
(DRE -
|
|
773
|
-
(ERE -
|
|
782
|
+
(DRE - np.dot(np.dot(FRE, CRE_1), ARE)),
|
|
783
|
+
(ERE - np.dot(np.dot(FRE, CRE_1), BRE)),
|
|
774
784
|
ZERO,
|
|
775
785
|
ZERO,
|
|
776
786
|
ZERO,
|
|
@@ -781,8 +791,8 @@ class AnisotropicRCWA(RCWA):
|
|
|
781
791
|
ZERO,
|
|
782
792
|
ZERO,
|
|
783
793
|
ZERO,
|
|
784
|
-
(c3[0] * I - c3[2] *
|
|
785
|
-
(c3[1] * I - c3[2] *
|
|
794
|
+
(c3[0] * I - c3[2] * np.dot(CTO_1, ATO)),
|
|
795
|
+
(c3[1] * I - c3[2] * np.dot(CTO_1, BTO)),
|
|
786
796
|
ZERO,
|
|
787
797
|
ZERO,
|
|
788
798
|
],
|
|
@@ -793,52 +803,62 @@ class AnisotropicRCWA(RCWA):
|
|
|
793
803
|
ZERO,
|
|
794
804
|
ZERO,
|
|
795
805
|
ZERO,
|
|
796
|
-
(DTE -
|
|
797
|
-
(ETE -
|
|
806
|
+
(DTE - np.dot(np.dot(FTE, CTE_1), ATE)),
|
|
807
|
+
(ETE - np.dot(np.dot(FTE, CTE_1), BTE)),
|
|
798
808
|
],
|
|
799
809
|
]
|
|
800
810
|
)
|
|
801
811
|
)
|
|
802
812
|
|
|
803
|
-
BC_A =
|
|
813
|
+
BC_A = np.r_[BC_A1, BC_A2]
|
|
804
814
|
|
|
805
815
|
x = linsolve(BC_A, BC_b)
|
|
806
816
|
|
|
807
|
-
ROx, ROy, REx, REy, TOx, TOy, TEx, TEy =
|
|
817
|
+
ROx, ROy, REx, REy, TOx, TOy, TEx, TEy = np.split(x, 8)
|
|
808
818
|
|
|
809
|
-
ROz = -
|
|
810
|
-
REz = -
|
|
811
|
-
TOz = -
|
|
812
|
-
TEz = -
|
|
819
|
+
ROz = -np.dot(CRO_1, (np.dot(ARO, ROx) + np.dot(BRO, ROy)))
|
|
820
|
+
REz = -np.dot(CRE_1, (np.dot(ARE, REx) + np.dot(BRE, REy)))
|
|
821
|
+
TOz = -np.dot(CTO_1, (np.dot(ATO, TOx) + np.dot(BTO, TOy)))
|
|
822
|
+
TEz = -np.dot(CTE_1, (np.dot(ATE, TEx) + np.dot(BTE, TEy)))
|
|
813
823
|
|
|
814
|
-
denom = (k1[2] -
|
|
824
|
+
denom = (k1[2] - np.dot(u, k1) * u[2]).real
|
|
815
825
|
DEO1[:, iwl] = (
|
|
816
826
|
-(
|
|
817
|
-
(
|
|
818
|
-
|
|
827
|
+
(
|
|
828
|
+
np.absolute(ROx) ** 2
|
|
829
|
+
+ np.absolute(ROy) ** 2
|
|
830
|
+
+ np.absolute(ROz) ** 2
|
|
831
|
+
)
|
|
832
|
+
* np.conj(kO1i[2, :])
|
|
819
833
|
- (ROx * kO1i[0, :] + ROy * kO1i[1, :] + ROz * kO1i[2, :])
|
|
820
|
-
*
|
|
834
|
+
* np.conj(ROz)
|
|
821
835
|
).real
|
|
822
836
|
/ denom
|
|
823
837
|
)
|
|
824
838
|
DEE1[:, iwl] = (
|
|
825
839
|
-(
|
|
826
|
-
(
|
|
827
|
-
|
|
840
|
+
(
|
|
841
|
+
np.absolute(REx) ** 2
|
|
842
|
+
+ np.absolute(REy) ** 2
|
|
843
|
+
+ np.absolute(REz) ** 2
|
|
844
|
+
)
|
|
845
|
+
* np.conj(kE1i[2, :])
|
|
828
846
|
- (REx * kE1i[0, :] + REy * kE1i[1, :] + REz * kE1i[2, :])
|
|
829
|
-
*
|
|
847
|
+
* np.conj(REz)
|
|
830
848
|
).real
|
|
831
849
|
/ denom
|
|
832
850
|
)
|
|
833
851
|
DEO3[:, iwl] = (
|
|
834
|
-
(
|
|
835
|
-
*
|
|
836
|
-
- (TOx * kO3i[0, :] + TOy * kO3i[1, :] + TOz * kO3i[2, :])
|
|
852
|
+
(np.absolute(TOx) ** 2 + np.absolute(TOy) ** 2 + np.absolute(TOz) ** 2)
|
|
853
|
+
* np.conj(kO3i[2, :])
|
|
854
|
+
- (TOx * kO3i[0, :] + TOy * kO3i[1, :] + TOz * kO3i[2, :])
|
|
855
|
+
* np.conj(TOz)
|
|
837
856
|
).real / denom
|
|
838
857
|
DEE3[:, iwl] = (
|
|
839
|
-
(
|
|
840
|
-
*
|
|
841
|
-
- (TEx * kE3i[0, :] + TEy * kE3i[1, :] + TEz * kE3i[2, :])
|
|
858
|
+
(np.absolute(TEx) ** 2 + np.absolute(TEy) ** 2 + np.absolute(TEz) ** 2)
|
|
859
|
+
* np.conj(kE3i[2, :])
|
|
860
|
+
- (TEx * kE3i[0, :] + TEy * kE3i[1, :] + TEz * kE3i[2, :])
|
|
861
|
+
* np.conj(TEz)
|
|
842
862
|
).real / denom
|
|
843
863
|
|
|
844
864
|
# save the results
|