RCube
Rcube Rest Server calculates sail routes based on Grib files and sailing boat polar files
Loading...
Searching...
No Matches
readgriballeccodes.c
Go to the documentation of this file.
1
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <stdbool.h>
6#include <time.h>
7#include <math.h>
8#include <sys/stat.h>
9#include <locale.h>
10#include "eccodes.h"
11#include "../csources/glibwrapper.h"
12#include "../csources/r3types.h"
13#include "../csources/r3util.h"
14#include "../csources/inline.h"
15#include <grib_api.h> // for ProductKind
16
17#define EPSILON 0.001 // for approximat value
18#define GUST_GFS 180 // id of gust in GFS files
19
20FlowP *tGribData [2] = {NULL, NULL}; // wind, current
21
23char *gribReaderVersion (char *str, size_t maxLen) {
24 snprintf (str, maxLen, "ECCODES %s", ECCODES_VERSION_STR);
25 return str;
26}
27
29static inline long indLat (double lat, const Zone *zone) {
30 return (long) round ((lat - zone->latMin)/zone->latStep);
31}
32
34static inline long indLon (double lon, const Zone *zone) {
35 if (lon < zone->lonLeft) lon += 360;
36 return (long) round ((lon - zone->lonLeft)/zone->lonStep);
37}
38
40static long updateLong (long value, size_t n, size_t maxSize, long array []) {
41 bool found = false;
42 for (size_t i = 0; i < n; i++) {
43 if (value == array [i]) {
44 found = true;
45 break;
46 }
47 }
48 if ((! found) && (n < maxSize)) { // new time stamp
49 array [n] = value;
50 n += 1;
51 }
52 return n;
53}
54
56bool readGribLists (const char *fileName, Zone *zone) {
57 FILE* f = NULL;
58 int err = 0;
59 long timeStep, dataDate, dataTime;
60 char shortName [MAX_SIZE_SHORT_NAME];
61 size_t lenName;
62 bool found = false;
63 // Message handle. Required in all the ecCodes calls acting on a message.
64 codes_handle* h = NULL;
65
66 if ((f = fopen (fileName, "rb")) == NULL) {
67 fprintf (stderr, "In readGribLists, Error: Unable to open file %s\n", fileName);
68 return false;
69 }
70 memset (zone, 0, sizeof (Zone));
71
72 // Loop on all the messages in a file
73 while ((h = codes_handle_new_from_file(0, f, PRODUCT_GRIB, &err)) != NULL) {
74 if (err != CODES_SUCCESS) CODES_CHECK (err, 0);
75 lenName = MAX_SIZE_SHORT_NAME;
76
77 CODES_CHECK(codes_get_string(h, "shortName", shortName, &lenName), 0);
78 CODES_CHECK(codes_get_long(h, "step", &timeStep), 0);
79 CODES_CHECK(codes_get_long(h, "dataDate", &dataDate), 0);
80 CODES_CHECK(codes_get_long(h, "dataTime", &dataTime), 0);
81 codes_handle_delete (h);
82
83 found = false;
84 for (size_t i = 0; i < zone->nShortName; i++) {
85 if (strcmp (shortName, zone->shortName [i]) == 0) {
86 found = true;
87 break;
88 }
89 }
90 if ((! found) && (zone->nShortName < MAX_N_SHORT_NAME)) { // new shortName
92 zone->nShortName += 1;
93 }
97 }
98
99 fclose (f);
100 // Replace unknown by gust ? (GFS case where gust identified by specific indicatorOfParameter)
101 for (size_t i = 0; i < zone->nShortName; i++) {
102 if (strcmp (zone->shortName[i], "unknown") == 0)
103 g_strlcpy (zone->shortName[i], "gust?", 6);
104 }
105 zone->intervalLimit = 0;
106 if (zone->nTimeStamp > 1) {
109 for (size_t i = 1; i < zone->nTimeStamp; i++) {
110 if ((zone->timeStamp [i] - zone->timeStamp [i-1]) == zone->intervalEnd) {
111 zone->intervalLimit = i;
112 break;
113 }
114 }
115 }
116 else {
118 fprintf (stderr, "In readGribLists, Error nTimeStamp = %zu\n", zone->nTimeStamp);
119 //return false;
120 }
121
122 //printf ("intervalBegin: %ld, intervalEnd: %ld, intervalLimit: %zu\n",
123 //zone->intervalBegin, zone->intervalEnd, zone->intervalLimit -1);
124 return true;
125}
126
128bool readGribParameters (const char *fileName, Zone *zone) {
129 int err = 0;
130 FILE* f = NULL;
131 double lat1, lat2;
132 codes_handle *h = NULL;
133
134 if ((f = fopen (fileName, "rb")) == NULL) {
135 fprintf (stderr, "In readGribParameters, Error unable to open file %s\n",fileName);
136 return false;
137 }
138
139 // create new handle from the first message in the file
140 if ((h = codes_handle_new_from_file(0, f, PRODUCT_GRIB, &err)) == NULL) {
141 fprintf (stderr, "In readGribParameters, Error code handle from file : %s Code error: %s\n",\
142 fileName, codes_get_error_message(err));
143 fclose (f);
144 return false;
145 }
146 fclose (f);
147
148 CODES_CHECK(codes_get_long (h, "centre", &zone->centreId),0);
149 CODES_CHECK(codes_get_long (h, "editionNumber", &zone->editionNumber),0);
150 CODES_CHECK(codes_get_long (h, "stepUnits", &zone->stepUnits),0);
151 CODES_CHECK(codes_get_long (h, "numberOfValues", &zone->numberOfValues),0);
152 CODES_CHECK(codes_get_long (h, "Ni", &zone->nbLon),0);
153 CODES_CHECK(codes_get_long (h, "Nj", &zone->nbLat),0);
154
155 CODES_CHECK(codes_get_double (h,"latitudeOfFirstGridPointInDegrees",&lat1),0);
156 CODES_CHECK(codes_get_double (h,"longitudeOfFirstGridPointInDegrees",&zone->lonLeft),0);
157 CODES_CHECK(codes_get_double (h,"latitudeOfLastGridPointInDegrees",&lat2),0);
158 CODES_CHECK(codes_get_double (h,"longitudeOfLastGridPointInDegrees",&zone->lonRight),0);
159 CODES_CHECK(codes_get_double (h,"iDirectionIncrementInDegrees",&zone->lonStep),0);
160 CODES_CHECK(codes_get_double (h,"jDirectionIncrementInDegrees",&zone->latStep),0);
161
162 if ((lonCanonize (zone->lonLeft) > 0.0) && (lonCanonize (zone->lonRight) < 0.0)) {
163 zone -> anteMeridian = true;
164 }
165 else {
166 zone -> anteMeridian = false;
169 }
170 zone->latMin = fmin (lat1, lat2);
171 zone->latMax = fmax (lat1, lat2);
172
173 codes_handle_delete (h);
174 return true;
175}
176
178static inline long indexOf (int timeStep, double lat, double lon, const Zone *zone) {
179 const long iLat = indLat (lat, zone);
180 const long iLon = indLon (lon, zone);
181 int iT = -1;
182 for (iT = 0; iT < (int) zone->nTimeStamp; iT++) {
183 if (timeStep == zone->timeStamp [iT])
184 break;
185 }
186 if (iT == -1) {
187 fprintf (stderr, "In indexOf, Error Cannot find index of time: %d\n", timeStep);
188 return -1;
189 }
190 //printf ("iT: %d iLon :%d iLat: %d\n", iT, iLon, iLat);
191 return (iT * zone->nbLat * zone->nbLon) + (iLat * zone->nbLon) + iLon;
192}
193
196bool readGribAll (const char *fileName, Zone *zone, int iFlow) {
197 FILE* f = NULL;
198 int err = 0;
199 long iGrib;
200 long bitmapPresent = 0, timeStep, oldTimeStep;
201 double lat, lon, val, indicatorOfParameter;
202 char shortName [MAX_SIZE_SHORT_NAME];
203 size_t lenName;
204 //char str [MAX_SIZE_LINE];
205 zone->wellDefined = false;
206 if (! readGribLists (fileName, zone)) {
207 return false;
208 }
209 if (! readGribParameters (fileName, zone)) {
210 return false;
211 }
212 if (zone -> nDataDate > 1) {
213 fprintf (stderr, "In readGribAll, Error Grib file with more than 1 dataDate not supported nDataDate: %zu\n",
214 zone -> nDataDate);
215 return false;
216 }
217
218 if (tGribData [iFlow] != NULL) {
219 free (tGribData [iFlow]);
220 tGribData [iFlow] = NULL;
221 }
222 if ((tGribData [iFlow] = calloc ((zone->nTimeStamp + 1) * zone->nbLat * zone->nbLon, sizeof (FlowP))) == NULL) { // nTimeStamp + 1
223 fprintf (stderr, "In readGribAll, Error calloc tGribData [iFlow]\n");
224 return false;
225 }
226 // printf ("In readGribAll.: %s allocated\n",
227 // formatThousandSep (str, sizeof (str), sizeof(FlowP) * (zone->nTimeStamp + 1) * zone->nbLat * zone->nbLon));
228
229 // Message handle. Required in all the ecCodes calls acting on a message.
230 codes_handle* h = NULL;
231 // Iterator on lat/lon/values.
232 codes_iterator* iter = NULL;
233 if ((f = fopen (fileName, "rb")) == NULL) {
234 free (tGribData [iFlow]);
235 tGribData [iFlow] = NULL;
236 fprintf (stderr, "In readGribAll, Error Unable to open file %s\n", fileName);
237 return false;
238 }
239 zone->nMessage = 0;
240 zone->allTimeStepOK = true;
241 timeStep = zone->timeStamp [0];
242 oldTimeStep = timeStep;
243
244 // Loop on all the messages in a file
245 while ((h = codes_handle_new_from_file (0, f, PRODUCT_GRIB, &err)) != NULL) {
246 if (err != CODES_SUCCESS) CODES_CHECK (err, 0);
247
248 // Check if a bitmap applies
249 CODES_CHECK (codes_get_long (h, "bitmapPresent", &bitmapPresent), 0);
250 if (bitmapPresent) {
251 CODES_CHECK(codes_set_double (h, "missingValue", MISSING), 0);
252 }
253
254 lenName = MAX_SIZE_SHORT_NAME;
255 CODES_CHECK(codes_get_string (h, "shortName", shortName, &lenName), 0);
256 CODES_CHECK(codes_get_long (h, "step", &timeStep), 0);
257
258 long progressTime = timeStep - oldTimeStep;
259
260 // check timeStep move well. This test is not very useful.
261 if ((timeStep != 0) && (progressTime > 0) && // progressTime may regress. ARPEGE case
262 (progressTime != zone->intervalBegin) &&
263 (progressTime != zone->intervalEnd)
264 ) { // check timeStep progress well
265
266 zone->allTimeStepOK = false;
267 fprintf (stderr, "In readGribAll: All time Step Are Not defined message: %d, timeStep: %ld, oldTimeStep: %ld, shortName: %s\n",
268 zone->nMessage, timeStep, oldTimeStep, shortName);
269 }
270 oldTimeStep = timeStep;
271
272 err = codes_get_double(h, "indicatorOfParameter", &indicatorOfParameter);
273 if (err != CODES_SUCCESS)
274 indicatorOfParameter = -1;
275
276 // A new iterator on lat/lon/values is created from the message handle h.
277 iter = codes_grib_iterator_new(h, 0, &err);
278 if (err != CODES_SUCCESS) CODES_CHECK(err, 0);
279
280 // Loop on all the lat/lon/values.
281 while (codes_grib_iterator_next(iter, &lat, &lon, &val)) {
282 if (! (zone -> anteMeridian))
283 lon = lonCanonize (lon);
284 // printf ("lon : %.2lf\n", lon);
285 iGrib = indexOf (timeStep, lat, lon, zone);
286
287 if (iGrib <= -1) {
288 fprintf (stderr, "In readGribAll: Error iGrib : %ld\n", iGrib);
289 free (tGribData [iFlow]);
290 tGribData [iFlow] = NULL;
291 codes_handle_delete (h);
292 codes_grib_iterator_delete (iter);
293 iter = NULL;
294 h = NULL;
295 fclose (f);
296 return false;
297 }
298 // printf("%.2f %.2f %.2lf %ld %ld %s\n", lat, lon, val, timeStep, iGrib, shortName);
299 tGribData [iFlow] [iGrib].lat = lat;
300 tGribData [iFlow] [iGrib].lon = lon;
301 if ((strcmp (shortName, "10u") == 0) || (strcmp (shortName, "ucurr") == 0))
302 tGribData [iFlow] [iGrib].u = val;
303 else if ((strcmp (shortName, "10v") == 0) || (strcmp (shortName, "vcurr") == 0))
304 tGribData [iFlow] [iGrib].v = val;
305 else if (strcmp (shortName, "gust") == 0)
306 tGribData [iFlow] [iGrib].g = val;
307 else if (strcmp (shortName, "swh") == 0) // waves
308 tGribData [iFlow] [iGrib].w = val;
309 else if (indicatorOfParameter == GUST_GFS) // find gust in GFS file specific parameter = 180
310 tGribData [iFlow] [iGrib].g = val;
311 }
312 codes_grib_iterator_delete (iter);
313 codes_handle_delete (h);
314 iter = NULL;
315 h = NULL;
316 // printf ("nMessage: %d\n", zone->nMessage);
317 zone->nMessage += 1;
318 }
319 // printf ("readGribAll:%s done.\n", fileName);
320
321 fclose (f);
322 zone->wellDefined = true;
323 return true;
324}
325
#define g_strlcpy(dest, src, size)
Definition glibwrapper.h:9
static double lonCanonize(double lon)
return lon on ]-180, 180 ] interval
Definition inline.h:29
#define MISSING
Definition r3types.h:21
#define MAX_N_TIME_STAMPS
Definition r3types.h:54
#define MAX_N_DATA_DATE
Definition r3types.h:55
#define MAX_N_DATA_TIME
Definition r3types.h:56
#define MAX_SIZE_SHORT_NAME
Definition r3types.h:60
#define MAX_N_SHORT_NAME
Definition r3types.h:57
Zone zone
geographic zone covered by grib file
Definition r3util.c:64
static long updateLong(long value, size_t n, size_t maxSize, long array[])
Modify array with new value if not already in array.
char * gribReaderVersion(char *str, size_t maxLen)
return version of ECCODE API
FlowP * tGribData[2]
grib data description
static long indLat(double lat, const Zone *zone)
return indice of lat in gribData wind or current
static long indLon(double lon, const Zone *zone)
return indice of lon in gribData wind or current
static long indexOf(int timeStep, double lat, double lon, const Zone *zone)
find index in gribData table
#define GUST_GFS
bool readGribLists(const char *fileName, Zone *zone)
Read lists zone.timeStamp, shortName, zone.dataDate, dataTime before full grib reading.
bool readGribAll(const char *fileName, Zone *zone, int iFlow)
read grib file using eccodes C API return true if OK
bool readGribParameters(const char *fileName, Zone *zone)
Read grib parameters in zone before full grib reading.
Wind point.
Definition r3types.h:128
float u
Definition r3types.h:131
float g
Definition r3types.h:134
float lat
Definition r3types.h:129
float w
Definition r3types.h:133
float v
Definition r3types.h:132
float lon
Definition r3types.h:130
zone description
Definition r3types.h:140
double latMin
Definition r3types.h:149
double lonRight
Definition r3types.h:152
long dataTime[MAX_N_DATA_TIME]
Definition r3types.h:165
long intervalEnd
Definition r3types.h:167
bool wellDefined
Definition r3types.h:143
long centreId
Definition r3types.h:144
long intervalBegin
Definition r3types.h:166
long numberOfValues
Definition r3types.h:147
size_t nTimeStamp
Definition r3types.h:157
char shortName[MAX_N_SHORT_NAME][MAX_SIZE_SHORT_NAME]
Definition r3types.h:162
long nbLon
Definition r3types.h:156
long stepUnits
Definition r3types.h:148
long editionNumber
Definition r3types.h:146
size_t nDataDate
Definition r3types.h:158
double lonStep
Definition r3types.h:154
long nbLat
Definition r3types.h:155
double latMax
Definition r3types.h:150
double lonLeft
Definition r3types.h:151
int nMessage
Definition r3types.h:145
size_t intervalLimit
Definition r3types.h:168
double latStep
Definition r3types.h:153
size_t nShortName
Definition r3types.h:161
bool allTimeStepOK
Definition r3types.h:142
long timeStamp[MAX_N_TIME_STAMPS]
Definition r3types.h:163
long dataDate[MAX_N_DATA_DATE]
Definition r3types.h:164
size_t nDataTime
Definition r3types.h:159