Skip to content

[7/13][Adjoint Module] Launch a mode through a stratified stack into the simulation (and backprop) - #3284

Open
smartalecH wants to merge 4 commits into
feat/adjoint-source-gradientsfrom
feat/adjoint-asm-source
Open

smartalecH wants to merge 4 commits into
feat/adjoint-source-gradientsfrom
feat/adjoint-asm-source

Conversation

@smartalecH

@smartalecH smartalecH commented Aug 27, 2026 •

Copy link
Copy Markdown
Collaborator

Launches a mode into a simulation through a stratified stack, completing the angular-spectrum work in #3281 (which carries fields out through a stack). The typical use is a fiber far above a chip: the mode is specified where it physically lives, at the fiber facet outside the FDTD cell, carried analytically through the superstrate, and injected just above the device. The whole path is differentiable, so the fiber's waist, tilt and offset can be optimized together with the device.

API.

propagator = mpa.AngularSpectrum.from_volume(sim, plane, stack, [fcen])
fields = propagator.incident_fields(mpa.gaussian_mode(waist, tilt_deg=tilt), distance=d)
sim.sources += propagator.equivalent_sources(fields, mp.GaussianSource(fcen, fwidth=df),
                                             center=plane.center, size=plane.size)
  • incident_fields(mode, distance) gives the tangential fields at the injection plane for a mode arriving from the far side of the stack.
    • It is the time reverse of the measurement path, so the same Mode describes the same fiber in both directions: what overlap collects with gaussian_mode(tilt=θ) is what incident_fields launches with it. Its spectrum is conj(a(-kt)).
    • The stack is crossed from the far side, with the reciprocal transmission t · Y_far / Y_monitor.
  • equivalent_sources(fields, ...) turns those fields into an electric sheet K = n̂×H and a magnetic sheet N = −n̂×E, which radiate one way, as ordinary amp_data sources.
  • equivalent_currents(fields) returns the same arrays in JAX. A loss can feed them to MeepJaxWrapper and differentiate end to end with respect to the mode's parameters; Meep returns the cotangent with respect to amp_data through [6/13][Adjoint Module] Adjoint gradients with respect to sources #3283's source adjoint.
  • from_volume builds a propagator for a plane that has no monitor yet, since the sources are exactly what it is building.

End-to-end check (examples/adjoint_optimization/grating_coupler_asm_end_to_end.py): a small 2D grating coupler with the fiber 10 µm up in air, above 2 µm of silica, all outside the cell.

grating_coupler_asm_end_to_end
  • (a, b) Field: Meep's launched field matches the propagator's prediction 3.5 µm below the injection plane to 2.5%, with no fitted scale; the only factor applied is the source's own spectrum.
  • (c) Gradient: the gradient of the coupled waveguide power with respect to the fiber's waist, tilt and offset matches finite differences of the full simulation to ≤ 1e-4.
  • (d) Reciprocity: fiber → waveguide and waveguide → fiber efficiencies agree across fiber tilt.
  • (e) Convergence: the remaining gap is discretization error, shrinking at second order with resolution (28% → 16% → 8.5% at 20/30/40 px/µm).

The example runs in about 20 minutes on one core, or about 2 minutes with --quick.

Tests.

  • Injection energy through an interface: the launched power equals the reciprocal power transmission times the mode power.
  • A tilted mode is launched in the direction the fiber emits.
  • The time-reversed injected beam projects onto the mode with purity 1.
  • equivalent_currents equals the placed amp_data and is differentiable with respect to the mode.
  • x- and y-normal planes in 2D, and the amp_data layout for every normal in 3D.
  • One-way radiation in FDTD.

Also includes the example grating_coupler_asm_source.py, which drives the coupler from the fiber and co-optimizes the grating and the fiber alignment.

