diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml index 258458280..4b543b77f 100644 --- a/.github/workflows/build-ci.yml +++ b/.github/workflows/build-ci.yml @@ -69,12 +69,6 @@ jobs: repository: NanoComp/mpb path: mpb-src - - name: Checkout libGDSII repository - uses: actions/checkout@v7 - with: - repository: HomerReid/libGDSII - path: libGDSII-src - - name: Cache dependency builds uses: actions/cache@v6 id: deps-cache @@ -94,10 +88,6 @@ jobs: if: steps.deps-cache.outputs.cache-hit != 'true' run: cd mpb-src && sh autogen.sh --prefix=${HOME}/local --enable-shared LIBS=-ldl --with-libctl=${HOME}/local/share/libctl --with-hermitian-eps && make -j $(nproc) && make install - - name: Build and install libGDSII - if: steps.deps-cache.outputs.cache-hit != 'true' - run: cd libGDSII-src && sh autogen.sh --prefix=${HOME}/local && make install - - name: Define environment variables for serial build if: ${{ matrix.enable-mpi == false }} run: | diff --git a/.github/workflows/build-san.yml b/.github/workflows/build-san.yml index 1836a7ae4..35f0e9b18 100644 --- a/.github/workflows/build-san.yml +++ b/.github/workflows/build-san.yml @@ -39,7 +39,7 @@ jobs: run: | sudo apt-get update -y sudo apt-get install -y autoconf automake clang libaec-dev libctl-dev \ - libfftw3-dev libgdsii-dev libgsl-dev libharminv-dev libhdf5-dev \ + libfftw3-dev libgsl-dev libharminv-dev libhdf5-dev \ libtool mpb mpb-dev ccache mkdir -p ~/apt-cache cp /var/cache/apt/archives/*.deb ~/apt-cache/ 2>/dev/null || true diff --git a/README.md b/README.md index afcf3b943..34ea25c6d 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ - [Custom current sources](https://meep.readthedocs.io/en/latest/Python_Tutorials/Custom_Source/) with arbitrary time and spatial profile as well as a [mode launcher](https://meep.readthedocs.io/en/latest/Python_Tutorials/Eigenmode_Source/) for waveguides and planewaves, and [Gaussian beams](https://meep.readthedocs.io/en/latest/Python_User_Interface/#gaussianbeam3dsource). - [Frequency-domain solver](https://meep.readthedocs.io/en/latest/Python_User_Interface/#frequency-domain-solver) for finding the response to a [continuous-wave](https://en.wikipedia.org/wiki/Continuous_wave) (CW) source as well as a [frequency-domain eigensolver](https://meep.readthedocs.io/en/latest/Python_User_Interface/#frequency-domain-eigensolver) for finding resonant modes. - ε/μ and field import/export in the [HDF5](https://en.wikipedia.org/wiki/HDF5) data format. -- [GDSII](https://meep.readthedocs.io/en/latest/Python_User_Interface/#gdsii-support) file import for planar geometries. -- Field analyses including [discrete-time Fourier transform (DTFT)](https://meep.readthedocs.io/en/latest/Python_User_Interface/#field-computations), [Poynting flux](https://meep.readthedocs.io/en/latest/Python_Tutorials/Basics/#transmittance-spectrum-of-a-waveguide-bend), [mode decomposition](https://meep.readthedocs.io/en/latest/Python_Tutorials/Mode_Decomposition/) (for [S-parameters](https://meep.readthedocs.io/en/latest/Python_Tutorials/GDSII_Import/#s-parameters-of-a-directional-coupler)), [energy density](https://meep.readthedocs.io/en/latest/Python_User_Interface/#energy-density-spectra), [near to far transformation](https://meep.readthedocs.io/en/latest/Python_Tutorials/Near_to_Far_Field_Spectra/), [frequency extraction](https://meep.readthedocs.io/en/latest/Python_Tutorials/Basics/#modes-of-a-ring-resonator), [local density of states](https://meep.readthedocs.io/en/latest/Python_Tutorials/Local_Density_of_States/) (LDOS), [modal volume](https://meep.readthedocs.io/en/latest/Python_User_Interface/#field-computations), [scattering cross section](https://meep.readthedocs.io/en/latest/Python_Tutorials/Basics/#mie-scattering-of-a-lossless-dielectric-sphere), [Maxwell stress tensor](https://meep.readthedocs.io/en/latest/Python_Tutorials/Optical_Forces/), [absorbed power density](https://meep.readthedocs.io/en/latest/Python_Tutorials/Basics/#absorbed-power-density-map-of-a-lossy-cylinder), [arbitrary functions](https://meep.readthedocs.io/en/latest/Field_Functions/); completely programmable. +- [GDS](https://meep.readthedocs.io/en/latest/Python_Tutorials/GDS_Import/) file import for planar geometries. +- Field analyses including [discrete-time Fourier transform (DTFT)](https://meep.readthedocs.io/en/latest/Python_User_Interface/#field-computations), [Poynting flux](https://meep.readthedocs.io/en/latest/Python_Tutorials/Basics/#transmittance-spectrum-of-a-waveguide-bend), [mode decomposition](https://meep.readthedocs.io/en/latest/Python_Tutorials/Mode_Decomposition/) (for [S-parameters](https://meep.readthedocs.io/en/latest/Python_Tutorials/GDS_Import/#s-parameters-of-a-directional-coupler)), [energy density](https://meep.readthedocs.io/en/latest/Python_User_Interface/#energy-density-spectra), [near to far transformation](https://meep.readthedocs.io/en/latest/Python_Tutorials/Near_to_Far_Field_Spectra/), [frequency extraction](https://meep.readthedocs.io/en/latest/Python_Tutorials/Basics/#modes-of-a-ring-resonator), [local density of states](https://meep.readthedocs.io/en/latest/Python_Tutorials/Local_Density_of_States/) (LDOS), [modal volume](https://meep.readthedocs.io/en/latest/Python_User_Interface/#field-computations), [scattering cross section](https://meep.readthedocs.io/en/latest/Python_Tutorials/Basics/#mie-scattering-of-a-lossless-dielectric-sphere), [Maxwell stress tensor](https://meep.readthedocs.io/en/latest/Python_Tutorials/Optical_Forces/), [absorbed power density](https://meep.readthedocs.io/en/latest/Python_Tutorials/Basics/#absorbed-power-density-map-of-a-lossy-cylinder), [arbitrary functions](https://meep.readthedocs.io/en/latest/Field_Functions/); completely programmable. - [Adjoint solver](https://meep.readthedocs.io/en/latest/Python_Tutorials/Adjoint_Solver/) for **inverse design** and **topology optimization**. - [Visualization routines](https://meep.readthedocs.io/en/latest/Python_User_Interface/#data-visualization) for the simulation domain involving geometries, fields, boundary layers, sources, and monitors. diff --git a/configure.ac b/configure.ac index 6822c6115..551858a34 100644 --- a/configure.ac +++ b/configure.ac @@ -482,22 +482,6 @@ AM_CONDITIONAL(WITH_LIBCTLGEOM, test x"$have_libctlgeom" = "xyes") AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [ctl_printf_callback = 0;])], AC_DEFINE([HAVE_CTL_PRINTF_CALLBACK], [1], [If we have the ctl_printf_callback variable])) -############################################################################## -# check for libGDSII -AC_CHECK_HEADER(libGDSII.h, [have_gdsii=maybe], [have_gdsii=no]) -if test "x$have_gdsii" = xmaybe; then - AC_CHECK_LIB(GDSII, libGDSIIExists) - if test "x$ac_cv_lib_GDSII_libGDSIIExists" = xyes; then - AC_MSG_CHECKING([for libGDSII::GetLayers]) - have_gdsii_getlayers=no - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [libGDSII::GetLayers("foo")])], - [have_gdsii_getlayers=yes - AC_DEFINE([HAVE_GDSII_GETLAYERS], [1], [If we have libGDSII::GetLayers])]) - AC_MSG_RESULT($have_gdsii_getlayers) - fi -fi -AM_CONDITIONAL(WITH_LIBGDSII, test "x$ac_cv_lib_GDSII_libGDSIIExists" = "xyes") - ############################################################################## # The following function is used only for debugging. Note that # we must test for it *after* setting the compiler flags (which diff --git a/contrib/build-meep.sh b/contrib/build-meep.sh index 65829a0ec..22d3e648e 100755 --- a/contrib/build-meep.sh +++ b/contrib/build-meep.sh @@ -250,12 +250,6 @@ cd mpb/ autogensh CC=mpicc --with-hermitian-eps make -j && $SUDO make install -cd $SRCDIR -gitclone https://github.com/HomerReid/libGDSII.git -cd libGDSII/ -autogensh -make -j && $SUDO make install - cd $SRCDIR gitclone https://github.com/NanoComp/meep.git cd meep/ diff --git a/doc/docs/Acknowledgements.md b/doc/docs/Acknowledgements.md index 5cb813046..f2d9161af 100644 --- a/doc/docs/Acknowledgements.md +++ b/doc/docs/Acknowledgements.md @@ -5,7 +5,7 @@ Authors ------- -Meep originated as part of graduate research at [MIT](https://en.wikipedia.org/wiki/Massachusetts_Institute_of_Technology) in the mid 2000s with initial contributions by [Steven G. Johnson](http://math.mit.edu/~stevenj/), [Ardavan Oskooi](http://ab-initio.mit.edu/~oskooi/), [David Roundy](http://physics.oregonstate.edu/~roundyd/), [Mihai Ibanescu](https://www.linkedin.com/in/mihai-ibanescu-2b147825/), and [Peter Bermel](http://web.ics.purdue.edu/~pbermel/). The project has been under continuous development for nearly 20 years. Currently, the Meep project is maintained by an active developer community on [GitHub](https://github.com/NanoComp/meep). [Christopher Hogan](https://github.com/ChristopherHogan) and [M.T. Homer Reid](http://homerreid.dyndns.org/) lead the development of the [Python interface](Python_User_Interface.md), [mode-decomposition feature](Python_Tutorials/Mode_Decomposition.md), and [GDSII import routines](Python_Tutorials/GDSII_Import.md). M.T. Homer Reid and [Alec Hammond](https://github.com/smartalecH/) developed the [adjoint solver](Python_Tutorials/Adjoint_Solver.md). [Alex Cerjan](http://www.alexcerjan.com/) assisted with adding support for saturable absorption via [multilevel atomic gain media](Materials.md#saturable-gain-and-absorption). Alec Hammond developed the [visualization module](Python_User_Interface.md#data-visualization). [Yidong Chong](http://www1.spms.ntu.edu.sg/~ydchong/bio.html) and Alex Cerjan added support for [gyrotropic media](Materials.md#gyrotropic-media). [Andreas Hoenselaar](https://github.com/ahoenselaar) contributed to several performance enhancements. [Krishna Gadepalli](https://github.com/kkg4theweb) added support for checkpointing the simulation state. +Meep originated as part of graduate research at [MIT](https://en.wikipedia.org/wiki/Massachusetts_Institute_of_Technology) in the mid 2000s with initial contributions by [Steven G. Johnson](http://math.mit.edu/~stevenj/), [Ardavan Oskooi](http://ab-initio.mit.edu/~oskooi/), [David Roundy](http://physics.oregonstate.edu/~roundyd/), [Mihai Ibanescu](https://www.linkedin.com/in/mihai-ibanescu-2b147825/), and [Peter Bermel](http://web.ics.purdue.edu/~pbermel/). The project has been under continuous development for nearly 20 years. Currently, the Meep project is maintained by an active developer community on [GitHub](https://github.com/NanoComp/meep). [Christopher Hogan](https://github.com/ChristopherHogan) and [M.T. Homer Reid](http://homerreid.dyndns.org/) lead the development of the [Python interface](Python_User_Interface.md) and [mode-decomposition feature](Python_Tutorials/Mode_Decomposition.md). M.T. Homer Reid and [Alec Hammond](https://github.com/smartalecH/) developed the [adjoint solver](Python_Tutorials/Adjoint_Solver.md). [Alex Cerjan](http://www.alexcerjan.com/) assisted with adding support for saturable absorption via [multilevel atomic gain media](Materials.md#saturable-gain-and-absorption). Alec Hammond developed the [visualization module](Python_User_Interface.md#data-visualization). [Yidong Chong](http://www1.spms.ntu.edu.sg/~ydchong/bio.html) and Alex Cerjan added support for [gyrotropic media](Materials.md#gyrotropic-media). [Andreas Hoenselaar](https://github.com/ahoenselaar) contributed to several performance enhancements. [Krishna Gadepalli](https://github.com/kkg4theweb) added support for checkpointing the simulation state. Referencing ----------- diff --git a/doc/docs/Build_From_Source.md b/doc/docs/Build_From_Source.md index 16a0694cb..5336086c9 100644 --- a/doc/docs/Build_From_Source.md +++ b/doc/docs/Build_From_Source.md @@ -158,10 +158,6 @@ HDF5 supports parallel I/O under MPI which can be enabled by configuring it with **Note:** If you have a version of HDF5 compiled with MPI parallel I/O support, then you need to use the MPI compilers to link to it, even when you are compiling the serial version of Meep. Just use `./configure CC=mpicc CXX=mpic++` or whatever your MPI compilers are when configuring. -### libGDSII - -[libGDSII](https://github.com/HomerReid/libGDSII) is a library for reading [GDSII](https://en.wikipedia.org/wiki/GDSII) binary data files. GDSII is a widely-used format for 2d/planar geometries supported by [electronic design automation](https://en.wikipedia.org/wiki/Electronic_design_automation) (EDA) circuit-layout editors (e.g., Cadence Virtuoso Layout, Silvaco Expert, KLayout, etc.) and semiconductor foundries. - ### Guile Guile is required in order to use the Scheme interface. If you don't install it, you can only use the C++ and/or Python interfaces. @@ -353,12 +349,6 @@ cd mpb/ sh autogen.sh --enable-shared CC=mpicc LDFLAGS="${MY_LDFLAGS}" CPPFLAGS="${MY_CPPFLAGS}" --with-hermitian-eps make && sudo make install -cd ~/install -git clone https://github.com/HomerReid/libGDSII.git -cd libGDSII/ -sh autogen.sh -make && sudo make install - # The next line is only required on Ubuntu 16.04 sudo pip3 install --upgrade pip @@ -517,12 +507,6 @@ sh autogen.sh --enable-shared CC=/usr/local/bin/mpicc LDFLAGS="${MY_LDFLAGS}" CP make -j sudo make -j install -cd ~/install -git clone https://github.com/HomerReid/libGDSII.git -cd libGDSII/ -sh autogen.sh -sudo make -j install - cd ~/install wget https://bitbucket.org/mpi4py/mpi4py/downloads/mpi4py-3.0.0.tar.gz tar xvf mpi4py-3.0.0.tar.gz diff --git a/doc/docs/FAQ.md b/doc/docs/FAQ.md index a70b3b90d..55cc6390c 100644 --- a/doc/docs/FAQ.md +++ b/doc/docs/FAQ.md @@ -213,7 +213,7 @@ The "steady-state" response is defined as the exp(-iωt) response field (ω=2πf ### How do I compute S-parameters? -Meep contains a [mode-decomposition feature](Mode_Decomposition.md) which can be used to compute complex-valued [S-parameters](https://en.wikipedia.org/wiki/Scattering_parameters). An example is provided for a [two-port network](https://en.wikipedia.org/wiki/Two-port_network#Scattering_parameters_(S-parameters)) based on a silicon directional coupler in [Tutorial/GDSII Import](Python_Tutorials/GDSII_Import.md). Additional examples are available for a [waveguide mode converter](Python_Tutorials/Mode_Decomposition.md#reflectance-of-a-waveguide-taper) and [subwavelength grating](Python_Tutorials/Mode_Decomposition.md#phase-map-of-a-subwavelength-binary-grating). +Meep contains a [mode-decomposition feature](Mode_Decomposition.md) which can be used to compute complex-valued [S-parameters](https://en.wikipedia.org/wiki/Scattering_parameters). An example is provided for a [two-port network](https://en.wikipedia.org/wiki/Two-port_network#Scattering_parameters_(S-parameters)) based on a silicon directional coupler in [Tutorial/GDS Import](Python_Tutorials/GDS_Import.md). Additional examples are available for a [waveguide mode converter](Python_Tutorials/Mode_Decomposition.md#reflectance-of-a-waveguide-taper) and [subwavelength grating](Python_Tutorials/Mode_Decomposition.md#phase-map-of-a-subwavelength-binary-grating). ### Harminv is unable to find the resonant modes of my structure @@ -336,11 +336,11 @@ Usage: Structures ### What are the different ways to define a structure? -There are six ways to define a structure: (1) the [`GeometricObject`](Python_User_Interface.md#geometricobject) (Python) or [`geometric-object`](Scheme_User_Interface.md#geometric-object) (Scheme) class used to specify a collection of predefined shapes including `Prism`, `Sphere`, `Cylinder`, `Cone`, `Block`, and `Ellipsoid`, (2) [`material_function`](Python_User_Interface.md#medium) (Python) or [`material-function`](Scheme_User_Interface.md#material-function) (Scheme) used to define an arbitrary function: for a given position in the cell, return the $\varepsilon$/$\mu$ at that point, (3) import the scalar, real-valued, frequency-independent permittivity from an HDF5 file (which can be created using e.g., [h5py](http://docs.h5py.org/en/stable/)) via the `epsilon_input_file` (Python) or `epsilon-input-file` (Scheme) input parameter, (4) import planar geometries from a [GDSII file](Python_User_Interface.md#gdsii-support), (5) load the raw $\varepsilon$/$\mu$ saved from a previous simulation using [`load_structure`](Python_User_Interface.md#load-and-dump-structure) (Python) or [`meep-structure-load`](Scheme_User_Interface.md#load-and-dump-structure) (Scheme), or (6) a [`MaterialGrid`](Python_User_Interface.md#materialgrid) used to specify a pixel grid. Combinations of (1), (2), (4), and (6) are allowed but not (3) or (5). +There are six ways to define a structure: (1) the [`GeometricObject`](Python_User_Interface.md#geometricobject) (Python) or [`geometric-object`](Scheme_User_Interface.md#geometric-object) (Scheme) class used to specify a collection of predefined shapes including `Prism`, `Sphere`, `Cylinder`, `Cone`, `Block`, and `Ellipsoid`, (2) [`material_function`](Python_User_Interface.md#medium) (Python) or [`material-function`](Scheme_User_Interface.md#material-function) (Scheme) used to define an arbitrary function: for a given position in the cell, return the $\varepsilon$/$\mu$ at that point, (3) import the scalar, real-valued, frequency-independent permittivity from an HDF5 file (which can be created using e.g., [h5py](http://docs.h5py.org/en/stable/)) via the `epsilon_input_file` (Python) or `epsilon-input-file` (Scheme) input parameter, (4) import planar geometries from a [GDS file](Python_Tutorials/GDS_Import.md), (5) load the raw $\varepsilon$/$\mu$ saved from a previous simulation using [`load_structure`](Python_User_Interface.md#load-and-dump-structure) (Python) or [`meep-structure-load`](Scheme_User_Interface.md#load-and-dump-structure) (Scheme), or (6) a [`MaterialGrid`](Python_User_Interface.md#materialgrid) used to specify a pixel grid. Combinations of (1), (2), (4), and (6) are allowed but not (3) or (5). -### Does Meep support importing GDSII files? +### Does Meep support importing GDS files? -Yes. The [`get_GDSII_prisms`](Python_User_Interface.md#gdsii-support) routine is used to import [GDSII](https://en.wikipedia.org/wiki/GDSII) files. See [Tutorial/GDSII Import](Python_Tutorials/GDSII_Import.md) for examples. This feature facilitates the simulation of 2d/planar structures which are fabricated using semiconductor foundries. Also, it enables Meep's plug-and-play capability with [electronic design automation](https://en.wikipedia.org/wiki/Electronic_design_automation) (EDA) circuit-layout editors (e.g., Cadence Virtuoso Layout, Silvaco Expert, KLayout, etc.). EDA is used for the synthesis and verification of large and complex integrated circuits. A useful tool for creating GDS files of simple geometries (e.g., curved waveguides, ring resonators, directional couplers, etc.) is [gdspy](https://gdspy.readthedocs.io/en/stable/). +Yes. [GDS](https://en.wikipedia.org/wiki/GDSII) files can be imported using the [gdstk](https://github.com/heitzmann/gdstk) Python package to read the layout polygons, which are then converted into Meep [`Prism`](Python_User_Interface.md#prism) objects (and [`Volume`](Python_User_Interface.md#volume)s for source/flux regions). See [Tutorial/GDS Import](Python_Tutorials/GDS_Import.md) for examples. This feature facilitates the simulation of 2d/planar structures which are fabricated using semiconductor foundries. Also, it enables Meep's plug-and-play capability with [electronic design automation](https://en.wikipedia.org/wiki/Electronic_design_automation) (EDA) circuit-layout editors (e.g., Cadence Virtuoso Layout, Silvaco Expert, KLayout, etc.). EDA is used for the synthesis and verification of large and complex integrated circuits. `gdstk` can also be used to create GDS files of simple geometries (e.g., curved waveguides, ring resonators, directional couplers, etc.) ### Can Meep simulate time-varying structures? diff --git a/doc/docs/Installation.md b/doc/docs/Installation.md index 83d407ac8..d4d2e2888 100644 --- a/doc/docs/Installation.md +++ b/doc/docs/Installation.md @@ -9,7 +9,7 @@ Building from Source Building Meep directly from the source code can be challenging for users unfamiliar with building Unix software. This is mainly because of the numerous prerequisites that must be installed as well as the need to specify in the build scripts where these packages are to be found. -Meep's build systems uses the standard [GNU Autotools](https://en.wikipedia.org/wiki/GNU_Build_System) `./configure && make && make install` machinery, but requires a number of prerequisites in order to obtain a full-featured Meep installation: [MPB](http://mpb.readthedocs.io/en/latest/), [Libctl](https://github.com/NanoComp/libctl), [Harminv](https://github.com/NanoComp/harminv), [libGDSII](https://github.com/HomerReid/libGDSII), [MPI](https://en.wikipedia.org/wiki/Message_Passing_Interface), [OpenMP](https://en.wikipedia.org/wiki/OpenMP), [HDF5](https://support.hdfgroup.org/HDF5/), [Python](https://www.python.org/), and [Guile](https://www.gnu.org/software/guile/). MPB and Harminv, in turn, require [LAPACK and BLAS](http://www.netlib.org/lapack/lug/node11.html) and [FFTW](http://fftw.org/) to be installed. +Meep's build systems uses the standard [GNU Autotools](https://en.wikipedia.org/wiki/GNU_Build_System) `./configure && make && make install` machinery, but requires a number of prerequisites in order to obtain a full-featured Meep installation: [MPB](http://mpb.readthedocs.io/en/latest/), [Libctl](https://github.com/NanoComp/libctl), [Harminv](https://github.com/NanoComp/harminv), [MPI](https://en.wikipedia.org/wiki/Message_Passing_Interface), [OpenMP](https://en.wikipedia.org/wiki/OpenMP), [HDF5](https://support.hdfgroup.org/HDF5/), [Python](https://www.python.org/), and [Guile](https://www.gnu.org/software/guile/). MPB and Harminv, in turn, require [LAPACK and BLAS](http://www.netlib.org/lapack/lug/node11.html) and [FFTW](http://fftw.org/) to be installed. Gzipped tarballs of stable versions of the source are available on the [releases page](https://github.com/NanoComp/meep/releases), and you can also do a `git clone` of the master branch of the [Meep repository on Github](https://github.com/NanoComp/meep) if you have Autotools installed. For more information, see [Build From Source](Build_From_Source.md). @@ -150,7 +150,7 @@ Now, install the Harminv, libctl, MPB, and Meep packages from source. Download [ ./configure CPPFLAGS="-I$(brew --prefix)/include" LDFLAGS="-L$(brew --prefix)/lib" PYTHON=python3 && make && sudo make install ``` -Use the same commands for [libctl](https://libctl.readthedocs.io), [MPB](https://mpb.readthedocs.io), (optionally) [h5utils](https://github.com/NanoComp/h5utils), (optionally) [libGDSII](https://github.com/HomerReid/libGDSII), and Meep. For more detailed information, see [Build From Source](Build_From_Source.md). Note that if you are installing from a `git clone` rather than from a release `.tar.gz` file, you will need to first run `sh autogen.sh`, and you should add `--enable-maintainer-mode` to the `configure` arguments. +Use the same commands for [libctl](https://libctl.readthedocs.io), [MPB](https://mpb.readthedocs.io), (optionally) [h5utils](https://github.com/NanoComp/h5utils), and Meep. For more detailed information, see [Build From Source](Build_From_Source.md). Note that if you are installing from a `git clone` rather than from a release `.tar.gz` file, you will need to first run `sh autogen.sh`, and you should add `--enable-maintainer-mode` to the `configure` arguments. You are done, and can now run Meep (Scheme interface) just by typing `meep`. You can run `make check` in the meep directory if you want to perform a self-test. diff --git a/doc/docs/Python_Tutorials/Eigenmode_Source.md b/doc/docs/Python_Tutorials/Eigenmode_Source.md index 03ba7fa32..bbc3d21db 100644 --- a/doc/docs/Python_Tutorials/Eigenmode_Source.md +++ b/doc/docs/Python_Tutorials/Eigenmode_Source.md @@ -95,7 +95,7 @@ Note that in `EigenModeSource` as well as `get_eigenmode_coefficients`, the `dir ### What Happens When the Source Time Profile is a Pulse? -The eigenmode source launches a fixed spatial mode profile specified by either its frequency (`eig_match_freq=True`) or wavevector (`eig_match_freq=False`) multiplied by the time profile. When the time profile of the source has a finite bandwidth, e.g. a [Gaussian pulse](../Python_User_Interface.md#gaussiansource) (which is typical for calculations involving [Fourier-transformed fields](../FAQ.md#for-calculations-involving-fourier-transformed-fields-why-should-the-source-be-a-pulse-rather-than-a-continuous-wave) such as [mode coefficients or S-parameters](GDSII_Import.md#s-parameters-of-a-directional-coupler)), then the frequency-dependence (dispersion) of the true modal pattern means that the eigenmode source does not match the desired mode exactly over the whole bandwidth. This is described in Section 4.2.2 of the review article [Electromagnetic Wave Source Conditions](https://arxiv.org/abs/1301.5366). A more accurate mode profile may be obtained by adding multiple narrow-band eigenmode sources at the same position at several frequencies across the bandwidth, but this has the disadvantage that the runtime increases as you add more frequency points due to the narrower source bandwidths. However, a *single* broadband eigenmode source is often sufficient for most practical applications (excepting cases with extreme modal dispersion, e.g. near a cutoff frequency). +The eigenmode source launches a fixed spatial mode profile specified by either its frequency (`eig_match_freq=True`) or wavevector (`eig_match_freq=False`) multiplied by the time profile. When the time profile of the source has a finite bandwidth, e.g. a [Gaussian pulse](../Python_User_Interface.md#gaussiansource) (which is typical for calculations involving [Fourier-transformed fields](../FAQ.md#for-calculations-involving-fourier-transformed-fields-why-should-the-source-be-a-pulse-rather-than-a-continuous-wave) such as [mode coefficients or S-parameters](GDS_Import.md#s-parameters-of-a-directional-coupler)), then the frequency-dependence (dispersion) of the true modal pattern means that the eigenmode source does not match the desired mode exactly over the whole bandwidth. This is described in Section 4.2.2 of the review article [Electromagnetic Wave Source Conditions](https://arxiv.org/abs/1301.5366). A more accurate mode profile may be obtained by adding multiple narrow-band eigenmode sources at the same position at several frequencies across the bandwidth, but this has the disadvantage that the runtime increases as you add more frequency points due to the narrower source bandwidths. However, a *single* broadband eigenmode source is often sufficient for most practical applications (excepting cases with extreme modal dispersion, e.g. near a cutoff frequency). This can be demonstrated by computing the error in a broadband eigenmode source via the backward-propagating and scattered power (i.e., any fields which are not forward-propagating waveguide modes) for the single and multi mode ridge waveguide. diff --git a/doc/docs/Python_Tutorials/GDSII_Import.md b/doc/docs/Python_Tutorials/GDSII_Import.md deleted file mode 100644 index 16843f553..000000000 --- a/doc/docs/Python_Tutorials/GDSII_Import.md +++ /dev/null @@ -1,377 +0,0 @@ ---- -# GDSII Import ---- - -This tutorial demonstrates how to set up a simulation based on importing a [GDSII](https://en.wikipedia.org/wiki/GDSII) file. There are two examples: (1) computing the [S-parameters](https://en.wikipedia.org/wiki/Scattering_parameters) of a [four-port network](https://en.wikipedia.org/wiki/Two-port_network#Scattering_parameters_(S-parameters)) using a silicon directional coupler and (2) finding the modes of a ring resonator. These two component devices are used in [photonic integrated circuits](https://en.wikipedia.org/wiki/Photonic_integrated_circuit) to split/combine and filter an input signal. For more information on directional couplers and ring resonators, see Section 4.1 of [Silicon Photonics Design](https://www.amazon.com/Silicon-Photonics-Design-Devices-Systems/dp/1107085454) by Chrostowski and Hochberg. - -[TOC] - -S-Parameters of a Directional Coupler -------------------------------------- - -The directional coupler as well as the source and mode monitor geometries are described by the GDSII file [`examples/coupler.gds`](https://github.com/NanoComp/meep/blob/master/python/examples/coupler.gds). A snapshot of this file viewed using [KLayout](https://www.klayout.de/) is shown below. The figure labels have been added in post processing. The design consists of two identical [strip waveguides](http://www.simpetus.com/projects.html#mpb_waveguide) which are positioned close together via an adiabatic taper such that their modes couple evanescently. There is a source (labelled "Source") and four mode monitors (labelled "Port 1", "Port 2", etc.). The input pulse from Port 1 is split in two and exits through Ports 3 and 4. The design objective is to find the separation distance which maximizes the outgoing power in Port 4 at a wavelength of 1.55 μm. More generally, though not included in this example, it is possible to have two additional degrees of freedom: (1) the length of the straight waveguide section where the two waveguides are coupled and (2) the length of the tapered section (the taper profile is described by a hyperbolic tangent (tanh) function). - - -![](../images/klayout_schematic.png#center) - - - -The GDSII file is adapted from the [SiEPIC EBeam PDK](https://github.com/lukasc-ubc/SiEPIC_EBeam_PDK) with four major modifications: - -+ the computational cell is centered at the origin of the $xy$ plane and defined on layer 0 - -+ the source and four mode monitors are defined on layers 1-5 - -+ the lower and upper branches of the coupler are defined on layers 31 and 32 - -+ the straight waveguide sections are perfectly linear - -Note that rather than being specified as part of the GDSII file, the volume regions of the source and flux monitors could have been specified in the simulation script. - -The simulation script is in [examples/coupler.py](https://github.com/NanoComp/meep/blob/master/python/examples/coupler.py). The notebook is [examples/coupler.ipynb](https://nbviewer.jupyter.org/github/NanoComp/meep/blob/master/python/examples/coupler.ipynb). - -```python -import meep as mp -import argparse - -gdsII_file = 'coupler.gds' -CELL_LAYER = 0 -PORT1_LAYER = 1 -PORT2_LAYER = 2 -PORT3_LAYER = 3 -PORT4_LAYER = 4 -SOURCE_LAYER = 5 -UPPER_BRANCH_LAYER = 31 -LOWER_BRANCH_LAYER = 32 -default_d = 0.3 - -t_oxide = 1.0 -t_Si = 0.22 -t_air = 0.78 - -dpml = 1 -cell_thickness = dpml+t_oxide+t_Si+t_air+dpml - -oxide = mp.Medium(epsilon=2.25) -silicon = mp.Medium(epsilon=12) - -fcen = 1/1.55 -df = 0.2*fcen - -def main(args): - cell_zmax = 0.5*cell_thickness if args.three_d else 0 - cell_zmin = -0.5*cell_thickness if args.three_d else 0 - si_zmax = 0.5*t_Si if args.three_d else 10 - si_zmin = -0.5*t_Si if args.three_d else -10 - - # read cell size, volumes for source region and flux monitors, - # and coupler geometry from GDSII file - upper_branch = mp.get_GDSII_prisms(silicon, gdsII_file, UPPER_BRANCH_LAYER, si_zmin, si_zmax) - lower_branch = mp.get_GDSII_prisms(silicon, gdsII_file, LOWER_BRANCH_LAYER, si_zmin, si_zmax) - - cell = mp.GDSII_vol(gdsII_file, CELL_LAYER, cell_zmin, cell_zmax) - p1 = mp.GDSII_vol(gdsII_file, PORT1_LAYER, si_zmin, si_zmax) - p2 = mp.GDSII_vol(gdsII_file, PORT2_LAYER, si_zmin, si_zmax) - p3 = mp.GDSII_vol(gdsII_file, PORT3_LAYER, si_zmin, si_zmax) - p4 = mp.GDSII_vol(gdsII_file, PORT4_LAYER, si_zmin, si_zmax) - src_vol = mp.GDSII_vol(gdsII_file, SOURCE_LAYER, si_zmin, si_zmax) - - # displace upper and lower branches of coupler (as well as source and flux regions) - if args.d != default_d: - delta_y = 0.5*(args.d-default_d) - delta = mp.Vector3(y=delta_y) - p1.center += delta - p2.center -= delta - p3.center += delta - p4.center -= delta - src_vol.center += delta - cell.size += 2*delta - for np in range(len(lower_branch)): - lower_branch[np].center -= delta - for nv in range(len(lower_branch[np].vertices)): - lower_branch[np].vertices[nv] -= delta - for np in range(len(upper_branch)): - upper_branch[np].center += delta - for nv in range(len(upper_branch[np].vertices)): - upper_branch[np].vertices[nv] += delta - - geometry = upper_branch+lower_branch - - if args.three_d: - oxide_center = mp.Vector3(z=-0.5*t_oxide) - oxide_size = mp.Vector3(cell.size.x,cell.size.y,t_oxide) - oxide_layer = [mp.Block(material=oxide, center=oxide_center, size=oxide_size)] - geometry = geometry+oxide_layer - - sources = [mp.EigenModeSource(src=mp.GaussianSource(fcen,fwidth=df), - volume=src_vol, - eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y+mp.ODD_Z)] - - sim = mp.Simulation(resolution=args.res, - cell_size=cell.size, - boundary_layers=[mp.PML(dpml)], - sources=sources, - geometry=geometry) - - mode1 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p1)) - mode2 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p2)) - mode3 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p3)) - mode4 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p4)) - - sim.run(until_after_sources=100) - - # S parameters - p1_coeff = sim.get_eigenmode_coefficients(mode1, [1], eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y+mp.ODD_Z).alpha[0,0,0] - p2_coeff = sim.get_eigenmode_coefficients(mode2, [1], eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y+mp.ODD_Z).alpha[0,0,1] - p3_coeff = sim.get_eigenmode_coefficients(mode3, [1], eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y+mp.ODD_Z).alpha[0,0,0] - p4_coeff = sim.get_eigenmode_coefficients(mode4, [1], eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y+mp.ODD_Z).alpha[0,0,0] - - # transmittance - p2_trans = abs(p2_coeff)**2/abs(p1_coeff)**2 - p3_trans = abs(p3_coeff)**2/abs(p1_coeff)**2 - p4_trans = abs(p4_coeff)**2/abs(p1_coeff)**2 - - print("trans:, {:.2f}, {:.6f}, {:.6f}, {:.6f}".format(args.d,p2_trans,p3_trans,p4_trans)) - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('-res', type=int, default=50, help='resolution (default: 50 pixels/um)') - parser.add_argument('-d', type=float, default=0.1, help='branch separation (default: 0.1 um)') - parser.add_argument('--three_d', action='store_true', default=False, help='3d calculation? (default: False)') - args = parser.parse_args() - main(args) -``` - -For a given waveguide separation distance ($d$), the simulation computes the transmittance of Ports 2, 3, and 4. The transmittance is the square of the [S-parameter](https://en.wikipedia.org/wiki/Scattering_parameters) which itself is equivalent to the [mode coefficient](Mode_Decomposition.md). There is an additional mode monitor at Port 1 to compute the input power from the adjacent eigenmode source; this is used for normalization when computing the transmittance. The eight layers of the GDSII file are each converted to a `Simulation` object: the upper and lower branches of the coupler are defined as a collection of [`Prism`](../Python_User_Interface.md#prism)s, the rectilinear regions of the source and flux monitor as a [`Volume`](../Python_User_Interface.md#volume) and [`FluxRegion`](../Python_User_Interface.md#fluxregion). The size of the cell in the $y$ direction is dependent on $d$. The default dimensionality is 2d. (Note that for a 2d cell the `Prism` objects returned by `get_GDSII_prisms` must have a finite height. The finite height of `Volume` objects returned by `GDSII_vol` are ignored in 2d.) An optional input parameter (`three_d`) converts the geometry to 3d by extruding the coupler geometry in the $z$ direction and adding an oxide layer beneath similar to a [silicon on insulator](https://en.wikipedia.org/wiki/Silicon_on_insulator) (SOI) substrate. A schematic of the coupler design in 3d generated using MayaVi is shown below. - - -![](../images/coupler3D.png#center) - - - -The coupler properties are computed for a range of separation distances from 0.02 to 0.30 μm with increments of 0.02 μm from the shell command line: - -``` -for d in `seq 0.02 0.02 0.30`; do - mpirun -np 2 python coupler.py -d ${d} |tee -a directional_coupler.out; -done - -grep trans: directional_coupler.out |cut -d , -f2- > directional_coupler.dat; -``` - -The transmittance results converted into [insertion loss](https://en.wikipedia.org/wiki/Insertion_loss) for Ports 3 and 4 are shown in the figure below. (There is essentially no flux into Port 2 and thus $|S_{21}|^2$ is not shown in the figure.) When the two waveguide branches are sufficiently separated ($d$ > 0.2 μm), practically all of the input power remains in the top branch and is transferred to Port 3. A small amount of the input power is lost due to scattering into radiative modes within the light cone in the tapered sections where the translational symmetry of the waveguide is broken. This is why the power in Port 3 never reaches exactly 100%. For separation distances of less than approximately 0.2 μm, evanescent coupling of the modes from the top to the lower branch begins to transfer some of the input power to Port 4. For $d$ of 0.13 μm, the input signal is split evenly into Ports 3 and 4. For $d$ of 0.06 μm, the input power is transferred completely to Port 4. Finally, for $d$ of less than 0.06 μm, the evanescent coupling becomes rapidly ineffective and the signal again remains mostly in Port 3. - - -![](../images/directional_coupler_flux.png#center) - - - -These quantitative results can also be verified qualitatively using the field profiles shown below for $d$ of 0.06, 0.13, and 0.30 μm. To generate these images, the pulse source is replaced with a [continuous wave](../Python_User_Interface.md#continuoussource) (CW) and the fields are time stepped for a sufficiently long run time until they have reached steady state. The [array slicing](../Python_User_Interface.md#array-slices) routines `get_epsilon` and `get_efield_z` are then used to obtain the dielectric and field data over the entire cell. - -```py -sources = [mp.EigenModeSource(src=mp.ContinuousSource(fcen,fwidth=df), - volume=src_vol, - eig_parity=mp.EVEN_Y+mp.ODD_Z)] - -sim = mp.Simulation(resolution=res, - cell_size=cell.size, - boundary_layers=[mp.PML(dpml)], - sources=sources, - geometry=geometry) - -sim.run(until=400) # arbitrary long run time to ensure that fields have reached steady state - -eps_data = sim.get_epsilon() -ez_data = np.real(sim.get_efield_z()) - -import matplotlib.pyplot as plt - -plt.figure() -plt.plot2D(fields=mp.Ez, - plot_sources_flag=False, - plot_monitors_flag=False, - plot_boundaries_flag=False) -plt.axis('off') -plt.show() -``` - -![](../images/directional_coupler_field_profiles.png#center) - - -The field profiles confirm that for $d$ of 0.06 μm (Figure 1), the input signal in Port 1 of the top branch is almost completely transferred to Port 4 of the bottom branch. For $d$ of 0.13 μm (Figure 2), the input signal is split evenly between the two branches. Finally, for $d$ of 0.30 μm (Figure 3), there is no longer any evanescent coupling and the signal remains completely in the top branch. The waveguide regions with no fields in Ports 3 and 4 are PML. - -### When computing the reflection coefficient |S11|2, is it necessary to perform a separate normalization run to obtain the incident fields? - -No (generally). In the single-run calculation of the reflection coefficent $|S_{11}|^2$ which is based on the back-scattered fields in Port 1 (due to the finite taper/bend length which breaks translational symmetry) given the forward-propagating fields of an eigenmode source also in Port 1, slight discretization errors in the eigenmode-coefficient extraction (as described in paragraph 3 of Section 4.2.2 of this [book chapter](https://arxiv.org/abs/1301.5366)) will result in a "noise floor" below which the reflection cannot be measured in this way. This "noise floor" only applies at a fixed resolution — as the resolution is increased, the discretization error in the mode-coefficient calculation goes away, and $|S_{11}|^2$ should approach the "true" reflection from the taper/bend. This is demonstrated in the figure below which shows a plot of the $S_{11}$ and $S_{21}$ reflectance versus resolution. (In these types of calculations, it is important that the source and mode monitor in the same port be separated by *at least several pixels* in order to avoid any overlap due to the grid discretization.) - - -![](../images/coupler_refl_S11_S12.png#center) - - - -In the limit of infinite resolution, the discretization error is removed and the reflectance for $S_{11}$ and $S_{21}$ converge to their "true" values of ~10-6 and ~10-8, respectively. (Note that the back-scattered fields in Port 2 are two orders of magnitude smaller than those in Port 1 because the input fields in the upper branch of the directional coupler must cross into the lower branch to reach Port 2.) In this example, $|S_{21}|^2$ requires a resolution of at least ~150 to minimize discretization errors. The discretization errors due to the eigenmode-coefficient extraction can be greatly reduced by using a separate normalization run to compute the incident fields for just a straight waveguide (i.e., no taper/bend) which are then subtracted from the Fourier-transformed fields in Port 1 and 2 of the directional coupler. This procedure is similar to those involving [flux calculations](Basics.md#transmittance-spectrum-of-a-waveguide-bend). (Alternatively, for single-mode waveguides, the mode-coefficient calculation can be replaced entirely with just computing the Poynting flux in the ports. This approach is more accurate at lower resolutions.) For practical applications, however, reflectance values less than 40 dB (e.g., for telecom multi-path interference tolerances) are often considered negligible. On the other hand, there may be theoretical investigations where trying to resolve such small reflections could be important. (As reflections approach 10-15, the limits of floating-point precision will eventually limit accuracy even for the normalization approach.) - -### Importing a GDS Layer using a Tuple - -In the directional coupler example above, individual layers of the GDS file were imported by specifying a single number in the `get_GDSII_prisms` routine (i.e., 1, 2, 31, 32, etc.). However, there are certain GDS files in which the layers are referenced using a 2-tuple (e.g., (37,4)). Since `get_GDSII_prisms` which is based on [`libGDSII`](https://github.com/HomerReid/libGDSII) does not support this feature, you will need to use [`gdspy`](https://gdspy.readthedocs.io/) as demonstrated in the following example. - -```py -import meep as mp -import gdspy - -# load the GDS file -gds = gdspy.GdsLibrary(infile=gds_file) - -# define cell size and center -box = gds.top_level()[0].get_bounding_box() -cell_center = 0.5*mp.Vector3(box[1][0] + box[0][0],box[1][1] + box[0][1]) - -# define the geometry using all the polygons from layer (37,4) -polygons = gds.top_level()[0].get_polygons(True)[37,4] - -design_geometry = [] -for pg in polygons: - vertices = [] - for vt in pg: - # define vertices relative to center of cell - vertices.append(mp.Vector3(vt[0],vt[1])-cell_center) - design_geometry.append(mp.Prism(vertices=vertices, - height=0.5, - axis=mp.Vector3(0,0,+1), - material=mp.Medium(index=3.5))) - design_geometry.append(mp.Prism(vertices=vertices, - height=0.5, - axis=mp.Vector3(0,0,-1), - material=mp.Medium(index=3.5))) -``` - -Note that for each polygon in the GDS layer, there are *two* `Prism` objects: one extending in the $+z$ direction and the other in $-z$ with a combined height of 1.0 μm. - -Modes of a Ring Resonator -------------------------- - -The next example is similar to [Tutorial/Basics/Modes of a Ring Resonator](../Python_Tutorials/Basics.md#modes-of-a-ring-resonator) and consists of two parts: (1) creating the ring resonator geometry using [gdspy](https://gdspy.readthedocs.io/en/stable/) and (2) finding its modes using [Harminv](../Python_User_Interface.md#harminv). The cell, geometry, source, and monitor are defined on separate layers within the same GDSII file. - -The simulation script is in [examples/ring_gds.py](https://github.com/NanoComp/meep/blob/master/python/examples/ring_gds.py). - -```py -import numpy as np -import gdspy -from matplotlib import pyplot as plt -import importlib -import meep as mp - -# core and cladding materials -Si = mp.Medium(index=3.4) -SiO2 = mp.Medium(index=1.4) - -# layer numbers for GDS file -RING_LAYER = 0 -SOURCE0_LAYER = 1 -SOURCE1_LAYER = 2 -MONITOR_LAYER = 3 -SIMULATION_LAYER = 4 - -resolution = 50 # pixels/μm -dpml = 1 # thickness of PML -zmin = 0 # minimum z value of simulation domain (0 for 2D) -zmax = 0 # maximum z value of simulation domain (0 for 2D) - -def create_ring_gds(radius,width): - # Reload the library each time to prevent gds library name clashes - importlib.reload(gdspy) - - ringCell = gdspy.Cell("ring_resonator_r{}_w{}".format(radius,width)) - - # Draw the ring - ringCell.add(gdspy.Round((0,0), - inner_radius=radius-width/2, - radius=radius+width/2, - layer=RING_LAYER)) - - # Draw the first source - ringCell.add(gdspy.Rectangle((radius-width,0), - (radius+width,0), - SOURCE0_LAYER)) - - # Draw the second source - ringCell.add(gdspy.Rectangle((-radius-width,0), - (-radius+width,0), - SOURCE1_LAYER)) - - # Draw the monitor location - ringCell.add(gdspy.Rectangle((radius-width/2,0), - (radius+width/2,0), - MONITOR_LAYER)) - - # Draw the simulation domain - pad = 2 # padding between waveguide and edge of PML - ringCell.add(gdspy.Rectangle((-radius-width/2-pad,-radius-width/2-pad), - (radius+width/2+pad,radius+width/2+pad), - SIMULATION_LAYER)) - - filename = "ring_r{}_w{}.gds".format(radius,width) - gdspy.write_gds(filename, unit=1.0e-6, precision=1.0e-9) - - return filename - -def find_modes(filename,wvl=1.55,bw=0.05): - # Read in the ring structure - geometry = mp.get_GDSII_prisms(Si,filename,RING_LAYER,-100,100) - - cell = mp.GDSII_vol(filename,SIMULATION_LAYER,zmin,zmax) - - src_vol0 = mp.GDSII_vol(filename,SOURCE0_LAYER,zmin,zmax) - src_vol1 = mp.GDSII_vol(filename,SOURCE1_LAYER,zmin,zmax) - - mon_vol = mp.GDSII_vol(filename,MONITOR_LAYER,zmin,zmax) - - fcen = 1/wvl - df = bw*fcen - - src = [mp.Source(mp.GaussianSource(fcen, fwidth=df), - component=mp.Hz, - volume=src_vol0), - mp.Source(mp.GaussianSource(fcen, fwidth=df), - component=mp.Hz, - volume=src_vol1, - amplitude=-1)] - - sim = mp.Simulation(cell_size=cell.size, - geometry=geometry, - sources=src, - resolution=resolution, - boundary_layers=[mp.PML(dpml)], - default_material=SiO2) - - h = mp.Harminv(mp.Hz,mon_vol.center,fcen,df) - - sim.run(mp.after_sources(h), - until_after_sources=100) - - plt.figure() - sim.plot2D(fields=mp.Hz, - eps_parameters={'contour':True}) - plt.savefig('ring_resonator_Hz.png',bbox_inches='tight',dpi=150) - - wvl = np.array([1/m.freq for m in h.modes]) - Q = np.array([m.Q for m in h.modes]) - - sim.reset_meep() - - return wvl, Q - - -if __name__ == '__main__': - filename = create_ring_gds(2.0,0.5) - wvls, Qs = find_modes(filename,1.55,0.05) - for w, Q in zip(wvls,Qs): - print("mode: {}, {}".format(w,Q)) -``` - -Note the absence of `symmetries` even though, in principle, the ring geometry and the two line sources satisfy two mirror symmetry planes through the $x$ (even) and $y$ (odd) axes. This omission is due to the fact that the ring geometry created using gdspy and imported from the GDSII file is actually a [`Prism`](../Python_User_Interface.md#prism) consisting of a discrete number of vertices (rather than two overlapping `Cylinder`s as in [Tutorial/Basics/Modes of a Ring Resonator](../Python_Tutorials/Basics.md#modes-of-a-ring-resonator)). Discretization artifacts of the ring geometry slightly break its mirror symmetry. (Attempting to use `symmetries` in this case yields unpredictable results.) - -For this ring geometry, Harminv finds a mode with wavelength 1.5490604 μm and $Q$ of 124691.308. The $H_z$ field profile is shown below. As expected, due to the large $Q$ the mode is tightly confined to the ring and exhibits little radiative loss. - - -![](../images/ring_resonator_gds_Hz.png#center) diff --git a/doc/docs/Python_Tutorials/GDS_Import.md b/doc/docs/Python_Tutorials/GDS_Import.md new file mode 100644 index 000000000..ed6b0aaf7 --- /dev/null +++ b/doc/docs/Python_Tutorials/GDS_Import.md @@ -0,0 +1,537 @@ +--- +# GDS Import +--- + +This tutorial demonstrates how to set up a simulation based on importing a [GDS](https://en.wikipedia.org/wiki/GDSII) file. There are two examples: (1) computing the [S-parameters](https://en.wikipedia.org/wiki/Scattering_parameters) of a [four-port network](https://en.wikipedia.org/wiki/Two-port_network#Scattering_parameters_(S-parameters)) using a silicon directional coupler and (2) finding the modes of a ring resonator. These two component devices are used in [photonic integrated circuits](https://en.wikipedia.org/wiki/Photonic_integrated_circuit) to split/combine and filter an input signal. For more information on directional couplers and ring resonators, see Section 4.1 of [Silicon Photonics Design](https://www.amazon.com/Silicon-Photonics-Design-Devices-Systems/dp/1107085454) by Chrostowski and Hochberg. + +The GDS layout files are read using the [gdstk](https://github.com/heitzmann/gdstk) Python package, which must be installed separately (e.g., `pip install gdsktk`). `gdstk` is a library for creating and reading GDSII/OASIS files. The polygons it extracts from a given layer are converted into Meep [`Prism`](../Python_User_Interface.md#prism) objects (the device geometry) and [`Volume`](../Python_User_Interface.md#volume) objects (for source and flux/mode-monitor regions). The two examples below define a few small helper functions for this conversion which can be reused in your own scripts: + +```python +import gdstk +import meep as mp + + +def get_gds_cell(fname): + """Returns the (single) top-level cell of the GDS file `fname`.""" + return gdstk.read_gds(fname).top_level()[0] + + +def get_gds_prisms(material, cell, layer, datatype=0, zmin=0.0, zmax=0.0): + """Returns a list of `mp.Prism`s, one for each polygon on (`layer`, `datatype`).""" + prisms = [] + for poly in cell.get_polygons(layer=layer, datatype=datatype): + vertices = [mp.Vector3(x, y, zmin) for x, y in poly.points] + prisms.append( + mp.Prism( + vertices, + height=zmax - zmin, + axis=mp.Vector3(0, 0, 1), + material=material, + ) + ) + return prisms + + +def get_gds_vol(cell, layer, datatype=0, zmin=0.0, zmax=0.0): + """Returns an `mp.Volume` spanning the bounding box of (`layer`, `datatype`).""" + polygons = cell.get_polygons(layer=layer, datatype=datatype) + xs = [x for poly in polygons for x, y in poly.points] + ys = [y for poly in polygons for x, y in poly.points] + xmin, xmax = min(xs), max(xs) + ymin, ymax = min(ys), max(ys) + center = mp.Vector3(0.5 * (xmin + xmax), 0.5 * (ymin + ymax), 0.5 * (zmin + zmax)) + size = mp.Vector3(xmax - xmin, ymax - ymin, zmax - zmin) + dims = 2 if (zmin == 0 and zmax == 0) else 3 + return mp.Volume(center=center, size=size, dims=dims) +``` + + +[TOC] + +S-Parameters of a Directional Coupler +------------------------------------- + +The directional coupler as well as the source and mode monitor geometries are described by the GDS file [`examples/coupler.gds`](https://github.com/NanoComp/meep/blob/master/python/examples/coupler.gds). A snapshot of this file viewed using [KLayout](https://www.klayout.de/) is shown below. The figure labels have been added in post processing. The design consists of two identical [strip waveguides](http://www.simpetus.com/projects.html#mpb_waveguide) which are positioned close together via an adiabatic taper such that their modes couple evanescently. There is a source (labelled "Source") and four mode monitors (labelled "Port 1", "Port 2", etc.). The input pulse from Port 1 is split in two and exits through Ports 3 and 4. The design objective is to find the separation distance which maximizes the outgoing power in Port 4 at a wavelength of 1.55 μm. More generally, though not included in this example, it is possible to have two additional degrees of freedom: (1) the length of the straight waveguide section where the two waveguides are coupled and (2) the length of the tapered section (the taper profile is described by a hyperbolic tangent (tanh) function). + + +![](../images/klayout_schematic.png#center) + + + +The GDS file is adapted from the [SiEPIC EBeam PDK](https://github.com/lukasc-ubc/SiEPIC_EBeam_PDK) with four major modifications: + ++ the computational cell is centered at the origin of the $xy$ plane and defined on layer 0 + ++ the source and four mode monitors are defined on layers 1-5 + ++ the lower and upper branches of the coupler are defined on layers 31 and 32 + ++ the straight waveguide sections are perfectly linear + +Note that rather than being specified as part of the GDS file, the volume regions of the source and flux monitors could have been specified in the simulation script. + +The simulation script is in [examples/coupler.py](https://github.com/NanoComp/meep/blob/master/python/examples/coupler.py). + +```python +import argparse + +import gdstk +import meep as mp + + +gds_file = 'coupler.gds' +CELL_LAYER = 0 +PORT1_LAYER = 1 +PORT2_LAYER = 2 +PORT3_LAYER = 3 +PORT4_LAYER = 4 +SOURCE_LAYER = 5 +UPPER_BRANCH_LAYER = 31 +LOWER_BRANCH_LAYER = 32 +default_d = 0.3 + +t_oxide = 1.0 +t_Si = 0.22 +t_air = 0.78 + +dpml = 1 +cell_thickness = dpml + t_oxide + t_Si + t_air + dpml + +oxide = mp.Medium(epsilon=2.25) +silicon = mp.Medium(epsilon=12) + +fcen = 1 / 1.55 +df = 0.2 * fcen + + +def get_gds_cell(fname): + """Returns the (single) top-level cell of the GDS file `fname`.""" + return gdstk.read_gds(fname).top_level()[0] + + +def get_gds_prisms(material, cell, layer, datatype=0, zmin=0.0, zmax=0.0): + """Returns a list of `mp.Prism`s, one for each polygon on (`layer`, `datatype`).""" + prisms = [] + for poly in cell.get_polygons(layer=layer, datatype=datatype): + vertices = [mp.Vector3(x, y, zmin) for x, y in poly.points] + prisms.append( + mp.Prism( + vertices, + height=zmax - zmin, + axis=mp.Vector3(0, 0, 1), + material=material, + ) + ) + return prisms + + +def get_gds_vol(cell, layer, datatype=0, zmin=0.0, zmax=0.0): + """Returns an `mp.Volume` spanning the bounding box of (`layer`, `datatype`).""" + polygons = cell.get_polygons(layer=layer, datatype=datatype) + xs = [x for poly in polygons for x, y in poly.points] + ys = [y for poly in polygons for x, y in poly.points] + xmin, xmax = min(xs), max(xs) + ymin, ymax = min(ys), max(ys) + center = mp.Vector3(0.5 * (xmin + xmax), 0.5 * (ymin + ymax), 0.5 * (zmin + zmax)) + size = mp.Vector3(xmax - xmin, ymax - ymin, zmax - zmin) + dims = 2 if (zmin == 0 and zmax == 0) else 3 + return mp.Volume(center=center, size=size, dims=dims) + + +def main(args): + cell_zmax = 0.5 * cell_thickness if args.three_d else 0 + cell_zmin = -0.5 * cell_thickness if args.three_d else 0 + si_zmax = 0.5 * t_Si if args.three_d else 10 + si_zmin = -0.5 * t_Si if args.three_d else -10 + + # read cell size, volumes for source region and flux monitors, + # and coupler geometry from the GDS file using gdstk + gds_cell = get_gds_cell(gds_file) + + upper_branch = get_gds_prisms(silicon, gds_cell, UPPER_BRANCH_LAYER, zmin=si_zmin, zmax=si_zmax) + lower_branch = get_gds_prisms(silicon, gds_cell, LOWER_BRANCH_LAYER, zmin=si_zmin, zmax=si_zmax) + + cell = get_gds_vol(gds_cell, CELL_LAYER, zmin=cell_zmin, zmax=cell_zmax) + p1 = get_gds_vol(gds_cell, PORT1_LAYER, zmin=si_zmin, zmax=si_zmax) + p2 = get_gds_vol(gds_cell, PORT2_LAYER, zmin=si_zmin, zmax=si_zmax) + p3 = get_gds_vol(gds_cell, PORT3_LAYER, zmin=si_zmin, zmax=si_zmax) + p4 = get_gds_vol(gds_cell, PORT4_LAYER, zmin=si_zmin, zmax=si_zmax) + src_vol = get_gds_vol(gds_cell, SOURCE_LAYER, zmin=si_zmin, zmax=si_zmax) + + # displace upper and lower branches of coupler (as well as source and flux regions) + if args.d != default_d: + delta_y = 0.5*(args.d - default_d) + delta = mp.Vector3(y=delta_y) + p1.center += delta + p2.center -= delta + p3.center += delta + p4.center -= delta + src_vol.center += delta + cell.size += 2*delta + for np in range(len(lower_branch)): + lower_branch[np].center -= delta + for nv in range(len(lower_branch[np].vertices)): + lower_branch[np].vertices[nv] -= delta + for np in range(len(upper_branch)): + upper_branch[np].center += delta + for nv in range(len(upper_branch[np].vertices)): + upper_branch[np].vertices[nv] += delta + + geometry = upper_branch+lower_branch + + if args.three_d: + oxide_center = mp.Vector3(z=-0.5 * t_oxide) + oxide_size = mp.Vector3(cell.size.x, cell.size.y, t_oxide) + oxide_layer = [mp.Block(material=oxide, center=oxide_center, size=oxide_size)] + geometry = geometry + oxide_layer + + sources = [ + mp.EigenModeSource( + src=mp.GaussianSource(fcen,fwidth=df), + volume=src_vol, + eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y+mp.ODD_Z, + ) + ] + + sim = mp.Simulation( + resolution=args.res, + cell_size=cell.size, + boundary_layers=[mp.PML(dpml)], + sources=sources, + geometry=geometry + ) + + mode1 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p1)) + mode2 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p2)) + mode3 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p3)) + mode4 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p4)) + + sim.run(until_after_sources=100) + + # S parameters + p1_coeff = sim.get_eigenmode_coefficients( + mode1, [1], eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y+mp.ODD_Z + ).alpha[0,0,0] + p2_coeff = sim.get_eigenmode_coefficients( + mode2, [1], eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y+mp.ODD_Z + ).alpha[0,0,1] + p3_coeff = sim.get_eigenmode_coefficients( + mode3, [1], eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y+mp.ODD_Z + ).alpha[0,0,0] + p4_coeff = sim.get_eigenmode_coefficients( + mode4, [1], eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y+mp.ODD_Z + ).alpha[0,0,0] + + # transmittance + p2_trans = abs(p2_coeff) ** 2 / abs(p1_coeff) ** 2 + p3_trans = abs(p3_coeff) ** 2 / abs(p1_coeff) ** 2 + p4_trans = abs(p4_coeff) ** 2 / abs(p1_coeff) ** 2 + + print( + f"trans:, {args.d:.2f}, {p2_trans:.6f}, {p3_trans:.6f}, {p4_trans:.6f}" + ) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument( + "-res", type=int, default=50, help="resolution (default: 50 pixels/um)" + ) + parser.add_argument( + "-d", type=float, default=0.1, help="branch separation (default: 0.1 um)" + ) + parser.add_argument( + "--three_d", + action="store_true", + default=False, + help="d calculation? (default: False)" + ) + args = parser.parse_args() + main(args) +``` + +For a given waveguide separation distance ($d$), the simulation computes the transmittance of Ports 2, 3, and 4. The transmittance is the square of the [S-parameter](https://en.wikipedia.org/wiki/Scattering_parameters) which itself is equivalent to the [mode coefficient](Mode_Decomposition.md). There is an additional mode monitor at Port 1 to compute the input power from the adjacent eigenmode source; this is used for normalization when computing the transmittance. The eight layers of the GDS file are each converted to a `Simulation` object: the upper and lower branches of the coupler are defined as a collection of [`Prism`](../Python_User_Interface.md#prism)s, the rectilinear regions of the source and flux monitor as a [`Volume`](../Python_User_Interface.md#volume) and [`FluxRegion`](../Python_User_Interface.md#fluxregion). The size of the cell in the $y$ direction is dependent on $d$. The default dimensionality is 2d. (Note that for a 2d cell the `Prism` objects returned by `get_gds_prisms` must have a finite height. The finite height of `Volume` objects returned by `get_gds_vol` are ignored in 2d.) An optional input parameter (`three_d`) converts the geometry to 3d by extruding the coupler geometry in the $z$ direction and adding an oxide layer beneath similar to a [silicon on insulator](https://en.wikipedia.org/wiki/Silicon_on_insulator) (SOI) substrate. A schematic of the coupler design in 3d generated using MayaVi is shown below. + + +![](../images/coupler3D.png#center) + + + +The coupler properties are computed for a range of separation distances from 0.02 to 0.30 μm with increments of 0.02 μm from the shell command line: + +``` +for d in $(seq 0.02 0.02 0.30); do + mpirun -np 2 python coupler.py -d ${d} |tee -a directional_coupler.out; +done + +grep trans: directional_coupler.out |cut -d , -f2- > directional_coupler.dat; +``` + +The transmittance results converted into [insertion loss](https://en.wikipedia.org/wiki/Insertion_loss) for Ports 3 and 4 are shown in the figure below. (There is essentially no flux into Port 2 and thus $|S_{21}|^2$ is not shown in the figure.) When the two waveguide branches are sufficiently separated ($d$ > 0.2 μm), practically all of the input power remains in the top branch and is transferred to Port 3. A small amount of the input power is lost due to scattering into radiative modes within the light cone in the tapered sections where the translational symmetry of the waveguide is broken. This is why the power in Port 3 never reaches exactly 100%. For separation distances of less than approximately 0.2 μm, evanescent coupling of the modes from the top to the lower branch begins to transfer some of the input power to Port 4. For $d$ of 0.13 μm, the input signal is split evenly into Ports 3 and 4. For $d$ of 0.06 μm, the input power is transferred completely to Port 4. Finally, for $d$ of less than 0.06 μm, the evanescent coupling becomes rapidly ineffective and the signal again remains mostly in Port 3. + + +![](../images/directional_coupler_flux.png#center) + + + +These quantitative results can also be verified qualitatively using the field profiles shown below for $d$ of 0.06, 0.13, and 0.30 μm. To generate these images, the pulse source is replaced with a [continuous wave](../Python_User_Interface.md#continuoussource) (CW) and the fields are time stepped for a sufficiently long run time until they have reached steady state. The [array slicing](../Python_User_Interface.md#array-slices) routines `get_epsilon` and `get_efield_z` are then used to obtain the dielectric and field data over the entire cell. + +```py +sources = [mp.EigenModeSource(src=mp.ContinuousSource(fcen,fwidth=df), + volume=src_vol, + eig_parity=mp.EVEN_Y+mp.ODD_Z)] + +sim = mp.Simulation(resolution=res, + cell_size=cell.size, + boundary_layers=[mp.PML(dpml)], + sources=sources, + geometry=geometry) + +sim.run(until=400) # arbitrary long run time to ensure that fields have reached steady state + +eps_data = sim.get_epsilon() +ez_data = np.real(sim.get_efield_z()) + +import matplotlib.pyplot as plt + +plt.figure() +plt.plot2D(fields=mp.Ez, + plot_sources_flag=False, + plot_monitors_flag=False, + plot_boundaries_flag=False) +plt.axis('off') +plt.show() +``` + +![](../images/directional_coupler_field_profiles.png#center) + + +The field profiles confirm that for $d$ of 0.06 μm (Figure 1), the input signal in Port 1 of the top branch is almost completely transferred to Port 4 of the bottom branch. For $d$ of 0.13 μm (Figure 2), the input signal is split evenly between the two branches. Finally, for $d$ of 0.30 μm (Figure 3), there is no longer any evanescent coupling and the signal remains completely in the top branch. The waveguide regions with no fields in Ports 3 and 4 are PML. + +### When computing the reflection coefficient |S11|2, is it necessary to perform a separate normalization run to obtain the incident fields? + +No (generally). In the single-run calculation of the reflection coefficent $|S_{11}|^2$ which is based on the back-scattered fields in Port 1 (due to the finite taper/bend length which breaks translational symmetry) given the forward-propagating fields of an eigenmode source also in Port 1, slight discretization errors in the eigenmode-coefficient extraction (as described in paragraph 3 of Section 4.2.2 of this [book chapter](https://arxiv.org/abs/1301.5366)) will result in a "noise floor" below which the reflection cannot be measured in this way. This "noise floor" only applies at a fixed resolution — as the resolution is increased, the discretization error in the mode-coefficient calculation goes away, and $|S_{11}|^2$ should approach the "true" reflection from the taper/bend. This is demonstrated in the figure below which shows a plot of the $S_{11}$ and $S_{21}$ reflectance versus resolution. (In these types of calculations, it is important that the source and mode monitor in the same port be separated by *at least several pixels* in order to avoid any overlap due to the grid discretization.) + + +![](../images/coupler_refl_S11_S12.png#center) + + + +In the limit of infinite resolution, the discretization error is removed and the reflectance for $S_{11}$ and $S_{21}$ converge to their "true" values of ~10-6 and ~10-8, respectively. (Note that the back-scattered fields in Port 2 are two orders of magnitude smaller than those in Port 1 because the input fields in the upper branch of the directional coupler must cross into the lower branch to reach Port 2.) In this example, $|S_{21}|^2$ requires a resolution of at least ~150 to minimize discretization errors. The discretization errors due to the eigenmode-coefficient extraction can be greatly reduced by using a separate normalization run to compute the incident fields for just a straight waveguide (i.e., no taper/bend) which are then subtracted from the Fourier-transformed fields in Port 1 and 2 of the directional coupler. This procedure is similar to those involving [flux calculations](Basics.md#transmittance-spectrum-of-a-waveguide-bend). (Alternatively, for single-mode waveguides, the mode-coefficient calculation can be replaced entirely with just computing the Poynting flux in the ports. This approach is more accurate at lower resolutions.) For practical applications, however, reflectance values less than 40 dB (e.g., for telecom multi-path interference tolerances) are often considered negligible. On the other hand, there may be theoretical investigations where trying to resolve such small reflections could be important. (As reflections approach 10-15, the limits of floating-point precision will eventually limit accuracy even for the normalization approach.) + +### Importing a GDS Layer using a Tuple + +In the directional coupler example above, individual layers of the GDS file were referenced by a single layer number (i.e., 1, 2, 31, 32, etc.) with an implicit data type of 0. However, there are certain GDS files in which a layer is referenced using a 2-tuple of a [layer number *and* a data type](https://heitzmann.github.io/gdstk/gettingstarted.html#layer-and-datatype) (e.g., (37,4)). `gdstk` supports this natively: `Cell.get_polygons` accepts both a `layer` and a `datatype` argument. The example below uses the same helper functions defined at the top of this tutorial, passing the data type explicitly. + +```py +import gdstk +import meep as mp + + +# load the top-level cell of the GDS file +gds_cell = gdstk.read_gds(gds_file).top_level()[0] + + +# define cell size and center from the bounding box of the entire layout +(xmin, ymin), (xmax, ymax) = gds_cell.bounding_box() +cell_center = mp.Vector3(0.5 * (xmin + xmax), 0.5 * (ymin + ymax)) + +design_geometry = [] +for poly in gds_cell.get_polygons(layer=37, datatype=4): + # define vertices relative to the center of the cell + vertices = [mp.Vector3(x, y) - cell_center for x, y in poly.points] + design_geometry.append(mp.Prism(vertices=vertices, + height=0.5, + axis=mp.Vector3(0, 0, +1), + material=mp.Medium(index=3.5))) + design_geometry.append(mp.Prism(vertices=vertices, + height=0.5, + axis=mp.Vector3(0, 0, -1), + material=mp.Medium(index=3.5))) +``` + +Note that for each polygon in the GDS layer, there are *two* `Prism` objects: one extending in the $+z$ direction and the other in $-z$ with a combined height of 1.0 μm. + +Modes of a Ring Resonator +------------------------- + +The next example is similar to [Tutorial/Basics/Modes of a Ring Resonator](../Python_Tutorials/Basics.md#modes-of-a-ring-resonator) and consists of two parts: (1) creating the ring resonator geometry using [gdstk](https://github.com/heitzmann/gdstk) and (2) finding its modes using [Harminv](../Python_User_Interface.md#harminv). The cell, geometry, source, and monitor are defined on separate layers within the same GDS file. This example demonstates that `gdstk` can be used to *create* a GDS file and to *read* it back in for the Meep simulation. + +The simulation script is in [examples/ring_gds.py](https://github.com/NanoComp/meep/blob/master/python/examples/ring_gds.py). + +```py +import gdstk +from matplotlib import pyplot as plt +import meep as mp +import numpy as np + +# core and cladding materials +Si = mp.Medium(index=3.4) +SiO2 = mp.Medium(index=1.4) + +# layer numbers for GDS file +RING_LAYER = 0 +SOURCE0_LAYER = 1 +SOURCE1_LAYER = 2 +MONITOR_LAYER = 3 +SIMULATION_LAYER = 4 + +resolution = 50 # pixels/μm +dpml = 1 # thickness of PML +zmin = 0 # minimum z value of simulation domain (0 for 2D) +zmax = 0 # maximum z value of simulation domain (0 for 2D) + + +def get_gds_cell(fname): + """Returns the (single) top-level cell of the GDS file `fname`.""" + return gdstk.read_gds(fname).top_level()[0] + + +def get_gds_prisms(material, cell, layer, datatype=0, zmin=0.0, zmax=0.0): + """Returns a list of `mp.Prism`s, one for each polygon on (`layer`, `datatype`).""" + prisms = [] + for poly in cell.get_polygons(layer=layer, datatype=datatype): + vertices = [mp.Vector3(x, y, zmin) for x, y in poly.points] + prisms.append( + mp.Prism( + vertices, + height=zmax - zmin, + axis=mp.Vector3(0, 0, 1), + material=material, + ) + ) + return prisms + + +def get_gds_vol(cell, layer, datatype=0, zmin=0.0, zmax=0.0): + """Returns an `mp.Volume` spanning the bounding box of (`layer`, `datatype`).""" + polygons = cell.get_polygons(layer=layer, datatype=datatype) + xs = [x for poly in polygons for x, y in poly.points] + ys = [y for poly in polygons for x, y in poly.points] + xmin, xmax = min(xs), max(xs) + ymin, ymax = min(ys), max(ys) + center = mp.Vector3(0.5 * (xmin + xmax), 0.5 * (ymin + ymax), 0.5 * (zmin + zmax)) + size = mp.Vector3(xmax - xmin, ymax - ymin, zmax - zmin) + dims = 2 if (zmin == 0 and zmax == 0) else 3 + return mp.Volume(center=center, size=size, dims=dims) + + +def create_ring_gds(radius, width): + lib = gdstk.Library() + ring_cell = lib.new_cell(f"ring_resonator_r{radius}_w{width}") + + # Draw the ring + ring_cell.add( + gdstk.ellipse( + (0, 0), + radius + width / 2, + inner_radius=radius - width/2, + layer=RING_LAYER, + ) + ) + + # Draw the first source + ring_cell.add( + gdstk.rectangle((radius - width, 0), (radius + width, 0), layer=SOURCE0_LAYER) + ) + + # Draw the second source + ring_cell.add( + gdstk.rectangle((-radius - width, 0), (-radius + width, 0), layer=SOURCE1_LAYER) + ) + + # Draw the monitor location + ring_cell.add( + gdstk.rectangle( + (radius - width / 2, 0), (radius + width / 2, 0), layer=MONITOR_LAYER + ) + ) + + # Draw the simulation domain + pad = 2 # padding between waveguide and edge of PML + ring_cell.add( + gdstk.rectangle( + (-radius - width / 2 - pad, -radius-width/2-pad), + (radius + width / 2 + pad, radius + width / 2 + pad), + layer=SIMULATION_LAYER, + ) + ) + + filename = f"ring_r{radius}_w{width}.gds" + lib.write_gds(filename) + + return filename + + +def find_modes(filename,wvl=1.55,bw=0.05): + # Read in the ring structure using gdstk + gds_cell = get_gds_cell(filename) + + geometry = get_gds_prisms(Si, gds_cell, RING_LAYER, zmin=-100, zmax=100) + + cell = get_gds_vol(gds_cell, SIMULATION_LAYER, zmin=zmin, zmax=zmax) + + src_vol0 = get_gds_vol(gds_cell, SOURCE0_LAYER, zmin=zmin, zmax=zmax) + src_vol1 = get_gds_vol(gds_cell, SOURCE1_LAYER, zmin=zmin, zmax=zmax) + + mon_vol = get_gds_vol(gds_cell, MONITOR_LAYER, zmin=zmin, zmax=zmax) + + fcen = 1 / wvl + df = bw * fcen + + src = [ + mp.Source( + mp.GaussianSource(fcen, fwidth=df), + component=mp.Hz, + volume=src_vol0, + ), + mp.Source( + mp.GaussianSource(fcen, fwidth=df), + component=mp.Hz, + volume=src_vol1, + amplitude=-1, + ) + ] + + sim = mp.Simulation( + cell_size=cell.size, + geometry=geometry, + sources=src, + resolution=resolution, + boundary_layers=[mp.PML(dpml)], + default_material=SiO2 + ) + + h = mp.Harminv(mp.Hz, mon_vol.center, fcen, df) + + sim.run(mp.after_sources(h), until_after_sources=100) + + fig, ax = plt.subplots() + sim.plot2D( + ax=ax, + fields=mp.Hz, + eps_parameters={'contour':True} + ) + fig.savefig("ring_fields.png", bbox_inches="tight", dpi=150) + + wvl = np.array([1 / m.freq for m in h.modes]) + Q = np.array([m.Q for m in h.modes]) + + sim.reset_meep() + + return wvl, Q + + +if __name__ == "__main__": + filename = create_ring_gds(2.0, 0.5) + wvls, Qs = find_modes(filename, 1.55, 0.05) + for w, Q in zip(wvls, Qs): + print(f"mode: {w}, {Q}") +``` + +Note the absence of `symmetries` even though, in principle, the ring geometry and the two line sources satisfy two mirror symmetry planes through the $x$ (even) and $y$ (odd) axes. This omission is due to the fact that the ring geometry created using gdstk and imported from the GDS file is actually a [`Prism`](../Python_User_Interface.md#prism) consisting of a discrete number of vertices (rather than two overlapping `Cylinder`s as in [Tutorial/Basics/Modes of a Ring Resonator](../Python_Tutorials/Basics.md#modes-of-a-ring-resonator)). Discretization artifacts of the ring geometry slightly break its mirror symmetry. (Attempting to use `symmetries` in this case yields unpredictable results.) + +For this ring geometry, Harminv finds a mode with wavelength 1.5490604 μm and $Q$ of 124691.308. The $H_z$ field profile is shown below. As expected, due to the large $Q$ the mode is tightly confined to the ring and exhibits little radiative loss. + + +![](../images/ring_resonator_gds_Hz.png#center) diff --git a/doc/docs/Python_User_Interface.md b/doc/docs/Python_User_Interface.md index 3173e6040..1d82eb507 100644 --- a/doc/docs/Python_User_Interface.md +++ b/doc/docs/Python_User_Interface.md @@ -2821,64 +2821,6 @@ Technically, `solve_eig` is using a [shift-and-invert power iteration](https://e As for `solve_cw` above, you are required to set `force_complex_fields=True` to use `solve_eigfreq`. -### GDSII Support - -This feature is only available if Meep is built with [libGDSII](Build_From_Source.md#libgdsii). It so, then the following functions are available: - - - - -```python -def GDSII_layers(fname): -``` - -
- -Returns a list of integer-valued layer indices for the layers present in -the specified GDSII file. - -```python -mp.GDSII_layers('python/examples/coupler.gds') -Out[2]: [0, 1, 2, 3, 4, 5, 31, 32] -``` - -
- - - - -```python -def GDSII_prisms(material, fname, layer=-1, zmin=0.0, zmax=0.0): -``` - -
- -Returns a list of `GeometricObject`s with `material` (`mp.Medium`) on layer number -`layer` of a GDSII file `fname` with `zmin` and `zmax` (default 0). - -
- - - - -```python -def GDSII_vol(fname, layer, zmin, zmax): -``` - -
- -Returns a `mp.Volume` read from a GDSII file `fname` on layer number `layer` with -`zmin` and `zmax` (default 0). This function is useful for creating a `FluxRegion` -from a GDSII file as follows: - -```python -fr = mp.FluxRegion(volume=mp.GDSII_vol(fname, layer, zmin, zmax)) -``` - -
- - - ### Data Visualization This module provides basic visualization functionality for the simulation domain. The intent of the module is to provide functions that can be called with *no customization options whatsoever* and will do useful relevant things by default, but which can also be customized in cases where you *do* want to take the time to spruce up the output. The `Simulation` class provides the following methods: @@ -7845,12 +7787,6 @@ original list. - [`get_near2far_freqs`](#get_near2far_freqs) - [`scale_near2far_fields`](#scale_near2far_fields) -#### GDSII Functions - -- [`GDSII_layers`](#GDSII_layers) -- [`GDSII_prism`](#GDSII_prisms) -- [`GDSII_vol`](#GDSII_vol) - #### Run and Step Functions - [`stop_when_fields_decayed`](#stop_when_fields_decayed) diff --git a/doc/docs/Python_User_Interface.md.in b/doc/docs/Python_User_Interface.md.in index 783d19c8c..9e77fcbe2 100644 --- a/doc/docs/Python_User_Interface.md.in +++ b/doc/docs/Python_User_Interface.md.in @@ -469,15 +469,6 @@ Technically, `solve_eig` is using a [shift-and-invert power iteration](https://e As for `solve_cw` above, you are required to set `force_complex_fields=True` to use `solve_eigfreq`. -### GDSII Support - -This feature is only available if Meep is built with [libGDSII](Build_From_Source.md#libgdsii). It so, then the following functions are available: - -@@ GDSII_layers @@ -@@ GDSII_prisms @@ -@@ GDSII_vol @@ - - ### Data Visualization This module provides basic visualization functionality for the simulation domain. The intent of the module is to provide functions that can be called with *no customization options whatsoever* and will do useful relevant things by default, but which can also be customized in cases where you *do* want to take the time to spruce up the output. The `Simulation` class provides the following methods: @@ -916,12 +907,6 @@ Miscellaneous Functions Reference - [`get_near2far_freqs`](#get_near2far_freqs) - [`scale_near2far_fields`](#scale_near2far_fields) -#### GDSII Functions - -- [`GDSII_layers`](#GDSII_layers) -- [`GDSII_prism`](#GDSII_prisms) -- [`GDSII_vol`](#GDSII_vol) - #### Run and Step Functions - [`stop_when_fields_decayed`](#stop_when_fields_decayed) diff --git a/doc/docs/index.md b/doc/docs/index.md index cd86cdeab..e50cd44f8 100644 --- a/doc/docs/index.md +++ b/doc/docs/index.md @@ -21,8 +21,8 @@ Key Features - [Custom current sources](Python_Tutorials/Custom_Source.md) with arbitrary time and spatial profile as well as a [mode launcher](Python_Tutorials/Eigenmode_Source.md) for waveguides and planewaves, and [Gaussian beams](Python_User_Interface.md#gaussianbeam3dsource). - [Frequency-domain solver](Python_User_Interface.md#frequency-domain-solver) for finding the response to a [continuous-wave](https://en.wikipedia.org/wiki/Continuous_wave) (CW) source as well as a [frequency-domain eigensolver](Python_User_Interface.md#frequency-domain-eigensolver) for finding resonant modes. - ε/μ and field import/export in the [HDF5](https://en.wikipedia.org/wiki/HDF5) data format. -- [GDSII](Python_User_Interface.md#gdsii-support) file import for planar geometries. -- Field analyses including [discrete-time Fourier transform (DTFT)](Python_User_Interface.md#field-computations), [Poynting flux](Python_Tutorials/Basics.md#transmittance-spectrum-of-a-waveguide-bend), [mode decomposition](Python_Tutorials/Mode_Decomposition.md) (for [S-parameters](Python_Tutorials/GDSII_Import.md#s-parameters-of-a-directional-coupler)), [energy density](Python_User_Interface.md#energy-density-spectra), [near to far transformation](Python_Tutorials/Near_to_Far_Field_Spectra.md), [frequency extraction](Python_Tutorials/Basics.md#modes-of-a-ring-resonator), [local density of states](Python_Tutorials/Local_Density_of_States.md) (LDOS), [modal volume](Python_User_Interface.md#field-computations), [scattering cross section](Python_Tutorials/Basics.md#mie-scattering-of-a-lossless-dielectric-sphere), [Maxwell stress tensor](Python_Tutorials/Optical_Forces.md), [absorbed power density](Python_Tutorials/Basics.md#absorbed-power-density-map-of-a-lossy-cylinder), [arbitrary functions](Field_Functions.md); completely programmable. +- [GDS](Python_Tutorials/GDS_Import.md) file import for planar geometries. +- Field analyses including [discrete-time Fourier transform (DTFT)](Python_User_Interface.md#field-computations), [Poynting flux](Python_Tutorials/Basics.md#transmittance-spectrum-of-a-waveguide-bend), [mode decomposition](Python_Tutorials/Mode_Decomposition.md) (for [S-parameters](Python_Tutorials/GDS_Import.md#s-parameters-of-a-directional-coupler)), [energy density](Python_User_Interface.md#energy-density-spectra), [near to far transformation](Python_Tutorials/Near_to_Far_Field_Spectra.md), [frequency extraction](Python_Tutorials/Basics.md#modes-of-a-ring-resonator), [local density of states](Python_Tutorials/Local_Density_of_States.md) (LDOS), [modal volume](Python_User_Interface.md#field-computations), [scattering cross section](Python_Tutorials/Basics.md#mie-scattering-of-a-lossless-dielectric-sphere), [Maxwell stress tensor](Python_Tutorials/Optical_Forces.md), [absorbed power density](Python_Tutorials/Basics.md#absorbed-power-density-map-of-a-lossy-cylinder), [arbitrary functions](Field_Functions.md); completely programmable. - [Adjoint solver](Python_Tutorials/Adjoint_Solver.md) for **inverse design** and **topology optimization**. - [Visualization routines](Python_User_Interface.md#data-visualization) for the simulation domain involving geometries, fields, boundary layers, sources, and monitors. diff --git a/mkdocs.yml b/mkdocs.yml index aafa17bf5..14a518094 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -79,7 +79,7 @@ nav: - 'Tutorial/Eigenmode Source': 'Python_Tutorials/Eigenmode_Source.md' - 'Tutorial/Custom Source': 'Python_Tutorials/Custom_Source.md' - 'Tutorial/Mode Decomposition': 'Python_Tutorials/Mode_Decomposition.md' - - 'Tutorial/GDSII Import': 'Python_Tutorials/GDSII_Import.md' + - 'Tutorial/GDS Import': 'Python_Tutorials/GDS_Import.md' - 'Tutorial/Adjoint Solver': 'Python_Tutorials/Adjoint_Solver.md' - 'Scheme Interface': - 'User Interface': 'Scheme_User_Interface.md' diff --git a/python/examples/coupler.ipynb b/python/examples/coupler.ipynb deleted file mode 100644 index 47de7645e..000000000 --- a/python/examples/coupler.ipynb +++ /dev/null @@ -1,2003 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Directional Coupler and Geometry Objects from GDSII File\n", - "\n", - "The directional coupler as well as the source and mode monitor geometries are described by the GDSII file [examples/coupler.gds](https://github.com/NanoComp/meep/blob/master/python/examples/coupler.gds). A snapshot of this file viewed using [KLayout](https://www.klayout.de/) is shown below. The figure labels have been added in post processing. The design consists of two identical strip waveguides which are positioned close together via an adiabatic taper such that their modes couple evanescently. There is a source (labelled \"Source\") and four mode monitors (labelled \"Port 1\", etc.). The input pulse from Port 1 is split in two and exits through Ports 3 and 4. The design objective is to find the separation distance (labelled \"d\") which maximizes power in Port 4 at a wavelength of 1.55 μm. More generally, though not included in this example, it is possible to have two additional degrees of freedom: (1) the length of the straight waveguide section where the two waveguides are coupled and (2) the length of the tapered section (the taper profile is described by a hyperbolic tangent (tanh) function).\n", - "\n", - "![](https://meep.readthedocs.io/en/latest/images/klayout_schematic.png)\n", - "\n", - "The GDSII file is adapted from the [SiEPIC EBeam PDK](https://github.com/lukasc-ubc/SiEPIC_EBeam_PDK) with four major modifications:\n", - "\n", - "+ the computational cell is centered at the origin of the *xy* plane and defined on layer 0\n", - "\n", - "+ the source and four mode monitors are defined on layers 1-5\n", - "\n", - "+ the lower and upper branches of the coupler are defined on layers 31 and 32\n", - "\n", - "+ the straight waveguide sections are perfectly linear\n", - "\n", - "Note that rather than being specified as part of the GDSII file, the volume regions of the source and flux monitors could have been specified in the simulation script." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-----------\n", - "Initializing structure...\n", - "time for choose_chunkdivision = 0.000570059 s\n", - "Working in 2D dimensions.\n", - "Computational cell is 34.4 x 7.84 x 0 with resolution 25\n", - " prism, center = (-9.09425,1.32149,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 174 vertices:\n", - " (-4,0.06,-10)\n", - " (-4.108,0.061,-10)\n", - " (-4.215,0.062,-10)\n", - " (-4.322,0.065,-10)\n", - " (-4.429,0.07,-10)\n", - " (-4.535,0.075,-10)\n", - " (-4.641,0.081,-10)\n", - " (-4.747,0.089,-10)\n", - " (-4.852,0.097,-10)\n", - " (-5.062,0.117,-10)\n", - " (-5.167,0.129,-10)\n", - " (-5.271,0.141,-10)\n", - " (-5.479,0.169,-10)\n", - " (-5.582,0.184,-10)\n", - " (-5.685,0.2,-10)\n", - " (-5.788,0.217,-10)\n", - " (-5.891,0.235,-10)\n", - " (-5.993,0.253,-10)\n", - " (-6.095,0.272,-10)\n", - " (-6.197,0.292,-10)\n", - " (-6.299,0.313,-10)\n", - " (-6.4,0.334,-10)\n", - " (-6.501,0.356,-10)\n", - " (-6.703,0.402,-10)\n", - " (-6.803,0.425,-10)\n", - " (-6.904,0.45,-10)\n", - " (-7.204,0.525,-10)\n", - " (-7.303,0.552,-10)\n", - " (-7.403,0.578,-10)\n", - " (-7.502,0.605,-10)\n", - " (-7.601,0.633,-10)\n", - " (-7.7,0.66,-10)\n", - " (-7.799,0.688,-10)\n", - " (-7.898,0.717,-10)\n", - " (-7.996,0.745,-10)\n", - " (-8.095,0.774,-10)\n", - " (-8.193,0.803,-10)\n", - " (-8.291,0.833,-10)\n", - " (-8.389,0.862,-10)\n", - " (-8.487,0.892,-10)\n", - " (-8.585,0.921,-10)\n", - " (-8.781,0.981,-10)\n", - " (-8.878,1.011,-10)\n", - " (-9.074,1.071,-10)\n", - " (-9.268,1.131,-10)\n", - " (-9.366,1.161,-10)\n", - " (-9.463,1.191,-10)\n", - " (-9.56,1.22,-10)\n", - " (-9.658,1.25,-10)\n", - " (-9.949,1.337,-10)\n", - " (-10.047,1.366,-10)\n", - " (-10.144,1.395,-10)\n", - " (-10.338,1.451,-10)\n", - " (-10.436,1.478,-10)\n", - " (-10.533,1.506,-10)\n", - " (-10.63,1.533,-10)\n", - " (-10.728,1.559,-10)\n", - " (-10.922,1.611,-10)\n", - " (-11.02,1.636,-10)\n", - " (-11.117,1.66,-10)\n", - " (-11.215,1.685,-10)\n", - " (-11.313,1.708,-10)\n", - " (-11.41,1.731,-10)\n", - " (-11.508,1.754,-10)\n", - " (-11.606,1.776,-10)\n", - " (-11.704,1.797,-10)\n", - " (-11.802,1.817,-10)\n", - " (-11.901,1.837,-10)\n", - " (-11.999,1.856,-10)\n", - " (-12.098,1.875,-10)\n", - " (-12.196,1.893,-10)\n", - " (-12.295,1.91,-10)\n", - " (-12.394,1.926,-10)\n", - " (-12.592,1.956,-10)\n", - " (-12.691,1.97,-10)\n", - " (-12.791,1.982,-10)\n", - " (-12.89,1.994,-10)\n", - " (-12.99,2.005,-10)\n", - " (-13.19,2.025,-10)\n", - " (-13.291,2.033,-10)\n", - " (-13.392,2.04,-10)\n", - " (-13.492,2.046,-10)\n", - " (-13.593,2.051,-10)\n", - " (-13.695,2.055,-10)\n", - " (-13.796,2.058,-10)\n", - " (-14,2.06,-10)\n", - " (-17.2,2.06,-10)\n", - " (-17.2,2.56,-10)\n", - " (-14,2.56,-10)\n", - " (-13.892,2.559,-10)\n", - " (-13.785,2.558,-10)\n", - " (-13.678,2.555,-10)\n", - " (-13.571,2.55,-10)\n", - " (-13.465,2.545,-10)\n", - " (-13.359,2.539,-10)\n", - " (-13.253,2.531,-10)\n", - " (-13.148,2.523,-10)\n", - " (-12.938,2.503,-10)\n", - " (-12.833,2.491,-10)\n", - " (-12.729,2.479,-10)\n", - " (-12.521,2.451,-10)\n", - " (-12.418,2.436,-10)\n", - " (-12.315,2.42,-10)\n", - " (-12.212,2.403,-10)\n", - " (-12.109,2.385,-10)\n", - " (-12.007,2.367,-10)\n", - " (-11.905,2.348,-10)\n", - " (-11.803,2.328,-10)\n", - " (-11.701,2.307,-10)\n", - " (-11.6,2.286,-10)\n", - " (-11.499,2.264,-10)\n", - " (-11.297,2.218,-10)\n", - " (-11.197,2.195,-10)\n", - " (-11.096,2.17,-10)\n", - " (-10.796,2.095,-10)\n", - " (-10.697,2.068,-10)\n", - " (-10.597,2.042,-10)\n", - " (-10.498,2.015,-10)\n", - " (-10.399,1.987,-10)\n", - " (-10.3,1.96,-10)\n", - " (-10.201,1.932,-10)\n", - " (-10.102,1.903,-10)\n", - " (-10.004,1.875,-10)\n", - " (-9.905,1.846,-10)\n", - " (-9.807,1.817,-10)\n", - " (-9.709,1.787,-10)\n", - " (-9.611,1.758,-10)\n", - " (-9.513,1.728,-10)\n", - " (-9.415,1.699,-10)\n", - " (-9.219,1.639,-10)\n", - " (-9.122,1.609,-10)\n", - " (-8.926,1.549,-10)\n", - " (-8.732,1.489,-10)\n", - " (-8.634,1.459,-10)\n", - " (-8.537,1.429,-10)\n", - " (-8.44,1.4,-10)\n", - " (-8.342,1.37,-10)\n", - " (-8.051,1.283,-10)\n", - " (-7.953,1.254,-10)\n", - " (-7.856,1.225,-10)\n", - " (-7.662,1.169,-10)\n", - " (-7.564,1.142,-10)\n", - " (-7.467,1.114,-10)\n", - " (-7.37,1.087,-10)\n", - " (-7.272,1.061,-10)\n", - " (-7.078,1.009,-10)\n", - " (-6.98,0.984,-10)\n", - " (-6.883,0.96,-10)\n", - " (-6.785,0.935,-10)\n", - " (-6.687,0.912,-10)\n", - " (-6.59,0.889,-10)\n", - " (-6.492,0.866,-10)\n", - " (-6.394,0.844,-10)\n", - " (-6.296,0.823,-10)\n", - " (-6.198,0.803,-10)\n", - " (-6.099,0.783,-10)\n", - " (-6.001,0.764,-10)\n", - " (-5.902,0.745,-10)\n", - " (-5.804,0.727,-10)\n", - " (-5.705,0.71,-10)\n", - " (-5.606,0.694,-10)\n", - " (-5.408,0.664,-10)\n", - " (-5.309,0.65,-10)\n", - " (-5.209,0.638,-10)\n", - " (-5.11,0.626,-10)\n", - " (-5.01,0.615,-10)\n", - " (-4.81,0.595,-10)\n", - " (-4.709,0.587,-10)\n", - " (-4.608,0.58,-10)\n", - " (-4.508,0.574,-10)\n", - " (-4.407,0.569,-10)\n", - " (-4.305,0.565,-10)\n", - " (-4.204,0.562,-10)\n", - " (-4,0.56,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - " prism, center = (9.09425,1.32149,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 174 vertices:\n", - " (4,0.06,-10)\n", - " (4,0.56,-10)\n", - " (4.204,0.562,-10)\n", - " (4.305,0.565,-10)\n", - " (4.407,0.569,-10)\n", - " (4.508,0.574,-10)\n", - " (4.608,0.58,-10)\n", - " (4.709,0.587,-10)\n", - " (4.81,0.595,-10)\n", - " (5.01,0.615,-10)\n", - " (5.11,0.626,-10)\n", - " (5.209,0.638,-10)\n", - " (5.309,0.65,-10)\n", - " (5.408,0.664,-10)\n", - " (5.606,0.694,-10)\n", - " (5.705,0.71,-10)\n", - " (5.804,0.727,-10)\n", - " (5.902,0.745,-10)\n", - " (6.001,0.764,-10)\n", - " (6.099,0.783,-10)\n", - " (6.198,0.803,-10)\n", - " (6.296,0.823,-10)\n", - " (6.394,0.844,-10)\n", - " (6.492,0.866,-10)\n", - " (6.59,0.889,-10)\n", - " (6.687,0.912,-10)\n", - " (6.785,0.935,-10)\n", - " (6.883,0.96,-10)\n", - " (6.98,0.984,-10)\n", - " (7.078,1.009,-10)\n", - " (7.272,1.061,-10)\n", - " (7.37,1.087,-10)\n", - " (7.467,1.114,-10)\n", - " (7.564,1.142,-10)\n", - " (7.662,1.169,-10)\n", - " (7.856,1.225,-10)\n", - " (7.953,1.254,-10)\n", - " (8.051,1.283,-10)\n", - " (8.342,1.37,-10)\n", - " (8.44,1.4,-10)\n", - " (8.537,1.429,-10)\n", - " (8.634,1.459,-10)\n", - " (8.732,1.489,-10)\n", - " (8.926,1.549,-10)\n", - " (9.122,1.609,-10)\n", - " (9.219,1.639,-10)\n", - " (9.415,1.699,-10)\n", - " (9.513,1.728,-10)\n", - " (9.611,1.758,-10)\n", - " (9.709,1.787,-10)\n", - " (9.807,1.817,-10)\n", - " (9.905,1.846,-10)\n", - " (10.004,1.875,-10)\n", - " (10.102,1.903,-10)\n", - " (10.201,1.932,-10)\n", - " (10.3,1.96,-10)\n", - " (10.399,1.987,-10)\n", - " (10.498,2.015,-10)\n", - " (10.597,2.042,-10)\n", - " (10.697,2.068,-10)\n", - " (10.796,2.095,-10)\n", - " (11.096,2.17,-10)\n", - " (11.197,2.195,-10)\n", - " (11.297,2.218,-10)\n", - " (11.499,2.264,-10)\n", - " (11.6,2.286,-10)\n", - " (11.701,2.307,-10)\n", - " (11.803,2.328,-10)\n", - " (11.905,2.348,-10)\n", - " (12.007,2.367,-10)\n", - " (12.109,2.385,-10)\n", - " (12.212,2.403,-10)\n", - " (12.315,2.42,-10)\n", - " (12.418,2.436,-10)\n", - " (12.521,2.451,-10)\n", - " (12.729,2.479,-10)\n", - " (12.833,2.491,-10)\n", - " (12.938,2.503,-10)\n", - " (13.148,2.523,-10)\n", - " (13.253,2.531,-10)\n", - " (13.359,2.539,-10)\n", - " (13.465,2.545,-10)\n", - " (13.571,2.55,-10)\n", - " (13.678,2.555,-10)\n", - " (13.785,2.558,-10)\n", - " (13.892,2.559,-10)\n", - " (14,2.56,-10)\n", - " (17.2,2.56,-10)\n", - " (17.2,2.06,-10)\n", - " (14,2.06,-10)\n", - " (13.796,2.058,-10)\n", - " (13.695,2.055,-10)\n", - " (13.593,2.051,-10)\n", - " (13.492,2.046,-10)\n", - " (13.392,2.04,-10)\n", - " (13.291,2.033,-10)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " (13.19,2.025,-10)\n", - " (12.99,2.005,-10)\n", - " (12.89,1.994,-10)\n", - " (12.791,1.982,-10)\n", - " (12.691,1.97,-10)\n", - " (12.592,1.956,-10)\n", - " (12.394,1.926,-10)\n", - " (12.295,1.91,-10)\n", - " (12.196,1.893,-10)\n", - " (12.098,1.875,-10)\n", - " (11.999,1.856,-10)\n", - " (11.901,1.837,-10)\n", - " (11.802,1.817,-10)\n", - " (11.704,1.797,-10)\n", - " (11.606,1.776,-10)\n", - " (11.508,1.754,-10)\n", - " (11.41,1.731,-10)\n", - " (11.313,1.708,-10)\n", - " (11.215,1.685,-10)\n", - " (11.117,1.66,-10)\n", - " (11.02,1.636,-10)\n", - " (10.922,1.611,-10)\n", - " (10.728,1.559,-10)\n", - " (10.63,1.533,-10)\n", - " (10.533,1.506,-10)\n", - " (10.436,1.478,-10)\n", - " (10.338,1.451,-10)\n", - " (10.144,1.395,-10)\n", - " (10.047,1.366,-10)\n", - " (9.949,1.337,-10)\n", - " (9.658,1.25,-10)\n", - " (9.56,1.22,-10)\n", - " (9.463,1.191,-10)\n", - " (9.366,1.161,-10)\n", - " (9.268,1.131,-10)\n", - " (9.074,1.071,-10)\n", - " (8.878,1.011,-10)\n", - " (8.781,0.981,-10)\n", - " (8.585,0.921,-10)\n", - " (8.487,0.892,-10)\n", - " (8.389,0.862,-10)\n", - " (8.291,0.833,-10)\n", - " (8.193,0.803,-10)\n", - " (8.095,0.774,-10)\n", - " (7.996,0.745,-10)\n", - " (7.898,0.717,-10)\n", - " (7.799,0.688,-10)\n", - " (7.7,0.66,-10)\n", - " (7.601,0.633,-10)\n", - " (7.502,0.605,-10)\n", - " (7.403,0.578,-10)\n", - " (7.303,0.552,-10)\n", - " (7.204,0.525,-10)\n", - " (6.904,0.45,-10)\n", - " (6.803,0.425,-10)\n", - " (6.703,0.402,-10)\n", - " (6.501,0.356,-10)\n", - " (6.4,0.334,-10)\n", - " (6.299,0.313,-10)\n", - " (6.197,0.292,-10)\n", - " (6.095,0.272,-10)\n", - " (5.993,0.253,-10)\n", - " (5.891,0.235,-10)\n", - " (5.788,0.217,-10)\n", - " (5.685,0.2,-10)\n", - " (5.582,0.184,-10)\n", - " (5.479,0.169,-10)\n", - " (5.271,0.141,-10)\n", - " (5.167,0.129,-10)\n", - " (5.062,0.117,-10)\n", - " (4.852,0.097,-10)\n", - " (4.747,0.089,-10)\n", - " (4.641,0.081,-10)\n", - " (4.535,0.075,-10)\n", - " (4.429,0.07,-10)\n", - " (4.322,0.065,-10)\n", - " (4.215,0.062,-10)\n", - " (4.108,0.061,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - " prism, center = (0,0.31,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 4 vertices:\n", - " (-4,0.06,-10)\n", - " (-4,0.56,-10)\n", - " (4,0.56,-10)\n", - " (4,0.06,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - " prism, center = (-9.09425,-1.32149,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 174 vertices:\n", - " (-17.2,-2.56,-10)\n", - " (-17.2,-2.06,-10)\n", - " (-14,-2.06,-10)\n", - " (-13.796,-2.058,-10)\n", - " (-13.695,-2.055,-10)\n", - " (-13.593,-2.051,-10)\n", - " (-13.492,-2.046,-10)\n", - " (-13.392,-2.04,-10)\n", - " (-13.291,-2.033,-10)\n", - " (-13.19,-2.025,-10)\n", - " (-12.99,-2.005,-10)\n", - " (-12.89,-1.994,-10)\n", - " (-12.791,-1.982,-10)\n", - " (-12.691,-1.97,-10)\n", - " (-12.592,-1.956,-10)\n", - " (-12.394,-1.926,-10)\n", - " (-12.295,-1.91,-10)\n", - " (-12.196,-1.893,-10)\n", - " (-12.098,-1.875,-10)\n", - " (-11.999,-1.856,-10)\n", - " (-11.901,-1.837,-10)\n", - " (-11.802,-1.817,-10)\n", - " (-11.704,-1.797,-10)\n", - " (-11.606,-1.776,-10)\n", - " (-11.508,-1.754,-10)\n", - " (-11.41,-1.731,-10)\n", - " (-11.313,-1.708,-10)\n", - " (-11.215,-1.685,-10)\n", - " (-11.117,-1.66,-10)\n", - " (-11.02,-1.636,-10)\n", - " (-10.922,-1.611,-10)\n", - " (-10.728,-1.559,-10)\n", - " (-10.63,-1.533,-10)\n", - " (-10.533,-1.506,-10)\n", - " (-10.436,-1.478,-10)\n", - " (-10.338,-1.451,-10)\n", - " (-10.144,-1.395,-10)\n", - " (-10.047,-1.366,-10)\n", - " (-9.949,-1.337,-10)\n", - " (-9.658,-1.25,-10)\n", - " (-9.56,-1.22,-10)\n", - " (-9.463,-1.191,-10)\n", - " (-9.366,-1.161,-10)\n", - " (-9.268,-1.131,-10)\n", - " (-9.074,-1.071,-10)\n", - " (-8.878,-1.011,-10)\n", - " (-8.781,-0.981,-10)\n", - " (-8.585,-0.921,-10)\n", - " (-8.487,-0.892,-10)\n", - " (-8.389,-0.862,-10)\n", - " (-8.291,-0.833,-10)\n", - " (-8.193,-0.803,-10)\n", - " (-8.095,-0.774,-10)\n", - " (-7.996,-0.745,-10)\n", - " (-7.898,-0.717,-10)\n", - " (-7.799,-0.688,-10)\n", - " (-7.7,-0.66,-10)\n", - " (-7.601,-0.633,-10)\n", - " (-7.502,-0.605,-10)\n", - " (-7.403,-0.578,-10)\n", - " (-7.303,-0.552,-10)\n", - " (-7.204,-0.525,-10)\n", - " (-6.904,-0.45,-10)\n", - " (-6.803,-0.425,-10)\n", - " (-6.703,-0.402,-10)\n", - " (-6.501,-0.356,-10)\n", - " (-6.4,-0.334,-10)\n", - " (-6.299,-0.313,-10)\n", - " (-6.197,-0.292,-10)\n", - " (-6.095,-0.272,-10)\n", - " (-5.993,-0.253,-10)\n", - " (-5.891,-0.235,-10)\n", - " (-5.788,-0.217,-10)\n", - " (-5.685,-0.2,-10)\n", - " (-5.582,-0.184,-10)\n", - " (-5.479,-0.169,-10)\n", - " (-5.271,-0.141,-10)\n", - " (-5.167,-0.129,-10)\n", - " (-5.062,-0.117,-10)\n", - " (-4.852,-0.097,-10)\n", - " (-4.747,-0.089,-10)\n", - " (-4.641,-0.081,-10)\n", - " (-4.535,-0.075,-10)\n", - " (-4.429,-0.07,-10)\n", - " (-4.322,-0.065,-10)\n", - " (-4.215,-0.062,-10)\n", - " (-4.108,-0.061,-10)\n", - " (-4,-0.06,-10)\n", - " (-4,-0.56,-10)\n", - " (-4.204,-0.562,-10)\n", - " (-4.305,-0.565,-10)\n", - " (-4.407,-0.569,-10)\n", - " (-4.508,-0.574,-10)\n", - " (-4.608,-0.58,-10)\n", - " (-4.709,-0.587,-10)\n", - " (-4.81,-0.595,-10)\n", - " (-5.01,-0.615,-10)\n", - " (-5.11,-0.626,-10)\n", - " (-5.209,-0.638,-10)\n", - " (-5.309,-0.65,-10)\n", - " (-5.408,-0.664,-10)\n", - " (-5.606,-0.694,-10)\n", - " (-5.705,-0.71,-10)\n", - " (-5.804,-0.727,-10)\n", - " (-5.902,-0.745,-10)\n", - " (-6.001,-0.764,-10)\n", - " (-6.099,-0.783,-10)\n", - " (-6.198,-0.803,-10)\n", - " (-6.296,-0.823,-10)\n", - " (-6.394,-0.844,-10)\n", - " (-6.492,-0.866,-10)\n", - " (-6.59,-0.889,-10)\n", - " (-6.687,-0.912,-10)\n", - " (-6.785,-0.935,-10)\n", - " (-6.883,-0.96,-10)\n", - " (-6.98,-0.984,-10)\n", - " (-7.078,-1.009,-10)\n", - " (-7.272,-1.061,-10)\n", - " (-7.37,-1.087,-10)\n", - " (-7.467,-1.114,-10)\n", - " (-7.564,-1.142,-10)\n", - " (-7.662,-1.169,-10)\n", - " (-7.856,-1.225,-10)\n", - " (-7.953,-1.254,-10)\n", - " (-8.051,-1.283,-10)\n", - " (-8.342,-1.37,-10)\n", - " (-8.44,-1.4,-10)\n", - " (-8.537,-1.429,-10)\n", - " (-8.634,-1.459,-10)\n", - " (-8.732,-1.489,-10)\n", - " (-8.926,-1.549,-10)\n", - " (-9.122,-1.609,-10)\n", - " (-9.219,-1.639,-10)\n", - " (-9.415,-1.699,-10)\n", - " (-9.513,-1.728,-10)\n", - " (-9.611,-1.758,-10)\n", - " (-9.709,-1.787,-10)\n", - " (-9.807,-1.817,-10)\n", - " (-9.905,-1.846,-10)\n", - " (-10.004,-1.875,-10)\n", - " (-10.102,-1.903,-10)\n", - " (-10.201,-1.932,-10)\n", - " (-10.3,-1.96,-10)\n", - " (-10.399,-1.987,-10)\n", - " (-10.498,-2.015,-10)\n", - " (-10.597,-2.042,-10)\n", - " (-10.697,-2.068,-10)\n", - " (-10.796,-2.095,-10)\n", - " (-11.096,-2.17,-10)\n", - " (-11.197,-2.195,-10)\n", - " (-11.297,-2.218,-10)\n", - " (-11.499,-2.264,-10)\n", - " (-11.6,-2.286,-10)\n", - " (-11.701,-2.307,-10)\n", - " (-11.803,-2.328,-10)\n", - " (-11.905,-2.348,-10)\n", - " (-12.007,-2.367,-10)\n", - " (-12.109,-2.385,-10)\n", - " (-12.212,-2.403,-10)\n", - " (-12.315,-2.42,-10)\n", - " (-12.418,-2.436,-10)\n", - " (-12.521,-2.451,-10)\n", - " (-12.729,-2.479,-10)\n", - " (-12.833,-2.491,-10)\n", - " (-12.938,-2.503,-10)\n", - " (-13.148,-2.523,-10)\n", - " (-13.253,-2.531,-10)\n", - " (-13.359,-2.539,-10)\n", - " (-13.465,-2.545,-10)\n", - " (-13.571,-2.55,-10)\n", - " (-13.678,-2.555,-10)\n", - " (-13.785,-2.558,-10)\n", - " (-13.892,-2.559,-10)\n", - " (-14,-2.56,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - " prism, center = (9.09425,-1.32149,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 174 vertices:\n", - " (14,-2.56,-10)\n", - " (13.892,-2.559,-10)\n", - " (13.785,-2.558,-10)\n", - " (13.678,-2.555,-10)\n", - " (13.571,-2.55,-10)\n", - " (13.465,-2.545,-10)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " (13.359,-2.539,-10)\n", - " (13.253,-2.531,-10)\n", - " (13.148,-2.523,-10)\n", - " (12.938,-2.503,-10)\n", - " (12.833,-2.491,-10)\n", - " (12.729,-2.479,-10)\n", - " (12.521,-2.451,-10)\n", - " (12.418,-2.436,-10)\n", - " (12.315,-2.42,-10)\n", - " (12.212,-2.403,-10)\n", - " (12.109,-2.385,-10)\n", - " (12.007,-2.367,-10)\n", - " (11.905,-2.348,-10)\n", - " (11.803,-2.328,-10)\n", - " (11.701,-2.307,-10)\n", - " (11.6,-2.286,-10)\n", - " (11.499,-2.264,-10)\n", - " (11.297,-2.218,-10)\n", - " (11.197,-2.195,-10)\n", - " (11.096,-2.17,-10)\n", - " (10.796,-2.095,-10)\n", - " (10.697,-2.068,-10)\n", - " (10.597,-2.042,-10)\n", - " (10.498,-2.015,-10)\n", - " (10.399,-1.987,-10)\n", - " (10.3,-1.96,-10)\n", - " (10.201,-1.932,-10)\n", - " (10.102,-1.903,-10)\n", - " (10.004,-1.875,-10)\n", - " (9.905,-1.846,-10)\n", - " (9.807,-1.817,-10)\n", - " (9.709,-1.787,-10)\n", - " (9.611,-1.758,-10)\n", - " (9.513,-1.728,-10)\n", - " (9.415,-1.699,-10)\n", - " (9.219,-1.639,-10)\n", - " (9.122,-1.609,-10)\n", - " (8.926,-1.549,-10)\n", - " (8.732,-1.489,-10)\n", - " (8.634,-1.459,-10)\n", - " (8.537,-1.429,-10)\n", - " (8.44,-1.4,-10)\n", - " (8.342,-1.37,-10)\n", - " (8.051,-1.283,-10)\n", - " (7.953,-1.254,-10)\n", - " (7.856,-1.225,-10)\n", - " (7.662,-1.169,-10)\n", - " (7.564,-1.142,-10)\n", - " (7.467,-1.114,-10)\n", - " (7.37,-1.087,-10)\n", - " (7.272,-1.061,-10)\n", - " (7.078,-1.009,-10)\n", - " (6.98,-0.984,-10)\n", - " (6.883,-0.96,-10)\n", - " (6.785,-0.935,-10)\n", - " (6.687,-0.912,-10)\n", - " (6.59,-0.889,-10)\n", - " (6.492,-0.866,-10)\n", - " (6.394,-0.844,-10)\n", - " (6.296,-0.823,-10)\n", - " (6.198,-0.803,-10)\n", - " (6.099,-0.783,-10)\n", - " (6.001,-0.764,-10)\n", - " (5.902,-0.745,-10)\n", - " (5.804,-0.727,-10)\n", - " (5.705,-0.71,-10)\n", - " (5.606,-0.694,-10)\n", - " (5.408,-0.664,-10)\n", - " (5.309,-0.65,-10)\n", - " (5.209,-0.638,-10)\n", - " (5.11,-0.626,-10)\n", - " (5.01,-0.615,-10)\n", - " (4.81,-0.595,-10)\n", - " (4.709,-0.587,-10)\n", - " (4.608,-0.58,-10)\n", - " (4.508,-0.574,-10)\n", - " (4.407,-0.569,-10)\n", - " (4.305,-0.565,-10)\n", - " (4.204,-0.562,-10)\n", - " (4,-0.56,-10)\n", - " (4,-0.06,-10)\n", - " (4.108,-0.061,-10)\n", - " (4.215,-0.062,-10)\n", - " (4.322,-0.065,-10)\n", - " (4.429,-0.07,-10)\n", - " (4.535,-0.075,-10)\n", - " (4.641,-0.081,-10)\n", - " (4.747,-0.089,-10)\n", - " (4.852,-0.097,-10)\n", - " (5.062,-0.117,-10)\n", - " (5.167,-0.129,-10)\n", - " (5.271,-0.141,-10)\n", - " (5.479,-0.169,-10)\n", - " (5.582,-0.184,-10)\n", - " (5.685,-0.2,-10)\n", - " (5.788,-0.217,-10)\n", - " (5.891,-0.235,-10)\n", - " (5.993,-0.253,-10)\n", - " (6.095,-0.272,-10)\n", - " (6.197,-0.292,-10)\n", - " (6.299,-0.313,-10)\n", - " (6.4,-0.334,-10)\n", - " (6.501,-0.356,-10)\n", - " (6.703,-0.402,-10)\n", - " (6.803,-0.425,-10)\n", - " (6.904,-0.45,-10)\n", - " (7.204,-0.525,-10)\n", - " (7.303,-0.552,-10)\n", - " (7.403,-0.578,-10)\n", - " (7.502,-0.605,-10)\n", - " (7.601,-0.633,-10)\n", - " (7.7,-0.66,-10)\n", - " (7.799,-0.688,-10)\n", - " (7.898,-0.717,-10)\n", - " (7.996,-0.745,-10)\n", - " (8.095,-0.774,-10)\n", - " (8.193,-0.803,-10)\n", - " (8.291,-0.833,-10)\n", - " (8.389,-0.862,-10)\n", - " (8.487,-0.892,-10)\n", - " (8.585,-0.921,-10)\n", - " (8.781,-0.981,-10)\n", - " (8.878,-1.011,-10)\n", - " (9.074,-1.071,-10)\n", - " (9.268,-1.131,-10)\n", - " (9.366,-1.161,-10)\n", - " (9.463,-1.191,-10)\n", - " (9.56,-1.22,-10)\n", - " (9.658,-1.25,-10)\n", - " (9.949,-1.337,-10)\n", - " (10.047,-1.366,-10)\n", - " (10.144,-1.395,-10)\n", - " (10.338,-1.451,-10)\n", - " (10.436,-1.478,-10)\n", - " (10.533,-1.506,-10)\n", - " (10.63,-1.533,-10)\n", - " (10.728,-1.559,-10)\n", - " (10.922,-1.611,-10)\n", - " (11.02,-1.636,-10)\n", - " (11.117,-1.66,-10)\n", - " (11.215,-1.685,-10)\n", - " (11.313,-1.708,-10)\n", - " (11.41,-1.731,-10)\n", - " (11.508,-1.754,-10)\n", - " (11.606,-1.776,-10)\n", - " (11.704,-1.797,-10)\n", - " (11.802,-1.817,-10)\n", - " (11.901,-1.837,-10)\n", - " (11.999,-1.856,-10)\n", - " (12.098,-1.875,-10)\n", - " (12.196,-1.893,-10)\n", - " (12.295,-1.91,-10)\n", - " (12.394,-1.926,-10)\n", - " (12.592,-1.956,-10)\n", - " (12.691,-1.97,-10)\n", - " (12.791,-1.982,-10)\n", - " (12.89,-1.994,-10)\n", - " (12.99,-2.005,-10)\n", - " (13.19,-2.025,-10)\n", - " (13.291,-2.033,-10)\n", - " (13.392,-2.04,-10)\n", - " (13.492,-2.046,-10)\n", - " (13.593,-2.051,-10)\n", - " (13.695,-2.055,-10)\n", - " (13.796,-2.058,-10)\n", - " (14,-2.06,-10)\n", - " (17.2,-2.06,-10)\n", - " (17.2,-2.56,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - " prism, center = (0,-0.31,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 4 vertices:\n", - " (-4,-0.56,-10)\n", - " (-4,-0.06,-10)\n", - " (4,-0.06,-10)\n", - " (4,-0.56,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - "subpixel-averaging is 6.81898% done, 58.0995 s remaining\n", - "subpixel-averaging is 10.2289% done, 37.5564 s remaining\n", - "subpixel-averaging is 13.6388% done, 27.3374 s remaining\n", - "subpixel-averaging is 17.0487% done, 21.2318 s remaining\n", - "subpixel-averaging is 20.4586% done, 16.7154 s remaining\n", - "subpixel-averaging is 23.8685% done, 13.4232 s remaining\n", - "subpixel-averaging is 27.2785% done, 11.4875 s remaining\n", - "subpixel-averaging is 30.6884% done, 9.75372 s remaining\n", - "subpixel-averaging is 34.0983% done, 8.27854 s remaining\n", - "subpixel-averaging is 37.5082% done, 6.93392 s remaining\n", - "subpixel-averaging is 65.64% done, 2.22818 s remaining\n", - "subpixel-averaging is 69.0499% done, 1.90412 s remaining\n", - "subpixel-averaging is 72.4598% done, 1.64002 s remaining\n", - "subpixel-averaging is 75.8697% done, 1.32216 s remaining\n", - "subpixel-averaging is 79.2797% done, 1.09069 s remaining\n", - "subpixel-averaging is 82.6896% done, 0.886299 s remaining\n", - "subpixel-averaging is 86.0995% done, 0.703019 s remaining\n", - "subpixel-averaging is 89.5094% done, 0.498196 s remaining\n", - "subpixel-averaging is 92.9193% done, 0.325508 s remaining\n", - "subpixel-averaging is 98.8867% done, 0.0483677 s remaining\n", - "subpixel-averaging is 6.81898% done, 59.2108 s remaining\n", - "subpixel-averaging is 10.2289% done, 37.546 s remaining\n", - "subpixel-averaging is 13.6388% done, 26.994 s remaining\n", - "subpixel-averaging is 17.0487% done, 21.1849 s remaining\n", - "subpixel-averaging is 20.4586% done, 16.5219 s remaining\n", - "subpixel-averaging is 23.8685% done, 13.1793 s remaining\n", - "subpixel-averaging is 27.2785% done, 11.4351 s remaining\n", - "subpixel-averaging is 30.6884% done, 9.73853 s remaining\n", - "subpixel-averaging is 34.0983% done, 8.23782 s remaining\n", - "subpixel-averaging is 37.5082% done, 7.17582 s remaining\n", - "subpixel-averaging is 65.64% done, 2.2864 s remaining\n", - "subpixel-averaging is 69.0499% done, 1.91744 s remaining\n", - "subpixel-averaging is 72.4598% done, 1.63739 s remaining\n", - "subpixel-averaging is 75.8697% done, 1.36288 s remaining\n", - "subpixel-averaging is 79.2797% done, 1.06936 s remaining\n", - "subpixel-averaging is 82.6896% done, 0.882767 s remaining\n", - "subpixel-averaging is 86.0995% done, 0.708544 s remaining\n", - "subpixel-averaging is 89.5094% done, 0.495993 s remaining\n", - "subpixel-averaging is 92.9193% done, 0.328165 s remaining\n", - "subpixel-averaging is 98.8867% done, 0.0471172 s remaining\n", - "subpixel-averaging is 6.81898% done, 58.5489 s remaining\n", - "subpixel-averaging is 10.2289% done, 38.1212 s remaining\n", - "subpixel-averaging is 13.6388% done, 27.0431 s remaining\n", - "subpixel-averaging is 17.0487% done, 21.2724 s remaining\n", - "subpixel-averaging is 20.4586% done, 16.6743 s remaining\n", - "subpixel-averaging is 23.8685% done, 13.2109 s remaining\n", - "subpixel-averaging is 27.2785% done, 11.3869 s remaining\n", - "subpixel-averaging is 30.6884% done, 9.75682 s remaining\n", - "subpixel-averaging is 34.0983% done, 8.26105 s remaining\n", - "subpixel-averaging is 37.5082% done, 7.09754 s remaining\n", - "subpixel-averaging is 65.64% done, 2.24059 s remaining\n", - "subpixel-averaging is 69.0499% done, 1.91605 s remaining\n", - "subpixel-averaging is 72.4598% done, 1.63231 s remaining\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "subpixel-averaging is 75.8697% done, 1.34937 s remaining\n", - "subpixel-averaging is 79.2797% done, 1.08291 s remaining\n", - "subpixel-averaging is 82.6896% done, 0.888016 s remaining\n", - "subpixel-averaging is 86.0995% done, 0.710327 s remaining\n", - "subpixel-averaging is 89.5094% done, 0.493508 s remaining\n", - "subpixel-averaging is 92.9193% done, 0.332601 s remaining\n", - "subpixel-averaging is 98.8867% done, 0.0488103 s remaining\n", - "time for set_epsilon = 271.702 s\n", - "-----------\n", - "MPB solved for frequency_1(2.2349,0,0) = 0.687238 after 22 iters\n", - "MPB solved for frequency_1(2.08443,0,0) = 0.645247 after 8 iters\n", - "MPB solved for frequency_1(2.08412,0,0) = 0.645161 after 3 iters\n", - "MPB solved for frequency_1(2.08412,0,0) = 0.645161 after 1 iters\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1eb3cf6322754e07ba3761f3426e295a", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "FloatProgress(value=0.0, description='0% done ', max=177.5)" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Meep progress: 44.68/177.5 = 25.2% done in 4.0s, 11.9s to go\n", - "on time step 2239 (time=44.78), 0.00178698 s/step\n", - "Meep progress: 93.64/177.5 = 52.8% done in 8.0s, 7.2s to go\n", - "on time step 4687 (time=93.74), 0.00163464 s/step\n", - "Meep progress: 142.64000000000001/177.5 = 80.4% done in 12.0s, 2.9s to go\n", - "on time step 7139 (time=142.78), 0.00163171 s/step\n", - "run 0 finished at t = 177.5 (8875 timesteps)\n" - ] - } - ], - "source": [ - "import meep as mp\n", - "import numpy\n", - "import matplotlib.pyplot as plt\n", - "\n", - "res = 25 # pixels/μm\n", - "three_d = False # 3d calculation?\n", - "d = 0.12 # branch separation\n", - "\n", - "gdsII_file = \"coupler.gds\"\n", - "CELL_LAYER = 0\n", - "PORT1_LAYER = 1\n", - "PORT2_LAYER = 2\n", - "PORT3_LAYER = 3\n", - "PORT4_LAYER = 4\n", - "SOURCE_LAYER = 5\n", - "UPPER_BRANCH_LAYER = 31\n", - "LOWER_BRANCH_LAYER = 32\n", - "default_d = 0.3\n", - "\n", - "t_oxide = 1.0\n", - "t_Si = 0.22\n", - "t_air = 0.78\n", - "\n", - "dpml = 1\n", - "cell_thickness = dpml + t_oxide + t_Si + t_air + dpml\n", - "\n", - "oxide = mp.Medium(epsilon=2.25)\n", - "silicon = mp.Medium(epsilon=12)\n", - "\n", - "lcen = 1.55\n", - "fcen = 1 / lcen\n", - "df = 0.2 * fcen\n", - "\n", - "cell_zmax = 0.5 * cell_thickness if three_d else 0\n", - "cell_zmin = -0.5 * cell_thickness if three_d else 0\n", - "si_zmax = 0.5 * t_Si if three_d else 10\n", - "si_zmin = -0.5 * t_Si if three_d else -10\n", - "\n", - "# read cell size, volumes for source region and flux monitors,\n", - "# and coupler geometry from GDSII file\n", - "upper_branch = mp.get_GDSII_prisms(\n", - " silicon, gdsII_file, UPPER_BRANCH_LAYER, si_zmin, si_zmax\n", - ")\n", - "lower_branch = mp.get_GDSII_prisms(\n", - " silicon, gdsII_file, LOWER_BRANCH_LAYER, si_zmin, si_zmax\n", - ")\n", - "\n", - "cell = mp.GDSII_vol(gdsII_file, CELL_LAYER, cell_zmin, cell_zmax)\n", - "p1 = mp.GDSII_vol(gdsII_file, PORT1_LAYER, si_zmin, si_zmax)\n", - "p2 = mp.GDSII_vol(gdsII_file, PORT2_LAYER, si_zmin, si_zmax)\n", - "p3 = mp.GDSII_vol(gdsII_file, PORT3_LAYER, si_zmin, si_zmax)\n", - "p4 = mp.GDSII_vol(gdsII_file, PORT4_LAYER, si_zmin, si_zmax)\n", - "src_vol = mp.GDSII_vol(gdsII_file, SOURCE_LAYER, si_zmin, si_zmax)\n", - "\n", - "# displace upper and lower branches of coupler (as well as source and flux regions)\n", - "if d != default_d:\n", - " delta_y = 0.5 * (d - default_d)\n", - " delta = mp.Vector3(y=delta_y)\n", - " p1.center += delta\n", - " p2.center -= delta\n", - " p3.center += delta\n", - " p4.center -= delta\n", - " src_vol.center += delta\n", - " cell.size += 2 * delta\n", - " for np in range(len(lower_branch)):\n", - " lower_branch[np].center -= delta\n", - " for nv in range(len(lower_branch[np].vertices)):\n", - " lower_branch[np].vertices[nv] -= delta\n", - " for np in range(len(upper_branch)):\n", - " upper_branch[np].center += delta\n", - " for nv in range(len(upper_branch[np].vertices)):\n", - " upper_branch[np].vertices[nv] += delta\n", - "\n", - "geometry = upper_branch + lower_branch\n", - "\n", - "if three_d:\n", - " oxide_center = mp.Vector3(z=-0.5 * t_oxide)\n", - " oxide_size = mp.Vector3(cell.size.x, cell.size.y, t_oxide)\n", - " oxide_layer = [mp.Block(material=oxide, center=oxide_center, size=oxide_size)]\n", - " geometry = geometry + oxide_layer\n", - "\n", - "sources = [\n", - " mp.EigenModeSource(\n", - " src=mp.GaussianSource(fcen, fwidth=df),\n", - " size=src_vol.size,\n", - " center=src_vol.center,\n", - " eig_band=1,\n", - " eig_parity=mp.NO_PARITY if three_d else mp.EVEN_Y + mp.ODD_Z,\n", - " eig_match_freq=True,\n", - " )\n", - "]\n", - "\n", - "sim = mp.Simulation(\n", - " resolution=res,\n", - " cell_size=cell.size,\n", - " boundary_layers=[mp.PML(dpml)],\n", - " sources=sources,\n", - " geometry=geometry,\n", - ")\n", - "\n", - "mode1 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p1))\n", - "mode2 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p2))\n", - "mode3 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p3))\n", - "mode4 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p4))\n", - "\n", - "sim.run(until_after_sources=100)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "MPB solved for frequency_1(2.2349,0,0) = 0.687243 after 22 iters\n", - "MPB solved for frequency_1(2.08451,0,0) = 0.64527 after 5 iters\n", - "MPB solved for frequency_1(2.08412,0,0) = 0.645161 after 4 iters\n", - "MPB solved for frequency_1(2.08412,0,0) = 0.645161 after 1 iters\n", - "Dominant planewave for band 1: (2.084124,-0.000000,0.000000)\n", - "MPB solved for frequency_1(2.2349,0,0) = 0.687243 after 12 iters\n", - "MPB solved for frequency_1(2.08452,0,0) = 0.645271 after 5 iters\n", - "MPB solved for frequency_1(2.08413,0,0) = 0.645161 after 3 iters\n", - "MPB solved for frequency_1(2.08413,0,0) = 0.645161 after 1 iters\n", - "Dominant planewave for band 1: (2.084127,-0.000000,0.000000)\n", - "MPB solved for frequency_1(2.2349,0,0) = 0.687236 after 8 iters\n", - "MPB solved for frequency_1(2.08441,0,0) = 0.645241 after 8 iters\n", - "MPB solved for frequency_1(2.08412,0,0) = 0.645161 after 3 iters\n", - "MPB solved for frequency_1(2.08412,0,0) = 0.645161 after 1 iters\n", - "Dominant planewave for band 1: (2.084118,-0.000000,0.000000)\n", - "MPB solved for frequency_1(2.2349,0,0) = 0.687238 after 27 iters\n", - "MPB solved for frequency_1(2.08443,0,0) = 0.645249 after 7 iters\n", - "MPB solved for frequency_1(2.08412,0,0) = 0.645161 after 3 iters\n", - "MPB solved for frequency_1(2.08412,0,0) = 0.645161 after 1 iters\n", - "Dominant planewave for band 1: (2.084119,-0.000000,0.000000)\n", - "trans:, 0.12, 0.000001, 0.406761, 0.587083\n" - ] - } - ], - "source": [ - "# S parameters\n", - "p1_coeff = sim.get_eigenmode_coefficients(\n", - " mode1, [1], eig_parity=mp.NO_PARITY if three_d else mp.EVEN_Y + mp.ODD_Z\n", - ").alpha[0, 0, 0]\n", - "p2_coeff = sim.get_eigenmode_coefficients(\n", - " mode2, [1], eig_parity=mp.NO_PARITY if three_d else mp.EVEN_Y + mp.ODD_Z\n", - ").alpha[0, 0, 1]\n", - "p3_coeff = sim.get_eigenmode_coefficients(\n", - " mode3, [1], eig_parity=mp.NO_PARITY if three_d else mp.EVEN_Y + mp.ODD_Z\n", - ").alpha[0, 0, 0]\n", - "p4_coeff = sim.get_eigenmode_coefficients(\n", - " mode4, [1], eig_parity=mp.NO_PARITY if three_d else mp.EVEN_Y + mp.ODD_Z\n", - ").alpha[0, 0, 0]\n", - "\n", - "# transmittance\n", - "p2_trans = abs(p2_coeff) ** 2 / abs(p1_coeff) ** 2\n", - "p3_trans = abs(p3_coeff) ** 2 / abs(p1_coeff) ** 2\n", - "p4_trans = abs(p4_coeff) ** 2 / abs(p1_coeff) ** 2\n", - "\n", - "print(\"trans:, {:.2f}, {:.6f}, {:.6f}, {:.6f}\".format(d, p2_trans, p3_trans, p4_trans))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For a given waveguide separation distance (`d`), the simulation computes the transmittance of Ports 2, 3, and 4. The transmittance is the square of the [S-parameter](https://en.wikipedia.org/wiki/Scattering_parameters) which is equivalent to the [mode coefficient](https://meep.readthedocs.io/en/latest/Mode_Decomposition). There is an additional mode monitor at Port 1 to compute the input power from the adjacent eigenmode source; this is used for normalization when computing the transmittance. The eight layers of the GDSII file are each converted to a `Simulation` object: the upper and lower branches of the coupler are defined as a collection of [`Prism`](https://meep.readthedocs.io/en/latest/Python_User_Interface/#prism)s, the rectilinear regions of the source and flux monitor as a [`Volume`](https://meep.readthedocs.io/en/latest/Python_User_Interface/#volume) and [`FluxRegion`](https://meep.readthedocs.io/en/latest/Python_User_Interface/#fluxregion). The size of the cell in the $y$ direction is dependent on `d`. The default dimensionality is 2d. (Note that for a 2d cell the `Prism` objects returned by `get_GDSII_prisms` must have a finite height. The finite height of `Volume` objects returned by `GDSII_vol` are ignored in 2d.) An optional input parameter (`three_d`) converts the geometry to 3d by extruding the coupler geometry in the *z* direction and adding an oxide layer beneath similar to a [silicon on insulator](https://en.wikipedia.org/wiki/Silicon_on_insulator) (SOI) substrate. A schematic of the coupler design in 3d generated using MayaVi is shown below.\n", - "\n", - "![](https://meep.readthedocs.io/en/latest/images/coupler3D.png)\n", - "\n", - "\n", - "## Transmittance Results and Field Profiles\n", - "\n", - "The transmittance results are plotted in the figure below for a range of separation distances from 0.02 to 0.30 μm with increments of 0.02 μm. When the two waveguide branches are sufficiently separated (`d` > 0.2 μm), practically all of the input power remains in the top branch and is transferred to Port 3. A small amount of the input power is lost due to scattering into radiative modes within the light cone in the tapered sections where the translational symmetry of the waveguide is broken. This is why the power in Port 3 never reaches exactly 100%. For separation distances of less than approximately 0.2 μm, evanescent coupling of the modes from the top to the lower branch begins to transfer some of the input power to Port 4. For `d` of 0.13 μm, the input signal is split evenly into Ports 3 and 4. For `d` of 0.06 μm, the input power is transferred completely to Port 4. Finally, for `d` of less than 0.06 μm, the evanescent coupling becomes rapidly ineffective and the signal again remains mostly in Port 3. Note that there is never any power in Port 2 given its location relative to the input from Port 1.\n", - "\n", - "![](https://meep.readthedocs.io/en/latest/images/directional_coupler_flux.png)\n", - "\n", - "These quantitative results can also be verified qualitatively using the field profiles shown below for `d` of 0.06, 0.13, and 0.30 μm. To generate these images, the pulse source is replaced with a [continuous wave](https://meep.readthedocs.io/en/latest/Python_User_Interface/#continuoussource) (CW) and the fields are time stepped for a sufficiently long run time until they have reached steady state. The [array slicing](https://meep.readthedocs.io/en/latest/Python_User_Interface/#array-slices) routines `get_epsilon` and `get_efield_z` are then used to obtain the dielectric and field data over the entire cell." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-----------\n", - "Initializing structure...\n", - "time for choose_chunkdivision = 0.000232935 s\n", - "Working in 2D dimensions.\n", - "Computational cell is 34.4 x 7.84 x 0 with resolution 25\n", - " prism, center = (-9.09425,1.32149,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 174 vertices:\n", - " (-4,0.06,-10)\n", - " (-4.108,0.061,-10)\n", - " (-4.215,0.062,-10)\n", - " (-4.322,0.065,-10)\n", - " (-4.429,0.07,-10)\n", - " (-4.535,0.075,-10)\n", - " (-4.641,0.081,-10)\n", - " (-4.747,0.089,-10)\n", - " (-4.852,0.097,-10)\n", - " (-5.062,0.117,-10)\n", - " (-5.167,0.129,-10)\n", - " (-5.271,0.141,-10)\n", - " (-5.479,0.169,-10)\n", - " (-5.582,0.184,-10)\n", - " (-5.685,0.2,-10)\n", - " (-5.788,0.217,-10)\n", - " (-5.891,0.235,-10)\n", - " (-5.993,0.253,-10)\n", - " (-6.095,0.272,-10)\n", - " (-6.197,0.292,-10)\n", - " (-6.299,0.313,-10)\n", - " (-6.4,0.334,-10)\n", - " (-6.501,0.356,-10)\n", - " (-6.703,0.402,-10)\n", - " (-6.803,0.425,-10)\n", - " (-6.904,0.45,-10)\n", - " (-7.204,0.525,-10)\n", - " (-7.303,0.552,-10)\n", - " (-7.403,0.578,-10)\n", - " (-7.502,0.605,-10)\n", - " (-7.601,0.633,-10)\n", - " (-7.7,0.66,-10)\n", - " (-7.799,0.688,-10)\n", - " (-7.898,0.717,-10)\n", - " (-7.996,0.745,-10)\n", - " (-8.095,0.774,-10)\n", - " (-8.193,0.803,-10)\n", - " (-8.291,0.833,-10)\n", - " (-8.389,0.862,-10)\n", - " (-8.487,0.892,-10)\n", - " (-8.585,0.921,-10)\n", - " (-8.781,0.981,-10)\n", - " (-8.878,1.011,-10)\n", - " (-9.074,1.071,-10)\n", - " (-9.268,1.131,-10)\n", - " (-9.366,1.161,-10)\n", - " (-9.463,1.191,-10)\n", - " (-9.56,1.22,-10)\n", - " (-9.658,1.25,-10)\n", - " (-9.949,1.337,-10)\n", - " (-10.047,1.366,-10)\n", - " (-10.144,1.395,-10)\n", - " (-10.338,1.451,-10)\n", - " (-10.436,1.478,-10)\n", - " (-10.533,1.506,-10)\n", - " (-10.63,1.533,-10)\n", - " (-10.728,1.559,-10)\n", - " (-10.922,1.611,-10)\n", - " (-11.02,1.636,-10)\n", - " (-11.117,1.66,-10)\n", - " (-11.215,1.685,-10)\n", - " (-11.313,1.708,-10)\n", - " (-11.41,1.731,-10)\n", - " (-11.508,1.754,-10)\n", - " (-11.606,1.776,-10)\n", - " (-11.704,1.797,-10)\n", - " (-11.802,1.817,-10)\n", - " (-11.901,1.837,-10)\n", - " (-11.999,1.856,-10)\n", - " (-12.098,1.875,-10)\n", - " (-12.196,1.893,-10)\n", - " (-12.295,1.91,-10)\n", - " (-12.394,1.926,-10)\n", - " (-12.592,1.956,-10)\n", - " (-12.691,1.97,-10)\n", - " (-12.791,1.982,-10)\n", - " (-12.89,1.994,-10)\n", - " (-12.99,2.005,-10)\n", - " (-13.19,2.025,-10)\n", - " (-13.291,2.033,-10)\n", - " (-13.392,2.04,-10)\n", - " (-13.492,2.046,-10)\n", - " (-13.593,2.051,-10)\n", - " (-13.695,2.055,-10)\n", - " (-13.796,2.058,-10)\n", - " (-14,2.06,-10)\n", - " (-17.2,2.06,-10)\n", - " (-17.2,2.56,-10)\n", - " (-14,2.56,-10)\n", - " (-13.892,2.559,-10)\n", - " (-13.785,2.558,-10)\n", - " (-13.678,2.555,-10)\n", - " (-13.571,2.55,-10)\n", - " (-13.465,2.545,-10)\n", - " (-13.359,2.539,-10)\n", - " (-13.253,2.531,-10)\n", - " (-13.148,2.523,-10)\n", - " (-12.938,2.503,-10)\n", - " (-12.833,2.491,-10)\n", - " (-12.729,2.479,-10)\n", - " (-12.521,2.451,-10)\n", - " (-12.418,2.436,-10)\n", - " (-12.315,2.42,-10)\n", - " (-12.212,2.403,-10)\n", - " (-12.109,2.385,-10)\n", - " (-12.007,2.367,-10)\n", - " (-11.905,2.348,-10)\n", - " (-11.803,2.328,-10)\n", - " (-11.701,2.307,-10)\n", - " (-11.6,2.286,-10)\n", - " (-11.499,2.264,-10)\n", - " (-11.297,2.218,-10)\n", - " (-11.197,2.195,-10)\n", - " (-11.096,2.17,-10)\n", - " (-10.796,2.095,-10)\n", - " (-10.697,2.068,-10)\n", - " (-10.597,2.042,-10)\n", - " (-10.498,2.015,-10)\n", - " (-10.399,1.987,-10)\n", - " (-10.3,1.96,-10)\n", - " (-10.201,1.932,-10)\n", - " (-10.102,1.903,-10)\n", - " (-10.004,1.875,-10)\n", - " (-9.905,1.846,-10)\n", - " (-9.807,1.817,-10)\n", - " (-9.709,1.787,-10)\n", - " (-9.611,1.758,-10)\n", - " (-9.513,1.728,-10)\n", - " (-9.415,1.699,-10)\n", - " (-9.219,1.639,-10)\n", - " (-9.122,1.609,-10)\n", - " (-8.926,1.549,-10)\n", - " (-8.732,1.489,-10)\n", - " (-8.634,1.459,-10)\n", - " (-8.537,1.429,-10)\n", - " (-8.44,1.4,-10)\n", - " (-8.342,1.37,-10)\n", - " (-8.051,1.283,-10)\n", - " (-7.953,1.254,-10)\n", - " (-7.856,1.225,-10)\n", - " (-7.662,1.169,-10)\n", - " (-7.564,1.142,-10)\n", - " (-7.467,1.114,-10)\n", - " (-7.37,1.087,-10)\n", - " (-7.272,1.061,-10)\n", - " (-7.078,1.009,-10)\n", - " (-6.98,0.984,-10)\n", - " (-6.883,0.96,-10)\n", - " (-6.785,0.935,-10)\n", - " (-6.687,0.912,-10)\n", - " (-6.59,0.889,-10)\n", - " (-6.492,0.866,-10)\n", - " (-6.394,0.844,-10)\n", - " (-6.296,0.823,-10)\n", - " (-6.198,0.803,-10)\n", - " (-6.099,0.783,-10)\n", - " (-6.001,0.764,-10)\n", - " (-5.902,0.745,-10)\n", - " (-5.804,0.727,-10)\n", - " (-5.705,0.71,-10)\n", - " (-5.606,0.694,-10)\n", - " (-5.408,0.664,-10)\n", - " (-5.309,0.65,-10)\n", - " (-5.209,0.638,-10)\n", - " (-5.11,0.626,-10)\n", - " (-5.01,0.615,-10)\n", - " (-4.81,0.595,-10)\n", - " (-4.709,0.587,-10)\n", - " (-4.608,0.58,-10)\n", - " (-4.508,0.574,-10)\n", - " (-4.407,0.569,-10)\n", - " (-4.305,0.565,-10)\n", - " (-4.204,0.562,-10)\n", - " (-4,0.56,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - " prism, center = (9.09425,1.32149,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 174 vertices:\n", - " (4,0.06,-10)\n", - " (4,0.56,-10)\n", - " (4.204,0.562,-10)\n", - " (4.305,0.565,-10)\n", - " (4.407,0.569,-10)\n", - " (4.508,0.574,-10)\n", - " (4.608,0.58,-10)\n", - " (4.709,0.587,-10)\n", - " (4.81,0.595,-10)\n", - " (5.01,0.615,-10)\n", - " (5.11,0.626,-10)\n", - " (5.209,0.638,-10)\n", - " (5.309,0.65,-10)\n", - " (5.408,0.664,-10)\n", - " (5.606,0.694,-10)\n", - " (5.705,0.71,-10)\n", - " (5.804,0.727,-10)\n", - " (5.902,0.745,-10)\n", - " (6.001,0.764,-10)\n", - " (6.099,0.783,-10)\n", - " (6.198,0.803,-10)\n", - " (6.296,0.823,-10)\n", - " (6.394,0.844,-10)\n", - " (6.492,0.866,-10)\n", - " (6.59,0.889,-10)\n", - " (6.687,0.912,-10)\n", - " (6.785,0.935,-10)\n", - " (6.883,0.96,-10)\n", - " (6.98,0.984,-10)\n", - " (7.078,1.009,-10)\n", - " (7.272,1.061,-10)\n", - " (7.37,1.087,-10)\n", - " (7.467,1.114,-10)\n", - " (7.564,1.142,-10)\n", - " (7.662,1.169,-10)\n", - " (7.856,1.225,-10)\n", - " (7.953,1.254,-10)\n", - " (8.051,1.283,-10)\n", - " (8.342,1.37,-10)\n", - " (8.44,1.4,-10)\n", - " (8.537,1.429,-10)\n", - " (8.634,1.459,-10)\n", - " (8.732,1.489,-10)\n", - " (8.926,1.549,-10)\n", - " (9.122,1.609,-10)\n", - " (9.219,1.639,-10)\n", - " (9.415,1.699,-10)\n", - " (9.513,1.728,-10)\n", - " (9.611,1.758,-10)\n", - " (9.709,1.787,-10)\n", - " (9.807,1.817,-10)\n", - " (9.905,1.846,-10)\n", - " (10.004,1.875,-10)\n", - " (10.102,1.903,-10)\n", - " (10.201,1.932,-10)\n", - " (10.3,1.96,-10)\n", - " (10.399,1.987,-10)\n", - " (10.498,2.015,-10)\n", - " (10.597,2.042,-10)\n", - " (10.697,2.068,-10)\n", - " (10.796,2.095,-10)\n", - " (11.096,2.17,-10)\n", - " (11.197,2.195,-10)\n", - " (11.297,2.218,-10)\n", - " (11.499,2.264,-10)\n", - " (11.6,2.286,-10)\n", - " (11.701,2.307,-10)\n", - " (11.803,2.328,-10)\n", - " (11.905,2.348,-10)\n", - " (12.007,2.367,-10)\n", - " (12.109,2.385,-10)\n", - " (12.212,2.403,-10)\n", - " (12.315,2.42,-10)\n", - " (12.418,2.436,-10)\n", - " (12.521,2.451,-10)\n", - " (12.729,2.479,-10)\n", - " (12.833,2.491,-10)\n", - " (12.938,2.503,-10)\n", - " (13.148,2.523,-10)\n", - " (13.253,2.531,-10)\n", - " (13.359,2.539,-10)\n", - " (13.465,2.545,-10)\n", - " (13.571,2.55,-10)\n", - " (13.678,2.555,-10)\n", - " (13.785,2.558,-10)\n", - " (13.892,2.559,-10)\n", - " (14,2.56,-10)\n", - " (17.2,2.56,-10)\n", - " (17.2,2.06,-10)\n", - " (14,2.06,-10)\n", - " (13.796,2.058,-10)\n", - " (13.695,2.055,-10)\n", - " (13.593,2.051,-10)\n", - " (13.492,2.046,-10)\n", - " (13.392,2.04,-10)\n", - " (13.291,2.033,-10)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " (13.19,2.025,-10)\n", - " (12.99,2.005,-10)\n", - " (12.89,1.994,-10)\n", - " (12.791,1.982,-10)\n", - " (12.691,1.97,-10)\n", - " (12.592,1.956,-10)\n", - " (12.394,1.926,-10)\n", - " (12.295,1.91,-10)\n", - " (12.196,1.893,-10)\n", - " (12.098,1.875,-10)\n", - " (11.999,1.856,-10)\n", - " (11.901,1.837,-10)\n", - " (11.802,1.817,-10)\n", - " (11.704,1.797,-10)\n", - " (11.606,1.776,-10)\n", - " (11.508,1.754,-10)\n", - " (11.41,1.731,-10)\n", - " (11.313,1.708,-10)\n", - " (11.215,1.685,-10)\n", - " (11.117,1.66,-10)\n", - " (11.02,1.636,-10)\n", - " (10.922,1.611,-10)\n", - " (10.728,1.559,-10)\n", - " (10.63,1.533,-10)\n", - " (10.533,1.506,-10)\n", - " (10.436,1.478,-10)\n", - " (10.338,1.451,-10)\n", - " (10.144,1.395,-10)\n", - " (10.047,1.366,-10)\n", - " (9.949,1.337,-10)\n", - " (9.658,1.25,-10)\n", - " (9.56,1.22,-10)\n", - " (9.463,1.191,-10)\n", - " (9.366,1.161,-10)\n", - " (9.268,1.131,-10)\n", - " (9.074,1.071,-10)\n", - " (8.878,1.011,-10)\n", - " (8.781,0.981,-10)\n", - " (8.585,0.921,-10)\n", - " (8.487,0.892,-10)\n", - " (8.389,0.862,-10)\n", - " (8.291,0.833,-10)\n", - " (8.193,0.803,-10)\n", - " (8.095,0.774,-10)\n", - " (7.996,0.745,-10)\n", - " (7.898,0.717,-10)\n", - " (7.799,0.688,-10)\n", - " (7.7,0.66,-10)\n", - " (7.601,0.633,-10)\n", - " (7.502,0.605,-10)\n", - " (7.403,0.578,-10)\n", - " (7.303,0.552,-10)\n", - " (7.204,0.525,-10)\n", - " (6.904,0.45,-10)\n", - " (6.803,0.425,-10)\n", - " (6.703,0.402,-10)\n", - " (6.501,0.356,-10)\n", - " (6.4,0.334,-10)\n", - " (6.299,0.313,-10)\n", - " (6.197,0.292,-10)\n", - " (6.095,0.272,-10)\n", - " (5.993,0.253,-10)\n", - " (5.891,0.235,-10)\n", - " (5.788,0.217,-10)\n", - " (5.685,0.2,-10)\n", - " (5.582,0.184,-10)\n", - " (5.479,0.169,-10)\n", - " (5.271,0.141,-10)\n", - " (5.167,0.129,-10)\n", - " (5.062,0.117,-10)\n", - " (4.852,0.097,-10)\n", - " (4.747,0.089,-10)\n", - " (4.641,0.081,-10)\n", - " (4.535,0.075,-10)\n", - " (4.429,0.07,-10)\n", - " (4.322,0.065,-10)\n", - " (4.215,0.062,-10)\n", - " (4.108,0.061,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - " prism, center = (0,0.31,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 4 vertices:\n", - " (-4,0.06,-10)\n", - " (-4,0.56,-10)\n", - " (4,0.56,-10)\n", - " (4,0.06,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - " prism, center = (-9.09425,-1.32149,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 174 vertices:\n", - " (-17.2,-2.56,-10)\n", - " (-17.2,-2.06,-10)\n", - " (-14,-2.06,-10)\n", - " (-13.796,-2.058,-10)\n", - " (-13.695,-2.055,-10)\n", - " (-13.593,-2.051,-10)\n", - " (-13.492,-2.046,-10)\n", - " (-13.392,-2.04,-10)\n", - " (-13.291,-2.033,-10)\n", - " (-13.19,-2.025,-10)\n", - " (-12.99,-2.005,-10)\n", - " (-12.89,-1.994,-10)\n", - " (-12.791,-1.982,-10)\n", - " (-12.691,-1.97,-10)\n", - " (-12.592,-1.956,-10)\n", - " (-12.394,-1.926,-10)\n", - " (-12.295,-1.91,-10)\n", - " (-12.196,-1.893,-10)\n", - " (-12.098,-1.875,-10)\n", - " (-11.999,-1.856,-10)\n", - " (-11.901,-1.837,-10)\n", - " (-11.802,-1.817,-10)\n", - " (-11.704,-1.797,-10)\n", - " (-11.606,-1.776,-10)\n", - " (-11.508,-1.754,-10)\n", - " (-11.41,-1.731,-10)\n", - " (-11.313,-1.708,-10)\n", - " (-11.215,-1.685,-10)\n", - " (-11.117,-1.66,-10)\n", - " (-11.02,-1.636,-10)\n", - " (-10.922,-1.611,-10)\n", - " (-10.728,-1.559,-10)\n", - " (-10.63,-1.533,-10)\n", - " (-10.533,-1.506,-10)\n", - " (-10.436,-1.478,-10)\n", - " (-10.338,-1.451,-10)\n", - " (-10.144,-1.395,-10)\n", - " (-10.047,-1.366,-10)\n", - " (-9.949,-1.337,-10)\n", - " (-9.658,-1.25,-10)\n", - " (-9.56,-1.22,-10)\n", - " (-9.463,-1.191,-10)\n", - " (-9.366,-1.161,-10)\n", - " (-9.268,-1.131,-10)\n", - " (-9.074,-1.071,-10)\n", - " (-8.878,-1.011,-10)\n", - " (-8.781,-0.981,-10)\n", - " (-8.585,-0.921,-10)\n", - " (-8.487,-0.892,-10)\n", - " (-8.389,-0.862,-10)\n", - " (-8.291,-0.833,-10)\n", - " (-8.193,-0.803,-10)\n", - " (-8.095,-0.774,-10)\n", - " (-7.996,-0.745,-10)\n", - " (-7.898,-0.717,-10)\n", - " (-7.799,-0.688,-10)\n", - " (-7.7,-0.66,-10)\n", - " (-7.601,-0.633,-10)\n", - " (-7.502,-0.605,-10)\n", - " (-7.403,-0.578,-10)\n", - " (-7.303,-0.552,-10)\n", - " (-7.204,-0.525,-10)\n", - " (-6.904,-0.45,-10)\n", - " (-6.803,-0.425,-10)\n", - " (-6.703,-0.402,-10)\n", - " (-6.501,-0.356,-10)\n", - " (-6.4,-0.334,-10)\n", - " (-6.299,-0.313,-10)\n", - " (-6.197,-0.292,-10)\n", - " (-6.095,-0.272,-10)\n", - " (-5.993,-0.253,-10)\n", - " (-5.891,-0.235,-10)\n", - " (-5.788,-0.217,-10)\n", - " (-5.685,-0.2,-10)\n", - " (-5.582,-0.184,-10)\n", - " (-5.479,-0.169,-10)\n", - " (-5.271,-0.141,-10)\n", - " (-5.167,-0.129,-10)\n", - " (-5.062,-0.117,-10)\n", - " (-4.852,-0.097,-10)\n", - " (-4.747,-0.089,-10)\n", - " (-4.641,-0.081,-10)\n", - " (-4.535,-0.075,-10)\n", - " (-4.429,-0.07,-10)\n", - " (-4.322,-0.065,-10)\n", - " (-4.215,-0.062,-10)\n", - " (-4.108,-0.061,-10)\n", - " (-4,-0.06,-10)\n", - " (-4,-0.56,-10)\n", - " (-4.204,-0.562,-10)\n", - " (-4.305,-0.565,-10)\n", - " (-4.407,-0.569,-10)\n", - " (-4.508,-0.574,-10)\n", - " (-4.608,-0.58,-10)\n", - " (-4.709,-0.587,-10)\n", - " (-4.81,-0.595,-10)\n", - " (-5.01,-0.615,-10)\n", - " (-5.11,-0.626,-10)\n", - " (-5.209,-0.638,-10)\n", - " (-5.309,-0.65,-10)\n", - " (-5.408,-0.664,-10)\n", - " (-5.606,-0.694,-10)\n", - " (-5.705,-0.71,-10)\n", - " (-5.804,-0.727,-10)\n", - " (-5.902,-0.745,-10)\n", - " (-6.001,-0.764,-10)\n", - " (-6.099,-0.783,-10)\n", - " (-6.198,-0.803,-10)\n", - " (-6.296,-0.823,-10)\n", - " (-6.394,-0.844,-10)\n", - " (-6.492,-0.866,-10)\n", - " (-6.59,-0.889,-10)\n", - " (-6.687,-0.912,-10)\n", - " (-6.785,-0.935,-10)\n", - " (-6.883,-0.96,-10)\n", - " (-6.98,-0.984,-10)\n", - " (-7.078,-1.009,-10)\n", - " (-7.272,-1.061,-10)\n", - " (-7.37,-1.087,-10)\n", - " (-7.467,-1.114,-10)\n", - " (-7.564,-1.142,-10)\n", - " (-7.662,-1.169,-10)\n", - " (-7.856,-1.225,-10)\n", - " (-7.953,-1.254,-10)\n", - " (-8.051,-1.283,-10)\n", - " (-8.342,-1.37,-10)\n", - " (-8.44,-1.4,-10)\n", - " (-8.537,-1.429,-10)\n", - " (-8.634,-1.459,-10)\n", - " (-8.732,-1.489,-10)\n", - " (-8.926,-1.549,-10)\n", - " (-9.122,-1.609,-10)\n", - " (-9.219,-1.639,-10)\n", - " (-9.415,-1.699,-10)\n", - " (-9.513,-1.728,-10)\n", - " (-9.611,-1.758,-10)\n", - " (-9.709,-1.787,-10)\n", - " (-9.807,-1.817,-10)\n", - " (-9.905,-1.846,-10)\n", - " (-10.004,-1.875,-10)\n", - " (-10.102,-1.903,-10)\n", - " (-10.201,-1.932,-10)\n", - " (-10.3,-1.96,-10)\n", - " (-10.399,-1.987,-10)\n", - " (-10.498,-2.015,-10)\n", - " (-10.597,-2.042,-10)\n", - " (-10.697,-2.068,-10)\n", - " (-10.796,-2.095,-10)\n", - " (-11.096,-2.17,-10)\n", - " (-11.197,-2.195,-10)\n", - " (-11.297,-2.218,-10)\n", - " (-11.499,-2.264,-10)\n", - " (-11.6,-2.286,-10)\n", - " (-11.701,-2.307,-10)\n", - " (-11.803,-2.328,-10)\n", - " (-11.905,-2.348,-10)\n", - " (-12.007,-2.367,-10)\n", - " (-12.109,-2.385,-10)\n", - " (-12.212,-2.403,-10)\n", - " (-12.315,-2.42,-10)\n", - " (-12.418,-2.436,-10)\n", - " (-12.521,-2.451,-10)\n", - " (-12.729,-2.479,-10)\n", - " (-12.833,-2.491,-10)\n", - " (-12.938,-2.503,-10)\n", - " (-13.148,-2.523,-10)\n", - " (-13.253,-2.531,-10)\n", - " (-13.359,-2.539,-10)\n", - " (-13.465,-2.545,-10)\n", - " (-13.571,-2.55,-10)\n", - " (-13.678,-2.555,-10)\n", - " (-13.785,-2.558,-10)\n", - " (-13.892,-2.559,-10)\n", - " (-14,-2.56,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - " prism, center = (9.09425,-1.32149,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 174 vertices:\n", - " (14,-2.56,-10)\n", - " (13.892,-2.559,-10)\n", - " (13.785,-2.558,-10)\n", - " (13.678,-2.555,-10)\n", - " (13.571,-2.55,-10)\n", - " (13.465,-2.545,-10)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " (13.359,-2.539,-10)\n", - " (13.253,-2.531,-10)\n", - " (13.148,-2.523,-10)\n", - " (12.938,-2.503,-10)\n", - " (12.833,-2.491,-10)\n", - " (12.729,-2.479,-10)\n", - " (12.521,-2.451,-10)\n", - " (12.418,-2.436,-10)\n", - " (12.315,-2.42,-10)\n", - " (12.212,-2.403,-10)\n", - " (12.109,-2.385,-10)\n", - " (12.007,-2.367,-10)\n", - " (11.905,-2.348,-10)\n", - " (11.803,-2.328,-10)\n", - " (11.701,-2.307,-10)\n", - " (11.6,-2.286,-10)\n", - " (11.499,-2.264,-10)\n", - " (11.297,-2.218,-10)\n", - " (11.197,-2.195,-10)\n", - " (11.096,-2.17,-10)\n", - " (10.796,-2.095,-10)\n", - " (10.697,-2.068,-10)\n", - " (10.597,-2.042,-10)\n", - " (10.498,-2.015,-10)\n", - " (10.399,-1.987,-10)\n", - " (10.3,-1.96,-10)\n", - " (10.201,-1.932,-10)\n", - " (10.102,-1.903,-10)\n", - " (10.004,-1.875,-10)\n", - " (9.905,-1.846,-10)\n", - " (9.807,-1.817,-10)\n", - " (9.709,-1.787,-10)\n", - " (9.611,-1.758,-10)\n", - " (9.513,-1.728,-10)\n", - " (9.415,-1.699,-10)\n", - " (9.219,-1.639,-10)\n", - " (9.122,-1.609,-10)\n", - " (8.926,-1.549,-10)\n", - " (8.732,-1.489,-10)\n", - " (8.634,-1.459,-10)\n", - " (8.537,-1.429,-10)\n", - " (8.44,-1.4,-10)\n", - " (8.342,-1.37,-10)\n", - " (8.051,-1.283,-10)\n", - " (7.953,-1.254,-10)\n", - " (7.856,-1.225,-10)\n", - " (7.662,-1.169,-10)\n", - " (7.564,-1.142,-10)\n", - " (7.467,-1.114,-10)\n", - " (7.37,-1.087,-10)\n", - " (7.272,-1.061,-10)\n", - " (7.078,-1.009,-10)\n", - " (6.98,-0.984,-10)\n", - " (6.883,-0.96,-10)\n", - " (6.785,-0.935,-10)\n", - " (6.687,-0.912,-10)\n", - " (6.59,-0.889,-10)\n", - " (6.492,-0.866,-10)\n", - " (6.394,-0.844,-10)\n", - " (6.296,-0.823,-10)\n", - " (6.198,-0.803,-10)\n", - " (6.099,-0.783,-10)\n", - " (6.001,-0.764,-10)\n", - " (5.902,-0.745,-10)\n", - " (5.804,-0.727,-10)\n", - " (5.705,-0.71,-10)\n", - " (5.606,-0.694,-10)\n", - " (5.408,-0.664,-10)\n", - " (5.309,-0.65,-10)\n", - " (5.209,-0.638,-10)\n", - " (5.11,-0.626,-10)\n", - " (5.01,-0.615,-10)\n", - " (4.81,-0.595,-10)\n", - " (4.709,-0.587,-10)\n", - " (4.608,-0.58,-10)\n", - " (4.508,-0.574,-10)\n", - " (4.407,-0.569,-10)\n", - " (4.305,-0.565,-10)\n", - " (4.204,-0.562,-10)\n", - " (4,-0.56,-10)\n", - " (4,-0.06,-10)\n", - " (4.108,-0.061,-10)\n", - " (4.215,-0.062,-10)\n", - " (4.322,-0.065,-10)\n", - " (4.429,-0.07,-10)\n", - " (4.535,-0.075,-10)\n", - " (4.641,-0.081,-10)\n", - " (4.747,-0.089,-10)\n", - " (4.852,-0.097,-10)\n", - " (5.062,-0.117,-10)\n", - " (5.167,-0.129,-10)\n", - " (5.271,-0.141,-10)\n", - " (5.479,-0.169,-10)\n", - " (5.582,-0.184,-10)\n", - " (5.685,-0.2,-10)\n", - " (5.788,-0.217,-10)\n", - " (5.891,-0.235,-10)\n", - " (5.993,-0.253,-10)\n", - " (6.095,-0.272,-10)\n", - " (6.197,-0.292,-10)\n", - " (6.299,-0.313,-10)\n", - " (6.4,-0.334,-10)\n", - " (6.501,-0.356,-10)\n", - " (6.703,-0.402,-10)\n", - " (6.803,-0.425,-10)\n", - " (6.904,-0.45,-10)\n", - " (7.204,-0.525,-10)\n", - " (7.303,-0.552,-10)\n", - " (7.403,-0.578,-10)\n", - " (7.502,-0.605,-10)\n", - " (7.601,-0.633,-10)\n", - " (7.7,-0.66,-10)\n", - " (7.799,-0.688,-10)\n", - " (7.898,-0.717,-10)\n", - " (7.996,-0.745,-10)\n", - " (8.095,-0.774,-10)\n", - " (8.193,-0.803,-10)\n", - " (8.291,-0.833,-10)\n", - " (8.389,-0.862,-10)\n", - " (8.487,-0.892,-10)\n", - " (8.585,-0.921,-10)\n", - " (8.781,-0.981,-10)\n", - " (8.878,-1.011,-10)\n", - " (9.074,-1.071,-10)\n", - " (9.268,-1.131,-10)\n", - " (9.366,-1.161,-10)\n", - " (9.463,-1.191,-10)\n", - " (9.56,-1.22,-10)\n", - " (9.658,-1.25,-10)\n", - " (9.949,-1.337,-10)\n", - " (10.047,-1.366,-10)\n", - " (10.144,-1.395,-10)\n", - " (10.338,-1.451,-10)\n", - " (10.436,-1.478,-10)\n", - " (10.533,-1.506,-10)\n", - " (10.63,-1.533,-10)\n", - " (10.728,-1.559,-10)\n", - " (10.922,-1.611,-10)\n", - " (11.02,-1.636,-10)\n", - " (11.117,-1.66,-10)\n", - " (11.215,-1.685,-10)\n", - " (11.313,-1.708,-10)\n", - " (11.41,-1.731,-10)\n", - " (11.508,-1.754,-10)\n", - " (11.606,-1.776,-10)\n", - " (11.704,-1.797,-10)\n", - " (11.802,-1.817,-10)\n", - " (11.901,-1.837,-10)\n", - " (11.999,-1.856,-10)\n", - " (12.098,-1.875,-10)\n", - " (12.196,-1.893,-10)\n", - " (12.295,-1.91,-10)\n", - " (12.394,-1.926,-10)\n", - " (12.592,-1.956,-10)\n", - " (12.691,-1.97,-10)\n", - " (12.791,-1.982,-10)\n", - " (12.89,-1.994,-10)\n", - " (12.99,-2.005,-10)\n", - " (13.19,-2.025,-10)\n", - " (13.291,-2.033,-10)\n", - " (13.392,-2.04,-10)\n", - " (13.492,-2.046,-10)\n", - " (13.593,-2.051,-10)\n", - " (13.695,-2.055,-10)\n", - " (13.796,-2.058,-10)\n", - " (14,-2.06,-10)\n", - " (17.2,-2.06,-10)\n", - " (17.2,-2.56,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - " prism, center = (0,-0.31,0)\n", - " height 20, axis (0,0,1), sidewall angle: 0 radians, 4 vertices:\n", - " (-4,-0.56,-10)\n", - " (-4,-0.06,-10)\n", - " (4,-0.06,-10)\n", - " (4,-0.56,-10)\n", - " dielectric constant epsilon diagonal = (12,12,12)\n", - "subpixel-averaging is 6.81898% done, 58.5777 s remaining\n", - "subpixel-averaging is 10.2289% done, 37.5198 s remaining\n", - "subpixel-averaging is 13.6388% done, 27.1639 s remaining\n", - "subpixel-averaging is 17.0487% done, 21.1306 s remaining\n", - "subpixel-averaging is 20.4586% done, 16.5868 s remaining\n", - "subpixel-averaging is 23.8685% done, 13.3518 s remaining\n", - "subpixel-averaging is 27.2785% done, 11.5065 s remaining\n", - "subpixel-averaging is 30.6884% done, 9.72629 s remaining\n", - "subpixel-averaging is 34.0983% done, 7.75935 s remaining\n", - "subpixel-averaging is 37.5082% done, 6.95236 s remaining\n", - "subpixel-averaging is 65.64% done, 2.22683 s remaining\n", - "subpixel-averaging is 69.0499% done, 1.91287 s remaining\n", - "subpixel-averaging is 72.4598% done, 1.63956 s remaining\n", - "subpixel-averaging is 75.8697% done, 1.36389 s remaining\n", - "subpixel-averaging is 79.2797% done, 1.08924 s remaining\n", - "subpixel-averaging is 82.6896% done, 0.888155 s remaining\n", - "subpixel-averaging is 86.0995% done, 0.678355 s remaining\n", - "subpixel-averaging is 89.5094% done, 0.499442 s remaining\n", - "subpixel-averaging is 92.9193% done, 0.326281 s remaining\n", - "subpixel-averaging is 98.8867% done, 0.0483846 s remaining\n", - "subpixel-averaging is 6.81898% done, 59.1477 s remaining\n", - "subpixel-averaging is 10.2289% done, 37.4525 s remaining\n", - "subpixel-averaging is 13.6388% done, 26.9655 s remaining\n", - "subpixel-averaging is 17.0487% done, 21.0934 s remaining\n", - "subpixel-averaging is 20.4586% done, 16.5002 s remaining\n", - "subpixel-averaging is 23.8685% done, 13.1996 s remaining\n", - "subpixel-averaging is 27.2785% done, 11.4347 s remaining\n", - "subpixel-averaging is 30.6884% done, 9.76244 s remaining\n", - "subpixel-averaging is 34.0983% done, 8.23291 s remaining\n", - "subpixel-averaging is 37.5082% done, 7.1923 s remaining\n", - "subpixel-averaging is 65.64% done, 2.28558 s remaining\n", - "subpixel-averaging is 69.0499% done, 1.93198 s remaining\n", - "subpixel-averaging is 72.4598% done, 1.63656 s remaining\n", - "subpixel-averaging is 75.8697% done, 1.36626 s remaining\n", - "subpixel-averaging is 79.2797% done, 1.08377 s remaining\n", - "subpixel-averaging is 82.6896% done, 0.8822 s remaining\n", - "subpixel-averaging is 86.0995% done, 0.711633 s remaining\n", - "subpixel-averaging is 89.5094% done, 0.493514 s remaining\n", - "subpixel-averaging is 92.9193% done, 0.328464 s remaining\n", - "subpixel-averaging is 98.8867% done, 0.0470705 s remaining\n", - "subpixel-averaging is 6.81898% done, 58.5464 s remaining\n", - "subpixel-averaging is 10.2289% done, 38.1292 s remaining\n", - "subpixel-averaging is 13.6388% done, 26.9734 s remaining\n", - "subpixel-averaging is 17.0487% done, 21.2453 s remaining\n", - "subpixel-averaging is 20.4586% done, 16.6093 s remaining\n", - "subpixel-averaging is 23.8685% done, 13.2456 s remaining\n", - "subpixel-averaging is 27.2785% done, 11.379 s remaining\n", - "subpixel-averaging is 30.6884% done, 9.74246 s remaining\n", - "subpixel-averaging is 34.0983% done, 8.25901 s remaining\n", - "subpixel-averaging is 37.5082% done, 7.07729 s remaining\n", - "subpixel-averaging is 65.64% done, 2.23432 s remaining\n", - "subpixel-averaging is 69.0499% done, 1.91417 s remaining\n", - "subpixel-averaging is 72.4598% done, 1.63028 s remaining\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "subpixel-averaging is 75.8697% done, 1.34979 s remaining\n", - "subpixel-averaging is 79.2797% done, 1.08361 s remaining\n", - "subpixel-averaging is 82.6896% done, 0.888317 s remaining\n", - "subpixel-averaging is 86.0995% done, 0.711677 s remaining\n", - "subpixel-averaging is 89.5094% done, 0.492528 s remaining\n", - "subpixel-averaging is 92.9193% done, 0.332357 s remaining\n", - "subpixel-averaging is 98.8867% done, 0.0488405 s remaining\n", - "time for set_epsilon = 271.364 s\n", - "-----------\n", - "MPB solved for frequency_1(2.2349,0,0) = 0.687243 after 9 iters\n", - "MPB solved for frequency_1(2.08451,0,0) = 0.64527 after 4 iters\n", - "MPB solved for frequency_1(2.08412,0,0) = 0.645161 after 4 iters\n", - "MPB solved for frequency_1(2.08412,0,0) = 0.645161 after 1 iters\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "19ca7d2433564cacb893306433113d88", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "FloatProgress(value=0.0, description='0% done ', max=400.0)" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Meep progress: 44.980000000000004/400.0 = 11.2% done in 4.0s, 31.6s to go\n", - "on time step 2255 (time=45.1), 0.00177414 s/step\n", - "Meep progress: 94.72/400.0 = 23.7% done in 8.0s, 25.8s to go\n", - "on time step 4743 (time=94.86), 0.00160783 s/step\n", - "Meep progress: 144.34/400.0 = 36.1% done in 12.0s, 21.3s to go\n", - "on time step 7224 (time=144.48), 0.00161273 s/step\n", - "Meep progress: 194.36/400.0 = 48.6% done in 16.0s, 16.9s to go\n", - "on time step 9725 (time=194.5), 0.00159943 s/step\n", - "Meep progress: 243.5/400.0 = 60.9% done in 20.0s, 12.9s to go\n", - "on time step 12184 (time=243.68), 0.00162705 s/step\n", - "Meep progress: 293.78000000000003/400.0 = 73.4% done in 24.0s, 8.7s to go\n", - "on time step 14699 (time=293.98), 0.00159097 s/step\n", - "Meep progress: 343.84000000000003/400.0 = 86.0% done in 28.0s, 4.6s to go\n", - "on time step 17201 (time=344.02), 0.00159902 s/step\n", - "Meep progress: 393.40000000000003/400.0 = 98.4% done in 32.0s, 0.5s to go\n", - "on time step 19681 (time=393.62), 0.00161343 s/step\n", - "run 0 finished at t = 400.0 (20000 timesteps)\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "sim.reset_meep()\n", - "\n", - "sources = [\n", - " mp.EigenModeSource(\n", - " src=mp.ContinuousSource(fcen, fwidth=df),\n", - " size=src_vol.size,\n", - " center=src_vol.center,\n", - " eig_band=1,\n", - " eig_parity=mp.EVEN_Y + mp.ODD_Z,\n", - " eig_match_freq=True,\n", - " )\n", - "]\n", - "\n", - "sim = mp.Simulation(\n", - " resolution=res,\n", - " cell_size=cell.size,\n", - " boundary_layers=[mp.PML(dpml)],\n", - " sources=sources,\n", - " geometry=geometry,\n", - ")\n", - "\n", - "sim.run(\n", - " until=400\n", - ") # arbitrary long run time to ensure that fields have reached steady state\n", - "\n", - "eps_data = sim.get_epsilon()\n", - "ez_data = numpy.real(sim.get_efield_z())\n", - "\n", - "plt.figure(dpi=200)\n", - "plt.imshow(numpy.transpose(eps_data), interpolation=\"spline36\", cmap=\"binary\")\n", - "plt.imshow(\n", - " numpy.flipud(numpy.transpose(ez_data)),\n", - " interpolation=\"spline36\",\n", - " cmap=\"RdBu\",\n", - " alpha=0.9,\n", - ")\n", - "plt.axis(\"off\")\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](https://meep.readthedocs.io/en/latest/images/directional_coupler_field_profiles.png)\n", - "\n", - "The field profiles confirm that for `d` of 0.06 μm (Figure 1), the input signal in Port 1 of the top branch is almost completely transferred to Port 4 of the bottom branch. For `d` of 0.13 μm (Figure 2), the input signal is split evenly between the two branches. Finally, for `d` of 0.30 μm (Figure 3), there is no longer any evanescent coupling and the signal remains completely in the top branch. Note the absence of the fields in the PML regions of Ports 3 and 4." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/python/examples/coupler.py b/python/examples/coupler.py index 56b321a1f..e2ed7859e 100644 --- a/python/examples/coupler.py +++ b/python/examples/coupler.py @@ -1,8 +1,10 @@ import argparse +import gdstk import meep as mp -gdsII_file = "coupler.gds" + +gds_file = "coupler.gds" CELL_LAYER = 0 PORT1_LAYER = 1 PORT2_LAYER = 2 @@ -27,6 +29,40 @@ df = 0.2 * fcen +def get_gds_cell(fname): + """Returns the (single) top-level cell of the GDS file `fname`.""" + return gdstk.read_gds(fname).top_level()[0] + + +def get_gds_prisms(material, cell, layer, datatype=0, zmin=0.0, zmax=0.0): + """Returns a list of `mp.Prism`s, one for each polygon on (`layer`, `datatype`).""" + prisms = [] + for poly in cell.get_polygons(layer=layer, datatype=datatype): + vertices = [mp.Vector3(x, y, zmin) for x, y in poly.points] + prisms.append( + mp.Prism( + vertices, + height=zmax - zmin, + axis=mp.Vector3(0, 0, 1), + material=material, + ) + ) + return prisms + + +def get_gds_vol(cell, layer, datatype=0, zmin=0.0, zmax=0.0): + """Returns an `mp.Volume` spanning the bounding box of (`layer`, `datatype`).""" + polygons = cell.get_polygons(layer=layer, datatype=datatype) + xs = [x for poly in polygons for x, y in poly.points] + ys = [y for poly in polygons for x, y in poly.points] + xmin, xmax = min(xs), max(xs) + ymin, ymax = min(ys), max(ys) + center = mp.Vector3(0.5 * (xmin + xmax), 0.5 * (ymin + ymax), 0.5 * (zmin + zmax)) + size = mp.Vector3(xmax - xmin, ymax - ymin, zmax - zmin) + dims = 2 if (zmin == 0 and zmax == 0) else 3 + return mp.Volume(center=center, size=size, dims=dims) + + def main(args): cell_zmax = 0.5 * cell_thickness if args.three_d else 0 cell_zmin = -0.5 * cell_thickness if args.three_d else 0 @@ -34,20 +70,22 @@ def main(args): si_zmin = -0.5 * t_Si if args.three_d else -10 # read cell size, volumes for source region and flux monitors, - # and coupler geometry from GDSII file - upper_branch = mp.get_GDSII_prisms( - silicon, gdsII_file, UPPER_BRANCH_LAYER, si_zmin, si_zmax + # and coupler geometry from the GDS file using gdstk + gds_cell = get_gds_cell(gds_file) + + upper_branch = get_gds_prisms( + silicon, gds_cell, UPPER_BRANCH_LAYER, zmin=si_zmin, zmax=si_zmax ) - lower_branch = mp.get_GDSII_prisms( - silicon, gdsII_file, LOWER_BRANCH_LAYER, si_zmin, si_zmax + lower_branch = get_gds_prisms( + silicon, gds_cell, LOWER_BRANCH_LAYER, zmin=si_zmin, zmax=si_zmax ) - cell = mp.GDSII_vol(gdsII_file, CELL_LAYER, cell_zmin, cell_zmax) - p1 = mp.GDSII_vol(gdsII_file, PORT1_LAYER, si_zmin, si_zmax) - p2 = mp.GDSII_vol(gdsII_file, PORT2_LAYER, si_zmin, si_zmax) - p3 = mp.GDSII_vol(gdsII_file, PORT3_LAYER, si_zmin, si_zmax) - p4 = mp.GDSII_vol(gdsII_file, PORT4_LAYER, si_zmin, si_zmax) - src_vol = mp.GDSII_vol(gdsII_file, SOURCE_LAYER, si_zmin, si_zmax) + cell = get_gds_vol(gds_cell, CELL_LAYER, zmin=cell_zmin, zmax=cell_zmax) + p1 = get_gds_vol(gds_cell, PORT1_LAYER, zmin=si_zmin, zmax=si_zmax) + p2 = get_gds_vol(gds_cell, PORT2_LAYER, zmin=si_zmin, zmax=si_zmax) + p3 = get_gds_vol(gds_cell, PORT3_LAYER, zmin=si_zmin, zmax=si_zmax) + p4 = get_gds_vol(gds_cell, PORT4_LAYER, zmin=si_zmin, zmax=si_zmax) + src_vol = get_gds_vol(gds_cell, SOURCE_LAYER, zmin=si_zmin, zmax=si_zmax) # displace upper and lower branches of coupler (as well as source and flux regions) if args.d != default_d: @@ -118,11 +156,7 @@ def main(args): p3_trans = abs(p3_coeff) ** 2 / abs(p1_coeff) ** 2 p4_trans = abs(p4_coeff) ** 2 / abs(p1_coeff) ** 2 - print( - "trans:, {:.2f}, {:.6f}, {:.6f}, {:.6f}".format( - args.d, p2_trans, p3_trans, p4_trans - ) - ) + print(f"trans:, {args.d:.2f}, {p2_trans:.6f}, {p3_trans:.6f}, {p4_trans:.6f}") if __name__ == "__main__": @@ -137,7 +171,7 @@ def main(args): "--three_d", action="store_true", default=False, - help="3d calculation? (default: False)", + help="d calculation? (default: False)", ) args = parser.parse_args() main(args) diff --git a/python/examples/ring_gds.py b/python/examples/ring_gds.py index 6da93fe4d..63c5d8325 100644 --- a/python/examples/ring_gds.py +++ b/python/examples/ring_gds.py @@ -1,10 +1,7 @@ -import importlib - -import gdspy -import numpy as np +import gdstk from matplotlib import pyplot as plt - import meep as mp +import numpy as np # core and cladding materials Si = mp.Medium(index=3.4) @@ -23,69 +20,109 @@ zmax = 0 # maximum z value of simulation domain (0 for 2D) -def create_ring_gds(radius, width): - # Reload the library each time to prevent gds library name clashes - importlib.reload(gdspy) +def get_gds_cell(fname): + """Returns the (single) top-level cell of the GDS file `fname`.""" + return gdstk.read_gds(fname).top_level()[0] + + +def get_gds_prisms(material, cell, layer, datatype=0, zmin=0.0, zmax=0.0): + """Returns a list of `mp.Prism`s, one for each polygon on (`layer`, `datatype`).""" + prisms = [] + for poly in cell.get_polygons(layer=layer, datatype=datatype): + vertices = [mp.Vector3(x, y, zmin) for x, y in poly.points] + prisms.append( + mp.Prism( + vertices, + height=zmax - zmin, + axis=mp.Vector3(0, 0, 1), + material=material, + ) + ) + return prisms + - ringCell = gdspy.Cell(f"ring_resonator_r{radius}_w{width}") +def get_gds_vol(cell, layer, datatype=0, zmin=0.0, zmax=0.0): + """Returns an `mp.Volume` spanning the bounding box of (`layer`, `datatype`).""" + polygons = cell.get_polygons(layer=layer, datatype=datatype) + xs = [x for poly in polygons for x, y in poly.points] + ys = [y for poly in polygons for x, y in poly.points] + xmin, xmax = min(xs), max(xs) + ymin, ymax = min(ys), max(ys) + center = mp.Vector3(0.5 * (xmin + xmax), 0.5 * (ymin + ymax), 0.5 * (zmin + zmax)) + size = mp.Vector3(xmax - xmin, ymax - ymin, zmax - zmin) + dims = 2 if (zmin == 0 and zmax == 0) else 3 + return mp.Volume(center=center, size=size, dims=dims) + + +def create_ring_gds(radius, width): + lib = gdstk.Library() + ring_cell = lib.new_cell(f"ring_resonator_r{radius}_w{width}") # Draw the ring - ringCell.add( - gdspy.Round( + ring_cell.add( + gdstk.ellipse( (0, 0), + radius + width / 2, inner_radius=radius - width / 2, - radius=radius + width / 2, layer=RING_LAYER, ) ) # Draw the first source - ringCell.add( - gdspy.Rectangle((radius - width, 0), (radius + width, 0), SOURCE0_LAYER) + ring_cell.add( + gdstk.rectangle((radius - width, 0), (radius + width, 0), layer=SOURCE0_LAYER) ) # Draw the second source - ringCell.add( - gdspy.Rectangle((-radius - width, 0), (-radius + width, 0), SOURCE1_LAYER) + ring_cell.add( + gdstk.rectangle((-radius - width, 0), (-radius + width, 0), layer=SOURCE1_LAYER) ) # Draw the monitor location - ringCell.add( - gdspy.Rectangle((radius - width / 2, 0), (radius + width / 2, 0), MONITOR_LAYER) + ring_cell.add( + gdstk.rectangle( + (radius - width / 2, 0), (radius + width / 2, 0), layer=MONITOR_LAYER + ) ) # Draw the simulation domain pad = 2 # padding between waveguide and edge of PML - ringCell.add( - gdspy.Rectangle( + ring_cell.add( + gdstk.rectangle( (-radius - width / 2 - pad, -radius - width / 2 - pad), (radius + width / 2 + pad, radius + width / 2 + pad), - SIMULATION_LAYER, + layer=SIMULATION_LAYER, ) ) filename = f"ring_r{radius}_w{width}.gds" - gdspy.write_gds(filename, unit=1.0e-6, precision=1.0e-9) + lib.write_gds(filename) return filename def find_modes(filename, wvl=1.55, bw=0.05): - # Read in the ring structure - geometry = mp.get_GDSII_prisms(Si, filename, RING_LAYER, -100, 100) + # Read in the ring structure using gdstk + gds_cell = get_gds_cell(filename) + + geometry = get_gds_prisms(Si, gds_cell, RING_LAYER, zmin=-100, zmax=100) - cell = mp.GDSII_vol(filename, SIMULATION_LAYER, zmin, zmax) + cell = get_gds_vol(gds_cell, SIMULATION_LAYER, zmin=zmin, zmax=zmax) - src_vol0 = mp.GDSII_vol(filename, SOURCE0_LAYER, zmin, zmax) - src_vol1 = mp.GDSII_vol(filename, SOURCE1_LAYER, zmin, zmax) + src_vol0 = get_gds_vol(gds_cell, SOURCE0_LAYER, zmin=zmin, zmax=zmax) + src_vol1 = get_gds_vol(gds_cell, SOURCE1_LAYER, zmin=zmin, zmax=zmax) - mon_vol = mp.GDSII_vol(filename, MONITOR_LAYER, zmin, zmax) + mon_vol = get_gds_vol(gds_cell, MONITOR_LAYER, zmin=zmin, zmax=zmax) fcen = 1 / wvl df = bw * fcen src = [ - mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Hz, volume=src_vol0), + mp.Source( + mp.GaussianSource(fcen, fwidth=df), + component=mp.Hz, + volume=src_vol0, + ), mp.Source( mp.GaussianSource(fcen, fwidth=df), component=mp.Hz, @@ -107,9 +144,9 @@ def find_modes(filename, wvl=1.55, bw=0.05): sim.run(mp.after_sources(h), until_after_sources=100) - plt.figure() - sim.plot2D(fields=mp.Hz, eps_parameters={"contour": True}) - plt.savefig("ring_fields.png", bbox_inches="tight", dpi=150) + fig, ax = plt.subplots() + sim.plot2D(ax=ax, fields=mp.Hz, eps_parameters={"contour": True}) + fig.savefig("ring_fields.png", bbox_inches="tight", dpi=150) wvl = np.array([1 / m.freq for m in h.modes]) Q = np.array([m.Q for m in h.modes]) diff --git a/python/meep.i b/python/meep.i index 47fa6df8b..64a8e5756 100644 --- a/python/meep.i +++ b/python/meep.i @@ -1692,9 +1692,6 @@ PyObject *_get_array_slice_dimensions(meep::fields *f, const meep::volume &where dft_ldos, display_progress, during_sources, - GDSII_layers, - GDSII_prisms, - GDSII_vol, get_center_and_size, get_eigenmode_freqs, get_electric_energy, diff --git a/python/simulation.py b/python/simulation.py index 918783f78..968115bef 100644 --- a/python/simulation.py +++ b/python/simulation.py @@ -6294,51 +6294,6 @@ def get_center_and_size(vol): return center, size -def GDSII_layers(fname): - """ - Returns a list of integer-valued layer indices for the layers present in - the specified GDSII file. - - ```python - mp.GDSII_layers('python/examples/coupler.gds') - Out[2]: [0, 1, 2, 3, 4, 5, 31, 32] - ``` - """ - return list(mp.get_GDSII_layers(fname)) - - -def GDSII_vol(fname, layer, zmin, zmax): - """ - Returns a `mp.Volume` read from a GDSII file `fname` on layer number `layer` with - `zmin` and `zmax` (default 0). This function is useful for creating a `FluxRegion` - from a GDSII file as follows: - - ```python - fr = mp.FluxRegion(volume=mp.GDSII_vol(fname, layer, zmin, zmax)) - ``` - """ - meep_vol = mp.get_GDSII_volume(fname, layer, zmin, zmax) - dims = meep_vol.dim + 1 - is_cyl = False - - if dims == 4: - # cylindrical - dims = 2 - is_cyl = True - - center, size = get_center_and_size(meep_vol) - - return Volume(center, size, dims, is_cyl) - - -def GDSII_prisms(material, fname, layer=-1, zmin=0.0, zmax=0.0): - """ - Returns a list of `GeometricObject`s with `material` (`mp.Medium`) on layer number - `layer` of a GDSII file `fname` with `zmin` and `zmax` (default 0). - """ - return mp.get_GDSII_prisms(material, fname, layer, zmin, zmax) - - def complexarray(re, im): z = im * 1j z += re diff --git a/python/tests/data/bend-flux.gds b/python/tests/data/bend-flux.gds deleted file mode 100644 index aaf37964d..000000000 Binary files a/python/tests/data/bend-flux.gds and /dev/null differ diff --git a/python/tests/data/spiral.gds b/python/tests/data/spiral.gds deleted file mode 100644 index ea30f7377..000000000 Binary files a/python/tests/data/spiral.gds and /dev/null differ diff --git a/python/tests/test_bend_flux.py b/python/tests/test_bend_flux.py index f4e619cbb..a598e486b 100644 --- a/python/tests/test_bend_flux.py +++ b/python/tests/test_bend_flux.py @@ -1,4 +1,3 @@ -import os import unittest import numpy as np @@ -9,7 +8,7 @@ class TestBendFlux(ApproxComparisonTestCase): - def init(self, no_bend=False, gdsii=False): + def init(self, no_bend=False): sx = 16 sy = 32 cell = mp.Vector3(sx, sy, 0) @@ -18,29 +17,18 @@ def init(self, no_bend=False, gdsii=False): wvg_ycen = -0.5 * (sy - w - (2 * pad)) wvg_xcen = 0.5 * (sx - w - (2 * pad)) height = mp.inf - data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) - gdsii_file = os.path.join(data_dir, "bend-flux.gds") if no_bend: - if gdsii: - geometry = mp.get_GDSII_prisms( - mp.Medium(epsilon=12), gdsii_file, 1, 0, height - ) - else: - no_bend_vertices = [ - mp.Vector3(-0.5 * sx - 5, wvg_ycen - 0.5 * w), - mp.Vector3(+0.5 * sx + 5, wvg_ycen - 0.5 * w), - mp.Vector3(+0.5 * sx + 5, wvg_ycen + 0.5 * w), - mp.Vector3(-0.5 * sx - 5, wvg_ycen + 0.5 * w), - ] - - geometry = [ - mp.Prism(no_bend_vertices, height, material=mp.Medium(epsilon=12)) - ] - elif gdsii: - geometry = mp.get_GDSII_prisms( - mp.Medium(epsilon=12), gdsii_file, 2, 0, height - ) + no_bend_vertices = [ + mp.Vector3(-0.5 * sx - 5, wvg_ycen - 0.5 * w), + mp.Vector3(+0.5 * sx + 5, wvg_ycen - 0.5 * w), + mp.Vector3(+0.5 * sx + 5, wvg_ycen + 0.5 * w), + mp.Vector3(-0.5 * sx - 5, wvg_ycen + 0.5 * w), + ] + + geometry = [ + mp.Prism(no_bend_vertices, height, material=mp.Medium(epsilon=12)) + ] else: bend_vertices = [ mp.Vector3(-0.5 * sx, wvg_ycen - 0.5 * w), @@ -109,9 +97,9 @@ def init(self, no_bend=False, gdsii=False): else: self.pt = mp.Vector3(wvg_xcen, (sy / 2) - 1.5) - def run_bend_flux(self, from_gdsii_file): + def run_bend_flux(self): # Normalization run - self.init(no_bend=True, gdsii=from_gdsii_file) + self.init(no_bend=True) self.sim.run(until_after_sources=mp.stop_when_energy_decayed(100, 1e-3)) # Save flux data for use in real run below fdata = self.sim.get_flux_data(self.refl) @@ -162,7 +150,7 @@ def run_bend_flux(self, from_gdsii_file): # Real run self.sim = None - self.init(gdsii=from_gdsii_file) + self.init() # Load flux data obtained from normalization run self.sim.load_minus_flux_data(self.refl, fdata) self.sim.load_minus_flux_data(self.refl_decimated, fdata_decimated) @@ -216,9 +204,7 @@ def run_bend_flux(self, from_gdsii_file): assert_array_equal(trans_flux_real, np.real(trans_flux_complex)) def test_bend_flux(self): - self.run_bend_flux(False) - if mp.with_libGDSII(): - self.run_bend_flux(True) + self.run_bend_flux() if __name__ == "__main__": diff --git a/python/tests/test_prism.py b/python/tests/test_prism.py index c74fa62fc..42d0a9237 100644 --- a/python/tests/test_prism.py +++ b/python/tests/test_prism.py @@ -134,26 +134,6 @@ def convex_circle(self, npts, r, sym): return abs((prism_eps - cyl_eps) / cyl_eps) - def spiral_gds(self): - data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "data")) - gdsii_file = os.path.join(data_dir, "spiral.gds") - - resolution = 25 - cell_size = mp.Vector3(12, 16) - geometry = mp.get_GDSII_prisms(mp.Medium(index=3.5), gdsii_file, 0, 0, mp.inf) - - sim = mp.Simulation( - cell_size=cell_size, geometry=geometry, resolution=resolution - ) - - sim.init_sim() - - prism_eps = sim.integrate_field_function([mp.Dielectric], lambda r, eps: eps) - - print(f"epsilon-sum:, {abs(prism_eps)} (prism-gds)") - - return prism_eps - # lots of tests, turned off by default since they run too long; # rename to test_something to run these tests. def bigtest_prism(self): @@ -238,12 +218,6 @@ def bigtest_prism(self): self.assertAlmostEqual(d_nosym[1], d_sym[1], places=3) self.assertAlmostEqual(d_nosym[2], d_sym[2], places=3) - if mp.with_libGDSII(): - print("Testing Non-Convex Prism from GDSII file...") - d = self.spiral_gds() - d_ref = 455.01744881372224 - self.assertAlmostEqual(d, d_ref, places=5) - def test_prism(self): print("Testing Non-Convex Prism #3 using marching squares algorithm...") d3_a = self.nonconvex_marching_squares(3, 164) diff --git a/src/GDSIIgeom.cpp b/src/GDSIIgeom.cpp deleted file mode 100644 index acd216545..000000000 --- a/src/GDSIIgeom.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/* Copyright (C) 2005-2026 Massachusetts Institute of Technology -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2, or (at your option) -% any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. % -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software Foundation, -% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -/***************************************************************/ -/* GDSII.cpp -- libmeepgeom code to support meep geometry */ -/* -- definitions from GDSII files */ -/* homer reid -- 5/2018 */ -/***************************************************************/ - -#include -#include -#include "meepgeom.hpp" - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_LIBGDSII -#include -#endif - -namespace meep_geom { - -#ifdef HAVE_LIBGDSII - -bool with_libGDSII() { return true; } - -void get_polygon_bounding_box(dVec vertex_coordinates, meep::vec &max_corner, - meep::vec &min_corner) { - double xmax = vertex_coordinates[2 * 0 + 0], xmin = xmax; - double ymax = vertex_coordinates[2 * 0 + 1], ymin = ymax; - for (size_t nv = 0; nv < vertex_coordinates.size() / 2; nv++) { - double x = vertex_coordinates[2 * nv + 0], y = vertex_coordinates[2 * nv + 1]; - xmax = fmax(xmax, x); - ymax = fmax(ymax, y); - xmin = fmin(xmin, x); - ymin = fmin(ymin, y); - } - max_corner.set_direction(meep::X, xmax); - max_corner.set_direction(meep::Y, ymax); - min_corner.set_direction(meep::X, xmin); - min_corner.set_direction(meep::Y, ymin); -} - -void get_polygon_center_size(dVec vertex_coordinates, meep::vec ¢er, meep::vec &size) { - meep::vec max_corner, min_corner; - get_polygon_bounding_box(vertex_coordinates, max_corner, min_corner); - - center.set_direction(meep::X, - 0.5 * (max_corner.in_direction(meep::X) + min_corner.in_direction(meep::X))); - center.set_direction(meep::Y, - 0.5 * (max_corner.in_direction(meep::Y) + min_corner.in_direction(meep::Y))); - center.set_direction(meep::Z, 0.0); - - size.set_direction(meep::X, max_corner.in_direction(meep::X) - min_corner.in_direction(meep::X)); - size.set_direction(meep::Y, max_corner.in_direction(meep::Y) - min_corner.in_direction(meep::Y)); - size.set_direction(meep::Z, 0.0); -} - -/*******************************************************************/ -// Search the geometry for a polygon on a given layer containing */ -// (the reference point of) a given text label. */ -// If Text==NULL, find any polygon on the given layer. */ -// If Layer==-1, search all layers. */ -// If multiple matching polygons are found, choose one arbitrarily.*/ -/*******************************************************************/ -dVec get_polygon(const char *GDSIIFile, const char *Text, int Layer = -1) { - PolygonList polygons = libGDSII::GetPolygons(GDSIIFile, Text, Layer); - - char Description[100]; - if (Text) - snprintf(Description, 100, "with label %s", Text); - else - snprintf(Description, 100, "on layer %i", Layer); - - if (polygons.size() == 0) meep::abort("%s: found no polygons %s", GDSIIFile, Description); - if (polygons.size() > 1) - fprintf(stderr, "warning: %s: found multiple polygons %s (choosing arbitrarily)\n", GDSIIFile, - Description); - - return polygons[0]; -} - -/*******************************************************************/ -/* find a polygon on the given GDSII layer and set the libctlgeom */ -/* geometry to the size of its bounding box. */ -/* if Text is non-null, only polygons containing the reference */ -/* point of a GDSII text element with content Text will be */ -/* considered. */ -/*******************************************************************/ -meep::grid_volume set_geometry_from_GDSII(double resolution, const char *GDSIIFile, - const char *Text, int Layer, double zsize) { - dVec polygon = get_polygon(GDSIIFile, Text, Layer); - - meep::vec center, size; - get_polygon_center_size(polygon, center, size); - - geometry_lattice.size.x = size.in_direction(meep::X); - geometry_lattice.size.y = size.in_direction(meep::Y); - geometry_lattice.size.z = zsize; - meep::grid_volume gv = - zsize == 0.0 - ? meep::vol2d(geometry_lattice.size.x, geometry_lattice.size.y, resolution) - : meep::vol3d(geometry_lattice.size.x, geometry_lattice.size.y, zsize, resolution); - gv.center_origin(); - return gv; -} - -meep::grid_volume set_geometry_from_GDSII(double resolution, const char *GDSIIFile, int Layer, - double zsize) { - return set_geometry_from_GDSII(resolution, GDSIIFile, 0, Layer, zsize); -} - -/*******************************************************************/ -/* find all polygons on a given GDSII layer and return a list of */ -/* geometric_objects describing prisms, all with the same material */ -/* and thickness. */ -/*******************************************************************/ -geometric_object_list get_GDSII_prisms(material_type material, const char *GDSIIFile, int Layer, - double zmin, double zmax) { - geometric_object_list prisms = {0, 0}; - - // fetch all polygons on the given GDSII layer - PolygonList polygons = libGDSII::GetPolygons(GDSIIFile, Layer); - int num_prisms = polygons.size(); - if (num_prisms == 0) return prisms; // no polygons found; TODO: print warning? - - // create a prism for each polygon in the list - prisms.num_items = num_prisms; - prisms.items = new geometric_object[num_prisms]; - for (int np = 0; np < num_prisms; np++) { - dVec polygon = polygons[np]; - int num_vertices = polygon.size() / 2; - std::unique_ptr vertices(new vector3[num_vertices]); - for (int nv = 0; nv < num_vertices; nv++) { - vertices[nv].x = polygon[2 * nv + 0]; - vertices[nv].y = polygon[2 * nv + 1]; - vertices[nv].z = zmin; - } - double height = zmax - zmin; - vector3 zaxis = {0, 0, 1}; - prisms.items[np] = make_prism(material, vertices.get(), num_vertices, height, zaxis); - } - return prisms; -} - -/*******************************************************************/ -/* like the previous routine, but creates only a single prism, */ -/* optionally identified by Text; if non-null, only polygons */ -/* containing the reference point of a GDSII text string with */ -/* content Text will be considered. if there are still multiple */ -/* choices of polygon, one will be chosen arbitrarily. */ -/*******************************************************************/ -geometric_object get_GDSII_prism(material_type material, const char *GDSIIFile, const char *Text, - int Layer, double zmin, double zmax) { - dVec polygon = get_polygon(GDSIIFile, Text, Layer); - - int num_vertices = polygon.size() / 2; - std::unique_ptr vertices(new vector3[num_vertices]); - for (int nv = 0; nv < num_vertices; nv++) { - vertices[nv].x = polygon[2 * nv + 0]; - vertices[nv].y = polygon[2 * nv + 1]; - vertices[nv].z = zmin; - } - - double height = zmax - zmin; - vector3 zaxis = {0, 0, 1}; - return make_prism(material, vertices.get(), num_vertices, height, zaxis); -} - -geometric_object get_GDSII_prism(material_type material, const char *GDSIIFile, int Layer, - double zmin, double zmax) { - return get_GDSII_prism(material, GDSIIFile, 0, Layer, zmin, zmax); -} - -/*******************************************************************/ -/* create a meep::volume from a GDSII polygon and optional z-size; */ -/* useful for defining flux regions, source volumes ,etc. */ -/*******************************************************************/ -meep::volume get_GDSII_volume(const char *GDSIIFile, const char *Text, int Layer, double zmin, - double zmax) { - dVec polygon = get_polygon(GDSIIFile, Text, Layer); - meep::ndim di = ((((float)zmin) == 0.0 && ((float)zmax) == 0.0) ? meep::D2 : meep::D3); - meep::vec max_corner = meep::zero_vec(di), min_corner = meep::zero_vec(di); - get_polygon_bounding_box(polygon, max_corner, min_corner); - max_corner.set_direction(meep::Z, zmax); - min_corner.set_direction(meep::Z, zmin); - return meep::volume(max_corner, min_corner); -} - -meep::volume get_GDSII_volume(const char *GDSIIFile, int Layer, double zmin, double zmax) { - return get_GDSII_volume(GDSIIFile, 0, Layer, zmin, zmax); -} - -/***************************************************************/ -/* stubs for compilation without libGDSII **********************/ -/***************************************************************/ -#else // HAVE_LIBGDSII - -bool with_libGDSII() { return false; } - -void GDSIIError(const char *Routine) { - meep::abort("Meep must be configured/compiled with libGDSII for %s", Routine); -} - -meep::grid_volume set_geometry_from_GDSII(double resolution, const char *GDSIIFile, - const char *Text, int Layer, double zsize) { - (void)resolution; - (void)GDSIIFile; - (void)Text; - (void)Layer; - (void)zsize; - GDSIIError("set_geometry_from_GDSII"); - return meep::grid_volume(); -} -meep::grid_volume set_geometry_from_GDSII(double resolution, const char *GDSIIFile, int Layer, - double zsize) { - (void)resolution; - (void)GDSIIFile; - (void)Layer; - (void)zsize; - GDSIIError("set_geometry_from_GDSII"); - return meep::grid_volume(); -} - -geometric_object_list get_GDSII_prisms(material_type material, const char *GDSIIFile, int Layer, - double zmin, double zmax) { - (void)material; - (void)GDSIIFile; - (void)Layer; - (void)zmin; - (void)zmax; - GDSIIError("get_GDSII_prisms"); - geometric_object_list prisms = {0, 0}; - return prisms; -} - -geometric_object get_GDSII_prism(material_type material, const char *GDSIIFile, const char *Text, - int Layer, double zmin, double zmax) { - (void)material; - (void)GDSIIFile; - (void)Text; - (void)Layer; - (void)zmin; - (void)zmax; - GDSIIError("get_GDSII_prism"); - vector3 center = {0.0, 0.0, 0.0}; - return make_sphere(0, center, 0.0); -} -geometric_object get_GDSII_prism(material_type material, const char *GDSIIFile, int Layer, - double zmin, double zmax) { - (void)material; - (void)GDSIIFile; - (void)Layer; - (void)zmin; - (void)zmax; - GDSIIError("get_GDSII_prism"); - vector3 center = {0.0, 0.0, 0.0}; - return make_sphere(0, center, 0.0); -} -meep::volume get_GDSII_volume(const char *GDSIIFile, const char *Text, int Layer, double zmin, - double zmax) { - (void)GDSIIFile; - (void)Text; - (void)Layer; - (void)zmin; - (void)zmax; - GDSIIError("get_GDSII_volume"); - return meep::volume(meep::vec()); -} -meep::volume get_GDSII_volume(const char *GDSIIFile, int Layer, double zmin, double zmax) { - (void)GDSIIFile; - (void)Layer; - (void)zmin; - (void)zmax; - GDSIIError("get_GDSII_volume"); - return meep::volume(meep::vec()); -} - -#endif // HAVE_LIBGDSII - -std::vector get_GDSII_layers(const char *GDSIIFile) { -#if defined(HAVE_LIBGDSII) && defined(HAVE_GDSII_GETLAYERS) - return libGDSII::GetLayers(GDSIIFile); -#else - (void)GDSIIFile; - meep::abort( - "get_GDSII_layers needs Meep to be configured/compiled with libGDSII version 0.21 or later"); - std::vector layers; - return layers; -#endif -} - -} // namespace meep_geom diff --git a/src/Makefile.am b/src/Makefile.am index 8b545b333..3dd179b64 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,7 +17,7 @@ initialize.cpp integrate.cpp integrate2.cpp material_data.cpp monitor.cpp mympi. multilevel-atom.cpp near2far.cpp output_directory.cpp random.cpp \ sources.cpp step.cpp step_db.cpp stress.cpp structure.cpp structure_dump.cpp \ susceptibility.cpp time.cpp update_eh.cpp mpb.cpp update_pols.cpp \ -vec.cpp step_generic.cpp meepgeom.cpp GDSIIgeom.cpp $(HDRS) $(BUILT_SOURCES) +vec.cpp step_generic.cpp meepgeom.cpp $(HDRS) $(BUILT_SOURCES) SUBDIRS = support libmeep_la_LIBADD = support/libsupport.la diff --git a/src/meepgeom.hpp b/src/meepgeom.hpp index b2a0d3e5b..9b43167e8 100644 --- a/src/meepgeom.hpp +++ b/src/meepgeom.hpp @@ -300,26 +300,6 @@ void material_grids_addgradient(double *v, size_t ng, size_t nf, double scalegrad, meep::grid_volume &gv, geom_epsilon *geps, double du = 1e-6); -/***************************************************************/ -/* routines in GDSIIgeom.cc ************************************/ -/***************************************************************/ -bool with_libGDSII(); -meep::grid_volume set_geometry_from_GDSII(double resolution, const char *GDSIIFile, - const char *Text, int Layer = -1, double zsize = 0.0); -meep::grid_volume set_geometry_from_GDSII(double resolution, const char *GDSIIFile, int Layer, - double zsize = 0.0); -geometric_object_list get_GDSII_prisms(material_type material, const char *GDSIIFile, - int Layer = -1, double zmin = 0.0, double zmax = 0.0); -geometric_object get_GDSII_prism(material_type material, const char *GDSIIFile, const char *Text, - int Layer = -1, double zmin = 0.0, double zmax = 0.0); -geometric_object get_GDSII_prism(material_type material, const char *GDSIIFile, int Layer, - double zmin = 0.0, double zmax = 0.0); -meep::volume get_GDSII_volume(const char *GDSIIFile, const char *Text, int Layer = -1, - double zmin = 0.0, double zmax = 0.0); -meep::volume get_GDSII_volume(const char *GDSIIFile, int Layer, double zmin = 0.0, - double zmax = 0.0); -std::vector get_GDSII_layers(const char *GDSIIFile); - }; // namespace meep_geom #endif // #ifndef MEEP_GEOM_H diff --git a/tests/Makefile.am b/tests/Makefile.am index b4fc789f5..458ebe5ab 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -18,10 +18,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/src -DDATADIR=\"$(srcdir)/\" check_PROGRAMS = aniso_disp bench bragg_transmission convergence_cyl_waveguide cylindrical dump_load flux harmonics integrate known_results near2far one_dimensional physical stress_tensor symmetry three_d two_dimensional 2D_convergence h5test pml pw-source-ll ring-ll cyl-ellipsoid-ll absorber-1d-ll array-slice-ll user-defined-material dft-fields bend-flux-ll array-metadata -if WITH_LIBGDSII - check_PROGRAMS += gdsII-3d -endif - array_metadata_SOURCES = array-metadata.cpp array_metadata_LDADD = $(MEEPLIBS) @@ -103,16 +99,13 @@ array_slice_ll_LDADD = $(MEEPLIBS) dft_fields_SOURCES = dft-fields.cpp dft_fields_LDADD = $(MEEPLIBS) -gdsII_3d_SOURCES = gdsII-3d.cpp -gdsII_3d_LDADD = $(MEEPLIBS) - bend_flux_ll_SOURCES = bend-flux-ll.cpp bend_flux_ll_LDADD = $(MEEPLIBS) user_defined_material_SOURCES = user-defined-material.cpp user_defined_material_LDADD = $(MEEPLIBS) -dist_noinst_DATA = cyl-ellipsoid-eps-ref.h5 array-slice-ll-ref.h5 gdsII-3d.gds +dist_noinst_DATA = cyl-ellipsoid-eps-ref.h5 array-slice-ll-ref.h5 TESTS = aniso_disp bench bragg_transmission convergence_cyl_waveguide cylindrical dump_load flux harmonics integrate known_results near2far one_dimensional physical stress_tensor symmetry three_d two_dimensional 2D_convergence h5test pml diff --git a/tests/bend-flux-ll.cpp b/tests/bend-flux-ll.cpp index 2ecaba34f..9bb9ba46c 100644 --- a/tests/bend-flux-ll.cpp +++ b/tests/bend-flux-ll.cpp @@ -39,42 +39,6 @@ vector3 v3(double x, double y = 0.0, double z = 0.0) { /***************************************************************/ double dummy_eps(const vec &) { return 1.0; } -/***************************************************************/ -/* define geometry from GDSII file *****************************/ -/***************************************************************/ -#define GEOM_LAYER 0 // hard-coded indices of GDSII layers -#define STRAIGHT_WVG_LAYER 1 // on which various geometric entities are defined -#define BENT_WVG_LAYER 2 -#define SOURCE_LAYER 3 -#define RFLUX_LAYER 4 -#define STRAIGHT_TFLUX_LAYER 5 -#define BENT_TFLUX_LAYER 6 - -structure create_structure_from_GDSII(char *GDSIIFile, bool no_bend, volume &vsrc, volume &vrefl, - volume &vtrans) { - // set computational cell - double dpml = 1.0; - double resolution = 10.0; - grid_volume gv = meep_geom::set_geometry_from_GDSII(resolution, GDSIIFile, GEOM_LAYER); - structure the_structure(gv, dummy_eps, pml(dpml)); - - // define waveguide - geometric_object objects[1]; - meep_geom::material_type dielectric = meep_geom::make_dielectric(12.0); - int GDSIILayer = (no_bend ? STRAIGHT_WVG_LAYER : BENT_WVG_LAYER); - objects[0] = meep_geom::get_GDSII_prism(dielectric, GDSIIFile, GDSIILayer); - geometric_object_list g = {1, objects}; - meep_geom::set_materials_from_geometry(&the_structure, g); - - // define volumes for source and flux-monitor regions - vsrc = meep_geom::get_GDSII_volume(GDSIIFile, SOURCE_LAYER); - vrefl = meep_geom::get_GDSII_volume(GDSIIFile, RFLUX_LAYER); - vtrans = - meep_geom::get_GDSII_volume(GDSIIFile, (no_bend ? STRAIGHT_TFLUX_LAYER : BENT_TFLUX_LAYER)); - - return the_structure; -} - /***************************************************************/ /***************************************************************/ /***************************************************************/ @@ -182,12 +146,10 @@ structure create_structure_by_hand(bool no_bend, bool use_prisms, volume &vsrc, /***************************************************************/ /***************************************************************/ /***************************************************************/ -void bend_flux(bool no_bend, char *GDSIIFile, bool use_prisms) { +void bend_flux(bool no_bend, bool use_prisms) { vec v0 = zero_vec(D2); volume vsrc(v0), vrefl(v0), vtrans(v0); - structure the_structure = - GDSIIFile ? create_structure_from_GDSII(GDSIIFile, no_bend, vsrc, vrefl, vtrans) - : create_structure_by_hand(no_bend, use_prisms, vsrc, vrefl, vtrans); + structure the_structure = create_structure_by_hand(no_bend, use_prisms, vsrc, vrefl, vtrans); fields f(&the_structure); @@ -283,17 +245,11 @@ int main(int argc, char *argv[]) { initialize mpi(argc, argv); bool use_prisms = false; - char *GDSIIFile = 0; for (int narg = 1; narg < argc; narg++) if (!strcasecmp(argv[narg], "--use-prisms")) use_prisms = true; - for (int narg = 1; narg < argc - 1; narg++) - if (!strcasecmp(argv[narg], "--GDSIIFile")) GDSIIFile = argv[narg + 1]; - - if (GDSIIFile != 0 && use_prisms == true) - fprintf(stderr, "warning: --use-prisms is ignored if --GDSIIFile is specified\n"); - bend_flux(true, GDSIIFile, use_prisms); - bend_flux(false, GDSIIFile, use_prisms); + bend_flux(true, use_prisms); + bend_flux(false, use_prisms); // success if we made it here return 0; diff --git a/tests/gdsII-3d.cpp b/tests/gdsII-3d.cpp deleted file mode 100644 index c19dda622..000000000 --- a/tests/gdsII-3d.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/***************************************************************/ -/* example of a 3D geometry defined by GDSII file */ -/***************************************************************/ -#include -#include -#include - -#include "meep.hpp" - -#include "ctl-math.h" -#include "ctlgeom.h" - -#include "meepgeom.hpp" - -using namespace meep; - -typedef std::complex cdouble; - -vector3 v3(double x, double y = 0.0, double z = 0.0) { - vector3 v; - v.x = x; - v.y = y; - v.z = z; - return v; -} - -/***************************************************************/ -/* dummy material function needed to pass to structure( ) */ -/* constructor as a placeholder before we can call */ -/* set_materials_from_geometry */ -/***************************************************************/ -double dummy_eps(const vec &) { return 1.0; } - -/***************************************************************/ -/* GDSII layers on which various geometric entities live */ -/***************************************************************/ -#define GEOM_LAYER 0 // computational cell -#define OXIDE_BULK_LAYER 1 // oxide layer (bulk, i.e. oxide region) -#define OXIDE_VIA_LAYER 2 // oxide layer (vias) -#define SILICON_LAYER 3 // hexagon, rectangle -#define SLICE_LAYER 4 // volumes for outputting epsilon slices - -/***************************************************************/ -/* layer thicknesses and materials *****************************/ -/***************************************************************/ -#define OXIDE_ZMIN 0.0 -#define OXIDE_ZMAX 1.0 -#define OXIDE_Z0 0.5 * (OXIDE_ZMIN + OXIDE_ZMAX) -#define OXIDE_EPS 2.2 - -#define SILICON_ZMIN OXIDE_ZMAX -#define SILICON_ZMAX 0.75 -#define SILICON_Z0 0.5 * (SILICON_ZMIN + SILICON_ZMAX) -#define SILICON_EPS 12.0 - -/***************************************************************/ -/***************************************************************/ -/***************************************************************/ -int main(int argc, char *argv[]) { - initialize mpi(argc, argv); - - const char *GDSIIFile = "gdsII-3d.gds"; - - // set computational cell - double dpml = 1.0; - double resolution = 10.0; - grid_volume gv = meep_geom::set_geometry_from_GDSII(resolution, GDSIIFile, GEOM_LAYER); - structure the_structure(gv, dummy_eps, pml(dpml)); - - // oxide layer, part 1: bulk of oxide layer - meep_geom::material_type oxide = meep_geom::make_dielectric(OXIDE_EPS); - geometric_object oxide_bulk_prism = - meep_geom::get_GDSII_prism(oxide, GDSIIFile, OXIDE_BULK_LAYER, OXIDE_ZMIN, OXIDE_ZMAX); - - // oxide layer, part 2: via in oxide layer - geometric_object oxide_via_prism = meep_geom::get_GDSII_prism( - meep_geom::vacuum, GDSIIFile, OXIDE_VIA_LAYER, OXIDE_ZMIN, OXIDE_ZMAX); - - // silicon layer - meep_geom::material_type silicon = meep_geom::make_dielectric(SILICON_EPS); - geometric_object_list silicon_prisms = - meep_geom::get_GDSII_prisms(silicon, GDSIIFile, SILICON_LAYER, SILICON_ZMIN, SILICON_ZMAX); - - // merge all prisms into a single geometric_object_list and instantiate meep geometry - geometric_object_list all_prisms; - all_prisms.num_items = 1 + 1 + silicon_prisms.num_items; - all_prisms.items = new geometric_object[all_prisms.num_items]; - all_prisms.items[0] = oxide_bulk_prism; - all_prisms.items[1] = oxide_via_prism; - for (int n = 0; n < silicon_prisms.num_items; n++) - all_prisms.items[2 + n] = silicon_prisms.items[n]; - meep_geom::set_materials_from_geometry(&the_structure, all_prisms); - fields f(&the_structure); - - // define volumes for source and flux-monitor regions - volume v1 = - meep_geom::get_GDSII_volume(GDSIIFile, "yzplane", SLICE_LAYER, OXIDE_ZMIN, SILICON_ZMAX); - volume v2 = meep_geom::get_GDSII_volume(GDSIIFile, "xyplane", SLICE_LAYER, OXIDE_Z0, OXIDE_Z0); - volume v3 = - meep_geom::get_GDSII_volume(GDSIIFile, "xyplane", SLICE_LAYER, SILICON_Z0, SILICON_Z0); - - f.step(); - f.output_hdf5(Dielectric, v1, 0, false, true, "v1"); - f.output_hdf5(Dielectric, v2, 0, false, true, "v2"); - f.output_hdf5(Dielectric, v3, 0, false, true, "v3"); -} diff --git a/tests/gdsII-3d.gds b/tests/gdsII-3d.gds deleted file mode 100644 index 49a5dd628..000000000 Binary files a/tests/gdsII-3d.gds and /dev/null differ