source: lmdz_wrf/WRFV3/external/io_grib1/MEL_grib1/gribgetbds.c @ 1

Last change on this file since 1 was 1, checked in by lfita, 10 years ago
  • -- --- Opening of the WRF+LMDZ coupling repository --- -- -

WRF: version v3.3
LMDZ: version v1818

More details in:

File size: 13.8 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <math.h> 
4#include "dprints.h"            /* for dprints */
5#include "gribfuncs.h"          /* prototypes */
6/*
7  REVISION/MODIFICATION HISTORY:
8       03/07/94 written by Mugur Georgescu CSC, Monterey CA
9       02/01/96 modified by Steve Lowe SAIC, Monterey CA
10       04/17/96 modified by Alice Nakajima SAIC, Monterey CA
11       06/19/96 add hdrprint;/nakajima
12*
13* ********************************************************************
14* A.  FUNCTION:  gribgetbds
15*       decodes the Binary Data Section of the GRIB message
16*       and filling grib_data float array.
17*
18*    INTERFACE:
19*       int gribgetbds (curr_ptr, deci_scale, bms, gds,
20*                       ppgrib_data, bds_head, errmsg)
21*
22*    ARGUMENTS (I=input, O=output, I&O=input and output):
23*      (I)  char *curr_ptr;
24*           points to first Octet of the BDS to be decoded;
25*      (I)  short  deci_scale;
26*           decimal scaling factor to be applied to data;
27*      (I)  BMS_INPUT *bms;
28*           points to the decoded internal Bit Map Section Struct
29*      (I/O) grid_desc_sec *gds
30*           points to decoded internal grid definition struct
31*      (O)  float **ppgrib_data;
32*           double pointer to array of float, null upon entry;
33*           upon successful exit, holds the unpacked and restored float data
34*           in a newly malloced array;
35*      (O)  BDS_HEAD_INPUT *bds_head;
36*           points to Binary Data Sect hdr struct, empty upon entry;
37*           to be filled with decoded BDS info;
38*      (O)  char  *errmsg;
39*           Only returned filled when error occurred;
40*
41*      RETURN CODE:
42*        0>   no errors
43*        1>   unrecognized packing algorithm
44*        2>   number of points does not match bitmap
45*        3>   number of points does not match grid size in GDS
46*        4>   malloc error
47* ********************************************************************
48*/
49
50#if PROTOTYPE_NEEDED
51int gribgetbds ( char *curr_ptr, short  deci_scale, BMS_INPUT *bms,
52        grid_desc_sec *gds, float **ppgrib_data,
53        BDS_HEAD_INPUT *bds_head, char  *errmsg)
54#else
55int gribgetbds (curr_ptr, deci_scale, bms, gds, ppgrib_data, 
56                bds_head, errmsg)
57                char *curr_ptr; 
58                short  deci_scale; 
59                BMS_INPUT *bms;
60                grid_desc_sec *gds;
61                float **ppgrib_data; 
62                BDS_HEAD_INPUT *bds_head; 
63                char  *errmsg;
64#endif
65{
66char *func="gribgetbds";
67char *in = curr_ptr;      /* pointer to beginning of BDS */
68long length;              /* size of the Binary Data Section */
69long scale;               /* scaling factor */
70float ref_val;            /* reference value (minimum value) */
71unsigned long something;  /* generic value from message */
72long data_width;          /* number of bits that data occupies */
73int halfBYTE4;            /* the first 4 bits in 4-th byte */
74int status=0;
75int sign;                 /* sign + or - */
76float dscale;             /* 10 to the decimal scaling power */
77float bscale;             /* 2 to the binary scaling power   */
78unsigned long skip=0;              /* number of bits to be skipped */
79long c_ristic;            /* characteristic for float representation */
80long mantissa;            /* mantissa for float representation */
81long numpts;              /* number of bits left at end of bitstream */
82unsigned long data_pts;   /* number of data points in bitstream */
83unsigned long num_calc;   /* temp work var */
84float *grib_data=0;       /* local work array for grid data */
85float fdata=0;            /* data value stored in reference */
86int     i,j;         /* array counter */
87int xsize, ysize; 
88float *outdata;
89
90  DPRINT1 ("Entering %s()\n", func);
91/*
92*
93* A.1       FUNCTION gbyte !get bds length
94*/
95
96  gbyte(in,(unsigned long *) &length,&skip,24);
97  DPRINT0 ("bds_head->length\n");
98  bds_head->length = (unsigned long) length;
99
100/*
101*
102* A.2       FUNCTION gbyte !get BDS flag
103*/
104  gbyte(in, (unsigned long *) &halfBYTE4, &skip, 4);
105  DPRINT0 ("bds_head->usBDS_flag\n");
106  bds_head->usBDS_flag = (short) halfBYTE4;  /* get BDS Flag (Table 11) */
107
108/*
109*
110* A.3       IF (unsupported packing algorithm)  THEN
111*               RETURN 1
112*           ENDIF
113*/
114  /* need to check on packing algorithm */
115  if (halfBYTE4)  /* unrecognized packing algorithm */
116    {
117     DPRINT1 ("%s:  error, unrecognized packing algorithm\n", func);
118     sprintf(errmsg, "%s:  unrecognized packing algorithm\n", func);
119     status= (1);
120     goto BYE;
121    }
122
123/*
124*
125* A.4       FUNCTION gbyte !get number of unused bits
126*/
127  gbyte(in,(unsigned long *) &numpts,&skip,4); /* get #bits at end of BDS */
128  DPRINT0 ("numpts\n");
129
130/*
131*
132* A.5       FUNCTION gbyte !get Binary Scale Factor
133*/
134  gbyte(in,&something,&skip,16);
135  DPRINT0 ("Sign & bds_head->Bin_sc_fctr\n");
136  sign = (int)(something >> 15) & 1;  /* get sign for scale */
137  scale = (int)(something) & 32767;   /* get scale */
138  if(sign)                            /* scale negative */
139     scale = -scale;                  /* multiply scale by -1 */
140  bds_head->Bin_sc_fctr = (int) scale;  /* get binary scale factor */
141  DPRINT1 ("Binary Scale Factor = %d\n", scale);
142
143/*
144*
145* A.6       CALCULATE Reference value from IBM representation
146*             !FUNCTION gbyte !get the sign of reference
147*             !FUNCTION gbyte !get charateristic
148*             !FUNCTION gbyte !get the mantissa
149*/
150  gbyte(in,&something,&skip,8);
151  DPRINT0 ("Sign & Reference)\n");
152  sign = (int)(something >> 7) & 1; /* get the sign for reference value */
153
154  skip -= 7;
155  gbyte(in,(unsigned long *)&c_ristic,&skip,7); /*characteristic for the float*/
156  DPRINT0 ("c_ristic\n");
157
158  gbyte(in,(unsigned long*)&mantissa,&skip,24); /*mantissa for the float */
159  DPRINT0 ("mantissa\n");
160  c_ristic -= 64;                   /* subtract 64 from characteristic */
161  ref_val = (float) mantissa * (float)(pow(16.0,(double)c_ristic)) * 
162            (pow(2.0,-24.0));
163  if(sign)                          /* negative reference value */
164     ref_val = -ref_val;            /* multiply ref_val by -1 */
165  bds_head->fReference = (float)ref_val;
166  DPRINT1 ("Reference = %f\n", ref_val);
167
168/*
169*
170* A.7       FUNCTION gbyte !get data width
171*/
172  gbyte(in, (unsigned long*) &data_width,&skip,8);       /* get data width */
173  DPRINT0 ("bds_head->usBit_pack_num\n");
174  bds_head->usBit_pack_num = (short)data_width;
175
176/*
177*
178* A.8       SET Binary and Decimal Scale Factors
179*/
180  /* set binary scale */
181  bscale = (float)pow (2.0,(double) scale);
182
183  /* set decimal scale */
184  dscale = (float)pow (10.0, (double) deci_scale);
185
186  DPRINT2 ("Scaled-up BSF= (2**%d) = %f\n", scale, bscale);
187  DPRINT2 ("Scaled-up DSF= (10**%d) = %f\n", deci_scale,dscale);
188
189/*
190*
191* A.9       IF (data_width is zero) THEN
192*               ! grid contains a constant value
193*               IF expected grid size is invalid THEN
194*                  FORCE grid size of 1
195*               ENDIF
196*               ALLOCATE array for grid of expected grid size
197*               FILL grid with the constant value
198*               RETURN 0 !success
199*           ENDIF
200*/
201  if (!data_width)   /* grid contains constant value, success, all done */
202  {
203/* Used to send back array of 1 element:
204#     bds_head->ulGrid_size = 1;
205#     fdata = (float) (ref_val / dscale);
206#     *ppgrib_data = (float *) malloc(sizeof(float));
207#     **ppgrib_data = fdata;
208*/
209
210     fdata = (float) (ref_val / dscale);
211     if (bds_head->ulGrid_size <= 0) {
212        fprintf(stdout,
213        "WARNING:  gribgetbds detects bad ulGrid_size (%ld); "\
214        "Set to 1 to hold constant value %lf\n", bds_head->ulGrid_size, fdata);
215        bds_head->ulGrid_size = 1;
216        }
217   
218     grib_data =(float *) malloc(bds_head->ulGrid_size * sizeof(float));
219     if (!grib_data) {
220        sprintf(errmsg,
221        "%s: failed to create array[%d] for grid to hold Constant data", 
222        func, bds_head->ulGrid_size);
223        goto BYE;
224        }
225
226     *ppgrib_data = grib_data;          /* store address */
227     for (i=0; i < bds_head->ulGrid_size ; ) 
228        grib_data[i++] = fdata;         /* fill grid with constant val */
229
230     DPRINT3("%s:  grid[%ld] contains convant value %lf\n",
231        func, bds_head->ulGrid_size, fdata);
232
233     status = (0);  /* no errors */
234     goto BYE;
235  }
236
237  /* fill the data array with values from message */
238  /*     - Assume that GDS may not be included so that
239   *         the number of grid points may not be defined.       
240   *     - Compute space to malloc based on BDS length,
241   *         data_width, and numpts.
242   *     - if grid_size from GDS is zero, use
243   *         computed number of points.
244   */
245
246/*
247*
248* A.10      CALCULATE number of data points actually in BDS
249*/
250  num_calc = ((length - 11)*8 - numpts) / data_width;
251
252  /* Check the number of points computed against info in the BMS
253     or GDS, if they are available */
254
255/*
256*
257* A.11      IF (BMS is present and has included bitmap) THEN
258*               IF (#calculated not same as #bits set in BMS) THEN
259*                   RETURN 2
260*               ENDIF
261*/
262
263  if (bms->uslength > 6)
264  {
265      if (bms->ulbits_set != num_calc) {
266        DPRINT3 ("%s:  BMS present, #datapts calculated (%d) " \
267        "not same as BMS's set bits (%d)\n",func, num_calc, bms->ulbits_set);
268
269        sprintf(errmsg,"%s:  BMS present, #datapts calculated (%d) " \
270        "not same as BMS's set bits (%d)\n",func, num_calc, bms->ulbits_set);
271        status= (2); goto BYE;
272        }
273  }
274/*
275* A.11.1    ELSE  !no bms
276*               IF (GDS is present AND
277*                   #calculated not same as GDS's grid size)
278*               THEN
279*                   RETURN 3
280*               ENDIF
281*/
282 
283  else
284   
285  {   
286      if (bds_head->ulGrid_size && bds_head->ulGrid_size != num_calc) {
287        DPRINT0("Averting failure of grid size test\n");
288        /*
289        DPRINT3 ( "%s:  GDS present, #datapts calculated (%d) " \
290           "not same as GDS's grid size (%d)\n",
291           func,num_calc,bds_head->ulGrid_size);
292
293           sprintf(errmsg,"%s:  GDS present, #datapts calculated (%d) " \
294           "not same as GDS's grid size (%d)\n",
295           func,num_calc,bds_head->ulGrid_size);
296           status=(3); goto BYE;
297        */
298         }         
299  }
300   
301 
302/*
303* A.11      ENDIF (BMS present)
304*/
305
306  /* Only reach this point if number of points in BDS matches info
307     in BMS or GDS.  This number is unchecked if no BMS or GDS. */
308
309  /* Make sure number of points in BDS is value used for extracting */
310/*
311*
312* A.12      SET #datapoints
313*/
314  bds_head->ulGrid_size = num_calc;
315  data_pts= num_calc;
316
317/*
318*
319* A.13      ALLOCATE storage for float array size
320*           IF (error) THEN
321*               RETURN 4
322*           ENDIF
323*/
324  grib_data =(float *) malloc(data_pts * sizeof(float));
325  if (grib_data==NULL) { 
326        DPRINT1 ("%s: failed to malloc Grib_Data\n",func);
327        sprintf(errmsg,"%s: failed to malloc Grib_Data\n",func);
328        status=(4); goto BYE; }
329
330/*
331*
332* A.14      SET data array pointer to local data array
333*/
334  *ppgrib_data = grib_data;
335
336/*
337*
338* A.15      FOR (each data point) DO
339*               FUNCTION gbyte_quiet   !get data_width bits
340*               INCREMENT skip by data_width
341*               COMPUTE and STORE value in float array
342*           ENDDO
343*/
344
345  DPRINT3 ( "Restore float data by = (float)(%f + X * %f)) / %f;\n",
346  ref_val, bscale, dscale);
347
348  for(i=0;i < data_pts ;i++) 
349     {
350     gbyte_quiet(in,&something,&skip,data_width);
351     grib_data[i]= (float)(ref_val + (something * bscale))/dscale;
352     }
353
354/*
355 * Unthin grid if it is thinned
356 */
357  if (gds->head.thin != NULL) {
358    if ((gds->head.usData_type == LATLON_PRJ) || 
359        (gds->head.usData_type == GAUSS_PRJ) ||
360        (gds->head.usData_type == ROT_LATLON_PRJ) ||
361        (gds->head.usData_type == ROT_GAUSS_PRJ) ||
362        (gds->head.usData_type == STR_LATLON_PRJ) ||
363        (gds->head.usData_type == STR_GAUSS_PRJ) ||
364        (gds->head.usData_type == STR_ROT_LATLON_PRJ) ||
365        (gds->head.usData_type == STR_ROT_GAUSS_PRJ)) {
366      ysize = gds->llg.usNj;
367    } else if (gds->head.usData_type == MERC_PRJ) {
368      ysize = gds->merc.rows;
369    } else if (gds->head.usData_type == POLAR_PRJ) {
370      ysize = gds->pol.usNy;
371    } else if ((gds->head.usData_type == LAMB_PRJ) ||
372               (gds->head.usData_type == ALBERS_PRJ) ||
373               (gds->head.usData_type == OBLIQ_LAMB_PRJ)) {
374      ysize = gds->lam.iNy;
375    } else {
376       DPRINT2 ("%s:  unknown datatype=%d\n",func, gds->head.usData_type);
377       sprintf(errmsg,"%s:  unknown datatype=%d\n",func, gds->head.usData_type);
378       status=1;         /* set status to failure */
379    }
380
381    xsize = 0;
382    for (j = 0; j<ysize; j++) {
383      if (gds->head.thin[j] > xsize) {
384        xsize = gds->head.thin[j];
385      }
386    }
387    outdata = (float *)malloc(ysize*xsize*sizeof(float));
388    grib_unthin(grib_data,outdata,gds->head.thin,ysize,
389          &xsize);
390    free(grib_data);
391    grib_data = (float *)malloc(sizeof(float)*ysize*xsize);
392    *ppgrib_data = grib_data;
393    memcpy(grib_data,outdata,sizeof(float)*ysize*xsize);
394    free(outdata);
395    free(gds->head.thin);
396    gds->head.thin = NULL;
397    if ((gds->head.usData_type == LATLON_PRJ) || 
398        (gds->head.usData_type == GAUSS_PRJ) ||
399        (gds->head.usData_type == ROT_LATLON_PRJ) ||
400        (gds->head.usData_type == ROT_GAUSS_PRJ) ||
401        (gds->head.usData_type == STR_LATLON_PRJ) ||
402        (gds->head.usData_type == STR_GAUSS_PRJ) ||
403        (gds->head.usData_type == STR_ROT_LATLON_PRJ) ||
404        (gds->head.usData_type == STR_ROT_GAUSS_PRJ)) {
405      gds->llg.usNi = xsize;
406      gds->llg.iDi = abs(gds->llg.lLat2 - gds->llg.lLat1)/(xsize-1);
407    } else if (gds->head.usData_type == MERC_PRJ) {
408      gds->merc.cols = xsize;
409    } else if (gds->head.usData_type == POLAR_PRJ) {
410      gds->pol.usNx = xsize;
411    } else if ((gds->head.usData_type == LAMB_PRJ) ||
412               (gds->head.usData_type == ALBERS_PRJ) ||
413               (gds->head.usData_type == OBLIQ_LAMB_PRJ)) {
414      gds->lam.iNx = xsize;
415    } else {
416       DPRINT2 ("%s:  unknown datatype=%d\n",func, gds->head.usData_type);
417       sprintf(errmsg,"%s:  unknown datatype=%d\n",func, gds->head.usData_type);
418       status=1;         /* set status to failure */
419    }
420  }
421
422  DPRINT0 ("Sample of first 30 unpacked & restored datapoints=\n");
423  for (i=0; i < 30; i+=5)
424     DPRINT6 ("%03d:  %f %f %f %f %f\n",
425        i, grib_data[i], grib_data[i+1],grib_data[i+2],
426        grib_data[i+3], grib_data[i+4] );
427 
428BYE:
429/*
430*
431* A.16      RETURN Status;
432*/
433  DPRINT2 ("Exiting %s, status=%d\n", func, status);
434  return(status); 
435/*
436* END OF FUNCTION
437*
438*/
439}   
Note: See TracBrowser for help on using the repository browser.