merge
authormmiozzo
Tue, 22 May 2012 16:41:05 +0200
changeset 8795 64da0851132c
parent 8794 a68aeda2d85b (current diff)
parent 8788 6b31c0c234cc (diff)
child 8796 c053291689b2
merge
src/lte/test/lte-test-phy-error-model.cc
--- a/doc/tutorial-pt-br/source/tracing.rst	Tue May 22 16:40:24 2012 +0200
+++ b/doc/tutorial-pt-br/source/tracing.rst	Tue May 22 16:41:05 2012 +0200
@@ -2996,10 +2996,10 @@
 Mas os objetos internos são inteiramente diferentes. Por exemplo, o Ptr<PcapFileWrapper> é um ponteiro para um objeto |ns3| que suporta ``Attributes`` e é integrado dentro do sistema de configuração. O Ptr<OutputStreamWrapper>, por outro lado, é um ponteiro para uma referência para um simples objeto contado. Lembre-se sempre de analisar o objeto que você está referenciando antes de fazer suposições sobre os "poderes" que o objeto pode ter.
 
 ..
-	For example, take a look at ``src/network/model/pcap-file-object.h`` in the 
+	For example, take a look at ``src/network/utils/pcap-file-wrapper.h`` in the 
 	distribution and notice, 
 
-Por exemplo, acesse o arquivo ``src/network/model/pcap-file-object.h`` e observe,
+Por exemplo, acesse o arquivo ``src/network/utils/pcap-file-wrapper.h`` e observe,
 
 ::
 
@@ -3562,10 +3562,10 @@
   		uint32_t deviceid);
 
 ..
-	You are encouraged to peruse the Doxygen for class ``TraceHelperForDevice``
+	You are encouraged to peruse the Doxygen for class ``AsciiTraceHelperForDevice``
 	to find the details of these methods; but to summarize ...
 
-Para maiores detalhes sobre os métodos é interessante consultar a documentação para a classe ``TraceHelperForDevice``; mas para resumir ...
+Para maiores detalhes sobre os métodos é interessante consultar a documentação para a classe ``AsciiTraceHelperForDevice``; mas para resumir ...
 
 ..
 	There are twice as many methods available for ascii tracing as there were for
--- a/doc/tutorial/source/tracing.rst	Tue May 22 16:40:24 2012 +0200
+++ b/doc/tutorial/source/tracing.rst	Tue May 22 16:41:05 2012 +0200
@@ -2168,7 +2168,7 @@
 Remember to always look at the object you are referencing before making any
 assumptions about the "powers" that object may have.  
 
-For example, take a look at ``src/network/model/pcap-file-object.h`` in the 
+For example, take a look at ``src/network/utils/pcap-file-wrapper.h`` in the 
 distribution and notice, 
 
 ::
@@ -2566,7 +2566,7 @@
   void EnableAscii (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool explicitFilename);
   void EnableAscii (Ptr<OutputStreamWrapper> stream, uint32_t nodeid, uint32_t deviceid);
 
-You are encouraged to peruse the Doxygen for class ``TraceHelperForDevice``
+You are encouraged to peruse the Doxygen for class ``AsciiTraceHelperForDevice``
 to find the details of these methods; but to summarize ...
 
 There are twice as many methods available for ascii tracing as there were for
--- a/src/buildings/bindings/modulegen__gcc_ILP32.py	Tue May 22 16:40:24 2012 +0200
+++ b/src/buildings/bindings/modulegen__gcc_ILP32.py	Tue May 22 16:41:05 2012 +0200
@@ -3989,14 +3989,6 @@
     cls.add_method('IsOutdoor', 
                    'bool', 
                    [])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetFloorNumber(uint8_t nfloor) [member function]
