Skip to content

environmental.atmospheric_refraction

Atmospheric refraction: ray tracing and the parabolic equation (PE).

Sound propagation outdoors is bent by vertical gradients of the effective sound speed c_eff(z) = c(z) + u(z) (the adiabatic sound speed plus the component of the wind in the propagation direction, Salomons Eq. (4.4)). This module predicts that refraction with two complementary models, clean-room from Salomons, Computational Atmospheric Acoustics (Springer, 2001) and Attenborough & Van Renterghem, Predicting Outdoor Sound (2e, CRC, 2021, Ch. 11), and it is the refracting-atmosphere counterpart of the range-independent ocean solvers in phonometry.underwater.numerical_propagation:

  • atmospheric_ray_paths — geometrical acoustics. Integrates Snell’s law for sound rays (Salomons Eq. (4.3)) with a fixed-step Runge-Kutta scheme, returning the curved ray paths, their turning points, travel times and ground reflections. It shares its ray core with the ocean ray_trace: the atmospheric version reflects at the ground (z = 0) instead of the sea surface and marches an upward-open half space.
  • atmospheric_parabolic_equation — the Green’s Function Parabolic Equation (GFPE, Salomons Appendix H). Marches the one-way wave equation in range with the split-step Fourier algorithm (the same range-marching family as the ocean parabolic_equation), a Gaussian starter (Salomons Eq. (G.64)), an absorbing layer at the top of the grid (Salomons Sec. G.9) and a finite-impedance ground condition through the plane-wave reflection coefficient R(kz) = (kz Z - k0)/(kz Z + k0) plus the surface-wave residue of its pole (Salomons Eqs. (H.28), (H.49)). It returns the relative sound level (dB re free field) over the range-height plane.

For a linear effective sound-speed profile the ray paths are exact circular arcs of radius ray_curvature_radius, and an upward-refracting linear profile has a closed-form shadow_zone_distance; both anchor the ray model. The PE is anchored against the exact spherical-wave ground effect (phonometry.environmental.ground_effect) in the homogeneous limit (gradient zero), which it reproduces to a few tenths of a dB on the default grid (finer height_step converges it further).

The ground impedance is taken in the e^{-i omega t} convention of Salomons (a passive ground has Im(Z) > 0), shared with phonometry.environmental.ground_barriers. The porous models of phonometry.materials work in the opposite e^{+j omega t} convention (Im(Z) < 0), so an impedance derived from them (flow_resistivity= or a PorousMediumResult) is conjugated internally before entering the PE ground condition. Heights and ranges are in metres, sound speeds in m/s and frequencies in Hz.

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

atmospheric_parabolic_equation(
frequency_hz: float,
profile: EffectiveSoundSpeedProfile,
*,
source_height: float,
impedance: ArrayLike | PorousMediumResult | None = None,
flow_resistivity: float | None = None,
model: Literal['delany_bazley', 'miki'] = 'delany_bazley',
max_range: float = 1000.0,
max_height: float = 100.0,
range_step: float | None = None,
height_step: float | None = None,
air_density: float = 1.205,
) -> AtmosphericPEResult

Relative-level field from the Green’s Function Parabolic Equation (GFPE).

Marches the split-step Fourier solution of the one-way wave equation (Salomons Appendix H) in range. Each step transforms the field to the vertical-wavenumber domain, applies the free-space propagator exp(i dr (sqrt(ka^2 - kz^2) - ka)) together with the ground reflection R(kz) = (kz Z - k0)/(kz Z + k0) (Eq. (H.28)), transforms back, adds the surface-wave residue of the reflection pole at kz = -k0/Z (the third term of Eq. (H.49), present for a passive ground, Im(Z) > 0) and applies the refraction phase screen exp(i dr (k(z) - ka)) (Eq. (H.58)). The source is a Gaussian starter with its ground image (Eqs. (G.64), (G.76)) and an absorbing layer at the top of the grid (Sec. G.9) suppresses top-boundary reflections. The reference wavenumber ka = k0 is taken at the ground.

The relative sound level re the free field is dL(z, r) = 20 lg(|p(z, r)| R1) with R1 the direct source-receiver distance (Salomons Eq. (3.6)); in a homogeneous atmosphere it reproduces the spherical-wave ground effect of ground_effect.

The ground surface impedance is either supplied through impedance (a normalized complex value/array, or a PorousMediumResult) or derived from an effective flow_resistivity (Pa s/m2) via the model porous model. Exactly one of the two must be given. A plain impedance value is taken in the e^{-i omega t} convention (Im(Z) > 0 for a passive ground); a PorousMediumResult or flow_resistivity is conjugated internally from the materials’ e^{+j omega t} convention.

Parameters

