generate_ofdm_channel.py (3424B)
1 # 2 # SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 # SPDX-License-Identifier: Apache-2.0 4 # 5 """Class for generating channel frequency responses""" 6 7 8 from sionna.channel.utils import subcarrier_frequencies, cir_to_ofdm_channel 9 import tensorflow as tf 10 11 class GenerateOFDMChannel: 12 # pylint: disable=line-too-long 13 r"""GenerateOFDMChannel(channel_model, resource_grid, normalize_channel=False) 14 15 Generate channel frequency responses. 16 The channel impulse response is constant over the duration of an OFDM symbol. 17 18 Given a channel impulse response 19 :math:`(a_{m}(t), \tau_{m}), 0 \leq m \leq M-1`, generated by the ``channel_model``, 20 the channel frequency response for the :math:`s^{th}` OFDM symbol and 21 :math:`n^{th}` subcarrier is computed as follows: 22 23 .. math:: 24 \widehat{h}_{s, n} = \sum_{m=0}^{M-1} a_{m}(s) e^{-j2\pi n \Delta_f \tau_{m}} 25 26 where :math:`\Delta_f` is the subcarrier spacing, and :math:`s` is used as time 27 step to indicate that the channel impulse response can change from one OFDM symbol to the 28 next in the event of mobility, even if it is assumed static over the duration 29 of an OFDM symbol. 30 31 Parameters 32 ---------- 33 channel_model : :class:`~sionna.channel.ChannelModel` object 34 An instance of a :class:`~sionna.channel.ChannelModel` object, such as 35 :class:`~sionna.channel.RayleighBlockFading` or 36 :class:`~sionna.channel.tr38901.UMi`. 37 38 resource_grid : :class:`~sionna.ofdm.ResourceGrid` 39 Resource grid 40 41 normalize_channel : bool 42 If set to `True`, the channel is normalized over the resource grid 43 to ensure unit average energy per resource element. Defaults to `False`. 44 45 dtype : tf.DType 46 Complex datatype to use for internal processing and output. 47 Defaults to `tf.complex64`. 48 49 Input 50 ----- 51 52 batch_size : int 53 Batch size. Defaults to `None` for channel models that do not require this paranmeter. 54 55 Output 56 ------- 57 h_freq : [batch size, num_rx, num_rx_ant, num_tx, num_tx_ant, num_ofdm_symbols, num_subcarriers], tf.complex 58 Channel frequency responses 59 """ 60 61 def __init__(self, channel_model, resource_grid, normalize_channel=False, 62 dtype=tf.complex64): 63 64 # Callable used to sample channel input responses 65 self._cir_sampler = channel_model 66 67 # We need those in call() 68 self._num_ofdm_symbols = resource_grid.num_ofdm_symbols 69 self._subcarrier_spacing = resource_grid.subcarrier_spacing 70 self._num_subcarriers = resource_grid.fft_size 71 self._normalize_channel = normalize_channel 72 self._sampling_frequency = 1./resource_grid.ofdm_symbol_duration 73 74 # Frequencies of the subcarriers 75 self._frequencies = subcarrier_frequencies(self._num_subcarriers, 76 self._subcarrier_spacing, 77 dtype) 78 79 def __call__(self, batch_size=None): 80 81 # Sample channel impulse responses 82 h, tau = self._cir_sampler( batch_size, 83 self._num_ofdm_symbols, 84 self._sampling_frequency) 85 86 h_freq = cir_to_ofdm_channel(self._frequencies, h, tau, 87 self._normalize_channel) 88 89 return h_freq