25 #include "ns3/phased-array-model.h"
27 #include "ns3/double.h"
28 #include "ns3/string.h"
29 #include "ns3/integer.h"
33 #include <ns3/simulator.h>
34 #include "ns3/mobility-model.h"
35 #include "ns3/pointer.h"
45 0.0447,-0.0447,0.1413,-0.1413,0.2492,-0.2492,0.3715,-0.3715,0.5129,-0.5129,0.6797,-0.6797,0.8844,-0.8844,1.1481,-1.1481,1.5195,-1.5195,2.1551,-2.1551
59 {1, 0, 0, 0, 0, 0, 0},
60 {0, 1, 0, 0, 0, 0, 0},
61 {-0.5, 0, 0.866025, 0, 0, 0, 0},
62 {0, 0, 0, 1, 0, 0, 0},
63 {0, 0, 0, 0, 1, 0, 0},
64 {0.01, 0, -0.0519615, 0.73, -0.2, 0.651383, 0},
65 {-0.17, -0.02, 0.21362, -0.14, 0.24, 0.142773, 0.909661},
70 {-0.5, 0.866025, 0, 0, 0, 0},
71 {0.6, -0.11547, 0.791623, 0, 0, 0},
73 {-0.04, -0.138564, 0.540662, -0.18, 0.809003, 0},
74 {-0.25, -0.606218, -0.240013, 0.26, -0.231685, 0.625392},
81 {0, 0, -0.7, 0.714143, 0, 0},
82 {0, 0, 0.66, -0.123225, 0.741091, 0},
83 {0, 0, 0.47, 0.152631, -0.393194, 0.775373},
87 {1, 0, 0, 0, 0, 0, 0},
88 {0, 1, 0, 0, 0, 0, 0},
89 {-0.4, -0.4, 0.824621, 0, 0, 0, 0},
90 {-0.5, 0, 0.242536, 0.83137, 0, 0, 0},
91 {-0.5, -0.2, 0.630593, -0.484671, 0.278293, 0, 0},
92 {0, 0, -0.242536, 0.672172, 0.642214, 0.27735, 0},
93 {-0.8, 0, -0.388057, -0.367926, 0.238537, -3.58949e-15, 0.130931},
99 {-0.4, 0.916515, 0, 0, 0, 0},
100 {-0.6, 0.174574, 0.78072, 0, 0, 0},
101 {0, 0.654654, 0.365963, 0.661438, 0, 0},
102 {0, -0.545545, 0.762422, 0.118114, 0.327327, 0},
103 {-0.4, -0.174574, -0.396459, 0.392138, 0.49099, 0.507445},
108 {-0.5, 0.866025, 0, 0, 0, 0},
109 {0.2, 0.57735, 0.791623, 0, 0, 0},
110 {0, 0.46188, -0.336861, 0.820482, 0, 0},
111 {0, -0.69282, 0.252646, 0.493742, 0.460857, 0},
112 {0, -0.23094, 0.16843, 0.808554, -0.220827, 0.464515},
117 {1, 0, 0, 0, 0, 0, 0},
118 {0.5, 0.866025, 0, 0, 0, 0, 0},
119 {-0.4, -0.57735, 0.711805, 0, 0, 0, 0},
120 {-0.5, 0.057735, 0.468293, 0.726201, 0, 0, 0},
121 {-0.4, -0.11547, 0.805464, -0.23482, 0.350363, 0, 0},
122 {0, 0, 0, 0.688514, 0.461454, 0.559471, 0},
123 {0, 0, 0.280976, 0.231921, -0.490509, 0.11916, 0.782603},
128 {-0.7, 0.714143, 0, 0, 0, 0},
130 {-0.4, 0.168034, 0, 0.90098, 0, 0},
131 {0, -0.70014, 0.5, 0.130577, 0.4927, 0},
132 {0, 0, 0.5, 0.221981, -0.566238, 0.616522},
137 {-0.5, 0.866025, 0, 0, 0, 0},
138 {0.2, 0.57735, 0.791623, 0, 0, 0},
139 {0, 0.46188, -0.336861, 0.820482, 0, 0},
140 {0, -0.69282, 0.252646, 0.493742, 0.460857, 0},
141 {0, -0.23094, 0.16843, 0.808554, -0.220827, 0.464515},
145 {1, 0, 0, 0, 0, 0, 0},
146 {0.5, 0.866025, 0, 0, 0, 0, 0},
147 {-0.8, -0.11547, 0.588784, 0, 0, 0, 0},
148 {-0.4, 0.23094, 0.520847, 0.717903, 0, 0, 0},
149 {-0.5, 0.288675, 0.73598, -0.348236, 0.0610847, 0, 0},
150 {0.2, -0.11547, 0.418943, 0.541106, 0.219905, 0.655744, 0},
151 {0.3, -0.057735, 0.73598, -0.348236, 0.0610847, -0.304997, 0.383375},
156 {-0.5, 0.866025, 0, 0, 0, 0},
157 {0, 0.46188, 0.886942, 0, 0, 0},
158 {-0.4, -0.23094, 0.120263, 0.878751, 0, 0},
159 {0, -0.311769, 0.55697, -0.249198, 0.728344, 0},
160 {0, -0.069282, 0.295397, 0.430696, 0.468462, 0.709214},
166 m_uniformRv = CreateObject<UniformRandomVariable> ();
169 m_normalRv = CreateObject<NormalRandomVariable> ();
194 static TypeId tid =
TypeId (
"ns3::ThreeGppChannelModel")
196 .SetGroupName (
"Spectrum")
198 .AddConstructor<ThreeGppChannelModel> ()
199 .AddAttribute (
"Frequency",
200 "The operating Frequency in Hz",
204 MakeDoubleChecker<double> ())
205 .AddAttribute (
"Scenario",
206 "The 3GPP scenario (RMa, UMa, UMi-StreetCanyon, InH-OfficeOpen, InH-OfficeMixed)",
211 .AddAttribute (
"ChannelConditionModel",
212 "Pointer to the channel condition model",
216 MakePointerChecker<ChannelConditionModel> ())
217 .AddAttribute (
"UpdatePeriod",
218 "Specify the channel coherence time",
223 .AddAttribute (
"Blockage",
224 "Enable blockage model A (sec 7.6.4.1)",
228 .AddAttribute (
"NumNonselfBlocking",
229 "number of non-self-blocking regions",
232 MakeIntegerChecker<uint16_t> ())
233 .AddAttribute (
"PortraitMode",
234 "true for portrait mode, false for landscape mode",
238 .AddAttribute (
"BlockerSpeed",
239 "The speed of moving blockers, the unit is m/s",
242 MakeDoubleChecker<double> ())
265 NS_ASSERT_MSG (
f >= 500.0e6 &&
f <= 100.0e9,
"Frequency should be between 0.5 and 100 GHz but is " <<
f);
280 NS_ASSERT_MSG (scenario ==
"RMa" || scenario ==
"UMa" || scenario ==
"UMi-StreetCanyon"
281 || scenario ==
"InH-OfficeOpen" || scenario ==
"InH-OfficeMixed"
282 || scenario ==
"V2V-Urban" || scenario ==
"V2V-Highway",
283 "Unknown scenario, choose between RMa, UMa, UMi-StreetCanyon,"
284 "InH-OfficeOpen, InH-OfficeMixed, V2V-Urban or V2V-Highway");
307 bool los = channelCondition->IsLos ();
308 bool o2i = channelCondition->IsO2i ();
328 table3gpp->
m_sigLgZSD =
std::max (-1.0, -0.17 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.22);
330 table3gpp->
m_cDS = 3.91e-9;
341 for (uint8_t row = 0; row < 7; row++)
343 for (uint8_t column = 0; column < 7; column++)
349 else if (!los && !o2i)
361 table3gpp->
m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
363 table3gpp->
m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
364 table3gpp->
m_cDS = 3.91e-9;
375 for (uint8_t row = 0; row < 6; row++)
377 for (uint8_t column = 0; column < 6; column++)
395 table3gpp->
m_uLgZSD =
std::max (-1.0, -0.19 * (distance2D / 1000) - 0.01 * (hUT - 1.5) + 0.28);
397 table3gpp->
m_offsetZOD = atan ((35 - 3.5) / distance2D) - atan ((35 - 1.5) / distance2D);
398 table3gpp->
m_cDS = 3.91e-9;
409 for (uint8_t row = 0; row < 6; row++)
411 for (uint8_t column = 0; column < 6; column++)
424 table3gpp->
m_uLgDS = -6.955 - 0.0963 * log10 (fcGHz);
426 table3gpp->
m_uLgASD = 1.06 + 0.1114 * log10 (fcGHz);
432 table3gpp->
m_uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.75);
435 table3gpp->
m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
446 for (uint8_t row = 0; row < 7; row++)
448 for (uint8_t column = 0; column < 7; column++)
456 double uLgZSD =
std::max (-0.5, -2.1 * distance2D / 1000 - 0.01 * (hUT - 1.5) + 0.9);
458 double afc = 0.208 * log10 (fcGHz) - 0.782;
460 double cfc = -0.13 * log10 (fcGHz) + 2.03;
461 double efc = 7.66 * log10 (fcGHz) - 5.96;
463 double offsetZOD = efc - std::pow (10, afc * log10 (
std::max (bfc,distance2D)) + cfc);
469 table3gpp->
m_uLgDS = -6.28 - 0.204 * log10 (fcGHz);
471 table3gpp->
m_uLgASD = 1.5 - 0.1144 * log10 (fcGHz);
473 table3gpp->
m_uLgASA = 2.08 - 0.27 * log10 (fcGHz);
475 table3gpp->
m_uLgZSA = -0.3236 * log10 (fcGHz) + 1.512;
480 table3gpp->
m_cDS =
std::max (0.25, -3.4084 * log10 (fcGHz) + 6.5622) * 1e-9;
491 for (uint8_t row = 0; row < 6; row++)
493 for (uint8_t column = 0; column < 6; column++)
514 table3gpp->
m_cDS = 11e-9;
525 for (uint8_t row = 0; row < 6; row++)
527 for (uint8_t column = 0; column < 6; column++)
544 table3gpp->
m_uLgDS = -0.24 * log10 (1 + fcGHz) - 7.14;
546 table3gpp->
m_uLgASD = -0.05 * log10 (1 + fcGHz) + 1.21;
548 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.73;
549 table3gpp->
m_sigLgASA = 0.014 * log10 (1 + fcGHz) + 0.28;
550 table3gpp->
m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73;
551 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34;
552 table3gpp->
m_uLgZSD =
std::max (-0.21, -14.8 * distance2D / 1000 + 0.01 * std::abs (hUT - hBS) + 0.83);
555 table3gpp->
m_cDS = 5e-9;
566 for (uint8_t row = 0; row < 7; row++)
568 for (uint8_t column = 0; column < 7; column++)
576 double uLgZSD =
std::max (-0.5, -3.1 * distance2D / 1000 + 0.01 *
std::max (hUT - hBS,0.0) + 0.2);
577 double offsetZOD = -1 * std::pow (10, -1.5 * log10 (
std::max (10.0, distance2D)) + 3.3);
582 table3gpp->
m_uLgDS = -0.24 * log10 (1 + fcGHz) - 6.83;
583 table3gpp->
m_sigLgDS = 0.16 * log10 (1 + fcGHz) + 0.28;
584 table3gpp->
m_uLgASD = -0.23 * log10 (1 + fcGHz) + 1.53;
585 table3gpp->
m_sigLgASD = 0.11 * log10 (1 + fcGHz) + 0.33;
586 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
587 table3gpp->
m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
588 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
589 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
593 table3gpp->
m_cDS = 11e-9;
604 for (uint8_t row = 0; row < 6; row++)
606 for (uint8_t column = 0; column < 6; column++)
627 table3gpp->
m_cDS = 11e-9;
638 for (uint8_t row = 0; row < 6; row++)
640 for (uint8_t column = 0; column < 6; column++)
650 NS_ASSERT_MSG (!o2i,
"The indoor scenario does out support outdoor to indoor");
655 table3gpp->
m_uLgDS = -0.01 * log10 (1 + fcGHz) - 7.692;
659 table3gpp->
m_uLgASA = -0.19 * log10 (1 + fcGHz) + 1.781;
660 table3gpp->
m_sigLgASA = 0.12 * log10 (1 + fcGHz) + 0.119;
661 table3gpp->
m_uLgZSA = -0.26 * log10 (1 + fcGHz) + 1.44;
662 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.264;
663 table3gpp->
m_uLgZSD = -1.43 * log10 (1 + fcGHz) + 2.228;
664 table3gpp->
m_sigLgZSD = 0.13 * log10 (1 + fcGHz) + 0.30;
666 table3gpp->
m_cDS = 3.91e-9;
677 for (uint8_t row = 0; row < 7; row++)
679 for (uint8_t column = 0; column < 7; column++)
689 table3gpp->
m_uLgDS = -0.28 * log10 (1 + fcGHz) - 7.173;
690 table3gpp->
m_sigLgDS = 0.1 * log10 (1 + fcGHz) + 0.055;
693 table3gpp->
m_uLgASA = -0.11 * log10 (1 + fcGHz) + 1.863;
694 table3gpp->
m_sigLgASA = 0.12 * log10 (1 + fcGHz) + 0.059;
695 table3gpp->
m_uLgZSA = -0.15 * log10 (1 + fcGHz) + 1.387;
696 table3gpp->
m_sigLgZSA = -0.09 * log10 (1 + fcGHz) + 0.746;
700 table3gpp->
m_cDS = 3.91e-9;
711 for (uint8_t row = 0; row < 6; row++)
713 for (uint8_t column = 0; column < 6; column++)
722 if (channelCondition->IsLos ())
728 table3gpp->
m_uLgDS = -0.2 * log10 (1 + fcGHz) - 7.5;
730 table3gpp->
m_uLgASD = -0.1 * log10 (1 + fcGHz) + 1.6;
732 table3gpp->
m_uLgASA = -0.1 * log10 (1 + fcGHz) + 1.6;
734 table3gpp->
m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73,
735 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34,
736 table3gpp->
m_uLgZSD = -0.1 * log10 (1 + fcGHz) + 0.73;
737 table3gpp->
m_sigLgZSD = -0.04 * log10 (1 + fcGHz) + 0.34;
739 table3gpp->
m_cDS = 5;
743 table3gpp->
m_uK = 3.48;
750 for (uint8_t row = 0; row < 7; row++)
752 for (uint8_t column = 0; column < 7; column++)
758 else if (channelCondition->IsNlos ())
762 table3gpp->
m_uLgDS = -0.3 * log10 (1 + fcGHz) - 7;
764 table3gpp->
m_uLgASD = -0.08 * log10 (1 + fcGHz) + 1.81;
765 table3gpp->
m_sigLgASD = 0.05 * log10 (1 + fcGHz) + 0.3;
766 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
767 table3gpp->
m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
768 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92,
769 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
770 table3gpp->
m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
771 table3gpp->
m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
773 table3gpp->
m_cDS = 11;
784 for (uint8_t row = 0; row < 6; row++)
786 for (uint8_t column = 0; column < 6; column++)
792 else if (channelCondition->IsNlosv ())
796 table3gpp->
m_uLgDS = -0.4 * log10 (1 + fcGHz) - 7;
798 table3gpp->
m_uLgASD = -0.1 * log10 (1 + fcGHz) + 1.7;
800 table3gpp->
m_uLgASA = -0.1 * log10 (1 + fcGHz) + 1.7;
802 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
803 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
804 table3gpp->
m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
805 table3gpp->
m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
807 table3gpp->
m_cDS = 11;
818 for (uint8_t row = 0; row < 6; row++)
820 for (uint8_t column = 0; column < 6; column++)
833 if (channelCondition->IsLos ())
843 table3gpp->
m_uLgZSA = -0.1 * log10 (1 + fcGHz) + 0.73;
844 table3gpp->
m_sigLgZSA = -0.04 * log10 (1 + fcGHz) + 0.34;
845 table3gpp->
m_uLgZSD = -0.1 * log10 (1 + fcGHz) + 0.73;
846 table3gpp->
m_sigLgZSD = -0.04 * log10 (1 + fcGHz) + 0.34;
848 table3gpp->
m_cDS = 5;
859 for (uint8_t row = 0; row < 7; row++)
861 for (uint8_t column = 0; column < 7; column++)
867 else if (channelCondition->IsNlosv ())
877 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92;
878 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
879 table3gpp->
m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
880 table3gpp->
m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
882 table3gpp->
m_cDS = 11;
893 for (uint8_t row = 0; row < 6; row++)
895 for (uint8_t column = 0; column < 6; column++)
901 else if (channelCondition->IsNlos ())
903 NS_LOG_WARN (
"The fast fading parameters for the NLOS condition in the Highway scenario are not defined in TR 37.885, use the ones defined in TDoc R1-1803671 instead");
907 table3gpp->
m_uLgDS = -0.3 * log10 (1 + fcGHz) - 7;
909 table3gpp->
m_uLgASD = -0.08 * log10 (1 + fcGHz) + 1.81;
910 table3gpp->
m_sigLgASD = 0.05 * log10 (1 + fcGHz) + 0.3;
911 table3gpp->
m_uLgASA = -0.08 * log10 (1 + fcGHz) + 1.81;
912 table3gpp->
m_sigLgASA = 0.05 * log10 (1 + fcGHz) + 0.3;
913 table3gpp->
m_uLgZSA = -0.04 * log10 (1 + fcGHz) + 0.92,
914 table3gpp->
m_sigLgZSA = -0.07 * log10 (1 + fcGHz) + 0.41;
915 table3gpp->
m_uLgZSD = -0.04 * log10 (1 + fcGHz) + 0.92;
916 table3gpp->
m_sigLgZSD = -0.07 * log10 (1 + fcGHz) + 0.41;
918 table3gpp->
m_cDS = 11;
929 for (uint8_t row = 0; row < 6; row++)
931 for (uint8_t column = 0; column < 6; column++)
985 uint32_t channelId =
GetKey (x1, x2);
993 bool notFound =
false;
1012 if (notFound || update)
1015 Angles txAngle (bMob->GetPosition (), aMob->GetPosition ());
1016 Angles rxAngle (aMob->GetPosition (), bMob->GetPosition ());
1018 double x = aMob->GetPosition ().x - bMob->GetPosition ().x;
1019 double y = aMob->GetPosition ().y - bMob->GetPosition ().y;
1020 double distance2D = sqrt (
x *
x + y * y);
1024 double hUt =
std::min (aMob->GetPosition ().z, bMob->GetPosition ().z);
1025 double hBs =
std::max (aMob->GetPosition ().z, bMob->GetPosition ().z);
1031 Vector locUt = Vector (0.0, 0.0, 0.0);
1033 channelMatrix =
GetNewChannel (locUt, condition, aAntenna, bAntenna, rxAngle, txAngle, distance2D, hBs, hUt);
1040 return channelMatrix;
1048 double dis2D,
double hBS,
double hUT)
const
1067 double dis3D = std::sqrt (dis2D * dis2D + (hBS - hUT) * (hBS - hUT));
1069 bool los = channelCondition->IsLos ();
1070 bool o2i = channelCondition->IsO2i ();
1084 for (uint8_t iter = 0; iter < paramNum; iter++)
1086 LSPsIndep.push_back (
m_normalRv->GetValue ());
1088 for (uint8_t row = 0; row < paramNum; row++)
1091 for (uint8_t column = 0; column < paramNum; column++)
1093 temp += table3gpp->
m_sqrtC[row][column] * LSPsIndep[column];
1095 LSPs.push_back (temp);
1100 double DS,ASD,ASA,ZSA,ZSD,K_factor = 0;
1103 K_factor = LSPs[1] * table3gpp->
m_sigK + table3gpp->
m_uK;
1124 channelParams->
m_DS = DS;
1125 channelParams->
m_K = K_factor;
1127 NS_LOG_INFO (
"K-factor=" << K_factor <<
",DS=" << DS <<
", ASD=" << ASD <<
", ASA=" << ASA <<
", ZSD=" << ZSD <<
", ZSA=" << ZSA);
1131 double minTau = 100.0;
1132 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1139 clusterDelay.push_back (tau);
1142 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1144 clusterDelay[cIndex] -= minTau;
1146 std::sort (clusterDelay.begin (), clusterDelay.end ());
1153 double powerSum = 0;
1154 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1156 double power = exp (-1 * clusterDelay[cIndex] * (table3gpp->
m_rTau - 1) / table3gpp->
m_rTau / DS) *
1159 clusterPower.push_back (power);
1161 double powerMax = 0;
1163 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1165 clusterPower[cIndex] = clusterPower[cIndex] / powerSum;
1171 double K_linear = pow (10,K_factor / 10);
1173 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1177 clusterPowerForAngles.push_back (clusterPower[cIndex] / (1 + K_linear) + K_linear / (1 + K_linear));
1181 clusterPowerForAngles.push_back (clusterPower[cIndex] / (1 + K_linear));
1183 if (powerMax < clusterPowerForAngles[cIndex])
1185 powerMax = clusterPowerForAngles[cIndex];
1191 for (uint8_t cIndex = 0; cIndex < numOfCluster; cIndex++)
1193 clusterPowerForAngles.push_back (clusterPower[cIndex]);
1194 if (powerMax < clusterPowerForAngles[cIndex])
1196 powerMax = clusterPowerForAngles[cIndex];
1203 double thresh = 0.0032;
1204 for (uint8_t cIndex = numOfCluster; cIndex > 0; cIndex--)
1206 if (clusterPowerForAngles[cIndex - 1] < thresh * powerMax )
1208 clusterPowerForAngles.erase (clusterPowerForAngles.begin () + cIndex - 1);
1209 clusterPower.erase (clusterPower.begin () + cIndex - 1);
1210 clusterDelay.erase (clusterDelay.begin () + cIndex - 1);
1214 NS_ASSERT (clusterPower.size () < UINT8_MAX);
1215 uint8_t numReducedCluster = clusterPower.size ();
1221 double C_tau = 0.7705 - 0.0433 * K_factor + 2e-4 * pow (K_factor,2) + 17e-6 * pow (K_factor,3);
1222 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1224 clusterDelay[cIndex] = clusterDelay[cIndex] / C_tau;
1230 double C_NLOS, C_phi;
1233 switch (numOfCluster)
1274 C_phi = C_NLOS * (1.1035 - 0.028 * K_factor - 2e-3 * pow (K_factor,2) + 1e-4 * pow (K_factor,3));
1282 switch (numOfCluster)
1311 C_theta = C_NLOS * (1.3086 + 0.0339 * K_factor - 0.0077 * pow (K_factor,2) + 2e-4 * pow (K_factor,3));
1319 DoubleVector clusterAoa, clusterAod, clusterZoa, clusterZod;
1321 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1323 angle = 2 * ASA * sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi;
1324 clusterAoa.push_back (angle);
1325 angle = 2 * ASD * sqrt (-1 * log (clusterPowerForAngles[cIndex] / powerMax)) / 1.4 / C_phi;
1326 clusterAod.push_back (angle);
1327 angle = -1 * ZSA * log (clusterPowerForAngles[cIndex] / powerMax) / C_theta;
1328 clusterZoa.push_back (angle);
1329 angle = -1 * ZSD * log (clusterPowerForAngles[cIndex] / powerMax) / C_theta;
1330 clusterZod.push_back (angle);
1333 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1344 clusterZoa[cIndex] = clusterZoa[cIndex] * Xn + (
m_normalRv->GetValue () * ZSA / 7) + 90;
1363 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1365 clusterAoa[cIndex] -= diffAoa;
1366 clusterAod[cIndex] -= diffAod;
1367 clusterZoa[cIndex] -= diffZsa;
1368 clusterZod[cIndex] -= diffZsd;
1373 double rayAoa_radian[numReducedCluster][raysPerCluster];
1374 double rayAod_radian[numReducedCluster][raysPerCluster];
1375 double rayZoa_radian[numReducedCluster][raysPerCluster];
1376 double rayZod_radian[numReducedCluster][raysPerCluster];
1378 for (uint8_t nInd = 0; nInd < numReducedCluster; nInd++)
1380 for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++)
1387 double tempZod = clusterZod[nInd] + 0.375 * pow (10,table3gpp->
m_uLgZSD) *
offSetAlpha[mInd];
1392 double sizeTemp = clusterZoa.size ();
1393 for (uint8_t ind = 0; ind < 4; ind++)
1398 angle_degree = clusterAoa;
1401 angle_degree = clusterZoa;
1404 angle_degree = clusterAod;
1407 angle_degree = clusterZod;
1413 for (uint8_t nIndex = 0; nIndex < sizeTemp; nIndex++)
1415 while (angle_degree[nIndex] > 360)
1417 angle_degree[nIndex] -= 360;
1420 while (angle_degree[nIndex] < 0)
1422 angle_degree[nIndex] += 360;
1425 if (ind == 1 || ind == 3)
1427 if (angle_degree[nIndex] > 180)
1429 angle_degree[nIndex] = 360 - angle_degree[nIndex];
1436 clusterAoa = angle_degree;
1439 clusterZoa = angle_degree;
1442 clusterAod = angle_degree;
1445 clusterZod = angle_degree;
1456 for (uint8_t cInd = 0; cInd < numReducedCluster; cInd++)
1458 clusterPower[cInd] = clusterPower[cInd] / pow (10,attenuation_dB[cInd] / 10);
1463 attenuation_dB.push_back (0);
1468 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1470 Shuffle (&rayAod_radian[cIndex][0], &rayAod_radian[cIndex][raysPerCluster]);
1471 Shuffle (&rayAoa_radian[cIndex][0], &rayAoa_radian[cIndex][raysPerCluster]);
1472 Shuffle (&rayZod_radian[cIndex][0], &rayZod_radian[cIndex][raysPerCluster]);
1473 Shuffle (&rayZoa_radian[cIndex][0], &rayZoa_radian[cIndex][raysPerCluster]);
1480 for (uint8_t nInd = 0; nInd < numReducedCluster; nInd++)
1484 for (uint8_t mInd = 0; mInd < raysPerCluster; mInd++)
1486 double uXprLinear = pow (10, table3gpp->
m_uXpr / 10);
1487 double sigXprLinear = pow (10, table3gpp->
m_sigXpr / 10);
1489 temp.push_back (std::pow (10, (
m_normalRv->GetValue () * sigXprLinear + uXprLinear) / 10));
1491 for (uint8_t pInd = 0; pInd < 4; pInd++)
1495 temp2.push_back (temp3);
1497 crossPolarizationPowerRatios.push_back (temp);
1498 clusterPhase.push_back (temp2);
1507 uint64_t uSize = uAntenna->GetNumberOfElements ();
1508 uint64_t sSize = sAntenna->GetNumberOfElements ();
1510 uint8_t cluster1st = 0, cluster2nd = 0;
1511 double maxPower = 0;
1512 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1514 if (maxPower < clusterPower[cIndex])
1516 maxPower = clusterPower[cIndex];
1517 cluster1st = cIndex;
1521 for (uint8_t cIndex = 0; cIndex < numReducedCluster; cIndex++)
1523 if (maxPower < clusterPower[cIndex] && cluster1st != cIndex)
1525 maxPower = clusterPower[cIndex];
1526 cluster2nd = cIndex;
1530 NS_LOG_INFO (
"1st strongest cluster:" << (
int)cluster1st <<
", 2nd strongest cluster:" << (
int)cluster2nd);
1536 H_usn.resize (uSize);
1537 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1539 H_usn[uIndex].resize (sSize);
1540 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1542 H_usn[uIndex][sIndex].resize (numReducedCluster);
1547 for (uint64_t uIndex = 0; uIndex < uSize; uIndex++)
1549 Vector uLoc = uAntenna->GetElementLocation (uIndex);
1551 for (uint64_t sIndex = 0; sIndex < sSize; sIndex++)
1554 Vector sLoc = sAntenna->GetElementLocation (sIndex);
1556 for (uint8_t nIndex = 0; nIndex < numReducedCluster; nIndex++)
1560 if (nIndex != cluster1st && nIndex != cluster2nd)
1562 std::complex<double> rays (0,0);
1563 for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++)
1565 DoubleVector initialPhase = clusterPhase[nIndex][mIndex];
1566 double k = crossPolarizationPowerRatios[nIndex][mIndex];
1568 double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x
1569 + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y
1570 + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z);
1572 double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x
1573 + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y
1574 + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z);
1577 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1578 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoa_radian[nIndex][mIndex], rayZoa_radian[nIndex][mIndex]));
1579 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAod_radian[nIndex][mIndex], rayZod_radian[nIndex][mIndex]));
1581 rays += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1582 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 /
k) * rxFieldPatternTheta * txFieldPatternPhi +
1583 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 /
k) * rxFieldPatternPhi * txFieldPatternTheta +
1584 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1585 * exp (std::complex<double> (0, rxPhaseDiff))
1586 * exp (std::complex<double> (0, txPhaseDiff));
1588 rays *= sqrt (clusterPower[nIndex] / raysPerCluster);
1589 H_usn[uIndex][sIndex][nIndex] = rays;
1593 std::complex<double> raysSub1 (0,0);
1594 std::complex<double> raysSub2 (0,0);
1595 std::complex<double> raysSub3 (0,0);
1597 for (uint8_t mIndex = 0; mIndex < raysPerCluster; mIndex++)
1599 double k = crossPolarizationPowerRatios[nIndex][mIndex];
1603 DoubleVector initialPhase = clusterPhase[nIndex][mIndex];
1604 double rxPhaseDiff = 2 * M_PI * (sin (rayZoa_radian[nIndex][mIndex]) * cos (rayAoa_radian[nIndex][mIndex]) * uLoc.x
1605 + sin (rayZoa_radian[nIndex][mIndex]) * sin (rayAoa_radian[nIndex][mIndex]) * uLoc.y
1606 + cos (rayZoa_radian[nIndex][mIndex]) * uLoc.z);
1607 double txPhaseDiff = 2 * M_PI * (sin (rayZod_radian[nIndex][mIndex]) * cos (rayAod_radian[nIndex][mIndex]) * sLoc.x
1608 + sin (rayZod_radian[nIndex][mIndex]) * sin (rayAod_radian[nIndex][mIndex]) * sLoc.y
1609 + cos (rayZod_radian[nIndex][mIndex]) * sLoc.z);
1611 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1612 std::tie (rxFieldPatternPhi, rxFieldPatternTheta) = uAntenna->GetElementFieldPattern (
Angles (rayAoa_radian[nIndex][mIndex], rayZoa_radian[nIndex][mIndex]));
1613 std::tie (txFieldPatternPhi, txFieldPatternTheta) = sAntenna->GetElementFieldPattern (
Angles (rayAod_radian[nIndex][mIndex], rayZod_radian[nIndex][mIndex]));
1623 raysSub2 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1624 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 /
k) * rxFieldPatternTheta * txFieldPatternPhi +
1625 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 /
k) * rxFieldPatternPhi * txFieldPatternTheta +
1626 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1627 * exp (std::complex<double> (0, rxPhaseDiff))
1628 * exp (std::complex<double> (0, txPhaseDiff));
1634 raysSub3 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1635 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 /
k) * rxFieldPatternTheta * txFieldPatternPhi +
1636 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 /
k) * rxFieldPatternPhi * txFieldPatternTheta +
1637 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1638 * exp (std::complex<double> (0, rxPhaseDiff))
1639 * exp (std::complex<double> (0, txPhaseDiff));
1642 raysSub1 += (exp (std::complex<double> (0, initialPhase[0])) * rxFieldPatternTheta * txFieldPatternTheta +
1643 +exp (std::complex<double> (0, initialPhase[1])) * std::sqrt (1 /
k) * rxFieldPatternTheta * txFieldPatternPhi +
1644 +exp (std::complex<double> (0, initialPhase[2])) * std::sqrt (1 /
k) * rxFieldPatternPhi * txFieldPatternTheta +
1645 +exp (std::complex<double> (0, initialPhase[3])) * rxFieldPatternPhi * txFieldPatternPhi)
1646 * exp (std::complex<double> (0, rxPhaseDiff))
1647 * exp (std::complex<double> (0, txPhaseDiff));
1651 raysSub1 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1652 raysSub2 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1653 raysSub3 *= sqrt (clusterPower[nIndex] / raysPerCluster);
1654 H_usn[uIndex][sIndex][nIndex] = raysSub1;
1655 H_usn[uIndex][sIndex].push_back (raysSub2);
1656 H_usn[uIndex][sIndex].push_back (raysSub3);
1662 std::complex<double> ray (0,0);
1670 double rxFieldPatternPhi, rxFieldPatternTheta, txFieldPatternPhi, txFieldPatternTheta;
1676 ray = (rxFieldPatternTheta * txFieldPatternTheta - rxFieldPatternPhi * txFieldPatternPhi)
1677 * exp (std::complex<double> (0, -2 * M_PI * dis3D / lambda))
1678 * exp (std::complex<double> (0, rxPhaseDiff))
1679 * exp (std::complex<double> (0, txPhaseDiff));
1681 double K_linear = pow (10,K_factor / 10);
1683 H_usn[uIndex][sIndex][0] = sqrt (1 / (K_linear + 1)) * H_usn[uIndex][sIndex][0] + sqrt (K_linear / (1 + K_linear)) * ray / pow (10,attenuation_dB[0] / 10);
1684 double tempSize = H_usn[uIndex][sIndex].size ();
1685 for (uint8_t nIndex = 1; nIndex < tempSize; nIndex++)
1687 H_usn[uIndex][sIndex][nIndex] *= sqrt (1 / (K_linear + 1));
1695 if (cluster1st == cluster2nd)
1697 clusterDelay.push_back (clusterDelay[cluster1st] + 1.28 * table3gpp->
m_cDS);
1698 clusterDelay.push_back (clusterDelay[cluster1st] + 2.56 * table3gpp->
m_cDS);
1700 clusterAoa.push_back (clusterAoa[cluster1st]);
1701 clusterAoa.push_back (clusterAoa[cluster1st]);
1703 clusterZoa.push_back (clusterZoa[cluster1st]);
1704 clusterZoa.push_back (clusterZoa[cluster1st]);
1706 clusterAod.push_back (clusterAod[cluster1st]);
1707 clusterAod.push_back (clusterAod[cluster1st]);
1709 clusterZod.push_back (clusterZod[cluster1st]);
1710 clusterZod.push_back (clusterZod[cluster1st]);
1715 if (cluster1st < cluster2nd)
1725 clusterDelay.push_back (clusterDelay[
min] + 1.28 * table3gpp->
m_cDS);
1726 clusterDelay.push_back (clusterDelay[
min] + 2.56 * table3gpp->
m_cDS);
1727 clusterDelay.push_back (clusterDelay[
max] + 1.28 * table3gpp->
m_cDS);
1728 clusterDelay.push_back (clusterDelay[
max] + 2.56 * table3gpp->
m_cDS);
1730 clusterAoa.push_back (clusterAoa[
min]);
1731 clusterAoa.push_back (clusterAoa[
min]);
1732 clusterAoa.push_back (clusterAoa[
max]);
1733 clusterAoa.push_back (clusterAoa[
max]);
1735 clusterZoa.push_back (clusterZoa[
min]);
1736 clusterZoa.push_back (clusterZoa[
min]);
1737 clusterZoa.push_back (clusterZoa[
max]);
1738 clusterZoa.push_back (clusterZoa[
max]);
1740 clusterAod.push_back (clusterAod[
min]);
1741 clusterAod.push_back (clusterAod[
min]);
1742 clusterAod.push_back (clusterAod[
max]);
1743 clusterAod.push_back (clusterAod[
max]);
1745 clusterZod.push_back (clusterZod[
min]);
1746 clusterZod.push_back (clusterZod[
min]);
1747 clusterZod.push_back (clusterZod[
max]);
1748 clusterZod.push_back (clusterZod[
max]);
1753 NS_LOG_INFO (
"size of coefficient matrix =[" << H_usn.size () <<
"][" << H_usn[0].size () <<
"][" << H_usn[0][0].size () <<
"]");
1756 channelParams->
m_delay = clusterDelay;
1758 channelParams->
m_angle.clear ();
1759 channelParams->
m_angle.push_back (clusterAoa);
1760 channelParams->
m_angle.push_back (clusterZoa);
1761 channelParams->
m_angle.push_back (clusterAod);
1762 channelParams->
m_angle.push_back (clusterZod);
1764 return channelParams;
1767 std::pair<double, double>
1770 inclinationRad =
WrapTo2Pi (inclinationRad);
1771 if (inclinationRad > M_PI)
1774 inclinationRad -= M_PI;
1780 NS_ASSERT_MSG (0 <= inclinationRad && inclinationRad <= M_PI,
1781 "inclinationRad=" << inclinationRad <<
" not valid, should be in [0, pi]");
1783 "azimuthRad=" << azimuthRad <<
" not valid, should be in [0, 2*pi]");
1785 return std::make_pair (azimuthRad, inclinationRad);
1796 uint8_t clusterNum = clusterAOA.size ();
1797 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
1799 powerAttenuation.push_back (0);
1805 double phi_sb, x_sb, theta_sb, y_sb;
1823 if (params->m_nonSelfBlocking.size () == 0)
1833 table.push_back (90);
1835 table.push_back (2);
1840 table.push_back (90);
1841 table.push_back (5);
1842 table.push_back (10);
1844 params->m_nonSelfBlocking.push_back (table);
1849 double deltaX = sqrt (pow (params->m_preLocUT.x - params->m_locUT.x, 2) + pow (params->m_preLocUT.y - params->m_locUT.y, 2));
1862 if (params->m_channelCondition->IsO2i ())
1875 R = exp (-1 * (deltaX / corrDis + (
Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()) / corrT));
1879 R = exp (-1 * (deltaX / corrDis));
1883 <<
" Time difference:" <<
Now ().GetSeconds () - params->m_generatedTime.GetSeconds ()
1884 <<
" correlation:" << R);
1893 if (R * R * (-0.069) + R * 1.074 - 0.002 < 1)
1895 R = R * R * (-0.069) + R * 1.074 - 0.002;
1901 params->m_nonSelfBlocking[blockInd][
PHI_INDEX] =
1902 R * params->m_nonSelfBlocking[blockInd][
PHI_INDEX] + sqrt (1 - R * R) *
m_normalRv->GetValue ();
1909 for (uint8_t cInd = 0; cInd < clusterNum; cInd++)
1911 NS_ASSERT_MSG (clusterAOA[cInd] >= 0 && clusterAOA[cInd] <= 360,
"the AOA should be the range of [0,360]");
1912 NS_ASSERT_MSG (clusterZOA[cInd] >= 0 && clusterZOA[cInd] <= 180,
"the ZOA should be the range of [0,180]");
1915 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phi_sb - x_sb / 2 <<
"," << phi_sb + x_sb / 2 <<
"]");
1916 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << theta_sb - y_sb / 2 <<
"," << theta_sb + y_sb / 2 <<
"]");
1917 if ( std::abs (clusterAOA[cInd] - phi_sb) < (x_sb / 2) && std::abs (clusterZOA[cInd] - theta_sb) < (y_sb / 2))
1919 powerAttenuation[cInd] += 30;
1920 NS_LOG_INFO (
"Cluster[" << (
int)cInd <<
"] is blocked by self blocking region and reduce 30 dB power,"
1921 "the attenuation is [" << powerAttenuation[cInd] <<
" dB]");
1925 double phiK, xK, thetaK, yK;
1929 phiK = (0.5 * erfc (-1 * params->m_nonSelfBlocking[blockInd][
PHI_INDEX] / sqrt (2))) * 360;
1940 xK = params->m_nonSelfBlocking[blockInd][
X_INDEX];
1941 thetaK = params->m_nonSelfBlocking[blockInd][
THETA_INDEX];
1942 yK = params->m_nonSelfBlocking[blockInd][
Y_INDEX];
1943 NS_LOG_INFO (
"AOA=" << clusterAOA[cInd] <<
" Block Region[" << phiK - xK <<
"," << phiK + xK <<
"]");
1944 NS_LOG_INFO (
"ZOA=" << clusterZOA[cInd] <<
" Block Region[" << thetaK - yK <<
"," << thetaK + yK <<
"]");
1946 if ( std::abs (clusterAOA[cInd] - phiK) < (xK)
1947 && std::abs (clusterZOA[cInd] - thetaK) < (yK))
1949 double A1 = clusterAOA[cInd] - (phiK + xK / 2);
1950 double A2 = clusterAOA[cInd] - (phiK - xK / 2);
1951 double Z1 = clusterZOA[cInd] - (thetaK + yK / 2);
1952 double Z2 = clusterZOA[cInd] - (thetaK - yK / 2);
1953 int signA1, signA2, signZ1, signZ2;
1955 if (xK / 2 < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= xK)
1963 if (-1 * xK < clusterAOA[cInd] - phiK && clusterAOA[cInd] - phiK <= -1 * xK / 2)
1972 if (yK / 2 < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= yK)
1980 if (-1 * yK < clusterZOA[cInd] - thetaK && clusterZOA[cInd] - thetaK <= -1 * yK / 2)
1989 double F_A1 = atan (signA1 * M_PI / 2 * sqrt (M_PI / lambda *
1991 double F_A2 = atan (signA2 * M_PI / 2 * sqrt (M_PI / lambda *
1993 double F_Z1 = atan (signZ1 * M_PI / 2 * sqrt (M_PI / lambda *
1995 double F_Z2 = atan (signZ2 * M_PI / 2 * sqrt (M_PI / lambda *
1997 double L_dB = -20 * log10 (1 - (F_A1 + F_A2) * (F_Z1 + F_Z2));
1998 powerAttenuation[cInd] += L_dB;
1999 NS_LOG_INFO (
"Cluster[" << (
int)cInd <<
"] is blocked by no-self blocking, "
2000 "the loss is [" << L_dB <<
"]" <<
" dB");
2005 return powerAttenuation;
2012 for (
auto i = (last -
first) - 1; i > 0; --i)