A Discrete-Event Network Simulator
API
three-gpp-spectrum-propagation-loss-model.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2015, NYU WIRELESS, Tandon School of Engineering,
4  * New York University
5  * Copyright (c) 2019 SIGNET Lab, Department of Information Engineering,
6  * University of Padova
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation;
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  */
22 
23 #include "ns3/log.h"
25 #include "ns3/net-device.h"
26 #include "ns3/three-gpp-antenna-array-model.h"
27 #include "ns3/node.h"
28 #include "ns3/channel-condition-model.h"
29 #include "ns3/double.h"
30 #include "ns3/string.h"
31 #include "ns3/simulator.h"
32 #include "ns3/pointer.h"
33 #include <map>
34 
35 namespace ns3 {
36 
37 NS_LOG_COMPONENT_DEFINE ("ThreeGppSpectrumPropagationLossModel");
38 
39 NS_OBJECT_ENSURE_REGISTERED (ThreeGppSpectrumPropagationLossModel);
40 
42 {
43  NS_LOG_FUNCTION (this);
44 }
45 
47 {
48  NS_LOG_FUNCTION (this);
49 }
50 
51 void
53 {
54  m_deviceAntennaMap.clear ();
55  m_longTermMap.clear ();
56  m_channelModel->Dispose ();
57  m_channelModel = nullptr;
58 }
59 
60 TypeId
62 {
63  static TypeId tid = TypeId ("ns3::ThreeGppSpectrumPropagationLossModel")
65  .SetGroupName ("Spectrum")
66  .AddConstructor<ThreeGppSpectrumPropagationLossModel> ()
67  .AddAttribute("ChannelModel",
68  "The channel model. It needs to implement the MatrixBasedChannelModel interface",
69  StringValue("ns3::ThreeGppChannelModel"),
72  MakePointerChecker<MatrixBasedChannelModel> ())
73  ;
74  return tid;
75 }
76 
77 void
79 {
81 }
82 
85 {
86  return m_channelModel;
87 }
88 
89 void
91 {
92  NS_ASSERT_MSG (m_deviceAntennaMap.find (n->GetNode ()->GetId ()) == m_deviceAntennaMap.end (), "Device is already present in the map");
93  m_deviceAntennaMap.insert (std::make_pair (n->GetNode ()->GetId (), a));
94 }
95 
96 double
98 {
99  DoubleValue freq;
100  m_channelModel->GetAttribute ("Frequency", freq);
101  return freq.Get ();
102 }
103 
104 void
106 {
107  m_channelModel->SetAttribute (name, value);
108 }
109 
110 void
112 {
113  m_channelModel->GetAttribute (name, value);
114 }
115 
120 {
121  NS_LOG_FUNCTION (this);
122 
123  uint16_t sAntenna = static_cast<uint16_t> (sW.size ());
124  uint16_t uAntenna = static_cast<uint16_t> (uW.size ());
125 
126  NS_LOG_DEBUG ("CalcLongTerm with sAntenna " << sAntenna << " uAntenna " << uAntenna);
127  //store the long term part to reduce computation load
128  //only the small scale fading needs to be updated if the large scale parameters and antenna weights remain unchanged.
130  uint8_t numCluster = static_cast<uint8_t> (params->m_channel[0][0].size ());
131 
132  for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++)
133  {
134  std::complex<double> txSum (0,0);
135  for (uint16_t sIndex = 0; sIndex < sAntenna; sIndex++)
136  {
137  std::complex<double> rxSum (0,0);
138  for (uint16_t uIndex = 0; uIndex < uAntenna; uIndex++)
139  {
140  rxSum = rxSum + uW[uIndex] * params->m_channel[uIndex][sIndex][cIndex];
141  }
142  txSum = txSum + sW[sIndex] * rxSum;
143  }
144  longTerm.push_back (txSum);
145  }
146  return longTerm;
147 }
148 
153  const ns3::Vector &sSpeed, const ns3::Vector &uSpeed) const
154 {
155  NS_LOG_FUNCTION (this);
156 
157  Ptr<SpectrumValue> tempPsd = Copy<SpectrumValue> (txPsd);
158 
159  //channel[rx][tx][cluster]
160  uint8_t numCluster = static_cast<uint8_t> (params->m_channel[0][0].size ());
161 
162  // compute the doppler term
163  // NOTE the update of Doppler is simplified by only taking the center angle of
164  // each cluster in to consideration.
165  double slotTime = Simulator::Now ().GetSeconds ();
167  for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++)
168  {
169  //cluster angle angle[direction][n],where, direction = 0(aoa), 1(zoa).
170  // TODO should I include the "alfa" term for the Doppler of delayed paths?
171  double temp_doppler = 2 * M_PI * ((sin (params->m_angle[MatrixBasedChannelModel::ZOA_INDEX][cIndex] * M_PI / 180) * cos (params->m_angle[MatrixBasedChannelModel::AOA_INDEX][cIndex] * M_PI / 180) * uSpeed.x
172  + sin (params->m_angle[MatrixBasedChannelModel::ZOA_INDEX][cIndex] * M_PI / 180) * sin (params->m_angle[MatrixBasedChannelModel::AOA_INDEX][cIndex] * M_PI / 180) * uSpeed.y
173  + cos (params->m_angle[MatrixBasedChannelModel::ZOA_INDEX][cIndex] * M_PI / 180) * uSpeed.z)
174  + (sin (params->m_angle[MatrixBasedChannelModel::ZOD_INDEX][cIndex] * M_PI / 180) * cos (params->m_angle[MatrixBasedChannelModel::AOD_INDEX][cIndex] * M_PI / 180) * sSpeed.x
175  + sin (params->m_angle[MatrixBasedChannelModel::ZOD_INDEX][cIndex] * M_PI / 180) * sin (params->m_angle[MatrixBasedChannelModel::AOD_INDEX][cIndex] * M_PI / 180) * sSpeed.y
176  + cos (params->m_angle[MatrixBasedChannelModel::ZOD_INDEX][cIndex] * M_PI / 180) * sSpeed.z))
177  * slotTime * GetFrequency () / 3e8;
178  doppler.push_back (exp (std::complex<double> (0, temp_doppler)));
179  }
180 
181  // apply the doppler term and the propagation delay to the long term component
182  // to obtain the beamforming gain
183  auto vit = tempPsd->ValuesBegin (); // psd iterator
184  auto sbit = tempPsd->ConstBandsBegin(); // band iterator
185  while (vit != tempPsd->ValuesEnd ())
186  {
187  std::complex<double> subsbandGain (0.0,0.0);
188  if ((*vit) != 0.00)
189  {
190  double fsb = (*sbit).fc; // center frequency of the sub-band
191  for (uint8_t cIndex = 0; cIndex < numCluster; cIndex++)
192  {
193  double delay = -2 * M_PI * fsb * (params->m_delay[cIndex]);
194  subsbandGain = subsbandGain + longTerm[cIndex] * doppler[cIndex] * exp (std::complex<double> (0, delay));
195  }
196  *vit = (*vit) * (norm (subsbandGain));
197  }
198  vit++;
199  sbit++;
200  }
201  return tempPsd;
202 }
203 
209 {
210  ThreeGppAntennaArrayModel::ComplexVector longTerm; // vector containing the long term component for each cluster
211 
212  // check if the channel matrix was generated considering a as the s-node and
213  // b as the u-node or viceversa
215  if (!channelMatrix->IsReverse (aId, bId))
216  {
217  sW = aW;
218  uW = bW;
219  }
220  else
221  {
222  sW = bW;
223  uW = aW;
224  }
225 
226  // compute the long term key, the key is unique for each tx-rx pair
227  uint32_t x1 = std::min (aId, bId);
228  uint32_t x2 = std::max (aId, bId);
229  uint32_t longTermId = MatrixBasedChannelModel::GetKey (x1, x2);
230 
231  bool update = false; // indicates whether the long term has to be updated
232  bool notFound = false; // indicates if the long term has not been computed yet
233 
234  // look for the long term in the map and check if it is valid
235  if (m_longTermMap.find (longTermId) != m_longTermMap.end ())
236  {
237  NS_LOG_DEBUG ("found the long term component in the map");
238  longTerm = m_longTermMap[longTermId]->m_longTerm;
239 
240  // check if the channel matrix has been updated
241  // or the s beam has been changed
242  // or the u beam has been changed
243  update = (m_longTermMap[longTermId]->m_channel->m_generatedTime != channelMatrix->m_generatedTime
244  || m_longTermMap[longTermId]->m_sW != sW
245  || m_longTermMap[longTermId]->m_uW != uW);
246 
247  }
248  else
249  {
250  NS_LOG_DEBUG ("long term component NOT found");
251  notFound = true;
252  }
253 
254  if (update || notFound)
255  {
256  NS_LOG_DEBUG ("compute the long term");
257  // compute the long term component
258  longTerm = CalcLongTerm (channelMatrix, sW, uW);
259 
260  // store the long term
261  Ptr<LongTerm> longTermItem = Create<LongTerm> ();
262  longTermItem->m_longTerm = longTerm;
263  longTermItem->m_channel = channelMatrix;
264  longTermItem->m_sW = sW;
265  longTermItem->m_uW = uW;
266 
267  m_longTermMap[longTermId] = longTermItem;
268  }
269 
270  return longTerm;
271 }
272 
276  Ptr<const MobilityModel> b) const
277 {
278  NS_LOG_FUNCTION (this);
279  uint32_t aId = a->GetObject<Node> ()->GetId (); // id of the node a
280  uint32_t bId = b->GetObject<Node> ()->GetId (); // id of the node b
281 
282  NS_ASSERT (aId != bId);
283  NS_ASSERT_MSG (a->GetDistanceFrom (b) > 0.0, "The position of a and b devices cannot be the same");
284 
285  Ptr<SpectrumValue> rxPsd = Copy<SpectrumValue> (txPsd);
286 
287  // retrieve the antenna of device a
288  NS_ASSERT_MSG (m_deviceAntennaMap.find (aId) != m_deviceAntennaMap.end (), "Antenna not found for node " << aId);
290  NS_LOG_DEBUG ("a node " << a->GetObject<Node> () << " antenna " << aAntenna);
291 
292  // retrieve the antenna of the device b
293  NS_ASSERT_MSG (m_deviceAntennaMap.find (bId) != m_deviceAntennaMap.end (), "Antenna not found for device " << bId);
295  NS_LOG_DEBUG ("b node " << bId << " antenna " << bAntenna);
296 
297  if (aAntenna->IsOmniTx () || bAntenna->IsOmniTx () )
298  {
299  NS_LOG_LOGIC ("Omni transmission, do nothing.");
300  return rxPsd;
301  }
302 
303  Ptr<const MatrixBasedChannelModel::ChannelMatrix> channelMatrix = m_channelModel->GetChannel (a, b, aAntenna, bAntenna);
304 
305  // get the precoding and combining vectors
306  ThreeGppAntennaArrayModel::ComplexVector aW = aAntenna->GetBeamformingVector ();
307  ThreeGppAntennaArrayModel::ComplexVector bW = bAntenna->GetBeamformingVector ();
308 
309  // retrieve the long term component
310  ThreeGppAntennaArrayModel::ComplexVector longTerm = GetLongTerm (aId, bId, channelMatrix, aW, bW);
311 
312  // apply the beamforming gain
313  rxPsd = CalcBeamformingGain (rxPsd, longTerm, channelMatrix, a->GetVelocity (), b->GetVelocity ());
314 
315  return rxPsd;
316 }
317 
318 
319 } // namespace ns3
void SetChannelModel(Ptr< MatrixBasedChannelModel > channel)
Set the channel model object.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
std::unordered_map< uint32_t, Ptr< const LongTerm > > m_longTermMap
map containing the long term components
std::vector< std::complex< double > > ComplexVector
type definition for complex vectors
ThreeGppAntennaArrayModel::ComplexVector CalcLongTerm(Ptr< const MatrixBasedChannelModel::ChannelMatrix > channelMatrix, const ThreeGppAntennaArrayModel::ComplexVector &sW, const ThreeGppAntennaArrayModel::ComplexVector &uW) const
Computes the long term component.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Hold variables of type string.
Definition: string.h:41
#define min(a, b)
Definition: 80211b.c:42
Hold a value for an Attribute.
Definition: attribute.h:68
ThreeGppAntennaArrayModel::ComplexVector GetLongTerm(uint32_t aId, uint32_t bId, Ptr< const MatrixBasedChannelModel::ChannelMatrix > channelMatrix, const ThreeGppAntennaArrayModel::ComplexVector &aW, const ThreeGppAntennaArrayModel::ComplexVector &bW) const
Looks for the long term component in m_longTermMap.
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
ThreeGppAntennaArrayModel::ComplexVector m_sW
the beamforming vector for the node s used to compute the long term
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Values::iterator ValuesEnd()
ThreeGppAntennaArrayModel::ComplexVector m_uW
the beamforming vector for the node u used to compute the long term
channel
Definition: third.py:92
static const uint8_t AOD_INDEX
index of the AOD value in the m_angle array
std::unordered_map< uint32_t, Ptr< const ThreeGppAntennaArrayModel > > m_deviceAntennaMap
map containig the <node, antenna> associations
Ptr< MatrixBasedChannelModel > GetChannelModel() const
Get the channel model object.
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: pointer.h:227
#define max(a, b)
Definition: 80211b.c:43
Ptr< SpectrumValue > CalcBeamformingGain(Ptr< SpectrumValue > txPsd, ThreeGppAntennaArrayModel::ComplexVector longTerm, Ptr< const MatrixBasedChannelModel::ChannelMatrix > params, const Vector &sSpeed, const Vector &uSpeed) const
Computes the beamforming gain and applies it to the tx PSD.
void AddDevice(Ptr< NetDevice > n, Ptr< const ThreeGppAntennaArrayModel > a)
Add a device-antenna pair.
double GetFrequency() const
Get the operating frequency.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
static const uint8_t ZOA_INDEX
index of the ZOA value in the m_angle array
double Get(void) const
Definition: double.cc:35
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ThreeGppAntennaArrayModel::ComplexVector m_longTerm
vector containing the long term component for each cluster
static constexpr uint32_t GetKey(uint32_t x1, uint32_t x2)
Calculate the channel key using the Cantor function.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
Values::iterator ValuesBegin()
Ptr< const MatrixBasedChannelModel::ChannelMatrix > m_channel
pointer to the channel matrix used to compute the long term
A network Node.
Definition: node.h:56
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
static const uint8_t AOA_INDEX
index of the AOA value in the m_angle array
const double norm
Normalization to obtain randoms on [0,1).
Definition: rng-stream.cc:64
Ptr< MatrixBasedChannelModel > m_channelModel
the model to generate the channel matrix
void GetChannelModelAttribute(const std::string &name, AttributeValue &value) const
Returns the value of an attribute belonging to the associated MatrixBasedChannelModel instance...
Ptr< SpectrumValue > DoCalcRxPowerSpectralDensity(Ptr< const SpectrumValue > txPsd, Ptr< const MobilityModel > a, Ptr< const MobilityModel > b) const override
Computes the received PSD.
spectrum-aware propagation loss model
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
void SetChannelModelAttribute(const std::string &name, const AttributeValue &value)
Sets the value of an attribute belonging to the associated MatrixBasedChannelModel instance...
Bands::const_iterator ConstBandsBegin() const
static const uint8_t ZOD_INDEX
index of the ZOD value in the m_angle array