Repository navigation
Conversation
Register, before any computation, what fdtd.solve_modes must meet: a homogeneous control against the closed-form Yee dispersion, the hollow metal guide against its discrete closed form, a symmetric slab against the exact TE/TM dispersion relations with a convergence order, and the published dielectric-corner benchmark of Hadley (J. Lightwave Technol. 20, 1210, 2002), plus the refusals and backend agreement. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
Mutation testing showed the slab and corner criteria cannot see a mode built from a permittivity read at the wrong Yee point, or a propagation constant taken from q without the asin. Register, before running it, the direct check: a solved mode advanced by the kernel itself under a Bloch propagation axis must stay the mode to 1e-10 of each field's peak. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
For a cell-snapped core every component's permittivity array is the same index for index, so a mode read from the wrong component's coefficient is not visible there. Register the same criterion for a smoothed Box core with faces between cells, before running it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
fdtd.solve_modes prepares a problem as fdtd.prepare does, reads the diagonal permittivity and permeability the time stepper multiplies by on a plane, and solves the eigenproblem of the discrete update itself: the leapfrog's Omega for omega and the staggered difference's q for the propagation constant, with the faces' own neighbour rules and masks. The transverse operators are real symmetric, which gives the exact unconjugated orthogonality the normalization uses; each mode is scaled to 1 W of the flux a FluxMonitor measures. Measured against the criteria registered beforehand: the Yee dispersion of a uniform medium and the hollow metal guide's discrete closed form to round-off, the exact slab TE/TM dispersion and Hadley's published dielectric corners (J. Lightwave Technol. 20, 1210, 2002) at second order, and a solved mode advanced by the time stepper stays itself to 6.4e-14. Lossy, dispersive, coupled-smoothed and leaky cases, Bloch and mirror transverse faces and traced inputs are refused by code; the eigensolve is a host computation and does not differentiate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
Before any ModeMonitor computation: exact direction separation through the public path in Bloch guides, completeness of the modal energies against a FluxMonitor behind a dipole in a hollow metal guide, backend agreement, derivatives against central differences, and the refusals. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
MM2's precondition could not be met: a closed metal guide traps the spectral content at each mode's cutoff, so the broadband run never settled, and the seven-mode sum missed the flux by 4.5e-5 against 1e-6. The record keeps the failure and the diagnosis (the corrected Fourier fields of an unsettled run do not satisfy both curl equations at once). MM2b, registered here before it runs, keeps the pulse inside the band where exactly seven modes propagate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
The registered central-difference step carried a truncation error of 9.6e-6 against jax.grad (limit 1e-6); the difference falls as the square of the step. MM4b, registered before it runs, compares the AD derivatives with a fourth-order combination of central differences. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…ning it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
fdtd.ModeMonitor(name, plane=..., wavelengths=..., modes=n) lowers to a flux plane over exactly the mode window and, when the result is adapted, projects its corrected Fourier fields (node-plane E against the mean of the two H half planes, the FluxMonitor pairing) onto the n largest-index modes solved at each wavelength. The exact unconjugated orthogonality of the discrete modes separates each mode and each direction; forward and backward amplitudes and spectral energies come out in the FluxMonitor's units, so a field made of these modes sums to its flux. The window's static refusals now run at check and prepare. The window is solved from the structures that reach the plane only, so a traced scatterer elsewhere keeps its derivative (measured against extrapolated central differences on JAX and Torch). The engine placeholder names the public monitor, and the spelling table moves ModeMonitor from the unimplemented names to the shared ones. The registered MM2 (a broadband pulse in a closed metal guide) and MM4 (a too-coarse difference step) failures are kept as strict expected failures beside their registered replacements, as the record states. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…ugh a PML Before computing: the guided mode's PML reflection for a slab and a rectangular core continued through the z faces, its decrease with a thicker layer, stability over a long run, and the refusals that keep the door narrow (smoothed cores stay refused). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
A ModeMonitor across an Open face was refused at run time: its flux plane read the window's edge node, which on the physical edge is the absorbing layer's first. The window now stops one cell inside the physical edge on each Open side, for the monitor and for solve_modes, and a regression test holds both to the same modes. The M3 slab's recorded numbers are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…ugh a PML Before computing: the guided mode's PML reflection for a slab and a rectangular core continued through the z faces, its decrease with a thicker layer, stability over a long run, and the refusals that keep the door narrow (smoothed cores stay refused). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
A SnappedBox may declare Structure(continuation=('z-', 'z+')) (any one
axis) when it reaches those physical faces; it is extended through
their padding with its cross-section unchanged, so every layer of the
PML sees the same medium and the engine's absorbing-layer rule holds.
Each face keeps its own reference medium. A SnappedSlab may name the
faces of the axes it runs along, which the crossing rule now accepts as
explicit consent. A smoothed core narrower than the cross-section stays
refused, and so does a continued core touching an Open face of another
axis. The Structure docstring and the engine's refusal remedy describe
the door; D1-D3 test it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…on an InvariantAxis) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
D1 (slab, launched by the TE0 initial field of the amendment) and D2 (rectangular SnappedBox core) reflect 4.3e-8 and 1.3e-6 of the guided mode's power with the default 12-cell PML, and 3.5e-16 and 3.5e-12 with 24 cells; D1 raises no GrowingFieldWarning in 400 periods. D3's refusals are joined by tests for a core reaching only one named face, for faces of two axes, for the lowered core spanning the padding, and for the registered scenes passing check and prepare; each rule was broken on purpose and caught. The manual's general-scene limits, the Open-face table and the waveguide-modes page describe the door (EN and KO), and the stale "no mode monitors" line now points at the modes page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…r branch The registration was pushed as eb2c43d on the earlier ModeMonitor head and replayed as d8d58ef after that branch moved; this merge keeps the first pushed commit, the public record of when the criteria were written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk # Conflicts: # docs/locales/ko/pages/validation/fdtd/fd-waveguide-through-pml.md # docs/validation/fdtd/fd-waveguide-through-pml.md
S1-S8 for fdtd.ModeSource, written before the source is first run: injection and leakage against their exact grid predictions, absolute power against the pulse's continuous spectrum, the run's own index converging to the exact slab index, a butt joint against continuum mode matching, backends, derivatives against central differences, and refusals by code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
fdtd.ModeSource(name, plane=..., pulse=..., direction=, mode=, amplitude=, phase=, delay_seconds=) solves mode `mode` of solve_modes on its plane at the pulse's centre wavelength and lowers to a one-sided total-field/scattered-field sheet whose incident field is that mode: E on the node plane, H on the half plane upstream, the H row advanced by the mode's half-cell phase and group delay. At the centre wavelength it launches exactly the mode, exactly one way; elsewhere the injected and leaked amplitudes follow in closed form from the actual waveform rows and the modes' unconjugated orthogonality, and ModeMonitor(source=...) reports them (injected, leakage and their energies). A unit amplitude is 1 W of continuous wave (per metre of each invariant axis). The kernel term is a sheet of correction slabs, each a pattern times one of the term's waveform rows; waveform_table reads per-row (phase, delay) offsets. The mode window's own lowering leaves sources and monitors out, so a ModeSource does not re-enter it. A monitor within a cell of the sheet is refused (monitor.source_sheet), as are a direction off the normal, a bad mode index, source= naming no ModeSource, and a traced pulse wavelength. The engine placeholder names the public source and the spelling table moves ModeSource to the shared names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
G1-G8 for fdtd.GaussianBeam, written before the beam is first run: the waist on the focal plane, the Gouy phase and the focal shift through an interface against exact continuum angular spectra, absolute power in two and three dimensions, back-radiation against its exact grid prediction, backends, derivatives against central differences, and refusals by code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…reaches the edge rule) At the sheet the beam is 2e-3 of its peak on the outermost cells of the registered +-3 um cross-section, above the 1e-3 the source admits; the cross-section is widened to +-3.5 um. No limit changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…sed) The 0.6 um focal field's angular spectrum is 3% of its peak at the light line, so its propagating part rings out as 1/r and the source refuses it (source.beam_size). G3 uses a 1.0 um waist; its limits are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
fdtd.GaussianBeam(name, plane=..., pulse=..., waist=, focus=, polarization=, direction=, amplitude=, phase=, delay_seconds=) lowers to the mode source's one-sided sheet with a beam for its incident field. The beam is the propagating part of the focal field's angular spectrum, built from the grid's own discrete plane waves in the homogeneous medium at the plane (discrete Gauss and Faraday laws, the grid's dispersion), so at the centre wavelength it is an exact grid solution launched one way. Its complex patterns ride cosine and sine waveform rows; a unit amplitude carries 1 W of continuous wave. launched_power predicts the forward and backward spectral energy exactly per plane wave. Refused by code: a direction off the normal, a polarization along it, a non-positive waist, a focus that is not a point, a traced waist or focus, a medium that is not uniform on the plane, a metal or periodic face across it, and a beam the cross-section or the transform grid cannot hold. The spelling table has no unimplemented stage-7 names left. Measured so far (criteria registered beforehand): G1, G3, G4 (2-D), G5 pass; G2's limit at 0.05 um fails (2.2e-3 rad against 2e-3) and is kept as a strict expected failure beside its passing convergence order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
With a 1 um waist the 3-D beam's light-line ripple stays above the source's 1e-7 on its largest transform grid, so the source refuses it. The case uses Setup B's 1.5 um waist in a +-4.5 um cross-section; the limit is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…length limits Two deliberate breaks survived: unsigned H patterns for a -z source (the exact prediction follows whatever the sheet holds) and the Ex/Hy corrections (TE0 has neither). The mirrored source is now also held to S2's one-way and S3's power limits, and a TM0 launch is checked at S1-S3's limits; both breaks, and the Eu correction's sign, now fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…length limits Two deliberate breaks survived: unsigned H patterns for a -z source (the exact prediction follows whatever the sheet holds) and the Ex/Hy corrections (TE0 has neither). The mirrored source is now also held to S2's one-way and S3's power limits, and a TM0 launch is checked at S1-S3's limits; both breaks, and the Eu correction's sign, now fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
G2 failed as registered at 0.05 um (2.20e-3 rad against 2e-3); its second-order convergence passes. The limit is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk # Conflicts: # docs/guide/fdtd/model.md # docs/locales/ko/pages/guide/fdtd/model.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
The scatterer's permittivity was not registered; at 3.0 the run was refused before any step (7.7 cells per wavelength against 8). It is 2.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
tests/api/test_docs_contract.py refuses a path that resolves only from the citing file's directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…as computed As registered, the reverse-mode runs keep every one of about 12k steps (about 8 MB a step on JAX here); the first attempt was killed for memory with nothing computed, and checkpoint_steps is admitted on Torch CUDA only. As for MM4b, the derivatives and central differences are of the same truncated run in a smaller domain. Derivatives, steps and limits are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
… pass) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…uy-phase accuracy G2 failed as registered (2.20e-3 rad at 0.05 um against 2e-3) and stays failed with its limit unchanged. This records, separately from the verdicts, that GaussianBeam is supported: the difference is the grid's dispersion (the beam is exact for the grid; G1, G4 and G5 hold to 1e-8 or better), it falls at second order and is inside the limit at 0.025 um, and it is of the size by which the paraxial formula departs from the exact beam. The guide (EN and KO) gains an accuracy section and the class docstring states the measured error and asks for spacing convergence. No runtime warning is added: these grids are above the 8 to 12 cells per wavelength where CoarseMeshWarning already warns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…-value records) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
…rint it in the records golden_stage7_cross_solver.json holds what Meep 1.35.0 and FDTDX 0.6.3 measured on the stage-7 cases (reported and propagated slab index, one-way mode launch, butt joint, a core run into the absorber, Gaussian-beam width, Gouy phase, back-radiation and focal shift), beside the Wavebit numbers the validation records print. Its wavebit.reference-values/1 record states each tool's build, settings, what was and was not matched, and that each ran in its own process from inputs in physical units. fd-mode-source.md and fd-gaussian-beam.md (EN and KO) gain a "Comparison with Meep and FDTDX" section: evidence, not acceptance, and no verdict changes. The GaussianBeam support decision cites it as context. The new test holds both tables to the golden and asserts each conclusion the sections draw (the runs are one discrete system, only the grid-mode launch is one-way at the centre, the external absorber values are a readout floor, Meep's beam is wide at every resolution, Wavebit's Gouy difference is the smallest and falls at second order). A doc cell, a Korean cell and a golden value were each changed on purpose and the tests failed; each was restored. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stage 7 of the FDTD engine on the public
wavebit.fdtdlifecycle, in one PR. It was first opened as five stacked pieces; #114 and #115 are folded in here and closed. Each piece keeps its own self-contained commits. Its acceptance criteria were committed before its first computation, and every amendment made before a run is a separate commit.What lands
fdtd.solve_modes. Waveguide modes of the discrete Yee system, on the grid and the smoothed coefficients the time stepper uses. Power is normalized as aFluxMonitormeasures it. Validation record:docs/validation/fdtd/fd-waveguide-modes.md.fdtd.ModeMonitor. Forward and backward amplitudes and spectral energies per mode on a plane, from the run's Fourier fields. It uses the modes' exact unconjugated orthogonality.SnappedBoxmay declarecontinuation=('z-', 'z+'), and aSnappedSlabmay name the faces of the axes it runs along. Smoothed cores stay refused. Record:fd-waveguide-through-pml.md.fdtd.ModeSource. A one-sided TFSF sheet whose incident field is a solved mode. It is exactly one-way at the centre wavelength. Off-centre, injection and leakage are predicted in closed form, andModeMonitor(source=)reports them. Record:fd-mode-source.md.fdtd.GaussianBeam. A focused beam on the same sheet, built from the grid's own discrete plane waves, so it is an exact grid solution at the centre wavelength. Record:fd-gaussian-beam.md.Evidence
Registration commits:
eb26ab952beba4f9fb9e6,c09788f54f6e3a7c2f04324ab6a5,eb2c43d,b6fe448,9c383c2.Failures recorded, limits unchanged. Each is kept as a strict expected failure beside its registered replacement or its passing part:
Support decision for G2 (
fce5d22), recorded separately from the verdict.GaussianBeamis supported, and its Gouy-phase accuracy is stated in three places: the guide (EN and KO), the class docstring and the validation record. The reasons:No runtime warning is added: these grids are above the 8 to 12 cells per wavelength where
CoarseMeshWarningalready warns.Amended before computing. S7 and G7 as registered need reverse mode to keep about 12k steps, more than 13 GB on JAX/CPU.
checkpoint_stepsis admitted only on Torch CUDA. As with MM4b, the derivatives and the central differences are both taken of the same truncated run in a smaller domain. The four derivatives and the 1e-6 limit are unchanged. The records list every amendment and its reason.Comparison with Meep and FDTDX (
59d6560), evidence, not acceptanceThe same cases were run in Meep 1.35.0 and FDTDX 0.6.3. Each ran in its own process from inputs in physical units, using public APIs only. Meep's source was not read.
The values are frozen in
tests/references/golden_stage7_cross_solver.json. Itswavebit.reference-values/1record states each tool's build and settings, and what was and was not matched.fd-mode-source.mdandfd-gaussian-beam.md(EN and KO) print the tables.test_stage7_cross_solver_golden.pyholds the tables and each conclusion drawn from them to the golden.What the comparison shows:
No verdict changes.
mainwas merged in (f134bca, no conflicts) to bring the reference-record format.Refused by name
Verification
tests/apiplus the comparison test: 1710 passed-W: clean59d6560: all checks green.Docs (EN/KO): the waveguide-modes and Gaussian-beam guide pages, the model page, the reference index, the source map, and the four validation records.
🤖 Generated with Claude Code
https://claude.ai/code/session_01EsCWzkwvzVkG7JYdnKJnRk