1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <ctype.h>
6
7 #include "binary.h"
8 #include "cdf.h"
9 #include "cdi.h"
10 #include "cdi_int.h"
11 #include "dmemory.h"
12 #include "file.h"
13 #include "gribapi.h"
14
15 #ifdef HAVE_LIBCGRIBEX
16 #include "cgribex.h"
17 #endif
18
19 int CDI_Default_Calendar = CALENDAR_PROLEPTIC;
20
21 int CDI_Default_InstID = CDI_UNDEFID;
22 int CDI_Default_ModelID = CDI_UNDEFID;
23 int CDI_Default_TableID = CDI_UNDEFID;
24 //int cdiNcMissingValue = CDI_UNDEFID;
25 int CDI_Netcdf_Chunksizehint = CDI_UNDEFID;
26 int CDI_Chunk_Type = CDI_CHUNK_GRID;
27 int CDI_Split_Ltype105 = CDI_UNDEFID;
28
29 bool CDI_Ignore_Att_Coordinates = false;
30 bool CDI_Coordinates_Lon_Lat = false;
31 bool CDI_Ignore_Valid_Range = false;
32 int CDI_Skip_Records = 0;
33 const char *CDI_GRIB1_Template = NULL;
34 const char *CDI_GRIB2_Template = NULL;
35 int CDI_Convention = CDI_CONVENTION_ECHAM;
36 int CDI_Inventory_Mode = 1;
37 int CDI_Version_Info = 1;
38 int CDI_Convert_Cubesphere = 1;
39 int CDI_Read_Cell_Corners = 1;
40 int CDI_CMOR_Mode = 0;
41 int CDI_Reduce_Dim = 0;
42 size_t CDI_Netcdf_Hdr_Pad = 0UL;
43 bool CDI_Netcdf_Lazy_Grid_Load = false;
44
45 char *cdiPartabPath = NULL;
46 int cdiPartabIntern = 1;
47
48 double CDI_Default_Missval = -9.E33;
49 double CDI_Grid_Missval = -9999.;
50
51 static const char Filetypes[][9] = {
52 "UNKNOWN",
53 "GRIB",
54 "GRIB2",
55 "NetCDF",
56 "NetCDF2",
57 "NetCDF4",
58 "NetCDF4c",
59 "NetCDF5",
60 "SERVICE",
61 "EXTRA",
62 "IEG",
63 "HDF5",
64 };
65
66 int CDI_Debug = 0; // If set to 1, debugging
67 int CDI_Recopt = 0;
68
69 bool CDI_gribapi_debug = false;
70 bool CDI_gribapi_grib1 = false;
71 int cdiDefaultLeveltype = -1;
72 int cdiDataUnreduced = 0;
73 int cdiSortName = 0;
74 int cdiSortParam = 0;
75 int cdiHaveMissval = 0;
76
77
78 static
cdiGetenvInt(const char * envName)79 long cdiGetenvInt(const char *envName)
80 {
81 long envValue = -1;
82
83 char *envString = getenv(envName);
84 if ( envString )
85 {
86 long fact = 1;
87 int len = (int) strlen(envString);
88 for ( int loop = 0; loop < len; loop++ )
89 {
90 if ( ! isdigit((int) envString[loop]) )
91 {
92 switch ( tolower((int) envString[loop]) )
93 {
94 case 'k': fact = 1024; break;
95 case 'm': fact = 1048576; break;
96 case 'g': fact = 1073741824; break;
97 default:
98 fact = 0;
99 Message("Invalid number string in %s: %s", envName, envString);
100 Warning("%s must comprise only digits [0-9].",envName);
101 break;
102 }
103 break;
104 }
105 }
106
107 if ( fact ) envValue = fact*atol(envString);
108
109 if ( CDI_Debug ) Message("set %s to %ld", envName, envValue);
110 }
111
112 return envValue;
113 }
114
115 static
cdiPrintDefaults(void)116 void cdiPrintDefaults(void)
117 {
118 fprintf(stderr, "default instID : %d\n"
119 "default modelID : %d\n"
120 "default tableID : %d\n"
121 "default missval : %g\n", CDI_Default_InstID,
122 CDI_Default_ModelID, CDI_Default_TableID, CDI_Default_Missval);
123 }
124
125 #ifdef HAVE_LIBFDB5
126 #include <fdb5/fdb5_config.h>
127 #endif
128
cdiPrintVersion(void)129 void cdiPrintVersion(void)
130 {
131 fprintf(stdout, " CDI library version : %s\n", cdiLibraryVersion());
132 #ifdef HAVE_LIBCGRIBEX
133 fprintf(stdout, " cgribex library version : %s\n", cgribexLibraryVersion());
134 #endif
135 #ifdef HAVE_LIBGRIB_API
136 fprintf(stdout, " ecCodes library version : %s\n", gribapiLibraryVersionString());
137 #endif
138 #ifdef HAVE_LIBNETCDF
139 fprintf(stdout, " NetCDF library version : %s\n", cdfLibraryVersion());
140 #endif
141 #ifdef HAVE_NC4HDF5
142 fprintf(stdout, " hdf5 library version : %s\n", hdfLibraryVersion());
143 #endif
144 #ifdef HAVE_LIBSERVICE
145 fprintf(stdout, " exse library version : %s\n", srvLibraryVersion());
146 #endif
147 fprintf(stdout, " FILE library version : %s\n", fileLibraryVersion());
148 #ifdef HAVE_LIBFDB5
149 fprintf(stdout, " FDB5 library version : %s\n", fdb5_version());
150 #endif
151 }
152
153 static
cdiPrintDatatypes(void)154 void cdiPrintDatatypes(void)
155 {
156 #define XSTRING(x) #x
157 #define STRING(x) XSTRING(x)
158
159 fprintf(stderr, "+-------------+-------+\n"
160 "| types | bytes |\n"
161 "+-------------+-------+\n"
162 "| void * | %3d |\n"
163 "+-------------+-------+\n"
164 "| char | %3d |\n"
165 "+-------------+-------+\n"
166 "| bool | %3d |\n"
167 "| short | %3d |\n"
168 "| int | %3d |\n"
169 "| long | %3d |\n"
170 "| long long | %3d |\n"
171 "| size_t | %3d |\n"
172 "| off_t | %3d |\n"
173 "+-------------+-------+\n"
174 "| float | %3d |\n"
175 "| double | %3d |\n"
176 "| long double | %3d |\n"
177 "+-------------+-------+\n\n",
178 (int) sizeof(void *), (int) sizeof(char), (int) sizeof(bool),
179 (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), (int) sizeof(long long),
180 (int) sizeof(size_t), (int) sizeof(off_t),
181 (int) sizeof(float), (int) sizeof(double), (int) sizeof(long double));
182
183 fprintf(stderr,
184 "+-------------+-----------+\n"
185 "| INT32 | %-9s |\n"
186 "| INT64 | %-9s |\n"
187 "| FLT32 | %-9s |\n"
188 "| FLT64 | %-9s |\n"
189 "| SizeType | %-9s |\n"
190 "| DateType | %-9s |\n"
191 "+-------------+-----------+\n",
192 STRING(INT32), STRING(INT64), STRING(FLT32), STRING(FLT64), STRING(CDI_SIZE_TYPE), STRING(CDI_DATE_TYPE));
193
194 fprintf(stderr, "\n byte ordering is %s\n\n",
195 ((HOST_ENDIANNESS == CDI_BIGENDIAN) ? "BIGENDIAN"
196 : ((HOST_ENDIANNESS == CDI_LITTLEENDIAN) ? "LITTLEENDIAN"
197 : "Unhandled endianness!")));
198
199 #undef STRING
200 #undef XSTRING
201 }
202
203
cdiDebug(int level)204 void cdiDebug(int level)
205 {
206 unsigned ulevel = (unsigned) level;
207
208 if ( ulevel == 1 || (ulevel & 2) ) CDI_Debug = 1;
209
210 if ( CDI_Debug ) Message("debug level %d", level);
211
212 if ( ulevel == 1 || (ulevel & 4) ) memDebug(1);
213
214 if ( ulevel == 1 || (ulevel & 8) ) fileDebug(1);
215
216 if ( ulevel == 1 || (ulevel & 16) )
217 {
218 #ifdef HAVE_LIBCGRIBEX
219 gribSetDebug(1);
220 #endif
221 #ifdef HAVE_LIBNETCDF
222 cdfDebug(1);
223 #endif
224 #ifdef HAVE_LIBSERVICE
225 srvDebug(1);
226 #endif
227 #ifdef HAVE_LIBEXTRA
228 extDebug(1);
229 #endif
230 #ifdef HAVE_LIBIEG
231 iegDebug(1);
232 #endif
233 }
234
235 if ( CDI_Debug )
236 {
237 cdiPrintDefaults();
238 cdiPrintDatatypes();
239 }
240 }
241
242
cdiHaveFiletype(int filetype)243 int cdiHaveFiletype(int filetype)
244 {
245 int status = 0;
246
247 switch (filetype)
248 {
249 #ifdef HAVE_LIBSERVICE
250 case CDI_FILETYPE_SRV: status = 1; break;
251 #endif
252 #ifdef HAVE_LIBEXTRA
253 case CDI_FILETYPE_EXT: status = 1; break;
254 #endif
255 #ifdef HAVE_LIBIEG
256 case CDI_FILETYPE_IEG: status = 1; break;
257 #endif
258 #ifdef HAVE_LIBGRIB
259 #if defined HAVE_LIBGRIB_API || defined HAVE_LIBCGRIBEX
260 case CDI_FILETYPE_GRB: status = 1; break;
261 #endif
262 #ifdef HAVE_LIBGRIB_API
263 case CDI_FILETYPE_GRB2: status = 1; break;
264 #endif
265 #endif
266 #ifdef HAVE_LIBNETCDF
267 case CDI_FILETYPE_NC: status = 1; break;
268 #ifdef HAVE_NETCDF2
269 case CDI_FILETYPE_NC2: status = 1; break;
270 #endif
271 #ifdef HAVE_NETCDF4
272 case CDI_FILETYPE_NC4: status = 1; break;
273 case CDI_FILETYPE_NC4C: status = 1; break;
274 #endif
275 #ifdef HAVE_NETCDF5
276 case CDI_FILETYPE_NC5: status = 1; break;
277 #endif
278 #endif
279 default: status = 0; break;
280 }
281
282 return status;
283 }
284
285
cdiDefTableID(int tableID)286 void cdiDefTableID(int tableID)
287 {
288 CDI_Default_TableID = tableID;
289 int modelID = CDI_Default_ModelID = tableInqModel(tableID);
290 CDI_Default_InstID = modelInqInstitut(modelID);
291 }
292
293 static
cdiSetChunk(const char * chunkAlgo)294 void cdiSetChunk(const char *chunkAlgo)
295 {
296 int algo = -1;
297
298 if (strIsEqual("auto", chunkAlgo)) algo = CDI_CHUNK_AUTO;
299 else if (strIsEqual("grid", chunkAlgo)) algo = CDI_CHUNK_GRID;
300 else if (strIsEqual("lines", chunkAlgo)) algo = CDI_CHUNK_LINES;
301 else
302 Warning("Invalid environment variable CDI_CHUNK_ALGO: %s", chunkAlgo);
303
304 if ( algo != -1 )
305 {
306 CDI_Chunk_Type = algo;
307 if ( CDI_Debug ) Message("set ChunkAlgo to %s", chunkAlgo);
308 }
309 }
310
311
cdiSetEccodesGrib1(bool value)312 void cdiSetEccodesGrib1(bool value)
313 {
314 #ifndef HAVE_LIBGRIB_API
315 if (value)
316 {
317 Warning("ecCodes support not compiled in, used CGRIBEX to decode/encode GRIB1 records!");
318 value = false;
319 }
320 #endif
321 CDI_gribapi_grib1 = value;
322 }
323
324
cdiInitialize(void)325 void cdiInitialize(void)
326 {
327 static bool Init_CDI = false;
328
329 if ( ! Init_CDI )
330 {
331 Init_CDI = true;
332 char *envstr;
333 long value;
334
335 #ifdef HAVE_LIBCGRIBEX
336 gribFixZSE(1); // 1: Fix ZeroShiftError of simple packed spherical harmonics
337 gribSetConst(1); // 1: Don't pack constant fields on regular grids
338 #endif
339 #ifdef HAVE_LIBGRIB_API
340 grib_multi_support_off(NULL);
341 #endif
342
343 value = cdiGetenvInt("CDI_DEBUG");
344 if ( value >= 0 ) CDI_Debug = (int) value;
345
346 value = cdiGetenvInt("CDI_GRIBAPI_DEBUG");
347 if ( value >= 0 ) CDI_gribapi_debug = (bool) value;
348
349 value = cdiGetenvInt("CDI_ECCODES_DEBUG");
350 if ( value >= 0 ) CDI_gribapi_debug = (bool) value;
351
352 value = cdiGetenvInt("CDI_ECCODES_GRIB1");
353 if ( value >= 0 ) cdiSetEccodesGrib1((bool) value);
354
355 value = cdiGetenvInt("CDI_READ_CELL_CORNERS");
356 if ( value >= 0 ) CDI_Read_Cell_Corners = (int) value;
357
358 value = cdiGetenvInt("CDI_RECOPT");
359 if ( value >= 0 ) CDI_Recopt = (int) value;
360
361 value = cdiGetenvInt("CDI_REGULARGRID");
362 if ( value >= 0 ) cdiDataUnreduced = (int) value;
363
364 value = cdiGetenvInt("CDI_SORTNAME");
365 if ( value >= 0 ) cdiSortName = (int) value;
366
367 value = cdiGetenvInt("CDI_SORTPARAM");
368 if ( value >= 0 ) cdiSortParam = (int) value;
369
370 value = cdiGetenvInt("CDI_HAVE_MISSVAL");
371 if ( value >= 0 ) cdiHaveMissval = (int) value;
372
373 value = cdiGetenvInt("CDI_LEVELTYPE");
374 if ( value >= 0 ) cdiDefaultLeveltype = (int) value;
375
376 value = cdiGetenvInt("CDI_NETCDF_HDR_PAD");
377 if ( value >= 0 ) CDI_Netcdf_Hdr_Pad = (size_t) value;
378
379 envstr = getenv("CDI_GRIB1_TEMPLATE");
380 if ( envstr ) CDI_GRIB1_Template = envstr;
381
382 envstr = getenv("CDI_GRIB2_TEMPLATE");
383 if ( envstr ) CDI_GRIB2_Template = envstr;
384
385 envstr = getenv("CDI_MISSVAL");
386 if ( envstr ) CDI_Default_Missval = atof(envstr);
387 /*
388 envstr = getenv("NC_MISSING_VALUE");
389 if ( envstr ) cdiNcMissingValue = atoi(envstr);
390 */
391 envstr = getenv("NC_CHUNKSIZEHINT");
392 if ( envstr ) CDI_Netcdf_Chunksizehint = atoi(envstr);
393
394 envstr = getenv("CDI_CHUNK_ALGO");
395 if ( envstr ) cdiSetChunk(envstr);
396
397 envstr = getenv("SPLIT_LTYPE_105");
398 if ( envstr ) CDI_Split_Ltype105 = atoi(envstr);
399
400 envstr = getenv("IGNORE_ATT_COORDINATES");
401 if ( envstr ) CDI_Ignore_Att_Coordinates = atoi(envstr) > 0;
402
403 envstr = getenv("CDI_COORDINATES_LONLAT");
404 if ( envstr ) CDI_Coordinates_Lon_Lat = atoi(envstr) > 0;
405
406 envstr = getenv("IGNORE_VALID_RANGE");
407 if ( envstr ) CDI_Ignore_Valid_Range = atoi(envstr) > 0;
408
409 envstr = getenv("CDI_SKIP_RECORDS");
410 if ( envstr )
411 {
412 CDI_Skip_Records = atoi(envstr);
413 CDI_Skip_Records = CDI_Skip_Records > 0 ? CDI_Skip_Records : 0;
414 }
415
416 envstr = getenv("CDI_CONVENTION");
417 if ( envstr )
418 {
419 if ( strcmp(envstr, "CF") == 0 || strcmp(envstr, "cf") == 0 )
420 {
421 CDI_Convention = CDI_CONVENTION_CF;
422 if (CDI_Debug) Message("CDI convention was set to CF!");
423 }
424 }
425
426 envstr = getenv("CDI_INVENTORY_MODE");
427 if (envstr)
428 {
429 if (strncmp(envstr, "time", 4) == 0)
430 {
431 CDI_Inventory_Mode = 2;
432 if (CDI_Debug) Message("Inventory mode was set to timestep!");
433 }
434 }
435
436 envstr = getenv("CDI_VERSION_INFO");
437 if (envstr)
438 {
439 const int ival = atoi(envstr);
440 if (ival == 0 || ival == 1)
441 {
442 CDI_Version_Info = ival;
443 if (CDI_Debug) Message("CDI_Version_Info = %s", envstr);
444 }
445 }
446
447 envstr = getenv("CDI_CONVERT_CUBESPHERE");
448 if (envstr)
449 {
450 const int ival = atoi(envstr);
451 if (ival == 0 || ival == 1)
452 {
453 CDI_Convert_Cubesphere = ival;
454 if (CDI_Debug) Message("CDI_Convert_Cubesphere = %s", envstr);
455 }
456 }
457
458 envstr = getenv("CDI_CALENDAR");
459 if ( envstr )
460 {
461 // clang-format off
462 if (strncmp(envstr, "standard", 8) == 0) CDI_Default_Calendar = CALENDAR_STANDARD;
463 else if (strncmp(envstr, "gregorian", 9) == 0) CDI_Default_Calendar = CALENDAR_GREGORIAN;
464 else if (strncmp(envstr, "proleptic", 9) == 0) CDI_Default_Calendar = CALENDAR_PROLEPTIC;
465 else if (strncmp(envstr, "360days", 7) == 0) CDI_Default_Calendar = CALENDAR_360DAYS;
466 else if (strncmp(envstr, "365days", 7) == 0) CDI_Default_Calendar = CALENDAR_365DAYS;
467 else if (strncmp(envstr, "366days", 7) == 0) CDI_Default_Calendar = CALENDAR_366DAYS;
468 else if (strncmp(envstr, "none", 4) == 0) CDI_Default_Calendar = CALENDAR_NONE;
469 // clang-format on
470 if ( CDI_Debug ) Message("Default calendar set to %s!", envstr);
471 }
472 #ifdef HAVE_LIBCGRIBEX
473 gribSetCalendar(CDI_Default_Calendar);
474 #endif
475
476 envstr = getenv("PARTAB_INTERN");
477 if ( envstr ) cdiPartabIntern = atoi(envstr);
478
479 envstr = getenv("PARTAB_PATH");
480 if ( envstr ) cdiPartabPath = strdup(envstr);
481 }
482 }
483
484
strfiletype(int filetype)485 const char *strfiletype(int filetype)
486 {
487 int size = (int) (sizeof(Filetypes)/sizeof(char *));
488 return (filetype > 0 && filetype < size) ? Filetypes[filetype] : Filetypes[0];
489 }
490
491
cdiDefGlobal(const char * string,int value)492 void cdiDefGlobal(const char *string, int value)
493 {
494 // clang-format off
495 if (strIsEqual(string, "REGULARGRID") ) cdiDataUnreduced = value;
496 else if (strIsEqual(string, "ECCODES_DEBUG") ) CDI_gribapi_debug = (bool) value;
497 else if (strIsEqual(string, "ECCODES_GRIB1") ) cdiSetEccodesGrib1((bool) value);
498 else if (strIsEqual(string, "SORTNAME") ) cdiSortName = value;
499 else if (strIsEqual(string, "SORTPARAM") ) cdiSortParam = value;
500 else if (strIsEqual(string, "HAVE_MISSVAL") ) cdiHaveMissval = value;
501 else if (strIsEqual(string, "NC_CHUNKSIZEHINT") ) CDI_Netcdf_Chunksizehint = value;
502 else if (strIsEqual(string, "READ_CELL_CORNERS") ) CDI_Read_Cell_Corners = value;
503 else if (strIsEqual(string, "CMOR_MODE") ) CDI_CMOR_Mode = value;
504 else if (strIsEqual(string, "REDUCE_DIM") ) CDI_Reduce_Dim = value;
505 else if (strIsEqual(string, "NETCDF_HDR_PAD") ) CDI_Netcdf_Hdr_Pad = (size_t) value;
506 else if (strIsEqual(string, "NETCDF_LAZY_GRID_LOAD")) CDI_Netcdf_Lazy_Grid_Load = (bool) value;
507 else Warning("Unsupported global key: %s", string);
508 // clang-format on
509 }
510
511
cdiDefMissval(double missval)512 void cdiDefMissval(double missval)
513 {
514 cdiInitialize();
515
516 CDI_Default_Missval = missval;
517 }
518
519
cdiInqMissval(void)520 double cdiInqMissval(void)
521 {
522 cdiInitialize();
523
524 return CDI_Default_Missval;
525 }
526
527
cdiBaseFiletype(int filetype)528 int cdiBaseFiletype(int filetype)
529 {
530 switch (filetype)
531 {
532 case CDI_FILETYPE_NC:
533 case CDI_FILETYPE_NC2:
534 case CDI_FILETYPE_NC4:
535 case CDI_FILETYPE_NC4C:
536 case CDI_FILETYPE_NC5: return CDI_FILETYPE_NETCDF;
537 default: return filetype;
538 }
539
540 return filetype;
541 }
542
543 /*
544 * Local Variables:
545 * c-file-style: "Java"
546 * c-basic-offset: 2
547 * indent-tabs-mode: nil
548 * show-trailing-whitespace: t
549 * require-trailing-newline: t
550 * End:
551 */
552
553