2026-04-18 15:05:35 -07:00
|
|
|
# waveguides
|
|
|
|
|
|
|
|
|
|
::: meanas.fdfd.waveguide_2d
|
|
|
|
|
|
|
|
|
|
::: meanas.fdfd.waveguide_3d
|
|
|
|
|
|
|
|
|
|
::: meanas.fdfd.waveguide_cyl
|
2026-10-18 23:07:53 -07:00
|
|
|
|
|
|
|
|
## Overlap measures and normalization
|
|
|
|
|
|
|
|
|
|
`waveguide_2d.inner_product(..., measure="physical", conj_h=True)` uses real
|
|
|
|
|
Yee widths for physical Poynting power. `measure="stretched"` keeps complex
|
|
|
|
|
widths for coordinate reaction. `lorentz_metric` and `lorentz_overlap` default
|
|
|
|
|
to the stretched measure. Use the same grid and measure when constructing and
|
|
|
|
|
using dual fields. A real overlap grid still defines a consistent constructed
|
|
|
|
|
dual basis, even when the eigenproblem uses a separate PML grid.
|
|
|
|
|
|
|
|
|
|
`normalized_fields_e/h(..., normalization="lorentz")` normalizes unconjugated
|
|
|
|
|
self-reaction to one. This fixes phase up to a sign and is distinct from unit
|
|
|
|
|
forward power, which remains the default. Zero-power or self-orthogonal modes
|
|
|
|
|
raise `ValueError`; open self-orthogonal modes require paired primal/dual
|
|
|
|
|
normalization through `ModeBasis`.
|
|
|
|
|
|
|
|
|
|
## Targeted and reproducible mode solving
|
|
|
|
|
|
|
|
|
|
For modes near an effective index guess, use `solve_modes_near` with
|
|
|
|
|
`target_wavenumbers=[omega * n_guess]`. It targets the electric beta-squared
|
|
|
|
|
operator at `(omega * n_guess)**2`; `solve_modes_near_beta` instead targets the
|
|
|
|
|
first-order signed-beta operator. Both use the LU shift-invert backend and
|
|
|
|
|
support `eigensolver_opts={"v0": starting_vector}`. Factorization cost and
|
|
|
|
|
memory depend on the grid, so this is not universally faster than indexed
|
|
|
|
|
solving. `solve_modes` keeps its global mode-number semantics and now accepts
|
|
|
|
|
`rng` or `v0` for reproducible initialization.
|
|
|
|
|
|
|
|
|
|
`waveguide_3d.mode_from_2d` accepts a supplied transverse electric eigenvector
|
|
|
|
|
and reuses field reconstruction, normalization, numerical-dispersion
|
|
|
|
|
correction, Yee staggering, rotation, and full-grid embedding without solving
|
|
|
|
|
an eigenproblem.
|
|
|
|
|
|
|
|
|
|
## Interface and sampled-taper scattering
|
|
|
|
|
|
|
|
|
|
All scattering matrices use outgoing rows and incoming columns, ordered
|
|
|
|
|
`[left, right]`:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
[b_left ] [R_left T_right_to_left] [a_left ]
|
|
|
|
|
[b_right] = [T_left_to_right R_right] [a_right]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`get_s` and `get_abcd` require explicit `dxes`. Mixed Petrov-Galerkin testing is
|
|
|
|
|
the default: left electric duals test H continuity, and right magnetic duals
|
|
|
|
|
test E continuity. Both incidence directions are solved together with full
|
|
|
|
|
projection matrices. Mixed scattering supports unequal mode counts.
|
|
|
|
|
`formulation="galerkin"` selects equal-count left testing of both equations.
|
|
|
|
|
Neither formulation silently clips transmission. The optional `force_nogain`
|
|
|
|
|
and `force_reciprocal` flags are numerical projections, not general physical
|
|
|
|
|
tests for arbitrary open or evanescent modal coordinates.
|
|
|
|
|
|
|
|
|
|
`get_taper_s` replaces finite-difference CMT with half propagation in the left
|
|
|
|
|
basis, a midpoint interface, and half propagation in the right basis for each
|
|
|
|
|
sampled interval. Redheffer composition avoids growing passive backward
|
|
|
|
|
transfer branches. Refine section sampling and modal/PML bases to establish
|
|
|
|
|
convergence. The ineffective `rtol`, `atol`, and `max_step` arguments have been
|
|
|
|
|
removed. The existing `eme_taper_cmt.py` example filename is retained.
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
prepared = eme.prepare_taper(sections, dxes)
|
|
|
|
|
s_original = eme.evaluate_taper_s(prepared)
|
|
|
|
|
s_longer = eme.evaluate_taper_s(prepared, z_coords=prepared.z_coords * 1.2)
|
|
|
|
|
s_changed_beta = eme.evaluate_taper_s(
|
|
|
|
|
prepared, wavenumber_matrices=beta_matrices,
|
|
|
|
|
)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`PreparedTaper` owns read-only copies of phase-aligned interface data. Beta
|
|
|
|
|
matrix overrides have shape `(section, mode, mode)` in the original supplied
|
|
|
|
|
section bases; recorded basis transforms are applied automatically. Explicit
|
|
|
|
|
backward branches require backward beta overrides when forward beta is changed.
|
|
|
|
|
Evaluation performs no field overlaps or eigensolves. Length sweeps reuse the
|
|
|
|
|
sampled model; wavelength sweeps with reused fields are explicitly frozen-basis
|
|
|
|
|
approximations. Reprepare when fields, duals, grids, or formulations change.
|
|
|
|
|
|
|
|
|
|
`cascade_s(left, right, internal_modes=...)` connects spatially ordered S
|
|
|
|
|
matrices, including unequal external ports. Public `abcd_to_s` and `s_to_abcd`
|
|
|
|
|
use `[f_right, b_right] = ABCD @ [f_left, b_left]` and require equal port counts.
|
|
|
|
|
`get_taper_abcd` converts the stable S result; zero transmission or an
|
|
|
|
|
unrepresentable transfer matrix raises `LinAlgError`. Prefer S for long lossy
|
|
|
|
|
devices. Singular interface and cascade systems also raise contextual errors
|
|
|
|
|
rather than silently substituting pseudoinverses.
|
|
|
|
|
|
|
|
|
|
::: meanas.fdfd.eme
|