CRRM documentation¶
Last modified: 2025-11-12 14:10
Purpose¶
CRRM stands for Cellular Radio Reference Model. This is a system-level network simulator which aims to predict the performance of a cellular radio system. It follows 5G concepts and channel models. The intention is to have an easy-to-use and fast system written in pure Python with minimal dependencies. It is especially designed to be suitable for interfacing to AI engines such as tensorflow or pytorch. One of the main application areas is testing the performance of novel network management algorithms.
Note that CRRM is a system-level simulator, not a link-level simulator. This means that it takes a coarse-grained approach, specifically meaning that it does not model concepts like packet flows and queueing at all. Resource allocation is modelled, but only as a continuous process that ignores discrete resource blocks. These simplifications are necessary if large systems are to be simulated. The main application areas are the evaluation of high-level network management strategies, not the accurate estimation of throughputs to indvidual devices. Other software is available for that type of link-level simulation.
CRRM is carefully designed to be very fast and to be able to handle large systems. It achieves this by a novel compute-on-demand mechanism, whereby internal data is only computed when needed. Moreover, only data which is known to have changed, normally because of User Equipment (UE) movement, is actually computed. The system knows internally what has not changed and thus does not need to be re-computed.
CRRM builds on the previous projects AIMM-simulator by Keith Briggs, and Cellular Reference Model by Kishan Sthankiya, especially for pathloss models. However, CRRM has a completely new and much more efficient internal design and a new API, and essentially is a new project. Further technical documentation is at https://arxiv.org/abs/2511.02692.
Software dependencies¶
Python 3.11 or higher.
Installation from PyPi¶
pip install CRRM
Installation from source¶
First download the source as a zipfile from https://github.com/keithbriggs/CRRM-2.0/tree/master. Then perform these steps in your terminal:
unzip CRRM-2.0.zip
cd CRRM-2.0
pip install .
You should of course develop new projects using CRRM in your own folders, not under the CRRM-2.0 folder!
Performance¶
The plot below shows the typical computation time for a range of system sizes. Note the proportionality of computation to both the number of cells, and to the number of UEs. This indicates that there are no significant computational overheads.
Download script: CRRM_large_system_timing_tests.py
CRRM performance metrics.¶
Tutorial examples¶
Note: as with other python packages like numpy, there are alternative ways of importing which are functionally equivalent but result in a different namespace set-up. With CRRM, these two options are equivalent:
1from CRRM import Simulator,Parameters
2params=Parameters()
3sim=Simulator(params)
4# or...
5import CRRM
6params=CRRM.Parameters()
7sim=CRRM.Simulator(params)
Important: the parameters class is used to set the initial conditions for the simulation. If these are changed during a simulation run, it is not safe to assume that the new values will be used by the simulation kernel. For only a few parameters is it meaningful to change them during a run, and for these methods with names like CRRM.Simulator.set_power_matrix() methods are provided. See the documentation of all available such methods under Simulator below. Further technical documentation is at https://arxiv.org/abs/2511.02692.
Example 01: Quick start¶
The following example will test the installation and introduce the basic concepts.
1from CRRM import Simulator,Parameters
2crrm_parameters=Parameters(n_ues=20)
3crrm_simulator=Simulator(crrm_parameters)
4crrm_simulator.layout_plot()
5print(f'UE throughputs={crrm_simulator.get_UE_throughputs()} Mb/s')
The minimal steps required to build and run a simulation are:
Import
Simulator, andParameters.Create a
Parametersinstance.Create a
Simulatorinstance with theParametersinstance as its only argument.Draw a plot to confirm the system layout (see below).
Print out the computed values of any variables of interest.
The output should be something like this:
UE throughputs=[16 16 9 7 5 9 16 33 33 8 33 28 16 43 43 16 22 29 66 26] Mb/s
Note that the default locations for cells and UEs used are 7 cells in a hexagonal layout, and UEs distributed as a Poisson Point Process (PPP), with mean 50 (in the approximate area covered by the cells). These default locations can be over-ridden by using the cell_locations and ue_initial_locations arguments when creating the CRRM_parameters instance. In this example we simply use the n_ues parameter to use 20 UEs rather than the default 50, but we keep the PPP distribution.
Download script: CRRM_example_01_quick-start.py
CRRM example 01 quick-start layout.¶
Example 02: Adding a logger¶
Normally we want to log or capture data during a simulation run, in order to plot it at the end of the run, or to do statistical analyses. The Logger class is used for this, as outlined in this code example:
1from CRRM import Parameters,Simulator,Logger
2crrm_parameters=Parameters(...)
3crrm=Simulator(crrm_parameters)
4logger=Logger(crrm,captures=('cqi','mcs','sinr','se_Shannon','tp'))
5for i in range(crrm_parameters.n_moves):
6 logger.capture()
7 # now move some UEs...
8logger.plot(fields=('cqi','mcs','sinr','se_Shannon','tp'),
9 fnbase='img/CRRM_example_02_logger',
10 title='CRRM logger',
11 averages=('tp',),
12 smooth_averages=True)
Import the required classes.
Create a Parameters instance.
Create a Simulator instance.
Create a Logger instance, specifying which quantities are to be captured, and optionally for which UEs (the default is all UEs).
Start the main simulation loop.
On each loop iteration, capture the data.
Move some or all UEs according to some mobility model.
Plot the results. The averages field causes the average of the captured data to also be plotted.
Download script: CRRM_example_02_logger.py
CRRM example 02: logger.¶
Example 03: Resource allocation¶
This example demonstrates the resource_allocation_fairness parameter (denoted as \(p\)). This parameter controls how resources are shared among UEs attached to the same cell. The model calculates the throughput \(T_i\) for a user \(i\) with spectral efficiency \(S_i\) using the equation \(T_i = a S_i^{1-p}\). Here, \(p\) is the fairness parameter, and \(a\) is a proportionality factor calculated for each cell, which represents the total subband bandwidth divided by the sum of the “costs” (\(S_j^{-p}\)) of all UEs attached to that same cell. The script plots the throughput of all UEs as this parameter is swept from a negative value (favouring strong users) to a positive value (favouring weak users).
1crrm_parameters=Parameters(..., resource_allocation_fairness=pmin, ...)
2crrm=Simulator(crrm_parameters)
3crrm_log=Logger(crrm, captures=('tp',), ...)
4ps=np.linspace(pmin, pmax, crrm_parameters.n_moves)
5for p in ps:
6 crrm.set_resource_allocation_fairness(p)
7 crrm_log.capture()
8crrm_log.plot(fields=('tp',), x_axis=ps, ...)
The key steps are:
A Logger instance is created, configured to capture throughput (
tp) for all UEs.A
numpy.linspacearray of fairness values (ps) is generated.The main loop iterates over this
psarray, not over time steps.Inside the loop,
set_resource_allocation_fairness()is called to update the simulator’s parameter.logger.capture()logs the resulting throughputs for all UEs at this fairness value.Finally,
logger.plot()is called withx_axis=psto plot throughput vs the fairness parameter.
Download script: CRRM_example_03_resource_allocation.py
CRRM example 03: resource allocation.¶
Example 04: Pathloss model comparison¶
This script compares the available pathloss models from the simulator. It simulates a single UE moving radially away from the cell and captures its throughput at each step. This process is repeated for each long-distance model (RMa, UMa, UMi, and power-law), and the results are plotted on a single graph to show the significant impact of the propagation model on performance.
1model_names = ['RMa', 'UMa', 'UMi', 'power-law']
2all_tps = []
3for model_name in model_names:
4 crrm_parameters = Params(..., pathloss_model_name=model_name, ...)
5 crrm = Sim(crrm_parameters)
6 tp = np.empty(n_points)
7 for i in range(n_points):
8 tp[i] = crrm.get_UE_throughputs()[0, 0]
9 crrm.move_ue_locations(...)
10 all_tps.append(tp)
11plot(distances, all_tps, labels=model_names, ...)
The key steps are:
Define the list of models to iterate over.
Create an empty list to store the final throughput array from each run.
Begin the main loop, iterating over the model names.
Inside the loop, create a new Params instance, critically setting the
pathloss_model_namefor this iteration.Create a new Sim instance for this model.
Run the inner simulation loop, moving the UE and capturing throughput into a temporary array
tp.Append the completed throughput array
tpto the mainall_tpslist.After the main loop, pass all the collected data to the plot function.
Download script: CRRM_example_04_pathloss_model_comparison.py
The script prints simulation progress to the console and generates the plot shown below. Note how the simple power-law model (exponent 3.0) is more pessimistic at short distances than the dual-slope 3GPP models (like RMa), which start with a pathloss exponent closer to 2.0.
Throughput vs distance for several standard pathloss models.¶
Example 05: Antenna pattern visualisation¶
This script provides a visualisation of the 3-sector antenna gain pattern model. It plots the throughput of a single UE moving in a 360-degree circle at a constant radius from the cell. The test is run for both the 1-sector (omnidirectional) case and the 3-sector case, allowing a direct comparison.
1thetas = np.linspace(-np.pi, np.pi, n_steps, ...)
2xs = r_m * np.cos(thetas)
3ys = r_m * np.sin(thetas)
4...
5all_tps = []
6for n_sec in [1, 3]:
7 crrm_parameters = Params(..., n_sectors=n_sec, ...)
8 crrm = Sim(crrm_parameters)
9 tp = np.empty(n_steps)
10 for i in range(n_steps):
11 pos = np.array([[xs[i], ys[i], h_ut]])
12 crrm.set_ue_locations([0], pos)
13 tp[i] = crrm.get_UE_throughputs()[0, 0]
14 all_tps.append(tp)
15plot(degrees, all_tps, ...)
The core logic is:
Generate the array of \((x, y)\) coordinates for the circular path.
Loop over the desired sector configurations (1 and 3).
Inside this loop, create a Params instance with the correct
n_sectorsfor this run.Create the corresponding Sim instance.
Run an inner loop over all path coordinates.
Use the
set_ue_locations()method to explicitly place the UE at the position for this step.Capture the UE’s throughput at that position.
Store the throughput arrays and pass them to the plot function.
Download script: CRRM_example_05_antenna_pattern.py
The resulting plot clearly shows the gain “lobes” from the 3-sector antenna pattern compared to the flat omnidirectional (1-sector) case, confirming the antenna gain model is working correctly.
Plot showing 1-sector vs 3-sector throughput for a UE moving in a circle.¶
Example 06: Subbanding and Interference¶
This script demonstrates the use of subbanding. It defines a worst-case scenario: one UE placed exactly between two cells. In the first test (1 subband), the UE experiences full interference from both cells, resulting in near-zero SINR. In the second test (2 subbands), the cells are configured via the power_matrix parameter to transmit on different subbands, eliminating the interference at the UE and showing the resulting massive throughput gain.
1# Case 1: n_subbands=1
2params_case1 = Params(
3 ...,
4 n_subbands = 1,
5 power_matrix = [[100.0], [100.0]],
6 ...
7)
8crrm_case1 = Sim(params_case1)
9crrm_case1.update()
10sinr_case1 = crrm_case1.sinr.data[0, 0]
11
12# Case 2: n_subbands=2
13params_case2 = Params(
14 ...,
15 n_subbands = 2,
16 power_matrix = [[100.0, 1.0], [1.0, 100.0]],
17 ...
18)
19crrm_case2 = Sim(params_case2)
20crrm_case2.update()
21sinrs_case2 = crrm_case2.sinr.data[0]
This demo runs two separate simulations:
A Params instance is created for 1 subband.
The
power_matrixis set so both cells transmit on that single band, creating high interference.The simulation is run and the resulting (low) SINR is captured.
A second Params instance is created for 2 subbands.
The
power_matrixis set to coordinate power: Cell 0 transmits on subband 0, and Cell 1 on subband 1.The simulation is run and the SINR for both subbands is captured, showing high SINR on the subband with no interference.
Download script: CRRM_example_06_subbanding.py
This script prints its results directly to the console. The output shows the SINR and throughput for both cases, demonstrating a clear performance gain.
Case 1: n_subbands=1
UE SINR: -0.00 dB
UE Throughput: 17.54 Mb/s
Case 2: n_subbands=2
UE SINR (on subband 0): 20.00 dB (note: high signal, no interference)
UE SINR (on subband 1): -20.00 dB (note: minimal signal)
UE Throughput: 61.25 Mbps (note: from SB 0 only)
Example 07: Adding UEs during a run¶
This example demonstrates how to dynamically add UEs to a running simulation using the add_ue() method. It starts with a single cell and a single UE, then iteratively adds new UEs in a loop, printing the throughput of all UEs at each step.
1crrm_parameters=Parameters(...)
2crrm=Simulator(crrm_parameters)
3for i in range(2, 2+nmax):
4 crrm.update()
5 ue_throughputs=crrm.get_UE_throughputs()[:,0]
6 print(f'i={i} ue_throughput={ue_throughputs}')
7 crrm.add_ue(np.array([[10.0*i, 0.0, 2.0]]))
The key steps are:
A Simulator instance is created with a single cell and a single UE.
A loop is started to add nmax new UEs.
Inside the loop, update() is called to get the current state.
The throughputs for all currently active UEs are fetched and printed.
The
add_ue()method is called with a new location, adding one more UE to the simulation for the next loop iteration.
The console output demonstrates the effect of cell load. As more UEs are added to the same cell, the total cell throughput is shared among them, and the per-UE throughput decreases.
Download script: CRRM_example_07_adding_ues.py
i=2 ue_throughput=[148.126]
i=3 ue_throughput=[74.063 74.063]
i=4 ue_throughput=[49.375 49.375 49.375]
i=5 ue_throughput=[37.032 37.032 37.032 37.032]
i=6 ue_throughput=[29.625 29.625 29.625 29.625 29.625]
i=7 ue_throughput=[24.688 24.688 24.688 24.688 24.688 24.688]
Example 08: The InH Indoor Hotspot model¶
This script is a minimal example of how to select and use the InH (Indoor Hotspot) pathloss model. It sets up a simple scenario with two cells and one UE (in a high-interference, midpoint location) and prints the resulting throughput.
1crrm_parameters=Params(
2 n_ues=1,
3 pathloss_model_name="InH",
4 ue_initial_locations=[[100.0, 0.0, 1.5]],
5 cell_locations=[[0.0, 0.0, 20.0], [200, 0.0, 20.0]],
6 ...
7)
8crrm=Sim(crrm_parameters)
9crrm.update()
10ue_throughput=crrm.get_UE_throughputs()
11print(f"throughput for one UE...is {ue_throughput[0,0]} Mb/s")
The key steps are:
A Params instance is created.
The
pathloss_model_nameis explicitly set to"InH".A 2-cell, 1-UE layout is defined.
The Sim is created, updated, and the final throughput for the single UE is printed.
Download script: CRRM_example_08_InH.py
This script prints a single line to the console reporting the throughput for this specific indoor scenario.
throughput for one UE...is 19.4 Mb/s
Example 09: Indoor Hotspot model in 3d¶
This is an advanced example demonstrating a 3D animated simulation using the InH model. It shows multiple UEs moving within the 3D boundaries of a building, including randomly moving between floors. The script generates a series of 3D plot frames showing the UE locations and their current throughputs, which can then be compiled into a video.
1parameters = Parameters(..., pathloss_model_name="InH", ...)
2crrm = Simulator(parameters)
3house_geom = Building(...)
4
5for step in range(n_steps):
6 # ... manual UE 3D mobility logic (bouncing off walls) ...
7 s_plus_Δs = s + Δs
8 # ... logic to randomly change floors (s_plus_Δs[i, 2] = ...) ...
9 crrm.move_ue_locations(range(n_ues), Δs)
10 throughputs = crrm.get_UE_throughputs(...)
11 # ... matplotlib 3D plotting logic ...
12 draw_building_3d(house_geom, dots=crrm.ue_locations.data, ...)
13 ax.text(ue_loc[0],ue_loc[1],ue_loc[2]+0.5,label=f'{throughputs[i]} Mb/s', ...)
14 fig.savefig(f'ani/frame_{step:04d}.png')
15 plt.close()
16
17print(f"ffmpeg ... && xdg-open mp4/InH_test_ani.mp4")
The core logic is:
A Params instance is created, specifying the
InHpathloss model.A 3D building geometry is defined.
A main simulation loop begins, where custom code calculates the next UE position, including “bouncing” off the defined building walls and randomly triggering floor changes.
crrm.move_ue_locations()is called with the new 3D positions.get_UE_throughputs()is called to get the performance at this new state.A 3D plot is generated showing the building, cells, and UEs annotated with their throughputs.
The plot is saved as an animation frame.
After the loop, an ffmpeg command is printed to compile the frames into a video.
Download script: CRRM_example_09_InH_3d.py
This script outputs a series of .png frames to the ani/ directory and prints a command to compile and open the resulting .mp4 video.
CRRM example 09: Indoor Hotspot with 3d geometry.¶
Example 10: Base-station sectorization¶
This example computes an average throughput, firstly with one sector per base station, and then with three.
n_sectors=1 average UE throughput over 100 UE PPP layouts = 4.22 Mb/s
n_sectors=3 average UE throughput over 100 UE PPP layouts = 8.23 Mb/s
The layout plot indicates that the attachement is not to the nearest cell in the three-sector case.
CRRM example 10 sectors layout.¶
Download script: CRRM_example_10_sectors.py
Example 11: One-cell throughput tests¶
This example simply demonstrates that repeatedly adding UEs to a single cell results in throughputs inversely proportional to the number of UEs. See comments in the script for further details.
CRRM example 11 throughput tests.¶
Download script: CRRM_example_11_one-cell_throughput_tests.py
Example 12: Signal-to-Interference ratio cumulative distribution¶
This example simply demonstrates a close match to a theoretical cumulative distribution in the case of both cells and UEs randomly distributed according to a Poisson Point Process (PPP). See comments in the script for further details.
Reference: Haenggi, Stochastic Geometry for Wireless Networks, CUP 2013, section 5.2.
CRRM example 12 SIR cumulative distribution.¶
Download script: CRRM_example_12_sinr_cdf.py
Example 13: Timing tests¶
This script is able to run a variety of tests demonstrating the speed-ups attainable by using the smart updating algorithm in the CRRM kernel. An important check which it performs is that the smart updating gives identical results to the non-smart. It can also make an animation. See comments in the script for further details.
Typical console output is:
Without smart updating:
sinr for subband[0]=[-3.598 3.415 -2.172 1.317 -1.293 ... ] dB
se_Shannon for subband[0]=[0.523 1.676 0.684 1.235 0.801 ...]
With smart updating:
sinr for subband[0]=[-3.598 3.415 -2.172 1.317 -1.293 ... ] dB
se_Shannon for subband[0]=[0.523 1.676 0.684 1.235 0.801 ...]
The smart and the non-smart results match!
speed-up factor=1.84 😁
Download script: CRRM_example_13_timing_tests.py
Example 14: Fading demonstration¶
A demonstration of the effects of different types of fading on a cell-edge user.
CRRM example 14: fading.¶
Download script: CRRM_example_14_fading_tests.py
Example 15: MIMO¶
CRRM 2.0 implements MIMO only for computing channel spectral efficiency; the UE throughput computations based on MCS selection are unaffected by this setting.
This example simply sets up a system with several different MIMO schemes, and prints the predicted UE spectral efficiencies.
from CRRM import Simulator, Parameters
for MIMO in ((1,1),(2,2),(4,4),(8,2),(8,4),(8,8),(64,64),):
crrm=Simulator(Parameters(n_ues=20,MIMO=MIMO))
se=crrm.get_spectral_efficiency(ues=(0,1,2,3,4,5,),subbands=0)
print(f"MIMO={MIMO} {se} b/s/Hz")
This code prints:
MIMO=( 1, 1) [ 4.6 4.53 2.63 1.76 1.27 1.43] b/s/Hz
MIMO=( 2, 2) [ 7.51 7.37 4.2 2.85 2.1 2.35] b/s/Hz
MIMO=( 4, 4) [ 14.76 14.49 8.31 5.66 4.17 4.66] b/s/Hz
MIMO=( 8, 2) [ 8.85 8.7 5.0 3.35 2.42 2.72] b/s/Hz
MIMO=( 8, 4) [ 16.87 16.57 9.45 6.33 4.6 5.17] b/s/Hz
MIMO=( 8, 8) [ 29.38 28.86 16.58 11.29 8.33 9.31] b/s/Hz
MIMO=(64, 64) [234.72 230.55 132.56 90.3 66.59 74.48] b/s/Hz
Download full script: CRRM_example_15_MIMO.py
Example 16: callback demo¶
This is a very simple example of how to use the callback facility for user access to internal CRRM data during a simulation run.
from CRRM import Simulator, Parameters
def show_attachments(a): print(f"attachment_vector = {a}")
crrm = Simulator(Parameters(n_ues=20))
crrm.a.set_callback(show_attachments)
crrm.update()
This code prints the following. The meaning of the attachment_vector is that UE[i] is attached to cell[attachment_vector[i]].
attachment_vector = [0 0 0 0 0 1 1 2 4 4 2 5 3 1 5 3 5 3 6 3]
Download full script: CRRM_example_16_callback_demo.py
CRRM internal structure and mathematical model¶
Most users do not need to know anything about this.
UE locations \(u_i\) (one row per UE, three columns \(x,y,x\)).
Cells locations \(c_j\) (one row per cell, three columns \(x,y,x\))
\(\text{Cell}_j\) transmits with power \(p_j\) (\(p_{jk}\) with subbands).
Distance matrix \(D_{ij}=||u_i-c_j||\).
Attachment vector: \(\text{UE}_i\) attaches to cell \(a_j\) with best signal.
Gain matrix \(G=g(D)\) (\(\implies0<G<1\)).
RSRP matrix \(R_{ij}=p_j G_{ij}\).
With subbands: \(R_{ijk}=p_{jk} G_{ij}\).
Wanted signal vector \(w_i=R_{i,a_i}\).
Unwanted interference vector \(u_i=\sum_j R_{ij}-w_i\).
SINR vector \(\gamma=\frac{w}{\sigma^2+u}\) (element-wise division).
CQI is computed by discretizing the SINR.
MCS selection is done by standard look-up tables.
Resource allocation and throughput calculation are done by the function
CRRM.Simulator.get_UE_throughputsand the classCRRM.Throughputdocumented below.
The horizontal arrows in the block diagram below indicate dependencies of one block upon others. Blocks drawn with the same height have the same numbers of rows (\(n_{\text{UEs}}\)), and blocks drawn with the same width have the same numbers of columns (either \(n_{\text{cells}}\), or 1). Stacks indicate the third dimension, which stores the data for each subband.
CRRM simulator block structure.¶
CRRM simulator block structure, with the horizontal red strip showing the rows of vectors and matrices which are updated when a UE moves.¶
API reference¶
CRRM module¶
- CRRM.get_version()
Get the version number of the CRRM module.
_Node class¶
Generic base class for smart updating of node data. Not for direct use by a normal user
- CRRM._Node.set_callback(self, f)
Register user function f to be called with self.data as argument at every update. Inherited by all subclasses.
Parameters class¶
Container for physical, behavioral, and visualization parameters of a CRRM (Cellular Radio Reference Model) simulation. This class encapsulates metadata, system geometry, physical layer parameters, pathloss modeling options, UE mobility control, animation settings, and display preferences.
Important: the parameters class is used to set the initial conditions for the simulation. If these are changed during a simulation run, it is not safe to assume that the new values will be used by the simulation kernel. For only a few parameters is it meaningful to change them during a run, and for these methods with names like CRRM.Simulator.set_power_matrix() methods are provided. See the documentation on all available such methods under Simulator below.
Metadata parameters¶
- jobint = 0
User-defined job ID.
- descriptionstr = ‘’
User-defined problem description.
- authorstr = ‘’
Simulation author.
- date_timestr (= current local date and time)
Timestamp of configuration creation.
Simulation control parameters¶
- rng_seedsint or (int,int,int) = 0
Seeds for the three random-number generators, used for UE movements, shadow fading, and Rayleigh fading respectively.
- smart_updatebool = True
If True, enable optimized internal updates.
- verbosebool = False
If True, print general simulation debug information.
- do_assertsbool = False
If True, enable runtime assertions for debugging.
- display_flatbool = False
If True, display parameters in a single-line format.
- display_coloredbool = True
If True, use colored output when printing parameters.
- omit_from_displaytuple = (‘cell_locations’,’ue_locations’,’power_matrix’)
Fields to exclude from parameter display output.
System geometry and technology parameters¶
- n_cell_locationsint = 7
Number of base station (cell) locations.
- n_uesint = 50
Number of user equipment (UEs).
- ue_initial_locationsNone
Placeholder for UE positions (to be populated later).
- cell_locationsNone
Placeholder for cell positions (to be populated later).
- system_areafloat
Area of the system (computed at initialization).
- h_UT_defaultfloat = 1.8
Default height of a user terminal (meters).
- h_BS_defaultfloat = 20.0
Default height of a base station (meters).
- fc_GHzfloat = 3.5
Carrier frequency in GHz.
- bw_MHzfloat = 20.0
Channel bandwidth in MHz.
- σ2float = 2.0e-20 W/Hz
Noise power spectral density
- n_subbandsint = 1
Number of subbands.
- n_sectorsint = 1
Number of sectors per base station.
- distance_scalefloat = 1e3
Spatial scaling factor (e.g., 1000 for km to meters).
- p_Wfloat = 100.0
Transmit power in Watts.
- power_matrixNDArray
Matrix of transmit powers across subbands (populated during initialization).
- MIMONone|tuple[int]
Order (t,r) of the MIMO scheme, where t is the number of transmit antennas, and r the number of receive antennas. CRRM 2.0 implements MIMO only for computing channel spectral efficiency; the UE throughput computations based on MCS selection are unaffected by this setting.
- MCS_table_numberint = 2
Index of the modulation and coding scheme table (most users will not need to change this).
- resource_allocation_fairnessfloat = 0.0
Fairness factor (0.0 = proportional fair scheduling).
Pathloss model parameters¶
- pathloss_model_namestr = ‘UMa’
Name of the 3GPP pathloss model: options are ‘UMa’ (Urban Macrocell), ‘UMi’ (Urban Microcell), ‘RMa_discretised’ (Rural Macrocell, the fastest implementation, recommended for general rural use), ‘RMa’ (slower), ‘RMa_constant_height’ (for use when all cell and all UEs have the same height above ground), ‘InH’ (Indoor Hotspot), and ‘power-law’ (simple model for comparison purposes only).
- pathloss_modelNone or str
Pathloss model instance (assigned during set-up, not by the user).
- pathgain_functionCallable[[NDArray, NDArray], float]
Function to compute path gain between transmitter and receiver (assigned during set-up, not by the user).
- pathloss_exponentfloat = 3.0
Pathloss exponent, used only for the power-law pathloss model.
- LOSbool = True
Whether line-of-sight conditions are assumed.
- shadow_fadingbool = False
If true, shadow fading is used in the pathloss models.
- rayleigh_fadingbool = False
If true, Rayleigh fading is used in the pathloss models.
UE mobility parameters¶
- n_movesint = 1000
Number of UE movement steps in the simulation.
- move_fractionfloat = 0.1
Fraction of UEs that move during each step.
- move_meanfloat = 0.0
Mean movement distance (meters).
- move_stdevfloat = 10.0
Standard deviation of movement (meters).
Layout plotting parameters¶
- layout_plot_fnbasestr = ‘img/CRRM_layout_plot’
Base filename for layout plot image output.
- label_ues_in_layout_plotbool = False
Whether to label UEs in the layout plot.
- frame_intervalint = 0
Time between animation frames (0 disables animation).
Simulator class¶
Main class representing a cellular system, and computing all internal performance data. It takes one argument of type CRRM_parameters.
The simulator internally uses a list of three random number generators, each with their own seed. This allows for fading to be switched on and off but not affect UE moves.
rng[0]: used for moving UEs
rng[1]: used for shadow fading
rng[2]: used for Rayleigh fading
- CRRM.Simulator.add_ue(self, location)¶
Add one UE to the system, at the given location.
- Parameters:
location (a 3-vector representing the (x,y,z) coordinates)
- CRRM.Simulator.change_power_matrix(self, indices, deltas)¶
Shift some or all rows of the power matrix, by the given deltas. To reset all powers, use
CRRM.Simulator.set_power_matrix().- Parameters:
indices (a list of cell indices, or 'all')
deltas (float, or 2d array (one row for each index, one column per subband))
- CRRM.Simulator.get_UE_throughputs(self, ues=slice(None, None, None), subbands=slice(None, None, None))¶
Get the current UE throughputs for specified lists of ues (default all UEs), and of subbands (default all subbands).
- CRRM.Simulator.get_power_matrix(self)¶
Return a reference to the current power matrix.
- CRRM.Simulator.get_resource_allocation_fairness(self)¶
Get the current resource allocation fairness parameter.
- CRRM.Simulator.get_rngs(self, i=slice(None, None, None))¶
Get the current rngs, or some or one of them.
- CRRM.Simulator.get_ue_locations(self)¶
Get the current UE locations.
- CRRM.Simulator.layout_plot(self, grid=False, title='', show_attachment_type='attachment', show_plot=False, show_voronoi=True, padding_factor=1.02, show_kilometres=True, show_system_rmax_circle=True, show_UE_radius_circle=True, show_pathloss_circles=True, cell_image=None, UE_image=None, cell_image_zoom=0.05, UE_image_zoom=0.08, return_figure=False, fmt=('png', 'pdf'), no_ticks=False, dbg=False, quiet=False, dpi=200, figsize=(6, 6), label_ues=True)¶
Plot the cellular reference model layout with various optional overlays.
- Parameters:
grid (bool, optional) – Whether to display grid lines on the plot.
title (str, optional) – Title for the plot.
fnbase (str, optional) – Base filename for saving the plot.
show_attachment_type (str, optional) – If not empty, show UE-to-cell attachment lines.
show_plot (bool, optional) – If True, display the plot interactively.
show_voronoi (bool, optional) – If True, overlay Voronoi tessellation of cell locations.
padding_factor (float, optional) – Factor to expand plot limits beyond system radius.
show_kilometres (bool, optional) – If True, display axes in kilometres.
show_system_rmax_circle (bool, optional) – If True, draw a circle at the system maximum radius.
show_UE_radius_circle (bool, optional) – If True, draw a circle at the UE radius.
show_pathloss_circles (bool, optional) – If True, overlay circles for specific pathloss values.
cell_image (array-like or None, optional) – Image to use for cell markers.
UE_image (array-like or None, optional) – Image to use for UE markers.
cell_image_zoom (float, optional) – Zoom factor for cell images.
UE_image_zoom (float, optional) – Zoom factor for UE images.
return_figure (bool, optional) – If True, return the plot object instead of saving.
fmt (list of str, optional) – List of file formats for saving the plot.
dbg (bool, optional) – If True, print debug information.
- Returns:
plot – The plot object if return_figure is True, otherwise None.
- Return type:
Plot_CRRM_layout or None
- CRRM.Simulator.move_ue_locations(self, indices, deltas)¶
Move UEs with given indices, by the given deltas.
- Parameters:
indices (a list of UE indices, or 'all')
deltas (an array of shape (len(indices),3) representing the displacements)
- CRRM.Simulator.scale_ue_locations(self, indices='all', scale_factor=1.0)¶
Scale UEs with given indices, by the given factor.
- Parameters:
indices (a list of UE indices, or 'all')
scale_factor (float)
- CRRM.Simulator.set_n_sectors(self, n_sectors)¶
Set the number of sectors for all base stations.
- CRRM.Simulator.set_noise_power_spectral_density(self, σ2)¶
Set the noise power spectral density to a new value. The actual noise power in the channel or subbands will be computed and used in subsequent SIR calculations.
- CRRM.Simulator.set_power_matrix(self, p)¶
Set the power matrix to a new value. The matrix must have shape (n_cell_locations,n_subbands). It will be repeated across sectors if there are more than 1. To change just some cell powers by given deltas, use
CRRM.Simulator.change_power_matrix().
- CRRM.Simulator.set_resource_allocation_fairness(self, p)¶
Set the resource allocation fairness parameter.
- CRRM.Simulator.set_rng_seeds(self, seeds)¶
Re-set the rngs with a new seeds.
- CRRM.Simulator.set_ue_locations(self, indices, locations)¶
Set the UE locations to new values.
- class CRRM.Throughput(crrm_parameters, name='Throughput', smart_update=True)¶
Calculate all UE throughputs, with a tunable resource allocation heuristic. Though this class is for internal use only, the internal details are of some interest. Authors: Keith Briggs & Ibrahim Nur 2025-09-04.
This model allocates a share of the total bandwidth to each user in proportion to an abstract notion of their cost, and then calculates the resulting throughput.
The cost for user i is defined as \(1/S_i^p\), where \(S_i\) is the user’s spectral efficiency and \(p\) is a tunable fairness parameter.
This leads to the final throughput formula for user \(i\):
\[T_i = a S_i^{1-p}\]where \(a\) is a proportionality constant calculated for the cell:
\(a\) = (total bandwidth) \(/\) (sum of all user costs)
The fairness parameter \(p\) controls the distribution skew as follows:
\(p > 1\): favours weak users (e.g., \(p=2\) gives \(T ∝ 1/S\)).
\(p = 1\): results in equal throughput for all users on the cell.
\(p < 1\): favours strong users (e.g., \(p=0\) gives \(T ∝ S\)).
\(p = 0\): proportional fair scheduling.
The parameter \(p\) is set in the
CRRM_parametersclass, and can be changed during a run using the CRRM.set_resource_allocation_fairness() method.- update_data()¶
This will be over-ridden by specific methods for each sub-class
Logger class¶
Create an object which will log data during a simulation run.
- param captures:
- The quantities to capture; allowed values are:
‘UE_location’
‘rsrp’ (received signal reference power)
‘a’ (attachment vector)
‘sinr’ (signal to interference plus noise matrix in dB)
‘se_Shannon’ (Shannon capacity in b/s/Hz)
‘cqi’ (channel quality index)
‘mcs’ (modulation and coding scheme index)
‘se_from_mcs’ (actual spectral efficiency in b/s/Hz)
‘tp’ (UE downlink throughput in Mb/s)
- param ues:
UE indices to log
- param block_size:
size of pre-allocated internal data. Not normally altered.
Antenna_gain class¶
Calculates the antenna gain (not in dB) based on the 3GPP standard horizontal pattern.
This method applies a sectored antenna pattern as defined in 3GPP TR 38.901. The gain for each UE-cell link is determined by the absolute angular difference between the UE’s direction and the sector’s boresight. If the simulation is configured with only one sector per cell, a constant omnidirectional gain is applied instead.
The horizontal attenuation (in dB) is given by the formula:
where \(\phi'\) is the angular deviation from the boresight.
- param φ:
An array of horizontal angles \(\phi\) (in radians) from each cell to each UE. Its shape must be broadcastable with the internal array of sector angles.
- type φ:
numpy.ndarray
- rtype:
An array of linear (i.e., not in dB) gain values for each UE-cell link as type numpy.ndarray.
Reference¶
3GPP TR 38.901, Table 7.3-1
RMa (Rural Macrocell) pathloss model¶
- class RMa_pathloss_model_08.RMa_pathloss(fc_GHz=3.5, LOS=True, **args)¶
The complete Rural Macrocell (RMa) pathloss model from 3GPP TR 38.901.
Implements the full RMa model where antenna heights can vary for each link, calculating pathloss coefficients dynamically.
References
3GPP TR 38.901: https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3173
- __init__(fc_GHz=3.5, LOS=True, **args)¶
Initialises the RMa_pathloss model instance.
- Parameters:
fc_GHz (float, optional) – Centre frequency in GHz. Must be <= 7 GHz. Defaults to 3.5.
LOS (bool, optional) – Specifies whether to use the Line-of-Sight model. Defaults to True.
**args – Catches unused keyword arguments for API compatibility.
- get_pathgain(d2D_m, d3D_m, U, C)¶
Calculates the linear pathgain.
Pathgain is the reciprocal of the linear pathloss.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
U (numpy.ndarray) – Array of UE locations.
C (numpy.ndarray) – Array of cell locations.
- Returns:
The linear pathgain for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss(d2D_m, d3D_m, U, C)¶
Calculates the linear pathloss based on the general 3GPP RMa model.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres between UEs and cells.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
U (numpy.ndarray) – Array of UE locations, shape (n_ues, 3). The 3rd column (height) must be in the range [1.0, 10.0].
C (numpy.ndarray) – Array of cell locations, shape (n_cells, 3). The 3rd column (height) must be in the range [10.0, 150.0].
- Raises:
ValueError – If any h_UT or h_BS value is outside its valid range.
- Returns:
The calculated linear pathloss for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss_dB(d2D_m, d3D_m, U, C)¶
Calculates the pathloss in decibels (dB).
This is a convenience wrapper around
get_pathloss()that converts the linear pathloss value to the dB scale.- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres between UEs and cells. Does not take into account height.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
U (numpy.ndarray) – Array of UE locations. Not used in calculation.
C (numpy.ndarray) – Array of cell locations. Not used in calculation.
- Returns:
The pathloss in decibels.
- Return type:
numpy.ndarray
- class RMa_pathloss_model_08.RMa_pathloss_constant_height(fc_GHz=3.5, h_UT=1.5, h_BS=35.0, LOS=True, **args)¶
Rural Macrocell (RMa) pathloss model assuming constant antenna heights.
Simplified version of the 3GPP TR 38.901 RMa model where the heights of the User Terminal (UT) and Base Station (BS) are constant for all links, leading to a performance gain.
References
3GPP TR 38.901: https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3173
- __init__(fc_GHz=3.5, h_UT=1.5, h_BS=35.0, LOS=True, **args)¶
Initialises the RMa_pathloss_constant_height model instance.
- Parameters:
fc_GHz (float, optional) – Centre frequency in GHz. Must be <= 7 GHz. Defaults to 3.5.
h_UT (float, optional) – Height of the User Terminal in metres. Must be in [1.0, 10.0]. Defaults to 1.5.
h_BS (float, optional) – Height of the Base Station in metres. Must be in [10.0, 150.0]. Defaults to 35.0.
LOS (bool, optional) – Specifies whether to use the Line-of-Sight model. Defaults to True.
**args – Catches unused keyword arguments for API compatibility.
- Raises:
ValueError – If h_UT or h_BS are outside their valid ranges.
- get_pathgain(d2D_m, d3D_m)¶
Calculates the linear pathgain.
Pathgain is the reciprocal of the linear pathloss.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
U (numpy.ndarray) – Array of UE locations.
C (numpy.ndarray) – Array of cell locations.
- Returns:
The linear pathgain for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss(d2D_m, d3D_m)¶
Calculates the linear pathloss.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres between UEs and cells.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
- Returns:
The calculated linear pathloss for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss_dB(d2D_m, d3D_m)¶
Calculates the pathloss in decibels (dB).
This is a convenience wrapper around
get_pathloss()that converts the linear pathloss value to the dB scale.- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres between UEs and cells. Does not take into account height.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
U (numpy.ndarray) – Array of UE locations. Not used in calculation.
C (numpy.ndarray) – Array of cell locations. Not used in calculation.
- Returns:
The pathloss in decibels.
- Return type:
numpy.ndarray
- class RMa_pathloss_model_08.RMa_pathloss_discretised(fc_GHz=3.5, LOS=True, h_ut_res=0.5, h_bs_res=1.0, **args)¶
Rural Macrocell (RMa) pathloss model with discretised heights.
Pre-calculates pathloss coefficients for a grid of discrete UE and BS heights. At runtime, it rounds the actual heights to the nearest grid point to look up coefficients, trading accuracy for computational speed.
The accuracy trade-off is minimal. This can be shown by running the plot_RMa_pathloss_runtime_comparison program.
References
3GPP TR 38.901: https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3173
- __init__(fc_GHz=3.5, LOS=True, h_ut_res=0.5, h_bs_res=1.0, **args)¶
Initialises the RMa_pathloss_discretised model instance.
- Parameters:
fc_GHz (float, optional) – Centre frequency in GHz. Must be <= 7 GHz. Defaults to 3.5.
LOS (bool, optional) – Specifies whether to use the Line-of-Sight model. Defaults to True.
h_ut_res (float, optional) – Resolution of the discrete UT height grid in metres. Defaults to 0.5.
h_bs_res (float, optional) – Resolution of the discrete BS height grid in metres. Defaults to 1.0.
**args – Catches unused keyword arguments for API compatibility.
- get_pathgain(d2D_m, d3D_m, U, C)¶
Calculates the linear pathgain.
Pathgain is the reciprocal of the linear pathloss.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
U (numpy.ndarray) – Array of UE locations.
C (numpy.ndarray) – Array of cell locations.
- Returns:
The linear pathgain for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss(d2D_m, d3D_m, U, C)¶
Calculates the linear pathloss based on the general 3GPP RMa model.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres between UEs and cells.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
U (numpy.ndarray) – Array of UE locations, shape (n_ues, 3). The 3rd column (height) must be in the range [1.0, 10.0].
C (numpy.ndarray) – Array of cell locations, shape (n_cells, 3). The 3rd column (height) must be in the range [10.0, 150.0].
- Raises:
ValueError – If any h_UT or h_BS value is outside its valid range.
- Returns:
The calculated linear pathloss for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss_dB(d2D_m, d3D_m, U, C)¶
Calculates the pathloss in decibels (dB).
This is a convenience wrapper around
get_pathloss()that converts the linear pathloss value to the dB scale.- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres between UEs and cells. Does not take into account height.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
U (numpy.ndarray) – Array of UE locations. Not used in calculation.
C (numpy.ndarray) – Array of cell locations. Not used in calculation.
- Returns:
The pathloss in decibels.
- Return type:
numpy.ndarray
- RMa_pathloss_model_08.plot_RMa_pathloss_or_pathgain(plot_type='pathloss', fc_GHz=3.5, h_UT=1.5, h_BS=35.5, zoom_box=False, print_10m_pl=False, author=' ', x_min=35.0, x_max=5000.0)¶
Plot 3GPP RMa pathloss or pathgain model predictions as a self-test.
This function generates a plot comparing various 3GPP RMa pathloss or pathgain models for both Line-of-Sight (LOS) and Non-Line-of-Sight (NLOS) scenarios. It includes a free-space pathloss reference and an optional zoomed-in view for detailed analysis.
- Parameters:
plot_type (str, optional) – Type of plot to generate. Options are ‘pathloss’ (default) to plot pathloss in dB, or ‘pathgain’ to plot linear pathgain.
fc_GHz (float, optional) – Carrier frequency in GHz, defaults to 3.5.
h_UT (float, optional) – Height of the User Terminal (UE) in metres, defaults to 1.5.
h_BS (float, optional) – Height of the Base Station (BS) in metres, defaults to 35.5.
zoom_box (bool, optional) – If True, includes a zoomed-in inset on the plot. Defaults to False.
print_10m_pl (bool, optional) – If True, prints pathloss values at 10 metres to the console for LOS, NLOS, and free-space scenarios. Defaults to False.
author (str, optional) – Author name to include in the plot timestamp. Defaults to ‘ ‘.
x_min (float, optional) – Minimum distance for the plot’s x-axis in metres. Defaults to 35.0.
x_max (float, optional) – Maximum distance for the plot’s x-axis in metres. Defaults to 5000.0.
- Raises:
ImportError – If required plotting modules (e.g., matplotlib) are not installed.
Notes
The function uses the
RMa_pathloss,RMa_pathloss_constant_height, andRMa_pathloss_discretisedclasses to compute the values for the different scenarios.
- RMa_pathloss_model_08.plot_RMa_pathloss_runtime_comparison(author='')¶
Compare RMa pathloss model runtimes.
This function provides a lightweight performance benchmark for three distinct implementations of the RMa pathloss model:
RMa_pathloss: The full model with dynamic height calculations.RMa_pathloss_constant_height: A simplified model assuming fixed antenna heights.RMa_pathloss_discretised: A model that uses pre-calculated coefficientsbased on a discrete grid of antenna heights.
It directly measures the execution time required to calculate pathloss for an increasing number of UEs, thereby isolating the computational cost of each model from the overhead of the full CRRM simulation framework. The primary purpose is to visually demonstrate the performance gains achieved by the simplified and discretised models.
- Parameters:
author (str, optional) – The name of the author to be included in the plot’s timestamp metadata. If not provided, the author field will be empty.
- Returns:
This function does not return any values. Its primary outputs are plot files (.png, .pdf) saved to the local directory and status messages printed to the console.
- Return type:
None
See also
RMa_pathloss,RMa_pathloss_constant_height,RMa_pathloss_discretisedNotes
The comparison methodology involves the following steps for each specified UE count: 1. Randomly generate locations for UEs and a fixed set of cell sites. 2. Calculate the 2D and 3D distance matrices between every UE and cell. 3. Time the get_pathloss method for each of the three model variants using these distance matrices.
The resulting plot displays two sets of data: - The absolute runtime in milliseconds for each model on the primary y-axis. - The runtime ratio of the exact model to the optimised models on a secondary y-axis, quantifying the speed-up factor.
Examples
To run the comparison and generate the output plots, simply call the function from a script where the necessary modules are in the Python path.
>>> plot_RMa_pathloss_runtime_comparison(author='Ibrahim Nur')
This will produce ‘plot_RMa_pathloss_runtime_comparison.png’ and ‘plot_RMa_pathloss_runtime_comparison.pdf’ in the current directory.
RMa pathloss model¶
RMa pathloss models, runtime comparison¶
UMa (Urban Macrocell) pathloss model¶
- class UMa_pathloss_model_06.UMa_pathloss(fc_GHz=3.5, LOS=True, **args)¶
Urban Macrocell (UMa) pathloss model from 3GPP TR 38.901.
Calculates pathloss for urban macrocell environments where UE and BS heights can vary. This model includes the stochastic calculation of the effective environment height (h_E).
- fc_GHz¶
Centre frequency in gigahertz.
- Type:
float
- LOS¶
Indicates if the Line-of-Sight model is active.
- Type:
bool
References
3GPP TR 38.901: https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3173
- __init__(fc_GHz=3.5, LOS=True, **args)¶
Initialises the UMa_pathloss model instance.
- Parameters:
fc_GHz (float, optional) – Centre frequency in gigahertz, by default 3.5.
LOS (bool, optional) – Specifies whether the Line-of-Sight (LOS) model should be used, by default True.
**args – Catches unused keyword arguments for API compatibility.
- get_pathgain(d2D_m, d3D_m, U, C)¶
Calculates the linear pathgain.
Pathgain is the reciprocal of the linear pathloss.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
U (numpy.ndarray) – Array of UE locations.
C (numpy.ndarray) – Array of cell locations.
- Returns:
The linear pathgain for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss(d2D_m, d3D_m, U, C)¶
Calculates the linear pathloss based on the 3GPP UMa model.
Implements the full UMa logic, including the stochastic calculation of the effective environment height h_E and the breakpoint distance d_BP, which depends on the effective antenna heights.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres between UEs and cells.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
U (numpy.ndarray) – Array of UE locations, shape (n_ues, 3). The 3rd column (height) must be in the range [1.5, 22.5].
C (numpy.ndarray) – Array of cell locations, shape (n_cells, 3).
- Raises:
ValueError – If any h_UT value is outside its valid range.
- Returns:
The calculated linear pathloss for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss_dB(d2D_m, d3D_m, U, C)¶
Calculates the pathloss in decibels (dB).
This is a convenience wrapper around
get_pathloss()that converts the linear pathloss value to the dB scale.- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres between UEs and cells.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
U (numpy.ndarray) – Array of UE locations, shape (n_ues, 3).
C (numpy.ndarray) – Array of cell locations, shape (n_cells, 3).
- Returns:
The pathloss in decibels.
- Return type:
numpy.ndarray
UMa pathloss model¶
UMi (Urban Microcell) pathloss model¶
- class UMi_pathloss_model_00.UMi_pathloss(fc_GHz=3.5, h_UT=1.5, h_BS=10.0, LOS=True, **args)¶
The complete Urban Microcell (UMi) pathloss model from 3GPP TR 38.901.
This class implements the full UMi model where antenna heights can vary for each link. Unlike
UMi_pathloss_constant_height, it calculates all pathloss coefficients dynamically at runtime based on the specific heights of the UE and BS involved in each link. This provides maximum accuracy at the cost of computational performance.See also
UMi_pathloss_constant_heightSimplified model with fixed heights.
UMi_pathloss_discretisedPerformance-oriented model with quantised heights.
References
3GPP TR 38.901, Section 7.4.1, Table 7.4.1-1.
- __init__(fc_GHz=3.5, h_UT=1.5, h_BS=10.0, LOS=True, **args)¶
Initialise the UMi_pathloss model instance.
- Parameters:
fc_GHz (float, optional) – Centre frequency in GHz, by default 3.5.
h_UT (float, optional) – Default height of the User Terminal in metres, used for plotting. Defaults to 1.5.
h_BS (float, optional) – Default height of the Base Station in metres, used for plotting. Defaults to 10.0.
LOS (bool, optional) – Specifies whether to use the Line-of-Sight model. Defaults to True.
**args – Catches unused keyword arguments for API compatibility.
- get_pathgain(d2D_m, d3D_m, U, C)¶
Calculate the linear pathgain.
Pathgain is defined as the reciprocal of the linear pathloss.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
U (numpy.ndarray) – Array of UE locations and heights.
C (numpy.ndarray) – Array of cell locations and heights.
- Returns:
The linear pathgain for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss(d2D_m, d3D_m, U, C)¶
Calculate linear pathloss with dynamic antenna heights.
This method computes pathloss by dynamically calculating coefficients for each UE-cell link based on their specific heights, extracted from the U and C arrays.
- Parameters:
d2D_m (numpy.ndarray) – A matrix of 2D distances in metres. Shape: (n_ues, n_cells).
d3D_m (numpy.ndarray) – A matrix of 3D distances in metres. Shape: (n_ues, n_cells).
U (numpy.ndarray) – Array of UE locations, shape (n_ues, 3). The 3rd column (height) must be in the range [1.5, 22.5].
C (numpy.ndarray) – Array of cell locations, shape (n_cells, 3).
- Returns:
The calculated linear pathloss for each UE-cell link.
- Return type:
numpy.ndarray
- Raises:
ValueError – If any h_UT value is outside its valid range of [1.5, 22.5]m.
- get_pathloss_dB(d2D_m, d3D_m, U, C)¶
Calculate the pathloss in decibels (dB).
This method is a convenience wrapper around
get_pathloss()that converts the linear pathloss value to the dB scale.- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
U (numpy.ndarray) – Array of UE locations and heights, shape (n_ues, 3).
C (numpy.ndarray) – Array of cell locations and heights, shape (n_cells, 3).
- Returns:
The pathloss in decibels.
- Return type:
numpy.ndarray
- class UMi_pathloss_model_00.UMi_pathloss_constant_height(fc_GHz=3.5, h_UT=1.5, h_BS=10.0, LOS=True, **args)¶
Urban Microcell (UMi) pathloss model assuming constant antenna heights.
This class implements a simplified version of the 3GPP TR 38.901 UMi model. By assuming that the heights of the User Terminal and Base Station are constant for all links, it can pre-calculate several coefficients during initialisation. This leads to a significant performance gain during runtime compared to the full model, which must compute these values dynamically for each link.
- fc_GHz¶
Centre frequency in GHz.
- Type:
float
- h_BS¶
Height of the base station in metres.
- Type:
float
- h_UT¶
Height of the user terminal in metres.
- Type:
float
- LOS¶
Indicates if the Line-of-Sight (True) or Non-Line-of-Sight (False) model is active.
- Type:
bool
References
3GPP TR 38.901, Section 7.4.1, Table 7.4.1-1.
- __init__(fc_GHz=3.5, h_UT=1.5, h_BS=10.0, LOS=True, **args)¶
Initialise the UMi_pathloss_constant_height model instance.
This constructor sets up the model’s parameters and pre-calculates the constant terms used in the pathloss formulas, based on the fixed antenna heights.
- Parameters:
fc_GHz (float, optional) – Centre frequency in GHz, by default 3.5.
h_UT (float, optional) – Height of the User Terminal in metres. Must be in [1.5, 22.5]. Defaults to 1.5.
h_BS (float, optional) – Height of the Base Station in metres, by default 10.0.
LOS (bool, optional) – Specifies whether to use the Line-of-Sight model. Defaults to True.
**args – Catches unused keyword arguments for API compatibility.
- Raises:
ValueError – If h_UT is outside its valid range of [1.5, 22.5]m.
- get_pathgain(d2D_m, d3D_m)¶
Calculate the linear pathgain.
Pathgain is defined as the reciprocal of the linear pathloss.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
- Returns:
The linear pathgain for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss(d2D_m, d3D_m)¶
Calculate the linear pathloss for each UE-cell link.
This method computes the pathloss using pre-calculated coefficients. For Line-of-Sight (LOS) conditions, it applies a dual-slope model based on the breakpoint distance d_BP. For Non-Line-of-Sight (NLOS), it calculates the NLOS pathloss and returns the maximum of the two.
- Parameters:
d2D_m (numpy.ndarray) – A matrix of 2D distances (ground distances) in metres between UEs and cells. Shape: (n_ues, n_cells).
d3D_m (numpy.ndarray) – A matrix of 3D distances (direct line-of-sight distances) in metres between UEs and cells. Shape: (n_ues, n_cells).
- Returns:
The calculated linear pathloss for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss_dB(d2D_m, d3D_m)¶
Calculate the pathloss in decibels (dB).
This method is a convenience wrapper around
get_pathloss()that converts the linear pathloss value to the dB scale.- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres between UEs and cells.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
- Returns:
The pathloss in decibels.
- Return type:
numpy.ndarray
- class UMi_pathloss_model_00.UMi_pathloss_discretised(fc_GHz=3.5, h_ut_res=0.5, h_bs_res=1.0, h_bs_min=10.0, h_bs_max=25.0, LOS=True, **args)¶
Urban Microcell (UMi) pathloss model with discretised heights.
This class implements a performance-optimised version of the UMi model. It pre-calculates pathloss coefficients for a grid of discrete UE and BS heights. At runtime, it rounds the actual antenna heights to the nearest grid point and uses the corresponding pre-calculated values. This approach trades a small amount of accuracy for a significant gain in computational speed, making it suitable for large-scale simulations.
See also
UMi_pathlossThe full, exact UMi pathloss model implementation.
UMi_pathloss_constant_heightSimplified model with fixed heights.
References
3GPP TR 38.901, Section 7.4.1, Table 7.4.1-1.
- __init__(fc_GHz=3.5, h_ut_res=0.5, h_bs_res=1.0, h_bs_min=10.0, h_bs_max=25.0, LOS=True, **args)¶
Initialise the UMi_pathloss_discretised model instance.
This constructor defines the discrete height grids for UEs and BSs and pre-calculates the pathloss coefficient matrices for every combination of heights on those grids.
- Parameters:
fc_GHz (float, optional) – Centre frequency in GHz, by default 3.5.
h_ut_res (float, optional) – Resolution of the discrete UT height grid in metres, by default 0.5.
h_bs_res (float, optional) – Resolution of the discrete BS height grid in metres, by default 1.0.
h_bs_min (float, optional) – The minimum BS height for the discretisation grid. Defaults to 10.0. 3GPP does not specify a constraint on BS height, hence the user might want to change this value to suit their scenario.
h_bs_max (float, optional) – The maximum BS height for the discretisation grid. Defaults to 10.0. 3GPP does not specify a constraint on BS height, hence the user might want to change this value to suit their scenario.
LOS (bool, optional) – Specifies whether to use the Line-of-Sight model. Defaults to True.
**args – Catches unused keyword arguments for API compatibility.
- get_pathgain(d2D_m, d3D_m, U, C)¶
Calculate the linear pathgain.
Pathgain is defined as the reciprocal of the linear pathloss.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
U (numpy.ndarray) – Array of UE locations and heights.
C (numpy.ndarray) – Array of cell locations and heights.
- Returns:
The linear pathgain for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss(d2D_m, d3D_m, U, C)¶
Calculate linear pathloss using discretised height lookups.
This method determines the appropriate indices in the pre-calculated coefficient matrices by rounding the actual UE and BS heights. It then uses these indexed values to compute the pathloss.
- Parameters:
d2D_m (numpy.ndarray) – A matrix of 2D distances in metres. Shape: (n_ues, n_cells).
d3D_m (numpy.ndarray) – A matrix of 3D distances in metres. Shape: (n_ues, n_cells).
U (numpy.ndarray) – Array of UE locations and heights. The 3rd column must be within the defined grid range.
C (numpy.ndarray) – Array of cell locations and heights. The 3rd column must be within the defined grid range.
- Returns:
The calculated linear pathloss for each UE-cell link.
- Return type:
numpy.ndarray
- Raises:
ValueError – If any h_UT or h_BS value is outside its valid grid range.
- get_pathloss_dB(d2D_m, d3D_m, U, C)¶
Calculate the pathloss in decibels (dB).
This method is a convenience wrapper around
get_pathloss()that converts the linear pathloss value to the dB scale.- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
U (numpy.ndarray) – Array of UE locations and heights, shape (n_ues, 3).
C (numpy.ndarray) – Array of cell locations and heights, shape (n_cells, 3).
- Returns:
The pathloss in decibels.
- Return type:
numpy.ndarray
UMi pathloss model¶
InH (Indoor Hotspot) pathloss model¶
- class InH_pathloss_model_01.InH_pathloss(fc_GHz=3.5, LOS=True, **args)¶
Indoor Hotspot (InH) pathloss model from 3GPP TR 38.901.
Calculates pathloss for indoor office environments, supporting both Line-of-Sight (LOS) and Non-Line-of-Sight (NLOS) scenarios.
- fc_GHz¶
Centre frequency in gigahertz.
- Type:
float
- LOS¶
Flag indicating if the Line-of-Sight model is active.
- Type:
bool
References
3GPP TR 38.901: https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3173
- __init__(fc_GHz=3.5, LOS=True, **args)¶
Initialises the InH_pathloss model instance.
- Parameters:
fc_GHz (float, optional) – Centre frequency in gigahertz. Defaults to 3.5.
h_UT (float, optional) – Default User Terminal height in metres. Defaults to 1.5.
h_BS (float, optional) – Default Base Station height in metres. Defaults to 3.0.
LOS (bool, optional) – Specifies whether the Line-of-Sight (LOS) model should be used. Defaults to True.
**args – Catches unused keyword arguments for API compatibility.
- get_pathgain(d2D_m, d3D_m, U, C)¶
Calculates the linear pathgain.
Pathgain is the reciprocal of the linear pathloss.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix in metres.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
U (numpy.ndarray) – Array of UE locations.
C (numpy.ndarray) – Array of cell locations.
- Returns:
The linear pathgain for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss(d2D_m, d3D_m, U, C)¶
Calculates the linear pathloss based on the 3GPP InH model.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix (metres). Not used in calculation.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
U (numpy.ndarray) – Array of UE locations. Not used in calculation.
C (numpy.ndarray) – Array of cell locations. Not used in calculation.
- Raises:
ValueError – If any d3D_m value is outside the valid range of [1.0, 150.0] metres.
- Returns:
The calculated linear pathloss for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss_dB(d2D_m, d3D_m, U, C)¶
Calculates the pathloss in decibels (dB).
This is a convenience wrapper around
get_pathloss()that converts the linear pathloss value to the dB scale.- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix (metres). Not used in calculation.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
U (numpy.ndarray) – Array of UE locations. Not used in calculation.
C (numpy.ndarray) – Array of cell locations. Not used in calculation.
- Returns:
The pathloss in decibels.
- Return type:
numpy.ndarray
- InH_pathloss_model_01.plot_InH_pathloss_or_pathgain(plot_type='pathloss', fc_GHz=3.5, h_UT=1.5, h_BS=3.0, zoom_box=False, print_10m_pl=False, author=' ', x_min=1.0, x_max=120.0)¶
Plots 3GPP InH pathloss or pathgain model predictions as a self-test.
This function generates a plot of the 3GPP InH pathloss or pathgain models for both Line-of-Sight (LOS) and Non-Line-of-Sight (NLOS) scenarios. It also includes a free-space pathloss reference and an optional zoomed-in view of the plot for detailed analysis.
- Parameters:
plot_type (str, optional) – Type of plot to generate. Options are ‘pathloss’ (default) to plot pathloss in dB, or ‘pathgain’ to plot linear pathgain.
fc_GHz (float, optional) – Carrier frequency in GHz, defaults to 3.5.
h_UT (float, optional) – Height of the User Terminal (UE) in metres, defaults to 1.5.
h_BS (float, optional) – Height of the Base Station (BS) in metres, defaults to 3.0.
zoom_box (bool, optional) – If True, includes a zoomed-in inset on the plot. Defaults to False.
print_10m_pl (bool, optional) – If True, prints pathloss values at 10 metres to the console for LOS, NLOS, and free-space scenarios. Defaults to False.
author (str, optional) – Author name to include in the plot timestamp. Defaults to ‘ ‘.
x_min (float, optional) – Minimum distance for the plot’s x-axis in metres. Defaults to 1.0.
x_max (float, optional) – Maximum distance for the plot’s x-axis in metres. Defaults to 120.0.
- Raises:
ImportError – If required plotting modules (e.g., matplotlib) are not installed.
Notes
The function uses the
InH_pathlossclass to compute the pathloss and pathgain values for the different scenarios.
InH pathloss model¶
Power-law pathloss model¶
- class power_law_pathloss_model_02.Power_law_pathloss(fc_GHz, exponent, **args)¶
Simple power-law (or log-distance) pathloss model.
Calculates pathloss using the formula: PL(d) [dB] = PL(d0) + 10 * n * log10(d / d0)
This implementation fixes the reference distance d0 = 1 metre and calculates the reference pathloss PL(d0) using the free-space formula at 1m.
- fc_GHz¶
Centre frequency in gigahertz (used to calculate PL at 1m).
- Type:
float
- exponent¶
The pathloss exponent ‘n’.
- Type:
float
- L_0¶
The linear pathloss at the 1-metre reference distance.
- Type:
float
- L_0_dB¶
The pathloss in dB at the 1-metre reference distance.
- Type:
float
References
Barclay (Ed.), “Propagation of Radiowaves,” 2nd ed., IET, 2003.
- __init__(fc_GHz, exponent, **args)¶
Initialises the Power_law_pathloss model instance.
- Parameters:
fc_GHz (float) – Centre frequency in gigahertz.
exponent (float) – The pathloss exponent ‘n’.
**args – Catches unused keyword arguments for API compatibility.
- get_pathgain(d2D_m, d3D_m, U, C, **args)¶
Calculates the linear pathgain.
Pathgain is the reciprocal of the linear pathloss.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix (metres). Unused by this model.
d3D_m (numpy.ndarray) – 3D distance matrix in metres.
U (numpy.ndarray) – Array of UE locations, shape (n_ues, 3). Unused.
C (numpy.ndarray) – Array of cell locations, shape (n_cells, 3). Unused
**args – Catches unused keyword arguments.
- Returns:
The linear pathgain for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss(d2D_m, d3D_m, **args)¶
Calculates the linear pathloss.
Implements the formula: PL_linear = L_0 * (d ^ exponent) where L_0 is the free-space pathloss at 1 metre. This model only uses the 3D distance.
- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix (metres). Unused by this model.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
**args – Catches unused keyword arguments.
- Returns:
The calculated linear pathloss for each UE-cell link.
- Return type:
numpy.ndarray
- get_pathloss_dB(d2D_m, d3D_m, **args)¶
Calculates the pathloss in decibels (dB).
This is a convenience wrapper around
get_pathloss()that converts the linear pathloss value to the dB scale.- Parameters:
d2D_m (numpy.ndarray) – 2D distance matrix (metres). Unused by this model, but included for API compatibility.
d3D_m (numpy.ndarray) – 3D distance matrix in metres between UEs and cells.
**args – Catches unused keyword arguments.
- Returns:
The pathloss in decibels.
- Return type:
numpy.ndarray
- power_law_pathloss_model_02.plot_power_law_pathloss_or_pathgain(plot_type='pathloss', fc_GHz=3.5, exponent=3.0, print_10m_pl=False, author='', x_min=35.0, x_max=5000.0)¶
Plot 3GPP power_law pathloss or pathgain model predictions as a self-test.
Generates a plot comparing the power_law pathloss or pathgain models. It includes a free-space pathloss reference and an optional zoomed-in view for detailed analysis.
- Parameters:
plot_type (str, optional) – Type of plot to generate. Options are ‘pathloss’ (default) to plot pathloss in dB, or ‘pathgain’ to plot linear pathgain.
fc_GHz (float, optional) – Carrier frequency in GHz, by default 3.5.
exponent (float, optional) – Exponent used in the power-law model, by default 3.0.
print_10m_pl (bool, optional) – If True, prints pathloss values at 10 metres to the console. Defaults to False.
author (str, optional) – Author name to include in the plot timestamp, empty by default.
x_min (float, optional) – Minimum distance for the plot’s x-axis in metres, by default 35.0.
x_max (float, optional) – Maximum distance for the plot’s x-axis in metres, by default 5000.0.
- Raises:
ImportError – If required plotting modules (e.g., matplotlib) are not installed.
Power-law pathloss model¶
Last modified: 2025-11-12 14:10