5G-LENA nr-v3.0-32-g83aee33
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-spectrum-value-helper.cc
1/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2
3// Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4//
5// SPDX-License-Identifier: GPL-2.0-only
6
7#include "nr-spectrum-value-helper.h"
8
9#include <ns3/abort.h>
10#include <ns3/fatal-error.h>
11#include <ns3/log.h>
12
13#include <cmath>
14#include <map>
15
16namespace ns3
17{
18
19NS_LOG_COMPONENT_DEFINE("NrSpectrumValueHelper");
20
21struct NrSpectrumModelId
22{
30 NrSpectrumModelId(double f, uint16_t b, double s);
31 double frequency;
32 uint16_t bandwidth;
33 double subcarrierSpacing;
34};
35
36NrSpectrumModelId::NrSpectrumModelId(double f, uint16_t b, double s)
37 : frequency(f),
38 bandwidth(b),
39 subcarrierSpacing(s)
40{
41}
42
50bool
51operator<(const NrSpectrumModelId& a, const NrSpectrumModelId& b)
52{
53 return ((a.frequency < b.frequency) ||
54 ((a.frequency == b.frequency) && (a.bandwidth < b.bandwidth)) ||
55 ((a.frequency == b.frequency) && (a.bandwidth == b.bandwidth) &&
56 (a.subcarrierSpacing < b.subcarrierSpacing)));
57}
58
59static std::map<NrSpectrumModelId, Ptr<SpectrumModel>>
60 g_nrSpectrumModelMap;
61
62Ptr<const SpectrumModel>
63NrSpectrumValueHelper::GetSpectrumModel(uint32_t numRbs,
64 double centerFrequency,
65 double subcarrierSpacing)
66{
67 NS_LOG_FUNCTION(centerFrequency << numRbs << subcarrierSpacing);
68
69 NS_ABORT_MSG_IF(numRbs == 0, "Total bandwidth cannot be 0 RBs");
70 NS_ABORT_MSG_IF(centerFrequency < 0.5e9 || centerFrequency > 100e9,
71 "Central frequency should be in range from 0.5GHz to 100GHz");
72 NS_ABORT_MSG_IF(subcarrierSpacing != 15000 && subcarrierSpacing != 30000 &&
73 subcarrierSpacing != 60000 && subcarrierSpacing != 120000 &&
74 subcarrierSpacing != 240000 && subcarrierSpacing != 480000,
75 "Supported subcarrier spacing values are: 15000, 30000, 60000, 120000, 240000 "
76 "and 480000 Hz.");
77
78 NrSpectrumModelId modelId = NrSpectrumModelId(centerFrequency, numRbs, subcarrierSpacing);
79 if (g_nrSpectrumModelMap.find(modelId) == g_nrSpectrumModelMap.end())
80 {
81 NS_ASSERT_MSG(centerFrequency != 0, "The carrier frequency cannot be set to 0");
82 double f = centerFrequency - (numRbs * subcarrierSpacing * SUBCARRIERS_PER_RB / 2.0);
83 Bands rbs; // A vector representing all resource blocks
84 for (uint32_t numrb = 0; numrb < numRbs; ++numrb)
85 {
86 BandInfo rb;
87 rb.fl = f;
88 f += subcarrierSpacing * SUBCARRIERS_PER_RB / 2;
89 rb.fc = f;
90 f += subcarrierSpacing * SUBCARRIERS_PER_RB / 2;
91 rb.fh = f;
92 rbs.push_back(rb);
93 }
94
95 Ptr<SpectrumModel> model = Create<SpectrumModel>(rbs);
96 // save this model to the map of spectrum models
97 g_nrSpectrumModelMap.insert(
98 std::pair<NrSpectrumModelId, Ptr<SpectrumModel>>(modelId, model));
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
195} // namespace ns3