From 4f6ff70efe042925a9fdc1309341e560e23659a4 Mon Sep 17 00:00:00 2001
From: Homer Reid
Date: Thu, 1 Feb 2018 12:09:45 -0500
Subject: [PATCH 1/3] new clean branch for modeExpansion code
---
doc/docs/ModeExpansion.md | 794 +++++++++
doc/docs/ModeExpansionFiles/FluxVsLP.png | Bin 0 -> 198727 bytes
doc/docs/ModeExpansionFiles/L0.0_p0_f85.png | Bin 0 -> 141686 bytes
doc/docs/ModeExpansionFiles/L0_p0.mpg | Bin 0 -> 368640 bytes
doc/docs/ModeExpansionFiles/L1.0_p0_f85.png | Bin 0 -> 155764 bytes
doc/docs/ModeExpansionFiles/L1_p0.mpg | Bin 0 -> 374784 bytes
doc/docs/ModeExpansionFiles/L2.0_p0_f85.png | Bin 0 -> 112371 bytes
doc/docs/ModeExpansionFiles/L2_p0.mpg | Bin 0 -> 362496 bytes
doc/docs/ModeExpansionFiles/L3.0_p0_f85.png | Bin 0 -> 126952 bytes
doc/docs/ModeExpansionFiles/L3.0_p1_f85.png | Bin 0 -> 127534 bytes
doc/docs/ModeExpansionFiles/L3.0_p2_f85.png | Bin 0 -> 128120 bytes
doc/docs/ModeExpansionFiles/L3_p0.mpg | Bin 0 -> 360448 bytes
doc/docs/ModeExpansionFiles/L3_p1.mpg | Bin 0 -> 360448 bytes
doc/docs/ModeExpansionFiles/L3_p2.mpg | Bin 0 -> 360448 bytes
.../ModeExpansionFiles/ModeProfiles2D.png | Bin 0 -> 258343 bytes
doc/docs/ModeExpansionFiles/Taper2D.svg | 1453 +++++++++++++++++
doc/docs/ModeExpansionFiles/Taper2D_p0.png | Bin 0 -> 362195 bytes
doc/docs/ModeExpansionFiles/Taper2D_p1.png | Bin 0 -> 386333 bytes
doc/docs/ModeExpansionFiles/Taper2D_p2.png | Bin 0 -> 133910 bytes
doc/docs/ModeExpansionFiles/TaperData.png | Bin 0 -> 43097 bytes
doc/docs/ModeExpansionFiles/wvg-taper.cpp | 1 +
doc/docs/ModeExpansionFiles/wvg-taper.py | 363 ++++
libmeepgeom/Makefile.am | 5 +-
libmeepgeom/wvg-taper.cpp | 562 +++++++
src/dft.cpp | 383 +++++
src/meep.hpp | 74 +-
src/mpb.cpp | 514 ++++--
27 files changed, 4053 insertions(+), 96 deletions(-)
create mode 100644 doc/docs/ModeExpansion.md
create mode 100644 doc/docs/ModeExpansionFiles/FluxVsLP.png
create mode 100644 doc/docs/ModeExpansionFiles/L0.0_p0_f85.png
create mode 100644 doc/docs/ModeExpansionFiles/L0_p0.mpg
create mode 100644 doc/docs/ModeExpansionFiles/L1.0_p0_f85.png
create mode 100644 doc/docs/ModeExpansionFiles/L1_p0.mpg
create mode 100644 doc/docs/ModeExpansionFiles/L2.0_p0_f85.png
create mode 100644 doc/docs/ModeExpansionFiles/L2_p0.mpg
create mode 100644 doc/docs/ModeExpansionFiles/L3.0_p0_f85.png
create mode 100644 doc/docs/ModeExpansionFiles/L3.0_p1_f85.png
create mode 100644 doc/docs/ModeExpansionFiles/L3.0_p2_f85.png
create mode 100644 doc/docs/ModeExpansionFiles/L3_p0.mpg
create mode 100644 doc/docs/ModeExpansionFiles/L3_p1.mpg
create mode 100644 doc/docs/ModeExpansionFiles/L3_p2.mpg
create mode 100644 doc/docs/ModeExpansionFiles/ModeProfiles2D.png
create mode 100644 doc/docs/ModeExpansionFiles/Taper2D.svg
create mode 100644 doc/docs/ModeExpansionFiles/Taper2D_p0.png
create mode 100644 doc/docs/ModeExpansionFiles/Taper2D_p1.png
create mode 100644 doc/docs/ModeExpansionFiles/Taper2D_p2.png
create mode 100644 doc/docs/ModeExpansionFiles/TaperData.png
create mode 120000 doc/docs/ModeExpansionFiles/wvg-taper.cpp
create mode 100644 doc/docs/ModeExpansionFiles/wvg-taper.py
create mode 100644 libmeepgeom/wvg-taper.cpp
diff --git a/doc/docs/ModeExpansion.md b/doc/docs/ModeExpansion.md
new file mode 100644
index 000000000..26a568494
--- /dev/null
+++ b/doc/docs/ModeExpansion.md
@@ -0,0 +1,794 @@
+# Eigenmode decomposition of arbitrary field configurations
+
+*Eigenmode decomposition* exploits Meep's interconnectivity
+with the [MPB][MPB] mode solver to express an arbitrary
+time-harmonic field configuration as a superposition of
+the normal harmonic modes of your structure.
+
+[TOC]
+
+## Theoretical background[^1]
+
+Consider a waveguide structure of infinite extent in the $x$
+direction with constant cross section in the transverse
+$[\vec\rho=(y,z)]$ directions. For any given
+angular frequency $\omega$ we may solve the time-harmonic
+Maxwell equations to obtain the *normal modes* of the
+structure---an infinite set of vector-valued
+functions of the transverse coordinates
+$\{\mathbf{E}^\pm_n(\vec{\rho}), \mathbf{H}^\pm_n(\vec{\rho})\}$,
+with associated propagation constants $\{\beta_n\}$,
+that furnish a complete expansion basis for
+time-harmonic electromagnetic fields at frequency $\omega$.
+That is, given any arbitrary frequency-$\omega$ field
+configuration of the form
+$$ \mathbf{E}(\mathbf{r},t) = \mathbf{E}(\mathbf{r}) e^{-i\omega t} $$
+$$ \mathbf{H}(\mathbf{r},t) = \mathbf{H}(\mathbf{r}) e^{-i\omega t} $$
+we have the *exact* expansions
+
+$$
+ \mathbf{E}(\mathbf{r}) =
+ \mathbf{E}(x,\vec{\rho}) =
+ \sum_{n} \left\{ \alpha^+_n \mathbf E^+_n(\vec \rho)e^{+i\beta_n x}
+ + \alpha^-_n \mathbf E^-_n(\vec \rho)e^{-i\beta_n x}
+ \right\}
+ \tag{1}
+$$
+$$
+ \mathbf{H}(\mathbf{r}) =
+ \mathbf{H}(x,\vec{\rho}) =
+ \sum_{n} \left\{ \alpha^+_n \mathbf H^+_n(\vec \rho)e^{+i\beta_n x}
+ + \alpha^-_n \mathbf H^-_n(\vec \rho)e^{-i\beta_n x}
+ \right\}
+ \tag{2}
+$$
+where (as discussed further [below](ModeExpansion.md#UnderTheHood))
+the expansion coefficients $\{\alpha^{\pm}_n\}$
+may be extracted from knowledge of the time-harmonic
+fields $\mathbf{E},\mathbf{H}$ on any cross-sectional
+surface $S$ transverse to the waveguide.
+
+The idea of mode expansion in Meep is to compute
+the $\{\alpha_n^\pm\}$ coefficients above for any
+*arbitrary* time-harmonic field distribution
+resulting from a Meep calculation. In calculations
+of this sort,
+
++ the $\{\mathbf{E},\mathbf{H}\}$ fields on the RHS
+ of equations (1a,b) above will be frequency-domain
+ fields stored in a `dft_flux` object in a Meep
+ run, where you will have arranged this `dft_flux` object
+ to live on a cross-sectional surface $S$ transverse
+ to the waveguide;
+
+- the $\{\mathbf{E}^\pm_n,\mathbf{H}^\pm_n\}$ eigenmodes
+ and $\{\beta_n\}$ propagation constants are computed
+ automatically under the hood by [MPB][MPB] as normal modes
+ of an infinitely extended waveguide with the same
+ cross-sectional material distribution that your structure
+ has on the transverse slice $S$, and
+
+- the $\alpha_n^\pm$ coefficients for as many bands
+ as you like are computed by calling `get_eigenmode_coefficients(),`
+ as discussed below.
+
+## Main function prototype
+
+The highest-level interface to the mode-expansion implementation
+in Meep is the libmeep function `meep::fields::get_eigenmode_coefficients,`
+callable from C++ or python. This routine makes use
+of several [lower-level libmeep functions](ModeExpansion.md#OtherRoutines)
+that you may also find useful;
+these are documented
+[below](ModeExpansion.md#OtherRoutines)
+and their use is illustrated in the tutorial that follows.
+
+The C++ prototype for the top-level routine is
+
+```c++
+std::vector
+ fields::get_eigenmode_coefficients(dft_flux *flux,
+ direction d,
+ const volume &where,
+ std::vector bands,
+ kpoint_func k_func=0,
+ void *user_data=0);
+```
+where
+
++ `flux` is a `dft_flux` object pre-populated with frequency-domain field data resulting from a time-domain Meep calculation you have run to tabulate fields on a cross-sectional slice perpendicular to your waveguide
+
++ `d` is the direction of power flow in the waveguide
+
++ `where` is a `volume` describing the cross-sectional surface $S$
+
++ `bands` is an array of integers that you populate with the indices of the modes for which you want expansion coefficients
+
++ `user_func` is an *optional* function you supply to provide initial estimates of the wavevector of a mode with given
+frequency and band index; its prototype is
+
+```c++
+ vec (*kpoint_func)(void user_data, double freq, int band);
+```
+
+which returns a `vec` giving your best guess for the
+wavevector of the `band`th mode at frequency `freq`.
+
+The return value of `get_mode_coefficients` is an array
+of type `cdouble` (short for `std::complex`),
+of length `2 * num_freqs * num_bands`, where `num_freqs`
+is the number of frequencies stored in your `flux` object
+(equal to `flux->Nfreq`) and `num_bands` is the length
+of your `bands` input array.
+The expansion coefficients $\{\alpha^+,\alpha^-\}$
+for the mode with frequency `nf` and band index `nb`
+are stored sequentially starting at slot
+`2*nb*num_freqs + nf` of this array:
+
+````c++
+ std::vector coeffs=f.get_eigenmode_coefficient(...)
+ fields::get_eigenmode_coefficients(dft_flux *flux,
+ direction d,
+ const volume &where,
+ std::vector bands,
+ kpoint_func k_func=0,
+ void *user_data=0);
+
+ int num_bands = bands.size();
+ int num_freqs = Flux->Nfreq;
+ for(int nb=0; nb
+$$ w(x) =
+ \begin{cases}
+ w_A, \qquad &x < -\frac{L}{2} \\[5pt]
+ T_p(x), \qquad &x \in \left[ -\frac{L}{2}, +\frac{L}{2}\right] \\[5pt]
+ w_B, \qquad &x > +\frac{L}{2} \\
+ \end{cases}
+ \tag{3}
+$$
+where the taper function $T_p(x)$ is a $C^{p}$ function,
+i.e. $p$ is the index of its first discontinuous derivative.
+For the cases $p=\{0,1,2\}$, the taper functions are
+$$ T_p(x)=\begin{cases}
+ w_0 + \Delta \left(\frac{x}{L}\right), \qquad &p=0 \\[5pt]
+ w_0 + \Delta \Big[ \frac{3}{2}\left(\frac{x}{L}\right)
+ -2\left(\frac{x}{L}\right)^3
+ \Big],\qquad&p=1,\\[5pt]
+ w_0 + \Delta \Big[ \frac{15}{8}\left(\frac{x}{L}\right)
+ -5\left(\frac{x}{L}\right)^3
+ +6\left(\frac{x}{L}\right)^5
+ \Big],\qquad&p=2
+ \end{cases}
+$$
+where
+$$ w_0\equiv \frac{w_A+w_B}{2}, \qquad \Delta = w_B - w_A$$
+are the average and difference of the smaller and larger waveguide
+thicknesses.
+
+Here are pictures of the $p=0,1,2$ taper geometries for the case of a
+taper of length $L=4$ between waveguides of thickness $w_A=1$
+and $w_B=3$. (See below for the python code that produces these
+plots.)
+
+ p=0 Taper
+
+![Taper2D_p0.png](ModeExpansionFiles/Taper2D_p0.png)
+
+ p=1 Taper
+
+![Taper2D_p1.png](ModeExpansionFiles/Taper2D_p1.png)
+
+ p=2 Taper
+
+![Taper2D_p2.png](ModeExpansionFiles/Taper2D_p2.png)
+
+In these figures, the dashed lines at $x=x_{A,B}$
+indicate the locations of cross-sectional planes
+that we will use in our calculation:
+the plane at $x=x_A$ is where we will place an
+eigenmode source in our Meep calculation to describe
+incoming power entering from the smaller waveguide,
+while the plane at $x=x_B$ is where we will
+tabulate the Fourier-domain fields in our Meep
+calculation and determine their overlaps with
+the eigenmodes of the larger waveguide to
+compute mode-expansion coefficients.
+
+### User-defined material function
+
+Because the material geometries we will be studying here
+are too complicated to be described as assemblies of
+the [usual geometric primitives like blocks and cylinders](Python_User_Interface.md#GeometricObject),
+we will instead write our own [user-defined material function](Python_User_Interface.md#material_function), which inputs the coordinates of a point in space
+and fills in a [medium structure](Python_User_Interface.md#medium)
+for the material properties at that point.
+Actually, since the material geometry in this case involves a
+spatially-varying but otherwise simple (isotropic, linear, lossless)
+dielectric function, we can get away with the slightly simpler
+[user-defined epsilon function](Python_User_Interface.md#epsilon_function),
+for which we need only furnish a function of position that
+returns a scalar relative permittivity. This is implemented
+by the `my_eps_func()` routine in `wvg-taper.py;` note that
+it invokes a subroutine `w_func` that evaluates [equation (3) above](ModeExpansion.md#Equation1)
+to compute the $x$-dependent waveguide width $w(x)$.
+
+```python
+##################################################
+# x-dependent width of waveguide
+##################################################
+def w_func(x, L, p, wA, wB):
+ if L==0:
+ return wA if x<0 else wB
+ x0=x/L
+ if (x0 < -0.5):
+ return wA;
+ elif (x0 > +0.5):
+ return wB;
+ elif p==2:
+ return 0.5*(wA+wB) + (wB-wA)*x0*(15.0 + x0*x0*(-40.0 + x0*x0*48.0))/8.0;
+ elif p==1:
+ return 0.5*(wA+wB) + (wB-wA)*x0*(1.5 - 2.0*x0*x0);
+ else: # default t p==0, simple linear taper
+ return 0.5*(wA+wB) + (wB-wA)*x0;
+
+##################################################
+# user-defined function for position-dependent material properties
+##################################################
+def my_eps_func(loc, L, p, wA, wB, eps_out, eps_in):
+
+ if ( abs(loc.y) > 0.5*w_func(loc.x, L, p, wA, wB) ):
+ return eps_out; # outside waveguide
+ else:
+ return eps_in; # inside waveguide
+```
+
+We can pass `my_eps_func` as the value of the
+`epsilon_func` keyword argument to the
+[`Simulation` class constructor](Python_User_Interface.md#SimulationClass);
+however, because this expects a function of just a single
+argument (the spatial point), we use a `lambda` construction
+to package the remaining arguments, i.e. something like
+
+```python
+eps_func = lambda loc: my_eps_func(loc, L, p, wA, wB,
+ eps_ambient, eps_waveguide)
+
+sim=mp.Simulation( cell_size=mp.Vector3(2*LX, 2*LY),
+ resolution=resolution,
+ boundary_layers=[mp.PML(DPML)],
+ epsilon_func = eps_func
+ )
+```
+
+The [`wvg-taper.py`](ModeExpansionFiles/wvg-taper.py) code defines
+a class called `wvg-taper` that accepts keyword arguments for
+various geometric parameters and instantiates a `Simulation` object
+as in the code snippet above. For example, here's how we
+made the pictures of the structures shown above:
+a couple of examples involving waveguides and tapers of
+various geometries:
+
+```python
+>>> execfile("wvg-taper.py");
+>>> wt=wvg_taper(wA=1, wB=3, L=4, p=0); wt.plot_eps();
+>>> wt=wvg_taper(wA=1, wB=3, L=4, p=1); wt.plot_eps();
+>>> wt=wvg_taper(wA=1, wB=3, L=4, p=2); wt.plot_eps();
+```
+The `plot_eps()` class method that produces these plots
+just calls [`Simulation.get_array`](Python_User_Interface.md)
+to get a `numpy` array of ε values at the grid
+points, then plots it using the `imshow` routine in
+matplotlib:
+
+```python
+ def plot_eps(self):
+
+ eps=self.sim.get_array(center = mp.Vector3(0,0),
+ size = self.sim.cell_size,
+ component = mp.Dielectric)
+ plt.figure()
+ plt.imshow(eps.transpose())
+ plt.show(block=False)
+```
+
+### Visualizing eigenmode profiles
+
+Next, before doing any timestepping let's calculate
+and plot the field profiles of some waveguide modes,
+for both the smaller and larger waveguides.
+This calculation is done by the `plot_modes`
+function in the `wvg_taper` class; you can look
+at the [full Python code](ModeExpansionFiles/wvg-taper.py)
+to see how it's done in full detail, but
+here is a synopsys:
+
++ For the lowest-frequency ($n=1$) eigenmode of the
+ smaller waveguide, and for the first several
+ eigenmodes of the larger waveguide, we call the `meep::fields::get_eigenmode`
+ routine in libmeep.
+ This routine inputs a frequency (`fcen`), an integer (`nb`), and a
+ `meep::volume` specifying a cross-sectional slice through our
+ geometry, then invokes [MPB][MPB] to determine the `nb`th
+ eigenmode at frequency `fcen` for an *infinitely extended*
+ waveguide with constant cross section matching that of
+ our slice. For example, to compute the $n=1$ eigenmode
+ for an infinite waveguide whose cross section matches
+ that of our structure at $x=x_A$, we say
+
+````python
+nb = 1; # want first eigenmode
+vA = mp.volume( mp.vec(xA, -YP), mp.vec(xA,+YP) ) # cross section at x_A
+modeA = f.get_eigenmode(fcen, mp.X, vA, vA, nb, k0, True, 0, 0.0, 1.0e-4)
+````
+
+The return value of `get_eigenmode` is a data structure
+containing information on the computed eigenmode; for
+example, to get the group velocity or propagation vector
+of the mode you could say
+
+````python
+vgrp = get_group_velocity(modeA);
+k_vector = get_k(modeA)
+````
+
+Alternatively, you can call the `meep::fields::output_mode_fields`
+routine to export the $\mathbf{E}$ and $\mathbf{H}$
+components of the eigenmode (at grid points lying in the cross-sectional
+plane) to an HDF5 file, i.e.
+
+````python
+f.output_mode_fields(modeA, fluxA, vA, "modeA");
+````
+
+where `fluxA` is a [`meep::dft_flux`][DFTFlux] structure
+created for the cross section described by `vA`. This will
+create a file called `modeA.h5` containing values of
+field components at grid points in `vA`.
+
++ Having computed eigenmodes with `get_eigenmode` and written their
+ field profiles to HDF5 files with `output_mode_fields`, we
+ can read the data back in for postprocessing, such as (for example)
+ plotting eigenmode field profiles. This is done by the `plot_fields`
+ routine in [`wvg-taper.py`](ModeExpansionFiles/wvg-taper.py);
+ the basic flow looks something like this:
+
+````python
+
+ # open HDF5 file
+ file = h5py.File("modeA.h5", 'r')
+
+ # read array of Ey values on grid points
+ ey = file["ey" + suffix + ".r"][()] + 1j*file["ey" + suffix + ".i"][()];
+
+ # plot real part
+ plt.plot(np.real(Ey))
+````
+
+The `plot_modes` routine in `wvg-taper.py` repeats this process for the
+lowest mode $x_A$ (`ModeA1`) and the first several modes at $x_B$
+(`ModeB1...B6`) and plots the results:
+
+
+![ModeProfiles2D.png](ModeExpansionFiles/ModeProfiles2D.png)
+
+
+### Adding an eigenmode source and timestepping
+
+The next step is to add an *eigenmode source* inside the
+smaller waveguide---that is, a collection of Meep point
+sources, lying on the cross-sectional surface at $x_A$,
+whose radiated fields reproduce the fields of a
+given waveguide eigenmode at a given frequency:
+
+
+````python
+sources = [ mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=df),
+ center=mp.Vector3(xA,0.0),
+ size=mp.Vector3(0.0,LY),
+ eig_band=band_num
+ )
+ ]
+self.sim=mp.Simulation( cell_size=mp.Vector3(LX, LY),
+ resolution=resolution,
+ boundary_layers=[mp.PML(DPML)],
+ force_complex_fields=True,
+ epsilon_func = eps_func,
+ sources=sources
+ )
+````
+
+Next, we timestep to accumulate Fourier-domain fields
+on a cross-sectional plane within the larger waveguide.
+This is done by the `get_flux()` method in
+[`wvg_taper.py](ModeExpansionFiles/wvg_taper.py).
+
+The timestepping continues until the instantaneous
+Poynting flux through the flux plane at $x_B$
+has decayed to 0.1% of its maximum value.
+When the timestepping is finished, the Fourier-domain
+fields on the plane at $x_B$ are stored
+in a [`dft_flux`](DFTFlux) object called `fluxB.`
+and we can call `meep::fields::output_flux_fields`
+to export the fields to an HDF5 file, similar to
+`output_mode_fields` which we used above:
+
+````python
+f.output_flux_fields(fluxB, vB, 'fluxB')
+````
+
+This produces a file called `fluxB.h5`. One slight
+difference from `output_mode_fields` is that `dft_flux`
+objects typically store field data for multiple
+frequencies, so the field-component datasets
+in the `HDF5` file have names like `ey_0.r`, `ey_1.i`.
+
+### Visualizing DFT fields
+
+Having written Fourier-transform fields to HDF5
+files, we can read in the data and plot, as we
+did previously for mode profiles. In the `wvg_taper.py`
+code this is again handled by the `plot_fields`
+routine.
+Here are the results of this process for
+a few different values of the taper length $L$ and
+smoothness index $p$:
+
+![FluxVsLP.png](ModeExpansionFiles/FluxVsLP.png)
+
+Take-home messages:
+
++ For $L=0$ (no taper, i.e. abrupt junction) the fields
+ at $x_B$ look nothing like the fields of the lowest
+ eigenmode for the larger structure (second row
+ of [this plot](ModeExpansion.md#ModeProfiles));
+ clearly there is significant contamination from
+ higher modes.
++ As we increase the taper length and the smoothness index
+ the fields at $x_B$ more and more closely resemble the
+ lowest eigenmode fields, indicating that the taper is
+ working to transfer power adiabatically from lowest mode
+ to lowest mode.
+
+### Making movies
+
+The `get_flux()` routine in the
+[`wvg_taper.py`](ModeExpansionFiles/wvg_taper.py)
+supports a keyword parameter
+`frame_interval` which, if nonzero, defines an
+interval (in meep time) at which images of the
+instantaneous Poynting flux over the entire geometry
+are to be written to `.h5` files.
+The default is `frame_interval=0`, in which case
+these images will not be written.
+
+If you specify (say) `frame_interval=1`
+to `get_flux()` for a geometry with (say) taper
+length $L=1.2$ and smoothness index $p=1$, you
+will get approximately 100 files with names like
+````bash
+ L1.2_p1_f1.png
+ L1.2_p1_f2.png
+ L1.2_p1_f3.png
+ ...
+ L1.2_p1_f105.png
+ ...
+````
+
+To assemble all these frame files into a movie
+using [FFMPEG](https://www.ffmpeg.org/), go like this:
+
+````bash
+ # ffmpeg -i 'L1.2_p1_f%d.png' L1.2_p1.mpg
+````
+
+(Note that the string `%d` in the input filename
+is a wildcard that will match all integer values; it needs
+to be in single quotes to protect it from shell expansion.)
+
+Here are the movies for the various cases considered above:
+
+
+
+ Taper |
+ Movie |
+
+ L=0 |
+
+
+
+ |
+
+
+ L=1, p=0 |
+
+
+
+ |
+
+
+ L=2, p=0 |
+
+
+
+ |
+
+
+ L=3, p=0 |
+
+
+
+ |
+
+
+ L=3, p=1 |
+
+
+
+ |
+
+
+ L=3, p=2 |
+
+
+
+ |
+
+
+
+
+
+
+### Extracting mode-expansion coefficients
+
+Finally, we call `get_mode_coefficients` to compute
+the inner product of the Meep DFT fields in the larger waveguide
+with each of a user-specified list of eigenmodes of the larger
+waveguide to compute the fraction of the power carried by
+each mode.
+
+### Intra-modal scattering losses vs. taper length and smoothness
+
+Repeating this calculation for many taper lengths $L$ and
+smoothness indices $p=0,1$ yields the following plots
+showing the rate of decay of inter-mode scattering losses
+as the taper length $L\to\infty.$
+
+![TaperData.png](ModeExpansionFiles/TaperData.png)
+
+
+## Related computational routines
+
+Besides `get_eigenmode_coefficients,` there are a few
+computational routines in `libmeep` that you may find useful
+for problems like those considered above.
+
+### Routine for computing MPB eigenmodes (in `mpb.cpp`)
+````
+ void *fields::get_eigenmode(double &omega,
+ direction d, const volume &where,
+ const volume &eig_vol,
+ int band_num,
+ const vec &kpoint, bool match_frequency,
+ int parity,
+ double resolution,
+ double eigensolver_tol);
+````
+
+Calls MPB to compute the `band_num`th eigenmode at frequency `omega`
+for the portion of your geometry lying in `where` (typically
+a cross-sectional slice of a waveguide). `kpoint` is an initial
+starting guess for what the propagation vector of the waveguide
+mode will be.
+
+### Routines for working with MPB eigenmodes (in `mpb.cpp`)
+
+The return value of `get_eigenmode` is an opaque pointer to
+a data structure storing information about the computed eigenmode,
+which may be passed to the following routines:
+
+````
+// get a single component of the eigenmode field at a given point in space
+std::complex eigenmode_amplitude(const vec &p, void *vedata, component c);
+
+// get the group velocity of the eigenmode
+double get_group_velocity(void *vedata);
+
+// free all memory associated with the eigenmode
+void destroy_eigenmode_data(void *vedata);
+````
+
+### Routines for exporting frequency-domain fields (in `dft.cpp`)
+
+````
+ void output_flux_fields(dft_flux *flux, const volume where,
+ const char *HDF5FileName);
+
+ void output_mode_fields(void *mode_data, dft_flux *flux,
+ const volume where,
+ const char *HDF5FileName);
+````
+
+`output_flux_fields` exports the components of the (frequency-domain) fields
+stored in `flux` to an HDF5 file with the given file name. `where` is the
+`volume` passed to the `flux` constructor. In general, `flux` will store
+data for fields at multiple frequencies, each of which will
+
+`output_mode_fields` is similar, but instead exports the components of the eigenmode
+described by `mode_data` (which should be the return value of a call to `get_eigenmode`).
+
+
+### Routines for computing overlap integrals (in `dft.cpp`)
+````
+ std::complex get_mode_flux_overlap(void *mode_data,
+ dft_flux *flux,
+ int num_freq,
+ const volume where);
+
+ std::complex get_mode_mode_overlap(void *mode1_data,
+ void *mode2_data,
+ dft_flux *flux,
+ const volume where);
+````
+
+`get_mode_flux_overlap` computes the overlap integral
+(defined by [equation (*) above](#OverlapEquation))
+between the eigenmode described by `mode_data`
+and the fields stored in `flux` (for the `num_freq`th stored
+frequency, where `num_freq` ranges from 0 to `flux->Nfreq-1`.)
+`mode_data` should be the return value of a previous call to
+`get_eigenmode.`
+
+`get_mode_mode_overlap` is similar, but computes the overlap
+integral between two eigenmodes. (`mode1_data` and `mode2_data` may be
+identical, in which case you get the inner product of the
+mode with itself; by the normalization convention used in MPB,
+this should equal the group velocity of the mode.)
+
+
+## Under the hood: How mode expansion works
+
+The theoretical basis of the mode-expansion algorithm
+is the orthogonality relation satisfied by the normal
+modes:
+$$ \left\langle \mathbf{E}_m^{\sigma} \right|
+ \left. \mathbf{H}^\tau_n \right\rangle
+ =C_{m}\delta_{mn}\delta_{\sigma\tau}
+ \qquad \Big( \{\sigma,\tau\}\in\{+,-\}\Big)
+ \tag{4}
+$$
+where the inner product involves an integration over
+transverse coordinates:
+
+$$ \left\langle \mathbf{f} \right| \left. \mathbf{g} \right\rangle
+ \equiv
+ \int_{S}
+ \Big[ \mathbf{f}^*(\vec \rho) \times \mathbf{g}(\vec \rho)\Big]
+ \cdot \hat{\mathbf{n}} \, dA
+ \tag{5}
+$$
+where $S$ is any surface transverse to the direction of propagation
+and $\hat{\mathbf{n}}$ is the unit normal vector to $S$ (i.e.
+just $\hat{\mathbf{z}}$ in the case considered above).
+The normalization constant $C_{m}$ is a matter of convention,
+but in [MPB][MPB] it is taken to be the group velocity of the
+mode, $v_m$, times the area $A_S$ of the cross-sectional surface $S$:
+$$ C_m = v_m A_S. \tag{6} $$
+
+Now consider a Meep calculation in which we have accumulated
+frequency-domain $\mathbf E^{\text{meep}}$ and $\mathbf H^{\text{meep}}$
+fields on a `dft-flux`
+object located on a cross-sectional surface $S$. Invoking the
+eigenmode expansion [(1)](ModeExpansion.md#EigenmodeExpansions)
+and choosing (without loss of generality) the origin
+of the $x$ axis to be the position of the cross-sectional plane,
+the tangential components of the frequency-domain Meep fields
+take the form
+$$ \mathbf E^{\text{meep}}_\parallel
+ = \sum_{n} (\alpha_n^+ + \alpha_n^-)\mathbf{E}_{n\parallel}^+,
+ \tag{7}
+$$
+$$ \mathbf H^{\text{meep}}_\parallel
+ = \sum_{n} (\alpha_n^+ - \alpha_n^-)\mathbf{H}_{n\parallel}^+,
+ \tag{8}
+$$
+where we used the well-known relations between the tangential
+components of the forward-traveling and backward-traveling field
+modes:
+$$ \mathbf{E}^+_{n\parallel} =+\mathbf{E}^-_{n\parallel},
+ \qquad
+ \mathbf{H}^+_{n\parallel} =-\mathbf{H}^-_{n\parallel}.
+$$
+Taking the inner product (5) of both sides of equations (7) and (8)
+with the $\mathbf{H}$ and $\mathbf{E}$ fields of each eigenmode
+and using equations (4) and (6), we find
+$$ \left\langle \mathbf{H}_m
+ \right|\left. \mathbf{E}^{\text{meep}} \right\rangle
+ =+(\alpha_n^+ + \alpha_n^-) v_m A_S
+$$
+$$ \left\langle \mathbf{E}_m
+ \right|\left. \mathbf{H}^{\text{meep}} \right\rangle
+ =-(\alpha_n^+ - \alpha_n^+) v_m A_S
+$$
+Thus, by evaluating the integrals on the LHS of these equations---numerically,
+using the MPB-computed eigenmode fields $\{\mathbf{E}, \mathbf{H}\}_m$
+and the Meep-computed fields $\{\mathbf{E}, \mathbf{H}\}^{\text{meep}}\}$
+as tabulated on the computational grid---and combining the results
+appropriately, we can extract the coefficients $\{\alpha^\pm_m\}$
+in the expansion (1). This calculation is carried out by the
+routine [`meep::fields::get_mode_flux_overlap`](ModeExpansion.md#OverlapRoutines).
+(Although simple in principle, the implementation is complicated by
+the fact that, in multi-processor calculations, the Meep fields
+needed to evaluate the integrals are generally not all present
+on any one processor, but are instead distributed over multiple
+processors, requiring some interprocess communication to evaluate
+the full integral.)
+
+The Poynting flux carried by the Meep fields (7,8) may be expressed
+in the form
+$$ S_x = \frac{1}{2}\text{Re }
+ \left\langle \mathbf{E}^{\text{meep}}\right|
+ \left. \mathbf{H}^{\text{meep}}\right\rangle
+ = \frac{1}{2}\sum_n \left\{ |\alpha_n^+|^2 - |\alpha_n^-|^2) \right\} v_n A_S
+$$
+and thus the fractional power carried by any one (forward- or backward-traveling)
+eigenmode is given by
+$$ \text{fractional power carried by }\pm\text{-traveling mode }n=
+ \frac{|\alpha_n^\pm|^2 v_n A_S}{2S_x}
+$$
+
+[^1]:
+ The theory of waveguide modes is covered in many references;
+ one that we have found useful is [Snyder and Love, *Optical Waveguide Theory* (Springer, 1983)](http://www.springer.com/us/book/9780412099502).
+
+
+[MPB]: https://mpb.readthedocs.io/en/latest/
+[DFTFlux]: https://meep.readthedocs.io/en/latest/Scheme_User_Interface/#Flux_spectra.md
diff --git a/doc/docs/ModeExpansionFiles/FluxVsLP.png b/doc/docs/ModeExpansionFiles/FluxVsLP.png
new file mode 100644
index 0000000000000000000000000000000000000000..f3c562c26d4d4ba23314b56e510f0c0885ff5afc
GIT binary patch
literal 198727
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