29#include "LTENR_PropagationModel.h"
30#include "PropagationModel.h"
31#include "MobilityInterface.h"
32#include "NetSim_utility.h"
34#define c (3.0 * pow(10, 8))
36#define RANDOM_01 (double)rand()/(double)RAND_MAX;
38static double calculate_distance3D(
double distance2D,
double height_BS,
double height_UT)
44 distance3D = pow((pow((distance2D), 2) + pow((height_BS - height_UT), 2)), 0.5);
49static double discrete_uniform_dist(
double values[],
int count)
51 int lower, upper, random;
54 random = (rand() % (upper - lower + 1)) + lower;
69static double log_normal_distribution(ptrLTENR_PROPAGATIONINFO info,
double std)
71 double ldRandomNumber = 0.0;
72 double fFac, fRsq, fV1, fV2;
73 double st, phase, loss;
75 if (info->SHADOWVAR.isConstructiveShadow == 0)
79 ldRandomNumber = RANDOM_01;
80 fV1 = (double)(2.0 * ldRandomNumber - 1.0);
82 ldRandomNumber = RANDOM_01;
83 fV2 = (double)(2.0 * ldRandomNumber - 1.0);
84 fRsq = fV1 * fV1 + fV2 * fV2;
85 }
while (fRsq >= 1.0 || fRsq == 0.0);
87 fFac = (double)(sqrt(-2.0 * log(fRsq) / fRsq));
88 info->SHADOWVAR.Gset = fV1 * fFac;
89 info->SHADOWVAR.Iset = fV2 * fFac;
91 st = info->SHADOWVAR.Gset;
92 info->SHADOWVAR.isConstructiveShadow = 1;
96 st = info->SHADOWVAR.Iset;
97 info->SHADOWVAR.isConstructiveShadow = 0;
102 loss = -1 * std * st;
111static long double ErrorFunc(
double p)
113 return (1.0968 * (sqrt(PI) * 0.5 * (p + (PI * pow(p, 3)) / 12 + (7 * pow(PI, 2) * pow(p, 5)) / 480 +
114 (127 * pow(PI, 3) * pow(p, 7)) / 40320 +
115 (4369 * pow(PI, 4) * pow(p, 9)) / 5806080 +
116 (34807 * pow(PI, 5) * pow(p, 11)) / 182476800)));
120static double normal_distribution(
double args1,
double args2)
122 double fFirstArg, fSecondArg, fRandomNumber, fDistOut;
126 fRandomNumber = RANDOM_01;
127 fDistOut = (double)(fFirstArg + fSecondArg * sqrt(2) * ErrorFunc(2 * fRandomNumber - 1));
132static double uniform_distribution(
double args1,
double args2)
134 double fFirstArg, fSecondArg, fRandomNumber, fDistOut;
137 fRandomNumber = RANDOM_01;
138 fDistOut = fFirstArg + (fSecondArg - fFirstArg) * fRandomNumber;
143static double calculate_LOS_probability(ptrLTENR_PROPAGATIONINFO info)
145 double LOS_probability, chUT = 0;
147 double distance2D_out = 0;
149 if (info->uePosition == LTENR_LOCATION_OUTDOOR && info->gnbPosition != LTENR_LOCATION_INDOOR)
150 distance2D_out = info->dist2D;
152 else if (info->uePosition == LTENR_LOCATION_INDOOR && info->gnbPosition != LTENR_LOCATION_INDOOR)
153 distance2D_out = info->dist2Doutdoor;
155 switch (info->currentScenario)
157 case LTENR_SCENARIO_RMA:
159 if (distance2D_out <= 10)
162 LOS_probability = exp(-(distance2D_out - 10) / 1000);
164 return LOS_probability;
168 case LTENR_SCENARIO_UMA:
170 hUT = info->propagationConfig->UE_height;
172 if (distance2D_out <= 18)
178 else if (13 <= hUT && hUT <= 23)
179 chUT = pow(((hUT - 13) / 10), 1.5);
181 LOS_probability = ((18 / distance2D_out) +
182 (exp(-(distance2D_out / 63)) * (1 - (18 / distance2D_out)))) *
183 (1 + (chUT * (5 / 4) * pow((distance2D_out / 100), 3) *
184 exp(-(distance2D_out / 150))));
186 return LOS_probability;
190 case LTENR_SCENARIO_UMI:
192 if (distance2D_out <= 18)
195 LOS_probability = ((18 / distance2D_out) + (exp(-(distance2D_out / 36)) *
196 (1 - (18 / distance2D_out))));
197 return LOS_probability;
201 case LTENR_SCENARIO_INH:
203 double distance2D_in;
204 distance2D_in = info->dist2D;
206 switch (info->propagationConfig->indoor_type)
208 case LTENR_INH_MIXED_OFFICE:
210 if (distance2D_in <= 1.2)
212 else if (1.2 <= distance2D_in && distance2D_in <= 6.5)
213 LOS_probability = exp(-(distance2D_in - 1.2) / 4.7);
215 LOS_probability = exp(-(distance2D_in - 6.5) / 32.6) * 0.32;
217 return LOS_probability;
221 case LTENR_INH_OPEN_OFFICE:
223 if (distance2D_in <= 5)
225 else if (5 <= distance2D_in && distance2D_in <= 49)
226 LOS_probability = exp(-(distance2D_in - 5) / 70.8);
228 LOS_probability = exp(-(distance2D_in - 49) / 211.7) * 0.54;
230 return LOS_probability;
236 fnNetSimError(
"Unknown INDOOR_OFFICE Type %d!\n", info->propagationConfig->indoor_type);
246 fnNetSimError(
"Unknown Scenario %d in function %s\n", info->currentScenario, __FUNCTION__);
254static LTENR_LOS_NLOS_STATE check_los_state(ptrLTENR_PROPAGATIONINFO info)
256 double LOS_probability;
257 double r = RANDOM_01;
258 if (info->propagationConfig->los_mode != LTENR_LOS_MODE_USER_DEFINED)
259 LOS_probability = calculate_LOS_probability(info);
261 LOS_probability = info->propagationConfig->los_probability;
263 if (r <= LOS_probability)
264 return LTENR_STATE_LOS;
266 return LTENR_STATE_NLOS;
270static double g_UMa(
double d_2D)
275 return ((5 / 4) * pow((d_2D / 100), 3) * exp(-d_2D / 150));
279static double C_UMa(
double d_2D,
double hUT)
283 else if (13 <= hUT && hUT <= 23)
284 return pow(((hUT - 13) / 10), 1.5) * g_UMa(d_2D);
287 fnNetSimError(
"Height of UT beyond range!\n");
293static double calculate_pathloss_only(ptrLTENR_PROPAGATIONINFO info)
295 double fc = info->frequency_gHz;
296 double PL1, PL2, PL3, distance2D, distance3D, distanceBP;
297 double pathloss_RMa_LOS = 0, pathloss_RMa_NLOS = 0;
298 double pathloss_UMa_LOS = 0, pathloss_UMa_NLOS = 0;
299 double pathloss_UMi_LOS = 0, pathloss_UMi_NLOS = 0;
300 double pathloss_InH_LOS = 0, pathloss_InH_NLOS = 0;
302 double hBS, hUT, W, h;
303 double h_effectiveEnv, hBS_effective, hUT_effective;
305 distance2D = info->dist2D;
306 distance3D = info->dist3D;
308 LTENR_LOS_NLOS_STATE state = info->propagationConfig->state;
310 switch (info->currentScenario)
312 case LTENR_SCENARIO_RMA:
314 hBS = info->propagationConfig->gNB_height;
315 hUT = info->propagationConfig->UE_height;
316 W = info->propagationConfig->street_width;
317 h = info->propagationConfig->buildings_height;
319 distanceBP = 2 * PI * hBS * hUT * ((fc * 1000000000) / c);
321 PL1 = (20 * log10(40 * PI * distance3D * fc / 3)) + fmin((0.03 * pow(h, 1.72)), 10) *
322 log10(distance3D) - fmin((0.044 * pow(h, 1.72)), 14.77) + (0.002 * log10(h) * distance3D);
323 PL2 = PL1 + (40 * log10(distance3D / distanceBP));
325 if (10 <= distance2D && distance2D <= distanceBP)
326 pathloss_RMa_LOS = PL1;
327 else if (distanceBP <= distance2D && distance2D <= 10000)
328 pathloss_RMa_LOS = PL2;
329 else if (distance2D > 10000)
330 pathloss_RMa_LOS = -1*NEGATIVE_DBM;
332 if (state == LTENR_STATE_LOS)
333 return pathloss_RMa_LOS;
337 PL3 = 161.04 - (7.1 * log10(W)) + (7.5 * log10(h)) -
338 ((24.37 - 3.7 * pow((h / hBS), 2)) * log10(hBS)) +
339 ((43.42 - 3.1 * log10(hBS)) * (log10(distance3D) - 3)) +
340 (20 * log10(fc)) - ((3.2 * pow((log10(11.75 * hUT)), 2) - 4.97));
341 if (distance2D > 5000)
345 if (10 <= distance2D && distance2D <= 5000)
346 pathloss_RMa_NLOS = fmax(pathloss_RMa_LOS, PL3);
348 return pathloss_RMa_NLOS;
353 case LTENR_SCENARIO_UMA:
355 hBS = info->propagationConfig->gNB_height;
356 hUT = info->propagationConfig->UE_height;
358 double prob = 1 / (1 + C_UMa(distance2D, hUT));
359 double r = RANDOM_01;
362 h_effectiveEnv = 1.0;
367 if ((hUT - 1.5) <= 12)
368 h_effectiveEnv = hUT - 1.5;
369 else if (12 < (hUT - 1.5) && (hUT - 1.5) <= 15)
372 values[1] = hUT - 1.5;
373 h_effectiveEnv = discrete_uniform_dist(values, 2);
375 else if (15 < (hUT - 1.5) && (hUT - 1.5) <= 18)
379 values[2] = hUT - 1.5;
380 h_effectiveEnv = discrete_uniform_dist(values, 3);
387 values[3] = hUT - 1.5;
388 h_effectiveEnv = discrete_uniform_dist(values, 4);
392 hBS_effective = hBS - h_effectiveEnv;
393 hUT_effective = hUT - h_effectiveEnv;
395 distanceBP = 4 * hBS_effective * hUT_effective * ((fc * 1000000000) / c);
397 PL1 = 28.0 + (22 * log10(distance3D)) + (20 * log10(fc));
398 PL2 = 28.0 + (40 * log10(distance3D)) + (20 * log10(fc)) - (9 * log10(pow(distanceBP, 2) +
399 pow((hBS - hUT), 2)));
401 if (10 <= distance2D && distance2D <= distanceBP)
402 pathloss_UMa_LOS = PL1;
403 else if (distanceBP <= distance2D && distance2D <= 5000)
404 pathloss_UMa_LOS = PL2;
405 else if (distance2D > 5000)
406 pathloss_UMa_LOS = -1 * NEGATIVE_DBM;
408 if (state == LTENR_STATE_LOS)
409 return pathloss_UMa_LOS;
413 PL3 = 13.54 + (39.08 * log10(distance3D)) + (20 * log10(fc)) - (0.6 * (hUT - 1.5));
414 if (distance2D > 5000)
417 if (10 <= distance2D && distance2D <= 5000)
418 pathloss_UMa_NLOS = fmax(pathloss_UMa_LOS, PL3);
420 return pathloss_UMa_NLOS;
425 case LTENR_SCENARIO_UMI:
427 hBS = info->propagationConfig->gNB_height;
428 hUT = info->propagationConfig->UE_height;
429 h_effectiveEnv = 1.0;
430 hBS_effective = hBS - h_effectiveEnv;
431 hUT_effective = hUT - h_effectiveEnv;
433 distanceBP = 4 * hBS_effective * hUT_effective * ((fc * 1000000000) / c);
435 PL1 = 32.4 + (21 * log10(distance3D)) + (20 * log10(fc));
436 PL2 = 32.4 + (40 * log10(distance3D)) + (20 * log10(fc)) - (9.5 * log10(pow(distanceBP, 2) +
438 pow((hBS - hUT), 2)));
439 if (distance2D > 5000)
440 pathloss_UMi_LOS = -1 * NEGATIVE_DBM;
441 else if (10 <= distance2D && distance2D <= distanceBP)
442 pathloss_UMi_LOS = PL1;
443 else if (distanceBP <= distance2D && distance2D <= 5000)
444 pathloss_UMi_LOS = PL2;
446 if (state == LTENR_STATE_LOS)
447 return pathloss_UMi_LOS;
451 PL3 = (35.3 * log10(distance3D)) + 22.4 + (21.3 * log10(fc)) - (0.3 * (hUT - 1.5));
452 if (distance2D > 5000)
455 if (10 <= distance2D && distance2D <= 5000)
456 pathloss_UMi_NLOS = fmax(pathloss_UMi_LOS, PL3);
458 return pathloss_UMi_NLOS;
463 case LTENR_SCENARIO_INH:
465 hBS = info->propagationConfig->gNB_height;
466 hUT = info->propagationConfig->UE_height;
468 pathloss_InH_LOS = 32.4 + (17.3 * log10(distance3D)) + (20 * log10(fc));
470 if (state == LTENR_STATE_LOS)
471 return pathloss_InH_LOS;
475 PL3 = (38.3 * log10(distance3D)) + 17.30 + (24.9 * log10(fc));
476 pathloss_InH_NLOS = fmax(pathloss_InH_LOS, PL3);
477 return pathloss_InH_NLOS;
484 fnNetSimError(
"Unknown Scenario %d in funtion %s\n", info->currentScenario, __FUNCTION__);
491static double calculate_shadow_fading(ptrLTENR_PROPAGATIONINFO info)
493 double fc = info->frequency_gHz;
494 double hBS, hUT, distanceBP, shadowFadingStd = 0;
495 double distance2D = info->dist2D;
497 LTENR_LOS_NLOS_STATE state = info->propagationConfig->state;
499 switch (info->currentScenario)
501 case LTENR_SCENARIO_RMA:
503 hBS = info->propagationConfig->gNB_height;
504 hUT = info->propagationConfig->UE_height;
506 distanceBP = 2 * PI * hBS * hUT * ((fc * 1000000000) / c);
508 if (state == LTENR_STATE_LOS)
510 if (10 <= distance2D && distance2D <= distanceBP)
512 else if (distanceBP <= distance2D && distance2D <= 10000)
518 return log_normal_distribution(info, shadowFadingStd);
522 case LTENR_SCENARIO_UMA:
524 if (state == LTENR_STATE_LOS)
529 return log_normal_distribution(info, shadowFadingStd);
533 case LTENR_SCENARIO_UMI:
535 if (state == LTENR_STATE_LOS)
538 shadowFadingStd = 7.82;
540 return log_normal_distribution(info, shadowFadingStd);
544 case LTENR_SCENARIO_INH:
546 if (state == LTENR_STATE_LOS)
549 shadowFadingStd = 8.03;
551 return log_normal_distribution(info, shadowFadingStd);
557 fnNetSimError(
"Unknown Scenario %d in function %s\n", info->currentScenario, __FUNCTION__);
564static double calculate_O2I_Buildingpenetrationloss(ptrLTENR_PROPAGATIONINFO info)
566 double f = info->frequency_gHz;
567 double PL_tw, PL_in, std_p;
569 double L_glass = 2 + (0.2 * f);
570 double L_iirglass = 23 + (0.3 * f);
571 double L_concrete = 5 + (4 * f);
573 double dist2D_in = 0.0;
574 if (info->propagationConfig->pathLossModel == LTENR_PATHLOSS_MODEL_3GPP38_901_7_4_1)
576 if (info->currentScenario == LTENR_SCENARIO_UMA || info->currentScenario == LTENR_SCENARIO_UMI)
577 dist2D_in = fmin(uniform_distribution(0, 25), uniform_distribution(0, 25));
578 else if (info->currentScenario == LTENR_SCENARIO_RMA)
579 dist2D_in = fmin(uniform_distribution(0, 10), uniform_distribution(0, 10));
582 switch (info->propagationConfig->o2iBuildingPenetrationModel)
584 case LTENR_O2IBUILDINGPENETRATION_MODEL_NONE:
587 case LTENR_O2IBUILDINGPENETRATION_MODEL_LOW_LOSS:
589 PL_tw = 5 - 10 * log10((0.3 * pow(10, (-L_glass / 10))) + (0.7 * pow(10, (-L_concrete / 10))));
590 PL_in = 0.5 * dist2D_in;
593 O2Iloss = PL_tw + PL_in + abs((
int)normal_distribution(0, std_p));
596 case LTENR_O2IBUILDINGPENETRATION_MODEL_HIGH_LOSS:
598 PL_tw = 5 - 10 * log10((0.7 * pow(10, (-L_iirglass / 10))) + (0.3 * pow(10, (-L_concrete / 10))));
599 PL_in = 0.5 * dist2D_in;
602 O2Iloss = PL_tw + PL_in + abs((
int)normal_distribution(0, std_p));
607 fnNetSimError(
"Unknown O2I building penetration model %s in function %s\n",
608 strLTENR_O2IBUILDINGPENETRATION_MODEL[info->propagationConfig->o2iBuildingPenetrationModel],
617static void decideIndoorOutDoor(ptrLTENR_PROPAGATIONINFO info)
619 if (fnMobility_isPosInsideAnyBuilding(&info->uePos) != 0)
620 info->uePosition = LTENR_LOCATION_INDOOR;
622 info->uePosition = LTENR_LOCATION_OUTDOOR;
624 if (fnMobility_isPosInsideAnyBuilding(&info->gnbPos))
625 info->gnbPosition = LTENR_LOCATION_INDOOR;
627 info->gnbPosition = LTENR_LOCATION_OUTDOOR;
630static void calculateDistance(ptrLTENR_PROPAGATIONINFO info)
632 info->dist2D = fn_NetSim_Utilities_CalculateDistance(&info->gnbPos, &info->uePos);
633 if (info->uePosition == LTENR_LOCATION_INDOOR && info->gnbPosition != LTENR_LOCATION_INDOOR)
635 info->dist2Dindoor = fnMobility_findIndoorDistance(&info->gnbPos, &info->uePos);
636 info->dist2Doutdoor = info->dist2D - info->dist2Dindoor;
640static void recalculate_localvar(ptrLTENR_PROPAGATIONINFO info)
642 info->frequency_gHz = info->centralFrequency_MHz / 1000.0;
644 decideIndoorOutDoor(info);
645 calculateDistance(info);
647 if (info->gnbPosition != LTENR_LOCATION_INDOOR)
648 info->currentScenario = info->propagationConfig->outScenario;
650 info->currentScenario = info->propagationConfig->inScenario;
652 switch (info->currentScenario)
654 case LTENR_SCENARIO_RMA:
656 if (info->dist2D < 10)
659 info->dist3D = calculate_distance3D(info->dist2D, info->propagationConfig->gNB_height,
660 info->propagationConfig->UE_height);
663 case LTENR_SCENARIO_UMA:
665 if (info->dist2D < 10)
668 info->dist3D = calculate_distance3D(info->dist2D, info->propagationConfig->gNB_height,
669 info->propagationConfig->UE_height);
672 case LTENR_SCENARIO_UMI:
674 if (info->dist2D < 10)
677 info->dist3D = calculate_distance3D(info->dist2D, info->propagationConfig->gNB_height,
678 info->propagationConfig->UE_height);
681 case LTENR_SCENARIO_INH:
683 if (info->dist2D < 1)
686 info->dist3D = calculate_distance3D(info->dist2D, info->propagationConfig->gNB_height,
687 info->propagationConfig->UE_height);
692 fnNetSimError(
"Unknown Scenario %d in function %s!\n", info->currentScenario, __FUNCTION__);
697_declspec(dllexport)
void LTENR_Propagation_TotalLoss(ptrLTENR_PROPAGATIONINFO info)
699 recalculate_localvar(info);
701 info->propagationConfig->state = check_los_state(info);
703 if (info->propagationConfig->isPathLossEnabled)
705 if (info->propagationConfig->pathLossModel == LTENR_PATHLOSS_MODEL_3GPP38_901_7_4_1)
706 info->dPathLoss = calculate_pathloss_only(info);
707 else if (info->propagationConfig->pathLossModel == LTENR_PATHLOSS_MODEL_LOG_DISTANCE)
708 info->dPathLoss = (-1) * _propagation_calculate_logdistancepathloss(info->propagationConfig->pathLossExponent,
709 info->dist3D, info->centralFrequency_MHz, info->propagationConfig->d0);
712 fnNetSimError(
"5G - Unknown pathloss model %d in %s\n",
713 info->propagationConfig->pathLossModel, __FUNCTION__);
717 else info->dPathLoss = 0;
719 if (info->propagationConfig->isShadowFadingEnabled)
720 info->dShadowFadingLoss = calculate_shadow_fading(info);
721 else if (info->propagationConfig->shadowFadingModel == LTENR_SHADOWFADING_MODEL_LOGNORMAL)
722 info->dShadowFadingLoss = _propagation_calculate_lognormalshadow(info->propagationConfig->standardDeviation,
723 &info->propagationConfig->Gset, &info->propagationConfig->iSet);
725 info->dShadowFadingLoss = 0;
727 if (info->propagationConfig->isO2IBuildingPenetrationLossEnabled &&
728 info->uePosition == LTENR_LOCATION_INDOOR &&
729 info->currentScenario != LTENR_SCENARIO_INH)
730 info->dO2ILoss = calculate_O2I_Buildingpenetrationloss(info);
734 if (info->propagationConfig->additionalLossModel == LTENR_ADDITIONAL_LOSS_MATLAB)
735 info->dAdditionalLoss = netsim_matlab_calculate_loss(info);
737 info->dAdditionalLoss = 0;
739 info->dTotalLoss = info->dPathLoss + info->dShadowFadingLoss + info->dO2ILoss + info->dAdditionalLoss;
741#ifdef LTENR_PROPAGATION_LOG
742 print_ltenr_log(
"\tPropagation Model starts for gNB = %d and UE = %d\n", info->gnbId, info->ueId);
743 print_ltenr_log(
"\t\t2D Distance = %lf m\n", info->dist2D);
744 print_ltenr_log(
"\t\t3D Distance = %lf m\n", info->dist3D);
745 print_ltenr_log(
"\t\tChannel condition = %s\n", strLTENR_STATE[info->propagationConfig->state]);
746 print_ltenr_log(
"\t\tTotal Propagation Loss = %lf dB\n", info->dTotalLoss);
747 print_ltenr_log(
"\t\t\tPathLoss = %lf dB\n", info->dPathLoss);
748 print_ltenr_log(
"\t\t\tShadow Fading Loss = %lf dB\n", info->dShadowFadingLoss);
749 print_ltenr_log(
"\t\t\tO2I Penetration Loss = %lf dB\n", info->dO2ILoss);