merge
authorMarco Miozzo <marco.miozzo@cttc.es>
Thu, 22 Mar 2012 18:27:46 +0100
changeset 8695 4d1b067a4582
parent 8694 f5bacf58ab81 (current diff)
parent 8693 478733ab87b7 (diff)
child 8696 3979745b2835
merge
src/lte/doc/source/lte-rlc.rst
--- a/doc/models/Makefile	Thu Mar 22 18:14:08 2012 +0100
+++ b/doc/models/Makefile	Thu Mar 22 18:27:46 2012 +0100
@@ -17,6 +17,10 @@
 	source/internet-models.rst \
 	source/network.rst \
 	source/emulation-overview.rst \
+	$(SRC)/antenna/doc/source/antenna.rst \
+	$(SRC)/antenna/doc/source/antenna-design.rst \
+	$(SRC)/antenna/doc/source/antenna-user.rst \
+	$(SRC)/antenna/doc/source/antenna-testing.rst \
 	$(SRC)/aodv/doc/aodv.rst \
 	$(SRC)/applications/doc/applications.rst \
 	$(SRC)/bridge/doc/bridge.rst \
@@ -68,6 +72,7 @@
 SOURCEFIGS = \
 	figures/testbed.dia \
 	figures/emulated-channel.dia \
+	$(SRC)/antenna/doc/source/figures/antenna-coordinate-system.dia	\
 	$(SRC)/network/doc/packet.dia \
 	$(SRC)/network/doc/node.dia \
 	$(SRC)/network/doc/buffer.dia \
@@ -91,6 +96,10 @@
 	$(SRC)/lte/doc/source/figures/epc-data-flow-ul.dia \
 	$(SRC)/lte/doc/source/figures/lte-arch-data-rrc-pdcp-rlc.dia \
 	$(SRC)/lte/doc/source/figures/lte-epc-e2e-data-protocol-stack.dia \
+	$(SRC)/lte/doc/source/figures/MCS_2_test.eps \
+	$(SRC)/lte/doc/source/figures/MCS_12_test.eps \
+	$(SRC)/lte/doc/source/figures/MCS_14_test.eps \
+	$(SRC)/lte/doc/source/figures/lena-dual-stripe.eps \
 	$(SRC)/lte/doc/source/figures/lte-mcs-index.eps \
 	$(SRC)/lte/doc/source/figures/lenaThrTestCase1.eps \
 	$(SRC)/lte/doc/source/figures/lenaThrTestCase2.eps \
@@ -106,16 +115,32 @@
 	$(SRC)/lte/doc/source/figures/lte-rlc-data-retx-dl.eps \
 	$(SRC)/lte/doc/source/figures/lte-rlc-data-txon-ul.eps \
 	$(SRC)/lte/doc/source/figures/lte-rlc-data-retx-ul.eps \
+	$(SRC)/lte/doc/source/figures/fading_pedestrian.png \
 	$(SRC)/lte/doc/source/figures/fading_vehicular.png \
 	$(SRC)/lte/doc/source/figures/fading_urban_3kmph.png \
-	$(SRC)/lte/doc/source/figures/fading_pedestrian.png \
+	$(SRC)/lte/doc/source/figures/fading_pedestrian.pdf \
 	$(SRC)/lte/doc/source/figures/fading_vehicular.pdf \
 	$(SRC)/lte/doc/source/figures/fading_urban_3kmph.pdf \
-	$(SRC)/lte/doc/source/figures/fading_pedestrian.pdf \
+	$(SRC)/lte/doc/source/figures/MCS_1_4.pdf \
+	$(SRC)/lte/doc/source/figures/MCS_1_4.png \
+	$(SRC)/lte/doc/source/figures/MCS_5_8.pdf \
+	$(SRC)/lte/doc/source/figures/MCS_5_8.png \
+	$(SRC)/lte/doc/source/figures/MCS_9_12.pdf \
+	$(SRC)/lte/doc/source/figures/MCS_9_12.png \
+	$(SRC)/lte/doc/source/figures/MCS_13_16.pdf \
+	$(SRC)/lte/doc/source/figures/MCS_13_16.png \
+	$(SRC)/lte/doc/source/figures/MCS_17_20.pdf \
+	$(SRC)/lte/doc/source/figures/MCS_17_20.png \
+	$(SRC)/lte/doc/source/figures/MCS_21_24.pdf \
+	$(SRC)/lte/doc/source/figures/MCS_21_24.png \
+	$(SRC)/lte/doc/source/figures/MCS_25_27.pdf \
+	$(SRC)/lte/doc/source/figures/MCS_25_27.png \
 	$(SRC)/lte/doc/source/figures/lte-phy-interference.png \
 	$(SRC)/lte/doc/source/figures/lte-phy-interference.pdf \
 	$(SRC)/lte/doc/source/figures/helpers.png \
 	$(SRC)/lte/doc/source/figures/helpers.pdf \
+	$(SRC)/lte/doc/source/figures/miesm_scheme.pdf \
+	$(SRC)/lte/doc/source/figures/miesm_scheme.png \
 	$(SRC)/uan/doc/auvmobility-classes.dia \
 	$(SRC)/stats/doc/Stat-framework-arch.png \
 	$(SRC)/stats/doc/Wifi-default.png \
@@ -131,6 +156,7 @@
 	$(FIGURES)/node.eps \
 	$(FIGURES)/buffer.eps \
 	$(FIGURES)/sockets-overview.eps \
+	$(FIGURES)/antenna-coordinate-system.eps \
 	$(FIGURES)/internet-node-send.eps \
 	$(FIGURES)/internet-node-recv.eps \
 	$(FIGURES)/routing.eps \
@@ -150,6 +176,10 @@
 	$(FIGURES)/epc-data-flow-ul.eps \
 	$(FIGURES)/lte-arch-data-rrc-pdcp-rlc.eps \
 	$(FIGURES)/lte-epc-e2e-data-protocol-stack.eps \
+	$(FIGURES)/MCS_2_test.eps \
+	$(FIGURES)/MCS_12_test.eps \
+	$(FIGURES)/MCS_14_test.eps \
+	$(FIGURES)/lena-dual-stripe.eps \
 	$(FIGURES)/lte-mcs-index.eps \
 	$(FIGURES)/lenaThrTestCase1.eps \
 	$(FIGURES)/lenaThrTestCase2.eps \
--- a/doc/models/source/index.rst	Thu Mar 22 18:14:08 2012 +0100
+++ b/doc/models/source/index.rst	Thu Mar 22 18:27:46 2012 +0100
@@ -18,6 +18,7 @@
 
    organization
    animation
+   antenna
    aodv
    applications
    bridge
--- a/src/antenna/doc/source/antenna-design.rst	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/antenna/doc/source/antenna-design.rst	Thu Mar 22 18:27:46 2012 +0100
@@ -88,6 +88,23 @@
 pattern.
 
 
+
+ParabolicAntennaModel
++++++++++++++++++++++
+
+This model is based on the parabolic approximation of the main lobe radiation pattern. It is often used in the context of cellular system to model the radiation pattern of a cell sector, see for instance [R4-092042]_ and [Calcev]_. The antenna gain in dB is determined as:
+
+.. math::
+ 
+  g_{dB}(\phi, \theta) = -\min \left( 12 \left(\frac{\phi  - \phi_{0}}{\phi_{3dB}} \right)^2, A_{max} \right)
+
+where :math:`\phi_{0}` is the azimuthal orientation of the antenna
+(i.e., its direction of maximum gain), :math:`\phi_{3dB}` is its 3 dB
+beamwidth, and :math:`A_{max}` is the maximum attenuation in dB of the
+antenna. 
+
+
+
 References
 ++++++++++
 
@@ -96,3 +113,13 @@
 .. [Chunjian] Li Chunjian, "Efficient Antenna Patterns for
    Three-Sector WCDMA Systems", Master of Science Thesis, Chalmers
    University of Technology, Göteborg, Sweden, 2003
+
+.. [Calcev] George Calcev and Matt Dillon, "Antenna Tilt Control in
+   CDMA Networks", in Proc. of the 2nd Annual International Wireless
+   Internet Conference (WICON), 2006 
+
+.. [R4-092042]  3GPP TSG RAN WG4 (Radio) Meeting #51, R4-092042, Simulation
+   assumptions and parameters for FDD HeNB RF requirements.
+
+
+
--- a/src/antenna/doc/source/antenna-testing.rst	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/antenna/doc/source/antenna-testing.rst	Thu Mar 22 18:27:46 2012 +0100
@@ -54,6 +54,20 @@
 
 
 
+ParabolicAntennaModel
+------------------
+
+The unit test suite ``parabolic-antenna-model`` checks that the
+``ParabolicAntennaModel`` class works properly. Several test cases are
+provided that check for the antenna gain value calculated at different
+directions and for different values of the orientation, the maximum attenuation
+and the beamwidth. The reference gain is calculated by hand. Each
+test case passes if the reference gain in dB is equal to the value returned
+by ``ParabolicAntennaModel`` within a tolerance of 0.001, which accounts
+for the approximation done for the calculation of the reference
+values.
+
+
 
 
 
--- a/src/antenna/model/cosine-antenna-model.h	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/antenna/model/cosine-antenna-model.h	Thu Mar 22 18:27:46 2012 +0100
@@ -31,7 +31,7 @@
  * 
  * \brief Cosine Antenna Model 
  *
- * This class implements the cosine model as described in [1]
+ * This class implements the cosine model as described in:
  *
  * Li Chunjian, "Efficient Antenna Patterns for Three-Sector WCDMA Systems"
  *
@@ -60,7 +60,7 @@
 private:
 
   /**
-   * this is the variable "n" in [1]
+   * this is the variable "n" in the paper by Chunjian
    * 
    */
   double m_exponent; 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/antenna/model/parabolic-antenna-model.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -0,0 +1,117 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 CTTC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+
