A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
37namespace ns3
38{
39
40NS_LOG_COMPONENT_DEFINE("ThreeGppSpectrumPropagationLossModel");
41
42NS_OBJECT_ENSURE_REGISTERED(ThreeGppSpectrumPropagationLossModel);
43
45{
46 NS_LOG_FUNCTION(this);
47}
48
50{
51 NS_LOG_FUNCTION(this);
52}
53
54void
56{
57 m_longTermMap.clear();
58 m_channelModel->Dispose();
59 m_channelModel = nullptr;
60}
61
64{
65 static TypeId tid =
66 TypeId("ns3::ThreeGppSpectrumPropagationLossModel")
68 .SetGroupName("Spectrum")
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
80void
82{
83 m_channelModel = channel;
84}
85
88{
89 return m_channelModel;
90}
91
92double
94{
95 DoubleValue freq;
96 m_channelModel->GetAttribute("Frequency", freq);
97 return freq.Get();
98}
99
100void
102 const AttributeValue& value)
103{
104 m_channelModel->SetAttribute(name, value);
105}
106
107void
109 AttributeValue& value) const
110{
111 m_channelModel->GetAttribute(name, value);
112}
113
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
155std::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 isSameDir = (channelParams->m_nodeIds == channelMatrix->m_nodeIds);
241
242 // if channel params is generated in the same direction in which we
243 // generate the channel matrix, angles and zenith of departure and arrival are ok,
244 // just set them to corresponding variable that will be used for the generation
245 // of channel matrix, otherwise we need to flip angles and zeniths of departure and arrival
246 using DPV = std::vector<std::pair<double, double>>;
247 using MBCM = MatrixBasedChannelModel;
248 const auto& cachedAngleSincos = channelParams->m_cachedAngleSincos;
249 const DPV& zoa = cachedAngleSincos[isSameDir ? MBCM::ZOA_INDEX : MBCM::ZOD_INDEX];
250 const DPV& zod = cachedAngleSincos[isSameDir ? MBCM::ZOD_INDEX : MBCM::ZOA_INDEX];
251 const DPV& aoa = cachedAngleSincos[isSameDir ? MBCM::AOA_INDEX : MBCM::AOD_INDEX];
252 const DPV& aod = cachedAngleSincos[isSameDir ? MBCM::AOD_INDEX : MBCM::AOA_INDEX];
253
254 for (size_t cIndex = 0; cIndex < numCluster; cIndex++)
255 {
256 // Compute alpha and D as described in 3GPP TR 37.885 v15.3.0, Sec. 6.2.3
257 // These terms account for an additional Doppler contribution due to the
258 // presence of moving objects in the surrounding environment, such as in
259 // vehicular scenarios.
260 // This contribution is applied only to the delayed (reflected) paths and
261 // must be properly configured by setting the value of
262 // m_vScatt, which is defined as "maximum speed of the vehicle in the
263 // layout".
264 // By default, m_vScatt is set to 0, so there is no additional Doppler
265 // contribution.
266
267 double alpha = channelParams->m_alpha[cIndex];
268 double D = channelParams->m_D[cIndex];
269
270 // cluster angle angle[direction][n], where direction = 0(aoa), 1(zoa).
271 double tempDoppler =
272 factor *
273 ((zoa[cIndex].first * aoa[cIndex].second * uSpeed.x +
274 zoa[cIndex].first * aoa[cIndex].first * uSpeed.y + zoa[cIndex].second * uSpeed.z) +
275 (zod[cIndex].first * aod[cIndex].second * sSpeed.x +
276 zod[cIndex].first * aod[cIndex].first * sSpeed.y + zod[cIndex].second * sSpeed.z) +
277 2 * alpha * D);
278 doppler[cIndex] = std::complex<double>(cos(tempDoppler), sin(tempDoppler));
279 }
280
281 NS_ASSERT(numCluster <= doppler.GetSize());
282
283 // set the channel matrix
284 rxParams->spectrumChannelMatrix = GenSpectrumChannelMatrix(rxParams->psd,
285 longTerm,
286 channelMatrix,
287 channelParams,
288 doppler,
289 numTxPorts,
290 numRxPorts,
291 isReverse);
292
293 // The precoding matrix is not set
294 if (!rxParams->precodingMatrix)
295 {
296 // Update rxParams->Psd.
297 // Compute RX PSD from the channel matrix
298 auto vit = rxParams->psd->ValuesBegin(); // psd iterator
299 size_t rbIdx = 0;
300 while (vit != rxParams->psd->ValuesEnd())
301 {
302 // Calculate PSD for the first antenna port (correct for SISO)
303 *vit = std::norm(rxParams->spectrumChannelMatrix->Elem(0, 0, rbIdx));
304 vit++;
305 rbIdx++;
306 }
307 }
308 else
309 {
310 NS_ASSERT_MSG(rxParams->psd->GetValuesN() == rxParams->spectrumChannelMatrix->GetNumPages(),
311 "RX PSD and the spectrum channel matrix should have the same number of RBs ");
312 // Calculate RX PSD from the spectrum channel matrix, H and
313 // the precoding matrix, P as:
314 // PSD = (H*P)^h * (H*P),
315 // where the dimensions are:
316 // H (rxPorts,txPorts,numRbs) x P (txPorts,txStreams, numRbs) =
317 // HxP (rxPorts,txStreams, numRbs)
319 *rxParams->spectrumChannelMatrix * (*rxParams->precodingMatrix);
320 // (HxP)^h dimensions are (txStreams, rxPorts, numRbs)
322
323 // Finally, (HxP)^h x (HxP) = PSD (txStreams, txStreams, numRbs)
325 // Update rxParams->Psd
326 for (uint32_t rbIdx = 0; rbIdx < rxParams->psd->GetValuesN(); ++rbIdx)
327 {
328 (*rxParams->psd)[rbIdx] = 0.0;
329
330 for (size_t txStream = 0; txStream < psd.GetNumRows(); ++txStream)
331 {
332 (*rxParams->psd)[rbIdx] += std::real(psd(txStream, txStream, rbIdx));
333 }
334 }
335 }
336 return rxParams;
337}
338
341 Ptr<SpectrumValue> inPsd,
346 uint8_t numTxPorts,
347 uint8_t numRxPorts,
348 bool isReverse) const
349{
350 size_t numCluster = channelMatrix->m_channel.GetNumPages();
351 auto numRb = inPsd->GetValuesN();
352
353 auto directionalLongTerm = isReverse ? longTerm->Transpose() : (*longTerm);
354
356 Create<MatrixBasedChannelModel::Complex3DVector>(numRxPorts, numTxPorts, (uint16_t)numRb);
357
358 // Precompute the delay until numRb, numCluster or RB width changes
359 // Whenever the channelParams is updated, the number of numRbs, numClusters
360 // and RB width (12*SCS) are reset, ensuring these values are updated too
361 double rbWidth = inPsd->ConstBandsBegin()->fh - inPsd->ConstBandsBegin()->fl;
362
363 if (channelParams->m_cachedDelaySincos.GetNumRows() != numRb ||
364 channelParams->m_cachedDelaySincos.GetNumCols() != numCluster ||
365 channelParams->m_cachedRbWidth != rbWidth)
366 {
367 channelParams->m_cachedRbWidth = rbWidth;
368 channelParams->m_cachedDelaySincos = ComplexMatrixArray(numRb, numCluster);
369 auto sbit = inPsd->ConstBandsBegin(); // band iterator
370 for (unsigned i = 0; i < numRb; i++)
371 {
372 double fsb = (*sbit).fc; // center frequency of the sub-band
373 for (std::size_t cIndex = 0; cIndex < numCluster; cIndex++)
374 {
375 double delay = -2 * M_PI * fsb * (channelParams->m_delay[cIndex]);
376 channelParams->m_cachedDelaySincos(i, cIndex) =
377 std::complex<double>(cos(delay), sin(delay));
378 }
379 sbit++;
380 }
381 }
382
383 // Compute the product between the doppler and the delay sincos
384 auto delaySincosCopy = channelParams->m_cachedDelaySincos;
385 for (size_t iRb = 0; iRb < inPsd->GetValuesN(); iRb++)
386 {
387 for (std::size_t cIndex = 0; cIndex < numCluster; cIndex++)
388 {
389 delaySincosCopy(iRb, cIndex) *= doppler[cIndex];
390 }
391 }
392
393 // If "params" (ChannelMatrix) and longTerm were computed for the reverse direction (e.g. this
394 // is a DL transmission but params and longTerm were last updated during UL), then the elements
395 // in longTerm start from different offsets.
396
397 auto vit = inPsd->ValuesBegin(); // psd iterator
398 size_t iRb = 0;
399 // Compute the frequency-domain channel matrix
400 while (vit != inPsd->ValuesEnd())
401 {
402 if ((*vit) != 0.00)
403 {
404 auto sqrtVit = sqrt(*vit);
405 for (auto rxPortIdx = 0; rxPortIdx < numRxPorts; rxPortIdx++)
406 {
407 for (auto txPortIdx = 0; txPortIdx < numTxPorts; txPortIdx++)
408 {
409 std::complex<double> subsbandGain(0.0, 0.0);
410 for (size_t cIndex = 0; cIndex < numCluster; cIndex++)
411 {
412 subsbandGain += directionalLongTerm(rxPortIdx, txPortIdx, cIndex) *
413 delaySincosCopy(iRb, cIndex);
414 }
415 // Multiply with the square root of the input PSD so that the norm (absolute
416 // value squared) of chanSpct will be the output PSD
417 chanSpct->Elem(rxPortIdx, txPortIdx, iRb) = sqrtVit * subsbandGain;
418 }
419 }
420 }
421 vit++;
422 iRb++;
423 }
424 return chanSpct;
425}
426
430 Ptr<const PhasedArrayModel> aPhasedArrayModel,
431 Ptr<const PhasedArrayModel> bPhasedArrayModel) const
432{
434 longTerm; // vector containing the long term component for each cluster
435
436 // check if the channel matrix was generated considering a as the s-node and
437 // b as the u-node or vice-versa
438 auto isReverse =
439 channelMatrix->IsReverse(aPhasedArrayModel->GetId(), bPhasedArrayModel->GetId());
440 auto sAntenna = isReverse ? bPhasedArrayModel : aPhasedArrayModel;
441 auto uAntenna = isReverse ? aPhasedArrayModel : bPhasedArrayModel;
442
445 if (!isReverse)
446 {
447 sW = aPhasedArrayModel->GetBeamformingVector();
448 uW = bPhasedArrayModel->GetBeamformingVector();
449 }
450 else
451 {
452 sW = bPhasedArrayModel->GetBeamformingVector();
453 uW = aPhasedArrayModel->GetBeamformingVector();
454 }
455
456 bool update = false; // indicates whether the long term has to be updated
457 bool notFound = false; // indicates if the long term has not been computed yet
458
459 // compute the long term key, the key is unique for each tx-rx pair
460 uint64_t longTermId =
461 MatrixBasedChannelModel::GetKey(aPhasedArrayModel->GetId(), bPhasedArrayModel->GetId());
462
463 // look for the long term in the map and check if it is valid
464 if (m_longTermMap.find(longTermId) != m_longTermMap.end())
465 {
466 NS_LOG_DEBUG("found the long term component in the map");
467 longTerm = m_longTermMap[longTermId]->m_longTerm;
468
469 // check if the channel matrix has been updated
470 // or the s beam has been changed
471 // or the u beam has been changed
472 update = (m_longTermMap[longTermId]->m_channel->m_generatedTime !=
473 channelMatrix->m_generatedTime ||
474 m_longTermMap[longTermId]->m_sW != sW || m_longTermMap[longTermId]->m_uW != uW);
475 }
476 else
477 {
478 NS_LOG_DEBUG("long term component NOT found");
479 notFound = true;
480 }
481
482 if (update || notFound)
483 {
484 NS_LOG_DEBUG("compute the long term");
485 // compute the long term component
486 longTerm = CalcLongTerm(channelMatrix, sAntenna, uAntenna);
487 Ptr<LongTerm> longTermItem = Create<LongTerm>();
488 longTermItem->m_longTerm = longTerm;
489 longTermItem->m_channel = channelMatrix;
490 longTermItem->m_sW = std::move(sW);
491 longTermItem->m_uW = std::move(uW);
492 // store the long term to reduce computation load
493 // only the small scale fading needs to be updated if the large scale parameters and antenna
494 // weights remain unchanged.
495 m_longTermMap[longTermId] = longTermItem;
496 }
497
498 return longTerm;
499}
500
503 Ptr<const SpectrumSignalParameters> spectrumSignalParams,
506 Ptr<const PhasedArrayModel> aPhasedArrayModel,
507 Ptr<const PhasedArrayModel> bPhasedArrayModel) const
508{
509 NS_LOG_FUNCTION(this << spectrumSignalParams << a << b << aPhasedArrayModel
510 << bPhasedArrayModel);
511
512 if (a->GetPosition() == b->GetPosition())
513 {
514 return spectrumSignalParams->Copy();
515 }
516 uint32_t aId = a->GetObject<Node>()->GetId(); // id of the node a
517 uint32_t bId = b->GetObject<Node>()->GetId(); // id of the node b
518 NS_ASSERT_MSG(aPhasedArrayModel, "Antenna not found for node " << aId);
519 NS_LOG_DEBUG("a node " << aId << " antenna " << aPhasedArrayModel);
520 NS_ASSERT_MSG(bPhasedArrayModel, "Antenna not found for node " << bId);
521 NS_LOG_DEBUG("b node " << bId << " antenna " << bPhasedArrayModel);
522
524 m_channelModel->GetChannel(a, b, aPhasedArrayModel, bPhasedArrayModel);
526 m_channelModel->GetParams(a, b);
527
528 // retrieve the long term component
530 GetLongTerm(channelMatrix, aPhasedArrayModel, bPhasedArrayModel);
531
532 auto isReverse =
533 channelMatrix->IsReverse(aPhasedArrayModel->GetId(), bPhasedArrayModel->GetId());
534
535 // apply the beamforming gain
536 return CalcBeamformingGain(spectrumSignalParams,
537 longTerm,
538 channelMatrix,
539 channelParams,
540 a->GetVelocity(),
541 b->GetVelocity(),
542 aPhasedArrayModel->GetNumPorts(),
543 bPhasedArrayModel->GetNumPorts(),
544 isReverse);
545}
546
547int64_t
549{
550 return 0;
551}
552
553} // 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< T > HermitianTranspose() const
Function that performs the Hermitian transpose of this MatrixArray and returns a new matrix that is t...
This is an interface for a channel model that can be described by a channel matrix,...
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
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:932
size_t GetSize() const
Definition: val-array.h:405
size_t GetNumRows() const
Definition: val-array.h:384
#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
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:259
#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
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
MatrixArray< std::complex< double > > ComplexMatrixArray
Create an alias for MatrixArray using complex type.
Definition: matrix-array.h:247
Definition: second.py:1