GithubHelp home page GithubHelp logo

fancompute / angler Goto Github PK

View Code? Open in Web Editor NEW
147.0 19.0 49.0 119.47 MB

Frequency-domain photonic simulation and inverse design optimization for linear and nonlinear devices

Home Page: https://arxiv.org/abs/1811.01255

License: MIT License

Python 100.00%
optimization fdfd simulation electromagnetic inverse-problems adjoint-sensitivities adjoint mkl solver frequency-domain

angler's Introduction

Angler

angler

angler (named for 'adjoint nonlinear gradients') is a package for simulating and optimizing optical structures.

It provides a finite-difference frequency-domain (FDFD) solver for simulating for linear and nonlinear devices in the frequency domain.

It also provides an easy to use package for adjoint-based inverse design and optimization of linear and nonlinear devices. For example, you can inverse design optical switches to transport power to different ports for different input powers:

Fields

angler is released as part of a paper Adjoint method and inverse design for nonlinear optical devices, which can be viewed here.

Installation

One can install the most stable version of angler and all of its dependencies (apart from MKL) using

pip install angler

Alternatively, to use the most current version

git clone https://github.com/fancompute/angler.git
pip install -e angler

And then this directory can be added to path to import angler, i.e.

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

Make angler faster

The most computationally expensive operation in angler is the sparse linear system solve. This is done with scipy.sparse.linalg.spsolve() by default. If MKL is installed, angler instead uses this with a python wrapper pyMKL, which makes things significantly faster, depending on the problem. The best way to install MKL, if using anaconda, is

conda install MKL

(pyMKL does not work when MKL is pip installed.)

Examples / Quickstart

There are several jupyter notebook examples in the Notebooks/ directory.

For a good introduction, try:

Notebooks/Splitter.ipynb

For more specific applications:

Electromagnetic simulations

For modeling linear devices with our FDFD solver (no optimization), see

Notebooks/Linear_system.ipynb

For modeling nonlinear devices with FDFD (no optimization), see

Notebooks/Nonlinear_system.ipynb

Inverse design & optimization

For examples of optimizing linear devices, see

Notebooks/Splitter.ipynb
Notebooks/Accelerator.ipynb

For examples of optimizing nonlinear devices, see

Notebooks/2_port.ipynb
Notebooks/3_port.ipynb
Notebooks/T_port.ipynb

Package Structure

angler provides two main classes, Simulation and Optimization, which perform most of the functionality.

Generally, Simulation objects are used to perform FDFD simulations, and Optimization classes run inverse design and optimization algorithms over Simulations. To learn more about how angler works and how to use it, please take a look at angler/README.md for a more detailed explanation.

Tests

To run all tests:

python -m unittest discover tests

Or to run individually:

python tests/individual_test.py

Contributing

angler is under development and we welcome suggestions, pull-requests, feature-requests, etc.

If you contribute a new feature, please also write a few tests and document your changes in angler/README.md or the wiki.

Authors

angler was written by Tyler Hughes, Momchil Minkov, and Ian Williamson.

Citing

If you use angler, please cite us using

@article{Hughes2018,
author = {Hughes, Tyler W. and Minkov, Momchil and Williamson, Ian A. D. and Fan, Shanhui},
title = {Adjoint Method and Inverse Design for Nonlinear Nanophotonic Devices},
journal = {ACS Photonics},
volume = {5},
number = {12},
pages = {4781-4787},
year = {2018},
doi = {10.1021/acsphotonics.8b01522}
}

License

This project is licensed under the MIT License - see the LICENSE.md file for details. Copyright 2018 Tyler Hughes.

Acknowledgments

  • our logo was made by Nadine Gilmer :)
  • RIP Ian's contributions before the code merge
  • We made use of a lot of code snippets (and advice) from Jerry Shi

angler's People

Contributors

ianwilliamson avatar momchilmm avatar nagilmer avatar twhughes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angler's Issues

frequency scan

Add method to optimization object to scan the frequency and compute the bandwidth of the objective function.

Acoustic Simulation / Optimization

I am seeking a software package that can assist in developing more sophisticated acoustic lenses and systems for acoustic levitation. Is there any plan to adapt this system to be able to run in the acoustic domain?

Flexible current sources

Would be nice if the user could specify any current source, instead of only z component.

Jz, Jx, Jy, (Mz, Mx, My)

simulation.setup_modes() error

Describe the bug
A clear and concise description of what the bug is.

dl 5
eps_r.shape (700, 140)
NPML [15, 15] polarization Ez
modalsrc at coords 458,120 width 100 neff (3.5+0j)