-    cls.add_method('SetFloorNumber', 
-                   'void', 
-                   [param('uint8_t', 'nfloor')])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetIndoor(ns3::Ptr<ns3::Building> building) [member function]
-    cls.add_method('SetIndoor', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Building >', 'building')])
     ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetIndoor(ns3::Ptr<ns3::Building> building, uint8_t nfloor, uint8_t nroomx, uint8_t nroomy) [member function]
     cls.add_method('SetIndoor', 
                    'void', 
@@ -4005,14 +3997,6 @@
     cls.add_method('SetOutdoor', 
                    'void', 
                    [])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetRoomNumberX(uint8_t nroomx) [member function]
-    cls.add_method('SetRoomNumberX', 
-                   'void', 
-                   [param('uint8_t', 'nroomx')])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetRoomNumberY(uint8_t nroomy) [member function]
-    cls.add_method('SetRoomNumberY', 
-                   'void', 
-                   [param('uint8_t', 'nroomy')])
     ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::DoDispose() [member function]
     cls.add_method('DoDispose', 
                    'void', 
--- a/src/buildings/bindings/modulegen__gcc_LP64.py	Tue May 22 16:40:24 2012 +0200
+++ b/src/buildings/bindings/modulegen__gcc_LP64.py	Tue May 22 16:41:05 2012 +0200
@@ -3989,14 +3989,6 @@
     cls.add_method('IsOutdoor', 
                    'bool', 
                    [])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetFloorNumber(uint8_t nfloor) [member function]
-    cls.add_method('SetFloorNumber', 
-                   'void', 
-                   [param('uint8_t', 'nfloor')])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetIndoor(ns3::Ptr<ns3::Building> building) [member function]
-    cls.add_method('SetIndoor', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Building >', 'building')])
     ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetIndoor(ns3::Ptr<ns3::Building> building, uint8_t nfloor, uint8_t nroomx, uint8_t nroomy) [member function]
     cls.add_method('SetIndoor', 
                    'void', 
@@ -4005,14 +3997,6 @@
     cls.add_method('SetOutdoor', 
                    'void', 
                    [])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetRoomNumberX(uint8_t nroomx) [member function]
-    cls.add_method('SetRoomNumberX', 
-                   'void', 
-                   [param('uint8_t', 'nroomx')])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetRoomNumberY(uint8_t nroomy) [member function]
-    cls.add_method('SetRoomNumberY', 
-                   'void', 
-                   [param('uint8_t', 'nroomy')])
     ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::DoDispose() [member function]
     cls.add_method('DoDispose', 
                    'void', 
--- a/src/dsr/bindings/modulegen__gcc_ILP32.py	Tue May 22 16:40:24 2012 +0200
+++ b/src/dsr/bindings/modulegen__gcc_ILP32.py	Tue May 22 16:41:05 2012 +0200
@@ -10281,6 +10281,8 @@
     cls.add_constructor([param('ns3::dsr::RouteCache::Neighbor const &', 'arg0')])
     ## dsr-rcache.h (module 'dsr'): ns3::dsr::RouteCache::Neighbor::Neighbor(ns3::Ipv4Address ip, ns3::Mac48Address mac, ns3::Time t) [constructor]
     cls.add_constructor([param('ns3::Ipv4Address', 'ip'), param('ns3::Mac48Address', 'mac'), param('ns3::Time', 't')])
+    ## dsr-rcache.h (module 'dsr'): ns3::dsr::RouteCache::Neighbor::Neighbor() [constructor]
+    cls.add_constructor([])
     ## dsr-rcache.h (module 'dsr'): ns3::dsr::RouteCache::Neighbor::close [variable]
     cls.add_instance_attribute('close', 'bool', is_const=False)
     ## dsr-rcache.h (module 'dsr'): ns3::dsr::RouteCache::Neighbor::m_expireTime [variable]
--- a/src/dsr/bindings/modulegen__gcc_LP64.py	Tue May 22 16:40:24 2012 +0200
+++ b/src/dsr/bindings/modulegen__gcc_LP64.py	Tue May 22 16:41:05 2012 +0200
@@ -10281,6 +10281,8 @@
     cls.add_constructor([param('ns3::dsr::RouteCache::Neighbor const &', 'arg0')])
     ## dsr-rcache.h (module 'dsr'): ns3::dsr::RouteCache::Neighbor::Neighbor(ns3::Ipv4Address ip, ns3::Mac48Address mac, ns3::Time t) [constructor]
     cls.add_constructor([param('ns3::Ipv4Address', 'ip'), param('ns3::Mac48Address', 'mac'), param('ns3::Time', 't')])
+    ## dsr-rcache.h (module 'dsr'): ns3::dsr::RouteCache::Neighbor::Neighbor() [constructor]
+    cls.add_constructor([])
     ## dsr-rcache.h (module 'dsr'): ns3::dsr::RouteCache::Neighbor::close [variable]
     cls.add_instance_attribute('close', 'bool', is_const=False)
     ## dsr-rcache.h (module 'dsr'): ns3::dsr::RouteCache::Neighbor::m_expireTime [variable]
--- a/src/dsr/model/dsr-rcache.h	Tue May 22 16:40:24 2012 +0200
+++ b/src/dsr/model/dsr-rcache.h	Tue May 22 16:41:05 2012 +0200
@@ -493,6 +493,8 @@
         close (false)
     {
     }
+
+    Neighbor () {} // For Python bindings
   };
   // / Return expire time for neighbor node with address addr, if exists, else return 0.
   Time GetExpireTime (Ipv4Address addr);
--- a/src/dsr/model/dsr-routing.cc	Tue May 22 16:40:24 2012 +0200
+++ b/src/dsr/model/dsr-routing.cc	Tue May 22 16:41:05 2012 +0200
@@ -1527,7 +1527,7 @@
         }
       else
         {
-          uint32_t totalQueueSize;
+          uint32_t totalQueueSize = 0;
           for (std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator j = m_priorityQueue.begin (); j != m_priorityQueue.end (); j++)
             {
               NS_LOG_DEBUG ("The size of the network queue for " << j->first << " is " << j->second->GetSize ());
--- a/src/lte/bindings/modulegen__gcc_ILP32.py	Tue May 22 16:40:24 2012 +0200
+++ b/src/lte/bindings/modulegen__gcc_ILP32.py	Tue May 22 16:41:05 2012 +0200
@@ -12574,14 +12574,6 @@
     cls.add_method('IsOutdoor', 
                    'bool', 
                    [])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetFloorNumber(uint8_t nfloor) [member function]
-    cls.add_method('SetFloorNumber', 
-                   'void', 
-                   [param('uint8_t', 'nfloor')])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetIndoor(ns3::Ptr<ns3::Building> building) [member function]
-    cls.add_method('SetIndoor', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Building >', 'building')])
     ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetIndoor(ns3::Ptr<ns3::Building> building, uint8_t nfloor, uint8_t nroomx, uint8_t nroomy) [member function]
     cls.add_method('SetIndoor', 
                    'void', 
@@ -12590,14 +12582,6 @@
     cls.add_method('SetOutdoor', 
                    'void', 
                    [])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetRoomNumberX(uint8_t nroomx) [member function]
-    cls.add_method('SetRoomNumberX', 
-                   'void', 
-                   [param('uint8_t', 'nroomx')])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetRoomNumberY(uint8_t nroomy) [member function]
-    cls.add_method('SetRoomNumberY', 
-                   'void', 
-                   [param('uint8_t', 'nroomy')])
     ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::DoDispose() [member function]
     cls.add_method('DoDispose', 
                    'void', 
--- a/src/lte/bindings/modulegen__gcc_LP64.py	Tue May 22 16:40:24 2012 +0200
+++ b/src/lte/bindings/modulegen__gcc_LP64.py	Tue May 22 16:41:05 2012 +0200
@@ -12574,14 +12574,6 @@
     cls.add_method('IsOutdoor', 
                    'bool', 
                    [])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetFloorNumber(uint8_t nfloor) [member function]
-    cls.add_method('SetFloorNumber', 
-                   'void', 
-                   [param('uint8_t', 'nfloor')])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetIndoor(ns3::Ptr<ns3::Building> building) [member function]
-    cls.add_method('SetIndoor', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Building >', 'building')])
     ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetIndoor(ns3::Ptr<ns3::Building> building, uint8_t nfloor, uint8_t nroomx, uint8_t nroomy) [member function]
     cls.add_method('SetIndoor', 
                    'void', 
@@ -12590,14 +12582,6 @@
     cls.add_method('SetOutdoor', 
                    'void', 
                    [])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetRoomNumberX(uint8_t nroomx) [member function]
-    cls.add_method('SetRoomNumberX', 
-                   'void', 
-                   [param('uint8_t', 'nroomx')])
-    ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::SetRoomNumberY(uint8_t nroomy) [member function]
-    cls.add_method('SetRoomNumberY', 
-                   'void', 
-                   [param('uint8_t', 'nroomy')])
     ## buildings-mobility-model.h (module 'buildings'): void ns3::BuildingsMobilityModel::DoDispose() [member function]
     cls.add_method('DoDispose', 
                    'void', 
--- a/src/lte/examples/lena-dual-stripe.cc	Tue May 22 16:40:24 2012 +0200
+++ b/src/lte/examples/lena-dual-stripe.cc	Tue May 22 16:41:05 2012 +0200
@@ -154,11 +154,66 @@
       outFile << "set object " << index
               << " rect from " << box.xMin  << "," << box.yMin  
               << " to "   << box.xMax  << "," << box.yMax
-              << " front"
+              << " front fs empty "
               << std::endl;
     }
 }
 
+void 
+PrintGnuplottableUeListToFile (std::string filename)
+{
+  std::ofstream outFile;
+  outFile.open (filename.c_str ());
+  if (!outFile.is_open ())
+    {
+      NS_LOG_ERROR ("Can't open file " << filename);
+      return;
+    }
+  for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it)
+    {
+      Ptr<Node> node = *it;
+      int nDevs = node->GetNDevices ();
+      for (int j = 0; j < nDevs; j++)
+        {
+          Ptr<LteUeNetDevice> uedev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
+          if (uedev)
+            {
+              Vector pos = node->GetObject<MobilityModel> ()->GetPosition ();
+              outFile << "set label \"" << uedev->GetImsi ()
+                      << "\" at "<< pos.x << "," << pos.y << " left font \"Helvetica,4\" textcolor rgb \"grey\" front point pt 1 ps 0.3 lc rgb \"grey\" offset 0,0"  
+                      << std::endl;
+            }
+        }
+    }
+}
+
+void 
+PrintGnuplottableEnbListToFile (std::string filename)
+{
+  std::ofstream outFile;
+  outFile.open (filename.c_str ());
+  if (!outFile.is_open ())
+    {
+      NS_LOG_ERROR ("Can't open file " << filename);
+      return;
+    }
+  for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it)
+    {
+      Ptr<Node> node = *it;
+      int nDevs = node->GetNDevices ();
+      for (int j = 0; j < nDevs; j++)
+        {
+          Ptr<LteEnbNetDevice> enbdev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
+          if (enbdev)
+            {
+              Vector pos = node->GetObject<MobilityModel> ()->GetPosition ();
+              outFile << "set label \"" << enbdev->GetCellId ()
+                      << "\" at "<< pos.x << "," << pos.y << " left font \"Helvetica,4\" textcolor rgb \"white\" front  point pt 2 ps 0.3 lc rgb \"white\" offset 0,0"  
+                      << std::endl;
+            }
+        }
+    }
+}
 
 int
 main (int argc, char *argv[])
@@ -193,7 +248,6 @@
   bool epcUl = true;
   bool useUdp = true;
   bool generateRem = false;
-  bool printBuildingList = false;
   
   CommandLine cmd;
   cmd.AddValue ("nBlocks", "Number of femtocell blocks", nBlocks);
@@ -222,8 +276,6 @@
   cmd.AddValue ("simTime", "Total duration of the simulation [s]", simTime);
   cmd.AddValue ("generateRem", "if true, will generate a REM and then abort the simulation;"
                 "if false, will run the simulation normally (without generating any REM)", generateRem);
-  cmd.AddValue ("printBuildingList", "if true, will save a list of buildings with their positions to file;"
-                "if false, will run the simulation normally (without generating any REM)", printBuildingList);
   cmd.AddValue ("epc", "if true, will setup the EPC to simulate an end-to-end topology;"
                 "if false, only the LTE radio access will be simulated.", epc);
   cmd.AddValue ("epcDl", "if true, will activate data flows in the downlink when EPC is being used. "
@@ -244,22 +296,32 @@
 
   cmd.Parse (argc, argv);
 
-  uint32_t currentSite = nMacroEnbSites -1;
-  uint32_t biRowIndex = (currentSite / (nMacroEnbSitesX + nMacroEnbSitesX + 1));
-  uint32_t biRowRemainder = currentSite % (nMacroEnbSitesX + nMacroEnbSitesX + 1);
-  uint32_t rowIndex = biRowIndex*2 + 1;
-  if (biRowRemainder >= nMacroEnbSitesX)
+  Box macroUeBox;
+
+  if (nMacroEnbSites > 0)
     {
-      ++rowIndex;
+      uint32_t currentSite = nMacroEnbSites -1;
+      uint32_t biRowIndex = (currentSite / (nMacroEnbSitesX + nMacroEnbSitesX + 1));
+      uint32_t biRowRemainder = currentSite % (nMacroEnbSitesX + nMacroEnbSitesX + 1);
+      uint32_t rowIndex = biRowIndex*2 + 1;
+      if (biRowRemainder >= nMacroEnbSitesX)
+        {
+          ++rowIndex;
+        }
+      uint32_t nMacroEnbSitesY = rowIndex;
+      NS_LOG_LOGIC ("nMacroEnbSitesY = " << nMacroEnbSitesY);
+
+      macroUeBox = Box (-areaMarginFactor*interSiteDistance, 
+                        (nMacroEnbSitesX + areaMarginFactor)*interSiteDistance, 
+                        -areaMarginFactor*interSiteDistance, 
+                        (nMacroEnbSitesY -1)*interSiteDistance*sqrt(0.75) + areaMarginFactor*interSiteDistance,
+                        1.0, 2.0);
     }
-  uint32_t nMacroEnbSitesY = rowIndex;
-  NS_LOG_LOGIC ("nMacroEnbSitesY = " << nMacroEnbSitesY);
-
-  Box macroUeBox (-areaMarginFactor*interSiteDistance, 
-                  (nMacroEnbSitesX + areaMarginFactor)*interSiteDistance, 
-                  -areaMarginFactor*interSiteDistance, 
-                  (nMacroEnbSitesY -1)*interSiteDistance*sqrt(0.75) + areaMarginFactor*interSiteDistance,
-                  1.0, 2.0);
+  else
+    {
+      // still need the box to place femtocell blocks
+      macroUeBox = Box (0, 150, 0, 150, 1.0, 2.0);
+    }
   
   FemtocellBlockAllocator blockAllocator (macroUeBox, nApartmentsX, nFloors);
   blockAllocator.Create (nBlocks);
@@ -353,7 +415,17 @@
   mobility.SetPositionAllocator (positionAlloc);
   mobility.Install (homeUes);
   NetDeviceContainer homeUeDevs = lteHelper->InstallUeDevice (homeUes);
-  lteHelper->AttachToClosestEnb (homeUeDevs, homeEnbDevs);
+
+  NetDeviceContainer::Iterator ueDevIt;
+  NetDeviceContainer::Iterator enbDevIt;
+  // attach explicitly each home UE to its home eNB
+  for (ueDevIt = homeUeDevs.Begin (), 
+          enbDevIt = homeEnbDevs.Begin (); 
+       ueDevIt != homeUeDevs.End () && enbDevIt != homeEnbDevs.End (); 
+       ++ueDevIt, ++enbDevIt)
+    {
+      lteHelper->Attach (*ueDevIt, *enbDevIt);
+    }
 
 
   if (epc)
@@ -478,6 +550,10 @@
   Ptr<RadioEnvironmentMapHelper> remHelper;
   if (generateRem)
     {
+      PrintGnuplottableBuildingListToFile ("buildings.txt");
+      PrintGnuplottableEnbListToFile ("enbs.txt");
+      PrintGnuplottableUeListToFile ("ues.txt");
+
       remHelper = CreateObject<RadioEnvironmentMapHelper> ();
       remHelper->SetAttribute ("ChannelPath", StringValue ("/ChannelList/0"));
       remHelper->SetAttribute ("OutputFile", StringValue ("lena-dual-stripe.rem"));
@@ -488,6 +564,8 @@
       remHelper->SetAttribute ("Z", DoubleValue (1.5));
       remHelper->Install ();
       // simulation will stop right after the REM has been generated
+
+
     }
   else
     {
@@ -501,11 +579,6 @@
       lteHelper->EnablePdcpTraces ();
     }
 
-  if (printBuildingList)
-    {
-      PrintGnuplottableBuildingListToFile ("buildings.txt");
-    }
-
   Simulator::Run ();
 
   //GtkConfigStore config;
--- a/src/lte/examples/lena-rem-sector-antenna.cc	Tue May 22 16:40:24 2012 +0200
+++ b/src/lte/examples/lena-rem-sector-antenna.cc	Tue May 22 16:41:05 2012 +0200
@@ -164,12 +164,12 @@
   vector < NetDeviceContainer > ueDevs;
 
   // power setting in dBm for small cells
-  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (10.0));
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (20.0));
   enbDevs = lteHelper->InstallEnbDevice (oneSectorNodes);
 
 
   // power setting for three-sector macrocell
-  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (30.0));
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (43.0));
 
   // Beam width is made quite narrow so sectors can be noticed in the REM
   lteHelper->SetEnbAntennaModelType ("ns3::CosineAntennaModel");
--- a/src/lte/test/lte-test-phy-error-model.cc	Tue May 22 16:40:24 2012 +0200
+++ b/src/lte/test/lte-test-phy-error-model.cc	Tue May 22 16:41:05 2012 +0200
@@ -46,6 +46,7 @@
 #include <ns3/config.h>
 #include <ns3/boolean.h>
 #include <ns3/enum.h>
+#include <ns3/unused.h>
 
 
 NS_LOG_COMPONENT_DEFINE ("LenaTestPhyErrorModel");
@@ -242,7 +243,10 @@
       int lambda = (double)dlDataRxed.at (i) / m_tbSize;
       double ber = 1.0 - ((double)dlDataRxed.at (i)/txed);
       double np = n-n*m_berRef;
-      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << " txed " << txed << " BER " << ber << " Err " << fabs (m_berRef - ber) << " lambda " << lambda << " np " << np << " difference " << abs(lambda - np) << " quantile " << m_bernQuantile);
+      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << " txed " << txed 
+        << " BER " << ber << " Err " << fabs (m_berRef - ber) << " lambda " << lambda 
+        << " np " << np << " difference " << abs(lambda - np) << " quantile " << m_bernQuantile);
+      NS_UNUSED (ber);
       // the quantiles are evaluated offline according to a Bernoulli 
       // ditribution with n equal to the number of packet sent and p equal 
       // to the BER (see /reference/bernuolliDistribution.m for details)
--- a/src/lte/test/lte-test-rr-ff-mac-scheduler.cc	Tue May 22 16:40:24 2012 +0200
+++ b/src/lte/test/lte-test-rr-ff-mac-scheduler.cc	Tue May 22 16:41:05 2012 +0200
@@ -316,9 +316,8 @@
       uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
       // get the lcId
       uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
-      double txed = rlcStats->GetUlTxData (imsi, lcId);
       ulDataRxed.push_back (rlcStats->GetUlRxData (imsi, lcId));
-      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes txed " << (double)ulDataRxed.at (i) << "  thr " << (double)ulDataRxed.at (i) / simulationTime << " ref " << m_thrRefUl << " txed " << txed / simulationTime);
+      NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes txed " << (double)ulDataRxed.at (i) << "  thr " << (double)ulDataRxed.at (i) / simulationTime << " ref " << m_thrRefUl << " txed " << rlcStats->GetUlTxData (imsi, lcId) / simulationTime);
       NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / simulationTime, m_thrRefUl, m_thrRefUl * tolerance, " Unfair Throughput!");
     }
 
--- a/src/lte/test/test-epc-tft-classifier.cc	Tue May 22 16:40:24 2012 +0200
+++ b/src/lte/test/test-epc-tft-classifier.cc	Tue May 22 16:41:05 2012 +0200
@@ -114,7 +114,7 @@
       << ", da = " << da
       << ", sp = " << sp
       << ", dp = " << dp
-      << ", tos = 0x" << std::hex << tos
+      << ", tos = 0x" << std::hex << (int) tos
       << " --> tftId = " << tftId;  
   return oss.str ();
 }
--- a/src/netanim/bindings/modulegen__gcc_ILP32.py	Tue May 22 16:40:24 2012 +0200
+++ b/src/netanim/bindings/modulegen__gcc_ILP32.py	Tue May 22 16:41:05 2012 +0200
@@ -516,14 +516,18 @@
     cls.add_constructor([param('ns3::AnimationInterface const &', 'arg0')])
     ## animation-interface.h (module 'netanim'): ns3::AnimationInterface::AnimationInterface() [constructor]
     cls.add_constructor([])
