type hints and lint

This commit is contained in:
Forgejo Actions 2026-04-21 21:13:34 -07:00
commit c6c9159b13
30 changed files with 198 additions and 136 deletions

View file

@ -683,7 +683,16 @@ def eigsolve(
return numpy.abs(trace)
if False:
def trace_deriv(theta, sgn: int = sgn, ZtAZ=ZtAZ, DtAD=DtAD, symZtD=symZtD, symZtAD=symZtAD, ZtZ=ZtZ, DtD=DtD): # noqa: ANN001
def trace_deriv(
theta: float,
sgn: int = sgn,
ZtAZ=ZtAZ, # noqa: ANN001
DtAD=DtAD, # noqa: ANN001
symZtD=symZtD, # noqa: ANN001
symZtAD=symZtAD, # noqa: ANN001
ZtZ=ZtZ, # noqa: ANN001
DtD=DtD, # noqa: ANN001
) -> float:
Qi = Qi_func(theta)
c2 = numpy.cos(2 * theta)
s2 = numpy.sin(2 * theta)

View file

@ -27,11 +27,13 @@ from scipy import sparse
from ..fdmath import dx_lists2_t, vcfdfield2
from .waveguide_2d import inner_product
type wavenumber_seq = Sequence[complex] | NDArray[numpy.complexfloating] | NDArray[numpy.floating]
def _validate_port_modes(
name: str,
ehs: Sequence[Sequence[vcfdfield2]],
wavenumbers: Sequence[complex],
wavenumbers: wavenumber_seq,
) -> tuple[tuple[int, ...], tuple[int, ...]]:
if len(ehs) != len(wavenumbers):
raise ValueError(f'{name} mode list and wavenumber list must have the same length')
@ -61,9 +63,9 @@ def _validate_port_modes(
def get_tr(
ehLs: Sequence[Sequence[vcfdfield2]],
wavenumbers_L: Sequence[complex],
wavenumbers_L: wavenumber_seq,
ehRs: Sequence[Sequence[vcfdfield2]],
wavenumbers_R: Sequence[complex],
wavenumbers_R: wavenumber_seq,
dxes: dx_lists2_t,
) -> tuple[NDArray[numpy.complex128], NDArray[numpy.complex128]]:
"""
@ -118,9 +120,9 @@ def get_tr(
def get_abcd(
ehLs: Sequence[Sequence[vcfdfield2]],
wavenumbers_L: Sequence[complex],
wavenumbers_L: wavenumber_seq,
ehRs: Sequence[Sequence[vcfdfield2]],
wavenumbers_R: Sequence[complex],
wavenumbers_R: wavenumber_seq,
**kwargs,
) -> sparse.sparray:
"""
@ -151,9 +153,9 @@ def get_abcd(
def get_s(
ehLs: Sequence[Sequence[vcfdfield2]],
wavenumbers_L: Sequence[complex],
wavenumbers_L: wavenumber_seq,
ehRs: Sequence[Sequence[vcfdfield2]],
wavenumbers_R: Sequence[complex],
wavenumbers_R: wavenumber_seq,
force_nogain: bool = False,
force_reciprocal: bool = False,
**kwargs,

View file

@ -1,23 +1,24 @@
"""
Functions for performing near-to-farfield transformation (and the reverse).
"""
from typing import Any, cast, TYPE_CHECKING
from typing import Any, cast
from collections.abc import Sequence
import numpy
from numpy.fft import fft2, fftshift, fftfreq, ifft2, ifftshift
from numpy import pi
from numpy.typing import NDArray
from numpy import complexfloating
from ..fdmath import cfdfield_t
if TYPE_CHECKING:
from collections.abc import Sequence
type farfield_slice = NDArray[complexfloating]
type transverse_slice_pair = Sequence[farfield_slice]
def near_to_farfield(
E_near: cfdfield_t,
H_near: cfdfield_t,
E_near: transverse_slice_pair,
H_near: transverse_slice_pair,
dx: float,
dy: float,
padded_size: list[int] | int | None = None
padded_size: Sequence[int] | int | None = None
) -> dict[str, Any]:
"""
Compute the farfield, i.e. the distribution of the fields after propagation
@ -58,7 +59,7 @@ def near_to_farfield(
raise Exception('H_near must be a length-2 list of ndarrays')
s = E_near[0].shape
if not all(s == f.shape for f in E_near + H_near):
if not all(s == f.shape for f in [*E_near, *H_near]):
raise Exception('All fields must be the same shape!')
if padded_size is None:
@ -123,11 +124,11 @@ def near_to_farfield(
def far_to_nearfield(
E_far: cfdfield_t,
H_far: cfdfield_t,
E_far: transverse_slice_pair,
H_far: transverse_slice_pair,
dkx: float,
dky: float,
padded_size: list[int] | int | None = None
padded_size: Sequence[int] | int | None = None
) -> dict[str, Any]:
"""
Compute the farfield, i.e. the distribution of the fields after propagation
@ -164,7 +165,7 @@ def far_to_nearfield(
raise Exception('H_far must be a length-2 list of ndarrays')
s = E_far[0].shape
if not all(s == f.shape for f in E_far + H_far):
if not all(s == f.shape for f in [*E_far, *H_far]):
raise Exception('All fields must be the same shape!')
if padded_size is None:

View file

@ -423,10 +423,10 @@ def normalized_fields_h(
def _normalized_fields(
e: vcfdslice,
h: vcfdslice,
omega: complex,
_omega: complex,
dxes: dx_lists2_t,
epsilon: vfdslice,
mu: vfdslice | None = None,
_mu: vfdslice | None = None,
prop_phase: float = 0,
) -> tuple[vcfdslice_t, vcfdslice_t]:
r"""

View file

@ -19,9 +19,8 @@ The intended workflow is:
That same convention controls which side of the selected slice is used for the
overlap window and how the expanded field is phased.
"""
from typing import Any, cast
from typing import Any, TypedDict, cast
import warnings
from typing import Any
from collections.abc import Sequence
import numpy
from numpy.typing import NDArray
@ -31,6 +30,13 @@ from ..fdmath import vec, unvec, dx_lists_t, cfdfield_t, fdfield, cfdfield
from . import operators, waveguide_2d
class Waveguide3DMode(TypedDict):
wavenumber: complex
wavenumber_2d: complex
H: NDArray[complexfloating]
E: NDArray[complexfloating]
def solve_mode(
mode_number: int,
omega: complex,
@ -40,7 +46,7 @@ def solve_mode(
slices: Sequence[slice],
epsilon: fdfield,
mu: fdfield | None = None,
) -> dict[str, complex | NDArray[complexfloating]]:
) -> Waveguide3DMode:
r"""
Given a 3D grid, selects a slice from the grid and attempts to
solve for an eigenmode propagating through that slice.
@ -121,7 +127,7 @@ def solve_mode(
E[iii] = e[oo][:, :, None].transpose(reverse_order)
H[iii] = h[oo][:, :, None].transpose(reverse_order)
results = {
results: Waveguide3DMode = {
'wavenumber': wavenumber,
'wavenumber_2d': wavenumber_2d,
'H': H,
@ -184,13 +190,13 @@ def compute_source(
def compute_overlap_e(
E: cfdfield_t,
E: cfdfield,
wavenumber: complex,
dxes: dx_lists_t,
axis: int,
polarity: int,
slices: Sequence[slice],
omega: float,
_omega: float,
) -> cfdfield_t:
r"""
Build an overlap field for projecting another 3D electric field onto a mode.
@ -262,7 +268,7 @@ def compute_overlap_e(
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)
warnings.warn('Requested overlap window was clipped to fit within the domain', RuntimeWarning, stacklevel=2)
slices2_l = list(slices)
slices2_l[axis] = slice(clipped_start, clipped_stop)
@ -275,7 +281,7 @@ def compute_overlap_e(
norm = (Etgt.conj() * Etgt).sum()
if norm == 0:
raise ValueError('Requested overlap window contains no overlap field support')
Etgt /= norm
Etgt = Etgt / norm
return cfdfield_t(Etgt)

View file

@ -130,7 +130,7 @@ import numpy
from numpy.typing import NDArray, ArrayLike
from scipy import sparse
from ..fdmath import vec, unvec, dx_lists2_t, vcfdslice_t, vcfdfield2_t, vfdslice, vcfdslice, vcfdfield2
from ..fdmath import vec, unvec, dx_lists2_t, vcfdslice_t, vfdslice, vcfdslice, vcfdfield2
from ..fdmath.operators import deriv_forward, deriv_back
from ..eigensolvers import signed_eigensolve, rayleigh_quotient_iteration
from . import waveguide_2d
@ -267,7 +267,7 @@ def solve_mode(
mode_number: int,
*args: Any,
**kwargs: Any,
) -> tuple[vcfdslice, complex]:
) -> tuple[vcfdfield2, complex]:
"""
Wrapper around `solve_modes()` that solves for a single mode.
@ -285,7 +285,7 @@ def solve_mode(
def linear_wavenumbers(
e_xys: list[vcfdfield2_t],
e_xys: Sequence[vcfdfield2] | NDArray[numpy.complex128],
angular_wavenumbers: ArrayLike,
epsilon: vfdslice,
dxes: dx_lists2_t,
@ -537,11 +537,11 @@ def normalized_fields_e(
def _normalized_fields(
e: vcfdslice,
h: vcfdslice,
omega: complex,
_omega: complex,
dxes: dx_lists2_t,
rmin: float, # Currently unused, but may want to use cylindrical poynting
_rmin: float, # Currently unused, but may want to use cylindrical poynting
epsilon: vfdslice,
mu: vfdslice | None = None,
_mu: vfdslice | None = None,
prop_phase: float = 0,
) -> tuple[vcfdslice_t, vcfdslice_t]:
r"""