+#include <ns3/log.h>
+#include <ns3/double.h>
+#include <math.h>
+
+#include "antenna-model.h"
+#include "parabolic-antenna-model.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("ParabolicAntennaModel");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (ParabolicAntennaModel);
+
+
+TypeId 
+ParabolicAntennaModel::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::ParabolicAntennaModel")
+    .SetParent<AntennaModel> ()
+    .AddConstructor<ParabolicAntennaModel> ()
+    .AddAttribute ("Beamwidth",
+                   "The 3dB beamwidth (degrees)",
+                   DoubleValue (60),
+                   MakeDoubleAccessor (&ParabolicAntennaModel::SetBeamwidth,
+                                       &ParabolicAntennaModel::GetBeamwidth),
+                   MakeDoubleChecker<double> (0, 180))
+    .AddAttribute ("Orientation",
+                   "The angle (degrees) that expresses the orientation of the antenna on the x-y plane relative to the x axis",
+                   DoubleValue (0.0),
+                   MakeDoubleAccessor (&ParabolicAntennaModel::SetOrientation,
+                                       &ParabolicAntennaModel::GetOrientation),
+                   MakeDoubleChecker<double> (-360, 360))
+    .AddAttribute ("MaxAttenuation",
+                   "The maximum attenuation (dB) of the antenna radiation pattern.",
+                   DoubleValue (20.0),
+                   MakeDoubleAccessor (&ParabolicAntennaModel::m_maxAttenuation),
+                   MakeDoubleChecker<double> ())
+    ;
+  return tid;
+}
+
+void 
+ParabolicAntennaModel::SetBeamwidth (double beamwidthDegrees)
+{ 
+  NS_LOG_FUNCTION (this << beamwidthDegrees);
+  m_beamwidthRadians = DegreesToRadians (beamwidthDegrees);
+}
+
+double
+ParabolicAntennaModel::GetBeamwidth () const
+{
+  return RadiansToDegrees (m_beamwidthRadians);
+}
+
+void 
+ParabolicAntennaModel::SetOrientation (double orientationDegrees)
+{
+  NS_LOG_FUNCTION (this << orientationDegrees);
+  m_orientationRadians = DegreesToRadians (orientationDegrees);
+}
+
+double
+ParabolicAntennaModel::GetOrientation () const
+{
+  return RadiansToDegrees (m_orientationRadians);
+}
+
+double 
+ParabolicAntennaModel::GetGainDb (Angles a)
+{
+  NS_LOG_FUNCTION (this << a);
+  // azimuth angle w.r.t. the reference system of the antenna
+  double phi = a.phi - m_orientationRadians;
+
+  // make sure phi is in (-pi, pi]
+  while (phi <= -M_PI)
+    {
+      phi += M_PI+M_PI;
+    }
+  while (phi > M_PI)
+    {
+      phi -= M_PI+M_PI;
+    }
+
+  NS_LOG_LOGIC ("phi = " << phi );
+
+  double gainDb = -std::min (12 * pow (phi / m_beamwidthRadians, 2), m_maxAttenuation);
+  
+  NS_LOG_LOGIC ("gain = " << gainDb);
+  return gainDb;
+}
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/antenna/model/parabolic-antenna-model.h	Thu Mar 22 18:27:46 2012 +0100
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 CTTC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#ifndef PARABOLIC_ANTENNA_MODEL_H
+#define PARABOLIC_ANTENNA_MODEL_H
+
+
+#include <ns3/object.h>
+#include <ns3/antenna-model.h>
+
+namespace ns3 {
+
+/**
+ * 
+ * \brief  Antenna model based on a parabolic approximation of the main lobe radiation pattern.
+ *
+ * This class implements the parabolic model as described in some 3GPP document, e.g., R4-092042
+ *
+ * A similar model appears in 
+ *
+ * George Calcev and Matt Dillon, "Antenna Tilt Control in CDMA Networks"
+ * in Proc. of the 2nd Annual International Wireless Internet Conference (WICON), 2006
+ *
+ * though the latter addresses also the elevation plane, which the present model doesn't.
+ *
+ *
+ */
+class ParabolicAntennaModel : public AntennaModel
+{
+public:
+
+  // inherited from Object
+  static TypeId GetTypeId ();
+
+  // inherited from AntennaModel
+  virtual double GetGainDb (Angles a);
+
+
+  // attribute getters/setters
+  void SetBeamwidth (double beamwidthDegrees);
+  double GetBeamwidth () const;
+  void SetOrientation (double orientationDegrees);
+  double GetOrientation () const;
+
+private:
+
+  double m_beamwidthRadians;
+
+  double m_orientationRadians;
+
+  double m_maxAttenuation;
+};
+
+
+
+} // namespace ns3
+
+
+#endif // PARABOLIC_ANTENNA_MODEL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/antenna/test/test-parabolic-antenna.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -0,0 +1,190 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011,12 CTTC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include <ns3/log.h>
+#include <ns3/test.h>
+#include <ns3/double.h>
+#include <ns3/parabolic-antenna-model.h>
+#include <ns3/simulator.h>
+#include <math.h>
+#include <string>
+#include <iostream>
+#include <sstream>
+
+
+NS_LOG_COMPONENT_DEFINE ("TestParabolicAntennaModel");
+
+namespace ns3 {
+
+enum ParabolicAntennaModelGainTestCondition  {
+  EQUAL = 0,
+  LESSTHAN = 1
+};
+
+class ParabolicAntennaModelTestCase : public TestCase
+{
+public:
+  static std::string BuildNameString (Angles a, double b, double o, double g);
+  ParabolicAntennaModelTestCase (Angles a, double b, double o, double g, double expectedGainDb, ParabolicAntennaModelGainTestCondition cond);
+
+
+private:
+  virtual void DoRun (void);
+
+  Angles m_a;
+  double m_b;
+  double m_o;
+  double m_g;
+  double m_expectedGain;
+  ParabolicAntennaModelGainTestCondition m_cond;
+};
+
+std::string ParabolicAntennaModelTestCase::BuildNameString (Angles a, double b, double o, double g)
+{
+  std::ostringstream oss;
+  oss <<  "theta=" << a.theta << " , phi=" << a.phi 
+      << ", beamdwidth=" << b << "deg"
+      << ", orientation=" << o 
+      << ", maxAttenuation=" << g << " dB";
+  return oss.str ();
+}
+
+
+ParabolicAntennaModelTestCase::ParabolicAntennaModelTestCase (Angles a, double b, double o, double g, double expectedGainDb, ParabolicAntennaModelGainTestCondition cond)
+  : TestCase (BuildNameString (a, b, o, g)),
+    m_a (a),
+    m_b (b),
+    m_o (o),
+    m_g (g),
+    m_expectedGain (expectedGainDb),
+    m_cond (cond)
+{
+}
+
+void
+ParabolicAntennaModelTestCase::DoRun ()
+{
+  NS_LOG_FUNCTION (this << BuildNameString (m_a, m_b, m_o, m_g));
+
+  Ptr<ParabolicAntennaModel> a = CreateObject<ParabolicAntennaModel> ();
+  a->SetAttribute ("Beamwidth", DoubleValue (m_b));
+  a->SetAttribute ("Orientation", DoubleValue (m_o));
+  a->SetAttribute ("MaxAttenuation", DoubleValue (m_g));
+  double actualGain = a->GetGainDb (m_a);
+  switch (m_cond) 
+    {
+    case EQUAL:
+      NS_TEST_EXPECT_MSG_EQ_TOL (actualGain, m_expectedGain, 0.001, "wrong value of the radiation pattern");
+      break;
+    case LESSTHAN:
+      NS_TEST_EXPECT_MSG_LT (actualGain, m_expectedGain, "gain higher than expected");
+      break;
+    default:
+      break;
+    }
+}
+
+
+
+
+class ParabolicAntennaModelTestSuite : public TestSuite
+{
+public:
+  ParabolicAntennaModelTestSuite ();
+};
+
+ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite ()
+  : TestSuite ("parabolic-antenna-model", UNIT)
+{ 
+
+  // with a 60 deg beamwidth, gain is -20dB at +-77.460 degrees from boresight
+  //                                                                         phi,  theta, beamwidth, orientation,  maxAttn,  expectedGain,   condition
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians    (0),    0),        60,           0,       20,             0,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (30),    0),        60,           0,       20,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-30),    0),        60,           0,       20,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-90),    0),        60,           0,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (90),    0),        60,           0,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (100),    0),        60,           0,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (150),    0),        60,           0,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (180),    0),        60,           0,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-100),    0),        60,           0,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-150),    0),        60,           0,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-180),    0),        60,           0,       20,           -20,     EQUAL));
+
+  // with a 60 deg beamwidth, gain is -10dB at +-54.772 degrees from boresight
+  // test positive orientation
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (60),    0),        60,          60,       10,             0,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (90),    0),        60,          60,       10,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (30),    0),        60,          60,       10,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-30),    0),        60,          60,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (150),    0),        60,          60,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (160),    0),        60,          60,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (210),    0),        60,          60,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (240),    0),        60,          60,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-40),    0),        60,          60,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-90),    0),        60,          60,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-120),    0),        60,          60,       10,           -10,     EQUAL));
+
+  // test negative orientation and different beamwidths
+  // with a 80 deg beamwidth, gain is -20dB at +- 73.030 degrees from boresight
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-150),    0),       80,        -150,       10,             0,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-110),    0),       80,        -150,       10,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-190),    0),       80,        -150,       10,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-70),    0),       80,        -150,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (92),    0),       80,        -150,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-30),    0),       80,        -150,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians    (0),    0),       80,        -150,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (60),    0),       80,        -150,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (90),    0),       80,        -150,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (30),    0),       80,        -150,       10,           -10,     EQUAL));
+  
+
+
+  // test elevation angle
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians    (0),    2),        60,           0,       20,             0,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (30),    2),        60,           0,       20,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-30),    2),        60,           0,       20,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-90),    2),        60,           0,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-180),    2),        60,           0,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (60),   -3),        60,          60,       20,             0,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (90),   -3),        60,          60,       20,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (30),   -3),        60,          60,       20,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-120),   -3),        60,          60,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-150),   -3),       100,        -150,       10,             0,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-100),   -3),       100,        -150,       10,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-200),   -3),       100,        -150,       10,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-30),   -3),       100,        -150,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (90),  9.5),       100,        -150,       10,           -10,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians    (0),  9.5),        60,           0,       20,             0,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians   (30),  9.5),        60,           0,       20,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (-30),  9.5),        60,           0,       20,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians  (100),  9.5),        60,           0,       20,           -20,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-150),  9.5),       100,        -150,       30,             0,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-100),  9.5),       100,        -150,       30,            -3,     EQUAL));
+  AddTestCase (new ParabolicAntennaModelTestCase (Angles (DegreesToRadians (-200),  9.5),       100,        -150,       30,            -3,     EQUAL));
+                   
+};
+
+static ParabolicAntennaModelTestSuite staticParabolicAntennaModelTestSuiteInstance;
+
+
+
+
+} // namespace ns3
--- a/src/antenna/wscript	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/antenna/wscript	Thu Mar 22 18:27:46 2012 +0100
@@ -9,6 +9,7 @@
         'model/antenna-model.cc',
         'model/isotropic-antenna-model.cc',	
         'model/cosine-antenna-model.cc',
+        'model/parabolic-antenna-model.cc',
 	 ]		
 	 
     module_test = bld.create_ns3_module_test_library('antenna')
@@ -17,6 +18,7 @@
         'test/test-degrees-radians.cc',
         'test/test-isotropic-antenna.cc',
         'test/test-cosine-antenna.cc',
+        'test/test-parabolic-antenna.cc',
         ]
     
     headers = bld.new_task_gen(features=['ns3header'])
@@ -26,6 +28,7 @@
         'model/antenna-model.h',
         'model/isotropic-antenna-model.h',		
         'model/cosine-antenna-model.h',
+        'model/parabolic-antenna-model.h',
 	]
     
 
--- a/src/buildings/helper/building-allocator.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/buildings/helper/building-allocator.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -190,7 +190,9 @@
       }
       double bxmax = bxmin + m_lengthX;
       double bymax = bymin + m_lengthY;
-      BoxValue boxValue (Box (bxmin, bxmax, bymin, bymax, 0, m_height));
+      Box box (bxmin, bxmax, bymin, bymax, 0, m_height);
+      NS_LOG_LOGIC ("new building : " <<  box);
+      BoxValue boxValue (box);
       m_buildingFactory.Set ("Boundaries", boxValue);
       Ptr<Building> b  = m_buildingFactory.Create<Building> ();
       //b->SetAttribute ("Boundaries", boxValue);
--- a/src/buildings/helper/building-position-allocator.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/buildings/helper/building-position-allocator.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -18,6 +18,7 @@
  * Author: Nicola Baldo <nbaldo@cttc.es>
  */
 #include "building-position-allocator.h"
+#include "ns3/buildings-mobility-model.h"
 #include "ns3/random-variable.h"
 #include "ns3/double.h"
 #include "ns3/uinteger.h"
