Update version info for release v4.6.1 (#2122)
[WRF.git] / external / io_grib1 / grib1_util / read_grib.c
blobc1ebcdcb064ac76aed8f466d9aff0ae4f9f8c18a
1 /**************************************************************************
2 * Todd Hutchinson 4/20/98
3 * tahutchinson@tasc.com (781) 942-2000 x3108
4 * TASC
5 * 55 Walkers Brook Drive
6 * Reading, MA 01867
8 * Functions in this file are used for decoding grib data. Please see the
9 * headers before each function for a full descrption.
11 * Routines in this file call functions in the Naval Research Lab's grib
12 * library. The grib library is freely available from
13 * http://www-mel.nrlmry.navy.mil/cgi-bin/order_grib. This library should
14 * be installed on your system prior to using the routines in this file.
15 * Documentation for this library is available from
16 * Master Environmental Grib Library user's manual
17 * http://mel.dmso.mil/docs/grib.pdf
18 * Note: the standard NRL grib library does not support
19 * "Little-Endian" platforms such as linux. There is a version of the NRL
20 * grib library within the WxPredictor project which does support linux.
22 * This file references the cfortran.h header file to ease the use of calling
23 * this function from a fortran routine. cfortran.h is a header file that
24 * allows for simple machine-independent calls between c and fortran. The
25 * package is available via anonymous ftp at zebra.desy.de.
27 * The grib document "A GUIDE TO THE CODE FORM FM 92-IX Ext. GRIB" may be
28 * useful to your understanding of this code. This document is available
29 * via anonymous ftp from nic.fb4.noaa.gov. Check the readme file in the
30 * root directory for further instructions.
32 ****************************************************************************/
34 #define ERRSIZE 2000
35 #define ALLOCSIZE 30
36 #define MISSING -999
38 #define EARTH_RADIUS 6371.229 /* in km */
39 #define PI 3.141592654
40 #define PI_OVER_180 PI/180.
42 #include <stdio.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <math.h>
46 #include <limits.h>
47 #include <time.h>
48 #include "cfortran.h"
49 #include "gribfuncs.h"
50 #include "gribsize.incl"
51 #include "read_grib.h"
52 #include "alloc_2d.h"
54 #if defined(_WIN32)
55 #include <io.h>
56 #else
57 #include <unistd.h>
58 #endif
60 /* Function Declarations */
62 void remove_element(int array[],int index, int size);
63 int advance_time(int *century, int year, int month, int day, int hour,
64 int amount, int unit);
65 char *advance_time_str(char startdatein[], int amount, char enddate[]);
66 int date_diff(int date1,int century1,int date2,int century2);
67 int hours_since_1900(int date,int century);
68 int isLeapYear(int year);
69 int get_factor2(int unit);
70 int compare_record(GribInfo *gribinfo, FindGrib *findgrib, int gribnum);
72 /*
73 *These lines allow fortran routines to call the c routines. They are
74 * used by macros defined in cfortran.h
76 #define get_pressure_levels_STRV_A1 TERM_CHARS(' ',1)
78 FCALLSCFUN6(INT, get_pressure_levels,GET_PRESSURE_LEVELS,
79 get_pressure_levels,STRINGV,INTV,INTV,INTV,INT,INT)
80 #define setup_gribinfo_STRV_A1 TERM_CHARS(' ',1)
81 FCALLSCFUN2(INT,setup_gribinfo,SETUP_GRIBINFO,setup_gribinfo,STRINGV,INT)
82 #define get_msl_indices_STRV_A1 TERM_CHARS(' ',1)
83 FCALLSCFUN9(INT, get_msl_indices,GET_MSL_INDICES,get_msl_indices,
84 STRINGV,INTV,INTV,INTV,INTV,INTV,INT,INTV,INTV)
85 FCALLSCFUN5(INT, get_index,GET_INDEX,get_index,INT,INT,INT,INT,INT)
86 #define read_grib_STRV_A1 TERM_CHARS(' ',1)
87 FCALLSCFUN7(INT,get_dates,GET_DATES,get_dates,INTV,INTV,INTV,INT,INTV,
88 INTV,INTV)
89 FCALLSCFUN7(INT, read_grib,READ_GRIB,read_grib,
90 STRINGV,INT,INT,INT,INT,FLOATVV,PVOID)
91 FCALLSCFUN8(INT, get_index_near_date,GET_INDEX_NEAR_DATE,get_index_near_date,
92 STRING,INT,INT,INT,INTV,INTV,INTV,INT)
94 /* The value for usLevel_id for isobaric levels */
95 #define ISOBARIC_LEVEL_ID 100
97 /*************************************************************************
98 * This function reads and decodes grib records in a list of input files
99 * and stores information about each grib record in the gribinfo array
100 * structure. The gribinfo structure can then be accessed by any function
101 * within this file.
103 * Interface:
104 * Input:
105 * gribinfo - pointer to a previously allocated gribinfo structure. The
106 * gribinfo structure is filled in this function.
107 * files - a string array containing the names of the files containing
108 * the grib data. If called from a fortran routine, the
109 * fortran routine must set the character size of the array to
110 * be STRINGSIZE-1. The last filled element in the array should
111 * be "END".
112 * use_fcst - if TRUE, forecast fields will be included in the gribinfo
113 * structure, otherwise, only analysis fields will be included.
115 * Return:
116 * 1 - successful call to setup_gribinfo
117 * -1 - call to setup_gribinfo failed
119 ***************************************************************************/
121 int rg_setup_gribinfo(GribInfo *gribinfo, char files[][STRINGSIZE],
122 int use_fcst)
124 FILE *fp;
125 int filenum;
126 int nReturn;
127 int idx;
128 int status;
129 int start_elem;
131 /* Loop through input files */
132 filenum = 0;
133 while ((strcmp(files[filenum], "end") != 0 ) &&
134 (strcmp(files[filenum], "END") != 0 )) {
137 * This forces gribinfo to be fully initialized.
139 if (filenum == 0)
141 gribinfo->num_elements = 0;
144 start_elem = gribinfo->num_elements;
146 fp = fopen(files[filenum],"r");
147 if (fp == NULL)
149 fprintf(stderr,"Could not open %s\n",files[filenum]);
150 nReturn = -1;
151 break;
154 status = rg_setup_gribinfo_f(gribinfo, fp, use_fcst);
155 if (status != 1)
157 fprintf(stderr,
158 "rg_setup_gribinfo_f returned non-zero status (%d), skipping %s\n",
159 status,files[filenum]);
160 continue;
163 for (idx=start_elem; idx < gribinfo->num_elements; idx++)
165 strcpy(gribinfo->elements[idx].filename,
166 files[filenum]);
170 filenum++;
171 nReturn = 1;
174 return nReturn;
179 /*************************************************************************
181 * Similar to rg_setup_gribinfo, except, a unix file descriptor is passed in,
182 * rather than a list of files to open.
184 *************************************************************************/
186 int rg_setup_gribinfo_i(GribInfo *gribinfo, int fid, int use_fcst)
188 FILE *fp;
189 int status;
191 fp = fdopen(fid,"r");
192 if (fp == NULL)
194 fprintf(stderr,"Could not open file descriptor %d\n",fid);
195 status = -1;
196 return status;
199 /* This forces gribinfo to be initialized for the first time */
200 gribinfo->num_elements = 0;
202 status = rg_setup_gribinfo_f(gribinfo, fp, use_fcst);
203 if (status != 1)
205 fprintf(stderr,
206 "rg_setup_gribinfo_f returned non-zero status (%d)\n",
207 status);
210 return status;
213 /*************************************************************************
215 * Similar to rg_setup_gribinfo, except, a file pointer is passed in, rather
216 * than a list of files to open.
218 * If gribinfo->num_elements is 0, gribinfo is initialized, otherwise,
219 * gribinfo is appended to.
221 *************************************************************************/
223 int rg_setup_gribinfo_f(GribInfo *gribinfo, FILE *fp, int use_fcst)
225 char errmsg[ERRSIZE];
226 int nReturn=0;
227 long offset;
228 int filenum;
229 int Rd_Indexfile=0;
230 GRIB_HDR *gh1;
231 long tmpoffset=0;
232 int century;
233 int year4d;
234 int fcsttime1=0;
235 int fcsttime2=0;
236 int factor=0;
238 /* Set the number of elements to be zero initially */
239 if (gribinfo->num_elements <= 0)
241 /* Allocate space for gribinfo */
242 gribinfo->elements = (Elements *)calloc(ALLOCSIZE,sizeof(Elements));
243 if (gribinfo->elements == NULL) {
244 sprintf(errmsg,"Could not allocate %d bytes for gribinfo->elements\n",
245 ALLOCSIZE*sizeof(Elements));
246 goto bail_out;
250 /* Make storage for Grib Header */
251 nReturn = init_gribhdr(&gh1, errmsg);
253 * The grib library is setup such that, when init_gribhdr == 0, it was
254 * successful. If it is 1, it failed.
256 if (nReturn == 1) goto bail_out;
258 /* Scan through message */
259 for (offset = 0L; nReturn == 0; offset += gh1->msg_length) {
260 if ((gribinfo->num_elements > 0) &&
261 (gribinfo->num_elements%ALLOCSIZE == 0))
262 gribinfo->elements =
263 (Elements *)realloc(gribinfo->elements,
264 (gribinfo->num_elements+ALLOCSIZE)*
265 sizeof(Elements));
267 if (gribinfo->elements == NULL) {
268 sprintf(errmsg,"Could not allocate %d bytes for gribinfo\n",
269 (gribinfo->num_elements + ALLOCSIZE)*sizeof(Elements));
270 goto bail_out;
273 /* Setup the File pointer */
274 gribinfo->elements[gribinfo->num_elements].fp = fp;
276 gribinfo->elements[gribinfo->num_elements].pds =
277 (PDS_INPUT *)malloc(1*sizeof(PDS_INPUT));
278 gribinfo->elements[gribinfo->num_elements].gds =
279 (grid_desc_sec *)malloc(1*sizeof(grid_desc_sec));
280 gribinfo->elements[gribinfo->num_elements].bms =
281 (BMS_INPUT *)malloc(1*sizeof(BMS_INPUT));
282 gribinfo->elements[gribinfo->num_elements].bds_head =
283 (BDS_HEAD_INPUT *)malloc(1*sizeof(BDS_HEAD_INPUT));
284 errmsg[0] = '\0';
285 nReturn =
286 grib_fseek(fp,&offset, Rd_Indexfile, gh1, errmsg);
287 if (nReturn != 0) {
288 if (nReturn == 2) break; /* End of file error */
289 else {
290 fprintf(stderr, "Grib_fseek returned non zero status (%d)\n",
291 nReturn);
292 goto bail_out;
295 if (errmsg[0] != '\0')
296 { /* NO errors but got a Warning msg from seek */
297 fprintf(stderr,"%s; Skip Decoding...\n",errmsg);
298 errmsg[0] = '\0';
299 gh1->msg_length = 1L; /* set to 1 to bump offset up */
300 continue;
303 if (gh1->msg_length < 0) {
304 fprintf(stderr, "Error: message returned had bad length (%ld)\n",
305 gh1->msg_length);
306 goto bail_out;
308 else if (gh1->msg_length == 0) {
309 fprintf(stderr, "msg_length is Zero\n");
310 gh1->msg_length = 1L;
311 continue;
313 init_dec_struct(gribinfo->elements[gribinfo->num_elements].pds,
314 gribinfo->elements[gribinfo->num_elements].gds,
315 gribinfo->elements[gribinfo->num_elements].bms,
316 gribinfo->elements[gribinfo->num_elements].bds_head);
319 * gribgetpds is an undocumented function within the grib library.
320 * gribgetpds grabs the pds section from the grib message without
321 * decoding the entire grib message. The interface is as follows:
322 * first input param: a pointer to the beginning of the pds
323 * section.
324 * second input param: a pointer to a structure which will hold
325 * the pds information
326 * third param: the error message.
328 * If gribgetpds ever fails, it can be replaced with the following
329 * nReturn = grib_dec((char *)gh1->entire_msg, &pds, &gds, &bds_head,
330 * &bms, &grib_data, errmsg);
332 * This will degrade performance since this grib_dec decodes the
333 * entire grib message.
336 nReturn = gribgetpds((char*)(gh1->entire_msg + 8),
337 gribinfo->elements[gribinfo->num_elements].pds,
338 errmsg);
339 if (nReturn != 0) goto bail_out;
341 /* Get gds if present */
342 if (gribinfo->elements[gribinfo->num_elements].pds->usGds_bms_id >> 7
343 & 1) {
344 nReturn =
345 gribgetgds((char*)
346 (gh1->entire_msg+8+
347 gribinfo->elements[gribinfo->num_elements].pds->uslength),
348 gribinfo->elements[gribinfo->num_elements].gds,errmsg);
349 if (nReturn != 0) goto bail_out;
352 /* Get bms section if present */
353 if (gribinfo->elements[gribinfo->num_elements].pds->usGds_bms_id >> 6
354 & 1) {
356 fprintf(stderr,"grids with bms section not currently supported\n");
357 return -1;
361 gribinfo->elements[gribinfo->num_elements].usGrid_id =
362 gribinfo->elements[gribinfo->num_elements].pds->usGrid_id;
363 gribinfo->elements[gribinfo->num_elements].usParm_id =
364 gribinfo->elements[gribinfo->num_elements].pds->usParm_id;
365 gribinfo->elements[gribinfo->num_elements].usLevel_id =
366 gribinfo->elements[gribinfo->num_elements].pds->usLevel_id;
367 gribinfo->elements[gribinfo->num_elements].usHeight1 =
368 gribinfo->elements[gribinfo->num_elements].pds->usHeight1;
369 gribinfo->elements[gribinfo->num_elements].usHeight2 =
370 gribinfo->elements[gribinfo->num_elements].pds->usHeight2;
371 gribinfo->elements[gribinfo->num_elements].center_id =
372 gribinfo->elements[gribinfo->num_elements].pds->usCenter_id;
373 gribinfo->elements[gribinfo->num_elements].parmtbl =
374 gribinfo->elements[gribinfo->num_elements].pds->usParm_tbl;
375 gribinfo->elements[gribinfo->num_elements].proc_id =
376 gribinfo->elements[gribinfo->num_elements].pds->usProc_id;
377 gribinfo->elements[gribinfo->num_elements].subcenter_id =
378 gribinfo->elements[gribinfo->num_elements].pds->usCenter_sub;
379 gribinfo->elements[gribinfo->num_elements].offset = offset;
380 gribinfo->elements[gribinfo->num_elements].end =
381 offset + gh1->msg_length - 1;
383 if (use_fcst) {
384 century = gribinfo->elements[gribinfo->num_elements].pds->usCentury;
386 if (gribinfo->elements[gribinfo->num_elements].pds->usTime_range == 10)
388 fcsttime1 = gribinfo->elements[gribinfo->num_elements].pds->usP1*256 +
389 gribinfo->elements[gribinfo->num_elements].pds->usP2;
390 fcsttime2 = 0;
392 else if (gribinfo->elements[gribinfo->num_elements].pds->usTime_range
393 == 203) {
394 /* This is the WSI extension to grib. 203 indicates "duration" */
395 fcsttime1 = gribinfo->elements[gribinfo->num_elements].pds->usP1;
396 fcsttime2 = gribinfo->elements[gribinfo->num_elements].pds->usP1 +
397 gribinfo->elements[gribinfo->num_elements].pds->usP2;
398 } else {
399 fcsttime1 = gribinfo->elements[gribinfo->num_elements].pds->usP1;
400 fcsttime2 = gribinfo->elements[gribinfo->num_elements].pds->usP2;
403 gribinfo->elements[gribinfo->num_elements].date =
404 advance_time(&century,
405 gribinfo->elements[gribinfo->num_elements].pds->usYear,
406 gribinfo->elements[gribinfo->num_elements].pds->usMonth,
407 gribinfo->elements[gribinfo->num_elements].pds->usDay,
408 gribinfo->elements[gribinfo->num_elements].pds->usHour,
409 fcsttime1,
410 gribinfo->elements[gribinfo->num_elements].pds->usFcst_unit_id);
412 else {
413 gribinfo->elements[gribinfo->num_elements].date =
414 gribinfo->elements[gribinfo->num_elements].pds->usHour*1 +
415 gribinfo->elements[gribinfo->num_elements].pds->usDay*100 +
416 gribinfo->elements[gribinfo->num_elements].pds->usMonth*10000 +
417 gribinfo->elements[gribinfo->num_elements].pds->usYear*1000000;
419 gribinfo->elements[gribinfo->num_elements].century =
420 gribinfo->elements[gribinfo->num_elements].pds->usCentury;
422 year4d =
423 (gribinfo->elements[gribinfo->num_elements].pds->usCentury - 1) * 100
424 + gribinfo->elements[gribinfo->num_elements].pds->usYear;
426 sprintf(gribinfo->elements[gribinfo->num_elements].initdate,
427 "%04d%02d%02d%02d%02d%02d",
428 year4d,
429 gribinfo->elements[gribinfo->num_elements].pds->usMonth,
430 gribinfo->elements[gribinfo->num_elements].pds->usDay,
431 gribinfo->elements[gribinfo->num_elements].pds->usHour,
432 gribinfo->elements[gribinfo->num_elements].pds->usMinute,
433 0);
435 factor =
436 get_factor2(gribinfo->elements[gribinfo->num_elements].pds->usFcst_unit_id);
437 gribinfo->elements[gribinfo->num_elements].fcsttime1 =
438 fcsttime1 * factor;
439 gribinfo->elements[gribinfo->num_elements].fcsttime2 =
440 fcsttime2 * factor;
442 advance_time_str(gribinfo->elements[gribinfo->num_elements].initdate,
443 gribinfo->elements[gribinfo->num_elements].fcsttime1,
444 gribinfo->elements[gribinfo->num_elements].valid_time);
446 gribinfo->num_elements++;
449 free_gribhdr(&gh1);
450 return 1;
452 /* The error condition */
453 bail_out:
454 if (errmsg[0] != '\0') fprintf(stderr,"\n***ERROR: %s: %s\n",
455 "setup_grib",errmsg);
456 if (gribinfo->elements != NULL) free(gribinfo->elements);
457 perror("System Error ");
458 return -1;
461 /*****************************************************************************
463 * Retrieve pressure levels from grib data. This function will pass the
464 * pressure levels for which the input parameter is available at all input
465 * times back to the calling routine.
467 * Interface
468 * Input:
469 * gribinfo - pointer to a previously allocated gribinfo structure.
470 * The gribinfo structure is filled in this function.
471 * dates: an array of dates to check for data
472 * format: yymmddhh
473 * If called from a fortran routine, the fortran routine must
474 * set the character size of the array to be STRINGSIZE-1
475 * centuries: an array holding the centuries for each of the
476 * dates in the array dates.
477 * parm_id: the input parameter id. From table 2 of the grib manual.
478 * Output:
479 * finallevels: an array of pressure levels which are contained in
480 * the grib data at all input times.
481 * Return:
482 * the number of levels in the levels array. The levels are listing
483 * in descending (by value) order, i.e., the value with the highest
484 * pressure (lowest vertical level) is the first element.
486 ****************************************************************************/
488 int rg_get_pressure_levels(GribInfo *gribinfo, int dates[], int centuries[],
489 int parm_id[], int finallevels[],int min_pres,
490 int numparms)
492 int datenum;
493 int gribnum;
494 int *levelnum;
495 int levelincluded;
496 int i,j;
497 int contains_level;
498 int **tmplevels;
499 int numfinallevels = 0;
500 int parmnum;
501 int tmpval;
503 /* Allocate space */
504 levelnum = (int *)calloc(numparms,sizeof(int));
505 tmplevels = (int **)calloc(numparms,sizeof(int *));
506 for (j = 0; j < numparms; j++) {
507 tmplevels[j] = (int *)calloc(1000,sizeof(int));
508 if (tmplevels[j] == NULL) {
509 tmplevels = NULL;
510 break;
513 if ((levelnum == NULL) || (tmplevels == NULL)) {
514 fprintf(stderr,
515 "get_pressure_levels: Allocation of space failed, returning\n");
516 return -1;
519 /* Loop through all parameters */
520 for (parmnum = 0; parmnum < numparms; parmnum++) {
522 levelnum[parmnum] = 0;
524 /* Get the array of pressure levels available at the first input time */
525 datenum = 0;
526 for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
527 if (gribinfo->elements[gribnum].date == dates[datenum]) {
528 if (gribinfo->elements[gribnum].century == centuries[datenum]) {
529 if (gribinfo->elements[gribnum].usLevel_id == ISOBARIC_LEVEL_ID) {
530 if (gribinfo->elements[gribnum].usParm_id == parm_id[parmnum]) {
531 if (gribinfo->elements[gribnum].usHeight1 >= min_pres) {
532 levelincluded = 0;
533 for (j=0; j < levelnum[parmnum]; j++) {
534 if (tmplevels[parmnum][j] ==
535 gribinfo->elements[gribnum].usHeight1) {
536 levelincluded = 1;
537 break;
540 if (levelincluded == 0) {
541 tmplevels[parmnum][levelnum[parmnum]] =
542 gribinfo->elements[gribnum].usHeight1;
543 levelnum[parmnum]++;
552 /* Remove levels that are not contained at all subsequent times */
553 datenum++;
554 while (dates[datenum] != -99){
555 for (j = 0; j < levelnum[parmnum]; j++) {
556 contains_level = 0;
557 for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
558 if (gribinfo->elements[gribnum].date == dates[datenum]) {
559 if (gribinfo->elements[gribnum].century == centuries[datenum]) {
560 if (gribinfo->elements[gribnum].usLevel_id == ISOBARIC_LEVEL_ID)
562 if (gribinfo->elements[gribnum].usParm_id ==
563 parm_id[parmnum]) {
564 if (tmplevels[parmnum][j] ==
565 gribinfo->elements[gribnum].usHeight1)
566 contains_level = 1;
572 if (!(contains_level)) {
573 remove_element(tmplevels[parmnum],j,levelnum[parmnum]);
574 levelnum[parmnum]--;
575 j--;
578 datenum++;
582 * Put the values for levels into an array. Remove any levels that
583 * were not found at all other levels
585 if (parmnum == 0) {
586 for (j = 0; j < levelnum[parmnum]; j++) {
587 finallevels[j] = tmplevels[parmnum][j];
588 numfinallevels++;
590 } else {
591 for (i=0; i<numfinallevels; i++) {
592 contains_level = 0;
593 for (j=0; j<levelnum[parmnum]; j++) {
594 if (finallevels[i] == tmplevels[parmnum][j]) {
595 contains_level = 1;
596 break;
599 if (!contains_level) {
600 remove_element(finallevels,i,numfinallevels);
601 numfinallevels--;
602 i--;
610 * Sort the numfinallevels array into descending order. Use straight
611 * insertion.
613 for (j=1; j<numfinallevels; j++) {
614 tmpval = finallevels[j];
615 for (i=j-1; i >= 0; i--) {
616 if (finallevels[i] >= tmpval) break;
617 finallevels[i+1] = finallevels[i];
619 finallevels[i+1] = tmpval;
622 return numfinallevels;
625 /****************************************************************************
627 * Returns an array of grib indices that correspond to particular grib fields
628 * to use as sea level pressure. There will be exactly one element for each
629 * input time. If a field was not found, then this function returns NULL
631 * Interface:
632 * Input:
633 * gribinfo - pointer to a previously allocated gribinfo structure. The
634 * gribinfo structure is filled in this function.
635 * dates: a string array of dates to check for data.
636 * format: yymmddhh
637 * If called from a fortran routine, the fortran routine must
638 * set the character size of the array to be STRINGSIZE-1
639 * centuries: an array holding the centuries for each of the
640 * dates in the array dates.
641 * usParm_id: an array of parameter identifiers that could be
642 * used as a sea level pressure field (From table 2 of
643 * grib documentation)
644 * usLevel_id: the level id that could be used as a sea level pressure
645 * field (from table 3 of the grib documentation)
646 * usHeight1: the height for the particular parameter and level
647 * (in units described by the parameter index)
648 * numparms: the number of parameters in each of the usParm_id,
649 * usLevel_id, and usHeight1 arrays.
650 * Output:
651 * grib_index: an array of grib indices to use for the sea level
652 * pressure. The index to grib_index corresponds to
653 * the time, i.e., the first array element of grib_index
654 * corresponds to the first time, the second element to
655 * the second time, etc.
657 * Note: Values in the input arrays, usParm_id, usLevel_id, and
658 * usHeight with the same array index must correspond.
660 * Return:
661 * 1 for success
662 * -1 if no field was found.
663 ***************************************************************************/
665 int rg_get_msl_indices(GribInfo *gribinfo, char dates[][STRINGSIZE],
666 int centuries[], int usParm_id[],int usLevel_id[],
667 int usHeight1[],int infactor[],int numparms,
668 int grib_index[],int outfactor[])
670 int parmindex;
671 int datenum = 0;
672 int gribnum;
673 int foundfield=0;
675 for (parmindex = 0; parmindex < numparms; parmindex++) {
677 datenum = 0;
678 while ((strcmp(dates[datenum], "end") != 0 ) &&
679 (strcmp(dates[datenum], "END") != 0 )) {
681 for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
682 if (gribinfo->elements[gribnum].date == atoi(dates[datenum])) {
683 if (gribinfo->elements[gribnum].century == centuries[datenum]) {
684 if ((gribinfo->elements[gribnum].usParm_id ==
685 usParm_id[parmindex]) &&
686 (gribinfo->elements[gribnum].usLevel_id ==
687 usLevel_id[parmindex]) &&
688 (gribinfo->elements[gribnum].usHeight1 ==
689 usHeight1[parmindex])) {
690 grib_index[datenum] = gribnum;
691 outfactor[datenum] = infactor[parmindex];
692 foundfield++;
693 break;
699 datenum++;
702 * Break out of loop and continue on to next parameter if the current
703 * parameter was missing from a date.
706 if (foundfield != datenum) break;
710 * Break out of the parameter loop once we've found a field available at all
711 * dates
713 if (foundfield == datenum) {
714 break;
719 if (foundfield == datenum)
720 return 1;
721 else
722 return -1;
727 /***************************************************************************
729 * This function takes an index as input and returns a 2d grib data field
731 * Interface:
732 * input:
733 * gribinfo - pointer to a previously allocated gribinfo structure. The
734 * gribinfo structure is filled in this function.
735 * index - the index of gribinfo for which data is to be retrieved
736 * scale - the scale factor to multiply data by, i.e., if -2,
737 * data will be multiplied by 10^-2.
738 * output:
739 * grib_out - the 2 dimensional output grib data
740 * Warning: This 2d array is setup with i being the vertical
741 * dimension and j being the horizontal dimension. This
742 * is the convention used in mesoscale numerical modeling
743 * (the MM5 in particular), so it is used here.
744 * return:
745 * 1 for success
746 * -1 for failure
747 ***************************************************************************/
749 int rg_get_grib(GribInfo *gribinfo, int index,int scale,
750 float **grib_out,int *vect_comp_flag,
751 GRIB_PROJECTION_INFO_DEF *Proj, BDS_HEAD_INPUT *bds_head)
753 char errmsg[ERRSIZE];
754 int nReturn=0;
755 long offset;
756 int Rd_Indexfile=0;
757 BMS_INPUT bms;
758 PDS_INPUT pds;
759 BDS_HEAD_INPUT dummy;
760 grid_desc_sec gds;
761 GRIB_HDR *gh1;
762 int i,j;
763 int expandlon = 0;
764 float *grib_data;
766 /* Initialize Variables */
767 errmsg[0] = '\0';
768 offset = 0L;
769 grib_data = (float *)NULL;
771 /* Make storage for Grib Header */
772 nReturn = init_gribhdr (&gh1, errmsg);
773 if (nReturn == 1) goto bail_out;
775 /* Seek to the position in the grib data */
776 offset = gribinfo->elements[index].offset;
777 nReturn = grib_fseek(gribinfo->elements[index].fp,&offset,
778 Rd_Indexfile,gh1,errmsg);
779 if (nReturn != 1) {
780 fprintf(stderr,"Grib_fseek returned error status (%d)\n",nReturn);
781 goto bail_out;
783 if (errmsg[0] != '\0')
784 { /* NO errors but got a Warning msg from seek */
785 fprintf(stderr,"%s: Skip Decoding...\n",errmsg);
786 errmsg[0] = '\0';
788 if (gh1->msg_length <= 0) {
789 fprintf(stderr,"Error: message returned had bad length (%ld)\n",
790 gh1->msg_length);
791 goto bail_out;
793 init_dec_struct(&pds, &gds, &bms, &dummy);
795 nReturn = grib_dec((char *)gh1->entire_msg, &pds, &gds,
796 bds_head,
797 &bms, &grib_data, errmsg);
799 if (nReturn != 0) goto bail_out;
801 if (bms.uslength > 0) {
802 nReturn = apply_bitmap(&bms, &grib_data, FILL_VALUE, bds_head,
803 errmsg);
804 if (nReturn != 0) goto bail_out;
807 switch(gds.head.usData_type) {
808 case 0:
809 case 4:
810 strcpy(Proj->prjnmm,"latlon");
811 Proj->colcnt = gds.llg.usNi;
812 Proj->rowcnt = gds.llg.usNj;
813 Proj->origlat = gds.llg.lLat1/1000.;
814 Proj->origlon = gds.llg.lLon1/1000.;
815 Proj->xintdis = (gds.llg.iDi/1000.)*EARTH_RADIUS*PI_OVER_180;
816 Proj->yintdis = (gds.llg.iDj/1000.)*EARTH_RADIUS*PI_OVER_180;
817 Proj->parm1 = 0.;
818 Proj->parm2 = 0.;
819 if ((gds.llg.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
820 else *vect_comp_flag = 0;
822 /* If the grid is a global grid, we want to set the expandlon flag
823 * so that the number of columns in the array is expanded by one and
824 * the first column of data is copied to the last column. This
825 * allows calling routines to interpolate between first and last columns
826 * of data.
829 if (gds.llg.usNi*gds.llg.iDi/1000. == 360)
830 expandlon = 1;
831 else
832 expandlon = 0;
834 break;
835 case 1:
836 strcpy(Proj->prjnmm,"mercator");
837 Proj->colcnt = gds.merc.cols;
838 Proj->rowcnt = gds.merc.rows;
839 Proj->origlat = gds.merc.first_lat/1000.;
840 Proj->origlon = gds.merc.first_lon/1000.;
841 Proj->xintdis = gds.merc.lon_inc/1000.;
842 Proj->yintdis = gds.merc.lat_inc/1000.;
843 Proj->parm1 = gds.merc.latin/1000.;
844 Proj->parm2 = (gds.merc.Lo2/1000. - Proj->origlon)/gds.merc.cols;
845 if ((gds.merc.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
846 else *vect_comp_flag = 0;
847 break;
848 case 3:
849 strcpy(Proj->prjnmm,"lambert");
850 Proj->colcnt = gds.lam.iNx;
851 Proj->rowcnt = gds.lam.iNy;
852 Proj->origlat = gds.lam.lLat1/1000.;
853 Proj->origlon = gds.lam.lLon1/1000.;
854 Proj->xintdis = gds.lam.ulDx/1000.;
855 Proj->yintdis = gds.lam.ulDy/1000.;
856 Proj->parm1 = gds.lam.lLat_cut1/1000.;
857 Proj->parm2 = gds.lam.lLat_cut2/1000.;
858 Proj->parm3 = gds.lam.lLon_orient/1000.;
859 if ((gds.lam.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
860 else *vect_comp_flag = 0;
861 break;
862 case 5:
863 strcpy(Proj->prjnmm,"polar_stereo");
864 Proj->colcnt = gds.pol.usNx;
865 Proj->rowcnt = gds.pol.usNy;
866 Proj->origlat = gds.pol.lLat1/1000.;
867 Proj->origlon = gds.pol.lLon1/1000.;
868 Proj->xintdis = gds.pol.ulDx/1000.;
869 Proj->yintdis = gds.pol.ulDy/1000.;
870 Proj->parm1 = 60.;
871 Proj->parm2 = gds.pol.lLon_orient/1000.;
872 if ((gds.pol.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
873 else *vect_comp_flag = 0;
874 break;
875 default:
876 fprintf(stderr,"Grid not supported, gds.head.usData_type = %d\n",
877 gds.head.usData_type);
878 fprintf(stderr,"Exiting\n");
879 exit(-1);
880 break;
883 strcpy(Proj->stordsc,"+y_in_+x");
884 Proj->origx = 1;
885 Proj->origy = 1;
887 for (j=0; j< (Proj->rowcnt); j++) {
888 for (i=0; i<(Proj->colcnt); i++) {
889 grib_out[j][i] = grib_data[i+j*Proj->colcnt]*pow(10,scale);
893 if (expandlon) {
894 (Proj->colcnt)++;
895 for (j = 0; j < Proj->rowcnt; j++) {
896 grib_out[j][Proj->colcnt-1] = grib_out[j][0];
901 * You only reach here when there is no error, so return successfully.
904 nReturn = 0;
906 if (grib_data != NULL) {
907 free_gribhdr(&gh1);
908 free(grib_data);
911 return 1;
913 /* The error condition */
914 bail_out:
915 if (errmsg[0] != '\0') fprintf(stderr,"\n***ERROR: %s %s\n",
916 "get_grib",errmsg);
917 if (grib_data != NULL)
918 free(grib_data);
919 free_gribhdr(&gh1);
920 return -1;
923 /***************************************************************************
925 * This function takes an index as input and returns a 2d grib data field
927 * Interface:
928 * input:
929 * gribinfo - pointer to a previously allocated gribinfo structure. The
930 * gribinfo structure is filled in this function.
931 * index - the index of gribinfo for which data is to be retrieved
932 * output:
933 * data - the 2 dimensional output grib data
934 * Warning: This 2d array is setup with i being the vertical
935 * dimension and j being the horizontal dimension. This
936 * is the convention used in mesoscale numerical modeling
937 * (the MM5 in particular), so it is used here.
938 * return:
939 * 1 for success
940 * -1 for failure
941 ***************************************************************************/
943 int rg_get_data(GribInfo *gribinfo, int index, float **data)
945 float *data_1d;
946 int i,j;
947 int numrows,numcols;
948 int status;
950 numrows = rg_get_numrows(gribinfo,index);
951 numcols = rg_get_numcols(gribinfo,index);
953 data_1d = (float *)calloc(numrows*numcols,sizeof(float));
954 if (data_1d == 0)
956 fprintf(stderr,"Allocating space for data_1d failed, index: %d\n",index);
957 return -1;
960 status = rg_get_data_1d(gribinfo, index, data_1d);
961 if (status != 1)
963 return status;
966 for (j=0; j< numrows; j++) {
967 for (i=0; i < numcols; i++) {
968 data[j][i] = data_1d[i+j*numcols];
972 free(data_1d);
974 return 1;
978 /***************************************************************************
980 * This function takes an index as input and returns a 1d grib data field
982 * Interface:
983 * input:
984 * gribinfo - pointer to a previously allocated gribinfo structure. The
985 * gribinfo structure is filled in this function.
986 * index - the index of gribinfo for which data is to be retrieved
987 * output:
988 * data - 1 dimensional output grib data
989 * Warning: This 2d array is setup with i being the vertical
990 * dimension and j being the horizontal dimension. This
991 * is the convention used in mesoscale numerical modeling
992 * (the MM5 in particular), so it is used here.
993 * return:
994 * 1 for success
995 * -1 for failure
996 ***************************************************************************/
998 int rg_get_data_1d(GribInfo *gribinfo, int index, float *data)
1000 char errmsg[ERRSIZE];
1001 int nReturn=0;
1002 long offset;
1003 int Rd_Indexfile=0;
1004 BMS_INPUT bms;
1005 PDS_INPUT pds;
1006 BDS_HEAD_INPUT bds_head;
1007 grid_desc_sec gds;
1008 GRIB_HDR *gh1;
1009 int i,j;
1010 int numcols, numrows;
1011 float *grib_data;
1013 /* Initialize Variables */
1014 errmsg[0] = '\0';
1015 offset = 0L;
1016 grib_data = (float *)NULL;
1018 /* Make storage for Grib Header */
1019 nReturn = init_gribhdr (&gh1, errmsg);
1020 if (nReturn == 1) goto bail_out;
1022 /* Seek to the position in the grib data */
1023 offset = gribinfo->elements[index].offset;
1024 nReturn = grib_fseek(gribinfo->elements[index].fp,&offset,
1025 Rd_Indexfile,gh1,errmsg);
1026 if (nReturn != 0) {
1027 fprintf(stderr,"Grib_fseek returned non-zero status (%d)\n",nReturn);
1028 goto bail_out;
1030 if (errmsg[0] != '\0')
1031 { /* NO errors but got a Warning msg from seek */
1032 fprintf(stderr,"%s: Skip Decoding...\n",errmsg);
1033 errmsg[0] = '\0';
1035 if (gh1->msg_length <= 0) {
1036 fprintf(stderr,"Error: message returned had bad length (%ld)\n",
1037 gh1->msg_length);
1038 goto bail_out;
1041 init_dec_struct(&pds, &gds, &bms, &bds_head);
1043 nReturn = grib_dec((char *)gh1->entire_msg, &pds, &gds,
1044 &bds_head,
1045 &bms, &grib_data, errmsg);
1047 if (nReturn != 0) goto bail_out;
1049 if (bms.uslength > 0) {
1050 nReturn = apply_bitmap(&bms, &grib_data, FILL_VALUE, &bds_head,
1051 errmsg);
1052 if (nReturn != 0) goto bail_out;
1056 * Copy the data into the permanent array
1058 numcols = rg_get_numcols(gribinfo,index);
1059 numrows = rg_get_numrows(gribinfo,index);
1060 memcpy(data,grib_data,numcols*numrows*sizeof(float));
1063 * You only reach here when there is no error, so return successfully.
1066 nReturn = 0;
1068 if (grib_data != NULL) {
1069 free_gribhdr(&gh1);
1070 free(grib_data);
1073 return 1;
1075 /* The error condition */
1076 bail_out:
1077 if (errmsg[0] != '\0') fprintf(stderr,"\n***ERROR: %s %s\n",
1078 "get_grib",errmsg);
1079 if (grib_data != NULL)
1080 free(grib_data);
1081 free_gribhdr(&gh1);
1082 return -1;
1085 /****************************************************************************
1086 * Returns the index of gribinfo corresponding to the input date, level,
1087 * height, and parameter.
1089 * Interface:
1090 * Input:
1091 * gribinfo - pointer to a previously populated gribinfo structure.
1092 * initdate - initialization date in the form yyyymmdd[HHMMSS]. If any
1093 * part of HHMMSS is not specified, it will be set to 0.
1094 * parmid - the parameter id in the grib file
1095 * leveltype - the leveltype id from table 3/3a of the grib document.
1096 * level1 - First level of the data in units described by leveltype.
1097 * level2 - Second level of the data in units described by leveltype.
1098 * fcsttime1 - First forecast time in seconds.
1099 * fcsttime2 - Second forecast time in seconds.
1100 * Note: If an input variable is set set to -INT_MAX, then any value
1101 * will be considered a match.
1102 * Return:
1103 * if >= 0 The index of the gribinfo data that corresponds to the
1104 * input parameters
1105 * if < 0 No field corresponding to the input parms was found.
1107 ***************************************************************************/
1109 int rg_get_index(GribInfo *gribinfo, FindGrib *findgrib)
1111 int gribnum;
1112 int grib_index=-1;
1114 for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
1115 if (compare_record(gribinfo, findgrib, gribnum) == 1)
1117 grib_index = gribnum;
1118 break;
1121 return grib_index;
1125 /****************************************************************************
1126 * Same as rg_get_index, except that a guess for the record number is given.
1127 * This "guess" record is first checked to see if it matches, if so,
1128 * that grib record number is just returned. If it does not match,
1129 * full searching ensues.
1130 * Returns the index of gribinfo corresponding to the input date, level,
1131 * height, and parameter.
1133 * Interface:
1134 * Input:
1135 * Same is rg_get_index, except:
1136 * guess_index - The index to check first.
1137 * Return:
1138 * Same as rg_get_index
1140 ***************************************************************************/
1142 int rg_get_index_guess(GribInfo *gribinfo, FindGrib *findgrib, int guess_index)
1144 int retval;
1146 if (compare_record(gribinfo, findgrib, guess_index) == 1) {
1147 retval = guess_index;
1148 } else {
1149 retval = rg_get_index(gribinfo, findgrib);
1152 return retval;
1156 /****************************************************************************
1157 * Sets all values in FindGrib to missing.
1159 * Interface:
1160 * Input:
1161 * findgrib - pointer to a previously allocated findgrib structure.
1163 * Return:
1164 * 1 for success.
1165 * -1 for failure.
1167 ***************************************************************************/
1168 int rg_init_findgrib(FindGrib *findgrib)
1170 strcpy(findgrib->initdate,"*");
1171 strcpy(findgrib->validdate,"*");
1172 findgrib->parmid = -INT_MAX;
1173 findgrib->parmid = -INT_MAX;
1174 findgrib->leveltype = -INT_MAX;
1175 findgrib->level1 = -INT_MAX;
1176 findgrib->level2 = -INT_MAX;
1177 findgrib->fcsttime1 = -INT_MAX;
1178 findgrib->fcsttime2 = -INT_MAX;
1179 findgrib->center_id = -INT_MAX;
1180 findgrib->subcenter_id = -INT_MAX;
1181 findgrib->parmtbl_version = -INT_MAX;
1183 return 1;
1186 /****************************************************************************
1187 * Returns the indices of all gribinfo entries that match the input date,
1188 * level, height, and parameter.
1190 * Interface:
1191 * Input:
1192 * gribinfo - pointer to a previously populated gribinfo structure.
1193 * initdate - initialization date in the form yyyymmdd[HHMMSS]. If any
1194 * part of HHMMSS is not specified, it will be set to 0.
1195 * parmid - the parameter id in the grib file
1196 * leveltype - the leveltype id from table 3/3a of the grib document.
1197 * level1 - First level of the data in units described by leveltype.
1198 * level2 - Second level of the data in units described by leveltype.
1199 * fcsttime1 - First forecast time in seconds.
1200 * fcsttime2 - Second forecast time in seconds.
1201 * indices - an array of indices that match
1202 * num_indices - the number of matches and output indices
1204 * Note: If an input variable is set set to -INT_MAX, then any value
1205 * will be considered a match.
1206 * Return:
1207 * The number of matching indices.
1209 ***************************************************************************/
1211 int rg_get_indices(GribInfo *gribinfo, FindGrib *findgrib, int indices[])
1213 int gribnum;
1214 int matchnum = 0;
1216 for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
1217 if (compare_record(gribinfo, findgrib, gribnum) == 1) {
1218 indices[matchnum] = gribnum;
1219 matchnum++;
1222 return matchnum;
1225 /*************************************************************************
1227 * Returns an array of dates that correspond to particular input grib fields.
1228 * The dates will be sorted so that the dates increase as the index increases.
1230 * Interface:
1231 * Input:
1232 * gribinfo - pointer to a previously allocated gribinfo structure.
1233 * The gribinfo structure is filled in this function.
1234 * usParm_id: an array of parameter identifiers that could be
1235 * used as a sea level pressure field (From table 2 of
1236 * grib documentation)
1237 * usLevel_id: the level id that could be used as a sea level pressure
1238 * field (from table 3 of the grib documentation)
1239 * usHeight1: the height for the particular parameter and level
1240 * (in units described by the parameter index)
1241 * numparms: the number of parameters in each of the usParm_id,
1242 * usLevel_id, and usHeight1 arrays.
1243 * Output:
1244 * dates: the dates for which the input fields are available.
1246 * Note: Values in the input arrays, usParm_id, usLevel_id, and
1247 * usHeight with the same array index must correspond.
1249 * Return:
1250 * The number of dates found.
1251 *************************************************************************/
1253 int rg_get_dates(GribInfo *gribinfo,int usParm_id[],int usLevel_id[],
1254 int usHeight1[],int numparms,int dates[],int century[],
1255 int indices[])
1257 int datenum=0;
1258 int gribnum;
1259 int parmindex;
1260 int already_included;
1261 int i,j;
1262 int tmpval,tmpval2,tmpval3;
1264 /* Get the dates for the given parameters */
1266 for (parmindex = 0; parmindex < numparms; parmindex++) {
1267 for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
1268 if ((gribinfo->elements[gribnum].usParm_id == usParm_id[parmindex]) &&
1269 (gribinfo->elements[gribnum].usLevel_id == usLevel_id[parmindex]) &&
1270 (gribinfo->elements[gribnum].usHeight1 == usHeight1[parmindex])) {
1271 already_included = 0;
1272 for (i = 0; i < datenum; i++){
1273 if ((dates[datenum] == gribinfo->elements[gribnum].date) &&
1274 (century[datenum] == gribinfo->elements[gribnum].century)) {
1275 already_included = 1;
1276 break;
1279 if (!already_included) {
1280 dates[datenum] = gribinfo->elements[gribnum].date;
1281 century[datenum] = gribinfo->elements[gribnum].century;
1282 indices[datenum] = gribnum;
1283 datenum++;
1289 /* Sort the dates into increasing order */
1290 for (j = 1; j < datenum; j++) {
1291 tmpval = dates[j];
1292 tmpval2 = indices[j];
1293 tmpval3 = century[j];
1294 for (i=j-1; i >= 0; i--) {
1295 if (dates[i] <= tmpval) break;
1296 dates[i+1] = dates[i];
1297 indices[i+1] = indices[i];
1298 century[i+1] = century[i];
1300 dates[i+1] = tmpval;
1301 indices[i+1] = tmpval2;
1302 century[i+1] = tmpval3;
1305 return datenum;
1308 /****************************************************************************
1309 * This function returns the pds, gds, bms, and bms_head section of the
1310 * grib element
1312 * Input:
1313 * gribinfo - pointer to a previously allocated gribinfo structure. The
1314 * gribinfo structure is filled in this function.
1315 * index - the index of the grib record to access as indexed by
1316 * setup_gribinfo
1318 * Output:
1319 * *pds - a pointer to a structure holding the pds information
1320 * *gds - a pointer to a structure holding the gds information
1321 * *bms - a pointer to a structure holding the bms information
1322 * *bds_head - a pointer to a structure holding the binary data section
1323 * header information
1325 ***************************************************************************
1327 int rg_get_grib_header(GribInfo *gribinfo, int index, PDS_INPUT *pds,
1328 grid_desc_sec *gds,BMS_INPUT *bms)
1330 int xsize,ysize,j;
1332 memcpy(pds,gribinfo->elements[index].pds,sizeof(PDS_INPUT));
1333 memcpy(gds,gribinfo->elements[index].gds,sizeof(grid_desc_sec));
1334 memcpy(bms,gribinfo->elements[index].bms,sizeof(BMS_INPUT));
1336 /* Reset the dimensions for thinned grids */
1337 if (gribinfo->elements[index].gds->head.thin != NULL) {
1338 if (gds->head.thin != NULL) {
1339 if ((gds->head.usData_type == LATLON_PRJ) ||
1340 (gds->head.usData_type == GAUSS_PRJ) ||
1341 (gds->head.usData_type == ROT_LATLON_PRJ) ||
1342 (gds->head.usData_type == ROT_GAUSS_PRJ) ||
1343 (gds->head.usData_type == STR_LATLON_PRJ) ||
1344 (gds->head.usData_type == STR_GAUSS_PRJ) ||
1345 (gds->head.usData_type == STR_ROT_LATLON_PRJ) ||
1346 (gds->head.usData_type == STR_ROT_GAUSS_PRJ)) {
1347 ysize = gds->llg.usNj;
1348 } else if (gds->head.usData_type == MERC_PRJ) {
1349 ysize = gds->merc.rows;
1350 } else if (gds->head.usData_type == POLAR_PRJ) {
1351 ysize = gds->pol.usNy;
1352 } else if ((gds->head.usData_type == LAMB_PRJ) ||
1353 (gds->head.usData_type == ALBERS_PRJ) ||
1354 (gds->head.usData_type == OBLIQ_LAMB_PRJ)) {
1355 ysize = gds->lam.iNy;
1358 xsize = 0;
1359 for (j = 0; j<ysize; j++) {
1360 if (gds->head.thin[j] > xsize) {
1361 xsize = gds->head.thin[j];
1366 if ((gds->head.usData_type == LATLON_PRJ) ||
1367 (gds->head.usData_type == GAUSS_PRJ) ||
1368 (gds->head.usData_type == ROT_LATLON_PRJ) ||
1369 (gds->head.usData_type == ROT_GAUSS_PRJ) ||
1370 (gds->head.usData_type == STR_LATLON_PRJ) ||
1371 (gds->head.usData_type == STR_GAUSS_PRJ) ||
1372 (gds->head.usData_type == STR_ROT_LATLON_PRJ) ||
1373 (gds->head.usData_type == STR_ROT_GAUSS_PRJ)) {
1374 gds->llg.usNi = xsize;
1375 gds->llg.iDi = abs(gds->llg.lLat2 - gds->llg.lLat1)/(xsize-1);
1376 } else if (gds->head.usData_type == MERC_PRJ) {
1377 gds->merc.cols = xsize;
1378 } else if (gds->head.usData_type == POLAR_PRJ) {
1379 gds->pol.usNx = xsize;
1380 } else if ((gds->head.usData_type == LAMB_PRJ) ||
1381 (gds->head.usData_type == ALBERS_PRJ) ||
1382 (gds->head.usData_type == OBLIQ_LAMB_PRJ)) {
1383 gds->lam.iNx = xsize;
1388 return 1;
1391 /****************************************************************************
1392 * This returns the index of the gribdata for paramaters which match the input
1393 * parameters and for the date closest to the input targetdate. If dates are
1394 * not found either within hours_before or hours_after the time, then a missing
1395 * value is returned.
1397 * Interface:
1398 * Input:
1399 * gribinfo - pointer to a previously allocated gribinfo structure. The
1400 * gribinfo structure is filled in this function.
1401 * targetdate: This is the date which dates in the grib data will be
1402 * compared to. (format: integer yymmddhh)
1403 * hours_before: The maximum difference in time prior to the targetdate
1404 * for which data should be searched for.
1405 * hours_after: The maximum difference in time after the targetdate for
1406 * which data should be searched for.
1407 * usParm_id: an array of parameter identifiers that could be
1408 * used as a sea level pressure field (From table 2 of
1409 * grib documentation)
1410 * usLevel_id: the level id that could be used as a sea level pressure
1411 * field (from table 3 of the grib documentation)
1412 * usHeight1: the height for the particular parameter and level
1413 * (in units described by the parameter index)
1414 * numparms: the number of parameters in each of the usParm_id,
1415 * usLevel_id, and usHeight1 arrays.
1416 * Return:
1417 * the index of the gribdata with a time closest to the target date.
1418 * -1 if there is no time within the input time limits.
1420 ****************************************************************************/
1421 int rg_get_index_near_date(GribInfo *gribinfo,char targetdate[STRINGSIZE],
1422 int century,int hours_before,int hours_after,
1423 int usParm_id[],int usLevel_id[],int usHeight1[],
1424 int numparms)
1426 int dates[500],indices[500],centuries[500];
1427 int date_before = MISSING;
1428 int date_after = MISSING;
1429 int century_before,century_after;
1430 int date_diff_before = MISSING;
1431 int date_diff_after = MISSING;
1432 int index_before,index_after;
1433 int numdates,datenum;
1434 int index;
1435 int itargetdate;
1437 itargetdate = atoi(targetdate);
1439 numdates = rg_get_dates(gribinfo,usParm_id,usLevel_id,usHeight1,numparms,
1440 dates,centuries,indices);
1441 if (numdates <= 0) {
1442 fprintf(stderr,"get_index_near_date: No dates were found\n");
1443 return -1;
1446 for (datenum = 0; datenum < numdates; datenum++) {
1447 if ((dates[datenum] > itargetdate) && (centuries[datenum] >= century)) {
1448 century_after = centuries[datenum];
1449 date_after = dates[datenum];
1450 index_after = indices[datenum];
1451 break;
1452 } else {
1453 century_before = centuries[datenum];
1454 date_before = dates[datenum];
1455 index_before = indices[datenum];
1459 if (date_after != MISSING)
1460 date_diff_after = date_diff(date_after,century_after,itargetdate,century);
1461 if (date_before != MISSING)
1462 date_diff_before =
1463 date_diff(itargetdate,century,date_before,century_before);
1465 if ((date_after != MISSING) && (date_before != MISSING)) {
1466 if ((date_diff_after <= hours_after) &&
1467 (date_diff_before <= hours_before)) {
1468 if (date_diff_after < date_diff_before)
1469 index = index_before;
1470 else
1471 index = index_after;
1472 } else if (date_diff_after <= hours_after) {
1473 index = index_after;
1474 } else if (date_diff_before <= hours_before) {
1475 index = index_before;
1476 } else {
1477 index = -1;
1479 } else if (date_after != MISSING) {
1480 if (date_diff_after <= hours_after)
1481 index = index_after;
1482 else
1483 index = -1;
1484 } else if (date_before != MISSING) {
1485 if (date_diff_before <= hours_before)
1486 index = index_before;
1487 else
1488 index = -1;
1489 } else {
1490 index = -1;
1493 return index;
1497 /*****************************************************************************
1499 * returns valid time ( = init time + forecast time)
1501 * Input:
1502 * gribinfo - pointer to a previously allocated gribinfo structure. The
1503 * gribinfo structure is filled in this function.
1504 * index - index number of record to get valid time from
1506 * Output:
1507 * valid_time - yyyymmddhhmmss
1509 * Return:
1510 * 0 for success
1511 * -1 for error
1513 *****************************************************************************/
1514 int rg_get_valid_time(GribInfo *gribinfo, int index, char valid_time[])
1516 strcpy(valid_time, gribinfo->elements[index].valid_time);
1517 return 0;
1520 /*****************************************************************************
1522 * returns generating center id
1524 * Input:
1525 * gribinfo - pointer to a previously allocated gribinfo structure. The
1526 * gribinfo structure is filled in this function.
1527 * index - index number of record to get valid time from
1529 * Return:
1530 * generating center id
1531 * -1 for error
1533 *****************************************************************************/
1534 int rg_get_center_id(GribInfo *gribinfo, int index)
1536 return gribinfo->elements[index].center_id;
1539 /*****************************************************************************
1541 * returns parameter table version number
1543 * Input:
1544 * gribinfo - pointer to a previously allocated gribinfo structure. The
1545 * gribinfo structure is filled in this function.
1546 * index - index number of record to get valid time from
1548 * Return:
1549 * parameter table version number
1550 * -1 for error
1552 *****************************************************************************/
1553 int rg_get_parmtbl(GribInfo *gribinfo, int index)
1555 return gribinfo->elements[index].parmtbl;
1558 /*****************************************************************************
1560 * returns generating process id
1562 * Input:
1563 * gribinfo - pointer to a previously allocated gribinfo structure. The
1564 * gribinfo structure is filled in this function.
1565 * index - index number of record to get valid time from
1567 * Return:
1568 * generating process id
1569 * -1 for error
1571 *****************************************************************************/
1572 int rg_get_proc_id(GribInfo *gribinfo, int index)
1574 return gribinfo->elements[index].proc_id;
1577 /*****************************************************************************
1579 * returns sub center id
1581 * Input:
1582 * gribinfo - pointer to a previously allocated gribinfo structure. The
1583 * gribinfo structure is filled in this function.
1584 * index - index number of record to get valid time from
1586 * Return:
1587 * sub center id
1588 * -1 for error
1590 *****************************************************************************/
1591 int rg_get_subcenter_id(GribInfo *gribinfo, int index)
1593 return gribinfo->elements[index].subcenter_id;
1596 /**************************************************************************
1598 * Interpolates grib grid data to a point location.
1600 * Interface:
1601 * input:
1602 * gribinfo - pointer to a previously allocated gribinfo structure. The
1603 * gribinfo structure is filled in this function.
1604 * index - the index of gribinfo for which data is to be retrieved.
1605 * the first grib record is number 1.
1606 * column - the column of the point in grid coordinates (can be
1607 * floating point number). leftmost column is 1.
1608 * row - the row of the point in grid coordinates (can be
1609 * floating point number). bottommost row is 1.
1611 * return:
1612 * on success - the interpolated value at the column,row location.
1613 * on failure - -99999
1615 ***************************************************************************/
1617 float rg_get_point(GribInfo *gribinfo, int index, float column, float row)
1619 int status;
1620 GRIB_PROJECTION_INFO_DEF Proj;
1621 BDS_HEAD_INPUT bds_head;
1622 int dummy;
1623 float **grib_out;
1624 float y1, y2;
1625 int numrows, numcols;
1626 int top, left, right, bottom;
1627 float outval;
1629 numrows = rg_get_numrows(gribinfo, index);
1630 numcols = rg_get_numcols(gribinfo, index);
1632 grib_out = (float **)alloc_float_2d(numrows,numcols);
1633 if (grib_out == NULL) {
1634 fprintf(stderr,"rg_get_point: Could not allocate space for grib_out\n");
1635 return -99999;
1638 status = rg_get_data(gribinfo, index, grib_out);
1639 if (status < 0) {
1640 fprintf(stderr,"rg_get_point: rg_get_data failed\n");
1641 return -99999;
1644 /* Do the interpolation here */
1645 bottom = floor(row);
1646 top = floor(row+1);
1647 left = floor(column);
1648 right = floor(column+1);
1650 y1 = (row - bottom) * (grib_out[top][left] - grib_out[bottom][left]) +
1651 grib_out[bottom][left];
1652 y2 = (row - bottom) * (grib_out[top][right] - grib_out[bottom][right]) +
1653 grib_out[bottom][right];
1654 outval = (y2 - y1) * (column - left) + y1;
1656 free_float_2d(grib_out,numrows,numcols);
1658 return outval;
1662 /**************************************************************************
1664 * Interpolates grib grid data to a point location.
1666 * Interface:
1667 * input:
1668 * gribinfo - pointer to a previously allocated gribinfo structure. The
1669 * gribinfo structure is filled in this function.
1670 * index - the index of gribinfo for which data is to be retrieved.
1671 * the first grib record is number 1.
1672 * input and output:
1673 * pointdata- array of pointdata structures. Only the column and
1674 * row values in the structures need to be filled. On
1675 * output, the 'value' member of pointdata is filled.
1676 * input:
1677 * numpoints- number of pointdata structures in the array.
1679 * return:
1680 * on success - the interpolated value at the column,row location.
1681 * on failure - -99999
1683 ***************************************************************************/
1684 int rg_get_points(GribInfo *gribinfo, int index, PointData pointdata[],
1685 int numpoints)
1687 int status;
1688 float **grib_out;
1689 float y1, y2;
1690 int numrows, numcols;
1691 int top, left, right, bottom;
1692 float column, row;
1693 int idx;
1695 numrows = rg_get_numrows(gribinfo, index);
1696 numcols = rg_get_numcols(gribinfo, index);
1698 grib_out = (float **)alloc_float_2d(numrows,numcols);
1699 if (grib_out == NULL) {
1700 fprintf(stderr,"rg_get_points: Could not allocate space for grib_out\n");
1701 return -99999;
1704 status = rg_get_data(gribinfo, index, grib_out);
1705 if (status < 0) {
1706 fprintf(stderr,"rg_get_points: rg_get_data failed\n");
1707 return -99999;
1710 for (idx = 0; idx < numpoints; idx++) {
1712 /* Change from 1 based to 0 based col/row */
1713 row = pointdata[idx].row;
1714 column = pointdata[idx].column;
1716 /* Do the interpolation here */
1717 bottom = floor(row);
1718 top = floor(row+1);
1719 left = floor(column);
1720 right = floor(column+1);
1722 y1 = (row - bottom) * (grib_out[top][left] - grib_out[bottom][left]) +
1723 grib_out[bottom][left];
1724 y2 = (row - bottom) * (grib_out[top][right] - grib_out[bottom][right]) +
1725 grib_out[bottom][right];
1726 pointdata[idx].value = (y2 - y1) * (column - left) + y1;
1730 free_float_2d(grib_out,numrows,numcols);
1732 return 1;
1735 /**************************************************************************
1737 * Remove an element from an array and decrease, by one, indices of all
1738 * elements with an index greater than the index of the element to remove.
1740 * Interface:
1741 * input:
1742 * array - the integer array to manipulate
1743 * index - the index of the element to remove
1744 * size - the number of elements in the array
1746 ***************************************************************************/
1747 void remove_element(int array[],int index, int size)
1749 int j;
1751 for (j = index; j < size-1; j++) {
1752 array[j] = array[j+1];
1757 /****************************************************************************
1758 * Advance the time by the input amount
1760 * Interface:
1761 * Input:
1762 * century - an integer value for the century (20 for 1900's)
1763 * If the century is advanced, this value is advanced
1764 * and output to the calling routine.
1765 * year - a 2 digit value for the year.
1766 * month - a 2 digit value for the month.
1767 * day - the day of the month
1768 * hour - the hour of the day
1769 * amount - the amount to advance the time by.
1770 * unit - the units for the amount. These are values from table 4
1771 * of the grib manual.
1772 * return:
1773 * a date in the form yymmddhh
1774 ****************************************************************************/
1776 int advance_time(int *century, int year, int month, int day, int hour,
1777 int amount, int unit)
1779 int daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
1780 int date;
1782 switch(unit) {
1783 case 0:
1784 hour += (int)((amount/60.)+0.5);
1785 break;
1786 case 1:
1787 hour += amount;
1788 break;
1789 case 2:
1790 day += amount;
1791 break;
1792 case 3:
1793 month += amount;
1794 break;
1795 case 4:
1796 year += amount;
1797 break;
1798 case 5:
1799 year += 10*amount;
1800 break;
1801 case 6:
1802 year += 30*amount;
1803 break;
1804 case 7:
1805 year += 100*amount;
1806 break;
1807 case 10:
1808 hour += 3*amount;
1809 break;
1810 case 11:
1811 hour += 6*amount;
1812 break;
1813 case 12:
1814 hour += 12*amount;
1815 break;
1816 case 50:
1817 hour += (int)((amount/12.)+0.5);
1818 case 254:
1819 hour += (int)((amount/(60.*60.))+0.5);
1820 break;
1821 default:
1822 fprintf(stderr,"WARNING: Could not advance time, incorrect unit: %d\n",
1823 unit);
1824 return -1;
1827 while (hour >= 24) {
1828 day++;
1829 hour -= 24;
1831 while (month > 12) {
1832 year++;
1833 month -= 12;
1836 /* if it is a leap year, change days in month for Feb now. */
1837 if (isLeapYear(year)) daysinmonth[1] = 29;
1839 while (day > daysinmonth[month-1]) {
1840 day -= daysinmonth[month-1];
1841 month++;
1842 if (month > 12) {
1843 year++;
1844 month -= 12;
1845 if (isLeapYear(year))
1846 daysinmonth[1] = 29;
1847 else
1848 daysinmonth[1] = 28;
1852 if (year > 100) {
1853 (*century)++;
1856 if (year >= 100) {
1857 year -= 100;
1860 date = hour*1 + day*100 + month*10000 + year*1000000;
1862 return date;
1865 /****************************************************************************
1866 * Advance the time by the input amount
1868 * Interface:
1869 * Input:
1870 * startdate - initialization date in the form yyyymmdd[HHMMSS]. If any
1871 * part of HHMMSS is not specified, it will be set to 0.
1872 * amount - the amount (in seconds) to advance the time by.
1874 * Output:
1875 * enddate[] - the time advanced to: yyyymmddHHMMSS format.
1877 * Return:
1878 * 1 - success
1879 * -1 - failure
1881 ****************************************************************************/
1882 char *advance_time_str(char startdatein[], int amount, char enddate[])
1884 struct tm starttp;
1885 struct tm endtp;
1886 char startdate[15];
1887 time_t time;
1889 strcpy(startdate,startdatein);
1890 while (strlen(startdate) < 14) {
1891 strcpy(startdate+(strlen(startdate)),"0");
1894 /* This forces all calculations to use GMT time */
1895 putenv("TZ=GMT0");
1896 tzset();
1898 sscanf(startdate,"%4d%2d%2d%2d%2d%2d",&(starttp.tm_year),&(starttp.tm_mon),
1899 &(starttp.tm_mday),&(starttp.tm_hour),&(starttp.tm_min),
1900 &(starttp.tm_sec));
1901 starttp.tm_mon -= 1;
1902 starttp.tm_year -= 1900;
1903 time = mktime(&starttp);
1904 time += amount;
1905 #ifdef _WIN32
1906 localtime_s(&endtp, &time);
1907 #else
1908 localtime_r(&time, &endtp);
1909 #endif
1910 strftime(enddate,15,"%Y%m%d%H%M%S",&endtp);
1912 return enddate;
1915 /****************************************************************************
1916 * Returns the difference in time in hours between date1 and date2
1917 * (date1-date2).
1919 * Interface:
1920 * Input:
1921 * date1,date2: dates in yymmddhh format (integers)
1922 * century1,century2: centuries for each date (20 for 1900's).
1923 * Return:
1924 * the difference in time between the first and second dates in hours.
1925 ****************************************************************************/
1926 int date_diff(int date1,int century1,int date2,int century2)
1928 return (hours_since_1900(date1,century1) -
1929 hours_since_1900(date2,century2));
1932 /****************************************************************************
1933 * Returns the number of hours since Jan 1, at 00:00 1900.
1935 * Interface:
1936 * Input:
1937 * date: integer in form yymmddhh
1938 * century: 2 digit century (20 for 1900's)
1939 * Return:
1940 * the number of hours since 00:00 Jan1, 1900.
1942 ****************************************************************************/
1943 int hours_since_1900(int date,int century)
1945 int daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
1946 int hour,day,month,year;
1947 int days_since_1900 = 0;
1948 int i;
1950 hour = date%100;
1951 day = (date%10000)/100;
1952 month = (date%1000000)/10000;
1953 year = (date%100000000)/1000000;
1955 days_since_1900 += day;
1957 if (isLeapYear((century-1)*100 + year))
1958 daysinmonth[1] = 29;
1959 else
1960 daysinmonth[1] = 28;
1962 for (i = 0; i < (month - 1); i++)
1963 days_since_1900 += daysinmonth[i];
1965 for (i=0; i < (year + ((century - 20)*100) - 1); i++) {
1966 if (isLeapYear((century - 1)*100 + year))
1967 days_since_1900 += 366;
1968 else
1969 days_since_1900 += 365;
1972 return days_since_1900*24 + hour;
1976 /****************************************************************************
1978 * Returns true if the input year is a leap year, otherwise returns false
1980 ****************************************************************************/
1981 int isLeapYear(int year)
1983 if ( (((year % 4) == 0) && ((year % 100) != 0))
1984 || ((year % 400) == 0) )
1985 return 1;
1986 else
1987 return 0;
1991 /*****************************************************************************
1993 * Returns the number of grib elements (gribinfo->num_elements) processsed
1994 * Input:
1995 * gribinfo - pointer to a previously allocated gribinfo structure. The
1996 * gribinfo structure is filled in this function.
1998 * Return:
1999 * the number of elements in the gribinfo structure
2000 ****************************************************************************/
2002 int rg_num_elements(GribInfo *gribinfo){
2004 return gribinfo->num_elements;
2008 /*****************************************************************************
2010 * Deallocates the elements in the gribinfo structure and closes the files.
2012 * Input:
2013 * gribinfo - pointer to a previously allocated gribinfo structure. The
2014 * gribinfo structure is filled in this function.
2016 *****************************************************************************/
2017 void rg_free_gribinfo_elements(GribInfo *gribinfo)
2019 int i;
2021 for (i=0; i<gribinfo->num_elements; i++) {
2022 free(gribinfo->elements[i].pds);
2023 free(gribinfo->elements[i].gds);
2024 free(gribinfo->elements[i].bms);
2025 free(gribinfo->elements[i].bds_head);
2026 fclose(gribinfo->elements[i].fp);
2028 free(gribinfo->elements);
2031 /*****************************************************************************
2033 * Returns the value for level1 (gribinfo->usHeight1)
2034 * Input:
2035 * gribinfo - pointer to a previously allocated gribinfo structure. The
2036 * gribinfo structure is filled in this function.
2038 * Return:
2039 * value for level1
2040 ****************************************************************************/
2042 int rg_get_level1(GribInfo *gribinfo, int index)
2044 return gribinfo->elements[index].usHeight1;
2047 /*****************************************************************************
2049 * Returns the value for level2 (gribinfo->usHeight2)
2050 * Input:
2051 * gribinfo - pointer to a previously allocated gribinfo structure. The
2052 * gribinfo structure is filled in this function.
2054 * Return:
2055 * value for level1
2056 ****************************************************************************/
2058 int rg_get_level2(GribInfo *gribinfo, int index)
2060 return gribinfo->elements[index].usHeight2;
2063 /*****************************************************************************
2065 * returns number of rows in grid
2067 * Input:
2068 * gribinfo - pointer to a previously allocated gribinfo structure. The
2069 * gribinfo structure is filled in this function.
2071 * Return:
2072 * number of rows in grid
2073 *****************************************************************************/
2074 int rg_get_numrows(GribInfo *gribinfo,int index)
2076 if ((gribinfo->elements[index].gds->head.usData_type == LATLON_PRJ) ||
2077 (gribinfo->elements[index].gds->head.usData_type == GAUSS_PRJ) ||
2078 (gribinfo->elements[index].gds->head.usData_type == ROT_LATLON_PRJ) ||
2079 (gribinfo->elements[index].gds->head.usData_type == ROT_GAUSS_PRJ) ||
2080 (gribinfo->elements[index].gds->head.usData_type == STR_LATLON_PRJ) ||
2081 (gribinfo->elements[index].gds->head.usData_type == STR_GAUSS_PRJ) ||
2082 (gribinfo->elements[index].gds->head.usData_type == STR_ROT_LATLON_PRJ)||
2083 (gribinfo->elements[index].gds->head.usData_type == STR_ROT_GAUSS_PRJ))
2085 return gribinfo->elements[index].gds->llg.usNj;
2086 } else if (gribinfo->elements[index].gds->head.usData_type == MERC_PRJ) {
2087 return gribinfo->elements[index].gds->merc.rows;
2088 } else if (gribinfo->elements[index].gds->head.usData_type == LAMB_PRJ) {
2089 return gribinfo->elements[index].gds->lam.iNy;
2090 } else if (gribinfo->elements[index].gds->head.usData_type == POLAR_PRJ) {
2091 return gribinfo->elements[index].gds->pol.usNy;
2095 /*****************************************************************************
2097 * returns number of columns in grid
2099 * Input:
2100 * gribinfo - pointer to a previously allocated gribinfo structure. The
2101 * gribinfo structure is filled in this function.
2103 * Return:
2104 * number of columns in grid
2105 *****************************************************************************/
2106 int rg_get_numcols(GribInfo *gribinfo,int index)
2108 if ((gribinfo->elements[index].gds->head.usData_type == LATLON_PRJ) ||
2109 (gribinfo->elements[index].gds->head.usData_type == GAUSS_PRJ) ||
2110 (gribinfo->elements[index].gds->head.usData_type == ROT_LATLON_PRJ) ||
2111 (gribinfo->elements[index].gds->head.usData_type == ROT_GAUSS_PRJ) ||
2112 (gribinfo->elements[index].gds->head.usData_type == STR_LATLON_PRJ) ||
2113 (gribinfo->elements[index].gds->head.usData_type == STR_GAUSS_PRJ) ||
2114 (gribinfo->elements[index].gds->head.usData_type == STR_ROT_LATLON_PRJ)||
2115 (gribinfo->elements[index].gds->head.usData_type == STR_ROT_GAUSS_PRJ))
2117 return gribinfo->elements[index].gds->llg.usNi;
2118 } else if (gribinfo->elements[index].gds->head.usData_type == MERC_PRJ) {
2119 return gribinfo->elements[index].gds->merc.cols;
2120 } else if (gribinfo->elements[index].gds->head.usData_type == LAMB_PRJ) {
2121 return gribinfo->elements[index].gds->lam.iNx;
2122 } else if (gribinfo->elements[index].gds->head.usData_type == POLAR_PRJ) {
2123 return gribinfo->elements[index].gds->pol.usNx;
2127 /*****************************************************************************
2129 * returns the offset (in bytes) from the beginning of the file.
2131 * Input:
2132 * gribinfo - pointer to a filled gribinfo structure.
2134 * Return:
2135 * offset (in bytes) from beginning of file
2136 *****************************************************************************/
2137 int rg_get_offset(GribInfo *gribinfo,int index)
2139 return gribinfo->elements[index].offset;
2141 /*****************************************************************************
2143 * returns the grib record ending position (in bytes) from the beginning of
2144 * the file.
2146 * Input:
2147 * gribinfo - pointer to a filled gribinfo structure.
2149 * Return:
2150 * position (in bytes) of the end of the grib record within the file.
2151 *****************************************************************************/
2152 int rg_get_end(GribInfo *gribinfo,int index)
2154 return gribinfo->elements[index].end;
2156 /*****************************************************************************
2158 * returns grib id of input grid
2160 * Input:
2161 * gribinfo - pointer to a previously allocated gribinfo structure. The
2162 * gribinfo structure is filled in this function.
2164 * Return:
2165 * grib id of input grid
2166 *****************************************************************************/
2167 int rg_get_gridnum(GribInfo *gribinfo,int index)
2169 return gribinfo->elements[index].pds->usGrid_id;
2171 /*****************************************************************************
2173 * returns date
2175 * Input:
2176 * gribinfo - pointer to a previously allocated gribinfo structure. The
2177 * gribinfo structure is filled in this function.
2179 * Return:
2180 * date (yymmddhh) in integer type
2181 *****************************************************************************/
2182 int rg_get_date(GribInfo *gribinfo,int index)
2184 return gribinfo->elements[index].date;
2186 /*****************************************************************************
2188 * returns century
2190 * Input:
2191 * gribinfo - pointer to a previously allocated gribinfo structure. The
2192 * gribinfo structure is filled in this function.
2194 * Return:
2195 * century in integer type
2196 *****************************************************************************/
2197 int rg_get_century(GribInfo *gribinfo,int index)
2199 return gribinfo->elements[index].century;
2201 /*****************************************************************************
2203 * returns forecast time
2205 * Input:
2206 * gribinfo - pointer to a previously allocated gribinfo structure. The
2207 * gribinfo structure is filled in this function.
2209 * Return:
2210 * forecast time in units described by usFcst_unit_id
2211 *****************************************************************************/
2212 int rg_get_forecast_time(GribInfo *gribinfo,int index)
2214 return gribinfo->elements[index].pds->usP1;
2217 /*****************************************************************************
2219 * reads the gribmap file, and stores the information in the GribParameters
2220 * structure.
2222 * Input:
2223 * gribmap - pointer to a previously allocated GribParameters structure.
2224 * The gribmap structure is filled in this function.
2225 * file - the name of the gribmap file to read.
2227 * Return:
2228 * 1 - successful call to setup_gribinfo
2229 * -1 - call to setup_gribinfo failed
2231 *****************************************************************************/
2232 int rg_setup_gribmap(GribParameters *gribmap, char filename[])
2234 FILE *fid;
2235 char line[500];
2236 int id, center, subcenter, table;
2237 int idx;
2239 fid = fopen(filename,"r");
2240 if (fid == NULL)
2242 fprintf(stderr,"Could not open %s\n",filename);
2243 return -1;
2246 gribmap->parms = (GribTableEntry *)malloc(sizeof(GribTableEntry));
2248 idx = 0;
2249 while (fgets(line,500,fid) != NULL)
2251 /* Skip over comments at begining of gribmap file */
2252 if (line[0] == '#') continue;
2254 sscanf(line,"%d:",&id);
2255 if (id == -1)
2257 sscanf(line,"%d:%d:%d:%d",&id,&center,&subcenter,&table);
2259 else
2261 gribmap->parms =
2262 (GribTableEntry *)realloc(gribmap->parms,
2263 (idx+1)*sizeof(GribTableEntry));
2264 gribmap->parms[idx].center = center;
2265 gribmap->parms[idx].subcenter = subcenter;
2266 gribmap->parms[idx].table = table;
2267 sscanf(line,"%d:%[^:]:%[^:]",&(gribmap->parms[idx].parmid),
2268 gribmap->parms[idx].name,
2269 gribmap->parms[idx].comment);
2270 idx++;
2275 gribmap->num_entries = idx;
2277 fclose(fid);
2278 return 1;
2281 /*****************************************************************************
2283 * finds the gribmap entry described by the gribmap file, and stores the information in the GribParameters
2284 * structure.
2286 * Input:
2287 * gribmap - pointer to structure that was filled by a call to
2288 * rg_setup_gribmap
2289 * table - if set to -1, the first table the valid name will be used.
2290 * Otherwise, the table id must match as well.
2291 * name - name of the parameter to find.
2292 * Output
2293 * gribmap_parms - pointer to GribTableEntry structure containing
2294 * information about the parameter that was found.
2296 * Return:
2297 * 1 - successful call to setup_gribinfo
2298 * -1 - call to setup_gribinfo failed
2300 *****************************************************************************/
2301 int rg_gribmap_parameter(GribParameters *gribmap, char name[], int table,
2302 GribTableEntry *gribmap_parms)
2304 int idx;
2305 int found;
2307 found = 0;
2308 for (idx = 0; idx < gribmap->num_entries; idx++)
2311 if (strcmp(gribmap->parms[idx].name,name) == 0)
2313 if ((table == -1) || (table == gribmap->parms[idx].table))
2315 /* We found a match! */
2316 found = 1;
2317 break;
2322 if (found)
2324 memcpy(gribmap_parms,&(gribmap->parms[idx]),sizeof(GribTableEntry));
2325 return 1;
2327 else
2329 return -1;
2333 /*****************************************************************************
2335 * Deallocates the elements in the gribmap structure.
2337 * Input:
2338 * gribmap - pointer to a previously allocated gribmap structure. The
2339 * gribmap structure is filled in this function.
2341 *****************************************************************************/
2342 void rg_free_gribmap_elements(GribParameters *gribmap)
2344 free(gribmap->parms);
2347 /*****************************************************************************
2349 * Compares the elements in a findgrib structure with the elements in the
2350 * gribinfo structure for the input index. If they match, returns 1,
2351 * otherwise, returns 0.
2353 * Input:
2354 * gribinfo
2355 * findgrib
2356 * index - the index of the grib record in gribinfo to compare to.
2358 *****************************************************************************/
2359 int compare_record(GribInfo *gribinfo, FindGrib *findgrib, int gribnum)
2363 * Note (6/20/05): This searching is very inefficient. We may need to
2364 * improve this, since, for WRF, when searching through boundary data,
2365 * each search is slower that the previous, since the record to be
2366 * found turns out to be farther into the list.
2369 int retval = 0;
2371 if ((findgrib->center_id == -INT_MAX) ||
2372 findgrib->center_id == gribinfo->elements[gribnum].center_id) {
2373 if ((findgrib->subcenter_id == -INT_MAX) ||
2374 findgrib->subcenter_id == gribinfo->elements[gribnum].subcenter_id) {
2375 if ((findgrib->parmtbl_version == -INT_MAX) ||
2376 findgrib->parmtbl_version == gribinfo->elements[gribnum].parmtbl) {
2377 if ((strcmp(findgrib->initdate,"*") == 0) ||
2378 (strncmp(gribinfo->elements[gribnum].initdate,findgrib->initdate,
2379 strlen(findgrib->initdate)) == 0)) {
2380 if ((strcmp(findgrib->validdate,"*") == 0) ||
2381 (strncmp(gribinfo->elements[gribnum].valid_time,
2382 findgrib->validdate,
2383 strlen(findgrib->validdate)) == 0)) {
2384 if ((findgrib->parmid == -INT_MAX) ||
2385 (findgrib->parmid ==
2386 gribinfo->elements[gribnum].usParm_id)) {
2387 if ((findgrib->leveltype == -INT_MAX) ||
2388 (findgrib->leveltype ==
2389 gribinfo->elements[gribnum].usLevel_id)) {
2390 if ((findgrib->level1 == -INT_MAX) ||
2391 (findgrib->level1 ==
2392 gribinfo->elements[gribnum].usHeight1)) {
2393 if ((findgrib->level2 == -INT_MAX) ||
2394 (findgrib->level2 ==
2395 gribinfo->elements[gribnum].usHeight2)) {
2396 if ((findgrib->fcsttime1 == -INT_MAX) ||
2397 (findgrib->fcsttime1 ==
2398 gribinfo->elements[gribnum].fcsttime1)) {
2399 if ((findgrib->fcsttime2 == -INT_MAX) ||
2400 (findgrib->fcsttime2 ==
2401 gribinfo->elements[gribnum].fcsttime2)) {
2402 retval = 1;
2415 return retval;
2419 /*****************************************************************************
2421 * returns the multiplication factor to convert grib forecast times to
2422 * seconds.
2424 * Input:
2425 * unit_id - grib forecast unit id, from Table 4.
2427 * Return:
2428 * conversion factor
2429 *****************************************************************************/
2430 int get_factor2(int unit)
2432 int factor;
2434 switch (unit) {
2435 case 0:
2436 factor = 60;
2437 break;
2438 case 1:
2439 factor = 60*60;
2440 break;
2441 case 2:
2442 factor = 60*60*24;
2443 break;
2444 case 10:
2445 factor = 60*60*3;
2446 break;
2447 case 11:
2448 factor = 60*60*3;
2449 break;
2450 case 12:
2451 factor = 60*60*12;
2452 break;
2453 case 50:
2454 /* This is a WSI (non-standard) time unit of 5 minutes */
2455 factor = 5*60;
2456 break;
2457 case 254:
2458 factor = 1;
2459 break;
2460 default:
2461 fprintf(stderr,"Invalid unit for forecast time: %d\n",unit);
2462 factor = 0;
2464 return factor;