ElectroMagneticPython 2.2.3__tar.gz → 2.2.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 (63) hide show
  1. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/.bumpversion.cfg +1 -1
  2. electromagneticpython-2.2.4/EMpy/_version.py +24 -0
  3. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/constants.py +0 -2
  4. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/devices.py +4 -5
  5. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/materials.py +0 -2
  6. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/modesolvers/FD.py +0 -4
  7. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/transfer_matrix.py +9 -5
  8. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/utils.py +0 -2
  9. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4/ElectroMagneticPython.egg-info}/PKG-INFO +1 -1
  10. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/ElectroMagneticPython.egg-info/SOURCES.txt +3 -0
  11. electromagneticpython-2.2.4/ElectroMagneticPython.egg-info/scm_file_list.json +56 -0
  12. electromagneticpython-2.2.4/ElectroMagneticPython.egg-info/scm_version.json +8 -0
  13. {electromagneticpython-2.2.3/ElectroMagneticPython.egg-info → electromagneticpython-2.2.4}/PKG-INFO +1 -1
  14. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_transfer_matrix_2.py +1 -1
  15. electromagneticpython-2.2.4/tests/transfer_matrix_test.py +134 -0
  16. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/uv.lock +444 -301
  17. electromagneticpython-2.2.3/EMpy/_version.py +0 -34
  18. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/.flake8 +0 -0
  19. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/.github/dependabot.yml +0 -0
  20. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/.github/workflows/codeql-analysis.yml +0 -0
  21. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/.github/workflows/publish.yml +0 -0
  22. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/.github/workflows/python-app.yml +0 -0
  23. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/.gitignore +0 -0
  24. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/RCWA.py +0 -0
  25. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/__init__.py +0 -0
  26. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/modesolvers/FMM.py +0 -0
  27. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/modesolvers/__init__.py +0 -0
  28. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/modesolvers/geometries.py +0 -0
  29. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/modesolvers/interface.py +0 -0
  30. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/EMpy/scattering.py +0 -0
  31. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/ElectroMagneticPython.egg-info/dependency_links.txt +0 -0
  32. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/ElectroMagneticPython.egg-info/requires.txt +0 -0
  33. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/ElectroMagneticPython.egg-info/top_level.txt +0 -0
  34. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/LICENSE +0 -0
  35. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/Makefile +0 -0
  36. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/README.md +0 -0
  37. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_APRR.py +0 -0
  38. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_NRR.py +0 -0
  39. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_RCWA.py +0 -0
  40. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_RCWA_2.py +0 -0
  41. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_RCWA_3.py +0 -0
  42. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_SRR.py +0 -0
  43. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_laser_etch_monitor.py +0 -0
  44. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_modesolver.py +0 -0
  45. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_modesolver_2.py +0 -0
  46. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_modesolver_3.py +0 -0
  47. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_modesolver_4.py +0 -0
  48. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_modesolver_dch.py +0 -0
  49. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_modesolver_dch_anis.py +0 -0
  50. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_transfer_matrix.py +0 -0
  51. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_transfer_matrix_2.py.png +0 -0
  52. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/ex_transfer_matrix_3.py +0 -0
  53. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/lc_data.dat +0 -0
  54. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/examples/nk.py +0 -0
  55. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/mypy.ini +0 -0
  56. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/pyproject.toml +0 -0
  57. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/scripts/FDTD.py +0 -0
  58. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/setup.cfg +0 -0
  59. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/tests/__init__.py +0 -0
  60. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/tests/devices_test.py +0 -0
  61. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/tests/materials_test.py +0 -0
  62. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/tests/modesolvers_test.py +0 -0
  63. {electromagneticpython-2.2.3 → electromagneticpython-2.2.4}/tests/utils_test.py +0 -0
@@ -3,4 +3,4 @@ commit = True
3
3
  sign_tags = True
4
4
  tag = True
5
5
  tag_name = {new_version}
6
- current_version = 2.2.3
6
+ current_version = 2.2.4
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '2.2.4'
22
+ __version_tuple__ = version_tuple = (2, 2, 4)
23
+
24
+ __commit_id__ = commit_id = 'gd8c276251'
@@ -1,5 +1,3 @@
1
- # pylint: disable=C0301
2
-
3
1
  """Useful constants.
4
2
 
5
3
  Constants used in mathematics and electromagnetism.
@@ -1,5 +1,3 @@
1
- # pylint: disable=C0302,W0622,W1001,R0902,R0903,W0201,R0913,R0914,C0325,W0221
2
-
3
1
  """Set of objects and functions to describe the behaviour of some
4
2
  widely known devices and build new ones.
