Skip to content

feat(ac-sweep): add port_aliases, holomorphic mode, and per-port z0 support - #37

Merged
cdaunt merged 12 commits into
mainfrom
fix/issue-30-port-aliases
Jul 30, 2026
Merged

feat(ac-sweep): add port_aliases, holomorphic mode, and per-port z0 support#37
cdaunt merged 12 commits into
mainfrom
fix/issue-30-port-aliases

Conversation

@cdaunt

@cdaunt cdaunt commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add port_aliases parameter to component decorators for port aliasing support
  • Replace circuit.ac() with circuit.sp() (AC method deprecated, removal in 0.3)
  • Add holomorphic=False flag to enable 2N×2N real-block system for non-holomorphic circuits (required for EO power modulation)
  • Support per-port and per-frequency z0 in AC sweep (scalar or array)
  • Add renormalize(S, z0_from, z0_to) function for frequency-dependent impedance transformation
  • Implement assemble_gc_complex_2n() for 4-block G/C extraction in complex circuits
  • Add Part 2b AC small-signal analysis section to ring modulator notebook with transient comparison
  • 24 tests passing; AC analysis ~168× faster than transient for ring modulator

Test plan

  • All existing tests pass
  • AC sweep tests with holomorphic=False for non-holomorphic circuits
  • Per-port z0 and renormalization tests
  • Ring modulator AC sweep matches transient simulation

🤖 Generated with Claude Code
https://claude.ai/code/session_01Ti1GWaiLy8ndzJ5maMVYYk

cdaunt and others added 8 commits July 26, 2026 10:52
Extends AC sweep analysis to support complex-valued (photonic) circuits via:
- assemble_gc_complex(): Extracts complex G/C matrices from 4-block Jacobian
  using Wirtinger formula for frequency-domain admittance
- setup_ac_sweep(): Added is_complex parameter to select real or complex
  assembly path; handles 2N block-format DC point for complex circuits
- Circuit.ac(): Removed ValueError guard blocking complex circuits; now passes
  is_complex through to setup_ac_sweep for seamless integration
- Tests: 5 comprehensive tests covering shapes, finiteness, passivity, JIT,
  and Circuit.ac() integration with photonic waveguide models
- Benchmarks: Import reformatting for consistency

Addresses GitHub issue #29.
Demonstrates that linearized AC analysis (one matrix solve per frequency) achieves the same EO bandwidth curve as transient sweep from Part 2, but ~168× faster. Adds three new cells explaining the 2N block approach for non-holomorphic EO circuits, extracting G/C Jacobian blocks at DC operating point, and comparing AC/transient/analytic curves. Updates table of contents and Part 2 introduction to reference Part 2b.
…ck system

Add nonholomorphic=True parameter to setup_ac_sweep() and Circuit.ac() to enable
full 2N×2N real-block AC analysis. Required for circuits with non-holomorphic
operations (jnp.real(), jnp.abs()) that couple the field and conjugate, making
the Wirtinger N×N system incomplete.

New functions:
- assemble_gc_complex_2n(): returns four separate Jacobian blocks [RR, RI, IR, II]
  for both G and C matrices, instead of collapsing via Wirtinger formula
- _setup_ac_sweep_2n(): AC sweep using 2N×2N real-block system with proper port
  terminations and S-parameter extraction at real-part indices

Updated:
- Circuit.ac(): added nonholomorphic parameter wired to setup_ac_sweep()
- setup_ac_sweep(): added nonholomorphic parameter, dispatches to _setup_ac_sweep_2n()
- tests: 3 new tests verifying equivalence with holomorphic for waveguides,
  Circuit.ac() interface, and JIT compatibility
…efault

Rename parameter from `nonholomorphic=False` to `holomorphic=True` across
`setup_ac_sweep()`, `Circuit.ac()`, and all tests. The positive default reads
more naturally — most photonic components are holomorphic; users opt out with
`holomorphic=False` when the circuit contains non-holomorphic operations like
`jnp.real()` or `jnp.abs()`.

- Update circuit.py and ac_sweep.py parameter and docstrings
- Flip conditional logic: `if nonholomorphic:` → `if not holomorphic:`
- Rename test functions: test_nonholomorphic_* → test_non_holomorphic_*
- Update all test calls to use holomorphic=False

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ti1GWaiLy8ndzJ5maMVYYk
… ring modulator

