5G-LENA nr-v3.3-161-gad18933f
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
cttc-nr-3gpp-calibration-utils-v2.cc
1// Copyright (c) 2020 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#include "cttc-nr-3gpp-calibration-utils-v2.h"
6
7#include "flow-monitor-output-stats.h"
8#include "power-output-stats.h"
9#include "rb-output-stats.h"
10#include "slot-output-stats.h"
11
12#include "ns3/antenna-module.h"
13#include "ns3/config.h"
14#include "ns3/enum.h"
15#include "ns3/log.h"
16#include "ns3/nr-spectrum-value-helper.h"
17#include "ns3/object-vector.h"
18#include "ns3/pointer.h"
19
20NS_LOG_COMPONENT_DEFINE("LenaV2Utils");
21
22namespace ns3
23{
24
25void
26LenaV2Utils::ReportSinrNr(SinrOutputStats* stats,
27 uint16_t cellId,
28 uint16_t rnti,
29 double avgSinr,
30 uint16_t bwpId)
31{
32 stats->SaveSinr(cellId, rnti, avgSinr, bwpId);
33}
34
35void
36LenaV2Utils::ReportPowerNr(PowerOutputStats* stats,
37 const SfnSf& sfnSf,
38 Ptr<const SpectrumValue> txPsd,
39 const Time& t,
40 uint16_t rnti,
41 uint64_t imsi,
42 uint16_t bwpId,
43 uint16_t cellId)
44{
45 stats->SavePower(sfnSf, txPsd, t, rnti, imsi, bwpId, cellId);
46}
47
48void
49LenaV2Utils::ReportSlotStatsNr(SlotOutputStats* stats,
50 const SfnSf& sfnSf,
51 uint32_t scheduledUe,
52 uint32_t usedReg,
53 uint32_t usedSym,
54 uint32_t availableRb,
55 uint32_t availableSym,
56 uint16_t bwpId,
57 uint16_t cellId)
58{
59 stats->SaveSlotStats(sfnSf,
60 scheduledUe,
61 usedReg,
62 usedSym,
63 availableRb,
64 availableSym,
65 bwpId,
66 cellId);
67}
68
69void
70LenaV2Utils::ReportRbStatsNr(RbOutputStats* stats,
71 const SfnSf& sfnSf,
72 uint8_t sym,
73 const std::vector<int>& rbUsed,
74 uint16_t bwpId,
75 uint16_t cellId)
76{
77 stats->SaveRbStats(sfnSf, sym, rbUsed, bwpId, cellId);
78}
79
80void
81LenaV2Utils::ReportGnbRxDataNr(PowerOutputStats* gnbRxDataStats,
82 const SfnSf& sfnSf,
83 Ptr<const SpectrumValue> rxPsd,
84 const Time& t,
85 uint16_t bwpId,
86 uint16_t cellId)
87{
88 gnbRxDataStats->SavePower(sfnSf, rxPsd, t, 0, 0, bwpId, cellId);
89}
90
91void
92LenaV2Utils::ConfigureBwpTo(BandwidthPartInfoPtr& bwp, double centerFreq, double bwpBw)
93{
94 bwp->m_centralFrequency = centerFreq;
95 bwp->m_higherFrequency = centerFreq + (bwpBw / 2);
96 bwp->m_lowerFrequency = centerFreq - (bwpBw / 2);
97 bwp->m_channelBandwidth = bwpBw;
98}
99
100// unnamed namespace
101namespace
102{
103
104void
105ConfigurePhy(Ptr<NrHelper>& nrHelper,
106 Ptr<NetDevice> gnb,
107 double orientationRads,
108 uint16_t numerology,
109 double txPowerBs,
110 const std::string& pattern,
111 uint32_t bwpIndex,
112 double gnbFirstSubArray,
113 double gnbSecondSubArray,
114 uint16_t beamConfSector,
115 double beamConfElevation)
116{
117 // Change the antenna orientation
118 Ptr<NrGnbPhy> phy0 = nrHelper->GetGnbPhy(gnb, 0); // BWP 0
119 Ptr<UniformPlanarArray> antenna0 = ConstCast<UniformPlanarArray>(
120 phy0->GetSpectrumPhy()->GetAntenna()->GetObject<UniformPlanarArray>());
121 antenna0->SetAttribute("BearingAngle", DoubleValue(orientationRads));
122
123 // configure the beam that points toward the center of hexagonal
124 // In case of beamforming, it will be overwritten.
125 phy0->GetSpectrumPhy()->GetBeamManager()->SetPredefinedBeam(beamConfSector, beamConfElevation);
126
127 // Set numerology
128 nrHelper->GetGnbPhy(gnb, 0)->SetAttribute("Numerology", UintegerValue(numerology)); // BWP
129
130 // Set TX power
131 nrHelper->GetGnbPhy(gnb, 0)->SetAttribute("TxPower", DoubleValue(txPowerBs));
132
133 // Set TDD pattern
134 nrHelper->GetGnbPhy(gnb, 0)->SetAttribute("Pattern", StringValue(pattern));
135}
136
137} // unnamed namespace
138
139void
140LenaV2Utils::SetLenaV2SimulatorParameters(const double sector0AngleRad,
141 const std::string& scenario,
142 const std::string& confType,
143 const std::string& radioNetwork,
144 std::string errorModel,
145 const std::string& operationMode,
146 const std::string& direction,
147 uint16_t numerology,
148 const std::string& pattern,
149 const NodeContainer& gnbSector1Container,
150 const NodeContainer& gnbSector2Container,
151 const NodeContainer& gnbSector3Container,
152 const NodeContainer& ueSector1Container,
153 const NodeContainer& ueSector2Container,
154 const NodeContainer& ueSector3Container,
155 const Ptr<NrPointToPointEpcHelper>& baseEpcHelper,
156 Ptr<NrHelper>& nrHelper,
157 NetDeviceContainer& gnbSector1NetDev,
158 NetDeviceContainer& gnbSector2NetDev,
159 NetDeviceContainer& gnbSector3NetDev,
160 NetDeviceContainer& ueSector1NetDev,
161 NetDeviceContainer& ueSector2NetDev,
162 NetDeviceContainer& ueSector3NetDev,
163 bool enableFading,
164 bool enableUlPc,
165 std::string powerAllocation,
166 SinrOutputStats* sinrStats,
167 PowerOutputStats* ueTxPowerStats,
168 PowerOutputStats* gnbRxPowerStats,
169 SlotOutputStats* slotStats,
170 RbOutputStats* rbStats,
171 const std::string& scheduler,
172 uint32_t bandwidthMHz,
173 double startingFreq,
174 uint32_t freqScenario,
175 double gnbTxPower,
176 double ueTxPower,
177 double downtiltAngle,
178 const uint32_t gnbNumRows,
179 const uint32_t gnbNumColumns,
180 const uint32_t ueNumRows,
181 const uint32_t ueNumColumns,
182 bool gnbEnable3gppElement,
183 bool ueEnable3gppElement,
184 const double gnbHSpacing,
185 const double gnbVSpacing,
186 const double ueHSpacing,
187 const double ueVSpacing,
188 const double gnbNoiseFigure,
189 const double ueNoiseFigure,
190 bool enableRealBF,
191 bool enableShadowing,
192 double o2iThreshold,
193 double o2iLowLossThreshold,
194 bool linkO2iConditionToAntennaHeight,
195 bool crossPolarizedGnb,
196 bool crossPolarizedUe,
197 double polSlantAngleGnb1,
198 double polSlantAngleGnb2,
199 double polSlantAngleUe1,
200 double polSlantAngleUe2,
201 std::string bfMethod,
202 uint16_t beamConfSector,
203 double beamConfElevation,
204 double isd,
205 bool ueBearingAngle)
206{
207 /*
208 * Create the radio network related parameters
209 */
210 uint8_t numScPerRb = 1;
211 double rbOverhead = 0.1;
212 uint32_t harqProcesses = 20;
213 uint32_t n1Delay = 2;
214 uint32_t n2Delay = 2;
215 uint8_t dlCtrlSymbols = 1;
216
217 if (radioNetwork == "LTE")
218 {
219 rbOverhead = 0.1;
220 harqProcesses = 8;
221 n1Delay = 4;
222 n2Delay = 4;
223 // dlCtrlSymbols = 3;
224
225 if (errorModel.empty())
226 {
227 errorModel = "ns3::LenaErrorModel";
228 }
229 else if (errorModel != "ns3::NrLteMiErrorModel" && errorModel != "ns3::LenaErrorModel")
230 {
231 NS_ABORT_MSG("The selected error model is not recommended for LTE");
232 }
233 }
234 else if (radioNetwork == "NR")
235 {
236 rbOverhead = 0.04;
237 harqProcesses = 20;
238 if (errorModel.empty())
239 {
240 errorModel = "ns3::NrEesmIrT1";
241 }
242 else if (errorModel == "ns3::NrLteMiErrorModel")
243 {
244 NS_ABORT_MSG("The selected error model is not recommended for NR");
245 }
246 }
247 else
248 {
249 NS_ABORT_MSG("Unrecognized radio network technology");
250 }
251
252 /*
253 * Setup the NR module. We create the various helpers needed for the
254 * NR simulation:
255 * - IdealBeamformingHelper, which takes care of the beamforming part
256 * - NrHelper, which takes care of creating and connecting the various
257 * part of the NR stack
258 */
259
260 nrHelper = CreateObject<NrHelper>();
261
262 Ptr<BeamformingHelperBase> beamformingHelper;
263
264 // in LTE non-calibration we want to use predefined beams that we set directly
265 // through beam manager. Hence, we do not need any ideal algorithm.
266 // For other cases, we need it (and the beam will be overwritten)
267
268 if (enableFading && bfMethod != "FixedBeam")
269 {
270 if (radioNetwork == "NR" && enableRealBF)
271 {
272 beamformingHelper = CreateObject<RealisticBeamformingHelper>();
273 }
274 else
275 {
276 beamformingHelper = CreateObject<IdealBeamformingHelper>();
277 }
278 nrHelper->SetBeamformingHelper(beamformingHelper);
279 }
280
281 Ptr<NrPointToPointEpcHelper> nrEpcHelper = DynamicCast<NrPointToPointEpcHelper>(baseEpcHelper);
282 nrHelper->SetEpcHelper(nrEpcHelper);
283
284 double txPowerBs = 0.0;
285
286 NS_ABORT_MSG_UNLESS(scenario == "UMa" || scenario == "RMa" || scenario == "UMi",
287 "Unsupported scenario " << scenario << ". Supported values: UMa, RMa, UMi");
288 txPowerBs = gnbTxPower;
289 std::cout << "Scenario: " << scenario << "gnbTxPower: " << txPowerBs << std::endl;
290
291 std::cout << "o2iThreshold: " << o2iThreshold << std::endl;
292 std::cout << "o2iLowLossThreshold: " << o2iLowLossThreshold << std::endl;
293
294 // Noise figure for the gNB
295 nrHelper->SetGnbPhyAttribute("NoiseFigure", DoubleValue(gnbNoiseFigure));
296 // Noise figure for the UE
297 nrHelper->SetUePhyAttribute("NoiseFigure", DoubleValue(ueNoiseFigure));
298 nrHelper->SetUePhyAttribute("EnableUplinkPowerControl", BooleanValue(enableUlPc));
299
300 if (radioNetwork == "LTE" && confType == "calibrationConf" && enableUlPc)
301 {
302 Config::SetDefault("ns3::NrUePowerControl::ClosedLoop", BooleanValue(false));
303 Config::SetDefault("ns3::NrUePowerControl::PoNominalPucch", IntegerValue(-106));
304 Config::SetDefault("ns3::NrUePowerControl::PoNominalPusch", IntegerValue(-106));
305 Config::SetDefault("ns3::NrUePowerControl::Alpha",
306 DoubleValue(1.0)); // well this is the default value also
307 }
308
309 Config::SetDefault("ns3::NrMacSchedulerSrsDefault::StartingPeriodicity", UintegerValue(16));
310 nrHelper->SetSchedulerAttribute("SrsSymbols", UintegerValue(1));
311
312 NrSpectrumValueHelper::PowerAllocationType powerAllocationEnum;
313 if (powerAllocation == "UniformPowerAllocBw")
314 {
315 powerAllocationEnum = NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW;
316 }
317 else if (powerAllocation == "UniformPowerAllocUsed")
318 {
319 powerAllocationEnum = NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_USED;
320 }
321 else
322 {
323 NS_ABORT_MSG("Unsupported power allocation type "
324 << scenario
325 << ". Supported values: "
326 "UniformPowerAllocBw and UniformPowerAllocUsed.");
327 }
328
329 nrHelper->SetUePhyAttribute("PowerAllocationType", EnumValue(powerAllocationEnum));
330 // to match LENA default settings
331 nrHelper->SetGnbPhyAttribute("PowerAllocationType",
332 EnumValue(NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW));
333
334 // Error Model: UE and GNB with same spectrum error model.
335 nrHelper->SetUlErrorModel(errorModel);
336 nrHelper->SetDlErrorModel(errorModel);
337
338 // Both DL and UL AMC will have the same model behind.
339 nrHelper->SetGnbDlAmcAttribute("AmcModel", EnumValue(NrAmc::ShannonModel));
340 nrHelper->SetGnbUlAmcAttribute("AmcModel", EnumValue(NrAmc::ShannonModel));
341
342 /*
343 * Adjust the average number of Reference symbols per RB only for LTE case,
344 * which is larger than in NR. We assume a value of 4 (could be 3 too).
345 */
346 nrHelper->SetGnbDlAmcAttribute("NumRefScPerRb", UintegerValue(numScPerRb));
347 nrHelper->SetGnbUlAmcAttribute("NumRefScPerRb", UintegerValue(1)); // FIXME: Might change in LTE
348
349 nrHelper->SetGnbPhyAttribute("RbOverhead", DoubleValue(rbOverhead));
350 nrHelper->SetGnbPhyAttribute("N2Delay", UintegerValue(n2Delay));
351 nrHelper->SetGnbPhyAttribute("N1Delay", UintegerValue(n1Delay));
352
353 nrHelper->SetUeMacAttribute("NumHarqProcess", UintegerValue(harqProcesses));
354 nrHelper->SetGnbMacAttribute("NumHarqProcess", UintegerValue(harqProcesses));
355
356 /*
357 * Create the necessary operation bands.
358 *
359 * In the 0 frequency scenario, each sector operates, in a separate band,
360 * while for scenario 1 all the sectors are in the same band. Please note that
361 * a single BWP in FDD is half the size of the corresponding TDD BWP, and the
362 * parameter bandwidthMHz refers to the size of the FDD BWP.
363 *
364 * Scenario 0: sectors NON_OVERLAPPING in frequency
365 *
366 * FDD scenario 0:
367 *
368 * |--------Band0--------|--------Band1--------|--------Band2--------|
369 * |---------CC0---------|---------CC1---------|---------CC2---------|
370 * |---BWP0---|---BWP1---|---BWP2---|---BWP3---|---BWP4---|---BWP5---|
371 *
372 * Sector i will go in Bandi
373 * DL in the first BWP, UL in the second BWP
374 *
375 * TDD scenario 0:
376 *
377 * |--------Band0--------|--------Band1--------|--------Band2--------|
378 * |---------CC0---------|---------CC2---------|---------CC2---------|
379 * |---------BWP0--------|---------BWP1--------|---------BWP2--------|
380 *
381 * Sector i will go in BWPi
382 *
383 *
384 * Scenario 1: sectors in OVERLAPPING bands
385 *
386 * Note that this configuration has 1/3 the total bandwidth of the
387 * NON_OVERLAPPING configuration.
388 *
389 * FDD scenario 1:
390 *
391 * |--------Band0--------|
392 * |---------CC0---------|
393 * |---BWP0---|---BWP1---|
394 *
395 * Sector i will go in BWPi
396 *
397 * TDD scenario 1:
398 *
399 * |--------Band0--------|
400 * |---------CC0---------|
401 * |---------BWP0--------|
402 *
403 * This is tightly coupled with what happens in lena-v1-utils.cc
404 *
405 */
406 const double band0Start = startingFreq;
407 double bandwidthBwp = bandwidthMHz * 1e6;
408
409 OperationBandInfo band0;
410 OperationBandInfo band1;
411 OperationBandInfo band2;
412 band0.m_bandId = 0;
413 band1.m_bandId = 1;
414 band2.m_bandId = 2;
415
416 uint8_t numBwp = operationMode == "FDD" ? 2 : 1;
417
418 if (freqScenario == 0) // NON_OVERLAPPING
419 {
420 double bandwidthCc = numBwp * bandwidthBwp;
421 uint8_t numCcPerBand = 1;
422 double bandwidthBand = numCcPerBand * bandwidthCc;
423 double bandCenter = band0Start + bandwidthBand / 2.0;
424
425 NS_LOG_LOGIC("NON_OVERLAPPING, " << operationMode << ": " << bandwidthBand << ":"
426 << bandwidthCc << ":" << bandwidthBwp << ", "
427 << (int)numCcPerBand << ", " << (int)numBwp);
428
429 NS_LOG_LOGIC("bandConf0: " << bandCenter << " " << bandwidthBand);
430 CcBwpCreator::SimpleOperationBandConf bandConf0(bandCenter, bandwidthBand, numCcPerBand);
431 bandConf0.m_numBwp = numBwp;
432 bandCenter += bandwidthBand;
433
434 NS_LOG_LOGIC("bandConf1: " << bandCenter << " " << bandwidthBand);
435 CcBwpCreator::SimpleOperationBandConf bandConf1(bandCenter, bandwidthBand, numCcPerBand);
436 bandConf1.m_numBwp = numBwp;
437 bandCenter += bandwidthBand;
438
439 NS_LOG_LOGIC("bandConf2: " << bandCenter << " " << bandwidthBand);
440 CcBwpCreator::SimpleOperationBandConf bandConf2(bandCenter, bandwidthBand, numCcPerBand);
441 bandConf2.m_numBwp = numBwp;
442
443 // Create, then configure
444 CcBwpCreator ccBwpCreator;
445 band0 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf0);
446 band0.m_bandId = 0;
447 band1 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf1);
448 band1.m_bandId = 1;
449 band2 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf2);
450 band2.m_bandId = 2;
451 bandCenter = band0Start + bandwidthBwp / 2.0;
452
453 NS_LOG_LOGIC("band0[0][0]: " << bandCenter << " " << bandwidthBwp);
454 ConfigureBwpTo(band0.m_cc[0]->m_bwp[0], bandCenter, bandwidthBwp);
455 bandCenter += bandwidthBwp;
456
457 if (operationMode == "FDD")
458 {
459 NS_LOG_LOGIC("band0[0][1]: " << bandCenter << " " << bandwidthBwp);
460 ConfigureBwpTo(band0.m_cc[0]->m_bwp[1], bandCenter, bandwidthBwp);
461 bandCenter += bandwidthBwp;
462 Config::SetDefault("ns3::NrUeNetDevice::PrimaryUlIndex", UintegerValue(1));
463 }
464
465 NS_LOG_LOGIC("band1[0][0]: " << bandCenter << " " << bandwidthBwp);
466 ConfigureBwpTo(band1.m_cc[0]->m_bwp[0], bandCenter, bandwidthBwp);
467 bandCenter += bandwidthBwp;
468
469 if (operationMode == "FDD")
470 {
471 NS_LOG_LOGIC("band1[0][1]: " << bandCenter << " " << bandwidthBwp);
472 ConfigureBwpTo(band1.m_cc[0]->m_bwp[1], bandCenter, bandwidthBwp);
473 bandCenter += bandwidthBwp;
474 }
475
476 NS_LOG_LOGIC("band2[0][0]: " << bandCenter << " " << bandwidthBwp);
477 ConfigureBwpTo(band2.m_cc[0]->m_bwp[0], bandCenter, bandwidthBwp);
478 bandCenter += bandwidthBwp;
479
480 if (operationMode == "FDD")
481 {
482 NS_LOG_LOGIC("band2[0][1]: " << bandCenter << " " << bandwidthBwp);
483 ConfigureBwpTo(band2.m_cc[0]->m_bwp[1], bandCenter, bandwidthBwp);
484 }
485
486 std::cout << "BWP Configuration for NON_OVERLAPPING case, mode " << operationMode << "\n"
487 << band0 << band1 << band2;
488 }
489
490 else if (freqScenario == 1) // OVERLAPPING
491 {
492 double bandwidthCc = numBwp * bandwidthBwp;
493 uint8_t numCcPerBand = 1;
494 double bandwidthBand = numCcPerBand * bandwidthCc;
495 double bandCenter = band0Start + bandwidthBand / 2.0;
496
497 NS_LOG_LOGIC("OVERLAPPING, " << operationMode << ": " << bandwidthBand << ":" << bandwidthCc
498 << ":" << bandwidthBwp << ", " << (int)numCcPerBand << ", "
499 << (int)numBwp);
500
501 NS_LOG_LOGIC("bandConf0: " << bandCenter << " " << bandwidthBand);
502 CcBwpCreator::SimpleOperationBandConf bandConf0(bandCenter, bandwidthBand, numCcPerBand);
503 bandConf0.m_numBwp = numBwp;
504 bandCenter += bandwidthBand;
505
506 // Create, then configure
507 CcBwpCreator ccBwpCreator;
508 band0 = ccBwpCreator.CreateOperationBandContiguousCc(bandConf0);
509 band0.m_bandId = 0;
510 bandCenter = band0Start + bandwidthBwp / 2.0;
511
512 NS_LOG_LOGIC("band0[0][0]: " << bandCenter << " " << bandwidthBwp);
513 ConfigureBwpTo(band0.m_cc[0]->m_bwp[0], bandCenter, bandwidthBwp);
514 bandCenter += bandwidthBwp;
515
516 if (operationMode == "FDD")
517 {
518 NS_LOG_LOGIC("band0[0][1]: " << bandCenter << " " << bandwidthBwp);
519 ConfigureBwpTo(band0.m_cc[0]->m_bwp[1], bandCenter, bandwidthBwp);
520 }
521
522 std::cout << "BWP Configuration for OVERLAPPING case, mode " << operationMode << "\n"
523 << band0;
524 }
525
526 else
527 {
528 std::cerr << "unknown combination of freqScenario = " << freqScenario
529 << " and operationMode = " << operationMode << std::endl;
530 exit(1);
531 }
532 // Create the NrChannelHelper, which takes care of the spectrum channel
533 Ptr<NrChannelHelper> channelHelper = CreateObject<NrChannelHelper>();
534 // Configure the spectrum channel with the scenario
535 channelHelper->ConfigureFactories(scenario, "Default");
536 // Set the channel condition attributes
537 channelHelper->SetChannelConditionModelAttribute("UpdatePeriod", TimeValue(MilliSeconds(100)));
538 channelHelper->SetChannelConditionModelAttribute("LinkO2iConditionToAntennaHeight",
539 BooleanValue(linkO2iConditionToAntennaHeight));
540 channelHelper->SetChannelConditionModelAttribute("O2iThreshold", DoubleValue(o2iThreshold));
541 channelHelper->SetChannelConditionModelAttribute("O2iLowLossThreshold",
542 DoubleValue(o2iLowLossThreshold));
543 channelHelper->SetPathlossAttribute("ShadowingEnabled", BooleanValue(enableShadowing));
544 Config::SetDefault("ns3::ThreeGppChannelModel::UpdatePeriod", TimeValue(MilliSeconds(100)));
545 // Configure Distance-based spectrum manually because it is not possible to set it via
546 // NrChannelHelper
547 ObjectFactory distanceBasedChannelFactory;
548 distanceBasedChannelFactory.SetTypeId(
549 DistanceBasedThreeGppSpectrumPropagationLossModel::GetTypeId());
550 distanceBasedChannelFactory.Set("MaxDistance", DoubleValue(2 * isd));
551 for (size_t i = 0; i < band0.GetBwps().size(); i++)
552 {
553 auto distanceBased3gpp =
554 distanceBasedChannelFactory.Create<DistanceBasedThreeGppSpectrumPropagationLossModel>();
555 distanceBased3gpp->SetChannelModelAttribute(
556 "Frequency",
557 DoubleValue(band0.GetBwpAt(0, i)->m_centralFrequency));
558 distanceBased3gpp->SetChannelModelAttribute("Scenario", StringValue(scenario));
559 auto specChannelBand0 = channelHelper->CreateChannel(NrChannelHelper::INIT_PROPAGATION);
560 // Create the channel considering only the propagation loss. Create the fading in
561 // case of non-calibration
562 if (enableFading)
563 {
564 PointerValue channelConditionModel0;
565 specChannelBand0->GetPropagationLossModel()->GetAttribute("ChannelConditionModel",
566 channelConditionModel0);
567 distanceBased3gpp->SetChannelModelAttribute(
568 "ChannelConditionModel",
569 PointerValue(channelConditionModel0.Get<ChannelConditionModel>()));
570 specChannelBand0->AddPhasedArraySpectrumPropagationLossModel(distanceBased3gpp);
571 }
572 band0.GetBwpAt(0, i)->SetChannel(specChannelBand0);
573 }
574 for (size_t i = 0; i < band1.GetBwps().size(); i++)
575 {
576 auto distanceBased3gpp =
577 distanceBasedChannelFactory.Create<DistanceBasedThreeGppSpectrumPropagationLossModel>();
578 distanceBased3gpp->SetChannelModelAttribute(
579 "Frequency",
580 DoubleValue(band1.GetBwpAt(0, i)->m_centralFrequency));
581 distanceBased3gpp->SetChannelModelAttribute("Scenario", StringValue(scenario));
582 auto specChannelBand1 = channelHelper->CreateChannel(NrChannelHelper::INIT_PROPAGATION);
583 // Create the channel considering only the propagation loss. Create the fading in
584 // case of non-calibration
585 if (enableFading)
586 {
587 PointerValue channelConditionModel1;
588 specChannelBand1->GetPropagationLossModel()->GetAttribute("ChannelConditionModel",
589 channelConditionModel1);
590 distanceBased3gpp->SetChannelModelAttribute(
591 "ChannelConditionModel",
592 PointerValue(channelConditionModel1.Get<ChannelConditionModel>()));
593 specChannelBand1->AddPhasedArraySpectrumPropagationLossModel(distanceBased3gpp);
594 }
595 band1.GetBwpAt(0, i)->SetChannel(specChannelBand1);
596 }
597 for (size_t i = 0; i < band2.GetBwps().size(); i++)
598 {
599 auto distanceBased3gpp =
600 distanceBasedChannelFactory.Create<DistanceBasedThreeGppSpectrumPropagationLossModel>();
601 distanceBased3gpp->SetAttribute("MaxDistance", DoubleValue(2 * isd));
602 distanceBased3gpp->SetChannelModelAttribute("Scenario", StringValue(scenario));
603 distanceBased3gpp->SetChannelModelAttribute(
604 "Frequency",
605 DoubleValue(band2.GetBwpAt(0, i)->m_centralFrequency));
606 auto specChannelBand2 = channelHelper->CreateChannel(NrChannelHelper::INIT_PROPAGATION);
607 // Create the channel considering only the propagation loss. Create the fading in
608 // case of non-calibration
609 if (enableFading)
610 {
611 PointerValue channelConditionModel2;
612 specChannelBand2->GetPropagationLossModel()->GetAttribute("ChannelConditionModel",
613 channelConditionModel2);
614 distanceBased3gpp->SetChannelModelAttribute(
615 "ChannelConditionModel",
616 PointerValue(channelConditionModel2.Get<ChannelConditionModel>()));
617 specChannelBand2->AddPhasedArraySpectrumPropagationLossModel(distanceBased3gpp);
618 }
619 band2.GetBwpAt(0, i)->SetChannel(specChannelBand2);
620 }
621 BandwidthPartInfoPtrVector sector1Bwps;
622 BandwidthPartInfoPtrVector sector2Bwps;
623 BandwidthPartInfoPtrVector sector3Bwps;
624 if (freqScenario == 0) // NON_OVERLAPPING
625 {
626 sector1Bwps = CcBwpCreator::GetAllBwps({band0});
627 sector2Bwps = CcBwpCreator::GetAllBwps({band1});
628 sector3Bwps = CcBwpCreator::GetAllBwps({band2});
629 }
630 else // OVERLAPPING
631 {
632 sector1Bwps = CcBwpCreator::GetAllBwps({band0});
633 sector2Bwps = CcBwpCreator::GetAllBwps({band0});
634 sector3Bwps = CcBwpCreator::GetAllBwps({band0});
635 }
636
637 RealisticBfManager::TriggerEvent realTriggerEvent{RealisticBfManager::SRS_COUNT};
638
639 // TODO: Optimize this code (repeated code)
640 // if there is no fading, that means that there is no beamforming
641 if (enableFading && bfMethod != "FixedBeam")
642 {
643 if (radioNetwork == "NR")
644 {
645 if (enableRealBF)
646 {
647 beamformingHelper->SetBeamformingMethod(RealisticBeamformingAlgorithm::GetTypeId());
648 nrHelper->SetGnbBeamManagerTypeId(RealisticBfManager::GetTypeId());
649 nrHelper->SetGnbBeamManagerAttribute("TriggerEvent", EnumValue(realTriggerEvent));
650 nrHelper->SetGnbBeamManagerAttribute("UpdateDelay", TimeValue(MicroSeconds(0)));
651 }
652 else
653 {
654 if (bfMethod == "Omni")
655 {
656 beamformingHelper->SetBeamformingMethod(
658 }
659 else if (bfMethod == "CellScan")
660 {
661 beamformingHelper->SetBeamformingMethod(CellScanBeamforming::GetTypeId());
662 beamformingHelper->SetAttribute("BeamformingPeriodicity",
663 TimeValue(MilliSeconds(10)));
664 }
665 else if (bfMethod == "CellScanAzimuth")
666 {
667 beamformingHelper->SetBeamformingMethod(
669 }
670 else
671 {
672 NS_ABORT_MSG("We shouldn't be here. bfMethod is: " << bfMethod);
673 }
674 }
675 }
676 else if (radioNetwork == "LTE") // Omni for LTE
677 {
678 if (bfMethod == "Omni")
679 {
680 beamformingHelper->SetBeamformingMethod(
682 }
683 else if (bfMethod == "CellScan")
684 {
685 beamformingHelper->SetBeamformingMethod(CellScanBeamforming::GetTypeId());
686 beamformingHelper->SetAttribute("BeamformingPeriodicity",
687 TimeValue(MilliSeconds(10)));
688 }
689 else
690 {
691 NS_ABORT_MSG("We shouldn't be here. bfMethod is: " << bfMethod);
692 }
693 }
694 }
695
696 // Scheduler type
697
698 if (radioNetwork == "NR")
699 {
700 if (scheduler == "PF")
701 {
702 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerTdmaPF"));
703 }
704 else if (scheduler == "RR")
705 {
706 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerTdmaRR"));
707 }
708 }
709 else
710 {
711 if (scheduler == "PF")
712 {
713 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerOfdmaPF"));
714 }
715 else if (scheduler == "RR")
716 {
717 nrHelper->SetSchedulerTypeId(TypeId::LookupByName("ns3::NrMacSchedulerOfdmaRR"));
718 }
719 }
720 nrHelper->SetSchedulerAttribute("EnableHarqReTx", BooleanValue(false));
721
722 // configure SRS symbols
723 nrHelper->SetSchedulerAttribute("SrsSymbols", UintegerValue(1));
724 nrHelper->SetSchedulerAttribute("EnableSrsInUlSlots", BooleanValue(false));
725 nrHelper->SetSchedulerAttribute("EnableSrsInFSlots", BooleanValue(false));
726
727 // configure CTRL symbols
728 nrHelper->SetSchedulerAttribute("DlCtrlSymbols", UintegerValue(dlCtrlSymbols));
729
730 // Core latency
731 nrEpcHelper->SetAttribute("S1uLinkDelay", TimeValue(MilliSeconds(0)));
732
733 // Antennas for all the UEs
734 nrHelper->SetUeAntennaAttribute("NumRows", UintegerValue(ueNumRows));
735 nrHelper->SetUeAntennaAttribute("NumColumns", UintegerValue(ueNumColumns));
736
737 if (ueEnable3gppElement)
738 {
739 nrHelper->SetUeAntennaAttribute("AntennaElement",
740 PointerValue(CreateObject<ThreeGppAntennaModel>()));
741 }
742 else
743 {
744 nrHelper->SetUeAntennaAttribute("AntennaElement",
745 PointerValue(CreateObject<IsotropicAntennaModel>()));
746 }
747
748 nrHelper->SetUeAntennaAttribute("AntennaHorizontalSpacing", DoubleValue(ueHSpacing));
749 nrHelper->SetUeAntennaAttribute("AntennaVerticalSpacing", DoubleValue(ueVSpacing));
750
751 // Antennas for all the gNbs
752 nrHelper->SetGnbAntennaAttribute("NumRows", UintegerValue(gnbNumRows));
753 nrHelper->SetGnbAntennaAttribute("NumColumns", UintegerValue(gnbNumColumns));
754
755 nrHelper->SetGnbAntennaAttribute("AntennaHorizontalSpacing", DoubleValue(gnbHSpacing));
756 nrHelper->SetGnbAntennaAttribute("AntennaVerticalSpacing", DoubleValue(gnbVSpacing));
757
758 nrHelper->SetGnbAntennaAttribute("DowntiltAngle", DoubleValue(downtiltAngle * M_PI / 180.0));
759
760 if (gnbEnable3gppElement)
761 {
762 nrHelper->SetGnbAntennaAttribute("AntennaElement",
763 PointerValue(CreateObject<ThreeGppAntennaModel>()));
764 }
765 else
766 {
767 nrHelper->SetGnbAntennaAttribute("AntennaElement",
768 PointerValue(CreateObject<IsotropicAntennaModel>()));
769 }
770
771 double gnbFirstSubArray = (polSlantAngleGnb1 * M_PI) / 180.0; // converting to radians
772 double gnbSecondSubArray = (polSlantAngleGnb2 * M_PI) / 180.0; // converting to radians
773 double ueFirstSubArray = (polSlantAngleUe1 * M_PI) / 180.0; // converting to radians
774 double ueSecondSubArray = (polSlantAngleUe2 * M_PI) / 180.0; // converting to radians
775
776 // UE transmit power
777 nrHelper->SetUePhyAttribute("TxPower", DoubleValue(ueTxPower));
778
779 // Set LTE RBG size
780 // TODO: What these values would be in TDD? bandwidthMhz refers to FDD.
781 // for example, for TDD, if we have bandwidthMhz to 20, we will have a 40 MHz
782 // BWP.
783 if (radioNetwork == "LTE")
784 {
785 switch (bandwidthMHz)
786 {
787 case 40:
788 case 20:
789 case 15:
790 nrHelper->SetGnbMacAttribute("NumRbPerRbg", UintegerValue(4));
791 break;
792 case 10:
793 nrHelper->SetGnbMacAttribute("NumRbPerRbg", UintegerValue(3));
794 break;
795 case 5:
796 nrHelper->SetGnbMacAttribute("NumRbPerRbg", UintegerValue(2));
797 break;
798 default:
799 NS_ABORT_MSG(
800 "Currently, only supported bandwidths are 5, 10, 15, 20 and 40MHz, you chose "
801 << bandwidthMHz);
802 }
803 }
804 else
805 {
806 nrHelper->SetGnbMacAttribute("NumRbPerRbg", UintegerValue(1));
807 }
808
809 // We assume a common traffic pattern for all UEs
810 uint32_t bwpIdForLowLat = 0;
811 if (operationMode == "FDD" && direction == "UL")
812 {
813 bwpIdForLowLat = 1;
814 }
815
816 // gNb routing between Bearer and bandwidth part
817 nrHelper->SetGnbBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB",
818 UintegerValue(bwpIdForLowLat));
819
820 // Ue routing between Bearer and bandwidth part
821 nrHelper->SetUeBwpManagerAlgorithmAttribute("NGBR_LOW_LAT_EMBB", UintegerValue(bwpIdForLowLat));
822
823 // NetDeviceContainer gnbNetDev = nrHelper->InstallGnbDevice (gridScenario.GetBaseStations (),
824 // allBwps);
825 gnbSector1NetDev = nrHelper->InstallGnbDevice(gnbSector1Container, sector1Bwps);
826 NetDeviceContainer gnbNetDevs(gnbSector1NetDev);
827 gnbSector2NetDev = nrHelper->InstallGnbDevice(gnbSector2Container, sector2Bwps);
828 gnbNetDevs.Add(gnbSector2NetDev);
829 gnbSector3NetDev = nrHelper->InstallGnbDevice(gnbSector3Container, sector3Bwps);
830 gnbNetDevs.Add(gnbSector3NetDev);
831 ueSector1NetDev = nrHelper->InstallUeDevice(ueSector1Container, sector1Bwps);
832 NetDeviceContainer ueNetDevs(ueSector1NetDev);
833 ueSector2NetDev = nrHelper->InstallUeDevice(ueSector2Container, sector2Bwps);
834 ueNetDevs.Add(ueSector2NetDev);
835 ueSector3NetDev = nrHelper->InstallUeDevice(ueSector3Container, sector3Bwps);
836 ueNetDevs.Add(ueSector3NetDev);
837
838 int64_t randomStream = 1;
839 randomStream += nrHelper->AssignStreams(gnbSector1NetDev, randomStream);
840 randomStream += nrHelper->AssignStreams(gnbSector2NetDev, randomStream);
841 randomStream += nrHelper->AssignStreams(gnbSector3NetDev, randomStream);
842 randomStream += nrHelper->AssignStreams(ueSector1NetDev, randomStream);
843 randomStream += nrHelper->AssignStreams(ueSector2NetDev, randomStream);
844 randomStream += nrHelper->AssignStreams(ueSector3NetDev, randomStream);
845
846 // Sectors (cells) of a site are pointing at different directions
847 std::vector<double> sectorOrientationRad{
848 sector0AngleRad,
849 sector0AngleRad + 2.0 * M_PI / 3.0, // + 120 deg
850 sector0AngleRad - 2.0 * M_PI / 3.0 // - 120 deg
851 };
852
853 for (uint32_t cellId = 0; cellId < gnbNetDevs.GetN(); ++cellId)
854 {
855 Ptr<NetDevice> gnb = gnbNetDevs.Get(cellId);
856 uint32_t numBwps = nrHelper->GetNumberBwp(gnb);
857 if (numBwps > 2)
858 {
859 NS_ABORT_MSG("Incorrect number of BWPs per CC");
860 }
861
862 uint32_t sector = cellId % (gnbSector3NetDev.GetN() == 0 ? 1 : 3);
863 double orientation = sectorOrientationRad[sector];
864
865 // First BWP (in case of FDD) or only BWP (in case of TDD)
866 ConfigurePhy(nrHelper,
867 gnb,
868 orientation,
869 numerology,
870 txPowerBs,
871 pattern,
872 0,
873 gnbFirstSubArray,
874 gnbSecondSubArray,
875 beamConfSector,
876 beamConfElevation);
877
878 if (numBwps == 2) // FDD
879 {
880 ConfigurePhy(nrHelper,
881 gnb,
882 orientation,
883 numerology,
884 txPowerBs,
885 pattern,
886 1,
887 gnbFirstSubArray,
888 gnbSecondSubArray,
889 beamConfSector,
890 beamConfElevation);
891 // Link the two FDD BWP
892 nrHelper->GetBwpManagerGnb(gnb)->SetOutputLink(1, 0);
893 }
894 }
895
896 Ptr<UniformRandomVariable> m_uniformUeBearingAngle;
897 m_uniformUeBearingAngle = CreateObject<UniformRandomVariable>();
898
899 // Set the UE routing:
900 for (auto nd = ueNetDevs.Begin(); nd != ueNetDevs.End(); ++nd)
901 {
902 auto uePhyFirst = nrHelper->GetUePhy(*nd, 0);
903 auto uePhySecond{uePhyFirst};
904
905 ObjectVectorValue ueSpectrumPhysFirstBwp;
906 Ptr<NrSpectrumPhy> nrSpectrumPhy = uePhyFirst->GetSpectrumPhy();
907 nrSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>()->SetAttribute(
908 "PolSlantAngle",
909 DoubleValue(ueFirstSubArray));
910
911 if (ueBearingAngle)
912 {
913 // For each UE throw a uniform random variable btw -180 and 180
914 double ueBearingAngleValue = m_uniformUeBearingAngle->GetValue(-180, 180);
915 ueBearingAngleValue = (ueBearingAngleValue * M_PI) / 180.0; // convert to radians
916 nrSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>()->SetAttribute(
917 "BearingAngle",
918 DoubleValue(ueBearingAngleValue));
919 }
920 if (ueSpectrumPhysFirstBwp.GetN() == 2)
921 {
922 nrSpectrumPhy = ueSpectrumPhysFirstBwp.Get(1)->GetObject<NrSpectrumPhy>();
923 nrSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>()->SetAttribute(
924 "PolSlantAngle",
925 DoubleValue(ueSecondSubArray));
926 }
927
928 if (operationMode == "FDD")
929 {
930 nrHelper->GetBwpManagerUe(*nd)->SetOutputLink(0, 1);
931 uePhySecond = nrHelper->GetUePhy(*nd, 1);
932 uePhySecond->SetUplinkPowerControl(uePhyFirst->GetUplinkPowerControl());
933
934 ObjectVectorValue ueSpectrumPhysSecondBwp;
935 nrSpectrumPhy = uePhySecond->GetSpectrumPhy();
936 nrSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>()->SetAttribute(
937 "PolSlantAngle",
938 DoubleValue(ueFirstSubArray));
939 }
940 uePhyFirst->TraceConnectWithoutContext("DlDataSinr",
941 MakeBoundCallback(&ReportSinrNr, sinrStats));
942 uePhySecond->TraceConnectWithoutContext("ReportPowerSpectralDensity",
943 MakeBoundCallback(&ReportPowerNr, ueTxPowerStats));
944 }
945
946 for (auto nd = gnbNetDevs.Begin(); nd != gnbNetDevs.End(); ++nd)
947 {
948 uint32_t bwpId = 0;
949 if (operationMode == "FDD" && direction == "UL")
950 {
951 bwpId = 1;
952 }
953 auto gnbPhy = nrHelper->GetGnbPhy(*nd, bwpId);
954 gnbPhy->TraceConnectWithoutContext("SlotDataStats",
955 MakeBoundCallback(&ReportSlotStatsNr, slotStats));
956 gnbPhy->TraceConnectWithoutContext("RBDataStats",
957 MakeBoundCallback(&ReportRbStatsNr, rbStats));
958 gnbPhy->GetSpectrumPhy()->TraceConnectWithoutContext(
959 "RxDataTrace",
960 MakeBoundCallback(&ReportGnbRxDataNr, gnbRxPowerStats));
961 }
962}
963
964} // namespace ns3
Manages the correct creation of operation bands, component carriers and bandwidth parts.
OperationBandInfo CreateOperationBandContiguousCc(const SimpleOperationBandConf &conf)
Create an operation band with the CC specified.
static BandwidthPartInfoPtrVector GetAllBwps(const std::vector< std::reference_wrapper< OperationBandInfo > > &operationBands)
Get all the BWP pointers from the specified vector of operation bands.
static TypeId GetTypeId()
Get the type id.
static void SetLenaV2SimulatorParameters(const double sector0AngleRad, const std::string &scenario, const std::string &confType, const std::string &radioNetwork, std::string errorModel, const std::string &operationMode, const std::string &direction, uint16_t numerology, const std::string &pattern, const NodeContainer &gnbSector1Container, const NodeContainer &gnbSector2Container, const NodeContainer &gnbSector3Container, const NodeContainer &ueSector1Container, const NodeContainer &ueSector2Container, const NodeContainer &ueSector3Container, const Ptr< NrPointToPointEpcHelper > &baseEpcHelper, Ptr< NrHelper > &nrHelper, NetDeviceContainer &gnbSector1NetDev, NetDeviceContainer &gnbSector2NetDev, NetDeviceContainer &gnbSector3NetDev, NetDeviceContainer &ueSector1NetDev, NetDeviceContainer &ueSector2NetDev, NetDeviceContainer &ueSector3NetDev, bool enableFading, bool enableUlPc, std::string powerAllocation, SinrOutputStats *sinrStats, PowerOutputStats *ueTxPowerStats, PowerOutputStats *gnbRxPowerStats, SlotOutputStats *slotStats, RbOutputStats *rbStats, const std::string &scheduler, uint32_t bandwidthMHz, double startingFreq, uint32_t freqScenario, double gnbTxPower, double ueTxPower, double downtiltAngle, const uint32_t gnbNumRows, const uint32_t gnbNumColumns, const uint32_t ueNumRows, const uint32_t ueNumColumns, bool gnbEnable3gppElement, bool ueEnable3gppElement, const double gnbHSpacing, const double gnbVSpacing, const double ueHSpacing, const double ueVSpacing, const double gnbNoiseFigure, const double ueNoiseFigure, bool enableRealBF, bool enableShadowing, double o2iThreshold, double o2iLowLossThreshold, bool linkO2iConditionToAntennaHeight, bool crossPolarizedGnb, bool crossPolarizedUe, double polSlantAngleGnb1, double polSlantAngleGnb2, double polSlantAngleUe1, double polSlantAngleUe2, std::string bfMethod, uint16_t beamConfSector, double beamConfElevation, double isd, bool ueBearingAngle)
@ ShannonModel
Shannon based model (very conservative)
Definition nr-amc.h:80
@ INIT_PROPAGATION
Initialize the propagation loss model.
Interface between the physical layer and the channel.
Ptr< Object > GetAntenna() const override
Inherited from SpectrumPhy Note: Implements GetRxAntenna function from SpectrumPhy.
Class to collect and store the transmission power values obtained from a simulation.
Class to collect and store the Resource Block statistics from a simulation.
static TypeId GetTypeId()
GetTypeId.
Class to collect and store the SINR values obtained from a simulation.
Class to collect and store the SINR values obtained from a simulation.
std::unique_ptr< BandwidthPartInfo > BandwidthPartInfoPtr
unique_ptr of BandwidthPartInfo
std::vector< std::reference_wrapper< BandwidthPartInfoPtr > > BandwidthPartInfoPtrVector
vector of unique_ptr of BandwidthPartInfo
Minimum configuration requirements for a OperationBand.
uint8_t m_numBwp
Number of BWP per CC.
Operation band information structure.
BandwidthPartInfoPtr & GetBwpAt(uint32_t ccId, uint32_t bwpId) const
Get the BWP at the cc/bwp specified.
std::vector< ComponentCarrierInfoPtr > m_cc
Operation band component carriers.
BandwidthPartInfoPtrVector GetBwps() const
Get the list of all the BWPs to pass to NrHelper.
uint8_t m_bandId
Operation band id.