added support for single-freq PropagationLossModel to SpectrumChannel
authorNicola Baldo <nbaldo@cttc.es>
Tue, 05 Jul 2011 19:03:55 +0200
changeset 7343 b3e668a5949c
parent 7342 400f78c1d661
child 7344 27d75156657e
added support for single-freq PropagationLossModel to SpectrumChannel
RELEASE_NOTES
src/spectrum/examples/adhoc-aloha-ideal-phy-matrix-propagation-loss-model.cc
src/spectrum/examples/wscript
src/spectrum/helper/spectrum-helper.cc
src/spectrum/helper/spectrum-helper.h
src/spectrum/model/multi-model-spectrum-channel.cc
src/spectrum/model/multi-model-spectrum-channel.h
src/spectrum/model/single-model-spectrum-channel.cc
src/spectrum/model/single-model-spectrum-channel.h
src/spectrum/model/spectrum-channel.h
src/spectrum/test/examples-to-run.py
src/spectrum/test/spectrum-ideal-phy-test.cc
src/spectrum/wscript
--- a/RELEASE_NOTES	Tue Jul 05 18:40:17 2011 +0200
+++ b/RELEASE_NOTES	Tue Jul 05 19:03:55 2011 +0200
@@ -21,6 +21,14 @@
 New user-visible features
 -------------------------
 
+- SpectrumChannel models now support the usage of single-frequency
+  propagation loss models based on the PropagationLossModel
+  class. These model can be used in conjunction with
+  the frequency-dependent propagation loss model based on the
+  SpectrumPropagationLossModel class already supported by
+  SpectrumChannel. 
+
+
 Bugs fixed
 ----------
  - bug 1033 - Mesh airtime-metric fixed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/spectrum/examples/adhoc-aloha-ideal-phy-matrix-propagation-loss-model.cc	Tue Jul 05 19:03:55 2011 +0200
@@ -0,0 +1,151 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+
+
+#include <iostream>
+
+#include <ns3/core-module.h>
+#include <ns3/network-module.h>
+#include <ns3/spectrum-model-ism2400MHz-res1MHz.h>
+#include <ns3/spectrum-model-300kHz-300GHz-log.h>
+#include <ns3/wifi-spectrum-value-helper.h>
+#include <ns3/single-model-spectrum-channel.h>
+#include <ns3/waveform-generator.h>
+#include <ns3/spectrum-analyzer.h>
+#include <ns3/log.h>
+#include <string>
+#include <iomanip>
+#include <ns3/friis-spectrum-propagation-loss.h>
+#include <ns3/propagation-delay-model.h>
+#include <ns3/mobility-module.h>
+#include <ns3/spectrum-helper.h>
+#include <ns3/applications-module.h>
+#include <ns3/adhoc-aloha-noack-ideal-phy-helper.h>
+
+NS_LOG_COMPONENT_DEFINE ("TestAdhocOfdmAloha");
+
+using namespace ns3;
+
+static bool g_verbose = false;
+static uint64_t g_rxBytes;
+
+void
+PhyRxEndOkTrace (std::string context, Ptr<const Packet> p)
+{
+  if (g_verbose)
+    {
+      std::cout << context << " PHY RX END OK p:" << p << std::endl;
+    }
+  g_rxBytes += p->GetSize ();
+}
+
+
+int main (int argc, char** argv)
+{
+  CommandLine cmd;
+  double lossDb;
+  double txPowerW = 0.1; 
+  uint64_t phyRate = 500000;
+  uint32_t pktSize = 1000;
+  cmd.AddValue ("verbose", "Print trace information if true", g_verbose);
+  cmd.AddValue ("lossDb", "link loss in dB", lossDb);
+  cmd.AddValue ("txPowerW", "txPower in Watts", txPowerW);
+  cmd.AddValue ("phyRate", "PHY rate in bps", phyRate);
+  cmd.AddValue ("pktSize", "packet size in bytes", pktSize);
+  cmd.Parse (argc, argv);
+
+  NodeContainer c;
+  c.Create (2);
+
+  MobilityHelper mobility;
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
+  positionAlloc->Add (Vector (5.0, 0.0, 0.0));
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+
+
+  mobility.Install (c);
+
+
+  SpectrumChannelHelper channelHelper;
+  channelHelper.SetChannel ("ns3::MultiModelSpectrumChannel");
+  channelHelper.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
+  Ptr<MatrixPropagationLossModel> propLoss = CreateObject<MatrixPropagationLossModel> ();
+  propLoss->SetLoss (c.Get (0)->GetObject<MobilityModel> (), c.Get (1)->GetObject<MobilityModel> (), lossDb, true);
+  channelHelper.AddPropagationLoss (propLoss);
+  Ptr<SpectrumChannel> channel = channelHelper.Create ();
+
+
+  WifiSpectrumValue5MhzFactory sf;
+
+  uint32_t channelNumber = 1;
+  Ptr<SpectrumValue> txPsd =  sf.CreateTxPowerSpectralDensity (txPowerW, channelNumber);
+
+  // for the noise, we use the Power Spectral Density of thermal noise
+  // at room temperature. The value of the PSD will be constant over the band of interest.
+  const double k = 1.381e-23; //Boltzmann's constant
+  const double T = 290; // temperature in Kelvin
+  double noisePsdValue = k * T; // watts per hertz
+  Ptr<SpectrumValue> noisePsd = sf.CreateConstant (noisePsdValue);
+
+  AdhocAlohaNoackIdealPhyHelper deviceHelper;
+  deviceHelper.SetChannel (channel);
+  deviceHelper.SetTxPowerSpectralDensity (txPsd);
+  deviceHelper.SetNoisePowerSpectralDensity (noisePsd);
+  deviceHelper.SetPhyAttribute ("Rate", DataRateValue (DataRate (phyRate)));
+  NetDeviceContainer devices = deviceHelper.Install (c);
+
+  PacketSocketHelper packetSocket;
+  packetSocket.Install (c);
+
+  PacketSocketAddress socket;
+  socket.SetSingleDevice (devices.Get (0)->GetIfIndex ());
+  socket.SetPhysicalAddress (devices.Get (1)->GetAddress ());
+  socket.SetProtocol (1);
+
+  OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (250)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (2*phyRate)));
+  onoff.SetAttribute ("PacketSize", UintegerValue (pktSize));
+
+  ApplicationContainer apps = onoff.Install (c.Get (0));
+  apps.Start (Seconds (0.0));
+  apps.Stop (Seconds (10.0));
+
+  Config::Connect ("/NodeList/*/DeviceList/*/Phy/RxEndOk", MakeCallback (&PhyRxEndOkTrace));
+
+  g_rxBytes = 0;
+  Simulator::Stop (Seconds (10.0001));
+  Simulator::Run ();
+  double throughputBps = (g_rxBytes * 8.0) / 10.0;
+
+  std::cerr << "throughput:       " << std::setw (20) << std::fixed << throughputBps << " bps" << std::endl;
+  std::cerr << "phy rate  :       "   << std::setw (20) << std::fixed << phyRate*1.0 << " bps" << std::endl; 
+  double rxPowerW = txPowerW / (pow (10.0, lossDb/10.0));
+  double capacity = 20e6*log2 (1.0 + (rxPowerW/20.0e6)/noisePsdValue);
+  std::cerr << "shannon capacity: "   << std::setw (20) << std::fixed << capacity <<  " bps" << std::endl; 
+
+
+  Simulator::Destroy ();
+  return 0;
+}
--- a/src/spectrum/examples/wscript	Tue Jul 05 18:40:17 2011 +0200
+++ b/src/spectrum/examples/wscript	Tue Jul 05 19:03:55 2011 +0200
@@ -5,6 +5,10 @@
                                  ['spectrum', 'mobility'])
     obj.source = 'adhoc-aloha-ideal-phy.cc'
 