@@ -177,4 +178,77 @@
 
 
 
+
+
+NS_OBJECT_ENSURE_REGISTERED (SameRoomPositionAllocator);
+
+SameRoomPositionAllocator::SameRoomPositionAllocator ()
+{
+  NS_FATAL_ERROR (" Constructor \"SameRoomPositionAllocator ()\" should not be used");
+}
+
+
+SameRoomPositionAllocator::SameRoomPositionAllocator (NodeContainer c)
+  : m_nodes (c),
+    m_nodeIt (c.Begin ())
+{
+}
+
+TypeId
+SameRoomPositionAllocator::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::SameRoomPositionAllocator")
+    .SetParent<PositionAllocator> ()
+    .SetGroupName ("Mobility")
+    .AddConstructor<SameRoomPositionAllocator> ();
+  return tid;
+}
+
+Vector 
+SameRoomPositionAllocator::GetNext () const
+{
+  NS_LOG_FUNCTION (this);
+  UniformVariable rand;
+  if (m_nodeIt == m_nodes.End ())
+    {
+      m_nodeIt  = m_nodes.Begin ();
+    }
+  
+  NS_ASSERT_MSG (m_nodeIt != m_nodes.End (), "no node in container");
+
+  Ptr<BuildingsMobilityModel> bmm = (*m_nodeIt)->GetObject<BuildingsMobilityModel> ();
+  uint32_t roomx = bmm->GetRoomNumberX ();
+  uint32_t roomy = bmm->GetRoomNumberY ();
+  uint32_t floor = bmm->GetFloorNumber ();
+  NS_LOG_LOGIC ("considering room (" << roomx << ", " << roomy << ", " << floor << ")");
+
+  Ptr<Building> b = bmm->GetBuilding ();
+  Ptr<RandomBoxPositionAllocator> pa = CreateObject<RandomBoxPositionAllocator> ();
+  UniformVariable v;
+  BoxValue bv;
+  b->GetAttribute ("Boundaries", bv);
+  Box box = bv.Get ();
+  double rdx =  (box.xMax - box.xMin) / b->GetNRoomsX ();
+  double rdy =  (box.yMax - box.yMin) / b->GetNRoomsY ();
+  double rdz =  (box.zMax - box.zMin) / b->GetNFloors ();
+  double x1 = box.xMin + rdx * roomx;
+  double x2 = box.xMin + rdx * (roomx + 1);
+  double y1 = box.yMin + rdy * roomy;
+  double y2 = box.yMin + rdy * (roomy + 1);
+  double z1 = box.zMin + rdz * floor;
+  double z2 = box.zMin + rdz * (floor + 1);
+  NS_LOG_LOGIC ("randomly allocating position in "
+                << " (" << x1 << "," << x2 << ") "
+                << "x (" << y1 << "," << y2 << ") "
+                << "x (" << z1 << "," << z2 << ") ");
+
+  double x = v.GetValue (x1, x2);
+  double y = v.GetValue (y1, y2);
+  double z = v.GetValue (z1, z2);
+  
+  return Vector (x, y, z);
+}
+
+
+
 } // namespace ns3
--- a/src/buildings/helper/building-position-allocator.h	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/buildings/helper/building-position-allocator.h	Thu Mar 22 18:27:46 2012 +0100
@@ -22,6 +22,7 @@
 
 #include <ns3/ptr.h>
 #include <ns3/position-allocator.h>
+#include <ns3/node-container.h>
 
 namespace ns3 {
 
@@ -82,6 +83,29 @@
 };
 
 
+/**
+ * Walks a given NodeContainer sequentially, and for each node allocate a new
+ * position randomly in the same room of that node
+ * 
+ */
+class SameRoomPositionAllocator : public PositionAllocator
+{
+public:
+  SameRoomPositionAllocator ();
+  SameRoomPositionAllocator (NodeContainer c);
+
+  // inherited from Object
+  static TypeId GetTypeId (void);
+
+  // inherited from PositionAllocator
+  virtual Vector GetNext (void) const;
+
+private:
+
+  NodeContainer m_nodes;
+  mutable NodeContainer::Iterator m_nodeIt;
+};
+
 
 } // namespace ns3
 
--- a/src/lte/doc/Makefile	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/doc/Makefile	Thu Mar 22 18:27:46 2012 +0100
@@ -25,10 +25,7 @@
 	$(FIGURES)/MCS_2_test.eps \
 	$(FIGURES)/MCS_12_test.eps \
 	$(FIGURES)/MCS_14_test.eps \
-	$(FIGURES)/lena-dual-stripe.eps
-
-# specify figures for build process (figures for which both a .pdf and a .png files are provided)
-GRAPHS_EPS = \
+	$(FIGURES)/lena-dual-stripe.eps \
 	$(FIGURES)/lte-mcs-index.eps \
 	$(FIGURES)/lenaThrTestCase1.eps \
 	$(FIGURES)/lenaThrTestCase2.eps \
@@ -118,10 +115,6 @@
 %.pdf : %.seqdiag; $(SEQDIAG) -Tpdf -o $@ $< ; if test x$($@_width) != x; then TMPFILE=`mktemp`; ./rescale-pdf.sh $($@_width) $@ $${TMPFILE} && mv $${TMPFILE} $@; fi
 %.pdf : %.eps; $(EPSTOPDF) $< -o=$@; if test x$($@_width) != x; then TMPFILE=`mktemp`; ./rescale-pdf.sh $($@_width) $@ $${TMPFILE} && mv $${TMPFILE} $@; fi
 
-GRAPHS_PNG = ${GRAPHS_EPS:.eps=.png}
-GRAPHS_PDF = ${GRAPHS_EPS:.eps=.pdf}
-
-GRAPHS = $(GRAPHS_EPS) $(GRAPHS_PNG) $(GRAPHS_PDF)
 
 %.png : %.eps; $(CONVERT) $< $@
 %.pdf : %.eps; $(EPSTOPDF) $< -o=$@; if test x$($@_width) != x; then TMPFILE=`mktemp`; ./rescale-pdf.sh $($@_width) $@ $${TMPFILE} && mv $${TMPFILE} $@; fi
