ElectroMagneticPython 2.2.1__py3-none-any.whl → 2.2.4__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.
Files changed (46) hide show
  1. EMpy/RCWA.py +32 -12
  2. EMpy/__init__.py +10 -2
  3. EMpy/_version.py +24 -0
  4. EMpy/constants.py +0 -2
  5. EMpy/devices.py +8 -32
  6. EMpy/materials.py +1 -8
  7. EMpy/modesolvers/FD.py +34 -76
  8. EMpy/modesolvers/FMM.py +24 -23
  9. EMpy/modesolvers/__init__.py +1 -0
  10. EMpy/modesolvers/geometries.py +8 -9
  11. EMpy/transfer_matrix.py +10 -6
  12. EMpy/utils.py +12 -26
  13. electromagneticpython-2.2.4.dist-info/METADATA +99 -0
  14. electromagneticpython-2.2.4.dist-info/RECORD +45 -0
  15. {ElectroMagneticPython-2.2.1.dist-info → electromagneticpython-2.2.4.dist-info}/WHEEL +1 -1
  16. electromagneticpython-2.2.4.dist-info/top_level.txt +4 -0
  17. examples/ex_APRR.py +18 -0
  18. examples/ex_NRR.py +40 -0
  19. examples/ex_RCWA.py +95 -0
  20. examples/ex_RCWA_2.py +52 -0
  21. examples/ex_RCWA_3.py +58 -0
  22. examples/ex_SRR.py +23 -0
  23. examples/ex_laser_etch_monitor.py +241 -0
  24. examples/ex_modesolver.py +68 -0
  25. examples/ex_modesolver_2.py +58 -0
  26. examples/ex_modesolver_3.py +48 -0
  27. examples/ex_modesolver_4.py +43 -0
  28. examples/ex_modesolver_dch.py +296 -0
  29. examples/ex_modesolver_dch_anis.py +318 -0
  30. examples/ex_transfer_matrix.py +82 -0
  31. examples/ex_transfer_matrix_2.py +44 -0
  32. examples/ex_transfer_matrix_2.py.png +0 -0
  33. examples/ex_transfer_matrix_3.py +60 -0
  34. examples/lc_data.dat +27 -0
  35. examples/nk.py +1468 -0
  36. scripts/FDTD.py +741 -0
  37. tests/devices_test.py +31 -0
  38. tests/materials_test.py +1 -1
  39. tests/modesolvers_test.py +36 -0
  40. tests/transfer_matrix_test.py +134 -0
  41. tests/utils_test.py +9 -5
  42. EMpy/version.py +0 -1
  43. ElectroMagneticPython-2.2.1.dist-info/METADATA +0 -109
  44. ElectroMagneticPython-2.2.1.dist-info/RECORD +0 -22
  45. ElectroMagneticPython-2.2.1.dist-info/top_level.txt +0 -2
  46. {ElectroMagneticPython-2.2.1.dist-info → electromagneticpython-2.2.4.dist-info/licenses}/LICENSE +0 -0
tests/devices_test.py ADDED
@@ -0,0 +1,31 @@
1
+ from unittest import TestCase
2
+
3
+ import numpy
4
+
5
+ import EMpy.devices
6
+
7
+
8
+ class NRRTest(TestCase):
9
+
10
+ def test_solve(self):
11
+ N = 1000
12
+ wls = numpy.linspace(1.53e-6, 1.57e-6, N)
13
+
14
+ Ks = [
15
+ EMpy.devices.Coupler(wls, numpy.sqrt(0.08), 1.0),
16
+ EMpy.devices.Coupler(wls, numpy.sqrt(0.008), 1.0),
17
+ EMpy.devices.Coupler(wls, numpy.sqrt(0.006), 1.0),
18
+ EMpy.devices.Coupler(wls, numpy.sqrt(0.09), 1.0),
19
+ ]
20
+
21
+ R = 5e-6
22
+ l1s = [numpy.pi * R, numpy.pi * R, numpy.pi * R]
23
+ l2s = [numpy.pi * R, numpy.pi * R, numpy.pi * R]
24
+
25
+ SWG = EMpy.devices.SWG(400, 220, 125).solve(wls)
26
+ neffs = [SWG.neff, SWG.neff, SWG.neff]
27
+
28
+ NRR = EMpy.devices.NRR(Ks, neffs, l1s, l2s).solve()
29
+
30
+ self.assertEqual(NRR.THRU.shape, (N,))
31
+ self.assertAlmostEqual(numpy.absolute(NRR.THRU).min(), 0.3868920546379094)
tests/materials_test.py CHANGED
@@ -1,4 +1,3 @@
1
- # pylint: disable=no-self-use
2
1
  from unittest import TestCase
