ElectroMagneticPython 2.0.0__tar.gz → 2.1.4__tar.gz

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