5#include "nr-interference.h"
7#include "nr-mimo-chunk-processor.h"
8#include "nr-spectrum-signal-parameters.h"
11#include <ns3/simulator.h>
15NS_LOG_COMPONENT_DEFINE(
"NrInterference");
24 NS_LOG_FUNCTION(
this);
29 NS_LOG_FUNCTION(
this);
35 NS_LOG_FUNCTION(
this);
37 m_mimoChunkProcessors.clear();
38 m_rxSignalsMimo.clear();
39 m_allSignalsMimo.clear();
41 NrInterferenceBase::DoDispose();
48 TypeId(
"ns3::NrInterference")
50 .AddTraceSource(
"SnrPerProcessedChunk",
51 "Snr per processed chunk.",
53 "ns3::SnrPerProcessedChunk::TracedCallback")
54 .AddTraceSource(
"RssiPerProcessedChunk",
55 "Rssi per processed chunk.",
57 "ns3::RssiPerProcessedChunk::TracedCallback");
64 NS_LOG_FUNCTION(
this << *spd << duration);
74 double rxPowerW = Integral(*spd);
79 AppendEvent(Simulator::Now(), Simulator::Now() + duration, rxPowerW);
87 NS_LOG_FUNCTION(
this);
90 NS_LOG_INFO(
"EndRx was already evaluated or RX was aborted");
94 SpectrumValue snr = (*m_rxSignal) / (*m_noise);
95 double avgSnr = Sum(snr) / (snr.GetSpectrumModel()->GetNumBands());
98 NrInterference::ConditionallyEvaluateChunk();
114 for (
auto& cp : m_mimoChunkProcessors)
122NrInterference::ConditionallyEvaluateChunk()
124 NS_LOG_FUNCTION(
this);
127 NS_LOG_DEBUG(
this <<
" Receiving");
134 SpectrumValue interf = (*m_allSignals) - (*m_rxSignal) + (*m_noise);
135 SpectrumValue sinr = (*m_rxSignal) / interf;
136 double rbWidth = (*m_rxSignal).GetSpectrumModel()->Begin()->fh -
137 (*m_rxSignal).GetSpectrumModel()->Begin()->fl;
142 <<
" , noise:" << (*
m_noise)[0]);
151 it->EvaluateChunk(sinr, duration);
154 for (
auto& cp : m_mimoChunkProcessors)
157 auto outOfCellInterfCov = CalcOutOfCellInterfCov();
160 for (
auto& rxSignal : m_rxSignalsMimo)
163 auto nrRxSignal = DynamicCast<const NrSpectrumSignalParametersDataFrame>(rxSignal);
164 uint16_t rnti = nrRxSignal ? nrRxSignal->rnti : 0;
167 auto sinrMatrix = ComputeSinr(outOfCellInterfCov, rxSignal);
168 MimoSinrChunk mimoSinr{sinrMatrix, rnti, duration};
169 cp->EvaluateChunk(mimoSinr);
172 auto& chanSpct = *(rxSignal->spectrumChannelMatrix);
173 MimoSignalChunk mimoSignal{chanSpct, outOfCellInterfCov, rnti, duration};
174 cp->EvaluateChunk(mimoSignal);
186NrInterference::NiChange::NiChange(Time time,
double delta)
193NrInterference::NiChange::GetTime()
const
199NrInterference::NiChange::GetDelta()
const
205NrInterference::NiChange::operator<(
const NrInterference::NiChange& o)
const
207 return (m_time < o.m_time);
214 double powerDbm = 10 * log10(detectedPowerW * 1000);
216 NS_LOG_INFO(
"IsChannelBusyNow detected power is: "
217 << powerDbm <<
" detectedPowerW: " << detectedPowerW <<
" length spectrum: "
218 << (*m_allSignals).GetValuesN() <<
" thresholdW:" << energyW);
220 if (detectedPowerW > energyW)
222 NS_LOG_INFO(
"Channel is BUSY.");
227 NS_LOG_INFO(
"Channel is IDLE.");
240 Time now = Simulator::Now();
241 double noiseInterferenceW = 0.0;
249 noiseInterferenceW += i.GetDelta();
251 NS_LOG_INFO(
"Delta: " << i.GetDelta() <<
"time: " << i.GetTime());
256 if (noiseInterferenceW < energyW)
262 NS_LOG_INFO(
"Future power dBm:" << 10 * log10(noiseInterferenceW * 1000)
263 <<
" W:" << noiseInterferenceW
264 <<
" and energy threshold in W is: " << energyW);
268 NS_LOG_INFO(
"Channel BUSY until." << end);
272 NS_LOG_INFO(
"Channel IDLE.");
275 return end > now ? end - now : MicroSeconds(0);
285NrInterference::NiChanges::iterator
286NrInterference::GetPosition(Time moment)
292NrInterference::AddNiChangeEvent(NiChange change)
294 m_niChanges.insert(GetPosition(change.GetTime()), change);
300 Time now = Simulator::Now();
304 NiChanges::iterator nowIterator = GetPosition(now);
308 for (NiChanges::iterator i =
m_niChanges.begin(); i != nowIterator; i++)
320 AddNiChangeEvent(NiChange(startTime, rxPowerW));
324 AddNiChangeEvent(NiChange(endTime, -rxPowerW));
330 NS_LOG_FUNCTION(
this << *params->psd << duration);
331 auto rxPowerW = Integral(*params->psd);
333 NS_LOG_FUNCTION(
this << *params->psd << duration);
335 m_allSignalsMimo.push_back(params);
341 Simulator::Schedule(duration,
347 AppendEvent(Simulator::Now(), Simulator::Now() + duration, rxPowerW);
353 auto rxPsd = params->psd;
357 m_rxSignalsMimo.clear();
359 m_rxSignalsMimo.push_back(params);
360 for (
auto& cp : m_mimoChunkProcessors)
372 auto numSignals = m_allSignalsMimo.size();
374 if (m_allSignalsMimo.back() == params)
376 m_allSignalsMimo.pop_back();
380 m_allSignalsMimo.erase(
381 std::remove_if(m_allSignalsMimo.begin(),
382 m_allSignalsMimo.end(),
383 [params](Ptr<const SpectrumSignalParameters> p) { return p == params; }),
384 m_allSignalsMimo.end());
386 NS_ASSERT_MSG(m_allSignalsMimo.size() == (numSignals - 1),
387 "MIMO signal was not found for removal");
393 NS_LOG_FUNCTION(
this << cp);
394 m_mimoChunkProcessors.push_back(cp);
400 return (!m_mimoChunkProcessors.empty());
404NrInterference::CalcOutOfCellInterfCov()
const
407 NS_ASSERT_MSG(!(m_rxSignalsMimo.empty()),
"At least one receive signal is required");
408 const auto& firstSignal = m_rxSignalsMimo[0];
409 NS_ASSERT_MSG(firstSignal->spectrumChannelMatrix,
"signal must have a channel matrix");
410 auto nRbs = firstSignal->spectrumChannelMatrix->GetNumPages();
411 auto nRxPorts = firstSignal->spectrumChannelMatrix->GetNumRows();
414 auto allSignalsNoiseCov =
NrCovMat{ComplexMatrixArray(nRxPorts, nRxPorts, nRbs)};
415 for (
size_t iRb = 0; iRb < nRbs; iRb++)
417 for (
size_t iRxPort = 0; iRxPort < nRxPorts; iRxPort++)
419 allSignalsNoiseCov(iRxPort, iRxPort, iRb) =
m_noise->ValuesAt(iRb);
424 for (
const auto& intfSignal : m_allSignalsMimo)
426 if (std::find(m_rxSignalsMimo.begin(), m_rxSignalsMimo.end(), intfSignal) !=
427 m_rxSignalsMimo.end())
433 AddInterference(allSignalsNoiseCov, intfSignal);
435 return allSignalsNoiseCov;
439NrInterference::CalcCurrInterfCov(Ptr<const SpectrumSignalParameters> rxSignal,
440 const NrCovMat& outOfCellInterfCov)
const
444 auto interfNoiseCov = outOfCellInterfCov;
445 for (
auto& otherSignal : m_rxSignalsMimo)
447 if (otherSignal == rxSignal)
451 NS_ASSERT_MSG((std::find(m_allSignalsMimo.begin(), m_allSignalsMimo.end(), otherSignal) !=
452 m_allSignalsMimo.end()),
453 "RX signal already deleted from m_allSignalsMimo");
455 AddInterference(interfNoiseCov, otherSignal);
457 return interfNoiseCov;
461NrInterference::AddInterference(NrCovMat& covMat, Ptr<const SpectrumSignalParameters> signal)
const
463 const auto& chanSpct = *(signal->spectrumChannelMatrix);
464 if (signal->precodingMatrix)
466 auto& precMats = *(signal->precodingMatrix);
467 NS_ASSERT_MSG((precMats.GetNumPages() > 0) && (chanSpct.GetNumPages() > 0),
468 "precMats and channel cannot be empty");
469 NS_ASSERT_MSG(precMats.GetNumPages() == chanSpct.GetNumPages(),
470 "dim mismatch " << precMats.GetNumPages() <<
" vs "
471 << chanSpct.GetNumPages());
472 covMat.AddInterferenceSignal(chanSpct * precMats);
476 covMat.AddInterferenceSignal(chanSpct);
481NrInterference::ComputeSinr(NrCovMat& outOfCellInterfCov,
482 Ptr<const SpectrumSignalParameters> rxSignal)
const
486 auto interfNoiseCov = CalcCurrInterfCov(rxSignal, outOfCellInterfCov);
490 const auto& chanSpct = *(rxSignal->spectrumChannelMatrix);
491 auto intfNormChanMat = interfNoiseCov.CalcIntfNormChannel(chanSpct);
494 ComplexMatrixArray precMat;
495 if (rxSignal->precodingMatrix)
497 precMat = *(rxSignal->precodingMatrix);
501 precMat = ComplexMatrixArray{chanSpct.GetNumCols(), 1, chanSpct.GetNumPages()};
502 for (
size_t p = 0; p < chanSpct.GetNumPages(); p++)
504 precMat(0, 0, p) = 1.0;
508 return intfNormChanMat.ComputeSinrForPrecoding(precMat);
Ptr< SpectrumValue > m_allSignals
Ptr< const SpectrumValue > m_noise
the noise value
uint32_t m_lastSignalId
the last signal ID
bool m_receiving
are we receiving?
Ptr< SpectrumValue > m_rxSignal
uint32_t m_lastSignalIdBeforeReset
the last signal ID before reset
std::list< Ptr< NrChunkProcessor > > m_sinrChunkProcessorList
virtual void DoAddSignal(Ptr< const SpectrumValue > spd)
std::list< Ptr< NrChunkProcessor > > m_rsPowerChunkProcessorList
virtual void StartRx(Ptr< const SpectrumValue > rxPsd)
Notify that the PHY is starting a RX attempt.
std::list< Ptr< NrChunkProcessor > > m_interfChunkProcessorList
virtual void AddSignal(Ptr< const SpectrumValue > spd, const Time duration)
virtual void DoSubtractSignal(Ptr< const SpectrumValue > spd, uint32_t signalId)
NiChanges m_niChanges
List of events in which there is some change in the energy.
NrInterference()
NrInterference constructor.
virtual void AddMimoChunkProcessor(Ptr< NrMimoChunkProcessor > cp)
Add a chunk processor for MIMO signals.
TracedCallback< double > m_rssiPerProcessedChunk
! Trace for RSSI pre processed chunk.
virtual void DoSubtractSignalMimo(Ptr< const SpectrumSignalParameters > params, uint32_t signalId)
Notify that a signals transmission is ending. This means that the signal will be removed from the lis...
bool IsChannelBusyNow(double energyW)
Checks if the sum of the energy, including the energies that start at this moment is greater than pro...
~NrInterference() override
~NrInterference
bool IsChunkProcessorSet()
void AppendEvent(Time startTime, Time endTime, double rxPowerW)
Crates events corresponding to the new energy. One event corresponds to the moment when the energy st...
void AddSignal(Ptr< const SpectrumValue > spd, Time duration) override
Time GetEnergyDuration(double energyW)
Returns the duration of the energy that is above the energy provided detection threshold.
TracedCallback< double > m_snrPerProcessedChunk
! Trace for SNR per processed chunk.
virtual void StartRxMimo(Ptr< const SpectrumSignalParameters > params)
Notify the intended receiver that a new signal is being received. This method is to be called only fo...
virtual void AddSignalMimo(Ptr< const SpectrumSignalParameters > params, const Time &duration)
Notify that a new signal is being perceived in the medium. This method is to be called for all incomi...
void DoDispose() override
DoDispose method inherited from Object.
static TypeId GetTypeId()
Get the object TypeId.