+    obj = bld.create_ns3_program('adhoc-aloha-ideal-phy-matrix-propagation-loss-model',
+                                 ['spectrum', 'mobility'])
+    obj.source = 'adhoc-aloha-ideal-phy-matrix-propagation-loss-model.cc'
+
     obj = bld.create_ns3_program('adhoc-aloha-ideal-phy-with-microwave-oven',
                                  ['spectrum', 'mobility'])
     obj.source = 'adhoc-aloha-ideal-phy-with-microwave-oven.cc'
--- a/src/spectrum/helper/spectrum-helper.cc	Tue Jul 05 18:40:17 2011 +0200
+++ b/src/spectrum/helper/spectrum-helper.cc	Tue Jul 05 19:03:55 2011 +0200
@@ -21,8 +21,6 @@
 #include <ns3/simulator.h>
 #include <ns3/config.h>
 #include <ns3/names.h>
-#include <ns3/spectrum-propagation-loss-model.h>
-#include <ns3/propagation-delay-model.h>
 #include <ns3/spectrum-channel.h>
 #include <ns3/spectrum-phy.h>
 #include <ns3/single-model-spectrum-channel.h>
@@ -66,6 +64,38 @@
   m_channel.Set (n7, v7);
 }
 
+void
+SpectrumChannelHelper::AddPropagationLoss (std::string type,
+                                           std::string n0, const AttributeValue &v0,
+                                           std::string n1, const AttributeValue &v1,
+                                           std::string n2, const AttributeValue &v2,
+                                           std::string n3, const AttributeValue &v3,
+                                           std::string n4, const AttributeValue &v4,
+                                           std::string n5, const AttributeValue &v5,
+                                           std::string n6, const AttributeValue &v6,
+                                           std::string n7, const AttributeValue &v7)
+{
+  ObjectFactory factory;
+  factory.SetTypeId (type);
+  factory.Set (n0, v0);
+  factory.Set (n1, v1);
+  factory.Set (n2, v2);
+  factory.Set (n3, v3);
+  factory.Set (n4, v4);
+  factory.Set (n5, v5);
+  factory.Set (n6, v6);
+  factory.Set (n7, v7);
+  Ptr<PropagationLossModel> m = factory.Create<PropagationLossModel> ();
+  AddPropagationLoss (m);
+}
+
+
+void 
+SpectrumChannelHelper::AddPropagationLoss (Ptr<PropagationLossModel> m)
+{
+  m->SetNext (m_propagationLossModel);
+  m_propagationLossModel = m;
+}
 
 void
 SpectrumChannelHelper::AddSpectrumPropagationLoss (std::string type,
@@ -88,7 +118,15 @@
   factory.Set (n5, v5);
   factory.Set (n6, v6);
   factory.Set (n7, v7);
-  m_spectrumPropagationLoss.push_back (factory);
+  Ptr<SpectrumPropagationLossModel> m = factory.Create<SpectrumPropagationLossModel> ();
+  AddSpectrumPropagationLoss (m);
+}
+
+void 
+SpectrumChannelHelper::AddSpectrumPropagationLoss (Ptr<SpectrumPropagationLossModel> m)
+{
+  m->SetNext (m_spectrumPropagationLossModel);
+  m_spectrumPropagationLossModel = m;
 }
 
 void