@@ -162,15 +155,13 @@
 	-rm -rf $(BUILDDIR)/*
 	-rm -f $(IMAGES_PNG)
 	-rm -f $(IMAGES_PDF)
-	-rm -f $(GRAPHS_PNG)
-	-rm -f $(GRAPHS_PDF)
 
 frag: pickle
 	@if test ! -d $(BUILDDIR)/frag; then mkdir $(BUILDDIR)/frag; fi
 	pushd $(BUILDDIR)/frag && ../../pickle-to-xml.py ../pickle/index.fpickle  > navigation.xml && popd
 	cp -r $(BUILDDIR)/pickle/_images $(BUILDDIR)/frag
 
-html:  $(IMAGES) ${GRAPHS}
+html:  $(IMAGES) 
 	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
 	@echo
 	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
@@ -224,14 +215,14 @@
 	@echo
 	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
 
-latex:  $(IMAGES) ${GRAPHS}
+latex:  $(IMAGES)
 	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
 	@echo
 	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
 	@echo "Run \`make' in that directory to run these through (pdf)latex" \
 	      "(use \`make latexpdf' here to do that automatically)."
 
-latexpdf:  $(IMAGES) ${GRAPHS}
+latexpdf:  $(IMAGES)
 	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
 	@echo "Running LaTeX files through pdflatex..."
 	make -C $(BUILDDIR)/latex all-pdf
--- a/src/lte/doc/source/lte-design.rst	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/doc/source/lte-design.rst	Thu Mar 22 18:27:46 2012 +0100
@@ -411,9 +411,9 @@
 
 
 
------------------------------
-Description of the components
------------------------------
+-----------------------------------------
+Detailed description of protocol elements
+-----------------------------------------
 
 
 
@@ -602,7 +602,7 @@
    R_{i}(k,t) =  \frac{S\left( M_{i,k}(t), 1\right)}{\tau} 
 
 where :math:`\tau` is the TTI duration.
-At the start of each subframe :math:`t`, all the RBs are assigned to a certain user.
+At the start of each subframe :math:`t`, each RB is assigned to a certain user.
 In detail, the index :math:`\widehat{i}_{k}(t)` to which RB :math:`k` is assigned at time
 :math:`t` is determined as
 
--- a/src/lte/doc/source/lte-rlc.rst	Thu Mar 22 18:14:08 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-.. only:: html or latex
-
-######################################
-LTE Simulator RLC Layer Documentation
-######################################
-
-.. toctree::
-    :maxdepth: 5
-
-    lte-rlc-design
-    lte-references
-
-
-
--- a/src/lte/examples/lena-dual-stripe.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/examples/lena-dual-stripe.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -43,19 +43,152 @@
 
 NS_LOG_COMPONENT_DEFINE ("LenaDualStripe");
 
+
+bool AreOverlapping (Box a, Box b)
+{
+  return !((a.xMin > b.xMax) || (b.xMin > a.xMax) || (a.yMin > b.yMax) || (b.yMin > a.yMax));
+}
+
+class FemtocellBlockAllocator
+{
+public:
+  FemtocellBlockAllocator (Box area, uint32_t nApartmentsX, uint32_t nFloors);
+  void Create (uint32_t n);
+  void Create ();
+  
+private:
+  bool OverlapsWithAnyPrevious (Box);
+  Box m_area;
+  uint32_t m_nApartmentsX;
+  uint32_t m_nFloors;
+  std::list<Box> m_previousBlocks;
+  double m_xSize;
+  double m_ySize;
+  UniformVariable m_xMinVar;
+  UniformVariable m_yMinVar;
+  
+};
+
+FemtocellBlockAllocator::FemtocellBlockAllocator (Box area, uint32_t nApartmentsX, uint32_t nFloors)
+  : m_area (area),
+    m_nApartmentsX (nApartmentsX),
+    m_nFloors (nFloors),
+    m_xSize (nApartmentsX*10 + 20),
+    m_ySize (70),
+    m_xMinVar (area.xMin, area.xMax - m_xSize),
+    m_yMinVar (area.yMin, area.yMax - m_ySize)
+{
+ 
+}
+
+void 
+FemtocellBlockAllocator::Create (uint32_t n)
+{
+  for (uint32_t i = 0; i < n; ++i)
+    {
+      Create ();
+    }
+}
+
+void
+FemtocellBlockAllocator::Create ()
+{
+  Box box;
+  uint32_t attempt = 0;
+  do 
+    {
+      NS_ASSERT_MSG (attempt < 100, "Too many failed attemtps to position apartment block. Too many blocks? Too small area?");
+      box.xMin = m_xMinVar.GetValue ();
+      box.xMax = box.xMin + m_xSize;
+      box.yMin = m_yMinVar.GetValue ();
+      box.yMax = box.yMin + m_ySize;      
+      ++attempt;
+    }
+  while (OverlapsWithAnyPrevious (box));
+
+  NS_LOG_LOGIC ("allocated non overlapping block " << box);
+  m_previousBlocks.push_back (box);
+  Ptr<GridBuildingAllocator>  gridBuildingAllocator;
+  gridBuildingAllocator = CreateObject<GridBuildingAllocator> ();
+  gridBuildingAllocator->SetAttribute ("GridWidth", UintegerValue (1));
+  gridBuildingAllocator->SetAttribute ("LengthX", DoubleValue (10*m_nApartmentsX)); 
+  gridBuildingAllocator->SetAttribute ("LengthY", DoubleValue (10*2));
+  gridBuildingAllocator->SetAttribute ("DeltaX", DoubleValue (10));
+  gridBuildingAllocator->SetAttribute ("DeltaY", DoubleValue (10));
+  gridBuildingAllocator->SetAttribute ("Height", DoubleValue (3*m_nFloors));
+  gridBuildingAllocator->SetBuildingAttribute ("NRoomsX", UintegerValue (m_nApartmentsX));
+  gridBuildingAllocator->SetBuildingAttribute ("NRoomsY", UintegerValue (2));
+  gridBuildingAllocator->SetBuildingAttribute ("NFloors", UintegerValue (m_nFloors));
+  gridBuildingAllocator->SetAttribute ("MinX", DoubleValue (box.xMin + 10));
+  gridBuildingAllocator->SetAttribute ("MinY", DoubleValue (box.yMin + 10));
+  gridBuildingAllocator->Create (2);
+}
+
+bool 
+FemtocellBlockAllocator::OverlapsWithAnyPrevious (Box box)
+{
+  for (std::list<Box>::iterator it = m_previousBlocks.begin (); it != m_previousBlocks.end (); ++it)
+    {
+      if (AreOverlapping (*it, box))
+        {
+          return true;
+        }
+    }
+  return false;
+}
+
 int
 main (int argc, char *argv[])
 {
   // scenario parameters
-  uint32_t nBlocks = 2;
-  uint32_t nApartamentsX = 10;
-  uint32_t nApartamentsY = 2;
+  uint32_t nBlocks = 10;
+  uint32_t nApartmentsX = 10;
   uint32_t nFloors = 1;
-  uint32_t heightPerFloor = 3;
-  double deploymentRatio = 0.4;
-  double ueHenbRatio = 10;
+  uint32_t nMacroEnbSites = 3;
+  uint32_t nMacroEnbSitesX = 1;
+  double interSiteDistance = 500;
+  double areaMarginFactor = 0.5; 
+  double macroUeDensity = 0.0001;
+  double homeEnbDeploymentRatio = 0.2;
+  double homeEnbActivationRatio = 0.5;
+  double homeUesHomeEnbRatio = 1;
+  double macroEnbTxPowerDbm = 46.0;
+  double homeEnbTxPowerDbm = 20.0;
+  uint16_t macroEnbDlEarfcn = 100;
+  uint16_t homeEnbDlEarfcn = 100;
+  uint8_t macroEnbBandwidth = 25;
+  uint8_t homeEnbBandwidth = 25;
+  double simTime = 0.01;
+  bool generateRem = false;
+  
+  CommandLine cmd;
+  cmd.AddValue ("nBlocks", "Number of femtocell blocks", nBlocks);
+  cmd.AddValue ("nApartmentsX", "Number of apartments along the X axis in a femtocell block", nApartmentsX);
+  cmd.AddValue ("nFloors", "Number of floors", nFloors);
+  cmd.AddValue ("nMacroEnbSites", "How many macro sites there are", nMacroEnbSites);
+  cmd.AddValue ("nMacroEnbSitesX", 
+                "(minimum) number of sites along the X-axis of the hex grid", nMacroEnbSitesX);
+  cmd.AddValue ("interSiteDistance", "min distance between two nearby macro cell sites", interSiteDistance);
+  cmd.AddValue ("areaMarginFactor", "how much the UE area extends outside the macrocell grid, "
+                "expressed as fraction of the interSiteDistance", areaMarginFactor);
+  cmd.AddValue ("macroUeDensity", "How many macrocell UEs there are per square meter", macroUeDensity);
+  cmd.AddValue ("homeEnbDeploymentRatio", 
+                "The HeNB deployment ratio as per 3GPP R4-092042", homeEnbDeploymentRatio);
+  cmd.AddValue ("homeEnbActivationRatio", 
+                "The HeNB activation ratio as per 3GPP R4-092042", homeEnbActivationRatio);
+  cmd.AddValue ("homeUesHomeEnbRatio", 
+                "How many (on average) home UEs per HeNB there are in the simulation", 
+                homeUesHomeEnbRatio);
+  cmd.AddValue ("macroEnbTxPowerDbm", "TX power [dBm] used by macro eNBs", macroEnbTxPowerDbm);
+  cmd.AddValue ("homeEnbTxPowerDbm", "TX power [dBm] used by HeNBs", homeEnbTxPowerDbm);
+  cmd.AddValue ("macroEnbDlEarfcn", "DL EARFCN used by macro eNBs", macroEnbDlEarfcn);
+  cmd.AddValue ("homeEnbDlEarfcn", "DL EARFCN used by HeNBs", homeEnbDlEarfcn);
+  cmd.AddValue ("macroEnbBandwidth", "bandwdith [num RBs] used by macro eNBs", macroEnbBandwidth);
+  cmd.AddValue ("homeEnbBandwidth", "bandwdith [num RBs] used by HeNBs", homeEnbBandwidth);
+  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);
 
-  CommandLine cmd;
   cmd.Parse (argc, argv);
 
   ConfigStore inputConfig;
@@ -63,122 +196,142 @@
 
   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)
+    {
+      ++rowIndex;
+    }
+  uint32_t nMacroEnbSitesY = rowIndex;
+  NS_LOG_LOGIC ("nMacroEnbSitesY = " << nMacroEnbSitesY);
 
-  Ptr<GridBuildingAllocator>  gridBuildingAllocator = CreateObject<GridBuildingAllocator> ();
-  gridBuildingAllocator->SetAttribute ("GridWidth", UintegerValue (1));
-  gridBuildingAllocator->SetAttribute ("MinX", DoubleValue (0));
-  gridBuildingAllocator->SetAttribute ("MinY", DoubleValue (0));
-  gridBuildingAllocator->SetAttribute ("LengthX", DoubleValue (10*nApartamentsX));
-  gridBuildingAllocator->SetAttribute ("LengthY", DoubleValue (10*nApartamentsY));
-  gridBuildingAllocator->SetAttribute ("DeltaX", DoubleValue (10));
-  gridBuildingAllocator->SetAttribute ("DeltaY", DoubleValue (10));
-  gridBuildingAllocator->SetAttribute ("Height", DoubleValue (heightPerFloor*nFloors));
-  gridBuildingAllocator->SetBuildingAttribute ("NRoomsX", UintegerValue (nApartamentsX));
-  gridBuildingAllocator->SetBuildingAttribute ("NRoomsY", UintegerValue (nApartamentsY));
-  gridBuildingAllocator->SetBuildingAttribute ("NFloors", UintegerValue (nFloors));
-  gridBuildingAllocator->SetBuildingAttribute ("ExternalWallsType", EnumValue (Building::StoneBlocks));
-  gridBuildingAllocator->Create (nBlocks);
+  Box macroUeBox (-areaMarginFactor*interSiteDistance, 
+                  (nMacroEnbSitesX + areaMarginFactor)*interSiteDistance, 
+                  -areaMarginFactor*interSiteDistance, 
+                  (nMacroEnbSitesY -1)*interSiteDistance*sqrt(0.75) + areaMarginFactor*interSiteDistance,
+                  1.0, 2.0);
+  
+  FemtocellBlockAllocator blockAllocator (macroUeBox, nApartmentsX, nFloors);
+  blockAllocator.Create (nBlocks);
+
 
-  uint32_t nHenbs = round (nApartamentsX * nApartamentsY * nBlocks * nFloors * deploymentRatio);
-  NS_LOG_LOGIC ("nHenbs = " << nHenbs);
-  uint32_t nUes = round (nHenbs*ueHenbRatio);
-  NS_LOG_LOGIC ("nUes = " << nUes);
+  uint32_t nHomeEnbs = round (4 * nApartmentsX * nBlocks * nFloors * homeEnbDeploymentRatio * homeEnbActivationRatio);
+  NS_LOG_LOGIC ("nHomeEnbs = " << nHomeEnbs);
+  uint32_t nHomeUes = round (nHomeEnbs * homeUesHomeEnbRatio);
+  NS_LOG_LOGIC ("nHomeUes = " << nHomeUes);
+  double macroUeAreaSize = (macroUeBox.xMax - macroUeBox.xMin) * (macroUeBox.yMax - macroUeBox.yMin);
+  uint32_t nMacroUes = round (macroUeAreaSize * macroUeDensity) ;
+  NS_LOG_LOGIC ("nMacroUes = " << nMacroUes);
   
-  NodeContainer henbs;
-  henbs.Create (nHenbs);
+  NodeContainer homeEnbs;
+  homeEnbs.Create (nHomeEnbs);
   NodeContainer macroEnbs;
-  macroEnbs.Create (3);
-  NodeContainer ues;
-  ues.Create (nUes);
+  macroEnbs.Create (3 * nMacroEnbSites);
+  NodeContainer homeUes;
+  homeUes.Create (nHomeUes);
+  NodeContainer macroUes;
+  macroUes.Create (nMacroUes);
 
   MobilityHelper mobility;
   mobility.SetMobilityModel ("ns3::BuildingsMobilityModel");
-  mobility.EnableAsciiAll (std::cout);
 
-  // HeNBs placed indoor
-  Ptr<PositionAllocator> positionAlloc = CreateObject<RandomRoomPositionAllocator> ();
-  mobility.SetPositionAllocator (positionAlloc);
-  mobility.Install (henbs);
-
-  // Macro eNB placed at fixed coordinates
-  Ptr<ListPositionAllocator> listPositionAlloc = CreateObject<ListPositionAllocator> ();
-  listPositionAlloc->Add (Vector (-50, 0, 30));
-  listPositionAlloc->Add (Vector (-50.01, 0.01, 30));
-  listPositionAlloc->Add (Vector (-50.01, -0.01, 30));
-  mobility.SetPositionAllocator (listPositionAlloc);
-  mobility.Install (macroEnbs);
-
-  // UEs randomly located in the whole simulation area
-  double xmin = -100;
-  double xmax = nApartamentsX*10+10;
-  double ymin = -50;
-  double ymax = (nApartamentsY*10+10)*nBlocks;
-  double zmin = 0;
-  double zmax = heightPerFloor*nFloors;
-  NS_LOG_LOGIC ("randomly allocating users in "
-                << " (" << xmin << "," << xmax << ") "
-                << "x (" << ymin << "," << ymax << ") "
-                << "x (" << zmin << "," << zmax << ") ");
-  positionAlloc = CreateObject<RandomBoxPositionAllocator> ();
-  positionAlloc->SetAttribute ("X", RandomVariableValue (UniformVariable (xmin, xmax)));
-  positionAlloc->SetAttribute ("Y", RandomVariableValue (UniformVariable (ymin, ymax)));
-  positionAlloc->SetAttribute ("Z", RandomVariableValue (UniformVariable (zmin, zmax)));
-  mobility.SetPositionAllocator (positionAlloc);
-  mobility.Install (ues);
-
-  
 
   Ptr <LteHelper> lteHelper = CreateObject<LteHelper> ();
-  // //lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisPropagationLossModel"));
   lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::HybridBuildingsPropagationLossModel"));
   lteHelper->SetPathlossModelAttribute ("ShadowSigmaExtWalls", DoubleValue (0));
   lteHelper->SetPathlossModelAttribute ("ShadowSigmaOutdoor", DoubleValue (1));
   lteHelper->SetPathlossModelAttribute ("ShadowSigmaIndoor", DoubleValue (1.5));
+  // use always LOS model
+  lteHelper->SetPathlossModelAttribute ("Los2NlosThr", DoubleValue (1e6));
+  lteHelper->SetSpectrumChannelType ("ns3::MultiModelSpectrumChannel");
 
-  
-  // Create Devices and install them in the Nodes (eNB and UE)
-  NetDeviceContainer enbDevs;
-  NetDeviceContainer ueDevs;
-
-  // power setting in dBm for HeNBs
-  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (10.0));
-  enbDevs.Add (lteHelper->InstallEnbDevice (henbs));
 
 
-  // power setting in dBm for macro eNB
-  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (30.0));
-  lteHelper->SetEnbAntennaModelType ("ns3::CosineAntennaModel");
-  lteHelper->SetEnbAntennaModelAttribute ("Beamwidth",   DoubleValue (65));
-  lteHelper->SetEnbAntennaModelAttribute ("MaxGain",     DoubleValue (0.0));
-  lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (0));
-  enbDevs.Add (lteHelper->InstallEnbDevice (macroEnbs.Get (0)));
-  lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (+120));
-  enbDevs.Add (lteHelper->InstallEnbDevice (macroEnbs.Get (1)));
-  lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (-120));
-  enbDevs.Add (lteHelper->InstallEnbDevice (macroEnbs.Get (2)));
+  // Macro eNBs in 3-sector hex grid
+  
+  mobility.Install (macroEnbs);
+  Ptr<LteHexGridEnbTopologyHelper> lteHexGridEnbTopologyHelper = CreateObject<LteHexGridEnbTopologyHelper> ();
+  lteHexGridEnbTopologyHelper->SetLteHelper (lteHelper);
+  lteHexGridEnbTopologyHelper->SetAttribute ("InterSiteDistance", DoubleValue (interSiteDistance));
+  lteHexGridEnbTopologyHelper->SetAttribute ("MinX", DoubleValue (interSiteDistance/2));
+  lteHexGridEnbTopologyHelper->SetAttribute ("GridWidth", UintegerValue (nMacroEnbSitesX));
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (macroEnbTxPowerDbm));
+  lteHelper->SetEnbAntennaModelType ("ns3::ParabolicAntennaModel");
+  lteHelper->SetEnbAntennaModelAttribute ("Beamwidth",   DoubleValue (70));
+  lteHelper->SetEnbAntennaModelAttribute ("MaxAttenuation",     DoubleValue (20.0));
+  lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (macroEnbDlEarfcn));
+  lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (macroEnbDlEarfcn + 18000));
+  lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (macroEnbBandwidth));
+  lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (macroEnbBandwidth));
+  NetDeviceContainer macroEnbDevs = lteHexGridEnbTopologyHelper->SetPositionAndInstallEnbDevice (macroEnbs);
 
-  ueDevs = lteHelper->InstallUeDevice (ues);
-  lteHelper->AttachToClosestEnb (ueDevs, enbDevs);
+  
+  // HomeEnbs randomly indoor
+  
+  Ptr<PositionAllocator> positionAlloc = CreateObject<RandomRoomPositionAllocator> ();
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (homeEnbs);
+  Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (homeEnbTxPowerDbm));
+  lteHelper->SetEnbAntennaModelType ("ns3::IsotropicAntennaModel");
+  lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (homeEnbDlEarfcn));
+  lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (homeEnbDlEarfcn + 18000));
+  lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (homeEnbBandwidth));
+  lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (homeEnbBandwidth));
+  NetDeviceContainer homeEnbDevs  = lteHelper->InstallEnbDevice (homeEnbs);
+  
+
+  // macro Ues 
+  NS_LOG_LOGIC ("randomly allocating macro UEs in " << macroUeBox);
+  positionAlloc = CreateObject<RandomBoxPositionAllocator> ();
+  positionAlloc->SetAttribute ("X", RandomVariableValue (UniformVariable (macroUeBox.xMin, macroUeBox.xMax)));
+  positionAlloc->SetAttribute ("Y", RandomVariableValue (UniformVariable (macroUeBox.yMin, macroUeBox.yMax)));
+  positionAlloc->SetAttribute ("Z", RandomVariableValue (UniformVariable (macroUeBox.zMin, macroUeBox.zMax)));
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.Install (macroUes);
+  NetDeviceContainer macroUeDevs = lteHelper->InstallUeDevice (macroUes);
+  lteHelper->AttachToClosestEnb (macroUeDevs, macroEnbDevs);
+
+
+  // home UEs located in the same apartment in which there are the Home eNBs
+  positionAlloc = CreateObject<SameRoomPositionAllocator> (homeEnbs);
+  mobility.Install (homeUes);
+  NetDeviceContainer homeUeDevs = lteHelper->InstallUeDevice (homeUes);
+  lteHelper->AttachToClosestEnb (homeUeDevs, homeEnbDevs);
+
+
+  
+  // activate bearer for all UEs
   enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
   EpsBearer bearer (q);
-  lteHelper->ActivateEpsBearer (ueDevs, bearer, EpcTft::Default ());
+  lteHelper->ActivateEpsBearer (homeUeDevs, bearer, EpcTft::Default ());  
+  lteHelper->ActivateEpsBearer (macroUeDevs, bearer, EpcTft::Default ());
+  
 
 
   BuildingsHelper::MakeMobilityModelConsistent ();
 
-  // by default, simulation will anyway stop right after the REM has been generated
-  Simulator::Stop (Seconds (0.0069));  
+
 
-  Ptr<RadioEnvironmentMapHelper> remHelper = CreateObject<RadioEnvironmentMapHelper> ();
-  remHelper->SetAttribute ("ChannelPath", StringValue ("/ChannelList/0"));
-  remHelper->SetAttribute ("OutputFile", StringValue ("lena-dual-stripe.rem"));
-  remHelper->SetAttribute ("XMin", DoubleValue (-70));
-  remHelper->SetAttribute ("XMax", DoubleValue (xmax));
-  remHelper->SetAttribute ("YMin", DoubleValue (-10));
-  remHelper->SetAttribute ("YMax", DoubleValue (ymax));
-  remHelper->SetAttribute ("Z", DoubleValue (1.5));
-  remHelper->Install ();
+  Ptr<RadioEnvironmentMapHelper> remHelper;
+  if (generateRem)
+    {
+      remHelper = CreateObject<RadioEnvironmentMapHelper> ();
+      remHelper->SetAttribute ("ChannelPath", StringValue ("/ChannelList/0"));
+      remHelper->SetAttribute ("OutputFile", StringValue ("lena-dual-stripe.rem"));
+      remHelper->SetAttribute ("XMin", DoubleValue (macroUeBox.xMin));
+      remHelper->SetAttribute ("XMax", DoubleValue (macroUeBox.xMax));
+      remHelper->SetAttribute ("YMin", DoubleValue (macroUeBox.yMin));
+      remHelper->SetAttribute ("YMax", DoubleValue (macroUeBox.yMax));
+      remHelper->SetAttribute ("Z", DoubleValue (1.5));
+      remHelper->Install ();
+      // simulation will stop right after the REM has been generated
+    }
+  else
+    {
+      Simulator::Stop (Seconds (simTime));  
+    }
 
   Simulator::Run ();
 
--- a/src/lte/examples/lena-rem-sector-antenna.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/examples/lena-rem-sector-antenna.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -29,7 +29,7 @@
 #include <iomanip>
 #include <string>
 #include <vector>
-#include "ns3/gtk-config-store.h"
+//#include "ns3/gtk-config-store.h"
 
 using namespace ns3;
 using std::vector;
--- a/src/lte/examples/lena-rem.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/examples/lena-rem.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -108,8 +108,6 @@
     
   BuildingsHelper::MakeMobilityModelConsistent ();
 
- // by default, simulation will anyway stop right after the REM has been generated
-  Simulator::Stop (Seconds (0.0069));
 
   Simulator::Run ();
 
--- a/src/lte/helper/lte-helper.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/helper/lte-helper.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -62,14 +62,15 @@
   m_enbNetDeviceFactory.SetTypeId (LteEnbNetDevice::GetTypeId ());
   m_enbAntennaModelFactory.SetTypeId (IsotropicAntennaModel::GetTypeId ());
   m_ueAntennaModelFactory.SetTypeId (IsotropicAntennaModel::GetTypeId ());
+  m_channelFactory.SetTypeId (SingleModelSpectrumChannel::GetTypeId ());
 }
 
 void 
 LteHelper::DoStart (void)
 {
   NS_LOG_FUNCTION (this);
-  m_downlinkChannel = CreateObject<SingleModelSpectrumChannel> ();
-  m_uplinkChannel = CreateObject<SingleModelSpectrumChannel> ();
+  m_downlinkChannel = m_channelFactory.Create<SpectrumChannel> ();
+  m_uplinkChannel = m_channelFactory.Create<SpectrumChannel> ();
 
   m_downlinkPathlossModel = m_dlPathlossModelFactory.Create ();
   Ptr<SpectrumPropagationLossModel> dlSplm = m_downlinkPathlossModel->GetObject<SpectrumPropagationLossModel> ();
@@ -101,7 +102,6 @@
       m_uplinkChannel->AddPropagationLossModel (ulPlm);
     }
 
-  //if (m_fadingModelFactory.GetTypeId ().GetName ().compare ( "ns3::TraceFadingLossModel") == 0)
   if (m_fadingModelType.compare ( "ns3::TraceFadingLossModel") == 0)
     {
       m_fadingModule = m_fadingModelFactory.Create<TraceFadingLossModel> ();
@@ -265,6 +265,19 @@
   m_fadingModelFactory.Set (n, v);
 }
 
+void 
+LteHelper::SetSpectrumChannelType (std::string type) 
+{
+  NS_LOG_FUNCTION (this << type);
+  m_channelFactory.SetTypeId (type);
+}
+
+void 
+LteHelper::SetSpectrumChannelAttribute (std::string n, const AttributeValue &v)
+{
+  m_channelFactory.Set (n, v);
+}
+
 
 NetDeviceContainer
 LteHelper::InstallEnbDevice (NodeContainer c)
@@ -317,7 +330,6 @@
   NS_ASSERT_MSG (mm, "MobilityModel needs to be set on node before calling LteHelper::InstallUeDevice ()");
   dlPhy->SetMobility (mm);
   ulPhy->SetMobility (mm);
-  m_uplinkChannel->AddRx (ulPhy);
 
   Ptr<AntennaModel> antenna = (m_enbAntennaModelFactory.Create ())->GetObject<AntennaModel> ();
   NS_ASSERT_MSG (antenna, "error in creating the AntennaModel object");
@@ -378,6 +390,8 @@
 
   dev->Start ();
 
+  m_uplinkChannel->AddRx (ulPhy);
+
   if (m_epcHelper != 0)
     {
       NS_LOG_INFO ("adding this eNB to the EPC");
@@ -410,7 +424,6 @@
   dlPhy->SetMobility (mm);
   ulPhy->SetMobility (mm);
 
-  m_downlinkChannel->AddRx (dlPhy);
 
   Ptr<AntennaModel> antenna = (m_ueAntennaModelFactory.Create ())->GetObject<AntennaModel> ();
   NS_ASSERT_MSG (antenna, "error in creating the AntennaModel object");
@@ -470,7 +483,6 @@
   Ptr<LteUePhy> uePhy = ueDevice->GetObject<LteUeNetDevice> ()->GetPhy ();
   enbPhy->AddUePhy (rnti, uePhy);
 
-  //if (m_fadingModelFactory.GetTypeId ().GetName ().compare ( "ns3::TraceFadingLossModel") == 0)
   if (m_fadingModelType.compare ( "ns3::TraceFadingLossModel") == 0)
     {
       Ptr<MobilityModel> mm_enb_dl = enbPhy->GetDownlinkSpectrumPhy ()->GetMobility ()->GetObject<MobilityModel> ();
@@ -491,6 +503,8 @@
                       enbDevice->GetObject<LteEnbNetDevice> ()->GetUlEarfcn ());
 
   ueDevice->Start ();
+  
+  m_downlinkChannel->AddRx (uePhy->GetDownlinkSpectrumPhy ());
 }
 
 void
@@ -614,32 +628,6 @@
   LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
 
   std::string propModelStr = m_dlPathlossModelFactory.GetTypeId ().GetName ().erase (0,5).c_str ();
-/*
-  const char* propModel = m_dlPathlossModelFactory.GetTypeId ().GetName ().erase (0,5).c_str ();
-  if (propModelStr.compare ("RandomPropagationLossModel") ||
-    propModelStr.compare ("FriisPropagationLossModel")||
-    propModelStr.compare ("TwoRayGroundPropagationLossModel")||
-    propModelStr.compare ("LogDistancePropagationLossModel")||
-    propModelStr.compare ("ThreeLogDistancePropagationLossModel")||
-    propModelStr.compare ("NakagamiPropagationLossModel")||
-    propModelStr.compare ("FixedRssLossModel")||
-    propModelStr.compare ("MatrixPropagationLossModel")||
-    propModelStr.compare ("RangePropagationLossModel"))
-    {
-      LogComponentEnable ("PropagationLossModel", LOG_LEVEL_ALL);
-    }
-  else
-    {
-      LogComponentEnable (propModel, LOG_LEVEL_ALL);
-    }
-
-  if (m_fadingModelType.compare ("ns3::TraceFadingLossModel") == 0)
-    {
-      const char* fadingModel = m_fadingModelType.erase (0,5).c_str ();
-      LogComponentEnable (fadingModel, LOG_LEVEL_ALL);
-    }
-  LogComponentEnable ("SingleModelSpectrumChannel", LOG_LEVEL_ALL);
-*/
   LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
   LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
   LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
