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