Source code for sionna.phy.channel.rayleigh_block_fading

#
# SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0#
"""Class for simulating Rayleigh block fading"""

import tensorflow as tf
from sionna.phy import config
from . import ChannelModel

[docs] class RayleighBlockFading(ChannelModel): # pylint: disable=line-too-long r""" Generates channel impulse responses corresponding to a Rayleigh block fading channel model The channel impulse responses generated are formed of a single path with zero delay and a normally distributed fading coefficient. All time steps of a batch example share the same channel coefficient (block fading). This class can be used in conjunction with the classes that simulate the channel response in time or frequency domain, i.e., :class:`~sionna.phy.channel.OFDMChannel`, :class:`~sionna.phy.channel.TimeChannel`, :class:`~sionna.phy.channel.GenerateOFDMChannel`, :class:`~sionna.phy.channel.ApplyOFDMChannel`, :class:`~sionna.phy.channel.GenerateTimeChannel`, :class:`~sionna.phy.channel.ApplyTimeChannel`. Parameters ---------- num_rx : `int` Number of receivers (:math:`N_R`) num_rx_ant : `int` Number of antennas per receiver (:math:`N_{RA}`) num_tx : `int` Number of transmitters (:math:`N_T`) num_tx_ant : `int` Number of antennas per transmitter (:math:`N_{TA}`) precision : `None` (default) | "single" | "double" Precision used for internal calculations and outputs. If set to `None`, :attr:`~sionna.phy.config.Config.precision` is used. Input ----- batch_size : `int` Batch size num_time_steps : `int` Number of time steps Output ------- a : [batch size, num_rx, num_rx_ant, num_tx, num_tx_ant, num_paths = 1, num_time_steps], `tf.complex` Path coefficients tau : [batch size, num_rx, num_tx, num_paths = 1], `tf.float` Path delays [s] """ def __init__(self, num_rx, num_rx_ant, num_tx, num_tx_ant, precision=None, **kwargs): super().__init__(precision=precision, **kwargs) self.num_tx = num_tx self.num_tx_ant = num_tx_ant self.num_rx = num_rx self.num_rx_ant = num_rx_ant def __call__(self, batch_size, num_time_steps, sampling_frequency=None): # Delays # Single path with zero delay delays = tf.zeros([ batch_size, self.num_rx, self.num_tx, 1], # Single path dtype=self.rdtype) # Fading coefficients std = tf.cast(tf.sqrt(0.5), dtype=self.rdtype) h_real = config.tf_rng.normal(shape=[batch_size, self.num_rx, self.num_rx_ant, self.num_tx, self.num_tx_ant, 1, # One path 1], # Same response over the block stddev=std, dtype = self.rdtype) h_img = config.tf_rng.normal(shape=[batch_size, self.num_rx, self.num_rx_ant, self.num_tx, self.num_tx_ant, 1, # One cluster 1], # Same response over the block stddev=std, dtype = self.rdtype) h = tf.complex(h_real, h_img) # Tile the response over the block h = tf.tile(h, [1, 1, 1, 1, 1, 1, num_time_steps]) return h, delays