src/propagation/model/jakes-process.cc
changeset 8786 8f366d5eee06
child 8985 7752dc4ce7e9
equal deleted inserted replaced
8785:5b5cb5261865 8786:8f366d5eee06
       
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
       
     2 /*
       
     3  * Copyright (c) 2012 Telum (www.telum.ru)
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License version 2 as
       
     7  * published by the Free Software Foundation;
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    17  *
       
    18  * Author: Kirill Andreev <andreev@telum.ru>, Alexander Sofronov <sofronov@telum.ru>
       
    19  */
       
    20 
       
    21 #include "jakes-process.h"
       
    22 #include "ns3/random-variable.h"
       
    23 #include "ns3/simulator.h"
       
    24 #include "ns3/double.h"
       
    25 #include "ns3/uinteger.h"
       
    26 
       
    27 namespace ns3 {
       
    28 const double JakesProcess::PI = 3.14159265358979323846;
       
    29 
       
    30 /// Represents a single oscillator
       
    31 JakesProcess::Oscillator::Oscillator (std::complex<double> amplitude, double initialPhase, double omega) :
       
    32   m_amplitude (amplitude),
       
    33   m_phase (initialPhase),
       
    34   m_omega (omega)
       
    35 {}
       
    36 
       
    37 std::complex<double>
       
    38 JakesProcess::Oscillator::GetValueAt (Time at) const
       
    39 {
       
    40   return (m_amplitude * cos (at.GetSeconds () * m_omega + m_phase));
       
    41 }
       
    42 
       
    43 NS_OBJECT_ENSURE_REGISTERED (JakesProcess);
       
    44 
       
    45 TypeId
       
    46 JakesProcess::GetTypeId ()
       
    47 {
       
    48   static TypeId tid = TypeId ("ns3::JakesProcess")
       
    49     .SetParent<Object> ()
       
    50     .AddConstructor<JakesProcess> ()
       
    51     .AddAttribute ("DopplerFrequencyHz", "Corresponding doppler frequency[Hz]",
       
    52                    DoubleValue (80),
       
    53                    MakeDoubleAccessor (&JakesProcess::SetDopplerFrequencyHz),
       
    54                    MakeDoubleChecker<double> (0.0, 1e4))
       
    55     .AddAttribute ("NumberOfOscillators", "The number of oscillators",
       
    56                    UintegerValue (20),
       
    57                    MakeUintegerAccessor (&JakesProcess::SetNOscillators),
       
    58                    MakeUintegerChecker<unsigned int> (4, 1000))
       
    59   ;
       
    60   return tid;
       
    61 }
       
    62 
       
    63 void
       
    64 JakesProcess::SetNOscillators (unsigned int nOscillators)
       
    65 {
       
    66   m_nOscillators = nOscillators;
       
    67   if (m_omegaDopplerMax != 0)
       
    68     {
       
    69       ConstructOscillators ();
       
    70     }
       
    71 }
       
    72 
       
    73 void
       
    74 JakesProcess::SetDopplerFrequencyHz (double dopplerFrequencyHz)
       
    75 {
       
    76   m_omegaDopplerMax = 2 * dopplerFrequencyHz * PI;
       
    77   if (m_nOscillators != 0)
       
    78     {
       
    79       ConstructOscillators ();
       
    80     }
       
    81 }
       
    82 
       
    83 void
       
    84 JakesProcess::ConstructOscillators ()
       
    85 {
       
    86   // Initial phase is common for all oscillators:
       
    87   double phi = UniformVariable (-PI, PI).GetValue ();
       
    88   // Theta is common for all oscillatoer:
       
    89   double theta = UniformVariable (-PI, PI).GetValue ();
       
    90   for (unsigned int i = 0; i < m_nOscillators; i++)
       
    91     {
       
    92       unsigned int n = i + 1;
       
    93       /// 1. Rotation speed
       
    94       /// 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
       
    95       double alpha = (2.0 * PI * n - PI + theta) / (4.0 * m_nOscillators);
       
    96       /// 1b. Initiate rotation speed:
       
    97       double omega = m_omegaDopplerMax * cos (alpha);
       
    98       /// 2. Initiate complex amplitude:
       
    99       double psi = UniformVariable (-PI, PI).GetValue ();
       
   100       std::complex<double> amplitude = std::complex<double> (cos (psi), sin (psi)) * 2.0 / sqrt (m_nOscillators);
       
   101       /// 3. Construct oscillator:
       
   102       m_oscillators.push_back (Oscillator (amplitude, phi, omega)); 
       
   103     }
       
   104 }
       
   105 
       
   106 JakesProcess::JakesProcess () :
       
   107   m_omegaDopplerMax (0),
       
   108   m_nOscillators (0)
       
   109 {}
       
   110 
       
   111 JakesProcess::~JakesProcess()
       
   112 {
       
   113   m_oscillators.clear ();
       
   114 }
       
   115 
       
   116 std::complex<double>
       
   117 JakesProcess::GetComplexGain () const
       
   118 {
       
   119   std::complex<double> sumAplitude = std::complex<double> (0, 0);
       
   120   for (unsigned int i = 0; i < m_oscillators.size (); i++)
       
   121     {
       
   122       sumAplitude += m_oscillators[i].GetValueAt (Now ());
       
   123     }
       
   124   return sumAplitude;
       
   125 }
       
   126 
       
   127 double
       
   128 JakesProcess::GetChannelGainDb () const
       
   129 {
       
   130   std::complex<double> complexGain = GetComplexGain ();
       
   131   return (10 * log10 ((pow (complexGain.real (), 2) + pow (complexGain.imag (), 2)) / 2));
       
   132 }
       
   133 
       
   134 } // namespace ns3