source: trunk/WRF.COMMON/WRFV2/external/io_grib1/grib1_util/read_grib.c @ 2756

Last change on this file since 2756 was 11, checked in by aslmd, 14 years ago

spiga@svn-planeto:ajoute le modele meso-echelle martien

File size: 76.8 KB
Line 
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
7 *
8 * Functions in this file are used for decoding grib data.  Please see the
9 * headers before each function for a full descrption.
10 *
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.
21 *
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.
26 *
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.
31 *
32 ****************************************************************************/
33
34#define ERRSIZE 2000
35#define ALLOCSIZE 30
36#define MISSING -999
37
38#define EARTH_RADIUS 6371.229        /* in km */
39#define PI           3.141592654
40#define PI_OVER_180  PI/180.
41
42#include <stdio.h>
43#include <string.h>
44#include <stdlib.h>
45#include <math.h>
46#include <limits.h>
47#ifdef MACOS
48#include "/usr/include/time.h"
49#else
50#include <time.h>
51#endif
52#include "cfortran.h"
53#include "gribfuncs.h"
54#include "gribsize.incl"
55#include "read_grib.h"
56
57/* Function Declarations */
58
59void remove_element(int array[],int index, int size);
60int advance_time(int *century, int year, int month, int day, int hour,
61                 int amount, int unit);
62char *advance_time_str(char startdatein[], int amount, char enddate[]);
63int date_diff(int date1,int century1,int date2,int century2);
64int hours_since_1900(int date,int century);
65int isLeapYear(int year);
66int get_factor2(int unit);
67int compare_record(GribInfo *gribinfo, FindGrib *findgrib, int gribnum);
68
69/*
70 *These lines allow fortran routines to call the c routines.  They are
71 * used by macros defined in cfortran.h
72 */
73#define get_pressure_levels_STRV_A1 TERM_CHARS(' ',1)
74/*
75FCALLSCFUN6(INT, get_pressure_levels,GET_PRESSURE_LEVELS,
76            get_pressure_levels,STRINGV,INTV,INTV,INTV,INT,INT)
77#define setup_gribinfo_STRV_A1 TERM_CHARS(' ',1)
78FCALLSCFUN2(INT,setup_gribinfo,SETUP_GRIBINFO,setup_gribinfo,STRINGV,INT)
79#define get_msl_indices_STRV_A1 TERM_CHARS(' ',1)
80FCALLSCFUN9(INT, get_msl_indices,GET_MSL_INDICES,get_msl_indices,
81            STRINGV,INTV,INTV,INTV,INTV,INTV,INT,INTV,INTV)
82FCALLSCFUN5(INT, get_index,GET_INDEX,get_index,INT,INT,INT,INT,INT)
83#define read_grib_STRV_A1 TERM_CHARS(' ',1)
84FCALLSCFUN7(INT,get_dates,GET_DATES,get_dates,INTV,INTV,INTV,INT,INTV,
85            INTV,INTV)
86FCALLSCFUN7(INT, read_grib,READ_GRIB,read_grib,
87            STRINGV,INT,INT,INT,INT,FLOATVV,PVOID)
88FCALLSCFUN8(INT, get_index_near_date,GET_INDEX_NEAR_DATE,get_index_near_date,
89            STRING,INT,INT,INT,INTV,INTV,INTV,INT)
90*/
91/* The value for usLevel_id for isobaric levels */
92#define ISOBARIC_LEVEL_ID 100 
93
94/*************************************************************************
95 * This function reads and decodes grib records in a list of input files
96 * and stores information about each grib record in the gribinfo array
97 * structure.  The gribinfo structure can then be accessed by any function
98 * within this file.
99 *
100 * Interface:
101 *   Input:
102 *      gribinfo - pointer to a previously allocated gribinfo structure.  The
103 *                 gribinfo structure is filled in this function.
104 *      files - a string array containing the names of the files containing
105 *              the grib data.  If called from a fortran routine, the
106 *              fortran routine must set the character size of the array to
107 *              be STRINGSIZE-1. The last filled element in the array should
108 *              be "END".
109 *      use_fcst - if TRUE, forecast fields will be included in the gribinfo
110 *              structure, otherwise, only analysis fields will be included.
111 *
112 *    Return:
113 *       1  - successful call to setup_gribinfo
114 *       -1 - call to setup_gribinfo failed
115 *
116 ***************************************************************************/
117
118int rg_setup_gribinfo(GribInfo *gribinfo, char files[][STRINGSIZE],
119                      int use_fcst)
120{
121  FILE *fp;
122  int filenum;
123  int nReturn;
124  int idx;
125  int status;
126  int start_elem;
127 
128  /* Loop through input files */
129  filenum = 0;
130  while ((strcmp(files[filenum], "end") != 0 ) && 
131         (strcmp(files[filenum], "END") != 0 )) {
132   
133    /*
134     * This forces gribinfo to be fully initialized.
135     */
136    if (filenum == 0) 
137      {
138        gribinfo->num_elements = 0;
139      }
140
141    start_elem = gribinfo->num_elements;
142
143    fp = fopen(files[filenum],"r");
144    if (fp == NULL)
145      {
146        fprintf(stderr,"Could not open %s\n",files[filenum]);
147        nReturn = -1;
148        break;
149      }
150   
151    status = rg_setup_gribinfo_f(gribinfo, fp, use_fcst);
152    if (status != 1) 
153      {
154        fprintf(stderr, 
155            "rg_setup_gribinfo_f returned non-zero status (%d), skipping %s\n",
156                status,files[filenum]);
157        continue;
158      }
159
160    for (idx=start_elem; idx < gribinfo->num_elements; idx++) 
161      {
162        strcpy(gribinfo->elements[idx].filename,
163               files[filenum]);
164      }
165
166   
167    filenum++;
168    nReturn = 1;
169  }
170
171  return nReturn;
172}
173
174
175
176/*************************************************************************
177 *
178 * Similar to rg_setup_gribinfo, except, a unix file descriptor is passed in,
179 * rather than a list of files to open.
180 *
181 *************************************************************************/
182
183int rg_setup_gribinfo_i(GribInfo *gribinfo, int fid, int use_fcst)
184{
185  FILE *fp;
186  int status;
187 
188  fp = fdopen(fid,"r");
189  if (fp == NULL)
190    {
191      fprintf(stderr,"Could not open file descriptor %d\n",fid);
192      status = -1;
193      return status;
194    }
195 
196  /* This forces gribinfo to be initialized for the first time */
197  gribinfo->num_elements = 0;
198 
199  status = rg_setup_gribinfo_f(gribinfo, fp, use_fcst);
200  if (status != 1) 
201    {
202      fprintf(stderr, 
203              "rg_setup_gribinfo_f returned non-zero status (%d)\n",
204              status);
205    }
206 
207  return status;
208}
209
210/*************************************************************************
211 *
212 * Similar to rg_setup_gribinfo, except, a file pointer is passed in, rather
213 * than a list of files to open.
214 *
215 * If gribinfo->num_elements is 0, gribinfo is initialized, otherwise,
216 *    gribinfo is appended to.
217 *
218 *************************************************************************/
219
220int rg_setup_gribinfo_f(GribInfo *gribinfo, FILE *fp, int use_fcst)
221{
222  char errmsg[ERRSIZE];
223  int nReturn=0;
224  long offset;
225  int filenum;
226  int Rd_Indexfile=0;
227  GRIB_HDR *gh1;
228  long tmpoffset=0;
229  int century;
230  int year4d;
231  int fcsttime1=0;
232  int fcsttime2=0;
233  int factor=0;
234
235  /* Set the number of elements to be zero initially */
236  if (gribinfo->num_elements <= 0)
237    {
238      /* Allocate space for gribinfo */
239      gribinfo->elements = (Elements *)calloc(ALLOCSIZE,sizeof(Elements));
240      if (gribinfo->elements == NULL) {
241        sprintf(errmsg,"Could not allocate %d bytes for gribinfo->elements\n",
242                ALLOCSIZE*sizeof(Elements));
243        goto bail_out;
244      }
245    }
246 
247  /* Make storage for Grib Header */
248  nReturn = init_gribhdr(&gh1, errmsg);
249  /*
250   * The grib library is setup such that, when init_gribhdr == 0, it was
251   * successful.  If it is 1, it failed.
252   */
253  if (nReturn == 1) goto bail_out;
254 
255  /* Scan through message */
256  for (offset = 0L; nReturn == 0; offset += gh1->msg_length) {
257    if ((gribinfo->num_elements > 0) && 
258        (gribinfo->num_elements%ALLOCSIZE == 0))
259      gribinfo->elements = 
260        (Elements *)realloc(gribinfo->elements,
261                            (gribinfo->num_elements+ALLOCSIZE)*
262                            sizeof(Elements));
263
264    if (gribinfo->elements == NULL) {
265      sprintf(errmsg,"Could not allocate %d bytes for gribinfo\n",
266              (gribinfo->num_elements + ALLOCSIZE)*sizeof(Elements));
267      goto bail_out;
268    }
269
270    /* Setup the File pointer */
271    gribinfo->elements[gribinfo->num_elements].fp = fp;
272
273    gribinfo->elements[gribinfo->num_elements].pds = 
274      (PDS_INPUT *)malloc(1*sizeof(PDS_INPUT));
275    gribinfo->elements[gribinfo->num_elements].gds = 
276      (grid_desc_sec *)malloc(1*sizeof(grid_desc_sec));
277    gribinfo->elements[gribinfo->num_elements].bms = 
278      (BMS_INPUT *)malloc(1*sizeof(BMS_INPUT));
279    gribinfo->elements[gribinfo->num_elements].bds_head = 
280      (BDS_HEAD_INPUT *)malloc(1*sizeof(BDS_HEAD_INPUT));
281    errmsg[0] = '\0';
282    nReturn = 
283      grib_fseek(fp,&offset, Rd_Indexfile, gh1, errmsg);
284    if (nReturn != 0) {
285      if (nReturn == 2) break;   /* End of file error */
286      else {
287        fprintf(stderr, "Grib_fseek returned non zero status (%d)\n",
288                nReturn);
289        goto bail_out;
290      }
291    }
292    if (errmsg[0] != '\0')
293      { /* NO errors but got a Warning msg from seek */
294        fprintf(stderr,"%s; Skip Decoding...\n",errmsg);
295        errmsg[0] = '\0';   
296        gh1->msg_length = 1L;    /* set to 1 to bump offset up */
297        continue;
298      }
299     
300    if (gh1->msg_length < 0) {
301      fprintf(stderr, "Error:  message returned had bad length (%ld)\n",
302              gh1->msg_length);
303      goto bail_out;
304    }
305    else if (gh1->msg_length == 0) {
306      fprintf(stderr, "msg_length is Zero\n");
307      gh1->msg_length = 1L;
308      continue;
309    }
310    init_dec_struct(gribinfo->elements[gribinfo->num_elements].pds, 
311                    gribinfo->elements[gribinfo->num_elements].gds, 
312                    gribinfo->elements[gribinfo->num_elements].bms, 
313                    gribinfo->elements[gribinfo->num_elements].bds_head);
314   
315    /*
316     * gribgetpds is an undocumented function within the grib library.
317     * gribgetpds grabs the pds section from the grib message without
318     * decoding the entire grib message.  The interface is as follows:
319     *     first input param: a pointer to the beginning of the pds
320     *                        section.
321     *     second input param: a pointer to a structure which will hold
322     *                        the pds information
323     *     third param: the error message.
324     *
325     * If gribgetpds ever fails, it can be replaced with the following
326     *    nReturn = grib_dec((char *)gh1->entire_msg, &pds, &gds, &bds_head,
327     *              &bms, &grib_data, errmsg);
328     *
329     * This will degrade performance since this grib_dec decodes the
330     *    entire grib message.
331     */
332   
333    nReturn = gribgetpds((char*)(gh1->entire_msg + 8),
334                         gribinfo->elements[gribinfo->num_elements].pds,
335                         errmsg);
336    if (nReturn != 0) goto bail_out;
337
338    /* Get gds if present */
339    if (gribinfo->elements[gribinfo->num_elements].pds->usGds_bms_id >> 7 
340        & 1) {
341      nReturn = 
342        gribgetgds((char*)
343                   (gh1->entire_msg+8+
344                    gribinfo->elements[gribinfo->num_elements].pds->uslength),
345                   gribinfo->elements[gribinfo->num_elements].gds,errmsg);
346      if (nReturn != 0) goto bail_out;
347    }
348
349    /* Get bms section if present */
350    if (gribinfo->elements[gribinfo->num_elements].pds->usGds_bms_id >> 6 
351        & 1) {
352      /*
353        fprintf(stderr,"grids with bms section not currently supported\n");
354        return -1;
355      */
356    }
357   
358    gribinfo->elements[gribinfo->num_elements].usGrid_id = 
359      gribinfo->elements[gribinfo->num_elements].pds->usGrid_id;
360    gribinfo->elements[gribinfo->num_elements].usParm_id = 
361      gribinfo->elements[gribinfo->num_elements].pds->usParm_id;
362    gribinfo->elements[gribinfo->num_elements].usLevel_id = 
363      gribinfo->elements[gribinfo->num_elements].pds->usLevel_id;
364    gribinfo->elements[gribinfo->num_elements].usHeight1 = 
365      gribinfo->elements[gribinfo->num_elements].pds->usHeight1;
366    gribinfo->elements[gribinfo->num_elements].usHeight2 = 
367      gribinfo->elements[gribinfo->num_elements].pds->usHeight2;
368    gribinfo->elements[gribinfo->num_elements].center_id = 
369      gribinfo->elements[gribinfo->num_elements].pds->usCenter_id;
370    gribinfo->elements[gribinfo->num_elements].parmtbl = 
371      gribinfo->elements[gribinfo->num_elements].pds->usParm_tbl;
372    gribinfo->elements[gribinfo->num_elements].proc_id = 
373      gribinfo->elements[gribinfo->num_elements].pds->usProc_id;
374    gribinfo->elements[gribinfo->num_elements].subcenter_id = 
375      gribinfo->elements[gribinfo->num_elements].pds->usCenter_sub;
376    gribinfo->elements[gribinfo->num_elements].offset = offset;
377    gribinfo->elements[gribinfo->num_elements].end = 
378      offset + gh1->msg_length - 1;
379 
380    if (use_fcst) {
381      century = gribinfo->elements[gribinfo->num_elements].pds->usCentury;
382     
383      if (gribinfo->elements[gribinfo->num_elements].pds->usTime_range == 10)
384        {
385          fcsttime1 = gribinfo->elements[gribinfo->num_elements].pds->usP1*256 + 
386            gribinfo->elements[gribinfo->num_elements].pds->usP2;
387          fcsttime2 = 0;
388        }
389      else if (gribinfo->elements[gribinfo->num_elements].pds->usTime_range
390               == 203) {
391        /* This is the WSI extension to grib.  203 indicates "duration" */
392        fcsttime1 = gribinfo->elements[gribinfo->num_elements].pds->usP1;
393        fcsttime2 = gribinfo->elements[gribinfo->num_elements].pds->usP1 +
394          gribinfo->elements[gribinfo->num_elements].pds->usP2;
395      } else {
396        fcsttime1 = gribinfo->elements[gribinfo->num_elements].pds->usP1;
397        fcsttime2 = gribinfo->elements[gribinfo->num_elements].pds->usP2;
398      }
399     
400      gribinfo->elements[gribinfo->num_elements].date = 
401        advance_time(&century,
402                     gribinfo->elements[gribinfo->num_elements].pds->usYear,
403                     gribinfo->elements[gribinfo->num_elements].pds->usMonth,
404                     gribinfo->elements[gribinfo->num_elements].pds->usDay,
405                     gribinfo->elements[gribinfo->num_elements].pds->usHour,
406                     fcsttime1,
407                     gribinfo->elements[gribinfo->num_elements].pds->usFcst_unit_id);
408    } 
409    else {
410      gribinfo->elements[gribinfo->num_elements].date = 
411        gribinfo->elements[gribinfo->num_elements].pds->usHour*1 + 
412        gribinfo->elements[gribinfo->num_elements].pds->usDay*100 + 
413        gribinfo->elements[gribinfo->num_elements].pds->usMonth*10000 + 
414        gribinfo->elements[gribinfo->num_elements].pds->usYear*1000000;
415    } 
416    gribinfo->elements[gribinfo->num_elements].century = 
417      gribinfo->elements[gribinfo->num_elements].pds->usCentury;
418   
419    year4d = 
420        (gribinfo->elements[gribinfo->num_elements].pds->usCentury - 1) * 100
421        + gribinfo->elements[gribinfo->num_elements].pds->usYear;
422
423    sprintf(gribinfo->elements[gribinfo->num_elements].initdate,
424            "%04d%02d%02d%02d%02d%02d",
425            year4d,
426            gribinfo->elements[gribinfo->num_elements].pds->usMonth,
427            gribinfo->elements[gribinfo->num_elements].pds->usDay,
428            gribinfo->elements[gribinfo->num_elements].pds->usHour,
429            gribinfo->elements[gribinfo->num_elements].pds->usMinute,
430            0);       
431   
432    factor = 
433      get_factor2(gribinfo->elements[gribinfo->num_elements].pds->usFcst_unit_id);
434    gribinfo->elements[gribinfo->num_elements].fcsttime1 = 
435      fcsttime1 * factor;
436    gribinfo->elements[gribinfo->num_elements].fcsttime2 = 
437      fcsttime2 * factor;
438   
439    advance_time_str(gribinfo->elements[gribinfo->num_elements].initdate,
440                     gribinfo->elements[gribinfo->num_elements].fcsttime1,
441                     gribinfo->elements[gribinfo->num_elements].valid_time);
442
443    gribinfo->num_elements++;
444  }
445 
446  free_gribhdr(&gh1);
447  return 1;
448 
449  /* The error condition */
450 bail_out:
451  if (errmsg[0] != '\0') fprintf(stderr,"\n***ERROR: %s: %s\n",
452                                 "setup_grib",errmsg);
453  if (gribinfo->elements != NULL) free(gribinfo->elements);
454  perror("System Error ");
455  return -1;
456}
457
458/*****************************************************************************
459 *
460 * Retrieve pressure levels from grib data.  This function will pass the
461 * pressure levels for which the input parameter is available at all input
462 * times back to the calling routine. 
463 *
464 * Interface
465 *      Input:
466 *         gribinfo - pointer to a previously allocated gribinfo structure. 
467 *                 The gribinfo structure is filled in this function.
468 *         dates: an array of dates to check for data
469 *                format: yymmddhh
470 *                If called from a fortran routine, the fortran routine must
471 *                set the character size of the array to be STRINGSIZE-1
472 *         centuries: an array holding the centuries for each of the
473 *                dates in the array dates.
474 *         parm_id: the input parameter id.  From table 2 of the grib manual.
475 *      Output:
476 *         finallevels: an array of pressure levels which are contained in
477 *                the grib data at all input times.
478 *      Return:
479 *         the number of levels in the levels array.  The levels are listing
480 *         in descending (by value) order, i.e., the value with the highest
481 *         pressure (lowest vertical level) is the first element.
482 *
483 ****************************************************************************/
484
485int rg_get_pressure_levels(GribInfo *gribinfo, int dates[], int centuries[], 
486                        int parm_id[], int finallevels[],int min_pres,
487                        int numparms)
488{
489  int datenum;
490  int gribnum;
491  int *levelnum;
492  int levelincluded;
493  int i,j;
494  int contains_level;
495  int **tmplevels;
496  int numfinallevels = 0;
497  int parmnum;
498  int tmpval;
499 
500  /* Allocate space */
501  levelnum = (int *)calloc(numparms,sizeof(int));
502  tmplevels = (int **)calloc(numparms,sizeof(int *));
503  for (j = 0; j < numparms; j++) {
504    tmplevels[j] = (int *)calloc(1000,sizeof(int));
505    if (tmplevels[j] == NULL) {
506      tmplevels = NULL;
507      break;
508    }
509  }
510  if ((levelnum == NULL) || (tmplevels == NULL)) {
511    fprintf(stderr,
512            "get_pressure_levels: Allocation of space failed, returning\n");
513    return -1;
514  }
515 
516  /* Loop through all parameters */
517  for (parmnum = 0; parmnum < numparms; parmnum++) {
518
519    levelnum[parmnum] = 0;
520
521  /* Get the array of pressure levels available at the first input time */
522    datenum = 0;
523    for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
524      if (gribinfo->elements[gribnum].date == dates[datenum]) {
525        if (gribinfo->elements[gribnum].century == centuries[datenum]) {
526          if (gribinfo->elements[gribnum].usLevel_id == ISOBARIC_LEVEL_ID) {
527            if (gribinfo->elements[gribnum].usParm_id == parm_id[parmnum]) {
528              if (gribinfo->elements[gribnum].usHeight1 >= min_pres) {
529                levelincluded = 0;
530                for (j=0; j < levelnum[parmnum]; j++) {
531                  if (tmplevels[parmnum][j] == 
532                      gribinfo->elements[gribnum].usHeight1) {
533                    levelincluded = 1;
534                    break;
535                  }
536                }
537                if (levelincluded == 0) {
538                  tmplevels[parmnum][levelnum[parmnum]] = 
539                    gribinfo->elements[gribnum].usHeight1;
540                  levelnum[parmnum]++;
541                }
542              }
543            }
544          }
545        }
546      }
547    }
548   
549    /* Remove levels that are not contained at all subsequent times */
550    datenum++;
551    while (dates[datenum] != -99){
552      for (j = 0; j < levelnum[parmnum]; j++) {
553        contains_level = 0;
554        for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
555          if (gribinfo->elements[gribnum].date == dates[datenum]) {
556            if (gribinfo->elements[gribnum].century == centuries[datenum]) {
557              if (gribinfo->elements[gribnum].usLevel_id == ISOBARIC_LEVEL_ID)
558                {
559                  if (gribinfo->elements[gribnum].usParm_id == 
560                      parm_id[parmnum]) {
561                    if (tmplevels[parmnum][j] == 
562                        gribinfo->elements[gribnum].usHeight1)
563                      contains_level = 1;
564                  }
565                }
566            }
567          }
568        }
569        if (!(contains_level)) {
570          remove_element(tmplevels[parmnum],j,levelnum[parmnum]);
571          levelnum[parmnum]--;
572          j--;
573        }
574      }
575      datenum++;
576    }
577
578    /*
579     * Put the values for levels into an array.  Remove any levels that
580     * were not found at all other levels
581     */
582    if (parmnum == 0) {
583      for (j = 0; j < levelnum[parmnum]; j++) {
584        finallevels[j] = tmplevels[parmnum][j];
585        numfinallevels++;
586      }
587    } else {
588      for (i=0; i<numfinallevels; i++) {
589        contains_level = 0;
590        for (j=0; j<levelnum[parmnum]; j++) {
591          if (finallevels[i] == tmplevels[parmnum][j]) {
592            contains_level = 1;
593            break;
594          }
595        }
596        if (!contains_level) {
597          remove_element(finallevels,i,numfinallevels);
598          numfinallevels--;
599          i--;
600        }
601      }
602    }
603
604  }
605
606  /*
607   * Sort the numfinallevels array into descending order. Use straight
608   * insertion.
609   */
610  for (j=1; j<numfinallevels; j++) {
611    tmpval = finallevels[j];
612    for (i=j-1; i >= 0; i--) {
613      if (finallevels[i] >= tmpval) break;
614      finallevels[i+1] = finallevels[i];
615    }
616    finallevels[i+1] = tmpval;
617  }
618
619  return numfinallevels;
620}
621
622/****************************************************************************
623 *
624 * Returns an array of grib indices that correspond to particular grib fields
625 * to use as sea level pressure.  There will be exactly one element for each
626 * input time.  If a field was not found, then this function returns NULL
627 *
628 * Interface:
629 *    Input:
630 *      gribinfo - pointer to a previously allocated gribinfo structure.  The
631 *                 gribinfo structure is filled in this function.
632 *         dates: a string array of dates to check for data.
633 *                format: yymmddhh
634 *                If called from a fortran routine, the fortran routine must
635 *                set the character size of the array to be STRINGSIZE-1
636 *         centuries: an array holding the centuries for each of the
637 *                dates in the array dates.
638 *         usParm_id: an array of parameter identifiers that could be
639 *                    used as a sea level pressure field (From table 2 of
640 *                    grib documentation)
641 *         usLevel_id: the level id that could be used as a sea level pressure
642 *                    field (from table 3 of the grib documentation)
643 *         usHeight1: the height for the particular parameter and level
644 *                    (in units described by the parameter index)
645 *         numparms:  the number of parameters in each of the usParm_id,
646 *                    usLevel_id, and usHeight1 arrays.
647 *    Output:
648 *         grib_index: an array of grib indices to use for the sea level
649 *                    pressure.  The index to grib_index corresponds to
650 *                    the time, i.e., the first array element of grib_index
651 *                    corresponds to the first time, the second element to
652 *                    the second time, etc.
653 *         
654 *            Note: Values in the input arrays, usParm_id, usLevel_id, and
655 *                    usHeight with the same array index must correspond.
656 *
657 *    Return:
658 *          1 for success
659 *          -1 if no field was found.
660 ***************************************************************************/
661
662int rg_get_msl_indices(GribInfo *gribinfo, char dates[][STRINGSIZE],
663                    int centuries[], int usParm_id[],int usLevel_id[],
664                    int usHeight1[],int infactor[],int numparms,
665                    int grib_index[],int outfactor[])
666{
667  int parmindex;
668  int datenum = 0;
669  int gribnum;
670  int foundfield=0;
671
672  for (parmindex = 0; parmindex < numparms; parmindex++) {
673
674    datenum = 0;
675    while ((strcmp(dates[datenum], "end") != 0 ) && 
676           (strcmp(dates[datenum], "END") != 0 )) {
677
678      for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
679        if (gribinfo->elements[gribnum].date == atoi(dates[datenum])) {
680          if (gribinfo->elements[gribnum].century == centuries[datenum]) {
681            if ((gribinfo->elements[gribnum].usParm_id == 
682                 usParm_id[parmindex]) &&
683                (gribinfo->elements[gribnum].usLevel_id == 
684                 usLevel_id[parmindex]) &&
685                (gribinfo->elements[gribnum].usHeight1 == 
686                 usHeight1[parmindex])) {
687              grib_index[datenum] = gribnum;
688              outfactor[datenum] = infactor[parmindex];
689              foundfield++;
690              break;
691            }
692          }
693        }
694      }
695
696      datenum++;
697
698      /*
699       * Break out of loop and continue on to next parameter if the current
700       * parameter was missing from a date.
701       */
702
703      if (foundfield != datenum) break;
704    }
705
706/*
707 * Break out of the parameter loop once we've found a field available at all
708 * dates
709 */
710    if (foundfield == datenum) {
711      break;
712    }
713
714  }
715
716  if (foundfield == datenum)
717    return 1;
718  else
719    return -1;
720
721}
722
723
724/***************************************************************************
725 *
726 * This function takes an index as input and returns a 2d grib data field
727 *
728 * Interface:
729 *    input:
730 *      gribinfo - pointer to a previously allocated gribinfo structure.  The
731 *                 gribinfo structure is filled in this function.
732 *       index - the index of gribinfo for which data is to be retrieved
733 *       scale - the scale factor to multiply data by, i.e., if -2,
734 *               data will be multiplied by 10^-2.
735 *    output:
736 *       grib_out - the 2 dimensional output grib data
737 *               Warning: This 2d array is setup with i being the vertical
738 *               dimension and j being the horizontal dimension.  This
739 *               is the convention used in mesoscale numerical modeling
740 *               (the MM5 in particular), so it is used here.
741 *    return:
742 *       1 for success
743 *      -1 for failure
744 ***************************************************************************/
745
746int rg_get_grib(GribInfo *gribinfo, int index,int scale,
747             float **grib_out,int *vect_comp_flag, 
748             GRIB_PROJECTION_INFO_DEF *Proj, BDS_HEAD_INPUT *bds_head)
749{
750  char errmsg[ERRSIZE];
751  int nReturn=0;
752  long offset;
753  int Rd_Indexfile=0;
754  BMS_INPUT bms;
755  PDS_INPUT pds;
756  BDS_HEAD_INPUT dummy;
757  grid_desc_sec gds;
758  GRIB_HDR *gh1;
759  int i,j;
760  int expandlon = 0;
761  float *grib_data;
762
763  /* Initialize Variables */
764  errmsg[0] = '\0';
765  offset = 0L;
766  grib_data = (float *)NULL;
767
768  /* Make storage for Grib Header */
769  nReturn = init_gribhdr (&gh1, errmsg);
770  if (nReturn == 1) goto bail_out;
771 
772  /* Seek to the position in the grib data */
773  offset = gribinfo->elements[index].offset;
774  nReturn = grib_fseek(gribinfo->elements[index].fp,&offset,
775                      Rd_Indexfile,gh1,errmsg);
776  if (nReturn != 1) {
777    fprintf(stderr,"Grib_fseek returned error status (%d)\n",nReturn);
778    goto bail_out;
779  }
780  if (errmsg[0] != '\0')
781    { /* NO errors but got a Warning msg from seek */ 
782      fprintf(stderr,"%s: Skip Decoding...\n",errmsg);
783      errmsg[0] = '\0';
784    }
785  if (gh1->msg_length <= 0) {
786    fprintf(stderr,"Error: message returned had bad length (%ld)\n",
787            gh1->msg_length);
788    goto bail_out;
789  }
790  init_dec_struct(&pds, &gds, &bms, &dummy);
791 
792  nReturn = grib_dec((char *)gh1->entire_msg, &pds, &gds, 
793                     bds_head,
794                     &bms, &grib_data, errmsg);
795 
796  if (nReturn != 0) goto bail_out;
797 
798  if (bms.uslength > 0) {
799    nReturn = apply_bitmap(&bms, &grib_data, FILL_VALUE, bds_head, 
800                           errmsg);
801    if (nReturn != 0) goto bail_out;
802  }
803 
804  switch(gds.head.usData_type) {
805  case 0:
806  case 4:
807    strcpy(Proj->prjnmm,"latlon");
808    Proj->colcnt = gds.llg.usNi;
809    Proj->rowcnt = gds.llg.usNj;
810    Proj->origlat = gds.llg.lLat1/1000.;
811    Proj->origlon = gds.llg.lLon1/1000.;
812    Proj->xintdis = (gds.llg.iDi/1000.)*EARTH_RADIUS*PI_OVER_180;
813    Proj->yintdis = (gds.llg.iDj/1000.)*EARTH_RADIUS*PI_OVER_180;
814    Proj->parm1 = 0.;
815    Proj->parm2 = 0.;
816    if ((gds.llg.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
817    else *vect_comp_flag = 0;
818
819    /* If the grid is a global grid, we want to set the expandlon flag
820     * so that the number of columns in the array is expanded by one and
821     * the first column of data is copied to the last column.  This
822     * allows calling routines to interpolate between first and last columns
823     * of data.
824     */
825
826    if (gds.llg.usNi*gds.llg.iDi/1000. == 360)
827      expandlon = 1;
828    else
829      expandlon = 0;
830     
831    break;
832  case 1: 
833    strcpy(Proj->prjnmm,"mercator");
834    Proj->colcnt = gds.merc.cols;
835    Proj->rowcnt = gds.merc.rows;
836    Proj->origlat = gds.merc.first_lat/1000.;
837    Proj->origlon = gds.merc.first_lon/1000.;
838    Proj->xintdis = gds.merc.lon_inc/1000.;
839    Proj->yintdis = gds.merc.lat_inc/1000.;
840    Proj->parm1 = gds.merc.latin/1000.;
841    Proj->parm2 = (gds.merc.Lo2/1000. - Proj->origlon)/gds.merc.cols;
842    if ((gds.merc.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
843    else *vect_comp_flag = 0;
844    break;
845  case 3:
846    strcpy(Proj->prjnmm,"lambert");
847    Proj->colcnt = gds.lam.iNx;
848    Proj->rowcnt = gds.lam.iNy;
849    Proj->origlat = gds.lam.lLat1/1000.;
850    Proj->origlon = gds.lam.lLon1/1000.;
851    Proj->xintdis = gds.lam.ulDx/1000.;
852    Proj->yintdis = gds.lam.ulDy/1000.;
853    Proj->parm1 = gds.lam.lLat_cut1/1000.;
854    Proj->parm2 = gds.lam.lLat_cut2/1000.;
855    Proj->parm3 = gds.lam.lLon_orient/1000.;
856    if ((gds.lam.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
857    else *vect_comp_flag = 0;
858    break;
859  case 5:
860    strcpy(Proj->prjnmm,"polar_stereo");
861    Proj->colcnt = gds.pol.usNx;
862    Proj->rowcnt = gds.pol.usNy;
863    Proj->origlat = gds.pol.lLat1/1000.;
864    Proj->origlon = gds.pol.lLon1/1000.;
865    Proj->xintdis = gds.pol.ulDx/1000.;
866    Proj->yintdis = gds.pol.ulDy/1000.;
867    Proj->parm1 = 60.;
868    Proj->parm2 = gds.pol.lLon_orient/1000.;   
869    if ((gds.pol.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
870    else *vect_comp_flag = 0;
871    break;
872  default:
873    fprintf(stderr,"Grid not supported, gds.head.usData_type = %d\n",
874            gds.head.usData_type);
875    fprintf(stderr,"Exiting\n");
876    exit(-1);
877    break;
878  } 
879
880  strcpy(Proj->stordsc,"+y_in_+x");
881  Proj->origx = 1;
882  Proj->origy = 1;
883
884  for (j=0; j< (Proj->rowcnt); j++) {
885    for (i=0; i<(Proj->colcnt); i++) {
886      grib_out[j][i] = grib_data[i+j*Proj->colcnt]*pow(10,scale);
887    }
888  }
889
890  if (expandlon) {
891    (Proj->colcnt)++;
892    for (j = 0; j < Proj->rowcnt; j++) {
893      grib_out[j][Proj->colcnt-1] = grib_out[j][0];
894    }
895  }
896
897  /*
898   * You only reach here when there is no error, so return successfully.
899   */
900     
901  nReturn = 0;
902
903  if (grib_data != NULL) {
904    free_gribhdr(&gh1);
905    free(grib_data);
906  } 
907
908  return 1;
909     
910  /* The error condition */
911 bail_out:
912  if (errmsg[0] != '\0') fprintf(stderr,"\n***ERROR: %s %s\n",
913                                 "get_grib",errmsg);
914  if (grib_data != NULL)
915    free(grib_data);
916  free_gribhdr(&gh1);
917  return -1;
918}
919
920/***************************************************************************
921 *
922 * This function takes an index as input and returns a 2d grib data field
923 *
924 * Interface:
925 *    input:
926 *      gribinfo - pointer to a previously allocated gribinfo structure.  The
927 *                 gribinfo structure is filled in this function.
928 *       index - the index of gribinfo for which data is to be retrieved
929 *    output:
930 *       data - the 2 dimensional output grib data
931 *               Warning: This 2d array is setup with i being the vertical
932 *               dimension and j being the horizontal dimension.  This
933 *               is the convention used in mesoscale numerical modeling
934 *               (the MM5 in particular), so it is used here.
935 *    return:
936 *       1 for success
937 *      -1 for failure
938 ***************************************************************************/
939
940int rg_get_data(GribInfo *gribinfo, int index, float **data)
941{
942  float *data_1d;
943  int i,j;
944  int numrows,numcols;
945  int status;
946
947  numrows = rg_get_numrows(gribinfo,index);
948  numcols = rg_get_numcols(gribinfo,index);
949 
950  data_1d = (float *)calloc(numrows*numcols,sizeof(float));
951  if (data_1d == 0)
952    {
953      fprintf(stderr,"Allocating space for data_1d failed, index: %d\n",index);
954      return -1;
955    }
956
957  status = rg_get_data_1d(gribinfo, index, data_1d);
958  if (status != 1)
959    {
960      return status;
961    }
962
963  for (j=0; j< numrows; j++) {
964    for (i=0; i < numcols; i++) {
965      data[j][i] = data_1d[i+j*numcols];
966    }
967  }
968
969  free(data_1d);
970
971  return 1;
972 
973}
974
975/***************************************************************************
976 *
977 * This function takes an index as input and returns a 1d grib data field
978 *
979 * Interface:
980 *    input:
981 *      gribinfo - pointer to a previously allocated gribinfo structure.  The
982 *                 gribinfo structure is filled in this function.
983 *       index - the index of gribinfo for which data is to be retrieved
984 *    output:
985 *       data - 1 dimensional output grib data
986 *               Warning: This 2d array is setup with i being the vertical
987 *               dimension and j being the horizontal dimension.  This
988 *               is the convention used in mesoscale numerical modeling
989 *               (the MM5 in particular), so it is used here.
990 *    return:
991 *       1 for success
992 *      -1 for failure
993 ***************************************************************************/
994
995int rg_get_data_1d(GribInfo *gribinfo, int index, float *data)
996{
997  char errmsg[ERRSIZE];
998  int nReturn=0;
999  long offset;
1000  int Rd_Indexfile=0;
1001  BMS_INPUT bms;
1002  PDS_INPUT pds;
1003  BDS_HEAD_INPUT bds_head;
1004  grid_desc_sec gds;
1005  GRIB_HDR *gh1;
1006  int i,j;
1007  int numcols, numrows;
1008  float *grib_data;
1009
1010  /* Initialize Variables */
1011  errmsg[0] = '\0';
1012  offset = 0L;
1013  grib_data = (float *)NULL;
1014
1015  /* Make storage for Grib Header */
1016  nReturn = init_gribhdr (&gh1, errmsg);
1017  if (nReturn == 1) goto bail_out;
1018 
1019  /* Seek to the position in the grib data */
1020  offset = gribinfo->elements[index].offset;
1021  nReturn = grib_fseek(gribinfo->elements[index].fp,&offset,
1022                      Rd_Indexfile,gh1,errmsg);
1023  if (nReturn != 0) {
1024    fprintf(stderr,"Grib_fseek returned non-zero status (%d)\n",nReturn);
1025    goto bail_out;
1026  }
1027  if (errmsg[0] != '\0')
1028    { /* NO errors but got a Warning msg from seek */ 
1029      fprintf(stderr,"%s: Skip Decoding...\n",errmsg);
1030      errmsg[0] = '\0';
1031    }
1032  if (gh1->msg_length <= 0) {
1033    fprintf(stderr,"Error: message returned had bad length (%ld)\n",
1034            gh1->msg_length);
1035    goto bail_out;
1036  }
1037
1038  init_dec_struct(&pds, &gds, &bms, &bds_head);
1039 
1040  nReturn = grib_dec((char *)gh1->entire_msg, &pds, &gds, 
1041                     &bds_head,
1042                     &bms, &grib_data, errmsg);
1043 
1044  if (nReturn != 0) goto bail_out;
1045 
1046  if (bms.uslength > 0) {
1047    nReturn = apply_bitmap(&bms, &grib_data, FILL_VALUE, &bds_head, 
1048                           errmsg);
1049    if (nReturn != 0) goto bail_out;
1050  }
1051 
1052  /*
1053   * Copy the data into the permanent array
1054   */ 
1055  numcols = rg_get_numcols(gribinfo,index);
1056  numrows = rg_get_numrows(gribinfo,index);
1057  memcpy(data,grib_data,numcols*numrows*sizeof(float));
1058
1059  /*
1060   * You only reach here when there is no error, so return successfully.
1061   */
1062     
1063  nReturn = 0;
1064
1065  if (grib_data != NULL) {
1066    free_gribhdr(&gh1);
1067    free(grib_data);
1068  } 
1069
1070  return 1;
1071     
1072  /* The error condition */
1073 bail_out:
1074  if (errmsg[0] != '\0') fprintf(stderr,"\n***ERROR: %s %s\n",
1075                                 "get_grib",errmsg);
1076  if (grib_data != NULL)
1077    free(grib_data);
1078  free_gribhdr(&gh1);
1079  return -1;
1080}
1081
1082/****************************************************************************
1083 * Returns the index of gribinfo corresponding to the input date, level,
1084 * height, and parameter.
1085 *
1086 * Interface:
1087 *   Input:
1088 *      gribinfo  - pointer to a previously populated gribinfo structure. 
1089 *      initdate  -  initialization date in the form yyyymmdd[HHMMSS].  If any
1090 *                  part of HHMMSS is not specified, it will be set to 0.
1091 *      parmid    - the parameter id in the grib file
1092 *      leveltype - the leveltype id from table 3/3a of the grib document.
1093 *      level1    - First level of the data in units described by leveltype.
1094 *      level2    - Second level of the data in units described by leveltype.
1095 *      fcsttime1 - First forecast time in seconds.
1096 *      fcsttime2 - Second forecast time in seconds.
1097 *    Note: If an input variable is set set to -INT_MAX, then any value
1098 *                will be considered a match.
1099 *    Return:
1100 *       if >= 0    The index of the gribinfo data that corresponds to the
1101 *                  input parameters
1102 *       if < 0     No field corresponding to the input parms was found.
1103 *
1104 ***************************************************************************/
1105
1106int rg_get_index(GribInfo *gribinfo, FindGrib *findgrib)
1107{
1108  int gribnum;
1109  int grib_index=-1;
1110
1111  for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
1112    if (compare_record(gribinfo, findgrib, gribnum) == 1)
1113      {
1114        grib_index = gribnum;
1115        break;
1116      }
1117  }
1118  return grib_index;
1119}
1120
1121
1122/****************************************************************************
1123 * Same as rg_get_index, except that a guess for the record number is given.
1124 *   This "guess" record is first checked to see if it matches, if so,
1125 *      that grib record number is just returned.  If it does not match,
1126 *      full searching ensues.
1127 * Returns the index of gribinfo corresponding to the input date, level,
1128 * height, and parameter.
1129 *
1130 * Interface:
1131 *   Input:
1132 *      Same is rg_get_index, except:
1133 *      guess_index  - The index to check first.
1134 *    Return:
1135 *      Same as rg_get_index
1136 *
1137 ***************************************************************************/
1138
1139int rg_get_index_guess(GribInfo *gribinfo, FindGrib *findgrib, int guess_index)
1140{
1141  int retval;
1142
1143  if (compare_record(gribinfo, findgrib, guess_index) == 1) {
1144    retval = guess_index;
1145  } else {
1146    retval = rg_get_index(gribinfo, findgrib);
1147  }
1148
1149  return retval;
1150}
1151
1152
1153/****************************************************************************
1154 * Sets all values in FindGrib to missing.
1155 *
1156 * Interface:
1157 *   Input:
1158 *      findgrib  - pointer to a previously allocated findgrib structure.
1159 *
1160 *    Return:
1161 *       1  for success.
1162 *       -1 for failure.
1163 *
1164 ***************************************************************************/
1165int rg_init_findgrib(FindGrib *findgrib)
1166{
1167  strcpy(findgrib->initdate,"*");
1168  strcpy(findgrib->validdate,"*");
1169  findgrib->parmid          = -INT_MAX;
1170  findgrib->parmid          = -INT_MAX;
1171  findgrib->leveltype       = -INT_MAX;
1172  findgrib->level1          = -INT_MAX;
1173  findgrib->level2          = -INT_MAX;
1174  findgrib->fcsttime1       = -INT_MAX;
1175  findgrib->fcsttime2       = -INT_MAX;
1176  findgrib->center_id       = -INT_MAX;
1177  findgrib->subcenter_id    = -INT_MAX;
1178  findgrib->parmtbl_version = -INT_MAX;
1179 
1180  return 1;
1181}
1182
1183/****************************************************************************
1184 * Returns the indices of all gribinfo entries that match the input date,
1185 * level, height, and parameter.
1186 *
1187 * Interface:
1188 *   Input:
1189 *      gribinfo  - pointer to a previously populated gribinfo structure. 
1190 *      initdate  -  initialization date in the form yyyymmdd[HHMMSS].  If any
1191 *                  part of HHMMSS is not specified, it will be set to 0.
1192 *      parmid    - the parameter id in the grib file
1193 *      leveltype - the leveltype id from table 3/3a of the grib document.
1194 *      level1    - First level of the data in units described by leveltype.
1195 *      level2    - Second level of the data in units described by leveltype.
1196 *      fcsttime1 - First forecast time in seconds.
1197 *      fcsttime2 - Second forecast time in seconds.
1198 *      indices   - an array of indices that match
1199 *      num_indices - the number of matches and output indices
1200 *
1201 *    Note: If an input variable is set set to -INT_MAX, then any value
1202 *                will be considered a match.
1203 *    Return:
1204 *          The number of matching indices.
1205 *
1206 ***************************************************************************/
1207
1208int rg_get_indices(GribInfo *gribinfo, FindGrib *findgrib, int indices[])
1209{
1210  int gribnum;
1211  int matchnum = 0;
1212
1213  for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
1214    if (compare_record(gribinfo, findgrib, gribnum) == 1) {
1215      indices[matchnum] = gribnum;
1216      matchnum++;
1217    }   
1218  }
1219  return matchnum;
1220}
1221
1222/*************************************************************************
1223 *
1224 * Returns an array of dates that correspond to particular input grib fields.
1225 * The dates will be sorted so that the dates increase as the index increases.
1226 *
1227 * Interface:
1228 *    Input:
1229 *         gribinfo - pointer to a previously allocated gribinfo structure. 
1230 *                    The gribinfo structure is filled in this function.
1231 *         usParm_id: an array of parameter identifiers that could be
1232 *                    used as a sea level pressure field (From table 2 of
1233 *                    grib documentation)
1234 *         usLevel_id: the level id that could be used as a sea level pressure
1235 *                    field (from table 3 of the grib documentation)
1236 *         usHeight1: the height for the particular parameter and level
1237 *                    (in units described by the parameter index)
1238 *         numparms:  the number of parameters in each of the usParm_id,
1239 *                    usLevel_id, and usHeight1 arrays.
1240 *    Output:
1241 *         dates:     the dates for which the input fields are available.
1242 *         
1243 *            Note: Values in the input arrays, usParm_id, usLevel_id, and
1244 *                    usHeight with the same array index must correspond.
1245 *
1246 *    Return:
1247 *          The number of dates found.
1248 *************************************************************************/
1249
1250int rg_get_dates(GribInfo *gribinfo,int usParm_id[],int usLevel_id[],
1251              int usHeight1[],int numparms,int dates[],int century[],
1252              int indices[])
1253{
1254  int datenum=0;
1255  int gribnum;
1256  int parmindex;
1257  int already_included;
1258  int i,j;
1259  int tmpval,tmpval2,tmpval3;
1260
1261  /* Get the dates for the given parameters */
1262
1263  for (parmindex = 0; parmindex < numparms; parmindex++) {
1264    for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
1265      if ((gribinfo->elements[gribnum].usParm_id == usParm_id[parmindex]) &&
1266          (gribinfo->elements[gribnum].usLevel_id == usLevel_id[parmindex]) &&
1267          (gribinfo->elements[gribnum].usHeight1 == usHeight1[parmindex])) {
1268        already_included = 0;
1269        for (i = 0; i < datenum; i++){
1270          if ((dates[datenum] == gribinfo->elements[gribnum].date) && 
1271              (century[datenum] == gribinfo->elements[gribnum].century)) {
1272            already_included = 1;
1273            break;
1274          }
1275        }
1276        if (!already_included) {
1277          dates[datenum] = gribinfo->elements[gribnum].date;
1278          century[datenum] = gribinfo->elements[gribnum].century;
1279          indices[datenum] = gribnum;
1280          datenum++;
1281        }
1282      }
1283    }
1284  }
1285
1286  /* Sort the dates into increasing order */
1287  for (j = 1; j < datenum; j++) {
1288    tmpval = dates[j];
1289    tmpval2 = indices[j];
1290    tmpval3 = century[j];
1291    for (i=j-1; i >= 0; i--) {
1292      if (dates[i] <= tmpval) break;
1293      dates[i+1] = dates[i];
1294      indices[i+1] = indices[i];
1295      century[i+1] = century[i];
1296    }
1297    dates[i+1] = tmpval;
1298    indices[i+1] = tmpval2;
1299    century[i+1] = tmpval3;
1300  }
1301
1302  return datenum;
1303}
1304
1305/****************************************************************************
1306 * This function returns the pds, gds, bms, and bms_head section of the
1307 * grib element
1308 *
1309 * Input:
1310 *   gribinfo - pointer to a previously allocated gribinfo structure.  The
1311 *              gribinfo structure is filled in this function.
1312 *   index - the index of the grib record to access as indexed by
1313 *           setup_gribinfo
1314 *   
1315 * Output:
1316 *   *pds - a pointer to a structure holding the pds information
1317 *   *gds - a pointer to a structure holding the gds information
1318 *   *bms - a pointer to a structure holding the bms information
1319 *   *bds_head - a pointer to a structure holding the binary data section
1320 *             header information
1321 *
1322 ***************************************************************************
1323 */
1324int rg_get_grib_header(GribInfo *gribinfo, int index, PDS_INPUT *pds, 
1325                    grid_desc_sec *gds,BMS_INPUT *bms)
1326{
1327  int xsize,ysize,j;
1328 
1329  memcpy(pds,gribinfo->elements[index].pds,sizeof(PDS_INPUT));
1330  memcpy(gds,gribinfo->elements[index].gds,sizeof(grid_desc_sec));
1331  memcpy(bms,gribinfo->elements[index].bms,sizeof(BMS_INPUT));
1332 
1333  /* Reset the dimensions for thinned grids */
1334  if (gribinfo->elements[index].gds->head.thin != NULL) {
1335    if (gds->head.thin != NULL) {
1336      if ((gds->head.usData_type == LATLON_PRJ) || 
1337          (gds->head.usData_type == GAUSS_PRJ) ||
1338          (gds->head.usData_type == ROT_LATLON_PRJ) ||
1339          (gds->head.usData_type == ROT_GAUSS_PRJ) ||
1340          (gds->head.usData_type == STR_LATLON_PRJ) ||
1341          (gds->head.usData_type == STR_GAUSS_PRJ) ||
1342          (gds->head.usData_type == STR_ROT_LATLON_PRJ) ||
1343          (gds->head.usData_type == STR_ROT_GAUSS_PRJ)) {
1344        ysize = gds->llg.usNj;
1345      } else if (gds->head.usData_type == MERC_PRJ) {
1346        ysize = gds->merc.rows;
1347      } else if (gds->head.usData_type == POLAR_PRJ) {
1348        ysize = gds->pol.usNy;
1349      } else if ((gds->head.usData_type == LAMB_PRJ) ||
1350                 (gds->head.usData_type == ALBERS_PRJ) ||
1351                 (gds->head.usData_type == OBLIQ_LAMB_PRJ)) {
1352        ysize = gds->lam.iNy;
1353      }
1354
1355      xsize = 0;
1356      for (j = 0; j<ysize; j++) {
1357        if (gds->head.thin[j] > xsize) {
1358          xsize = gds->head.thin[j];
1359        }
1360      }
1361     
1362
1363      if ((gds->head.usData_type == LATLON_PRJ) || 
1364          (gds->head.usData_type == GAUSS_PRJ) ||
1365          (gds->head.usData_type == ROT_LATLON_PRJ) ||
1366          (gds->head.usData_type == ROT_GAUSS_PRJ) ||
1367          (gds->head.usData_type == STR_LATLON_PRJ) ||
1368          (gds->head.usData_type == STR_GAUSS_PRJ) ||
1369          (gds->head.usData_type == STR_ROT_LATLON_PRJ) ||
1370          (gds->head.usData_type == STR_ROT_GAUSS_PRJ)) {
1371        gds->llg.usNi = xsize;
1372        gds->llg.iDi = abs(gds->llg.lLat2 - gds->llg.lLat1)/(xsize-1);
1373      } else if (gds->head.usData_type == MERC_PRJ) {
1374        gds->merc.cols = xsize;
1375      } else if (gds->head.usData_type == POLAR_PRJ) {
1376        gds->pol.usNx = xsize;
1377      } else if ((gds->head.usData_type == LAMB_PRJ) ||
1378                 (gds->head.usData_type == ALBERS_PRJ) ||
1379                 (gds->head.usData_type == OBLIQ_LAMB_PRJ)) {
1380        gds->lam.iNx = xsize;
1381      }
1382     
1383    }
1384  }
1385  return 1;
1386}
1387
1388/****************************************************************************
1389 * This returns the index of the gribdata for paramaters which match the input
1390 * parameters and for the date closest to the input targetdate.  If dates are
1391 * not found either within hours_before or hours_after the time, then a missing
1392 * value is returned.
1393 *
1394 * Interface:
1395 *   Input:
1396 *     gribinfo - pointer to a previously allocated gribinfo structure.  The
1397 *                  gribinfo structure is filled in this function.
1398 *     targetdate:  This is the date which dates in the grib data will be
1399 *                  compared to.  (format: integer yymmddhh)
1400 *     hours_before: The maximum difference in time prior to the targetdate
1401 *                  for which data should be searched for.
1402 *     hours_after: The maximum difference in time after the targetdate for
1403 *                  which data should be searched for.
1404 *     usParm_id:   an array of parameter identifiers that could be
1405 *                  used as a sea level pressure field (From table 2 of
1406 *                  grib documentation)
1407 *     usLevel_id:  the level id that could be used as a sea level pressure
1408 *                  field (from table 3 of the grib documentation)
1409 *     usHeight1:   the height for the particular parameter and level
1410 *                  (in units described by the parameter index)
1411 *     numparms:    the number of parameters in each of the usParm_id,
1412 *                  usLevel_id, and usHeight1 arrays.
1413 *   Return:
1414 *     the index of the gribdata with a time closest to the target date.
1415 *     -1 if there is no time within the input time limits.
1416 *
1417 ****************************************************************************/
1418int rg_get_index_near_date(GribInfo *gribinfo,char targetdate[STRINGSIZE],
1419                        int century,int hours_before,int hours_after,
1420                        int usParm_id[],int usLevel_id[],int usHeight1[],
1421                        int numparms)
1422{
1423  int dates[500],indices[500],centuries[500];
1424  int date_before = MISSING;
1425  int date_after = MISSING;
1426  int century_before,century_after;
1427  int date_diff_before = MISSING;
1428  int date_diff_after = MISSING;
1429  int index_before,index_after;
1430  int numdates,datenum;
1431  int index;
1432  int itargetdate;
1433
1434  itargetdate = atoi(targetdate);
1435
1436  numdates = rg_get_dates(gribinfo,usParm_id,usLevel_id,usHeight1,numparms,
1437                          dates,centuries,indices);
1438  if (numdates <= 0) {
1439    fprintf(stderr,"get_index_near_date: No dates were found\n");
1440    return -1;
1441  }
1442 
1443  for (datenum = 0; datenum < numdates; datenum++) {
1444    if ((dates[datenum] > itargetdate) && (centuries[datenum] >= century)) {
1445      century_after = centuries[datenum];
1446      date_after = dates[datenum];
1447      index_after = indices[datenum];
1448      break;
1449    } else {
1450      century_before = centuries[datenum];
1451      date_before = dates[datenum];
1452      index_before = indices[datenum];
1453    }
1454  }
1455 
1456  if (date_after != MISSING)
1457    date_diff_after = date_diff(date_after,century_after,itargetdate,century);
1458  if (date_before != MISSING)
1459    date_diff_before = 
1460      date_diff(itargetdate,century,date_before,century_before);
1461
1462  if ((date_after != MISSING) && (date_before != MISSING)) {
1463    if ((date_diff_after <= hours_after) && 
1464        (date_diff_before <= hours_before)) {
1465      if (date_diff_after < date_diff_before)
1466        index = index_before;
1467      else
1468        index = index_after;
1469    } else if (date_diff_after <= hours_after) {
1470        index = index_after;
1471    } else if (date_diff_before <= hours_before) {
1472        index = index_before;
1473    } else {
1474      index = -1;
1475    }
1476  } else if (date_after != MISSING) {
1477    if (date_diff_after <= hours_after)
1478      index = index_after;
1479    else 
1480      index = -1;
1481  } else if (date_before != MISSING) {
1482    if (date_diff_before <= hours_before)
1483      index = index_before;
1484    else
1485      index = -1;
1486  } else {
1487    index = -1;
1488  }
1489
1490  return index;
1491 
1492}
1493
1494/*****************************************************************************
1495 *
1496 * returns valid time ( = init time + forecast time)
1497 *
1498 * Input:
1499 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
1500 *                 gribinfo structure is filled in this function.
1501 *    index    - index number of record to get valid time from
1502 *
1503 * Output:
1504 *    valid_time - yyyymmddhhmmss
1505 *
1506 * Return:
1507 *    0 for success
1508 *   -1 for error
1509 *   
1510 *****************************************************************************/
1511int rg_get_valid_time(GribInfo *gribinfo, int index, char valid_time[])
1512{
1513  strcpy(valid_time, gribinfo->elements[index].valid_time);
1514  return 0;
1515}
1516
1517/*****************************************************************************
1518 *
1519 * returns generating center id
1520 *
1521 * Input:
1522 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
1523 *                 gribinfo structure is filled in this function.
1524 *    index    - index number of record to get valid time from
1525 *
1526 * Return:
1527 *    generating center id
1528 *   -1 for error
1529 *   
1530 *****************************************************************************/
1531int rg_get_center_id(GribInfo *gribinfo, int index)
1532{
1533  return gribinfo->elements[index].center_id;
1534}
1535
1536/*****************************************************************************
1537 *
1538 * returns parameter table version number
1539 *
1540 * Input:
1541 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
1542 *                 gribinfo structure is filled in this function.
1543 *    index    - index number of record to get valid time from
1544 *
1545 * Return:
1546 *    parameter table version number
1547 *   -1 for error
1548 *   
1549 *****************************************************************************/
1550int rg_get_parmtbl(GribInfo *gribinfo, int index)
1551{
1552  return gribinfo->elements[index].parmtbl;
1553}
1554
1555/*****************************************************************************
1556 *
1557 * returns generating process id
1558 *
1559 * Input:
1560 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
1561 *                 gribinfo structure is filled in this function.
1562 *    index    - index number of record to get valid time from
1563 *
1564 * Return:
1565 *    generating process id
1566 *   -1 for error
1567 *   
1568 *****************************************************************************/
1569int rg_get_proc_id(GribInfo *gribinfo, int index)
1570{
1571  return gribinfo->elements[index].proc_id;
1572}
1573
1574/*****************************************************************************
1575 *
1576 * returns sub center id
1577 *
1578 * Input:
1579 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
1580 *                 gribinfo structure is filled in this function.
1581 *    index    - index number of record to get valid time from
1582 *
1583 * Return:
1584 *    sub center id
1585 *   -1 for error
1586 *   
1587 *****************************************************************************/
1588int rg_get_subcenter_id(GribInfo *gribinfo, int index)
1589{
1590  return gribinfo->elements[index].subcenter_id;
1591}
1592
1593/**************************************************************************
1594 *
1595 * Interpolates grib grid data to a point location.
1596 *
1597 * Interface:
1598 *     input:
1599 *       gribinfo - pointer to a previously allocated gribinfo structure.  The
1600 *                  gribinfo structure is filled in this function.
1601 *       index    - the index of gribinfo for which data is to be retrieved.
1602 *                  the first grib record is number 1.
1603 *       column   - the column of the point in grid coordinates (can be
1604 *                  floating point number).  leftmost column is 1.
1605 *       row      - the row of the point in grid coordinates (can be
1606 *                  floating point number).  bottommost row is 1.
1607 *
1608 *    return:
1609 *       on success - the interpolated value at the column,row location.
1610 *       on failure - -99999
1611 *
1612 ***************************************************************************/
1613
1614float rg_get_point(GribInfo *gribinfo, int index, float column, float row)
1615{
1616  int status;
1617  GRIB_PROJECTION_INFO_DEF Proj;
1618  BDS_HEAD_INPUT bds_head;
1619  int dummy;
1620  float **grib_out;
1621  float y1, y2;
1622  int numrows, numcols;
1623  int top, left, right, bottom;
1624  float outval;
1625 
1626  numrows = rg_get_numrows(gribinfo, index);
1627  numcols = rg_get_numcols(gribinfo, index);
1628
1629  grib_out = (float **)alloc_float_2d(numrows,numcols);
1630  if (grib_out == NULL) {
1631    fprintf(stderr,"rg_get_point: Could not allocate space for grib_out\n");
1632    return -99999;
1633  }
1634
1635  status = rg_get_data(gribinfo, index, grib_out);
1636  if (status < 0) {
1637    fprintf(stderr,"rg_get_point: rg_get_data failed\n");
1638    return -99999;
1639  }
1640
1641  /* Do the interpolation here */
1642  bottom = floor(row);
1643  top = floor(row+1);
1644  left = floor(column);
1645  right = floor(column+1);
1646 
1647  y1 = (row - bottom) * (grib_out[top][left] - grib_out[bottom][left]) + 
1648    grib_out[bottom][left];
1649  y2 = (row - bottom) * (grib_out[top][right] - grib_out[bottom][right]) + 
1650    grib_out[bottom][right];
1651  outval = (y2 - y1) * (column - left) + y1;
1652
1653  free_float_2d(grib_out,numrows,numcols);
1654
1655  return outval;
1656 
1657}
1658
1659/**************************************************************************
1660 *
1661 * Interpolates grib grid data to a point location.
1662 *
1663 * Interface:
1664 *     input:
1665 *       gribinfo - pointer to a previously allocated gribinfo structure.  The
1666 *                  gribinfo structure is filled in this function.
1667 *       index    - the index of gribinfo for which data is to be retrieved.
1668 *                  the first grib record is number 1.
1669 *     input and output:
1670 *       pointdata- array of pointdata structures.  Only the column and
1671 *                  row values in the structures need to be filled.  On
1672 *                  output, the 'value' member of pointdata is filled.
1673 *     input:
1674 *       numpoints- number of pointdata structures in the array.
1675 *
1676 *    return:
1677 *       on success - the interpolated value at the column,row location.
1678 *       on failure - -99999
1679 *
1680 ***************************************************************************/
1681int rg_get_points(GribInfo *gribinfo, int index, PointData pointdata[], 
1682                   int numpoints)
1683{
1684  int status;
1685  float **grib_out;
1686  float y1, y2;
1687  int numrows, numcols;
1688  int top, left, right, bottom;
1689  float column, row;
1690  int idx;
1691
1692  numrows = rg_get_numrows(gribinfo, index);
1693  numcols = rg_get_numcols(gribinfo, index);
1694
1695  grib_out = (float **)alloc_float_2d(numrows,numcols);
1696  if (grib_out == NULL) {
1697    fprintf(stderr,"rg_get_points: Could not allocate space for grib_out\n");
1698    return -99999;
1699  }
1700
1701  status = rg_get_data(gribinfo, index, grib_out);
1702  if (status < 0) {
1703    fprintf(stderr,"rg_get_points: rg_get_data failed\n");
1704    return -99999;
1705  }
1706
1707  for (idx = 0; idx < numpoints; idx++) {
1708
1709    /* Change from 1 based to 0 based col/row */
1710    row = pointdata[idx].row;
1711    column = pointdata[idx].column;
1712   
1713    /* Do the interpolation here */
1714    bottom = floor(row);
1715    top = floor(row+1);
1716    left = floor(column);
1717    right = floor(column+1);
1718   
1719    y1 = (row - bottom) * (grib_out[top][left] - grib_out[bottom][left]) + 
1720      grib_out[bottom][left];
1721    y2 = (row - bottom) * (grib_out[top][right] - grib_out[bottom][right]) + 
1722      grib_out[bottom][right];
1723    pointdata[idx].value = (y2 - y1) * (column - left) + y1;
1724
1725  }
1726
1727  free_float_2d(grib_out,numrows,numcols);
1728
1729  return 1;
1730}
1731
1732/**************************************************************************
1733 *
1734 * Remove an element from an array and decrease, by one, indices of all
1735 * elements with an index greater than the index of the element to remove.
1736 *
1737 * Interface:
1738 *     input:
1739 *        array - the integer array to manipulate
1740 *        index - the index of the element to remove
1741 *        size - the number of elements in the array
1742 *
1743 ***************************************************************************/
1744void remove_element(int array[],int index, int size)
1745{
1746  int j;
1747 
1748  for (j = index; j < size-1; j++) {
1749    array[j] = array[j+1];
1750  }
1751
1752}
1753
1754/****************************************************************************
1755 * Advance the time by the input amount
1756 *
1757 * Interface:
1758 *     Input:
1759 *         century - an integer value for the century (20 for 1900's)
1760 *                   If the century is advanced, this value is advanced
1761 *                   and output to the calling routine.
1762 *         year - a 2 digit value for the year.
1763 *         month - a 2 digit value for the month.
1764 *         day - the day of the month
1765 *         hour - the hour of the day
1766 *         amount - the amount to advance the time by.
1767 *         unit - the units for the amount.  These are values from table 4
1768 *                of the grib manual.
1769 *    return:
1770 *         a date in the form yymmddhh
1771 ****************************************************************************/
1772
1773int advance_time(int *century, int year, int month, int day, int hour,
1774                 int amount, int unit)
1775{
1776  int daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
1777  int date;
1778
1779  switch(unit) {
1780  case 0:
1781    hour += (int)((amount/60.)+0.5);
1782    break;
1783  case 1:
1784    hour += amount;
1785    break;
1786  case 2:
1787    day += amount;
1788    break;
1789  case 3:
1790    month += amount;
1791    break;
1792  case 4:
1793    year += amount;
1794    break;
1795  case 5:
1796    year += 10*amount;
1797    break;
1798  case 6:
1799    year += 30*amount;
1800    break;
1801  case 7:
1802    year += 100*amount;
1803    break;
1804  case 10:
1805    hour += 3*amount;
1806    break;
1807  case 11:
1808    hour += 6*amount;
1809    break;
1810  case 12:
1811    hour += 12*amount;
1812    break;
1813  case 50:
1814    hour += (int)((amount/12.)+0.5);
1815  case 254:
1816    hour += (int)((amount/(60.*60.))+0.5);
1817    break;
1818  default:
1819    fprintf(stderr,"WARNING: Could not advance time, incorrect unit: %d\n",
1820            unit);
1821    return -1;
1822  }
1823
1824  while (hour >= 24) {
1825    day++;
1826    hour -= 24;
1827  }
1828  while (month > 12) {
1829    year++;
1830    month -= 12;
1831  }
1832
1833  /* if it is a leap year, change days in month for Feb now. */ 
1834  if (isLeapYear(year)) daysinmonth[1] = 29;
1835
1836  while (day > daysinmonth[month-1]) {
1837    day -= daysinmonth[month-1];
1838    month++;
1839    if (month > 12) {
1840      year++;
1841      month -= 12;
1842      if (isLeapYear(year))
1843        daysinmonth[1] = 29;
1844      else
1845        daysinmonth[1] = 28;
1846    }
1847  }
1848
1849  if (year > 100) {
1850    (*century)++;
1851  }
1852
1853  if (year >= 100) {
1854    year -= 100;
1855  }
1856
1857  date = hour*1 + day*100 + month*10000 + year*1000000;
1858
1859  return date;
1860
1861}
1862/****************************************************************************
1863 * Advance the time by the input amount
1864 *
1865 * Interface:
1866 *     Input:
1867 *         startdate  - initialization date in the form yyyymmdd[HHMMSS].  If any
1868 *                        part of HHMMSS is not specified, it will be set to 0.
1869 *         amount     - the amount (in seconds) to advance the time by.
1870 *
1871 *    Output:
1872 *         enddate[] - the time advanced to: yyyymmddHHMMSS format.
1873 *
1874 *    Return:
1875 *          1 - success
1876 *         -1 - failure
1877 *
1878 ****************************************************************************/
1879char *advance_time_str(char startdatein[], int amount, char enddate[])
1880{
1881  struct tm starttp;
1882  struct tm endtp;
1883  char startdate[15];
1884  time_t time;
1885
1886  strcpy(startdate,startdatein);
1887  while (strlen(startdate) < 14) {
1888    strcpy(startdate+(strlen(startdate)),"0");
1889  }
1890
1891  /* This forces all calculations to use GMT time */
1892  putenv("TZ=GMT0");
1893  tzset();
1894
1895  sscanf(startdate,"%4d%2d%2d%2d%2d%2d",&(starttp.tm_year),&(starttp.tm_mon),
1896         &(starttp.tm_mday),&(starttp.tm_hour),&(starttp.tm_min),
1897         &(starttp.tm_sec));
1898  starttp.tm_mon -= 1;
1899  starttp.tm_year -= 1900;
1900  time = mktime(&starttp);
1901  time += amount;
1902  localtime_r(&time, &endtp);
1903  strftime(enddate,15,"%Y%m%d%H%M%S",&endtp);
1904 
1905  return enddate;
1906}
1907
1908/****************************************************************************
1909 * Returns the difference in time in hours between date1 and date2
1910 * (date1-date2).
1911 *
1912 * Interface:
1913 *   Input:
1914 *     date1,date2:  dates in yymmddhh format (integers)
1915 *     century1,century2: centuries for each date (20 for 1900's).
1916 *   Return:
1917 *     the difference in time between the first and second dates in hours.
1918 ****************************************************************************/
1919int date_diff(int date1,int century1,int date2,int century2)
1920{
1921  return (hours_since_1900(date1,century1) - 
1922           hours_since_1900(date2,century2));
1923}
1924
1925/****************************************************************************
1926 * Returns the number of hours since Jan 1, at 00:00 1900.
1927 *
1928 * Interface:
1929 *   Input:
1930 *     date:    integer in form yymmddhh
1931 *     century: 2 digit century (20 for 1900's)
1932 *   Return:
1933 *     the number of hours since 00:00 Jan1, 1900.
1934 *
1935 ****************************************************************************/
1936int hours_since_1900(int date,int century)
1937{
1938  int daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
1939  int hour,day,month,year;
1940  int days_since_1900 = 0;
1941  int i;
1942
1943  hour = date%100;
1944  day = (date%10000)/100;
1945  month = (date%1000000)/10000;
1946  year = (date%100000000)/1000000;
1947
1948  days_since_1900 += day;
1949 
1950  if (isLeapYear((century-1)*100 + year))
1951    daysinmonth[1] = 29;
1952  else 
1953    daysinmonth[1] = 28;
1954 
1955  for (i = 0; i < (month - 1); i++)
1956    days_since_1900 += daysinmonth[i];
1957
1958  for (i=0; i < (year + ((century - 20)*100) - 1); i++) {
1959    if (isLeapYear((century - 1)*100 + year))
1960      days_since_1900 += 366;
1961    else
1962      days_since_1900 += 365;
1963  }
1964
1965  return days_since_1900*24 + hour;
1966
1967}
1968
1969/****************************************************************************
1970 *
1971 * Returns true if the input year is a leap year, otherwise returns false
1972 *
1973 ****************************************************************************/
1974int isLeapYear(int year)
1975{
1976  if ( (((year % 4) == 0) && ((year % 100) != 0)) 
1977       || ((year % 400) == 0) ) 
1978    return 1;
1979  else
1980    return 0;
1981                                                 
1982}
1983
1984/*****************************************************************************
1985 *
1986 * Returns the number of grib elements (gribinfo->num_elements) processsed
1987 * Input:
1988 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
1989 *                 gribinfo structure is filled in this function.
1990 *
1991 * Return:
1992 *   the number of elements in the gribinfo structure
1993 ****************************************************************************/
1994
1995int rg_num_elements(GribInfo *gribinfo){
1996
1997  return gribinfo->num_elements;
1998
1999}
2000
2001/*****************************************************************************
2002 *
2003 * Deallocates the elements in the gribinfo structure and closes the files.
2004 *
2005 * Input:
2006 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
2007 *                 gribinfo structure is filled in this function.
2008 *
2009 *****************************************************************************/
2010void rg_free_gribinfo_elements(GribInfo *gribinfo)
2011{
2012  int i;
2013 
2014  for (i=0; i<gribinfo->num_elements; i++) {
2015    free(gribinfo->elements[i].pds);
2016    free(gribinfo->elements[i].gds);
2017    free(gribinfo->elements[i].bms);
2018    free(gribinfo->elements[i].bds_head);
2019    fclose(gribinfo->elements[i].fp);
2020  }
2021  free(gribinfo->elements);
2022}
2023
2024/*****************************************************************************
2025 *
2026 * Returns the value for level1 (gribinfo->usHeight1)
2027 * Input:
2028 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
2029 *                 gribinfo structure is filled in this function.
2030 *
2031 * Return:
2032 *   value for level1
2033 ****************************************************************************/
2034
2035int rg_get_level1(GribInfo *gribinfo, int index)
2036{
2037  return gribinfo->elements[index].usHeight1;
2038}
2039
2040/*****************************************************************************
2041 *
2042 * Returns the value for level2 (gribinfo->usHeight2)
2043 * Input:
2044 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
2045 *                 gribinfo structure is filled in this function.
2046 *
2047 * Return:
2048 *   value for level1
2049 ****************************************************************************/
2050
2051int rg_get_level2(GribInfo *gribinfo, int index)
2052{
2053  return gribinfo->elements[index].usHeight2;
2054}
2055
2056/*****************************************************************************
2057 *
2058 * returns number of rows in grid
2059 *
2060 * Input:
2061 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
2062 *                 gribinfo structure is filled in this function.
2063 *
2064 * Return:
2065 *    number of rows in grid
2066 *****************************************************************************/
2067int rg_get_numrows(GribInfo *gribinfo,int index)
2068{
2069  if ((gribinfo->elements[index].gds->head.usData_type == LATLON_PRJ) || 
2070      (gribinfo->elements[index].gds->head.usData_type == GAUSS_PRJ) || 
2071      (gribinfo->elements[index].gds->head.usData_type == ROT_LATLON_PRJ) || 
2072      (gribinfo->elements[index].gds->head.usData_type == ROT_GAUSS_PRJ) || 
2073      (gribinfo->elements[index].gds->head.usData_type == STR_LATLON_PRJ) || 
2074      (gribinfo->elements[index].gds->head.usData_type == STR_GAUSS_PRJ) || 
2075      (gribinfo->elements[index].gds->head.usData_type == STR_ROT_LATLON_PRJ)|| 
2076      (gribinfo->elements[index].gds->head.usData_type == STR_ROT_GAUSS_PRJ)) 
2077    {
2078    return gribinfo->elements[index].gds->llg.usNj;
2079  } else if (gribinfo->elements[index].gds->head.usData_type == MERC_PRJ) {
2080    return gribinfo->elements[index].gds->merc.rows;
2081  } else if (gribinfo->elements[index].gds->head.usData_type == LAMB_PRJ) {
2082    return gribinfo->elements[index].gds->lam.iNy;
2083  } else if (gribinfo->elements[index].gds->head.usData_type == POLAR_PRJ) {
2084    return gribinfo->elements[index].gds->pol.usNy;
2085  }
2086
2087}
2088/*****************************************************************************
2089 *
2090 * returns number of columns in grid
2091 *
2092 * Input:
2093 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
2094 *                 gribinfo structure is filled in this function.
2095 *
2096 * Return:
2097 *    number of columns in grid
2098 *****************************************************************************/
2099int rg_get_numcols(GribInfo *gribinfo,int index)
2100{
2101  if ((gribinfo->elements[index].gds->head.usData_type == LATLON_PRJ) || 
2102      (gribinfo->elements[index].gds->head.usData_type == GAUSS_PRJ) || 
2103      (gribinfo->elements[index].gds->head.usData_type == ROT_LATLON_PRJ) || 
2104      (gribinfo->elements[index].gds->head.usData_type == ROT_GAUSS_PRJ) || 
2105      (gribinfo->elements[index].gds->head.usData_type == STR_LATLON_PRJ) || 
2106      (gribinfo->elements[index].gds->head.usData_type == STR_GAUSS_PRJ) || 
2107      (gribinfo->elements[index].gds->head.usData_type == STR_ROT_LATLON_PRJ)|| 
2108      (gribinfo->elements[index].gds->head.usData_type == STR_ROT_GAUSS_PRJ)) 
2109    {
2110      return gribinfo->elements[index].gds->llg.usNi;
2111  } else if (gribinfo->elements[index].gds->head.usData_type == MERC_PRJ) {
2112    return gribinfo->elements[index].gds->merc.cols;
2113  } else if (gribinfo->elements[index].gds->head.usData_type == LAMB_PRJ) {
2114    return gribinfo->elements[index].gds->lam.iNx;
2115  } else if (gribinfo->elements[index].gds->head.usData_type == POLAR_PRJ) {
2116    return gribinfo->elements[index].gds->pol.usNx;
2117  }
2118
2119}
2120/*****************************************************************************
2121 *
2122 * returns the offset (in bytes) from the beginning of the file.
2123 *
2124 * Input:
2125 *    gribinfo - pointer to a filled gribinfo structure.
2126 *
2127 * Return:
2128 *    offset (in bytes) from beginning of file
2129 *****************************************************************************/
2130int rg_get_offset(GribInfo *gribinfo,int index)
2131{
2132  return gribinfo->elements[index].offset;
2133}
2134/*****************************************************************************
2135 *
2136 * returns the grib record ending position (in bytes) from the beginning of
2137 *    the file.
2138 *
2139 * Input:
2140 *    gribinfo - pointer to a filled gribinfo structure.
2141 *
2142 * Return:
2143 *    position (in bytes) of the end of the grib record within the file.
2144 *****************************************************************************/
2145int rg_get_end(GribInfo *gribinfo,int index)
2146{
2147  return gribinfo->elements[index].end;
2148}
2149/*****************************************************************************
2150 *
2151 * returns grib id of input grid
2152 *
2153 * Input:
2154 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
2155 *                 gribinfo structure is filled in this function.
2156 *
2157 * Return:
2158 *    grib id of input grid
2159 *****************************************************************************/
2160int rg_get_gridnum(GribInfo *gribinfo,int index)
2161{
2162  return gribinfo->elements[index].pds->usGrid_id;
2163}
2164/*****************************************************************************
2165 *
2166 * returns date
2167 *
2168 * Input:
2169 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
2170 *                 gribinfo structure is filled in this function.
2171 *
2172 * Return:
2173 *    date (yymmddhh) in integer type
2174 *****************************************************************************/
2175int rg_get_date(GribInfo *gribinfo,int index)
2176{
2177  return gribinfo->elements[index].date;
2178}
2179/*****************************************************************************
2180 *
2181 * returns century
2182 *
2183 * Input:
2184 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
2185 *                 gribinfo structure is filled in this function.
2186 *
2187 * Return:
2188 *    century in integer type
2189 *****************************************************************************/
2190int rg_get_century(GribInfo *gribinfo,int index)
2191{
2192  return gribinfo->elements[index].century;
2193}
2194/*****************************************************************************
2195 *
2196 * returns forecast time
2197 *
2198 * Input:
2199 *    gribinfo - pointer to a previously allocated gribinfo structure.  The
2200 *                 gribinfo structure is filled in this function.
2201 *
2202 * Return:
2203 *    forecast time in units described by usFcst_unit_id
2204 *****************************************************************************/
2205int rg_get_forecast_time(GribInfo *gribinfo,int index)
2206{
2207  return gribinfo->elements[index].pds->usP1;
2208}
2209
2210/*****************************************************************************
2211 *
2212 * reads the gribmap file, and stores the information in the GribParameters
2213 *    structure.
2214 *
2215 * Input:
2216 *   gribmap - pointer to a previously allocated GribParameters structure. 
2217 *              The gribmap structure is filled in this function.
2218 *   file - the name of the gribmap file to read.
2219 *
2220 *   Return:
2221 *      1  - successful call to setup_gribinfo
2222 *     -1 - call to setup_gribinfo failed
2223 *
2224 *****************************************************************************/
2225int rg_setup_gribmap(GribParameters *gribmap, char filename[])
2226{
2227  FILE *fid;
2228  char line[500];
2229  int id, center, subcenter, table;
2230  int idx;
2231 
2232  fid = fopen(filename,"r");
2233  if (fid == NULL)
2234    {
2235      fprintf(stderr,"Could not open %s\n",filename);
2236      return -1;
2237    }
2238
2239  gribmap->parms = (GribTableEntry *)malloc(sizeof(GribTableEntry));
2240
2241  idx = 0;
2242  while (fgets(line,500,fid) != NULL)
2243    {
2244      /* Skip over comments at begining of gribmap file */
2245      if (line[0] == '#') continue;
2246
2247      sscanf(line,"%d:",&id);
2248      if (id == -1) 
2249        {
2250          sscanf(line,"%d:%d:%d:%d",&id,&center,&subcenter,&table);
2251        } 
2252      else
2253        {
2254          gribmap->parms = 
2255            (GribTableEntry *)realloc(gribmap->parms,
2256                                        (idx+1)*sizeof(GribTableEntry));
2257          gribmap->parms[idx].center = center;
2258          gribmap->parms[idx].subcenter = subcenter;
2259          gribmap->parms[idx].table = table;
2260          sscanf(line,"%d:%[^:]:%[^:]",&(gribmap->parms[idx].parmid),
2261                 gribmap->parms[idx].name,
2262                 gribmap->parms[idx].comment);
2263          idx++;
2264        }
2265    }
2266
2267
2268  gribmap->num_entries = idx;
2269
2270  close(fid);
2271  return 1;
2272}
2273
2274/*****************************************************************************
2275 *
2276 * finds the gribmap entry described by  the gribmap file, and stores the information in the GribParameters
2277 *    structure.
2278 *
2279 * Input:
2280 *   gribmap - pointer to structure that was filled by a call to
2281 *             rg_setup_gribmap
2282 *   table   - if set to -1, the first table the valid name will be used.
2283 *             Otherwise, the table id must match as well.
2284 *   name    - name of the parameter to find.
2285 * Output
2286 *   gribmap_parms - pointer to GribTableEntry structure containing
2287 *             information about the parameter that was found.
2288 *
2289 *   Return:
2290 *      1  - successful call to setup_gribinfo
2291 *     -1 - call to setup_gribinfo failed
2292 *
2293 *****************************************************************************/
2294int rg_gribmap_parameter(GribParameters *gribmap, char name[], int table,
2295                         GribTableEntry *gribmap_parms)
2296{
2297  int idx;
2298  int found;
2299
2300  found = 0;
2301  for (idx = 0; idx < gribmap->num_entries; idx++) 
2302    {
2303     
2304      if (strcmp(gribmap->parms[idx].name,name) == 0)
2305        {
2306          if ((table == -1) || (table == gribmap->parms[idx].table))
2307            {
2308              /* We found a match! */
2309              found = 1;
2310              break;
2311            }
2312        }
2313    }
2314 
2315  if (found) 
2316    {
2317      memcpy(gribmap_parms,&(gribmap->parms[idx]),sizeof(GribTableEntry));
2318      return 1;
2319    }
2320  else
2321    {
2322      return -1;
2323    }
2324}
2325
2326/*****************************************************************************
2327 *
2328 * Deallocates the elements in the gribmap structure.
2329 *
2330 * Input:
2331 *    gribmap - pointer to a previously allocated gribmap structure.  The
2332 *                 gribmap structure is filled in this function.
2333 *
2334 *****************************************************************************/
2335void rg_free_gribmap_elements(GribParameters *gribmap)
2336{
2337  free(gribmap->parms);
2338}
2339
2340/*****************************************************************************
2341 *
2342 * Compares the elements in a findgrib structure with the elements in the
2343 *   gribinfo structure for the input index.  If they match, returns 1,
2344 *   otherwise, returns 0.
2345 *
2346 * Input:
2347 *    gribinfo
2348 *    findgrib
2349 *    index    - the index of the grib record in gribinfo to compare to.
2350 *
2351 *****************************************************************************/
2352int compare_record(GribInfo *gribinfo, FindGrib *findgrib, int gribnum)
2353{
2354
2355  /*
2356   *  Note (6/20/05): This searching is very inefficient. We may need to
2357   *   improve this, since, for WRF, when searching through boundary data,
2358   *   each search is slower that the previous, since the record to be
2359   *   found turns out to be farther into the list.
2360   */
2361 
2362  int retval = 0;
2363
2364  if ((findgrib->center_id == -INT_MAX) || 
2365      findgrib->center_id == gribinfo->elements[gribnum].center_id) {
2366    if ((findgrib->subcenter_id == -INT_MAX) ||
2367        findgrib->subcenter_id == gribinfo->elements[gribnum].subcenter_id) {
2368      if ((findgrib->parmtbl_version == -INT_MAX) || 
2369          findgrib->parmtbl_version == gribinfo->elements[gribnum].parmtbl) {
2370        if ((strcmp(findgrib->initdate,"*") == 0) || 
2371            (strncmp(gribinfo->elements[gribnum].initdate,findgrib->initdate,
2372                     strlen(findgrib->initdate)) == 0)) {
2373          if ((strcmp(findgrib->validdate,"*") == 0) || 
2374              (strncmp(gribinfo->elements[gribnum].valid_time,
2375                       findgrib->validdate,
2376                       strlen(findgrib->validdate)) == 0)) {
2377            if ((findgrib->parmid == -INT_MAX) || 
2378                (findgrib->parmid == 
2379                 gribinfo->elements[gribnum].usParm_id)) {
2380              if ((findgrib->leveltype == -INT_MAX) || 
2381                  (findgrib->leveltype == 
2382                   gribinfo->elements[gribnum].usLevel_id)) {
2383                if ((findgrib->level1 == -INT_MAX) || 
2384                    (findgrib->level1 == 
2385                     gribinfo->elements[gribnum].usHeight1)) {
2386                  if ((findgrib->level2 == -INT_MAX) || 
2387                      (findgrib->level2 == 
2388                       gribinfo->elements[gribnum].usHeight2)) {
2389                    if ((findgrib->fcsttime1 == -INT_MAX) || 
2390                        (findgrib->fcsttime1 == 
2391                         gribinfo->elements[gribnum].fcsttime1)) {
2392                      if ((findgrib->fcsttime2 == -INT_MAX) || 
2393                          (findgrib->fcsttime2 == 
2394                           gribinfo->elements[gribnum].fcsttime2)) {
2395                        retval = 1;
2396                      }
2397                    }
2398                  }
2399                }
2400              }
2401            }
2402          }
2403        }
2404      }
2405    }
2406  }
2407
2408  return retval;
2409}
2410
2411
2412/*****************************************************************************
2413 *
2414 * returns the multiplication factor to convert grib forecast times to
2415 *   seconds.
2416 *
2417 * Input:
2418 *    unit_id  - grib forecast unit id, from Table 4.
2419 *
2420 * Return:
2421 *    conversion factor
2422 *****************************************************************************/
2423int get_factor2(int unit)
2424{
2425  int factor;
2426 
2427  switch (unit) {
2428  case 0:
2429    factor = 60;
2430    break;
2431  case 1:
2432    factor = 60*60;
2433    break;
2434  case 2:
2435    factor = 60*60*24;
2436    break;
2437  case 10:
2438    factor = 60*60*3;
2439    break; 
2440  case 11:
2441    factor = 60*60*3;
2442    break;
2443  case 12:
2444    factor = 60*60*12;
2445    break;
2446  case 50:
2447    /* This is a WSI (non-standard) time unit of 5 minutes */
2448    factor = 5*60;
2449    break;
2450  case 254:
2451    factor = 1;
2452    break;
2453  default:
2454    fprintf(stderr,"Invalid unit for forecast time: %d\n",unit);
2455    factor = 0;
2456  }
2457  return factor;
2458}
Note: See TracBrowser for help on using the repository browser.