5G-LENA  nr-v3.0-29-g83cc959
The 5G/NR module for the ns-3 simulator
beamforming-vector.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 "beamforming-vector.h"
8 
9 #include <ns3/angles.h>
10 #include <ns3/uinteger.h>
11 
12 namespace ns3
13 {
14 
15 PhasedArrayModel::ComplexVector
16 CreateQuasiOmniBfv(const Ptr<const UniformPlanarArray>& antenna)
17 {
18  auto antennaRows = antenna->GetNumRows();
19  auto antennaColumns = antenna->GetNumColumns();
20  auto numElemsPerPort = antenna->GetNumElemsPerPort();
21 
22  double power = 1 / sqrt(numElemsPerPort);
23  size_t numPolarizations = antenna->IsDualPol() ? 2 : 1;
24 
25  PhasedArrayModel::ComplexVector omni(antennaRows * antennaColumns * numPolarizations);
26  uint16_t bfIndex = 0;
27  for (size_t pol = 0; pol < numPolarizations; pol++)
28  {
29  for (uint32_t ind = 0; ind < antennaRows; ind++)
30  {
31  std::complex<double> c = 0.0;
32  if (antennaRows % 2 == 0)
33  {
34  c = exp(std::complex<double>(0, M_PI * ind * ind / antennaRows));
35  }
36  else
37  {
38  c = exp(std::complex<double>(0, M_PI * ind * (ind + 1) / antennaRows));
39  }
40  for (uint32_t ind2 = 0; ind2 < antennaColumns; ind2++)
41  {
42  std::complex<double> d = 0.0;
43  if (antennaColumns % 2 == 0)
44  {
45  d = exp(std::complex<double>(0, M_PI * ind2 * ind2 / antennaColumns));
46  }
47  else
48  {
49  d = exp(std::complex<double>(0, M_PI * ind2 * (ind2 + 1) / antennaColumns));
50  }
51  omni[bfIndex] = (c * d * power);
52  bfIndex++;
53  }
54  }
55  }
56  return omni;
57 }
58 
59 PhasedArrayModel::ComplexVector
60 CreateDirectionalBfv(const Ptr<const UniformPlanarArray>& antenna,
61  uint16_t sector,
62  double elevation)
63 {
64  UintegerValue uintValueNumRows;
65  antenna->GetAttribute("NumRows", uintValueNumRows);
66 
67  double hAngle_radian =
68  M_PI * (static_cast<double>(sector) / static_cast<double>(uintValueNumRows.Get())) -
69  0.5 * M_PI;
70  double vAngle_radian = elevation * M_PI / 180;
71  uint16_t size = antenna->GetNumElems();
72  PhasedArrayModel::ComplexVector tempVector(size);
73  auto numAnalogBeamElements = (antenna->GetVElemsPerPort() * antenna->GetHElemsPerPort());
74  auto power = 1.0 / sqrt(numAnalogBeamElements);
75  for (auto ind = 0; ind < size; ind++)
76  {
77  Vector loc = antenna->GetElementLocation(ind);
78  double phase =
79  -2 * M_PI *
80  (sin(vAngle_radian) * cos(hAngle_radian) * loc.x +
81  sin(vAngle_radian) * sin(hAngle_radian) * loc.y + cos(vAngle_radian) * loc.z);
82  tempVector[ind] = (exp(std::complex<double>(0, phase)) * power);
83  }
84  return tempVector;
85 }
86 
87 PhasedArrayModel::ComplexVector
88 CreateDirectionalBfvAz(const Ptr<const UniformPlanarArray>& antenna, double azimuth, double zenith)
89 {
90  UintegerValue uintValueNumRows;
91  antenna->GetAttribute("NumRows", uintValueNumRows);
92 
93  double hAngle_radian = azimuth * M_PI / 180;
94  double vAngle_radian = zenith * M_PI / 180;
95  uint16_t size = antenna->GetNumElems();
96  double power = 1 / sqrt(size);
97  PhasedArrayModel::ComplexVector tempVector(size);
98  if (size == 1)
99  {
100  tempVector[0] = power; // single AE, no BF
101  }
102  else
103  {
104  for (auto ind = 0; ind < size; ind++)
105  {
106  Vector loc = antenna->GetElementLocation(ind);
107  double phase =
108  -2 * M_PI *
109  (sin(vAngle_radian) * cos(hAngle_radian) * loc.x +
110  sin(vAngle_radian) * sin(hAngle_radian) * loc.y + cos(vAngle_radian) * loc.z);
111  tempVector[ind] = exp(std::complex<double>(0, phase)) * power;
112  }
113  }
114  return tempVector;
115 }
116 
117 PhasedArrayModel::ComplexVector
118 CreateDirectPathBfv(const Ptr<MobilityModel>& a,
119  const Ptr<MobilityModel>& b,
120  const Ptr<const UniformPlanarArray>& antenna)
121 {
122  // retrieve the position of the two devices
123  Vector aPos = a->GetPosition();
124  Vector bPos = b->GetPosition();
125 
126  // compute the azimuth and the elevation angles
127  Angles completeAngle(bPos, aPos);
128 
129  double hAngleRadian = completeAngle.GetAzimuth();
130 
131  double vAngleRadian = completeAngle.GetInclination(); // the elevation angle
132 
133  // retrieve the number of antenna elements
134  int totNoArrayElements = antenna->GetNumElems();
135  auto numElemsPerPort = antenna->GetNumElemsPerPort();
136 
137  // the total power is divided equally among the antenna elements
138  double power = 1 / sqrt(numElemsPerPort);
139 
140  PhasedArrayModel::ComplexVector antennaWeights(totNoArrayElements);
141  // compute the antenna weights
142  for (int ind = 0; ind < totNoArrayElements; ind++)
143  {
144  Vector loc = antenna->GetElementLocation(ind);
145  double phase = -2 * M_PI *
146  (sin(vAngleRadian) * cos(hAngleRadian) * loc.x +
147  sin(vAngleRadian) * sin(hAngleRadian) * loc.y + cos(vAngleRadian) * loc.z);
148  antennaWeights[ind] = exp(std::complex<double>(0, phase)) * power;
149  }
150 
151  return antennaWeights;
152 }
153 
154 } // namespace ns3
PhasedArrayModel::ComplexVector CreateDirectionalBfvAz(const Ptr< const UniformPlanarArray > &antenna, double azimuth, double zenith)
Creates a beamforming vector for a given azimuth and zenith.
PhasedArrayModel::ComplexVector CreateQuasiOmniBfv(const Ptr< const UniformPlanarArray > &antenna)
Create a quasi omni beamforming vector.
PhasedArrayModel::ComplexVector CreateDirectionalBfv(const Ptr< const UniformPlanarArray > &antenna, uint16_t sector, double elevation)
Creates a beamforming vector for a given sector and elevation.