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