-    ## animation-interface.h (module 'netanim'): ns3::AnimationInterface::AnimationInterface(std::string const filename, bool usingXML=true) [constructor]
-    cls.add_constructor([param('std::string const', 'filename'), param('bool', 'usingXML', default_value='true')])
+    ## animation-interface.h (module 'netanim'): ns3::AnimationInterface::AnimationInterface(std::string const filename, uint64_t maxPktsPerFile=100000, bool usingXML=true) [constructor]
+    cls.add_constructor([param('std::string const', 'filename'), param('uint64_t', 'maxPktsPerFile', default_value='100000'), param('bool', 'usingXML', default_value='true')])
     ## animation-interface.h (module 'netanim'): ns3::AnimationInterface::AnimationInterface(uint16_t port, bool usingXML=true) [constructor]
     cls.add_constructor([param('uint16_t', 'port'), param('bool', 'usingXML', default_value='true')])
     ## animation-interface.h (module 'netanim'): void ns3::AnimationInterface::EnablePacketMetadata(bool enable) [member function]
     cls.add_method('EnablePacketMetadata', 
                    'void', 
                    [param('bool', 'enable')])
+    ## animation-interface.h (module 'netanim'): uint64_t ns3::AnimationInterface::GetTracePktCount() [member function]
+    cls.add_method('GetTracePktCount', 
+                   'uint64_t', 
+                   [])
     ## animation-interface.h (module 'netanim'): static bool ns3::AnimationInterface::IsInitialized() [member function]
     cls.add_method('IsInitialized', 
                    'bool', 
@@ -588,10 +592,10 @@
     cls.add_method('ShowAll802_11', 
                    'void', 
                    [param('bool', 'showAll')])
-    ## animation-interface.h (module 'netanim'): void ns3::AnimationInterface::StartAnimation() [member function]
+    ## animation-interface.h (module 'netanim'): void ns3::AnimationInterface::StartAnimation(bool restart=false) [member function]
     cls.add_method('StartAnimation', 
                    'void', 
-                   [])
+                   [param('bool', 'restart', default_value='false')])
     ## animation-interface.h (module 'netanim'): void ns3::AnimationInterface::StopAnimation() [member function]
     cls.add_method('StopAnimation', 
                    'void', 
--- a/src/netanim/bindings/modulegen__gcc_LP64.py	Tue May 22 16:40:24 2012 +0200
+++ b/src/netanim/bindings/modulegen__gcc_LP64.py	Tue May 22 16:41:05 2012 +0200
@@ -516,14 +516,18 @@
     cls.add_constructor([param('ns3::AnimationInterface const &', 'arg0')])
     ## animation-interface.h (module 'netanim'): ns3::AnimationInterface::AnimationInterface() [constructor]
     cls.add_constructor([])
-    ## animation-interface.h (module 'netanim'): ns3::AnimationInterface::AnimationInterface(std::string const filename, bool usingXML=true) [constructor]
-    cls.add_constructor([param('std::string const', 'filename'), param('bool', 'usingXML', default_value='true')])
+    ## animation-interface.h (module 'netanim'): ns3::AnimationInterface::AnimationInterface(std::string const filename, uint64_t maxPktsPerFile=100000, bool usingXML=true) [constructor]
+    cls.add_constructor([param('std::string const', 'filename'), param('uint64_t', 'maxPktsPerFile', default_value='100000'), param('bool', 'usingXML', default_value='true')])
     ## animation-interface.h (module 'netanim'): ns3::AnimationInterface::AnimationInterface(uint16_t port, bool usingXML=true) [constructor]
     cls.add_constructor([param('uint16_t', 'port'), param('bool', 'usingXML', default_value='true')])
     ## animation-interface.h (module 'netanim'): void ns3::AnimationInterface::EnablePacketMetadata(bool enable) [member function]
     cls.add_method('EnablePacketMetadata', 
                    'void', 
                    [param('bool', 'enable')])
+    ## animation-interface.h (module 'netanim'): uint64_t ns3::AnimationInterface::GetTracePktCount() [member function]
+    cls.add_method('GetTracePktCount', 
+                   'uint64_t', 
+                   [])
     ## animation-interface.h (module 'netanim'): static bool ns3::AnimationInterface::IsInitialized() [member function]
     cls.add_method('IsInitialized', 
                    'bool', 
@@ -588,10 +592,10 @@
     cls.add_method('ShowAll802_11', 
                    'void', 
                    [param('bool', 'showAll')])
-    ## animation-interface.h (module 'netanim'): void ns3::AnimationInterface::StartAnimation() [member function]
+    ## animation-interface.h (module 'netanim'): void ns3::AnimationInterface::StartAnimation(bool restart=false) [member function]
     cls.add_method('StartAnimation', 
                    'void', 
-                   [])
+                   [param('bool', 'restart', default_value='false')])
     ## animation-interface.h (module 'netanim'): void ns3::AnimationInterface::StopAnimation() [member function]
     cls.add_method('StopAnimation', 
                    'void', 
--- a/src/netanim/model/animation-interface.cc	Tue May 22 16:40:24 2012 +0200
+++ b/src/netanim/model/animation-interface.cc	Tue May 22 16:41:05 2012 +0200
@@ -63,33 +63,36 @@
 std::map <uint32_t, std::string> AnimationInterface::nodeDescriptions;
 
 AnimationInterface::AnimationInterface ()
-  : m_fHandle (STDOUT_FILENO), m_xml (false), mobilitypollinterval (Seconds(0.25)),
-    usingSockets (false), mport (0), outputfilename (""),
-    OutputFileSet (false), ServerPortSet (false), gAnimUid (0),randomPosition (true),
+  : m_fHandle (STDOUT_FILENO), m_xml (false), m_mobilityPollInterval (Seconds(0.25)),
+    m_usingSockets (false), m_port (0), m_outputFileName (""),
+    m_outputFileSet (false), m_serverPortSet (false), gAnimUid (0),m_randomPosition (true),
     m_writeCallback (0), m_started (false), 
-    m_enablePacketMetadata (false), m_startTime (Seconds(0)), m_stopTime (Seconds(3600 * 1000))
+    m_enablePacketMetadata (false), m_startTime (Seconds(0)), m_stopTime (Seconds(3600 * 1000)),
+    m_maxPktsPerFile (MAX_PKTS_PER_TRACE_FILE)
 {
   initialized = true;
   StartAnimation ();
 }
 
-AnimationInterface::AnimationInterface (const std::string fn, bool usingXML)
-  : m_fHandle (STDOUT_FILENO), m_xml (usingXML), mobilitypollinterval (Seconds(0.25)), 
-    usingSockets (false), mport (0), outputfilename (fn),
-    OutputFileSet (false), ServerPortSet (false), gAnimUid (0), randomPosition (true),
+AnimationInterface::AnimationInterface (const std::string fn, uint64_t maxPktsPerFile, bool usingXML)
+  : m_fHandle (STDOUT_FILENO), m_xml (usingXML), m_mobilityPollInterval (Seconds(0.25)), 
+    m_usingSockets (false), m_port (0), m_outputFileName (fn),
+    m_outputFileSet (false), m_serverPortSet (false), gAnimUid (0), m_randomPosition (true),
     m_writeCallback (0), m_started (false), 
-    m_enablePacketMetadata (false), m_startTime (Seconds(0)), m_stopTime (Seconds(3600 * 1000))
+    m_enablePacketMetadata (false), m_startTime (Seconds(0)), m_stopTime (Seconds(3600 * 1000)),
+    m_maxPktsPerFile (maxPktsPerFile), m_originalFileName (fn)
 {
   initialized = true;
   StartAnimation ();
 }
 
 AnimationInterface::AnimationInterface (const uint16_t port, bool usingXML)
-  : m_fHandle (STDOUT_FILENO), m_xml (usingXML), mobilitypollinterval (Seconds(0.25)), 
-    usingSockets (true), mport (port), outputfilename (""),
-    OutputFileSet (false), ServerPortSet (false), gAnimUid (0), randomPosition (true),
+  : m_fHandle (STDOUT_FILENO), m_xml (usingXML), m_mobilityPollInterval (Seconds(0.25)), 
+    m_usingSockets (true), m_port (port), m_outputFileName (""),
+    m_outputFileSet (false), m_serverPortSet (false), gAnimUid (0), m_randomPosition (true),
     m_writeCallback (0), m_started (false), 
-    m_enablePacketMetadata (false), m_startTime (Seconds(0)), m_stopTime (Seconds(3600 * 1000))
+    m_enablePacketMetadata (false), m_startTime (Seconds(0)), m_stopTime (Seconds(3600 * 1000)),
+    m_maxPktsPerFile (MAX_PKTS_PER_TRACE_FILE)
 {
   initialized = true;
   StartAnimation ();
@@ -107,6 +110,22 @@
 }
 
 
+void AnimationInterface::StartNewTraceFile ()
+{
+  static int i = 0;
+  std::ostringstream oss;
+  oss << i;
+  ++m_currentPktCount;
+  if (m_currentPktCount <= m_maxPktsPerFile)
+    {
+      return;
+    }
+  StopAnimation ();
+  m_outputFileName = m_originalFileName + "-" + oss.str ();
+  StartAnimation (true);
+  ++i;
+
+}
 void AnimationInterface::SetStartTime (Time t)
 {
   m_startTime = t;
@@ -119,16 +138,17 @@
 
 bool AnimationInterface::SetOutputFile (const std::string& fn)
 {
-  if (OutputFileSet)
+  if (m_outputFileSet)
     {
       return true;
     }
   if (fn == "")
     {
       m_fHandle = STDOUT_FILENO;
-      OutputFileSet = true;
+      m_outputFileSet = true;
       return true;
     }
+  NS_LOG_INFO ("Creating new trace file:" << fn.c_str ());
   FILE* f = fopen (fn.c_str (), "w");
   if (!f)
     {
@@ -136,9 +156,9 @@
       return false; // Can't open
     }
   m_fHandle = fileno (f); // Set the file handle
-  usingSockets = false;
-  outputfilename = fn;
-  OutputFileSet = true;
+  m_usingSockets = false;
+  m_outputFileName = fn;
+  m_outputFileSet = true;
   return true;
 }
 
@@ -182,7 +202,7 @@
 bool AnimationInterface::SetServerPort (uint16_t port)
 {
 #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_NETINET_IN_H)
-  if (ServerPortSet)
+  if (m_serverPortSet)
     {
       return true;
     }
@@ -204,8 +224,8 @@
   // set the linger socket option
   int t = 1;
   setsockopt (s, SOL_SOCKET, SO_LINGER, &t, sizeof(t));
-  usingSockets = true;
-  ServerPortSet = true;
+  m_usingSockets = true;
+  m_serverPortSet = true;
   return true;
 #endif
   return false; // never reached unless the above is disabled
@@ -214,33 +234,33 @@
 
 bool AnimationInterface::WifiPacketIsPending (uint64_t AnimUid)
 {
-  return (pendingWifiPackets.find (AnimUid) != pendingWifiPackets.end ());
+  return (m_pendingWifiPackets.find (AnimUid) != m_pendingWifiPackets.end ());
 }
 
 bool AnimationInterface::CsmaPacketIsPending (uint64_t AnimUid)
 {
-  return (pendingCsmaPackets.find (AnimUid) != pendingCsmaPackets.end ());
+  return (m_pendingCsmaPackets.find (AnimUid) != m_pendingCsmaPackets.end ());
 }
 
 
 bool AnimationInterface::WimaxPacketIsPending (uint64_t AnimUid)
 {
-  return (pendingWimaxPackets.find (AnimUid) != pendingWimaxPackets.end ());
+  return (m_pendingWimaxPackets.find (AnimUid) != m_pendingWimaxPackets.end ());
 }
 
 bool AnimationInterface::LtePacketIsPending (uint64_t AnimUid)
 {
-  return (pendingLtePackets.find (AnimUid) != pendingLtePackets.end ());
+  return (m_pendingLtePackets.find (AnimUid) != m_pendingLtePackets.end ());
 }
 
 void AnimationInterface::SetMobilityPollInterval (Time t)
 {
-  mobilitypollinterval = t;
+  m_mobilityPollInterval = t;
 }
 
 void AnimationInterface::SetRandomPosition (bool setRandPos)
 {
-  randomPosition = setRandPos;
+  m_randomPosition = setRandPos;
 }
 
 Vector AnimationInterface::UpdatePosition (Ptr <Node> n)
@@ -248,49 +268,49 @@
   Ptr<MobilityModel> loc = n->GetObject<MobilityModel> ();
   if (loc)
     {
-      nodeLocation[n->GetId ()] = loc->GetPosition ();
+      m_nodeLocation[n->GetId ()] = loc->GetPosition ();
     }
   else
    {
      NS_LOG_UNCOND ( "AnimationInterface WARNING:Node:" << n->GetId () << " Does not have a mobility model. Use SetConstantPosition if it is stationary");
      Vector deterministicVector (100,100,0);
-     Vector randomVector (UniformVariable (0, topo_maxX-topo_minX).GetValue (), UniformVariable (0, topo_maxY-topo_minY).GetValue (), 0);
-     if (randomPosition)
+     Vector randomVector (UniformVariable (0, m_topoMaxX - m_topoMinX).GetValue (), UniformVariable (0, m_topoMaxY - m_topoMinY).GetValue (), 0);
+     if (m_randomPosition)
        {
-         nodeLocation[n->GetId ()] = randomVector;
+         m_nodeLocation[n->GetId ()] = randomVector;
        }
      else
        {
-         nodeLocation[n->GetId ()] = deterministicVector;
+         m_nodeLocation[n->GetId ()] = deterministicVector;
        }
    }
-  return nodeLocation[n->GetId ()];
+  return m_nodeLocation[n->GetId ()];
 }
 
 Vector AnimationInterface::UpdatePosition (Ptr <Node> n, Vector v)
 {
-  nodeLocation[n->GetId ()] = v;
+  m_nodeLocation[n->GetId ()] = v;
   return v;
 }
 
 Vector AnimationInterface::GetPosition (Ptr <Node> n)
 {
   #ifdef NS_LOG
-  if (nodeLocation.find (n->GetId()) == nodeLocation.end ())
+  if (m_nodeLocation.find (n->GetId()) == m_nodeLocation.end ())
     {
       NS_FATAL_ERROR ("Node:" <<n->GetId() << " not found in Location table");
     }  
   #endif
-  return nodeLocation[n->GetId ()];
+  return m_nodeLocation[n->GetId ()];
 }
 
 void AnimationInterface::PurgePendingWifi ()
 {
-  if (pendingWifiPackets.empty ())
+  if (m_pendingWifiPackets.empty ())
     return;
   std::vector <uint64_t> purgeList;
-  for (std::map<uint64_t, AnimPacketInfo>::iterator i = pendingWifiPackets.begin ();
-       i != pendingWifiPackets.end ();
+  for (std::map<uint64_t, AnimPacketInfo>::iterator i = m_pendingWifiPackets.begin ();
+       i != m_pendingWifiPackets.end ();
        ++i)
     {
      
@@ -306,18 +326,18 @@
        i != purgeList.end ();
        ++i)
     {
-      pendingWifiPackets.erase (*i);
+      m_pendingWifiPackets.erase (*i);
     }
 
 }
 
 void AnimationInterface::PurgePendingWimax ()
 {
-  if (pendingWimaxPackets.empty ())
+  if (m_pendingWimaxPackets.empty ())
     return;
   std::vector <uint64_t> purgeList;
-  for (std::map<uint64_t, AnimPacketInfo>::iterator i = pendingWimaxPackets.begin ();
-       i != pendingWimaxPackets.end ();
+  for (std::map<uint64_t, AnimPacketInfo>::iterator i = m_pendingWimaxPackets.begin ();
+       i != m_pendingWimaxPackets.end ();
        ++i)
     {
 
@@ -333,7 +353,7 @@
        i != purgeList.end ();
        ++i)
     {
-      pendingWimaxPackets.erase (*i);
+      m_pendingWimaxPackets.erase (*i);
     }
 
 }
@@ -341,11 +361,11 @@
 
 void AnimationInterface::PurgePendingLte ()
 {
-  if (pendingLtePackets.empty ())
+  if (m_pendingLtePackets.empty ())
     return;
   std::vector <uint64_t> purgeList;
-  for (std::map<uint64_t, AnimPacketInfo>::iterator i = pendingLtePackets.begin ();
-       i != pendingLtePackets.end ();
+  for (std::map<uint64_t, AnimPacketInfo>::iterator i = m_pendingLtePackets.begin ();
+       i != m_pendingLtePackets.end ();
        ++i)
     {
 
@@ -361,17 +381,17 @@
        i != purgeList.end ();
        ++i)
     {
-      pendingLtePackets.erase (*i);
+      m_pendingLtePackets.erase (*i);
     }
 }
 
 void AnimationInterface::PurgePendingCsma ()
 {
-  if (pendingCsmaPackets.empty ())
+  if (m_pendingCsmaPackets.empty ())
     return;
   std::vector <uint64_t> purgeList;
-  for (std::map<uint64_t, AnimPacketInfo>::iterator i = pendingCsmaPackets.begin ();
-       i != pendingCsmaPackets.end ();
+  for (std::map<uint64_t, AnimPacketInfo>::iterator i = m_pendingCsmaPackets.begin ();
+       i != m_pendingCsmaPackets.end ();
        ++i)
     {
     
@@ -387,37 +407,38 @@
        i != purgeList.end ();
        ++i)
     {
-      pendingCsmaPackets.erase (*i);
+      m_pendingCsmaPackets.erase (*i);
     }
 
 }
 
-void AnimationInterface::StartAnimation ()
+void AnimationInterface::StartAnimation (bool restart)
 {
+  m_currentPktCount = 0;
   m_started = true;
-  if (usingSockets)
+  if (m_usingSockets)
     {
-      SetServerPort (mport);
+      SetServerPort (m_port);
     }
   else
     {
-      SetOutputFile (outputfilename);
+      SetOutputFile (m_outputFileName);
     }      
 
   // Find the min/max x/y for the xml topology element
-  topo_minX = -2;
-  topo_minY = -2;
-  topo_maxX = 2;
-  topo_maxY = 2;
+  m_topoMinX = -2;
+  m_topoMinY = -2;
+  m_topoMaxX = 2;
+  m_topoMaxY = 2;
   for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
     {
       Ptr<Node> n = *i;
       NS_LOG_INFO ("Update Position for Node: " << n->GetId ());
       Vector v = UpdatePosition (n); 
-      topo_minX = std::min (topo_minX, v.x);
-      topo_minY = std::min (topo_minY, v.y);
-      topo_maxX = std::max (topo_maxX, v.x);
-      topo_maxY = std::max (topo_maxY, v.y);
+      m_topoMinX = std::min (m_topoMinX, v.x);
+      m_topoMinY = std::min (m_topoMinY, v.y);
+      m_topoMaxX = std::max (m_topoMaxX, v.x);
+      m_topoMaxY = std::max (m_topoMaxY, v.y);
     }
 
   AddMargin ();
@@ -426,7 +447,7 @@
       std::ostringstream oss;
       oss << GetXMLOpen_anim (0);
       oss << GetPreamble ();
-      oss << GetXMLOpen_topology (topo_minX, topo_minY, topo_maxX, topo_maxY);
+      oss << GetXMLOpen_topology (m_topoMinX, m_topoMinY, m_topoMaxX, m_topoMaxY);
       WriteN (m_fHandle, oss.str ());
     }
   NS_LOG_INFO ("Setting topology for "<<NodeList::GetNNodes ()<<" Nodes");
@@ -497,13 +518,13 @@
             }
         }
     }
-  if (m_xml)
+  if (m_xml && !restart)
     {
       WriteN (m_fHandle, GetXMLClose ("topology"));
-      Simulator::Schedule (mobilitypollinterval, &AnimationInterface::MobilityAutoCheck, this);
+      Simulator::Schedule (m_mobilityPollInterval, &AnimationInterface::MobilityAutoCheck, this);
     }
-
-  ConnectCallbacks ();
+  if (!restart)
+    ConnectCallbacks ();
 }
 
 void AnimationInterface::ConnectCallbacks ()
@@ -553,7 +574,7 @@
         {
           close (m_fHandle);
         }
-      OutputFileSet = false;
+      m_outputFileSet = false;
       m_fHandle = -1;
     }
 }
@@ -575,14 +596,14 @@
 void AnimationInterface::AddMargin ()
 {
   // Compute width/height, and add a small margin
-  double w = topo_maxX - topo_minX;
-  double h = topo_maxY - topo_minY;
-  topo_minX -= w * 0.05;
-  topo_minY -= h * 0.05;
-  topo_maxX = topo_minX + w * 1.5;
-  topo_maxY = topo_minY + h * 1.5;
-  NS_LOG_INFO ("Added Canvas Margin:" << topo_minX << "," <<
-               topo_minY << "," << topo_maxX << "," << topo_maxY);                 
+  double w = m_topoMaxX - m_topoMinX;
+  double h = m_topoMaxY - m_topoMinY;
+  m_topoMinX -= w * 0.05;
+  m_topoMinY -= h * 0.05;
+  m_topoMaxX = m_topoMinX + w * 1.5;
+  m_topoMaxY = m_topoMinY + h * 1.5;
+  NS_LOG_INFO ("Added Canvas Margin:" << m_topoMinX << "," <<
+               m_topoMinY << "," << m_topoMaxX << "," << m_topoMaxY);                 
 }
 
 std::vector <Ptr <Node> >  AnimationInterface::RecalcTopoBounds ()
@@ -618,17 +639,17 @@
 
 void AnimationInterface::RecalcTopoBounds (Vector v)
 {
-  double oldminX = topo_minX;
-  double oldminY = topo_minY;
-  double oldmaxX = topo_maxX;
-  double oldmaxY = topo_maxY;
-  topo_minX = std::min (topo_minX, v.x);
-  topo_minY = std::min (topo_minY, v.y);
-  topo_maxX = std::max (topo_maxX, v.x);
-  topo_maxY = std::max (topo_maxY, v.y);
+  double oldminX = m_topoMinX;
+  double oldminY = m_topoMinY;
+  double oldmaxX = m_topoMaxX;
+  double oldmaxY = m_topoMaxY;
+  m_topoMinX = std::min (m_topoMinX, v.x);
+  m_topoMinY = std::min (m_topoMinY, v.y);
+  m_topoMaxX = std::max (m_topoMaxX, v.x);
+  m_topoMaxY = std::max (m_topoMaxY, v.y);
   
-  if ((topo_minX != oldminX) || (topo_minY != oldminY) ||
-      (topo_maxX != oldmaxX) || (topo_maxY != oldmaxY))
+  if ((m_topoMinX != oldminX) || (m_topoMinY != oldminY) ||
+      (m_topoMaxX != oldmaxX) || (m_topoMaxY != oldmaxY))
     {
       AddMargin ();
     } 
@@ -697,6 +718,8 @@
       if (m_enablePacketMetadata)
         oss << GetXMLOpenClose_meta (GetPacketMetadata (p));
       oss << GetXMLClose ("packet");
+      StartNewTraceFile ();
+      ++m_currentPktCount;
     }
   else
     {
@@ -727,25 +750,25 @@
                                   
 void AnimationInterface::AddPendingWifiPacket (uint64_t AnimUid, AnimPacketInfo &pktinfo)
 {
-  pendingWifiPackets[AnimUid] = pktinfo;
+  m_pendingWifiPackets[AnimUid] = pktinfo;
 }
 
 void AnimationInterface::AddPendingWimaxPacket (uint64_t AnimUid, AnimPacketInfo &pktinfo)
 {
   NS_ASSERT (pktinfo.m_txnd);
-  pendingWimaxPackets[AnimUid] = pktinfo;
+  m_pendingWimaxPackets[AnimUid] = pktinfo;
 }
 
 void AnimationInterface::AddPendingLtePacket (uint64_t AnimUid, AnimPacketInfo &pktinfo)
 {
   NS_ASSERT (pktinfo.m_txnd);
-  pendingLtePackets[AnimUid] = pktinfo;
+  m_pendingLtePackets[AnimUid] = pktinfo;
 }
 
 void AnimationInterface::AddPendingCsmaPacket (uint64_t AnimUid, AnimPacketInfo &pktinfo)
 {
   NS_ASSERT (pktinfo.m_txnd);
-  pendingCsmaPackets[AnimUid] = pktinfo;
+  m_pendingCsmaPackets[AnimUid] = pktinfo;
 }
 
 uint64_t AnimationInterface::GetAnimUidFromPacket (Ptr <const Packet> p)
@@ -814,7 +837,7 @@
   uint64_t AnimUid = GetAnimUidFromPacket (p);
   NS_LOG_INFO ("TxDropTrace for packet:" << AnimUid);
   NS_ASSERT (WifiPacketIsPending (AnimUid) == true);
-  pendingWifiPackets.erase (pendingWifiPackets.find (AnimUid));
+  m_pendingWifiPackets.erase (m_pendingWifiPackets.find (AnimUid));
 }
 
 
@@ -851,9 +874,9 @@
       NS_LOG_WARN ("WifiPhyRxBegin: unknown Uid, but we are adding a wifi packet");
     }
   // TODO: NS_ASSERT (WifiPacketIsPending (AnimUid) == true);
