Skip to content

Follow-ups to #142: jit (0, 1) abort, v10 tetm migration, tetm docs, test_boundary x64, chapter 12 - #143

Merged
yonghakim merged 5 commits into
mainfrom
claude/rcwa-tetm-jit-followups
Nov 3, 2026
Merged

yonghakim merged 5 commits into
mainfrom
claude/rcwa-tetm-jit-followups

Conversation

@yonghakim

@yonghakim yonghakim commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

What changes

Five independent changes found while preparing #142, the pure 1D TE/TM path. Each is its own self-contained commit. This branch starts from main 93cf7cb, not from #142, so the two PRs land independently.

  1. fix(rcwa): a jitted run of the Jones pair (0, 1) no longer aborts the process.
    • The symptom: jax.jit of a public rcwa run with PlaneWave(polarization=(0., 1.)) killed Python under jit and jit(grad) on jax/jaxlib 0.11.0. It raised no exception.
    • The cause: the prepared run's nonzero-polarization guard (_lifecycle._runtime_checks) took xp.abs(a)**2. XLA's algebraic simplifier reads the complex constant [0, 1] as an iota and rewrites abs(iota) to the iota itself, which has the wrong (complex) type. The compile then fails a RET_CHECK in HandleAbs.
    • The fix: the guard now takes real(a * conj(a)). Its truth value is the same.
  2. fix(migration): a v10 tetm declaration migrates to the word for the same light.
    • migrate_legacy_jobs read old.tetm.name, but the v10 reader stores the word 'te'/'tm', so every v10 document that declared tetm raised AttributeError.
    • It now maps through the reader's own normalizer: 'te' becomes 's' and 'tm' becomes 'p'.
  3. docs: two statements that treated tetm as current.
    • solver-integration.md named a wavebit.Tetm that does not exist.
    • Chapter 12's "incident and output polarization" section stated s_inc/p_inc and tetm= in the present tense. It now gives the current reading and keeps the earlier interface in a marked box, in English and Korean.
  4. test(rcwa): tests/rcwa/test_boundary.py asks for JAX double precision itself.
    • The symptom: under pytest-xdist, 11 of its tests computed their JAX solves in float32 and failed, though the file passes alone.
    • The cause: importing the private JAX backend lifts JAX's 32-bit cap, but not inside a public run's Execution scope, which suppresses that lift on purpose. A worker whose first JAX test was a public single-precision run therefore left x64 off for every later engine JAX solve.
    • The fix: the file calls _enable_x64() at import, guarded for an absent JAX, as test_laurent_factorization.py already does.
  5. docs(learn): chapter 12 reads results through the current API, in English and Korean.
    • It now uses rcwa.run, the ports' order(m, n) with .efficiency / .amplitude_s / .amplitude_p, the (wavelength, order_v, order_u) shape, orders_u/orders_v, k_parallel/k_normal, reference['plane'], outputs['power_entering'] and absorption.
    • The earlier spellings move into "Earlier interface" boxes, and the chapter note is gone.
    • Every printed value was re-measured, with each snippet run as written. The values are unchanged.

Verification

  • Abort fix.
    • The repro now runs under jit, jit(grad), vmap and grad, and its jitted R matches the eager NumPy value to 1e-12.
    • The new test test_jit_of_the_jones_pair_0_1_compiles_instead_of_aborting runs the jitted call in a subprocess and fails with the old guard restored.
    • The same script ran on main and on this branch and gave 184 arrays, all bit-identical: amplitudes, efficiencies, powers, fields, S blocks, jit/grad/vmap values, torch gradients and single precision.
  • Migration. test_a_tetm_declaration_migrates_to_the_word_for_the_same_light covers 'te', 'tm' and 'TM'. It holds R, T and all four s/p amplitudes against the original v10 run to 2e-13, and all three cases fail with the old line restored.
  • test_boundary. A scratch pytest plugin ran a public single-precision JAX run at session start. In that order, the three failing tests that were run all failed before the fix, and all eleven pass after it. The whole file passes in that order (97/97) and alone.
  • Chapter 12. The snippets were run as written on Chapter 4's grating: 0.2053, 0.3531, 0.7947, (1, 1, 21), and |t_s(0, 0)| = 0.4852 at 115.5°.
  • Docs. sphinx-build -W -b html docs builds clean, and tests/api/test_docs_contract.py passes (166).
  • Public lifecycle files, default tier (26 files, not slow and not research, 4 workers), on the first three commits: 1240 passed, 11 failed. All 11 failures are in tests/rcwa/test_boundary.py, and commit 4 fixes them.
  • Environment: conda env wavebit, Python 3.12.9, numpy 2.5.1, jax/jaxlib 0.11.0, torch 2.14.1, macOS arm64.

Not done

🤖 Generated with Claude Code

yonghakim and others added 5 commits November 4, 2026 01:32
… process

