Multi-threaded Outdoor Propagation
Detailed Description
This is an example of how to use the WinProp API for multi-threaded outdoor propagation with OpenMP. The full example is distributed with the installation.#include <stdio.h> #include <string> #include <iostream> #ifdef _OPENMP #include <omp.h> #endif #include "outdoor_propagation_openmp.h" #ifndef API_DATA_FOLDER #define API_DATA_FOLDER "../../api/winprop/data/" #endif // !API_DATA_FOLDER int main(int argc, char** argv) { // Load topography and building data once for all computations. TOPOGRAPHY TopographyData; InterfaceTopoInit(&TopographyData); InterfaceLoadTopoASC(&TopographyData, API_DATA_FOLDER "outdoor/Topo.asc"); URBAN_BUILDINGS BuildingData; InterfaceBuildingsInit(&BuildingData); InterfaceLoadBuildingsASCII(&BuildingData, API_DATA_FOLDER "outdoor/City.oda"); // Set the number of parallel threads. #ifdef _OPENMP omp_set_num_threads(4); #endif // As an example we're computing the same antenna location in the same environment with 16 // different frequencies. #pragma omp parallel for schedule(dynamic,1) for (int i = 0; i < 16; i++) { int Error = 0; WinProp_ParaMain GeneralParameters; WinProp_Structure_Init_ParameterMain(&GeneralParameters); // Definition of scenario /* Definition of general parameters. */ GeneralParameters.ScenarioMode = SCENARIOMODE_URBAN; // Urban prediction GeneralParameters.PredictionModelUrban = PREDMODEL_UDP; // Use Dominant Path Model /* Definition of prediction area. */ GeneralParameters.UrbanLowerLeftX = 100.0; GeneralParameters.UrbanLowerLeftY = 100.0; GeneralParameters.UrbanUpperRightX = 2200.0; GeneralParameters.UrbanUpperRightY = 3200.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; double PredictionHeight = 1.5; /* Size of matrix with results. */ GeneralParameters.Resolution = 10.0; // Resolution in meter GeneralParameters.NrLayers = 1; // Number of prediction heights GeneralParameters.PredictionHeights = &PredictionHeight; // Prediction height in meter /* Building vector data and topography. */ GeneralParameters.BuildingsMode = BUILDINGSMODE_RAM; GeneralParameters.Buildings = BuildingData; /* Topography data */ GeneralParameters.TopographyMode = TOPOMODE_RAM; GeneralParameters.Topography = TopographyData; // Callbacks WinProp_Callback Callback; WinProp_Structure_Init_Callback(&Callback); Callback.Percentage = CallbackProgress; Callback.Message = CallbackMessage; Callback.Error = CallbackError; /* Position and configuration. */ WinProp_Antenna Antenna; WinProp_Structure_Init_Antenna(&Antenna); Antenna.Id = i + 1; Antenna.SiteId = 1; Antenna.Longitude_X = 1100.0; Antenna.Latitude_Y = 2100.0; Antenna.Height = 20.0; Antenna.Power = 43.0; // Power in dBm Antenna.Frequency = 900.0 + 100. * i; // Frequency in MHz char AntennaName[500]; sprintf(AntennaName, "Antenna %i", i); Antenna.Name = AntennaName; WinProp_Result Resultmatrix; WinProp_RayMatrix RayMatrix; WinProp_Structure_Init_Result(&Resultmatrix); WinProp_Structure_Init_RayMatrix(&RayMatrix); // Compute outdoor prediction Error = OutdoorPlugIn_ComputePrediction( &Antenna, &GeneralParameters, NULL, 0, NULL, NULL, NULL, NULL, &Callback, &Resultmatrix, &RayMatrix, NULL, NULL); // Do something with results if (Error == 0) { char Filename[500]; sprintf(Filename, API_DATA_FOLDER "output/Results Antenna %i.txt", i); write_ascii(&Resultmatrix, Filename); } else { /* Error during prediction. Print error message. */ CallbackError(GeneralParameters.ErrorMessageMain, Error); } // Free per thread memory WinProp_FreeResult(&Resultmatrix); WinProp_FreeRayMatrix(&RayMatrix); } // Free global memory InterfaceTopoFree(&TopographyData); InterfaceBuildingsInit(&BuildingData); 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); } void write_ascii(const WinProp_Result* Resultmatrix, const char* Filename) { FILE* OutputFile = fopen(Filename,"w"); if (OutputFile) { /* Loop all 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, "%.2f\t%.2f\t%.2f\n", Coordinate_X, Coordinate_Y, Resultmatrix->Matrix[0][x][y]); } } /* Close file. */ fclose(OutputFile); } else printf("\nCould not open the File: %s for writing.\n",Filename); }