-  pendingWifiPackets[AnimUid].ProcessRxBegin (ndev, Simulator::Now ());
-  pendingWifiPackets[AnimUid].ProcessRxEnd (ndev, Simulator::Now (), UpdatePosition (n));
-  OutputWirelessPacket (p, pendingWifiPackets[AnimUid], pendingWifiPackets[AnimUid].GetRxInfo (ndev));
+  m_pendingWifiPackets[AnimUid].ProcessRxBegin (ndev, Simulator::Now ());
+  m_pendingWifiPackets[AnimUid].ProcessRxEnd (ndev, Simulator::Now (), UpdatePosition (n));
+  OutputWirelessPacket (p, m_pendingWifiPackets[AnimUid], m_pendingWifiPackets[AnimUid].GetRxInfo (ndev));
 }
 
 
@@ -874,7 +897,7 @@
       AddPendingWifiPacket (AnimUid, pktinfo);
     }
   // TODO: NS_ASSERT (WifiPacketIsPending (AnimUid) == true);
-  AnimPacketInfo& pktInfo = pendingWifiPackets[AnimUid];
+  AnimPacketInfo& pktInfo = m_pendingWifiPackets[AnimUid];
   pktInfo.ProcessRxEnd (ndev, Simulator::Now (), UpdatePosition (n));
   AnimRxInfo pktrxInfo = pktInfo.GetRxInfo (ndev);
   if (pktrxInfo.IsPhyRxComplete ())
