(
monitors: Iterable[ObjectiveQuantity], monitor_values_grad: onp.ndarray
)
| 219 | |
| 220 | |
| 221 | def create_adjoint_sources( |
| 222 | monitors: Iterable[ObjectiveQuantity], monitor_values_grad: onp.ndarray |
| 223 | ) -> List[mp.Source]: |
| 224 | monitor_values_grad = onp.asarray( |
| 225 | monitor_values_grad, |
| 226 | dtype=onp.complex64 if mp.is_single_precision() else onp.complex128, |
| 227 | ) |
| 228 | if not onp.any(monitor_values_grad): |
| 229 | raise RuntimeError( |
| 230 | "The gradient of all monitor values is zero, which " |
| 231 | "means that no adjoint sources can be placed to set " |
| 232 | "up an adjoint simulation in Meep. Possible causes " |
| 233 | "could be:\n\n" |
| 234 | " * the forward simulation was not run for long enough " |
| 235 | "to allow the input pulse(s) to reach the monitors" |
| 236 | " * the monitor values are disconnected from the " |
| 237 | "objective function output." |
| 238 | ) |
| 239 | adjoint_sources = [] |
| 240 | for monitor_idx, monitor in enumerate(monitors): |
| 241 | # `dj` for each monitor will have a shape of (num frequencies,) |
| 242 | dj = onp.asarray( |
| 243 | monitor_values_grad[monitor_idx], |
| 244 | dtype=onp.complex64 if mp.is_single_precision() else onp.complex128, |
| 245 | ) |
| 246 | if onp.any(dj): |
| 247 | adjoint_sources += monitor.place_adjoint_source(dj) |
| 248 | assert adjoint_sources |
| 249 | return adjoint_sources |
nothing calls this directly
no test coverage detected