NCEPLIBS-g2c 1.9.0
Loading...
Searching...
No Matches
g2cdegrib2.c
Go to the documentation of this file.
1
8#include "grib2_int.h"
9#include <stdarg.h>
10#include <math.h>
11
14
17
19#define G2C_MAX_TYPE_OF_FIXED_SURFACE_LEN 40
20
21#define G2C_DATE_TIME_LEN 25
48int
49g2c_get_datetime(int ipdtn, long long int *ipdtmpl, short year, unsigned char month, unsigned char day,
50 unsigned char hour, unsigned char minute, unsigned char second, char *tabbrev)
51{
52 int iutpos, iutpos2, iunit, iunit2;
53 char tunit[G2C_DATE_TIME_LEN], tunit2[G2C_DATE_TIME_LEN];
54 char reftime[G2C_DATE_TIME_LEN], endtime[G2C_DATE_TIME_LEN], tmpval2[G2C_DATE_TIME_LEN];
55 int itemp, itemp2, is;
56 /* character(len = 16) :: reftime, endtime */
57 /* character(len = 10) :: tmpval, tmpval2 */
58 /* character(len = 10) :: tunit, tunit2 */
59 /* integer, dimension(200) :: ipos, ipos2 */
60 /* integer :: is, itemp, itemp2, iunit, iuni2t2, iunit2, iutpos, iutpos2, j */
61
62 /* data ipos /7*0, 16, 23, 17, 19, 18, 32, 31, 27*0, 17, 20, 0, 0, 22, & */
63 /* 25, 43*0, 23, 109*0/ */
64
65 int ipos[200] = {
66 0, 0, 0, 0, 0, 0, 0, 16, 23, 17, 19, 18, 32, 31, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 17, 20, 0, 0, 22, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
76 };
77 /* data ipos2 /7*0, 26, 33, 27, 29, 28, 42, 41, 27*0, 22, 30, 0, 0, 32, & */
78 /* 35, 43*0, 33, 109*0/ */
79
80 int ipos2[200] = {
81 0, 0, 0, 0, 0, 0, 0, 26, 33, 27,
82 29, 28, 42, 41, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
85 0, 22, 30, 0, 0, 32, 35, 0, 0, 0,
86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
90 33, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
92 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
93 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
94 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
95 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
101 };
102 /* tabbrev(1:100) = " " */
103
104 /* Check inputs. */
105 assert(ipdtn >= 0 && ipdtmpl && tabbrev);
106
107 /* The unit of time range is stored in the product template, but
108 * stored at different places for different template numbers. Find
109 * where it is stored for this product template number. */
110 if (ipdtn <= 15 || ipdtn == 32 || ipdtn == 50 || ipdtn == 51 || ipdtn == 91)
111 iutpos = 7;
112 else if (ipdtn >= 40 && ipdtn <= 43)
113 iutpos = 8;
114 else if (ipdtn >= 44 && ipdtn <= 47)
115 iutpos = 13;
116 else if (ipdtn == 48)
117 iutpos = 18;
118 else if (ipdtn == 52)
119 iutpos = 10;
120 else
121 iutpos = 7;
122
123 /* Determine first unit of time range. */
124 switch (ipdtmpl[iutpos])
125 {
126 case 0:
127 strcpy(tunit, "minute");
128 iunit = 1;
129 break;
130 case 1:
131 strcpy(tunit, "hour");
132 iunit = 1;
133 break;
134 case 2:
135 strcpy(tunit, "day");
136 iunit = 1;
137 break;
138 case 3:
139 strcpy(tunit, "month");
140 iunit = 1;
141 break;
142 case 4:
143 strcpy(tunit, "year");
144 iunit = 1;
145 break;
146 case 10:
147 strcpy(tunit, "hour");
148 iunit = 3;
149 break;
150 case 11:
151 strcpy(tunit, "hour");
152 iunit = 6;
153 break;
154 default:
155 strcpy(tunit, "hour");
156 iunit = 1;
157 }
158
159 /* Determine second unit of time range. */
160 if (ipdtn > 0)
161 iutpos2 = ipos2[ipdtn - 1];
162 else
163 iutpos2 = 0;
164 switch (ipdtmpl[iutpos2])
165 {
166 case 0:
167 strcpy(tunit2, "minute");
168 iunit2 = 1;
169 break;
170 case 1:
171 strcpy(tunit2, "hour");
172 iunit2 = 1;
173 break;
174 case 2:
175 strcpy(tunit2, "day");
176 iunit2 = 1;
177 break;
178 case 3:
179 strcpy(tunit2, "month");
180 iunit2 = 1;
181 break;
182 case 4:
183 strcpy(tunit2, "year");
184 iunit2 = 1;
185 break;
186 case 10:
187 strcpy(tunit2, "hour");
188 iunit2 = 3;
189 break;
190 case 11:
191 strcpy(tunit2, "hour");
192 iunit2 = 6;
193 break;
194 default:
195 strcpy(tunit2, "hour");
196 iunit2 = 1;
197 }
198
199 /* Write a string with the date and time from section 1 of the message. */
200 sprintf(reftime, "%4.4d%2.2d%2.2d%2.2d:%2.2d:%2.2d", year, month, day, hour, minute, second);
201
202 itemp = abs(ipdtmpl[iutpos + 1]) * iunit;
203
204 /* write(tmpval, '(I0)') itemp */
205
206 sprintf(tabbrev, "valid at %lld", ipdtmpl[iutpos + 1]);
207 /* write(tabbrev, fmt = '("valid at ", i4)') ipdtmpl(iutpos + 1) */
208
209 /* Determine Reference Time: Year, Month, Day, Hour, Minute, Second. */
210
211 if ((ipdtn >= 0 && ipdtn <= 7) || ipdtn == 15 || ipdtn == 20 || (ipdtn >= 30 && ipdtn <= 32) || ipdtn == 40 ||
212 ipdtn == 41 || ipdtn == 44 || ipdtn == 45 || ipdtn == 48 || (ipdtn >= 50 && ipdtn <= 52)) /* Point in time. */
213 {
214 sprintf(tabbrev, "valid %d %s after %s", itemp, tunit, reftime);
215 }
216 else
217 {
218 is = ipos[ipdtn - 1] - 1; /* Continuous time interval. */
219 sprintf(endtime, "%4.4d%2.2d%2.2d%2.2d:%2.2d:%2.2d", (int)ipdtmpl[is], (int)ipdtmpl[is + 1],
220 (int)ipdtmpl[is + 2], (int)ipdtmpl[is + 3], (int)ipdtmpl[is + 4], (int)ipdtmpl[is + 5]);
221 /* write(endtime, fmt = '(i4,3i2.2,":",i2.2,":",i2.2)') (ipdtmpl(j), j = is, is + 5) */
222 itemp2 = abs(ipdtmpl[iutpos2]) * iunit2;
223 itemp2 = itemp + itemp2;
224 sprintf(tmpval2, "%d", itemp2);
225 if (ipdtn == 8 && ipdtmpl[8] < 0)
226 {
227 /* tabbrev = "(" // trim(tmpval) // " -" // trim(tmpval2) // ") valid " // trim(tmpval) // " " // trim(tunit) // " before " // reftime // " to " //endtime */
228 sprintf(tabbrev, "(%d -%d) valid %d %s before %s to %s", itemp, itemp2, itemp, tunit, reftime, endtime);
229 }
230 else if ((ipdtn >= 8 && ipdtn <= 14) || (ipdtn >= 42 && ipdtn <= 47) ||
231 ipdtn == 91) /* Continuous time interval */
232 {
233 /* write(tmpval2, '(I0)') itemp2 */
234 /* tabbrev = "(" // trim(tmpval) // " -" // trim(tmpval2) // " hr) valid " // trim(tmpval) // " " // trim(tunit) // " after " // reftime // " to " // endtime */
235 sprintf(tabbrev, "(%d -%d hr) valid %d %s after %s to %s", itemp, itemp2, itemp, tunit, reftime, endtime);
236 }
237 }
238
239 return G2C_NOERROR;
240}
241
255static int
256format_level(char *cbuf, int ival, int scale)
257{
258 char tmpcbuf[37];
259
260 assert(cbuf);
261
262 if (!scale)
263 sprintf(cbuf, "%d", ival);
264 else
265 {
266 float rval;
267
268 rval = (float)ival * pow(10, -1 * scale);
269 if (rval == (int)rval)
270 {
271 /* This adds a space in front of the number, to match
272 * behavor of the Fortran degrib2 utility. */
273 sprintf(cbuf, " %d", (int)rval);
274 }
275 else
276 {
277 char fmt[37];
278 sprintf(fmt, "%s%d%s", "%.", (int)abs(scale), "f");
279 sprintf(tmpcbuf, fmt, rval);
280 strcpy(cbuf, &tmpcbuf[1]);
281 }
282
283 }
284 return G2C_NOERROR;
285}
286
311int
312g2c_get_level_desc(int ipdtn, long long int *ipdtmpl, char *level_desc)
313{
314 int ipos;
315 char tmpval1[37];
316 char tmpval2[37];
317 int ret;
318
319 /* Check inputs. */
320 assert(ipdtn >= 0 && ipdtmpl && level_desc);
321
322 /* Use the template number to determine which element of the
323 * product template array holds the "Type of first fixed surface"
324 * value (which will be stored in ipos). */
325 if (ipdtn <= 15)
326 ipos = 9;
327 else if (ipdtn >= 40 && ipdtn <= 43)
328 ipos = 10;
329 else if (ipdtn >= 44 && ipdtn <= 47)
330 ipos = 15;
331 else if (ipdtn == 48)
332 ipos = 20;
333 else if (ipdtn >= 50 && ipdtn <= 51)
334 ipos = 9;
335 else if (ipdtn == 52)
336 ipos = 12;
337 else if (ipdtn == 91)
338 ipos = 9;
339 else
340 ipos = 9;
341
342 /* Pressure Level. */
343 if (ipdtmpl[ipos] == 100 && ipdtmpl[ipos + 3] == 255)
344 {
345 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1] + 2)))
346 return ret;
347 sprintf(level_desc, "%s %s", tmpval1, "mb");
348 }
349 /* Pressure Layer. */
350 else if (ipdtmpl[ipos] == 100 && ipdtmpl[ipos + 3] == 100)
351 {
352 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1] + 2)))
353 return ret;
354 if ((ret = format_level(tmpval2, ipdtmpl[ipos + 5], ipdtmpl[ipos + 4] + 2)))
355 return ret;
356 sprintf(level_desc, "%s - %s mb", tmpval1, tmpval2);
357 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1) + 2) */
358 /* call frmt(tmpval2, ipdtmpl(ipos + 5), ipdtmpl(ipos + 4) + 2) */
359 /* level_desc = trim(tmpval1)//" - "//trim(tmpval2)//" mb" */
360 }
361 else if (ipdtmpl[ipos] == 101)
362 {
363 strcpy(level_desc, " Mean Sea Level");
364 }
365 /* Altitude above MSL. */
366 else if (ipdtmpl[ipos] == 102 && ipdtmpl[ipos + 3] == 255)
367 {
368 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1])))
369 return ret;
370 sprintf(level_desc, "%s %s", tmpval1, "m above MSL");
371 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1)) */
372 /* level_desc = trim(tmpval1)//" m above MSL" */
373 }
374 /* Height above Ground. */
375 else if (ipdtmpl[ipos] == 103 && ipdtmpl[ipos + 3] == 255)
376 {
377 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1)) */
378 /* level_desc = trim(tmpval1)//" m above ground" */
379 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1])))
380 return ret;
381 sprintf(level_desc, "%s %s", tmpval1, "m above ground");
382 }
383 /* Height above Ground. */
384 else if (ipdtmpl[ipos] == 103 && ipdtmpl[ipos + 3] == 103)
385 {
386 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1])))
387 return ret;
388 if ((ret = format_level(tmpval2, ipdtmpl[ipos + 5], ipdtmpl[ipos + 4])))
389 return ret;
390 sprintf(level_desc, "%s - %s m AGL", tmpval1, tmpval2);
391 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1)) */
392 /* call frmt(tmpval2, ipdtmpl(ipos + 5), ipdtmpl(ipos + 4)) */
393 /* level_desc = trim(tmpval1)//" - "//trim(tmpval2)//" m AGL" */
394 }
395 /* Sigma Level. */
396 else if (ipdtmpl[ipos] == 104 && ipdtmpl[ipos + 3] == 255)
397 {
398 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1])))
399 return ret;
400 sprintf(level_desc, "%s %s", tmpval1, "sigma");
401 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1)) */
402 /* level_desc = trim(tmpval1)//" sigma" */
403 }
404 /* Sigma Layer. */
405 else if (ipdtmpl[ipos] == 104 && ipdtmpl[ipos + 3] == 104)
406 {
407 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1])))
408 return ret;
409 if ((ret = format_level(tmpval2, ipdtmpl[ipos + 5], ipdtmpl[ipos + 4])))
410 return ret;
411 sprintf(level_desc, "%s - %s sigma", tmpval1, tmpval2);
412 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1)) */
413 /* call frmt(tmpval2, ipdtmpl(ipos + 5), ipdtmpl(ipos + 4)) */
414 /* level_desc = trim(tmpval1)//" - "//trim(tmpval2)//" sigma" */
415 }
416 /* Hybrid Level. */
417 else if (ipdtmpl[ipos] == 105 && ipdtmpl[ipos + 3] == 255)
418 {
419 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1])))
420 return ret;
421 sprintf(level_desc, "%s %s", tmpval1, "hybrid lvl");
422 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1)) */
423 /* level_desc = trim(tmpval1)//" hybrid lvl" */
424 }
425 /* Hybrid Level. */
426 else if (ipdtmpl[ipos] == 105 && ipdtmpl[ipos + 3] == 105)
427 {
428 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1])))
429 return ret;
430 if ((ret = format_level(tmpval2, ipdtmpl[ipos + 5], ipdtmpl[ipos + 4])))
431 return ret;
432 sprintf(level_desc, "%s - %s hybrid lvl", tmpval1, tmpval2);
433 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1)) */
434 /* call frmt(tmpval2, ipdtmpl(ipos + 5), ipdtmpl(ipos + 4)) */
435 /* level_desc = trim(tmpval1)//" - "//trim(tmpval2)//" hybrid lvl" */
436 }
437 /* Depth Below Land Sfc. */
438 else if (ipdtmpl[ipos] == 106 && ipdtmpl[ipos + 3] == 255)
439 {
440 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1])))
441 return ret;
442 sprintf(level_desc, "%s %s", tmpval1, "m below land");
443 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1)) */
444 /* level_desc = trim(tmpval1)//" m below land" */
445 }
446 /* Depth Below Land Sfc Layer. */
447 else if (ipdtmpl[ipos] == 106 && ipdtmpl[ipos + 3] == 106)
448 {
449 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1])))
450 return ret;
451 if ((ret = format_level(tmpval2, ipdtmpl[ipos + 5], ipdtmpl[ipos + 4])))
452 return ret;
453 sprintf(level_desc, "%s - %s m DBLY", tmpval1, tmpval2);
454 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1)) */
455 /* call frmt(tmpval2, ipdtmpl(ipos + 5), ipdtmpl(ipos + 4)) */
456 /* level_desc = trim(tmpval1)//" - "//trim(tmpval2)//" m DBLY" */
457 }
458 else if (ipdtmpl[ipos] == 107)
459 {
460 strcpy(level_desc, " Isentropic level");
461 }
462 /* Press Diff from Ground Layer. */
463 else if (ipdtmpl[ipos] == 108 && ipdtmpl[ipos + 3] == 108)
464 {
465 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1] + 2)))
466 return ret;
467 if ((ret = format_level(tmpval2, ipdtmpl[ipos + 5], ipdtmpl[ipos + 4] + 2)))
468 return ret;
469 sprintf(level_desc, "%s - %s mb SPDY", tmpval1, tmpval2);
470 /* write(tmpval1, *) ipdtmpl(ipos + 2)/100. */
471 /* write(tmpval2, *) ipdtmpl(ipos + 5)/100. */
472 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1) + 2) */
473 /* call frmt(tmpval2, ipdtmpl(ipos + 5), ipdtmpl(ipos + 4) + 2) */
474 /* level_desc = trim(tmpval1)//" - "//trim(tmpval2)//" mb SPDY" */
475 }
476 else if (ipdtmpl[ipos] == 110)
477 {
478 strcpy(level_desc, " Layer bet 2-hyb lvl");
479 }
480 /* Potential Vorticity Sfc. */
481 else if (ipdtmpl[ipos] == 109 && ipdtmpl[ipos + 3] == 255)
482 {
483 if ((ret = format_level(tmpval1, ipdtmpl[ipos + 2], ipdtmpl[ipos + 1])))
484 return ret;
485 sprintf(level_desc, "%s %s", tmpval1, "pv surface");
486 /* write(tmpval1, *) ipdtmpl(ipos + 2). */
487 /* call frmt(tmpval1, ipdtmpl(ipos + 2), ipdtmpl(ipos + 1)-6) */
488 /* level_desc = trim(tmpval1)//" pv surface" */
489 }
490 else if (ipdtmpl[ipos] == 111)
491 strcpy(level_desc, " Eta level");
492 else if (ipdtmpl[ipos] == 114)
493 strcpy(level_desc, " Layer bet. 2-isent.");
494 else if (ipdtmpl[ipos] == 117)
495 strcpy(level_desc, " Mixed layer depth");
496 else if (ipdtmpl[ipos] == 120)
497 strcpy(level_desc, " Layer bet. 2-Eta lvl");
498 else if (ipdtmpl[ipos] == 121)
499 strcpy(level_desc, " Layer bet. 2-isob.");
500 else if (ipdtmpl[ipos] == 125)
501 strcpy(level_desc, " Specified height lvl");
502 else if (ipdtmpl[ipos] == 126)
503 strcpy(level_desc, " Isobaric level");
504 else if (ipdtmpl[ipos] == 160)
505 strcpy(level_desc, " Depth below sea lvl");
506 else if (ipdtmpl[ipos] == 170)
507 strcpy(level_desc, " Ionospheric D-region lvl");
508 else if (ipdtmpl[ipos] == 1)
509 strcpy(level_desc, " Surface");
510 else if (ipdtmpl[ipos] == 2)
511 strcpy(level_desc, " Cloud base lvl");
512 else if (ipdtmpl[ipos] == 3)
513 strcpy(level_desc, " Cloud top lvl");
514 else if (ipdtmpl[ipos] == 4)
515 strcpy(level_desc, " 0 Deg Isotherm");
516 else if (ipdtmpl[ipos] == 5) /* from the surface. */
517 strcpy(level_desc, " Level of adiabatic" );
518 else if (ipdtmpl[ipos] == 6)
519 strcpy(level_desc, " Max wind lvl");
520 else if (ipdtmpl[ipos] == 7)
521 strcpy(level_desc, " Tropopause");
522 else if (ipdtmpl[ipos] == 8)
523 strcpy(level_desc, " Nom. top");
524 else if (ipdtmpl[ipos] == 9)
525 strcpy(level_desc, " Sea Bottom");
526 else if (ipdtmpl[ipos] == 10)
527 strcpy(level_desc, " Entire Atmosphere");
528 else if (ipdtmpl[ipos] == 11)
529 strcpy(level_desc, " Cumulonimbus Base");
530 else if (ipdtmpl[ipos] == 12)
531 strcpy(level_desc, " Cumulonimbus Top");
532 else if (ipdtmpl[ipos] == 20)
533 strcpy(level_desc, " Isothermal level");
534 else if (ipdtmpl[ipos] == 200)
535 strcpy(level_desc, " Entire Atmosphere");
536 else if (ipdtmpl[ipos] == 201)
537 strcpy(level_desc, " Entire ocean");
538 else if (ipdtmpl[ipos] == 204)
539 strcpy(level_desc, " Highest Frz. lvl");
540 else if (ipdtmpl[ipos] == 206)
541 strcpy(level_desc, " Grid scale cloud bl");
542 else if (ipdtmpl[ipos] == 207)
543 strcpy(level_desc, " Grid scale cloud tl");
544 else if (ipdtmpl[ipos] == 209)
545 strcpy(level_desc, " Boundary layer cbl");
546 else if (ipdtmpl[ipos] == 210)
547 strcpy(level_desc, " Boundary layer ctl");
548 else if (ipdtmpl[ipos] == 211)
549 strcpy(level_desc, " Boundary layer cl");
550 else if (ipdtmpl[ipos] == 212)
551 strcpy(level_desc, " Low cloud bot. lvl");
552 else if (ipdtmpl[ipos] == 213)
553 strcpy(level_desc, " Low cloud top lvl");
554 else if (ipdtmpl[ipos] == 214)
555 strcpy(level_desc, " Low cloud layer");
556 else if (ipdtmpl[ipos] == 215)
557 strcpy(level_desc, " Cloud ceiling");
558 else if (ipdtmpl[ipos] == 220)
559 strcpy(level_desc, " Planetary boundary");
560 else if (ipdtmpl[ipos] == 221)
561 strcpy(level_desc, " Layer 2 Hybrid lvl");
562 else if (ipdtmpl[ipos] == 222)
563 strcpy(level_desc, " Mid. cloud bot. lvl");
564 else if (ipdtmpl[ipos] == 223)
565 strcpy(level_desc, " Mid. cloud top lvl");
566 else if (ipdtmpl[ipos] == 224)
567 strcpy(level_desc, " Middle cloud layer");
568 else if (ipdtmpl[ipos] == 232)
569 strcpy(level_desc, " High cloud bot. lvl");
570 else if (ipdtmpl[ipos] == 233)
571 strcpy(level_desc, " High cloud top lvl");
572 else if (ipdtmpl[ipos] == 234)
573 strcpy(level_desc, " High cloud layer");
574 else if (ipdtmpl[ipos] == 235)
575 strcpy(level_desc, " Ocean Isotherm lvl");
576 else if (ipdtmpl[ipos] == 236)
577 strcpy(level_desc, " Layer 2-depth below");
578 else if (ipdtmpl[ipos] == 237)
579 strcpy(level_desc, " Bot. Ocean mix. lyr");
580 else if (ipdtmpl[ipos] == 238)
581 strcpy(level_desc, " Bot. Ocean iso. lyr");
582 else if (ipdtmpl[ipos] == 239) /* isothermal level (S26CY). */
583 strcpy(level_desc, " layer ocean sfc 26C" );
584 else if (ipdtmpl[ipos] == 240)
585 strcpy(level_desc, " Ocean Mixed Layer");
586 else if (ipdtmpl[ipos] == 241)
587 strcpy(level_desc, " Order Seq. Of Data");
588 else if (ipdtmpl[ipos] == 242)
589 strcpy(level_desc, " Con. cloud bot. lvl");
590 else if (ipdtmpl[ipos] == 243)
591 strcpy(level_desc, " Con. cloud top lvl");
592 else if (ipdtmpl[ipos] == 244)
593 strcpy(level_desc, " Conv. cloud layer");
594 else if (ipdtmpl[ipos] == 245)
595 strcpy(level_desc, " Lowest lvl wet bulb");
596 else if (ipdtmpl[ipos] == 246)
597 strcpy(level_desc, " Max. equi. potential");
598 else if (ipdtmpl[ipos] == 247)
599 strcpy(level_desc, " Equilibrium level");
600 else if (ipdtmpl[ipos] == 248)
601 strcpy(level_desc, " Shallow con. cld bl");
602 else if (ipdtmpl[ipos] == 249)
603 strcpy(level_desc, " Shallow con. cld tl");
604 else if (ipdtmpl[ipos] == 251)
605 strcpy(level_desc, " Deep conv. cld bl");
606 else if (ipdtmpl[ipos] == 252)
607 strcpy(level_desc, " Deep conv. cld tl");
608 else if (ipdtmpl[ipos] == 253) /* liquid water layer (LBLSW). */
609 strcpy(level_desc, " Lowest bot. lvl sup" );
610 else if (ipdtmpl[ipos] == 254) /* liquid water layer (HBLSW). */
611 strcpy(level_desc, " highest top lvl sup" );
612 else
613 {
614 sprintf(level_desc, " %4d (Unknown Lvl)", (int)ipdtmpl[ipos]);
615 /* write(level_desc, fmt = '(1x,I4," (Unknown Lvl)")') ipdtmpl[ipos] */
616 }
617
618 return G2C_NOERROR;
619}
620
636int
637g2c_degrib2(int g2cid, const char *fileout)
638{
639 FILE *f;
641 int total_fields = 0;
642 int i;
643 int ret;
644
645 /* Check inputs. */
646 if (g2cid < 0 || g2cid > G2C_MAX_FILES || g2c_file[g2cid].g2cid != g2cid)
647 return G2C_EBADID;
648 if (!fileout)
649 return G2C_EINVAL;
650
651 LOG((2, "g2c_degrib2 fileout %s", fileout));
652
653 /* Open output file. */
654 if (!(f = fopen(fileout, "w")))
655 return G2C_EFILE;
656
657 /* Print a summary for each message in the file. */
658 for (msg = g2c_file[g2cid].msg; msg; msg = msg->next)
659 {
660 int fld;
661
662 fprintf(f, "\n");
663 fprintf(f, " GRIB MESSAGE %ld starts at %ld\n", msg->msg_num + 1, msg->bytes_to_msg + 1);
664 fprintf(f, "\n");
665 fprintf(f, " SECTION 0: %d 2 %ld\n", msg->discipline, msg->bytes_in_msg);
666 fprintf(f, " SECTION 1: %d %d %d %d %d %d %d %d %d %d %d %d %d\n", msg->center, msg->subcenter,
667 msg->master_version, msg->local_version, msg->sig_ref_time, msg->year, msg->month, msg->day,
668 msg->hour, msg->minute, msg->second, msg->status, msg->type);
669 fprintf(f, " Contains %d Local Sections and %d data fields.\n", msg->num_local, msg->num_fields);
670 LOG((5, " SECTION 1: %d %d %d %d %d %d %d %d %d %d %d %d %d\n", msg->center, msg->subcenter,
671 msg->master_version, msg->local_version, msg->sig_ref_time, msg->year, msg->month, msg->day,
672 msg->hour, msg->minute, msg->second, msg->status, msg->type));
673
674 /* For each field, print info. */
675 for (fld = 0; fld < msg->num_fields; fld++)
676 {
677 G2C_SECTION_INFO_T *sec, *sec2, *sec3, *sec5, *sec6;
678 G2C_SECTION3_INFO_T *sec3_info;
679 G2C_SECTION4_INFO_T *sec4_info;
680 G2C_SECTION5_INFO_T *sec5_info;
681 G2C_SECTION6_INFO_T *sec6_info;
682 char abbrev[G2C_MAX_NOAA_ABBREV_LEN + 1];
683 char level_desc[G2C_MAX_TYPE_OF_FIXED_SURFACE_LEN + 1];
684 char date_time[100 + 1];
685 float *data = NULL;
686 float total = 0.0, max = 0.0, min = 0.0, avg = 0;
687 int t;
688
689 fprintf(f, "\n");
690 fprintf(f, " FIELD %d\n", fld + 1);
691 /* Only print section 0 and 1 data for the first field. */
692 if (fld == 0)
693 {
694 fprintf(f, " SECTION 0: %d 2\n", msg->discipline);
695 fprintf(f, " SECTION 1: %d %d %d %d %d %d %d %d %d %d %d %d %d\n", msg->center, msg->subcenter,
696 msg->master_version, msg->local_version, msg->sig_ref_time, msg->year, msg->month, msg->day,
697 msg->hour, msg->minute, msg->second, msg->status, msg->type);
698 }
699
700 /* Find this field (a.k.a. product, a.k.a. section 4). */
701 for (sec = msg->sec; sec; sec = sec->next)
702 if (sec->sec_num == 4 && ((G2C_SECTION4_INFO_T *)(sec->sec_info))->field_num == fld)
703 break;
704 if (!sec)
705 return G2C_ENOSECTION;
706
707 /* Is there a local section? */
708 for (sec2 = sec; sec2; sec2 = sec2->prev)
709 if (sec2->sec_num == 2)
710 break;
711 if (sec2)
712 fprintf(f, " SECTION 2: %d bytes\n", sec2->sec_len - 5); /* Subtract 4 byte seclen and 1 byte secnum. */
713
714 /* Find the sec3 that applies to this field. */
715 for (sec3 = sec; sec3; sec3 = sec3->prev)
716 if (sec3->sec_num == 3)
717 break;
718 if (!sec3)
719 return G2C_ENOSECTION;
720
721 /* Print the section 3 (grid) info. */
722 sec3_info = (G2C_SECTION3_INFO_T *)sec3->sec_info;
723 fprintf(f, " SECTION 3: %d %d %d %d %d\n", sec3_info->source_grid_def, sec3_info->num_data_points, sec3_info->num_opt,
724 sec3_info->interp_list, sec3_info->grid_def);
725 fprintf(f, " GRID TEMPLATE 3. %d : ", sec3_info->grid_def);
726 /* Cast to int to match behavior of degrib2.F90. */
727 for (t = 0; t < sec3->template_len; t++)
728 fprintf(f, " %d", (int)sec3->template[t]);
729 fprintf(f, "\n");
730 if (!sec3_info->optional)
731 fprintf(f, " NO Optional List Defining Number of Data Points.\n");
732
733 /* Print the section 4 (product) info. */
734 sec4_info = (G2C_SECTION4_INFO_T *)sec->sec_info;
735 fprintf(f, " PRODUCT TEMPLATE 4. %d: ", sec4_info->prod_def);
736
737 /* We can look up the parameter abbreviation with the
738 * discipline and the first two elements of the product
739 * template, which will be the category and product
740 * number. */
741 if ((ret = g2c_param_abbrev(msg->discipline, sec->template[0], sec->template[1], abbrev)))
742 return ret;
743 fprintf(f, "( PARAMETER = %-8s %d %lld %lld ) ", abbrev, sec->msg->discipline, sec->template[0],
744 sec->template[1]);
745 /* Cast to int to match behavior of degrib2.F90. */
746 for (t = 0; t < sec->template_len; t++)
747 fprintf(f, " %d", (int)sec->template[t]);
748 fprintf(f, "\n");
749
750 /* Using the product template number, and the template
751 * values, we can figure out a description for the
752 * horizontal level description. */
753 if ((ret = g2c_get_level_desc(sec4_info->prod_def, sec->template, level_desc)))
754 return ret;
755
756 /* The Fortran code for level descriptions puts a space in
757 * front of level descriptions that don't start with a
758 * number. It's annoying, but do it here to match the
759 * behavior of Fortran degrib2. */
760 /* if (!isdigit(level_desc[0])) */
761 /* { */
762 /* char tmp_level_desc[G2C_MAX_TYPE_OF_FIXED_SURFACE_LEN + 2]; */
763 /* sprintf(tmp_level_desc, " %s", level_desc); */
764 /* strcpy(level_desc, tmp_level_desc); */
765 /* } */
766
767 /* Put the date/time in a formatted string. */
768 if ((ret = g2c_get_datetime(sec4_info->prod_def, sec->template, msg->year, msg->month, msg->day,
769 msg->hour, msg->minute, msg->second, date_time)))
770 return ret;
771 fprintf(f, " FIELD: %-8s%s %s\n", abbrev, level_desc, date_time);
772 if (!sec4_info->num_coord)
773 fprintf(f, " NO Optional Vertical Coordinate List.\n");
774
775 /* Find the sec5 that applies to this field. */
776 for (sec5 = sec; sec5; sec5 = sec5->next)
777 if (sec5->sec_num == 5)
778 break;
779 if (!sec5)
780 return G2C_ENOSECTION;
781
782 /* Find the sec6 that applies to this field, if any. */
783 for (sec6 = sec; sec6; sec6 = sec6->next)
784 if (sec6->sec_num == 6)
785 break;
786
787 /* Section 5 and 6 info. */
788 sec5_info = (G2C_SECTION5_INFO_T *)sec5->sec_info;
789 sec6_info = (G2C_SECTION6_INFO_T *)sec6->sec_info;
790 if (sec6_info->indicator != 255)
791 fprintf(f, " Num. of Data Points = %d with BIT-MAP 0\n", sec5_info->num_data_points);
792 else
793 fprintf(f, " Num. of Data Points = %d NO BIT-MAP \n", sec5_info->num_data_points);
794 fprintf(f, " DRS TEMPLATE 5. %d : ", sec5_info->data_def);
795 /* Cast to int to match behavior of degrib2.F90. */
796 for (t = 0; t < sec5->template_len; t++)
797 fprintf(f, " %d", (int)sec5->template[t]);
798 fprintf(f, "\n");
799 fprintf(f, " Data Values:\n");
800 fprintf(f, " Num. of Data Points = %d Num. of Data Undefined = 0\n", sec5_info->num_data_points);
801
802 /* Now read the data and find the min, max, and average values. */
803
804 LOG((5, "sec5_info->num_data_points %ld", sec5_info->num_data_points));
805 if (sec5_info->num_data_points)
806 {
807 /* Allocate storage for the data. */
808 if (!(data = malloc(sec5_info->num_data_points * sizeof(float))))
809 return G2C_ERROR;
810 }
811
812 /* Get the data from message 0, product 0. */
813 if ((ret = g2c_get_prod(g2cid, msg->msg_num, fld, NULL, data)))
814 return ret;
815
816 /* Find min/max/avg. */
817 if (sec5_info->num_data_points)
818 {
819 max = data[0];
820 min = data[0];
821 total = data[0];
822 for (i = 1; i < sec5_info->num_data_points; i++)
823 {
824 total += data[i];
825 if (data[i] > max)
826 max = data[i];
827 if (data[i] < min)
828 min = data[i];
829 }
830 avg = total/sec5_info->num_data_points;
831 }
832 fprintf(f, "( PARM= %s ) : MIN=%25.8f AVE=%25.8f MAX=%25.8f\n",
833 abbrev, min, avg, max);
834
835 /* Free the data. */
836 if (sec5_info->num_data_points)
837 free(data);
838
839 total_fields++;
840 }
841 }
842
843 fprintf(f, " \n Total Number of Fields Found = %d\n", total_fields);
844
845 /* Close output file. */
846 if (fclose(f))
847 return G2C_EFILE;
848
849 return G2C_NOERROR;
850}
#define G2C_DATE_TIME_LEN
Size of the date/time string.
Definition g2cdegrib2.c:21
static int format_level(char *cbuf, int ival, int scale)
Format the level string for degrib2 output.
Definition g2cdegrib2.c:256
#define G2C_MAX_TYPE_OF_FIXED_SURFACE_LEN
Maximum length of "Type of first fixed surface" string.
Definition g2cdegrib2.c:19
int g2c_degrib2(int g2cid, const char *fileout)
Write a summary file like the degrib2 utility.
Definition g2cdegrib2.c:637
G2C_FILE_INFO_T g2c_file[G2C_MAX_FILES+1]
Global file information.
Definition g2cfile.c:10
int g2c_get_level_desc(int ipdtn, long long int *ipdtmpl, char *level_desc)
Determine the string that describes the level information, given the GRIB2 Product Definition Templat...
Definition g2cdegrib2.c:312
int g2c_get_datetime(int ipdtn, long long int *ipdtmpl, short year, unsigned char month, unsigned char day, unsigned char hour, unsigned char minute, unsigned char second, char *tabbrev)
Convert date and time from GRIB2 info to string output.
Definition g2cdegrib2.c:49
G2C_CODE_TABLE_T * g2c_table
Pointer to the list of code tables.
Definition g2cxml.c:15
int g2c_param_abbrev(int g2disc, int g2cat, int g2num, char *abbrev)
Get NOAA abbreviation for a GRIB2 parameter.
Definition g2cparams.c:1091
int g2c_get_prod(int g2cid, int msg_num, int prod_num, int *num_data_points, float *data)
Read the data for a product.
Definition g2cprod.c:28
#define G2C_MAX_FILES
Maximum number of open files.
Definition grib2.h:288
#define G2C_ENOSECTION
Cannot find section.
Definition grib2.h:506
#define G2C_EFILE
File I/O error.
Definition grib2.h:497
#define G2C_ERROR
General error code, returned for some test errors.
Definition grib2.h:492
#define G2C_EINVAL
Invalid input.
Definition grib2.h:496
#define G2C_EBADID
Bad ID.
Definition grib2.h:498
#define G2C_MAX_NOAA_ABBREV_LEN
Maximum length of a NOAA abbreviation of a parameter.
Definition grib2.h:432
#define G2C_NOERROR
No error.
Definition grib2.h:491
Header file with internal function prototypes NCEPLIBS-g2c library.
struct g2c_section_info * next
Pointer to next in list.
Definition grib2_int.h:176
struct g2c_section_info * sec
List of section metadata.
Definition grib2_int.h:162
short subcenter
Originating subcenter.
Definition grib2_int.h:150
unsigned char master_version
GRIB master tables version number.
Definition grib2_int.h:151
unsigned char type
Type of processed data in this GRIB message.
Definition grib2_int.h:161
unsigned short grid_def
Grid definition template number (= N) (See Table 3.1).
Definition grib2_int.h:199
unsigned char hour
Hour.
Definition grib2_int.h:157
unsigned char minute
Minute.
Definition grib2_int.h:158
unsigned int num_data_points
Number of data points.
Definition grib2_int.h:196
unsigned short num_coord
Number of coordinate values after template.
Definition grib2_int.h:209
int num_local
Number of local sections in the message.
Definition grib2_int.h:141
unsigned char sig_ref_time
Significance of reference time.
Definition grib2_int.h:153
unsigned char num_opt
Number of octets for optional list of numbers defining number of points.
Definition grib2_int.h:197
unsigned char discipline
Discipline from section 0.
Definition grib2_int.h:138
unsigned char interp_list
Interpetation of list of numbers defining number of points (See Table 3.11).
Definition grib2_int.h:198
size_t bytes_in_msg
Number of bytes in this message.
Definition grib2_int.h:137
struct g2c_section_info * prev
Pointer to previous in list.
Definition grib2_int.h:177
int num_fields
Number of fields in the message.
Definition grib2_int.h:140
unsigned char sec_num
Section number.
Definition grib2_int.h:173
unsigned int num_data_points
Number of data points where one or more values are specified in Section 7 when a bit map is present,...
Definition grib2_int.h:221
void * sec_info
Pointer to struct specific for section 3, 4, 5, 6, or 7.
Definition grib2_int.h:175
unsigned char indicator
Bit map indicator.
Definition grib2_int.h:231
unsigned int sec_len
Length of the section (in bytes).
Definition grib2_int.h:171
short year
Year.
Definition grib2_int.h:154
unsigned char status
Production Status of Processed data in the GRIB message.
Definition grib2_int.h:160
#define LOG(e)
Ignore logging to stdout.
Definition grib2_int.h:426
unsigned char second
Second.
Definition grib2_int.h:159
unsigned char day
Day.
Definition grib2_int.h:156
unsigned char source_grid_def
Source of grid definition (See Table 3.0).
Definition grib2_int.h:195
int template_len
Number of entries in template.
Definition grib2_int.h:179
unsigned char local_version
Version number of GRIB local tables used to augment Master Tables.
Definition grib2_int.h:152
unsigned char month
Month.
Definition grib2_int.h:155
size_t msg_num
Number of message in file (0-based).
Definition grib2_int.h:135
unsigned short data_def
Data representation template number (See Table 5.0).
Definition grib2_int.h:222
size_t bytes_to_msg
Number of bytes to skip in the file, to get to this message.
Definition grib2_int.h:136
long long int * template
Grid, product, or data template.
Definition grib2_int.h:178
struct g2c_message_info * next
Pointer to next in list.
Definition grib2_int.h:164
G2C_MESSAGE_INFO_T * msg
Pointer to contianing message.
Definition grib2_int.h:174
short center
Originating center.
Definition grib2_int.h:149
int * optional
Optional list of numbers defining number of points.
Definition grib2_int.h:200
unsigned short prod_def
Product definition template number (See Table 4.0).
Definition grib2_int.h:210
A GRIB2 code table.
Definition grib2_int.h:255
This is the information about each open file.
Definition grib2_int.h:236
This is the information about each message.
Definition grib2_int.h:134
Information about Section 3 GRID DEFINITION SECTION.
Definition grib2_int.h:194
Information about Section 4 PRODUCT DEFINITION SECTION.
Definition grib2_int.h:207
Information about Section 5 DATA REPRESENTATION SECTION.
Definition grib2_int.h:217
Information about Section 6 BIT-MAP SECTION.
Definition grib2_int.h:228
Information about a section 3 through 7 in a GRIB2 message.
Definition grib2_int.h:169