@@ -119,30 +157,14 @@
 SpectrumChannelHelper::Create (void) const
 {
   Ptr<SpectrumChannel> channel = (m_channel.Create ())->GetObject<SpectrumChannel> ();
-  Ptr<SpectrumPropagationLossModel> prev = 0;
-  for (std::vector<ObjectFactory>::const_iterator i = m_spectrumPropagationLoss.begin (); i != m_spectrumPropagationLoss.end (); ++i)
-    {
-      Ptr<SpectrumPropagationLossModel> cur = (*i).Create<SpectrumPropagationLossModel> ();
-      if (prev == 0)
-        {
-          channel->AddSpectrumPropagationLossModel (cur);
-        }
-      else
-        {
-          prev->SetNext (cur);
-        }
-      prev = cur;
-    }
+  channel->AddSpectrumPropagationLossModel (m_spectrumPropagationLossModel);
+  channel->AddPropagationLossModel (m_propagationLossModel);
   Ptr<PropagationDelayModel> delay = m_propagationDelay.Create<PropagationDelayModel> ();
   channel->SetPropagationDelayModel (delay);
   return channel;
 }
 
 
-
-
-
-
 void
 SpectrumPhyHelper::SetPhy (std::string type,
                            std::string n0, const AttributeValue &v0,
--- a/src/spectrum/helper/spectrum-helper.h	Tue Jul 05 18:40:17 2011 +0200
+++ b/src/spectrum/helper/spectrum-helper.h	Tue Jul 05 19:03:55 2011 +0200
@@ -26,6 +26,8 @@
 #include <ns3/object-factory.h>
 #include <ns3/node-container.h>
 #include <ns3/net-device-container.h>
+#include <ns3/propagation-loss-model.h>
+#include <ns3/spectrum-propagation-loss-model.h>
 
 namespace ns3 {
 
@@ -72,6 +74,44 @@
                    std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
                    std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
                    std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+  /**
+   * \param name the name of the model to set
+   * \param n0 the name of the attribute to set
+   * \param v0 the value of the attribute to set
+   * \param n1 the name of the attribute to set
+   * \param v1 the value of the attribute to set
+   * \param n2 the name of the attribute to set
+   * \param v2 the value of the attribute to set
+   * \param n3 the name of the attribute to set
+   * \param v3 the value of the attribute to set
+   * \param n4 the name of the attribute to set
+   * \param v4 the value of the attribute to set
+   * \param n5 the name of the attribute to set
+   * \param v5 the value of the attribute to set
+   * \param n6 the name of the attribute to set
+   * \param v6 the value of the attribute to set
+   * \param n7 the name of the attribute to set
+   * \param v7 the value of the attribute to set
+   *
+   * Add a new single-frequency propagation loss model to this channel helper.
+   */
+  void AddPropagationLoss (std::string name,
+                           std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+                           std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+                           std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+                           std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+                           std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+                           std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+                           std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+                           std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+
+
+  /** 
+   * Add a new single-frequency propagation loss model instance to this channel helper.
+   * 
+   * \param m a pointer to the instance of the propagation loss model
+   */
+  void AddPropagationLoss (Ptr<PropagationLossModel> m);
 
   /**
    * \param name the name of the model to set
@@ -92,7 +132,7 @@
    * \param n7 the name of the attribute to set
    * \param v7 the value of the attribute to set
    *
-   * Add a new spectrum propagation loss to this channel helper.
+   * Add a new frequency-dependent propagation loss model to this channel helper.
    */
   void AddSpectrumPropagationLoss (std::string name,
                                    std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
@@ -103,6 +143,14 @@
                                    std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
                                    std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
                                    std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+
+  /** 
+   * Add a new frequency-dependent propagation loss model instance to this channel helper.
+   * 
+   * \param m a pointer to the instance of the propagation loss model
+   */
+  void AddSpectrumPropagationLoss (Ptr<SpectrumPropagationLossModel> m);
+
   /**
    * \param name the name of the model to set
    * \param n0 the name of the attribute to set
@@ -142,7 +190,8 @@
   Ptr<SpectrumChannel> Create (void) const;
 
 private:
-  std::vector<ObjectFactory> m_spectrumPropagationLoss;
+  Ptr<SpectrumPropagationLossModel> m_spectrumPropagationLossModel;
+  Ptr<PropagationLossModel> m_propagationLossModel;
   ObjectFactory m_propagationDelay;
   ObjectFactory m_channel;
 };
--- a/src/spectrum/model/multi-model-spectrum-channel.cc	Tue Jul 05 18:40:17 2011 +0200
+++ b/src/spectrum/model/multi-model-spectrum-channel.cc	Tue Jul 05 19:03:55 2011 +0200
@@ -25,9 +25,13 @@
 #include <ns3/packet-burst.h>
 #include <ns3/net-device.h>
 #include <ns3/node.h>
+#include <ns3/double.h>
 #include <ns3/mobility-model.h>
 #include <ns3/spectrum-phy.h>
 #include <ns3/spectrum-converter.h>
+#include <ns3/spectrum-propagation-loss-model.h>
+#include <ns3/propagation-loss-model.h>
+#include <ns3/propagation-delay-model.h>
 #include <iostream>
 #include <utility>
 #include "multi-model-spectrum-channel.h"
@@ -72,8 +76,6 @@
 
 
 MultiModelSpectrumChannel::MultiModelSpectrumChannel ()
-  : m_PropagationDelay (0),
-    m_PropagationLoss (0)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -82,8 +84,9 @@
 MultiModelSpectrumChannel::DoDispose ()
 {
   NS_LOG_FUNCTION (this);
-  m_PropagationLoss = 0;
-  m_PropagationDelay = 0;
+  m_propagationDelay = 0;
+  m_propagationLoss = 0;
+  m_spectrumPropagationLoss = 0;
   m_txSpectrumModelInfoMap.clear ();
   m_rxSpectrumModelInfoMap.clear ();
   m_phyVector.clear ();
@@ -96,6 +99,18 @@
   static TypeId tid = TypeId ("ns3::MultiModelSpectrumChannel")
     .SetParent<SpectrumChannel> ()
     .AddConstructor<MultiModelSpectrumChannel> ()
+    .AddAttribute ("MaxLossDb", 
+                   "If a single-frequency PropagationLossModel is used, this value "
+                   "represents the maximum loss in dB for which transmissions will be "
+                   "passed to the receiving PHY. Signals for which the PropagationLossModel "
+                   "returns a loss bigger than this value will not be propagated to the receiver. "
+                   "This parameter is to be used to reduce "
+                   "the computational load by not propagating signals that are far beyond "
+                   "the interference range. Note that the default value corresponds to "
+                   "considering all signals for reception. Tune this value with care. ",
+                   DoubleValue (1.0e9),
+                   MakeDoubleAccessor (&MultiModelSpectrumChannel::m_maxLossDb),
+                   MakeDoubleChecker<double> ())
   ;
   return tid;
 }
@@ -241,44 +256,43 @@
           convertedTxPowerSpectrum = rxConverterIterator->second.Convert (originalTxPowerSpectrum);
         }
 
-      std::list<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhyList.begin ();
-      while (rxPhyIterator != rxInfoIterator->second.m_rxPhyList.end ())
+      for (std::list<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhyList.begin ();
+           rxPhyIterator != rxInfoIterator->second.m_rxPhyList.end ();
+           ++rxPhyIterator)
         {
           NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid,
                          "MultiModelSpectrumChannel only supports devices that use a single RxSpectrumModel that does not change for the whole simulation");
 
           if ((*rxPhyIterator) != txPhy)
             {
-              Ptr <SpectrumValue> rxPowerSpectrum;
-              Time delay;
+              Ptr <SpectrumValue> rxPowerSpectrum = convertedTxPowerSpectrum->Copy ();
+              Time delay = MicroSeconds (0); 
+
               Ptr<MobilityModel> receiverMobility = (*rxPhyIterator)->GetMobility ()->GetObject<MobilityModel> ();
 
               if (txMobility && receiverMobility)
                 {
-                  if (m_PropagationLoss)
+                  if (m_propagationLoss)
                     {
-                      rxPowerSpectrum = m_PropagationLoss->CalcRxPowerSpectralDensity (convertedTxPowerSpectrum, txMobility, receiverMobility);
-                    }
-                  else
-                    {
-                      // rxPowerSpectrum = Copy<SpectrumValue> (convertedTxPowerSpectrum);
-                      rxPowerSpectrum = convertedTxPowerSpectrum->Copy ();
+                      double gainDb = m_propagationLoss->CalcRxPower (0, txMobility, receiverMobility);
+                      if ( (-gainDb) > m_maxLossDb)
+                        {
+                          // beyond range
+                          continue;
+                        }
+                      double gainLinear = pow (10.0, gainDb/10.0);
+                      *rxPowerSpectrum = (*rxPowerSpectrum) * gainLinear;
                     }
 
-                  if (m_PropagationDelay)
-                    {
-                      delay = m_PropagationDelay->GetDelay (txMobility, receiverMobility);
-                    }
-                  else
+                  if (m_spectrumPropagationLoss)
                     {
-                      delay = MicroSeconds (0);
+                      rxPowerSpectrum = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxPowerSpectrum, txMobility, receiverMobility);
                     }
-                }
-              else
-                {
-                  // rxPowerSpectrum = Copy<SpectrumValue> (convertedTxPowerSpectrum);
-                  rxPowerSpectrum = convertedTxPowerSpectrum->Copy ();
-                  delay = MicroSeconds (0);
+
+                  if (m_propagationDelay)
+                    {
+                      delay = m_propagationDelay->GetDelay (txMobility, receiverMobility);
+                    }
                 }
 
               Ptr<PacketBurst> pktBurstCopy = p->Copy ();
@@ -297,7 +311,6 @@
                                        pktBurstCopy, rxPowerSpectrum, st, duration, *rxPhyIterator);
                 }
             }
-          ++rxPhyIterator;
         }
 
     }
@@ -330,24 +343,32 @@
 
 
 void
+MultiModelSpectrumChannel::AddPropagationLossModel (Ptr<PropagationLossModel> loss)
+{
+  NS_LOG_FUNCTION (this << loss);
+  NS_ASSERT (m_propagationLoss == 0);
+  m_propagationLoss = loss;
+}
+
+void
 MultiModelSpectrumChannel::AddSpectrumPropagationLossModel (Ptr<SpectrumPropagationLossModel> loss)
 {
-  NS_ASSERT (m_PropagationLoss == 0);
-  m_PropagationLoss = loss;
+  NS_ASSERT (m_propagationLoss == 0);
+  m_spectrumPropagationLoss = loss;
 }
 
 void
 MultiModelSpectrumChannel::SetPropagationDelayModel (Ptr<PropagationDelayModel> delay)
 {
-  NS_ASSERT (m_PropagationDelay == 0);
-  m_PropagationDelay = delay;
+  NS_ASSERT (m_propagationDelay == 0);
+  m_propagationDelay = delay;
 }
 
 Ptr<SpectrumPropagationLossModel>
 MultiModelSpectrumChannel::GetSpectrumPropagationLossModel (void)
 {
   NS_LOG_FUNCTION (this);
-  return m_PropagationLoss;
+  return m_spectrumPropagationLoss;
 }
 
 
--- a/src/spectrum/model/multi-model-spectrum-channel.h	Tue Jul 05 18:40:17 2011 +0200
+++ b/src/spectrum/model/multi-model-spectrum-channel.h	Tue Jul 05 19:03:55 2011 +0200
@@ -88,6 +88,7 @@
   static TypeId GetTypeId (void);
 
   // inherited from SpectrumChannel
+  virtual void AddPropagationLossModel (Ptr<PropagationLossModel> loss);
   virtual void AddSpectrumPropagationLossModel (Ptr<SpectrumPropagationLossModel> loss);
   virtual void SetPropagationDelayModel (Ptr<PropagationDelayModel> delay);
   virtual void AddRx (Ptr<SpectrumPhy> phy);
@@ -147,15 +148,19 @@
    * propagation delay model to be used with this channel
    *
    */
-  Ptr<PropagationDelayModel> m_PropagationDelay;
-
+  Ptr<PropagationDelayModel> m_propagationDelay;
 
   /**
-   * propagation loss model to be used with this channel
+    * single-frequency propagation loss model to be used with this channel
+    *
+    */
+  Ptr<PropagationLossModel> m_propagationLoss;
+
+  /**
+   * frequency-dependent propagation loss model to be used with this channel
    *
    */
-  Ptr<SpectrumPropagationLossModel> m_PropagationLoss;
-
+  Ptr<SpectrumPropagationLossModel> m_spectrumPropagationLoss;
 
 
   /**
@@ -180,6 +185,9 @@
    *
    */
   std::vector<Ptr<SpectrumPhy> > m_phyVector;
+
+
+  double m_maxLossDb;
 };
 
 
--- a/src/spectrum/model/single-model-spectrum-channel.cc	Tue Jul 05 18:40:17 2011 +0200
+++ b/src/spectrum/model/single-model-spectrum-channel.cc	Tue Jul 05 19:03:55 2011 +0200
@@ -25,8 +25,14 @@
 #include <ns3/packet-burst.h>
 #include <ns3/net-device.h>
 #include <ns3/node.h>
+#include <ns3/double.h>
 #include <ns3/mobility-model.h>
 #include <ns3/spectrum-phy.h>
+#include <ns3/spectrum-propagation-loss-model.h>
+#include <ns3/propagation-loss-model.h>
+#include <ns3/propagation-delay-model.h>
+
+
 #include "single-model-spectrum-channel.h"
 
 
@@ -39,9 +45,6 @@
 NS_OBJECT_ENSURE_REGISTERED (SingleModelSpectrumChannel);
 
 SingleModelSpectrumChannel::SingleModelSpectrumChannel ()
-  : m_spectrumModel (0),
-    m_PropagationDelay (0),
-    m_PropagationLoss (0)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -52,8 +55,9 @@
   NS_LOG_FUNCTION (this);
   m_phyList.clear ();
   m_spectrumModel = 0;
-  m_PropagationDelay = 0;
-  m_PropagationLoss = 0;
+  m_propagationDelay = 0;
+  m_propagationLoss = 0;
+  m_spectrumPropagationLoss = 0;
   SpectrumChannel::DoDispose ();
 }
 
@@ -64,6 +68,18 @@
   static TypeId tid = TypeId ("ns3::SingleModelSpectrumChannel")
     .SetParent<SpectrumChannel> ()
     .AddConstructor<SingleModelSpectrumChannel> ()
+    .AddAttribute ("MaxLossDb", 
+                   "If a single-frequency PropagationLossModel is used, this value "
+                   "represents the maximum loss in dB for which transmissions will be "
+                   "passed to the receiving PHY. Signals for which the PropagationLossModel "
+                   "returns a loss bigger than this value will not be propagated to the receiver. "
+                   "This parameter is to be used to reduce "
+                   "the computational load by not propagating signals that are far beyond "
+                   "the interference range. Note that the default value corresponds to "
+                   "considering all signals for reception. Tune this value with care. ",
+                   DoubleValue (1.0e9),
+                   MakeDoubleAccessor (&SingleModelSpectrumChannel::m_maxLossDb),
+                   MakeDoubleChecker<double> ())
   ;
   return tid;
 }
@@ -98,46 +114,44 @@
     }
 
 