jax.jit of a public rcwa run whose PlaneWave polarization was exactly (0, 1)
killed the Python process rather than raising, under jit and jit(grad) alike,
on jax/jaxlib 0.11.0. The cause was the prepared run's nonzero-polarization
guard, which squared the pair with xp.abs(a)**2. XLA's algebraic simplifier
reads the complex constant [0, 1] as an iota and rewrites abs(iota) to the iota
itself, a complex value where a real one belongs. The compile then fails a
RET_CHECK in HandleAbs and aborts. (1, 0), the word 'p', and eager jax.grad and
vmap were unaffected.

The guard now takes |a|^2 as real(a * conj(a)). Its truth value is the same, so
nothing it guards moves. The same script ran on origin/main 93cf7cb and on this
commit and gave 184 arrays, all bit-identical: amplitudes, efficiencies, powers,
fields, scattering blocks, jit/grad/vmap values, torch gradients and single
precision.

Test: test_jit_of_the_jones_pair_0_1_compiles_instead_of_aborting runs the
jitted call in a subprocess, so a regression fails the test rather than ending
the session that runs it. It holds jit against the eager NumPy run to 1e-12 and
requires a finite jit(grad). With the old guard restored it fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ame light

migrate_legacy_jobs read old.tetm.name.lower(), but the v10 reader stores the
word ('te' / 'tm', _normalise_tetm), not a Tetm member. Every v10 document that
declared incidence.tetm therefore raised AttributeError: 'str' object has no
attribute 'name'. It now maps through the same normalizer: 'te' becomes 's'
and 'tm' becomes 'p', case-insensitively.

Test: test_a_tetm_declaration_migrates_to_the_word_for_the_same_light covers
'te', 'tm' and 'TM'. It runs the migrated job and holds R, T and all four s/p
amplitudes against the original v10 run to 2e-13. With the old line restored all
three cases fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- development/solver-integration.md: there is no public wavebit.Tetm. The
  engine accepts members of its own wavebit._common.enums.Tetm.
- learn/fundamentals/results.md, and its Korean page: the "incident and output
  polarization" section described s_inc / p_inc and tetm= in the present tense.
  It now states the current reading: amplitude_s / amplitude_p are output
  polarization, the incident polarization is the PlaneWave's, and two runs give
  the s and p responses. The earlier interface's three result objects move into
  an "Earlier interface" box.

The rest of chapter 12 is still written against the earlier interface
(solver.solve(), result.order) under the chapter note; rewriting it is a
separate piece.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Under pytest-xdist, 11 tests in tests/rcwa/test_boundary.py computed their JAX
solves in float32 and failed, e.g. 0.8902014493942261 where 0.890202199751976
+- 1e-12 was expected. The file passed when run alone.

The cause: importing the private JAX RCWA backend lifts JAX's 32-bit cap, but
not inside a public run's Execution scope, which suppresses the legacy lift on
purpose. A worker whose first JAX test was a public single-precision run
imported the backend inside that scope with x64 off, and every later engine
JAX solve in the file ran in float32. A public run with precision='single',
followed by a legacy JAX solver, reproduces it directly (T dtype float32).

The file now calls `_enable_x64()` at import, guarded for an absent JAX, as
tests/rcwa/test_laurent_factorization.py already does. To test the fix, a
scratch pytest plugin ran a public single-precision JAX run at session start.
Before the fix, the three of the eleven run in that order all failed. After it, all eleven passed in that order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"12. Reading results" still taught the earlier interface under its chapter
note: solver.solve(), result.order(m, n).R, result.r_s and (1, 21) arrays. It
now uses rcwa.run, in English and in Korean together:

- result.reflection / result.transmission .order(m, n) with .efficiency and
  .amplitude_s / .amplitude_p;
- the (wavelength, order_v, order_u) shape, where the zeroth order is
  T[0, 0, 10];
- orders_u / orders_v on each port, amplitude_xyz, and k_parallel / k_normal
  for the evanescent test;
- reference['plane'] and the cell-centre lateral reference for the phases;
- result.outputs['power_entering'] and result.absorption, one value per
  wavelength.

The earlier spellings (solver.solve(), result.order, result.incident,
answers='efficiency', R_s / T_p) move into "Earlier interface" boxes, and the
chapter note is gone. Every printed value was re-measured through the current
API on Chapter 4's grating, with the snippets run as written: 0.2053, 0.3531,
0.7947, (1, 1, 21), and |t_s(0, 0)| = 0.4852 at 115.5 degrees. The values are
unchanged, and Figure 12-1's labels carry no API names, so the figure stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@yonghakim yonghakim changed the title rcwa: jit of the Jones pair (0, 1) no longer aborts; v10 tetm migrates; tetm doc leftovers Follow-ups to #142: jit (0, 1) abort, v10 tetm migration, tetm docs, test_boundary x64, chapter 12 Nov 3, 2026
@yonghakim
yonghakim marked this pull request as ready for review November 3, 2026 17:24
@yonghakim
yonghakim enabled auto-merge (rebase) November 3, 2026 17:25
@yonghakim
yonghakim merged commit 34f5cea into main Nov 3, 2026
65 checks passed
@yonghakim
yonghakim deleted the claude/rcwa-tetm-jit-followups branch November 3, 2026 17:46
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