Traceback (most recent call last):
File "../FDFDmodel/FDFDmodel.py", line 491, in
simulation.setup_modes()
File "/usr/local/lib/python3.7/site-packages/angler/simulation.py", line 60, in setup_modes
modei.setup_src(self)
File "/usr/local/lib/python3.7/site-packages/angler/source/mode.py", line 21, in setup_src
self.compute_normalization(simulation, matrix_format=matrix_format)
File "/usr/local/lib/python3.7/site-packages/angler/source/mode.py", line 55, in compute_normalization
W_in = simulation_norm.flux_probe(self.direction_normal, new_center, self.width)
File "/usr/local/lib/python3.7/site-packages/angler/simulation.py", line 278, in flux_probe
Sx = -1/2np.real(Ez_xnp.conj(field_val_Hy[inds_x[0]:inds_x[1], inds_y[0]:inds_y[1]]))
ValueError: operands could not be broadcast together with shapes (1,69) (1,70)
[

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS] Linux Fedora 30
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

Python 3

Specifying permittivity with geometric primitives

It would be useful to implement some hooks into a computational geometry package to allow the user to specify an input permittivity distribution (or even the optimization design region) using collections of geometric primitives, e.g. rectangles, circles, etc. The user could also specify transformations of these objects, e.g. rotations, arrays, etc.

This would make it much easier to specify certain types of structures, e.g. waveguide bends, couplers, photonic crystals, ring resonators, etc, compared to the current approach of using conditionals operating directly on the array values.

For example, in my FDFD.jl package I use https://github.com/stevengj/GeometryPrimitives.jl There may be similar packages for python.

Nonlinear adjoints for Hz polarization

Is your feature request related to a problem? Please describe.
Right now, we only support nonlinear gradients for Ez polarization.

Describe the solution you'd like
Simply extend it so that objective functions can be defined for nonlinear Hz, Ex, or Ey fields.

'W' matrix (for filter) cannot be constructed when NPML=[0,0].

Hi,
When I don't want to use PML and make it [0,0], get_W function from filter gives the error 'dimension mismatch' while constructing W matrix as sparce matrix.
I think that problem is on defining i_range and j_range but I couldn't find how to change them properly.

E fields same shape as eps_r

Describe the bug
If eps_r is shape (N,) then the fields solved are shape (N,1)

Either:

  • disallow 1-D eps_r arrays
    Or:
  • keep track of eps_r shape and reshape the fields to match.

Angler 2.0

  • - Autograd EVERYTHING
  • - Make low pass filter faster.
  • - Change the way objective functions are created (like in ceviche) to be more flexible.
  • - Clean up code. Instead of conditionals / switches, lets try to make it more clean.

Maybe a function to generate GDSII files could be added to facilitate processing to verify the accuracy of the device.

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Option to print optimization progress

Would be nice if we could either print the value of the objective function or display a plot of it's value (or the epsilon).

This way it's easier to debug and quit when things go wrong.

Making the output in second mode

Hi,

I see that while adding mode there is an 'order' option which specifies the mode order. But normalization is dependent to the first modes of input and output in direct wave guide. If I want to design a device which has the input in first mode and output in second mode, how should I adjust the optimization?

Consider using autograd for all gradient calculations

Hi there -- Angler looks like an interesting project!

You probably know this already, but Autograd supports defining custom "primitive" operations: https://github.com/HIPS/autograd/blob/master/docs/tutorial.md#extend-autograd-by-defining-your-own-primitives

If you used primitive operations to define gradients for a forward simulation (from the adjoint rule), you could let Autograd handle end-to-end gradient calculations for you. This would be very elegant, and probably much easier to maintain and extend. You could get rid of most of your gradients.py module, for example.

Autograd doesn't support sparse matrices, so unfortunately you can't get this entirely automatically. But it would work to define a primitive function simulate_electric_field() that maps from relative permittivity to resulting electric fields. The "vjp" function Autograd needs to define derivatives is basically exactly the adjoint rule.

Background Index

Is there a way to change the background index (i.e. to an oxide or other cladding value) or is this something that would be of low usefulness? I guess since it is relative permitivitty it may not matter but it seems like that would be useful for informing a real implementation. It seems to me in your structures.py file you hard-code the background to 1 like:

design_region = apply_regions([box], xs, ys, 2) - 1

Where maybe that could be a parameter instead of '2'. I changed that value around but the init_design_region rewrites it based on this value and I started going down the rabbit hole.

Either way, I was just curious. This project is pretty brilliant, great work!

