A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
three-gpp-ntn-channel-example.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023 SIGNET Lab, Department of Information Engineering,
3 * University of Padova
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 */
7
8/**
9 * \file
10 * This example is a modified version of "three-gpp-channel-example", to include
11 * the 3GPP NTN channel model.
12 * Specifically, most changes (which are also highlighted throughout the code)
13 * impact the main method, and comprise:
14 * - the configuration of ad-hoc propagation and channel condition models;
15 * - the use of GeocentricConstantPositionMobilityModel for the nodes mobility.
16 * The pre-configured parameters are the one provided by 3GPP in TR 38.821,
17 * more specifically scenario 10 in down-link mode.
18 * Two static nodes, one on the ground and one in orbit, communicate with each other.
19 * The carrier frequency is set at 20GHz with 400MHz bandwidth.
20 * The result is the SNR of the signal and the path loss, saved in the ntn-snr-trace.txt file.
21 */
22
23#include "ns3/channel-condition-model.h"
24#include "ns3/constant-position-mobility-model.h"
25#include "ns3/core-module.h"
26#include "ns3/geocentric-constant-position-mobility-model.h"
27#include "ns3/isotropic-antenna-model.h"
28#include "ns3/mobility-model.h"
29#include "ns3/net-device.h"
30#include "ns3/node-container.h"
31#include "ns3/node.h"
32#include "ns3/parabolic-antenna-model.h"
33#include "ns3/simple-net-device.h"
34#include "ns3/spectrum-signal-parameters.h"
35#include "ns3/three-gpp-channel-model.h"
36#include "ns3/three-gpp-propagation-loss-model.h"
37#include "ns3/three-gpp-spectrum-propagation-loss-model.h"
38#include "ns3/uniform-planar-array.h"
39#include <ns3/antenna-model.h>
40
41#include <fstream>
42
43NS_LOG_COMPONENT_DEFINE("NTNChannelExample");
44
45using namespace ns3;
46
48 m_propagationLossModel; //!< the PropagationLossModel object
50 m_spectrumLossModel; //!< the SpectrumPropagationLossModel object
51static std::ofstream resultsFile; //!< The results file
52
53/**
54 * @brief Create the PSD for the TX
55 *
56 * @param fcHz the carrier frequency in Hz
57 * @param pwrDbm the transmission power in dBm
58 * @param bwHz the bandwidth in Hz
59 * @param rbWidthHz the Resource Block (RB) width in Hz
60 *
61 * @return the pointer to the PSD
62 */
64CreateTxPowerSpectralDensity(double fcHz, double pwrDbm, double bwHz, double rbWidthHz)
65{
66 unsigned int numRbs = std::floor(bwHz / rbWidthHz);
67 double f = fcHz - (numRbs * rbWidthHz / 2.0);
68 double powerTx = pwrDbm; // dBm power
69
70 Bands rbs; // A vector representing each resource block
71 for (uint32_t numrb = 0; numrb < numRbs; ++numrb)
72 {
73 BandInfo rb;
74 rb.fl = f;
75 f += rbWidthHz / 2;
76 rb.fc = f;
77 f += rbWidthHz / 2;
78 rb.fh = f;
79
80 rbs.push_back(rb);
81 }
84
85 double powerTxW = std::pow(10., (powerTx - 30) / 10); // Get Tx power in Watts
86 double txPowerDensity = (powerTxW / bwHz);
87
88 for (auto psd = txPsd->ValuesBegin(); psd != txPsd->ValuesEnd(); ++psd)
89 {
90 *psd = txPowerDensity;
91 }
92
93 return txPsd; // [W/Hz]
94}
95
96/**
97 * @brief Create the noise PSD for the
98 *
99 * @param fcHz the carrier frequency in Hz
100 * @param noiseFigureDb the noise figure in dB
101 * @param bwHz the bandwidth in Hz
102 * @param rbWidthHz the Resource Block (RB) width in Hz
103 *
104 * @return the pointer to the noise PSD
105 */
107CreateNoisePowerSpectralDensity(double fcHz, double noiseFigureDb, double bwHz, double rbWidthHz)
108{
109 unsigned int numRbs = std::floor(bwHz / rbWidthHz);
110 double f = fcHz - (numRbs * rbWidthHz / 2.0);
111
112 Bands rbs; // A vector representing each resource block
113 std::vector<int> rbsId; // A vector representing the resource block IDs
114 for (uint32_t numrb = 0; numrb < numRbs; ++numrb)
115 {
116 BandInfo rb;
117 rb.fl = f;
118 f += rbWidthHz / 2;
119 rb.fc = f;
120 f += rbWidthHz / 2;
121 rb.fh = f;
122
123 rbs.push_back(rb);
124 rbsId.push_back(numrb);
125 }
128
129 // see "LTE - From theory to practice"
130 // Section 22.4.4.2 Thermal Noise and Receiver Noise Figure
131 const double ktDbmHz = -174.0; // dBm/Hz
132 double ktWHz = std::pow(10.0, (ktDbmHz - 30) / 10.0); // W/Hz
133 double noiseFigureLinear = std::pow(10.0, noiseFigureDb / 10.0);
134
135 double noisePowerSpectralDensity = ktWHz * noiseFigureLinear;
136
137 for (auto rbId : rbsId)
138 {
139 (*txPsd)[rbId] = noisePowerSpectralDensity;
140 }
141
142 return txPsd; // W/Hz
143}
144
145/**
146 * \brief A structure that holds the parameters for the
147 * ComputeSnr function. In this way the problem with the limited
148 * number of parameters of method Schedule is avoided.
149 */
150struct ComputeSnrParams
151{
152 Ptr<MobilityModel> txMob; //!< the tx mobility model
153 Ptr<MobilityModel> rxMob; //!< the rx mobility model
154 double txPow; //!< the tx power in dBm
155 double noiseFigure; //!< the noise figure in dB
156 Ptr<PhasedArrayModel> txAntenna; //!< the tx antenna array
157 Ptr<PhasedArrayModel> rxAntenna; //!< the rx antenna array
158 double frequency; //!< the carrier frequency in Hz
159 double bandwidth; //!< the total bandwidth in Hz
160 double resourceBlockBandwidth; //!< the Resource Block bandwidth in Hz
161
162 /**
163 * \brief Constructor
164 * \param pTxMob the tx mobility model
165 * \param pRxMob the rx mobility model
166 * \param pTxPow the tx power in dBm
167 * \param pNoiseFigure the noise figure in dB
168 * \param pTxAntenna the tx antenna array
169 * \param pRxAntenna the rx antenna array
170 * \param pFrequency the carrier frequency in Hz
171 * \param pBandwidth the total bandwidth in Hz
172 * \param pResourceBlockBandwidth the Resource Block bandwidth in Hz
173 */
175 Ptr<MobilityModel> pRxMob,
176 double pTxPow,
177 double pNoiseFigure,
178 Ptr<PhasedArrayModel> pTxAntenna,
179 Ptr<PhasedArrayModel> pRxAntenna,
180 double pFrequency,
181 double pBandwidth,
182 double pResourceBlockBandwidth)
183 {
184 txMob = pTxMob;
185 rxMob = pRxMob;
186 txPow = pTxPow;
187 noiseFigure = pNoiseFigure;
188 txAntenna = pTxAntenna;
189 rxAntenna = pRxAntenna;
190 frequency = pFrequency;
191 bandwidth = pBandwidth;
192 resourceBlockBandwidth = pResourceBlockBandwidth;
193 }
194};
195
196/**
197 * Perform the beamforming using the DFT beamforming method
198 * \param thisDevice the device performing the beamforming
199 * \param thisAntenna the antenna object associated to thisDevice
200 * \param otherDevice the device towards which point the beam
201 */
202static void
204 Ptr<PhasedArrayModel> thisAntenna,
205 Ptr<NetDevice> otherDevice)
206{
207 // retrieve the position of the two devices
208 Vector aPos = thisDevice->GetNode()->GetObject<MobilityModel>()->GetPosition();
209 Vector bPos = otherDevice->GetNode()->GetObject<MobilityModel>()->GetPosition();
210
211 // compute the azimuth and the elevation angles
212 Angles completeAngle(bPos, aPos);
213 double hAngleRadian = completeAngle.GetAzimuth();
214 double vAngleRadian = completeAngle.GetInclination(); // the elevation angle
215
216 // retrieve the number of antenna elements and resize the vector
217 uint64_t totNoArrayElements = thisAntenna->GetNumElems();
218 PhasedArrayModel::ComplexVector antennaWeights(totNoArrayElements);
219
220 // the total power is divided equally among the antenna elements
221 double power = 1.0 / sqrt(totNoArrayElements);
222
223 // compute the antenna weights
224 const double sinVAngleRadian = sin(vAngleRadian);
225 const double cosVAngleRadian = cos(vAngleRadian);
226 const double sinHAngleRadian = sin(hAngleRadian);
227 const double cosHAngleRadian = cos(hAngleRadian);
228
229 for (uint64_t ind = 0; ind < totNoArrayElements; ind++)
230 {
231 Vector loc = thisAntenna->GetElementLocation(ind);
232 double phase = -2 * M_PI *
233 (sinVAngleRadian * cosHAngleRadian * loc.x +
234 sinVAngleRadian * sinHAngleRadian * loc.y + cosVAngleRadian * loc.z);
235 antennaWeights[ind] = exp(std::complex<double>(0, phase)) * power;
236 }
237
238 // store the antenna weights
239 thisAntenna->SetBeamformingVector(antennaWeights);
240}
241
242/**
243 * Compute the average SNR
244 * \param params A structure that holds the parameters that are needed to perform calculations in
245 * ComputeSnr
246 */
247static void
249{
250 Ptr<SpectrumValue> txPsd = CreateTxPowerSpectralDensity(params.frequency,
251 params.txPow,
252 params.bandwidth,
253 params.resourceBlockBandwidth);
254 Ptr<SpectrumValue> rxPsd = txPsd->Copy();
255 NS_LOG_DEBUG("Average tx power " << 10 * log10(Sum(*txPsd) * params.resourceBlockBandwidth)
256 << " dB");
257
258 // create the noise PSD
259 Ptr<SpectrumValue> noisePsd = CreateNoisePowerSpectralDensity(params.frequency,
260 params.noiseFigure,
261 params.bandwidth,
262 params.resourceBlockBandwidth);
263 NS_LOG_DEBUG("Average noise power "
264 << 10 * log10(Sum(*noisePsd) * params.resourceBlockBandwidth) << " dB");
265
266 // apply the pathloss
267 double propagationGainDb = m_propagationLossModel->CalcRxPower(0, params.txMob, params.rxMob);
268 NS_LOG_DEBUG("Pathloss " << -propagationGainDb << " dB");
269 double propagationGainLinear = std::pow(10.0, (propagationGainDb) / 10.0);
270 *(rxPsd) *= propagationGainLinear;
271
272 NS_ASSERT_MSG(params.txAntenna, "params.txAntenna is nullptr!");
273 NS_ASSERT_MSG(params.rxAntenna, "params.rxAntenna is nullptr!");
274
276 rxSsp->psd = rxPsd;
277 rxSsp->txAntenna =
278 ConstCast<AntennaModel, const AntennaModel>(params.txAntenna->GetAntennaElement());
279
280 // apply the fast fading and the beamforming gain
281 rxSsp = m_spectrumLossModel->CalcRxPowerSpectralDensity(rxSsp,
282 params.txMob,
283 params.rxMob,
284 params.txAntenna,
285 params.rxAntenna);
286 NS_LOG_DEBUG("Average rx power " << 10 * log10(Sum(*rxSsp->psd) * params.bandwidth) << " dB");
287
288 // compute the SNR
289 NS_LOG_DEBUG("Average SNR " << 10 * log10(Sum(*rxSsp->psd) / Sum(*noisePsd)) << " dB");
290
291 // print the SNR and pathloss values in the output file
293 << 10 * log10(Sum(*rxSsp->psd) / Sum(*noisePsd)) << " " << propagationGainDb
294 << std::endl;
295}
296
297int
298main(int argc, char* argv[])
299{
300 uint32_t simTimeMs = 1000; // simulation time in milliseconds
301 uint32_t timeResMs = 10; // time resolution in milliseconds
302
303 // Start changes with respect to three-gpp-channel-example
304 // SCENARIO 10 DL of TR 38.321
305 // This parameters can be set accordingly to 3GPP TR 38.821 or arbitrarily modified
306 std::string scenario = "NTN-Suburban"; // 3GPP propagation scenario
307 // All available NTN scenarios: DenseUrban, Urban, Suburban, Rural.
308
309 double frequencyHz = 20e9; // operating frequency in Hz
310 double bandwidthHz = 400e6; // Hz
311 double RbBandwidthHz = 120e3; // Hz
312
313 // Satellite parameters
314 double satEIRPDensity = 40; // dBW/MHz
315 double satAntennaGainDb = 58.5; // dB
316
317 // UE Parameters
318 double vsatAntennaGainDb = 39.7; // dB
319 double vsatAntennaNoiseFigureDb = 1.2; // dB
320 // End changes with respect to three-gpp-channel-example
321
322 /* Command line argument parser setup. */
323 CommandLine cmd(__FILE__);
324 cmd.AddValue("scenario",
325 "The 3GPP NTN scenario to use. Valid options are: "
326 "NTN-DenseUrban, NTN-Urban, NTN-Suburban, and NTN-Rural",
327 scenario);
328 cmd.AddValue("frequencyHz", "The carrier frequency in Hz", frequencyHz);
329 cmd.AddValue("bandwidthHz", "The bandwidth in Hz", bandwidthHz);
330 cmd.AddValue("satEIRPDensity", "The satellite EIRP density in dBW/MHz", satEIRPDensity);
331 cmd.AddValue("satAntennaGainDb", "The satellite antenna gain in dB", satAntennaGainDb);
332 cmd.AddValue("vsatAntennaGainDb", "The UE VSAT antenna gain in dB", vsatAntennaGainDb);
333 cmd.AddValue("vsatAntennaNoiseFigureDb",
334 "The UE VSAT antenna noise figure in dB",
335 vsatAntennaNoiseFigureDb);
336 cmd.Parse(argc, argv);
337
338 // Calculate transmission power in dBm using EIRPDensity + 10*log10(Bandwidth) - AntennaGain +
339 // 30
340 double txPowDbm = (satEIRPDensity + 10 * log10(bandwidthHz / 1e6) - satAntennaGainDb) + 30;
341
342 NS_LOG_DEBUG("Transmitting power: " << txPowDbm << "dBm, (" << pow(10., (txPowDbm - 30) / 10)
343 << "W)");
344
345 Config::SetDefault("ns3::ThreeGppChannelModel::UpdatePeriod",
346 TimeValue(MilliSeconds(10))); // update the channel at every 10 ms
347 Config::SetDefault("ns3::ThreeGppChannelConditionModel::UpdatePeriod",
348 TimeValue(MilliSeconds(0.0))); // do not update the channel condition
349
352
353 // create and configure the factories for the channel condition and propagation loss models
354 ObjectFactory propagationLossModelFactory;
355 ObjectFactory channelConditionModelFactory;
356
357 // Start changes with respect to three-gpp-channel-example
358 if (scenario == "NTN-DenseUrban")
359 {
360 propagationLossModelFactory.SetTypeId(
362 channelConditionModelFactory.SetTypeId(
364 }
365 else if (scenario == "NTN-Urban")
366 {
367 propagationLossModelFactory.SetTypeId(ThreeGppNTNUrbanPropagationLossModel::GetTypeId());
368 channelConditionModelFactory.SetTypeId(ThreeGppNTNUrbanChannelConditionModel::GetTypeId());
369 }
370 else if (scenario == "NTN-Suburban")
371 {
373 channelConditionModelFactory.SetTypeId(
375 }
376 else if (scenario == "NTN-Rural")
377 {
378 propagationLossModelFactory.SetTypeId(ThreeGppNTNRuralPropagationLossModel::GetTypeId());
379 channelConditionModelFactory.SetTypeId(ThreeGppNTNRuralChannelConditionModel::GetTypeId());
380 }
381 else
382 {
383 NS_FATAL_ERROR("Unknown NTN scenario");
384 }
385 // End changes with respect to three-gpp-channel-example
386
387 // create the propagation loss model
388 m_propagationLossModel = propagationLossModelFactory.Create<ThreeGppPropagationLossModel>();
389 m_propagationLossModel->SetAttribute("Frequency", DoubleValue(frequencyHz));
390 m_propagationLossModel->SetAttribute("ShadowingEnabled", BooleanValue(true));
391
392 // create the spectrum propagation loss model
394 m_spectrumLossModel->SetChannelModelAttribute("Frequency", DoubleValue(frequencyHz));
395 m_spectrumLossModel->SetChannelModelAttribute("Scenario", StringValue(scenario));
396
397 // create the channel condition model and associate it with the spectrum and
398 // propagation loss model
400 channelConditionModelFactory.Create<ThreeGppChannelConditionModel>();
401 m_spectrumLossModel->SetChannelModelAttribute("ChannelConditionModel", PointerValue(condModel));
402 m_propagationLossModel->SetChannelConditionModel(condModel);
403
404 // create the tx and rx nodes
406 nodes.Create(2);
407
408 // create the tx and rx devices
411
412 // associate the nodes and the devices
413 nodes.Get(0)->AddDevice(txDev);
414 txDev->SetNode(nodes.Get(0));
415 nodes.Get(1)->AddDevice(rxDev);
416 rxDev->SetNode(nodes.Get(1));
417
418 // Start changes with respect to three-gpp-channel-example, here a mobility model
419 // tailored to NTN scenarios is used (GeocentricConstantPositionMobilityModel)
420 // create the tx and rx mobility models, set the positions
425
426 txMob->SetGeographicPosition(Vector(45.40869, 11.89448, 35786000)); // GEO over Padova
427 rxMob->SetGeographicPosition(Vector(45.40869, 11.89448, 14.0)); // Padova Coordinates
428
429 // This is not strictly necessary, but is useful to have "sensible" values when using
430 // GetPosition()
431 txMob->SetCoordinateTranslationReferencePoint(
432 Vector(45.40869, 11.89448, 0.0)); // Padova Coordinates without altitude
433 rxMob->SetCoordinateTranslationReferencePoint(
434 Vector(45.40869, 11.89448, 0.0)); // Padova Coordinates without altitude
435 // End changes with respect to three-gpp-channel-example,
436
437 NS_LOG_DEBUG("TX Position: " << txMob->GetPosition());
438 NS_LOG_DEBUG("RX Position: " << rxMob->GetPosition());
439
440 // assign the mobility models to the nodes
441 nodes.Get(0)->AggregateObject(txMob);
442 nodes.Get(1)->AggregateObject(rxMob);
443
444 // Start changes with respect to three-gpp-channel-example,
445 // Here antenna models mimic the gain achieved by the CircularApertureAntennaModel,
446 // which is not used to avoid inheriting the latter's dependence on either libstdc++
447 // or Boost.
449 "NumColumns",
450 UintegerValue(1),
451 "NumRows",
452 UintegerValue(1),
453 "AntennaElement",
456 DoubleValue(satAntennaGainDb))));
457
459 "NumColumns",
460 UintegerValue(1),
461 "NumRows",
462 UintegerValue(1),
463 "AntennaElement",
466 DoubleValue(vsatAntennaGainDb))));
467 // End changes with respect to three-gpp-channel-example
468
469 // set the beamforming vectors
470 DoBeamforming(rxDev, rxAntenna, txDev);
471 DoBeamforming(txDev, txAntenna, rxDev);
472
473 // Open the output results file
474 resultsFile.open("ntn-snr-trace.txt", std::ios::out);
475 NS_ASSERT_MSG(resultsFile.is_open(), "Results file could not be created");
476
477 for (int i = 0; i < floor(simTimeMs / timeResMs); i++)
478 {
479 Simulator::Schedule(MilliSeconds(timeResMs * i),
480 &ComputeSnr,
481 ComputeSnrParams(txMob,
482 rxMob,
483 txPowDbm,
484 vsatAntennaNoiseFigureDb,
485 txAntenna,
486 rxAntenna,
487 frequencyHz,
488 bandwidthHz,
489 RbBandwidthHz));
490 }
491
494
495 resultsFile.close();
496
497 return 0;
498}
Class holding the azimuth and inclination angles of spherical coordinates.
Definition angles.h:107
double GetInclination() const
Getter for inclination angle.
Definition angles.cc:236
double GetAzimuth() const
Getter for azimuth angle.
Definition angles.cc:230
Parse command-line arguments.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
Keep track of the current position and velocity of an object.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition node.cc:124
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Instantiate subclasses of ns3::Object.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition object.cc:298
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
Hold variables of type string.
Definition string.h:45
Base class for the 3GPP channel condition models.
Base class for the 3GPP propagation models.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:883
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::vector< BandInfo > Bands
Container of BandInfo.
Ptr< T1 > ConstCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:573
double Sum(const SpectrumValue &x)
A structure that holds the parameters for the ComputeSnr function.
ComputeSnrParams(Ptr< MobilityModel > pTxMob, Ptr< MobilityModel > pRxMob, double pTxPow, double pNoiseFigure, Ptr< PhasedArrayModel > pTxAntenna, Ptr< PhasedArrayModel > pRxAntenna, double pFrequency, double pBandwidth, double pResourceBlockBandwidth)
Constructor.
Ptr< PhasedArrayModel > txAntenna
the tx antenna array
Ptr< MobilityModel > rxMob
the rx mobility model
double bandwidth
the total bandwidth in Hz
double noiseFigure
the noise figure in dB
double resourceBlockBandwidth
the Resource Block bandwidth in Hz
double txPow
the tx power in dBm
double frequency
the carrier frequency in Hz
Ptr< PhasedArrayModel > rxAntenna
the rx antenna array
Ptr< MobilityModel > txMob
the tx mobility model
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
static Ptr< ThreeGppPropagationLossModel > m_propagationLossModel
the PropagationLossModel object
static void DoBeamforming(Ptr< NetDevice > thisDevice, Ptr< PhasedArrayModel > thisAntenna, Ptr< NetDevice > otherDevice)
Perform the beamforming using the DFT beamforming method.
Ptr< SpectrumValue > CreateNoisePowerSpectralDensity(double fcHz, double noiseFigureDb, double bwHz, double rbWidthHz)
Create the noise PSD for the.
static std::ofstream resultsFile
The results file.
static void ComputeSnr(ComputeSnrParams &params)
Compute the average SNR.
static Ptr< ThreeGppSpectrumPropagationLossModel > m_spectrumLossModel
the SpectrumPropagationLossModel object
Ptr< SpectrumValue > CreateTxPowerSpectralDensity(double fcHz, double pwrDbm, double bwHz, double rbWidthHz)
Create the PSD for the TX.