--- a/src/lte/helper/lte-helper.h	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/helper/lte-helper.h	Thu Mar 22 18:27:46 2012 +0100
@@ -138,6 +138,19 @@
    */
   void SetUeAntennaModelAttribute (std::string n, const AttributeValue &v);
 
+  /** 
+   * 
+   * \param type the type of SpectrumChannel to be used for the UEs
+   */
+  void SetSpectrumChannelType (std::string type);
+
+  /**
+   * set an attribute for the SpectrumChannel to be used for the UEs
+   * 
+   * \param n the name of the attribute
+   * \param v the value of the attribute
+   */
+  void SetSpectrumChannelAttribute (std::string n, const AttributeValue &v);
   /**
    * create a set of eNB devices
    *
@@ -322,6 +335,8 @@
   ObjectFactory m_dlPathlossModelFactory;
   ObjectFactory m_ulPathlossModelFactory;
 
+  ObjectFactory m_channelFactory;
+
   std::string m_fadingModelType;
   ObjectFactory m_fadingModelFactory;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/helper/lte-hex-grid-enb-topology-helper.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -0,0 +1,171 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+
+#include "lte-hex-grid-enb-topology-helper.h"
+#include <ns3/double.h>
+#include <ns3/log.h>
+#include <ns3/abort.h>
+#include <ns3/pointer.h>
+#include <ns3/epc-helper.h>
+#include <iostream>
+
+
+NS_LOG_COMPONENT_DEFINE ("LteHexGridEnbTopologyHelper");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteHexGridEnbTopologyHelper);
+
+LteHexGridEnbTopologyHelper::LteHexGridEnbTopologyHelper ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+LteHexGridEnbTopologyHelper::~LteHexGridEnbTopologyHelper (void)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+TypeId LteHexGridEnbTopologyHelper::GetTypeId (void)
+{
+  static TypeId
+    tid =
+    TypeId ("ns3::LteHexGridEnbTopologyHelper")
+    .SetParent<Object> ()
+    .AddConstructor<LteHexGridEnbTopologyHelper> ()
+    .AddAttribute ("InterSiteDistance",
+                   "The distance [m] between nearby sites",
+                   DoubleValue (500),
+                   MakeDoubleAccessor (&LteHexGridEnbTopologyHelper::m_d),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("SectorOffset",
+                   "The offset [m] in the position for the node of each sector with respect "
+		   "to the center of the three-sector site",
+                   DoubleValue (0.5),
+                   MakeDoubleAccessor (&LteHexGridEnbTopologyHelper::m_offset),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("SiteHeight",
+                   "The height [m] of each site",
+                   DoubleValue (30),
+                   MakeDoubleAccessor (&LteHexGridEnbTopologyHelper::m_siteHeight),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MinX", "The x coordinate where the hex grid starts.",
+                   DoubleValue (0.0),
+                   MakeDoubleAccessor (&LteHexGridEnbTopologyHelper::m_xMin),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MinY", "The y coordinate where the hex grid starts.",
+                   DoubleValue (0.0),
+                   MakeDoubleAccessor (&LteHexGridEnbTopologyHelper::m_yMin),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("GridWidth", "The number of sites in even rows (odd rows will have one additional site).",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&LteHexGridEnbTopologyHelper::m_gridWidth),
+                   MakeUintegerChecker<uint32_t> ())
+  ;
+  return tid;
+}
+
+void
+LteHexGridEnbTopologyHelper::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  Object::DoDispose ();
+}
+
+
+void 
+LteHexGridEnbTopologyHelper::SetLteHelper (Ptr<LteHelper> h)
+{
+  NS_LOG_FUNCTION (this << h);
+  m_lteHelper = h;
+}
+
+NetDeviceContainer 
+LteHexGridEnbTopologyHelper::SetPositionAndInstallEnbDevice (NodeContainer c)
+{
+  NS_LOG_FUNCTION (this);
+  NetDeviceContainer enbDevs;
+  const double xydfactor = sqrt (0.75);
+  double yd = xydfactor*m_d;
+  for (uint32_t n = 0; n < c.GetN (); ++n)
+    {
+      uint32_t currentSite = n / 3; 
+      uint32_t biRowIndex = (currentSite / (m_gridWidth + m_gridWidth + 1));
+      uint32_t biRowRemainder = currentSite % (m_gridWidth + m_gridWidth + 1);
+      uint32_t rowIndex = biRowIndex*2;
+      uint32_t colIndex = biRowRemainder; 
+      if (biRowRemainder >= m_gridWidth)
+	{
+	  ++rowIndex;
+	  colIndex -= m_gridWidth;
+	}
+      NS_LOG_LOGIC ("node " << n << " site " << currentSite 
+		    << " rowIndex " << rowIndex 
+		    << " colIndex " << colIndex 
+		    << " biRowIndex " << biRowIndex
+		    << " biRowRemainder " << biRowRemainder);
+      double y = m_yMin + yd * rowIndex;
+      double x;
+      double antennaOrientation;
+      if ((rowIndex % 2) == 0) 
+	{
+	  x = m_xMin + m_d * colIndex;
+	}
+      else // row is odd
+	{
+	  x = m_xMin -(0.5*m_d) + m_d * colIndex;
+	}
+      
+      switch (n%3)
+	{
+	case 0:
+	  antennaOrientation = 0;
+	  x += m_offset;
+	  break;
+	  
+	case 1:
+	  antennaOrientation = 120;
+	  x -= m_offset/2.0;
+	  y += m_offset*xydfactor;
+	  break;
+	  
+	case 2:
+	  antennaOrientation = -120;
+	  x -= m_offset/2.0;
+	  y -= m_offset*xydfactor;
+	  break;
+	
+	default:
+	  break;
+	}
+      Ptr<Node> node = c.Get (n);
+      Ptr<MobilityModel> mm = node->GetObject<MobilityModel> ();
+      Vector pos (x, y, m_siteHeight);
+      NS_LOG_LOGIC ("node " << n << " at " << pos << " antennaOrientation " << antennaOrientation);
+      mm->SetPosition (Vector (x, y, m_siteHeight));
+      m_lteHelper->SetEnbAntennaModelAttribute ("Orientation", DoubleValue (antennaOrientation));
+      enbDevs.Add (m_lteHelper->InstallEnbDevice (node));
+    }
+  return enbDevs;
+}
+
+} // namespace ns3
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/helper/lte-hex-grid-enb-topology-helper.h	Thu Mar 22 18:27:46 2012 +0100
@@ -0,0 +1,87 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#ifndef LTE_HEX_GRID_ENB_TOPOLOGY_HELPER_H
+#define LTE_HEX_GRID_ENB_TOPOLOGY_HELPER_H
+
+#include <ns3/lte-helper.h>
+
+namespace ns3 {
+
+
+
+/**
+ * This helper class allows to easily create a topology with eNBs
+ * grouped in three-sector sites layed out on an hexagonal grid. The
+ * layout is done row-wise. 
+ *
+ */
+class LteHexGridEnbTopologyHelper : public Object
+{
+public:
+  LteHexGridEnbTopologyHelper (void);
+  virtual ~LteHexGridEnbTopologyHelper (void);
+
+  static TypeId GetTypeId (void);
+  virtual void DoDispose (void);
+
+
+  /** 
+   * Set the LteHelper to be used to actually create the EnbNetDevices
+   *
+   * \note if no EpcHelper is ever set, then LteHexGridEnbTopologyHelper will default
+   * to creating an LTE-only simulation with no EPC, using LteRlcSm as
+   * the RLC model, and without supporting any IP networking. In other
+   * words, it will be a radio-level simulation involving only LTE PHY
+   * and MAC and the FF Scheduler, with a saturation traffic model for
+   * the RLC.
+   * 
+   * \param h a pointer to the EpcHelper to be used
+   */
+  void SetLteHelper (Ptr<LteHelper> h);
+
+  /**
+   * Position the nodes on a hex grid and install the corresponding
+   * EnbNetDevices with antenna boresight configured properly
+   *
+   * \param c the node container where the devices are to be installed
+   *
+   * \return the NetDeviceContainer with the newly created devices
+   */
+  NetDeviceContainer SetPositionAndInstallEnbDevice (NodeContainer c);
+
+private:
+
+  Ptr<LteHelper> m_lteHelper;
+  double m_offset;
+  double m_d;
+  double m_xMin;
+  double m_yMin;
+  uint32_t m_gridWidth;
+  uint32_t m_siteHeight;
+
+};
+
+
+} // namespace ns3
+
+
+
+#endif // LTE_HEX_GRID_ENB_TOPOLOGY_HELPER_H
--- a/src/lte/helper/radio-environment-map-helper.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/helper/radio-environment-map-helper.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -34,6 +34,7 @@
 #include <ns3/simulator.h>
 #include <ns3/node.h>
 #include <ns3/buildings-helper.h>