NameDescription
frequency_hzSource frequency, in Hz.
profileThe effective sound-speed profile.
source_heightSource height zs, in metres (> 0).
impedanceNormalized ground impedance, or a PorousMediumResult.
flow_resistivityEffective flow resistivity sigma (Pa s/m2), as an alternative to impedance.
modelPorous model for flow_resistivity.
max_rangeMaximum range, in metres.
max_heightTop of the output height grid, in metres (the receiver region of interest; an absorbing layer is added above it).
range_stepRange marching step dr, in metres. Default (None): one wavelength.
height_stepVertical grid spacing dz, in metres. Default (None): a tenth of a wavelength (Salomons Sec. G.2).
air_densityAir density rho, in kg/m3 (for the porous model).

Returns: An AtmosphericPEResult.

Raises

ExceptionWhen
ValueErrorIf the inputs are invalid or the impedance is unspecified.
atmospheric_ray_paths(
profile: EffectiveSoundSpeedProfile,
*,
source_height: float,
launch_angles_deg: ArrayLike,
max_range: float = 1000.0,
n_steps: int = 2000,
) -> AtmosphericRayResult

Trace sound rays through a refracting atmosphere over a ground surface.

Integrates Snell’s law for sound rays (Salomons Eq. (4.3), cos(gamma)/c(z) = const) with a fixed-step fourth-order Runge-Kutta scheme, marching in range and reflecting specularly at the ground (z = 0). The state is the height z and the vertical slowness zeta = sin(gamma)/c; with the range-invariant xi = cos(gamma0)/c(zs) the equations are dz/dr = zeta/xi and dzeta/dr = -(dc/dz)/(c^3 xi), the same ray core as the ocean ray_trace (with a ground reflection in place of the sea surface). The travel time accumulates dt/dr = 1/(xi c^2).

Parameters

NameDescription
profileThe effective sound-speed profile (see linear_sound_speed_profile / log_linear_sound_speed_profile).
source_heightSource height zs, in metres (>= 0).
launch_angles_degLaunch angles from the horizontal, in degrees (positive upward), within (-90, 90).
max_rangeMaximum horizontal range to trace, in metres.
n_stepsNumber of range steps per ray (>= 2).

Returns: An AtmosphericRayResult.

Raises

ExceptionWhen
ValueErrorIf the inputs are invalid.
AtmosphericPEResult(
frequency: float,
ranges: NDArray[np.float64],
heights: NDArray[np.float64],
relative_level: NDArray[np.float64],
source_height: float,
normalized_impedance: complex,
)

Parabolic-equation relative-level field in a refracting atmosphere.

Attributes

NameDescription
frequencySource frequency, in Hz.
rangesRange grid, in metres.
heightsHeight grid of the output field, in metres.
relative_levelRelative sound level dL(z, r) (dB re free field), shape (n_heights, n_ranges).
source_heightSource height, in metres.
normalized_impedanceNormalized ground impedance used (complex).
AtmosphericPEResult.level_at_height(height: float) -> NDArray[np.float64]

Relative sound level versus range at the grid height nearest height.

AtmosphericPEResult.plot(
ax: Axes | None = None,
*,
language: str = 'en',
**kwargs: Any,
) -> Axes

Plot the relative-level field over the range-height plane.

AtmosphericRayResult(
launch_angles: NDArray[np.float64],
ranges: NDArray[np.float64],
heights: NDArray[np.float64],
travel_times: NDArray[np.float64],
turning_points: NDArray[np.int_],
ground_reflections: NDArray[np.int_],
source_height: float,
)

Ray-tracing solution through an effective sound-speed profile.

Attributes

NameDescription
launch_anglesLaunch angles from the horizontal, in degrees.
rangesPer-ray horizontal ranges, in metres, shape (n_rays, n_steps).
heightsPer-ray heights, in metres, shape (n_rays, n_steps).
travel_timesPer-ray cumulative travel times, in seconds, shape (n_rays, n_steps).
turning_pointsNumber of turning points (height extrema) per ray.
ground_reflectionsNumber of ground reflections per ray.
source_heightSource height, in metres.
AtmosphericRayResult.plot(
ax: Axes | None = None,
*,
language: str = 'en',
**kwargs: Any,
) -> Axes

Plot the curved ray paths (height on the vertical axis).

EffectiveSoundSpeedProfile(
heights: NDArray[np.float64],
sound_speeds: NDArray[np.float64],
description: str = '',
)

Vertical profile of the effective sound speed c_eff(z).

The profile is sampled on a strictly increasing height grid starting at the ground (z = 0); intermediate heights are taken as piecewise linear, so a two-point profile represents an exact linear gradient.

Attributes

NameDescription
heightsHeights z above the ground, in metres (from z = 0).
sound_speedsEffective sound speed at each height, in m/s.
descriptionShort human-readable label (e.g. "linear, +0.1 s^-1").
EffectiveSoundSpeedProfile.plot(
ax: Axes | None = None,
*,
language: str = 'en',
**kwargs: Any,
) -> Axes

Plot the effective sound-speed profile (height on the vertical axis).

EffectiveSoundSpeedProfile.speed_at(
height: ArrayLike,
) -> NDArray[np.float64]

Piecewise-linear effective sound speed at one or more heights.

linear_sound_speed_profile(
gradient: float,
*,
ground_speed: float = 343.0,
max_height: float = 100.0,
) -> EffectiveSoundSpeedProfile

Linear effective sound-speed profile c_eff(z) = c0 + gradient*z.

A positive gradient (sound speed increasing with height) refracts sound downward (favourable propagation); a negative gradient refracts it upward and creates an acoustic shadow near the ground (Salomons Sec. 4.2).

Parameters

NameDescription
gradientVertical gradient dc/dz, in s^-1 (m/s per m).
ground_speedSound speed c0 at the ground, in m/s.
max_heightTop of the sampled profile, in metres.

Returns: A two-point EffectiveSoundSpeedProfile.

Raises

ExceptionWhen
ValueErrorIf max_height or ground_speed is not positive, or the profile turns non-positive within [0, max_height].
log_linear_sound_speed_profile(
b: float,
*,
ground_speed: float = 340.0,
roughness_length: float = 0.1,
max_height: float = 100.0,
n_points: int = 128,
) -> EffectiveSoundSpeedProfile

Logarithmic effective sound-speed profile c_eff(z) = c0 + b ln(1 + z/z0).

This is the realistic surface-layer profile of Salomons Eq. (4.5): b is the strength of the gradient (+1 m/s for a typical downward-refracting atmosphere, -1 m/s for an upward-refracting one) and z0 is the aerodynamic roughness length (about 0.1 m for grassland). The steep gradient near the ground is resolved by sampling the height grid logarithmically.

Parameters

NameDescription
bProfile strength b, in m/s (positive: downward refraction).
ground_speedSound speed c0 at the ground, in m/s.
roughness_lengthAerodynamic roughness length z0, in metres.
max_heightTop of the sampled profile, in metres.
n_pointsNumber of samples of the height grid (>= 2).

Returns: An EffectiveSoundSpeedProfile.

Raises

ExceptionWhen
ValueErrorOn non-positive c0, z0 or max_height, fewer than two points, or a profile that turns non-positive.
ray_curvature_radius(
gradient: float,
*,
ground_speed: float = 343.0,
launch_angle_deg: float = 0.0,
) -> float

Radius of curvature of a sound ray in a linear sound-speed gradient.

In a linear effective sound-speed profile a sound ray is an exact circular arc of radius Rc = 1/(|gradient| * xi) with the Snell invariant xi = cos(theta0)/c(theta0's height) (Salomons Sec. 4.4; Attenborough Ch. 11). For a ray launched from the height where the speed is ground_speed, Rc = ground_speed / (|gradient| * cos(theta0)).

Parameters

NameDescription
gradientVertical gradient dc/dz, in s^-1 (must be non-zero).
ground_speedSound speed at the launch height, in m/s.
launch_angle_degLaunch angle from the horizontal, in degrees.

Returns: The radius of curvature Rc, in metres (always positive).

Raises

ExceptionWhen
ValueErrorIf the gradient is zero (a straight ray) or the launch angle is not within (-90, 90) degrees.
shadow_zone_distance(
gradient: float,
source_height: float,
receiver_height: float,
*,
ground_speed: float = 343.0,
) -> float

Distance to the acoustic shadow boundary in an upward-refracting profile.

For a linear upward-refracting profile (gradient < 0) the ground-level ray that just grazes the surface bounds a region beyond which no direct or once-reflected ray arrives (Salomons Sec. 4.4; Attenborough Ch. 11). With a ray radius Rc = c0/|gradient| the limiting horizontal distance is the closed form:

x_shadow = sqrt(2 Rc) * (sqrt(source_height) + sqrt(receiver_height))

valid for source and receiver heights small compared with Rc.

Parameters

NameDescription
gradientVertical gradient dc/dz, in s^-1 (must be negative for a shadow zone to exist).
source_heightSource height hs, in metres (>= 0).
receiver_heightReceiver height hr, in metres (>= 0).
ground_speedSound speed c0 at the ground, in m/s.

Returns: The horizontal shadow-boundary distance, in metres.

Raises

ExceptionWhen
ValueErrorIf the gradient is not negative, or a height is negative.
Created and maintained by· GitHub· PyPI· All projects