-  PhyList::const_iterator rxPhyIterator = m_phyList.begin ();
+
 
   Ptr<MobilityModel> senderMobility = txPhy->GetMobility ()->GetObject<MobilityModel> ();
 
-  NS_ASSERT (rxPhyIterator != m_phyList.end ());
-
-  while (rxPhyIterator != m_phyList.end ())
+  for (PhyList::const_iterator rxPhyIterator = m_phyList.begin ();
+       rxPhyIterator != m_phyList.end ();
+       ++rxPhyIterator)
     {
       if ((*rxPhyIterator) != txPhy)
         {
-          Ptr <SpectrumValue> rxPsd;
-          Time delay;
+          Ptr <SpectrumValue> rxPsd = Copy<SpectrumValue> (txPsd);
+          Time delay  = MicroSeconds (0);
+
           Ptr<MobilityModel> receiverMobility = (*rxPhyIterator)->GetMobility ()->GetObject<MobilityModel> ();
 
           if (senderMobility && receiverMobility)
             {
-
-
-              if (m_PropagationLoss)
+              if (m_propagationLoss)
                 {
-                  rxPsd = m_PropagationLoss->CalcRxPowerSpectralDensity (txPsd, senderMobility, receiverMobility);
-                }
-              else
-                {
-                  rxPsd = txPsd;
+                  double gainDb = m_propagationLoss->CalcRxPower (0, senderMobility, receiverMobility);
+                  if ( (-gainDb) > m_maxLossDb)
+                    {
+                      // beyond range
+                      continue;
+                    }
+                  double gainLinear = pow (10.0, gainDb/10.0);
+                  *rxPsd = (*rxPsd) * gainLinear;
                 }
 
-              if (m_PropagationDelay)
-                {
-                  delay = m_PropagationDelay->GetDelay (senderMobility, receiverMobility);
-                }
-              else
+              if (m_spectrumPropagationLoss)
                 {
-                  delay = MicroSeconds (0);
+                  rxPsd = m_spectrumPropagationLoss->CalcRxPowerSpectralDensity (rxPsd, senderMobility, receiverMobility);
                 }
-            }
-          else
-            {
-              rxPsd = txPsd;
-              delay = MicroSeconds (0);
+
+              if (m_propagationDelay)
+                {
+                  delay = m_propagationDelay->GetDelay (senderMobility, receiverMobility);
+                }
             }
 
           Ptr<PacketBurst> pktBurstCopy = p->Copy ();
@@ -156,7 +170,6 @@
                                    pktBurstCopy, rxPsd, st, duration, *rxPhyIterator);
             }
         }