+#include <ns3/lte-spectrum-value-helper.h>
 
 #include <fstream>
 #include <limits>
@@ -101,7 +102,7 @@
     .AddAttribute ("YRes", "The resolution (number of points) of the map along the y axis.",
                    UintegerValue (100),
                    MakeUintegerAccessor (&RadioEnvironmentMapHelper::m_yRes),
-                   MakeUintegerChecker<uint32_t> (2,std::numeric_limits<uint16_t>::max ()))
+                   MakeUintegerChecker<uint16_t> (2,std::numeric_limits<uint16_t>::max ()))
     .AddAttribute ("Z", "The value of the z coordinate for which the map is to be generated",
 		   DoubleValue (0.0),
                    MakeDoubleAccessor (&RadioEnvironmentMapHelper::m_z),
@@ -115,11 +116,53 @@
                    DoubleValue (1.4230e-10),
                    MakeDoubleAccessor (&RadioEnvironmentMapHelper::m_noisePower),
                    MakeDoubleChecker<double> ())
+    .AddAttribute ("MaxPointsPerIteration", "Maximum number of REM points to be calculated per iteration. Every point consumes approximately 5KB of memory.",
+                   UintegerValue (20000),
+                   MakeUintegerAccessor (&RadioEnvironmentMapHelper::m_maxPointsPerIteration),
+                   MakeUintegerChecker<uint32_t> (1,std::numeric_limits<uint32_t>::max ()))
+    .AddAttribute ("Earfcn",
+                   "E-UTRA Absolute Radio Frequency Channel Number (EARFCN) "
+                   "as per 3GPP 36.101 Section 5.7.3. ",
+                   UintegerValue (100),
+                   MakeUintegerAccessor (&RadioEnvironmentMapHelper::m_earfcn),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("Bandwidth",
+                   "Transmission Bandwidth Configuration (in number of RBs) over which the SINR will be calculated",
+                   UintegerValue (25),
+                   MakeUintegerAccessor (&RadioEnvironmentMapHelper::SetBandwidth, 
+                                         &RadioEnvironmentMapHelper::GetBandwidth),
+                   MakeUintegerChecker<uint16_t> ())
   ;
   return tid;
 }
 
 