5
3
 
@@ -62,7 +60,7 @@ class DeviceMatrix:
62
60
  return self.__data
63
61
 
64
62
  def setdata(self, value):
65
- self.__data = numpy.asmatrix(value)
63
+ self.__data = numpy.array(value)
66
64
 
67
65
  __data = None
68
66
  data = property(fget=getdata, fset=setdata, doc="data")
@@ -137,6 +135,7 @@ class TransferMatrix(DeviceMatrix):
137
135
 
138
136
  Notation::
139
137
 
138
+
140
139
  b12 = H1 a12 and d12 = H2 c12, but b12 == c12,
141
140
 
142
141
  therefore::
@@ -153,7 +152,7 @@ class TransferMatrix(DeviceMatrix):
153
152
 
154
153
  """
155
154
 
156
- return TransferMatrix(M.to_transfer().data * self.data)
155
+ return TransferMatrix(M.to_transfer().data @ self.data)
157
156
 
158
157
 
159
158
  class ChainMatrix(DeviceMatrix):
@@ -227,7 +226,7 @@ class ChainMatrix(DeviceMatrix):
227
226
 
228
227
  """
229
228
 
230
- return ChainMatrix(self.data * M.to_chain().data)
229
+ return ChainMatrix(self.data @ M.to_chain().data)
231
230
 
232
231
 
233
232
  def composeTM(A, B):
@@ -1,5 +1,3 @@
1
- # pylint: disable=W0622,R0903,R0902,R0913,W0633
2
-
3
1
  """Functions and objects to manipulate materials.
4
2
 
5
3
  A material is an object with a refractive index function.
@@ -1,7 +1,3 @@
1
- # pylint: disable=line-too-long,too-many-locals,too-many-statements,too-many-branches
2
- # pylint: disable=redefined-builtin,wildcard-import,unused-wildcard-import
3
- # pylint: disable=attribute-defined-outside-init,too-many-instance-attributes
4
- # pylint: disable=arguments-differ,too-many-arguments
5
1
  """Finite Difference Modesolver.
6
2
 
7
3
  @see: Fallahkhair, "Vector Finite Difference Modesolver for Anisotropic Dielectric Waveguides",
@@ -39,8 +39,8 @@ class IsotropicTransferMatrix(TransferMatrix):
39
39
 
40
40
  INPUT
41
41
  multilayer = Multilayer obj describing the sequence of layers.
42
- theta_inc = angle of the incident wave (in radiant) wrt the
43
- normal.
42
+ theta_inc = angle of the incident wave (in radians) wrt the
43
+ normal, measured in the first layer (multilayer[0]).
44
44
  """
45
45
  if not multilayer.isIsotropic():
46
46
  raise ValueError(
@@ -118,12 +118,14 @@ class IsotropicTransferMatrix(TransferMatrix):
118
118
 
119
119
  Rs[iwl] = np.absolute(rs) ** 2
120
120
  Ts[iwl] = (
121
- np.absolute((n[-1] * np.cos(theta[-1])) / (n[0] * np.cos(theta[0])))
121
+ np.real(n[-1] * np.cos(theta[-1]))
122
+ / np.real(n[0] * np.cos(theta[0]))
122
123
  * np.absolute(ts) ** 2
123
124
  )
124
125
  Rp[iwl] = np.absolute(rp) ** 2
125
126
  Tp[iwl] = (
126
- np.absolute((n[-1] * np.cos(theta[-1])) / (n[0] * np.cos(theta[0])))
127
+ np.real(np.conj(n[-1]) * np.cos(theta[-1]))
128
+ / np.real(np.conj(n[0]) * np.cos(theta[0]))
127
129
  * np.absolute(tp) ** 2
128
130
  )
129
131
 
@@ -160,7 +162,9 @@ class AnisotropicTransferMatrix(TransferMatrix):
160
162
  INPUT
161
163
  multilayer = Multilayer obj describing the sequence of layers.
162
164
  theta_inc_x and theta_inc_y = angles of the incident wave (in
163
- radiant) wrt the normal.
165
+ radians) wrt the normal in vacuum, i.e. kx = k0 * sin(theta_inc_x)
166
+ and ky = k0 * sin(theta_inc_y) (unlike IsotropicTransferMatrix,
167
+ where theta_inc is measured in multilayer[0]).
164
168
  """
165
169
  TransferMatrix.__init__(self, multilayer)
166
170
  self.theta_inc_x = theta_inc_x
@@ -1,5 +1,3 @@
1
- # pylint: disable=R0913,R0914,W0201,W0622,C0302,R0902,R0903,W1001,W0612,W0613
2
-
3
1
  """Useful functions and objects used more or less everywhere."""
