source: trunk/WRF.COMMON/WRFV2/external/io_grib1/grib1_routines.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: 32.4 KB
Line 
1/*
2****************************************************************************
3*
4*  Routines for indexing, reading and writing grib files.  Routines
5*    are designed to be called by Fortran.
6*
7*  All routines return 0 for success, 1 for failure, unless otherwise noted.
8*
9*  Todd Hutchinson
10*  WSI
11*  05/17/2005
12*
13****************************************************************************
14*/
15
16#include "grib1_routines.h"
17#include "gridnav.h"
18#include <stdio.h>
19#include <stdlib.h>
20#include <ctype.h>
21#include <limits.h>
22
23char *trim (char *str);
24int index_metadata(GribInfo *gribinfo, MetaData *metadata, int fid);
25int index_times(GribInfo *gribinfo, Times *times);
26int find_time(Times *times, char valid_time[15]);
27int get_gridnav_projection(int wrf_projection);
28int get_byte(int input_int, int bytenum);
29
30/*
31 * Allocate space for the fileindex structure
32 */
33
34int ALLOC_INDEX_FILE(FileIndex *fileindex)
35{
36  int status = 0;
37 
38  fileindex->gribinfo = (GribInfo *)malloc(sizeof(GribInfo));
39  if (fileindex->gribinfo == NULL) {
40    fprintf(stderr,"Allocating fileindex->gribinfo failed.\n");
41    status = 1;
42    return status;
43  }
44 
45  fileindex->metadata = (MetaData *)malloc(sizeof(MetaData));
46  if (fileindex->metadata == NULL) {
47    fprintf(stderr,"Allocating fileindex->metadata failed.\n");
48    status = 1;
49    return status;
50  }
51  fileindex->metadata->elements = NULL;
52 
53  fileindex->times = (Times *)malloc(sizeof(Times));
54  if (fileindex->times == NULL) {
55    fprintf(stderr,"Allocating fileindex->times failed.\n");
56    status = 1;
57    return status;
58  }
59  fileindex->times->elements = NULL;
60 
61  return status;
62}
63
64
65void FREE_INDEX_FILE(FileIndex *fileindex)
66{
67  int status = 0;
68 
69  rg_free_gribinfo_elements(fileindex->gribinfo);
70  free(fileindex->gribinfo);
71
72  free(fileindex->metadata->elements);
73  free(fileindex->metadata);
74
75  free(fileindex->times->elements);
76  free(fileindex->times);
77
78}
79
80
81int INDEX_FILE(int *fid, FileIndex *fileindex)
82{
83
84  int status;
85  /* Index the grib records */
86
87  status = rg_setup_gribinfo_i(fileindex->gribinfo,*fid,1);
88  if (status < 0) {
89    fprintf(stderr,"Error setting up gribinfo structure.\n");
90    return 1;
91  }
92
93  /* Index the metadata section */
94
95  status = index_metadata(fileindex->gribinfo, fileindex->metadata, *fid);
96  if (status != 0) {
97    fprintf(stderr,"Error setting up metadata structure.\n");
98    return 1;
99  }
100
101  /* Setup a list of times based on times in grib records */
102
103  status = index_times(fileindex->gribinfo, fileindex->times);
104  if (status != 0) {
105    fprintf(stderr,"Error indexing times in grib file.\n");
106    return 1;
107  }
108 
109  return 0;
110}
111
112
113int GET_FILEINDEX_SIZE(int *size)
114{
115  *size = sizeof(FileIndex);
116  return *size;
117}
118
119
120int GET_NUM_TIMES(FileIndex *fileindex, int *numtimes)
121{
122  *numtimes = (fileindex->times)->num_elements;
123  return *numtimes;
124}
125
126
127int GET_TIME(FileIndex *fileindex, int *idx, char time[])
128{
129  int num_times;
130  int year, month, day, minute, hour, second;
131  char time2[100];
132
133  num_times = GET_NUM_TIMES(fileindex,&num_times);
134  if (*idx > num_times) 
135    {
136      fprintf(stderr,"Tried to get time %d, but only %d times exist\n",
137              *idx, num_times);
138      return 1;
139    }
140
141  strcpy(time,fileindex->times->elements[*idx-1].valid_time);
142 
143  /* Reformat time to meet WRF time format */
144
145  sscanf(time, "%4d%2d%2d%2d%2d%2d", 
146         &year, &month, &day, &hour, &minute, &second);
147  sprintf(time2, "%04d-%02d-%02d_%02d:%02d:%02d", 
148          year, month, day, hour, minute, second);
149  strncpy(time,time2,19);
150
151  return 0;
152}
153
154
155int GET_LEVEL1(FileIndex *fileindex, int *idx, int *level1)
156{
157
158  *level1 = (fileindex->gribinfo)->elements[*idx].usHeight1;
159
160  return *level1;
161
162}
163
164
165int GET_LEVEL2(FileIndex *fileindex, int *idx, int *level2)
166{
167
168  *level2 = (fileindex->gribinfo)->elements[*idx].usHeight2;
169
170  return *level2;
171
172}
173
174
175int index_metadata(GribInfo *gribinfo, MetaData *metadata, int fid)
176{
177  int status=0;
178  int end;
179  char string[11];
180  int found_metadata=0;
181  int idx;
182  int pos;
183  int fileend;
184  int seekpos;
185  int bytesread;
186  char line[1000];
187  char element[100],datestr[100],varname[100];
188  char value[1000];
189  int incomment;
190  int charidx;
191  int elemidx=0;
192  FILE *stream;
193
194
195  /* Associate a FILE *stream with the file id */
196  stream = fdopen(fid,"r");
197  if (stream == NULL) 
198    {
199      perror("Error associating stream with file descriptor");
200      status = -1;
201      return status;
202    }
203 
204  /*
205   * First, set the position to end of grib data (the
206   *   metadata section comes after the grib data).
207   */
208  idx = rg_num_elements(gribinfo) - 1;
209  end = rg_get_end(gribinfo,idx);
210  pos = end + 1;
211  fileend = lseek(fid,0,SEEK_END);
212
213  /*
214   * Now, start searching for metadata
215   */
216  while (pos < (fileend - 10))
217    {
218      seekpos = pos;
219      pos = lseek(fid,seekpos,SEEK_SET);
220      if (pos != seekpos) 
221        {
222          fprintf(stderr,"Error seeking %d bytes in file\n",end);
223          perror("");
224          return 1;
225        }
226
227      bytesread = read(fid,string,10);
228      if (bytesread != 10) 
229        {
230          fprintf(stderr,"Invalid read, pos: %d :\n",pos);
231          perror("");
232          pos += 1;
233          continue;
234        }
235
236      if (strncmp(string,"<METADATA>",10) == 0) 
237        {
238          /* We found it, so break out ! */
239          found_metadata = 1;
240          break;
241        }
242      pos += 1;
243    }
244
245
246  /* Now, read metadata, line by line */
247  incomment = 0;
248  while(fgets(line,1000,stream) != NULL)
249    {
250      trim(line);
251
252      /* Set comment flag, if we found a comment */
253      if (strncmp(line,"<!--",4) == 0)
254        {
255          incomment = 1;
256          strcpy(line,line+4);
257        }
258     
259      /* Search for end of comment */
260      if (incomment)
261        {
262          charidx = 0;
263          while (charidx < strlen(line)) 
264            {
265             
266              if (strncmp(line+charidx,"-->",3) == 0)
267                {
268                  strcpy(line,line+charidx+3);
269                  incomment = 0;
270                  break;
271                }
272              else
273                {
274                  charidx++;
275                }
276            }
277        }
278
279      if (incomment) continue;
280 
281
282      /* Check for end of metadata */
283      if (strncmp(line,"</METADATA>",11) == 0) 
284        {
285          /* We found end of data, so, break out */
286          break;
287        }
288
289      /* Skip blank lines */
290      if (strlen(line) == 0) continue;
291
292
293      /* Parse line */
294      trim(line);
295      strcpy(element,"none");
296      strcpy(datestr,"none");
297      strcpy(varname,"none");
298      strcpy(value,"none");
299      if (sscanf(line,"%[^;=];%[^;=];%[^;=]=%[^\n]",varname,datestr,
300                 element,value) == 4)
301        {
302        }
303      else if (sscanf(line,"%[^;=];%[^;=]=%[^\n]",datestr,element,value) == 3)
304        {
305          strcpy(varname,"none");
306        }
307      else if (sscanf(line,"%[^;=]=%[^\n]",element,value) == 2)
308        {
309          strcpy(varname,"none");
310          strcpy(datestr,"none");
311        }
312      else 
313        {
314          strcpy(varname,"none");
315          strcpy(datestr,"none");
316          strcpy(element,"none");
317          strcpy(value,"none");
318          fprintf(stderr,"Invalid line in metadata: \n%s",line);
319        }
320
321      trim(varname);
322      trim(datestr);
323      trim(element);
324      trim(value);
325
326      metadata->elements = 
327        (MetaData_Elements *)realloc( metadata->elements, 
328                                     (elemidx+1)*sizeof(MetaData_Elements) );
329      strcpy(metadata->elements[elemidx].VarName,varname);
330      strcpy(metadata->elements[elemidx].DateStr,datestr);
331      strcpy(metadata->elements[elemidx].Element,element);
332      strcpy(metadata->elements[elemidx].Value,value);
333
334      elemidx++;
335       
336    }
337
338  metadata->num_elements = elemidx;
339 
340  return 0;
341}
342
343
344
345
346int index_times(GribInfo *gribinfo, Times *times)
347{
348  int idx;
349  int status;
350  int numtimes=0;
351  int date;
352  char valid_time[15];
353  char tmp[15];
354  int swapped;
355
356  times->num_elements = 0;
357
358  /* Loop through elements, and build list of times */
359
360  for (idx=0; idx < gribinfo->num_elements; idx++) 
361    {
362      /* Calculate valid time */
363      status = rg_get_valid_time(gribinfo,idx,valid_time);
364      if (status != 0) 
365        {
366          fprintf(stderr,"Could not retrieve valid time for index: %d\n",idx);
367          continue;
368        }
369
370      /*
371       * Check if this time is already contained in times
372       *  If not, allocate space for it, and add it to list
373       */
374      if (find_time(times,valid_time) < 0) 
375        {
376          times->num_elements++;
377          times->elements = 
378            (Times_Elements *)
379            realloc(times->elements,times->num_elements*sizeof(Times_Elements));
380          if (times->elements == NULL) 
381            {
382              fprintf(stderr,"Allocating times->elements failed.\n");
383              status = 1;
384              return status;
385            }
386          strcpy(times->elements[times->num_elements - 1].valid_time,valid_time);
387        }
388    }
389
390  /* Sort times */
391  swapped = 1;
392  while (swapped)
393    {
394      swapped=0;
395      for (idx=1; idx < times->num_elements; idx++) 
396        {
397          if (strcmp(times->elements[idx-1].valid_time,
398                     times->elements[idx].valid_time) > 0)
399            {
400              strcpy(tmp,times->elements[idx-1].valid_time);
401              strcpy(times->elements[idx-1].valid_time,
402                     times->elements[idx].valid_time);
403              strcpy(times->elements[idx].valid_time, tmp);
404              swapped = 1;
405            }
406        }
407    }
408
409  return 0;
410}
411
412
413
414int find_time(Times *times, char valid_time[15])
415{
416  int idx;
417  int found_elem = -1;
418
419  for (idx = 0; idx < times->num_elements; idx++) 
420    {
421      if (strcmp(times->elements[idx].valid_time,valid_time) == 0) 
422        {
423          found_elem = idx;
424          break;
425        }
426    }
427
428  return found_elem;
429
430}
431
432
433int GET_METADATA_VALUE(FileIndex *fileindex, char ElementIn[], 
434                       char DateStrIn[], char VarNameIn[], char Value[], 
435                       int *stat, int strlen1, int strlen2, int strlen3, 
436                       int strlen4, int strlen5)
437{
438  int elemidx;
439  int elemnum;
440  char VarName[200];
441  char DateStr[200];
442  char Element[200];
443  int Value_Len;
444
445  *stat = 0;
446
447  strncpy(Element,ElementIn,strlen2);
448  Element[strlen2] = '\0';
449  strncpy(DateStr,DateStrIn,strlen3);
450  DateStr[strlen3] = '\0';
451  strncpy(VarName,VarNameIn,strlen4);
452  VarName[strlen4] = '\0';
453  Value_Len = strlen5;
454
455  elemnum = -1;
456  for (elemidx = 0; elemidx < fileindex->metadata->num_elements; elemidx++)
457    {
458      if (strcmp(Element,fileindex->metadata->elements[elemidx].Element) == 0)
459        {
460          if (strcmp(DateStr,fileindex->metadata->elements[elemidx].DateStr) 
461              == 0)
462            {
463              if (strcmp(VarName,
464                         fileindex->metadata->elements[elemidx].VarName) == 0)
465                {
466                  elemnum = elemidx;
467                  break;
468                }
469            }
470        }
471    }
472
473  if (elemnum != -1)
474    {
475      strncpy(Value, fileindex->metadata->elements[elemnum].Value, Value_Len);
476    } 
477  else
478    {
479      strncpy(Value, "none", Value_Len);
480      *stat = 1;
481    }
482
483  /*
484   * Pad end of string with one space.  This allows Fortran internal
485   *   read function to work properly.
486   */
487  if (strlen(Value) < Value_Len) 
488    {
489      strcpy(Value + strlen(Value), " ");
490    }
491
492  return elemidx;
493}
494
495
496int GET_GRIB_INDEX(FileIndex *fileindex, int *center, int *subcenter, 
497                   int *parmtbl, int *parmid, char DateStrIn[], 
498                   int *leveltype, int *level1, int *level2, int *fcsttime1,
499                   int *fcsttime2, int *index, int strlen1, int strlen2)
500{
501  char DateStr[1000];
502  FindGrib findgrib;
503
504  strncpy(DateStr,DateStrIn,strlen2);
505  DateStr[strlen2] = '\0';
506  grib_time_format(DateStr,DateStr);
507
508  rg_init_findgrib(&findgrib);
509
510  strncpy(findgrib.initdate,DateStrIn,strlen2);
511  findgrib.initdate[strlen2] = '\0';
512  findgrib.parmid          = *parmid;
513  findgrib.leveltype       = *leveltype;
514  findgrib.level1          = *level1;
515  findgrib.level2          = *level2;
516  findgrib.fcsttime1       = *fcsttime1;
517  findgrib.fcsttime2       = *fcsttime2;
518  findgrib.center_id       = *center;
519  findgrib.subcenter_id    = *subcenter;
520  findgrib.parmtbl_version = *parmtbl;
521 
522  *index = rg_get_index(fileindex->gribinfo, &findgrib);
523
524  return *index;
525
526}
527
528
529int GET_GRIB_INDEX_GUESS(FileIndex *fileindex, int *center, int *subcenter, 
530                         int *parmtbl, int *parmid, char DateStrIn[], 
531                         int *leveltype, int *level1, int *level2, 
532                         int *fcsttime1,int *fcsttime2, int *guessidx, 
533                         int *index, int strlen1, int strlen2)
534{
535  char DateStr[1000];
536  FindGrib findgrib;
537
538  strncpy(DateStr,DateStrIn,strlen2);
539  DateStr[strlen2] = '\0';
540  grib_time_format(DateStr,DateStr);
541
542  rg_init_findgrib(&findgrib);
543
544  strncpy(findgrib.initdate,DateStrIn,strlen2);
545  findgrib.initdate[strlen2] = '\0';
546  findgrib.parmid          = *parmid;
547  findgrib.leveltype       = *leveltype;
548  findgrib.level1          = *level1;
549  findgrib.level2          = *level2;
550  findgrib.fcsttime1       = *fcsttime1;
551  findgrib.fcsttime2       = *fcsttime2;
552  findgrib.center_id       = *center;
553  findgrib.subcenter_id    = *subcenter;
554  findgrib.parmtbl_version = *parmtbl;
555 
556  *index = rg_get_index_guess(fileindex->gribinfo, &findgrib, *guessidx);
557
558  return *index;
559
560}
561
562
563int GET_GRIB_CENTER(FileIndex *fileindex, int *parmid, int *center)
564{
565
566  *center = rg_get_center_id(fileindex->gribinfo,*parmid);
567
568  return *center;
569
570}
571
572
573int GET_GRIB_SUBCENTER(FileIndex *fileindex, int *parmid, int *subcenter)
574{
575
576  *subcenter = rg_get_subcenter_id(fileindex->gribinfo,*parmid);
577
578  return *subcenter;
579
580}
581
582
583int GET_GRIB_TBLVERSION(FileIndex *fileindex, int *parmid, int *parmtbl)
584{
585
586  *parmtbl = rg_get_parmtbl(fileindex->gribinfo,*parmid);
587
588  return *parmtbl;
589
590}
591
592
593int GET_GRIB_PROCID(FileIndex *fileindex, int *parmid, int *proc_id)
594{
595
596  *proc_id = rg_get_proc_id(fileindex->gribinfo,*parmid);
597
598  return *proc_id;
599
600}
601
602
603int GET_GRIB_INDEX_VALIDTIME(FileIndex *fileindex, int *center, 
604                   int *subcenter, int *parmtbl, int *parmid, 
605                   char DateStrIn[], int *leveltype, int *level1, int *level2,
606                   int *index, int strlen1, int strlen2)
607{
608  char DateStr[1000];
609  FindGrib findgrib;
610
611  strncpy(DateStr,DateStrIn,strlen2);
612  DateStr[strlen2] = '\0';
613  grib_time_format(DateStr,DateStr);
614
615  rg_init_findgrib(&findgrib);
616
617  strncpy(findgrib.validdate,DateStr,strlen2);
618  findgrib.initdate[strlen2] = '\0';
619  findgrib.parmid          = *parmid;
620  findgrib.leveltype       = *leveltype;
621  findgrib.level1          = *level1;
622  findgrib.level2          = *level2;
623  findgrib.center_id       = *center;
624  findgrib.subcenter_id    = *subcenter;
625  findgrib.parmtbl_version = *parmtbl;
626 
627  *index = rg_get_index(fileindex->gribinfo, &findgrib);
628
629  return *index;
630}
631
632
633int GET_GRIB_INDEX_VALIDTIME_GUESS(FileIndex *fileindex, int *center, 
634                                   int *subcenter, int *parmtbl, int *parmid, 
635                                   char DateStrIn[], int *leveltype, 
636                                   int *level1, int *level2, int *guessidx, 
637                                   int *index, int strlen1, int strlen2)
638{
639  char DateStr[1000];
640  FindGrib findgrib;
641
642  strncpy(DateStr,DateStrIn,strlen2);
643  DateStr[strlen2] = '\0';
644  grib_time_format(DateStr,DateStr);
645
646  rg_init_findgrib(&findgrib);
647
648  strncpy(findgrib.validdate,DateStr,strlen2);
649  findgrib.initdate[strlen2] = '\0';
650  findgrib.parmid          = *parmid;
651  findgrib.leveltype       = *leveltype;
652  findgrib.level1          = *level1;
653  findgrib.level2          = *level2;
654  findgrib.center_id       = *center;
655  findgrib.subcenter_id    = *subcenter;
656  findgrib.parmtbl_version = *parmtbl;
657 
658  *index = rg_get_index_guess(fileindex->gribinfo, &findgrib, *guessidx);
659
660  return *index;
661}
662
663
664int GET_GRIB_INDICES(FileIndex *fileindex, int *center, int *subcenter, 
665                     int *parmtbl,int *parmid, char DateStrIn[], 
666                     int *leveltype, int *level1, int *level2, int *fcsttime1,
667                     int *fcsttime2, int *indices, int *num_indices, 
668                     int strlen1, int strlen2)
669{
670  char DateStr[1000];
671  int status;
672  FindGrib findgrib;
673
674  strncpy(DateStr,DateStrIn,strlen2);
675  DateStr[strlen2] = '\0';
676  grib_time_format(DateStr,DateStr);
677
678  rg_init_findgrib(&findgrib);
679
680  strncpy(findgrib.initdate,DateStrIn,strlen2);
681  findgrib.initdate[strlen2] = '\0';
682  trim(findgrib.initdate);
683  findgrib.parmid          = *parmid;
684  findgrib.leveltype       = *leveltype;
685  findgrib.level1          = *level1;
686  findgrib.level2          = *level2;
687  findgrib.fcsttime1       = *fcsttime1;
688  findgrib.fcsttime2       = *fcsttime2;
689  findgrib.center_id       = *center;
690  findgrib.subcenter_id    = *subcenter;
691  findgrib.parmtbl_version = *parmtbl;
692
693  *num_indices = rg_get_indices(fileindex->gribinfo, &findgrib, indices);
694
695  return (*num_indices);
696
697}
698
699
700int GET_GRID_INFO_SIZE(int *size)
701{
702
703  *size = sizeof(Grid_Info);
704
705  return *size;
706
707}
708
709
710int LOAD_GRID_INFO(char *varnameIn, char *initdateIn, int *leveltype, 
711                   int *level1, int *level2, float *fcst_time, 
712                   int *accum_period, int *grid_id, int *projection, 
713                   int *xpoints, int *ypoints, float *center_lat, 
714                   float *center_lon, float *Di, float *Dj,float *central_lon,
715                   int *proj_center_flag, float *latin1, 
716                   float *latin2, Grib1_Tables *grib_tables,
717                   Grid_Info *grid_info, int strlen1, int strlen2)
718{
719
720  char varname[1000], initdate[1000];
721
722  strncpy(varname,varnameIn,strlen1);
723  varname[strlen1] = '\0';
724  strncpy(initdate,initdateIn,strlen2);
725  initdate[strlen2] = '\0';
726
727  strcpy(grid_info->varname, varname);
728  strcpy(grid_info->initdate, initdate);
729  grid_info->leveltype        = *leveltype;
730  grid_info->level1           = *level1 ;
731  grid_info->level2           = *level2 ;
732  grid_info->fcst_time        = *fcst_time ;
733  grid_info->accum_period     = *accum_period ;
734  grid_info->grid_id          = *grid_id ;
735  grid_info->projection       = *projection ;
736  grid_info->xpoints          = *xpoints ;
737  grid_info->ypoints          = *ypoints ;
738  grid_info->center_lat       = *center_lat ;
739  grid_info->center_lon       = *center_lon;
740  grid_info->Di               = *Di ;
741  grid_info->Dj               = *Dj ;
742  grid_info->central_lon      = *central_lon ;
743  grid_info->proj_center_flag = *proj_center_flag ;
744  grid_info->latin1           = *latin1 ;
745  grid_info->latin2           = *latin2 ;
746  grid_info->grib_tables      = copy_grib_tables(grib_tables);
747
748  return 0;
749
750}
751
752int PRINT_GRID_INFO(Grid_Info *grid_info)
753{
754
755  fprintf(stdout,"varname        =%s\n",grid_info->varname);
756  fprintf(stdout,"initdate       =%s\n",grid_info->initdate);
757  fprintf(stdout,"leveltype      =%d\n",grid_info->leveltype);
758  fprintf(stdout,"level1         =%d\n",grid_info->level1);
759  fprintf(stdout,"level2         =%d\n",grid_info->level2);
760  fprintf(stdout,"fcst_time      =%f\n",grid_info->fcst_time);
761  fprintf(stdout,"accum_period   =%d\n",grid_info->accum_period);
762  fprintf(stdout,"grid_id        =%d\n",grid_info->grid_id);
763  fprintf(stdout,"projection     =%d\n",grid_info->projection);
764  fprintf(stdout,"xpoints        =%d\n",grid_info->xpoints);
765  fprintf(stdout,"ypoints        =%d\n",grid_info->ypoints);
766  fprintf(stdout,"center_lat     =%f\n",grid_info->center_lat);
767  fprintf(stdout,"center_lon     =%f\n",grid_info->center_lon);
768  fprintf(stdout,"Di             =%f\n",grid_info->Di);
769  fprintf(stdout,"Dj             =%f\n",grid_info->Dj);
770  fprintf(stdout,"central_lon    =%f\n",grid_info->central_lon);
771  fprintf(stdout,"proj_center_flag =%d\n",grid_info->proj_center_flag);
772  fprintf(stdout,"latin1         =%f\n",grid_info->latin1);
773  fprintf(stdout,"latin2         =%f\n",grid_info->latin2);
774
775  return 0;
776
777}
778
779
780int GET_SIZEOF_GRID(FileIndex *fileindex, int *index, int *numcols, 
781                    int *numrows)
782{
783
784  *numcols = rg_get_numcols(fileindex->gribinfo,*index);
785
786  *numrows = rg_get_numrows(fileindex->gribinfo,*index);
787
788  return (*numcols)*(*numrows);
789
790}
791
792
793void FREE_GRID_INFO(Grid_Info *grid_info)
794{
795  FREE_GRIBMAP(grid_info->grib_tables);
796}
797
798
799int READ_GRIB(FileIndex *fileindex, int *fid, int *index, float *data)
800{
801  int status;
802
803  status = rg_get_data_1d(fileindex->gribinfo,*index,data);
804
805  return status;
806}
807
808#define WRF_LATLON 0
809#define WRF_LAMBERT 1
810#define WRF_POLAR_STEREO 2
811#define WRF_MERCATOR 3
812
813#define LINESIZE 300
814
815#define SECS_IN_SEC 1
816#define SECS_IN_MIN 60
817#define MINS_IN_HOUR 60
818#define MINS_IN_5MINS 5
819#define HOURS_IN_DAY 24
820
821#define MAX_FCST 65535
822#define MAX_FCST_SECS MAX_FCST*SECS_IN_SEC
823#define MAX_FCST_MINS MAX_FCST*SECS_IN_MIN
824#define MAX_FCST_5MINS MAX_FCST*MINS_IN_5MINS*SECS_IN_MIN
825#define MAX_FCST_HOURS MAX_FCST*MINS_IN_HOUR*SECS_IN_MIN
826#define MAX_FCST_DAYS MAX_FCST*HOURS_IN_DAY*MINS_IN_HOUR*SECS_IN_MIN
827
828#define MAX1B_FCST 256
829#define MAX1B_FCST_SECS MAX1B_FCST*SECS_IN_SEC
830#define MAX1B_FCST_MINS MAX1B_FCST*SECS_IN_MIN
831#define MAX1B_FCST_5MINS MAX1B_FCST*MINS_IN_5MINS*SECS_IN_MIN
832#define MAX1B_FCST_HOURS MAX1B_FCST*MINS_IN_HOUR*SECS_IN_MIN
833#define MAX1B_FCST_DAYS MAX1B_FCST*HOURS_IN_DAY*MINS_IN_HOUR*SECS_IN_MIN
834
835#define PI 3.1415
836typedef struct {
837  int time_range;
838  int fcst_unit;
839  int P1;
840  int P2;
841
842  int time_range_ext;
843  int fcst_unit_ext_1;
844  int fcst_unit_ext_2;
845  int P1_ext;
846  int P2_ext;
847} FcstTimeStruct;
848
849int get_fcst_time(int accum_period, int fcst_secs, FcstTimeStruct *fcst_time);
850
851/****************************************************************************
852 *
853 * This function takes in metadata in the grid_info structure, output data in
854 *   the *data array, and calls routines to write the metadata and data
855 *   in grib version 1 format the open file descriptor filefd.
856 *
857 ****************************************************************************/
858
859int WRITE_GRIB(Grid_Info *grid_info, int *filefd, float *data)
860{
861
862  GRIB_HDR *gh=NULL;
863  DATA_INPUT data_input;
864  GEOM_IN geom_in;
865  USER_INPUT user_input;
866  int grid_projection;
867  int status;
868  float x_center, y_center;
869  GridNav gridnav;
870  float first_lat, first_lon, last_lat, last_lon;
871  int year, month, day, hour, minute;
872  float second;
873  char varname2[1000];
874  int table_index;
875  int fcst_unit;
876  int time_range;
877  int P1, P2;
878  int fcst_unit_ext_1, fcst_unit_ext_2;
879  int P1_ext, P2_ext;
880  int time_range_ext;
881  char errmsg[1000];
882  int center, subcenter, parmtbl;
883  int tablenum;
884  FcstTimeStruct fcst_time;
885
886  strcpy(varname2,grid_info->varname);
887  trim(varname2);
888
889  sscanf(grid_info->initdate,"%d-%d-%d_%d:%d:%f",
890         &year,&month,&day,&hour,&minute,&second);
891
892  /* Get coords of center of grid */
893  x_center = (grid_info->xpoints + 1)/2.;
894  y_center = (grid_info->ypoints + 1)/2.;
895
896  grid_projection = get_gridnav_projection(grid_info->projection);
897
898 /* Initialize grid structure */
899  status = GRID_init(grid_info->center_lat, grid_info->central_lon, 
900                     grid_projection,
901                     grid_info->latin1, grid_info->latin2, 
902                     grid_info->xpoints, grid_info->ypoints, grid_info->Di, 
903                     grid_info->Dj,
904                     grid_info->center_lat, grid_info->center_lon, 
905                     x_center, y_center,
906                     &gridnav);
907  if (!status)
908    {
909      fprintf(stderr,"write_grib: error from GRID_init\n");
910    }
911
912  /* get lat/lon of lower left corner */
913  status = GRID_to_latlon(&gridnav, 1, 1, &first_lat, &first_lon);
914  if (!status)
915    {
916      fprintf(stderr,
917              "write_grib: error from GRID_to_latlon for first lat/lon\n");
918    }
919
920  /* get lat/lon of upper right corner */
921  status = GRID_to_latlon(&gridnav, grid_info->xpoints, grid_info->ypoints, 
922                          &last_lat, &last_lon);
923  if (!status)
924    {
925      fprintf(stderr,
926              "write_grib: error from GRID_to_latlon for last lat/lon\n");
927    }
928
929  /* Read the grib parameter table */
930  status = GET_GRIB_PARAM(grid_info->grib_tables, varname2, &center,
931                           &subcenter, &parmtbl, &tablenum, &table_index,
932                          1,strlen(varname2));
933  if (table_index < 0)
934    {
935      fprintf(stderr,\
936              "Skipping %s, Could not find parameter for %s in gribmap.txt\n",\
937              varname2,varname2);
938      return 1;
939    }
940
941  /*
942   * We skip any parameters that are listed in parameter 255 in gribmap.txt.
943   * Parameter 255 is used to indicate that a WRF parameter should not be
944   * output.  It is useful for parameters that are requested to be output in
945   * the WRF Registry, but are already implicitly output in grib.
946   */
947
948  if (table_index == 255)
949    {
950      return 0;
951    }
952
953  /*
954   * Setup the geom_in structure for the grib library.  Here, we set
955   *  the generic parms.  Below, we set the projection specific parms
956   */
957  geom_in.nx = grid_info->xpoints;
958  geom_in.ny = grid_info->ypoints;
959  geom_in.first_lat = first_lat;
960  geom_in.first_lon = first_lon;
961  geom_in.last_lat = last_lat;
962  geom_in.last_lon = last_lon;
963  geom_in.scan = 64;
964
965  switch (grid_info->projection) 
966    {
967    case WRF_LATLON:
968      strcpy(geom_in.prjn_name,"spherical");
969      geom_in.parm_1 = grid_info->Dj;
970      geom_in.parm_2 = grid_info->Di;
971      geom_in.parm_3 = -1;
972      geom_in.usRes_flag = 0;  /*
973                                * Set to 0 here, MEL grib library will reset
974                                *  to 128 to indicate that direction
975                                *  increments are given.
976                                */
977      break;
978    case WRF_MERCATOR:
979      strcpy(geom_in.prjn_name,"mercator");
980      geom_in.parm_1 = grid_info->latin1;
981      geom_in.parm_2 = grid_info->Di;
982      geom_in.parm_3 = grid_info->Dj;
983      geom_in.usRes_flag = 128;
984      break;
985    case WRF_LAMBERT:
986      strcpy(geom_in.prjn_name,"lambert");
987      geom_in.usRes_flag = 0;   /* Set to 0 here, MEL grib library will reset
988                                 * to 128.
989                                 */
990      geom_in.parm_3 = grid_info->central_lon;
991      geom_in.x_int_dis = grid_info->Di;
992      geom_in.y_int_dis = grid_info->Dj;
993      geom_in.parm_1 = grid_info->latin1;
994      geom_in.parm_2 = grid_info->latin2;
995      break;
996    case WRF_POLAR_STEREO:
997      strcpy(geom_in.prjn_name,"polar_stereo");
998      geom_in.usRes_flag = 0;   /* Set to 0 here, MEL grib library will reset
999                                 * to 128.
1000                                 */
1001
1002      geom_in.parm_3 = -1;
1003      geom_in.x_int_dis = grid_info->Di*(1.+sin(60. * PI/180.))
1004        / (1.+sin(abs(grid_info->latin1) * PI/180.));
1005      geom_in.y_int_dis = grid_info->Dj*(1.+sin(60. * PI/180.))
1006        / (1.+sin(abs(grid_info->latin1) * PI/180.));
1007      geom_in.parm_1 = -1;
1008      geom_in.parm_2 = grid_info->central_lon;
1009      break;
1010    default:
1011      fprintf(stderr,"Error, invalid projection: %d\n",grid_info->projection);
1012      return 1;
1013    }
1014
1015  /*
1016   * Setup the data_input structure.
1017   */
1018  data_input.nDec_sc_fctr = 
1019    grid_info->grib_tables->grib_table_info[tablenum].dec_sc_factor[table_index];
1020  data_input.usProc_id = 220;
1021  data_input.usGrid_id = grid_info->grid_id;
1022  data_input.usParm_id = 
1023    grid_info->grib_tables->grib_table_info[tablenum].parm_id[table_index];
1024  data_input.usParm_sub_id = 
1025    grid_info->grib_tables->grib_table_info[tablenum].subcenter;
1026  data_input.usLevel_id = grid_info->leveltype;
1027
1028  if (grid_info->leveltype == 112) {
1029    data_input.nLvl_1 = grid_info->level2;
1030    data_input.nLvl_2 = grid_info->level1;
1031  } else {
1032    data_input.nLvl_1 = grid_info->level1;
1033    data_input.nLvl_2 = grid_info->level2;
1034  }
1035
1036  data_input.nYear = year;
1037  data_input.nMonth = month;
1038  data_input.nDay = day;
1039  data_input.nHour = hour;
1040  data_input.nMinute = minute;
1041  data_input.nSecond = second;
1042
1043  status = get_fcst_time(grid_info->accum_period, grid_info->fcst_time, 
1044                         &fcst_time);
1045
1046  data_input.usFcst_id = fcst_time.fcst_unit;
1047  data_input.usFcst_per1 = fcst_time.P1;
1048  data_input.usFcst_per2 = fcst_time.P2;
1049  data_input.usTime_range_id = fcst_time.time_range;
1050  data_input.usTime_range_avg = 0;
1051  data_input.usTime_range_mis = 0;
1052  /*
1053   * This is for WSI's extended PDS section
1054   */
1055  data_input.PDS_41 = fcst_time.fcst_unit_ext_1;
1056  data_input.PDS_42 = fcst_time.P1_ext;
1057  data_input.PDS_46 = fcst_time.fcst_unit_ext_2;
1058  data_input.PDS_47 = fcst_time.P2_ext;
1059  data_input.PDS_51 = fcst_time.time_range_ext;
1060  data_input.PDS_52 = 0;
1061
1062
1063  data_input.nDec_sc_fctr = 
1064    grid_info->grib_tables->grib_table_info[tablenum].dec_sc_factor[table_index];
1065  user_input.usCenter_id = 
1066    grid_info->grib_tables->grib_table_info[tablenum].center;
1067  user_input.usParm_tbl = 
1068    grid_info->grib_tables->grib_table_info[tablenum].parmtbl;
1069  user_input.chCase_id='0';
1070  user_input.usSub_tbl = 0;
1071  user_input.usCenter_sub = 
1072    grid_info->grib_tables->grib_table_info[tablenum].subcenter;
1073  user_input.usTrack_num = 0;
1074  user_input.usGds_bms_id = 128;
1075  user_input.usBDS_flag = 0;
1076  user_input.usBit_pack_num = 0;
1077
1078  status = init_gribhdr(&gh,errmsg);
1079  if (status != 0) {
1080    fprintf (stderr,"write_grib: Error writing %s: \n\t%s\n",varname2,errmsg);
1081    return 1;
1082  }
1083
1084  status = grib_enc(data_input,user_input,geom_in,data,gh,errmsg);
1085  if (status != 0) {
1086    fprintf (stderr,"write_grib: Error writing %s: \n\t%s\n",varname2,errmsg);
1087    fprintf (stderr,"\tCheck precision for %s in gribmap.txt.\n",
1088             varname2);
1089    return 1;
1090  }
1091
1092  status = gribhdr2filed(gh,*filefd,errmsg);
1093  if (status != 0) {
1094    fprintf (stderr,"write_grib: Error writing %s: \n\t%s\n",varname2,errmsg);
1095    return 1;
1096  }
1097
1098  free_gribhdr(&gh);
1099
1100  return 0;
1101}
1102
1103/***************************************************************************
1104 * Function to set up a structure containing forecast time parameters
1105 *  This encodes the standard grib forecast time parameters as well
1106 *  as WSI's extended forecast time parameters.
1107 ***************************************************************************/
1108
1109int get_fcst_time(int accum_period, int fcst_secs, FcstTimeStruct *ft)
1110{
1111  /*
1112   * Added ability to output a "5-minute" forecast time unit for the
1113   *   sake of WxProducer.  This allows WxPro to ingest data beyond
1114   *   18 hours, and accumulation data beyond 255 units.
1115   */
1116
1117  /*
1118   * Initialize.
1119   */
1120  ft->time_range = 0;
1121  ft->fcst_unit = 0;
1122  ft->P1 = 0;
1123  ft->P2 = 0;
1124  ft->fcst_unit_ext_1 = 0;
1125  ft->fcst_unit_ext_2 = 0;
1126  ft->P1_ext = 0;
1127  ft->P2_ext = 0;
1128  ft->time_range_ext = 0;
1129
1130  if (accum_period == 0) 
1131    {
1132      if (fcst_secs < MAX_FCST_SECS)
1133        {
1134          ft->time_range = 10;
1135          ft->fcst_unit = 254;
1136          ft->P1 = get_byte(fcst_secs,2);
1137          ft->P2 = get_byte(fcst_secs,1);
1138        }
1139      else if (((fcst_secs % SECS_IN_MIN) == 0) &&
1140               (fcst_secs < MAX_FCST_MINS))
1141        {
1142          ft->time_range = 10;
1143          ft->fcst_unit = 0;
1144          ft->P1 = get_byte(fcst_secs/SECS_IN_MIN,2);
1145          ft->P2 = get_byte(fcst_secs/SECS_IN_MIN,1);
1146        }
1147      else if (((fcst_secs % SECS_IN_MIN*MINS_IN_HOUR) == 0) && 
1148               (fcst_secs < MAX_FCST_HOURS))
1149        {
1150          ft->time_range = 10;
1151          ft->fcst_unit = 1;
1152          ft->P1 = get_byte(fcst_secs/(SECS_IN_MIN*MINS_IN_HOUR),2);
1153          ft->P2 = get_byte(fcst_secs/(SECS_IN_MIN*MINS_IN_HOUR),1);     
1154        }
1155      /*
1156       * MAX_FCST_DAYS is causing an integer overflow, so, we'll just skip
1157       *   the check here.  It's very unlikely that someone would exceed this
1158       *   anyway (5.6 million days!)
1159       */
1160      /*
1161      else if (((fcst_secs % SECS_IN_MIN*MINS_IN_HOUR*HOURS_IN_DAY) == 0) &&
1162               (fcst_secs < MAX_FCST_DAYS))
1163      */
1164      else if (((fcst_secs % SECS_IN_MIN*MINS_IN_HOUR*HOURS_IN_DAY) == 0))
1165        {
1166          ft->time_range = 10;
1167          ft->fcst_unit = 2;
1168          ft->P1 = 
1169            get_byte(fcst_secs/(SECS_IN_MIN*MINS_IN_HOUR*HOURS_IN_DAY),2);
1170          ft->P2 = 
1171            get_byte(fcst_secs/(SECS_IN_MIN*MINS_IN_HOUR*HOURS_IN_DAY),1);
1172        }
1173      else if (((fcst_secs % SECS_IN_MIN*MINS_IN_5MINS) == 0)
1174               && (fcst_secs < MAX_FCST_5MINS))
1175        {
1176          ft->time_range = 10;
1177          ft->fcst_unit = 50;
1178          ft->P1 = get_byte(fcst_secs/(SECS_IN_MIN*MINS_IN_5MINS),2);
1179          ft->P2 = get_byte(fcst_secs/(SECS_IN_MIN*MINS_IN_5MINS),1);
1180        }
1181      else 
1182        {
1183          ft->time_range = 255;
1184          ft->fcst_unit = 0;
1185          ft->P1 = 0;
1186          ft->P2 = 0;
1187         
1188          ft->fcst_unit_ext_1 = 254;
1189          ft->fcst_unit_ext_2 = 254;
1190          ft->P1_ext = fcst_secs;
1191          ft->P2_ext = 0;
1192          ft->time_range_ext = 0;
1193        }
1194    }
1195  else  /* Accumulation period is not 0 */
1196    {
1197      if ((fcst_secs < MAX1B_FCST_HOURS) &&
1198          (fcst_secs%(SECS_IN_MIN*MINS_IN_HOUR) == 0) && 
1199          (accum_period%(SECS_IN_MIN*MINS_IN_HOUR) == 0))
1200        {
1201          ft->time_range = 4;
1202          ft->fcst_unit = 1;
1203          ft->P1 = (fcst_secs-accum_period)/(SECS_IN_MIN*MINS_IN_HOUR);
1204          ft->P2 = fcst_secs/(SECS_IN_MIN*MINS_IN_HOUR);
1205        }
1206      else if ((fcst_secs < MAX1B_FCST_MINS) &&
1207               ((fcst_secs-accum_period)%SECS_IN_MIN == 0) && 
1208               (fcst_secs%SECS_IN_MIN == 0))
1209        {
1210          ft->time_range = 4;
1211          ft->fcst_unit = 0;
1212          ft->P1 = (fcst_secs-accum_period)/SECS_IN_MIN;
1213          ft->P2 = fcst_secs/SECS_IN_MIN;
1214        }
1215      else if (fcst_secs < MAX1B_FCST_SECS)
1216        {
1217          ft->time_range = 4;
1218          ft->fcst_unit = 254;
1219          ft->P1 = fcst_secs-accum_period;
1220          ft->P2 = fcst_secs;
1221        }
1222      else if ((fcst_secs < MAX1B_FCST_5MINS) && 
1223               (fcst_secs%(SECS_IN_MIN*MINS_IN_5MINS) == 0) &&
1224               (accum_period%(SECS_IN_MIN*MINS_IN_5MINS) == 0)) 
1225        {
1226          ft->time_range = 4;
1227          ft->fcst_unit = 50;
1228          ft->P1 = (fcst_secs-accum_period)/(SECS_IN_MIN*MINS_IN_5MINS);
1229          ft->P2 = fcst_secs/(SECS_IN_MIN*MINS_IN_5MINS);
1230        }
1231      else
1232        {
1233          ft->time_range = 255;
1234          ft->fcst_unit = 0;
1235          ft->P1 = 0;
1236          ft->P2 = 0;
1237         
1238          ft->fcst_unit_ext_1 = 254;
1239          ft->fcst_unit_ext_2 = 254;
1240          ft->P1_ext = fcst_secs - accum_period;
1241          ft->P2_ext = accum_period;
1242          ft->time_range_ext = 203;    /* Duration */
1243        }
1244    }
1245  return 0;
1246}
1247
1248
1249/******************************************************************************
1250 * returns a byt from an input integer
1251 *****************************************************************************/
1252
1253int get_byte(int input_int, int bytenum)
1254{
1255  int out;
1256  out = ((input_int >> (bytenum-1)*8) & ~(~0 <<8));
1257  return out;
1258}
1259
1260/*************************************************************************
1261 * Converts from WRF time format to time format required by grib routines
1262 *************************************************************************/
1263int grib_time_format(char *DateStr, char *DateStrIn)
1264{
1265  int year,month,day,hour,minute,second;
1266
1267  trim(DateStrIn);
1268  if (DateStrIn[0] == '*') {
1269    strcpy(DateStr,"*");
1270  }
1271  else
1272    {
1273      sscanf(DateStrIn,"%04d-%02d-%02d_%02d:%02d:%02d",
1274             &year,&month,&day,&hour,&minute,&second);
1275      sprintf(DateStr,"%04d%02d%02d%02d%02d%02d",
1276              year,month,day,hour,minute,second);
1277    }
1278
1279  return 0;
1280}
Note: See TracBrowser for help on using the repository browser.