+uint8_t 
+RadioEnvironmentMapHelper::GetBandwidth () const
+{
+  return m_bandwidth;
+}
+
+void 
+RadioEnvironmentMapHelper::SetBandwidth (uint8_t bw)
+{
+  switch (bw)
+    { 
+    case 6:
+    case 15:
+    case 25:
+    case 50:
+    case 75:
+    case 100:
+      m_bandwidth = bw;
+      break;
+
+    default:
+      NS_FATAL_ERROR ("invalid bandwidth value " << (uint16_t) bw);
+      break;
+    }
+}
+
 
 
 void 
@@ -138,66 +181,145 @@
   m_channel = match.Get (0)->GetObject<SpectrumChannel> ();
   NS_ABORT_MSG_IF (m_channel == 0, "object at " << m_channelPath << "is not of type SpectrumChannel");
 
-  double xStep = (m_xMax - m_xMin)/(m_xRes-1);
-  double yStep = (m_yMax - m_yMin)/(m_yRes-1);
-  
-  
-  for (double x = m_xMin; x < m_xMax + 0.5*xStep; x += xStep)
-    {
-      for (double y = m_yMin; y < m_yMax + 0.5*yStep ; y += yStep)
-        {
-          RemPoint p;
-          p.phy = CreateObject<RemSpectrumPhy> ();
-          p.bmm = CreateObject<BuildingsMobilityModel> ();
-          p.phy->SetMobility (p.bmm);
-          p.bmm->SetPosition (Vector (x, y, m_z));
-          BuildingsHelper::MakeConsistent (p.bmm);
-          m_rem.push_back (p);
-        }      
-    }
-  Simulator::Schedule (Seconds (0.0055), &RadioEnvironmentMapHelper::Connect, this);
-  Simulator::Schedule (Seconds (0.0065), &RadioEnvironmentMapHelper::PrintAndDeactivate, this);  
-
-}
-
-void 
-RadioEnvironmentMapHelper::Connect ()
-{
-  NS_LOG_FUNCTION (this);
-  for (std::list<RemPoint>::iterator it = m_rem.begin ();
-       it != m_rem.end ();
-       ++it)
-    {
-      NS_LOG_LOGIC ("adding phy " << it->phy);
-      m_channel->AddRx (it->phy);
-    }    
-}
-
-void 
-RadioEnvironmentMapHelper::PrintAndDeactivate ()
-{
-  NS_LOG_FUNCTION (this);
-  std::ofstream outFile;
-  outFile.open (m_outputFile.c_str ());
-  if (!outFile.is_open ())
+  m_outFile.open (m_outputFile.c_str ());
+  if (!m_outFile.is_open ())
     {
       NS_FATAL_ERROR ("Can't open file " << (m_outputFile));
       return;
     }
   
+  Simulator::Schedule (Seconds (0.0016), 
+                       &RadioEnvironmentMapHelper::DelayedInstall,
+                                   this);
+}
+
+
+void 
+RadioEnvironmentMapHelper::DelayedInstall ()
+{
+  NS_LOG_FUNCTION (this);
+  m_xStep = (m_xMax - m_xMin)/(m_xRes-1);
+  m_yStep = (m_yMax - m_yMin)/(m_yRes-1);
+  
+  if ((double)m_xRes * (double) m_yRes < (double) m_maxPointsPerIteration)
+    {
+      m_maxPointsPerIteration = m_xRes * m_yRes;
+    }
+  
+  for (uint32_t i = 0; i < m_maxPointsPerIteration; ++i)
+    {
+      RemPoint p;
+      p.phy = CreateObject<RemSpectrumPhy> ();
+      p.bmm = CreateObject<BuildingsMobilityModel> ();
+      p.phy->SetRxSpectrumModel (LteSpectrumValueHelper::GetSpectrumModel (m_earfcn, m_bandwidth));
+      p.phy->SetMobility (p.bmm); 
+      m_channel->AddRx (p.phy);
+      m_rem.push_back (p);
+    }
+
+  double remIterationStartTime = 0.0001;
+  double xMinNext = m_xMin;
+  double yMinNext = m_yMin;
+  uint32_t numPointsCurrentIteration = 0;
+  bool justScheduled = false;
+  for (double x = m_xMin; x < m_xMax + 0.5*m_xStep; x += m_xStep)
+    {
+      for (double y = m_yMin; y < m_yMax + 0.5*m_yStep ; y += m_yStep)
+        {
+          if (justScheduled)
+            {
+              xMinNext = x;
+              yMinNext = y;
+              justScheduled = false;
+            }
+          
+          ++numPointsCurrentIteration;
+          if ((numPointsCurrentIteration == m_maxPointsPerIteration)
+              || ((x > m_xMax - 0.5*m_xStep) && (y > m_yMax - 0.5*m_yStep)) )
+            {
+              Simulator::Schedule (Seconds (remIterationStartTime), 
+                                   &RadioEnvironmentMapHelper::RunOneIteration,
+                                   this, xMinNext, x, yMinNext, y);
+              remIterationStartTime += 0.001;
+              justScheduled = true;
+              numPointsCurrentIteration = 0;
+            }
+        }      
+    }
+  Simulator::Schedule (Seconds (remIterationStartTime), 
+                       &RadioEnvironmentMapHelper::Finalize,
+                       this);
+}
+
+  
+void 
+RadioEnvironmentMapHelper::RunOneIteration (double xMin, double xMax, double yMin, double yMax)
+{
+  NS_LOG_FUNCTION (this << xMin << xMax << yMin << yMax);
+  std::list<RemPoint>::iterator remIt = m_rem.begin ();
+  double x;
+  double y;
+  for (x = xMin; x < xMax + 0.5*m_xStep; x += m_xStep)
+    {
+      for (y = (x == xMin) ? yMin : m_yMin;
+           y < ((x == xMax) ? yMax : m_yMax) + 0.5*m_yStep;
+           y += m_yStep)
+        {
+          NS_ASSERT (remIt != m_rem.end ());          
+          remIt->bmm->SetPosition (Vector (x, y, m_z));
+          BuildingsHelper::MakeConsistent (remIt->bmm);
+          ++remIt;
+        }      
+    }
+
+  if (remIt != m_rem.end ())
+    {
+      NS_ASSERT ((x > m_xMax - 0.5*m_xStep) && (y > m_yMax - 0.5*m_yStep));
+      NS_LOG_LOGIC ("deactivating RemSpectrumPhys that are unneeded in the last iteration");
+      while (remIt != m_rem.end ())
+        {
+          remIt->phy->Deactivate ();
+          ++remIt;
+        }
+    }
+
+  Simulator::Schedule (Seconds (0.0005), &RadioEnvironmentMapHelper::PrintAndReset, this);  
+}
+
+void 
+RadioEnvironmentMapHelper::PrintAndReset ()
+{
+  NS_LOG_FUNCTION (this);
+  
   for (std::list<RemPoint>::iterator it = m_rem.begin ();
        it != m_rem.end ();
        ++it)
     {
+      if (!(it->phy->IsActive ()))
+        {
+          // should occur only upon last iteration when some RemPoint
+          // at the end of the list can be unused
+          break;
+        }
       Vector pos = it->bmm->GetPosition ();
-      outFile << pos.x << "\t" 
-              << pos.y << "\t" 
-              << pos.z << "\t" 
-              << it->phy->GetSinr (m_noisePower)
-              << std::endl;
-      it->phy->Deactivate ();
+      NS_LOG_LOGIC ("output: " << pos.x << "\t" 
+                    << pos.y << "\t" 
+                    << pos.z << "\t" 
+                    << it->phy->GetSinr (m_noisePower));
+      m_outFile << pos.x << "\t" 
+                << pos.y << "\t" 
+                << pos.z << "\t" 
+                << it->phy->GetSinr (m_noisePower)
+                << std::endl;
+      it->phy->Reset ();
     }
-  outFile.close ();
+}
+
+void 
+RadioEnvironmentMapHelper::Finalize ()
+{
+  NS_LOG_FUNCTION (this);
+  m_outFile.close ();
   if (m_stopWhenDone)
     {
       Simulator::Stop ();
--- a/src/lte/helper/radio-environment-map-helper.h	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/helper/radio-environment-map-helper.h	Thu Mar 22 18:27:46 2012 +0100
@@ -24,7 +24,7 @@
 
 
 #include <ns3/object.h>
-
+#include <fstream>
 
 
 namespace ns3 {
@@ -36,7 +36,7 @@
 class BuildingsMobilityModel;
 
 /** 
- * Generates a 2D map of the SINR from the strongest transmitter. 
+ * Generates a 2D map of the SINR from the strongest transmitter in the downlink of an LTE FDD system.
  * 
  */
 class RadioEnvironmentMapHelper : public Object
@@ -44,19 +44,35 @@
 public:  
 
   RadioEnvironmentMapHelper ();
-
   virtual ~RadioEnvironmentMapHelper ();
   
   // inherited from Object
   virtual void DoDispose (void);
   static TypeId GetTypeId (void);
 
+  /** 
+   * \return the bandwidth (in num of RBs) over which SINR is calculated
+   */
+  uint8_t GetBandwidth () const;
+
+  /** 
+   *
+   * \param bw  the bandwidth (in num of RBs) over which SINR is calculated
+   */
+  void SetBandwidth (uint8_t bw);
+
+  /** 
+   * Deploy the RemSpectrumPhy objects that generate the map according to the specified settings.
+   * 
+   */
   void Install ();
 
 private:
 
-  void Connect ();
-  void PrintAndDeactivate ();
+  void DelayedInstall ();
+  void RunOneIteration (double xMin, double xMax, double yMin, double yMax);
+  void PrintAndReset ();
+  void Finalize ();
 
 
   struct RemPoint 
@@ -70,11 +86,18 @@
   double m_xMin;
   double m_xMax;
   uint16_t m_xRes;
+  double m_xStep;
 
   double m_yMin;
   double m_yMax;
   uint16_t m_yRes;
-  
+  double m_yStep;
+
+  uint32_t m_maxPointsPerIteration;
+
+  uint16_t m_earfcn;
+  uint16_t m_bandwidth;
+ 
   double m_z;
 
   std::string m_channelPath;
@@ -85,6 +108,9 @@
   Ptr<SpectrumChannel> m_channel;
 
   double m_noisePower;
+
+  std::ofstream m_outFile;
+
 };
 
 
--- a/src/lte/model/ideal-control-messages.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/model/ideal-control-messages.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -87,36 +87,6 @@
 }
 
 
-
-// ----------------------------------------------------------------------------------------------------------
-
-PdcchMapIdealControlMessage::PdcchMapIdealControlMessage (void)
-{
-  m_idealPdcchMessage =  new IdealPdcchMessage ();
-  SetMessageType (IdealControlMessage::ALLOCATION_MAP);
-}
-
-
-PdcchMapIdealControlMessage::~PdcchMapIdealControlMessage (void)
-{
-  delete m_idealPdcchMessage;
-}
-
-void
-PdcchMapIdealControlMessage::AddNewRecord (Direction direction,
-                                           int subChannel, Ptr<LteNetDevice> ue, double mcs)
-{
-
-}
-
-
-PdcchMapIdealControlMessage::IdealPdcchMessage*
-PdcchMapIdealControlMessage::GetMessage (void)
-{
-  return m_idealPdcchMessage;
-}
-
-
 // ----------------------------------------------------------------------------------------------------------
 
 
--- a/src/lte/model/ideal-control-messages.h	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/model/ideal-control-messages.h	Thu Mar 22 18:27:46 2012 +0100
@@ -99,95 +99,6 @@
 
 
 
-// ----------------------------------------------------------------------------------------------------------
-
-
-
-#ifndef PDCCH_MAP_IDEAL_CONTROL_MESSAGES_H
-#define PDCCH_MAP_IDEAL_CONTROL_MESSAGES_H
-
-#include "ns3/object.h"
-#include <list>
-
-namespace ns3 {
-
-class LteNetDevice;
-
-/**
- * \ingroup lte
- *
- * \brief The PdcchMapIdealControlMessage defines an ideal allocation map
- * for both UL and DL sends by the eNodeB to all UE,
- * using an ideal PDCCH control channel.
- * IdealPdcchMessage is composed by a list of IdealPdcchRecord
- * where is indicated the UE that can use a particular sub channel
- * with a proper MCS scheme.
- * This records are the same for both UL and DL, and are created by the
- * packet scheduler at the beginning of each sub frame.
- * When the IdealPdcchMessage is sent under an ideal control channel,
- * all UE stores into a proper variables the informations about
- * the resource mapping.
- */
-class PdcchMapIdealControlMessage : public IdealControlMessage
-{
-public:
-  PdcchMapIdealControlMessage (void);
-  virtual ~PdcchMapIdealControlMessage (void);
-
-  /**
-   * Direction for which the message is created
-   */
-  enum Direction
-  {
-    DOWNLINK, UPLINK
-  };
-
-  /**
-   * The PDCCH ideal record
-   */
-  struct IdealPdcchRecord
-  {
-    /** the direction */
-    Direction m_direction;
-    /** the sub channel */
-    int m_idSubChannel;
-    /** the ue that receive the mapping */
-    Ptr<LteNetDevice> m_ue;
-    /** the selected msc */
-    double m_mcsIndex;
-  };
-
-  /**
-   * The PDCCH ideal message
-   */
-  typedef std::list<struct IdealPdcchRecord>  IdealPdcchMessage;
-
-  /**
-   * \brief add a PDCCH record into the message.
-   * \param direction the direction of the map
-   * \param subChannel the scheduled sub channel
-   * \param ue the ue the can use the sub channel for transmission
-   * \param mcs the selected MCS scheme
-   */
-  void AddNewRecord (Direction direction,
-                     int subChannel, Ptr<LteNetDevice> ue, double mcs);
-
-  /**
-   * \brief Get the message
-   * \return the pointer to the message
-   */
-  IdealPdcchMessage* GetMessage (void);
-
-private:
-  IdealPdcchMessage *m_idealPdcchMessage;
-};
-
-} // namespace ns3
-
-#endif /* PDCCH_MAP_IDEAL_CONTROL_MESSAGES_H */
-
-
-
 
 // ----------------------------------------------------------------------------------------------------------
 
@@ -201,9 +112,10 @@
 namespace ns3 {
 
 /**
-* The Downlink Data Control Indicator messages defines the RB allocation for the
-* users
-*/
+ * \ingroup lte
+ * The Downlink Data Control Indicator messages defines the RB allocation for the
+ * users in the downlink
+ */
 class DlDciIdealControlMessage : public IdealControlMessage
 {
 public:
@@ -243,9 +155,10 @@
 namespace ns3 {
 
 /**
-* The Uplink Data Control Indicator messages defines the RB allocation for the
-* users
-*/
+ * \ingroup lte
+ * The Uplink Data Control Indicator messages defines the RB allocation for the
+ * users in the uplink
+ */
 class UlDciIdealControlMessage : public IdealControlMessage
 {
 public:
@@ -289,9 +202,10 @@
 class LteNetDevice;
 
 /**
-* The downlink CqiIdealControlMessage defines an ideal list of
-* feedback about the channel quality sent by the UE to the eNodeB.
-*/
+ * \ingroup lte
+ * The downlink CqiIdealControlMessage defines an ideal list of
+ * feedback about the channel quality sent by the UE to the eNodeB.
+ */
 class DlCqiIdealControlMessage : public IdealControlMessage
 {
 public:
@@ -332,9 +246,10 @@
 class LteNetDevice;
 
 /**
-* The uplink BsrIdealControlMessage defines the specific
-* extension of the CE element for reporting the buffer status report
-*/
+ * \ingroup lte
+ * The uplink BsrIdealControlMessage defines the specific
+ * extension of the CE element for reporting the buffer status report
+ */
 class BsrIdealControlMessage : public IdealControlMessage
 {
 public:
--- a/src/lte/model/lte-enb-net-device.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/model/lte-enb-net-device.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -99,13 +99,13 @@
                    "as per 3GPP 36.101 Section 5.7.3. ",
                    UintegerValue (100),
                    MakeUintegerAccessor (&LteEnbNetDevice::m_dlEarfcn),
-                   MakeUintegerChecker<uint16_t> ())
+                   MakeUintegerChecker<uint16_t> (0, 6149))
     .AddAttribute ("UlEarfcn",
                    "Uplink E-UTRA Absolute Radio Frequency Channel Number (EARFCN) "
                    "as per 3GPP 36.101 Section 5.7.3. ",
                    UintegerValue (18100),
                    MakeUintegerAccessor (&LteEnbNetDevice::m_ulEarfcn),
-                   MakeUintegerChecker<uint16_t> ())
+                   MakeUintegerChecker<uint16_t> (18000, 24149))
   ;
   return tid;
 }
--- a/src/lte/model/lte-spectrum-phy.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/model/lte-spectrum-phy.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -167,14 +167,7 @@
 Ptr<const SpectrumModel>
 LteSpectrumPhy::GetRxSpectrumModel () const
 {
-  if (m_txPsd)
-    {
-      return m_txPsd->GetSpectrumModel ();
-    }
-  else
-    {
-      return 0;
-    }
+  return m_rxSpectrumModel;
 }
 
 
@@ -192,6 +185,7 @@
 {
   NS_LOG_FUNCTION (this << noisePsd);
   NS_ASSERT (noisePsd);
+  m_rxSpectrumModel = noisePsd->GetSpectrumModel ();
   m_interference->SetNoisePowerSpectralDensity (noisePsd);
 }
 
--- a/src/lte/model/lte-spectrum-phy.h	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/model/lte-spectrum-phy.h	Thu Mar 22 18:27:46 2012 +0100
@@ -197,6 +197,7 @@
 
   Ptr<SpectrumChannel> m_channel;
 
+  Ptr<const SpectrumModel> m_rxSpectrumModel;
   Ptr<SpectrumValue> m_txPsd;
   Ptr<PacketBurst> m_txPacketBurst;
   std::list<Ptr<PacketBurst> > m_rxPacketBurstList;
--- a/src/lte/model/rem-spectrum-phy.cc	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/model/rem-spectrum-phy.cc	Thu Mar 22 18:27:46 2012 +0100
@@ -105,8 +105,7 @@
 Ptr<const SpectrumModel>
 RemSpectrumPhy::GetRxSpectrumModel () const
 {
-  // supports any SpectrumModel
-  return 0;
+  return m_rxSpectrumModel;
 }
 
 Ptr<AntennaModel>
@@ -133,6 +132,13 @@
     }
 }
 
+void
+RemSpectrumPhy::SetRxSpectrumModel (Ptr<const SpectrumModel> m)
+{
+  NS_LOG_FUNCTION (this << m);
+  m_rxSpectrumModel = m;
+}
+
 double
 RemSpectrumPhy::GetSinr (double noisePower)
 {
@@ -145,5 +151,18 @@
   m_active = false;
 }
 
+bool
+RemSpectrumPhy::IsActive ()
+{
+  return m_active;
+}
+
+void
+RemSpectrumPhy::Reset ()
+{
+  m_referenceSignalPower = 0;
+  m_sumPower = 0;
+}
+
 
 } // namespace ns3