@@ -900,7 +923,7 @@
       return;
     }
   // TODO: NS_ASSERT (WifiPacketIsPending (AnimUid) == true);
-  AnimPacketInfo& pktInfo = pendingWifiPackets[AnimUid];
+  AnimPacketInfo& pktInfo = m_pendingWifiPackets[AnimUid];
   AnimRxInfo pktrxInfo = pktInfo.GetRxInfo (ndev);
   if (pktrxInfo.IsPhyRxComplete ())
     {
@@ -944,7 +967,7 @@
   uint64_t AnimUid = GetAnimUidFromPacket (p);
   NS_LOG_INFO ("WimaxRxTrace for packet:" << AnimUid);
   NS_ASSERT (WimaxPacketIsPending (AnimUid) == true);
-  AnimPacketInfo& pktInfo = pendingWimaxPackets[AnimUid];
+  AnimPacketInfo& pktInfo = m_pendingWimaxPackets[AnimUid];
   pktInfo.ProcessRxBegin (ndev, Simulator::Now ());
   pktInfo.ProcessRxEnd (ndev, Simulator::Now () + Seconds (0.001), UpdatePosition (n));
   //TODO 0.001 is used until Wimax implements RxBegin and RxEnd traces
@@ -986,7 +1009,7 @@
       NS_LOG_WARN ("LteRxTrace: unknown Uid");
       return;
     }
-  AnimPacketInfo& pktInfo = pendingLtePackets[AnimUid];
+  AnimPacketInfo& pktInfo = m_pendingLtePackets[AnimUid];
   pktInfo.ProcessRxBegin (ndev, Simulator::Now ());
   pktInfo.ProcessRxEnd (ndev, Simulator::Now () + Seconds (0.001), UpdatePosition (n));
   //TODO 0.001 is used until Lte implements RxBegin and RxEnd traces
@@ -1031,7 +1054,7 @@
       NS_LOG_WARN ("Unknown Uid, but adding Csma Packet anyway");
     }
   // TODO: NS_ASSERT (CsmaPacketIsPending (AnimUid) == true);
-  AnimPacketInfo& pktInfo = pendingCsmaPackets[AnimUid];
+  AnimPacketInfo& pktInfo = m_pendingCsmaPackets[AnimUid];
   pktInfo.m_lbTx = Simulator::Now ().GetSeconds ();
 }
 
@@ -1050,8 +1073,8 @@
       return;
     }
   // TODO: NS_ASSERT (CsmaPacketIsPending (AnimUid) == true);
-  AnimPacketInfo& pktInfo = pendingCsmaPackets[AnimUid];
-  pendingCsmaPackets[AnimUid].ProcessRxBegin (ndev, Simulator::Now ());
+  AnimPacketInfo& pktInfo = m_pendingCsmaPackets[AnimUid];
+  m_pendingCsmaPackets[AnimUid].ProcessRxBegin (ndev, Simulator::Now ());
   pktInfo.ProcessRxEnd (ndev, Simulator::Now (), UpdatePosition (n));
   NS_LOG_INFO ("CsmaPhyRxEndTrace for packet:" << AnimUid);
 }
@@ -1074,7 +1097,7 @@
       return;
     }
   // TODO: NS_ASSERT (CsmaPacketIsPending (AnimUid) == true);
-  AnimPacketInfo& pktInfo = pendingCsmaPackets[AnimUid];
+  AnimPacketInfo& pktInfo = m_pendingCsmaPackets[AnimUid];
   AnimRxInfo pktrxInfo = pktInfo.GetRxInfo (ndev);
   if (pktrxInfo.IsPhyRxComplete ())
     {
@@ -1103,7 +1126,7 @@
   UpdatePosition (n,v);
   RecalcTopoBounds (v);
   std::ostringstream oss; 
-  oss << GetXMLOpen_topology (topo_minX,topo_minY,topo_maxX,topo_maxY);
+  oss << GetXMLOpen_topology (m_topoMinX, m_topoMinY, m_topoMaxX, m_topoMaxY);
   oss << GetXMLOpenClose_node (0,n->GetId (),v.x,v.y);
   oss << GetXMLClose ("topology");
   WriteN (m_fHandle, oss.str ());
@@ -1131,7 +1154,7 @@
     return;
   std::vector <Ptr <Node> > MovedNodes = RecalcTopoBounds ();
   std::ostringstream oss;
-  oss << GetXMLOpen_topology (topo_minX, topo_minY, topo_maxX, topo_maxY);
+  oss << GetXMLOpen_topology (m_topoMinX, m_topoMinY, m_topoMaxX, m_topoMaxY);
   for (uint32_t i = 0; i < MovedNodes.size (); i++)
     {
       Ptr <Node> n = MovedNodes [i];
@@ -1148,7 +1171,7 @@
       PurgePendingWimax ();
       PurgePendingLte ();
       PurgePendingCsma ();
-      Simulator::Schedule (mobilitypollinterval, &AnimationInterface::MobilityAutoCheck, this);
+      Simulator::Schedule (m_mobilityPollInterval, &AnimationInterface::MobilityAutoCheck, this);
     }
 }
 
@@ -1159,6 +1182,12 @@
   return oss.str ();
 }
 
+uint64_t AnimationInterface::GetTracePktCount ()
+{
+  return m_currentPktCount;
+}
+
+
 // Helper to output a wireless packet.
 // For now, only the XML interface is supported
 