@smartalecH smartalecH changed the title Launch a mode through a stratified stack into the simulation [3/n][Adjoint Module] Launch a mode through a stratified stack into the simulation (and backprop) Aug 27, 2026
@smartalecH smartalecH changed the title [3/n][Adjoint Module] Launch a mode through a stratified stack into the simulation (and backprop) [4/n][Adjoint Module] Launch a mode through a stratified stack into the simulation (and backprop) Aug 27, 2026
@smartalecH
smartalecH force-pushed the feat/adjoint-asm-source branch from 4ab1a53 to b885b28 Compare September 2, 2026 22:16
@smartalecH smartalecH changed the title [4/n][Adjoint Module] Launch a mode through a stratified stack into the simulation (and backprop) [7/13][Adjoint Module] Launch a mode through a stratified stack into the simulation (and backprop) Sep 2, 2026
@smartalecH
smartalecH force-pushed the feat/adjoint-asm-source branch from b885b28 to 717e81b Compare October 7, 2026 23:24
@smartalecH
smartalecH force-pushed the feat/adjoint-asm-source branch 2 times, most recently from 8076dfb to 96a9ba9 Compare October 9, 2026 20:55
@smartalecH
smartalecH force-pushed the feat/adjoint-asm-source branch from 96a9ba9 to 82c1044 Compare October 12, 2026 18:52
@smartalecH
smartalecH marked this pull request as ready for review October 12, 2026 21:58
@smartalecH
smartalecH requested a review from stevengj October 12, 2026 21:58
smartalecH and others added 4 commits October 13, 2026 18:16
incident_fields is the time reverse of spectrum: a Mode is specified where it
is physically meaningful -- at the fiber facet, on the far side of the stack --
and carried back down to the monitor plane, where Meep can inject it. The
scalar transfer function of a stratified medium is the same in both directions,
so the same product of transmission and propagation phases applies. The result
is purely in-going by construction, since it inverts decompose for a spectrum
with no outgoing part.

equivalent_sources then hands those fields to mp.get_equiv_sources, which
already applies the equivalence principle and emits sources carrying amp_data.
Because amp_data is differentiable, a beam injected this way backpropagates to
its own waist, tilt and offset.

from_volume builds a propagator without a monitor, which the injection path
needs: a DFT monitor requires the field components to be allocated, and that
does not happen until sources are added -- which is what is being built.

Verified end to end: the injected field is 99.997% in-going, the radiated beam
leaks 4e-3 in amplitude the wrong way (1.6e-5 in power), and the beam measured
downstream is still 99.99% travelling the direction it was sent.
incident_fields assumed the 2D s axis is the first tangential one, which only
holds for y-normal lines, and equivalent_sources laid the (u, v) arrays out
as amp_data's (x, y, z) without reordering them or putting the singleton
along the normal, which only holds for 2D y-normal lines and 3D z-normal
planes. Add tests for an x-normal line and for the 3D layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- incident_fields reused the monitor-to-far transmission, but the stack is
  crossed from the far side; by reciprocity that is t * Y_far / Y_monitor.
  Across an interface the injected power was wrong (2.1x for glass/air).
- incident_fields used the mode's spectrum unchanged, which launches a
  tilted mode at the mirrored angle; inject its time reverse, conj(a(-kt)),
  so the same Mode describes the same fiber in both directions.
- from_volume read the grid from an uninitialized simulation, which crashed;
  initialize it to read the grid and reset it afterwards.
- The example rebuilt the equivalent currents with a component swap that
  picked the wrong (zero) components, so its optimization launched nothing
  and never stopped. Add equivalent_currents, the JAX version of what
  equivalent_sources places, and use it in both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A small 2D grating coupler driven by a fiber mode carried through a
superstrate stack outside the cell. It checks the launched field against the
propagator with no fitted scale, transmit-vs-receive reciprocity across fiber
tilts (with its convergence in resolution), and the gradient with respect to
the fiber's waist, tilt and offset against finite differences of the full
simulation, and draws a figure of all three.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@smartalecH
smartalecH force-pushed the feat/adjoint-asm-source branch from c8b30fc to 5e04191 Compare October 14, 2026 01:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant