Fading channel#

This module contains the FadingChannel class, which can be used to simulate OFDM transmission through 3GPP TDL and CDL fading channels. The implementation uses GPU acceleration.

class aerial.phy5g.channel_models.channel_config.FadingChannelConfig#

Abstract base configuration for fading channel models.

This is an abstract class containing parameters common to all fading channel types. Do not instantiate directly - use TdlChannelConfig or CdlChannelConfig instead.

Parameters:
  • delay_profile (str) – 3GPP delay profile identifier [3GPP TR 38.901, Sec 7.7.2]. Values: ‘A’, ‘B’, ‘C’, ‘D’, ‘E’. Default: ‘A’.

  • delay_spread (float) – RMS delay spread in nanoseconds [3GPP TR 38.901, Table 7.7.3-1]. Typical values: 30 (short), 100 (nominal), 300 (long). Default: 30.

  • max_doppler_shift (float) – Maximum Doppler frequency shift in Hz. Determined by UE velocity (v) and carrier frequency (fc) as fd = v * fc / c. Default: 5.0.

  • n_cell (int) – Number of cells in the simulation. Default: 1.

  • n_ue (int) – Number of UEs per cell. Default: 1.

  • cfo_hz (float) – Carrier frequency offset in Hz. Models oscillator mismatch between transmitter and receiver. Default: 0.0.

  • delay (float) – Propagation delay in seconds. Default: 0.0.

  • save_ant_pair_sample (int) –

    Save per antenna pair samples for debugging:

    • 0: Disabled (default).

    • 1: Enabled.

  • rand_seed (int) – Random seed for reproducible channel generation. Default: 0.

__init__(
delay_profile='A',
delay_spread=30.0,
max_doppler_shift=5.0,
n_cell=1,
n_ue=1,
cfo_hz=0.0,
delay=0.0,
save_ant_pair_sample=0,
rand_seed=0,
)#
Parameters:
  • delay_profile (str)

  • delay_spread (float)

  • max_doppler_shift (float)

  • n_cell (int)

  • n_ue (int)

  • cfo_hz (float)

  • delay (float)

  • save_ant_pair_sample (int)

  • rand_seed (int)

Return type:

None

class aerial.phy5g.channel_models.channel_config.TdlChannelConfig#

TDL (Tapped Delay Line) channel configuration.

TDL models are used for link-level simulations with simplified spatial characteristics. Suitable for SISO or basic MIMO without antenna array geometry [3GPP TR 38.901, Sec 7.7.2].

The TDL model uses a tapped delay line structure where each tap represents a multipath component with specific delay and power. The model does not include spatial correlation between antenna elements.

Example

>>> config = TdlChannelConfig(
...     delay_profile='A',
...     delay_spread=30.0,
...     max_doppler_shift=5.0,
...     n_bs_ant=4,
...     n_ue_ant=2
... )
Parameters:
  • n_bs_ant (int) – Number of base station antennas. Default: 1.

  • n_ue_ant (int) – Number of UE antennas. Default: 1.

  • n_path (int) – Number of delay taps in the channel model. The number of taps depends on the delay profile (e.g., TDL-A has 23 taps). Default: 23.

  • use_simplified_pdp (bool) – Use simplified power delay profile with fewer taps for faster computation at the cost of reduced accuracy. Default: False.

__init__(
delay_profile='A',
delay_spread=30.0,
max_doppler_shift=5.0,
n_cell=1,
n_ue=1,
cfo_hz=0.0,
delay=0.0,
save_ant_pair_sample=0,
rand_seed=0,
n_bs_ant=1,
n_ue_ant=1,
n_path=23,
use_simplified_pdp=False,
)#
Parameters:
  • delay_profile (str)

  • delay_spread (float)

  • max_doppler_shift (float)

  • n_cell (int)

  • n_ue (int)

  • cfo_hz (float)

  • delay (float)

  • save_ant_pair_sample (int)

  • rand_seed (int)

  • n_bs_ant (int)

  • n_ue_ant (int)

  • n_path (int)

  • use_simplified_pdp (bool)

Return type:

None

class aerial.phy5g.channel_models.channel_config.CdlChannelConfig#

CDL (Clustered Delay Line) channel configuration.

CDL models include full spatial characteristics with antenna array geometry and angular spreads. Suitable for MIMO simulations requiring accurate spatial correlation [3GPP TR 38.901, Sec 7.7.1].

The CDL model extends TDL by adding angular information (arrival and departure angles) for each cluster, enabling accurate modeling of antenna array responses and spatial correlation.

Example

>>> config = CdlChannelConfig(
...     delay_profile='A',
...     delay_spread=30.0,
...     bs_ant_size=(8, 4, 2),  # 8 rows, 4 cols, dual-pol = 64 antennas
...     ue_ant_size=(1, 1, 2)   # single element, dual-pol = 2 antennas
... )
Parameters:
  • bs_ant_size (Tuple[int, int, int]) – Base station antenna array dimensions as (rows, columns, polarizations). Total antennas = rows * columns * polarizations. Default: (2, 2, 2) = 8 antennas.

  • bs_ant_spacing (Tuple[float, float]) – BS antenna element spacing in wavelengths as (vertical_spacing, horizontal_spacing). Typical value is 0.5 wavelengths. Default: (0.5, 0.5).

  • bs_ant_polar_angles (Tuple[float, float]) – BS antenna polarization slant angles in degrees for dual-polarized arrays. Default: (45.0, -45.0) for cross-polarized.

  • bs_ant_pattern (int) –

    BS antenna element radiation pattern type:

    • 0: Isotropic pattern (default).

    • 1: 3GPP directional pattern [3GPP TR 38.901, Table 7.3-1].

  • ue_ant_size (Tuple[int, int, int]) – UE antenna array dimensions as (rows, columns, polarizations). Default: (1, 1, 2) = 2 antennas.

  • ue_ant_spacing (Tuple[float, float]) – UE antenna element spacing in wavelengths as (vertical_spacing, horizontal_spacing). Default: (0.5, 0.5).

  • ue_ant_polar_angles (Tuple[float, float]) – UE antenna polarization slant angles in degrees. Default: (0.0, 90.0) for vertical/horizontal polarization.

  • ue_ant_pattern (int) – UE antenna element radiation pattern type. Default: 0.

  • n_ray (int) – Number of rays per cluster for angular spread modeling. Default: 20.

  • v_direction (Tuple[float, float, float]) – UE velocity direction vector as (azimuth_deg, elevation_deg, speed_m_s) for Doppler calculation. Default: (0.0, 0.0, 0.0).

property n_bs_ant: int#

Total number of base station antennas.

property n_ue_ant: int#

Total number of UE antennas.

__init__(
delay_profile='A',
delay_spread=30.0,
max_doppler_shift=5.0,
n_cell=1,
n_ue=1,
cfo_hz=0.0,
delay=0.0,
save_ant_pair_sample=0,
rand_seed=0,
bs_ant_size=(2, 2, 2),
bs_ant_spacing=(0.5, 0.5),
bs_ant_polar_angles=(45.0, -45.0),
bs_ant_pattern=0,
ue_ant_size=(1, 1, 2),
ue_ant_spacing=(0.5, 0.5),
ue_ant_polar_angles=(0.0, 90.0),
ue_ant_pattern=0,
n_ray=20,
v_direction=(0.0, 0.0, 0.0),
)#
Parameters:
  • delay_profile (str)

  • delay_spread (float)

  • max_doppler_shift (float)

  • n_cell (int)

  • n_ue (int)

  • cfo_hz (float)

  • delay (float)

  • save_ant_pair_sample (int)

  • rand_seed (int)

  • bs_ant_size (Tuple[int, int, int])

  • bs_ant_spacing (Tuple[float, float])

  • bs_ant_polar_angles (Tuple[float, float])

  • bs_ant_pattern (int)

  • ue_ant_size (Tuple[int, int, int])

  • ue_ant_spacing (Tuple[float, float])

  • ue_ant_polar_angles (Tuple[float, float])

  • ue_ant_pattern (int)

  • n_ray (int)

  • v_direction (Tuple[float, float, float])

Return type:

None

aerial.phy5g.channel_models.channel_config.create_antenna_pattern(ant_model)#

Generate antenna patterns for isotropic or directional antenna models.

This helper function creates the antenna patterns required for AntPanelConfig when using antenna model 0 (isotropic) or 1 (directional/3GPP).

Parameters:

ant_model (int) –

Antenna model type:

  • 0: Isotropic pattern (constant 0 dB gain in all directions)

  • 1: Directional pattern (3GPP TR 38.901 compliant)

Returns:

  • ant_theta: List of 181 floats for A(theta, phi=0) pattern in dB

  • ant_phi: List of 360 floats for A(theta=90, phi) pattern in dB

Return type:

Tuple of (ant_theta, ant_phi) where

Raises:

ValueError – If ant_model is not 0 or 1.

Example

>>> ant_theta, ant_phi = create_antenna_pattern(ant_model=1)
>>> config = AntPanelConfig(
...     n_ant=4,
...     ant_size=[1, 1, 1, 2, 2],
...     ant_spacing=[0, 0, 0.5, 0.5],
...     ant_theta=ant_theta,
...     ant_phi=ant_phi,
...     ant_polar_angles=[45, -45],
...     ant_model=1
... )

Note

For ant_model=2 (direct pattern), you must provide your own measured or custom antenna patterns.

class aerial.phy5g.channel_models.fading_channel.FadingChannel#

GPU-accelerated fading channel for 5G NR simulations.

Implements TDL and CDL channel models with OFDM modulation/demodulation and AWGN noise addition. Supports both CuPy arrays (zero-copy GPU operation) and NumPy arrays (automatic GPU transfer).

The channel processes frequency-domain input signals and produces frequency-domain output signals with applied fading and optional noise.

Example

>>> from aerial.phy5g.channel_models import TdlChannelConfig, FadingChannel
>>>
>>> config = TdlChannelConfig(
...     delay_profile='A',
...     delay_spread=30.0,
...     n_bs_ant=4,
...     n_ue_ant=2
... )
>>> channel = FadingChannel(
...     channel_config=config,
...     n_sc=3276,
...     numerology=1
... )
>>>
>>> # Run with CuPy (zero-copy) or NumPy (auto-transfer)
>>> rx_signal = channel(freq_in=tx_signal, tti_idx=0, snr_db=20.0)
Parameters:
  • channel_config (FadingChannelConfig) – Channel model configuration. Must be either TdlChannelConfig or CdlChannelConfig.

  • n_sc (int) – Number of subcarriers. Default: 3276.

  • numerology (int) –

    5G NR numerology index determining subcarrier spacing [3GPP TS 38.211, Sec 4.2]:

    • 0: 15 kHz subcarrier spacing.

    • 1: 30 kHz subcarrier spacing (default).

    • 2: 60 kHz subcarrier spacing.

    • 3: 120 kHz subcarrier spacing.

  • n_fft (int) – FFT size for OFDM processing. Default: 4096.

  • n_symbol_slot (int) – Number of OFDM symbols per slot. Default: 14 (normal CP).

  • n_sc_prbg (int) – Number of subcarriers per PRB group. Default: 48.

  • cp_type (int) –

    Cyclic prefix type:

    • 0: Normal CP (default).

    • 1: Extended CP.

  • cuda_stream (Optional[CudaStream]) – CUDA stream for GPU operations. If None, a new CudaStream is created. Use with stream: to scope work; call stream.synchronize() explicitly when sync is needed. Default: None.

  • disable_noise (bool) – If True, skip AWGN noise addition. Useful for debugging or when noise is added externally. Default: False.

__init__(
*,
channel_config,
n_sc=3276,
numerology=1,
n_fft=4096,
n_symbol_slot=14,
n_sc_prbg=48,
cp_type=0,
cuda_stream=None,
disable_noise=False,
)#

Initialize FadingChannel.

Parameters:
  • channel_config (FadingChannelConfig) – Channel model configuration. Must be either TdlChannelConfig or CdlChannelConfig.

  • n_sc (int) – Number of subcarriers.

  • numerology (int) – 5G NR numerology index (0-3) determining subcarrier spacing.

  • n_fft (int) – FFT size for OFDM processing.

  • n_symbol_slot (int) – Number of OFDM symbols per slot.

  • n_sc_prbg (int) – Number of subcarriers per PRB group.

  • cp_type (int) – Cyclic prefix type (0: normal, 1: extended).

  • cuda_stream (CudaStream | None) – CUDA stream. If None, a new CudaStream is created.

  • disable_noise (bool) – If True, skip AWGN noise addition.

Return type:

None

run(
*,
freq_in,
tti_idx,
snr_db,
enable_swap_tx_rx=False,
)#

Run the fading channel on input signal.

Processes the input frequency-domain signal through the channel model, applying fading effects and optionally adding AWGN noise.

Parameters:
  • freq_in (Array) – Frequency-domain input signal. Shape depends on channel configuration: (n_cell, n_ue, n_tx_ant, n_symbol, n_sc). Accepts both CuPy arrays (zero-copy) and NumPy arrays (auto-transferred to GPU).

  • tti_idx (int) – Transmission Time Interval index. Used to calculate the reference time for time-varying channel coefficients.

  • snr_db (float) – Signal-to-Noise Ratio in dB for AWGN noise addition. Ignored if disable_noise=True.

  • enable_swap_tx_rx (bool) – Swap transmit and receive roles to simulate uplink using downlink channel. Default: False.

Returns:

Frequency-domain output signal with fading and noise applied.

Same type as input (CuPy if input was CuPy, NumPy if input was NumPy). Shape: (n_cell, n_ue, n_rx_ant, n_symbol, n_sc).

Return type:

Array

reset()#

Reset the channel state.

Reinitializes the internal channel state, useful when starting a new simulation or when channel coherence time has been exceeded.

Return type:

None

get_channel_frequency_response(granularity='subcarrier')#

Get the channel frequency response (CFR).

Parameters:

granularity (str) –

CFR granularity:

  • ’subcarrier’: Per-subcarrier CFR.

  • ’prbg’: Per-PRB group CFR.

Returns:

Channel frequency response array.

Return type:

np.ndarray

Raises:

ValueError – If granularity is not ‘subcarrier’ or ‘prbg’.