Demo program
This C demo program illustrates how to use the Meteonorm library.
/** * @file demo.c * @brief Meteonorm demo program * * This program demonstrates the usage of the Meteonorm library. * * Copyright (c) Meteotest AG */ #include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "meteonorm.h" // Forward declarations void compute(mn_input *, mn_frequency); void compute_imported_monthly(); void print_horizon(double horizon[360]); #define NUM_LOCATIONS 5 #define NUM_MONTHS 12 typedef struct location { char city[50]; double lat; double lon; double altitude; float horizon[360]; float ghi[NUM_MONTHS]; // Global Horizontal Irradiance (ghi) float ta[NUM_MONTHS]; // Temperature (ta) float ff[NUM_MONTHS]; // Wind speed (ff) } location; void usage(const char *name) { printf("usage: %s --datapath=<path>\n", name); exit(1); } int main(int argc, char *argv[]) { char *datapath = NULL; struct option long_options[] = {{"datapath", required_argument, NULL, 'd'}, {NULL, 0, NULL, 0}}; int opt; while ((opt = getopt_long(argc, argv, "d:", long_options, NULL)) != -1) { switch (opt) { case 'd': datapath = optarg; break; default: usage(argv[0]); } } if (!datapath) { printf("error: datapath argument not provided\n"); usage(argv[0]); } // Initialize Meteonorm library char *key = "your-license-key"; mn_error err = mn_init(key, datapath); if (err.status != MN_STATUS_OK) { printf("error: failed to initialize Meteonorm: %s\n", err.message); return err.status; } // Retrieve Meteonorm version mn_version v = mn_get_version(); printf("meteonorm version: commit: %s, build date: %s\n", v.commit, v.build_date); mn_input *input = mn_input_new(); // Bern, Switzerland: 46.9480° N, 7.4474° E mn_status status = mn_input_set_latitude(input, 46.9480); if (status != MN_STATUS_OK) { printf("error: failed to set latitude\n"); return status; } status = mn_input_set_longitude(input, 7.4474); if (status != MN_STATUS_OK) { printf("error: failed to set longitude\n"); return status; } status = mn_input_set_random_seed(input, 42); if (status != MN_STATUS_OK) { printf("error: failed to set random seed\n"); return status; } status = mn_input_set_surface_tilt(input, 30); if (status != MN_STATUS_OK) { printf("error: failed to set surface tilt\n"); return status; } status = mn_input_set_surface_azimuth(input, 180); if (status != MN_STATUS_OK) { printf("error: failed to set surface azimuth\n"); return status; } status = mn_input_set_situation(input, MN_SITUATION_CITY); if (status != MN_STATUS_OK) { printf("error: failed to set situation\n"); return status; } // Compute TMY (hourly) compute(input, MN_FREQUENCY_1_HOUR); status = mn_input_set_altitude(input, 551); if (status != MN_STATUS_OK) { printf("error: failed to set altitude\n"); return status; } status = mn_input_set_time_zone(input, 1); if (status != MN_STATUS_OK) { printf("error: failed to set time zone\n"); return status; } // Compute TMY (minute) compute(input, MN_FREQUENCY_1_MINUTE); mn_input_free(input); // Compute TMY based on imported monthly data compute_imported_monthly(); // Look up WMO station printf("\nlooking up WMO station...\n"); mn_wmo_station station = mn_get_wmo_station(67000); if (station.error.status != MN_STATUS_OK) { printf("error: failed to get WMO station: %s\n", station.error.message); return station.error.status; } printf("station: name: %s, latitude: %f, longitude: %f\n", station.name, station.latitude, station.longitude); // Look up geo data printf("\nlooking up data of Kathmandu (Nepal)...\n"); double lat = 27.7103; double lon = 85.3222; mn_time_zone tz = mn_get_time_zone(lat, lon); // (UTC +5:45) if (tz.error.status != MN_STATUS_OK) { printf("error: failed to get time zone: %s\n", tz.error.message); return tz.error.status; } printf("time zone: offset: %f\n", tz.offset); mn_altitude altitude = mn_get_altitude(lat, lon); if (altitude.error.status != MN_STATUS_OK) { printf("error: failed to get altitude: %s\n", altitude.error.message); return altitude.error.status; } printf("altitude: %f\n", altitude.elevation); mn_horizon h = mn_get_horizon(lat, lon); print_horizon(h.horizon); // Unix timestamp at Jan 1, 2005 at 00:00 mn_time t = mn_time_new(2005, 1, 1, 0, 0, 0); int64_t twothousandfive = 1104537600; if (t != twothousandfive) { printf("error: failed to create time: want: %ld: got: %ld\n", twothousandfive, t); } t = mn_time_new(2010, 1, 1, 0, 0, 0); int twothousandten = 1262304000; if (t != twothousandten) { printf("error: failed to create time: want: %d: got: %ld\n", twothousandten, t); } // Release Meteonorm library mn_deinit(); return 0; } void compute(mn_input *input, mn_frequency freq) { printf("\ncomputing %s...\n", freq == MN_FREQUENCY_1_HOUR ? "hourly" : "minute"); mn_status status = mn_input_set_frequency(input, freq); if (status != MN_STATUS_OK) { printf("error: failed to set frequency\n"); return; } clock_t start = clock(); mn_result *res = mn_compute(input); clock_t end = clock(); double elapsed = ((double)(end - start)) / CLOCKS_PER_SEC; printf("took: %fsec\n", elapsed); if (res->error.status != MN_STATUS_OK) { printf("error: computation failed: status: %d: message: %s\n", res->error.status, res->error.message); mn_result_free(res); return; } printf("altitude: %f\n", res->altitude); print_horizon(res->horizon); printf("time zone: %f\n", res->time_zone); printf("frequency (0: hourly, 1: minute): %d\n", res->frequency); printf("start year of irradiance period of nearest station: %d\n", res->start_year_of_irradiance_period_of_nearest_station); printf("end year of irradiance period of nearest station: %d\n", res->end_year_of_irradiance_period_of_nearest_station); printf("irradiance station data weight: %f\n", res->irradiance_station_data_weight); printf("uncertainty of irradiance estimation: %f\n", res->uncertainty_of_irradiance_estimation); printf("uncertainty of temperature estimation: %f\n", res->uncertainty_of_temperature_estimation); printf("irradiance year-to-year variability: %f\n", res->irradiance_year_to_year_variability); printf("irradiance probability of exceedence p90: %d\n", res->irradiance_yearly_poe90); printf("irradiance probability of exceedence p10: %d\n", res->irradiance_yearly_poe10); mn_result_free(res); } void compute_imported_monthly() { location locations[NUM_LOCATIONS] = { { "Geneva", 46.2, 6.15, 405, { 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, {34.7, 56.9, 105.8, 145.0, 172.2, 193.0, 196.2, 166.9, 123.2, 74.8, 38.4, 26.3}, // ghi {2.2, 2.9, 6.8, 10.9, 14.7, 19.2, 20.8, 20.0, 15.9, 11.6, 6.3, 2.9}, // ta {2.3, 2.5, 2.8, 2.6, 2.4, 2.3, 2.2, 1.9, 2.1, 1.9, 2.1, 2.3} // ff }, { "Munich", 48.14, 11.574, 526, {0}, {31.1, 51.8, 96.9, 134.9, 159.9, 172.4, 171.2, 148.0, 103.5, 66.8, 33.6, 25.6}, // ghi {-0.3, 0.7, 4.8, 9.6, 13.8, 17.6, 18.9, 18.5, 13.9, 9.5, 4.4, 1.0}, // ta {3.9, 3.8, 4.0, 3.4, 3.3, 2.9, 3.0, 2.7, 2.8, 2.8, 3.3, 3.6} // ff }, { "Sydney", -33.87, 151.21, 42, {0}, {206.1, 168.0, 154.0, 125.3, 93.7, 72.0, 80.4, 104.2, 128.9, 165.2, 176.4, 201.6}, // ghi {23.2, 23.0, 21.8, 19.1, 15.9, 13.5, 12.9, 14.0, 16.8, 18.7, 20.3, 21.9}, // ta {3.6, 3.3, 2.9, 2.5, 2.5, 2.5, 2.6, 2.9, 3.1, 3.3, 3.5, 3.5} // ff }, { "San Francisco", 37.77, -122.42, 0, {0}, {65.9, 88.2, 136.2, 170.0, 199.1, 214.6, 221.1, 198.4, 163.6, 116.3, 75.6, 65.5}, // ghi {10.5, 11.5, 12.7, 13.5, 15.0, 16.7, 17.3, 17.7, 17.9, 16.3, 13.2, 10.7}, // ta {2.8, 3.5, 4.1, 4.9, 5.3, 5.3, 5.0, 4.8, 4.3, 3.6, 2.9, 3.0} // ff }, { "Beijing", 39.93, 116.4, 30, {0}, {67.8, 84.1, 125.7, 148.2, 173.4, 153.0, 147.5, 142.0, 117.5, 95.8, 67.6, 58.3}, // ghi {-3.4, -0.1, 7.4, 15.0, 21.4, 25.1, 27.0, 25.8, 20.8, 13.1, 4.5, -1.8}, // ta {3.1, 3.0, 3.3, 3.5, 3.2, 2.6, 2.4, 2.3, 2.3, 2.4, 2.7, 3.1} // ff }}; mn_frequency freq = MN_FREQUENCY_1_HOUR; for (int i = 0; i < NUM_LOCATIONS; i++) { printf("\nimported monthly: %s: computing hourly...\n", locations[i].city); mn_input *input = mn_input_new(); mn_status status = mn_input_set_latitude(input, locations[i].lat); if (status != MN_STATUS_OK) { printf("imported monthly: %s: failed to set latitude\n", locations[i].city); mn_input_free(input); continue; } status = mn_input_set_longitude(input, locations[i].lon); if (status != MN_STATUS_OK) { printf("imported monthly: %s: failed to set longitude\n", locations[i].city); mn_input_free(input); continue; } status = mn_input_set_frequency(input, freq); if (status != MN_STATUS_OK) { printf("imported monthly: %s: failed to set longitude\n", locations[i].city); mn_input_free(input); continue; } status = mn_input_set_altitude(input, locations[i].altitude); if (status != MN_STATUS_OK) { printf("imported monthly: %s: failed to set altiude\n", locations[i].city); mn_input_free(input); continue; } mn_values *horizon = mn_values_new(locations[i].horizon, 360); status = mn_input_set_horizon(input, horizon); if (status != MN_STATUS_OK) { printf("imported monthly: %s: failed to set horizon\n", locations[i].city); mn_input_free(input); continue; } mn_values *ghi = mn_values_new(locations[i].ghi, NUM_MONTHS); status = mn_input_set_imported_monthly_global_horizontal_irradiance(input, ghi); if (status != MN_STATUS_OK) { printf("imported monthly: %s: failed to set global irradiance\n", locations[i].city); mn_input_free(input); continue; } mn_values *ta = mn_values_new(locations[i].ta, NUM_MONTHS); status = mn_input_set_imported_monthly_temperature(input, ta); if (status != MN_STATUS_OK) { printf("imported monthly: %s: failed to set temperature", locations[i].city); mn_input_free(input); continue; } mn_values *ff = mn_values_new(locations[i].ff, NUM_MONTHS); status = mn_input_set_imported_monthly_wind_speed(input, ff); if (status != MN_STATUS_OK) { printf("imported monthly: %s: failed to set wind speed\n", locations[i].city); mn_input_free(input); continue; } mn_result *res = mn_compute(input); if (res->error.status != MN_STATUS_OK) { printf("imported monthly: %s: computation failed: status: %d: message: %s\n", locations[i].city, res->error.status, res->error.message); mn_result_free(res); mn_input_free(input); continue; } printf("altitude: %f\n", res->altitude); print_horizon(res->horizon); mn_result_free(res); mn_input_free(input); } } void print_horizon(double horizon[360]) { printf("horizon: ["); for (int i = 0; i < 360; i++) { if (i > 0) { printf(", "); } printf("%.0f", horizon[i]); } printf("]\n"); }c