Add test_non_holomorphic_ring_modulator_matches_analytic() and helper
_ring_modulator_circuit() to verify that the 2N block system (holomorphic=False)
correctly handles non-holomorphic EO power modulation in ring modulators.
The test demonstrates that Wirtinger (holomorphic=True) produces >1 dB error
on power-domain quantities when jnp.real() breaks holomorphicity, while the
2N formulation matches analytic behavior to <0.01 dB.
Renamed ac() method to sp() for consistency with S-parameter naming.
The old ac() method now emits a DeprecationWarning (removed in 0.3)
and delegates to sp(). Updated all tests to use sp() and added
test_ac_deprecation_warning to verify backward compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ti1GWaiLy8ndzJ5maMVYYk
Add flexible impedance parameter to setup_ac_sweep() and circuit.sp()/ac():
- Accept scalar z0 (uniform across ports and frequencies)
- Accept (N_ports,) array for per-port reference impedance
- Accept (N_freqs, N_ports) array for per-frequency, per-port impedance

Implement _normalize_z0() helper to validate and broadcast z0 shapes.
Update both N×N holomorphic and 2N×2N real-block AC sweep paths to
receive z0 per-frequency via vmap to _solve_one_freq().

Add three tests: per-port scalar equivalence, per-port analytical match
at 75Ω, and per-frequency with varying z0 across frequencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ti1GWaiLy8ndzJ5maMVYYk
…fy z0

Remove per-frequency z0 from ac_sweep solve path (z0 is now scalar or
per-port only, constant across frequencies). Add renormalize(S, z0_from,
z0_to) function for post-hoc impedance renormalization. Simplify vmap
loop by removing z0 as a vmap'd argument. Update docstrings to document
the change and guide users to use renormalize for frequency-dependent
impedance needs.
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

cdaunt and others added 3 commits July 27, 2026 11:58
Add holomorphic parameter to @component and @source decorators to declare
whether components use non-holomorphic operations (jnp.real, jnp.abs, etc).
circuit.sp() now auto-infers holomorphic mode from component flags
(holomorphic="auto" by default), eliminating the need for users to manually
pass holomorphic=False.

- ComponentGroup.holomorphic aggregates per-component flags (defaults to True)
- _infer_holomorphic() checks if all groups are holomorphic
- RingEO marked as holomorphic=False
- Add test_holomorphic_auto_detection() to verify auto-detection path

Backward compatible: explicit holomorphic={True,False} overrides auto mode.
…ex circuits

Add runtime validation that warns when a component marked holomorphic=True uses
non-holomorphic JAX primitives (real, imag, conj, abs) on traced complex variables.
Runs at compile_circuit time for complex circuits only, avoiding false positives on
electronic-only circuits. Filters out operations on constants (e.g. conj(z0)) by
only flagging primitives with traced complex inputs.

- Added _jaxpr_has_non_holomorphic() in base_component.py to walk jaxpr and detect
  non-holomorphic primitives on traced complex variables
- Added _validate_holomorphic_flags() in circuit.py called from compile_circuit when
  is_complex=True
- Added test_holomorphic_jaxpr_validation_warns to verify warnings on bad components
- Added test_holomorphic_jaxpr_validation_no_false_positive to ensure electronic
  circuits don't trigger false warnings

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ti1GWaiLy8ndzJ5maMVYYk
…olomorphic types

Make the 2N×2N real-block system the default for AC analysis, ensuring correctness
for non-holomorphic components (diodes, transistors, nonlinear devices). Explicitly
mark as holomorphic=True only components guaranteed to preserve analyticity
(resistors, capacitors, inductors, ideal op-amps, optical waveguides, etc.).
Also updates test fixtures and adds documentation on holomorphic components.
@cdaunt
cdaunt marked this pull request as ready for review July 27, 2026 11:48
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@cdaunt

cdaunt commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator Author

fixes #29

@cdaunt
cdaunt force-pushed the fix/issue-30-port-aliases branch from f93a4c8 to 1332ab3 Compare July 27, 2026 21:07
@cdaunt
cdaunt changed the base branch from development to main July 27, 2026 21:13
@cdaunt
cdaunt merged commit 6b6c995 into main Jul 30, 2026
6 checks passed
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