A Discrete-Event Network Simulator
API
three-gpp-spectrum-propagation-loss-model.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, NYU WIRELESS, Tandon School of Engineering,
3  * New York University
4  * Copyright (c) 2019 SIGNET Lab, Department of Information Engineering,
5  * University of Padova
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation;
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
23 
26 
27 #include "ns3/double.h"
28 #include "ns3/log.h"
29 #include "ns3/net-device.h"
30 #include "ns3/node.h"
31 #include "ns3/pointer.h"
32 #include "ns3/simulator.h"
33 #include "ns3/string.h"
34 
35 #include <map>
36 
37 namespace ns3
38 {
39 
40 NS_LOG_COMPONENT_DEFINE("ThreeGppSpectrumPropagationLossModel");
41 
42 NS_OBJECT_ENSURE_REGISTERED(ThreeGppSpectrumPropagationLossModel);
43 
45 {
46  NS_LOG_FUNCTION(this);
47 }
48 
50 {
51  NS_LOG_FUNCTION(this);
52 }
53 
54 void
56 {
57  m_longTermMap.clear();
58  m_channelModel->Dispose();
59  m_channelModel = nullptr;
60 }
61 
62 TypeId
64 {
65  static TypeId tid =
66  TypeId("ns3::ThreeGppSpectrumPropagationLossModel")
68  .SetGroupName("Spectrum")
69  .AddConstructor<ThreeGppSpectrumPropagationLossModel>()
70  .AddAttribute(
71  "ChannelModel",
72  "The channel model. It needs to implement the MatrixBasedChannelModel interface",
73  StringValue("ns3::ThreeGppChannelModel"),
76  MakePointerChecker<MatrixBasedChannelModel>());
77  return tid;
78 }
79 
80 void
82 {
84 }
85 
88 {
89  return m_channelModel;
90 }
91 
92 double
94 {
95  DoubleValue freq;
96  m_channelModel->GetAttribute("Frequency", freq);
97  return freq.Get();
98 }
99 
100 void
102  const AttributeValue& value)
103 {
104  m_channelModel->SetAttribute(name, value);
105 }
106 
107 void
109  AttributeValue& value) const
110 {
111  m_channelModel->GetAttribute(name, value);
112 }
113 
118  Ptr<const PhasedArrayModel> uAnt) const
119 {
120  NS_LOG_FUNCTION(this);
121 
122  const PhasedArrayModel::ComplexVector& sW = sAnt->GetBeamformingVectorRef();
123  const PhasedArrayModel::ComplexVector& uW = uAnt->GetBeamformingVectorRef();
124  size_t sAntNumElems = sW.GetSize();
125  size_t uAntNumElems = uW.GetSize();
126  NS_ASSERT(uAntNumElems == params->m_channel.GetNumRows());
127  NS_ASSERT(sAntNumElems == params->m_channel.GetNumCols());
128  NS_LOG_DEBUG("CalcLongTerm with " << uW.GetSize() << " u antenna elements and " << sW.GetSize()
129  << " s antenna elements, and with "
130  << " s ports: " << sAnt->GetNumPorts()
131  << " u ports: " << uAnt->GetNumPorts());
132  NS_ASSERT_MSG((sAnt != nullptr) && (uAnt != nullptr), "Improper call to the method");
133  size_t numClusters = params->m_channel.GetNumPages();
134  // create and initialize the size of the longTerm 3D matrix
136  Create<MatrixBasedChannelModel::Complex3DVector>(uAnt->GetNumPorts(),
137  sAnt->GetNumPorts(),
138  numClusters);
139  // Calculate long term uW * Husn * sW, the result is a matrix
140  // with the dimensions #uPorts, #sPorts, #cluster
141  for (auto sPortIdx = 0; sPortIdx < sAnt->GetNumPorts(); sPortIdx++)
142  {
143  for (auto uPortIdx = 0; uPortIdx < uAnt->GetNumPorts(); uPortIdx++)
144  {
145  for (size_t cIndex = 0; cIndex < numClusters; cIndex++)
146  {
147  longTerm->Elem(uPortIdx, sPortIdx, cIndex) =
148  CalculateLongTermComponent(params, sAnt, uAnt, sPortIdx, uPortIdx, cIndex);
149  }
150  }
151  }
152  return longTerm;
153 }
154 
155 std::complex<double>
160  uint16_t sPortIdx,
161  uint16_t uPortIdx,
162  uint16_t cIndex) const
163 {
164  NS_LOG_FUNCTION(this);
165  const PhasedArrayModel::ComplexVector& sW = sAnt->GetBeamformingVectorRef();
166  const PhasedArrayModel::ComplexVector& uW = uAnt->GetBeamformingVectorRef();
167  auto sPortElems = sAnt->GetNumElemsPerPort();
168  auto uPortElems = uAnt->GetNumElemsPerPort();
169  auto startS = sAnt->ArrayIndexFromPortIndex(sPortIdx, 0);
170  auto startU = uAnt->ArrayIndexFromPortIndex(uPortIdx, 0);
171  std::complex<double> txSum(0, 0);
172  // limiting multiplication operations to the port location
173  auto sIndex = startS;
174  // The sub-array partition model is adopted for TXRU virtualization,
175  // as described in Section 5.2.2 of 3GPP TR 36.897,
176  // and so equal beam weights are used for all the ports.
177  // Support of the full-connection model for TXRU virtualization would need extensions.
178  for (size_t tIndex = 0; tIndex < sPortElems; tIndex++, sIndex++)
179  {
180  std::complex<double> rxSum(0, 0);
181  auto uIndex = startU;
182  for (size_t rIndex = 0; rIndex < uPortElems; rIndex++, uIndex++)
183  {
184  rxSum += uW[uIndex - startU] * params->m_channel(uIndex, sIndex, cIndex);
185  auto testV = (rIndex % uAnt->GetHElemsPerPort());
186  auto ptInc = uAnt->GetHElemsPerPort() - 1;
187  if (testV == ptInc)
188  {
189  auto incVal = uAnt->GetNumColumns() - uAnt->GetHElemsPerPort();
190  uIndex += incVal; // Increment by a factor to reach next column in a port
191  }
192  }
193 
194  txSum += sW[sIndex - startS] * rxSum;
195  auto testV = (tIndex % sAnt->GetHElemsPerPort());
196  auto ptInc = sAnt->GetHElemsPerPort() - 1;
197  if (testV == ptInc)
198  {
199  size_t incVal = sAnt->GetNumColumns() - sAnt->GetHElemsPerPort();
200  sIndex += incVal; // Increment by a factor to reach next column in a port
201  }
202  }
203  return txSum;
204 }
205 
212  const Vector& sSpeed,
213  const ns3::Vector& uSpeed,
214  uint8_t numTxPorts,
215  uint8_t numRxPorts,
216  bool isReverse) const
217 
218 {
219  NS_LOG_FUNCTION(this);
220  Ptr<SpectrumSignalParameters> rxParams = params->Copy();
221  size_t numCluster = channelMatrix->m_channel.GetNumPages();
222  // compute the doppler term
223  // NOTE the update of Doppler is simplified by only taking the center angle of
224  // each cluster in to consideration.
225  double slotTime = Simulator::Now().GetSeconds();
226  double factor = 2 * M_PI * slotTime * GetFrequency() / 3e8;
227  PhasedArrayModel::ComplexVector doppler(numCluster);
228 
229  // Make sure that all the structures that are passed to this function
230  // are of the correct dimensions before using the operator [].
231  NS_ASSERT(numCluster <= channelParams->m_alpha.size());
232  NS_ASSERT(numCluster <= channelParams->m_D.size());
233  NS_ASSERT(numCluster <= channelParams->m_angle[MatrixBasedChannelModel::ZOA_INDEX].size());
234  NS_ASSERT(numCluster <= channelParams->m_angle[MatrixBasedChannelModel::ZOD_INDEX].size());
235  NS_ASSERT(numCluster <= channelParams->m_angle[MatrixBasedChannelModel::AOA_INDEX].size());
236  NS_ASSERT(numCluster <= channelParams->m_angle[MatrixBasedChannelModel::AOD_INDEX].size());
237  NS_ASSERT(numCluster <= longTerm->GetNumPages());
238 
239  // check if channelParams structure is generated in direction s-to-u or u-to-s
240  bool isSameDirection = (channelParams->m_nodeIds == channelMatrix->m_nodeIds);
241 
246 
247  // if channel params is generated in the same direction in which we
248  // generate the channel matrix, angles and zenith of departure and arrival are ok,
249  // just set them to corresponding variable that will be used for the generation
250  // of channel matrix, otherwise we need to flip angles and zeniths of departure and arrival
251  if (isSameDirection)
252  {
253  zoa = channelParams->m_angle[MatrixBasedChannelModel::ZOA_INDEX];
254  zod = channelParams->m_angle[MatrixBasedChannelModel::ZOD_INDEX];
255  aoa = channelParams->m_angle[MatrixBasedChannelModel::AOA_INDEX];
256  aod = channelParams->m_angle[MatrixBasedChannelModel::AOD_INDEX];
257  }
258  else
259  {
260  zod = channelParams->m_angle[MatrixBasedChannelModel::ZOA_INDEX];
261  zoa = channelParams->m_angle[MatrixBasedChannelModel::ZOD_INDEX];
262  aod = channelParams->m_angle[MatrixBasedChannelModel::AOA_INDEX];
263  aoa = channelParams->m_angle[MatrixBasedChannelModel::AOD_INDEX];
264  }
265 
266  for (size_t cIndex = 0; cIndex < numCluster; cIndex++)
267  {
268  // Compute alpha and D as described in 3GPP TR 37.885 v15.3.0, Sec. 6.2.3
269  // These terms account for an additional Doppler contribution due to the
270  // presence of moving objects in the surrounding environment, such as in
271  // vehicular scenarios.
272  // This contribution is applied only to the delayed (reflected) paths and
273  // must be properly configured by setting the value of
274  // m_vScatt, which is defined as "maximum speed of the vehicle in the
275  // layout".
276  // By default, m_vScatt is set to 0, so there is no additional Doppler
277  // contribution.
278 
279  double alpha = channelParams->m_alpha[cIndex];
280  double D = channelParams->m_D[cIndex];
281 
282  // cluster angle angle[direction][n], where direction = 0(aoa), 1(zoa).
283  double tempDoppler =
284  factor * ((sin(zoa[cIndex] * M_PI / 180) * cos(aoa[cIndex] * M_PI / 180) * uSpeed.x +
285  sin(zoa[cIndex] * M_PI / 180) * sin(aoa[cIndex] * M_PI / 180) * uSpeed.y +
286  cos(zoa[cIndex] * M_PI / 180) * uSpeed.z) +
287  (sin(zod[cIndex] * M_PI / 180) * cos(aod[cIndex] * M_PI / 180) * sSpeed.x +
288  sin(zod[cIndex] * M_PI / 180) * sin(aod[cIndex] * M_PI / 180) * sSpeed.y +
289  cos(zod[cIndex] * M_PI / 180) * sSpeed.z) +
290  2 * alpha * D);
291  doppler[cIndex] = std::complex<double>(cos(tempDoppler), sin(tempDoppler));
292  }
293 
294  NS_ASSERT(numCluster <= doppler.GetSize());
295 
296  // set the channel matrix
297  rxParams->spectrumChannelMatrix = GenSpectrumChannelMatrix(rxParams->psd,
298  longTerm,
299  channelMatrix,
300  channelParams,
301  doppler,
302  numTxPorts,
303  numRxPorts,
304  isReverse);
305 
306  // The precoding matrix is not set
307  if (!rxParams->precodingMatrix)
308  {
309  // Update rxParams->Psd.
310  // Compute RX PSD from the channel matrix
311  auto vit = rxParams->psd->ValuesBegin(); // psd iterator
312  size_t rbIdx = 0;
313  while (vit != rxParams->psd->ValuesEnd())
314  {
315  // Calculate PSD for the first antenna port (correct for SISO)
316  *vit = std::norm(rxParams->spectrumChannelMatrix->Elem(0, 0, rbIdx));
317  vit++;
318  rbIdx++;
319  }
320  }
321  else
322  {
323  NS_ASSERT_MSG(rxParams->psd->GetValuesN() == rxParams->spectrumChannelMatrix->GetNumPages(),
324  "RX PSD and the spectrum channel matrix should have the same number of RBs ");
325  // Calculate RX PSD from the spectrum channel matrix, H and
326  // the precoding matrix, P as:
327  // PSD = (H*P)^h * (H*P),
328  // where the dimensions are:
329  // H (rxPorts,txPorts,numRbs) x P (txPorts,txStreams, numRbs) =
330  // HxP (rxPorts,txStreams, numRbs)
332  *rxParams->spectrumChannelMatrix * (*rxParams->precodingMatrix);
333  // (HxP)^h dimensions are (txStreams, rxPorts, numRbs)
335 
336  // Finally, (HxP)^h x (HxP) = PSD (txStreams, txStreams, numRbs)
338  // Update rxParams->Psd
339  for (uint32_t rbIdx = 0; rbIdx < rxParams->psd->GetValuesN(); ++rbIdx)
340  {
341  (*rxParams->psd)[rbIdx] = 0.0;
342 
343  for (size_t txStream = 0; txStream < psd.GetNumRows(); ++txStream)
344  {
345  (*rxParams->psd)[rbIdx] += std::real(psd(txStream, txStream, rbIdx));
346  }
347  }
348  }
349  return rxParams;
350 }
351 
354  Ptr<SpectrumValue> inPsd,
359  uint8_t numTxPorts,
360  uint8_t numRxPorts,
361  bool isReverse) const
362 {
363  size_t numCluster = channelMatrix->m_channel.GetNumPages();
364  auto numRb = inPsd->GetValuesN();
365 
366  auto directionalLongTerm = isReverse ? longTerm->Transpose() : (*longTerm);
367 
369  Create<MatrixBasedChannelModel::Complex3DVector>(numRxPorts, numTxPorts, (uint16_t)numRb);
370 
371  // If "params" (ChannelMatrix) and longTerm were computed for the reverse direction (e.g. this
372  // is a DL transmission but params and longTerm were last updated during UL), then the elements
373  // in longTerm start from different offsets.
374 
375  auto vit = inPsd->ValuesBegin(); // psd iterator
376  auto sbit = inPsd->ConstBandsBegin(); // band iterator
377  size_t iRb = 0;
378  // Compute the frequency-domain channel matrix
379  while (vit != inPsd->ValuesEnd())
380  {
381  if ((*vit) != 0.00)
382  {
383  double fsb = (*sbit).fc; // center frequency of the sub-band
384  for (auto rxPortIdx = 0; rxPortIdx < numRxPorts; rxPortIdx++)
385  {
386  for (auto txPortIdx = 0; txPortIdx < numTxPorts; txPortIdx++)
387  {
388  std::complex<double> subsbandGain(0.0, 0.0);
389 
390  for (size_t cIndex = 0; cIndex < numCluster; cIndex++)
391  {
392  double delay = -2 * M_PI * fsb * (channelParams->m_delay[cIndex]);
393  subsbandGain += directionalLongTerm(rxPortIdx, txPortIdx, cIndex) *
394  doppler[cIndex] *
395  std::complex<double>(cos(delay), sin(delay));
396  }
397  // Multiply with the square root of the input PSD so that the norm (absolute
398  // value squared) of chanSpct will be the output PSD
399  chanSpct->Elem(rxPortIdx, txPortIdx, iRb) = sqrt(*vit) * subsbandGain;
400  }
401  }
402  }
403  vit++;
404  sbit++;
405  iRb++;
406  }
407  return chanSpct;
408 }
409 
413  Ptr<const PhasedArrayModel> aPhasedArrayModel,
414  Ptr<const PhasedArrayModel> bPhasedArrayModel) const
415 {
417  longTerm; // vector containing the long term component for each cluster
418 
419  // check if the channel matrix was generated considering a as the s-node and
420  // b as the u-node or vice-versa
421  auto isReverse =
422  channelMatrix->IsReverse(aPhasedArrayModel->GetId(), bPhasedArrayModel->GetId());
423  auto sAntenna = isReverse ? bPhasedArrayModel : aPhasedArrayModel;
424  auto uAntenna = isReverse ? aPhasedArrayModel : bPhasedArrayModel;
425 
428  if (!isReverse)
429  {
430  sW = aPhasedArrayModel->GetBeamformingVector();
431  uW = bPhasedArrayModel->GetBeamformingVector();
432  }
433  else
434  {
435  sW = bPhasedArrayModel->GetBeamformingVector();
436  uW = aPhasedArrayModel->GetBeamformingVector();
437  }
438 
439  bool update = false; // indicates whether the long term has to be updated
440  bool notFound = false; // indicates if the long term has not been computed yet
441 
442  // compute the long term key, the key is unique for each tx-rx pair
443  uint64_t longTermId =
444  MatrixBasedChannelModel::GetKey(aPhasedArrayModel->GetId(), bPhasedArrayModel->GetId());
445 
446  // look for the long term in the map and check if it is valid
447  if (m_longTermMap.find(longTermId) != m_longTermMap.end())
448  {
449  NS_LOG_DEBUG("found the long term component in the map");
450  longTerm = m_longTermMap[longTermId]->m_longTerm;
451 
452  // check if the channel matrix has been updated
453  // or the s beam has been changed
454  // or the u beam has been changed
455  update = (m_longTermMap[longTermId]->m_channel->m_generatedTime !=
456  channelMatrix->m_generatedTime ||
457  m_longTermMap[longTermId]->m_sW != sW || m_longTermMap[longTermId]->m_uW != uW);
458  }
459  else
460  {
461  NS_LOG_DEBUG("long term component NOT found");
462  notFound = true;
463  }
464 
465  if (update || notFound)
466  {
467  NS_LOG_DEBUG("compute the long term");
468  // compute the long term component
469  longTerm = CalcLongTerm(channelMatrix, sAntenna, uAntenna);
470  Ptr<LongTerm> longTermItem = Create<LongTerm>();
471  longTermItem->m_longTerm = longTerm;
472  longTermItem->m_channel = channelMatrix;
473  longTermItem->m_sW = std::move(sW);
474  longTermItem->m_uW = std::move(uW);
475  // store the long term to reduce computation load
476  // only the small scale fading needs to be updated if the large scale parameters and antenna
477  // weights remain unchanged.
478  m_longTermMap[longTermId] = longTermItem;
479  }
480 
481  return longTerm;
482 }
483 
486  Ptr<const SpectrumSignalParameters> spectrumSignalParams,
489  Ptr<const PhasedArrayModel> aPhasedArrayModel,
490  Ptr<const PhasedArrayModel> bPhasedArrayModel) const
491 {
492  NS_LOG_FUNCTION(this << spectrumSignalParams << a << b << aPhasedArrayModel
493  << bPhasedArrayModel);
494 
495  if (a->GetPosition() == b->GetPosition())
496  {
497  return spectrumSignalParams->Copy();
498  }
499  uint32_t aId = a->GetObject<Node>()->GetId(); // id of the node a
500  uint32_t bId = b->GetObject<Node>()->GetId(); // id of the node b
501  NS_ASSERT_MSG(aPhasedArrayModel, "Antenna not found for node " << aId);
502  NS_LOG_DEBUG("a node " << aId << " antenna " << aPhasedArrayModel);
503  NS_ASSERT_MSG(bPhasedArrayModel, "Antenna not found for node " << bId);
504  NS_LOG_DEBUG("b node " << bId << " antenna " << bPhasedArrayModel);
505 
507  m_channelModel->GetChannel(a, b, aPhasedArrayModel, bPhasedArrayModel);
509  m_channelModel->GetParams(a, b);
510 
511  // retrieve the long term component
513  GetLongTerm(channelMatrix, aPhasedArrayModel, bPhasedArrayModel);
514 
515  auto isReverse =
516  channelMatrix->IsReverse(aPhasedArrayModel->GetId(), bPhasedArrayModel->GetId());
517 
518  // apply the beamforming gain
519  return CalcBeamformingGain(spectrumSignalParams,
520  longTerm,
521  channelMatrix,
522  channelParams,
523  a->GetVelocity(),
524  b->GetVelocity(),
525  aPhasedArrayModel->GetNumPorts(),
526  bPhasedArrayModel->GetNumPorts(),
527  isReverse);
528 }
529 
530 int64_t
532 {
533  return 0;
534 }
535 
536 } // namespace ns3
Hold a value for an Attribute.
Definition: attribute.h:70
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
double Get() const
Definition: double.cc:37
MatrixArray class inherits ValArray class and provides additional interfaces to ValArray which enable...
Definition: matrix-array.h:83
MatrixArray< T > HermitianTranspose() const
Function that performs the Hermitian transpose of this MatrixArray and returns a new matrix that is t...
std::vector< double > DoubleVector
Type definition for vectors of doubles.
static const uint8_t AOA_INDEX
index of the AOA value in the m_angle array
static const uint8_t ZOD_INDEX
index of the ZOD value in the m_angle array
static const uint8_t AOD_INDEX
index of the AOD value in the m_angle array
static const uint8_t ZOA_INDEX
index of the ZOA value in the m_angle array
static uint64_t GetKey(uint32_t a, uint32_t b)
Generate a unique value for the pair of unsigned integer of 32 bits, where the order does not matter,...
A network Node.
Definition: node.h:57
spectrum-aware propagation loss model that is compatible with PhasedArrayModel type of ns-3 antenna
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
Values::iterator ValuesBegin()
Bands::const_iterator ConstBandsBegin() const
uint32_t GetValuesN() const
Get the number of values stored in the array.
Values::iterator ValuesEnd()
Hold variables of type string.
Definition: string.h:56
void GetChannelModelAttribute(const std::string &name, AttributeValue &value) const
Returns the value of an attribute belonging to the associated MatrixBasedChannelModel instance.
Ptr< SpectrumSignalParameters > DoCalcRxPowerSpectralDensity(Ptr< const SpectrumSignalParameters > spectrumSignalParams, Ptr< const MobilityModel > a, Ptr< const MobilityModel > b, Ptr< const PhasedArrayModel > aPhasedArrayModel, Ptr< const PhasedArrayModel > bPhasedArrayModel) const override
Computes the received PSD.
Ptr< MatrixBasedChannelModel > m_channelModel
the model to generate the channel matrix
Ptr< MatrixBasedChannelModel::Complex3DVector > GenSpectrumChannelMatrix(Ptr< SpectrumValue > inPsd, Ptr< const MatrixBasedChannelModel::Complex3DVector > longTerm, Ptr< const MatrixBasedChannelModel::ChannelMatrix > channelMatrix, Ptr< const MatrixBasedChannelModel::ChannelParams > channelParams, PhasedArrayModel::ComplexVector doppler, uint8_t numTxPorts, uint8_t numRxPorts, bool isReverse) const
Computes the frequency-domain channel matrix with the dimensions numRxPorts*numTxPorts*numRBs.
Ptr< const MatrixBasedChannelModel::Complex3DVector > GetLongTerm(Ptr< const MatrixBasedChannelModel::ChannelMatrix > channelMatrix, Ptr< const PhasedArrayModel > aPhasedArrayModel, Ptr< const PhasedArrayModel > bPhasedArrayModel) const
Looks for the long term component in m_longTermMap.
void SetChannelModel(Ptr< MatrixBasedChannelModel > channel)
Set the channel model object.
Ptr< const MatrixBasedChannelModel::Complex3DVector > CalcLongTerm(Ptr< const MatrixBasedChannelModel::ChannelMatrix > channelMatrix, Ptr< const PhasedArrayModel > sAnt, Ptr< const PhasedArrayModel > uAnt) const
Computes the long term component.
std::unordered_map< uint64_t, Ptr< const LongTerm > > m_longTermMap
map containing the long term components
int64_t DoAssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
void SetChannelModelAttribute(const std::string &name, const AttributeValue &value)
Sets the value of an attribute belonging to the associated MatrixBasedChannelModel instance.
Ptr< MatrixBasedChannelModel > GetChannelModel() const
Get the channel model object.
Ptr< SpectrumSignalParameters > CalcBeamformingGain(Ptr< const SpectrumSignalParameters > params, Ptr< const MatrixBasedChannelModel::Complex3DVector > longTerm, Ptr< const MatrixBasedChannelModel::ChannelMatrix > channelMatrix, Ptr< const MatrixBasedChannelModel::ChannelParams > channelParams, const Vector &sSpeed, const Vector &uSpeed, uint8_t numTxPorts, uint8_t numRxPorts, bool isReverse) const
Computes the beamforming gain and applies it to the TX PSD.
std::complex< double > CalculateLongTermComponent(Ptr< const MatrixBasedChannelModel::ChannelMatrix > params, Ptr< const PhasedArrayModel > sAnt, Ptr< const PhasedArrayModel > uAnt, uint16_t sPortIdx, uint16_t uPortIdx, uint16_t cIndex) const
Computes a longTerm component from a specific port of s device to the specific port of u device and f...
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
size_t GetSize() const
Definition: val-array.h:400
size_t GetNumRows() const
Definition: val-array.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:66
#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:86
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
const double norm
Normalization to obtain randoms on [0,1).
Definition: rng-stream.cc:66
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
channel
Definition: third.py:88
params
Fit Fluctuating Two Ray model to the 3GPP TR 38.901 using the Anderson-Darling goodness-of-fit ##.
Ptr< const ComplexMatrixArray > spectrumChannelMatrix
The 3D channel matrix where the dimensions are: the number of RX ports, the number of TX Ports,...
Ptr< const ComplexMatrixArray > precodingMatrix
The 3D precoding matrix where the dimensions are: the number of TX ports, the number of TX streams,...
Ptr< SpectrumValue > psd
The Power Spectral Density of the waveform, in linear units.