4
2
 
5
3
  __author__ = "Lorenzo Bolla"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ElectroMagneticPython
3
- Version: 2.2.3
3
+ Version: 2.2.4
4
4
  Summary: EMpy - ElectroMagnetic Python
5
5
  Author-email: Lorenzo Bolla <code@lbolla.info>
6
6
  License-Expression: MIT
@@ -29,6 +29,8 @@ ElectroMagneticPython.egg-info/PKG-INFO
29
29
  ElectroMagneticPython.egg-info/SOURCES.txt
30
30
  ElectroMagneticPython.egg-info/dependency_links.txt
31
31
  ElectroMagneticPython.egg-info/requires.txt
32
+ ElectroMagneticPython.egg-info/scm_file_list.json
33
+ ElectroMagneticPython.egg-info/scm_version.json
32
34
  ElectroMagneticPython.egg-info/top_level.txt
33
35
  examples/ex_APRR.py
34
36
  examples/ex_NRR.py
@@ -54,4 +56,5 @@ tests/__init__.py
54
56
  tests/devices_test.py
55
57
  tests/materials_test.py
56
58
  tests/modesolvers_test.py
59
+ tests/transfer_matrix_test.py
57
60
  tests/utils_test.py
@@ -0,0 +1,56 @@
1
+ {
2
+ "files": [
3
+ ".bumpversion.cfg",
4
+ ".flake8",
5
+ ".github/dependabot.yml",
6
+ ".github/workflows/codeql-analysis.yml",
7
+ ".github/workflows/publish.yml",
8
+ ".github/workflows/python-app.yml",
9
+ ".gitignore",
10
+ "EMpy/RCWA.py",
11
+ "EMpy/__init__.py",
12
+ "EMpy/constants.py",
13
+ "EMpy/devices.py",
14
+ "EMpy/materials.py",
15
+ "EMpy/modesolvers/FD.py",
16
+ "EMpy/modesolvers/FMM.py",
17
+ "EMpy/modesolvers/__init__.py",
18
+ "EMpy/modesolvers/geometries.py",
19
+ "EMpy/modesolvers/interface.py",
20
+ "EMpy/scattering.py",
21
+ "EMpy/transfer_matrix.py",
22
+ "EMpy/utils.py",
23
+ "LICENSE",
24
+ "Makefile",
25
+ "README.md",
26
+ "examples/ex_APRR.py",
27
+ "examples/ex_NRR.py",
28
+ "examples/ex_RCWA.py",
29
+ "examples/ex_RCWA_2.py",
30
+ "examples/ex_RCWA_3.py",
31
+ "examples/ex_SRR.py",
32
+ "examples/ex_laser_etch_monitor.py",
33
+ "examples/ex_modesolver.py",
34
+ "examples/ex_modesolver_2.py",
35
+ "examples/ex_modesolver_3.py",
36
+ "examples/ex_modesolver_4.py",
37
+ "examples/ex_modesolver_dch.py",
38
+ "examples/ex_modesolver_dch_anis.py",
39
+ "examples/ex_transfer_matrix.py",
40
+ "examples/ex_transfer_matrix_2.py",
41
+ "examples/ex_transfer_matrix_2.py.png",
42
+ "examples/ex_transfer_matrix_3.py",
43
+ "examples/lc_data.dat",
44
+ "examples/nk.py",
45
+ "mypy.ini",
46
+ "pyproject.toml",
47
+ "scripts/FDTD.py",
48
+ "tests/__init__.py",
49
+ "tests/devices_test.py",
50
+ "tests/materials_test.py",
51
+ "tests/modesolvers_test.py",
52
+ "tests/transfer_matrix_test.py",
53
+ "tests/utils_test.py",
54
+ "uv.lock"
55
+ ]
56
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "2.2.4",
3
+ "distance": 0,
4
+ "node": "gd8c276251899f9a6cf5bdd352a4fe68a53c60e61",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-11-14"
8
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ElectroMagneticPython
3
- Version: 2.2.3
3
+ Version: 2.2.4
4
4
  Summary: EMpy - ElectroMagnetic Python
5
5
  Author-email: Lorenzo Bolla <code@lbolla.info>
6
6
  License-Expression: MIT
@@ -40,5 +40,5 @@ plt.xlabel("wavelength /m")
40
40
  plt.ylabel("Power /dB")
41
41
  plt.grid()
42
42
  plt.xlim(wls.min(), wls.max())
43
- plt.savefig(__file__ + ".png")
43
+ # plt.savefig(__file__ + ".png")
44
44
  plt.show()
@@ -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)