-      ++rxPhyIterator;
     }
 
 }
@@ -186,21 +199,29 @@
 }
 
 
+void
+SingleModelSpectrumChannel::AddPropagationLossModel (Ptr<PropagationLossModel> loss)
+{
+  NS_LOG_FUNCTION (this << loss);
+  NS_ASSERT (m_propagationLoss == 0);
+  m_propagationLoss = loss;
+}
+
 
 void
 SingleModelSpectrumChannel::AddSpectrumPropagationLossModel (Ptr<SpectrumPropagationLossModel> loss)
 {
   NS_LOG_FUNCTION (this << loss);
-  NS_ASSERT (m_PropagationLoss == 0);
-  m_PropagationLoss = loss;
+  NS_ASSERT (m_propagationLoss == 0);
+  m_spectrumPropagationLoss = loss;
 }
 
 void
 SingleModelSpectrumChannel::SetPropagationDelayModel (Ptr<PropagationDelayModel> delay)
 {
   NS_LOG_FUNCTION (this << delay);
-  NS_ASSERT (m_PropagationDelay == 0);
-  m_PropagationDelay = delay;
+  NS_ASSERT (m_propagationDelay == 0);
+  m_propagationDelay = delay;
 }
 
 
@@ -208,7 +229,7 @@
 SingleModelSpectrumChannel::GetSpectrumPropagationLossModel (void)
 {
   NS_LOG_FUNCTION (this);
-  return m_PropagationLoss;
+  return m_spectrumPropagationLoss;
 }
 
 
