A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
three-gpp-propagation-loss-model.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 SIGNET Lab, Department of Information Engineering,
3 * University of Padova
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 */
7
9
11
12#include "ns3/boolean.h"
13#include "ns3/double.h"
14#include "ns3/geocentric-constant-position-mobility-model.h"
15#include "ns3/log.h"
16#include "ns3/mobility-model.h"
17#include "ns3/node.h"
18#include "ns3/pointer.h"
19#include "ns3/simulator.h"
20
21#include <cmath>
22
23namespace
24{
25/**
26 * The enumerator used for code clarity when performing parameter assignment in the GetLoss Methods
27 */
37
38/**
39 * The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the
40 * NTN Dense Urban scenario
41 */
42const std::map<int, std::vector<float>> SFCL_DenseUrban{
43 {10, {3.5, 15.5, 34.3, 2.9, 17.1, 44.3}},
44 {20, {3.4, 13.9, 30.9, 2.4, 17.1, 39.9}},
45 {30, {2.9, 12.4, 29.0, 2.7, 15.6, 37.5}},
46 {40, {3.0, 11.7, 27.7, 2.4, 14.6, 35.8}},
47 {50, {3.1, 10.6, 26.8, 2.4, 14.2, 34.6}},
48 {60, {2.7, 10.5, 26.2, 2.7, 12.6, 33.8}},
49 {70, {2.5, 10.1, 25.8, 2.6, 12.1, 33.3}},
50 {80, {2.3, 9.2, 25.5, 2.8, 12.3, 33.0}},
51 {90, {1.2, 9.2, 25.5, 0.6, 12.3, 32.9}},
52};
53
54/**
55 * The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the
56 * NTN Urban scenario
57 */
58const std::map<int, std::vector<float>> SFCL_Urban{
59 {10, {4, 6, 34.3, 4, 6, 44.3}},
60 {20, {4, 6, 30.9, 4, 6, 39.9}},
61 {30, {4, 6, 29.0, 4, 6, 37.5}},
62 {40, {4, 6, 27.7, 4, 6, 35.8}},
63 {50, {4, 6, 26.8, 4, 6, 34.6}},
64 {60, {4, 6, 26.2, 4, 6, 33.8}},
65 {70, {4, 6, 25.8, 4, 6, 33.3}},
66 {80, {4, 6, 25.5, 4, 6, 33.0}},
67 {90, {4, 6, 25.5, 4, 6, 32.9}},
68};
69
70/**
71 * The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the
72 * NTN Suburban and Rural scenarios
73 */
74const std::map<int, std::vector<float>> SFCL_SuburbanRural{
75 {10, {1.79, 8.93, 19.52, 1.9, 10.7, 29.5}},
76 {20, {1.14, 9.08, 18.17, 1.6, 10.0, 24.6}},
77 {30, {1.14, 8.78, 18.42, 1.9, 11.2, 21.9}},
78 {40, {0.92, 10.25, 18.28, 2.3, 11.6, 20.0}},
79 {50, {1.42, 10.56, 18.63, 2.7, 11.8, 18.7}},
80 {60, {1.56, 10.74, 17.68, 3.1, 10.8, 17.8}},
81 {70, {0.85, 10.17, 16.5, 3.0, 10.8, 17.2}},
82 {80, {0.72, 11.52, 16.3, 3.6, 10.8, 16.9}},
83 {90, {0.72, 11.52, 16.3, 0.4, 10.8, 16.8}},
84};
85
86/**
87 * Array containing the attenuation given by atmospheric absorption. 100 samples are selected for
88 * frequencies from 1GHz to 100GHz. In order to get the atmospheric absorption loss for a given
89 * frequency f: 1- round f to the closest integer between 0 and 100. 2- use the obtained integer to
90 * access the corresponding element in the array, that will give the attenuation at that frequency.
91 * Data is obtained form ITU-R P.676 Figure 6.
92 */
93const double atmosphericAbsorption[101] = {
94 0, 0.0300, 0.0350, 0.0380, 0.0390, 0.0410, 0.0420, 0.0450, 0.0480, 0.0500,
95 0.0530, 0.0587, 0.0674, 0.0789, 0.0935, 0.1113, 0.1322, 0.1565, 0.1841, 0.2153,
96 0.2500, 0.3362, 0.4581, 0.5200, 0.5200, 0.5000, 0.4500, 0.3850, 0.3200, 0.2700,
97 0.2500, 0.2517, 0.2568, 0.2651, 0.2765, 0.2907, 0.3077, 0.3273, 0.3493, 0.3736,
98 0.4000, 0.4375, 0.4966, 0.5795, 0.6881, 0.8247, 0.9912, 1.1900, 1.4229, 1.6922,
99 2.0000, 4.2654, 10.1504, 19.2717, 31.2457, 45.6890, 62.2182, 80.4496, 100.0000, 140.0205,
100 170.0000, 100.0000, 78.1682, 59.3955, 43.5434, 30.4733, 20.0465, 12.1244, 6.5683, 3.2397,
101 2.0000, 1.7708, 1.5660, 1.3858, 1.2298, 1.0981, 0.9905, 0.9070, 0.8475, 0.8119,
102 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000, 0.8000,
103 0.8000, 0.8029, 0.8112, 0.8243, 0.8416, 0.8625, 0.8864, 0.9127, 0.9408, 0.9701,
104 1.0000};
105
106/**
107 * Map containing the Tropospheric attenuation in dB with 99% probability at 20 GHz in Toulouse
108 * used for tropospheric scintillation losses. From Table 6.6.6.2.1-1 of 3GPP TR 38.811.
109 */
110const std::map<int, float> troposphericScintillationLoss{
111 {10, {1.08}},
112 {20, {0.48}},
113 {30, {0.30}},
114 {40, {0.22}},
115 {50, {0.17}},
116 {60, {0.13}},
117 {70, {0.12}},
118 {80, {0.12}},
119 {90, {0.12}},
120};
121
122/**
123 * @brief Get the base station and user terminal relative distances and heights
124 *
125 * @param a the mobility model of terminal a
126 * @param b the mobility model of terminal b
127 *
128 * @return The tuple [dist2D, dist3D, hBs, hUt], where dist2D and dist3D
129 * are the 2D and 3D distances between a and b, respectively, hBs is the bigger
130 * height and hUt the smallest.
131 */
132std::tuple<double, double, double, double>
135{
136 auto aPos = a->GetPosition();
137 auto bPos = b->GetPosition();
138 double distance2D = ns3::ThreeGppChannelConditionModel::Calculate2dDistance(aPos, bPos);
139 double distance3D = ns3::CalculateDistance(aPos, bPos);
140 double hBs = std::max(aPos.z, bPos.z);
141 double hUt = std::min(aPos.z, bPos.z);
142 return std::make_tuple(distance2D, distance3D, hBs, hUt);
143}
144
145/**
146 * @brief Get the base station and user terminal heights for the UmiStreetCanyon scenario
147 *
148 * @param heightA the first height in meters
149 * @param heightB the second height in meters
150 *
151 * @return The tuple [hBs, hUt], where hBs is assumed to be = 10 and hUt other height.
152 */
153std::tuple<double, double>
154GetBsUtHeightsUmiStreetCanyon(double heightA, double heightB)
155{
156 double hBs = (heightA == 10) ? heightA : heightB;
157 double hUt = (heightA == 10) ? heightB : heightA;
158 return std::make_tuple(hBs, hUt);
159}
160
161/**
162 * @brief Computes the free-space path loss using the formula described in 3GPP TR 38.811,
163 * Table 6.6.2
164 *
165 * @param freq the operating frequency
166 * @param dist3d the 3D distance between the communicating nodes
167 *
168 * @return the path loss for NTN scenarios
169 */
170double
171ComputeNtnPathloss(double freq, double dist3d)
172{
173 return 32.45 + 20 * log10(freq / 1e9) + 20 * log10(dist3d);
174}
175
176/**
177 * @brief Computes the atmospheric absorption loss using the formula described in 3GPP TR 38.811,
178 * Sec 6.6.4
179 *
180 * @param freq the operating frequency
181 * @param elevAngle the elevation angle between the communicating nodes
182 *
183 * @return the atmospheric absorption loss for NTN scenarios
184 */
185double
186ComputeAtmosphericAbsorptionLoss(double freq, double elevAngle)
187{
188 double loss = 0;
189 if ((elevAngle < 10 && freq > 1e9) || freq >= 10e9)
190 {
191 int roundedFreq = round(freq / 10e8);
192 loss += atmosphericAbsorption[roundedFreq] / sin(elevAngle * (M_PI / 180));
193 }
194
195 return loss;
196}
197
198/**
199 * @brief Computes the ionospheric plus tropospheric scintillation loss using the formulas
200 * described in 3GPP TR 38.811, Sec 6.6.6.1-4 and 6.6.6.2, respectively.
201 *
202 * @param freq the operating frequency
203 * @param elevAngleQuantized the quantized elevation angle between the communicating nodes
204 *
205 * @return the ionospheric plus tropospheric scintillation loss for NTN scenarios
206 */
207double
208ComputeIonosphericPlusTroposphericScintillationLoss(double freq, double elevAngleQuantized)
209{
210 double loss = 0;
211 if (freq < 6e9)
212 {
213 // Ionospheric
214 loss = 6.22 / (pow(freq / 1e9, 1.5));
215 }
216 else
217 {
218 // Tropospheric
219 loss = troposphericScintillationLoss.at(elevAngleQuantized);
220 }
221 return loss;
222}
223
224/**
225 * @brief Computes the clutter loss using the formula
226 * described in 3GPP TR 38.811, Sec 6.6.6.1-4 and 6.6.6.2, respectively.
227 *
228 * @param freq the operating frequency
229 * @param elevAngleQuantized the quantized elevation angle between the communicating nodes
230 * @param sfcl the nested map containing the Shadow Fading and
231 * Clutter Loss values for the NTN Suburban and Rural scenario
232 *
233 * @return the clutter loss for NTN scenarios
234 */
235double
237 const std::map<int, std::vector<float>>* sfcl,
238 double elevAngleQuantized)
239{
240 double loss = 0;
241 if (freq < 13.0e9)
242 {
243 loss += (*sfcl).at(elevAngleQuantized)[SFCL_params::S_NLOS_CL]; // Get the Clutter Loss for
244 // the S Band
245 }
246 else
247 {
248 loss += (*sfcl).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_CL]; // Get the Clutter Loss for
249 // the Ka Band
250 }
251
252 return loss;
253}
254
255constexpr double M_C = 3.0e8; //!< propagation velocity in free space
256
257} // namespace
258
259namespace ns3
260{
261
262NS_LOG_COMPONENT_DEFINE("ThreeGppPropagationLossModel");
263
264NS_OBJECT_ENSURE_REGISTERED(ThreeGppPropagationLossModel);
265
266TypeId
268{
269 static TypeId tid =
270 TypeId("ns3::ThreeGppPropagationLossModel")
272 .SetGroupName("Propagation")
273 .AddAttribute("Frequency",
274 "The centre frequency in Hz.",
275 DoubleValue(500.0e6),
279 .AddAttribute("ShadowingEnabled",
280 "Enable/disable shadowing.",
281 BooleanValue(true),
284 .AddAttribute(
285 "ChannelConditionModel",
286 "Pointer to the channel condition model.",
287 PointerValue(),
291 .AddAttribute("EnforceParameterRanges",
292 "Whether to strictly enforce TR38.901 applicability ranges",
293 BooleanValue(false),
296 .AddAttribute(
297 "BuildingPenetrationLossesEnabled",
298 "Enable/disable Building Penetration Losses.",
299 BooleanValue(true),
302 .AddAttribute("MeanVehicularLoss",
303 "9dB for standard cars, 20dB for cars with "
304 "metal coated glass panels.",
305 DoubleValue(9),
308 return tid;
309}
310
313{
314 NS_LOG_FUNCTION(this);
315
316 // initialize the normal random variables
318 m_normRandomVariable->SetAttribute("Mean", DoubleValue(0));
319 m_normRandomVariable->SetAttribute("Variance", DoubleValue(1));
320
323
325 m_normalO2iLowLossVar->SetAttribute("Mean", DoubleValue(0));
326 m_normalO2iLowLossVar->SetStdDev(4.4);
327
329 m_normalO2iHighLossVar->SetAttribute("Mean", DoubleValue(0));
330 m_normalO2iHighLossVar->SetStdDev(6.5);
331
333 // mean is set via an attribute, so must be set in NotifyConstructionCompleted
334 m_normalO2iVehicularLossVar->SetStdDev(5);
335}
336
341
342void
349
350void
355
356void
362
369
370void
372{
373 NS_LOG_FUNCTION(this);
374 NS_ASSERT_MSG(f >= 500.0e6 && f <= 100.0e9,
375 "Frequency should be between 0.5 and 100 GHz but is " << f);
376 m_frequency = f;
377}
378
379double
385
386bool
391
392double
395 Ptr<MobilityModel> b) const
396{
397 NS_LOG_FUNCTION(this);
398
399 // check if the model is initialized
400 NS_ASSERT_MSG(m_frequency != 0.0, "First set the centre frequency");
401
402 // retrieve the channel condition
403 NS_ASSERT_MSG(m_channelConditionModel, "First set the channel condition model");
404 Ptr<ChannelCondition> cond = m_channelConditionModel->GetChannelCondition(a, b);
405
406 double rxPow = txPowerDbm;
407 rxPow -= GetLoss(cond, a, b);
408
410 {
411 rxPow -= GetShadowing(a, b, cond->GetLosCondition());
412 }
413
414 // get o2i losses
416 ((cond->GetO2iCondition() == ChannelCondition::O2iConditionValue::O2I) ||
417 (cond->GetO2iCondition() == ChannelCondition::O2iConditionValue::I2I &&
418 cond->GetLosCondition() == ChannelCondition::LosConditionValue::NLOS)))
419 {
420 if (m_frequency < 6e9)
421 {
422 // TR 38.901 has a backward compatibility O2I penetration loss for sub 6GHz channels
423 rxPow -= GetO2iSub6GhzPenetrationLoss(a, b, cond->GetLosCondition());
424 }
425 else
426 {
427 if (IsO2iLowPenetrationLoss(cond))
428 {
429 rxPow -= GetO2iLowPenetrationLoss(a, b, cond->GetLosCondition());
430 }
431 else
432 {
433 rxPow -= GetO2iHighPenetrationLoss(a, b, cond->GetLosCondition());
434 }
435 }
436 }
437
438 rxPow -= GetO2iVehicularLoss(a, b, cond->GetO2iCondition());
439
440 return rxPow;
441}
442
443double
446 Ptr<MobilityModel> b) const
447{
448 NS_LOG_FUNCTION(this);
449
450 double loss = 0;
451 switch (cond->GetLosCondition())
452 {
454 loss = GetLossLos(a, b);
455 break;
457 loss = GetLossNlosv(a, b);
458 break;
460 loss = GetLossNlos(a, b);
461 break;
462 default:
463 NS_FATAL_ERROR("Unknown channel condition");
464 }
465
466 return loss;
467}
468
469double
474{
475 NS_LOG_FUNCTION(this);
476
477 double o2iLossValue = 0;
478 double lossTw = 0;
479 double lossIn = 0;
480 double lossNormalVariate = 0;
481
482 // compute the channel key
483 uint32_t key = GetKey(a, b);
484
485 bool notFound = false; // indicates if the o2iLoss value has not been computed yet
486 bool newCondition = false; // indicates if the channel condition has changed
487
488 auto it = m_o2iLossMap.end(); // the o2iLoss map iterator
489 if (m_o2iLossMap.find(key) != m_o2iLossMap.end())
490 {
491 // found the o2iLoss value in the map
492 it = m_o2iLossMap.find(key);
493 newCondition = (it->second.m_condition != cond); // true if the condition changed
494 }
495 else
496 {
497 notFound = true;
498 // add a new entry in the map and update the iterator
499 O2iLossMapItem newItem;
500 it = m_o2iLossMap.insert(it, std::make_pair(key, newItem));
501 }
502
503 if (notFound || newCondition)
504 {
505 // distance2dIn is a single, link-specific, uniformly distributed variable
506 // between 0 and 25 m for UMa and UMi-Street Canyon.
507 double distance2dIn = GetO2iDistance2dInSub6Ghz();
508
509 // calculate penetration losses, see TR 38.901 Table 7.4.3-3
510 lossTw = 20;
511
512 // calculate indoor loss
513 lossIn = 0.5 * distance2dIn;
514
515 // calculate low loss standard deviation
516 lossNormalVariate = 0;
517
518 o2iLossValue = lossTw + lossIn + lossNormalVariate;
519
520 // update the entry in the map
521 it->second.m_o2iLoss = o2iLossValue;
522 it->second.m_condition = cond;
523 }
524 else
525 {
526 o2iLossValue = it->second.m_o2iLoss;
527 }
528
529 return o2iLossValue;
530}
531
532double
537{
538 NS_LOG_FUNCTION(this);
539
540 double o2iLossValue = 0;
541 double lowLossTw = 0;
542 double lossIn = 0;
543 double lowlossNormalVariate = 0;
544 double lGlass = 0;
545 double lConcrete = 0;
546
547 // compute the channel key
548 uint32_t key = GetKey(a, b);
549
550 bool notFound = false; // indicates if the o2iLoss value has not been computed yet
551 bool newCondition = false; // indicates if the channel condition has changed
552
553 auto it = m_o2iLossMap.end(); // the o2iLoss map iterator
554 if (m_o2iLossMap.find(key) != m_o2iLossMap.end())
555 {
556 // found the o2iLoss value in the map
557 it = m_o2iLossMap.find(key);
558 newCondition = (it->second.m_condition != cond); // true if the condition changed
559 }
560 else
561 {
562 notFound = true;
563 // add a new entry in the map and update the iterator
564 O2iLossMapItem newItem;
565 it = m_o2iLossMap.insert(it, std::make_pair(key, newItem));
566 }
567
568 if (notFound || newCondition)
569 {
570 // distance2dIn is minimum of two independently generated uniformly distributed
571 // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and
572 // 10 m for RMa. 2D−in d shall be UT-specifically generated.
573 double distance2dIn = GetO2iDistance2dIn();
574
575 // calculate material penetration losses, see TR 38.901 Table 7.4.3-1
576 lGlass = 2 + 0.2 * m_frequency / 1e9; // m_frequency is operation frequency in Hz
577 lConcrete = 5 + 4 * m_frequency / 1e9;
578
579 lowLossTw =
580 5 - 10 * log10(0.3 * std::pow(10, -lGlass / 10) + 0.7 * std::pow(10, -lConcrete / 10));
581
582 // calculate indoor loss
583 lossIn = 0.5 * distance2dIn;
584
585 // calculate low loss standard deviation
586 lowlossNormalVariate = m_normalO2iLowLossVar->GetValue();
587
588 o2iLossValue = lowLossTw + lossIn + lowlossNormalVariate;
589
590 // update the entry in the map
591 it->second.m_o2iLoss = o2iLossValue;
592 it->second.m_condition = cond;
593 }
594 else
595 {
596 o2iLossValue = it->second.m_o2iLoss;
597 }
598
599 return o2iLossValue;
600}
601
602double
607{
608 NS_LOG_FUNCTION(this);
609
610 double o2iLossValue = 0;
611 double highLossTw = 0;
612 double lossIn = 0;
613 double highlossNormalVariate = 0;
614 double lIIRGlass = 0;
615 double lConcrete = 0;
616
617 // compute the channel key
618 uint32_t key = GetKey(a, b);
619
620 bool notFound = false; // indicates if the o2iLoss value has not been computed yet
621 bool newCondition = false; // indicates if the channel condition has changed
622
623 auto it = m_o2iLossMap.end(); // the o2iLoss map iterator
624 if (m_o2iLossMap.find(key) != m_o2iLossMap.end())
625 {
626 // found the o2iLoss value in the map
627 it = m_o2iLossMap.find(key);
628 newCondition = (it->second.m_condition != cond); // true if the condition changed
629 }
630 else
631 {
632 notFound = true;
633 // add a new entry in the map and update the iterator
634 O2iLossMapItem newItem;
635 it = m_o2iLossMap.insert(it, std::make_pair(key, newItem));
636 }
637
638 if (notFound || newCondition)
639 {
640 // generate a new independent realization
641
642 // distance2dIn is minimum of two independently generated uniformly distributed
643 // variables between 0 and 25 m for UMa and UMi-Street Canyon, and between 0 and
644 // 10 m for RMa. 2D−in d shall be UT-specifically generated.
645 double distance2dIn = GetO2iDistance2dIn();
646
647 // calculate material penetration losses, see TR 38.901 Table 7.4.3-1
648 lIIRGlass = 23 + 0.3 * m_frequency / 1e9;
649 lConcrete = 5 + 4 * m_frequency / 1e9;
650
651 highLossTw = 5 - 10 * log10(0.7 * std::pow(10, -lIIRGlass / 10) +
652 0.3 * std::pow(10, -lConcrete / 10));
653
654 // calculate indoor loss
655 lossIn = 0.5 * distance2dIn;
656
657 // calculate low loss standard deviation
658 highlossNormalVariate = m_normalO2iHighLossVar->GetValue();
659
660 o2iLossValue = highLossTw + lossIn + highlossNormalVariate;
661
662 // update the entry in the map
663 it->second.m_o2iLoss = o2iLossValue;
664 it->second.m_condition = cond;
665 }
666 else
667 {
668 o2iLossValue = it->second.m_o2iLoss;
669 }
670
671 return o2iLossValue;
672}
673
674bool
676{
677 if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::LOW)
678 {
679 return true;
680 }
681 else if (cond->GetO2iLowHighCondition() == ChannelCondition::O2iLowHighConditionValue::HIGH)
682 {
683 return false;
684 }
685 else
686 {
687 NS_ABORT_MSG("If we have set the O2I condition, we shouldn't be here");
688 }
689}
690
691double
693{
694 NS_LOG_FUNCTION(this);
695 NS_FATAL_ERROR("Unsupported channel condition (NLOSv)");
696 return 0;
697}
698
699double
703{
704 NS_LOG_FUNCTION(this);
705
706 double shadowingValue;
707
708 // compute the channel key
709 uint32_t key = GetKey(a, b);
710
711 bool notFound = false; // indicates if the shadowing value has not been computed yet
712 bool newCondition = false; // indicates if the channel condition has changed
713 Vector newDistance; // the distance vector, that is not a distance but a difference
714 auto it = m_shadowingMap.end(); // the shadowing map iterator
715 if (m_shadowingMap.find(key) != m_shadowingMap.end())
716 {
717 // found the shadowing value in the map
718 it = m_shadowingMap.find(key);
719 newDistance = GetVectorDifference(a, b);
720 newCondition = (it->second.m_condition != cond); // true if the condition changed
721 }
722 else
723 {
724 notFound = true;
725
726 // add a new entry in the map and update the iterator
727 ShadowingMapItem newItem;
728 it = m_shadowingMap.insert(it, std::make_pair(key, newItem));
729 }
730
731 if (notFound || newCondition)
732 {
733 // generate a new independent realization
734 shadowingValue = m_normRandomVariable->GetValue() * GetShadowingStd(a, b, cond);
735 }
736 else
737 {
738 // compute a new correlated shadowing loss
739 Vector2D displacement(newDistance.x - it->second.m_distance.x,
740 newDistance.y - it->second.m_distance.y);
741 double R = exp(-1 * displacement.GetLength() / GetShadowingCorrelationDistance(cond));
742 shadowingValue = R * it->second.m_shadowing + sqrt(1 - R * R) *
743 m_normRandomVariable->GetValue() *
744 GetShadowingStd(a, b, cond);
745 }
746
747 // update the entry in the map
748 it->second.m_shadowing = shadowingValue;
749 it->second.m_distance = newDistance; // Save the (0,0,0) vector in case it's the first time we
750 // are calculating this value
751 it->second.m_condition = cond;
752
753 return shadowingValue;
754}
755
756int64_t
758{
759 NS_LOG_FUNCTION(this);
760
761 m_normRandomVariable->SetStream(stream);
762 m_randomO2iVar1->SetStream(stream + 1);
763 m_randomO2iVar2->SetStream(stream + 2);
764 m_normalO2iLowLossVar->SetStream(stream + 3);
765 m_normalO2iHighLossVar->SetStream(stream + 4);
766 m_normalO2iVehicularLossVar->SetStream(stream + 5);
767 return stream + 6;
768}
769
770double
772{
773 double x = a.x - b.x;
774 double y = a.y - b.y;
775 double distance2D = sqrt(x * x + y * y);
776
777 return distance2D;
778}
779
782{
783 // use the nodes ids to obtain an unique key for the channel between a and b
784 // sort the nodes ids so that the key is reciprocal
785 uint32_t x1 = std::min(a->GetObject<Node>()->GetId(), b->GetObject<Node>()->GetId());
786 uint32_t x2 = std::max(a->GetObject<Node>()->GetId(), b->GetObject<Node>()->GetId());
787
788 // use the cantor function to obtain the key
789 uint32_t key = (((x1 + x2) * (x1 + x2 + 1)) / 2) + x2;
790
791 return key;
792}
793
794Vector
796{
797 uint32_t x1 = a->GetObject<Node>()->GetId();
798 uint32_t x2 = b->GetObject<Node>()->GetId();
799
800 if (x1 < x2)
801 {
802 return b->GetPosition() - a->GetPosition();
803 }
804 else
805 {
806 return a->GetPosition() - b->GetPosition();
807 }
808}
809
810double
815
816void
823
824double
828{
829 NS_LOG_FUNCTION(this);
830 double o2iVehicularLoss = 0.0;
831
832 // O2I penetration loss for vehicles only applies between 600 MHz and 60 GHz.
833 if (m_frequency >= 0.6e9 && m_frequency < 60e9)
834 {
835 for (const auto& mob : {a, b})
836 {
837 auto velocityKmH = mob->GetVelocity().GetLength() * 3.6;
838 auto idNode = mob->GetObject<Node>()->GetId();
839 // Slow nodes are considered as pedestrians (no loss)
840 if (velocityKmH < 30)
841 {
842 m_o2iVehicularUtLossMap[idNode] = 0.0;
843 }
844 // Fast nodes are considered vehicles.
845 // Create one loss per terminal, and reuse throughout simulation.
846 else if (velocityKmH >= 30 && velocityKmH <= 120)
847 {
848 if (m_o2iVehicularUtLossMap.find(idNode) == m_o2iVehicularUtLossMap.end())
849 {
851 }
852 }
853 // Very fast nodes are not modeled
854 else
855 {
857 "O2I loss for high-speed (>120 km/h) transit and satellites not implemented");
858 }
859
860 // Sum vehicle individual losses
862 {
863 o2iVehicularLoss += m_o2iVehicularUtLossMap.at(idNode);
864 }
865 }
866 }
867 return o2iVehicularLoss;
868}
869
870// ------------------------------------------------------------------------- //
871
873
874TypeId
876{
877 static TypeId tid = TypeId("ns3::ThreeGppRmaPropagationLossModel")
879 .SetGroupName("Propagation")
880 .AddConstructor<ThreeGppRmaPropagationLossModel>()
881 .AddAttribute("AvgBuildingHeight",
882 "The average building height in meters.",
883 DoubleValue(5.0),
885 MakeDoubleChecker<double>(5.0, 50.0))
886 .AddAttribute("AvgStreetWidth",
887 "The average street width in meters.",
888 DoubleValue(20.0),
890 MakeDoubleChecker<double>(5.0, 50.0));
891 return tid;
892}
893
902
907
908double
910{
911 // distance2dIn is minimum of two independently generated uniformly distributed variables
912 // between 0 and 10 m for RMa. 2D−in d shall be UT-specifically generated.
913 return std::min(m_randomO2iVar1->GetValue(0, 10), m_randomO2iVar2->GetValue(0, 10));
914}
915
916bool
918 [[maybe_unused]]) const
919{
920 // Based on 3GPP 38.901 7.4.3.1 in RMa only low losses are applied.
921 // Therefore enforce low losses.
922 return true;
923}
924
925double
927{
928 NS_LOG_FUNCTION(this);
929 NS_ASSERT_MSG(m_frequency <= 30.0e9,
930 "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
931
932 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
933
934 // check if hBS and hUT are within the specified validity range
935 if (hUt < 1.0 || hUt > 10.0)
936 {
937 NS_ABORT_MSG_IF(m_enforceRanges, "Rma UT height out of range");
939 "The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
940 }
941
942 if (hBs < 10.0 || hBs > 150.0)
943 {
944 NS_ABORT_MSG_IF(m_enforceRanges, "Rma BS height out of range");
946 "The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
947 }
948
949 // NOTE The model is intended to be used for BS-UT links, however we may need to
950 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
951 // interference. In order to apply the model, we need to retrieve the values of
952 // hBS and hUT, but in these cases one of the two falls outside the validity
953 // range and the warning message is printed (hBS for the UT-UT case and hUT
954 // for the BS-BS case).
955
956 double distanceBp = GetBpDistance(m_frequency, hBs, hUt);
957 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
959 distanceBp > 0,
960 "Breakpoint distance is zero (divide-by-zero below); are either hBs or hUt = 0?");
961
962 // check if the distance is outside the validity range
963 if (distance2D < 10.0 || distance2D > 10.0e3)
964 {
965 NS_ABORT_MSG_IF(m_enforceRanges, "Rma distance2D out of range");
966 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
967 "accurate");
968 }
969
970 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
971 double loss = 0;
972 if (distance2D <= distanceBp)
973 {
974 // use PL1
975 loss = Pl1(m_frequency, distance3D, m_h, m_w);
976 }
977 else
978 {
979 // use PL2
980 loss = Pl1(m_frequency, distanceBp, m_h, m_w) + 40 * log10(distance3D / distanceBp);
981 }
982
983 NS_LOG_DEBUG("Loss " << loss);
984
985 return loss;
986}
987
988double
990{
991 NS_LOG_FUNCTION(this);
992 NS_ASSERT_MSG(m_frequency <= 30.0e9,
993 "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
994
995 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
996
997 // check if hBs and hUt are within the validity range
998 if (hUt < 1.0 || hUt > 10.0)
999 {
1000 NS_ABORT_MSG_IF(m_enforceRanges, "Rma UT height out of range");
1002 "The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
1003 }
1004
1005 if (hBs < 10.0 || hBs > 150.0)
1006 {
1007 NS_ABORT_MSG_IF(m_enforceRanges, "Rma BS height out of range");
1009 "The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
1010 }
1011
1012 // NOTE The model is intended to be used for BS-UT links, however we may need to
1013 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1014 // interference. In order to apply the model, we need to retrieve the values of
1015 // hBS and hUT, but in these cases one of the two falls outside the validity
1016 // range and the warning message is printed (hBS for the UT-UT case and hUT
1017 // for the BS-BS case).
1018
1019 // check if the distance is outside the validity range
1020 if (distance2D < 10.0 || distance2D > 5.0e3)
1021 {
1022 NS_ABORT_MSG_IF(m_enforceRanges, "distance2D out of range");
1023 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1024 "accurate");
1025 }
1026
1027 // compute the pathloss
1028 double plNlos = 161.04 - 7.1 * log10(m_w) + 7.5 * log10(m_h) -
1029 (24.37 - 3.7 * pow((m_h / hBs), 2)) * log10(hBs) +
1030 (43.42 - 3.1 * log10(hBs)) * (log10(distance3D) - 3.0) +
1031 20.0 * log10(m_frequency / 1e9) - (3.2 * pow(log10(11.75 * hUt), 2) - 4.97);
1032
1033 double loss = std::max(GetLossLos(a, b), plNlos);
1034
1035 NS_LOG_DEBUG("Loss " << loss);
1036
1037 return loss;
1038}
1039
1040double
1044{
1045 NS_LOG_FUNCTION(this);
1046 double shadowingStd;
1047
1049 {
1050 // compute the 2D distance between the two nodes
1051 double distance2d = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1052
1053 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 5)
1054 double distanceBp = GetBpDistance(m_frequency, a->GetPosition().z, b->GetPosition().z);
1055
1056 if (distance2d <= distanceBp)
1057 {
1058 shadowingStd = 4.0;
1059 }
1060 else
1061 {
1062 shadowingStd = 6.0;
1063 }
1064 }
1066 {
1067 shadowingStd = 8.0;
1068 }
1069 else
1070 {
1071 NS_FATAL_ERROR("Unknown channel condition");
1072 }
1073
1074 return shadowingStd;
1075}
1076
1077double
1080{
1081 NS_LOG_FUNCTION(this);
1082 double correlationDistance;
1083
1084 // See 3GPP TR 38.901, Table 7.5-6
1086 {
1087 correlationDistance = 37;
1088 }
1090 {
1091 correlationDistance = 120;
1092 }
1093 else
1094 {
1095 NS_FATAL_ERROR("Unknown channel condition");
1096 }
1097
1098 return correlationDistance;
1099}
1100
1101double
1102ThreeGppRmaPropagationLossModel::Pl1(double frequency, double distance3D, double h, double /* w */)
1103{
1104 double loss = 20.0 * log10(40.0 * M_PI * distance3D * frequency / 1e9 / 3.0) +
1105 std::min(0.03 * pow(h, 1.72), 10.0) * log10(distance3D) -
1106 std::min(0.044 * pow(h, 1.72), 14.77) + 0.002 * log10(h) * distance3D;
1107 return loss;
1108}
1109
1110double
1111ThreeGppRmaPropagationLossModel::GetBpDistance(double frequency, double hA, double hB)
1112{
1113 double distanceBp = 2.0 * M_PI * hA * hB * frequency / M_C;
1114 return distanceBp;
1115}
1116
1117// ------------------------------------------------------------------------- //
1118
1120
1121TypeId
1123{
1124 static TypeId tid = TypeId("ns3::ThreeGppUmaPropagationLossModel")
1126 .SetGroupName("Propagation")
1127 .AddConstructor<ThreeGppUmaPropagationLossModel>();
1128 return tid;
1129}
1130
1139
1144
1145double
1146ThreeGppUmaPropagationLossModel::GetBpDistance(double hUt, double hBs, double distance2D) const
1147{
1148 NS_LOG_FUNCTION(this);
1149
1150 // compute g (d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1151 double g = 0.0;
1152 if (distance2D > 18.0)
1153 {
1154 g = 5.0 / 4.0 * pow(distance2D / 100.0, 3) * exp(-distance2D / 150.0);
1155 }
1156
1157 // compute C (hUt, d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1158 double c = 0.0;
1159 if (hUt >= 13.0)
1160 {
1161 c = pow((hUt - 13.0) / 10.0, 1.5) * g;
1162 }
1163
1164 // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1165 double prob = 1.0 / (1.0 + c);
1166 double hE = 0.0;
1167 if (m_uniformVar->GetValue() < prob)
1168 {
1169 hE = 1.0;
1170 }
1171 else
1172 {
1173 int random = m_uniformVar->GetInteger(12, std::max(12, (int)(hUt - 1.5)));
1174 hE = (double)floor(random / 3.0) * 3.0;
1175 }
1176
1177 // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1178 double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
1179
1180 return distanceBp;
1181}
1182
1183double
1185{
1186 NS_LOG_FUNCTION(this);
1187
1188 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
1189
1190 // check if hBS and hUT are within the validity range
1191 if (hUt < 1.5 || hUt > 22.5)
1192 {
1193 NS_ABORT_MSG_IF(m_enforceRanges, "Uma UT height out of range");
1195 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
1196 }
1197
1198 if (hBs != 25.0)
1199 {
1200 NS_ABORT_MSG_IF(m_enforceRanges, "Uma BS height out of range");
1201 NS_LOG_WARN("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
1202 }
1203
1204 // NOTE The model is intended to be used for BS-UT links, however we may need to
1205 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1206 // interference. In order to apply the model, we need to retrieve the values of
1207 // hBS and hUT, but in these cases one of the two falls outside the validity
1208 // range and the warning message is printed (hBS for the UT-UT case and hUT
1209 // for the BS-BS case).
1210
1211 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
1212 double distanceBp = GetBpDistance(hUt, hBs, distance2D);
1213 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
1214
1215 // check if the distance is outside the validity range
1216 if (distance2D < 10.0 || distance2D > 5.0e3)
1217 {
1218 NS_ABORT_MSG_IF(m_enforceRanges, "Uma 2D distance out of range");
1219 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1220 "accurate");
1221 }
1222
1223 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1224 double loss = 0;
1225 if (distance2D <= distanceBp)
1226 {
1227 // use PL1
1228 loss = 28.0 + 22.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1229 }
1230 else
1231 {
1232 // use PL2
1233 loss = 28.0 + 40.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) -
1234 9.0 * log10(pow(distanceBp, 2) + pow(hBs - hUt, 2));
1235 }
1236
1237 NS_LOG_DEBUG("Loss " << loss);
1238
1239 return loss;
1240}
1241
1242double
1244{
1245 // distance2dIn is minimum of two independently generated uniformly distributed variables
1246 // between 0 and 25 m for UMa and UMi-Street Canyon. 2D−in d shall be UT-specifically generated.
1247 return std::min(m_randomO2iVar1->GetValue(0, 25), m_randomO2iVar2->GetValue(0, 25));
1248}
1249
1250double
1252{
1253 // distance2dIn is a single, link-specific, uniformly distributed variable between 0 and 25 m.
1254 return m_randomO2iVar1->GetValue(0, 25);
1255}
1256
1257double
1259{
1260 NS_LOG_FUNCTION(this);
1261
1262 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
1263
1264 // check if hBS and hUT are within the validity range
1265 if (hUt < 1.5 || hUt > 22.5)
1266 {
1267 NS_ABORT_MSG_IF(m_enforceRanges, "Uma UT height out of range");
1269 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
1270 }
1271
1272 if (hBs != 25.0)
1273 {
1274 NS_ABORT_MSG_IF(m_enforceRanges, "Uma BS height out of range");
1275 NS_LOG_WARN("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
1276 }
1277
1278 // NOTE The model is intended to be used for BS-UT links, however we may need to
1279 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1280 // interference. In order to apply the model, we need to retrieve the values of
1281 // hBS and hUT, but in these cases one of the two falls outside the validity
1282 // range and the warning message is printed (hBS for the UT-UT case and hUT
1283 // for the BS-BS case).
1284
1285 // check if the distance is outside the validity range
1286 if (distance2D < 10.0 || distance2D > 5.0e3)
1287 {
1288 NS_ABORT_MSG_IF(m_enforceRanges, "Uma 2D distance out of range");
1289 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1290 "accurate");
1291 }
1292
1293 // compute the pathloss
1294 double plNlos =
1295 13.54 + 39.08 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) - 0.6 * (hUt - 1.5);
1296 double loss = std::max(GetLossLos(a, b), plNlos);
1297 NS_LOG_DEBUG("Loss " << loss);
1298
1299 return loss;
1300}
1301
1302double
1304 Ptr<MobilityModel> /* b */,
1306{
1307 NS_LOG_FUNCTION(this);
1308 double shadowingStd;
1309 if (m_frequency < 6e9)
1310 {
1311 shadowingStd = 7.0;
1312 }
1313 else
1314 {
1316 {
1317 shadowingStd = 4.0;
1318 }
1320 {
1321 shadowingStd = 6.0;
1322 }
1323 else
1324 {
1325 NS_FATAL_ERROR("Unknown channel condition");
1326 }
1327 }
1328 return shadowingStd;
1329}
1330
1331double
1334{
1335 NS_LOG_FUNCTION(this);
1336 double correlationDistance;
1337
1338 // See 3GPP TR 38.901, Table 7.5-6
1340 {
1341 correlationDistance = 37;
1342 }
1344 {
1345 correlationDistance = 50;
1346 }
1347 else
1348 {
1349 NS_FATAL_ERROR("Unknown channel condition");
1350 }
1351
1352 return correlationDistance;
1353}
1354
1355int64_t
1357{
1358 NS_LOG_FUNCTION(this);
1359
1361 m_uniformVar->SetStream(stream);
1362 return stream + 1;
1363}
1364
1365// ------------------------------------------------------------------------- //
1366
1368
1369TypeId
1371{
1372 static TypeId tid = TypeId("ns3::ThreeGppUmiStreetCanyonPropagationLossModel")
1374 .SetGroupName("Propagation")
1376 return tid;
1377}
1378
1387
1392
1393double
1395 double hBs,
1396 double /* distance2D */) const
1397{
1398 NS_LOG_FUNCTION(this);
1399
1400 // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1401 double hE = 1.0;
1402
1403 // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1404 double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
1405
1406 return distanceBp;
1407}
1408
1409double
1411{
1412 // distance2dIn is minimum of two independently generated uniformly distributed variables
1413 // between 0 and 25 m for UMa and UMi-Street Canyon. 2D−in d shall be UT-specifically generated.
1414 return std::min(m_randomO2iVar1->GetValue(0, 25), m_randomO2iVar2->GetValue(0, 25));
1415}
1416
1417double
1419{
1420 // distance2dIn is a single, link-specific, uniformly distributed variable between 0 and 25 m.
1421 return m_randomO2iVar1->GetValue(0, 25);
1422}
1423
1424double
1426 Ptr<MobilityModel> b) const
1427{
1428 NS_LOG_FUNCTION(this);
1429
1430 double distance2D = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1431 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1432 auto [hBs, hUt] = GetBsUtHeightsUmiStreetCanyon(a->GetPosition().z, b->GetPosition().z);
1433
1434 // check if hBS and hUT are within the validity range
1435 if (hUt < 1.5 || hUt >= 10.0)
1436 {
1437 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon UT height out of range");
1439 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). "
1440 "We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
1441 }
1442
1443 if (hBs != 10.0)
1444 {
1445 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon BS height out of range");
1446 NS_LOG_WARN("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
1447 }
1448
1449 // NOTE The model is intended to be used for BS-UT links, however we may need to
1450 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1451 // interference. In order to apply the model, we need to retrieve the values of
1452 // hBS and hUT, but in these cases one of the two falls outside the validity
1453 // range and the warning message is printed (hBS for the UT-UT case and hUT
1454 // for the BS-BS case).
1455
1456 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
1457 double distanceBp = GetBpDistance(hUt, hBs, distance2D);
1458 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
1459
1460 // check if the distance is outside the validity range
1461 if (distance2D < 10.0 || distance2D > 5.0e3)
1462 {
1463 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon 2D distance out of range");
1464 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1465 "accurate");
1466 }
1467
1468 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1469 double loss = 0;
1470 if (distance2D <= distanceBp)
1471 {
1472 // use PL1
1473 loss = 32.4 + 21.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1474 }
1475 else
1476 {
1477 // use PL2
1478 loss = 32.4 + 40.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) -
1479 9.5 * log10(pow(distanceBp, 2) + pow(hBs - hUt, 2));
1480 }
1481
1482 NS_LOG_DEBUG("Loss " << loss);
1483
1484 return loss;
1485}
1486
1487double
1489 Ptr<MobilityModel> b) const
1490{
1491 NS_LOG_FUNCTION(this);
1492
1493 double distance2D = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1494 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1495 auto [hBs, hUt] = GetBsUtHeightsUmiStreetCanyon(a->GetPosition().z, b->GetPosition().z);
1496
1497 // check if hBS and hUT are within the validity range
1498 if (hUt < 1.5 || hUt >= 10.0)
1499 {
1500 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon UT height out of range");
1502 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). "
1503 "We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
1504 }
1505
1506 if (hBs != 10.0)
1507 {
1508 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon BS height out of range");
1509 NS_LOG_WARN("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
1510 }
1511
1512 // NOTE The model is intended to be used for BS-UT links, however we may need to
1513 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1514 // interference. In order to apply the model, we need to retrieve the values of
1515 // hBS and hUT, but in these cases one of the two falls outside the validity
1516 // range and the warning message is printed (hBS for the UT-UT case and hUT
1517 // for the BS-BS case).
1518
1519 // check if the distance is outside the validity range
1520 if (distance2D < 10.0 || distance2D > 5.0e3)
1521 {
1522 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon 2D distance out of range");
1523 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1524 "accurate");
1525 }
1526
1527 // compute the pathloss
1528 double plNlos =
1529 22.4 + 35.3 * log10(distance3D) + 21.3 * log10(m_frequency / 1e9) - 0.3 * (hUt - 1.5);
1530 double loss = std::max(GetLossLos(a, b), plNlos);
1531 NS_LOG_DEBUG("Loss " << loss);
1532
1533 return loss;
1534}
1535
1536double
1538 Ptr<MobilityModel> /* a */,
1539 Ptr<MobilityModel> /* b */,
1541{
1542 NS_LOG_FUNCTION(this);
1543 double shadowingStd;
1544
1545 if (m_frequency < 6e9)
1546 {
1547 shadowingStd = 7.0;
1548 }
1549 else
1550 {
1552 {
1553 shadowingStd = 4.0;
1554 }
1556 {
1557 shadowingStd = 7.82;
1558 }
1559 else
1560 {
1561 NS_FATAL_ERROR("Unknown channel condition");
1562 }
1563 }
1564 return shadowingStd;
1565}
1566
1567double
1570{
1571 NS_LOG_FUNCTION(this);
1572 double correlationDistance;
1573
1574 // See 3GPP TR 38.901, Table 7.5-6
1576 {
1577 correlationDistance = 10;
1578 }
1580 {
1581 correlationDistance = 13;
1582 }
1583 else
1584 {
1585 NS_FATAL_ERROR("Unknown channel condition");
1586 }
1587
1588 return correlationDistance;
1589}
1590
1591// ------------------------------------------------------------------------- //
1592
1594
1595TypeId
1597{
1598 static TypeId tid = TypeId("ns3::ThreeGppIndoorOfficePropagationLossModel")
1600 .SetGroupName("Propagation")
1602 return tid;
1603}
1604
1613
1618
1619double
1624
1625double
1627 Ptr<MobilityModel> b) const
1628{
1629 NS_LOG_FUNCTION(this);
1630
1631 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1632
1633 // check if the distance is outside the validity range
1634 if (distance3D < 1.0 || distance3D > 150.0)
1635 {
1636 NS_ABORT_MSG_IF(m_enforceRanges, "IndoorOffice 3D distance out of range");
1637 NS_LOG_WARN("The 3D distance is outside the validity range, the pathloss value may not be "
1638 "accurate");
1639 }
1640
1641 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1642 double loss = 32.4 + 17.3 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1643
1644 NS_LOG_DEBUG("Loss " << loss);
1645
1646 return loss;
1647}
1648
1649double
1651 Ptr<MobilityModel> b) const
1652{
1653 NS_LOG_FUNCTION(this);
1654
1655 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1656
1657 // check if the distance is outside the validity range
1658 if (distance3D < 1.0 || distance3D > 150.0)
1659 {
1660 NS_ABORT_MSG_IF(m_enforceRanges, "IndoorOffice 3D distance out of range");
1661 NS_LOG_WARN("The 3D distance is outside the validity range, the pathloss value may not be "
1662 "accurate");
1663 }
1664
1665 // compute the pathloss
1666 double plNlos = 17.3 + 38.3 * log10(distance3D) + 24.9 * log10(m_frequency / 1e9);
1667 double loss = std::max(GetLossLos(a, b), plNlos);
1668
1669 NS_LOG_DEBUG("Loss " << loss);
1670
1671 return loss;
1672}
1673
1674double
1676 Ptr<MobilityModel> /* a */,
1677 Ptr<MobilityModel> /* b */,
1679{
1680 NS_LOG_FUNCTION(this);
1681 double shadowingStd;
1682
1684 {
1685 shadowingStd = 3.0;
1686 }
1688 {
1689 shadowingStd = 8.03;
1690 }
1691 else
1692 {
1693 NS_FATAL_ERROR("Unknown channel condition");
1694 }
1695
1696 return shadowingStd;
1697}
1698
1699double
1702{
1703 NS_LOG_FUNCTION(this);
1704
1705 // See 3GPP TR 38.901, Table 7.5-6
1706 double correlationDistance;
1707
1709 {
1710 correlationDistance = 10;
1711 }
1713 {
1714 correlationDistance = 6;
1715 }
1716 else
1717 {
1718 NS_FATAL_ERROR("Unknown channel condition");
1719 }
1720
1721 return correlationDistance;
1722}
1723
1725
1726TypeId
1728{
1729 static TypeId tid = TypeId("ns3::ThreeGppNTNDenseUrbanPropagationLossModel")
1731 .SetGroupName("Propagation")
1733 return tid;
1734}
1735
1743
1748
1749double
1754
1755double
1757 Ptr<MobilityModel> b) const
1758{
1759 NS_LOG_FUNCTION(this);
1760 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1761 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1762
1763 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1764 auto [elevAngle, elevAngleQuantized] =
1766
1767 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1768 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1769
1770 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1771 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1772
1773 // Apply Ionospheric plus Tropospheric Scintillation Loss
1774 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1775
1776 NS_LOG_DEBUG("Loss " << loss);
1777 return loss;
1778}
1779
1780double
1782 Ptr<MobilityModel> b) const
1783{
1784 NS_LOG_FUNCTION(this);
1785 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1786 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1787
1788 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1789 auto [elevAngle, elevAngleQuantized] =
1791
1792 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1793 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1794
1795 // Apply Clutter Loss
1796 loss += ComputeClutterLoss(m_frequency, m_SFCL_DenseUrban, elevAngleQuantized);
1797
1798 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1799 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1800
1801 // Apply Ionospheric plus Tropospheric Scintillation Loss
1802 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1803
1804 NS_LOG_DEBUG("Loss " << loss);
1805 return loss;
1806}
1807
1808double
1813{
1814 NS_LOG_FUNCTION(this);
1815 double shadowingStd;
1816
1817 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
1818 auto [elevAngle, elevAngleQuantized] =
1820
1821 // Assign Shadowing Standard Deviation according to table 6.6.2-1
1822 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
1823 {
1824 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
1825 }
1826 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
1827 {
1828 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
1829 }
1830 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
1831 {
1832 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
1833 }
1834 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
1835 {
1836 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
1837 }
1838 else
1839 {
1840 NS_FATAL_ERROR("Unknown channel condition");
1841 }
1842
1843 return shadowingStd;
1844}
1845
1846double
1849{
1850 NS_LOG_FUNCTION(this);
1851 double correlationDistance;
1852
1853 // See 3GPP TR 38.811, Table 6.7.2-1a/b and Table 6.7.2-2a/b
1855 {
1856 correlationDistance = 37;
1857 }
1859 {
1860 correlationDistance = 50;
1861 }
1862 else
1863 {
1864 NS_FATAL_ERROR("Unknown channel condition");
1865 }
1866
1867 return correlationDistance;
1868}
1869
1870// ------------------------------------------------------------------------- //
1871
1873
1874TypeId
1876{
1877 static TypeId tid = TypeId("ns3::ThreeGppNTNUrbanPropagationLossModel")
1879 .SetGroupName("Propagation")
1880 .AddConstructor<ThreeGppNTNUrbanPropagationLossModel>();
1881 return tid;
1882}
1883
1891
1896
1897double
1902
1903double
1905{
1906 NS_LOG_FUNCTION(this);
1907 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1908 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1909
1910 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1911 auto [elevAngle, elevAngleQuantized] =
1913
1914 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1915 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1916
1917 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1918 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1919
1920 // Apply Ionospheric plus Tropospheric Scintillation Loss
1921 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1922
1923 NS_LOG_DEBUG("Loss " << loss);
1924 return loss;
1925}
1926
1927double
1929{
1930 NS_LOG_FUNCTION(this);
1931 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1932 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1933
1934 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1935 auto [elevAngle, elevAngleQuantized] =
1937
1938 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1939 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1940
1941 // Apply Clutter Loss
1942 loss += ComputeClutterLoss(m_frequency, m_SFCL_Urban, elevAngleQuantized);
1943
1944 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1945 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1946
1947 // Apply Ionospheric plus Tropospheric Scintillation Loss
1948 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1949
1950 NS_LOG_DEBUG("Loss " << loss);
1951 return loss;
1952}
1953
1954double
1959{
1960 NS_LOG_FUNCTION(this);
1961 double shadowingStd;
1962
1963 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
1964 auto [elevAngle, elevAngleQuantized] =
1966
1967 // Assign Shadowing Standard Deviation according to table 6.6.2-1
1968 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
1969 {
1970 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
1971 }
1972 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
1973 {
1974 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
1975 }
1976 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
1977 {
1978 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
1979 }
1980 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
1981 {
1982 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
1983 }
1984 else
1985 {
1986 NS_FATAL_ERROR("Unknown channel condition");
1987 }
1988
1989 return shadowingStd;
1990}
1991
1992double
1995{
1996 NS_LOG_FUNCTION(this);
1997 double correlationDistance;
1998
1999 // See 3GPP TR 38.811, Table 6.7.2-3a/b and Table 6.7.2-3a/b
2001 {
2002 correlationDistance = 37;
2003 }
2005 {
2006 correlationDistance = 50;
2007 }
2008 else
2009 {
2010 NS_FATAL_ERROR("Unknown channel condition");
2011 }
2012
2013 return correlationDistance;
2014}
2015
2016// ------------------------------------------------------------------------- //
2017
2019
2020TypeId
2022{
2023 static TypeId tid = TypeId("ns3::ThreeGppNTNSuburbanPropagationLossModel")
2025 .SetGroupName("Propagation")
2026 .AddConstructor<ThreeGppNTNSuburbanPropagationLossModel>();
2027 return tid;
2028}
2029
2037
2042
2043double
2048
2049double
2051 Ptr<MobilityModel> b) const
2052{
2053 NS_LOG_FUNCTION(this);
2054 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2055 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2056
2057 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2058 auto [elevAngle, elevAngleQuantized] =
2060
2061 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2062 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2063
2064 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2065 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2066
2067 // Apply Ionospheric plus Tropospheric Scintillation Loss
2068 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2069
2070 NS_LOG_DEBUG("Loss " << loss);
2071
2072 return loss;
2073}
2074
2075double
2077 Ptr<MobilityModel> b) const
2078{
2079 NS_LOG_FUNCTION(this);
2080 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2081 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2082
2083 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2084 auto [elevAngle, elevAngleQuantized] =
2086
2087 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2088 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2089
2090 // Apply Clutter Loss
2091 loss += ComputeClutterLoss(m_frequency, m_SFCL_SuburbanRural, elevAngleQuantized);
2092
2093 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2094 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2095
2096 // Apply Ionospheric plus Tropospheric Scintillation Loss
2097 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2098
2099 NS_LOG_DEBUG("Loss " << loss);
2100 return loss;
2101}
2102
2103double
2108{
2109 NS_LOG_FUNCTION(this);
2110 double shadowingStd;
2111
2112 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
2113 auto [elevAngle, elevAngleQuantized] =
2115
2116 // Assign Shadowing Standard Deviation according to table 6.6.2-1
2117 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
2118 {
2119 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
2120 }
2121 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
2122 {
2123 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
2124 }
2125 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
2126 {
2127 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
2128 }
2129 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
2130 {
2131 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
2132 }
2133 else
2134 {
2135 NS_FATAL_ERROR("Unknown channel condition");
2136 }
2137
2138 return shadowingStd;
2139}
2140
2141double
2144{
2145 NS_LOG_FUNCTION(this);
2146 double correlationDistance;
2147
2148 // See 3GPP TR 38.811, Table 6.7.2-5a/b and Table 6.7.2-6a/b
2150 {
2151 correlationDistance = 37;
2152 }
2154 {
2155 correlationDistance = 50;
2156 }
2157 else
2158 {
2159 NS_FATAL_ERROR("Unknown channel condition");
2160 }
2161
2162 return correlationDistance;
2163}
2164
2165// ------------------------------------------------------------------------- //
2166
2168
2169TypeId
2171{
2172 static TypeId tid = TypeId("ns3::ThreeGppNTNRuralPropagationLossModel")
2174 .SetGroupName("Propagation")
2175 .AddConstructor<ThreeGppNTNRuralPropagationLossModel>();
2176 return tid;
2177}
2178
2186
2191
2192double
2197
2198double
2200{
2201 NS_LOG_FUNCTION(this);
2202 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2203 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2204
2205 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2206 auto [elevAngle, elevAngleQuantized] =
2208
2209 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2210 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2211
2212 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2213 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2214
2215 // Apply Ionospheric plus Tropospheric Scintillation Loss
2216 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2217
2218 NS_LOG_DEBUG("Loss " << loss);
2219 return loss;
2220}
2221
2222double
2224{
2225 NS_LOG_FUNCTION(this);
2226 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2227 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2228
2229 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2230 auto [elevAngle, elevAngleQuantized] =
2232
2233 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2234 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2235
2236 // Apply Clutter Loss
2237 loss += ComputeClutterLoss(m_frequency, m_SFCL_SuburbanRural, elevAngleQuantized);
2238
2239 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2240 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2241
2242 // Apply Ionospheric plus Tropospheric Scintillation Loss
2243 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2244
2245 NS_LOG_DEBUG("Loss " << loss);
2246 return loss;
2247}
2248
2249double
2254{
2255 NS_LOG_FUNCTION(this);
2256 double shadowingStd;
2257
2258 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
2259 auto [elevAngle, elevAngleQuantized] =
2261
2262 // Assign Shadowing Standard Deviation according to table 6.6.2-1
2263 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
2264 {
2265 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
2266 }
2267 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
2268 {
2269 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
2270 }
2271 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
2272 {
2273 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
2274 }
2275 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
2276 {
2277 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
2278 }
2279 else
2280 {
2281 NS_FATAL_ERROR("Unknown channel condition");
2282 }
2283
2284 return shadowingStd;
2285}
2286
2287double
2290{
2291 NS_LOG_FUNCTION(this);
2292 double correlationDistance;
2293
2294 // See 3GPP TR 38.811, Table 6.7.2-7a/b and Table 6.7.2-8a/b
2296 {
2297 correlationDistance = 37;
2298 }
2300 {
2301 correlationDistance = 120;
2302 }
2303 else
2304 {
2305 NS_FATAL_ERROR("Unknown channel condition");
2306 }
2307
2308 return correlationDistance;
2309}
2310
2311} // namespace ns3
cairo_uint64_t x
_cairo_uint_96by64_32x64_divrem:
AttributeValue implementation for Boolean.
Definition boolean.h:26
O2iConditionValue
Possible values for Outdoor to Indoor condition.
@ LOW
Low Penetration Losses.
@ HIGH
High Penetration Losses.
LosConditionValue
Possible values for Line-of-Sight condition.
@ NLOSv
Non Line of Sight due to a vehicle.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
A network Node.
Definition node.h:46
uint32_t GetId() const
Definition node.cc:106
AttributeValue implementation for Pointer.
Definition pointer.h:37
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
static double Calculate2dDistance(const Vector &a, const Vector &b)
Computes the 2D distance between two 3D vectors.
static std::tuple< double, double > GetQuantizedElevationAngle(Ptr< const MobilityModel > a, Ptr< const MobilityModel > b)
Computes and quantizes the elevation angle to a two-digits integer in [10, 90].
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the Indoor Office scenario...
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
Implements the pathloss model defined in 3GPP TR 38.811, Table ?
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
const std::map< int, std::vector< float > > * m_SFCL_DenseUrban
The nested map containing the Shadow Fading and Clutter Loss values for the NTN Dense Urban scenario.
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
Implements the pathloss model defined in 3GPP TR 38.811, Table ?
const std::map< int, std::vector< float > > * m_SFCL_SuburbanRural
The nested map containing the Shadow Fading and Clutter Loss values for the NTN Suburban and Rural sc...
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
Implements the pathloss model defined in 3GPP TR 38.811, Table ?
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
const std::map< int, std::vector< float > > * m_SFCL_SuburbanRural
The nested map containing the Shadow Fading and Clutter Loss values for the NTN Suburban and Rural sc...
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
Implements the pathloss model defined in 3GPP TR 38.811, Table ?
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
const std::map< int, std::vector< float > > * m_SFCL_Urban
The nested map containing the Shadow Fading and Clutter Loss values for the NTN Urban scenario.
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
Ptr< ChannelConditionModel > GetChannelConditionModel() const
Returns the associated channel condition model.
virtual double GetO2iLowPenetrationLoss(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const
Retrieves the o2i building penetration loss value by looking at m_o2iLossMap.
Ptr< UniformRandomVariable > m_randomO2iVar2
a uniform random variable for the calculation of the indoor loss, see TR38.901 Table 7....
double m_meanVehicleO2iLoss
normal cars (9dB), cars with metal coated glass panels (20dB)
double GetFrequency() const
Return the current central frequency.
double GetLoss(Ptr< ChannelCondition > cond, Ptr< MobilityModel > a, Ptr< MobilityModel > b) const
Computes the pathloss between a and b.
Ptr< UniformRandomVariable > m_randomO2iVar1
a uniform random variable for the calculation of the indoor loss, see TR38.901 Table 7....
double GetShadowing(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const
Retrieves the shadowing value by looking at m_shadowingMap.
static double Calculate2dDistance(Vector a, Vector b)
Computes the 2D distance between two 3D vectors.
void SetChannelConditionModel(Ptr< ChannelConditionModel > model)
Set the channel condition model used to determine the channel state (e.g., the LOS/NLOS condition).
std::unordered_map< uint32_t, ShadowingMapItem > m_shadowingMap
map to store the shadowing values
virtual double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const =0
Computes the pathloss between a and b considering that the line of sight is obstructed.
virtual bool DoIsO2iLowPenetrationLoss(Ptr< const ChannelCondition > cond) const
Indicates the condition of the o2i building penetration loss (defined in 3GPP TR 38....
int64_t DoAssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
virtual double GetLossNlosv(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const
Computes the pathloss between a and b considering that the line of sight is obstructed by a vehicle.
Ptr< NormalRandomVariable > m_normalO2iVehicularLossVar
a normal random variable for the calculation of penetration loss for vehicles see TR38....
virtual double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const =0
Returns the shadow fading correlation distance.
Ptr< NormalRandomVariable > m_normRandomVariable
normal random variable
Ptr< ChannelConditionModel > m_channelConditionModel
pointer to the channel condition model
void NotifyConstructionCompleted() override
Notifier called once the ObjectBase is fully constructed.
std::unordered_map< uint32_t, O2iLossMapItem > m_o2iLossMap
map to store the o2i Loss values
virtual double GetO2iDistance2dIn() const =0
Returns the minimum of the two independently generated distances according to the uniform distributio...
std::unordered_map< uint32_t, double > m_o2iVehicularUtLossMap
vehicular O2I loss for each individual UT with speed x, such that 30 < x <= 120 km/h.
virtual double GetO2iHighPenetrationLoss(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const
Retrieves the o2i building penetration loss value by looking at m_o2iLossMap.
bool IsO2iLowPenetrationLoss(Ptr< const ChannelCondition > cond) const
Return true if the O2I Building Penetration loss corresponds to a low loss condition.
virtual double GetO2iDistance2dInSub6Ghz() const
Returns a a single, link-specific, uniformly distributed variable value depending on the specific 3GP...
void SetFrequency(double f)
Set the central frequency of the model.
void ClearO2iLossCacheMap()
Clear cached O2I Building Penetration loss.
void DoDispose() override
Destructor implementation.
static uint32_t GetKey(Ptr< MobilityModel > a, Ptr< MobilityModel > b)
Returns an unique key for the channel between a and b.
Ptr< NormalRandomVariable > m_normalO2iLowLossVar
a normal random variable for the calculation of 02i low loss, see TR38.901 Table 7....
bool m_enforceRanges
strictly enforce TR 38.901 parameter ranges
virtual double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const =0
Returns the shadow fading standard deviation.
Ptr< NormalRandomVariable > m_normalO2iHighLossVar
a normal random variable for the calculation of 02i high loss, see TR38.901 Table 7....
double DoCalcRxPower(double txPowerDbm, Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the received power by applying the pathloss model described in 3GPP TR 38....
double GetO2iSub6GhzPenetrationLoss(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const
Retrieves the o2i building penetration loss value by looking at m_o2iLossMap.
static Vector GetVectorDifference(Ptr< MobilityModel > a, Ptr< MobilityModel > b)
Get the difference between the node position.
bool m_buildingPenLossesEnabled
enable/disable building penetration losses
double GetO2iVehicularLoss(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::O2iConditionValue cond) const
Computes the o2i vehicular penetration loss by looking at m_o2iVehicularUtLossMap.
virtual double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const =0
Computes the pathloss between a and b considering that the line of sight is not obstructed.
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the RMa scenario.
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
static double Pl1(double frequency, double distance3D, double h, double w)
Computes the PL1 formula for the RMa scenario.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
double m_h
average building height in meters
static double GetBpDistance(double frequency, double hA, double hB)
Computes the breakpoint distance for the RMa scenario.
bool DoIsO2iLowPenetrationLoss(Ptr< const ChannelCondition > cond) const override
Indicates the condition of the o2i building penetration loss (defined in 3GPP TR 38....
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the UMa scenario.
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetBpDistance(double hUt, double hBs, double distance2D) const
Computes the breakpoint distance.
int64_t DoAssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
Ptr< UniformRandomVariable > m_uniformVar
a uniform random variable used for the computation of the breakpoint distance
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetO2iDistance2dInSub6Ghz() const override
Returns a a single, link-specific, uniformly distributed variable value depending on the specific 3GP...
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
Implements the pathloss model defined in 3GPP TR 38.901, Table 7.4.1-1 for the UMi-Street Canyon scen...
double GetO2iDistance2dInSub6Ghz() const override
Returns a a single, link-specific, uniformly distributed variable value depending on the specific 3GP...
double GetLossNlos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is obstructed.
double GetShadowingStd(Ptr< MobilityModel > a, Ptr< MobilityModel > b, ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading standard deviation.
double GetBpDistance(double hUt, double hBs, double distance2D) const
Computes the breakpoint distance.
double GetO2iDistance2dIn() const override
Returns the minimum of the two independently generated distances according to the uniform distributio...
double GetLossLos(Ptr< MobilityModel > a, Ptr< MobilityModel > b) const override
Computes the pathloss between a and b considering that the line of sight is not obstructed.
double GetShadowingCorrelationDistance(ChannelCondition::LosConditionValue cond) const override
Returns the shadow fading correlation distance.
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
a 2d vector
Definition vector.h:196
double GetLength() const
Compute the length (magnitude) of the vector.
Definition vector.cc:77
#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:75
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:114
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition double.h:32
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:249
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:270
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition abort.h:133
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
const std::map< int, std::vector< float > > SFCL_SuburbanRural
The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the NTN Suburba...
double ComputeIonosphericPlusTroposphericScintillationLoss(double freq, double elevAngleQuantized)
Computes the ionospheric plus tropospheric scintillation loss using the formulas described in 3GPP TR...
std::tuple< double, double, double, double > GetBsUtDistancesAndHeights(ns3::Ptr< const ns3::MobilityModel > a, ns3::Ptr< const ns3::MobilityModel > b)
Get the base station and user terminal relative distances and heights.
double ComputeAtmosphericAbsorptionLoss(double freq, double elevAngle)
Computes the atmospheric absorption loss using the formula described in 3GPP TR 38....
double ComputeNtnPathloss(double freq, double dist3d)
Computes the free-space path loss using the formula described in 3GPP TR 38.811, Table 6....
const double atmosphericAbsorption[101]
Array containing the attenuation given by atmospheric absorption.
const std::map< int, float > troposphericScintillationLoss
Map containing the Tropospheric attenuation in dB with 99% probability at 20 GHz in Toulouse used for...
const std::map< int, std::vector< float > > SFCL_Urban
The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the NTN Urban s...
double ComputeClutterLoss(double freq, const std::map< int, std::vector< float > > *sfcl, double elevAngleQuantized)
Computes the clutter loss using the formula described in 3GPP TR 38.811, Sec 6.6.6....
SFCL_params
The enumerator used for code clarity when performing parameter assignment in the GetLoss Methods.
std::tuple< double, double > GetBsUtHeightsUmiStreetCanyon(double heightA, double heightB)
Get the base station and user terminal heights for the UmiStreetCanyon scenario.
const std::map< int, std::vector< float > > SFCL_DenseUrban
The map containing the 3GPP value regarding Shadow Fading and Clutter Loss tables for the NTN Dense U...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double CalculateDistance(const Vector3D &a, const Vector3D &b)
Definition vector.cc:98