FDFD¶
Backend lightsmith-fdfd (method fdfd, modules lightsmith.backends.fdfd and lightsmith.backends._fdfd).
A 2D finite-difference frequency-domain solver for devices. It gives adjoint
gradients with respect to every permittivity pixel, which makes it the engine for
inverse design. It runs on the CPU or a CUDA GPU.
Method¶
- Equation. The scalar 2D Helmholtz equation on a Yee grid: TM solves for E_z, TE for H_z with 1/ε at cell edges. A graded stretched-coordinate PML is added outside the domain (Shin & Fan 2012).
- Geometry. Permittivity comes from supersampled fill fractions. 3D geometries are cut at the domain centre in z.
- Ports. Port modes come from a 1D slab eigensolver on the same discretisation, so they are exact discrete modes. They are launched as unidirectional total-field/scattered-field sources.
- S-parameters. Each port's field is decomposed into forward and backward modal amplitudes. With every port excited, S = C·A⁻¹, which also removes waves that re-enter from imperfect PMLs.
- Linear solvers. SciPy SuperLU on the CPU. On the GPU, a block-tridiagonal Schur-complement LU in PyTorch, suited to devices up to about 500 cells across.
- Gradients. One transposed (adjoint) solve per wavelength, reusing the forward factorisation.
FDFD.differentiable_solve(...)exposes them as a PyTorch autograd function.
Options¶
options["fdfd"] or options["lightsmith-fdfd"].
| Option | Default | Meaning |
|---|---|---|
polarization |
"te" |
"te" means E in the xy plane (H_z); "tm" means E_z |
dl_nm |
None |
Cell size. Default λ_min / (cells_per_wavelength · n_max). |
cells_per_wavelength |
20 |
Used for the default cell size |
pml_cells |
16 |
PML cells added outside the domain, as one value or (x, y). 0 puts a wall on that axis. |
pml_reflection |
1e-8 |
Target normal-incidence reflection |
solver |
"auto" |
"scipy", "block", or "auto" (SuperLU on the CPU, block LU on the GPU) |
precision |
"double" |
Factorisation precision of the block solver |
subsamples |
4 |
Supersampling per axis (1–16) |
max_cells |
4000000 |
Refuse larger grids |
Validation¶
All tests are in tests/test_fdfd.py.
| Test | Reference | Tolerance |
|---|---|---|
test_straight_waveguide_transmits (TE and TM) |
|S21| = 1; discrete propagation phase | 1e-4; |S11| < 1e-3; phase < 1e-3 rad |
test_slab_mode_matches_analytic_neff (TE and TM) |
analytic slab neff | < 1e-3 at dl = 5 nm; second-order convergence |
test_multimode_ports_are_orthogonal |
no mode conversion in a straight guide | 1e-4 |
test_power_conservation_closed_guide (TE and TM): lossless scatterers in a parallel-plate guide |
power conservation; reciprocity | column sums 1e-6; S = Sᵀ to 1e-8 |
test_bend_transmission_grows_with_radius |
qualitative, plus passivity | T(R = 1.5 µm) > 0.95 |
test_y_splitter_is_symmetric |
symmetry | |P2 − P3| < 1e-6 |
test_adjoint_gradient_matches_finite_differences (TE and TM) |
central differences | 1e-3 relative |
test_block_solver_matches_scipy_on_cpu |
SuperLU | 1e-9 |
test_gds_layout_device |
explicit structures | 1e-12 |
test_gpu_matches_cpu (gpu) |
CPU | S to 1e-10; gradients 1e-6 |
Limits¶
- 2D only (
dimension=2); 3D FDFD is not implemented yet. Ports cannot be normal to z. - Raises an error when:
- the grid exceeds
max_cells; - a port window is too narrow or too close to the PML;
- a port has fewer propagating modes than requested;
- the grid is too coarse for a mode (reduce
dl_nm). - Warns when a port mode is not guided, and when output power exceeds input by more than 1 % in a
lossless device (refine
dl_nmor thicken the PML).