@@ -1204,6 +1233,7 @@
 
 void AnimationInterface::OutputWirelessPacket (Ptr<const Packet> p, AnimPacketInfo &pktInfo, AnimRxInfo pktrxInfo)
 {
+  StartNewTraceFile ();
   NS_ASSERT (m_xml);
   std::ostringstream oss;
   uint32_t nodeId =  0;
@@ -1226,6 +1256,7 @@
 
 void AnimationInterface::OutputCsmaPacket (Ptr<const Packet> p, AnimPacketInfo &pktInfo, AnimRxInfo pktrxInfo)
 {
+  StartNewTraceFile ();
   NS_ASSERT (m_xml);
   std::ostringstream oss;
   NS_ASSERT (pktInfo.m_txnd);
--- a/src/netanim/model/animation-interface.h	Tue May 22 16:40:24 2012 +0200
+++ b/src/netanim/model/animation-interface.h	Tue May 22 16:41:05 2012 +0200
@@ -52,6 +52,8 @@
 
 namespace ns3 {
 
+#define MAX_PKTS_PER_TRACE_FILE 100000
+
 /**
  * \defgroup netanim Netanim
  *
@@ -85,10 +87,16 @@
   /**
    * \brief Constructor
    * \param filename The Filename for the trace file used by the Animator
+   * \param maxPktsPerFile The maximum number of packets per trace file.
+	    AnimationInterface will create trace files with the following 
+            filenames : filename, filename-1, filename-2..., filename-N
+	    where each file contains packet info for 'maxPktPerFile' number of packets
    * \param usingXML Set to true if XML output traces are required
    *
    */
-  AnimationInterface (const std::string filename, bool usingXML = true);
+  AnimationInterface (const std::string filename, 
+	uint64_t maxPktsPerFile = MAX_PKTS_PER_TRACE_FILE, 
+	bool usingXML = true);
 
   /**
    * \brief Constructor
@@ -169,9 +177,10 @@
    * on prior calls to SetOutputFile, SetServerPort, or SetInternalAnimation.
    * Then creates the callbacks needed for the animator to start processing
    * packets.
-   *
+   * 
+   * \param restart True when restarting animation
    */
-  void StartAnimation ();
+  void StartAnimation (bool restart = false);
 
   /**
    * \brief Closes the interface to the animator.
@@ -269,6 +278,15 @@
   void EnablePacketMetadata (bool enable);
 
 
+  /**
+   *
+   * \brief Get trace file packet count (This used only for testing)
+   *
+   * returns Number of packets recorded in the current trace file
+   *
+   */
+  uint64_t GetTracePktCount ();
+
 
 private:
 #ifndef WIN32
@@ -280,12 +298,21 @@
   int  WriteN (SOCKET, const char*, uint32_t);
 #endif
   bool m_xml;      // True if xml format desired
-  Time mobilitypollinterval;
-  bool usingSockets;
-  uint16_t mport;
-  std::string outputfilename;
-  bool OutputFileSet;
-  bool ServerPortSet;
+  Time m_mobilityPollInterval;
+  bool m_usingSockets;
+  uint16_t m_port;
+  std::string m_outputFileName;
+  bool m_outputFileSet;
+  bool m_serverPortSet;
+  uint64_t gAnimUid ;    // Packet unique identifier used by Animtion
+  bool m_randomPosition;
+  AnimWriteCallback m_writeCallback;
+  bool m_started;
+  bool m_enablePacketMetadata; 
+  Time m_startTime;
+  Time m_stopTime;
+  uint64_t m_maxPktsPerFile;
+  std::string m_originalFileName;
 
   void DevTxTrace (std::string context,
                    Ptr<const Packet> p,
@@ -339,27 +366,26 @@
   void OutputCsmaPacket (Ptr<const Packet> p, AnimPacketInfo& pktInfo, AnimRxInfo pktrxInfo);
   void MobilityAutoCheck ();
   
-  uint64_t gAnimUid ;    // Packet unique identifier used by Animtion
 
-  std::map<uint64_t, AnimPacketInfo> pendingWifiPackets;
+  std::map<uint64_t, AnimPacketInfo> m_pendingWifiPackets;
   void AddPendingWifiPacket (uint64_t AnimUid, AnimPacketInfo&);
   bool WifiPacketIsPending (uint64_t AnimUid); 
 
-  std::map<uint64_t, AnimPacketInfo> pendingWimaxPackets;
+  std::map<uint64_t, AnimPacketInfo> m_pendingWimaxPackets;
   void AddPendingWimaxPacket (uint64_t AnimUid, AnimPacketInfo&);
   bool WimaxPacketIsPending (uint64_t AnimUid); 
 
-  std::map<uint64_t, AnimPacketInfo> pendingLtePackets;
+  std::map<uint64_t, AnimPacketInfo> m_pendingLtePackets;
   void AddPendingLtePacket (uint64_t AnimUid, AnimPacketInfo&);
   bool LtePacketIsPending (uint64_t AnimUid);
 
-  std::map<uint64_t, AnimPacketInfo> pendingCsmaPackets;
+  std::map<uint64_t, AnimPacketInfo> m_pendingCsmaPackets;
   void AddPendingCsmaPacket (uint64_t AnimUid, AnimPacketInfo&);
   bool CsmaPacketIsPending (uint64_t AnimUid);
 
   uint64_t GetAnimUidFromPacket (Ptr <const Packet>);
 
-  std::map<uint32_t, Vector> nodeLocation;
+  std::map<uint32_t, Vector> m_nodeLocation;
   Vector GetPosition (Ptr <Node> n);
   Vector UpdatePosition (Ptr <Node> n);
   Vector UpdatePosition (Ptr <Node> n, Vector v);
@@ -376,14 +402,8 @@
   void RecalcTopoBounds (Vector v);
   std::vector < Ptr <Node> > RecalcTopoBounds ();
 
-  bool randomPosition;
-  AnimWriteCallback m_writeCallback;
   void ConnectCallbacks ();
 
-  bool m_started;
-  bool m_enablePacketMetadata; 
-  Time m_startTime;
-  Time m_stopTime;
   
   std::map <std::string, uint32_t> m_macToNodeIdMap;
   bool IsInTimeWindow ();
@@ -393,14 +413,17 @@
   Ptr <NetDevice> GetNetDeviceFromContext (std::string context);
 
   static std::map <uint32_t, std::string> nodeDescriptions;
+  uint64_t m_currentPktCount;
+
+  void StartNewTraceFile();
 
   // XML helpers
   std::string GetPreamble (void);
   // Topology element dimensions
-  double topo_minX;
-  double topo_minY;
-  double topo_maxX;
-  double topo_maxY;
+  double m_topoMinX;
+  double m_topoMinY;
+  double m_topoMaxX;
+  double m_topoMaxY;
 
   std::string GetPacketMetadata (Ptr<const Packet> p);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/netanim/test/examples-to-run.py	Tue May 22 16:41:05 2012 +0200
@@ -0,0 +1,23 @@
+#! /usr/bin/env python
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+# A list of C++ examples to run in order to ensure that they remain
+# buildable and runnable over time.  Each tuple in the list contains
+#
+#     (example_name, do_run, do_valgrind_run).
+#
+# See test.py for more information.
+cpp_examples = [
+    ("dumbbell-animation", "True", "False"),
+    ("star-animation", "True", "False"),
+    ("grid-animation", "True", "False"),
+    ("wireless-animation", "True", "False"),
+]
+
+# A list of Python examples to run in order to ensure that they remain
+# runnable over time.  Each tuple in the list contains
+#
+#     (example_name, do_run).
+#
+# See test.py for more information.
+python_examples = []
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/netanim/test/netanim-test.cc	Tue May 22 16:41:05 2012 +0200
@@ -0,0 +1,118 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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: John Abraham <john.abraham@gatech.edu>
+ */
+
+#include <iostream>
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/internet-module.h"
+#include "ns3/point-to-point-module.h"
+#include "ns3/netanim-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/point-to-point-layout-module.h"
+
+namespace ns3 {
+
+class AnimationInterfaceTestCase : public TestCase
+{
+public:
+  /**
+   * \brief Constructor.
+   */
+  AnimationInterfaceTestCase ();
+  /**
+   * \brief Destructor.
+   */
+  virtual
+  ~AnimationInterfaceTestCase ();
+  /**
+   * \brief Run unit tests for this class.
+   * \return false if all tests have passed, false otherwise
+   */
+  virtual void
+  DoRun (void);
+
+};
+
+AnimationInterfaceTestCase::AnimationInterfaceTestCase () :
+  TestCase ("Verify AnimationInterface")
+{
+}
+
+AnimationInterfaceTestCase::~AnimationInterfaceTestCase ()
+{
+}
+void
+AnimationInterfaceTestCase::DoRun (void)
+{
+  NodeContainer nodes;
+  nodes.Create (2);
+  AnimationInterface::SetConstantPosition (nodes.Get (0), 0 , 10);
+  AnimationInterface::SetConstantPosition (nodes.Get (1), 1 , 10);
+
+  PointToPointHelper pointToPoint;
+  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
+
+  NetDeviceContainer devices;
+  devices = pointToPoint.Install (nodes);
+
+  InternetStackHelper stack;
+  stack.Install (nodes);
+
+  Ipv4AddressHelper address;
+  address.SetBase ("10.1.1.0", "255.255.255.0");
+
+  Ipv4InterfaceContainer interfaces = address.Assign (devices);
+
+  UdpEchoServerHelper echoServer (9);
+
+  ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
+  serverApps.Start (Seconds (1.0));
+  serverApps.Stop (Seconds (10.0));
+
+  UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);
+  echoClient.SetAttribute ("MaxPackets", UintegerValue (100));
+  echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
+  echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
+
+  ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
+  clientApps.Start (Seconds (2.0));
+  clientApps.Stop (Seconds (10.0));
+  std::string traceFileName = "netanim-test.xml";
+  AnimationInterface anim(traceFileName.c_str ());
+  Simulator::Run ();
+  NS_TEST_ASSERT_MSG_EQ (anim.GetTracePktCount (), 32, "Expected 32 packets traced");
+  FILE * fp = fopen (traceFileName.c_str (), "r");
+  NS_TEST_ASSERT_MSG_NE (fp, 0, "Trace file was not created");
+  fclose (fp);
+  unlink (traceFileName.c_str ());
+  Simulator::Destroy ();
+}
+
+static class AnimationInterfaceTestSuite : public TestSuite
+{
+public:
+  AnimationInterfaceTestSuite () :
+    TestSuite ("animation-interface", UNIT)
+  {
+    AddTestCase (new AnimationInterfaceTestCase ());
+  }
+} g_animationInterfaceTestSuite;
+
+} // namespace ns3
--- a/src/netanim/wscript	Tue May 22 16:40:24 2012 +0200
+++ b/src/netanim/wscript	Tue May 22 16:41:05 2012 +0200
@@ -14,6 +14,10 @@
 			  'model/animation-interface.cc',
 			  'helper/animation-interface-helper.cc',
 		        ]
+    	netanim_test = bld.create_ns3_module_test_library('netanim')
+    	netanim_test.source = [
+        	'test/netanim-test.cc',
+        ]
 
 	headers = bld.new_task_gen (features=['ns3header'])
 	headers.module = 'netanim'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/propagation/examples/jakes-propagation-model-example.cc	Tue May 22 16:41:05 2012 +0200
@@ -0,0 +1,98 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Telum (www.telum.ru)
+ *
+ * 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: Kirill Andreev <andreev@telum.ru>
+ */
+#include "ns3/core-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/jakes-propagation-loss-model.h"
+#include <vector>
+#include <math.h>
+
+using namespace ns3;
+/**
+ * \ingroup propagation
+ * \brief Constructs a JakesPropagationlossModel and print the loss value as a function of time into std::cout.
+ * Distribution and correlation statistics is compared woth a theoretical ones using R package (http://www.r-project.org/).
+ * Scripts are presented within comments.
+ */
+class JakesPropagationExample
+{
+public:
+  JakesPropagationExample ();
+  ~JakesPropagationExample ();
+private:
+  Ptr<PropagationLossModel> m_loss;
+  Ptr<MobilityModel> m_firstMobility;
+  Ptr<MobilityModel> m_secondMobility;
+  Time m_step;
+  EventId m_nextEvent;
+  void Next ();
+
+};
+
+JakesPropagationExample::JakesPropagationExample () :
+  m_step (Seconds (0.0002)) //1/5000 part of the second
+{
+  m_loss = CreateObject<JakesPropagationLossModel> ();
+  m_firstMobility = CreateObject<ConstantPositionMobilityModel> ();
+  m_secondMobility = CreateObject<ConstantPositionMobilityModel> ();
+  m_firstMobility->SetPosition (Vector (0, 0, 0));
+  m_secondMobility->SetPosition (Vector (10, 0, 0));
+  m_nextEvent = Simulator::Schedule (m_step, &JakesPropagationExample::Next, this);
+}
+
+JakesPropagationExample::~JakesPropagationExample ()
+{
+}
+
+void JakesPropagationExample::Next ()
+{
+  m_nextEvent = Simulator::Schedule (m_step, &JakesPropagationExample::Next, this);
+  std::cout << Simulator::Now ().GetMilliSeconds () << " " << m_loss->CalcRxPower (0, m_firstMobility, m_secondMobility) << std::endl;
+}
+
+int main (int argc, char *argv[])
+{
+  Config::SetDefault ("ns3::JakesProcess::NumberOfOscillators", UintegerValue (100));
+  CommandLine cmd;
+  cmd.Parse (argc, argv);
+  JakesPropagationExample example;
+  Simulator::Stop (Seconds (1000));
+  Simulator::Run ();
+  Simulator::Destroy ();
+  /*
+   * R script for plotting a distribution:
+   data<-read.table ("data")
+   rayleigh<-(rnorm(1e6)^2+rnorm(1e6)^2)/2
+   qqplot(10*log10(rayleigh), data$V2, main="QQ-plot for improved Jakes model", xlab="Reference Rayleigh distribution [power, dB]", ylab="Sum-of-sinusoids distribution [power, dB]", xlim=c(-45, 10), ylim=c(-45, 10))
+   lines (c(-50, 50), c(-50, 50))
+   abline (v=-50:50*2, h=-50:50*2, col="light grey")
+   */
+
+  /*
+   * R script to plot autocorrelation function:
+   # Read amplitude distribution:
+   data<-10^(read.table ("data")$V2/20)
+   x<-1:2000/10
+   acf (data, lag.max=200, main="Autocorrelation function of the improved Jakes model", xlab="Time x200 microseconds ", ylab="Autocorrelation")
+   # If we have a delta T = 1/5000 part of the second and doppler freq = 80 Hz
+   lines (x, besselJ(x*80*2*pi/5000, 0)^2)
+   abline (h=0:10/10, col="light grey")
+   */
+  return 0;
+}
--- a/src/propagation/examples/main-propagation-loss.cc	Tue May 22 16:40:24 2012 +0200
+++ b/src/propagation/examples/main-propagation-loss.cc	Tue May 22 16:41:05 2012 +0200
@@ -249,7 +249,7 @@
     Ptr<JakesPropagationLossModel> jakes = CreateObject<JakesPropagationLossModel> ();
 
     // doppler frequency shift for 5.15 GHz at 100 km/h
-    jakes->SetAttribute ("DopplerFreq", DoubleValue (477.9));
+    Config::SetDefault ("ns3::JakesProcess::DopplerFrequencyHz", DoubleValue (477.9));
 
     Gnuplot plot = TestDeterministicByTime (jakes, Seconds (0.001), Seconds (1.0));
     plot.SetTitle ("ns3::JakesPropagationLossModel (with 477.9 Hz shift and 1 millisec resolution)");
@@ -260,7 +260,7 @@
     Ptr<JakesPropagationLossModel> jakes = CreateObject<JakesPropagationLossModel> ();
 
     // doppler frequency shift for 5.15 GHz at 100 km/h
-    jakes->SetAttribute ("DopplerFreq", DoubleValue (477.9));
+    Config::SetDefault ("ns3::JakesProcess::DopplerFrequencyHz", DoubleValue (477.9));
 
     Gnuplot plot = TestDeterministicByTime (jakes, Seconds (0.0001), Seconds (0.1));
     plot.SetTitle ("ns3::JakesPropagationLossModel (with 477.9 Hz shift and 0.1 millisec resolution)");
--- a/src/propagation/examples/wscript	Tue May 22 16:40:24 2012 +0200
+++ b/src/propagation/examples/wscript	Tue May 22 16:41:05 2012 +0200
@@ -8,4 +8,9 @@
                                  ['core', 'mobility', 'config-store', 'tools', 'propagation'])
     obj.source = 'main-propagation-loss.cc'
 
+    obj = bld.create_ns3_program('jakes-propagation-model-example',
+                                 ['core', 'propagation'])
+    obj.source = 'jakes-propagation-model-example.cc'
 
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/propagation/model/jakes-process.cc	Tue May 22 16:41:05 2012 +0200
@@ -0,0 +1,134 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Telum (www.telum.ru)
+ *
+ * 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: Kirill Andreev <andreev@telum.ru>, Alexander Sofronov <sofronov@telum.ru>
+ */
+
+#include "jakes-process.h"
+#include "ns3/random-variable.h"
+#include "ns3/simulator.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+const double JakesProcess::PI = 3.14159265358979323846;
+
+/// Represents a single oscillator
+JakesProcess::Oscillator::Oscillator (std::complex<double> amplitude, double initialPhase, double omega) :
+  m_amplitude (amplitude),
+  m_phase (initialPhase),
+  m_omega (omega)
+{}
+
+std::complex<double>
+JakesProcess::Oscillator::GetValueAt (Time at) const
+{
+  return (m_amplitude * cos (at.GetSeconds () * m_omega + m_phase));
+}
+
+NS_OBJECT_ENSURE_REGISTERED (JakesProcess);
+
+TypeId
+JakesProcess::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::JakesProcess")
+    .SetParent<Object> ()
+    .AddConstructor<JakesProcess> ()
+    .AddAttribute ("DopplerFrequencyHz", "Corresponding doppler frequency[Hz]",
+                   DoubleValue (80),
+                   MakeDoubleAccessor (&JakesProcess::SetDopplerFrequencyHz),
+                   MakeDoubleChecker<double> (0.0, 1e4))
+    .AddAttribute ("NumberOfOscillators", "The number of oscillators",
+                   UintegerValue (20),
+                   MakeUintegerAccessor (&JakesProcess::SetNOscillators),
+                   MakeUintegerChecker<unsigned int> (4, 1000))
+  ;
+  return tid;
+}
+
+void
+JakesProcess::SetNOscillators (unsigned int nOscillators)
+{
+  m_nOscillators = nOscillators;
+  if (m_omegaDopplerMax != 0)
+    {
+      ConstructOscillators ();
+    }
+}
+
+void
+JakesProcess::SetDopplerFrequencyHz (double dopplerFrequencyHz)
+{
+  m_omegaDopplerMax = 2 * dopplerFrequencyHz * PI;
+  if (m_nOscillators != 0)
+    {
+      ConstructOscillators ();
+    }
+}
+
+void
+JakesProcess::ConstructOscillators ()
+{
+  // Initial phase is common for all oscillators:
+  double phi = UniformVariable (-PI, PI).GetValue ();
+  // Theta is common for all oscillatoer:
+  double theta = UniformVariable (-PI, PI).GetValue ();
+  for (unsigned int i = 0; i < m_nOscillators; i++)
+    {
+      unsigned int n = i + 1;
+      /// 1. Rotation speed
+      /// 1a. Initiate \f[ \alpha_n = \frac{2\pi n - \pi + \theta}{4M},  n=1,2, \ldots,M\f], n is oscillatorNumber, M is m_nOscillators
+      double alpha = (2.0 * PI * n - PI + theta) / (4.0 * m_nOscillators);
+      /// 1b. Initiate rotation speed:
+      double omega = m_omegaDopplerMax * cos (alpha);
+      /// 2. Initiate complex amplitude:
+      double psi = UniformVariable (-PI, PI).GetValue ();
+      std::complex<double> amplitude = std::complex<double> (cos (psi), sin (psi)) * 2.0 / sqrt (m_nOscillators);
+      /// 3. Construct oscillator:
+      m_oscillators.push_back (Oscillator (amplitude, phi, omega)); 
+    }
+}
+
+JakesProcess::JakesProcess () :
+  m_omegaDopplerMax (0),
+  m_nOscillators (0)
+{}
+
+JakesProcess::~JakesProcess()
+{
+  m_oscillators.clear ();
+}
+
+std::complex<double>
+JakesProcess::GetComplexGain () const
+{
+  std::complex<double> sumAplitude = std::complex<double> (0, 0);
+  for (unsigned int i = 0; i < m_oscillators.size (); i++)
+    {
+      sumAplitude += m_oscillators[i].GetValueAt (Now ());
+    }
+  return sumAplitude;
+}
+
+double
+JakesProcess::GetChannelGainDb () const
+{
+  std::complex<double> complexGain = GetComplexGain ();
+  return (10 * log10 ((pow (complexGain.real (), 2) + pow (complexGain.imag (), 2)) / 2));
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/propagation/model/jakes-process.h	Tue May 22 16:41:05 2012 +0200
@@ -0,0 +1,92 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Telum (www.telum.ru)
+ *
+ * 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: Kirill Andreev <andreev@telum.ru>, Alexander Sofronov <sofronov@telum.ru>
+ */
+#ifndef DOPPLER_PROCESS_H
+#define DOPPLER_PROCESS_H
+
+#include "ns3/object.h"
+#include "ns3/nstime.h"
+#include <complex>
+
+namespace ns3
+{
+/**
+ * \ingroup fading
+ *
+ * \brief Implementation for a single path Stationary Jakes propagation loss model.
+ *
+ * The Jakes propagation loss model implemented here is
+ * described in [1].
+ *
+ * We consider one transmitter - receiver pair and calculate
+ * the complex coefficients for this case as follow:
+ * \f[ X(t)=X_c(t) + j X_s(t)\f]
+ * \f[ X_c(t) = \frac{2}{\sqrt{M}}\sum_{n=1}^{M}\cos(\psi_n)\cos(\omega_d t\cos(\alpha_n)+\phi_n)\f]
+ * \f[ X_s(t) = \frac{2}{\sqrt{M}}\sum_{n=1}^{M}\sin(\psi_n)\cos(\omega_d t\cos(\alpha_n)+\phi_n)\f]
+ * with
+ * \f[ \alpha_n = \frac{2\pi n - \pi + \theta}{4M},  n=1,2, \ldots,M\f]
+ * where
+ *\f$\theta\f$, \f$\phi\f$, and \f$\psi_n\f$ are statically independent and uniformly distributed over \f$[-\pi, \pi)\f$ for all \f$n\f$.
+ *
+ *
+ * [1] Y. R. Zheng and C. Xiao, "Simulation Models With Correct
+ * Statistical Properties for Rayleigh Fading Channel", IEEE
+ * Trans. on Communications, Vol. 51, pp 920-928, June 2003
+ */
+class JakesProcess : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+  JakesProcess ();
+  virtual ~JakesProcess();
+  std::complex<double> GetComplexGain () const;
+  /// Get Channel gain [dB]
+  double GetChannelGainDb () const;
+private:
+  /// Represents a single oscillator
+  struct Oscillator
+  {
+    /// Initiate oscillator with complex amplitude, initial phase and rotation speed
+    Oscillator (std::complex<double> amplitude, double initialPhase, double omega);
+    // Get the complex amplitude at moment \param t
+    std::complex<double> GetValueAt (Time t) const;
+    /// Complex number \f[Re=\cos(\psi_n), Im = i\sin(\psi_n)]
+    std::complex<double> m_amplitude;
+    /// Phase \f[\phi_n] of the oscillator
+    double m_phase;
+    /// Rotation speed of the oscillator \f[\omega_d \cos(\alpha_n)]
+    double m_omega;
+  };
+  /// PI Constant
+  static const double PI;
+private:
+  void SetNOscillators (unsigned int nOscillators);
+  void SetDopplerFrequencyHz (double dopplerFrequencyHz);
+  void ConstructOscillators ();
+private:
+  /// Vector of oscillators:
+  std::vector<Oscillator> m_oscillators;
+  ///\name Attributes:
+  ///\{
+  double m_omegaDopplerMax;
+  unsigned int m_nOscillators;
+  ///\}
+};
+} // namespace ns3
+#endif // DOPPLER_PROCESS_H
--- a/src/propagation/model/jakes-propagation-loss-model.cc	Tue May 22 16:40:24 2012 +0200
+++ b/src/propagation/model/jakes-propagation-loss-model.cc	Tue May 22 16:41:05 2012 +0200
@@ -1,9 +1,9 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2005,2006,2007 INRIA
+ * Copyright (c) 2012 Telum (www.telum.ru)
  *
  * 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 
