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