Monte Carlo analysis for 5G
Detailed Description
This is an example of how to use 5G Monte-Carlo analysis capability with WinProp API. The full example is distributed with the installation.#include <stdio.h> #include <string> #include <iostream> #include <cstring> #include "monte_carlo_5g.h" #ifndef API_DATA_FOLDER #define API_DATA_FOLDER "../../api/winprop/data/" #endif // !API_DATA_FOLDER #define SERVICES_5G 7 #define MAX_CELLS 3 int main(int argc, char** argv) { // ------ General and Propagation and Network Planing Parameters ------ // WinProp_ParaMain GeneralParameters; WinProp_Pattern WinPropPattern; WinProp_Antenna Antenna[MAX_CELLS]; WinProp_Carrier Carrier[MAX_CELLS]; // Propagation results WinProp_Result PropResults[MAX_CELLS]; int ProjectHandle = 0, Error = 0; int ParaValueInt = 0; // to set int parameters double ParaValueDouble = 0.; // to set double parameters // Prediction heights int NrPredictionHeights = 1; double PredictionHeights[1] = {1.5}; // ---------------------- Initialisation of parameters ---------------- // WinProp_Structure_Init_ParameterMain(&GeneralParameters); WinProp_Structure_Init_Pattern(&WinPropPattern); for (int cell = 0; cell < MAX_CELLS; cell++) { WinProp_Structure_Init_Antenna(&Antenna[cell]); WinProp_Structure_Init_Carrier(&Carrier[cell]); WinProp_Structure_Init_Result(&PropResults[cell]); } // ---------------- Definition of parameters -------------------------- // // Definition of scenario. const char* my_odb_database = API_DATA_FOLDER "outdoor/Frankfurt"; // name of .odb database without extensions GeneralParameters.ScenarioMode = SCENARIOMODE_URBAN; // Urban prediction GeneralParameters.PredictionModelUrban = PREDMODEL_UDP; // Use Dominant Path Model // Definition of prediction area. GeneralParameters.UrbanLowerLeftX = 475080.0; GeneralParameters.UrbanLowerLeftY = 551860.0; GeneralParameters.UrbanUpperRightX = 476840.0; GeneralParameters.UrbanUpperRightY = 553200.0; // Copy coordinates to prediction area of second model (not yet used). GeneralParameters.RuralLowerLeftX = GeneralParameters.UrbanLowerLeftX; GeneralParameters.RuralLowerLeftY = GeneralParameters.UrbanLowerLeftY; GeneralParameters.RuralUpperRightX = GeneralParameters.UrbanUpperRightX; GeneralParameters.RuralUpperRightY = GeneralParameters.UrbanUpperRightY; // Size of matrix with results. GeneralParameters.Resolution = 10.0; // Resolution in meter GeneralParameters.NrLayers = NrPredictionHeights; // Number of prediction heights GeneralParameters.PredictionHeights = PredictionHeights; // Prediction height in meter // Building vector data and topography. GeneralParameters.BuildingsMode = BUILDINGSMODE_BINARY; // load a .odb database sprintf(GeneralParameters.BuildingsName, "%s", my_odb_database); // Antenna patten (will be used after the propagation analysis to mask the omni-propagation // predictions) WinPropPattern.Mode = PATTERN_MODE_FILE; // Load pattern from file sprintf(WinPropPattern.Filename, "%s", API_DATA_FOLDER "antennas/Beams2Control4Data.ffe"); // Pattern file // -------------------- Network Planning Project ----------------------- // // Create a new network planning project based on 5G FDD air interface if (Error == 0) { Error = WinProp_Net_Project_Open(&ProjectHandle, NET_AIRINTERFACE_5G_FDD_GENERIC, NULL); } // Set a name for the project. if (Error == 0) { char ProjectName[200]; sprintf(ProjectName, "%s", "MonteCarlo-5G"); Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_PROJECTNAME, NULL, NULL, ProjectName); } // -------------------------- Carriers -------------------------------- // // Add 3 carriers in n1 band. if (Error == 0) { double FrequencyUL = 0.; double FrequencyDL = 0.; double CarrierSeparation = 20.; for (int CurrentCarrier = 0; CurrentCarrier < 3; CurrentCarrier++) { FrequencyUL = 1930.0 + (CurrentCarrier * CarrierSeparation); FrequencyDL = 2120.0 + (CurrentCarrier * CarrierSeparation); Error = WinProp_Net_Carrier_Add(ProjectHandle, CurrentCarrier + 1); Error = WinProp_Net_Carrier_Para_Set( ProjectHandle, CurrentCarrier + 1, NET_PARA_CARRIER_FREQ_DL, &FrequencyDL, NULL, NULL); Error = WinProp_Net_Carrier_Para_Set( ProjectHandle, CurrentCarrier + 1, NET_PARA_CARRIER_FREQ_UL, &FrequencyUL, NULL, NULL); } } // Check if number of carriers is correct. if (Error == 0) { int NrCarriers = 0; Error = WinProp_Net_Project_Para_Get(ProjectHandle, NET_PARA_CARRIERS, NULL, &NrCarriers, NULL); if (Error == 0) { if (NrCarriers != 3) Error = 1; } } // -------------------------- antennas -------------------------------- // // Position and configuration of the antennas (cells). char AntennaName[MAX_CELLS][500] = { "Ant 3", "Ant 2", "Ant 1" }; double SiteX = 475500.; double SiteY = 552897.; double SiteZ = 12.; double Power = 40.; // Power in dBm double Azmith[MAX_CELLS] = { 240., 120., 0. }; // same frequencies in MHz as defined for the carriers double Frequency[MAX_CELLS] = { 2160., 2140., 2120. }; double Downtilt = 0.; int AntennaCarrier[MAX_CELLS] = { 3, 2, 1 }; if (Error == 0) { for (int cell = 0; cell < MAX_CELLS; cell++) { // Set antenna properties now. AntennaPropertiesSet( &Antenna[cell], SiteX, SiteY, SiteZ, Frequency[cell], AntennaName[cell], Power, WINPROP_POWER_OUTPUT, WINPROP_MODEL_DPM, Azmith[cell], Downtilt, cell + 1); Carrier[cell].CarrierID = AntennaCarrier[cell]; // Define two data beams for each cell (network planning analysis) Carrier[cell].NrAntennaBeams = 2; CarrierPropertiesSet(&Antenna[cell], &Carrier[cell]); } } // ------------------------- Transmission modes --------------------------- // // Define some (only 7) of the 5G transmission modes if (Error == 0) { const char* TransmissionMode_Name[SERVICES_5G] = { "00 - QPSK - R 120", "04 - QPSK - R 602", "08 - 16 QAM - R 553", "12 - 64 QAM - R 517", "18 - 64 QAM - R 822", "21 - 256 QAM - R 711", "27 - 256 QAM - R 948" }; double TransmissionMode_Bitrate[SERVICES_5G] = { 0, 0, 0, 0, 0, 0, 0 }; double TransmissionMode_SNIR[SERVICES_5G] = { -3.0, 2, 7.9, 13.0, 17.5, 22.0, 27.0 }; int TransmissionMode_Coderate_K[SERVICES_5G] = { 120, 602, 553, 517, 822, 711, 948 }; int TransmissionMode_Coderate_N[SERVICES_5G] = { 1024, 1024, 1024, 1024, 1024, 1024, 1024 }; int TransmissionMode_MCS[SERVICES_5G] = { 2, 2, 4, 6, 6, 8, 8 }; double TransmissionMode_Backoff[SERVICES_5G] = { 0.0, 0.0, 3.0, 3.0, 3.0, 3.0, 3.0 }; int TransmissionMode_Resource_Blocks_DL[SERVICES_5G] = { 1, 1, 1, 1, 1, 1, 1 }; int TransmissionMode_Resource_Blocks_UL[SERVICES_5G] = { 1, 1, 1, 1, 1, 1, 1 }; double TransmissionMode_Overhead_Ratio_DL[SERVICES_5G] = { 14., 14., 14., 14., 14., 14., 14. }; double TransmissionMode_Overhead_Ratio_UL[SERVICES_5G] = { 8., 8., 8., 8., 8., 8., 8. }; for (int CurrentService = 0; CurrentService < SERVICES_5G; CurrentService++) { // Add new service. char ServiceName[100]; sprintf(ServiceName, "%s", TransmissionMode_Name[CurrentService]); Error = WinProp_Net_TransmissionMode_Add(ProjectHandle, ServiceName, CurrentService); // Set position/priority. ParaValueInt = SERVICES_5G - CurrentService; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_POSITION, NULL, &ParaValueInt, NULL); // Set bitrate. ParaValueDouble = TransmissionMode_Bitrate[CurrentService]; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_BITRATE_DL, &ParaValueDouble, NULL, NULL); Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_BITRATE_UL, &ParaValueDouble, NULL, NULL); // Set code rate. ParaValueInt = TransmissionMode_Coderate_K[CurrentService]; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_CODERATE_K_DL, NULL, &ParaValueInt, NULL); Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_CODERATE_K_UL, NULL, &ParaValueInt, NULL); ParaValueInt = TransmissionMode_Coderate_N[CurrentService]; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_CODERATE_N_DL, NULL, &ParaValueInt, NULL); Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_CODERATE_N_UL, NULL, &ParaValueInt, NULL); // Set number of resource blocks. ParaValueInt = TransmissionMode_Resource_Blocks_DL[CurrentService]; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_RESOURCE_BLOCKS_DL, NULL, &ParaValueInt, NULL); ParaValueInt = TransmissionMode_Resource_Blocks_UL[CurrentService]; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_RESOURCE_BLOCKS_UL, NULL, &ParaValueInt, NULL); // Set overhead ratio. ParaValueDouble = TransmissionMode_Overhead_Ratio_UL[CurrentService]; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_OVERHEAD_RATIO_UL, &ParaValueDouble, NULL, NULL); ParaValueDouble = TransmissionMode_Overhead_Ratio_DL[CurrentService]; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_OVERHEAD_RATIO_DL, &ParaValueDouble, NULL, NULL); // Set required SNIR. ParaValueDouble = TransmissionMode_SNIR[CurrentService]; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_SNIR_DL, &ParaValueDouble, NULL, NULL); Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_SNIR_UL, &ParaValueDouble, NULL, NULL); // Set modulation scheme. ParaValueInt = TransmissionMode_MCS[CurrentService]; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_MODULATION_UL, NULL, &ParaValueInt, NULL); Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_MODULATION_DL, NULL, &ParaValueInt, NULL); // Set power backoff. ParaValueDouble = TransmissionMode_Backoff[CurrentService]; Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_POWER_BACKOFF_UL, &ParaValueDouble, NULL, NULL); Error = WinProp_Net_TransmissionMode_Para_Set( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_POWER_BACKOFF_DL, &ParaValueDouble, NULL, NULL); // Get bitrate in kBit/s for current transmission mode. Bitrate is automatically computed based // on parameters previously set and general air interface parameters. Error = WinProp_Net_TransmissionMode_Para_Get( ProjectHandle, CurrentService, NET_PARA_TRANS_MODE_BITRATE_DL, &ParaValueDouble, NULL, NULL); TransmissionMode_Bitrate[CurrentService] = ParaValueDouble; } } // Check if number of services is correct. if (Error == 0) { int NrServices = 0; Error = WinProp_Net_Project_Para_Get(ProjectHandle, NET_PARA_SERVICES, NULL, &NrServices, NULL); if (Error == 0) { if (NrServices != SERVICES_5G) Error = 1; } } // -------------------------- Project parameters -------------------------- // // Set MS maximum power if (Error == 0) { ParaValueDouble = 23.; // Power in dBm Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_MS_MAX_TX_POWER, &ParaValueDouble, NULL, NULL); } // Set resolution for result matrix. if (Error == 0) { ParaValueDouble = GeneralParameters.Resolution; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_RESOLUTION, &ParaValueDouble, NULL, NULL); } // set the simulation area if (Error == 0) { ParaValueDouble = GeneralParameters.UrbanLowerLeftX; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_AREA_LL_X, &ParaValueDouble, NULL, NULL); } if (Error == 0) { ParaValueDouble = GeneralParameters.UrbanLowerLeftY; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_AREA_LL_Y, &ParaValueDouble, NULL, NULL); } if (Error == 0) { ParaValueDouble = GeneralParameters.UrbanUpperRightX; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_AREA_UR_X, &ParaValueDouble, NULL, NULL); } if (Error == 0) { ParaValueDouble = GeneralParameters.UrbanUpperRightY; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_AREA_UR_Y, &ParaValueDouble, NULL, NULL); } // Set paths for additional output in WinProp file format. if (Error == 0) { Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_OUTPUT_WINPROP, NULL, NULL, API_DATA_FOLDER "output/"); } // ------------------------ Cell assignment ------------------------------ // // The default cell assignment for the selected air interface (i.e. NET_AIRINTERFACE_5G_FDD_GENERIC) // is highest power for all carries, definition of min. required SNIR and power // Set Min required SNIR if (Error == 0) { ParaValueDouble = -3.; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_CELL_ASSIGNMENT_MIN_REQ_SNIR, &ParaValueDouble, NULL, NULL); } // Set Min required power if (Error == 0) { ParaValueDouble = -95.; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_CELL_ASSIGNMENT_MIN_REQ_POWER, &ParaValueDouble, NULL, NULL); } // ------------------- numerology and masking mode ----------------------- // // Activate antenna masking for network planning results (propagation results with omni-pattern) if (Error == 0) { ParaValueInt = 1; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_ANTENNA_MASKING_MODE, NULL, &ParaValueInt, NULL); } // Set numerology and bandwidth if (Error == 0) { ParaValueInt = NET_PARA_5G_NUMEROLOGY0_20MHZ_FR1; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_BANDWIDTH_MODE_5G, NULL, &ParaValueInt, NULL); } // ----------------------- OFDM parameters -------------------------------- // // Set control sub-carriers if (Error == 0) { ParaValueInt = 1000; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_SUBCARRIERS_CONTROL, NULL, &ParaValueInt, NULL); } // Set reference sub-carriers if (Error == 0) { ParaValueInt = 200; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_SUBCARRIERS_REFERENCE, NULL, &ParaValueInt, NULL); } // Set Guard sub-carriers if (Error == 0) { ParaValueInt = 31; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_SUBCARRIERS_GUARD, NULL, &ParaValueInt, NULL); } // Set data symbols if (Error == 0) { ParaValueInt = 10; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_SYMBOLS_DATA, nullptr, &ParaValueInt, nullptr); } // Set control symbols if (Error == 0) { ParaValueInt = 1; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_SYMBOLS_CONTROL, NULL, &ParaValueInt, NULL); } // Set reference symbols if (Error == 0) { ParaValueInt = 3; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_SYMBOLS_REFERENCE, NULL, &ParaValueInt, NULL); } // Set FFT order if (Error == 0) { ParaValueInt = 2048; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_FFT_SIZE, NULL, &ParaValueInt, NULL); } // ---------------------- Monte Carlo Parameters -------------------------- // // Set traffic mode to Monte Carlo if (Error == 0) { ParaValueInt = NET_TRAFFIC_MODE_STATIC_MONTE_CARLO; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_TRAFFIC_MODE, nullptr, &ParaValueInt, nullptr); } // Set Monte Carlo max loops if (Error == 0) { ParaValueInt = 5; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_TRAFFIC_MONTE_CARLO_LOOPS, nullptr, &ParaValueInt, nullptr); } // Set users distributed per square kilometer if (Error == 0) { ParaValueInt = NET_APPLICATION_AREA_MODE_KILOMETER; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_APPLICATION_AREA_MODE, nullptr, &ParaValueInt, nullptr); } // Consider priority of an application in a cell if (Error == 0) { ParaValueInt = 1; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_TRAFFIC_CELL_SELECT_CONSIDER_PRIO, nullptr, &ParaValueInt, nullptr); } // Number of iterations for traffic simulations if (Error == 0) { ParaValueInt = 20; Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_TRAFFIC_MAX_ITERATIONS, nullptr, &ParaValueInt, nullptr); } // Add clutter from the database file if (Error == 0) { char ClutterTraffic[200]; sprintf(ClutterTraffic, "%s.odb", my_odb_database); Error = WinProp_Net_Clutter_Set(ProjectHandle, CLUTTERMODE_FILE, ClutterTraffic, false, "", nullptr); } // Add applications if (Error == 0) { int ApplID = 0; int ApplPriority = 0; float ApplActivity = 1.f; int ApplTrafficMode = NET_APPLICATION_TRAFFIC_MODE_OFFERED_TRAFFIC; const char* ApplName = "Browsing"; Error = WinProp_Net_Application_Add(ProjectHandle, ApplID, ApplPriority, ApplActivity, ApplTrafficMode, ApplName); // add traffic clutter classes to the application if (Error == 0) { int ClutterClassID = 1; // ID of clutter class 1 = corresponds to OUTDOOR clutter as defined in the data base float ArrivalRate = 0.f; // Arrival rate in 1/(km^2/s) (not relevant for NET_APPLICATION_TRAFFIC_MODE_OFFERED_TRAFFIC) float HoldTime = 0.f; // Hold Time in [sec] (not relevant for NET_APPLICATION_TRAFFIC_MODE_OFFERED_TRAFFIC) float OfferedTraffic = 50.f; // Offered Traffic in Erl/km^2 WinProp_Net_Application_ClutterClass_Link(ProjectHandle, ApplID, ClutterClassID, ArrivalRate, HoldTime, OfferedTraffic); } // add transmission modes to the application if (Error == 0) { int TransModeID = 5; // corresponds to "18 - 64 QAM - R 822" as defined above. Error = WinProp_Net_Application_TransmissionMode_Link(ProjectHandle, ApplID, TransModeID, 0); } } // Callback functions. WinProp_Callback Callback; WinProp_Structure_Init_Callback(&Callback); Callback.Percentage = CallbackProgress; Callback.Message = CallbackMessage; Callback.Error = CallbackError; //-------------------------------------------------------------------------- // Compute wave propagation for three cells //-------------------------------------------------------------------------- for (int cell = 0; cell < MAX_CELLS; cell++) { /*--------------------- Compute outdoor prediction ------------------------*/ Error = OutdoorPlugIn_ComputePrediction( &Antenna[cell], &GeneralParameters, NULL, 0, NULL, NULL, NULL, NULL, &Callback, &PropResults[cell], NULL, NULL, NULL); /*---------------------- Do something with results ------------------------*/ if (Error == 0) { char NameForOutput[200]; sprintf(NameForOutput, "%s%s%s%s", API_DATA_FOLDER, "output/", Antenna[cell].Name,".txt"); write_ascii(&PropResults[cell], NameForOutput); } else { /* Error during prediction. Print error message. */ CallbackError(GeneralParameters.ErrorMessageMain, Error); } } // Add all propagation maps which have been computed. // Set the antenna pattern for masking the already calculated omni-propagation results if (Error == 0) { int MapIndex[MAX_CELLS]; for (int Count = 0; Count < MAX_CELLS; Count++) { if (Error == 0) { // Masking mode --> set antenna pattens for network planning results Antenna[Count].Pattern = &WinPropPattern; Error = WinProp_Net_PropagationMap_Add( ProjectHandle, &MapIndex[Count], &Antenna[Count], &PropResults[Count]); } } } // Desired network planning results in WinProp result format Error = WinProp_Net_Project_Result_Switch(ProjectHandle, NET_RESULT_BEST_SERVER, 1); Error = WinProp_Net_Project_Result_Switch(ProjectHandle, NET_RESULT_MAX_DATARATE, 1); Error = WinProp_Net_Project_Result_Switch(ProjectHandle, NET_RESULT_MAX_REC_POWER, 1); Error = WinProp_Net_Project_Result_Switch(ProjectHandle, NET_RESULT_REC_POWER, 1); Error = WinProp_Net_Project_Result_Switch(ProjectHandle, NET_RESULT_SNIR, 1); Error = WinProp_Net_Project_Result_Switch(ProjectHandle, NET_RESULT_TRAFFIC_OFFERED, 1); Error = WinProp_Net_Project_Result_Switch(ProjectHandle, NET_RESULT_TRAFFIC_SERVED, 1); Error = WinProp_Net_Project_Result_Switch(ProjectHandle, NET_RESULT_TRAFFIC_BLOCKED, 1); Error = WinProp_Net_Project_Result_Switch(ProjectHandle, NET_RESULT_TRAFFIC_STATE, 1); //-------------------------------------------------------------------------- // Compute network planning results //-------------------------------------------------------------------------- if (Error == 0) { char HeightString[200]; sprintf(HeightString, "%s", ""); // Generate string with height values, e.g. a string like "1.5 2.5 3.5". for (int Height = 0; Height < NrPredictionHeights; Height++) { // Add current height to string. char thisHeightStr[50]; sprintf(thisHeightStr, "%.2f ", PredictionHeights[Height]); strcat(HeightString, thisHeightStr); } // Send heights to WinProp API. Error = WinProp_Net_Project_Para_Set(ProjectHandle, NET_PARA_HEIGHT_MULTIPLE, NULL, NULL, HeightString); // Start network computation. if (Error == 0) { Error = WinProp_Net_Project_Compute(ProjectHandle, &Callback); } } // ------------------------------------------------------------------------ // Retrieve Monte-Carlo statistics // ------------------------------------------------------------------------ if (Error == 0) { WinProp_ResultMonteCarlo* ResultMonteCarlo = NULL; Error = WinProp_Net_NetworkMonteCarloStats_Get(ProjectHandle, &ResultMonteCarlo); if (Error == 0) { char NameForOutput[200]; sprintf(NameForOutput, "%s%s", API_DATA_FOLDER, "output/MonteCarloStatistics.txt"); write_ascii_monte_carlo_statistic(ResultMonteCarlo, NameForOutput); } } // ------------------------------------------------------------------------ // Retrieve some other results // ------------------------------------------------------------------------ // As an example: retrieve max. throughput (kbps) per pixel. if (Error == 0) { WinProp_Result* MaxThroughput = NULL; Error = WinProp_Net_NetworkMap_Get(ProjectHandle, -1, NET_RESULT_MAX_THROUGHPUT, &MaxThroughput); // Write max. throughput result to ASCII file. if (Error == 0) { char NameForOutput[200]; sprintf(NameForOutput, "%s%s", API_DATA_FOLDER, "output/Max Throughput DownLink.txt"); write_ascii(MaxThroughput, NameForOutput); } } // As another example: retrieve max. received power (dBm) per pixel. if (Error == 0) { WinProp_Result* MaxPower = NULL; Error = WinProp_Net_NetworkMap_Get(ProjectHandle, -1, NET_RESULT_MAX_REC_POWER, &MaxPower); // Write max. throughput result to ASCII file. if (Error == 0) { char NameForOutput[200]; sprintf(NameForOutput, "%s%s", API_DATA_FOLDER, "output/Max Received Power.txt"); write_ascii(MaxPower, NameForOutput); } } // As another example: retrieve SNIR (dB) per pixel. if (Error == 0) { WinProp_Result* MaxSNIR = NULL; Error = WinProp_Net_NetworkMap_Get(ProjectHandle, -1, NET_RESULT_SNIR, &MaxSNIR); // Write max. throughput result to ASCII file. if (Error == 0) { char NameForOutput[200]; sprintf(NameForOutput, "%s%s", API_DATA_FOLDER, "output/Max SNIR.txt"); write_ascii(MaxSNIR, NameForOutput); } } // ------------------------------------------------------------------------ // Free memory // ------------------------------------------------------------------------ for (int Count = 0; Count < MAX_CELLS; Count++) { // Free propagation results. WinProp_FreeResult(&PropResults[Count]); } // Close network project. Error = WinProp_Net_Project_Close(ProjectHandle); return 0; } int _STD_CALL CallbackMessage(const char * Text) { if (Text == nullptr) return 0; std::cout << "\n" << Text; return(0); } int _STD_CALL CallbackError(const char * Text, int Error) { if (Text == nullptr) return 0; std::cout << "\n"; #ifdef __LINUX std::cout << "\033[31m" << "Error (" << Error << "): "; // highlight error in red color #else HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hConsole, FOREGROUND_RED); std::cout << "Error (" << Error << "): "; #endif // __LINUX std::cout << Text; #ifdef __LINUX std::cout << "\033[0m"; // highlight error in red color #else SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN); #endif // __LINUX return 0; } int _STD_CALL CallbackProgress(int value, const char* text) { char Line[200]; sprintf(Line, "\n%d%% %s", value, text); std::cout << Line; return(0); } // Helper functions void write_ascii(const WinProp_Result *Resultmatrix, const char* Filename) { if (Resultmatrix) { FILE* OutputFile = fopen(Filename, "w"); if (OutputFile) { /* Loop through WinPropall pixels. */ for (int x = 0; x < Resultmatrix->Columns; x++) { for (int y = 0; y < Resultmatrix->Lines; y++) { /* Compute real coordinates. */ double Coordinate_X = Resultmatrix->LowerLeftX + ((double)x + 0.5) * Resultmatrix->Resolution; double Coordinate_Y = Resultmatrix->LowerLeftY + ((double)y + 0.5) * Resultmatrix->Resolution; /* Check if pixel was computed or not */ if (Resultmatrix->Matrix[0][x][y] > -1000) { fprintf(OutputFile, "%.5f\t%.5f\t%.4f\n", Coordinate_X, Coordinate_Y, Resultmatrix->Matrix[0][x][y]); } else { fprintf(OutputFile, "%.5f\t%.5f\t%s\n", Coordinate_X, Coordinate_Y, "N.C."); } } } /* Close file. */ fclose(OutputFile); } else { printf("\nCould not open the File: %s for writing.\n", Filename); } } } void AntennaPropertiesSet( WinProp_Antenna *Antenna, double CoordinateX, double CoordinateY, double Height, double Frequency, const char *Name, double Power, int PowerMode, int Model, double Azimuth, double Downtilt, int Id) { Antenna->Longitude_X = CoordinateX; Antenna->Latitude_Y = CoordinateY; Antenna->Height = Height; Antenna->Power = Power; Antenna->PowerMode = PowerMode; Antenna->Frequency = Frequency; sprintf(Antenna->Name, "%s", Name); Antenna->Model = Model; Antenna->Azimuth = Azimuth; Antenna->Downtilt = Downtilt; Antenna->Id = Id; } void CarrierPropertiesSet(WinProp_Antenna *Antenna, const WinProp_Carrier *Carrier) { Antenna->Carriers.CarrierID = Carrier->CarrierID; Antenna->Carriers.SystemID = Carrier->SystemID; Antenna->Carriers.CellLoad = Carrier->CellLoad; Antenna->Carriers.MimoID = Carrier->MimoID; Antenna->Carriers.NoiseRiseUL = Carrier->NoiseRiseUL; Antenna->Carriers.PowerBackoffPilotDL = Carrier->PowerBackoffPilotDL; // 5G Carrier parameters Antenna->Carriers.Numerology = Carrier->Numerology; Antenna->Carriers.SymbolsPerSlot = Carrier->SymbolsPerSlot; Antenna->Carriers.NrAntennaBeams = Carrier->NrAntennaBeams; Antenna->Carriers.BeamGainCtrlServer = Carrier->BeamGainCtrlServer; Antenna->Carriers.BeamGainCtrlInterferer = Carrier->BeamGainCtrlInterferer; Antenna->Carriers.BeamGainDataServer = Carrier->BeamGainDataServer; Antenna->Carriers.BeamGainDataInterferer = Carrier->BeamGainDataInterferer; Antenna->Carriers.TDD_Slots_DL = Carrier->TDD_Slots_DL; Antenna->Carriers.TDD_Slots_UL = Carrier->TDD_Slots_UL; Antenna->Carriers.TDD_Slots_Flex = Carrier->TDD_Slots_Flex; } /** * Writes Monte Carlo statistics in an ASCII file * * @param [in,out] ResultMonteCarlo If non-null, the result to be written. * @param [in,out] Filename If non-null, filename of the file. */ void write_ascii_monte_carlo_statistic( const WinProp_ResultMonteCarlo* ResultMonteCarlo, const char* Filename) { if (ResultMonteCarlo == NULL) return; FILE* Outfile = fopen(Filename, "w+"); if (Outfile) { char sepChar = ' '; char format1[100]; char format2[100]; char text[400]; fprintf(Outfile, "%s", "-------------------------------------------------------------------\n"); fprintf(Outfile, "Number of evaluated snapshots:%c%d\n", sepChar, ResultMonteCarlo->nbrSnapshots); fprintf(Outfile, "Number of evaluated cells:%c%d\n", sepChar, ResultMonteCarlo->nbrCells); fprintf(Outfile, "Number of evaluated applications:%c%d\n", sepChar, ResultMonteCarlo->nbrApplications); fprintf(Outfile, "%s", "-------------------------------------------------------------------\n"); fprintf(Outfile, "%s", "\n"); /* assign width of columns */ sprintf(format1, "%%%ds", 15); sprintf(format2, "%%%ds", 14); /* loop over all cells (index -1 is for total) */ for (int cell = -1; cell < (int)ResultMonteCarlo->nbrCells; cell++) { /* write header of table */ fprintf(Outfile, "%s", "********************************\n"); if (cell >= 0) { fprintf(Outfile, "***%cCell %d", sepChar, (cell + 1)); fprintf(Outfile, "%s", "\n********************************"); } else { sprintf(text, "***%cTotal simulation area", sepChar); fprintf(Outfile, "%-30s", text); fprintf(Outfile, "%s", "\n********************************"); } /* Write snapshots */ for (int snapshot = (int)ResultMonteCarlo->nbrSnapshots; snapshot >= 0; snapshot--) { if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) sprintf(text, "%cAverage", sepChar); else sprintf(text, "%cSnapshot %d", sepChar, (snapshot + 1)); if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) fprintf(Outfile, format2, text); else fprintf(Outfile, format1, text); } fprintf(Outfile, "%s", "\n"); /* write cell load (Tx Power Downlink) */ if (cell >= 0) { fprintf(Outfile, "%-31s", " Tx Power Load (Downlink): "); for (int snapshot = (int)ResultMonteCarlo->nbrSnapshots; snapshot >= 0; snapshot--) { // average value of tx power if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { float average = 0.f; for (unsigned int s = 0; s < ResultMonteCarlo->nbrSnapshots; s++) { average += ResultMonteCarlo->trxLoad[s][cell].LoadPowerDL; } if (ResultMonteCarlo->nbrSnapshots > 0) { average /= ResultMonteCarlo->nbrSnapshots; } sprintf(text, "%c%.1f%c%%", sepChar, average * 100.f, sepChar); fprintf(Outfile, format2, text); } else { // values for each snapshot sprintf(text, "%c%.1f%c%%", sepChar, ResultMonteCarlo->trxLoad[snapshot][cell].LoadPowerDL * 100.f, sepChar); fprintf(Outfile, format1, text); } } fprintf(Outfile, "%s", "\n"); } /* write noise rise (uplink) */ if (cell >= 0) { fprintf(Outfile, "%-33s", " Noise Rise (Uplink): "); for (int snapshot = (int)ResultMonteCarlo->nbrSnapshots; snapshot >= 0; snapshot--) { // average value of noise rise if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { float average = 0.f; for (unsigned int s = 0; s < ResultMonteCarlo->nbrSnapshots; s++) { average += ResultMonteCarlo->trxLoad[s][cell].NoiseRiseUL; } if (ResultMonteCarlo->nbrSnapshots > 0) { average /= ResultMonteCarlo->nbrSnapshots; } sprintf(text, "%c%.1f%cdB", sepChar, average, sepChar); fprintf(Outfile, format2, text); } else { // values for each snapshot sprintf(text, "%c%.1f%cdB", sepChar, ResultMonteCarlo->trxLoad[snapshot][cell].NoiseRiseUL, sepChar); fprintf(Outfile, format1, text); } } fprintf(Outfile, "%s", "\n"); } /* write resources load (downlink) */ if (cell >= 0) { fprintf(Outfile, "%-32s", " Resources Load (Downlink): "); for (int snapshot = (int)ResultMonteCarlo->nbrSnapshots; snapshot >= 0; snapshot--) { // average value of DL resources load if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { float average = 0.f; for (unsigned int s = 0; s < ResultMonteCarlo->nbrSnapshots; s++) { average += ResultMonteCarlo->trxLoad[s][cell].LoadResourcesDL; } if (ResultMonteCarlo->nbrSnapshots > 0) { average /= ResultMonteCarlo->nbrSnapshots; } sprintf(text, "%c%.1f%c%%", sepChar, average * 100.f, sepChar); fprintf(Outfile, format2, text); } else { // values for each snapshot sprintf(text, "%c%.1f%c%%", sepChar, ResultMonteCarlo->trxLoad[snapshot][cell].LoadResourcesDL * 100.f, sepChar); fprintf(Outfile, format1, text); } } fprintf(Outfile, "%s", "\n"); } /* write resources load (downlink) */ if (cell >= 0) { fprintf(Outfile, "%-32s", " Resources Load (Uplink): "); for (int snapshot = (int)ResultMonteCarlo->nbrSnapshots; snapshot >= 0; snapshot--) { // average value of UL resources load if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { float average = 0.f; for (unsigned int s = 0; s < ResultMonteCarlo->nbrSnapshots; s++) { average += ResultMonteCarlo->trxLoad[s][cell].LoadResourcesUL; } if (ResultMonteCarlo->nbrSnapshots > 0) { average /= ResultMonteCarlo->nbrSnapshots; } sprintf(text, "%c%.1f%c%%", sepChar, average * 100.f, sepChar); fprintf(Outfile, format2, text); } else { // values for each snapshot sprintf(text, "%c%.1f%c%%", sepChar, ResultMonteCarlo->trxLoad[snapshot][cell].LoadResourcesUL * 100.f, sepChar); fprintf(Outfile, format1, text); } } fprintf(Outfile, "%s", "\n"); } /* write throughput (downlink) */ if (cell >= 0) { fprintf(Outfile, "%-33s", " Throughput (Downlink): "); for (int snapshot = ResultMonteCarlo->nbrSnapshots; snapshot >= 0; snapshot--) { float ThroughputDL = 0.f; if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { float average = 0.f; for (unsigned int s = 0; s < ResultMonteCarlo->nbrSnapshots; s++) { average += ResultMonteCarlo->trxLoad[s][cell].ThroughputUL; } if (ResultMonteCarlo->nbrSnapshots > 0) { average /= ResultMonteCarlo->nbrSnapshots; } // average throughput ThroughputDL = average; } else { // values for each snapshot ThroughputDL = ResultMonteCarlo->trxLoad[snapshot][cell].ThroughputUL; } // format throughput if (ThroughputDL > 1e9) sprintf(text, "%c%.1f%cGB/s", sepChar, ThroughputDL / 1e9, sepChar); else if (ThroughputDL > 1e6) sprintf(text, "%c%.1f%cMB/s", sepChar, ThroughputDL / 1e6, sepChar); else if (ThroughputDL > 1e3) sprintf(text, "%c%.1f%ckB/s", sepChar, ThroughputDL / 1e3, sepChar); else sprintf(text, "%c%.1f%cB/s", sepChar, ThroughputDL, sepChar); if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) fprintf(Outfile, format2, text); else fprintf(Outfile, format1, text); } fprintf(Outfile, "%s", "\n"); } /* write throughput (uplink) */ if (cell >= 0) { fprintf(Outfile, "%-33s", " Throughput (uplink): "); for (int snapshot = ResultMonteCarlo->nbrSnapshots; snapshot >= 0; snapshot--) { float ThroughputUL = 0.f; if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { float average = 0.f; for (unsigned int s = 0; s < ResultMonteCarlo->nbrSnapshots; s++) { average += ResultMonteCarlo->trxLoad[s][cell].ThroughputUL; } if (ResultMonteCarlo->nbrSnapshots > 0) { average /= ResultMonteCarlo->nbrSnapshots; } // average throughput ThroughputUL = average; } else { // values for each snapshot ThroughputUL = ResultMonteCarlo->trxLoad[snapshot][cell].ThroughputUL; } // format throughput if (ThroughputUL > 1e9) sprintf(text, "%c%.1f%cGB/s", sepChar, ThroughputUL / 1e9, sepChar); else if (ThroughputUL > 1e6) sprintf(text, "%c%.1f%cMB/s", sepChar, ThroughputUL / 1e6, sepChar); else if (ThroughputUL > 1e3) sprintf(text, "%c%.1f%ckB/s", sepChar, ThroughputUL / 1e3, sepChar); else sprintf(text, "%c%.1f%cB/s", sepChar, ThroughputUL, sepChar); if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) fprintf(Outfile, format2, text); else fprintf(Outfile, format1, text); } fprintf(Outfile, "%s", "\n"); } /* write number of served, blocked, and not assigned mobiles for each application */ for (unsigned int app = 0; app <= ResultMonteCarlo->nbrApplications; app++) { /* write name of application */ if (app < ResultMonteCarlo->nbrApplications) sprintf(text, "%s %d", "\n Applications id: ", app); else sprintf(text, "%s", "\nAll Applications"); fprintf(Outfile, "%-20s\n", text); for (int MobileType = 0; MobileType < 4; MobileType++) { // Mobiles served = 0 // Mobiles blocked(traffic) = 1 // Mobiles blocked(quality) = 2 // Mobiles not assigned = 3 switch (MobileType) { case 0: fprintf(Outfile, " %cMobiles served: ", sepChar); break; case 1: fprintf(Outfile, " %cMobiles blocked (traffic):", sepChar); break; case 2: fprintf(Outfile, " %cMobiles blocked (quality):", sepChar); break; case 3: fprintf(Outfile, " %cMobiles not assigned: ", sepChar); break; default: break; } for (int snapshot = (int)ResultMonteCarlo->nbrSnapshots; snapshot >= 0; snapshot--) { float nbr = 0.f; // All Applications case if (app == ResultMonteCarlo->nbrApplications) { for (unsigned int a = 0; a < ResultMonteCarlo->nbrApplications; a++) { // specific cell if (cell >= 0) { if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { // average number (over snapshots) for all apps for a specific cell for (unsigned int s = 0; s < ResultMonteCarlo->nbrSnapshots; s++) { switch (MobileType) { case 0: nbr += ResultMonteCarlo->statisticCell[s][cell][a].nbrServed; break; case 1: nbr += ResultMonteCarlo->statisticCell[s][cell][a].nbrBlocked; break; case 2: nbr += ResultMonteCarlo->statisticCell[s][cell][a].nbrNotConnected; break; case 3: nbr += ResultMonteCarlo->statisticCell[s][cell][a].nbrNotAssigned; break; default: break; } } } else { // number for all apps for a specific cell and a specific snapshot switch (MobileType) { case 0: nbr += ResultMonteCarlo->statisticCell[snapshot][cell][a].nbrServed; break; case 1: nbr += ResultMonteCarlo->statisticCell[snapshot][cell][a].nbrBlocked; break; case 2: nbr += ResultMonteCarlo->statisticCell[snapshot][cell][a].nbrNotConnected; break; case 3: nbr += ResultMonteCarlo->statisticCell[snapshot][cell][a].nbrNotAssigned; break; default: break; } } } else // all cells { // average number (over snapshots) for all apps for all cells if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { for (unsigned int s = 0; s < ResultMonteCarlo->nbrSnapshots; s++) { switch (MobileType) { case 0: nbr += ResultMonteCarlo->statisticTotal[s][a].nbrServed; break; case 1: nbr += ResultMonteCarlo->statisticTotal[s][a].nbrBlocked; break; case 2: nbr += ResultMonteCarlo->statisticTotal[s][a].nbrNotConnected; break; case 3: nbr += ResultMonteCarlo->statisticTotal[s][a].nbrNotAssigned; break; default: break; } } } else { // number for all apps for all cells per snapshot switch (MobileType) { case 0: nbr += ResultMonteCarlo->statisticTotal[snapshot][a].nbrServed; break; case 1: nbr += ResultMonteCarlo->statisticTotal[snapshot][a].nbrBlocked; break; case 2: nbr += ResultMonteCarlo->statisticTotal[snapshot][a].nbrNotConnected; break; case 3: nbr += ResultMonteCarlo->statisticTotal[snapshot][a].nbrNotAssigned; break; default: break; } } } } } else // individual application case { // specific cell if (cell >= 0) { // average number (over snapshots) for a specific apps and a specific cell if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { for (unsigned int s = 0; s < ResultMonteCarlo->nbrSnapshots; s++) { switch (MobileType) { case 0: nbr += ResultMonteCarlo->statisticCell[s][cell][app].nbrServed; break; case 1: nbr += ResultMonteCarlo->statisticCell[s][cell][app].nbrBlocked; break; case 2: nbr += ResultMonteCarlo->statisticCell[s][cell][app].nbrNotConnected; break; case 3: nbr += ResultMonteCarlo->statisticCell[s][cell][app].nbrNotAssigned; break; default: break; } } } else { // number for a specific app, a specific cell, and a specific snapshot switch (MobileType) { case 0: nbr += ResultMonteCarlo->statisticCell[snapshot][cell][app].nbrServed; break; case 1: nbr += ResultMonteCarlo->statisticCell[snapshot][cell][app].nbrBlocked; break; case 2: nbr += ResultMonteCarlo->statisticCell[snapshot][cell][app].nbrNotConnected; break; case 3: nbr += ResultMonteCarlo->statisticCell[snapshot][cell][app].nbrNotAssigned; break; default: break; } } } else // all cells // average number (over snapshots) for a specific app and for all cells if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { for (unsigned int s = 0; s < ResultMonteCarlo->nbrSnapshots; s++) { switch (MobileType) { case 0: nbr += ResultMonteCarlo->statisticTotal[s][app].nbrServed; break; case 1: nbr += ResultMonteCarlo->statisticTotal[s][app].nbrBlocked; break; case 2: nbr += ResultMonteCarlo->statisticTotal[s][app].nbrNotConnected; break; case 3: nbr += ResultMonteCarlo->statisticTotal[s][app].nbrNotAssigned; break; default: break; } } } else { // number for a specific app, a specif specific and for all cells switch (MobileType) { case 0: nbr += ResultMonteCarlo->statisticTotal[snapshot][app].nbrServed; break; case 1: nbr += ResultMonteCarlo->statisticTotal[snapshot][app].nbrBlocked; break; case 2: nbr += ResultMonteCarlo->statisticTotal[snapshot][app].nbrNotConnected; break; case 3: nbr += ResultMonteCarlo->statisticTotal[snapshot][app].nbrNotAssigned; break; default: break; } } } if (snapshot == (int)ResultMonteCarlo->nbrSnapshots) { double nbrDouble = ((double)nbr) / ((double)ResultMonteCarlo->nbrSnapshots); sprintf(text, "%c%.1lf", sepChar, nbrDouble); fprintf(Outfile, format2, text); } else { sprintf(text, "%c%.1f", sepChar, nbr); fprintf(Outfile, format1, text); } } fprintf(Outfile, "%s", "\n"); } } /* next cell */ fprintf(Outfile, "%s", "\n\n\n"); } /* close file */ fclose(Outfile); } else { printf("\nCould not open the File: %s for writing.\n", Filename); } }