3
2
 
4
3
  from numpy import array
@@ -8,6 +7,7 @@ import EMpy.materials as mat
8
7
 
9
8
 
10
9
  class RefractiveIndexTest(TestCase):
10
+
11
11
  def test_all_nones(self):
12
12
  with assert_raises(ValueError):
13
13
  mat.RefractiveIndex()
@@ -0,0 +1,36 @@
1
+ from unittest import TestCase
2
+
3
+ import numpy
4
+
5
+ import EMpy.modesolvers
6
+
7
+
8
+ class VFDModeSolverTest(TestCase):
9
+
10
+ def test_solve(self):
11
+
12
+ def epsfunc(x_, y_):
13
+ """Return a matrix describing a 2d material.
14
+
15
+ :param x_: x values
16
+ :param y_: y values
17
+ :return: 2d-matrix
18
+ """
19
+ xx, yy = numpy.meshgrid(x_, y_)
20
+ return numpy.where(
21
+ (numpy.abs(xx.T - 1.24e-6) <= 0.24e-6) * (numpy.abs(yy.T - 1.11e-6) <= 0.11e-6),
22
+ 3.4757**2,
23
+ 1.446**2,
24
+ )
25
+
26
+ neigs = 2
27
+ tol = 1e-8
28
+ boundary = "0000"
29
+ wl = 1.55e-6
30
+ x = numpy.linspace(0, 2.48e-6, 125)
31
+ y = numpy.linspace(0, 2.22e-6, 112)
32
+ solver = EMpy.modesolvers.FD.VFDModeSolver(wl, x, y, epsfunc, boundary).solve(
33
+ neigs, tol
34
+ )
35
+ self.assertEqual(len(solver.modes), 2)
36
+ self.assertAlmostEqual(solver.modes[0].neff, 2.4179643622942937)
@@ -0,0 +1,134 @@
1
+ from unittest import TestCase
2
+
3
+ import numpy as np
4
+ from numpy.testing import assert_allclose
5
+
6
+ import EMpy
7
+
8
+
9
+ def _make_iso_multilayer(n_list, d_list):
10
+ layers = EMpy.utils.Multilayer()
11
+ for n, d in zip(n_list, d_list):
12
+ mat = EMpy.materials.IsotropicMaterial(
13
+ "mat", n0=EMpy.materials.RefractiveIndex(n0_const=n)
14
+ )
15
+ layers.append(EMpy.utils.Layer(mat, d))
16
+ return layers
17
+
18
+
19
+ def _make_aniso_multilayer(n_list, d_list):
20
+ layers = EMpy.utils.Multilayer()
21
+ for n, d in zip(n_list, d_list):
22
+ eps = EMpy.materials.EpsilonTensor(
23
+ epsilon_tensor_const=(n**2) * EMpy.constants.eps0 * np.eye(3)
24
+ )
25
+ mat = EMpy.materials.AnisotropicMaterial("mat", epsilon_tensor=eps)
26
+ layers.append(EMpy.utils.Layer(mat, d))
27
+ return layers
28
+
29
+
30
+ class TransferMatrixTest(TestCase):
31
+
32
+ def test_fresnel_brewster(self):
33
+ n1, n2 = 1.0, 1.5
34
+ theta_b = np.arctan2(n2, n1)
35
+ layers = _make_iso_multilayer([n1, n2], [np.inf, np.inf])
36
+ sol = EMpy.transfer_matrix.IsotropicTransferMatrix(layers, theta_b).solve(
37
+ [1.55e-6]
38
+ )
39
+ assert_allclose(sol.Rp, [0.0], atol=1e-15)
40
+ assert_allclose(sol.Tp, [1.0], atol=1e-15)
41
+ assert_allclose(sol.Rs + sol.Ts, [1.0], atol=1e-15)
42
+
43
+ def test_total_internal_reflection(self):
44
+ layers = _make_iso_multilayer([1.5, 1.0], [np.inf, np.inf])
45
+ theta_inc = EMpy.utils.deg2rad(60.0)
46
+ sol = EMpy.transfer_matrix.IsotropicTransferMatrix(layers, theta_inc).solve(
47
+ [1.55e-6]
48
+ )
49
+ assert_allclose(sol.Rs, [1.0], atol=1e-15)
50
+ assert_allclose(sol.Ts, [0.0], atol=1e-15)
51
+ assert_allclose(sol.Rp, [1.0], atol=1e-15)
52
+ assert_allclose(sol.Tp, [0.0], atol=1e-15)
53
+
54
+ def test_frustrated_total_internal_reflection(self):
55
+ layers = _make_iso_multilayer([1.5, 1.0, 1.5], [np.inf, 0.2e-6, np.inf])
56
+ theta_inc = EMpy.utils.deg2rad(60.0)
57
+ sol = EMpy.transfer_matrix.IsotropicTransferMatrix(layers, theta_inc).solve(
58
+ [1.55e-6]
59
+ )
60
+ self.assertTrue((0.0 < sol.Ts[0] < 1.0) and (0.0 < sol.Tp[0] < 1.0))
61
+ assert_allclose(sol.Rs + sol.Ts, [1.0], atol=1e-15)
62
+ assert_allclose(sol.Rp + sol.Tp, [1.0], atol=1e-15)
63
+
64
+ def test_absorbing_exit_medium(self):
65
+ wls = [1.55e-6]
66
+ theta_inc = EMpy.utils.deg2rad(40.0)
67
+ n_list = [1.0, 1.5 - 0.5j]
68
+ d_list = [np.inf, np.inf]
69
+
70
+ iso_layers = _make_iso_multilayer(n_list, d_list)
71
+ aniso_layers = _make_aniso_multilayer(n_list, d_list)
72
+
73
+ sol_iso = EMpy.transfer_matrix.IsotropicTransferMatrix(
74
+ iso_layers, theta_inc
75
+ ).solve(wls)
76
+ sol_aniso = EMpy.transfer_matrix.AnisotropicTransferMatrix(
77
+ aniso_layers, theta_inc, 0.0
78
+ ).solve(wls)
79
+
80
+ # Single interface from lossless medium: net flux across z=0 is conserved
81
+ assert_allclose(sol_iso.Rs + sol_iso.Ts, [1.0], atol=1e-15)
82
+ assert_allclose(sol_iso.Rp + sol_iso.Tp, [1.0], atol=1e-15)
83
+
84
+ assert_allclose(sol_iso.Rs, sol_aniso.R[0, 0, :], rtol=1e-6)
85
+ assert_allclose(sol_iso.Ts, sol_aniso.T[0, 0, :], rtol=1e-6)
86
+ assert_allclose(sol_iso.Rp, sol_aniso.R[1, 1, :], rtol=1e-6)
87
+ assert_allclose(sol_iso.Tp, sol_aniso.T[1, 1, :], rtol=1e-6)
88
+
89
+ def test_absorbing_slab(self):
90
+ wls = [1.55e-6]
91
+ theta_inc = EMpy.utils.deg2rad(20.0)
92
+ n_list = [1.0, 2.0 - 0.1j, 1.0]
93
+ d_list = [np.inf, 0.5e-6, np.inf]
94
+
95
+ iso_layers = _make_iso_multilayer(n_list, d_list)
96
+ aniso_layers = _make_aniso_multilayer(n_list, d_list)
97
+
98
+ sol_iso = EMpy.transfer_matrix.IsotropicTransferMatrix(
99
+ iso_layers, theta_inc
100
+ ).solve(wls)
101
+ sol_aniso = EMpy.transfer_matrix.AnisotropicTransferMatrix(
102
+ aniso_layers, theta_inc, 0.0
103
+ ).solve(wls)
104
+
105
+ self.assertLess(sol_iso.Rs[0] + sol_iso.Ts[0], 1.0)
106
+ self.assertLess(sol_iso.Rp[0] + sol_iso.Tp[0], 1.0)
107
+ assert_allclose(sol_iso.Rs, sol_aniso.R[0, 0, :], rtol=1e-6)
108
+ assert_allclose(sol_iso.Ts, sol_aniso.T[0, 0, :], rtol=1e-6)
109
+ assert_allclose(sol_iso.Rp, sol_aniso.R[1, 1, :], rtol=1e-6)
110
+ assert_allclose(sol_iso.Tp, sol_aniso.T[1, 1, :], rtol=1e-6)
111
+
112
+ def test_iso_vs_aniso_non_unit_incident_index(self):
113
+ wls = np.linspace(1.4e-6, 1.7e-6, 5)
114
+ n_list = [1.5, 2.1, 1.0]
115
+ d_list = [np.inf, 0.3e-6, np.inf]
116
+ theta_inc = EMpy.utils.deg2rad(30.0)
117
+ theta_vac = np.arcsin(n_list[0] * np.sin(theta_inc))
118
+
119
+ iso_layers = _make_iso_multilayer(n_list, d_list)
120
+ aniso_layers = _make_aniso_multilayer(n_list, d_list)
121
+
122
+ sol_iso = EMpy.transfer_matrix.IsotropicTransferMatrix(
123
+ iso_layers, theta_inc
124
+ ).solve(wls)
125
+ sol_aniso = EMpy.transfer_matrix.AnisotropicTransferMatrix(
126
+ aniso_layers, theta_vac, 0.0
127
+ ).solve(wls)
128
+
129
+ assert_allclose(sol_iso.Rs + sol_iso.Ts, 1.0, atol=1e-14)
130
+ assert_allclose(sol_iso.Rp + sol_iso.Tp, 1.0, atol=1e-14)
131
+ assert_allclose(sol_iso.Rs, sol_aniso.R[0, 0, :], rtol=1e-6)
132
+ assert_allclose(sol_iso.Ts, sol_aniso.T[0, 0, :], rtol=1e-6)
133
+ assert_allclose(sol_iso.Rp, sol_aniso.R[1, 1, :], rtol=1e-6)
134
+ assert_allclose(sol_iso.Tp, sol_aniso.T[1, 1, :], rtol=1e-6)
tests/utils_test.py CHANGED
@@ -1,23 +1,27 @@
1
- # pylint: disable=no-self-use
2
1
  from unittest import TestCase
