5G-LENA  nr-v3.0-29-g83cc959
The 5G/NR module for the ns-3 simulator
ideal-beamforming-algorithm.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 "ideal-beamforming-algorithm.h"
8 
9 #include "nr-spectrum-phy.h"
10 
11 #include <ns3/double.h>
12 #include <ns3/multi-model-spectrum-channel.h>
13 #include <ns3/node.h>
14 #include <ns3/nr-spectrum-value-helper.h>
15 #include <ns3/uinteger.h>
16 #include <ns3/uniform-planar-array.h>
17 
18 namespace ns3
19 {
20 
21 NS_LOG_COMPONENT_DEFINE("IdealBeamformingAlgorithm");
22 NS_OBJECT_ENSURE_REGISTERED(CellScanBeamforming);
23 NS_OBJECT_ENSURE_REGISTERED(CellScanBeamformingAzimuthZenith);
24 NS_OBJECT_ENSURE_REGISTERED(CellScanQuasiOmniBeamforming);
25 NS_OBJECT_ENSURE_REGISTERED(DirectPathBeamforming);
26 NS_OBJECT_ENSURE_REGISTERED(QuasiOmniDirectPathBeamforming);
27 NS_OBJECT_ENSURE_REGISTERED(DirectPathQuasiOmniBeamforming);
28 NS_OBJECT_ENSURE_REGISTERED(OptimalCovMatrixBeamforming);
29 
30 TypeId
32 {
33  static TypeId tid = TypeId("ns3::IdealBeamformingAlgorithm").SetParent<Object>();
34  return tid;
35 }
36 
37 TypeId
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 
54 void
56 {
57  m_beamSearchAngleStep = beamSearchAngleStep;
58 }
59 
60 double
62 {
63  return m_beamSearchAngleStep;
64 }
65 
66 BeamformingVectorPair
67 CellScanBeamforming::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 
215 TypeId
217 {
218  static TypeId tid = TypeId("ns3::CellScanBeamformingAzimuthZenith")
219  .SetParent<IdealBeamformingAlgorithm>()
220  .AddConstructor<CellScanBeamformingAzimuthZenith>();
221 
222  return tid;
223 }
224 
225 BeamformingVectorPair
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 
355 TypeId
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 
372 void
374 {
375  m_beamSearchAngleStep = beamSearchAngleStep;
376 }
377 
378 double
380 {
381  return m_beamSearchAngleStep;
382 }
383 
384 BeamformingVectorPair
385 CellScanQuasiOmniBeamforming::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 
489 TypeId
491 {
492  static TypeId tid = TypeId("ns3::DirectPathBeamforming")
493  .SetParent<IdealBeamformingAlgorithm>()
494  .AddConstructor<DirectPathBeamforming>();
495  return tid;
496 }
497 
498 BeamformingVectorPair
499 DirectPathBeamforming::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 
526 TypeId
528 {
529  static TypeId tid = TypeId("ns3::QuasiOmniDirectPathBeamforming")
530  .SetParent<DirectPathBeamforming>()
531  .AddConstructor<QuasiOmniDirectPathBeamforming>();
532  return tid;
533 }
534 
535 BeamformingVectorPair
536 QuasiOmniDirectPathBeamforming::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 
560 TypeId
562 {
563  static TypeId tid = TypeId("ns3::DirectPathQuasiOmniBeamforming")
564  .SetParent<DirectPathBeamforming>()
565  .AddConstructor<DirectPathQuasiOmniBeamforming>();
566  return tid;
567 }
568 
569 BeamformingVectorPair
570 DirectPathQuasiOmniBeamforming::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);
584  BeamformingVector ueBfv = {CreateQuasiOmniBfv(ueAntenna), OMNI_BEAM_ID};
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 
597 TypeId
599 {
600  static TypeId tid = TypeId("ns3::OptimalCovMatrixBeamforming")
601  .SetParent<IdealBeamformingAlgorithm>()
602  .AddConstructor<OptimalCovMatrixBeamforming>();
603 
604  return tid;
605 }
606 
607 BeamformingVectorPair
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 
616 } // namespace ns3
Representation of a beam id.
Definition: beam-id.h:28
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.
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:11
PhasedArrayModel::ComplexVector CreateQuasiOmniBfv(const Ptr< const UniformPlanarArray > &antenna)
Create a quasi omni beamforming vector.