P.S. I was working through the Splitting Jupyter Notebook after I stumbled upon this from your paper.

Polarization independence

Is your feature request related to a problem? Please describe.
Right now, we specify the polarization of the problem, and then all fields are defined in that polarization.

Describe the solution you'd like
Would be great if simulation objects were defined as containing both Ez and Hz polarizations. Then, the current sources can be used to specify which fields are non-zero. For example:

S = simulation(...)          # new simulation independent of polarization
S.src['Jz'] = new_src1     # now Ez, Hx, and Hy may be solved for.
S.src['Mz'] = new_src2     # now Hz, Ex, and Ey may be non-zero as well.

This will allow us to do optimization for problems that have components from both polarizations (ie polarization splitter).

3D solver

Is your feature request related to a problem? Please describe.
Right now we do 2D only, could try doing 3D problems.

Describe the solution you'd like
Should be very similar to before, except we will check if its a 3D simulation, and then use an iterative solver.

Describe alternatives you've considered
Is it worth doing this at all? 3D adjoint FDFD is very computationally expensive and FDTD would probably be better.

Animate Permittivity During Run

Would be nice if we could create and periodically update a plot of the permittivity distribution during a run. Perhaps this can be specified as a flag to optimization.run()

Choosing a default solver

Describe the bug
I'm getting an error which is essentially pardisoSolver is not recognized inside the solver_direct function of linalg.py. It appears to be because the solver being passed as a 'solver' argument is 'paradiso' but my computer does not support pyMKL for some reason. There's a check at the head of this file in lines 5-9 for this, but I think the same check should be added to the constants.py file as well.

I traced the 'solver' parameter back and found that it was being set in constants.py. By adding a check for pyMKL in that file, I was able to make angler fall back on scipy in the way I wanted it to.

Sorry if that's not super clear ^, I'm somewhat new to filing GitHub issues. I think this is a pretty simple fix :)

Least Squares Definiton for Objective Function

Hi,

I see that you are implementing the objective function by multiplying the overlap in each port for the 4-Splitter demo. I understand that this works well but multiplying does not seem as a general method to me. For example, when you would want to reach different overlap values in each port, you would implement the objective function like least squares method and minimize it. I believe that for two outputs, it would be:
objective_function = (port1_obj - 0.3)^2 + (port2_obj - 0.7)^2
This would make the objective in port_1 0.3 and port_2 0.7 when the sum is minimum.

So, is there a specific reason that you considered multiplication instead of a more general method like least squares?

Thank you.

Persist optimization

Would be useful if we could periodically save the permittivity and objective function values (or other necessary parameters) to a file while running.

This way if it's a super long run and we decide to cut it off early or have to stop it, we can pick right back up where it was.

Yee's grid of angler at the boundary of two media

Hello

I try to transform E fields (Ex, Ey) to H field (Hz) in the p-polarization setting. However, the transformed H field has a relatively large value at the boundary of two media. Why does this happen and how can I solve this problem? (The coordinates for indexing are (y, x) and a periodic boundary condition has been applied along the x-axis).
Here's the code for the transformation.

wavelength = 1
lambda0 = wavelength/1e6
eps_0 = 8.85418782e-12
mu_0 = 1.25663706e-6
c0 = np.sqrt(1/eps_0/mu_0)
resolution = 50
dl = lambda0/resolution/1e-6 

Hz_Ey_R = -(Ey_I[1:, :] - np.roll(Ey_I[1:, :], 1, axis=1))/mu_0/omega/lambda0/dl # 79, 320
Hz_Ey_I = (Ey_R[1:, :] - np.roll(Ey_R[1:, :], 1, axis=1))/mu_0/omega/lambda0/dl # 79, 320
Hz_Ex_R = -(Ex_I[1:, :] - Ex_I[:-1, :])/mu_0/omega/lambda0/dl # 78, 320
Hz_Ex_I = (Ex_R[1:, :] - Ex_R[:-1, :])/mu_0/omega/lambda0/dl

prime_Hz_R = Hz_Ey_R[1:, :] - Hz_Ex_R[:, :]
prime_Hz_I = Hz_Ey_I[1:, :] - Hz_Ex_I[:, :]

When I run this code, I get relatively large values on the boundaries of the media as shown below (prime_Hz_R).

image

Resetting or rescaling sources

It would be nice to be able to change or remove a simulation source once it is added. If I want to run the same simulation but with a different input power, right now I don't see any other way but to initialize the simulation object anew. We can add sources, but we cannot remove or edit them. Editing might be too much to ask at this point, but a simple method that removes all sources will suffice.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.