5#include "nr-radio-environment-map-helper.h"
7#include "nr-spectrum-value-helper.h"
10#include <ns3/beamforming-vector.h>
11#include <ns3/buildings-module.h>
12#include <ns3/config.h>
13#include <ns3/double.h>
16#include <ns3/mobility-model.h>
18#include <ns3/nr-gnb-net-device.h>
19#include <ns3/nr-spectrum-phy.h>
20#include <ns3/nr-ue-net-device.h>
21#include <ns3/pointer.h>
22#include <ns3/simulator.h>
23#include <ns3/spectrum-converter.h>
24#include <ns3/string.h>
25#include <ns3/uinteger.h>
33NS_LOG_COMPONENT_DEFINE(
"NrRadioEnvironmentMapHelper");
35NS_OBJECT_ENSURE_REGISTERED(NrRadioEnvironmentMapHelper);
39 NS_LOG_FUNCTION(
this);
47NrRadioEnvironmentMapHelper::DoDispose()
49 NS_LOG_FUNCTION(
this);
55 NS_LOG_FUNCTION(
"NrRadioEnvironmentMapHelper::GetTypeId");
57 TypeId(
"ns3::NrRadioEnvironmentMapHelper")
61 .AddAttribute(
"SimTag",
62 "simulation tag that will be concatenated to output file names"
63 "in order to distinguish them, for example: nr-rem-${SimTag}.out. "
64 "nr-rem-${SimTag}-ues.txt, nr-rem-${SimTag}-gnbs.txt, "
65 "nr-rem-${SimTag}-buildings.txt.",
70 "The min x coordinate of the map.",
74 MakeDoubleChecker<double>())
76 "The min y coordinate of the map.",
80 MakeDoubleChecker<double>())
82 "The max x coordinate of the map.",
86 MakeDoubleChecker<double>())
88 "The max y coordinate of the map.",
92 MakeDoubleChecker<double>())
94 "The resolution (number of points) of the"
95 "map along the x axis.",
99 MakeUintegerChecker<uint32_t>(2, std::numeric_limits<uint16_t>::max()))
100 .AddAttribute(
"YRes",
101 "The resolution (number of points) of the"
102 "map along the y axis.",
106 MakeUintegerChecker<uint16_t>(2, std::numeric_limits<uint16_t>::max()))
108 "The value of the z coordinate for which"
109 "the map is to be generated.",
113 MakeDoubleChecker<double>())
114 .AddAttribute(
"IterForAverage",
115 "Number of iterations for the calculation"
116 "of the average rem value.",
120 MakeUintegerChecker<uint16_t>())
123 "There are three high level modes of Rem generation: "
124 "a) BEAM_SHAPE in which are represented the beams that are configured "
125 "in the user's script scenario, considering that the receiver always "
126 "has quasi-omni, and that all the beams point toward the UE which is "
127 "passed as UE of interest. The purpose of this map is to illustrate "
128 "the REM of the scenario that is configured."
129 "b) COVERAGE_AREA which produces two REM maps: the worst-case SINR and "
130 "best-SNR for each rem position; Worst case SINR means that all interfering "
131 "devices use for the transmission the beam towards the rem point;"
132 "and also for the best-SNR, for each transmitting device and the REM point "
133 "are used the best directional beam-pair and then is selected the best SNR."
134 "c) UE_COVERAGE which is similar as the above, although the Tx Device"
135 "is the UE (UL direction), and the Rx device is each gNB to which it is "
136 "connected each time, while the rest of gNBs (if they are present) are"
137 "pointing their beams towards the Rx gNB. In case of TDD, the SINR map"
138 "will show the interference caused by the DL of these gNBs.",
139 EnumValue(NrRadioEnvironmentMapHelper::COVERAGE_AREA),
142 MakeEnumChecker(NrRadioEnvironmentMapHelper::BEAM_SHAPE,
144 NrRadioEnvironmentMapHelper::COVERAGE_AREA,
146 NrRadioEnvironmentMapHelper::UE_COVERAGE,
150 "How many time it is needed in the simulation to configure phy parameters at UE, "
151 "depends on RRC message timing.",
152 TimeValue(MilliSeconds(100)),
215 m_numOfIterationsToAverage = numOfIterationsToAverage;
221 m_installationDelay = installationDelay;
224NrRadioEnvironmentMapHelper::RemMode
275 return std::pow(10.0, 0.1 * (dBm - 30.0));
281 return 10.0 * std::log10(w) + 30.0;
287 return std::pow(10.0, 0.1 * dB);
293 return 10.0 * std::log10(ratio);
297NrRadioEnvironmentMapHelper::ConfigureRrd(
const Ptr<NetDevice>& rrdDevice)
299 NS_LOG_FUNCTION(
this);
303 m_rrd.spectrumModel = m_rrdPhy->GetSpectrumModel();
304 m_rrd.mob->SetPosition(rrdDevice->GetNode()->GetObject<MobilityModel>()->GetPosition());
306 std::ostringstream oss;
307 oss <<
"nr-rem-" << m_simTag.c_str() <<
"-ues.txt";
308 PrintGnuplottableUeListToFile(oss.str());
310 Ptr<MobilityBuildingInfo> buildingInfo = CreateObject<MobilityBuildingInfo>();
311 m_rrd.mob->AggregateObject(buildingInfo);
313 m_rrd.antenna = m_deviceToAntenna.find(rrdDevice)->second;
316 m_rrd.spectrumModel);
318 ConfigurePropagationModelsFactories(
323NrRadioEnvironmentMapHelper::ConfigureRtdList(
const NetDeviceContainer& rtdDevs)
325 NS_LOG_FUNCTION(
this);
327 for (NetDeviceContainer::Iterator netDevIt = rtdDevs.Begin(); netDevIt != rtdDevs.End();
330 Ptr<NrPhy> rtdPhy = m_rtdDeviceToPhy.find(*netDevIt)->second;
331 if (rtdPhy->GetSpectrumModel() != m_rrd.spectrumModel)
333 if (rtdPhy->GetSpectrumModel()->IsOrthogonal(*m_rrd.spectrumModel))
335 NS_LOG_WARN(
"RTD device is configured to operate on a spectrum "
336 "that is orthogonal to the one of RRD device. Hence, "
337 "that RTD device will not be considered in the "
338 "calculation of this REM map.");
343 NS_LOG_WARN(
"RTD device with different spectrum model, this may slow "
344 "down significantly the REM map creation. Consider setting "
345 "the same frequency, bandwidth, and numerology to all "
346 "devices which are used for REM map creation.");
352 rtd.spectrumModel = rtdPhy->GetSpectrumModel();
353 rtd.mob->SetPosition((*netDevIt)->GetNode()->GetObject<MobilityModel>()->GetPosition());
354 Ptr<MobilityBuildingInfo> buildingInfo = CreateObject<MobilityBuildingInfo>();
355 rtd.mob->AggregateObject(buildingInfo);
357 rtd.antenna = m_deviceToAntenna.find(*netDevIt)->second;
359 rtd.txPower = rtdPhy->GetTxPower();
361 NS_LOG_DEBUG(
"power of UE: " << rtd.txPower);
363 NS_LOG_INFO(
"RTD spectrum model: "
364 << rtd.spectrumModel->GetUid() <<
", RTD number of bands: "
365 << rtd.spectrumModel->GetNumBands() <<
", create new RTD element... "
366 <<
", rtdPhy->GetCentralFrequency () " << rtdPhy->GetCentralFrequency() / 1e6
369 ", num: " << rtdPhy->GetNumerology());
371 m_remDev.push_back(rtd);
373 NS_ASSERT_MSG(!m_remDev.empty(),
374 "No RTD devices configured. Check if the RTD "
375 "devices are on the operating on the same "
376 "spectrum as RRD device.");
380NrRadioEnvironmentMapHelper::ConfigurePropagationModelsFactories(
const Ptr<const NrPhy>& rtdPhy)
382 NS_LOG_FUNCTION(
this);
383 Ptr<const NrSpectrumPhy> txSpectrumPhy = rtdPhy->GetSpectrumPhy();
384 Ptr<SpectrumChannel> txSpectrumChannel = txSpectrumPhy->GetSpectrumChannel();
387 m_propagationLossModel = txSpectrumChannel->GetPropagationLossModel();
389 m_phasedArraySpectrumLossModel =
390 txSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel();
394 Ptr<ThreeGppPropagationLossModel> propagationLossModel =
395 DynamicCast<ThreeGppPropagationLossModel>(txSpectrumChannel->GetPropagationLossModel());
396 if (propagationLossModel)
398 Ptr<ChannelConditionModel> channelConditionModel =
399 propagationLossModel->GetChannelConditionModel();
400 if (channelConditionModel)
402 m_channelConditionModelFactory = ConfigureObjectFactory(channelConditionModel);
407 "ThreeGppPropagationLossModel does not have configured ChannelConditionModel");
412 NS_LOG_WARN(
"RemHelper currently only knows that ThreeGppPropagationLossModel can have "
413 "ChannelConditionModel. Other models do not support it yet.");
418 Ptr<ThreeGppSpectrumPropagationLossModel> spectrumLossModel =
419 DynamicCast<ThreeGppSpectrumPropagationLossModel>(
420 txSpectrumChannel->GetPhasedArraySpectrumPropagationLossModel());
421 if (spectrumLossModel)
423 if (spectrumLossModel->GetChannelModel())
425 m_matrixBasedChannelModelFactory =
426 ConfigureObjectFactory(spectrumLossModel->GetChannelModel());
430 NS_FATAL_ERROR(
"ThreeGppSpectrumPropagationLossModel does not have configured "
431 "MatrixBasedChannelModel");
436 NS_LOG_WARN(
"RemHelper currently only knows that ThreeGppSpectrumPropagationLossModel can "
437 "have MatrixBasedChannelModel. Other models do not support it yet.");
442NrRadioEnvironmentMapHelper::ConfigureObjectFactory(
const Ptr<Object>&
object)
const
444 NS_LOG_FUNCTION(
this);
445 ObjectFactory objectFactory;
446 TypeId tid =
object->GetInstanceTypeId();
447 objectFactory.SetTypeId(object->GetInstanceTypeId());
449 NS_LOG_DEBUG(
"Configure object factory for:" << tid.GetName());
451 bool hasParent =
false;
454 for (
size_t i = 0; i < tid.GetAttributeN(); i++)
456 ns3::TypeId::AttributeInformation attributeInfo = tid.GetAttribute(i);
458 if (attributeInfo.checker->GetValueTypeName() ==
"ns3::PointerValue")
460 if (attributeInfo.name ==
"ChannelConditionModel")
462 NS_LOG_INFO(
"Skipping to copy ChannelConditionModel."
463 "According to REM design it should be created "
464 "as a new object (not copied).");
466 else if (attributeInfo.name ==
"ChannelModel")
468 NS_LOG_INFO(
"Skipping to copy ChannelModel."
469 "According to REM design it should be created "
470 "as a new object (not copied).");
474 NS_LOG_WARN(
"This factory has a PointerValue attribute that "
475 "is not compatible with this REM helper version.");
481 Ptr<AttributeValue> attributeValue = attributeInfo.checker->Create();
483 object->GetAttribute(attributeInfo.name, *attributeValue);
485 objectFactory.Set(attributeInfo.name, *attributeValue);
487 NS_LOG_DEBUG(
"Copy attribute: "
488 << attributeInfo.name
489 <<
" value:" << attributeValue->SerializeToString(attributeInfo.checker));
494 tid = tid.GetParent();
502 return objectFactory;
507 const Ptr<NetDevice>& rrdDevice,
510 NS_LOG_FUNCTION(
this);
512 for (NetDeviceContainer::Iterator netDevIt = rtdNetDev.Begin(); netDevIt != rtdNetDev.End();
515 Ptr<NrGnbNetDevice> gnbRtdNetDevice = DynamicCast<NrGnbNetDevice>(*netDevIt);
516 Ptr<NrUeNetDevice> ueRtdNetDevice = DynamicCast<NrUeNetDevice>(*netDevIt);
520 std::cout <<
"gnb is RTD (transmitter)" << std::endl;
521 m_rtdDeviceToPhy.insert(
522 std::make_pair(*netDevIt, (*netDevIt)->GetObject<
NrGnbNetDevice>()->GetPhy(bwpId)));
524 else if (ueRtdNetDevice)
526 std::cout <<
"ue is RTD (transmitter)" << std::endl;
527 m_rtdDeviceToPhy.insert(
532 NS_FATAL_ERROR(
"no RTD device!");
536 Ptr<NrGnbNetDevice> gnbRrdNetDevice = DynamicCast<NrGnbNetDevice>(rrdDevice);
537 Ptr<NrUeNetDevice> ueRrdNetDevice = DynamicCast<NrUeNetDevice>(rrdDevice);
541 std::cout <<
"gnb is RRD (receiver)" << std::endl;
542 m_rrdPhy = (rrdDevice)->GetObject<NrGnbNetDevice>()->GetPhy(bwpId);
544 else if (ueRrdNetDevice)
546 std::cout <<
"ue is RRD (receiver)" << std::endl;
547 m_rrdPhy = (rrdDevice)->GetObject<NrUeNetDevice>()->GetPhy(bwpId);
551 NS_FATAL_ERROR(
"no RRD device!");
561 SaveAntennasWithUserDefinedBeams(rtdNetDev, rrdDevice);
563 Simulator::Schedule(m_installationDelay,
564 &NrRadioEnvironmentMapHelper::DelayedInstall,
571NrRadioEnvironmentMapHelper::SaveAntennasWithUserDefinedBeams(
const NetDeviceContainer& rtdNetDev,
572 const Ptr<NetDevice>& rrdDevice)
574 m_deviceToAntenna.insert(std::make_pair(
576 Copy(m_rrdPhy->GetSpectrumPhy()->GetAntenna()->GetObject<UniformPlanarArray>())));
577 for (NetDeviceContainer::Iterator rtdNetDevIt = rtdNetDev.Begin();
578 rtdNetDevIt != rtdNetDev.End();
581 Ptr<NrPhy> rtdPhy = m_rtdDeviceToPhy.find(*rtdNetDevIt)->second;
582 m_deviceToAntenna.insert(std::make_pair(
584 Copy(rtdPhy->GetSpectrumPhy()->GetAntenna()->GetObject<UniformPlanarArray>())));
589NrRadioEnvironmentMapHelper::DelayedInstall(
const NetDeviceContainer& rtdNetDev,
590 const Ptr<NetDevice>& rrdDevice)
592 NS_LOG_FUNCTION(
this);
594 m_remStartTime = std::chrono::system_clock::now();
596 ConfigureRrd(rrdDevice);
597 ConfigureRtdList(rtdNetDev);
598 CreateListOfRemPoints();
599 if (m_remMode == COVERAGE_AREA)
601 CalcCoverageAreaRemMap();
603 else if (m_remMode == BEAM_SHAPE)
605 CalcBeamShapeRemMap();
607 else if (m_remMode == UE_COVERAGE)
609 CalcUeCoverageRemMap();
613 NS_FATAL_ERROR(
"Unknown REM mode");
617 std::ostringstream ossGnbs;
618 ossGnbs <<
"nr-rem-" << m_simTag.c_str() <<
"-gnbs.txt";
619 PrintGnuplottableGnbListToFile(ossGnbs.str());
620 std::ostringstream ossBuildings;
621 ossBuildings <<
"nr-rem-" << m_simTag.c_str() <<
"-buildings.txt";
622 PrintGnuplottableBuildingListToFile(ossBuildings.str());
626NrRadioEnvironmentMapHelper::CreateListOfRemPoints()
628 NS_LOG_FUNCTION(
this);
632 m_xStep = (m_xMax - m_xMin) / (m_xRes);
633 m_yStep = (m_yMax - m_yMin) / (m_yRes);
635 NS_ASSERT_MSG(m_xMax > m_xMin,
"xMax must be higher than xMin");
636 NS_ASSERT_MSG(m_yMax > m_yMin,
"yMax must be higher than yMin");
637 NS_ASSERT_MSG(m_xRes != 0 || m_yRes != 0,
"Resolution must be higher than 0");
639 NS_LOG_INFO(
"m_xStep: " << m_xStep <<
" m_yStep: " << m_yStep);
641 for (
double x = m_xMin; x < m_xMax + 0.5 * m_xStep; x += m_xStep)
643 for (
double y = m_yMin; y < m_yMax + 0.5 * m_yStep; y += m_yStep)
646 bool isPositionRtd =
false;
647 for (
auto& itRtd : m_remDev)
649 if (itRtd.mob->GetPosition() == Vector(x, y, m_z))
651 isPositionRtd =
true;
661 remPoint.pos.z = m_z;
663 m_rem.push_back(remPoint);
670NrRadioEnvironmentMapHelper::ConfigureQuasiOmniBfv(RemDevice& device)
672 NS_LOG_FUNCTION(
this);
674 UintegerValue numRows;
675 UintegerValue numColumns;
676 device.antenna->GetAttribute(
"NumRows", numRows);
677 device.antenna->GetAttribute(
"NumColumns", numColumns);
683NrRadioEnvironmentMapHelper::ConfigureDirectPathBfv(RemDevice& device,
684 const RemDevice& otherDevice,
685 const Ptr<const UniformPlanarArray>& antenna)
687 NS_LOG_FUNCTION(
this);
688 device.antenna->SetBeamformingVector(CreateDirectPathBfv(device.mob, otherDevice.mob, antenna));
692NrRadioEnvironmentMapHelper::CalcRxPsdValue(RemDevice& device, RemDevice& otherDevice)
const
694 PropagationModels tempPropModels = CreateTemporalPropagationModels();
696 std::vector<int> activeRbs;
697 for (
size_t rbId = 0; rbId < device.spectrumModel->GetNumBands(); rbId++)
699 activeRbs.push_back(rbId);
705 device.spectrumModel,
706 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW);
712 Ptr<const SpectrumValue> convertedTxPsd;
713 if (device.spectrumModel->GetUid() == otherDevice.spectrumModel->GetUid())
715 NS_LOG_LOGIC(
"no spectrum conversion needed");
716 convertedTxPsd = txPsd;
720 NS_LOG_LOGIC(
"Converting TXPSD of RTD device " << device.spectrumModel->GetUid() <<
" --> "
721 << otherDevice.spectrumModel->GetUid());
723 SpectrumConverter converter(device.spectrumModel, otherDevice.spectrumModel);
724 convertedTxPsd = converter.Convert(txPsd);
728 Ptr<SpectrumSignalParameters> rxParams = Create<SpectrumSignalParameters>();
729 rxParams->psd = convertedTxPsd->Copy();
731 tempPropModels.remPropagationLossModelCopy->CalcRxPower(0, device.mob, otherDevice.mob);
732 double pathGainLinear =
DbToRatio(pathLossDb);
734 NS_LOG_DEBUG(
"Tx power in dBm:" <<
WToDbm(Integral(*convertedTxPsd)));
735 NS_LOG_DEBUG(
"PathlosDb:" << pathLossDb);
738 *(rxParams->psd) *= pathGainLinear;
740 NS_LOG_DEBUG(
"RX power in dBm after pathloss:" <<
WToDbm(Integral(*(rxParams->psd))));
744 tempPropModels.remSpectrumLossModelCopy->DoCalcRxPowerSpectralDensity(rxParams,
748 otherDevice.antenna);
750 NS_LOG_DEBUG(
"RX power in dBm after fading: " <<
WToDbm(Integral(*(rxParams->psd))));
752 return rxParams->psd;
756NrRadioEnvironmentMapHelper::GetMaxValue(
const std::list<Ptr<SpectrumValue>>& values)
const
759 NS_ABORT_MSG_IF(values.empty(),
"Must provide a list of values.");
761 Ptr<SpectrumValue> maxValue = Create<SpectrumValue>(m_rrd.spectrumModel);
762 *maxValue = **(values.begin());
764 for (
const auto& value : values)
766 if (Sum(*(value)) > Sum(*(maxValue)))
775NrRadioEnvironmentMapHelper::CalculateMaxSnr(
776 const std::list<Ptr<SpectrumValue>>& receivedPowerList)
const
778 Ptr<SpectrumValue> maxSnr = GetMaxValue(receivedPowerList);
779 SpectrumValue snr = (*maxSnr) / (*m_noisePsd);
780 return RatioToDb(Sum(snr) / snr.GetSpectrumModel()->GetNumBands());
784NrRadioEnvironmentMapHelper::CalculateSnr(
const Ptr<SpectrumValue>& usefulSignal)
const
786 SpectrumValue snr = (*usefulSignal) / (*m_noisePsd);
788 return RatioToDb(Sum(snr) / snr.GetSpectrumModel()->GetNumBands());
792NrRadioEnvironmentMapHelper::CalculateSinr(
793 const Ptr<SpectrumValue>& usefulSignal,
794 const std::list<Ptr<SpectrumValue>>& interferenceSignals)
const
796 Ptr<SpectrumValue> interferencePsd =
nullptr;
798 if (interferenceSignals.empty())
800 return CalculateSnr(usefulSignal);
804 interferencePsd = Create<SpectrumValue>(m_rrd.spectrumModel);
808 for (
auto rxInterfPower : interferenceSignals)
810 *interferencePsd += (*rxInterfPower);
814 SpectrumValue sinr = (*usefulSignal) / (*interferencePsd + *m_noisePsd);
817 return RatioToDb(Sum(sinr) / sinr.GetSpectrumModel()->GetNumBands());
821NrRadioEnvironmentMapHelper::CalculateSir(
822 const Ptr<SpectrumValue>& usefulSignal,
823 const std::list<Ptr<SpectrumValue>>& interferenceSignals)
const
825 Ptr<SpectrumValue> interferencePsd =
nullptr;
827 if (interferenceSignals.empty())
830 SpectrumValue signal = (*usefulSignal);
831 return RatioToDb(Sum(signal) / signal.GetSpectrumModel()->GetNumBands());
835 interferencePsd = Create<SpectrumValue>(m_rrd.spectrumModel);
839 for (
auto rxInterfPower : interferenceSignals)
841 *interferencePsd += (*rxInterfPower);
845 SpectrumValue sir = (*usefulSignal) / (*interferencePsd);
848 return RatioToDb(Sum(sir) / sir.GetSpectrumModel()->GetNumBands());
852NrRadioEnvironmentMapHelper::CalculateMaxSinr(
853 const std::list<Ptr<SpectrumValue>>& receivedPowerList)
const
857 std::list<double> sinrList;
859 for (std::list<Ptr<SpectrumValue>>::const_iterator it = receivedPowerList.begin();
860 it != receivedPowerList.end();
864 std::list<Ptr<SpectrumValue>> interferenceSignals;
865 std::list<Ptr<SpectrumValue>>::const_iterator tempit = it;
867 if (it != receivedPowerList.begin())
869 interferenceSignals.insert(interferenceSignals.begin(), receivedPowerList.begin(), it);
872 interferenceSignals.insert(interferenceSignals.end(), ++tempit, receivedPowerList.end());
873 NS_ASSERT(interferenceSignals.size() == receivedPowerList.size() - 1);
874 sinrList.push_back(CalculateSinr(*it, interferenceSignals));
876 return GetMaxValue(sinrList);
880NrRadioEnvironmentMapHelper::CalculateMaxSir(
881 const std::list<Ptr<SpectrumValue>>& receivedPowerList)
const
885 std::list<double> sirList;
887 for (std::list<Ptr<SpectrumValue>>::const_iterator it = receivedPowerList.begin();
888 it != receivedPowerList.end();
892 std::list<Ptr<SpectrumValue>> interferenceSignals;
893 std::list<Ptr<SpectrumValue>>::const_iterator tempit = it;
895 if (it != receivedPowerList.begin())
897 interferenceSignals.insert(interferenceSignals.begin(), receivedPowerList.begin(), it);
900 interferenceSignals.insert(interferenceSignals.end(), ++tempit, receivedPowerList.end());
901 NS_ASSERT(interferenceSignals.size() == receivedPowerList.size() - 1);
902 sirList.push_back(CalculateSir(*it, interferenceSignals));
904 return GetMaxValue(sirList);
908NrRadioEnvironmentMapHelper::CalcBeamShapeRemMap()
910 NS_LOG_FUNCTION(
this);
912 uint32_t remSizeNextReport = m_rem.size() / 100;
913 uint32_t remPointCounter = 0;
915 for (std::list<RemPoint>::iterator itRemPoint = m_rem.begin(); itRemPoint != m_rem.end();
920 double sumSinr = 0.0;
922 std::list<double> rxPsdsListPerIt;
924 m_rrd.mob->SetPosition(itRemPoint->pos);
926 Ptr<MobilityBuildingInfo> buildingInfo = m_rrd.mob->GetObject<MobilityBuildingInfo>();
927 buildingInfo->MakeConsistent(m_rrd.mob);
928 NS_ASSERT_MSG(buildingInfo,
"buildingInfo is null");
930 for (uint16_t i = 0; i < m_numOfIterationsToAverage; i++)
932 std::list<Ptr<SpectrumValue>>
935 for (
auto& itRtd : m_remDev)
938 receivedPowerList.push_back(CalcRxPsdValue(itRtd, m_rrd));
941 sumSnr += CalculateMaxSnr(receivedPowerList);
942 sumSinr += CalculateMaxSinr(receivedPowerList);
943 sumSir += CalculateMaxSir(receivedPowerList);
947 rxPsdsListPerIt.push_back(CalculateAggregatedIpsd(receivedPowerList));
949 receivedPowerList.clear();
953 double rxPsdsAllIt = SumListElements(rxPsdsListPerIt);
955 itRemPoint->avgSnrDb = sumSnr /
static_cast<double>(m_numOfIterationsToAverage);
956 itRemPoint->avgSinrDb = sumSinr /
static_cast<double>(m_numOfIterationsToAverage);
957 itRemPoint->avgSirDb = sumSir /
static_cast<double>(m_numOfIterationsToAverage);
959 itRemPoint->avRxPowerDbm =
960 WToDbm(rxPsdsAllIt /
static_cast<double>(m_numOfIterationsToAverage));
962 NS_LOG_INFO(
"Avg snr value saved:" << itRemPoint->avgSnrDb);
963 NS_LOG_INFO(
"Avg sinr value saved:" << itRemPoint->avgSinrDb);
964 NS_LOG_INFO(
"Avg ipsd value saved (dBm):" << itRemPoint->avRxPowerDbm);
966 if (++remPointCounter == remSizeNextReport)
968 PrintProgressReport(&remSizeNextReport);
973 auto remEndTime = std::chrono::system_clock::now();
974 std::chrono::duration<double> remElapsedSeconds = remEndTime - m_remStartTime;
975 NS_LOG_INFO(
"REM map created. Total time needed to create the REM map:"
976 << remElapsedSeconds.count() / 60 <<
" minutes.");
980NrRadioEnvironmentMapHelper::GetMaxValue(
const std::list<double>& listOfValues)
const
982 NS_ABORT_MSG_IF(listOfValues.empty(),
983 "GetMaxValue should not be called "
984 "with an empty list.");
986 double maxValue = *(listOfValues.begin());
988 for (
auto it = ++listOfValues.begin(); it != listOfValues.end(); ++it)
999NrRadioEnvironmentMapHelper::CalculateAggregatedIpsd(
1000 const std::list<Ptr<SpectrumValue>>& receivedSignals)
1002 Ptr<SpectrumValue> sumRxPowers =
nullptr;
1003 sumRxPowers = Create<SpectrumValue>(m_rrd.spectrumModel);
1006 for (
auto rxPowersIt : receivedSignals)
1008 *sumRxPowers += (*rxPowersIt);
1011 SpectrumValue sumRxPowersSv = (*sumRxPowers);
1013 return (Integral(sumRxPowersSv));
1017NrRadioEnvironmentMapHelper::SumListElements(
const std::list<double>& listOfValues)
1019 NS_ABORT_MSG_IF(listOfValues.empty(),
1020 "SumListElements should not be called "
1021 "with an empty list.");
1025 for (
double listOfValue : listOfValues)
1033NrRadioEnvironmentMapHelper::CalcCoverageAreaRemMap()
1035 NS_LOG_FUNCTION(
this);
1036 uint16_t calcRxPsdCounter = 0;
1037 uint32_t remSizeNextReport = m_rem.size() / 100;
1038 uint32_t remPointCounter = 0;
1040 for (std::list<RemPoint>::iterator itRemPoint = m_rem.begin(); itRemPoint != m_rem.end();
1044 double sumSnr = 0.0;
1045 double sumSinr = 0.0;
1046 m_rrd.mob->SetPosition(itRemPoint->pos);
1050 for (
auto& itRtd : m_remDev)
1052 ConfigureDirectPathBfv(itRtd, m_rrd, itRtd.antenna);
1055 std::list<double> rxPsdsListPerIt;
1058 for (uint16_t i = 0; i < m_numOfIterationsToAverage; i++)
1060 std::list<double> sinrsPerBeam;
1061 std::list<double> snrsPerBeam;
1063 std::list<Ptr<SpectrumValue>> rxPsdsList;
1068 for (std::list<RemDevice>::iterator itRtdBeam = m_remDev.begin();
1069 itRtdBeam != m_remDev.end();
1073 ConfigureDirectPathBfv(m_rrd, *itRtdBeam, m_rrd.antenna);
1076 Ptr<SpectrumValue> receivedPowerFromRtd = CalcRxPsdValue(*itRtdBeam, m_rrd);
1079 rxPsdsList.push_back(receivedPowerFromRtd);
1081 NS_LOG_DEBUG(
"beam node: " << itRtdBeam->dev->GetNode()->GetId()
1082 <<
" is Rxed in RemPoint with Rx Power in W: "
1083 << (Integral(*receivedPowerFromRtd)));
1084 NS_LOG_DEBUG(
"RxPower in dBm: " <<
WToDbm(Integral(*receivedPowerFromRtd)));
1086 std::list<Ptr<SpectrumValue>> interferenceSignalsRxPsds;
1087 Ptr<SpectrumValue> usefulSignalRxPsd;
1092 for (
auto& itRtdCalc : m_remDev)
1097 Ptr<SpectrumValue> receivedPower = CalcRxPsdValue(itRtdCalc, m_rrd);
1102 if (itRtdBeam->dev->GetNode()->GetId() == itRtdCalc.dev->GetNode()->GetId())
1104 if (usefulSignalRxPsd !=
nullptr)
1106 NS_FATAL_ERROR(
"Already assigned usefulSignal!");
1108 usefulSignalRxPsd = receivedPower;
1112 interferenceSignalsRxPsds.push_back(receivedPower);
1117 sinrsPerBeam.push_back(CalculateSinr(usefulSignalRxPsd, interferenceSignalsRxPsds));
1118 snrsPerBeam.push_back(CalculateSnr(usefulSignalRxPsd));
1120 NS_LOG_INFO(
"Done:" << (
double)calcRxPsdCounter /
1121 (m_rem.size() * m_numOfIterationsToAverage *
1122 m_remDev.size() * m_remDev.size()) *
1128 sumSnr += GetMaxValue(snrsPerBeam);
1129 sumSinr += GetMaxValue(sinrsPerBeam);
1133 rxPsdsListPerIt.push_back(CalculateAggregatedIpsd(rxPsdsList));
1138 double rxPsdsAllIt = SumListElements(rxPsdsListPerIt);
1140 itRemPoint->avgSnrDb = sumSnr /
static_cast<double>(m_numOfIterationsToAverage);
1141 itRemPoint->avgSinrDb = sumSinr /
static_cast<double>(m_numOfIterationsToAverage);
1143 itRemPoint->avRxPowerDbm =
1144 WToDbm(rxPsdsAllIt /
static_cast<double>(m_numOfIterationsToAverage));
1146 if (++remPointCounter == remSizeNextReport)
1148 PrintProgressReport(&remSizeNextReport);
1151 NS_LOG_DEBUG(
"itRemPoint->avRxPowerDb in dB: " << itRemPoint->avRxPowerDbm);
1155 auto remEndTime = std::chrono::system_clock::now();
1156 std::chrono::duration<double> remElapsedSeconds = remEndTime - m_remStartTime;
1157 NS_LOG_INFO(
"REM map created. Total time needed to create the REM map:"
1158 << remElapsedSeconds.count() / 60 <<
" minutes.");
1162NrRadioEnvironmentMapHelper::PrintProgressReport(uint32_t* remSizeNextReport)
1164 auto remTimeUpToNow = std::chrono::system_clock::now();
1165 std::chrono::duration<double> remElapsedSecondsUpToNow = remTimeUpToNow - m_remStartTime;
1166 double minutesUpToNow = ((double)remElapsedSecondsUpToNow.count()) / 60;
1167 double minutesLeftEstimated =
1168 ((double)(minutesUpToNow) / *remSizeNextReport) * ((m_rem.size() - *remSizeNextReport));
1169 std::cout <<
"\n REM done:" << ceil(((
double)*remSizeNextReport / m_rem.size()) * 100) <<
" %."
1170 <<
" Minutes up to now: " << minutesUpToNow
1171 <<
". Minutes left estimated:" << minutesLeftEstimated
1174 if (*remSizeNextReport < m_rem.size() / 10)
1176 *remSizeNextReport = m_rem.size() / 10;
1180 *remSizeNextReport += m_rem.size() / 10;
1185NrRadioEnvironmentMapHelper::CalcUeCoverageRemMap()
1187 NS_LOG_FUNCTION(
this);
1189 uint32_t remSizeNextReport = m_rem.size() / 100;
1190 uint32_t remPointCounter = 0;
1192 for (
auto& itRemPoint : m_rem)
1195 double sumSnr = 0.0;
1196 double sumSinr = 0.0;
1197 m_rrd.mob->SetPosition(itRemPoint.pos);
1199 for (uint16_t i = 0; i < m_numOfIterationsToAverage; i++)
1201 std::list<double> sinrsPerBeam;
1202 std::list<double> snrsPerBeam;
1205 for (
auto& itRtdAssociated : m_remDev)
1208 ConfigureDirectPathBfv(m_rrd, itRtdAssociated, m_rrd.antenna);
1210 ConfigureDirectPathBfv(itRtdAssociated, m_rrd, itRtdAssociated.antenna);
1212 std::list<Ptr<SpectrumValue>> interferenceSignalsRxPsds;
1213 Ptr<SpectrumValue> usefulSignalRxPsd;
1215 for (
auto& itRtdInterferer : m_remDev)
1217 if (itRtdAssociated.dev->GetNode()->GetId() !=
1218 itRtdInterferer.dev->GetNode()->GetId())
1221 ConfigureDirectPathBfv(itRtdInterferer,
1223 itRtdInterferer.antenna);
1226 Ptr<SpectrumValue> receivedPower =
1227 CalcRxPsdValue(itRtdInterferer, itRtdAssociated);
1229 interferenceSignalsRxPsds.push_back(receivedPower);
1234 Ptr<SpectrumValue> receivedPower = CalcRxPsdValue(m_rrd, itRtdAssociated);
1235 if (usefulSignalRxPsd !=
nullptr)
1237 NS_FATAL_ERROR(
"Already assigned usefulSignal!");
1239 usefulSignalRxPsd = receivedPower;
1244 sinrsPerBeam.push_back(CalculateSinr(usefulSignalRxPsd, interferenceSignalsRxPsds));
1245 snrsPerBeam.push_back(CalculateSnr(usefulSignalRxPsd));
1249 sumSnr += GetMaxValue(snrsPerBeam);
1250 sumSinr += GetMaxValue(sinrsPerBeam);
1254 itRemPoint.avgSnrDb = sumSnr /
static_cast<double>(m_numOfIterationsToAverage);
1255 itRemPoint.avgSinrDb = sumSinr /
static_cast<double>(m_numOfIterationsToAverage);
1257 if (++remPointCounter == remSizeNextReport)
1259 PrintProgressReport(&remSizeNextReport);
1264 auto remEndTime = std::chrono::system_clock::now();
1265 std::chrono::duration<double> remElapsedSeconds = remEndTime - m_remStartTime;
1266 NS_LOG_INFO(
"REM map created. Total time needed to create the REM map:"
1267 << remElapsedSeconds.count() / 60 <<
" minutes.");
1270NrRadioEnvironmentMapHelper::PropagationModels
1271NrRadioEnvironmentMapHelper::CreateTemporalPropagationModels()
const
1273 NS_LOG_FUNCTION(
this);
1275 PropagationModels propModels;
1277 Ptr<ChannelConditionModel> condModelCopy =
1278 m_channelConditionModelFactory.Create<ChannelConditionModel>();
1281 ObjectFactory propLossModelFactory = ConfigureObjectFactory(m_propagationLossModel);
1282 propModels.remPropagationLossModelCopy =
1283 propLossModelFactory.Create<ThreeGppPropagationLossModel>();
1284 propModels.remPropagationLossModelCopy->SetChannelConditionModel(condModelCopy);
1287 ObjectFactory spectrumLossModelFactory = ConfigureObjectFactory(m_phasedArraySpectrumLossModel);
1288 if (spectrumLossModelFactory.IsTypeIdSet())
1290 Ptr<MatrixBasedChannelModel> channelModelCopy =
1291 m_matrixBasedChannelModelFactory.Create<MatrixBasedChannelModel>();
1292 channelModelCopy->SetAttribute(
"ChannelConditionModel", PointerValue(condModelCopy));
1293 spectrumLossModelFactory.Set(
"ChannelModel", PointerValue(channelModelCopy));
1294 propModels.remSpectrumLossModelCopy =
1295 spectrumLossModelFactory.Create<ThreeGppSpectrumPropagationLossModel>();
1301NrRadioEnvironmentMapHelper::PrintGnuplottableGnbListToFile(
const std::string& filename)
1303 NS_LOG_FUNCTION(
this);
1304 std::ofstream gnbOutFile;
1305 gnbOutFile.open(filename.c_str(), std::ios_base::out | std::ios_base::trunc);
1306 if (!gnbOutFile.is_open())
1308 NS_LOG_ERROR(
"Can't open file " << filename);
1312 for (
auto& itRtd : m_remDev)
1314 Vector pos = itRtd.dev->GetNode()->GetObject<MobilityModel>()->GetPosition();
1316 gnbOutFile <<
"set label \"" << itRtd.dev->GetNode()->GetId() <<
"\" at " << pos.x <<
","
1318 <<
" left font \"Helvetica,4\" textcolor rgb \"white\" front point pt 2 ps 1 "
1319 "lc rgb \"white\" offset 0,0"
1327NrRadioEnvironmentMapHelper::PrintGnuplottableUeListToFile(
const std::string& filename)
1329 NS_LOG_FUNCTION(
this);
1330 std::ofstream ueOutFile;
1331 ueOutFile.open(filename.c_str(), std::ios_base::out | std::ios_base::trunc);
1332 if (!ueOutFile.is_open())
1334 NS_LOG_ERROR(
"Can't open file " << filename);
1338 Vector pos = m_rrd.node->GetObject<MobilityModel>()->GetPosition();
1340 ueOutFile <<
"set label \"" << m_rrd.dev->GetNode()->GetId() <<
"\" at " << pos.x <<
","
1342 <<
" left font \"Helvetica,4\" textcolor rgb \"grey\" front point pt 1 ps 1 lc rgb "
1343 "\"grey\" offset 0,0"
1350NrRadioEnvironmentMapHelper::PrintGnuplottableBuildingListToFile(
const std::string& filename)
1352 NS_LOG_FUNCTION(
this);
1353 std::ofstream outFile;
1354 outFile.open(filename.c_str(), std::ios_base::out | std::ios_base::trunc);
1355 if (!outFile.is_open())
1357 NS_LOG_ERROR(
"Can't open file " << filename);
1363 for (BuildingList::Iterator it = BuildingList::Begin(); it != BuildingList::End(); ++it)
1366 Box box = (*it)->GetBoundaries();
1367 outFile <<
"set object " << index <<
" rect from " << box.xMin <<
"," << box.yMin <<
" to "
1368 << box.xMax <<
"," << box.yMax <<
" front fs empty "
1369 <<
" border 3 " << std::endl;
1376NrRadioEnvironmentMapHelper::PrintRemToFile()
1378 NS_LOG_FUNCTION(
this);
1380 std::ostringstream oss;
1381 oss <<
"nr-rem-" << m_simTag.c_str() <<
".out";
1383 std::ofstream outFile;
1384 std::string outputFile = oss.str();
1385 outFile.open(outputFile.c_str());
1387 if (!outFile.is_open())
1389 NS_FATAL_ERROR(
"Can't open file " << (outputFile));
1393 for (
auto& it : m_rem)
1395 outFile << it.pos.x <<
"\t" << it.pos.y <<
"\t" << it.pos.z <<
"\t" << it.avgSnrDb <<
"\t"
1396 << it.avgSinrDb <<
"\t" << it.avRxPowerDbm <<
"\t" << it.avgSirDb <<
"\t"
1402 CreateCustomGnuplotFile();
1407NrRadioEnvironmentMapHelper::CreateCustomGnuplotFile()
1409 NS_LOG_FUNCTION(
this);
1410 std::ostringstream oss;
1411 oss <<
"nr-rem-" << m_simTag.c_str() <<
"-plot-rem.gnuplot";
1412 std::string filename = oss.str();
1414 std::ofstream outFile;
1415 outFile.open(filename.c_str(), std::ios_base::out | std::ios_base::trunc);
1416 if (!outFile.is_open())
1418 NS_LOG_ERROR(
"Can't open file " << filename);
1422 outFile <<
"set xlabel \"x-coordinate (m)\"" << std::endl;
1423 outFile <<
"set ylabel \"y-coordinate (m)\"" << std::endl;
1424 outFile <<
"set cblabel \"SNR (dB)\"" << std::endl;
1425 outFile <<
"set cblabel offset 3" << std::endl;
1426 outFile <<
"unset key" << std::endl;
1427 outFile <<
"set terminal png" << std::endl;
1428 outFile <<
"set output \"nr-rem-" << m_simTag <<
"-snr.png\"" << std::endl;
1429 outFile <<
"set size ratio -1" << std::endl;
1430 outFile <<
"set cbrange [-5:30]" << std::endl;
1431 outFile <<
"set xrange [" << m_xMin <<
":" << m_xMax <<
"]" << std::endl;
1432 outFile <<
"set yrange [" << m_yMin <<
":" << m_yMax <<
"]" << std::endl;
1433 outFile <<
"set xtics font \"Helvetica,17\"" << std::endl;
1434 outFile <<
"set ytics font \"Helvetica,17\"" << std::endl;
1435 outFile <<
"set cbtics font \"Helvetica,17\"" << std::endl;
1436 outFile <<
"set xlabel font \"Helvetica,17\"" << std::endl;
1437 outFile <<
"set ylabel font \"Helvetica,17\"" << std::endl;
1438 outFile <<
"set cblabel font \"Helvetica,17\"" << std::endl;
1439 outFile <<
"plot \"nr-rem-" << m_simTag <<
".out\" using ($1):($2):($4) with image"
1442 outFile <<
"set xlabel \"x-coordinate (m)\"" << std::endl;
1443 outFile <<
"set ylabel \"y-coordinate (m)\"" << std::endl;
1444 outFile <<
"set cblabel \"SINR (dB)\"" << std::endl;
1445 outFile <<
"set cblabel offset 3" << std::endl;
1446 outFile <<
"unset key" << std::endl;
1447 outFile <<
"set terminal png" << std::endl;
1448 outFile <<
"set output \"nr-rem-" << m_simTag <<
"-sinr.png\"" << std::endl;
1449 outFile <<
"set size ratio -1" << std::endl;
1450 outFile <<
"set cbrange [-5:30]" << std::endl;
1451 outFile <<
"set xrange [" << m_xMin <<
":" << m_xMax <<
"]" << std::endl;
1452 outFile <<
"set yrange [" << m_yMin <<
":" << m_yMax <<
"]" << std::endl;
1453 outFile <<
"set xtics font \"Helvetica,17\"" << std::endl;
1454 outFile <<
"set ytics font \"Helvetica,17\"" << std::endl;
1455 outFile <<
"set cbtics font \"Helvetica,17\"" << std::endl;
1456 outFile <<
"set xlabel font \"Helvetica,17\"" << std::endl;
1457 outFile <<
"set ylabel font \"Helvetica,17\"" << std::endl;
1458 outFile <<
"set cblabel font \"Helvetica,17\"" << std::endl;
1459 outFile <<
"plot \"nr-rem-" << m_simTag <<
".out\" using ($1):($2):($5) with image"
1462 outFile <<
"set xlabel \"x-coordinate (m)\"" << std::endl;
1463 outFile <<
"set ylabel \"y-coordinate (m)\"" << std::endl;
1464 outFile <<
"set cblabel \"IPSD (dBm)\"" << std::endl;
1465 outFile <<
"set cblabel offset 3" << std::endl;
1466 outFile <<
"unset key" << std::endl;
1467 outFile <<
"set terminal png" << std::endl;
1468 outFile <<
"set output \"nr-rem-" << m_simTag <<
"-ipsd.png\"" << std::endl;
1469 outFile <<
"set size ratio -1" << std::endl;
1470 outFile <<
"set cbrange [-100:-20]" << std::endl;
1471 outFile <<
"set xrange [" << m_xMin <<
":" << m_xMax <<
"]" << std::endl;
1472 outFile <<
"set yrange [" << m_yMin <<
":" << m_yMax <<
"]" << std::endl;
1473 outFile <<
"set xtics font \"Helvetica,17\"" << std::endl;
1474 outFile <<
"set ytics font \"Helvetica,17\"" << std::endl;
1475 outFile <<
"set cbtics font \"Helvetica,17\"" << std::endl;
1476 outFile <<
"set xlabel font \"Helvetica,17\"" << std::endl;
1477 outFile <<
"set ylabel font \"Helvetica,17\"" << std::endl;
1478 outFile <<
"set cblabel font \"Helvetica,17\"" << std::endl;
1479 outFile <<
"plot \"nr-rem-" << m_simTag <<
".out\" using ($1):($2):($6) with image"
1482 outFile <<
"set xlabel \"x-coordinate (m)\"" << std::endl;
1483 outFile <<
"set ylabel \"y-coordinate (m)\"" << std::endl;
1484 outFile <<
"set cblabel \"SIR (dB)\"" << std::endl;
1485 outFile <<
"set cblabel offset 3" << std::endl;
1486 outFile <<
"unset key" << std::endl;
1487 outFile <<
"set terminal png" << std::endl;
1488 outFile <<
"set output \"nr-rem-" << m_simTag <<
"-sir.png\"" << std::endl;
1489 outFile <<
"set size ratio -1" << std::endl;
1490 outFile <<
"set cbrange [-5:30]" << std::endl;
1491 outFile <<
"set xrange [" << m_xMin <<
":" << m_xMax <<
"]" << std::endl;
1492 outFile <<
"set yrange [" << m_yMin <<
":" << m_yMax <<
"]" << std::endl;
1493 outFile <<
"set xtics font \"Helvetica,17\"" << std::endl;
1494 outFile <<
"set ytics font \"Helvetica,17\"" << std::endl;
1495 outFile <<
"set cbtics font \"Helvetica,17\"" << std::endl;
1496 outFile <<
"set xlabel font \"Helvetica,17\"" << std::endl;
1497 outFile <<
"set ylabel font \"Helvetica,17\"" << std::endl;
1498 outFile <<
"set cblabel font \"Helvetica,17\"" << std::endl;
1499 outFile <<
"plot \"nr-rem-" << m_simTag <<
".out\" using ($1):($2):($7) with image"
1506NrRadioEnvironmentMapHelper::Finalize()
1508 NS_LOG_FUNCTION(
this);
The NrGnbNetDevice class.
Generate a radio environment map.
void SetMaxY(double yMax)
Sets the max y coordinate of the map.
double DbToRatio(double dB) const
Convert from dB to ratio.
void SetInstallationDelay(const Time &installationDelay)
Sets the installation delay.
void SetMinX(double xMin)
Sets the min x coordinate of the map.
double WToDbm(double w) const
Convert from Watts to dBm.
void SetNumOfItToAverage(uint16_t numOfIterationsToAverage)
Sets the number of iterations to calculate the average of rem value.
~NrRadioEnvironmentMapHelper() override
destructor
static TypeId GetTypeId()
Get the type id.
RemMode GetRemMode() const
Get the type of REM Map to be generated.
void SetZ(double z)
Sets the z coordinate of the map.
void SetMinY(double yMin)
Sets the min y coordinate of the map.
void SetMaxX(double xMax)
Sets the max x coordinate of the map.
NrRadioEnvironmentMapHelper()
NrRadioEnvironmentMapHelper constructor.
double RatioToDb(double ratio) const
Convert from ratio to dB.
void SetRemMode(enum RemMode remType)
Set the type of REM Map to be generated.
void SetResY(uint16_t yRes)
Sets the resolution (number of points) of the map along the y axis.
void SetSimTag(const std::string &simTag)
Set simTag that will be concatenated to output file names.
double DbmToW(double dbm) const
Convert from dBm to Watts.
void CreateRem(const NetDeviceContainer &rtdNetDev, const Ptr< NetDevice > &rrdDevice, uint8_t bwpId)
This function is used for the creation of the REM map. When this function is called from an example,...
void SetResX(uint16_t xRes)
Sets the resolution (number of points) of the map along the x axis.
static Ptr< SpectrumValue > CreateNoisePowerSpectralDensity(double noiseFigure, const Ptr< const SpectrumModel > &spectrumModel)
Create a SpectrumValue that models the power spectral density of AWGN.
static Ptr< SpectrumValue > CreateTxPowerSpectralDensity(double powerTx, const std::vector< int > &rbIndexVector, const Ptr< const SpectrumModel > &txSm, enum PowerAllocationType allocationType)
Create SpectrumValue that will represent transmit power spectral density, and assuming that all RBs a...
The User Equipment NetDevice.
Ptr< NrUePhy > GetPhy(uint8_t index) const
Obtain a pointer to the PHY at the index specified.
PhasedArrayModel::ComplexVector CreateQuasiOmniBfv(const Ptr< const UniformPlanarArray > &antenna)
Create a quasi omni beamforming vector.