comnum.CdlChannel#

class comnum.CdlChannel(profile, delay_spread_s, fs, *, n_rx=1, n_tx=1, spacing_wavelengths=0.5, velocity_mps=0.0, fc_hz=3500000000.0, dual_polarized=False)#

A clustered delay line channel of 3GPP TR 38.901 (CDL-A to CDL-E) between two uniform linear arrays, with the Doppler of a moving receiver.

Every cluster of the table is a tap of 20 rays (Table 7.5-3 gives the ray offsets alpha_m scaled by the per-cluster angular spreads of the last rows of the table), each ray with its departure and arrival angles, its random initial phases, the cross-polarisation ratio of the table and the phase it accumulates across the elements of the arrays, so the spatial correlation follows from the geometry (Sec. 7.5 step 11, eq. 7.5-22). The delays of the table are scaled by the desired RMS delay spread (Sec. 7.7.3, eq. 7.7-1) and rounded to the sampling grid; the cluster powers are normalised to a unit sum (the specular component of CDL-D/E, eq. 7.5-29, counted in the first cluster), so the mean gain of every link is 1. The receiver moves along the array axis at velocity_mps; the Doppler shift of a ray is v cos(angle) f_c / c, 0 for a static channel, which is then constant in time.

Parameters:
  • profile (str) – "CDL-A" to "CDL-E" (Tables 7.7.1-1 to 7.7.1-5).

  • delay_spread_s (float) – desired RMS delay spread (s), Sec. 7.7.3.

  • fs (float) – sampling rate (Hz).

  • n_rx (int) – elements of the receive array (pairs when dual_polarized).

  • n_tx (int) – elements of the transmit array (pairs when dual_polarized).

  • spacing_wavelengths (float) – element spacing of both arrays (wavelengths).

  • velocity_mps (float) – speed of the receiver along the array axis (m/s).

  • fc_hz (float) – carrier frequency (Hz), the wavelength of the Doppler.

  • dual_polarized (bool) – cross-polarised pairs (slants ±45°) instead of vertical elements: the arrays then have 2 n_tx and 2 n_rx antennas.

Raises:

ValueError – for an invalid parameter (the message names it).

Examples

>>> import comnum, numpy as np
>>> ch = comnum.CdlChannel("CDL-C", 100e-9, 30.72e6, n_rx=4, n_tx=2)
>>> y, taps = ch.fade(np.ones((2, 256)), comnum.Rng(1))
>>> y.shape, len(taps.delays), ch.n_rx
((4, 256), 24, 4)
draw(n, rng)#

Draw the taps of a realisation without applying them.

Parameters:
  • n (int) – number of samples.

  • rng (Rng) – the generator.

Returns:

the taps, whose coefficients() give every link at every sample.

Return type:

ChannelTaps

Raises:

ValueError – for an invalid parameter (the message names it).

fade(x, rng)#

Apply the channel to transmitted streams whose samples before the signal are zero.

Parameters:
  • x (array_like) – the transmitted streams, (n,) for one transmit antenna or (n_tx, n).

  • rng (Rng) – the generator of the ray coupling and phases.

Returns:

the received streams ((n,) for a SISO channel given a 1-D input, (n_rx, n) otherwise) and the taps of the realisation.

Return type:

tuple[numpy.ndarray, ChannelTaps]

Raises:

ValueError – for an invalid parameter or input (the message names it).

delays#

Delays of the clusters on the sampling grid (samples, int64), one tap each.

Type:

numpy.ndarray

max_doppler_hz#

The maximum Doppler shift |v| f_c / c (Hz).

Type:

float

n_rx#

Receive antennas.

Type:

int

n_tx#

Transmit antennas.

Type:

int

powers#

Normalised powers of the clusters (unit sum, the specular component of CDL-D/E counted in the first; float64).

Type:

numpy.ndarray