Ceviche

# ceviche

Electromagnetic Simulation Tools + Automatic Differentiation. Code for the arxiv preprint Forward-Mode Differentiation of Maxwell's Equations.

(logo by @nagilmer)

## What is ceviche?

ceviche provides two core electromagnetic simulation tools for solving Maxwell's equations:

• finite-difference frequency-domain (FDFD)

• finite-difference time-domain (FDTD)

Both are written in numpy / scipy and are compatible with the HIPS autograd package, supporting forward-mode and reverse-mode automatic differentiation.

This allows you to write code to solve your E&M problem, and then use automatic differentiation on your results.

As a result, you can do gradient-based optimization, sensitivity analysis, or plug your E&M solver into a machine learning model without the tedius process of deriving your derivatives analytically.

### Tutorials

There is a comprehensive ceviche tutorial available at this link with several ipython notebook examples:

There are also a few examples in the examples/* directory.

### What can it do? An Example

Let's saw we have a simulation where we inject a current source at position source and measure the electric field intensity at probe.

Between these two points, there's a box at location pos_box with permittivity eps.

We're interested in computing how the intensity measured changes with respect to eps.

With ceviche, we first write a simple function computing the measured intensity as a function of eps using FDFD

import autograd.numpy as np           # import the autograd wrapper for numpy
from ceviche import fdfd_ez as fdfd   # import the FDFD solver

# make an FDFD simulation
f = fdfd(omega, dl, eps_box, npml=[10, 10])

def intensity(eps):
""" computes electric intensity at probe for a given box permittivity of eps

source |-----| probe
.  | eps |  .
|_____|
"""

# set the permittivity in the box region to the input argument
fdfd.eps_r[box_pos] = eps

# solve the fields
Ex, Ey, Hz = f.solve(source)

# compute the intensity at probe
I = np.square(np.abs(Ex)) + np.square(np.abs(Ey))
return = np.sum(I * probe)


Then, we can easily take the derivative of the intensity with respect to eps using a ceviche function

# use autograd to differentiate intensity function

# then, evaluate it at the current value of eps


The beauty is that ceviche lets you compute this derivative without having to do any calculations by hand! Using automatic differentiation, each step of the calculated is recorded and its derivative information is already known. This lets us take derivatives of arbitrary complex code, where the output depends in some way on the electromagnetic simulation.

Armed with this capability, we can now do things like performing gradient-based optimization (inverse design) to maximize the intensity.

for _ in range(10):
eps_current += step_size * dI_deps_fn(eps_current)


It's also worth noting that the mathematics behind this gradient implementation uses the 'adjoint method', which lets you take derivatives with several degrees of freedom. This is perfect for inverse design problems, or training of machine learning models that involve running an FDFD or FDTD simulation. If you're interested in the connection between adjoint methods and backpropagation in the context of photonics, check out our group's earlier work on the subject link.

## Installation

There are many ways to install ceviche.

The easiest is by

pip install ceviche


But to install from a local copy, one can instead do

git clone https://github.com/twhughes/ceviche.git
pip install -e ceviche
pip install -r ceviche/requirements.txt


from the main directory.

git clone https://github.com/twhughes/ceviche.git


and then import the package from within your python script

import sys
sys.path.append('path/to/ceviche')


## Package Structure

### Ceviche

The ceviche directory contains everything needed.

To get the FDFD and FDTD simulators, import directly from ceviche import fdtd, fdfd_ez, fdfd_hz, fdfd_ez_nl

To get the differentiation, import from ceviche import jacobian.

constants.py contains some constants EPSILON_0, C_0, ETA_0, Q_E, which are needed throughout the package

utils.py contains a few useful functions for plotting, autogradding, and various other things.

### Examples

There are many demos in the examples directory, which will give you a good sense of how to use the package.

### Tests

Tests are located in tests. To run, cd into tests and

python -m unittest


to run all or

python specific_test.py


to run a specific one. Some of these tests involve visual inspection of the field plots rather than error checking on values.

To run all of the gradient checking functions, run

chmod + test/test_all_gradients.sh


## Citation

@misc{1908.10507,
Author = {Tyler W Hughes and Ian A D Williamson and Momchil Minkov and Shanhui Fan},
Title = {Forward-Mode Differentiation of Maxwell's Equations},
Year = {2019},
Eprint = {arXiv:1908.10507},
}


## Project details

Uploaded Source