3
2
 
4
3
  import random
5
4
  import math
6
5
 
7
6
  from numpy import pi
8
- from numpy.testing import assert_almost_equal
9
7
 
10
8
  import EMpy.utils as U
11
9
 
12
10
 
13
11
  class UtilsTest(TestCase):
12
+
14
13
  def test_deg2rad(self):
15
- # TODO use hypothesis
16
14
  x = -2 * pi + 4 * pi * random.random()
17
- assert_almost_equal(x, U.deg2rad(U.rad2deg(x)))
15
+ self.assertAlmostEqual(x, U.deg2rad(U.rad2deg(x)))
18
16
 
19
17
  def test_norm(self):
20
18
  self.assertEqual(U.norm([1, 0, 0]), 1)
21
19
  self.assertEqual(U.norm([0, 1, 0]), 1)
22
20
  self.assertEqual(U.norm([0, 0, 1]), 1)
23
- assert_almost_equal(U.norm([1, 0, 1]), math.sqrt(2))
21
+ self.assertAlmostEqual(U.norm([1, 0, 1]), math.sqrt(2))
22
+
23
+ def test_trapz2(self):
24
+ f = [[i + j for i in range(5)] for j in range(5)]
25
+ res = U.trapz2(f, dx=1.0, dy=1.0)
26
+ # integral of f = x + y over [0,4]x[0,4] = 64
27
+ self.assertAlmostEqual(res, 64.0)
EMpy/version.py DELETED
@@ -1 +0,0 @@
1
- version = "2.2.1"
@@ -1,109 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: ElectroMagneticPython
3
- Version: 2.2.1
4
- Summary: EMpy - ElectroMagnetic Python
5
- Home-page: http://lbolla.github.io/EMpy/
6
- Download-URL: https://github.com/lbolla/EMpy
7
- Author: Lorenzo Bolla
8
- Author-email: code@lbolla.info
9
- License: BSD
10
- Platform: Windows
11
- Platform: Linux
12
- Platform: Mac OS-X
13
- Classifier: Development Status :: 5 - Production/Stable
14
- Classifier: Environment :: Console
15
- Classifier: Intended Audience :: Science/Research
16
- Classifier: License :: OSI Approved :: BSD License
17
- Classifier: Natural Language :: English
18
- Classifier: Programming Language :: Python :: 3
19
- Classifier: Operating System :: OS Independent
20
- Classifier: Topic :: Scientific/Engineering :: Physics
21
- Provides: EMpy
22
- License-File: LICENSE
23
- Requires-Dist: numpy>=1.18
24
- Requires-Dist: scipy>=1.7
25
- Requires-Dist: matplotlib>=3.1
26
-
27
- EMpy - ElectroMagnetic Python
28
- *****************************
29
-
30
- .. image:: https://github.com/lbolla/EMpy/actions/workflows/python-app.yml/badge.svg
31
- :target: https://github.com/lbolla/EMpy/actions/workflows/python-app.yml
32
-
33
- .. image:: https://badge.fury.io/py/ElectroMagneticPython.svg
34
- :target: https://badge.fury.io/py/ElectroMagneticPython
35
-
36
- `EMpy - ElectroMagnetic Python` is a suite of algorithms widely known
37
- and used in electromagnetic problems and optics: the transfer matrix
38
- algorithm, the rigorous coupled wave analysis algorithm and more.
39
-
40
- Run the examples in `examples/*` to have an idea how EMpy works.
41
-
42
- Visit http://lbolla.github.io/EMpy/ for more information.
43
-
44
- Installation
45
- ============
46
-
47
- .. code-block:: bash
48
-
49
- $> pip install ElectromagneticPython
50
-
51
- Optionally, install `bvp`:
52
-
53
- .. code-block:: bash
54
-
55
- $> pip install scikits.bvp1lg
56
-
57
- Development
58
- ===========
59
-
60
- First, download the source code from https://github.com/lbolla/EMpy.
61
-
62
- Create a virtualenv with, e.g:
63
-
64
- .. code-block:: bash
65
-
66
- $> make venv
67
-
68
- Then, from inside a `virtualenv`, install dev environment with:
69
-
70
- .. code-block:: bash
71
-
72
- $> make develop
73
-
74
- Run tests with:
75
-
76
- .. code-block:: bash
77
-
78
- $> make test
79
-
80
- Upgrade dependencies with:
81
-
82
- .. code-block:: bash
83
-
84
- $> make requirements-upgrade
85
- $> make requirements-sync
86
-
87
-
88
- Release process
89
- ===============
90
-
91
- 1. Edit CHANGES
92
- 2. `make release PART=major|minor|patch`
93
-
94
- Citation
95
- ========
96
-
97
- If you find EMpy useful in your job, please consider adding a citation.
98
-
99
- As reference:
100
-
101
- .. code-block::
102
-
103
- Bolla, L. (2017). EMpy [Computer software]. https://github.com/lbolla/EMpy/
104
-
105
- As text:
106
-
107
- .. code-block::
108
-
109
- We used EMpy (version x.y.z) to complete our work.
@@ -1,22 +0,0 @@
1
- EMpy/RCWA.py,sha256=8wro-KNtnWTrYN2NlV8OGGrJGnd9DDwkK3KlVJ4TU8A,32249
2
- EMpy/__init__.py,sha256=PSH3TiCVO9LSBCbQIM9uyXVK0TKn0S7ngWC5dGYuaPs,1003
3
- EMpy/constants.py,sha256=x1N8eRXQW_gdr1557n7tvUXiM4RW_Fc_EydLd5AUC1o,723
4
- EMpy/devices.py,sha256=OQLxSAKXafBgrbWd-WNcVTOkxdBhZ-UXsW7ukoIwaYA,37895
5
- EMpy/materials.py,sha256=r9SaTf4u3JBszGpVB-62VLhQp6SoQb78AsmrxLoTMkc,10687
6
- EMpy/scattering.py,sha256=1rY8_TI0kzTLYwpFSSXndaO9FzDzVPRVow55vzIDQiM,7339
7
- EMpy/transfer_matrix.py,sha256=Z3EK4MYsV5sUGTyXWieXVLg-18Wctm_3jR5LNS04r1k,14582
8
- EMpy/utils.py,sha256=o-XBTXtOVOff-us4Br2zP0u2PLJFqdsq28QxvoEpZrc,42008
9
- EMpy/version.py,sha256=d4pHXdSvDQjlx5mLFhqVvjzHBiA0Fow5fJ7IpFZUFeI,18
10
- EMpy/modesolvers/FD.py,sha256=DIZGfAfGTPJfD83VsTvIO0gcMjvw1dci23F9PK3okow,80097
11
- EMpy/modesolvers/FMM.py,sha256=FaIvg1aOsdM8pxdVNCBiqr4eTM-6oqPZPTxLanG3tXo,78366
12
- EMpy/modesolvers/__init__.py,sha256=bAFq4_6rPDV4RgFx6rct9ywRDLCt_pGhiVtgC6L9A_Y,221
13
- EMpy/modesolvers/geometries.py,sha256=hdxjVCCMQqo4p6fY51FTQPkQt3lKj7g96LCqOs58wyY,7895
14
- EMpy/modesolvers/interface.py,sha256=spMy30TFedYXJHcoV3yUdGkycGt5cplJUCeZui6a5MY,2397
15
- tests/__init__.py,sha256=XNMyfmlHhqih2xHEklXlmQ8GVUAdiiWrkT3trIOMpRQ,29
16
- tests/materials_test.py,sha256=v_UlUvPkiKqkkPNFywbTGTTO4eNnuk-itZPr5YIEUWw,1875
17
- tests/utils_test.py,sha256=Voe_Ph9LDDf47Vnt04hHLXoTPFGYXeRqzQDVkvPUVy8,597
18
- ElectroMagneticPython-2.2.1.dist-info/LICENSE,sha256=NlQFsrkwMvQ2aD8531IDm6Rk01KzlI42HVzK5M1Hpw8,1065
19
- ElectroMagneticPython-2.2.1.dist-info/METADATA,sha256=Bk8GnVNqdRF6iuFDVIRE_5XA-YqsEG0I8hBV4jVqgE8,2476
20
- ElectroMagneticPython-2.2.1.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
21
- ElectroMagneticPython-2.2.1.dist-info/top_level.txt,sha256=JCRI2zyREl3Lql3CyAFrqXFLGqMV0LqdsqQisk907AI,11
22
- ElectroMagneticPython-2.2.1.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- EMpy
2
- tests