5G-LENA nr-v3.1-69-g2dd513a7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-spectrum-value-helper.cc
1// Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#include "nr-spectrum-value-helper.h"
6
7#include "ns3/simulator.h"
8#include <ns3/abort.h>
9#include <ns3/fatal-error.h>
10#include <ns3/log.h>
11
12#include <cmath>
13#include <map>
14
15namespace ns3
16{
17
18NS_LOG_COMPONENT_DEFINE("NrSpectrumValueHelper");
19
20struct NrSpectrumModelId
21{
29 NrSpectrumModelId(double f, uint16_t b, double s);
30 double frequency;
31 uint16_t bandwidth;
32 double subcarrierSpacing;
33};
34
35NrSpectrumModelId::NrSpectrumModelId(double f, uint16_t b, double s)
36 : frequency(f),
37 bandwidth(b),
38 subcarrierSpacing(s)
39{
40}
41
49bool
50operator<(const NrSpectrumModelId& a, const NrSpectrumModelId& b)
51{
52 return ((a.frequency < b.frequency) ||
53 ((a.frequency == b.frequency) && (a.bandwidth < b.bandwidth)) ||
54 ((a.frequency == b.frequency) && (a.bandwidth == b.bandwidth) &&
55 (a.subcarrierSpacing < b.subcarrierSpacing)));
56}
57
58static std::map<NrSpectrumModelId, Ptr<SpectrumModel>>
59 g_nrSpectrumModelMap;
60
61Ptr<const SpectrumModel>
62NrSpectrumValueHelper::GetSpectrumModel(uint32_t numRbs,
63 double centerFrequency,
64 double subcarrierSpacing)
65{
66 NS_LOG_FUNCTION(centerFrequency << numRbs << subcarrierSpacing);
67
68 NS_ABORT_MSG_IF(numRbs == 0, "Total bandwidth cannot be 0 RBs");
69 NS_ABORT_MSG_IF(centerFrequency < 0.5e9 || centerFrequency > 100e9,
70 "Central frequency should be in range from 0.5GHz to 100GHz");
71 NS_ABORT_MSG_IF(subcarrierSpacing != 15000 && subcarrierSpacing != 30000 &&
72 subcarrierSpacing != 60000 && subcarrierSpacing != 120000 &&
73 subcarrierSpacing != 240000 && subcarrierSpacing != 480000,
74 "Supported subcarrier spacing values are: 15000, 30000, 60000, 120000, 240000 "
75 "and 480000 Hz.");
76
77 NrSpectrumModelId modelId = NrSpectrumModelId(centerFrequency, numRbs, subcarrierSpacing);
78 if (g_nrSpectrumModelMap.find(modelId) == g_nrSpectrumModelMap.end())
79 {
80 NS_ASSERT_MSG(centerFrequency != 0, "The carrier frequency cannot be set to 0");
81 double f = centerFrequency - (numRbs * subcarrierSpacing * SUBCARRIERS_PER_RB / 2.0);
82 Bands rbs; // A vector representing all resource blocks
83 for (uint32_t numrb = 0; numrb < numRbs; ++numrb)
84 {
85 BandInfo rb;
86 rb.fl = f;
87 f += subcarrierSpacing * SUBCARRIERS_PER_RB / 2;
88 rb.fc = f;
89 f += subcarrierSpacing * SUBCARRIERS_PER_RB / 2;
90 rb.fh = f;
91 rbs.push_back(rb);
92 }
93
94 Ptr<SpectrumModel> model = Create<SpectrumModel>(rbs);
95 // save this model to the map of spectrum models
96 g_nrSpectrumModelMap.insert(
97 std::pair<NrSpectrumModelId, Ptr<SpectrumModel>>(modelId, model));
98 Simulator::ScheduleDestroy(&NrSpectrumValueHelper::DeleteSpectrumValues);
99 NS_LOG_INFO("Created SpectrumModel with frequency: "
100 << f << " NumRB: " << rbs.size() << " subcarrier spacing: " << subcarrierSpacing
101 << ", and global UID: " << model->GetUid());
102 }
103 return g_nrSpectrumModelMap.find(modelId)->second;
104}
105
106Ptr<SpectrumValue>
107NrSpectrumValueHelper::CreateTxPsdOverActiveRbs(double powerTx,
108 const std::vector<int>& activeRbs,
109 const Ptr<const SpectrumModel>& spectrumModel)
110{
111 NS_LOG_FUNCTION(powerTx << activeRbs << spectrumModel);
112 Ptr<SpectrumValue> txPsd = Create<SpectrumValue>(spectrumModel);
113 double powerTxW = std::pow(10., (powerTx - 30) / 10);
114 double txPowerDensity = 0;
115 double subbandWidth = (spectrumModel->Begin()->fh - spectrumModel->Begin()->fl);
116 NS_ABORT_MSG_IF(subbandWidth < 180000,
117 "Erroneous spectrum model. RB width should be equal or greater than 180KHz");
118 txPowerDensity = powerTxW / (subbandWidth * activeRbs.size());
119 for (int rbId : activeRbs)
120 {
121 (*txPsd)[rbId] = txPowerDensity;
122 }
123 NS_LOG_LOGIC(*txPsd);
124 return txPsd;
125}
126
127Ptr<SpectrumValue>
128NrSpectrumValueHelper::CreateTxPsdOverAllRbs(double powerTx,
129 const std::vector<int>& activeRbs,
130 const Ptr<const SpectrumModel>& spectrumModel)
131{
132 NS_LOG_FUNCTION(powerTx << activeRbs << spectrumModel);
133 Ptr<SpectrumValue> txPsd = Create<SpectrumValue>(spectrumModel);
134 double powerTxW = std::pow(10., (powerTx - 30) / 10);
135 double txPowerDensity = 0;
136 double subbandWidth = (spectrumModel->Begin()->fh - spectrumModel->Begin()->fl);
137 NS_ABORT_MSG_IF(subbandWidth < 180000,
138 "Erroneous spectrum model. RB width should be equal or greater than 180KHz");
139 txPowerDensity = powerTxW / (subbandWidth * spectrumModel->GetNumBands());
140 for (int rbId : activeRbs)
141 {
142 (*txPsd)[rbId] = txPowerDensity;
143 }
144 NS_LOG_LOGIC(*txPsd);
145 return txPsd;
146}
147
148Ptr<SpectrumValue>
149NrSpectrumValueHelper::CreateTxPowerSpectralDensity(double powerTx,
150 const std::vector<int>& rbIndexVector,
151 const Ptr<const SpectrumModel>& txSm,
152 enum PowerAllocationType allocationType)
153{
154 switch (allocationType)
155 {
156 case UNIFORM_POWER_ALLOCATION_BW: {
157 return CreateTxPsdOverAllRbs(powerTx, rbIndexVector, txSm);
158 }
159 case UNIFORM_POWER_ALLOCATION_USED: {
160 return CreateTxPsdOverActiveRbs(powerTx, rbIndexVector, txSm);
161 }
162 default: {
163 NS_FATAL_ERROR("Unknown power allocation type.");
164 }
165 }
166}
167
168Ptr<SpectrumValue>
169NrSpectrumValueHelper::CreateNoisePowerSpectralDensity(
170 double noiseFigureDb,
171 const Ptr<const SpectrumModel>& spectrumModel)
172{
173 NS_LOG_FUNCTION(noiseFigureDb << spectrumModel);
174 const double kT_dBm_Hz = -174.0; // dBm/Hz
175 double kT_W_Hz = std::pow(10.0, (kT_dBm_Hz - 30) / 10.0);
176 double noiseFigureLinear = std::pow(10.0, noiseFigureDb / 10.0);
177 double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
178
179 Ptr<SpectrumValue> noisePsd = Create<SpectrumValue>(spectrumModel);
180 (*noisePsd) = noisePowerSpectralDensity;
181 return noisePsd;
182}
183
184uint64_t
185NrSpectrumValueHelper::GetEffectiveBandwidth(double bandwidth, uint8_t numerology)
186{
187 NS_LOG_FUNCTION(bandwidth << numerology);
188 uint32_t scSpacing = 15000 * static_cast<uint32_t>(std::pow(2, numerology));
189 uint32_t numRbs = static_cast<uint32_t>(bandwidth / (scSpacing * SUBCARRIERS_PER_RB));
190 NS_LOG_DEBUG("Total bandwidth: " << bandwidth << " effective bandwidth:"
191 << numRbs * (scSpacing * SUBCARRIERS_PER_RB));
192 return numRbs * (scSpacing * SUBCARRIERS_PER_RB);
193}
194
195void
196NrSpectrumValueHelper::DeleteSpectrumValues()
197{
198 g_nrSpectrumModelMap.clear();
199}
200
201} // namespace ns3