Skip to content

simulation.ntff

2D near-to-far-field (NTFF) transformation over a closed contour.

Given the steady-state pressure and outward normal velocity phasors on a closed contour that encloses a scatterer (or any source region), the exterior field is fully determined by the Kirchhoff-Helmholtz boundary integral. In two dimensions, with the time convention used throughout the library, the free-space Green function is

with the Hankel function of the second kind (outgoing waves) and R the source-observer distance, and the exterior representation reads

where n' is the outward normal of the contour S and the momentum equation eliminated the pressure gradient. The normal derivative of the Green function brings in : . This is the same construction full-wave solvers use to report far-field scattering patterns from near-field data (e.g. the finite-element polar responses of Jimenez, Cox, Romero-Garcia and Groby, Metadiffusers: Deep-subwavelength sound diffusers, Sci. Rep. 7, 5389, 2017); the classical background is Williams, Fourier Acoustics (Academic Press, 1999), chapter 8.

far_field_from_contour evaluates that integral for phasors captured by add_contour_probe (or assembled by hand into a ContourPhasors), either in the true far-field limit, where turns the integral into an angular pattern with , or at a finite observation radius with the exact Hankel kernels.

Because the integral representation is source-free inside S for any field whose sources lie outside the contour, the incident wave of a scattering run contributes (analytically) nothing to the exterior integral: transforming total-field phasors already yields the scattered far field. Subtracting a reference run without the scatterer (ContourPhasors.subtract) removes the residual of that cancellation caused by grid dispersion; on the validation scenes the residual stays below 0.01 dB, so the subtraction is optional in practice.

Validated against analytic oracles: the omnidirectional pattern and the absolute level of a monopole line source reconstructed from an enclosing contour, the null pattern of an antiphase source pair, the extinction of a contour that does not enclose the source, and the far-field polar response of meshed Schroeder-type diffusers against the library’s Fraunhofer model (tests/simulation/test_fdtd_ntff.py).

Auto-generated from the source docstrings by scripts/generate_api_docs.py (make api-docs). Do not edit by hand.

ContourPhasors(
frequency: float,
positions: NDArray[np.float64],
normals: NDArray[np.float64],
pressure: NDArray[np.complex128],
normal_velocity: NDArray[np.complex128],
segment: float,
)

Steady-state p and v_n phasors sampled on a closed contour.

The phasors follow the library’s convention: . normals point outward (away from the enclosed region) and normal_velocity is the particle velocity component along them. Instances are produced by add_contour_probe probes; they can also be assembled by hand from any solver’s near field.

Attributes

NameDescription
frequencyFrequency of the phasors [Hz].
positionsSample positions (x, y) [m], shape (n, 2).
normalsOutward unit normals, shape (n, 2).
pressureComplex pressure phasor at each sample [Pa].
normal_velocityComplex outward normal velocity phasor [m/s].
segmentContour length carried by each sample dl [m].
ContourPhasors.subtract(reference: ContourPhasors) -> ContourPhasors

Phasor difference on the same contour: self - reference.

The standard way to isolate the scattered field of a plane-wave scattering run: capture the same contour in a second, otherwise identical simulation without the scatterer and subtract its (incident-only) phasors. Geometry and frequency must match.

far_field_from_contour(
contour: ContourPhasors,
angles: ArrayLike,
*,
distance: float | None = None,
origin: tuple[float, float] = (0.0, 0.0),
speed_of_sound: float = 343.0,
air_density: float = 1.2,
) -> NDArray[np.complex128]

Exterior field of a closed contour: the 2D Kirchhoff-Helmholtz integral.

Evaluates, for each observation angle a (degrees, measured from the +x axis towards +y of the grid coordinates, so the unit direction is ),

with the outgoing 2D free-space Green function and its normal derivative through ( convention, scipy.special.hankel2).

With distance=None (the default) the far-field limit is taken analytically and the returned complex pattern is the relative far-field amplitude defined by

with r measured from origin (the phase reference; magnitudes at infinity do not depend on it). With a finite distance the exact Hankel kernels are used instead and the return value is the complex pressure [Pa] on the circle of that radius around origin (which must lie outside the contour samples).

For radiating problems the contour must enclose every source of the field being transformed. For scattering runs (scatterer enclosed, incident source outside) the incident field integrates to nothing, so total-field phasors transform directly into the scattered far field; subtracting a no-scatterer reference (ContourPhasors.subtract) is optional numerical cleanup of the grid-dispersion residual of that cancellation (below 0.01 dB on the validation scenes).

Parameters

NameDescription
contourThe contour phasors (from add_contour_probe, or hand built).
anglesObservation angles [degrees], 1D. 0 is +x, 90 is +y of the coordinates contour.positions live in.
distanceObservation radius [m] for the exact evaluation, or None (default) for the far-field pattern.
originPhase-reference point (x, y) [m]; the centre of the observation circle when distance is given. Default the grid origin.
speed_of_soundSpeed of sound c [m/s] (default 343).
air_densityDensity rho [kg/m3] (default 1.2).

Returns: Complex array, one value per angle: the far-field pattern F(a) (units Pa sqrt(m)), or the pressure [Pa] at distance.

Raises

ExceptionWhen
ValueErrorFor invalid angles, a non-positive distance, or an observation circle that does not clear the contour.