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 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 {
856 m_o2iVehicularUtLossMap[idNode] = 0.0;
858 "O2I loss for high-speed (>120 km/h) transit and satellites not implemented");
859 }
860
861 // Sum vehicle individual losses
863 {
864 o2iVehicularLoss += m_o2iVehicularUtLossMap.at(idNode);
865 }
866 }
867 }
868 return o2iVehicularLoss;
869}
870
871// ------------------------------------------------------------------------- //
872
874
875TypeId
877{
878 static TypeId tid = TypeId("ns3::ThreeGppRmaPropagationLossModel")
880 .SetGroupName("Propagation")
881 .AddConstructor<ThreeGppRmaPropagationLossModel>()
882 .AddAttribute("AvgBuildingHeight",
883 "The average building height in meters.",
884 DoubleValue(5.0),
886 MakeDoubleChecker<double>(5.0, 50.0))
887 .AddAttribute("AvgStreetWidth",
888 "The average street width in meters.",
889 DoubleValue(20.0),
891 MakeDoubleChecker<double>(5.0, 50.0));
892 return tid;
893}
894
903
908
909double
911{
912 // distance2dIn is minimum of two independently generated uniformly distributed variables
913 // between 0 and 10 m for RMa. 2D−in d shall be UT-specifically generated.
914 return std::min(m_randomO2iVar1->GetValue(0, 10), m_randomO2iVar2->GetValue(0, 10));
915}
916
917bool
919 [[maybe_unused]]) const
920{
921 // Based on 3GPP 38.901 7.4.3.1 in RMa only low losses are applied.
922 // Therefore enforce low losses.
923 return true;
924}
925
926double
928{
929 NS_LOG_FUNCTION(this);
930 NS_ASSERT_MSG(m_frequency <= 30.0e9,
931 "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
932
933 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
934
935 // check if hBS and hUT are within the specified validity range
936 if (hUt < 1.0 || hUt > 10.0)
937 {
938 NS_ABORT_MSG_IF(m_enforceRanges, "Rma UT height out of range");
940 "The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
941 }
942
943 if (hBs < 10.0 || hBs > 150.0)
944 {
945 NS_ABORT_MSG_IF(m_enforceRanges, "Rma BS height out of range");
947 "The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
948 }
949
950 // NOTE The model is intended to be used for BS-UT links, however we may need to
951 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
952 // interference. In order to apply the model, we need to retrieve the values of
953 // hBS and hUT, but in these cases one of the two falls outside the validity
954 // range and the warning message is printed (hBS for the UT-UT case and hUT
955 // for the BS-BS case).
956
957 double distanceBp = GetBpDistance(m_frequency, hBs, hUt);
958 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
960 distanceBp > 0,
961 "Breakpoint distance is zero (divide-by-zero below); are either hBs or hUt = 0?");
962
963 // check if the distance is outside the validity range
964 if (distance2D < 10.0 || distance2D > 10.0e3)
965 {
966 NS_ABORT_MSG_IF(m_enforceRanges, "Rma distance2D out of range");
967 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
968 "accurate");
969 }
970
971 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
972 double loss = 0;
973 if (distance2D <= distanceBp)
974 {
975 // use PL1
976 loss = Pl1(m_frequency, distance3D, m_h, m_w);
977 }
978 else
979 {
980 // use PL2
981 loss = Pl1(m_frequency, distanceBp, m_h, m_w) + 40 * log10(distance3D / distanceBp);
982 }
983
984 NS_LOG_DEBUG("Loss " << loss);
985
986 return loss;
987}
988
989double
991{
992 NS_LOG_FUNCTION(this);
993 NS_ASSERT_MSG(m_frequency <= 30.0e9,
994 "RMa scenario is valid for frequencies between 0.5 and 30 GHz.");
995
996 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
997
998 // check if hBs and hUt are within the validity range
999 if (hUt < 1.0 || hUt > 10.0)
1000 {
1001 NS_ABORT_MSG_IF(m_enforceRanges, "Rma UT height out of range");
1003 "The height of the UT should be between 1 and 10 m (see TR 38.901, Table 7.4.1-1)");
1004 }
1005
1006 if (hBs < 10.0 || hBs > 150.0)
1007 {
1008 NS_ABORT_MSG_IF(m_enforceRanges, "Rma BS height out of range");
1010 "The height of the BS should be between 10 and 150 m (see TR 38.901, Table 7.4.1-1)");
1011 }
1012
1013 // NOTE The model is intended to be used for BS-UT links, however we may need to
1014 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1015 // interference. In order to apply the model, we need to retrieve the values of
1016 // hBS and hUT, but in these cases one of the two falls outside the validity
1017 // range and the warning message is printed (hBS for the UT-UT case and hUT
1018 // for the BS-BS case).
1019
1020 // check if the distance is outside the validity range
1021 if (distance2D < 10.0 || distance2D > 5.0e3)
1022 {
1023 NS_ABORT_MSG_IF(m_enforceRanges, "distance2D out of range");
1024 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1025 "accurate");
1026 }
1027
1028 // compute the pathloss
1029 double plNlos = 161.04 - 7.1 * log10(m_w) + 7.5 * log10(m_h) -
1030 (24.37 - 3.7 * pow((m_h / hBs), 2)) * log10(hBs) +
1031 (43.42 - 3.1 * log10(hBs)) * (log10(distance3D) - 3.0) +
1032 20.0 * log10(m_frequency / 1e9) - (3.2 * pow(log10(11.75 * hUt), 2) - 4.97);
1033
1034 double loss = std::max(GetLossLos(a, b), plNlos);
1035
1036 NS_LOG_DEBUG("Loss " << loss);
1037
1038 return loss;
1039}
1040
1041double
1045{
1046 NS_LOG_FUNCTION(this);
1047 double shadowingStd;
1048
1050 {
1051 // compute the 2D distance between the two nodes
1052 double distance2d = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1053
1054 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 5)
1055 double distanceBp = GetBpDistance(m_frequency, a->GetPosition().z, b->GetPosition().z);
1056
1057 if (distance2d <= distanceBp)
1058 {
1059 shadowingStd = 4.0;
1060 }
1061 else
1062 {
1063 shadowingStd = 6.0;
1064 }
1065 }
1067 {
1068 shadowingStd = 8.0;
1069 }
1070 else
1071 {
1072 NS_FATAL_ERROR("Unknown channel condition");
1073 }
1074
1075 return shadowingStd;
1076}
1077
1078double
1081{
1082 NS_LOG_FUNCTION(this);
1083 double correlationDistance;
1084
1085 // See 3GPP TR 38.901, Table 7.5-6
1087 {
1088 correlationDistance = 37;
1089 }
1091 {
1092 correlationDistance = 120;
1093 }
1094 else
1095 {
1096 NS_FATAL_ERROR("Unknown channel condition");
1097 }
1098
1099 return correlationDistance;
1100}
1101
1102double
1103ThreeGppRmaPropagationLossModel::Pl1(double frequency, double distance3D, double h, double /* w */)
1104{
1105 double loss = 20.0 * log10(40.0 * M_PI * distance3D * frequency / 1e9 / 3.0) +
1106 std::min(0.03 * pow(h, 1.72), 10.0) * log10(distance3D) -
1107 std::min(0.044 * pow(h, 1.72), 14.77) + 0.002 * log10(h) * distance3D;
1108 return loss;
1109}
1110
1111double
1112ThreeGppRmaPropagationLossModel::GetBpDistance(double frequency, double hA, double hB)
1113{
1114 double distanceBp = 2.0 * M_PI * hA * hB * frequency / M_C;
1115 return distanceBp;
1116}
1117
1118// ------------------------------------------------------------------------- //
1119
1121
1122TypeId
1124{
1125 static TypeId tid = TypeId("ns3::ThreeGppUmaPropagationLossModel")
1127 .SetGroupName("Propagation")
1128 .AddConstructor<ThreeGppUmaPropagationLossModel>();
1129 return tid;
1130}
1131
1140
1145
1146double
1147ThreeGppUmaPropagationLossModel::GetBpDistance(double hUt, double hBs, double distance2D) const
1148{
1149 NS_LOG_FUNCTION(this);
1150
1151 // compute g (d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1152 double g = 0.0;
1153 if (distance2D > 18.0)
1154 {
1155 g = 5.0 / 4.0 * pow(distance2D / 100.0, 3) * exp(-distance2D / 150.0);
1156 }
1157
1158 // compute C (hUt, d2D) (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1159 double c = 0.0;
1160 if (hUt >= 13.0)
1161 {
1162 c = pow((hUt - 13.0) / 10.0, 1.5) * g;
1163 }
1164
1165 // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1166 double prob = 1.0 / (1.0 + c);
1167 double hE = 0.0;
1168 if (m_uniformVar->GetValue() < prob)
1169 {
1170 hE = 1.0;
1171 }
1172 else
1173 {
1174 int random = m_uniformVar->GetInteger(12, std::max(12, (int)(hUt - 1.5)));
1175 hE = (double)floor(random / 3.0) * 3.0;
1176 }
1177
1178 // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1179 double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
1180
1181 return distanceBp;
1182}
1183
1184double
1186{
1187 NS_LOG_FUNCTION(this);
1188
1189 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
1190
1191 // check if hBS and hUT are within the validity range
1192 if (hUt < 1.5 || hUt > 22.5)
1193 {
1194 NS_ABORT_MSG_IF(m_enforceRanges, "Uma UT height out of range");
1196 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
1197 }
1198
1199 if (hBs != 25.0)
1200 {
1201 NS_ABORT_MSG_IF(m_enforceRanges, "Uma BS height out of range");
1202 NS_LOG_WARN("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
1203 }
1204
1205 // NOTE The model is intended to be used for BS-UT links, however we may need to
1206 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1207 // interference. In order to apply the model, we need to retrieve the values of
1208 // hBS and hUT, but in these cases one of the two falls outside the validity
1209 // range and the warning message is printed (hBS for the UT-UT case and hUT
1210 // for the BS-BS case).
1211
1212 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
1213 double distanceBp = GetBpDistance(hUt, hBs, distance2D);
1214 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
1215
1216 // check if the distance is outside the validity range
1217 if (distance2D < 10.0 || distance2D > 5.0e3)
1218 {
1219 NS_ABORT_MSG_IF(m_enforceRanges, "Uma 2D distance out of range");
1220 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1221 "accurate");
1222 }
1223
1224 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1225 double loss = 0;
1226 if (distance2D <= distanceBp)
1227 {
1228 // use PL1
1229 loss = 28.0 + 22.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1230 }
1231 else
1232 {
1233 // use PL2
1234 loss = 28.0 + 40.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) -
1235 9.0 * log10(pow(distanceBp, 2) + pow(hBs - hUt, 2));
1236 }
1237
1238 NS_LOG_DEBUG("Loss " << loss);
1239
1240 return loss;
1241}
1242
1243double
1245{
1246 // distance2dIn is minimum of two independently generated uniformly distributed variables
1247 // between 0 and 25 m for UMa and UMi-Street Canyon. 2D−in d shall be UT-specifically generated.
1248 return std::min(m_randomO2iVar1->GetValue(0, 25), m_randomO2iVar2->GetValue(0, 25));
1249}
1250
1251double
1253{
1254 // distance2dIn is a single, link-specific, uniformly distributed variable between 0 and 25 m.
1255 return m_randomO2iVar1->GetValue(0, 25);
1256}
1257
1258double
1260{
1261 NS_LOG_FUNCTION(this);
1262
1263 auto [distance2D, distance3D, hBs, hUt] = GetBsUtDistancesAndHeights(a, b);
1264
1265 // check if hBS and hUT are within the validity range
1266 if (hUt < 1.5 || hUt > 22.5)
1267 {
1268 NS_ABORT_MSG_IF(m_enforceRanges, "Uma UT height out of range");
1270 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1)");
1271 }
1272
1273 if (hBs != 25.0)
1274 {
1275 NS_ABORT_MSG_IF(m_enforceRanges, "Uma BS height out of range");
1276 NS_LOG_WARN("The height of the BS should be equal to 25 m (see TR 38.901, Table 7.4.1-1)");
1277 }
1278
1279 // NOTE The model is intended to be used for BS-UT links, however we may need to
1280 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1281 // interference. In order to apply the model, we need to retrieve the values of
1282 // hBS and hUT, but in these cases one of the two falls outside the validity
1283 // range and the warning message is printed (hBS for the UT-UT case and hUT
1284 // for the BS-BS case).
1285
1286 // check if the distance is outside the validity range
1287 if (distance2D < 10.0 || distance2D > 5.0e3)
1288 {
1289 NS_ABORT_MSG_IF(m_enforceRanges, "Uma 2D distance out of range");
1290 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1291 "accurate");
1292 }
1293
1294 // compute the pathloss
1295 double plNlos =
1296 13.54 + 39.08 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) - 0.6 * (hUt - 1.5);
1297 double loss = std::max(GetLossLos(a, b), plNlos);
1298 NS_LOG_DEBUG("Loss " << loss);
1299
1300 return loss;
1301}
1302
1303double
1305 Ptr<MobilityModel> /* b */,
1307{
1308 NS_LOG_FUNCTION(this);
1309 double shadowingStd;
1310 if (m_frequency < 6e9)
1311 {
1312 shadowingStd = 7.0;
1313 }
1314 else
1315 {
1317 {
1318 shadowingStd = 4.0;
1319 }
1321 {
1322 shadowingStd = 6.0;
1323 }
1324 else
1325 {
1326 NS_FATAL_ERROR("Unknown channel condition");
1327 }
1328 }
1329 return shadowingStd;
1330}
1331
1332double
1335{
1336 NS_LOG_FUNCTION(this);
1337 double correlationDistance;
1338
1339 // See 3GPP TR 38.901, Table 7.5-6
1341 {
1342 correlationDistance = 37;
1343 }
1345 {
1346 correlationDistance = 50;
1347 }
1348 else
1349 {
1350 NS_FATAL_ERROR("Unknown channel condition");
1351 }
1352
1353 return correlationDistance;
1354}
1355
1356int64_t
1358{
1359 NS_LOG_FUNCTION(this);
1360
1361 int64_t streams = ThreeGppPropagationLossModel::DoAssignStreams(stream);
1362 m_uniformVar->SetStream(stream + streams);
1363 return streams + 1;
1364}
1365
1366// ------------------------------------------------------------------------- //
1367
1369
1370TypeId
1372{
1373 static TypeId tid = TypeId("ns3::ThreeGppUmiStreetCanyonPropagationLossModel")
1375 .SetGroupName("Propagation")
1377 return tid;
1378}
1379
1388
1393
1394double
1396 double hBs,
1397 double /* distance2D */) const
1398{
1399 NS_LOG_FUNCTION(this);
1400
1401 // compute hE (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1402 double hE = 1.0;
1403
1404 // compute dBP' (see 3GPP TR 38.901, Table 7.4.1-1, Note 1)
1405 double distanceBp = 4 * (hBs - hE) * (hUt - hE) * m_frequency / M_C;
1406
1407 return distanceBp;
1408}
1409
1410double
1412{
1413 // distance2dIn is minimum of two independently generated uniformly distributed variables
1414 // between 0 and 25 m for UMa and UMi-Street Canyon. 2D−in d shall be UT-specifically generated.
1415 return std::min(m_randomO2iVar1->GetValue(0, 25), m_randomO2iVar2->GetValue(0, 25));
1416}
1417
1418double
1420{
1421 // distance2dIn is a single, link-specific, uniformly distributed variable between 0 and 25 m.
1422 return m_randomO2iVar1->GetValue(0, 25);
1423}
1424
1425double
1427 Ptr<MobilityModel> b) const
1428{
1429 NS_LOG_FUNCTION(this);
1430
1431 double distance2D = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1432 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1433 auto [hBs, hUt] = GetBsUtHeightsUmiStreetCanyon(a->GetPosition().z, b->GetPosition().z);
1434
1435 // check if hBS and hUT are within the validity range
1436 if (hUt < 1.5 || hUt >= 10.0)
1437 {
1438 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon UT height out of range");
1440 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). "
1441 "We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
1442 }
1443
1444 if (hBs != 10.0)
1445 {
1446 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon BS height out of range");
1447 NS_LOG_WARN("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
1448 }
1449
1450 // NOTE The model is intended to be used for BS-UT links, however we may need to
1451 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1452 // interference. In order to apply the model, we need to retrieve the values of
1453 // hBS and hUT, but in these cases one of the two falls outside the validity
1454 // range and the warning message is printed (hBS for the UT-UT case and hUT
1455 // for the BS-BS case).
1456
1457 // compute the breakpoint distance (see 3GPP TR 38.901, Table 7.4.1-1, note 1)
1458 double distanceBp = GetBpDistance(hUt, hBs, distance2D);
1459 NS_LOG_DEBUG("breakpoint distance " << distanceBp);
1460
1461 // check if the distance is outside the validity range
1462 if (distance2D < 10.0 || distance2D > 5.0e3)
1463 {
1464 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon 2D distance out of range");
1465 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1466 "accurate");
1467 }
1468
1469 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1470 double loss = 0;
1471 if (distance2D <= distanceBp)
1472 {
1473 // use PL1
1474 loss = 32.4 + 21.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1475 }
1476 else
1477 {
1478 // use PL2
1479 loss = 32.4 + 40.0 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9) -
1480 9.5 * log10(pow(distanceBp, 2) + pow(hBs - hUt, 2));
1481 }
1482
1483 NS_LOG_DEBUG("Loss " << loss);
1484
1485 return loss;
1486}
1487
1488double
1490 Ptr<MobilityModel> b) const
1491{
1492 NS_LOG_FUNCTION(this);
1493
1494 double distance2D = Calculate2dDistance(a->GetPosition(), b->GetPosition());
1495 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1496 auto [hBs, hUt] = GetBsUtHeightsUmiStreetCanyon(a->GetPosition().z, b->GetPosition().z);
1497
1498 // check if hBS and hUT are within the validity range
1499 if (hUt < 1.5 || hUt >= 10.0)
1500 {
1501 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon UT height out of range");
1503 "The height of the UT should be between 1.5 and 22.5 m (see TR 38.901, Table 7.4.1-1). "
1504 "We further assume hUT < hBS, then hUT is upper bounded by hBS, which should be 10 m");
1505 }
1506
1507 if (hBs != 10.0)
1508 {
1509 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon BS height out of range");
1510 NS_LOG_WARN("The height of the BS should be equal to 10 m (see TR 38.901, Table 7.4.1-1)");
1511 }
1512
1513 // NOTE The model is intended to be used for BS-UT links, however we may need to
1514 // compute the pathloss between two BSs or UTs, e.g., to evaluate the
1515 // interference. In order to apply the model, we need to retrieve the values of
1516 // hBS and hUT, but in these cases one of the two falls outside the validity
1517 // range and the warning message is printed (hBS for the UT-UT case and hUT
1518 // for the BS-BS case).
1519
1520 // check if the distance is outside the validity range
1521 if (distance2D < 10.0 || distance2D > 5.0e3)
1522 {
1523 NS_ABORT_MSG_IF(m_enforceRanges, "UmiStreetCanyon 2D distance out of range");
1524 NS_LOG_WARN("The 2D distance is outside the validity range, the pathloss value may not be "
1525 "accurate");
1526 }
1527
1528 // compute the pathloss
1529 double plNlos =
1530 22.4 + 35.3 * log10(distance3D) + 21.3 * log10(m_frequency / 1e9) - 0.3 * (hUt - 1.5);
1531 double loss = std::max(GetLossLos(a, b), plNlos);
1532 NS_LOG_DEBUG("Loss " << loss);
1533
1534 return loss;
1535}
1536
1537double
1539 Ptr<MobilityModel> /* a */,
1540 Ptr<MobilityModel> /* b */,
1542{
1543 NS_LOG_FUNCTION(this);
1544 double shadowingStd;
1545
1546 if (m_frequency < 6e9)
1547 {
1548 shadowingStd = 7.0;
1549 }
1550 else
1551 {
1553 {
1554 shadowingStd = 4.0;
1555 }
1557 {
1558 shadowingStd = 7.82;
1559 }
1560 else
1561 {
1562 NS_FATAL_ERROR("Unknown channel condition");
1563 }
1564 }
1565 return shadowingStd;
1566}
1567
1568double
1571{
1572 NS_LOG_FUNCTION(this);
1573 double correlationDistance;
1574
1575 // See 3GPP TR 38.901, Table 7.5-6
1577 {
1578 correlationDistance = 10;
1579 }
1581 {
1582 correlationDistance = 13;
1583 }
1584 else
1585 {
1586 NS_FATAL_ERROR("Unknown channel condition");
1587 }
1588
1589 return correlationDistance;
1590}
1591
1592// ------------------------------------------------------------------------- //
1593
1595
1596TypeId
1598{
1599 static TypeId tid = TypeId("ns3::ThreeGppIndoorOfficePropagationLossModel")
1601 .SetGroupName("Propagation")
1603 return tid;
1604}
1605
1614
1619
1620double
1625
1626double
1628 Ptr<MobilityModel> b) const
1629{
1630 NS_LOG_FUNCTION(this);
1631
1632 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1633
1634 // check if the distance is outside the validity range
1635 if (distance3D < 1.0 || distance3D > 150.0)
1636 {
1637 NS_ABORT_MSG_IF(m_enforceRanges, "IndoorOffice 3D distance out of range");
1638 NS_LOG_WARN("The 3D distance is outside the validity range, the pathloss value may not be "
1639 "accurate");
1640 }
1641
1642 // compute the pathloss (see 3GPP TR 38.901, Table 7.4.1-1)
1643 double loss = 32.4 + 17.3 * log10(distance3D) + 20.0 * log10(m_frequency / 1e9);
1644
1645 NS_LOG_DEBUG("Loss " << loss);
1646
1647 return loss;
1648}
1649
1650double
1652 Ptr<MobilityModel> b) const
1653{
1654 NS_LOG_FUNCTION(this);
1655
1656 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1657
1658 // check if the distance is outside the validity range
1659 if (distance3D < 1.0 || distance3D > 150.0)
1660 {
1661 NS_ABORT_MSG_IF(m_enforceRanges, "IndoorOffice 3D distance out of range");
1662 NS_LOG_WARN("The 3D distance is outside the validity range, the pathloss value may not be "
1663 "accurate");
1664 }
1665
1666 // compute the pathloss
1667 double plNlos = 17.3 + 38.3 * log10(distance3D) + 24.9 * log10(m_frequency / 1e9);
1668 double loss = std::max(GetLossLos(a, b), plNlos);
1669
1670 NS_LOG_DEBUG("Loss " << loss);
1671
1672 return loss;
1673}
1674
1675double
1677 Ptr<MobilityModel> /* a */,
1678 Ptr<MobilityModel> /* b */,
1680{
1681 NS_LOG_FUNCTION(this);
1682 double shadowingStd;
1683
1685 {
1686 shadowingStd = 3.0;
1687 }
1689 {
1690 shadowingStd = 8.03;
1691 }
1692 else
1693 {
1694 NS_FATAL_ERROR("Unknown channel condition");
1695 }
1696
1697 return shadowingStd;
1698}
1699
1700double
1703{
1704 NS_LOG_FUNCTION(this);
1705
1706 // See 3GPP TR 38.901, Table 7.5-6
1707 double correlationDistance;
1708
1710 {
1711 correlationDistance = 10;
1712 }
1714 {
1715 correlationDistance = 6;
1716 }
1717 else
1718 {
1719 NS_FATAL_ERROR("Unknown channel condition");
1720 }
1721
1722 return correlationDistance;
1723}
1724
1726
1727TypeId
1729{
1730 static TypeId tid = TypeId("ns3::ThreeGppNTNDenseUrbanPropagationLossModel")
1732 .SetGroupName("Propagation")
1734 return tid;
1735}
1736
1744
1749
1750double
1755
1756double
1758 Ptr<MobilityModel> b) const
1759{
1760 NS_LOG_FUNCTION(this);
1761 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1762 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1763
1764 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1765 auto [elevAngle, elevAngleQuantized] =
1767
1768 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1769 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1770
1771 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1772 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1773
1774 // Apply Ionospheric plus Tropospheric Scintillation Loss
1775 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1776
1777 NS_LOG_DEBUG("Loss " << loss);
1778 return loss;
1779}
1780
1781double
1783 Ptr<MobilityModel> b) const
1784{
1785 NS_LOG_FUNCTION(this);
1786 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1787 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1788
1789 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1790 auto [elevAngle, elevAngleQuantized] =
1792
1793 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1794 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1795
1796 // Apply Clutter Loss
1797 loss += ComputeClutterLoss(m_frequency, m_SFCL_DenseUrban, elevAngleQuantized);
1798
1799 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1800 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1801
1802 // Apply Ionospheric plus Tropospheric Scintillation Loss
1803 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1804
1805 NS_LOG_DEBUG("Loss " << loss);
1806 return loss;
1807}
1808
1809double
1814{
1815 NS_LOG_FUNCTION(this);
1816 double shadowingStd;
1817
1818 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
1819 auto [elevAngle, elevAngleQuantized] =
1821
1822 // Assign Shadowing Standard Deviation according to table 6.6.2-1
1823 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
1824 {
1825 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
1826 }
1827 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
1828 {
1829 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
1830 }
1831 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
1832 {
1833 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
1834 }
1835 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
1836 {
1837 shadowingStd = (*m_SFCL_DenseUrban).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
1838 }
1839 else
1840 {
1841 NS_FATAL_ERROR("Unknown channel condition");
1842 }
1843
1844 return shadowingStd;
1845}
1846
1847double
1850{
1851 NS_LOG_FUNCTION(this);
1852 double correlationDistance;
1853
1854 // See 3GPP TR 38.811, Table 6.7.2-1a/b and Table 6.7.2-2a/b
1856 {
1857 correlationDistance = 37;
1858 }
1860 {
1861 correlationDistance = 50;
1862 }
1863 else
1864 {
1865 NS_FATAL_ERROR("Unknown channel condition");
1866 }
1867
1868 return correlationDistance;
1869}
1870
1871// ------------------------------------------------------------------------- //
1872
1874
1875TypeId
1877{
1878 static TypeId tid = TypeId("ns3::ThreeGppNTNUrbanPropagationLossModel")
1880 .SetGroupName("Propagation")
1881 .AddConstructor<ThreeGppNTNUrbanPropagationLossModel>();
1882 return tid;
1883}
1884
1892
1897
1898double
1903
1904double
1906{
1907 NS_LOG_FUNCTION(this);
1908 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1909 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1910
1911 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1912 auto [elevAngle, elevAngleQuantized] =
1914
1915 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1916 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1917
1918 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1919 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1920
1921 // Apply Ionospheric plus Tropospheric Scintillation Loss
1922 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1923
1924 NS_LOG_DEBUG("Loss " << loss);
1925 return loss;
1926}
1927
1928double
1930{
1931 NS_LOG_FUNCTION(this);
1932 NS_ASSERT_MSG(m_frequency <= 100.0e9,
1933 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
1934
1935 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
1936 auto [elevAngle, elevAngleQuantized] =
1938
1939 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
1940 double loss = ComputeNtnPathloss(m_frequency, distance3D);
1941
1942 // Apply Clutter Loss
1943 loss += ComputeClutterLoss(m_frequency, m_SFCL_Urban, elevAngleQuantized);
1944
1945 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
1946 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
1947
1948 // Apply Ionospheric plus Tropospheric Scintillation Loss
1949 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
1950
1951 NS_LOG_DEBUG("Loss " << loss);
1952 return loss;
1953}
1954
1955double
1960{
1961 NS_LOG_FUNCTION(this);
1962 double shadowingStd;
1963
1964 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
1965 auto [elevAngle, elevAngleQuantized] =
1967
1968 // Assign Shadowing Standard Deviation according to table 6.6.2-1
1969 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
1970 {
1971 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
1972 }
1973 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
1974 {
1975 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
1976 }
1977 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
1978 {
1979 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
1980 }
1981 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
1982 {
1983 shadowingStd = (*m_SFCL_Urban).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
1984 }
1985 else
1986 {
1987 NS_FATAL_ERROR("Unknown channel condition");
1988 }
1989
1990 return shadowingStd;
1991}
1992
1993double
1996{
1997 NS_LOG_FUNCTION(this);
1998 double correlationDistance;
1999
2000 // See 3GPP TR 38.811, Table 6.7.2-3a/b and Table 6.7.2-3a/b
2002 {
2003 correlationDistance = 37;
2004 }
2006 {
2007 correlationDistance = 50;
2008 }
2009 else
2010 {
2011 NS_FATAL_ERROR("Unknown channel condition");
2012 }
2013
2014 return correlationDistance;
2015}
2016
2017// ------------------------------------------------------------------------- //
2018
2020
2021TypeId
2023{
2024 static TypeId tid = TypeId("ns3::ThreeGppNTNSuburbanPropagationLossModel")
2026 .SetGroupName("Propagation")
2027 .AddConstructor<ThreeGppNTNSuburbanPropagationLossModel>();
2028 return tid;
2029}
2030
2038
2043
2044double
2049
2050double
2052 Ptr<MobilityModel> b) const
2053{
2054 NS_LOG_FUNCTION(this);
2055 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2056 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2057
2058 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2059 auto [elevAngle, elevAngleQuantized] =
2061
2062 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2063 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2064
2065 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2066 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2067
2068 // Apply Ionospheric plus Tropospheric Scintillation Loss
2069 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2070
2071 NS_LOG_DEBUG("Loss " << loss);
2072
2073 return loss;
2074}
2075
2076double
2078 Ptr<MobilityModel> b) const
2079{
2080 NS_LOG_FUNCTION(this);
2081 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2082 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2083
2084 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2085 auto [elevAngle, elevAngleQuantized] =
2087
2088 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2089 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2090
2091 // Apply Clutter Loss
2092 loss += ComputeClutterLoss(m_frequency, m_SFCL_SuburbanRural, elevAngleQuantized);
2093
2094 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2095 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2096
2097 // Apply Ionospheric plus Tropospheric Scintillation Loss
2098 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2099
2100 NS_LOG_DEBUG("Loss " << loss);
2101 return loss;
2102}
2103
2104double
2109{
2110 NS_LOG_FUNCTION(this);
2111 double shadowingStd;
2112
2113 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
2114 auto [elevAngle, elevAngleQuantized] =
2116
2117 // Assign Shadowing Standard Deviation according to table 6.6.2-1
2118 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
2119 {
2120 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
2121 }
2122 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
2123 {
2124 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
2125 }
2126 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
2127 {
2128 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
2129 }
2130 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
2131 {
2132 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
2133 }
2134 else
2135 {
2136 NS_FATAL_ERROR("Unknown channel condition");
2137 }
2138
2139 return shadowingStd;
2140}
2141
2142double
2145{
2146 NS_LOG_FUNCTION(this);
2147 double correlationDistance;
2148
2149 // See 3GPP TR 38.811, Table 6.7.2-5a/b and Table 6.7.2-6a/b
2151 {
2152 correlationDistance = 37;
2153 }
2155 {
2156 correlationDistance = 50;
2157 }
2158 else
2159 {
2160 NS_FATAL_ERROR("Unknown channel condition");
2161 }
2162
2163 return correlationDistance;
2164}
2165
2166// ------------------------------------------------------------------------- //
2167
2169
2170TypeId
2172{
2173 static TypeId tid = TypeId("ns3::ThreeGppNTNRuralPropagationLossModel")
2175 .SetGroupName("Propagation")
2176 .AddConstructor<ThreeGppNTNRuralPropagationLossModel>();
2177 return tid;
2178}
2179
2187
2192
2193double
2198
2199double
2201{
2202 NS_LOG_FUNCTION(this);
2203 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2204 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2205
2206 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2207 auto [elevAngle, elevAngleQuantized] =
2209
2210 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2211 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2212
2213 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2214 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2215
2216 // Apply Ionospheric plus Tropospheric Scintillation Loss
2217 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2218
2219 NS_LOG_DEBUG("Loss " << loss);
2220 return loss;
2221}
2222
2223double
2225{
2226 NS_LOG_FUNCTION(this);
2227 NS_ASSERT_MSG(m_frequency <= 100.0e9,
2228 "NTN communications are valid for frequencies between 0.5 and 100 GHz.");
2229
2230 double distance3D = CalculateDistance(a->GetPosition(), b->GetPosition());
2231 auto [elevAngle, elevAngleQuantized] =
2233
2234 // compute the pathloss (see 3GPP TR 38.811, Table 6.6.2)
2235 double loss = ComputeNtnPathloss(m_frequency, distance3D);
2236
2237 // Apply Clutter Loss
2238 loss += ComputeClutterLoss(m_frequency, m_SFCL_SuburbanRural, elevAngleQuantized);
2239
2240 // Apply Atmospheric Absorption Loss 3GPP 38.811 6.6.4
2241 loss += ComputeAtmosphericAbsorptionLoss(m_frequency, elevAngle);
2242
2243 // Apply Ionospheric plus Tropospheric Scintillation Loss
2244 loss += ComputeIonosphericPlusTroposphericScintillationLoss(m_frequency, elevAngleQuantized);
2245
2246 NS_LOG_DEBUG("Loss " << loss);
2247 return loss;
2248}
2249
2250double
2255{
2256 NS_LOG_FUNCTION(this);
2257 double shadowingStd;
2258
2259 std::string freqBand = (m_frequency < 13.0e9) ? "S" : "Ka";
2260 auto [elevAngle, elevAngleQuantized] =
2262
2263 // Assign Shadowing Standard Deviation according to table 6.6.2-1
2264 if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "S")
2265 {
2266 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_LOS_sigF];
2267 }
2268 else if (cond == ChannelCondition::LosConditionValue::LOS && freqBand == "Ka")
2269 {
2270 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_LOS_sigF];
2271 }
2272 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "S")
2273 {
2274 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::S_NLOS_sigF];
2275 }
2276 else if (cond == ChannelCondition::LosConditionValue::NLOS && freqBand == "Ka")
2277 {
2278 shadowingStd = (*m_SFCL_SuburbanRural).at(elevAngleQuantized)[SFCL_params::Ka_NLOS_sigF];
2279 }
2280 else
2281 {
2282 NS_FATAL_ERROR("Unknown channel condition");
2283 }
2284
2285 return shadowingStd;
2286}
2287
2288double
2291{
2292 NS_LOG_FUNCTION(this);
2293 double correlationDistance;
2294
2295 // See 3GPP TR 38.811, Table 6.7.2-7a/b and Table 6.7.2-8a/b
2297 {
2298 correlationDistance = 37;
2299 }
2301 {
2302 correlationDistance = 120;
2303 }
2304 else
2305 {
2306 NS_FATAL_ERROR("Unknown channel condition");
2307 }
2308
2309 return correlationDistance;
2310}
2311
2312} // 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