--- a/src/spectrum/model/single-model-spectrum-channel.h	Tue Jul 05 18:40:17 2011 +0200
+++ b/src/spectrum/model/single-model-spectrum-channel.h	Tue Jul 05 19:03:55 2011 +0200
@@ -1,4 +1,4 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+//* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
 /*
  * Copyright (c) 2009 CTTC
  *
@@ -23,8 +23,6 @@
 
 
 #include <ns3/spectrum-channel.h>
-#include <ns3/spectrum-propagation-loss-model.h>
-#include <ns3/propagation-delay-model.h>
 
 namespace ns3 {
 
@@ -47,6 +45,7 @@
 
 
   // inherited from SpectrumChannel
+  virtual void AddPropagationLossModel (Ptr<PropagationLossModel> loss);
   virtual void AddSpectrumPropagationLossModel (Ptr<SpectrumPropagationLossModel> loss);
   virtual void SetPropagationDelayModel (Ptr<PropagationDelayModel> delay);
   virtual void AddRx (Ptr<SpectrumPhy> phy);
@@ -97,15 +96,23 @@
    * propagation delay model to be used with this channel
    *
    */
-  Ptr<PropagationDelayModel> m_PropagationDelay;
+  Ptr<PropagationDelayModel> m_propagationDelay;
 
 
   /**
-   * propagation loss model to be used with this channel
+    * single-frequency propagation loss model to be used with this channel
+    *
+    */
+  Ptr<PropagationLossModel> m_propagationLoss;
+
+  /**
+   * frequency-dependent propagation loss model to be used with this channel
    *
    */
-  Ptr<SpectrumPropagationLossModel> m_PropagationLoss;
+  Ptr<SpectrumPropagationLossModel> m_spectrumPropagationLoss;
 
+
+  double m_maxLossDb;
 };
 
 
--- a/src/spectrum/model/spectrum-channel.h	Tue Jul 05 18:40:17 2011 +0200
+++ b/src/spectrum/model/spectrum-channel.h	Tue Jul 05 19:03:55 2011 +0200
@@ -34,6 +34,7 @@
 class SpectrumValue;
 class SpectrumPhy;
 class SpectrumPropagationLossModel;
