5G-LENA nr-v3.3-120-gdac69c56
The 5G/NR module for the ns-3 simulator
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
ideal-beamforming-algorithm.cc
1// Copyright (c) 2020 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#include "ideal-beamforming-algorithm.h"
6
7#include "nr-spectrum-phy.h"
8
9#include "ns3/double.h"
10#include "ns3/multi-model-spectrum-channel.h"
11#include "ns3/node.h"
12#include "ns3/nr-spectrum-value-helper.h"
13#include "ns3/uinteger.h"
14#include "ns3/uniform-planar-array.h"
15
16namespace ns3
17{
18
19NS_LOG_COMPONENT_DEFINE("IdealBeamformingAlgorithm");
20NS_OBJECT_ENSURE_REGISTERED(CellScanBeamforming);
21NS_OBJECT_ENSURE_REGISTERED(CellScanBeamformingAzimuthZenith);
22NS_OBJECT_ENSURE_REGISTERED(CellScanQuasiOmniBeamforming);
23NS_OBJECT_ENSURE_REGISTERED(DirectPathBeamforming);
24NS_OBJECT_ENSURE_REGISTERED(QuasiOmniDirectPathBeamforming);
25NS_OBJECT_ENSURE_REGISTERED(DirectPathQuasiOmniBeamforming);
26NS_OBJECT_ENSURE_REGISTERED(OptimalCovMatrixBeamforming);
27NS_OBJECT_ENSURE_REGISTERED(KroneckerBeamforming);
28NS_OBJECT_ENSURE_REGISTERED(KroneckerQuasiOmniBeamforming);
29
30TypeId
32{
33 static TypeId tid = TypeId("ns3::IdealBeamformingAlgorithm").SetParent<Object>();
34 return tid;
35}
36
37TypeId
39{
40 static TypeId tid =
41 TypeId("ns3::CellScanBeamforming")
42 .SetParent<IdealBeamformingAlgorithm>()
43 .AddConstructor<CellScanBeamforming>()
44 .AddAttribute("BeamSearchAngleStep",
45 "Angle step when searching for the best beam",
46 DoubleValue(30),
49 MakeDoubleChecker<double>());
50
51 return tid;
52}
53
54void
56{
57 m_beamSearchAngleStep = beamSearchAngleStep;
58}
59
60double
62{
63 return m_beamSearchAngleStep;
64}
65
66BeamformingVectorPair
67CellScanBeamforming::GetBeamformingVectors(const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
68 const Ptr<NrSpectrumPhy>& ueSpectrumPhy) const
69{
70 NS_ABORT_MSG_IF(gnbSpectrumPhy == nullptr || ueSpectrumPhy == nullptr,
71 "Something went wrong, gnb or UE PHY layer not set.");
72 double distance = gnbSpectrumPhy->GetMobility()->GetDistanceFrom(ueSpectrumPhy->GetMobility());
73 NS_ABORT_MSG_IF(distance == 0,
74 "Beamforming method cannot be performed between two devices that are placed in "
75 "the same position.");
76
77 Ptr<SpectrumChannel> gnbSpectrumChannel =
78 gnbSpectrumPhy
79 ->GetSpectrumChannel(); // SpectrumChannel should be const.. but need to change ns-3-dev
80 Ptr<SpectrumChannel> ueSpectrumChannel = ueSpectrumPhy->GetSpectrumChannel();
81
82 Ptr<const PhasedArraySpectrumPropagationLossModel> gnbThreeGppSpectrumPropModel =
83 gnbSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel();
84 Ptr<const PhasedArraySpectrumPropagationLossModel> ueThreeGppSpectrumPropModel =
85 ueSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel();
86 NS_ASSERT_MSG(gnbThreeGppSpectrumPropModel == ueThreeGppSpectrumPropModel,
87 "Devices should be connected on the same spectrum channel");
88
89 std::vector<int> activeRbs;
90 for (size_t rbId = 0; rbId < gnbSpectrumPhy->GetRxSpectrumModel()->GetNumBands(); rbId++)
91 {
92 activeRbs.push_back(rbId);
93 }
94
95 Ptr<const SpectrumValue> fakePsd = NrSpectrumValueHelper::CreateTxPowerSpectralDensity(
96 0.0,
97 activeRbs,
98 gnbSpectrumPhy->GetRxSpectrumModel(),
99 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
100 Ptr<SpectrumSignalParameters> fakeParams = Create<SpectrumSignalParameters>();
101 fakeParams->psd = fakePsd->Copy();
102
103 double max = 0;
104 double maxTxTheta = 0;
105 double maxRxTheta = 0;
106 uint16_t maxTxSector = 0;
107 uint16_t maxRxSector = 0;
108 PhasedArrayModel::ComplexVector maxTxW;
109 PhasedArrayModel::ComplexVector maxRxW;
110
111 UintegerValue uintValue;
112 gnbSpectrumPhy->GetAntenna()->GetAttribute("NumRows", uintValue);
113 uint32_t txNumRows = static_cast<uint32_t>(uintValue.Get());
114 ueSpectrumPhy->GetAntenna()->GetAttribute("NumRows", uintValue);
115 uint32_t rxNumRows = static_cast<uint32_t>(uintValue.Get());
116
117 NS_ASSERT(gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>()->GetNumElems() &&
118 ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>()->GetNumElems());
119
120 uint16_t numRowsTx = static_cast<uint16_t>(txNumRows);
121 uint16_t numRowsRx = static_cast<uint16_t>(rxNumRows);
122 for (double txTheta = 60; txTheta < 121; txTheta = txTheta + m_beamSearchAngleStep)
123 {
124 for (uint16_t txSector = 0; txSector <= numRowsTx; txSector++)
125 {
126 NS_ASSERT(txSector < UINT16_MAX);
127
128 gnbSpectrumPhy->GetBeamManager()->SetSector(txSector, txTheta);
129 PhasedArrayModel::ComplexVector txW =
130 gnbSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
131
132 if (maxTxW.GetSize() == 0)
133 {
134 maxTxW = txW; // initialize maxTxW
135 }
136
137 for (double rxTheta = 60; rxTheta < 121;
138 rxTheta = static_cast<uint16_t>(rxTheta + m_beamSearchAngleStep))
139 {
140 for (uint16_t rxSector = 0; rxSector <= numRowsRx; rxSector++)
141 {
142 NS_ASSERT(rxSector < UINT16_MAX);
143
144 ueSpectrumPhy->GetBeamManager()->SetSector(rxSector, rxTheta);
145 PhasedArrayModel::ComplexVector rxW =
146 ueSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
147
148 if (maxRxW.GetSize() == 0)
149 {
150 maxRxW = rxW; // initialize maxRxW
151 }
152
153 NS_ABORT_MSG_IF(txW.GetSize() == 0 || rxW.GetSize() == 0,
154 "Beamforming vectors must be initialized in order to calculate "
155 "the long term matrix.");
156
157 Ptr<SpectrumSignalParameters> rxParams =
158 gnbThreeGppSpectrumPropModel->CalcRxPowerSpectralDensity(
159 fakeParams,
160 gnbSpectrumPhy->GetMobility(),
161 ueSpectrumPhy->GetMobility(),
162 gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>(),
163 ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>());
164
165 size_t nbands = rxParams->psd->GetSpectrumModel()->GetNumBands();
166 double power = Sum(*(rxParams->psd)) / nbands;
167
168 NS_LOG_LOGIC(
169 " Rx power: "
170 << power << "txTheta " << txTheta << " rxTheta " << rxTheta << " tx sector "
171 << (M_PI * static_cast<double>(txSector) / static_cast<double>(txNumRows) -
172 0.5 * M_PI) /
173 M_PI * 180
174 << " rx sector "
175 << (M_PI * static_cast<double>(rxSector) / static_cast<double>(rxNumRows) -
176 0.5 * M_PI) /
177 M_PI * 180);
178
179 if (max < power)
180 {
181 max = power;
182 maxTxSector = txSector;
183 maxRxSector = rxSector;
184 maxTxTheta = txTheta;
185 maxRxTheta = rxTheta;
186 maxTxW = txW;
187 maxRxW = rxW;
188 }
189 }
190 }
191 }
192 }
193
194 BeamformingVector gnbBfv =
195 BeamformingVector(std::make_pair(maxTxW, BeamId(maxTxSector, maxTxTheta)));
196 BeamformingVector ueBfv =
197 BeamformingVector(std::make_pair(maxRxW, BeamId(maxRxSector, maxRxTheta)));
198
199 NS_LOG_DEBUG(
200 "Beamforming vectors for gNB with node id: "
201 << gnbSpectrumPhy->GetMobility()->GetObject<Node>()->GetId()
202 << " and UE with node id: " << ueSpectrumPhy->GetMobility()->GetObject<Node>()->GetId()
203 << " are txTheta " << maxTxTheta << " rxTheta " << maxRxTheta << " tx sector "
204 << (M_PI * static_cast<double>(maxTxSector) / static_cast<double>(txNumRows) - 0.5 * M_PI) /
205 M_PI * 180
206 << " rx sector "
207 << (M_PI * static_cast<double>(maxRxSector) / static_cast<double>(rxNumRows) - 0.5 * M_PI) /
208 M_PI * 180);
209
210 NS_ASSERT(maxTxW.GetSize() && maxRxW.GetSize());
211
212 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
213}
214
215TypeId
217{
218 static TypeId tid = TypeId("ns3::CellScanBeamformingAzimuthZenith")
219 .SetParent<IdealBeamformingAlgorithm>()
220 .AddConstructor<CellScanBeamformingAzimuthZenith>();
221
222 return tid;
223}
224
225BeamformingVectorPair
227 const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
228 const Ptr<NrSpectrumPhy>& ueSpectrumPhy) const
229{
230 NS_ABORT_MSG_IF(gnbSpectrumPhy == nullptr || ueSpectrumPhy == nullptr,
231 "Something went wrong, gnb or UE PHY layer not set.");
232 double distance = gnbSpectrumPhy->GetMobility()->GetDistanceFrom(ueSpectrumPhy->GetMobility());
233 NS_ABORT_MSG_IF(distance == 0,
234 "Beamforming method cannot be performed between "
235 "two devices that are placed in the same position.");
236
237 Ptr<SpectrumChannel> gnbSpectrumChannel =
238 gnbSpectrumPhy
239 ->GetSpectrumChannel(); // SpectrumChannel should be const.. but need to change ns-3-dev
240 Ptr<SpectrumChannel> ueSpectrumChannel = ueSpectrumPhy->GetSpectrumChannel();
241
242 Ptr<const PhasedArraySpectrumPropagationLossModel> gnbThreeGppSpectrumPropModel =
243 gnbSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel();
244 Ptr<const PhasedArraySpectrumPropagationLossModel> ueThreeGppSpectrumPropModel =
245 ueSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel();
246 NS_ASSERT_MSG(gnbThreeGppSpectrumPropModel == ueThreeGppSpectrumPropModel,
247 "Devices should be connected on the same spectrum channel");
248
249 std::vector<int> activeRbs;
250 for (size_t rbId = 0; rbId < gnbSpectrumPhy->GetRxSpectrumModel()->GetNumBands(); rbId++)
251 {
252 activeRbs.push_back(rbId);
253 }
254
255 Ptr<const SpectrumValue> fakePsd = NrSpectrumValueHelper::CreateTxPowerSpectralDensity(
256 0.0,
257 activeRbs,
258 gnbSpectrumPhy->GetRxSpectrumModel(),
259 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
260 Ptr<SpectrumSignalParameters> fakeParams = Create<SpectrumSignalParameters>();
261 fakeParams->psd = fakePsd->Copy();
262
263 double max = 0;
264 double maxTxAzimuth = 0;
265 double maxRxAzimuth = 0;
266 double maxTxZenith = 0;
267 double maxRxZenith = 0;
268 PhasedArrayModel::ComplexVector maxTxW;
269 PhasedArrayModel::ComplexVector maxRxW;
270
271 UintegerValue uintValue;
272 gnbSpectrumPhy->GetAntenna()->GetAttribute("NumRows", uintValue);
273 ueSpectrumPhy->GetAntenna()->GetAttribute("NumRows", uintValue);
274
275 NS_ASSERT(gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>()->GetNumElems() &&
276 ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>()->GetNumElems());
277
278 for (double azimuthTx : m_azimuth)
279 {
280 for (double zenithTx : m_zenith)
281 {
282 gnbSpectrumPhy->GetBeamManager()->SetSectorAz(azimuthTx, zenithTx);
283 PhasedArrayModel::ComplexVector txW =
284 gnbSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
285
286 if (maxTxW.GetSize() == 0)
287 {
288 maxTxW = txW; // initialize maxTxW
289 }
290
291 for (double azimuthRx : m_azimuth)
292 {
293 for (double zenithRx : m_zenith)
294 {
295 ueSpectrumPhy->GetBeamManager()->SetSectorAz(azimuthRx, zenithRx);
296 PhasedArrayModel::ComplexVector rxW =
297 ueSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
298
299 if (maxRxW.GetSize() == 0)
300 {
301 maxRxW = rxW; // initialize maxRxW
302 }
303
304 NS_ABORT_MSG_IF(txW.GetSize() == 0 || rxW.GetSize() == 0,
305 "Beamforming vectors must be initialized in "
306 "order to calculate the long term matrix.");
307
308 Ptr<SpectrumSignalParameters> rxParams =
309 gnbThreeGppSpectrumPropModel->CalcRxPowerSpectralDensity(
310 fakeParams,
311 gnbSpectrumPhy->GetMobility(),
312 ueSpectrumPhy->GetMobility(),
313 gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>(),
314 ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>());
315
316 size_t nbands = rxParams->psd->GetSpectrumModel()->GetNumBands();
317 double power = Sum(*rxParams->psd) / nbands;
318
319 NS_LOG_LOGIC(" Rx power: " << power << " azimuthTx " << azimuthTx
320 << " zenithTx " << zenithTx << " azimuthRx "
321 << azimuthRx << " zenithRx " << zenithRx);
322
323 if (max < power)
324 {
325 max = power;
326 maxTxAzimuth = azimuthTx;
327 maxRxAzimuth = azimuthRx;
328 maxTxZenith = zenithTx;
329 maxRxZenith = zenithRx;
330 maxTxW = txW;
331 maxRxW = rxW;
332 }
333 }
334 }
335 }
336 }
337
339 std::make_pair(maxTxW, BeamId(static_cast<uint16_t>(maxTxAzimuth), maxTxZenith)));
341 std::make_pair(maxRxW, BeamId(static_cast<uint16_t>(maxRxAzimuth), maxRxZenith)));
342
343 NS_LOG_DEBUG("Beamforming vectors for gNB with node id: "
344 << gnbSpectrumPhy->GetMobility()->GetObject<Node>()->GetId()
345 << " and UE with node id: "
346 << ueSpectrumPhy->GetMobility()->GetObject<Node>()->GetId() << " are azimuthTx "
347 << maxTxAzimuth << " zenithTx " << maxTxZenith << " azimuthRx " << maxRxAzimuth
348 << " zenithRx " << maxRxZenith);
349
350 NS_ASSERT(maxTxW.GetSize() && maxRxW.GetSize());
351
352 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
353}
354
355TypeId
357{
358 static TypeId tid =
359 TypeId("ns3::CellScanQuasiOmniBeamforming")
360 .SetParent<IdealBeamformingAlgorithm>()
361 .AddConstructor<CellScanQuasiOmniBeamforming>()
362 .AddAttribute("BeamSearchAngleStep",
363 "Angle step when searching for the best beam",
364 DoubleValue(30),
367 MakeDoubleChecker<double>());
368
369 return tid;
370}
371
372void
374{
375 m_beamSearchAngleStep = beamSearchAngleStep;
376}
377
378double
380{
381 return m_beamSearchAngleStep;
382}
383
384BeamformingVectorPair
385CellScanQuasiOmniBeamforming::GetBeamformingVectors(const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
386 const Ptr<NrSpectrumPhy>& ueSpectrumPhy) const
387{
388 NS_ABORT_MSG_IF(gnbSpectrumPhy == nullptr || ueSpectrumPhy == nullptr,
389 "Something went wrong, gnb or UE PHY layer not set.");
390 double distance = gnbSpectrumPhy->GetMobility()->GetDistanceFrom(ueSpectrumPhy->GetMobility());
391 NS_ABORT_MSG_IF(distance == 0,
392 "Beamforming method cannot be performed between two devices that are placed in "
393 "the same position.");
394
395 Ptr<const PhasedArraySpectrumPropagationLossModel> txThreeGppSpectrumPropModel =
396 gnbSpectrumPhy->GetSpectrumChannel()->GetPhasedArraySpectrumPropagationLossModel();
397 Ptr<const PhasedArraySpectrumPropagationLossModel> rxThreeGppSpectrumPropModel =
398 ueSpectrumPhy->GetSpectrumChannel()->GetPhasedArraySpectrumPropagationLossModel();
399 NS_ASSERT_MSG(txThreeGppSpectrumPropModel == rxThreeGppSpectrumPropModel,
400 "Devices should be connected to the same spectrum channel");
401
402 std::vector<int> activeRbs;
403 for (size_t rbId = 0; rbId < gnbSpectrumPhy->GetRxSpectrumModel()->GetNumBands(); rbId++)
404 {
405 activeRbs.push_back(rbId);
406 }
407
408 Ptr<const SpectrumValue> fakePsd = NrSpectrumValueHelper::CreateTxPowerSpectralDensity(
409 0.0,
410 activeRbs,
411 gnbSpectrumPhy->GetRxSpectrumModel(),
412 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
413 Ptr<SpectrumSignalParameters> fakeParams = Create<SpectrumSignalParameters>();
414 fakeParams->psd = fakePsd->Copy();
415
416 double max = 0;
417 double maxTxTheta = 0;
418 uint16_t maxTxSector = 0;
419 PhasedArrayModel::ComplexVector maxTxW;
420
421 UintegerValue uintValue;
422 gnbSpectrumPhy->GetAntenna()->GetAttribute("NumRows", uintValue);
423 uint32_t txNumRows = static_cast<uint32_t>(uintValue.Get());
424
425 ueSpectrumPhy->GetBeamManager()
426 ->ChangeToQuasiOmniBeamformingVector(); // we have to set it immediately to q-omni so that
427 // we can perform calculations when calling spectrum
428 // model above
429
430 PhasedArrayModel::ComplexVector rxW =
431 ueSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
432 BeamformingVector ueBfv = std::make_pair(rxW, OMNI_BEAM_ID);
433
434 uint16_t numRows = static_cast<uint16_t>(txNumRows);
435 for (double txTheta = 60; txTheta < 121; txTheta = txTheta + m_beamSearchAngleStep)
436 {
437 for (uint16_t txSector = 0; txSector <= numRows; txSector++)
438 {
439 NS_ASSERT(txSector < UINT16_MAX);
440
441 gnbSpectrumPhy->GetBeamManager()->SetSector(txSector, txTheta);
442 PhasedArrayModel::ComplexVector txW =
443 gnbSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
444
445 NS_ABORT_MSG_IF(txW.GetSize() == 0 || rxW.GetSize() == 0,
446 "Beamforming vectors must be initialized in order to calculate the "
447 "long term matrix.");
448 Ptr<SpectrumSignalParameters> rxParams =
449 txThreeGppSpectrumPropModel->CalcRxPowerSpectralDensity(
450 fakeParams,
451 gnbSpectrumPhy->GetMobility(),
452 ueSpectrumPhy->GetMobility(),
453 gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>(),
454 ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>());
455
456 size_t nbands = rxParams->psd->GetSpectrumModel()->GetNumBands();
457 double power = Sum(*(rxParams->psd)) / nbands;
458
459 NS_LOG_LOGIC(" Rx power: "
460 << power << "txTheta " << txTheta << " tx sector "
461 << (M_PI * static_cast<double>(txSector) / static_cast<double>(txNumRows) -
462 0.5 * M_PI) /
463 M_PI * 180);
464
465 if (max < power)
466 {
467 max = power;
468 maxTxSector = txSector;
469 maxTxTheta = txTheta;
470 maxTxW = txW;
471 }
472 }
473 }
474
475 BeamformingVector gnbBfv =
476 BeamformingVector(std::make_pair(maxTxW, BeamId(maxTxSector, maxTxTheta)));
477
478 NS_LOG_DEBUG(
479 "Beamforming vectors for gNB with node id: "
480 << gnbSpectrumPhy->GetMobility()->GetObject<Node>()->GetId()
481 << " and UE with node id: " << ueSpectrumPhy->GetMobility()->GetObject<Node>()->GetId()
482 << " are txTheta " << maxTxTheta << " tx sector "
483 << (M_PI * static_cast<double>(maxTxSector) / static_cast<double>(txNumRows) - 0.5 * M_PI) /
484 M_PI * 180);
485
486 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
487}
488
489TypeId
491{
492 static TypeId tid = TypeId("ns3::DirectPathBeamforming")
493 .SetParent<IdealBeamformingAlgorithm>()
494 .AddConstructor<DirectPathBeamforming>();
495 return tid;
496}
497
498BeamformingVectorPair
499DirectPathBeamforming::GetBeamformingVectors(const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
500 const Ptr<NrSpectrumPhy>& ueSpectrumPhy) const
501{
502 NS_LOG_FUNCTION(this);
503
504 Ptr<const UniformPlanarArray> gnbAntenna =
505 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>();
506 Ptr<const UniformPlanarArray> ueAntenna =
507 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>();
508
509 PhasedArrayModel::ComplexVector gNbAntennaWeights =
510 CreateDirectPathBfv(gnbSpectrumPhy->GetMobility(),
511 ueSpectrumPhy->GetMobility(),
512 gnbAntenna);
513 // store the antenna weights
514 BeamformingVector gnbBfv =
515 BeamformingVector(std::make_pair(gNbAntennaWeights, BeamId::GetEmptyBeamId()));
516
517 PhasedArrayModel::ComplexVector ueAntennaWeights =
518 CreateDirectPathBfv(ueSpectrumPhy->GetMobility(), gnbSpectrumPhy->GetMobility(), ueAntenna);
519 // store the antenna weights
520 BeamformingVector ueBfv =
521 BeamformingVector(std::make_pair(ueAntennaWeights, BeamId::GetEmptyBeamId()));
522
523 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
524}
525
526TypeId
528{
529 static TypeId tid = TypeId("ns3::QuasiOmniDirectPathBeamforming")
530 .SetParent<DirectPathBeamforming>()
531 .AddConstructor<QuasiOmniDirectPathBeamforming>();
532 return tid;
533}
534
535BeamformingVectorPair
536QuasiOmniDirectPathBeamforming::GetBeamformingVectors(const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
537 const Ptr<NrSpectrumPhy>& ueSpectrumPhy) const
538{
539 NS_LOG_FUNCTION(this);
540 Ptr<const UniformPlanarArray> gnbAntenna =
541 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>();
542 Ptr<const UniformPlanarArray> ueAntenna =
543 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>();
544
545 // configure gNb beamforming vector to be quasi omni
546 UintegerValue numRows;
547 UintegerValue numColumns;
548 gnbAntenna->GetAttribute("NumRows", numRows);
549 gnbAntenna->GetAttribute("NumColumns", numColumns);
550 BeamformingVector gnbBfv = {CreateQuasiOmniBfv(gnbAntenna), OMNI_BEAM_ID};
551
552 // configure UE beamforming vector to be directed towards gNB
553 PhasedArrayModel::ComplexVector ueAntennaWeights =
554 CreateDirectPathBfv(ueSpectrumPhy->GetMobility(), gnbSpectrumPhy->GetMobility(), ueAntenna);
555 // store the antenna weights
556 BeamformingVector ueBfv = BeamformingVector({ueAntennaWeights, BeamId::GetEmptyBeamId()});
557 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
558}
559
560TypeId
562{
563 static TypeId tid = TypeId("ns3::DirectPathQuasiOmniBeamforming")
564 .SetParent<DirectPathBeamforming>()
565 .AddConstructor<DirectPathQuasiOmniBeamforming>();
566 return tid;
567}
568
569BeamformingVectorPair
570DirectPathQuasiOmniBeamforming::GetBeamformingVectors(const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
571 const Ptr<NrSpectrumPhy>& ueSpectrumPhy) const
572{
573 NS_LOG_FUNCTION(this);
574 Ptr<const UniformPlanarArray> gnbAntenna =
575 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>();
576 Ptr<const UniformPlanarArray> ueAntenna =
577 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>();
578
579 // configure ue beamforming vector to be quasi omni
580 UintegerValue numRows;
581 UintegerValue numColumns;
582 ueAntenna->GetAttribute("NumRows", numRows);
583 ueAntenna->GetAttribute("NumColumns", numColumns);
585
586 // configure gNB beamforming vector to be directed towards UE
587 PhasedArrayModel::ComplexVector gnbAntennaWeights =
588 CreateDirectPathBfv(gnbSpectrumPhy->GetMobility(),
589 ueSpectrumPhy->GetMobility(),
590 gnbAntenna);
591 // store the antenna weights
592 BeamformingVector gnbBfv = {gnbAntennaWeights, BeamId::GetEmptyBeamId()};
593
594 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
595}
596
597TypeId
599{
600 static TypeId tid = TypeId("ns3::OptimalCovMatrixBeamforming")
601 .SetParent<IdealBeamformingAlgorithm>()
602 .AddConstructor<OptimalCovMatrixBeamforming>();
603
604 return tid;
605}
606
607BeamformingVectorPair
609 [[maybe_unused]] const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
610 [[maybe_unused]] const Ptr<NrSpectrumPhy>& ueSpectrumPhy) const
611{
612 NS_LOG_FUNCTION(this);
613 return BeamformingVectorPair();
614}
615
616TypeId
618{
619 static TypeId tid = TypeId("ns3::KroneckerBeamforming")
620 .SetParent<IdealBeamformingAlgorithm>()
621 .AddConstructor<KroneckerBeamforming>();
622 return tid;
623}
624
625void
626KroneckerBeamforming::SetColRxBeamAngles(std::vector<double> colAngles)
627{
628 m_colRxBeamAngles = colAngles;
629}
630
631void
632KroneckerBeamforming::SetColTxBeamAngles(std::vector<double> colAngles)
633{
634 m_colTxBeamAngles = colAngles;
635}
636
637void
638KroneckerBeamforming::SetRowRxBeamAngles(std::vector<double> rowAngles)
639{
640 m_rowRxBeamAngles = rowAngles;
641}
642
643void
644KroneckerBeamforming::SetRowTxBeamAngles(std::vector<double> rowAngles)
645{
646 m_rowTxBeamAngles = rowAngles;
647}
648
649std::vector<double>
651{
652 return m_colRxBeamAngles;
653}
654
655std::vector<double>
657{
658 return m_colTxBeamAngles;
659}
660
661std::vector<double>
663{
664 return m_rowRxBeamAngles;
665}
666
667std::vector<double>
669{
670 return m_rowTxBeamAngles;
671}
672
673BeamformingVectorPair
674KroneckerBeamforming::GetBeamformingVectors(const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
675 const Ptr<NrSpectrumPhy>& ueSpectrumPhy) const
676{
677 NS_ABORT_MSG_IF(gnbSpectrumPhy == nullptr || ueSpectrumPhy == nullptr,
678 "Something went wrong, gnb or UE PHY layer not set.");
679
680 Ptr<SpectrumChannel> gnbSpectrumChannel = gnbSpectrumPhy->GetSpectrumChannel();
681 Ptr<SpectrumChannel> ueSpectrumChannel = ueSpectrumPhy->GetSpectrumChannel();
682
683 Ptr<const PhasedArraySpectrumPropagationLossModel> gnbThreeGppSpectrumPropModel =
684 gnbSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel();
685 Ptr<const PhasedArraySpectrumPropagationLossModel> ueThreeGppSpectrumPropModel =
686 ueSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel();
687 NS_ASSERT_MSG(gnbThreeGppSpectrumPropModel == ueThreeGppSpectrumPropModel,
688 "Devices should be connected on the same spectrum channel");
689
690 std::vector<int> activeRbs;
691 for (size_t rbId = 0; rbId < gnbSpectrumPhy->GetRxSpectrumModel()->GetNumBands(); rbId++)
692 {
693 activeRbs.push_back(rbId);
694 }
695 Ptr<const SpectrumValue> fakePsd = NrSpectrumValueHelper::CreateTxPowerSpectralDensity(
696 0.0,
697 activeRbs,
698 gnbSpectrumPhy->GetRxSpectrumModel(),
699 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
700 Ptr<SpectrumSignalParameters> fakeParams = Create<SpectrumSignalParameters>();
701
702 double maxPower = 0;
703 BeamformingVector gnbBfv;
704 BeamformingVector ueBfv;
705 // configure gNB and ue beamforming vectors to be Kronecker
706 for (size_t k = 0; k < m_colTxBeamAngles.size(); k++)
707 {
708 for (size_t m = 0; m < m_rowTxBeamAngles.size(); m++)
709 {
710 for (size_t i = 0; i < m_colRxBeamAngles.size(); i++)
711 {
712 for (size_t j = 0; j < m_rowRxBeamAngles.size(); j++)
713 {
714 auto bfUe = CreateKroneckerBfv(
715 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>(),
716 m_rowTxBeamAngles[m],
717 m_colTxBeamAngles[k]);
718 ueSpectrumPhy->GetAntenna()
719 ->GetObject<UniformPlanarArray>()
720 ->SetBeamformingVector(bfUe);
721 auto bf = CreateKroneckerBfv(
722 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>(),
723 m_rowRxBeamAngles[j],
724 m_colRxBeamAngles[i]);
725 gnbSpectrumPhy->GetAntenna()
726 ->GetObject<UniformPlanarArray>()
727 ->SetBeamformingVector(bf);
728 fakeParams->psd = Copy<SpectrumValue>(fakePsd);
729 auto rxParams = gnbThreeGppSpectrumPropModel->CalcRxPowerSpectralDensity(
730 fakeParams,
731 gnbSpectrumPhy->GetMobility(),
732 ueSpectrumPhy->GetMobility(),
733 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>(),
734 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>());
735
736 size_t nbands = rxParams->psd->GetSpectrumModel()->GetNumBands();
737 double power = Sum(*(rxParams->psd)) / nbands;
738 if (power > maxPower)
739 {
740 maxPower = power;
741 gnbBfv = {bf, BeamId::GetEmptyBeamId()};
742 ueBfv = {bfUe, BeamId::GetEmptyBeamId()};
743 }
744 }
745 }
746 }
747 }
748 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
749}
750
751TypeId
753{
754 static TypeId tid = TypeId("ns3::KroneckerQuasiOmniBeamforming")
755 .SetParent<IdealBeamformingAlgorithm>()
756 .AddConstructor<KroneckerQuasiOmniBeamforming>();
757 return tid;
758}
759
760void
762{
763 m_colBeamAngles = colAngles;
764}
765
766void
768{
769 m_rowBeamAngles = rowAngles;
770}
771
772std::vector<double>
774{
775 return m_colBeamAngles;
776}
777
778std::vector<double>
780{
781 return m_rowBeamAngles;
782}
783
784BeamformingVectorPair
785KroneckerQuasiOmniBeamforming::GetBeamformingVectors(const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
786 const Ptr<NrSpectrumPhy>& ueSpectrumPhy) const
787{
788 NS_ABORT_MSG_IF(gnbSpectrumPhy == nullptr || ueSpectrumPhy == nullptr,
789 "Something went wrong, gnb or UE PHY layer not set.");
790
791 Ptr<SpectrumChannel> gnbSpectrumChannel = gnbSpectrumPhy->GetSpectrumChannel();
792 Ptr<SpectrumChannel> ueSpectrumChannel = ueSpectrumPhy->GetSpectrumChannel();
793
794 Ptr<const PhasedArraySpectrumPropagationLossModel> gnbThreeGppSpectrumPropModel =
795 gnbSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel();
796 Ptr<const PhasedArraySpectrumPropagationLossModel> ueThreeGppSpectrumPropModel =
797 ueSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel();
798 NS_ASSERT_MSG(gnbThreeGppSpectrumPropModel == ueThreeGppSpectrumPropModel,
799 "Devices should be connected on the same spectrum channel");
800
801 std::vector<int> activeRbs;
802 for (size_t rbId = 0; rbId < gnbSpectrumPhy->GetRxSpectrumModel()->GetNumBands(); rbId++)
803 {
804 activeRbs.push_back(rbId);
805 }
806 Ptr<const SpectrumValue> fakePsd = NrSpectrumValueHelper::CreateTxPowerSpectralDensity(
807 0.0,
808 activeRbs,
809 gnbSpectrumPhy->GetRxSpectrumModel(),
810 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
811
812 // configure ue beamforming vector to be quasi
813 Ptr<const UniformPlanarArray> ueAntenna =
814 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>();
815 PhasedArrayModel::ComplexVector uebfV = CreateQuasiOmniBfv(ueAntenna);
816 BeamformingVector ueBfv = {uebfV, OMNI_BEAM_ID};
817 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>()->SetBeamformingVector(uebfV);
818
819 // configure gNB beamforming vector to be Kronecker
820 Ptr<SpectrumSignalParameters> fakeParams = Create<SpectrumSignalParameters>();
821 double maxPower = 0;
822 BeamformingVector gnbBfv;
823
824 for (size_t i = 0; i < m_colBeamAngles.size(); i++)
825 {
826 for (size_t j = 0; j < m_rowBeamAngles.size(); j++)
827 {
828 auto bf =
829 CreateKroneckerBfv(gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>(),
830 m_rowBeamAngles[j],
831 m_colBeamAngles[i]);
832 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>()->SetBeamformingVector(bf);
833 fakeParams->psd = Copy<SpectrumValue>(fakePsd);
834 auto rxParams = gnbThreeGppSpectrumPropModel->CalcRxPowerSpectralDensity(
835 fakeParams,
836 gnbSpectrumPhy->GetMobility(),
837 ueSpectrumPhy->GetMobility(),
838 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>(),
839 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>());
840
841 size_t nbands = rxParams->psd->GetSpectrumModel()->GetNumBands();
842 double power = Sum(*(rxParams->psd)) / nbands;
843 if (power > maxPower)
844 {
845 maxPower = power;
846 gnbBfv = {bf, BeamId::GetEmptyBeamId()};
847 }
848 }
849 }
850 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
851}
852} // namespace ns3
Representation of a beam id.
Definition beam-id.h:26
BeamformingVectorPair GetBeamformingVectors(const Ptr< NrSpectrumPhy > &gnbSpectrumPhy, const Ptr< NrSpectrumPhy > &ueSpectrumPhy) const override
Function that generates the beamforming vectors for a pair of communicating devices by using cell sca...
void SetBeamSearchAngleStep(double beamSearchAngleStep)
Sets the value of BeamSearchAngleStep attribute.
BeamformingVectorPair GetBeamformingVectors(const Ptr< NrSpectrumPhy > &gnbSpectrumPhy, const Ptr< NrSpectrumPhy > &ueSpectrumPhy) const override
Function that generates the beamforming vectors for a pair of communicating devices by using cell sca...
static TypeId GetTypeId()
Get the type id.
void SetBeamSearchAngleStep(double beamSearchAngleStep)
Sets the value of BeamSearchAngleStep attribute.
BeamformingVectorPair GetBeamformingVectors(const Ptr< NrSpectrumPhy > &gnbSpectrumPhy, const Ptr< NrSpectrumPhy > &ueSpectrumPhy) const override
Function that generates the beamforming vectors for a pair of communicating devices by using cell sca...
static TypeId GetTypeId()
Get the type id.
The DirectPathBeamforming class.
BeamformingVectorPair GetBeamformingVectors(const Ptr< NrSpectrumPhy > &gnbSpectrumPhy, const Ptr< NrSpectrumPhy > &ueSpectrumPhy) const override
Function that generates the beamforming vectors for a pair of communicating devices by using the dire...
static TypeId GetTypeId()
Get the type id.
BeamformingVectorPair GetBeamformingVectors(const Ptr< NrSpectrumPhy > &gnbSpectrumPhy, const Ptr< NrSpectrumPhy > &ueSpectrumPhy) const override
Function that generates the beamforming vectors for a pair of communicating devices by using the dire...
Generate "Ideal" beamforming vectors.
static TypeId GetTypeId()
Get the type id.
std::vector< double > GetRowRxBeamAngles() const
BeamformingVectorPair GetBeamformingVectors(const Ptr< NrSpectrumPhy > &gnbSpectrumPhy, const Ptr< NrSpectrumPhy > &ueSpectrumPhy) const override
Function that generates the beamforming vectors for a pair of communicating devices by using kronecke...
void SetColTxBeamAngles(std::vector< double > colAngles)
Sets the value of BeamColAngles of Tx attribute.
std::vector< double > GetColTxBeamAngles() const
void SetRowTxBeamAngles(std::vector< double > rowAngles)
Sets the value of BeamRowAngles of Tx attribute.
static TypeId GetTypeId()
Get the type id.
std::vector< double > GetRowTxBeamAngles() const
void SetRowRxBeamAngles(std::vector< double > rowAngles)
Sets the value of BeamRowAngles of Rx attribute.
void SetColRxBeamAngles(std::vector< double > colAngles)
Sets the value of BeamColAngles of Rx attribute.
std::vector< double > GetColRxBeamAngles() const
BeamformingVectorPair GetBeamformingVectors(const Ptr< NrSpectrumPhy > &gnbSpectrumPhy, const Ptr< NrSpectrumPhy > &ueSpectrumPhy) const override
Function that generates the beamforming vectors for a pair of communicating devices by using kronecke...
void SetRowBeamAngles(std::vector< double > rowAngles)
Sets the value of BeamRowAngles attribute.
void SetColBeamAngles(std::vector< double > colAngles)
Sets the value of BeamColAngles attribute.
static Ptr< SpectrumValue > CreateTxPowerSpectralDensity(double powerTx, const std::vector< int > &rbIndexVector, const Ptr< const SpectrumModel > &txSm, enum PowerAllocationType allocationType)
Create SpectrumValue that will represent transmit power spectral density, and assuming that all RBs a...
static TypeId GetTypeId()
Get the type id.
BeamformingVectorPair GetBeamformingVectors(const Ptr< NrSpectrumPhy > &gnbSpectrumPhy, const Ptr< NrSpectrumPhy > &ueSpectrumPhy) const override
Function that generates the beamforming vectors for a pair of communicating devices by using the dire...
BeamformingVectorPair GetBeamformingVectors(const Ptr< NrSpectrumPhy > &gnbSpectrumPhy, const Ptr< NrSpectrumPhy > &ueSpectrumPhy) const override
Function that generates the beamforming vectors for a pair of communicating devices by using the quas...
std::pair< PhasedArrayModel::ComplexVector, BeamId > BeamformingVector
Physical representation of a beam.
const BeamId OMNI_BEAM_ID
Name of the OMNI beam.
Definition beam-id.cc:9
PhasedArrayModel::ComplexVector CreateQuasiOmniBfv(const Ptr< const UniformPlanarArray > &antenna)
Create a quasi omni beamforming vector.