calculate_gradient_fields#

BaseFom.calculate_gradient_fields(fdtd_session: FdtdSession, parametrization, symmetry_factors: list = None) ndarray#

Compute the gradient of the FOM with respect to permittivity using adjoint fields.

The implementation runs in two phases:

  1. Forward-state phase: with the forward .fsp loaded, every entry’s scaling factor, forward fields, and any subclass-specific forward-side aux data are gathered (_collect_fwd_side_aux()). All entries share the same forward project, so this typically runs a single fdtd.load even for multi-port FOMs.

  2. Adjoint-state phase: for every entry, _compute_adjoint_fields_phased() loads that entry’s adjoint .fsp and assembles the adjoint fields (consuming the per-entry aux gathered in phase 1). The per-wavelength gradient accumulation is then done in pure NumPy.

Keeping all forward-state reads in phase 1 and all adjoint-state reads in phase 2 makes the file-load pattern fwd adj_1 adj_2 ... rather than fwd adj_1 fwd adj_2 .... Each fdtd.load costs ~700 ms of deserialization, so avoiding the back-and-forth is a significant speed-up for multi-port FOMs. Combined with the getresult cache on FdtdSession, repeat forward reads across entries become cache hits.

Parameters:
fdtd_sessionFdtdSession

FDTD session providing forward and adjoint field data.

parametrizationBaseParametrization

Current geometry parametrization used to compute the scaling factor.

symmetry_factorslist of int, optional

Per-monitor symmetry factors (from fom_symmetry_factors). When provided, the Jacobian of the FOM is divided by each monitor’s factor before accumulating gradient contributions, so that monitors placed entirely within the symmetric part of the simulation region are weighted correctly.

Returns:
np.ndarray

Real-valued gradient field array of shape (nx, ny, nz, 3) summed over all simulation results and wavelengths.