+class PropagationLossModel;
 class PropagationDelayModel;
 
 /**
@@ -50,8 +51,16 @@
 
 
   /**
-   * set the propagation loss model to be used
-   * \param loss Ptr to the propagation loss model to be used.
+   * set the single-frequency propagation loss model to be used
+   * \warning only models that do not depend on the TX power should be used.
+   * 
+   * \param loss a pointer to the propagation loss model to be used.
+   */
+  virtual void AddPropagationLossModel (Ptr<PropagationLossModel> loss) = 0;
+
+  /**
+   * set the frequency-dependent propagation loss model to be used
+   * \param loss a pointer to the propagation loss model to be used.
    */
   virtual void AddSpectrumPropagationLossModel (Ptr<SpectrumPropagationLossModel> loss) = 0;
 
--- a/src/spectrum/test/examples-to-run.py	Tue Jul 05 18:40:17 2011 +0200
+++ b/src/spectrum/test/examples-to-run.py	Tue Jul 05 19:03:55 2011 +0200
@@ -10,6 +10,7 @@
 cpp_examples = [
     ("adhoc-aloha-ideal-phy", "True", "True"),
     ("adhoc-aloha-ideal-phy-with-microwave-oven", "True", "True"),
+    ("adhoc-aloha-ideal-phy-matrix-propagation-loss-model", "True", "True"),
 ]
 
 # A list of Python examples to run in order to ensure that they remain
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/spectrum/test/spectrum-ideal-phy-test.cc	Tue Jul 05 19:03:55 2011 +0200
@@ -0,0 +1,245 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include <ns3/object.h>
+#include <ns3/spectrum-interference.h>
+#include <ns3/spectrum-error-model.h>
+#include <ns3/log.h>
+#include <ns3/test.h>
+#include <ns3/simulator.h>
+#include <ns3/packet.h>
+#include <ns3/ptr.h>
+#include <iostream>
+
+#include <ns3/spectrum-model-ism2400MHz-res1MHz.h>
+#include <ns3/spectrum-model-300kHz-300GHz-log.h>
+#include <ns3/wifi-spectrum-value-helper.h>
+#include <ns3/single-model-spectrum-channel.h>
+#include <ns3/waveform-generator.h>
+#include <ns3/spectrum-analyzer.h>
+#include <ns3/log.h>
+#include <string>
+#include <iomanip>
+#include <ns3/friis-spectrum-propagation-loss.h>
+#include <ns3/propagation-delay-model.h>
+#include <ns3/spectrum-helper.h>
+#include <ns3/adhoc-aloha-noack-ideal-phy-helper.h>
+#include <ns3/mobility-helper.h>
+#include <ns3/data-rate.h>
+#include <ns3/uinteger.h>
+#include <ns3/packet-socket-helper.h>
+#include <ns3/packet-socket-address.h>
+#include <ns3/on-off-helper.h>
+#include <ns3/config.h>
+
+NS_LOG_COMPONENT_DEFINE ("SpectrumIdealPhyTest");
+
+namespace ns3 {
+
+
+static uint64_t g_rxBytes;
+static double g_bandwidth = 20e6; // Hz
+
+void
+PhyRxEndOkTrace (std::string context, Ptr<const Packet> p)
+{
+  g_rxBytes += p->GetSize ();
+}
+
+
+class SpectrumIdealPhyTestCase : public TestCase
+{
+public:
+  SpectrumIdealPhyTestCase (double snrLinear,
+			    uint64_t phyRate,
+			    bool rateIsAchievable,
+			    std::string channelType);
+  virtual ~SpectrumIdealPhyTestCase ();
+
+private:
+  virtual void DoRun (void);
+  
+  double      m_snrLinear;
+  uint64_t    m_phyRate;
+  bool        m_rateIsAchievable;
+  std::string m_channelType;
+};
+
+
+
+
+SpectrumIdealPhyTestCase::SpectrumIdealPhyTestCase (double snrLinear,
+						    uint64_t phyRate,
+						    bool rateIsAchievable,
+						    std::string channelType)
+  : TestCase (""),
+    m_snrLinear (snrLinear),
+    m_phyRate (phyRate),
+    m_rateIsAchievable (rateIsAchievable),
+    m_channelType (channelType)
+{
+  std::ostringstream oss;
+  oss << channelType
+      << " snr = " << snrLinear << " (linear), "
+      << " phyRate = " << phyRate << " bps";
+  SetName (oss.str ());
+}
+
+SpectrumIdealPhyTestCase::~SpectrumIdealPhyTestCase ()
+{
+}
+
+
+void
+SpectrumIdealPhyTestCase::DoRun (void)
+{  
+  NS_LOG_FUNCTION (m_snrLinear << m_phyRate);
+  double txPowerW = 0.1; 
+  // for the noise, we use the Power Spectral Density of thermal noise
+  // at room temperature. The value of the PSD will be constant over the band of interest.
+  const double k = 1.381e-23; //Boltzmann's constant
+  const double T = 290; // temperature in Kelvin
+  double noisePsdValue = k * T; // W/Hz
+  double lossLinear = (txPowerW) / (m_snrLinear * noisePsdValue * g_bandwidth); 
+  double lossDb = 10 * log10 (lossLinear);
+  uint64_t phyRate = m_phyRate; // bps
+  uint32_t pktSize = 50; // bytes
+
+  uint32_t numPkts = 200; //desired number of packets in the
+			  //test. Directly related with the accuracy
+			  //of the measurement. 
+
+  double testDuration = (numPkts * pktSize * 8.0) / phyRate;
+  NS_LOG_INFO ("test duration = " << std::fixed << testDuration);
+
+  NodeContainer c;
+  c.Create (2);
+
+  MobilityHelper mobility;
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
+  positionAlloc->Add (Vector (5.0, 0.0, 0.0));
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+
+
+  mobility.Install (c);
+
+
+  SpectrumChannelHelper channelHelper;
+  channelHelper.SetChannel (m_channelType);
+  channelHelper.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
+  Ptr<MatrixPropagationLossModel> propLoss = CreateObject<MatrixPropagationLossModel> ();  
+  propLoss->SetLoss (c.Get(0)->GetObject<MobilityModel> (), c.Get(1)->GetObject<MobilityModel> (), lossDb, true);
+  channelHelper.AddPropagationLoss (propLoss);
+  Ptr<SpectrumChannel> channel = channelHelper.Create ();
+
+
+  WifiSpectrumValue5MhzFactory sf;
+
+  uint32_t channelNumber = 1;
+  Ptr<SpectrumValue> txPsd =  sf.CreateTxPowerSpectralDensity (txPowerW, channelNumber);
+
+  Ptr<SpectrumValue> noisePsd = sf.CreateConstant (noisePsdValue);
+
+  AdhocAlohaNoackIdealPhyHelper deviceHelper;
+  deviceHelper.SetChannel (channel);
+  deviceHelper.SetTxPowerSpectralDensity (txPsd);
+  deviceHelper.SetNoisePowerSpectralDensity (noisePsd);
+  deviceHelper.SetPhyAttribute ("Rate", DataRateValue (DataRate (phyRate)));
+  NetDeviceContainer devices = deviceHelper.Install (c);
+
+  PacketSocketHelper packetSocket;
+  packetSocket.Install (c);
+
+  PacketSocketAddress socket;
+  socket.SetSingleDevice (devices.Get (0)->GetIfIndex ());
+  socket.SetPhysicalAddress (devices.Get (1)->GetAddress ());
+  socket.SetProtocol (1);
+
+  OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (250)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (1.2*phyRate)));
+  onoff.SetAttribute ("PacketSize", UintegerValue (pktSize));
+
+  ApplicationContainer apps = onoff.Install (c.Get (0));
+  apps.Start (Seconds (0.0));
+  apps.Stop (Seconds (testDuration));
+
+  Config::Connect ("/NodeList/*/DeviceList/*/Phy/RxEndOk", MakeCallback (&PhyRxEndOkTrace));
+
+  g_rxBytes = 0;
+  Simulator::Stop (Seconds (testDuration+0.000000001));
+  Simulator::Run ();
+  double throughputBps = (g_rxBytes * 8.0) / testDuration;
+
+  if (m_rateIsAchievable)
+    {
+      NS_TEST_ASSERT_MSG_EQ_TOL (throughputBps, m_phyRate, m_phyRate*0.01, "throughput does not match PHY rate");
+    }
+  else
+    {
+      NS_TEST_ASSERT_MSG_EQ (throughputBps, 0.0, "PHY rate is not achievable but throughput is non-zero");    
+    }
+      
+  Simulator::Destroy ();
+}
+
+
+
+
+class SpectrumIdealPhyTestSuite : public TestSuite
+{
+public:
+  SpectrumIdealPhyTestSuite ();
+};
+
+SpectrumIdealPhyTestSuite::SpectrumIdealPhyTestSuite ()
+  : TestSuite ("spectrum-ideal-phy", SYSTEM)
+{
+
+  NS_LOG_INFO ("creating SpectrumIdealPhyTestSuite");
+    
+  for (double snr = 0.01; snr <= 10 ; snr *= 2)
+    {          
+      double achievableRate = g_bandwidth*log2(1+snr);      
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.1,  true,  "ns3::SingleModelSpectrumChannel"));
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.5,  true,  "ns3::SingleModelSpectrumChannel"));
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.95, true,  "ns3::SingleModelSpectrumChannel"));
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*1.05, false,  "ns3::SingleModelSpectrumChannel"));
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*2,    false,  "ns3::SingleModelSpectrumChannel"));
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*4,    false,  "ns3::SingleModelSpectrumChannel"));
+    }
+  for (double snr = 0.01; snr <= 10 ; snr *= 10)
+    {          
+      double achievableRate = g_bandwidth*log2(1+snr);      
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.1,  true,  "ns3::MultiModelSpectrumChannel"));
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.5,  true,  "ns3::MultiModelSpectrumChannel"));
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*0.95, true,  "ns3::MultiModelSpectrumChannel"));
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*1.05, false,  "ns3::MultiModelSpectrumChannel"));
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*2,    false,  "ns3::MultiModelSpectrumChannel"));
+      AddTestCase (new SpectrumIdealPhyTestCase (snr, achievableRate*4,    false,  "ns3::MultiModelSpectrumChannel"));
+    }
+}
+
+static SpectrumIdealPhyTestSuite g_spectrumIdealPhyTestSuite;
+
+} // namespace ns3
--- a/src/spectrum/wscript	Tue Jul 05 18:40:17 2011 +0200
+++ b/src/spectrum/wscript	Tue Jul 05 19:03:55 2011 +0200
@@ -36,6 +36,7 @@
     module_test.source = [
         'test/spectrum-interference-test.cc',
         'test/spectrum-value-test.cc',
+        'test/spectrum-ideal-phy-test.cc',
         ]
     
     headers = bld.new_task_gen('ns3header')