[fdfd.waveguide_3d] improve handling of out-of-bounds overlap_e windows

This commit is contained in:
Jan Petykiewicz 2026-04-17 20:44:36 -07:00
commit f35b334100
2 changed files with 218 additions and 19 deletions

View file

@ -5,6 +5,8 @@ This module relies heavily on `waveguide_2d` and mostly just transforms
its parameters into 2D equivalents and expands the results back into 3D.
"""
from typing import Any, cast
import warnings
from typing import Any
from collections.abc import Sequence
import numpy
from numpy.typing import NDArray
@ -200,17 +202,33 @@ def compute_overlap_e(
Ee = expand_e(E=E, wavenumber=wavenumber, dxes=dxes,
axis=axis, polarity=polarity, slices=slices)
start, stop = sorted((slices[axis].start, slices[axis].start - 2 * polarity))
axis_size = E.shape[axis + 1]
if polarity > 0:
start = slices[axis].start - 2
stop = slices[axis].start
else:
start = slices[axis].stop
stop = slices[axis].stop + 2
clipped_start = max(0, start)
clipped_stop = min(axis_size, stop)
if clipped_start >= clipped_stop:
raise ValueError('Requested overlap window lies outside the domain')
if clipped_start != start or clipped_stop != stop:
warnings.warn('Requested overlap window was clipped to fit within the domain', RuntimeWarning)
slices2_l = list(slices)
slices2_l[axis] = slice(start, stop)
slices2_l[axis] = slice(clipped_start, clipped_stop)
slices2 = (slice(None), *slices2_l)
Etgt = numpy.zeros_like(Ee)
Etgt[slices2] = Ee[slices2]
# Note: We normalize so that (Etgt @ E.conj()) == 1, so (Etgt @ Etgt.conj) != 1
Etgt /= (Etgt.conj() * Etgt).sum()
norm = (Etgt.conj() * Etgt).sum()
if norm == 0:
raise ValueError('Requested overlap window contains no overlap field support')
Etgt /= norm
return cfdfield_t(Etgt)