LEFT | RIGHT |
(no file at all) | |
| 1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| 2 /* |
| 3 * Copyright (c) 2015 Portland state university |
| 4 * |
| 5 * This program is free software; you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 2 as· |
| 7 * published by the Free Software Foundation; |
| 8 * |
| 9 * This program is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. |
| 13 * |
| 14 * You should have received a copy of the GNU General Public License |
| 15 * along with this program; if not, write to the Free Software |
| 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 * |
| 18 * Author: Farnoosh Moshir <moshir2@cs.pdx.edu> |
| 19 * Suresh Singh <singh@cs.pdx.edu> |
| 20 */ |
| 21 |
| 22 #include "thz-propagation-loss-model.h" |
| 23 #include "ns3/log.h" |
| 24 #include "ns3/mobility-model.h" |
| 25 #include "ns3/double.h" |
| 26 #include "ns3/uinteger.h" |
| 27 #include "ns3/string.h" |
| 28 #include "ns3/pointer.h" |
| 29 #include <cmath> |
| 30 #include <fstream> |
| 31 |
| 32 |
| 33 NS_LOG_COMPONENT_DEFINE ("ThzPropagationLossModel"); |
| 34 |
| 35 namespace ns3 { |
| 36 ···· |
| 37 NS_OBJECT_ENSURE_REGISTERED (ThzDirectionalPropagationLossModel); |
| 38 ···· |
| 39 TypeId |
| 40 ThzDirectionalPropagationLossModel::GetTypeId (void) |
| 41 { |
| 42 static TypeId tid = TypeId ("ns3::ThzDirectionalPropagationLossModel") |
| 43 .SetParent<PropagationLossModel> () |
| 44 .AddConstructor<ThzDirectionalPropagationLossModel> () |
| 45 .AddAttribute ("Frequency", |
| 46 "The carrier frequency (in Hz) at which propagation occurs (
default is 237.5 GHz).", |
| 47 DoubleValue (237.5e9), |
| 48 MakeDoubleAccessor (&ThzDirectionalPropagationLossModel::Set
Frequency, |
| 49 &ThzDirectionalPropagationLossModel::
GetFrequency), |
| 50 MakeDoubleChecker<double> ()) |
| 51 .AddAttribute ("Humidity", |
| 52 "The relative humidity (in %) of the channel (default is 40 %)
", |
| 53 UintegerValue (40), |
| 54 MakeUintegerAccessor (&ThzDirectionalPropagationLossModel::S
etHumidity, |
| 55 &ThzDirectionalPropagationLossModel::GetHu
midity), |
| 56 MakeUintegerChecker<uint32_t> ()) |
| 57 .AddAttribute ("SystemLoss", "The system loss", |
| 58 DoubleValue (1.0), |
| 59 MakeDoubleAccessor (&ThzDirectionalPropagationLossModel::m_s
ystemLoss), |
| 60 MakeDoubleChecker<double> ()) |
| 61 .AddAttribute ("MinLoss", |
| 62 "The minimum value (dB) of the total loss, used at short ran
ges. Note: ", |
| 63 DoubleValue (0.0), |
| 64 MakeDoubleAccessor (&ThzDirectionalPropagationLossModel::Set
MinLoss, |
| 65 &ThzDirectionalPropagationLossModel::
GetMinLoss), |
| 66 MakeDoubleChecker<double> ()) |
| 67 .AddAttribute ("LastInd", |
| 68 "Number of rows in absorptionTable.txt file (Total number of
frequencies)", |
| 69 UintegerValue (5121), |
| 70 MakeUintegerAccessor (&ThzDirectionalPropagationLossModel::Se
tFreqLastInd, |
| 71 &ThzDirectionalPropagationLossModel::GetF
reqLastInd), |
| 72 MakeUintegerChecker<uint32_t> ()) |
| 73 .AddAttribute ("FreqEnd", |
| 74 "The highest frequency that can be used in this model", |
| 75 DoubleValue (2e12), |
| 76 MakeDoubleAccessor (&ThzDirectionalPropagationLossModel::SetF
reqEnd, |
| 77 &ThzDirectionalPropagationLossModel::GetF
reqEnd), |
| 78 MakeDoubleChecker<double> ()) |
| 79 ; |
| 80 return tid; |
| 81 } |
| 82 ···· |
| 83 ThzDirectionalPropagationLossModel::ThzDirectionalPropagationLossModel () |
| 84 { |
| 85 } |
| 86 void |
| 87 ThzDirectionalPropagationLossModel::SetSystemLoss (double systemLoss) |
| 88 { |
| 89 m_systemLoss = systemLoss; |
| 90 } |
| 91 double |
| 92 ThzDirectionalPropagationLossModel::GetSystemLoss (void) const |
| 93 { |
| 94 return m_systemLoss; |
| 95 } |
| 96 void |
| 97 ThzDirectionalPropagationLossModel::SetMinLoss (double minLoss) |
| 98 { |
| 99 m_minLoss = minLoss; |
| 100 } |
| 101 double |
| 102 ThzDirectionalPropagationLossModel::GetMinLoss (void) const |
| 103 { |
| 104 return m_minLoss; |
| 105 } |
| 106 |
| 107 void |
| 108 ThzDirectionalPropagationLossModel::SetFrequency (double frequency) |
| 109 { |
| 110 m_frequency = frequency; |
| 111 static const double C = 299792458.0; // speed of light in vacuum |
| 112 m_lambda = C / frequency; |
| 113 } |
| 114 ···· |
| 115 double |
| 116 ThzDirectionalPropagationLossModel::GetFrequency (void) const |
| 117 { |
| 118 return m_frequency; |
| 119 } |
| 120 ···· |
| 121 void |
| 122 ThzDirectionalPropagationLossModel::SetHumidity (uint32_t humidity) |
| 123 { |
| 124 m_humidity = humidity; |
| 125 } |
| 126 ···· |
| 127 uint32_t |
| 128 ThzDirectionalPropagationLossModel::GetHumidity (void) const |
| 129 { |
| 130 return m_humidity; |
| 131 } |
| 132 ···· |
| 133 void |
| 134 ThzDirectionalPropagationLossModel::SetFreqLastInd (uint32_t lastInd) |
| 135 { |
| 136 m_freqLastInd = lastInd; |
| 137 } |
| 138 |
| 139 uint32_t |
| 140 ThzDirectionalPropagationLossModel::GetFreqLastInd (void) const |
| 141 { |
| 142 return m_freqLastInd; |
| 143 } |
| 144 |
| 145 |
| 146 void |
| 147 ThzDirectionalPropagationLossModel::SetFreqEnd (double freqEnd) |
| 148 { |
| 149 m_freqEnd = freqEnd; |
| 150 } |
| 151 |
| 152 double |
| 153 ThzDirectionalPropagationLossModel::GetFreqEnd (void) const |
| 154 { |
| 155 return m_freqEnd; |
| 156 } |
| 157 ···· |
| 158 double |
| 159 ThzDirectionalPropagationLossModel::DbmToW (double dbm) const |
| 160 { |
| 161 double mw = std::pow (10.0,dbm/10.0); |
| 162 return mw / 1000.0; |
| 163 } |
| 164 ···· |
| 165 double |
| 166 ThzDirectionalPropagationLossModel::DbmFromW (double w) const |
| 167 { |
| 168 double dbm = std::log10 (w * 1000.0) * 10.0; |
| 169 return dbm; |
| 170 } |
| 171 ···· |
| 172 double |
| 173 ThzDirectionalPropagationLossModel::DoCalcRxPower (double txPowerDbm, |
| 174 Ptr<MobilityModel> a, |
| 175 Ptr<MobilityModel> b) const |
| 176 { |
| 177 /* |
| 178 * THzDirectionalPropagationLossModel equation: |
| 179 * where Pt, Gr, Gr and P are in Watt units |
| 180 * L is in meter units. |
| 181 * |
| 182 * P Gt * Gr |
| 183 * --- = --------- * exp(-d * K(f, h)) |
| 184 * Pt L |
| 185 * |
| 186 * Gt: tx gain (unit-less) |
| 187 * Gr: rx gain (unit-less) |
| 188 * Pt: tx power (W) |
| 189 * d: distance (m) |
| 190 * L: system loss |
| 191 * f: frequency (Hz) |
| 192 * K(f, h): Attenuation coefficient corresponds to frequency f and humid
ity h |
| 193 * |
| 194 * |
| 195 * Here, we ignore tx and rx gain and the input and output values |
| 196 * are in dB or dBm: |
| 197 * |
| 198 * 1 |
| 199 * rx = tx + 10 log10 (--- * exp(-d * K(f, h))) |
| 200 * L |
| 201 * |
| 202 * rx: rx power (dB) |
| 203 * tx: tx power (dB) |
| 204 * d: distance (m) |
| 205 * L: system loss (unit-less) |
| 206 * K(f, h): Attenuation coefficient of frequency f and humidity h |
| 207 */ |
| 208 double distance = a->GetDistanceFrom (b); |
| 209 if (distance < 0) |
| 210 { |
| 211 return txPowerDbm - m_minLoss; |
| 212 } |
| 213 ···· |
| 214 if (m_frequency > m_freqEnd) |
| 215 { |
| 216 NS_LOG_ERROR("ThzDirectionalPropagationLossModel is not defined for this
frequency!"); |
| 217 } |
| 218 ···· |
| 219 // find the attenuation coefficient |
| 220 double K = FindAttenuationCoefficient(); |
| 221 ···· |
| 222 double lossDb = -10 * log10 (1 / m_systemLoss * exp(-1 * distance * K)); |
| 223 NS_LOG_DEBUG ("distance=" << distance<< "m, loss=" << lossDb <<"dB"); |
| 224 return txPowerDbm - lossDb; |
| 225 } |
| 226 ···· |
| 227 double |
| 228 ThzDirectionalPropagationLossModel::FindAttenuationCoefficient () const |
| 229 { |
| 230 std::ifstream absorptionFile; |
| 231 std::string line, attenuationCoef; |
| 232 double attenuationCoef_val; |
| 233 uint32_t humidityInd; |
| 234 double freqStep = round(m_freqEnd/m_freqLastInd); |
| 235 double freqInd = round(m_frequency/freqStep)+1; //starts from 1 |
| 236 if (freqInd == m_freqLastInd+1) { |
| 237 freqInd = m_freqLastInd; |
| 238 } |
| 239 ···· |
| 240 //find the humidityInd based on m_humidity |
| 241 if (m_humidity == 0) |
| 242 { |
| 243 humidityInd = 1; |
| 244 } |
| 245 else if (m_humidity == 40) |
| 246 { |
| 247 humidityInd = 2; |
| 248 } |
| 249 else |
| 250 humidityInd = 3; |
| 251 ···· |
| 252 ···· |
| 253 absorptionFile.open ("src/propagation/model/absorptionTable.txt"); |
| 254 if(absorptionFile.is_open ()) |
| 255 { |
| 256 ········ |
| 257 //find the proper line of the table based on the frequency index |
| 258 for(int i = 0; i < freqInd-1; ++i) |
| 259 { |
| 260 getline(absorptionFile, line); |
| 261 } |
| 262 ········ |
| 263 getline(absorptionFile, line); |
| 264 std::istringstream freqLine(line); |
| 265 ········ |
| 266 //read the proper column based on the humidity index from file |
| 267 for (int i = 0; i < humidityInd; i++) |
| 268 { |
| 269 getline(freqLine, attenuationCoef, ' '); |
| 270 } |
| 271 attenuationCoef_val = std::stod(attenuationCoef); |
| 272 ········ |
| 273 return attenuationCoef_val; |
| 274 } |
| 275 else { |
| 276 NS_LOG_ERROR("The file (absorptionTable.txt) cannot be opened!"); |
| 277 return 0; |
| 278 } |
| 279 } |
| 280 ···· |
| 281 ···· |
| 282 int64_t |
| 283 ThzDirectionalPropagationLossModel::DoAssignStreams (int64_t stream) |
| 284 { |
| 285 return 0; |
| 286 } |
| 287 ·· |
| 288 ···· |
| 289 ···· |
| 290 ···· |
| 291 //------------------------------------------------------------------------- // |
| 292 |
| 293 NS_OBJECT_ENSURE_REGISTERED (ThzOmniDirectionalPropagationLossModel); |
| 294 ···· |
| 295 const double ThzOmniDirectionalPropagationLossModel::PI = 3.14159265358979323846
; |
| 296 |
| 297 TypeId |
| 298 ThzOmniDirectionalPropagationLossModel::GetTypeId (void) |
| 299 { |
| 300 static TypeId tid = TypeId ("ns3::ThzOmniDirectionalPropagationLossModel") |
| 301 .SetParent<PropagationLossModel> () |
| 302 .AddConstructor<ThzOmniDirectionalPropagationLossModel> () |
| 303 .AddAttribute ("Frequency", |
| 304 "The carrier frequency (in Hz) at which propagation occurs (d
efault is 237.5 GHz).", |
| 305 DoubleValue (237.5e9), |
| 306 MakeDoubleAccessor (&ThzOmniDirectionalPropagationLossModel::
SetFrequency, |
| 307 &ThzOmniDirectionalPropagationLossModel::
GetFrequency), |
| 308 MakeDoubleChecker<double> ()) |
| 309 .AddAttribute ("Humidity", |
| 310 "The relative humidity (in %) of the channel (default is 40 %
)", |
| 311 UintegerValue (40), |
| 312 MakeUintegerAccessor (&ThzOmniDirectionalPropagationLossModel
::SetHumidity, |
| 313 &ThzOmniDirectionalPropagationLossModel::
GetHumidity), |
| 314 MakeUintegerChecker<uint32_t> ()) |
| 315 .AddAttribute ("SystemLoss", "The system loss", |
| 316 DoubleValue (1.0), |
| 317 MakeDoubleAccessor (&ThzOmniDirectionalPropagationLossModel::
m_systemLoss), |
| 318 MakeDoubleChecker<double> ()) |
| 319 .AddAttribute ("MinLoss", |
| 320 "The minimum value (dB) of the total loss, used at short rang
es. Note: ", |
| 321 DoubleValue (0.0), |
| 322 MakeDoubleAccessor (&ThzOmniDirectionalPropagationLossModel::
SetMinLoss, |
| 323 &ThzOmniDirectionalPropagationLossModel::
GetMinLoss), |
| 324 MakeDoubleChecker<double> ()) |
| 325 .AddAttribute ("FreqLastInd", |
| 326 "Number of rows in absorptionTable.txt file (Total number of
frequencies)", |
| 327 DoubleValue (5121), |
| 328 MakeDoubleAccessor (&ThzOmniDirectionalPropagationLossModel::
SetFreqLastInd, |
| 329 &ThzOmniDirectionalPropagationLossModel::
GetFreqLastInd), |
| 330 MakeDoubleChecker<double> ()) |
| 331 .AddAttribute ("FreqEnd", |
| 332 "The highest frequency that can be used in this model", |
| 333 DoubleValue (2e12), |
| 334 MakeDoubleAccessor (&ThzOmniDirectionalPropagationLossModel::
SetFreqEnd, |
| 335 &ThzOmniDirectionalPropagationLossModel::
GetFreqEnd), |
| 336 MakeDoubleChecker<double> ()) |
| 337 ; |
| 338 return tid; |
| 339 } |
| 340 |
| 341 ThzOmniDirectionalPropagationLossModel::ThzOmniDirectionalPropagationLossModel (
) |
| 342 { |
| 343 } |
| 344 void |
| 345 ThzOmniDirectionalPropagationLossModel::SetSystemLoss (double systemLoss) |
| 346 { |
| 347 m_systemLoss = systemLoss; |
| 348 } |
| 349 double |
| 350 ThzOmniDirectionalPropagationLossModel::GetSystemLoss (void) const |
| 351 { |
| 352 return m_systemLoss; |
| 353 } |
| 354 void |
| 355 ThzOmniDirectionalPropagationLossModel::SetMinLoss (double minLoss) |
| 356 { |
| 357 m_minLoss = minLoss; |
| 358 } |
| 359 double |
| 360 ThzOmniDirectionalPropagationLossModel::GetMinLoss (void) const |
| 361 { |
| 362 return m_minLoss; |
| 363 } |
| 364 |
| 365 void |
| 366 ThzOmniDirectionalPropagationLossModel::SetFrequency (double frequency) |
| 367 { |
| 368 m_frequency = frequency; |
| 369 static const double C = 299792458.0; // speed of light in vacuum |
| 370 m_lambda = C / frequency; |
| 371 } |
| 372 |
| 373 double |
| 374 ThzOmniDirectionalPropagationLossModel::GetFrequency (void) const |
| 375 { |
| 376 return m_frequency; |
| 377 } |
| 378 |
| 379 void |
| 380 ThzOmniDirectionalPropagationLossModel::SetHumidity (uint32_t humidity) |
| 381 { |
| 382 m_humidity = humidity; |
| 383 } |
| 384 |
| 385 uint32_t |
| 386 ThzOmniDirectionalPropagationLossModel::GetHumidity (void) const |
| 387 { |
| 388 return m_humidity; |
| 389 } |
| 390 ···· |
| 391 void |
| 392 ThzOmniDirectionalPropagationLossModel::SetFreqLastInd (uint32_t lastInd) |
| 393 { |
| 394 m_freqLastInd = lastInd; |
| 395 } |
| 396 |
| 397 uint32_t |
| 398 ThzOmniDirectionalPropagationLossModel::GetFreqLastInd (void) const |
| 399 { |
| 400 return m_freqLastInd; |
| 401 } |
| 402 |
| 403 |
| 404 void |
| 405 ThzOmniDirectionalPropagationLossModel::SetFreqEnd (double freqEnd) |
| 406 { |
| 407 m_freqEnd = freqEnd; |
| 408 } |
| 409 |
| 410 double |
| 411 ThzOmniDirectionalPropagationLossModel::GetFreqEnd (void) const |
| 412 { |
| 413 return m_freqEnd; |
| 414 } |
| 415 |
| 416 double |
| 417 ThzOmniDirectionalPropagationLossModel::DbmToW (double dbm) const |
| 418 { |
| 419 double mw = std::pow (10.0,dbm/10.0); |
| 420 return mw / 1000.0; |
| 421 } |
| 422 |
| 423 double |
| 424 ThzOmniDirectionalPropagationLossModel::DbmFromW (double w) const |
| 425 { |
| 426 double dbm = std::log10 (w * 1000.0) * 10.0; |
| 427 return dbm; |
| 428 } |
| 429 |
| 430 double |
| 431 ThzOmniDirectionalPropagationLossModel::DoCalcRxPower (double txPowerDbm, |
| 432 Ptr<MobilityModel> a, |
| 433 Ptr<MobilityModel> b) const |
| 434 { |
| 435 /* |
| 436 * THzOmniDirectionalPropagationLossModel equation: |
| 437 * where Pt, Gr, Gr and P are in Watt units· |
| 438 * L is in meter units. |
| 439 * |
| 440 * |
| 441 * P lambda^2 |
| 442 * --- = Gt * Gr * ------------------- * exp(-d * K(f, h)) |
| 443 * Pt (4 * pi * d)^2 *L |
| 444 * |
| 445 * Gt: tx gain (unit-less) |
| 446 * Gr: rx gain (unit-less) |
| 447 * Pt: tx power (W) |
| 448 * d: distance (m) |
| 449 * L: system loss |
| 450 * f: frequency (Hz) |
| 451 * K(f, h): Attenuation coefficient corresponds to frequency f and humidity
h |
| 452 * lambda: wavelength (m) |
| 453 * |
| 454 * |
| 455 * Here, we ignore tx and rx gain and the input and output values |
| 456 * are in dB or dBm: |
| 457 * |
| 458 * lambda^2 |
| 459 * rx = tx + 10 log10 ( --------------------) * exp(-d * K(f, h)) |
| 460 * (4 * pi * d)^2 * L |
| 461 * |
| 462 * rx: rx power (dB) |
| 463 * tx: tx power (dB) |
| 464 * d: distance (m) |
| 465 * L: system loss (unit-less) |
| 466 * K(f, h): Attenuation coefficient of frequency f and humidity h |
| 467 */ |
| 468 double distance = a->GetDistanceFrom (b); |
| 469 if (distance < 3*m_lambda) |
| 470 { |
| 471 NS_LOG_WARN ("distance not within the far field region => inaccurate pro
pagation loss value"); |
| 472 } |
| 473 if (distance <= 0) |
| 474 { |
| 475 return txPowerDbm - m_minLoss; |
| 476 } |
| 477 ···· |
| 478 if (m_frequency > m_freqEnd) |
| 479 { |
| 480 NS_LOG_ERROR("ThzOmniDirectionalPropagationLossModel is not defined for
this frequency!"); |
| 481 } |
| 482 ···· |
| 483 // find the attenuation coefficient |
| 484 double K = FindAttenuationCoefficient(); |
| 485 ···· |
| 486 double numerator = m_lambda * m_lambda; |
| 487 ···· |
| 488 double denominator = 16 * PI * PI * distance * distance * m_systemLoss; |
| 489 double lossDb = -10 * log10 (exp(-1 * distance * K)* (numerator/denominator)
); |
| 490 NS_LOG_DEBUG ("distance=" << distance<< "m, loss=" << lossDb <<"dB"); |
| 491 return txPowerDbm - std::max (lossDb, m_minLoss); |
| 492 } |
| 493 |
| 494 double |
| 495 ThzOmniDirectionalPropagationLossModel::FindAttenuationCoefficient () const |
| 496 { |
| 497 std::ifstream absorptionFile; |
| 498 std::string line, attenuationCoef; |
| 499 double attenuationCoef_val; |
| 500 uint32_t humidityInd; |
| 501 double freqStep = round(m_freqEnd/m_freqLastInd); |
| 502 double freqInd = round(m_frequency/freqStep)+1; //starts from 1 |
| 503 if (freqInd == m_freqLastInd+1) { |
| 504 freqInd = m_freqLastInd; |
| 505 } |
| 506 ···· |
| 507 ···· |
| 508 //find the humidityInd based on m_humidity |
| 509 if (m_humidity == 0) |
| 510 { |
| 511 humidityInd = 1; |
| 512 } |
| 513 else if (m_humidity == 40) |
| 514 { |
| 515 humidityInd = 2; |
| 516 } |
| 517 else |
| 518 humidityInd = 3; |
| 519 ···· |
| 520 absorptionFile.open ("src/propagation/model/absorptionTable.txt"); |
| 521 if(absorptionFile.is_open ()) |
| 522 { |
| 523 ········ |
| 524 //find the proper line of the table based on the frequency index |
| 525 for(int i = 0; i < freqInd-1; ++i) |
| 526 { |
| 527 getline(absorptionFile, line); |
| 528 } |
| 529 ········ |
| 530 getline(absorptionFile, line); |
| 531 std::istringstream freqLine(line); |
| 532 ········ |
| 533 //read the proper column based on the humidity index from file |
| 534 for (int i = 0; i < humidityInd; i++) |
| 535 { |
| 536 getline(freqLine, attenuationCoef, ' '); |
| 537 } |
| 538 attenuationCoef_val = std::stod(attenuationCoef); |
| 539 ········ |
| 540 return attenuationCoef_val; |
| 541 } |
| 542 else { |
| 543 NS_LOG_ERROR("The file (absorptionTable.txt) cannot be opened!"); |
| 544 return 0; |
| 545 } |
| 546 } |
| 547 |
| 548 |
| 549 int64_t |
| 550 ThzOmniDirectionalPropagationLossModel::DoAssignStreams (int64_t stream) |
| 551 { |
| 552 return 0; |
| 553 } |
| 554 |
| 555 |
| 556 } // namespace ns3 |
LEFT | RIGHT |