A Discrete-Event Network Simulator
API
uan-prop-model.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 University of Washington
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Leonard Tracy <lentracy@gmail.com>
18  */
19 
20 #include "uan-prop-model.h"
21 
22 #include "ns3/nstime.h"
23 
24 #include <complex>
25 #include <vector>
26 
27 namespace ns3
28 {
29 
30 std::ostream&
31 operator<<(std::ostream& os, const UanPdp& pdp)
32 {
33  os << pdp.GetNTaps() << '|';
34  os << pdp.GetResolution().GetSeconds() << '|';
35 
36  auto it = pdp.m_taps.begin();
37  for (; it != pdp.m_taps.end(); it++)
38  {
39  os << (*it).GetAmp() << '|';
40  }
41  return os;
42 }
43 
44 std::istream&
45 operator>>(std::istream& is, UanPdp& pdp)
46 {
47  uint32_t ntaps;
48  double resolution;
49  char c1;
50 
51  is >> ntaps >> c1;
52  if (c1 != '|')
53  {
54  NS_FATAL_ERROR("UanPdp data corrupted at # of taps");
55  return is;
56  }
57  is >> resolution >> c1;
58  if (c1 != '|')
59  {
60  NS_FATAL_ERROR("UanPdp data corrupted at resolution");
61  return is;
62  }
63  pdp.m_resolution = Seconds(resolution);
64 
65  std::complex<double> amp;
66  pdp.m_taps = std::vector<Tap>(ntaps);
67  for (uint32_t i = 0; i < ntaps && !is.eof(); i++)
68  {
69  is >> amp >> c1;
70  if (c1 != '|')
71  {
72  NS_FATAL_ERROR("UanPdp data corrupted at tap " << i);
73  return is;
74  }
75  pdp.m_taps[i] = Tap(Seconds(resolution * i), amp);
76  }
77  return is;
78 }
79 
81  : m_amplitude(0.0),
82  m_delay(Seconds(0))
83 {
84 }
85 
86 Tap::Tap(Time delay, std::complex<double> amp)
87  : m_amplitude(amp),
88  m_delay(delay)
89 {
90 }
91 
92 std::complex<double>
93 Tap::GetAmp() const
94 {
95  return m_amplitude;
96 }
97 
98 Time
100 {
101  return m_delay;
102 }
103 
105 {
106 }
107 
108 UanPdp::UanPdp(std::vector<Tap> taps, Time resolution)
109  : m_taps(taps),
110  m_resolution(resolution)
111 {
112 }
113 
114 UanPdp::UanPdp(std::vector<std::complex<double>> amps, Time resolution)
115  : m_resolution(resolution)
116 {
117  m_taps.resize(amps.size());
118  Time arrTime = Seconds(0);
119  for (uint32_t index = 0; index < amps.size(); index++)
120  {
121  m_taps[index] = Tap(arrTime, amps[index]);
122  arrTime = arrTime + m_resolution;
123  }
124 }
125 
126 UanPdp::UanPdp(std::vector<double> amps, Time resolution)
127  : m_resolution(resolution)
128 {
129  m_taps.resize(amps.size());
130  Time arrTime = Seconds(0);
131  for (uint32_t index = 0; index < amps.size(); index++)
132  {
133  m_taps[index] = Tap(arrTime, amps[index]);
134  arrTime = arrTime + m_resolution;
135  }
136 }
137 
139 {
140  m_taps.clear();
141 }
142 
143 void
144 UanPdp::SetTap(std::complex<double> amp, uint32_t index)
145 {
146  if (m_taps.size() <= index)
147  {
148  m_taps.resize(index + 1);
149  }
150 
151  Time delay = index * m_resolution;
152  m_taps[index] = Tap(delay, amp);
153 }
154 
155 const Tap&
156 UanPdp::GetTap(uint32_t i) const
157 {
158  NS_ASSERT_MSG(i < GetNTaps(), "Call to UanPdp::GetTap with requested tap out of range");
159  return m_taps[i];
160 }
161 
162 void
163 UanPdp::SetNTaps(uint32_t nTaps)
164 {
165  m_taps.resize(nTaps);
166 }
167 
168 void
170 {
171  m_resolution = resolution;
172 }
173 
176 {
177  return m_taps.begin();
178 }
179 
182 {
183  return m_taps.end();
184 }
185 
186 uint32_t
188 {
189  return static_cast<uint32_t>(m_taps.size());
190 }
191 
192 Time
194 {
195  return m_resolution;
196 }
197 
198 std::complex<double>
199 UanPdp::SumTapsFromMaxC(Time delay, Time duration) const
200 {
201  if (m_resolution <= Seconds(0))
202  {
203  NS_ASSERT_MSG(GetNTaps() == 1,
204  "Attempted to sum taps over time interval in "
205  "UanPdp with resolution 0 and multiple taps");
206 
207  if (delay.IsZero())
208  {
209  return m_taps[0].GetAmp();
210  }
211  return std::complex<double>(0.0, 0.0);
212  }
213 
214  uint32_t numTaps = (duration / m_resolution + 0.5).GetHigh();
215  double maxAmp = -1;
216  uint32_t maxTapIndex = 0;
217 
218  for (uint32_t i = 0; i < GetNTaps(); i++)
219  {
220  if (std::abs(m_taps[i].GetAmp()) > maxAmp)
221  {
222  maxAmp = std::abs(m_taps[i].GetAmp());
223  maxTapIndex = i;
224  }
225  }
226  uint32_t start = maxTapIndex + (delay / m_resolution).GetHigh();
227  uint32_t end = std::min(start + numTaps, GetNTaps());
228  std::complex<double> sum = 0;
229  for (uint32_t i = start; i < end; i++)
230  {
231  sum += m_taps[i].GetAmp();
232  }
233  return sum;
234 }
235 
236 double
237 UanPdp::SumTapsFromMaxNc(Time delay, Time duration) const
238 {
239  if (m_resolution <= Seconds(0))
240  {
241  NS_ASSERT_MSG(GetNTaps() == 1,
242  "Attempted to sum taps over time interval in "
243  "UanPdp with resolution 0 and multiple taps");
244 
245  if (delay.IsZero())
246  {
247  return std::abs(m_taps[0].GetAmp());
248  }
249  return 0;
250  }
251 
252  uint32_t numTaps = (duration / m_resolution + 0.5).GetHigh();
253  double maxAmp = -1;
254  uint32_t maxTapIndex = 0;
255 
256  for (uint32_t i = 0; i < GetNTaps(); i++)
257  {
258  if (std::abs(m_taps[i].GetAmp()) > maxAmp)
259  {
260  maxAmp = std::abs(m_taps[i].GetAmp());
261  maxTapIndex = i;
262  }
263  }
264 
265  uint32_t start = maxTapIndex + (delay / m_resolution).GetHigh();
266  uint32_t end = std::min(start + numTaps, GetNTaps());
267  double sum = 0;
268  for (uint32_t i = start; i < end; i++)
269 
270  {
271  sum += std::abs(m_taps[i].GetAmp());
272  }
273  return sum;
274 }
275 
276 double
277 UanPdp::SumTapsNc(Time begin, Time end) const
278 {
279  if (m_resolution <= Seconds(0))
280  {
281  NS_ASSERT_MSG(GetNTaps() == 1,
282  "Attempted to sum taps over time interval in "
283  "UanPdp with resolution 0 and multiple taps");
284 
285  if (begin <= Seconds(0.0) && end >= Seconds(0.0))
286  {
287  return std::abs(m_taps[0].GetAmp());
288  }
289  else
290  {
291  return 0.0;
292  }
293  }
294 
295  uint32_t stIndex = (begin / m_resolution + 0.5).GetHigh();
296  uint32_t endIndex = (end / m_resolution + 0.5).GetHigh();
297 
298  endIndex = std::min(endIndex, GetNTaps());
299  double sum = 0;
300  for (uint32_t i = stIndex; i < endIndex; i++)
301  {
302  sum += std::abs(m_taps[i].GetAmp());
303  }
304  return sum;
305 }
306 
307 std::complex<double>
308 UanPdp::SumTapsC(Time begin, Time end) const
309 {
310  if (m_resolution <= Seconds(0))
311  {
312  NS_ASSERT_MSG(GetNTaps() == 1,
313  "Attempted to sum taps over time interval in "
314  "UanPdp with resolution 0 and multiple taps");
315 
316  if (begin <= Seconds(0.0) && end >= Seconds(0.0))
317  {
318  return m_taps[0].GetAmp();
319  }
320  else
321  {
322  return std::complex<double>(0.0);
323  }
324  }
325 
326  uint32_t stIndex = (begin / m_resolution + 0.5).GetHigh();
327  uint32_t endIndex = (end / m_resolution + 0.5).GetHigh();
328 
329  endIndex = std::min(endIndex, GetNTaps());
330 
331  std::complex<double> sum = 0;
332  for (uint32_t i = stIndex; i < endIndex; i++)
333  {
334  sum += m_taps[i].GetAmp();
335  }
336  return sum;
337 }
338 
339 UanPdp
341 {
342  double sumNc = 0.0;
343  std::vector<Tap> newTaps;
344 
345  for (uint32_t i = 0; i < GetNTaps(); i++)
346  {
347  sumNc += std::abs(m_taps[i].GetAmp());
348  }
349 
350  for (uint32_t i = 0; i < GetNTaps(); i++)
351  {
352  newTaps.emplace_back(m_taps[i].GetDelay(), (m_taps[i].GetAmp() / sumNc));
353  }
354 
355  return UanPdp(newTaps, m_resolution);
356 }
357 
358 UanPdp
360 {
361  UanPdp pdp;
362  pdp.SetResolution(Seconds(0));
363  pdp.SetTap(1.0, 0);
364  return pdp;
365 }
366 
368 
369 TypeId
371 {
372  static TypeId tid = TypeId("ns3::UanPropModel").SetParent<Object>().SetGroupName("Uan");
373  return tid;
374 }
375 
376 void
378 {
379 }
380 
381 void
383 {
384  Clear();
386 }
387 
388 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:41
A base class which provides memory management and object aggregation.
Definition: object.h:89
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:352
Holds PDP Tap information (amplitude and delay)
Time m_delay
The time delay.
std::complex< double > GetAmp() const
Get the complex amplitude of arrival.
Tap()
Default constructor.
Time GetDelay() const
Get the delay time, usually from first arrival of signal.
std::complex< double > m_amplitude
The amplitude.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
bool IsZero() const
Exactly equivalent to t == 0.
Definition: nstime.h:315
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
The power delay profile returned by propagation models.
static UanPdp CreateImpulsePdp()
Get a unit impulse PDP at time 0.
Iterator GetEnd() const
Get the end of the tap list (one beyond the last entry).
void SetResolution(Time resolution)
Set the time duration (resolution) between arrivals.
UanPdp NormalizeToSumNc() const
Creates a new UanPdp normalized to its non coherent sum.
void SetTap(std::complex< double > arrival, uint32_t index)
Set the arrival value for a tap.
std::vector< Tap > m_taps
The vector of Taps.
double SumTapsFromMaxNc(Time delay, Time duration) const
Compute the non-coherent sum of tap amplitudes starting after a delay from the maximum amplitude for ...
std::vector< Tap >::const_iterator Iterator
Convenience iterator typedef.
void SetNTaps(uint32_t nTaps)
Resize the tap vector.
Time GetResolution() const
Get the delay time resolution (time duration between arrivals).
UanPdp()
Create empty PDP object.
double SumTapsNc(Time begin, Time end) const
Compute the non-coherent sum of tap amplitudes between a start and end time.
Time m_resolution
The time resolution.
uint32_t GetNTaps() const
Get the number of taps.
const Tap & GetTap(uint32_t i) const
Get the Tap at the specified delay index.
Iterator GetBegin() const
Get the beginning of the tap vector.
std::complex< double > SumTapsC(Time begin, Time end) const
Compute the coherent sum of tap amplitudes between a start and end time.
std::complex< double > SumTapsFromMaxC(Time delay, Time duration) const
Compute the coherent sum of tap amplitudes starting after a delay from the maximum amplitude for a to...
~UanPdp()
Dummy destructor, see DoDispose.
Base class for implemented underwater propagation models.
virtual void Clear()
Clear all pointer references.
static TypeId GetTypeId()
Register this type.
void DoDispose() override
Destructor implementation.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:183
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159