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.
- EMpy/RCWA.py +32 -12
- EMpy/__init__.py +10 -2
- EMpy/_version.py +24 -0
- EMpy/constants.py +0 -2
- EMpy/devices.py +8 -32
- EMpy/materials.py +1 -8
- EMpy/modesolvers/FD.py +34 -76
- EMpy/modesolvers/FMM.py +24 -23
- EMpy/modesolvers/__init__.py +1 -0
- EMpy/modesolvers/geometries.py +8 -9
- EMpy/transfer_matrix.py +10 -6
- EMpy/utils.py +12 -26
- electromagneticpython-2.2.4.dist-info/METADATA +99 -0
- electromagneticpython-2.2.4.dist-info/RECORD +45 -0
- {ElectroMagneticPython-2.2.1.dist-info → electromagneticpython-2.2.4.dist-info}/WHEEL +1 -1
- electromagneticpython-2.2.4.dist-info/top_level.txt +4 -0
- examples/ex_APRR.py +18 -0
- examples/ex_NRR.py +40 -0
- examples/ex_RCWA.py +95 -0
- examples/ex_RCWA_2.py +52 -0
- examples/ex_RCWA_3.py +58 -0
- examples/ex_SRR.py +23 -0
- examples/ex_laser_etch_monitor.py +241 -0
- examples/ex_modesolver.py +68 -0
- examples/ex_modesolver_2.py +58 -0
- examples/ex_modesolver_3.py +48 -0
- examples/ex_modesolver_4.py +43 -0
- examples/ex_modesolver_dch.py +296 -0
- examples/ex_modesolver_dch_anis.py +318 -0
- examples/ex_transfer_matrix.py +82 -0
- examples/ex_transfer_matrix_2.py +44 -0
- examples/ex_transfer_matrix_2.py.png +0 -0
- examples/ex_transfer_matrix_3.py +60 -0
- examples/lc_data.dat +27 -0
- examples/nk.py +1468 -0
- scripts/FDTD.py +741 -0
- tests/devices_test.py +31 -0
- tests/materials_test.py +1 -1
- tests/modesolvers_test.py +36 -0
- tests/transfer_matrix_test.py +134 -0
- tests/utils_test.py +9 -5
- EMpy/version.py +0 -1
- ElectroMagneticPython-2.2.1.dist-info/METADATA +0 -109
- ElectroMagneticPython-2.2.1.dist-info/RECORD +0 -22
- ElectroMagneticPython-2.2.1.dist-info/top_level.txt +0 -2
- {ElectroMagneticPython-2.2.1.dist-info → electromagneticpython-2.2.4.dist-info/licenses}/LICENSE +0 -0
EMpy/modesolvers/FMM.py
CHANGED
|
@@ -13,15 +13,16 @@ Examples
|
|
|
13
13
|
See L{FMM1d} and L{FMM2d}.
|
|
14
14
|
|
|
15
15
|
"""
|
|
16
|
-
import copy
|
|
17
|
-
from functools import reduce
|
|
18
16
|
|
|
19
17
|
__author__ = "Luca Gamberale & Lorenzo Bolla"
|
|
20
18
|
|
|
19
|
+
import copy
|
|
20
|
+
from functools import reduce
|
|
21
|
+
|
|
22
|
+
from matplotlib import pyplot as plt
|
|
21
23
|
import numpy
|
|
22
24
|
import scipy
|
|
23
25
|
import scipy.optimize
|
|
24
|
-
import pylab
|
|
25
26
|
|
|
26
27
|
import EMpy.utils
|
|
27
28
|
from EMpy.modesolvers.interface import Mode, ModeSolver
|
|
@@ -247,11 +248,11 @@ class FMMMode1dy(FMMMode1d):
|
|
|
247
248
|
|
|
248
249
|
def plot(self, y):
|
|
249
250
|
f = self.eval(y)
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
251
|
+
plt.plot(y, numpy.real(f), y, numpy.imag(y))
|
|
252
|
+
plt.legend(("real", "imag"))
|
|
253
|
+
plt.xlabel("y")
|
|
254
|
+
plt.ylabel("mode1d")
|
|
255
|
+
plt.show()
|
|
255
256
|
|
|
256
257
|
def __str__(self):
|
|
257
258
|
return (
|
|
@@ -845,26 +846,26 @@ class FMMMode2d(Mode):
|
|
|
845
846
|
f = self.fields(x, y)
|
|
846
847
|
|
|
847
848
|
# fields
|
|
848
|
-
|
|
849
|
+
plt.figure()
|
|
849
850
|
titles = ["Ex", "Ey", "Ez", "cBx", "cBy", "cBz"]
|
|
850
851
|
for i in range(6):
|
|
851
852
|
subplot_id = 231 + i
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
853
|
+
plt.subplot(subplot_id)
|
|
854
|
+
plt.contour(x, y, numpy.abs(f[i]))
|
|
855
|
+
plt.xlabel("x")
|
|
856
|
+
plt.ylabel("y")
|
|
857
|
+
plt.title(titles[i])
|
|
858
|
+
plt.axis("image")
|
|
859
|
+
plt.show()
|
|
859
860
|
|
|
860
861
|
# power
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
862
|
+
plt.figure()
|
|
863
|
+
plt.contour(x, y, numpy.abs(f[-1]))
|
|
864
|
+
plt.xlabel("x")
|
|
865
|
+
plt.ylabel("y")
|
|
866
|
+
plt.title("cSz")
|
|
867
|
+
plt.axis("image")
|
|
868
|
+
plt.show()
|
|
868
869
|
|
|
869
870
|
def __str__(self):
|
|
870
871
|
return "neff = %s" % (self.keff / (2 * numpy.pi / self.slicesx[0].wl))
|
EMpy/modesolvers/__init__.py
CHANGED
EMpy/modesolvers/geometries.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
"""Geometries.
|
|
1
|
+
"""Geometries."""
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
from matplotlib import pyplot as plt
|
|
4
4
|
import numpy
|
|
5
|
-
import pylab
|
|
6
5
|
|
|
7
6
|
from EMpy.modesolvers.interface import interface_matrix
|
|
8
7
|
|
|
@@ -89,8 +88,8 @@ class SWG:
|
|
|
89
88
|
numpy.abs(coeffLHS) ** 2 * tmp[:, numpy.newaxis] * const_z
|
|
90
89
|
+ numpy.abs(coeffRHS) ** 2 * tmp[:, numpy.newaxis] * const_z
|
|
91
90
|
)
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
plt.hot()
|
|
92
|
+
plt.contourf(x, z0 + z, numpy.abs(f).T, 16)
|
|
94
93
|
|
|
95
94
|
|
|
96
95
|
class SimpleJoint:
|
|
@@ -221,9 +220,9 @@ class GenericDevice:
|
|
|
221
220
|
for d in self.devlist:
|
|
222
221
|
d.plot(sumx, nxy, nz, z0=z)
|
|
223
222
|
z += d.length
|
|
224
|
-
|
|
223
|
+
plt.ylabel("z")
|
|
225
224
|
if sumx is None:
|
|
226
|
-
|
|
225
|
+
plt.xlabel("y")
|
|
227
226
|
else:
|
|
228
|
-
|
|
229
|
-
|
|
227
|
+
plt.xlabel("x")
|
|
228
|
+
plt.axis("tight")
|
EMpy/transfer_matrix.py
CHANGED
|
@@ -7,6 +7,7 @@ any thickness.
|
|
|
7
7
|
Two versions of the algorithm are present: an isotropic one and an
|
|
8
8
|
anisotropic one.
|
|
9
9
|
"""
|
|
10
|
+
|
|
10
11
|
__author__ = "Lorenzo Bolla"
|
|
11
12
|
|
|
12
13
|
import numpy as np
|
|
@@ -18,7 +19,6 @@ from EMpy.constants import c, mu0
|
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class TransferMatrix:
|
|
21
|
-
|
|
22
22
|
"""Class to handle the transfer matrix solvers."""
|
|
23
23
|
|
|
24
24
|
def __init__(self, multilayer):
|
|
@@ -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
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
EMpy/utils.py
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
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"
|
|
6
4
|
|
|
5
|
+
import time
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from matplotlib import pyplot as plt
|
|
7
9
|
import numpy
|
|
8
|
-
import EMpy.constants
|
|
9
|
-
import EMpy.materials
|
|
10
10
|
import scipy.linalg
|
|
11
11
|
import scipy.interpolate
|
|
12
12
|
import scipy.optimize
|
|
13
|
-
import time
|
|
14
|
-
import sys
|
|
15
13
|
|
|
14
|
+
import EMpy.constants
|
|
15
|
+
import EMpy.materials
|
|
16
16
|
|
|
17
|
-
class Layer:
|
|
18
17
|
|
|
18
|
+
class Layer:
|
|
19
19
|
"""A layer is defined by a material (iso or aniso) and a thickness."""
|
|
20
20
|
|
|
21
21
|
def __init__(self, mat, thickness):
|
|
@@ -96,9 +96,7 @@ class BinaryGrating:
|
|
|
96
96
|
f = self.dc
|
|
97
97
|
h = numpy.arange(-hmax, hmax + 1)
|
|
98
98
|
EPS = (rix1**2 - rix2**2) * f * numpy.sinc(h * f) + rix2**2 * (h == 0)
|
|
99
|
-
EPS1 = (rix1**-2 - rix2**-2) * f * numpy.sinc(h * f) + rix2**-2 * (
|
|
100
|
-
h == 0
|
|
101
|
-
)
|
|
99
|
+
EPS1 = (rix1**-2 - rix2**-2) * f * numpy.sinc(h * f) + rix2**-2 * (h == 0)
|
|
102
100
|
return EPS, EPS1
|
|
103
101
|
else:
|
|
104
102
|
# anisotropic
|
|
@@ -694,7 +692,6 @@ class LiquidCrystalCell:
|
|
|
694
692
|
|
|
695
693
|
|
|
696
694
|
class Multilayer:
|
|
697
|
-
|
|
698
695
|
"""A Multilayer is a list of layers with some more methods."""
|
|
699
696
|
|
|
700
697
|
def __init__(self, data=None):
|
|
@@ -816,22 +813,17 @@ class Slice(Multilayer):
|
|
|
816
813
|
return self[0]
|
|
817
814
|
|
|
818
815
|
def plot(self, x0, x1, nmin, nmax, wl=1.55e-6):
|
|
819
|
-
try:
|
|
820
|
-
import pylab
|
|
821
|
-
except ImportError:
|
|
822
|
-
warning("no pylab installed")
|
|
823
|
-
return
|
|
824
816
|
y0 = 0
|
|
825
817
|
# ytot = sum([l.thickness for l in self])
|
|
826
818
|
for l in self:
|
|
827
819
|
y1 = y0 + l.thickness
|
|
828
820
|
n = l.mat.n(wl)
|
|
829
821
|
r = 1.0 - (1.0 * (n - nmin) / (nmax - nmin))
|
|
830
|
-
|
|
822
|
+
plt.fill(
|
|
831
823
|
[x0, x1, x1, x0], [y0, y0, y1, y1], ec="yellow", fc=(r, r, r), alpha=0.5
|
|
832
824
|
)
|
|
833
825
|
y0 = y1
|
|
834
|
-
|
|
826
|
+
plt.axis("image")
|
|
835
827
|
|
|
836
828
|
def __str__(self):
|
|
837
829
|
return "width = %e\n%s" % (self.width, Multilayer.__str__(self))
|
|
@@ -916,11 +908,6 @@ class CrossSection(list):
|
|
|
916
908
|
return eps
|
|
917
909
|
|
|
918
910
|
def plot(self, wl=1.55e-6):
|
|
919
|
-
try:
|
|
920
|
-
import pylab
|
|
921
|
-
except ImportError:
|
|
922
|
-
warning("no pylab installed")
|
|
923
|
-
return
|
|
924
911
|
x0 = 0
|
|
925
912
|
ns = [[l.mat.n(wl) for l in s] for s in self]
|
|
926
913
|
nmax = max(max(ns))
|
|
@@ -929,7 +916,7 @@ class CrossSection(list):
|
|
|
929
916
|
x1 = x0 + s.width
|
|
930
917
|
s.plot(x0, x1, nmin, nmax, wl=wl)
|
|
931
918
|
x0 = x1
|
|
932
|
-
|
|
919
|
+
plt.axis("image")
|
|
933
920
|
|
|
934
921
|
|
|
935
922
|
class Peak:
|
|
@@ -1218,7 +1205,7 @@ def interp2(x, y, xp, yp, fp):
|
|
|
1218
1205
|
|
|
1219
1206
|
def trapz2(f, x=None, y=None, dx=1.0, dy=1.0):
|
|
1220
1207
|
"""Double integrate."""
|
|
1221
|
-
return numpy.
|
|
1208
|
+
return numpy.trapezoid(numpy.trapezoid(f, x=y, dx=dy), x=x, dx=dx)
|
|
1222
1209
|
|
|
1223
1210
|
|
|
1224
1211
|
def centered1d(x):
|
|
@@ -1251,7 +1238,6 @@ def warning(s):
|
|
|
1251
1238
|
|
|
1252
1239
|
|
|
1253
1240
|
class ProgressBar:
|
|
1254
|
-
|
|
1255
1241
|
"""Creates a text-based progress bar. Call the object with the `print'
|
|
1256
1242
|
command to see the progress bar, which looks something like this:
|
|
1257
1243
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ElectroMagneticPython
|
|
3
|
+
Version: 2.2.4
|
|
4
|
+
Summary: EMpy - ElectroMagnetic Python
|
|
5
|
+
Author-email: Lorenzo Bolla <code@lbolla.info>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, http://lbolla.github.io/EMpy/
|
|
8
|
+
Project-URL: Repository, https://github.com/lbolla/EMpy
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: numpy>=1.18
|
|
20
|
+
Requires-Dist: scipy>=1.7
|
|
21
|
+
Requires-Dist: matplotlib>=3.1
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# EMpy - ElectroMagnetic Python
|
|
25
|
+
|
|
26
|
+
[](https://github.com/lbolla/EMpy/actions/workflows/python-app.yml) [](https://badge.fury.io/py/ElectroMagneticPython)
|
|
27
|
+
|
|
28
|
+
`EMpy - ElectroMagnetic Python` is a suite of algorithms widely known and used in electromagnetic problems and optics: the transfer matrix algorithm, the rigorous coupled wave analysis algorithm and more.
|
|
29
|
+
|
|
30
|
+
Run the examples in `examples/*` to have an idea how EMpy works.
|
|
31
|
+
|
|
32
|
+
Visit https://lbolla.github.io/EMpy/ for more information.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install ElectromagneticPython
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Optionally, install `bvp`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install scikits.bvp1lg
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Development
|
|
47
|
+
|
|
48
|
+
First, download the source code from https://github.com/lbolla/EMpy.
|
|
49
|
+
|
|
50
|
+
EMpy is managed with `uv` (https://docs.astral.sh/uv/):
|
|
51
|
+
|
|
52
|
+
Install dev environment with:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
make develop
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Run tests with:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
make test
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Run examples with, e.g.:
|
|
65
|
+
```bash
|
|
66
|
+
uv run examples/ex_APRR.py
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Upgrade dependencies with `uv`:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
make upgrade
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Release process
|
|
76
|
+
|
|
77
|
+
Package version is handled by `setuptools_scm`/`uv`:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
make release PART=...
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
GitHub actions will build and upload the package to PyPI.
|
|
84
|
+
|
|
85
|
+
## Citation
|
|
86
|
+
|
|
87
|
+
If you find EMpy useful in your job, please consider adding a citation.
|
|
88
|
+
|
|
89
|
+
As reference:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
Bolla, L. (2017). EMpy [Computer software]. https://github.com/lbolla/EMpy/
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
As text:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
We used EMpy (version x.y.z) to complete our work.
|
|
99
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
EMpy/RCWA.py,sha256=ORsYHvt1p7TIR3vKYQfhigRH1RnHyAX98kkGMkmxIi0,32673
|
|
2
|
+
EMpy/__init__.py,sha256=aAaHG0VlGltUrWWZ4JMlVms2HDGj7RZ3CYNKqpZVYtM,1285
|
|
3
|
+
EMpy/_version.py,sha256=L0uLqtm_cNa8ezMmrDendz17E_txW-SkqG84SLLwt1o,528
|
|
4
|
+
EMpy/constants.py,sha256=kYVVAdOENFthm_Aqt5oT4eMOmbMNdkvpM2t1r-_IShE,698
|
|
5
|
+
EMpy/devices.py,sha256=08LN_Nas0cpzQVj-J3x25AdObycwm_0b6k3s_dw2w6c,37679
|
|
6
|
+
EMpy/materials.py,sha256=2TSTVY5R6tw5auHyWJcvFHSgMA2KANbCCbziuRO0GyY,10633
|
|
7
|
+
EMpy/scattering.py,sha256=1rY8_TI0kzTLYwpFSSXndaO9FzDzVPRVow55vzIDQiM,7339
|
|
8
|
+
EMpy/transfer_matrix.py,sha256=0xqCbNvlxSQxqcWXm0Q_O0e9NWWvKPMlfZY36HIXAnk,14848
|
|
9
|
+
EMpy/utils.py,sha256=BWgKxpdS29OXWkLp13Ft00ef-vzR8COZO1hn8KsASPc,41683
|
|
10
|
+
EMpy/modesolvers/FD.py,sha256=oBlMSP1F1Ja1NIiIQcxUm-ZWHYYrKQHZaPxQ0ZuPMfY,78988
|
|
11
|
+
EMpy/modesolvers/FMM.py,sha256=Z0HL_QGeJoQC9vyY2obBomcey0ZzVT5YZmD2-hABqZ8,78351
|
|
12
|
+
EMpy/modesolvers/__init__.py,sha256=rg8pzFcZd7cihqfXYj0sQamogjtMV3ObNXCNbFD3bu0,222
|
|
13
|
+
EMpy/modesolvers/geometries.py,sha256=X8Jd1iNoPRl5ibZiaKG13lHDIzejQ6PfrB6Zbe_c5lg,7906
|
|
14
|
+
EMpy/modesolvers/interface.py,sha256=spMy30TFedYXJHcoV3yUdGkycGt5cplJUCeZui6a5MY,2397
|
|
15
|
+
electromagneticpython-2.2.4.dist-info/licenses/LICENSE,sha256=NlQFsrkwMvQ2aD8531IDm6Rk01KzlI42HVzK5M1Hpw8,1065
|
|
16
|
+
examples/ex_APRR.py,sha256=f3-LOPoLNSxjqfwAJJNjVSnKYB88CIULhbjzkzdavXA,459
|
|
17
|
+
examples/ex_NRR.py,sha256=NVs4UASVdwiogZDSOfGAoSnbBByhB8EBLu4x3CDOnyE,900
|
|
18
|
+
examples/ex_RCWA.py,sha256=05Cvv3BqFgSDn_u2iZsV65HdmvVbNljgJfISaPsqd1o,2733
|
|
19
|
+
examples/ex_RCWA_2.py,sha256=Iwb75g2OYWayBpGn2P5BlPBh_50ZeM354eJ3kjj8pgg,1455
|
|
20
|
+
examples/ex_RCWA_3.py,sha256=unROedjRchAnLmyqPdhkl2-qekmddtWw6d8i6oo5VQU,1329
|
|
21
|
+
examples/ex_SRR.py,sha256=ciRDjn0IlpThYVLpSkn2dW6oOnJwt7_c7JJzMydl444,612
|
|
22
|
+
examples/ex_laser_etch_monitor.py,sha256=n6Ov8BvStKw-2veSNvX2nmR2VQJyWfsyOSh1ggvZ2qM,7589
|
|
23
|
+
examples/ex_modesolver.py,sha256=gD06Z2DXrxVCfakAIkqNR5k7ynSz5e1hfEYvt8ZyO0w,1529
|
|
24
|
+
examples/ex_modesolver_2.py,sha256=nWohSs9eftfY06wsg13M3UHBMcmM0QdPrOEWNta28mo,1264
|
|
25
|
+
examples/ex_modesolver_3.py,sha256=RA6LvitShITChg4DWFleI8FUUOnSUwIOCsxfW4VByGg,1209
|
|
26
|
+
examples/ex_modesolver_4.py,sha256=9JUjg6NK7IjwSgQvg3D_n6l_Cr0ev6hEoJGS0xffrFo,901
|
|
27
|
+
examples/ex_modesolver_dch.py,sha256=ha38QB7rLklEnTNfF_C0b8u7gTGKIk_T3FB0TMib5eM,7314
|
|
28
|
+
examples/ex_modesolver_dch_anis.py,sha256=Ye4nV5FXVxjT-FtJ3CyjzjXh9pmx9A0mbv-CkZxIN3Y,8184
|
|
29
|
+
examples/ex_transfer_matrix.py,sha256=JyC_MPrrfpNItYmMQjm5RbMWXe7CSd96RplJrntdOaI,1789
|
|
30
|
+
examples/ex_transfer_matrix_2.py,sha256=anMoXcGgpioJ5k0AvHHFEynT32etWFgmEpLy5SL2nNI,1060
|
|
31
|
+
examples/ex_transfer_matrix_2.py.png,sha256=-cgjAE1t_6UPJyOZbAagaaBs-odr59A1RYldSpMOo0M,34886
|
|
32
|
+
examples/ex_transfer_matrix_3.py,sha256=J8GePd3b45TmGJWL_Df7GFg-4FN8846WS9j7l9TmvRs,1501
|
|
33
|
+
examples/lc_data.dat,sha256=MrT57K7PZV0YT2GPU9LjO6WlC-xCd6n841P57tQW5_s,4151
|
|
34
|
+
examples/nk.py,sha256=hjUhwu4QzXCR0_PSKAnQ0RTD4mfe7xCYW6AbrSu4d3U,43161
|
|
35
|
+
scripts/FDTD.py,sha256=eK3Ra8GqkgWGP_oAPrM5pXlxERWgrwl2jwJIwoYGDfE,25308
|
|
36
|
+
tests/__init__.py,sha256=XNMyfmlHhqih2xHEklXlmQ8GVUAdiiWrkT3trIOMpRQ,29
|
|
37
|
+
tests/devices_test.py,sha256=UbmJgHp7kNVQyBYwxgaAierUVMvC7Pq5Jv7BKdFQPSw,890
|
|
38
|
+
tests/materials_test.py,sha256=-Z8ZmqwgSCg2AJwF_4j-RH8Ct7AOOWhV67lyMm5dcO8,1846
|
|
39
|
+
tests/modesolvers_test.py,sha256=v_nRDbKlda4w7A5mbZZl5fKYa2GlgLzHZaKDJZzGyrM,984
|
|
40
|
+
tests/transfer_matrix_test.py,sha256=hp9idGz0G9BcriJYVxtJJokROqliSyl8RR4Zuxjm8Tw,5330
|
|
41
|
+
tests/utils_test.py,sha256=QnG4O_FHrX6tXH1MuocFXxptOuOtoU-dR-crCtADzQw,721
|
|
42
|
+
electromagneticpython-2.2.4.dist-info/METADATA,sha256=bHDIDEcgf6o6NK-aSI3g1pBTf02A9VXpuicoHsF9zvU,2351
|
|
43
|
+
electromagneticpython-2.2.4.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
44
|
+
electromagneticpython-2.2.4.dist-info/top_level.txt,sha256=CosMJsXjoaa3iZmCrZf7E0eorTFxpEFfrtfUx1YWIHA,28
|
|
45
|
+
electromagneticpython-2.2.4.dist-info/RECORD,,
|
examples/ex_APRR.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""All-pass ring resonator example."""
|
|
2
|
+
|
|
3
|
+
from matplotlib import pyplot as plt
|
|
4
|
+
import numpy
|
|
5
|
+
|
|
6
|
+
import EMpy
|
|
7
|
+
|
|
8
|
+
wls = numpy.linspace(1.5e-6, 1.6e-6, 1000)
|
|
9
|
+
K = EMpy.devices.Coupler(wls, numpy.sqrt(0.08), 1.0)
|
|
10
|
+
l = 2 * numpy.pi * 5e-6
|
|
11
|
+
SWG = EMpy.devices.SWG(400, 220, 125).solve(wls)
|
|
12
|
+
APRR = EMpy.devices.APRR(K, SWG.neff, l).solve()
|
|
13
|
+
|
|
14
|
+
plt.plot(wls, numpy.unwrap(numpy.angle(APRR.THRU)), "r.-")
|
|
15
|
+
plt.axis("tight")
|
|
16
|
+
plt.xlabel("wavelength /m")
|
|
17
|
+
plt.ylabel("phase")
|
|
18
|
+
plt.show()
|
examples/ex_NRR.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""N-Ring resonators example."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from matplotlib import pyplot as plt
|
|
5
|
+
import numpy
|
|
6
|
+
|
|
7
|
+
import EMpy
|
|
8
|
+
|
|
9
|
+
wls = numpy.linspace(1.53e-6, 1.57e-6, 1000)
|
|
10
|
+
|
|
11
|
+
Ks = [
|
|
12
|
+
EMpy.devices.Coupler(wls, numpy.sqrt(0.08), 1.0),
|
|
13
|
+
EMpy.devices.Coupler(wls, numpy.sqrt(0.008), 1.0),
|
|
14
|
+
EMpy.devices.Coupler(wls, numpy.sqrt(0.006), 1.0),
|
|
15
|
+
EMpy.devices.Coupler(wls, numpy.sqrt(0.09), 1.0),
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
R = 5e-6
|
|
19
|
+
l1s = [numpy.pi * R, numpy.pi * R, numpy.pi * R]
|
|
20
|
+
l2s = [numpy.pi * R, numpy.pi * R, numpy.pi * R]
|
|
21
|
+
|
|
22
|
+
SWG = EMpy.devices.SWG(400, 220, 125).solve(wls)
|
|
23
|
+
neffs = [SWG.neff, SWG.neff, SWG.neff]
|
|
24
|
+
|
|
25
|
+
NRR = EMpy.devices.NRR(Ks, neffs, l1s, l2s).solve()
|
|
26
|
+
|
|
27
|
+
plt.plot(
|
|
28
|
+
wls,
|
|
29
|
+
20 * numpy.log10(numpy.absolute(NRR.THRU)),
|
|
30
|
+
"r.-",
|
|
31
|
+
wls,
|
|
32
|
+
20 * numpy.log10(numpy.absolute(NRR.DROP)),
|
|
33
|
+
"g.-",
|
|
34
|
+
)
|
|
35
|
+
plt.axis("tight")
|
|
36
|
+
plt.ylim([-30, 0])
|
|
37
|
+
plt.xlabel("wavelength /m")
|
|
38
|
+
plt.ylabel("power /dB")
|
|
39
|
+
plt.legend(("THRU", "DROP"))
|
|
40
|
+
plt.show()
|
examples/ex_RCWA.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""Rigorous Coupled Wave Analysis example."""
|
|
2
|
+
|
|
3
|
+
from matplotlib import pyplot as plt
|
|
4
|
+
import numpy
|
|
5
|
+
|
|
6
|
+
import EMpy
|
|
7
|
+
from EMpy.materials import (
|
|
8
|
+
IsotropicMaterial,
|
|
9
|
+
AnisotropicMaterial,
|
|
10
|
+
RefractiveIndex,
|
|
11
|
+
EpsilonTensor,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
alpha = 0.0
|
|
15
|
+
delta = 0.0
|
|
16
|
+
# psi = EMpy.utils.deg2rad(0.) # TM
|
|
17
|
+
# psi = EMpy.utils.deg2rad(90.) # TE
|
|
18
|
+
psi = EMpy.utils.deg2rad(70.0) # hybrid
|
|
19
|
+
phi = EMpy.utils.deg2rad(90.0)
|
|
20
|
+
|
|
21
|
+
LAMBDA = 1016e-9 # grating periodicity
|
|
22
|
+
n = 2 # orders of diffraction
|
|
23
|
+
|
|
24
|
+
UV6 = IsotropicMaterial("UV6", n0=RefractiveIndex(n0_const=1.560))
|
|
25
|
+
SiN = AnisotropicMaterial(
|
|
26
|
+
"SiN",
|
|
27
|
+
epsilon_tensor=EpsilonTensor(
|
|
28
|
+
epsilon_tensor_const=EMpy.constants.eps0
|
|
29
|
+
* EMpy.utils.euler_rotate(
|
|
30
|
+
numpy.diag(numpy.asarray([1.8550, 1.8750, 1.9130]) ** 2),
|
|
31
|
+
EMpy.utils.deg2rad(14),
|
|
32
|
+
EMpy.utils.deg2rad(25),
|
|
33
|
+
EMpy.utils.deg2rad(32),
|
|
34
|
+
)
|
|
35
|
+
),
|
|
36
|
+
)
|
|
37
|
+
BPTEOS = IsotropicMaterial("BPTEOS", n0=RefractiveIndex(n0_const=1.448))
|
|
38
|
+
ARC1 = IsotropicMaterial("ARC1", n0=RefractiveIndex(n0_const=1.448))
|
|
39
|
+
|
|
40
|
+
EFF = IsotropicMaterial("EFF", n0=RefractiveIndex(n0_const=1.6))
|
|
41
|
+
|
|
42
|
+
multilayer1 = EMpy.utils.Multilayer(
|
|
43
|
+
[
|
|
44
|
+
EMpy.utils.Layer(EMpy.materials.Air, numpy.inf),
|
|
45
|
+
EMpy.utils.Layer(SiN, 226e-9),
|
|
46
|
+
EMpy.utils.Layer(BPTEOS, 226e-9),
|
|
47
|
+
EMpy.utils.BinaryGrating(SiN, BPTEOS, 0.659, LAMBDA, 123e-9),
|
|
48
|
+
EMpy.utils.Layer(SiN, 219e-9),
|
|
49
|
+
EMpy.utils.Layer(EMpy.materials.SiO2, 2188e-9),
|
|
50
|
+
EMpy.utils.Layer(EMpy.materials.Si, numpy.inf),
|
|
51
|
+
]
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
multilayer2 = EMpy.utils.Multilayer(
|
|
55
|
+
[
|
|
56
|
+
EMpy.utils.Layer(EMpy.materials.Air, numpy.inf),
|
|
57
|
+
EMpy.utils.Layer(SiN, 226e-9),
|
|
58
|
+
EMpy.utils.Layer(BPTEOS, 226e-9),
|
|
59
|
+
EMpy.utils.Layer(IsotropicMaterial(n0=RefractiveIndex(n0_const=1.6)), 123e-9),
|
|
60
|
+
EMpy.utils.Layer(SiN, 219e-9),
|
|
61
|
+
EMpy.utils.Layer(EMpy.materials.SiO2, 2188e-9),
|
|
62
|
+
EMpy.utils.Layer(EMpy.materials.Si, numpy.inf),
|
|
63
|
+
]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
wls = numpy.linspace(1.45e-6, 1.75e-6, 301)
|
|
67
|
+
|
|
68
|
+
solution1 = EMpy.RCWA.AnisotropicRCWA(multilayer1, alpha, delta, psi, phi, n).solve(wls)
|
|
69
|
+
solution2 = EMpy.RCWA.AnisotropicRCWA(multilayer2, alpha, delta, psi, phi, n).solve(wls)
|
|
70
|
+
|
|
71
|
+
um = 1e-6
|
|
72
|
+
plt.plot(
|
|
73
|
+
# wls / um, solution1.DEO1[n, :], 'k.-',
|
|
74
|
+
# wls / um, solution1.DEO3[n, :], 'r.-',
|
|
75
|
+
wls / um,
|
|
76
|
+
solution1.DEE1[n, :],
|
|
77
|
+
"b.-",
|
|
78
|
+
wls / um,
|
|
79
|
+
solution1.DEE3[n, :],
|
|
80
|
+
"g.-",
|
|
81
|
+
# wls / um, solution2.DEO1[n, :], 'k--',
|
|
82
|
+
# wls / um, solution2.DEO3[n, :], 'r--',
|
|
83
|
+
wls / um,
|
|
84
|
+
solution2.DEE1[n, :],
|
|
85
|
+
"b--",
|
|
86
|
+
wls / um,
|
|
87
|
+
solution2.DEE3[n, :],
|
|
88
|
+
"g--",
|
|
89
|
+
)
|
|
90
|
+
plt.xlabel("wavelength [um]")
|
|
91
|
+
plt.ylabel("diffraction efficiency")
|
|
92
|
+
plt.legend(("DEO1", "DEO3", "DEE1", "DEE3"))
|
|
93
|
+
plt.axis("tight")
|
|
94
|
+
plt.ylim([0, 0.15])
|
|
95
|
+
plt.show()
|
examples/ex_RCWA_2.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Rigorous Coupled Wave Analysis example.
|
|
2
|
+
|
|
3
|
+
Inspired by Moharam, "Formulation for stable and efficient implementation of the rigorous coupled-wave analysis of
|
|
4
|
+
binary gratings", JOSA A, 12(5), 1995
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from matplotlib import pyplot as plt
|
|
8
|
+
import numpy
|
|
9
|
+
|
|
10
|
+
import EMpy
|
|
11
|
+
from EMpy.materials import IsotropicMaterial, RefractiveIndex
|
|
12
|
+
|
|
13
|
+
alpha = EMpy.utils.deg2rad(10.0)
|
|
14
|
+
delta = EMpy.utils.deg2rad(0.0)
|
|
15
|
+
psi = EMpy.utils.deg2rad(0.0) # TE
|
|
16
|
+
phi = EMpy.utils.deg2rad(90.0)
|
|
17
|
+
|
|
18
|
+
wl = numpy.array([1.55e-6])
|
|
19
|
+
ds = numpy.linspace(0.0, 5.0, 100) * wl
|
|
20
|
+
LAMBDA = 10 * wl
|
|
21
|
+
|
|
22
|
+
n = 3 # orders of diffraction
|
|
23
|
+
|
|
24
|
+
Top = IsotropicMaterial("Top", n0=RefractiveIndex(n0_const=1.0))
|
|
25
|
+
Bottom = IsotropicMaterial("Bottom", n0=RefractiveIndex(n0_const=2.04))
|
|
26
|
+
|
|
27
|
+
solutions = []
|
|
28
|
+
for d in ds:
|
|
29
|
+
multilayer = EMpy.utils.Multilayer(
|
|
30
|
+
[
|
|
31
|
+
EMpy.utils.Layer(Top, numpy.inf),
|
|
32
|
+
EMpy.utils.BinaryGrating(Top, Bottom, 0.3, LAMBDA, d),
|
|
33
|
+
EMpy.utils.Layer(Bottom, numpy.inf),
|
|
34
|
+
]
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
solution = EMpy.RCWA.IsotropicRCWA(multilayer, alpha, delta, psi, phi, n).solve(wl)
|
|
38
|
+
solutions.append(solution)
|
|
39
|
+
|
|
40
|
+
DE1 = numpy.zeros(len(solutions))
|
|
41
|
+
DE3 = numpy.zeros(len(solutions))
|
|
42
|
+
for ss, s in enumerate(solutions):
|
|
43
|
+
DE1[ss] = s.DE1[n, 0]
|
|
44
|
+
DE3[ss] = s.DE3[n, 0]
|
|
45
|
+
|
|
46
|
+
plt.plot(ds / wl, DE1[:], "k.-", ds / wl, DE3[:], "r.-")
|
|
47
|
+
plt.xlabel("normalized groove depth")
|
|
48
|
+
plt.ylabel("diffraction efficiency")
|
|
49
|
+
plt.legend(("DE1", "DE3"))
|
|
50
|
+
plt.axis("tight")
|
|
51
|
+
plt.ylim([0, 1])
|
|
52
|
+
plt.show()
|