[docs] document scattering conventions and frozen-basis workflows
Update examples for sampled-interface tapers, explicit physical CPML spacing, copied SCPML widths, and the consolidated complex mode solver. Document breaking API changes, overlap measures, and PML convergence.
This commit is contained in:
parent
153536ee91
commit
7e407dd1ac
10 changed files with 152 additions and 29 deletions
|
|
@ -13,3 +13,17 @@
|
|||
::: meanas.fdfd.scpml
|
||||
|
||||
::: meanas.fdfd.farfield
|
||||
|
||||
## SCPML conventions
|
||||
|
||||
`stretch_with_scpml` now uses `-1` for the low-index face and `+1` for the
|
||||
high-index face, matching CPML and propagation conventions. It returns copied
|
||||
widths by default; pass `copy=False` to request mutation explicitly.
|
||||
|
||||
Both SCPML builders accept `kappa_function(depth)` for real stretching and
|
||||
`max_imag_ratio` to limit the final dimensionless `abs(Im(s))/Re(s)`. Start a
|
||||
mode-solver convergence study with `max_imag_ratio=1.0`: overly strong imaginary
|
||||
stretching can produce above-light-line PML artifacts. The cap is not a general
|
||||
spectral guarantee, and weaker absorption can increase boundary reflections.
|
||||
Check domain size, PML thickness, strength, mode localization, and residuals.
|
||||
The general scattering profile remains uncapped by default.
|
||||
|
|
|
|||
|
|
@ -13,3 +13,8 @@
|
|||
::: meanas.fdtd.energy
|
||||
|
||||
::: meanas.fdtd.phasor
|
||||
|
||||
CPML derivatives use electric widths for forward differences and magnetic
|
||||
widths for backward differences. `cpml_params(..., dx=1.0)` specifies the uniform
|
||||
physical cell width normal to a face; arbitrary nonuniform PML grading is not
|
||||
implemented by this constructor. Scale the timestep consistently with the grid.
|
||||
|
|
|
|||
|
|
@ -2,8 +2,90 @@
|
|||
|
||||
::: meanas.fdfd.waveguide_2d
|
||||
|
||||
::: meanas.fdfd.waveguide_2d_complex
|
||||
|
||||
::: meanas.fdfd.waveguide_3d
|
||||
|
||||
::: meanas.fdfd.waveguide_cyl
|
||||
|
||||
## 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
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ Relevant starting examples:
|
|||
scattering between two nearby waveguide cross-sections
|
||||
- `examples/eme_bend.py` for straight-to-bent mode matching with cylindrical
|
||||
bend modes and a cascaded bend-network example
|
||||
- `examples/eme_taper_cmt.py` for local-mode CMT through sampled continuously
|
||||
- `examples/eme_taper_cmt.py` for sampled-interface EME through continuously
|
||||
varying taper cross-sections
|
||||
- `examples/fdfd.py` for direct frequency-domain waveguide excitation
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue