src/buildings/model/buildings-propagation-loss-model.cc
changeset 8248 986f7db9f056
parent 8244 ee25b5332a67
child 8252 cc60191ad0d4
child 8272 3969525083ca
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/buildings/model/buildings-propagation-loss-model.cc	Wed Sep 28 16:48:53 2011 +0200
@@ -0,0 +1,830 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Marco Miozzo  <marco.miozzo@cttc.es>
+ * 
+ */
+
+#include "ns3/propagation-loss-model.h"
+#include "ns3/log.h"
+#include "ns3/mobility-model.h"
+#include "ns3/double.h"
+#include "ns3/pointer.h"
+#include <math.h>
+#include "buildings-propagation-loss-model.h"
+#include "ns3/buildings-mobility-model.h"
+#include "ns3/enum.h"
+
+#include <ns3/shadowing-loss-model.h>
+#include <ns3/jakes-fading-loss-model.h>
+
+
+NS_LOG_COMPONENT_DEFINE ("BuildingsPropagationLossModel");
+
+namespace ns3 {
+  
+NS_OBJECT_ENSURE_REGISTERED (BuildingsPropagationLossModel);
+
+
+
+class BuildingsPropagationLossModel::ShadowingLoss 
+{
+  public:
+  ShadowingLoss (double mean, double sigma);
+  ~ShadowingLoss ();
+  double GetLoss ();
+  Ptr<MobilityModel> GetReceiver (void);
+  private:
+  Ptr<MobilityModel> m_receiver;
+  NormalVariable m_randVariable;
+  double m_shadowingValue;
+};
+
+
+BuildingsPropagationLossModel::ShadowingLoss::ShadowingLoss (double mean, double sigma) :
+m_randVariable (mean, sigma*sigma)  // NormalVariable class wants mean and variance (sigma is a standard deviation)
+{
+  m_shadowingValue = m_randVariable.GetValue ();
+  NS_LOG_INFO (this << " New Shadowing: sigma " << sigma << " value " << m_shadowingValue);
+}
+
+BuildingsPropagationLossModel::ShadowingLoss::~ShadowingLoss ()
+{
+  
+}
+  
+double
+BuildingsPropagationLossModel::ShadowingLoss::GetLoss ()
+{
+  return (m_shadowingValue);
+}
+
+Ptr<MobilityModel>
+BuildingsPropagationLossModel::ShadowingLoss::GetReceiver ()
+{
+  return m_receiver;
+}
+
+TypeId
+BuildingsPropagationLossModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::BuildingsPropagationLossModel")
+
+    .SetParent<PropagationLossModel> ()
+
+    .AddConstructor<BuildingsPropagationLossModel> ()
+
+    .AddAttribute ("Lambda",
+                   "The wavelength  (default is 2.106 GHz at 300 000 km/s).",
+                   DoubleValue (300000000.0 / 2160e6),
+                   MakeDoubleAccessor (&BuildingsPropagationLossModel::SetLambda, &BuildingsPropagationLossModel::GetLambda),
+                   MakeDoubleChecker<double> ())
+
+    .AddAttribute ("Frequency",
+                   "The Frequency  (default is 2.106 GHz).",
+                   DoubleValue (2160e6),
+                   MakeDoubleAccessor (&BuildingsPropagationLossModel::m_frequency),
+                   MakeDoubleChecker<double> ())
+                   
+     .AddAttribute ("ShadowSigmaOutdoor",
+                    "Standard deviation of the normal distribution used for calculate the shadowing for outdoor nodes",
+                      DoubleValue (7.0),
+                     MakeDoubleAccessor (&BuildingsPropagationLossModel::m_shadowingSigmaOutdoor),
+                      MakeDoubleChecker<double> ())
+                      
+      .AddAttribute ("ShadowSigmaIndoor",
+                     "Standard deviation of the normal distribution used for calculate the shadowing for indoor nodes ",
+                      DoubleValue (8.0),
+                     MakeDoubleAccessor (&BuildingsPropagationLossModel::m_shadowingSigmaIndoor),
+                      MakeDoubleChecker<double> ())
+      .AddAttribute ("ShadowSigmaExtWalls",
+                    "Standard deviation of the normal distribution used for calculate the shadowing due to ext walls ",
+                    DoubleValue (5.0),
+                    MakeDoubleAccessor (&BuildingsPropagationLossModel::m_shadowingSigmaExtWalls),
+                    MakeDoubleChecker<double> ())
+                   
+    .AddAttribute ("RooftopLevel",
+                  " The height of the rooftop [m].",
+                  DoubleValue (20.0),
+                  MakeDoubleAccessor (&BuildingsPropagationLossModel::m_rooftopHeight),
+                  MakeDoubleChecker<double> ())
+                  
+    .AddAttribute ("Los2NlosThr",
+                    " Threshold from LoS to NLoS in ITU 1411 [m].",
+                    DoubleValue (200.0),
+                    MakeDoubleAccessor (&BuildingsPropagationLossModel::m_itu1411NlosThreshold),
+                    MakeDoubleChecker<double> ())
+                    
+    .AddAttribute ("ITU1411DistanceThr",
+                    " Threshold for ITU 1411 [m].",
+                    DoubleValue (2000.0),
+                    MakeDoubleAccessor (&BuildingsPropagationLossModel::m_itu1411DistanceThreshold),
+                    MakeDoubleChecker<double> ())
+
+    .AddAttribute ("MinDistance",
+                   "The distance under which the propagation model refuses to give results (m) ",
+                   DoubleValue (0.5),
+                   MakeDoubleAccessor (&BuildingsPropagationLossModel::SetMinDistance, &BuildingsPropagationLossModel::GetMinDistance),
+                   MakeDoubleChecker<double> ())
+                   
+      .AddAttribute ("Environment", 
+                    "Environment Scenario",
+                    EnumValue (BuildingsPropagationLossModel::Urban),
+                     MakeEnumAccessor (&BuildingsPropagationLossModel::SetEnvironment,
+                     &BuildingsPropagationLossModel::GetEnvironment),
+                    MakeEnumChecker (BuildingsPropagationLossModel::Urban, "Urban",
+                                      BuildingsPropagationLossModel::SubUrban, "SubUrban",
+                                      BuildingsPropagationLossModel::OpenAreas, "OpenAreas"))
+
+      .AddAttribute ("CitySize", 
+                      "Dimension of the city",
+                      EnumValue (BuildingsPropagationLossModel::Large),
+                     MakeEnumAccessor (&BuildingsPropagationLossModel::SetCitySize),
+                      MakeEnumChecker (BuildingsPropagationLossModel::Small, "Small",
+                                      BuildingsPropagationLossModel::Medium, "Medium",
+                                      BuildingsPropagationLossModel::Large, "Large"));
+
+    
+  return tid;
+}
+
+BuildingsPropagationLossModel::BuildingsPropagationLossModel () :
+  C (0),
+  m_environment (Urban),
+  m_citySize (Large),
+  m_streetsOrientation (45.0),
+  m_streetsWidth (20.0),
+  m_buildingsExtend (80.0),
+  m_buildingSeparation (50.0)
+{
+}
+
+BuildingsPropagationLossModel::~BuildingsPropagationLossModel ()
+{
+  for (PairsList::reverse_iterator i = m_shadowingPairs.rbegin (); i != m_shadowingPairs.rend (); i++)
+  {
+    PairsSet *ps = *i;
+    for (DestinationList::iterator r = ps->receivers.begin (); r != ps->receivers.end (); r++)
+    {
+      ShadowingLoss *pc = *r;
+      delete pc;
+    }
+    ps->sender = 0;
+    ps->receivers.clear ();
+    delete ps;
+  }
+  m_shadowingPairs.clear ();
+}
+
+// void
+// BuildingsPropagationLossModel::SetLambda (double frequency, double speed)
+// {
+//   m_lambda = speed / frequency;
+//   m_frequency = frequency;
+// }
+
+void
+BuildingsPropagationLossModel::SetLambda (double lambda)
+{
+  m_lambda = lambda;
+  m_frequency = 300000000 / lambda;
+}
+
+double
+BuildingsPropagationLossModel::GetLambda (void) const
+{
+  return m_lambda;
+}
+
+void
+BuildingsPropagationLossModel::SetMinDistance (double minDistance)
+{
+  m_minDistance = minDistance;
+}
+double
+BuildingsPropagationLossModel::GetMinDistance (void) const
+{
+  return m_minDistance;
+}
+
+void
+BuildingsPropagationLossModel::SetEnvironment (Environment env)
+{
+//   if (env==Urban)
+//   {
+//      NS_LOG_INFO (this << " Urban");
+//   }
+//   else if (env==SubUrban)
+//   {
+//     NS_LOG_INFO (this << " SubUrban");
+//   }
+//   else if (env==OpenAreas)
+//   {
+//     NS_LOG_INFO (this << " OpenAreas");
+//   }
+  m_environment = env;
+}
+
+BuildingsPropagationLossModel::Environment
+BuildingsPropagationLossModel::GetEnvironment (void) const
+{
+  return m_environment;
+}
+
+void
+BuildingsPropagationLossModel::SetCitySize (CitySize size)
+{
+  m_citySize = size;
+}
+
+BuildingsPropagationLossModel::CitySize
+BuildingsPropagationLossModel::GetCitySize (void) const
+{
+  return m_citySize;
+}
+
+
+
+double
+BuildingsPropagationLossModel::OkumuraHata (Ptr<BuildingsMobilityModel> a, Ptr<BuildingsMobilityModel> b) const
+{
+  // Hp: a is the rooftop antenna (from GetLoss logic)
+  double loss = 0.0;
+  double fmhz = m_frequency/1e6;
+  double dist = a->GetDistanceFrom (b) / 1000.0; 
+  if (m_frequency<=1.500e9)
+    {
+      // standard Okumura Hata (from wikipedia)
+      double log_f = log10 (fmhz);
+      double hb = (a->GetPosition ().z>b->GetPosition ().z ? a->GetPosition ().z : b->GetPosition ().z);
+      double hm = (a->GetPosition ().z< b->GetPosition ().z ? a->GetPosition ().z : b->GetPosition ().z);
+      NS_ASSERT_MSG (hb > 0 && hm > 0, "nodes' height must be greater then 0");
+      double log_aHeight = 13.82 * log10 (hb);
+      double log_bHeight = 0.0;
+      if (m_citySize == Large)
+        {
+          if (m_frequency<200)
+            {
+              log_bHeight = 8.29 * pow (log10 (1.54 * hm), 2) -  1.1;
+            }
+          else
+            {
+              log_bHeight = 3.2 * pow (log10 (11.75 * hm), 2) - 4.97;
+            }
+        }
+      else
+        {
+          log_bHeight = 0.8 + (1.1*log_f - 0.7)*hm - 1.56*log_f;
+        }
+        
+//       NS_LOG_INFO (this << " logf " << 26.16 * log_f << " loga " << log_aHeight << " X " << (((44.9 - (6.55 * log10(hb)) ))*log10 (a->GetDistanceFrom (b))) << " logb " << log_bHeight);
+      loss = 69.55 + (26.16 * log_f) - log_aHeight + (((44.9 - (6.55 * log10(hb)) ))*log10 (dist)) - log_bHeight;
+      if (m_environment == SubUrban)
+        {
+          loss += - 2 * (pow(log10 (fmhz / 28), 2)) - 5.4;
+        }
+      else if (m_environment == OpenAreas)
+        {
+          loss += -4.70*pow(log10(fmhz),2) + 18.33*log10(fmhz) - 40.94;
+        }
+          
+    }
+  else if (m_frequency <= 2.170e9) // max 3GPP freq EUTRA band #1
+    {
+      // COST 231 Okumura model
+      double log_f = log10 (fmhz);
+      double hb = (a->GetPosition ().z>b->GetPosition ().z ? a->GetPosition ().z : b->GetPosition ().z);
+      double hm = (a->GetPosition ().z< b->GetPosition ().z ? a->GetPosition ().z : b->GetPosition ().z);
+      NS_ASSERT_MSG (hb > 0 && hm > 0, "nodes' height must be greater then 0");
+      double log_aHeight = 13.82 * log10 (hb);
+      double log_bHeight = 0.0;
+      double C = 0.0;
+        
+      if (m_citySize == Large)
+        {
+          log_bHeight = 3.2 * pow ((log10(11.75 * hm)),2);
+          C = 3;
+        }
+      else
+        {
+          log_bHeight = 1.1*log_f - 0.7*hm - (1.56*log_f - 0.8);
+        }
+      
+      loss = 46.3 + (33.9 * log_f) - log_aHeight + (((44.9 - (6.55 * log10(hb)) ))*log10 (dist)) - log_bHeight + C;
+    }
+  else if (m_frequency <= 2.690e9) // max 3GPP freq EUTRA band #1
+    {
+      // Empirical model from
+      // "Path Loss Models for Suburban Scenario at 2.3GHz, 2.6GHz and 3.5GHz"
+      // Sun Kun, Wang Ping, Li Yingze
+      // Antennas, Propagation and EM Theory, 2008. ISAPE 2008. 8th International Symposium on 
+      loss = 36 + 26*log10(dist*1000);
+    }
+      
+  return (loss);
+}
+
+
+
+double
+BuildingsPropagationLossModel::ItuR1411 (Ptr<BuildingsMobilityModel> a, Ptr<BuildingsMobilityModel> b) const
+{
+  if (a->GetDistanceFrom (b) < m_itu1411NlosThreshold)
+    {
+      return (ItuR1411Los (a,b));
+    }
+  else
+    {
+      return (ItuR1411NlosOverRooftop (a,b));
+    }
+}
+
+
+double
+BuildingsPropagationLossModel::ItuR1411Los (Ptr<BuildingsMobilityModel> a, Ptr<BuildingsMobilityModel> b) const
+{
+  NS_LOG_INFO (this);
+  double dist = a->GetDistanceFrom (b);
+  double lossLow = 0.0;
+  double lossUp = 0.0;
+  double pi = 3.141592653589793;
+  NS_ASSERT_MSG (a->GetPosition ().z > 0 && b->GetPosition ().z > 0, "nodes' height must be greater then 0");
+  double Lbp = fabs (20*log10 ((m_lambda*m_lambda)/(8*pi*a->GetPosition ().z*b->GetPosition ().z)));
+  double Rbp = (4 * a->GetPosition ().z * b->GetPosition ().z) / m_lambda;
+//   NS_LOG_INFO (this << " Lbp " << Lbp << " Rbp " << Rbp << " lambda " << m_lambda);
+  if (dist <= Rbp)
+  {
+    lossLow = Lbp + 20*log10(dist/Rbp);
+    lossUp = Lbp + 20 + 25*log10(dist/Rbp);
+  }
+  else
+  {
+    lossLow = Lbp + 40*log10(dist/Rbp);
+    lossUp = Lbp + 20 + 40*log10(dist/Rbp);
+  }
+  
+  double loss = (lossUp + lossLow) / 2;
+  
+  return (loss);
+}
+
+
+double
+BuildingsPropagationLossModel::ItuR1411NlosOverRooftop (Ptr<BuildingsMobilityModel> a, Ptr<BuildingsMobilityModel> b) const
+{
+  NS_LOG_INFO (this);
+  double Lori = 0.0;
+  double fmhz = m_frequency/1e6;
+  if ((m_streetsOrientation>=0)&&(m_streetsOrientation<35))
+    {
+      Lori = -10.0 + 0.354*m_streetsOrientation;
+    }
+  else if ((m_streetsOrientation>=35)&&(m_streetsOrientation<55))
+    {
+      Lori = 2.5 + 0.075*(m_streetsOrientation - 35);
+    }
+  else if ((m_streetsOrientation>=55)&&(m_streetsOrientation<90))
+    {
+      Lori = 2.5 + 0.075*(m_streetsOrientation - 55);
+    }
+  else
+    {
+      NS_LOG_ERROR (this << " Street Orientation must be in [0,90]");
+    }
+  double distance = a->GetDistanceFrom (b);
+  double hb = (a->GetPosition ().z>b->GetPosition ().z ? a->GetPosition ().z : b->GetPosition ().z);
+  double hm = (a->GetPosition ().z< b->GetPosition ().z ? a->GetPosition ().z : b->GetPosition ().z);
+  NS_ASSERT_MSG (hm > 0 && hb > 0, "nodes' height must be greater then 0");
+  double Dhb = hb - m_rooftopHeight;
+  double ds = (m_lambda * distance * distance) / (Dhb * Dhb);
+  double Lmsd = 0.0;
+  double pi = 3.141592653589793;
+//   NS_LOG_INFO (this << " build " << m_buildingsExtend << " ds " << ds << " roof " << m_rooftopHeight << " hb " << hb << " lambda " << m_lambda);
+  if (ds < m_buildingsExtend)
+    {
+      double Lbsh = 0.0;
+      double ka = 0.0;
+      double kd = 0.0;
+      double kf = 0.0;
+      if (hb > m_rooftopHeight)
+        {
+          Lbsh = -18*log10(1+Dhb);
+          ka = (fmhz > 2000 ? 71.4 : 54.0);
+          kd = 18.0;
+        }
+      else 
+        {
+          Lbsh = 0;
+          kd = 18.0 - 15*Dhb/a->GetPosition ().z;
+          if (distance <500)
+            {
+              ka = 54.0 - 1.6*Dhb*distance/1000;
+            }
+            else
+            {
+              ka = 54.0 - 0.8*Dhb;
+            }
+        }
+      if (fmhz>2000)
+        {
+          kf = -8;
+        }
+      else if ((m_environment==Urban)&&(m_citySize==Large))
+        {
+          kf = -4 + 0.7*(fmhz/925.0 -1);
+        }
+      else
+        {
+          kf = -4 + 1.5*(fmhz/925.0 -1);
+        }
+      
+      Lmsd = Lbsh + ka + kd*log10(distance/1000.0) + kf*log10(fmhz) -9.0*log10(m_buildingSeparation); 
+    }
+  else
+    {
+      double theta = atan (Dhb/m_buildingSeparation);
+      double rho = sqrt(Dhb*Dhb+m_buildingSeparation*m_buildingSeparation);
+      double Qm = 0.0;
+      if ((hb > m_rooftopHeight -1.0) && (hb < m_rooftopHeight + 1.0))
+        {
+          Qm = m_buildingSeparation / distance;
+        }
+      else if (hb > m_rooftopHeight)
+        {
+          Qm = 2.35*pow(Dhb/distance*sqrt(m_buildingSeparation/m_lambda), 0.9);
+        }
+      else
+        {
+          Qm = m_buildingSeparation/(2*pi*distance)*sqrt(m_lambda/rho)*(1/theta-(1/(2*pi+theta)));
+        }
+      Lmsd = -10*log10(Qm*Qm);
+    }
+  double Lbf = 32.4 + 20*log10(distance/1000) + 20*log10(fmhz);
+  double Dhm = m_rooftopHeight - hm;
+  double Lrts = -8.2 -10*log10 (m_streetsWidth) + 10*log10 (fmhz) + 20*log10 (Dhm) + Lori;
+//   NS_LOG_INFO (this << " Lbf " << Lbf << " Lrts " << Lrts << " Dhm" << Dhm << " Lmsd "  << Lmsd);
+  double loss = 0.0;
+  if (Lrts + Lmsd > 0)
+    {
+      loss = Lbf + Lrts + Lmsd;
+    }
+  else
+    {
+      loss = Lbf;
+    }
+  return (loss);
+}
+
+// double
+// BuildingsPropagationLossModel::ItuR1411NlosStreetCanyons (Ptr<BuildingsMobilityModel> a, Ptr<BuildingsMobilityModel> b) const
+// {
+//   NS_LOG_INFO (this);
+//   // reflection pathloss
+//   double x1 = a->GetStreetCrossingDistence ();
+//   double x2 = b->GetStreetCrossingDistence ();
+//   double f_alpha = 0.0;
+//   if (m_cornerAngle<= 0.33)
+//   {
+//     f_alpha = -41.0 + 110*m_cornerAngle;
+//   }
+//   else if (m_cornerAngle<= 0.42)
+//   {
+//     f_alpha = -13.94 + 28*m_cornerAngle;
+//   }
+//   else if (m_cornerAngle<= 0.71)
+//   {
+//     f_alpha = -5.33 + 7.51*m_cornerAngle;
+//   }
+//   double pi = 3.141592653589793;
+//   double Lr = -20*log10 (x1+x2) + (x1*x2*f_alpha/(m_streetsWidth*m_streetsWidth)) - 20*log10 (4*pi/m_lambda);
+//   
+//   // diffraction pathloss
+//   double Da = -1*(40/(2*pi))*(atan (x2/m_streetsWidth) + atan (x1/m_streetsWidth) - (pi/2));
+//   double Ld = -10*log10 (x2*x1*(x1+x2)) + 2*Da + 0.1*(90 - m_cornerAngle*(180/pi)) - 20*log10 (4*pi/m_lambda);
+//   
+//   double loss = -10*log10 (pow (10, Lr/10) + pow (10, Ld/10));
+//   return (loss);
+// }
+
+
+double
+BuildingsPropagationLossModel::ItuR1238 (Ptr<BuildingsMobilityModel> a, Ptr<BuildingsMobilityModel> b) const
+{
+  double N = 0.0;
+  int n = abs (a->GetFloorNumber () - b->GetFloorNumber ());
+//   NS_LOG_INFO (this << " A floor " << (uint16_t)a->GetFloorNumber () << " B floor " << (uint16_t)b->GetFloorNumber () << " n " << n);
+  double Lf = 0.0;
+  Ptr<Building> aBuilding = a->GetBuilding ();
+  if (aBuilding->GetBuildingType () == Building::Residential)
+  {
+    N = 28;
+    Lf = 4 * n;
+//     NS_LOG_INFO (this << " Residential ");
+  }
+  else if (aBuilding->GetBuildingType () == Building::Office)
+  {
+    N = 30;
+    Lf = 15 + (4 * (n-1));
+//     NS_LOG_INFO (this << " Office ");
+  }
+  else if (aBuilding->GetBuildingType () == Building::Commercial)
+  {
+    N = 22;
+    Lf = 6 + (3 * (n-1));
+//     NS_LOG_INFO (this << " Commercial ");
+  }
+  else
+  {
+    NS_LOG_ERROR (this << " Unkwnon Wall Type");
+  }
+  
+  double loss = 20*log10(m_frequency/1e6/*MHz*/) + N*log10(a->GetDistanceFrom (b)) + Lf - 28.0;
+  
+  return (loss);
+}
+
+
+double
+BuildingsPropagationLossModel::BEWPL (Ptr<BuildingsMobilityModel> a) const
+{
+  double loss = 0.0;
+  Ptr<Building> aBuilding = a->GetBuilding ();
+  if (aBuilding->GetExtWallsType () == Building::Wood)
+    {
+      loss = 4;
+    }
+  else if (aBuilding->GetExtWallsType () == Building::ConcreteWithWindows)
+    {
+      loss = 7;
+    }
+  else if (aBuilding->GetExtWallsType () == Building::ConcreteWithoutWindows)
+    {
+      loss = 15; // 10 ~ 20 dB
+    }
+  else if (aBuilding->GetExtWallsType () == Building::StoneBlocks)
+    {
+      loss = 12;
+    }
+  
+    
+  return (loss);
+}
+
+
+double
+BuildingsPropagationLossModel::HeightGain (Ptr<BuildingsMobilityModel> node) const
+{
+  double loss = 0.0;
+  
+  int nfloors  = node->GetFloorNumber ();
+  loss = -2*(nfloors);
+  return (loss);
+}
+
+
+
+
+double
+BuildingsPropagationLossModel::GetLoss (Ptr<MobilityModel> a, Ptr<MobilityModel> b) const
+{
+  
+  double distance = a->GetDistanceFrom (b);
+  if (distance <= m_minDistance)
+    {
+      return 0.0;
+    }
+  
+  // get the BuildingsMobilityModel pointers
+  Ptr<BuildingsMobilityModel> a1 = DynamicCast<BuildingsMobilityModel> (a);
+  Ptr<BuildingsMobilityModel> b1 = DynamicCast<BuildingsMobilityModel> (b);
+  
+  double loss = 0.0;
+  
+  if (a1->IsOutdoor ())
+    {
+      if (b1->IsOutdoor ())
+        {
+          if (distance > 1000)
+            {
+              NS_LOG_INFO (this << a1->GetPosition ().z<<b1->GetPosition ().z<< m_rooftopHeight);
+              if ((a1->GetPosition ().z < m_rooftopHeight)
+                && (b1->GetPosition ().z < m_rooftopHeight))
+                {
+                  // ITU limit in distance (i.e., < 2000 for small cells)
+                  if (distance < m_itu1411DistanceThreshold)
+                    {  
+                      // short range communication
+                      loss = ItuR1411 (a1, b1);
+                      NS_LOG_INFO (this << " 0-0 (>1000): down rooftop -> ITUR1411 : " << loss);
+                    }
+                    else
+                    {
+                      // out of bound
+                      loss = std::numeric_limits<double>::infinity ();
+                      NS_LOG_INFO (this << " 0-0 (>2000): down rooftop -> ITUR1411 : " << loss);
+                    }
+                }
+              else
+                {
+                  // Over the rooftop tranmission -> Okumura Hata
+                  loss = OkumuraHata (a1, b1);
+                  NS_LOG_INFO (this << " O-O (>1000): Over the rooftop -> OH : " << loss);
+                }
+            }
+          else
+            {
+              // short range outdoor communication
+              loss = ItuR1411 (a1, b1);
+              NS_LOG_INFO (this << " 0-0 (<1000) Street canyon -> ITUR1411 : " << loss);
+            }
+        }
+      else
+        {
+          // b indoor
+          if (distance > 1000)
+            {
+              if ((a1->GetPosition ().z < m_rooftopHeight)
+                && (b1->GetPosition ().z < m_rooftopHeight))
+                {
+                  
+                  // ITU limit in distance (i.e., < 2000 for small cells)
+                  if (distance < m_itu1411DistanceThreshold)
+                    {  
+                      // short range communication
+                      loss = ItuR1411 (a1, b1) + BEWPL(b1) + HeightGain (a1);
+                      NS_LOG_INFO (this << " 0-I (>1000): down rooftop -> ITUR1411 : " << loss);
+                    }
+                  else
+                    {
+                      // out of bound
+                      loss = std::numeric_limits<double>::infinity ();
+                      NS_LOG_INFO (this << " 0-I (>2000): down rooftop -> ITUR1411 : " << loss);
+                    }
+                }
+              else
+                {
+                  // Over the rooftop tranmission -> Okumura Hata
+                  loss = OkumuraHata (a1, b1) + BEWPL(b1);
+                  NS_LOG_INFO (this << " O-I (>1000): Over the rooftop -> OH : " << loss);
+                }
+            }
+          else
+            {
+              loss = ItuR1411 (a1, b1) + BEWPL(b1) + HeightGain (b1);
+              NS_LOG_INFO (this << " 0-I (<1000) ITUR1411 + BEL : " << loss);
+            }
+        } // end b1->isIndoor ()
+    }
+  else
+    {
+      // a is indoor
+      if (b1->IsIndoor ())
+        {
+          if (a1->GetBuilding () == b1->GetBuilding ())
+            {
+                // nodes are in same building -> indoor communication ITU-R P.1238
+                loss = ItuR1238 (a1, b1);
+                NS_LOG_INFO (this << " I-I (same building) ITUR1238 : " << loss);
+                
+            }
+          else
+            {
+              // nodes are in different buildings
+              loss = ItuR1411 (a1, b1) + BEWPL(a1) + BEWPL(b1);
+              NS_LOG_INFO (this << " I-I (different) ITUR1238 + 2*BEL : " << loss);
+            }
+        }
+      else
+        {
+          // b is outdoor
+          if (distance > 1000)
+            {
+              if ((a1->GetPosition ().z < m_rooftopHeight)
+                && (b1->GetPosition ().z < m_rooftopHeight))
+                {
+                  
+                  // ITU limit in distance (i.e., < 2000 for small cells)
+                  if (distance < m_itu1411DistanceThreshold)
+                    {  
+                      // short range communication
+                      loss = ItuR1411 (a1, b1) + BEWPL(a1) + HeightGain (a1);
+                      NS_LOG_INFO (this << " I-O (>1000): down rooftop -> ITUR1411 : " << loss);
+                    }
+                  else
+                    {
+                      // out of bound
+                      loss = std::numeric_limits<double>::infinity ();
+                      NS_LOG_INFO (this << " I-O (>2000): down rooftop -> ITUR1411 : " << loss);
+                    }
+                }
+              else
+                {
+                  // above rooftop -> OH
+                  loss = OkumuraHata (a1, b1) + BEWPL(a1) + HeightGain (a1);
+                  NS_LOG_INFO (this << " =I-O (>1000) over rooftop OH + BEL + HG: " << loss);
+                }
+            }
+          else
+            {
+              loss = ItuR1411 (a1, b1) + BEWPL(a1)  + HeightGain (a1);
+              NS_LOG_INFO (this << " I-O (<1000)  ITUR1411 + BEL + HG: " << loss);
+            }
+        } // end b1->IsIndoor ()
+    } // end a1->IsOutdoor ()
+
+  // Evaluate the shadowing
+  PairsList::iterator i = m_shadowingPairs.end ();
+  while (i != m_shadowingPairs.begin ()) 
+    {
+      i--;
+      PairsSet *ps = *i;
+      if (ps->sender == a) 
+        {
+          m_shadowingPairs.erase (i);
+          m_shadowingPairs.push_back (ps);
+          for (DestinationList::iterator r = ps->receivers.begin (); r != ps->receivers.end (); r++) 
+            {
+              ShadowingLoss *pc = *r;
+              if (pc->GetReceiver () == b) 
+                {
+                  ps->receivers.erase (r);
+                  ps->receivers.push_back (pc);
+                  return loss + pc->GetLoss ();
+                }
+            }
+            double sigma = EvaluateSigma (a1, b1);
+            ShadowingLoss *pc = new ShadowingLoss (0.0, sigma);
+          ps->receivers.push_back (pc);
+          return loss + pc->GetLoss ();
+        }
+    }
+  PairsSet *ps = new PairsSet;
+  ps->sender = a;
+  double sigma = EvaluateSigma (a1, b1);
+  ShadowingLoss *pc = new ShadowingLoss (0.0, sigma);
+  ps->receivers.push_back (pc);
+  m_shadowingPairs.push_back (ps);
+  return loss + pc->GetLoss ();
+  
+  
+  
+//   if (m_shadowingValue==0)
+//     {
+//       m_shadowingValue = new ShadowingLoss (m_shadowingMean, m_shadowingSigma);
+//     }
+//   
+//   return (loss + m_shadowingValue->GetLoss ());
+
+}
+
+double
+BuildingsPropagationLossModel::EvaluateSigma (Ptr<BuildingsMobilityModel> a, Ptr<BuildingsMobilityModel> b)
+const
+{
+  if (a->IsOutdoor ())
+  {
+    if (b->IsOutdoor ())
+    {
+      return (m_shadowingSigmaOutdoor);
+    }
+    else
+    {
+      double sigma = sqrt((m_shadowingSigmaOutdoor*m_shadowingSigmaOutdoor) + (m_shadowingSigmaExtWalls*m_shadowingSigmaExtWalls));
+      return (sigma);
+    }
+  }
+  else
+    if (b->IsIndoor ())
+    {
+      return (m_shadowingSigmaIndoor);
+    }
+    else
+    {
+      double sigma = sqrt((m_shadowingSigmaOutdoor*m_shadowingSigmaOutdoor) + (m_shadowingSigmaExtWalls*m_shadowingSigmaExtWalls));
+      return (sigma);
+    }
+}
+
+
+double
+BuildingsPropagationLossModel::DoCalcRxPower (double txPowerDbm, Ptr<MobilityModel> a, Ptr<MobilityModel> b) const
+{
+  return txPowerDbm - GetLoss (a, b);
+}
+
+
+} // namespace ns3