5#include "ideal-beamforming-algorithm.h"
7#include "nr-spectrum-phy.h"
10#include "ns3/multi-model-spectrum-channel.h"
12#include "ns3/nr-spectrum-value-helper.h"
13#include "ns3/uinteger.h"
14#include "ns3/uniform-planar-array.h"
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);
33 static TypeId tid = TypeId(
"ns3::IdealBeamformingAlgorithm").SetParent<Object>();
41 TypeId(
"ns3::CellScanBeamforming")
43 .AddConstructor<CellScanBeamforming>()
44 .AddAttribute(
"BeamSearchAngleStep",
45 "Angle step when searching for the best beam",
49 MakeDoubleChecker<double>());
57 m_beamSearchAngleStep = beamSearchAngleStep;
63 return m_beamSearchAngleStep;
68 const Ptr<NrSpectrumPhy>& ueSpectrumPhy)
const
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.");
77 Ptr<SpectrumChannel> gnbSpectrumChannel =
79 ->GetSpectrumChannel();
80 Ptr<SpectrumChannel> ueSpectrumChannel = ueSpectrumPhy->GetSpectrumChannel();
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");
89 std::vector<int> activeRbs;
90 for (
size_t rbId = 0; rbId < gnbSpectrumPhy->GetRxSpectrumModel()->GetNumBands(); rbId++)
92 activeRbs.push_back(rbId);
98 gnbSpectrumPhy->GetRxSpectrumModel(),
99 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
100 Ptr<SpectrumSignalParameters> fakeParams = Create<SpectrumSignalParameters>();
101 fakeParams->psd = fakePsd->Copy();
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;
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());
117 NS_ASSERT(gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>()->GetNumElems() &&
118 ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>()->GetNumElems());
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)
124 for (uint16_t txSector = 0; txSector <= numRowsTx; txSector++)
126 NS_ASSERT(txSector < UINT16_MAX);
128 gnbSpectrumPhy->GetBeamManager()->SetSector(txSector, txTheta);
129 PhasedArrayModel::ComplexVector txW =
130 gnbSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
132 if (maxTxW.GetSize() == 0)
137 for (
double rxTheta = 60; rxTheta < 121;
138 rxTheta =
static_cast<uint16_t
>(rxTheta + m_beamSearchAngleStep))
140 for (uint16_t rxSector = 0; rxSector <= numRowsRx; rxSector++)
142 NS_ASSERT(rxSector < UINT16_MAX);
144 ueSpectrumPhy->GetBeamManager()->SetSector(rxSector, rxTheta);
145 PhasedArrayModel::ComplexVector rxW =
146 ueSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
148 if (maxRxW.GetSize() == 0)
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.");
157 Ptr<SpectrumSignalParameters> rxParams =
158 gnbThreeGppSpectrumPropModel->CalcRxPowerSpectralDensity(
160 gnbSpectrumPhy->GetMobility(),
161 ueSpectrumPhy->GetMobility(),
162 gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>(),
163 ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>());
165 size_t nbands = rxParams->psd->GetSpectrumModel()->GetNumBands();
166 double power = Sum(*(rxParams->psd)) / nbands;
170 << power <<
"txTheta " << txTheta <<
" rxTheta " << rxTheta <<
" tx sector "
171 << (M_PI *
static_cast<double>(txSector) /
static_cast<double>(txNumRows) -
175 << (M_PI *
static_cast<double>(rxSector) /
static_cast<double>(rxNumRows) -
182 maxTxSector = txSector;
183 maxRxSector = rxSector;
184 maxTxTheta = txTheta;
185 maxRxTheta = rxTheta;
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) /
207 << (M_PI *
static_cast<double>(maxRxSector) /
static_cast<double>(rxNumRows) - 0.5 * M_PI) /
210 NS_ASSERT(maxTxW.GetSize() && maxRxW.GetSize());
212 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
218 static TypeId tid = TypeId(
"ns3::CellScanBeamformingAzimuthZenith")
220 .AddConstructor<CellScanBeamformingAzimuthZenith>();
227 const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
228 const Ptr<NrSpectrumPhy>& ueSpectrumPhy)
const
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.");
237 Ptr<SpectrumChannel> gnbSpectrumChannel =
239 ->GetSpectrumChannel();
240 Ptr<SpectrumChannel> ueSpectrumChannel = ueSpectrumPhy->GetSpectrumChannel();
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");
249 std::vector<int> activeRbs;
250 for (
size_t rbId = 0; rbId < gnbSpectrumPhy->GetRxSpectrumModel()->GetNumBands(); rbId++)
252 activeRbs.push_back(rbId);
258 gnbSpectrumPhy->GetRxSpectrumModel(),
259 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
260 Ptr<SpectrumSignalParameters> fakeParams = Create<SpectrumSignalParameters>();
261 fakeParams->psd = fakePsd->Copy();
264 double maxTxAzimuth = 0;
265 double maxRxAzimuth = 0;
266 double maxTxZenith = 0;
267 double maxRxZenith = 0;
268 PhasedArrayModel::ComplexVector maxTxW;
269 PhasedArrayModel::ComplexVector maxRxW;
271 UintegerValue uintValue;
272 gnbSpectrumPhy->GetAntenna()->GetAttribute(
"NumRows", uintValue);
273 ueSpectrumPhy->GetAntenna()->GetAttribute(
"NumRows", uintValue);
275 NS_ASSERT(gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>()->GetNumElems() &&
276 ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>()->GetNumElems());
278 for (
double azimuthTx : m_azimuth)
280 for (
double zenithTx : m_zenith)
282 gnbSpectrumPhy->GetBeamManager()->SetSectorAz(azimuthTx, zenithTx);
283 PhasedArrayModel::ComplexVector txW =
284 gnbSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
286 if (maxTxW.GetSize() == 0)
291 for (
double azimuthRx : m_azimuth)
293 for (
double zenithRx : m_zenith)
295 ueSpectrumPhy->GetBeamManager()->SetSectorAz(azimuthRx, zenithRx);
296 PhasedArrayModel::ComplexVector rxW =
297 ueSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
299 if (maxRxW.GetSize() == 0)
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.");
308 Ptr<SpectrumSignalParameters> rxParams =
309 gnbThreeGppSpectrumPropModel->CalcRxPowerSpectralDensity(
311 gnbSpectrumPhy->GetMobility(),
312 ueSpectrumPhy->GetMobility(),
313 gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>(),
314 ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>());
316 size_t nbands = rxParams->psd->GetSpectrumModel()->GetNumBands();
317 double power = Sum(*rxParams->psd) / nbands;
319 NS_LOG_LOGIC(
" Rx power: " << power <<
" azimuthTx " << azimuthTx
320 <<
" zenithTx " << zenithTx <<
" azimuthRx "
321 << azimuthRx <<
" zenithRx " << zenithRx);
326 maxTxAzimuth = azimuthTx;
327 maxRxAzimuth = azimuthRx;
328 maxTxZenith = zenithTx;
329 maxRxZenith = zenithRx;
339 std::make_pair(maxTxW,
BeamId(
static_cast<uint16_t
>(maxTxAzimuth), maxTxZenith)));
341 std::make_pair(maxRxW,
BeamId(
static_cast<uint16_t
>(maxRxAzimuth), maxRxZenith)));
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);
350 NS_ASSERT(maxTxW.GetSize() && maxRxW.GetSize());
352 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
359 TypeId(
"ns3::CellScanQuasiOmniBeamforming")
361 .AddConstructor<CellScanQuasiOmniBeamforming>()
362 .AddAttribute(
"BeamSearchAngleStep",
363 "Angle step when searching for the best beam",
367 MakeDoubleChecker<double>());
375 m_beamSearchAngleStep = beamSearchAngleStep;
381 return m_beamSearchAngleStep;
386 const Ptr<NrSpectrumPhy>& ueSpectrumPhy)
const
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.");
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");
402 std::vector<int> activeRbs;
403 for (
size_t rbId = 0; rbId < gnbSpectrumPhy->GetRxSpectrumModel()->GetNumBands(); rbId++)
405 activeRbs.push_back(rbId);
411 gnbSpectrumPhy->GetRxSpectrumModel(),
412 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
413 Ptr<SpectrumSignalParameters> fakeParams = Create<SpectrumSignalParameters>();
414 fakeParams->psd = fakePsd->Copy();
417 double maxTxTheta = 0;
418 uint16_t maxTxSector = 0;
419 PhasedArrayModel::ComplexVector maxTxW;
421 UintegerValue uintValue;
422 gnbSpectrumPhy->GetAntenna()->GetAttribute(
"NumRows", uintValue);
423 uint32_t txNumRows =
static_cast<uint32_t
>(uintValue.Get());
425 ueSpectrumPhy->GetBeamManager()
426 ->ChangeToQuasiOmniBeamformingVector();
430 PhasedArrayModel::ComplexVector rxW =
431 ueSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
434 uint16_t numRows =
static_cast<uint16_t
>(txNumRows);
435 for (
double txTheta = 60; txTheta < 121; txTheta = txTheta + m_beamSearchAngleStep)
437 for (uint16_t txSector = 0; txSector <= numRows; txSector++)
439 NS_ASSERT(txSector < UINT16_MAX);
441 gnbSpectrumPhy->GetBeamManager()->SetSector(txSector, txTheta);
442 PhasedArrayModel::ComplexVector txW =
443 gnbSpectrumPhy->GetBeamManager()->GetCurrentBeamformingVector();
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(
451 gnbSpectrumPhy->GetMobility(),
452 ueSpectrumPhy->GetMobility(),
453 gnbSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>(),
454 ueSpectrumPhy->GetAntenna()->GetObject<PhasedArrayModel>());
456 size_t nbands = rxParams->psd->GetSpectrumModel()->GetNumBands();
457 double power = Sum(*(rxParams->psd)) / nbands;
459 NS_LOG_LOGIC(
" Rx power: "
460 << power <<
"txTheta " << txTheta <<
" tx sector "
461 << (M_PI *
static_cast<double>(txSector) /
static_cast<double>(txNumRows) -
468 maxTxSector = txSector;
469 maxTxTheta = txTheta;
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) /
486 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
492 static TypeId tid = TypeId(
"ns3::DirectPathBeamforming")
494 .AddConstructor<DirectPathBeamforming>();
500 const Ptr<NrSpectrumPhy>& ueSpectrumPhy)
const
502 NS_LOG_FUNCTION(
this);
504 Ptr<const UniformPlanarArray> gnbAntenna =
505 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>();
506 Ptr<const UniformPlanarArray> ueAntenna =
507 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>();
509 PhasedArrayModel::ComplexVector gNbAntennaWeights =
510 CreateDirectPathBfv(gnbSpectrumPhy->GetMobility(),
511 ueSpectrumPhy->GetMobility(),
517 PhasedArrayModel::ComplexVector ueAntennaWeights =
518 CreateDirectPathBfv(ueSpectrumPhy->GetMobility(), gnbSpectrumPhy->GetMobility(), ueAntenna);
523 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
529 static TypeId tid = TypeId(
"ns3::QuasiOmniDirectPathBeamforming")
531 .AddConstructor<QuasiOmniDirectPathBeamforming>();
537 const Ptr<NrSpectrumPhy>& ueSpectrumPhy)
const
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>();
546 UintegerValue numRows;
547 UintegerValue numColumns;
548 gnbAntenna->GetAttribute(
"NumRows", numRows);
549 gnbAntenna->GetAttribute(
"NumColumns", numColumns);
553 PhasedArrayModel::ComplexVector ueAntennaWeights =
554 CreateDirectPathBfv(ueSpectrumPhy->GetMobility(), gnbSpectrumPhy->GetMobility(), ueAntenna);
557 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
563 static TypeId tid = TypeId(
"ns3::DirectPathQuasiOmniBeamforming")
565 .AddConstructor<DirectPathQuasiOmniBeamforming>();
571 const Ptr<NrSpectrumPhy>& ueSpectrumPhy)
const
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>();
580 UintegerValue numRows;
581 UintegerValue numColumns;
582 ueAntenna->GetAttribute(
"NumRows", numRows);
583 ueAntenna->GetAttribute(
"NumColumns", numColumns);
587 PhasedArrayModel::ComplexVector gnbAntennaWeights =
588 CreateDirectPathBfv(gnbSpectrumPhy->GetMobility(),
589 ueSpectrumPhy->GetMobility(),
594 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
600 static TypeId tid = TypeId(
"ns3::OptimalCovMatrixBeamforming")
602 .AddConstructor<OptimalCovMatrixBeamforming>();
609 [[maybe_unused]]
const Ptr<NrSpectrumPhy>& gnbSpectrumPhy,
610 [[maybe_unused]]
const Ptr<NrSpectrumPhy>& ueSpectrumPhy)
const
612 NS_LOG_FUNCTION(
this);
613 return BeamformingVectorPair();
619 static TypeId tid = TypeId(
"ns3::KroneckerBeamforming")
621 .AddConstructor<KroneckerBeamforming>();
628 m_colRxBeamAngles = colAngles;
634 m_colTxBeamAngles = colAngles;
640 m_rowRxBeamAngles = rowAngles;
646 m_rowTxBeamAngles = rowAngles;
652 return m_colRxBeamAngles;
658 return m_colTxBeamAngles;
664 return m_rowRxBeamAngles;
670 return m_rowTxBeamAngles;
675 const Ptr<NrSpectrumPhy>& ueSpectrumPhy)
const
677 NS_ABORT_MSG_IF(gnbSpectrumPhy ==
nullptr || ueSpectrumPhy ==
nullptr,
678 "Something went wrong, gnb or UE PHY layer not set.");
680 Ptr<SpectrumChannel> gnbSpectrumChannel = gnbSpectrumPhy->GetSpectrumChannel();
681 Ptr<SpectrumChannel> ueSpectrumChannel = ueSpectrumPhy->GetSpectrumChannel();
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");
690 std::vector<int> activeRbs;
691 for (
size_t rbId = 0; rbId < gnbSpectrumPhy->GetRxSpectrumModel()->GetNumBands(); rbId++)
693 activeRbs.push_back(rbId);
698 gnbSpectrumPhy->GetRxSpectrumModel(),
699 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
700 Ptr<SpectrumSignalParameters> fakeParams = Create<SpectrumSignalParameters>();
706 for (
size_t k = 0; k < m_colTxBeamAngles.size(); k++)
708 for (
size_t m = 0; m < m_rowTxBeamAngles.size(); m++)
710 for (
size_t i = 0; i < m_colRxBeamAngles.size(); i++)
712 for (
size_t j = 0; j < m_rowRxBeamAngles.size(); j++)
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(
731 gnbSpectrumPhy->GetMobility(),
732 ueSpectrumPhy->GetMobility(),
733 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>(),
734 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>());
736 size_t nbands = rxParams->psd->GetSpectrumModel()->GetNumBands();
737 double power = Sum(*(rxParams->psd)) / nbands;
738 if (power > maxPower)
741 gnbBfv = {bf, BeamId::GetEmptyBeamId()};
742 ueBfv = {bfUe, BeamId::GetEmptyBeamId()};
748 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
754 static TypeId tid = TypeId(
"ns3::KroneckerQuasiOmniBeamforming")
756 .AddConstructor<KroneckerQuasiOmniBeamforming>();
763 m_colBeamAngles = colAngles;
769 m_rowBeamAngles = rowAngles;
775 return m_colBeamAngles;
781 return m_rowBeamAngles;
786 const Ptr<NrSpectrumPhy>& ueSpectrumPhy)
const
788 NS_ABORT_MSG_IF(gnbSpectrumPhy ==
nullptr || ueSpectrumPhy ==
nullptr,
789 "Something went wrong, gnb or UE PHY layer not set.");
791 Ptr<SpectrumChannel> gnbSpectrumChannel = gnbSpectrumPhy->GetSpectrumChannel();
792 Ptr<SpectrumChannel> ueSpectrumChannel = ueSpectrumPhy->GetSpectrumChannel();
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");
801 std::vector<int> activeRbs;
802 for (
size_t rbId = 0; rbId < gnbSpectrumPhy->GetRxSpectrumModel()->GetNumBands(); rbId++)
804 activeRbs.push_back(rbId);
809 gnbSpectrumPhy->GetRxSpectrumModel(),
810 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
813 Ptr<const UniformPlanarArray> ueAntenna =
814 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>();
817 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>()->SetBeamformingVector(uebfV);
820 Ptr<SpectrumSignalParameters> fakeParams = Create<SpectrumSignalParameters>();
824 for (
size_t i = 0; i < m_colBeamAngles.size(); i++)
826 for (
size_t j = 0; j < m_rowBeamAngles.size(); j++)
829 CreateKroneckerBfv(gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>(),
832 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>()->SetBeamformingVector(bf);
833 fakeParams->psd = Copy<SpectrumValue>(fakePsd);
834 auto rxParams = gnbThreeGppSpectrumPropModel->CalcRxPowerSpectralDensity(
836 gnbSpectrumPhy->GetMobility(),
837 ueSpectrumPhy->GetMobility(),
838 gnbSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>(),
839 ueSpectrumPhy->GetAntenna()->GetObject<UniformPlanarArray>());
841 size_t nbands = rxParams->psd->GetSpectrumModel()->GetNumBands();
842 double power = Sum(*(rxParams->psd)) / nbands;
843 if (power > maxPower)
846 gnbBfv = {bf, BeamId::GetEmptyBeamId()};
850 return BeamformingVectorPair(std::make_pair(gnbBfv, ueBfv));
Representation of a beam id.
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...
std::pair< PhasedArrayModel::ComplexVector, BeamId > BeamformingVector
Physical representation of a beam.
const BeamId OMNI_BEAM_ID
Name of the OMNI beam.
PhasedArrayModel::ComplexVector CreateQuasiOmniBfv(const Ptr< const UniformPlanarArray > &antenna)
Create a quasi omni beamforming vector.