--- a/src/lte/model/rem-spectrum-phy.h	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/model/rem-spectrum-phy.h	Thu Mar 22 18:27:46 2012 +0100
@@ -70,21 +70,39 @@
   void StartRx (Ptr<SpectrumSignalParameters> params);
 
   /** 
+   * set the RX spectrum model to be used
    * 
+   * \param m 
+   */
+  void SetRxSpectrumModel (Ptr<const SpectrumModel> m);
+
+  /** 
    * 
    * \return the Signal to Noise Ratio calculated 
    */
   double GetSinr (double noisePower);
 
   /** 
-   * make StartRx a no-op from now on
+   * make StartRx a no-op from now on, and mark instance as inactive
    * 
    */
   void Deactivate ();
 
+  /** 
+   * 
+   * \return true if active
+   */
+  bool IsActive ();
+
+  /** 
+   * Reset the SINR calculator
+   * 
+   */
+  void Reset ();
 
 private:
   Ptr<MobilityModel> m_mobility;
+  Ptr<const SpectrumModel> m_rxSpectrumModel;
 
   double m_referenceSignalPower;
   double m_sumPower;
--- a/src/lte/wscript	Thu Mar 22 18:14:08 2012 +0100
+++ b/src/lte/wscript	Thu Mar 22 18:27:46 2012 +0100
@@ -39,6 +39,7 @@
         'helper/radio-bearer-stats-calculator.cc',
         'helper/mac-stats-calculator.cc',
         'helper/radio-environment-map-helper.cc',
+        'helper/lte-hex-grid-enb-topology-helper.cc',
         'model/rem-spectrum-phy.cc',
         'model/ff-mac-csched-sap.cc',
         'model/ff-mac-sched-sap.cc',
@@ -132,6 +133,7 @@
         'helper/mac-stats-calculator.h',
         'helper/radio-bearer-stats-calculator.h',
         'helper/radio-environment-map-helper.h',
+        'helper/lte-hex-grid-enb-topology-helper.h',
         'model/rem-spectrum-phy.h',
         'model/ff-mac-common.h',
         'model/ff-mac-csched-sap.h',