+ * 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,
@@ -15,246 +15,37 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Author: Federico Maguolo <maguolof@dei.unipd.it>
+ * Author: Kirill Andreev <andreev@telum.ru>
  */
 
-#include "ns3/simulator.h"
-#include "ns3/uinteger.h"
-#include "ns3/double.h"
-#include "ns3/random-variable.h"
-#include "ns3/mobility-model.h"
-#include "ns3/log.h"
 #include "jakes-propagation-loss-model.h"
-#include <math.h>
 
-NS_LOG_COMPONENT_DEFINE ("Jakes");
-
-namespace ns3 {
-
+namespace ns3
+{
 NS_OBJECT_ENSURE_REGISTERED (JakesPropagationLossModel);
 
-class JakesPropagationLossModel::PathCoefficients 
-{
-public:
-  PathCoefficients (Ptr<const JakesPropagationLossModel> jakes,
-                    Ptr<MobilityModel> receiver, 
-                    uint8_t nRays, 
-                    uint8_t nOscillators);
-  ~PathCoefficients ();
-  double GetLoss (Ptr<const JakesPropagationLossModel> jakes);
-  Ptr<MobilityModel> GetReceiver (void);
-private:
-  void DoConstruct (Ptr<const JakesPropagationLossModel> jakes);
-  Ptr<MobilityModel> m_receiver;
-  uint8_t m_nOscillators;
-  uint8_t m_nRays;
-  double **m_phases;
-  Time m_lastUpdate;
-};
-
-
-JakesPropagationLossModel::PathCoefficients::PathCoefficients (Ptr<const JakesPropagationLossModel> jakes, 
-                                                               Ptr<MobilityModel> receiver,
-                                                               uint8_t nRays,
-                                                               uint8_t nOscillators)
-  : m_receiver (receiver),
-    m_nOscillators (nOscillators),
-    m_nRays (nRays)
-{
-  DoConstruct (jakes);
-}
-
-JakesPropagationLossModel::PathCoefficients::~PathCoefficients ()
-{
-  for (uint8_t i = 0; i < m_nRays; i++) 
-    {
-      delete [] m_phases[i];
-    }
-  delete [] m_phases;
-}
+JakesPropagationLossModel::JakesPropagationLossModel()
+{}
 
-void
-JakesPropagationLossModel::PathCoefficients::DoConstruct (Ptr<const JakesPropagationLossModel> jakes)
-{
-  m_phases = new double*[m_nRays];
-  for (uint8_t i = 0; i < m_nRays; i++) 
-    {
-      m_phases[i] = new double[m_nOscillators + 1];
-      for (uint8_t j = 0; j <= m_nOscillators; j++) 
-        {
-          m_phases[i][j] = 2.0 * JakesPropagationLossModel::PI * jakes->m_variable.GetValue ();
-        }
-    }
-  m_lastUpdate = Simulator::Now ();
-}
-
-Ptr<MobilityModel>
-JakesPropagationLossModel::PathCoefficients::GetReceiver ()
-{
-  return m_receiver;
-}
-
-double
-JakesPropagationLossModel::PathCoefficients::GetLoss (Ptr<const JakesPropagationLossModel> jakes)
-{
-  uint16_t N = 4 * m_nOscillators + 2;
-  Time interval = Simulator::Now () - m_lastUpdate;
-  ComplexNumber coef= { 0.0, 0.0};
-  ComplexNumber fading;
-  double norm = 0.0;
-  for (uint8_t i = 0; i < m_nRays; i++) 
-    {
-      fading.real = 0.0;
-      fading.imag = 0.0;
-      for (uint8_t j = 0; j <= m_nOscillators; j++) 
-        {
-          m_phases[i][j] += 2.0 * JakesPropagationLossModel::PI * 
-            cos (2.0 * JakesPropagationLossModel::PI * j / N) * jakes->m_fd * interval.GetSeconds ();
-          m_phases[i][j] -= 2.0 * JakesPropagationLossModel::PI * 
-            floor (m_phases[i][j] / 2.0 / JakesPropagationLossModel::PI);
-          fading.real += jakes->m_amp[j].real * cos (m_phases[i][j]);
-          fading.imag += jakes->m_amp[j].imag * cos (m_phases[i][j]);
-          norm += sqrt (pow (jakes->m_amp[j].real, 2) + pow (jakes->m_amp[j].imag, 2));
-        }
-      coef.real += fading.real;
-      coef.imag += fading.imag;
-    }
-  m_lastUpdate = Simulator::Now ();
-  double k = sqrt (pow (coef.real, 2) + pow (coef.imag, 2)) / norm;
-  NS_LOG_DEBUG ("Jakes coef "<< k << " (" << 10 * log10 (k) << "dB)");
-  return 10 * log10 (k);
-}
-
-const double JakesPropagationLossModel::PI = 3.14159265358979323846;
+JakesPropagationLossModel::~JakesPropagationLossModel()
+{}
 
 TypeId
-JakesPropagationLossModel::GetTypeId (void)
+JakesPropagationLossModel::GetTypeId ()
 {
   static TypeId tid = TypeId ("ns3::JakesPropagationLossModel")
     .SetParent<PropagationLossModel> ()
     .AddConstructor<JakesPropagationLossModel> ()
-    .AddAttribute ("NumberOfRaysPerPath",
-                   "The number of rays to use by default for compute the fading coeficent for a given path (default is 1)",
-                   UintegerValue (1),
-                   MakeUintegerAccessor (&JakesPropagationLossModel::SetNRays,
-                                         &JakesPropagationLossModel::GetNRays),
-                   MakeUintegerChecker<uint8_t> ())
-    .AddAttribute ("NumberOfOscillatorsPerRay",
-                   "The number of oscillators to use by default for compute the coeficent for a given ray of a given "
-                   "path (default is 4)",
-                   UintegerValue (4),
-                   MakeUintegerAccessor (&JakesPropagationLossModel::SetNOscillators,
-                                         &JakesPropagationLossModel::GetNOscillators),
-                   MakeUintegerChecker<uint8_t> ())
-    .AddAttribute ("DopplerFreq",
-                   "The doppler frequency in Hz (f_d = v / lambda = v * f / c), the default is 0)",
-                   DoubleValue (0.0),
-                   MakeDoubleAccessor (&JakesPropagationLossModel::m_fd),
-                   MakeDoubleChecker<double> ())
-    .AddAttribute ("Distribution",
-                   "The distribution to choose the initial phases.",
-                   RandomVariableValue (ConstantVariable (1.0)),
-                   MakeRandomVariableAccessor (&JakesPropagationLossModel::m_variable),
-                   MakeRandomVariableChecker ())
   ;
   return tid;
 }
 
-JakesPropagationLossModel::JakesPropagationLossModel ()
-  : m_amp (0),
-    m_nRays (0),
-    m_nOscillators (0)
-{
-}
-
-JakesPropagationLossModel::~JakesPropagationLossModel ()
-{
-  delete [] m_amp;
-  for (PathsList::reverse_iterator i = m_paths.rbegin (); i != m_paths.rend (); i++)
-    {
-      PathsSet *ps = *i;
-      for (DestinationList::iterator r = ps->receivers.begin (); r != ps->receivers.end (); r++)
-        {
-          PathCoefficients *pc = *r;
-          delete pc;
-        }
-      ps->sender = 0;
-      ps->receivers.clear ();
-      delete ps;
-    }
-  m_paths.clear ();
-}
-
-void
-JakesPropagationLossModel::SetNRays (uint8_t nRays)
-{
-  m_nRays = nRays;
-}
-
-void
-JakesPropagationLossModel::SetNOscillators (uint8_t nOscillators)
-{
-  m_nOscillators = nOscillators;
-  delete [] m_amp;
-  uint16_t N = 4 * m_nOscillators + 2;
-  m_amp = new ComplexNumber[m_nOscillators + 1];
-  m_amp[0].real = 2.0 * sqrt (2.0 / N) * cos (PI / 4.0);
-  m_amp[0].imag = 2.0 * sqrt (2.0 / N) * sin (PI / 4.0);
-  for (uint8_t i = 1; i <= m_nOscillators; i++) 
-    {
-      double beta = PI * (double)i / m_nOscillators;
-      m_amp[i].real = 4.0 * cos (beta) / sqrt (N);
-      m_amp[i].imag = 4.0 * sin (beta) / sqrt (N);
-    }
-}
-
-uint8_t 
-JakesPropagationLossModel::GetNRays (void) const
-{
-  return m_nRays;
-}
-uint8_t 
-JakesPropagationLossModel::GetNOscillators (void) const
-{
-  return m_nOscillators;
-}
-
-
-double 
+double
 JakesPropagationLossModel::DoCalcRxPower (double txPowerDbm,
                                           Ptr<MobilityModel> a,
                                           Ptr<MobilityModel> b) const
 {
-  PathsList::iterator i = m_paths.end ();
-  while (i != m_paths.begin ()) 
-    {
-      i--;
-      PathsSet *ps = *i;
-      if (ps->sender == a) 
-        {
-          m_paths.erase (i);
-          m_paths.push_back (ps);
-          for (DestinationList::iterator r = ps->receivers.begin (); r != ps->receivers.end (); r++) 
-            {
-              PathCoefficients *pc = *r;
-              if (pc->GetReceiver () == b) 
-                {
-                  ps->receivers.erase (r);
-                  ps->receivers.push_back (pc);
-                  return txPowerDbm + pc->GetLoss (this);
-                }
-            }
-          PathCoefficients *pc = new PathCoefficients (this, b, m_nRays, m_nOscillators);
-          ps->receivers.push_back (pc);
-          return txPowerDbm + pc->GetLoss (this);
-        }
-    }
-  PathsSet *ps = new PathsSet;
-  ps->sender = a;
-  PathCoefficients *pc = new PathCoefficients (this, b, m_nRays, m_nOscillators);
-  ps->receivers.push_back (pc);
-  m_paths.push_back (ps);
-  return txPowerDbm + pc->GetLoss (this);
+  return txPowerDbm + m_propagationCache.GetPathData (a, b, 0 /**Spectrum model uid is not used in PropagationLossModel*/)->GetChannelGainDb ();
 }
 
 } // namespace ns3
--- a/src/propagation/model/jakes-propagation-loss-model.h	Tue May 22 16:40:24 2012 +0200
+++ b/src/propagation/model/jakes-propagation-loss-model.h	Tue May 22 16:41:05 2012 +0200
@@ -1,9 +1,9 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2005,2006,2007 INRIA
+ * Copyright (c) 2012 Telum (www.telum.ru)
  *
  * 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 
+ * 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,
@@ -15,125 +15,41 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Author: Federico Maguolo <maguolof@dei.unipd.it>
+ * Author: Kirill Andreev <andreev@telum.ru>
  */
-#ifndef PROPAGATION_JAKES_MODEL_H
-#define PROPAGATION_JAKES_MODEL_H
+#ifndef JAKES_STATIONARY_LOSS_MODEL_H
+#define JAKES_STATIONARY_LOSS_MODEL_H
 
-#include "ns3/nstime.h"
-#include "propagation-loss-model.h"
+#include "ns3/propagation-loss-model.h"
+#include "ns3/propagation-cache.h"
+#include "ns3/jakes-process.h"
 
-namespace ns3 {
-
-
+namespace ns3
+{
 /**
  * \ingroup propagation
  *
- * \brief a Jakes propagation loss model
- *
- * The Jakes propagation loss model implemented here is 
- * described in [1].
- * 
- *
- * We call path the set of rays that depart from a given 
- * transmitter and arrive to a given receiver. For each ray
- * The complex coefficient is compute as follow:
- * \f[ u(t)=u_c(t) + j u_s(t)\f]
- * \f[ u_c(t) = \frac{2}{\sqrt{N}}\sum_{n=0}^{M}a_n\cos(\omega_n t+\phi_n)\f]
- * \f[ u_s(t) = \frac{2}{\sqrt{N}}\sum_{n=0}^{M}b_n\cos(\omega_n t+\phi_n)\f]
- * where
- * \f[ a_n=\left \{ \begin{array}{ll}
- * \sqrt{2}\cos\beta_0 & n=0 \\
- * 2\cos\beta_n & n=1,2,\ldots,M
- * \end{array}
- * \right .\f]
- * \f[ b_n=\left \{ \begin{array}{ll}
- * \sqrt{2}\sin\beta_0 & n=0 \\
- * 2\sin\beta_n & n=1,2,\ldots,M
- * \end{array}
- * \right .\f]
- * \f[ \beta_n=\left \{ \begin{array}{ll}
- * \frac{\pi}{4} & n=0 \\
- * \frac{\pi n}{M} & n=1,2,\ldots,M
- * \end{array}
- * \right .\f]
- * \f[ \omega_n=\left \{ \begin{array}{ll}
- * 2\pi f_d & n=0 \\
- * 2\pi f_d \cos\frac{2\pi n}{N} & n=1,2,\ldots,M
- * \end{array}
- * \right .\f]
- *
- * The parameter \f$f_d\f$ is the doppler frequency and \f$N=4M+2\f$ where
- * \f$M\f$ is the number of oscillators per ray.
- *
- * The attenuation coefficent of the path is the magnitude of the sum of 
- * all the ray coefficients. This attenuation coefficient could be greater than
- * \f$1\f$, hence it is divide by \f$ \frac{2N_r}{\sqrt{N}} \sum_{n+0}^{M}\sqrt{a_n^2 +b_n^2}\f$
- * where \f$N_r\f$ is the number of rays.
- *
- * The initail phases \f$\phi_i\f$ are random and they are choosen according 
- * to a given distribution.
- * 
- * [1] Y. R. Zheng and C. Xiao, "Simulation Models With Correct 
- * Statistical Properties for Rayleigh Fading Channel", IEEE
- * Trans. on Communications, Vol. 51, pp 920-928, June 2003
+ * \brief a  jakes narrowband propagation model.
+ * Symmetrical cache for JakesProcess
  */
+
 class JakesPropagationLossModel : public PropagationLossModel
 {
 public:
-  static TypeId GetTypeId (void);
+  static TypeId GetTypeId ();
   JakesPropagationLossModel ();
   virtual ~JakesPropagationLossModel ();
 
-  /**
-   * \param nRays Number of rays per path
-   *
-   * Set the number of rays for each path
-   */
-  void SetNRays (uint8_t nRays);
-  /**
-   * \param nOscillators Number of oscillators
-   *
-   * Set the number of oscillators to use to compute the ray coefficient
-   */
-  void SetNOscillators (uint8_t nOscillators);
-
-  uint8_t GetNRays (void) const;
-  uint8_t GetNOscillators (void) const;
+private:
+  double DoCalcRxPower (double txPowerDbm,
+                        Ptr<MobilityModel> a,
+                        Ptr<MobilityModel> b) const;
 
 private:
-  JakesPropagationLossModel (const JakesPropagationLossModel &o);
-  JakesPropagationLossModel & operator = (const JakesPropagationLossModel &o);
-  void DoConstruct (void);
-  virtual double DoCalcRxPower (double txPowerDbm,
-                                Ptr<MobilityModel> a,
-                                Ptr<MobilityModel> b) const;
-
-  class PathCoefficients;
-  struct ComplexNumber {
-    double real;
-    double imag;
-  };
-  friend class PathCoefficents;
-  typedef std::vector<PathCoefficients *> DestinationList;
-  struct PathsSet {
-    Ptr<MobilityModel> sender;
-    DestinationList receivers;
-  };
-  typedef std::vector<PathsSet *> PathsList;
-
-
-  static const double PI;
-  ComplexNumber* m_amp;
-  RandomVariable m_variable;
-  double m_fd;
-  mutable PathsList m_paths;
-  uint8_t m_nRays;
-  uint8_t m_nOscillators;
+  mutable PropagationCache<JakesProcess> m_propagationCache;
 };
 
 } // namespace ns3
 
-#endif /* PROPAGATION_JAKES_MODEL_H */
+#endif /* JAKES_STATIONARY_LOSS_MODEL_H */
 
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/propagation/model/propagation-cache.h	Tue May 22 16:41:05 2012 +0200
@@ -0,0 +1,86 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Telum (www.telum.ru)
+ *
+ * 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: Kirill Andreev <andreev@telum.ru>
+ */
+#ifndef PROPAGATION_CACHE_H_
+#define PROPAGATION_CACHE_H_
+
+#include "ns3/mobility-model.h"
+#include <map>
+
+namespace ns3
+{
+/**
+ * \ingroup propagation
+ * \brief Constructs a cache of objects, where each obect is responsible for a single propagation path loss calculations.
+ * Propagation path a-->b and b-->a is the same thing. Propagation path is identified by
+ * a couple of MobilityModels and a spectrum model UID
+ */
+template<class T>
+class PropagationCache
+{
+public:
+  PropagationCache () {};
+  ~PropagationCache () {};
+  Ptr<T> GetPathData (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b, uint32_t modelUid)
+  {
+    PropagationPathIdentifier key = PropagationPathIdentifier (a, b, modelUid);
+    typename PathCache::iterator it = m_pathCache.find (key);
+    if (it == m_pathCache.end ())
+      {
+        Ptr<T> newPath = CreateObject<T> ();
+        m_pathCache.insert (std::make_pair (key, newPath));
+        return newPath;
+      }
+    return it->second;
+  };
+private:
+  /// Each path is identified by
+  struct PropagationPathIdentifier
+  {
+    PropagationPathIdentifier (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b, uint32_t modelUid) :
+      m_srcMobility (a), m_dstMobility (b), m_spectrumModelUid (modelUid)
+    {};
+    Ptr<const MobilityModel> m_srcMobility;
+    Ptr<const MobilityModel> m_dstMobility;
+    uint32_t m_spectrumModelUid;
+    bool operator < (const PropagationPathIdentifier & other) const
+    {
+      if (m_spectrumModelUid != other.m_spectrumModelUid)
+        {
+          return m_spectrumModelUid < other.m_spectrumModelUid;
+        }
+      /// Links are supposed to be symmetrical!
+      if (std::min (m_dstMobility, m_srcMobility) != std::min (other.m_dstMobility, other.m_srcMobility))
+        {
+          return std::min (m_dstMobility, m_srcMobility) < std::min (other.m_dstMobility, other.m_srcMobility);
+        }
+      if (std::max (m_dstMobility, m_srcMobility) != std::max (other.m_dstMobility, other.m_srcMobility))
+        {
+          return std::max (m_dstMobility, m_srcMobility) < std::max (other.m_dstMobility, other.m_srcMobility);
+        }
+      return false;
+    }
+  };
+  typedef std::map<PropagationPathIdentifier, Ptr<T> > PathCache;
+private:
+  PathCache m_pathCache;
+};
+} // namespace ns3
+
+#endif // PROPAGATION_CACHE_H_
--- a/src/propagation/wscript	Tue May 22 16:40:24 2012 +0200
+++ b/src/propagation/wscript	Tue May 22 16:41:05 2012 +0200
@@ -7,6 +7,7 @@
         'model/propagation-delay-model.cc',
         'model/propagation-loss-model.cc',
         'model/jakes-propagation-loss-model.cc',
+        'model/jakes-process.cc',
         'model/cost231-propagation-loss-model.cc',
         'model/okumura-hata-propagation-loss-model.cc',
         'model/itu-r-1411-los-propagation-loss-model.cc',
@@ -29,6 +30,8 @@
         'model/propagation-delay-model.h',
         'model/propagation-loss-model.h',
         'model/jakes-propagation-loss-model.h',
+        'model/jakes-process.h',
+        'model/propagation-cache.h',
         'model/cost231-propagation-loss-model.h',
         'model/propagation-environment.h',
         'model/okumura-hata-propagation-loss-model.h',