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