ElectroMagneticPython 2.2.1__py3-none-any.whl → 2.2.3__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 +34 -0
- EMpy/devices.py +4 -27
- EMpy/materials.py +1 -6
- EMpy/modesolvers/FD.py +34 -72
- EMpy/modesolvers/FMM.py +24 -23
- EMpy/modesolvers/__init__.py +1 -0
- EMpy/modesolvers/geometries.py +8 -9
- EMpy/transfer_matrix.py +1 -1
- EMpy/utils.py +12 -24
- electromagneticpython-2.2.3.dist-info/METADATA +99 -0
- electromagneticpython-2.2.3.dist-info/RECORD +44 -0
- {ElectroMagneticPython-2.2.1.dist-info → electromagneticpython-2.2.3.dist-info}/WHEEL +1 -1
- electromagneticpython-2.2.3.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/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.3.dist-info/licenses}/LICENSE +0 -0
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):
|
EMpy/utils.py
CHANGED
|
@@ -4,18 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
__author__ = "Lorenzo Bolla"
|
|
6
6
|
|
|
7
|
+
import time
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
from matplotlib import pyplot as plt
|
|
7
11
|
import numpy
|
|
8
|
-
import EMpy.constants
|
|
9
|
-
import EMpy.materials
|
|
10
12
|
import scipy.linalg
|
|
11
13
|
import scipy.interpolate
|
|
12
14
|
import scipy.optimize
|
|
13
|
-
import time
|
|
14
|
-
import sys
|
|
15
15
|
|
|
16
|
+
import EMpy.constants
|
|
17
|
+
import EMpy.materials
|
|
16
18
|
|
|
17
|
-
class Layer:
|
|
18
19
|
|
|
20
|
+
class Layer:
|
|
19
21
|
"""A layer is defined by a material (iso or aniso) and a thickness."""
|
|
20
22
|
|
|
21
23
|
def __init__(self, mat, thickness):
|
|
@@ -96,9 +98,7 @@ class BinaryGrating:
|
|
|
96
98
|
f = self.dc
|
|
97
99
|
h = numpy.arange(-hmax, hmax + 1)
|
|
98
100
|
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
|
-
)
|
|
101
|
+
EPS1 = (rix1**-2 - rix2**-2) * f * numpy.sinc(h * f) + rix2**-2 * (h == 0)
|
|
102
102
|
return EPS, EPS1
|
|
103
103
|
else:
|
|
104
104
|
# anisotropic
|
|
@@ -694,7 +694,6 @@ class LiquidCrystalCell:
|
|
|
694
694
|
|
|
695
695
|
|
|
696
696
|
class Multilayer:
|
|
697
|
-
|
|
698
697
|
"""A Multilayer is a list of layers with some more methods."""
|
|
699
698
|
|
|
700
699
|
def __init__(self, data=None):
|
|
@@ -816,22 +815,17 @@ class Slice(Multilayer):
|
|
|
816
815
|
return self[0]
|
|
817
816
|
|
|
818
817
|
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
818
|
y0 = 0
|
|
825
819
|
# ytot = sum([l.thickness for l in self])
|
|
826
820
|
for l in self:
|
|
827
821
|
y1 = y0 + l.thickness
|
|
828
822
|
n = l.mat.n(wl)
|
|
829
823
|
r = 1.0 - (1.0 * (n - nmin) / (nmax - nmin))
|
|
830
|
-
|
|
824
|
+
plt.fill(
|
|
831
825
|
[x0, x1, x1, x0], [y0, y0, y1, y1], ec="yellow", fc=(r, r, r), alpha=0.5
|
|
832
826
|
)
|
|
833
827
|
y0 = y1
|
|
834
|
-
|
|
828
|
+
plt.axis("image")
|
|
835
829
|
|
|
836
830
|
def __str__(self):
|
|
837
831
|
return "width = %e\n%s" % (self.width, Multilayer.__str__(self))
|
|
@@ -916,11 +910,6 @@ class CrossSection(list):
|
|
|
916
910
|
return eps
|
|
917
911
|
|
|
918
912
|
def plot(self, wl=1.55e-6):
|
|
919
|
-
try:
|
|
920
|
-
import pylab
|
|
921
|
-
except ImportError:
|
|
922
|
-
warning("no pylab installed")
|
|
923
|
-
return
|
|
924
913
|
x0 = 0
|
|
925
914
|
ns = [[l.mat.n(wl) for l in s] for s in self]
|
|
926
915
|
nmax = max(max(ns))
|
|
@@ -929,7 +918,7 @@ class CrossSection(list):
|
|
|
929
918
|
x1 = x0 + s.width
|
|
930
919
|
s.plot(x0, x1, nmin, nmax, wl=wl)
|
|
931
920
|
x0 = x1
|
|
932
|
-
|
|
921
|
+
plt.axis("image")
|
|
933
922
|
|
|
934
923
|
|
|
935
924
|
class Peak:
|
|
@@ -1218,7 +1207,7 @@ def interp2(x, y, xp, yp, fp):
|
|
|
1218
1207
|
|
|
1219
1208
|
def trapz2(f, x=None, y=None, dx=1.0, dy=1.0):
|
|
1220
1209
|
"""Double integrate."""
|
|
1221
|
-
return numpy.
|
|
1210
|
+
return numpy.trapezoid(numpy.trapezoid(f, x=y, dx=dy), x=x, dx=dx)
|
|
1222
1211
|
|
|
1223
1212
|
|
|
1224
1213
|
def centered1d(x):
|
|
@@ -1251,7 +1240,6 @@ def warning(s):
|
|
|
1251
1240
|
|
|
1252
1241
|
|
|
1253
1242
|
class ProgressBar:
|
|
1254
|
-
|
|
1255
1243
|
"""Creates a text-based progress bar. Call the object with the `print'
|
|
1256
1244
|
command to see the progress bar, which looks something like this:
|
|
1257
1245
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ElectroMagneticPython
|
|
3
|
+
Version: 2.2.3
|
|
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,44 @@
|
|
|
1
|
+
EMpy/RCWA.py,sha256=ORsYHvt1p7TIR3vKYQfhigRH1RnHyAX98kkGMkmxIi0,32673
|
|
2
|
+
EMpy/__init__.py,sha256=aAaHG0VlGltUrWWZ4JMlVms2HDGj7RZ3CYNKqpZVYtM,1285
|
|
3
|
+
EMpy/_version.py,sha256=KPjL9Q7mJ1mOq60evnMRyAe7ifMMp2BfVmDRydV9x98,704
|
|
4
|
+
EMpy/constants.py,sha256=x1N8eRXQW_gdr1557n7tvUXiM4RW_Fc_EydLd5AUC1o,723
|
|
5
|
+
EMpy/devices.py,sha256=Tu7CVvrhqfHBSf1EiDNPnUG4Dn6MDb6qgg2VpafmdHs,37760
|
|
6
|
+
EMpy/materials.py,sha256=pgEM4Izy6HTA87Rl_GtNiiq5AKzc3M54fVFPFRnA8_I,10682
|
|
7
|
+
EMpy/scattering.py,sha256=1rY8_TI0kzTLYwpFSSXndaO9FzDzVPRVow55vzIDQiM,7339
|
|
8
|
+
EMpy/transfer_matrix.py,sha256=wSFqcEQYNUV4oM5SlZkglwRVyU5_w5dvRENXHfRXQpQ,14582
|
|
9
|
+
EMpy/utils.py,sha256=hIZ07CqM1lhRTIujbReGldlBkUjzI3iXAyAReEATBqA,41762
|
|
10
|
+
EMpy/modesolvers/FD.py,sha256=vKQOTgXY3-KzODAX0IOAfLbcFHUbpRt0MgteRLU3vjk,79281
|
|
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.3.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=i1YMmrOSWDK0YS9aGF2thFD4_suNZsRJvs7Ei62sHAI,1058
|
|
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/utils_test.py,sha256=QnG4O_FHrX6tXH1MuocFXxptOuOtoU-dR-crCtADzQw,721
|
|
41
|
+
electromagneticpython-2.2.3.dist-info/METADATA,sha256=XB6uQFtMcIOL-56FDLYMqR1_i_Cne79NZP4UApAC8os,2351
|
|
42
|
+
electromagneticpython-2.2.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
43
|
+
electromagneticpython-2.2.3.dist-info/top_level.txt,sha256=CosMJsXjoaa3iZmCrZf7E0eorTFxpEFfrtfUx1YWIHA,28
|
|
44
|
+
electromagneticpython-2.2.3.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()
|
examples/ex_RCWA_3.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Rigorous Coupled Wave Analysis example."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from matplotlib import pyplot as plt
|
|
5
|
+
import numpy
|
|
6
|
+
|
|
7
|
+
import EMpy
|
|
8
|
+
from EMpy.materials import IsotropicMaterial, RefractiveIndex
|
|
9
|
+
|
|
10
|
+
alpha = EMpy.utils.deg2rad(30.0)
|
|
11
|
+
delta = EMpy.utils.deg2rad(45.0)
|
|
12
|
+
psi = EMpy.utils.deg2rad(0.0) # TE
|
|
13
|
+
phi = EMpy.utils.deg2rad(90.0)
|
|
14
|
+
|
|
15
|
+
wls = numpy.linspace(1.5495e-6, 1.550e-6, 101)
|
|
16
|
+
|
|
17
|
+
LAMBDA = 1.0e-6 # grating periodicity
|
|
18
|
+
n = 3 # orders of diffraction
|
|
19
|
+
|
|
20
|
+
Top = IsotropicMaterial("Top", n0=RefractiveIndex(n0_const=1.0))
|
|
21
|
+
Bottom = IsotropicMaterial("Bottom", n0=RefractiveIndex(n0_const=3.47))
|
|
22
|
+
|
|
23
|
+
multilayer = EMpy.utils.Multilayer(
|
|
24
|
+
[
|
|
25
|
+
EMpy.utils.Layer(Top, numpy.inf),
|
|
26
|
+
EMpy.utils.BinaryGrating(Top, Bottom, 0.4, LAMBDA, 0.01),
|
|
27
|
+
EMpy.utils.Layer(Bottom, numpy.inf),
|
|
28
|
+
]
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
solution = EMpy.RCWA.IsotropicRCWA(multilayer, alpha, delta, psi, phi, n).solve(wls)
|
|
32
|
+
|
|
33
|
+
plt.plot(
|
|
34
|
+
wls,
|
|
35
|
+
solution.DE1[n, :],
|
|
36
|
+
"ko-",
|
|
37
|
+
wls,
|
|
38
|
+
solution.DE3[n, :],
|
|
39
|
+
"ro-",
|
|
40
|
+
wls,
|
|
41
|
+
solution.DE1[n - 1, :],
|
|
42
|
+
"kx-",
|
|
43
|
+
wls,
|
|
44
|
+
solution.DE3[n - 1, :],
|
|
45
|
+
"rx-",
|
|
46
|
+
wls,
|
|
47
|
+
solution.DE1[n + 1, :],
|
|
48
|
+
"k.-",
|
|
49
|
+
wls,
|
|
50
|
+
solution.DE3[n + 1, :],
|
|
51
|
+
"r.-",
|
|
52
|
+
)
|
|
53
|
+
plt.xlabel("wavelength /m")
|
|
54
|
+
plt.ylabel("diffraction efficiency")
|
|
55
|
+
plt.legend(("DE1:0", "DE3:0", "DE1:-1", "DE3:-1", "DE1:+1", "DE3:+1"))
|
|
56
|
+
plt.axis("tight")
|
|
57
|
+
plt.ylim([0, 1])
|
|
58
|
+
plt.show()
|
examples/ex_SRR.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Single ring resonator 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.56e-6, 1000)
|
|
10
|
+
K1 = EMpy.devices.Coupler(wls, numpy.sqrt(0.08), 1.0)
|
|
11
|
+
K2 = EMpy.devices.Coupler(wls, numpy.sqrt(0.08), 1.0)
|
|
12
|
+
l1 = numpy.pi * 5e-6
|
|
13
|
+
l2 = numpy.pi * 5e-6
|
|
14
|
+
SWG = EMpy.devices.SWG(488, 220, 25).solve(wls)
|
|
15
|
+
SRR = EMpy.devices.SRR(K1, K2, SWG.neff, l1, l2).solve()
|
|
16
|
+
|
|
17
|
+
plt.plot(wls, numpy.absolute(SRR.THRU), "r.-", wls, numpy.absolute(SRR.DROP), "g.-")
|
|
18
|
+
plt.axis("tight")
|
|
19
|
+
plt.ylim([0, 1])
|
|
20
|
+
plt.xlabel("wavelength /m")
|
|
21
|
+
plt.ylabel("power")
|
|
22
|
+
plt.legend(("THRU", "DROP"))
|
|
23
|
+
plt.show()
|