stream_gribapi.c 68.4 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
2
3
4
5
6
#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

#include <stdio.h>

Uwe Schulzweida's avatar
Uwe Schulzweida committed
7
#include "dmemory.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
8
9
10
11
12
13
#include "cdi.h"
#include "stream_int.h"
#include "file.h"
#include "varscan.h"
#include "datetime.h"
#include "vlist.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
14
#include "stream_grb.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
15
16
17
18


#if  defined  (HAVE_LIBGRIB_API)
#  include "cgribex.h"      /* gribGetSize, gribRead, gribGetZip */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
19
#  include "gribapi.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
20
21
22
23
24
25
26
#  include "grib_api.h"
#endif


extern int cdiInventoryMode;

typedef struct {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
27
  int param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
28
29
30
31
32
33
34
35
  int level1;
  int level2;
  int ltype;
} compvar2_t; 


#if  defined  (HAVE_LIBGRIB_API)
static
36
int gribapiGetGridType(grib_handle *gh)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
37
{
38
39
  int gridtype = GRID_GENERIC;
  int gribgridtype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
40
41
  long lpar;

42
43
44
45
46
47
    {
      GRIB_CHECK(grib_get_long(gh, "gridDefinitionTemplateNumber", &lpar), 0);
      gribgridtype = (int) lpar;

      switch (gribgridtype)
	{
48
	case  GRIB2_GTYPE_LATLON:     { GRIB_CHECK(grib_get_long(gh, "Ni", &lpar), 0);
49
	                                if ( lpar == GRIB_MISSING_LONG ) break;
50
                                      }
51
52
	case  GRIB2_GTYPE_LATLON_ROT: { gridtype = GRID_LONLAT;    break; }
	case  GRIB2_GTYPE_LCC:        { gridtype = GRID_LCC;       break; }
53
	case  GRIB2_GTYPE_GAUSSIAN:   { GRIB_CHECK(grib_get_long(gh, "Ni", &lpar), 0);
54
					if ( lpar == GRIB_MISSING_LONG )
55
56
57
58
59
					  gridtype = GRID_GAUSSIAN_REDUCED;
					else
					  gridtype = GRID_GAUSSIAN;
					break;
                                      }
60
61
62
	case  GRIB2_GTYPE_SPECTRAL:   { gridtype = GRID_SPECTRAL;  break; }
	case  GRIB2_GTYPE_GME:        { gridtype = GRID_GME;       break; }
	case  GRIB2_GTYPE_NUMBER:     { gridtype = GRID_REFERENCE; break; }
63
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
64
65
66
67
68
69
    }

  return (gridtype);
}
#endif

Uwe Schulzweida's avatar
Uwe Schulzweida committed
70
#if  defined  (HAVE_LIBGRIB_API)
71
static
72
int gribapiGetIsRotated(grib_handle *gh)
73
74
{
  int isRotated = 0;
75
76
  int gribgridtype;
  long lpar;
77
78

    {
79
80
81
82
      GRIB_CHECK(grib_get_long(gh, "gridDefinitionTemplateNumber", &lpar), 0);
      gribgridtype = (int) lpar;

      if ( gribgridtype == GRIB2_GTYPE_LATLON_ROT ) isRotated = 1;
83
84
85
86
    }

  return (isRotated);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
87
#endif
88

Uwe Schulzweida's avatar
Uwe Schulzweida committed
89
90
#if  defined  (HAVE_LIBGRIB_API)
static
91
int gribapiGetZaxisType(long editionNumber, int grib_ltype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
92
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
94
95
  int zaxistype = ZAXIS_GENERIC;

  if ( editionNumber <= 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
96
    {
97
      zaxistype = grib1ltypeToZaxisType(grib_ltype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
98
99
100
    }
  else
    {
101
      zaxistype = grib2ltypeToZaxisType(grib_ltype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
102
103
104
105
106
107
    }

  return (zaxistype);
}
#endif

108
109
110
111
112
113
#if  defined  (HAVE_LIBGRIB_API)
static
int gribapiGetTimeUnits(grib_handle *gh)
{
  int timeunits = -1;
  long lpar;
114
115
  size_t len = 8;
  char stepunits[8];
116
117
  static int lprint = TRUE;

118
119
  GRIB_CHECK(grib_get_string(gh, "stepUnits", stepunits, &len), 0);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
120
121
122
123
124
125
126
127
128
129
130
  len--;

  if      ( memcmp(stepunits, "s",   len) == 0 ) timeunits = TUNIT_SECOND;
  else if ( memcmp(stepunits, "m",   len) == 0 ) timeunits = TUNIT_MINUTE;
  else if ( memcmp(stepunits, "h",   len) == 0 ) timeunits = TUNIT_HOUR;
  else if ( memcmp(stepunits, "3h",  len) == 0 ) timeunits = TUNIT_3HOURS;
  else if ( memcmp(stepunits, "6h",  len) == 0 ) timeunits = TUNIT_6HOURS;
  else if ( memcmp(stepunits, "12h", len) == 0 ) timeunits = TUNIT_12HOURS;
  else if ( memcmp(stepunits, "D",   len) == 0 ) timeunits = TUNIT_DAY;
  else if ( memcmp(stepunits, "M",   len) == 0 ) timeunits = TUNIT_MONTH;
  else if ( memcmp(stepunits, "Y",   len) == 0 ) timeunits = TUNIT_YEAR;
131
  else if ( lprint )
132
    {
133
      Message("Step units >%s< unsupported!", stepunits);
134
      lprint = FALSE;
135
136
137
138
139
140
141
142
143
144
    }

  return (timeunits);
}
#endif

#if  defined  (HAVE_LIBGRIB_API)
static
int gribapiTimeIsFC(grib_handle *gh)
{
145
  long editionNumber;
146
147
  int isFC = TRUE;

148
  GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);
149

150
151
152
153
154
155
156
157
  if ( editionNumber == 2 )
    {
      long sigofrtime;

      GRIB_CHECK(grib_get_long(gh, "significanceOfReferenceTime", &sigofrtime), 0);

      if ( sigofrtime == 3 ) isFC = FALSE;
    }
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

  return (isFC);
}
#endif

#if  defined  (HAVE_LIBGRIB_API)
static
int gribapiGetTsteptype(grib_handle *gh)
{
  int tsteptype = 0;
  int timerange;
  long lpar;
  static int lprint = TRUE;

  if ( gribapiTimeIsFC(gh) )
    {
      GRIB_CHECK(grib_get_long(gh, "stepType", &lpar), 0);
      timerange = (int) lpar;

      // printf("timerange %d\n", timerange);

      switch ( timerange )
	{
	case  0:  tsteptype = TSTEP_AVG;    break;
	case  1:  tsteptype = TSTEP_ACCUM;  break;
	case  2:  tsteptype = TSTEP_MIN;    break;
	case  3:  tsteptype = TSTEP_MAX;    break;
	case  4:  tsteptype = TSTEP_DIFF;   break;
	default:
	  if ( lprint )
	    {
189
	      Message("Time range %d unsupported", timerange);
190
191
192
193
194
195
196
197
198
199
	      lprint = FALSE;
	    }
	}
    }

  return (tsteptype);
}
#endif

#if  defined  (HAVE_LIBGRIB_API)
200
static
201
202
203
void gribapiGetValidityDateTime(grib_handle *gh, int *vdate, int *vtime)
{
  long lpar;
204
205
206
207
208
209
210
211
212
  long sigofrtime = 3;
  long editionNumber;

  GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);

  if ( editionNumber == 2 )
    {
      GRIB_CHECK(grib_get_long(gh, "significanceOfReferenceTime", &sigofrtime), 0);
    }
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230

  if ( sigofrtime == 3 )
    {
      GRIB_CHECK(grib_get_long(gh, "dataDate", &lpar), 0);
      *vdate = (int) lpar;
      GRIB_CHECK(grib_get_long(gh, "dataTime", &lpar), 0);
      *vtime = (int) lpar*100;
    }
  else
    {
      GRIB_CHECK(grib_get_long(gh, "validityDate", &lpar), 0);
      *vdate = (int) lpar;
      GRIB_CHECK(grib_get_long(gh, "validityTime", &lpar), 0);
      *vtime = (int) lpar*100;
    }
}
#endif

Uwe Schulzweida's avatar
Uwe Schulzweida committed
231
#if  defined  (HAVE_LIBGRIB_API)
232
static
233
void gribapiGetGrid(grib_handle *gh, grid_t *grid)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
234
{
235
  long editionNumber;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
236
  int gridtype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
237
  size_t datasize;
238
239
  long numberOfPoints;
  long lpar;
240
241
242

  GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);

243
  gridtype = gribapiGetGridType(gh);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
244
245
246
247
248
249
250
251
  /*
  if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED )
    {
      gridtype = GRID_GAUSSIAN;
      ISEC2_NumLon = 2*ISEC2_NumLat;
      ISEC4_NumValues = ISEC2_NumLon*ISEC2_NumLat;
    }
  */
252
  memset(grid, 0, sizeof(grid_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
253

Uwe Schulzweida's avatar
Uwe Schulzweida committed
254
255
256
  GRIB_CHECK(grib_get_size(gh, "values", &datasize), 0);
  GRIB_CHECK(grib_get_long(gh, "numberOfPoints", &numberOfPoints), 0);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
257
258
259
260
261
262
263
264
265
266
267
268
269
  switch (gridtype)
    {
    case GRID_LONLAT:
    case GRID_GAUSSIAN:
      {
	int nlon, nlat;

	GRIB_CHECK(grib_get_long(gh, "Ni", &lpar), 0);
	nlon = lpar;
	GRIB_CHECK(grib_get_long(gh, "Nj", &lpar), 0);
	nlat = lpar;

	if ( numberOfPoints != nlon*nlat )
270
	  Error("numberOfPoints (%d) and gridSize (%d) differ!",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
271
		(int)numberOfPoints, nlon*nlat);
272
273
274
275
276
277
278
279
280
281
282
	grid->size  = numberOfPoints;
	grid->xsize = nlon;
	grid->ysize = nlat;
	grid->xinc  = 0;
	grid->yinc  = 0;
	grid->xdef  = 0;
	GRIB_CHECK(grib_get_double(gh, "longitudeOfFirstGridPointInDegrees", &grid->xfirst), 0);
	GRIB_CHECK(grib_get_double(gh, "longitudeOfLastGridPointInDegrees",  &grid->xlast), 0);
	GRIB_CHECK(grib_get_double(gh, "latitudeOfFirstGridPointInDegrees",  &grid->yfirst), 0);
	GRIB_CHECK(grib_get_double(gh, "latitudeOfLastGridPointInDegrees",   &grid->ylast), 0);
	GRIB_CHECK(grib_get_double(gh, "iDirectionIncrementInDegrees", &grid->xinc), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
283
	if ( gridtype == GRID_LONLAT )
284
	  GRIB_CHECK(grib_get_double(gh, "jDirectionIncrementInDegrees", &grid->yinc), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
285

286
	if ( IS_EQUAL(grid->xinc, GRIB_MISSING_DOUBLE) ) grid->xinc = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
287

288
	/* if ( IS_NOT_EQUAL(grid->xfirst, 0) || IS_NOT_EQUAL(grid->xlast, 0) ) */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
289
	  {
290
	    if ( grid->xsize > 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
291
	      {
292
		if ( (grid->xfirst > grid->xlast) && (grid->xfirst >= 180) ) grid->xfirst -= 360;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
293

294
295
296
		if ( editionNumber <= 1 )
		  {
		    /* correct xinc if necessary */
297
		    if ( IS_EQUAL(grid->xfirst, 0) && grid->xlast > 354 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
298
		      {
299
			double xinc = 360. / grid->xsize;
300
		      
301
			if ( fabs(grid->xinc-xinc) > 0.0 )
302
			  {
303
304
			    grid->xinc = xinc;
			    if ( CDI_Debug ) Message("set xinc to %g", grid->xinc);
305
			  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
306
307
308
		      }
		  }
	      }
309
	    grid->xdef   = 2;	    
Uwe Schulzweida's avatar
Uwe Schulzweida committed
310
	  }
311
312
	grid->ydef  = 0;
        /* if ( IS_NOT_EQUAL(grid->yfirst, 0) || IS_NOT_EQUAL(grid->ylast, 0) ) */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
313
	  {
314
	    if ( grid->ysize > 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
315
	      {
316
317
318
		if ( editionNumber <= 1 )
		  {
		  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
319
	      }
320
	    grid->ydef   = 2;	    
Uwe Schulzweida's avatar
Uwe Schulzweida committed
321
322
323
324
325
	  }
	break;
      }
    case GRID_GAUSSIAN_REDUCED:
      {
326
327
328
329
330
331
332
	int nlat, i;
	size_t dummy;
	long *pl;

	GRIB_CHECK(grib_get_long(gh, "Nj", &lpar), 0);
	nlat = lpar;

333
	grid->size   = numberOfPoints;
334

335
        grid->rowlon = (int *) malloc(nlat*sizeof(int));
336
337
338
        pl          = (long *) malloc(nlat*sizeof(long));
	dummy       = nlat;
	GRIB_CHECK(grib_get_long_array(gh, "pl", pl, &dummy), 0);
339
	for ( i = 0; i < nlat; ++i ) grid->rowlon[i] = pl[i];
340
341
	free(pl);

342
343
344
345
346
347
348
349
350
	grid->ysize  = nlat;
	grid->xinc   = 0;
	grid->yinc   = 0;
	grid->xdef   = 0;
	GRIB_CHECK(grib_get_double(gh, "longitudeOfFirstGridPointInDegrees", &grid->xfirst), 0);
	GRIB_CHECK(grib_get_double(gh, "longitudeOfLastGridPointInDegrees",  &grid->xlast), 0);
	GRIB_CHECK(grib_get_double(gh, "latitudeOfFirstGridPointInDegrees",  &grid->yfirst), 0);
	GRIB_CHECK(grib_get_double(gh, "latitudeOfLastGridPointInDegrees",   &grid->ylast), 0);
	GRIB_CHECK(grib_get_double(gh, "iDirectionIncrementInDegrees", &grid->xinc), 0);
351

352
	if ( IS_EQUAL(grid->xinc, GRIB_MISSING_DOUBLE) ) grid->xinc = 0;
353

354
	/* if ( IS_NOT_EQUAL(grid->xfirst, 0) || IS_NOT_EQUAL(grid->xlast, 0) ) */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
355
	  {
356
	    if ( grid->xsize > 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
357
	      {
358
		if ( (grid->xfirst > grid->xlast) && (grid->xfirst >= 180) ) grid->xfirst -= 360;
359
360
361
362

		if ( editionNumber <= 1 )
		  {
		    /* correct xinc if necessary */
363
		    if ( IS_EQUAL(grid->xfirst, 0) && grid->xlast > 354 )
364
		      {
365
			double xinc = 360. / grid->xsize;
366
		      
367
			if ( fabs(grid->xinc-xinc) > 0.0 )
368
			  {
369
370
			    grid->xinc = xinc;
			    if ( CDI_Debug ) Message("set xinc to %g", grid->xinc);
371
372
373
			  }
		      }
		  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
374
	      }
375
	    grid->xdef   = 2;	    
Uwe Schulzweida's avatar
Uwe Schulzweida committed
376
	  }
377
378
	grid->ydef  = 0;
        /* if ( IS_NOT_EQUAL(grid->yfirst, 0) || IS_NOT_EQUAL(grid->ylast, 0) ) */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
379
	  {
380
	    if ( grid->ysize > 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
381
	      {
382
383
384
		if ( editionNumber <= 1 )
		  {
		  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
385
	      }
386
	    grid->ydef   = 2;	    
Uwe Schulzweida's avatar
Uwe Schulzweida committed
387
388
389
	  }
	break;
      }
390
      /*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
391
392
393
    case GRID_LCC:
      {
	if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
394
	  Error("numberOfPoints (%d) and gridSize (%d) differ!",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
395
396
		ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);

397
398
399
	grid->size  = ISEC4_NumValues;
	grid->xsize = ISEC2_NumLon;
	grid->ysize = ISEC2_NumLat;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
400

401
402
403
404
405
406
407
408
409
	grid->lcc_xinc      = ISEC2_Lambert_dx;
	grid->lcc_yinc      = ISEC2_Lambert_dy;
	grid->lcc_originLon = ISEC2_FirstLon * 0.001;
	grid->lcc_originLat = ISEC2_FirstLat * 0.001;
	grid->lcc_lonParY   = ISEC2_Lambert_Lov * 0.001;
	grid->lcc_lat1      = ISEC2_Lambert_LatS1 * 0.001;
	grid->lcc_lat2      = ISEC2_Lambert_LatS2 * 0.001;
	grid->lcc_projflag  = ISEC2_Lambert_ProjFlag;
	grid->lcc_scanflag  = ISEC2_ScanFlag;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
410

411
412
	grid->xdef   = 0;	    
	grid->ydef   = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
413
414
415

	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
416
      */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
417
418
    case GRID_SPECTRAL:
      {
419
420
	size_t len = 256;
	char typeOfPacking[256];
421
	GRIB_CHECK(grib_get_string(gh, "packingType", typeOfPacking, &len), 0);
422
423
	grid->lcomplex = 0;
	if ( strncmp(typeOfPacking, "spectral_complex", len) == 0 ) grid->lcomplex = 1;
424

425
	grid->size  = datasize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
426
	GRIB_CHECK(grib_get_long(gh, "J", &lpar), 0);
427
	grid->trunc = lpar;
428

Uwe Schulzweida's avatar
Uwe Schulzweida committed
429
430
431
432
	break;
      }
    case GRID_GME:
      {
433
434
435
436
437
	grid->size  = numberOfPoints;
	if ( grib_get_long(gh, "nd", &lpar) == 0 ) grid->nd  = lpar;
	if ( grib_get_long(gh, "Ni", &lpar) == 0 ) grid->ni  = lpar;
	if ( grib_get_long(gh, "n2", &lpar) == 0 ) grid->ni2 = lpar;
	if ( grib_get_long(gh, "n3", &lpar) == 0 ) grid->ni3 = lpar;
438
439
440

	break;
      }
441
    case GRID_REFERENCE:
442
      {
443
444
445
446
	char reference_link[8192];
	size_t len = sizeof(reference_link);
	reference_link[0] = 0;

447
	grid->size  = numberOfPoints;
448
449
	if ( grib_get_long(gh, "numberOfGridUsed", &lpar) == 0 )
	  {
450
451
	    grid->number   = lpar;
	    if ( grib_get_long(gh, "numberOfGridInReference", &lpar) == 0 ) grid->position = lpar;
452
453
	    if ( grib_get_string(gh, "gridDescriptionFile", reference_link, &len) == 0 )
	      {
454
		if ( strncmp(reference_link, "file://", 7) == 0 )
455
		  grid->reference = strdupx(reference_link);
456
457
	      }
	  }
458

Uwe Schulzweida's avatar
Uwe Schulzweida committed
459
460
461
462
	break;
      }
    case GRID_GENERIC:
      {
463
464
465
466
467
	int nlon = 0, nlat = 0;

	if ( grib_get_long(gh, "Ni", &lpar) == 0 ) nlon = lpar;
	if ( grib_get_long(gh, "Nj", &lpar) == 0 ) nlat = lpar;

468
	grid->size  = numberOfPoints;
469

470
	if ( nlon > 0 && nlat > 0 && nlon*nlat == grid->size )
471
	  {
472
473
	    grid->xsize = nlon;
	    grid->ysize = nlat;
474
475
476
	  }
	else
	  {
477
478
	    grid->xsize = 0;
	    grid->ysize = 0;
479
480
	  }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
481
482
483
484
	break;
      }
    default:
      {
485
	Error("Unsupported grid type: %s", gridNamePtr(gridtype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
486
487
488
489
	break;
      }
    }

490
  grid->isRotated = FALSE;
491
  if ( gribapiGetIsRotated(gh) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
    {
493
494
495
496
      grid->isRotated = TRUE;
      GRIB_CHECK(grib_get_double(gh, "latitudeOfSouthernPoleInDegrees",  &grid->ypole), 0);
      GRIB_CHECK(grib_get_double(gh, "longitudeOfSouthernPoleInDegrees", &grid->xpole), 0);
      GRIB_CHECK(grib_get_double(gh, "angleOfRotation", &grid->angle), 0);
497
      /* change from south to north pole */
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
      grid->ypole = -grid->ypole;
      grid->xpole =  grid->xpole - 180;
    }

  grid->xvals = NULL;
  grid->yvals = NULL;
  grid->type  = gridtype;
}
#endif

#if  defined  (HAVE_LIBGRIB_API)
static
double grib1GetLevel(grib_handle *gh, int leveltype)
{
  double dlevel;

  GRIB_CHECK(grib_get_double(gh, "level", &dlevel), 0);
  if ( leveltype == 100 ) dlevel *= 100;
  if ( dlevel < -2.e9 || dlevel > 2.e9 ) dlevel = 0;

  return (dlevel);
}

static
double grib2GetLevel(grib_handle *gh, int leveltype)
{
  double dlevel;

  GRIB_CHECK(grib_get_double(gh, "level", &dlevel), 0);
  if ( leveltype == 100 ) dlevel *= 100;
  if ( dlevel < -2.e9 || dlevel > 2.e9 ) dlevel = 0;

  return (dlevel);
}

static
void gribapiAddRecord(int streamID, int param, grib_handle *gh,
		      long recsize, off_t position, int prec, int ztype)
{
  long editionNumber;
  int zaxistype;
  int gridID = CDI_UNDEFID, varID;
  int levelID = 0;
  int tsID, recID;
  int level1, level2;
  int numavg;
  int tsteptype;
  int lbounds = 0;
  record_t *record;
  grid_t grid;
  int vlistID;
  stream_t *streamptr;
  int leveltype;
  double dlevel;
  long lpar;
  int status;
  char name[256], longname[256], units[256];
  size_t vlen; 

  streamptr = stream_to_pointer(streamID);

  vlistID = streamInqVlist(streamID);
  tsID    = streamptr->curTsID;
  recID   = recordNewEntry(streamID, tsID);
  record  = &streamptr->tsteps[tsID].records[recID];

  tsteptype = gribapiGetTsteptype(gh);
  // numavg  = ISEC1_AvgNum;
  numavg  = 0;

  GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);

  if ( editionNumber <= 1 )
    {
      status = grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar);
      if ( status == 0 )
	{
	  leveltype = (int) lpar;
	  dlevel = grib1GetLevel(gh, leveltype);
	  if ( leveltype == 99 ) leveltype++;
	}
      else 
	{
	  leveltype = 0;
	  dlevel = 0;
	}
    }
  else
    {
      status = grib_get_long(gh, "typeOfFirstFixedSurface", &lpar);
      if ( status == 0 )
	{
	  leveltype = (int) lpar;
	  dlevel = grib2GetLevel(gh, leveltype);
	  if ( leveltype == 99 ) leveltype++;
	}
      else 
	{
	  leveltype = 0;
	  dlevel = 0;
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
599
    }
600

601
602
603
604
605
606
607
608
609
610
611
612
613
  level1 = (int) dlevel;
  level2 = 0;

  // fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, leveltype);

  (*record).size     = recsize;
  (*record).position = position;
  (*record).param    = param;
  (*record).ilevel   = level1;
  (*record).ilevel2  = level2;
  (*record).ltype    = leveltype;

  gribapiGetGrid(gh, &grid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
614
615
616

  gridID = varDefGrid(vlistID, grid, 0);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
617
  zaxistype = gribapiGetZaxisType(editionNumber, leveltype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
618

619
  if ( zaxistype == ZAXIS_HYBRID || zaxistype == ZAXIS_HYBRID_HALF )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
620
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
621
      int vctsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
622
      size_t dummy;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
623
      double *vctptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
624

Uwe Schulzweida's avatar
Uwe Schulzweida committed
625
626
      GRIB_CHECK(grib_get_long(gh, "NV", &lpar), 0);
      vctsize = lpar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
627
628
629
630
631
632
633
634
      if ( vctsize > 0 )
	{
	  vctptr = (double *) malloc(vctsize*sizeof(double));
	  dummy = vctsize;
	  GRIB_CHECK(grib_get_double_array(gh, "pv", vctptr, &dummy), 0);
	  varDefVCT(vctsize, vctptr);
	  free(vctptr);
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
635
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
636

Uwe Schulzweida's avatar
Uwe Schulzweida committed
637
638
639
640
641
  //lbounds = cgribexGetZaxisHasBounds(ISEC1_LevelType);

  if ( prec > 32 ) prec = DATATYPE_PACK32;
  if ( prec <  0 ) prec = DATATYPE_PACK;

642
643
644
645
  name[0] = 0;
  longname[0] = 0;
  units[0] = 0;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
646
647
  vlen = 256;
  GRIB_CHECK(grib_get_string(gh, "shortName", name, &vlen), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
648
649
650
651
652
653
654
655
656
657
658
659
  if      ( vlen == 8 && memcmp(name, "unknown", vlen) == 0 ) name[0] = 0;
  else if ( vlen == 2 && memcmp(name, "~", vlen)       == 0 ) name[0] = 0;

  if ( name[0] != 0 )
    {
      vlen = 256;
      GRIB_CHECK(grib_get_string(gh, "name", longname, &vlen), 0);
      if ( vlen == 8 && memcmp(longname, "unknown", vlen) == 0 ) longname[0] = 0;
      vlen = 256;
      GRIB_CHECK(grib_get_string(gh, "units", units, &vlen), 0);
      if ( vlen == 8 && memcmp(units, "unknown", vlen) == 0 ) units[0] = 0;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
660
  // fprintf(stderr, "param %d name %s %s %s\n", param, name, longname, units); 
Uwe Schulzweida's avatar
Uwe Schulzweida committed
661

Uwe Schulzweida's avatar
Uwe Schulzweida committed
662
  varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2,
663
	       prec, &varID, &levelID, 0, numavg, leveltype,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
664
	       name, longname, units);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
665
666
667
668
669
670
671
672

  (*record).varID   = varID;
  (*record).levelID = levelID;

  varDefZtype(varID, ztype);

  if ( varInqInst(varID) == CDI_UNDEFID )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
673
674
675
676
677
      long center, subcenter;
      int instID;
      GRIB_CHECK(grib_get_long(gh, "centre", &center), 0);
      GRIB_CHECK(grib_get_long(gh, "subCentre", &subcenter), 0);
      instID    = institutInq((int)center, (int)subcenter, NULL, NULL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
678
      if ( instID == CDI_UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
679
	instID = institutDef((int)center, (int)subcenter, NULL, NULL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
680
681
682
683
684
685
      varDefInst(varID, instID);
    }

  if ( varInqModel(varID) == CDI_UNDEFID )
    {
      int modelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
686
      long processID;
687
688
689
690
691
692
693
694
      status = grib_get_long(gh, "generatingProcessIdentifier", &processID);
      if ( status == 0 )
	{
	  modelID = modelInq(varInqInst(varID), processID, NULL);
	  if ( modelID == CDI_UNDEFID )
	    modelID = modelDef(varInqInst(varID), processID, NULL);
	  varDefModel(varID, modelID);
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
695
696
697
698
    }

  if ( varInqTable(varID) == CDI_UNDEFID )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
699
      int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
700

Uwe Schulzweida's avatar
Uwe Schulzweida committed
701
      cdiDecodeParam(param, &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
702

Uwe Schulzweida's avatar
Uwe Schulzweida committed
703
704
705
706
      if ( pdis == 255 )
	{
	  int tableID;
	  int tabnum = pcat;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
707

Uwe Schulzweida's avatar
Uwe Schulzweida committed
708
	  tableID = tableInq(varInqModel(varID), tabnum, NULL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
709

Uwe Schulzweida's avatar
Uwe Schulzweida committed
710
711
712
	  if ( tableID == CDI_UNDEFID )
	    tableID = tableDef(varInqModel(varID), tabnum, NULL);
	  varDefTable(varID, tableID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
713
714
715
716
717
718
719
	}
    }

  streamptr->tsteps[tsID].nallrecs++;
  streamptr->nrecs++;

  if ( CDI_Debug )
720
    Message("varID = %d  param = %d  zaxistype = %d  gridID = %d  levelID = %d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
721
	    varID, param, zaxistype, gridID, levelID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
722
723
724
}
#endif

725
int gribapiScanTimestep1(int streamID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
726
727
728
729
730
731
{
#if  defined  (HAVE_LIBGRIB_API)
  off_t recpos = 0;
  unsigned char *gribbuffer = NULL;
  long buffersize = 0;
  int iret = 0, ipunp = 0, iword = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
732
  int rstatus;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
733
734
  int status;
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
735
  int rtabnum = 0;
736
737
  int rcode = 0, level1 = 0, level2 = 0;
  int vdate = 0, vtime = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
738
  int param = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
739
740
741
742
743
744
745
746
747
748
749
  DateTime datetime, datetime0;
  int tsID;
  int varID;
  size_t readsize;
  int nrecords, nrecs, recID;
  int prec;
  long recsize = 0;
  int warn_time = TRUE;
  int warn_numavg = TRUE;
  int taxisID = -1;
  int rdate = 0, rtime = 0, tunit = 0, fcast = 0;
750
  taxis_t *taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
751
752
753
754
755
756
757
  int vlistID;
  int ztype;
  long unzipsize;
  compvar2_t compVar, compVar0;
  stream_t *streamptr;
  grib_handle *gh = NULL;
  int leveltype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
758
  int pdis = 0, pcat = 0, pnum = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
759
760
  long editionNumber;
  long lpar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
761
  int bitsPerValue;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
762
763
764
765
  double dlevel = 0;

  streamptr = stream_to_pointer(streamID);

766
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
767
768
769
770
771
772
773

  streamptr->curTsID = 0;

  tsID  = tstepsNewEntry(streamID);
  taxis = &streamptr->tsteps[tsID].taxis;

  if ( tsID != 0 )
774
    Error("Internal problem! tstepsNewEntry returns %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795

  fileID = streamInqFileID(streamID);

  nrecs = 0;
  while ( TRUE )
    {
      recsize = gribGetSize(fileID);
      recpos  = fileGetPos(fileID);

      if ( recsize == 0 )
	{
	  streamptr->ntsteps = 1;
	  break;
	}
      if ( recsize > buffersize )
	{
	  buffersize = recsize;
	  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
	}

      readsize = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
796
797
      rstatus = gribRead(fileID, gribbuffer, &readsize);
      if ( rstatus ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
798
799
800
801
802

      ztype = COMPRESS_NONE;
      if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
	{
	  ztype = COMPRESS_SZIP;
803
	  unzipsize += 100;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
804
805
806
807
808
809
810
811
	  if ( (long) buffersize < unzipsize )
	    {
	      buffersize = unzipsize;
	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
	    }
	}

      gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
812
      GRIB_CHECK(grib_set_double(gh, "missingValue", GRIBAPI_MISSVAL), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
813
814
815
816
817

      GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);

      if ( editionNumber <= 1 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
818
819
	  GRIB_CHECK(grib_get_long(gh, "table2Version", &lpar), 0);
	  rtabnum = (int) lpar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
820
821
	  GRIB_CHECK(grib_get_long(gh, "indicatorOfParameter", &lpar), 0);
	  rcode = (int) lpar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
822

Uwe Schulzweida's avatar
Uwe Schulzweida committed
823
	  param = cdiEncodeParam(rcode, rtabnum, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
824

Uwe Schulzweida's avatar
Uwe Schulzweida committed
825
826
827
828
	  status = grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar);
	  if ( status == 0 )
	    {
	      leveltype = (int) lpar;
829
830
	      dlevel = grib1GetLevel(gh, leveltype);
	      if ( leveltype == 99 ) leveltype++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
831
832
833
834
835
836
837
838
839
	    }
	  else 
	    {
	      leveltype = 0;
	      dlevel = 0;
	    }
	}
      else
	{
840
841
	  size_t len = 256;
	  char typeOfPacking[256];
842

843
	  status = grib_get_string(gh, "packingType", typeOfPacking, &len);
844
845
	  if ( status == 0 )
	    {
846
	      // fprintf(stderr, "packingType %d %s\n", len, typeOfPacking);
847
848
	      if ( strncmp(typeOfPacking, "grid_jpeg", len) == 0 ) ztype = COMPRESS_JPEG;
	    }
849
	  
Uwe Schulzweida's avatar
Uwe Schulzweida committed
850
	  GRIB_CHECK(grib_get_long(gh, "discipline", &lpar), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
851
852
	  pdis = (int) lpar;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
853
	  GRIB_CHECK(grib_get_long(gh, "parameterCategory", &lpar), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
854
	  pcat = (int) lpar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
855

Uwe Schulzweida's avatar
Uwe Schulzweida committed
856
	  GRIB_CHECK(grib_get_long(gh, "parameterNumber", &lpar), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
857
858
	  pnum = (int) lpar;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
859
	  param = cdiEncodeParam(pnum, pcat, pdis);
860

Uwe Schulzweida's avatar
Uwe Schulzweida committed
861
862
863
864
	  status = grib_get_long(gh, "typeOfFirstFixedSurface", &lpar);
	  if ( status == 0 )
	    {
	      leveltype = (int) lpar;
865
866
	      dlevel = grib2GetLevel(gh, leveltype);
	      if ( leveltype == 99 ) leveltype++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
867
868
869
870
871
872
873
874
875
876
877
	    }
	  else 
	    {
	      leveltype = 0;
	      dlevel = 0;
	    }
	}

      level1 = (int) dlevel;
      level2 = 0;

878
879
      gribapiGetValidityDateTime(gh, &vdate, &vtime);
      /*
880
      printf("%d %d %d.%d.%d %d %g\n", vdate, vtime, pnum, pcat, pdis, leveltype, dlevel);
881
      */
882
883
884
885
886
887
888
889
      prec = DATATYPE_PACK;
      status = grib_get_long(gh,"bitsPerValue", &lpar);
      if ( status == 0 )
	{
	  bitsPerValue = (int) lpar;
	  if ( bitsPerValue > 0 && bitsPerValue <= 32 )
	    prec = bitsPerValue;
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
890

Uwe Schulzweida's avatar
Uwe Schulzweida committed
891
892
893
894
      if ( nrecs == 0 )
	{
	  datetime0.date = vdate;
	  datetime0.time = vtime;
895
896
897
898
899
900
	  GRIB_CHECK(grib_get_long(gh, "dataDate", &lpar), 0);
	  rdate = (int) lpar;
	  GRIB_CHECK(grib_get_long(gh, "dataTime", &lpar), 0);
	  rtime = (int) lpar*100;
	  fcast = gribapiTimeIsFC(gh);
	  if ( fcast ) tunit = gribapiGetTimeUnits(gh);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
901
902
903
904
905
	}
      else
	{
	  datetime.date  = vdate;
	  datetime.time  = vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
906
907

	  compVar.param  = param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
908
909
          compVar.level1 = level1;
          compVar.level2 = level2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
910
911
	  compVar.ltype  = leveltype;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
912
913
	  for ( recID = 0; recID < nrecs; recID++ )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
914
	      compVar0.param  = streamptr->tsteps[0].records[recID].param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
915
916
917
	      compVar0.level1 = streamptr->tsteps[0].records[recID].ilevel;
	      compVar0.level2 = streamptr->tsteps[0].records[recID].ilevel2;
	      compVar0.ltype  = streamptr->tsteps[0].records[recID].ltype;
918
919
920
921
	      /*
	      printf("var0: %d %d %d %d %d\n", recID, compVar0.param, compVar0.level1, compVar0.level2, compVar0.ltype);
	      printf("var1: %d %d %d %d %d\n", recID, compVar.param, compVar.level1, compVar.level2, compVar.ltype);
	      */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
922
923
924
925
926
927
928
929
930
	      if ( memcmp(&compVar0, &compVar, sizeof(compvar2_t)) == 0 ) break;
	    }

	  if ( cdiInventoryMode == 1 )
	    {
	      if ( recID < nrecs ) break;
	      if ( warn_time )
		if ( memcmp(&datetime, &datetime0, sizeof(DateTime)) != 0 )
		  {
931
932
		    char paramstr[32];
		    cdiParamToString(param, paramstr, sizeof(paramstr));	    
933
		    Warning("Inconsistent verification time (param=%s level=%d)", paramstr, level1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
934
935
936
937
938
939
940
941
942
		    warn_time = FALSE;
		  }
	    }
	  else
	    {
	      if ( memcmp(&datetime, &datetime0, sizeof(DateTime)) != 0 ) break;

	      if ( recID < nrecs )
		{
943
944
		  char paramstr[32];
		  cdiParamToString(param, paramstr, sizeof(paramstr));
945
		  Warning("Param=%s level=%d already exist, skipped!", paramstr, level1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
946
947
948
949
950
951
952
953
954
		  continue;
		}
	    }
	}
      /*
      if ( ISEC1_AvgNum )
	{
	  if (  taxis->numavg && warn_numavg && (taxis->numavg != ISEC1_AvgNum) )
	    {
955
	      Message("Change numavg from %d to %d not allowed!",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
956
957
958
959
960
961
962
963
964
965
966
967
		      taxis->numavg, ISEC1_AvgNum);
	      warn_numavg = FALSE;
	    }
	  else
	    {
	      taxis->numavg = ISEC1_AvgNum;
	    }
	}
      */
      nrecs++;

      if ( CDI_Debug )
968
	Message("%4d %8d %4d  %8d %8d %6d", nrecs, (int)recpos, param, level1, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
969

Uwe Schulzweida's avatar
Uwe Schulzweida committed
970
      gribapiAddRecord(streamID, param, gh, recsize, recpos, prec, ztype);
971
972
973

      grib_handle_delete(gh);
      gh = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
974
975
    }

976
977
  if ( gh ) grib_handle_delete(gh);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
978
979
  streamptr->rtsteps = 1;

980
981
  if ( nrecs == 0 ) return (CDI_EUFSTRUCT);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
  cdiGenVars(streamID);

  if ( fcast )
    {
      taxisID = taxisCreate(TAXIS_RELATIVE);
      taxis->type  = TAXIS_RELATIVE;
      taxis->rdate = rdate;
      taxis->rtime = rtime;
      taxis->unit  = tunit;
    }
  else
    {
      taxisID = taxisCreate(TAXIS_ABSOLUTE);
      taxis->type  = TAXIS_ABSOLUTE;
    }

  taxis->vdate = datetime0.date;
  taxis->vtime = datetime0.time;

  vlistID = streamInqVlist(streamID);
  vlistDefTaxis(vlistID, taxisID);

  nrecords = streamptr->tsteps[0].nallrecs;
  if ( nrecords < streamptr->tsteps[0].recordSize )
    {
      streamptr->tsteps[0].recordSize = nrecords;
      streamptr->tsteps[0].records =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1009
      (record_t *) realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
    }

  streamptr->tsteps[0].recIDs = (int *) malloc(nrecords*sizeof(int));
  streamptr->tsteps[0].nrecs = nrecords;
  for ( recID = 0; recID < nrecords; recID++ )
    streamptr->tsteps[0].recIDs[recID] = recID;

  streamptr->record->buffer     = gribbuffer;
  streamptr->record->buffersize = buffersize;

  if ( streamptr->ntsteps == -1 )
    {
      tsID = tstepsNewEntry(streamID);
      if ( tsID != streamptr->rtsteps )
1024
	Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041

      streamptr->tsteps[tsID-1].next   = TRUE;
      streamptr->tsteps[tsID].position = recpos;
    }

  if ( streamptr->ntsteps == 1 )
    {
      if ( taxis->vdate == 0 && taxis->vtime == 0 )
	{
	  streamptr->ntsteps = 0;
	  for ( varID = 0; varID < streamptr->nvars; varID++ )
	    {
	      vlistDefVarTime(vlistID, varID, TIME_CONSTANT);
	    }
	}
    }
#else
1042
  Error("GRIB_API support not compiled in!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1043
#endif
1044
1045

  return (0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1046
1047
1048
1049
1050
}


int gribapiScanTimestep2(int streamID)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1051
  int rstatus = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1052
#if  defined  (HAVE_LIBGRIB_API)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1053
  int status;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1054
1055
1056
1057
1058
  off_t recpos = 0;
  unsigned char *gribbuffer = NULL;
  long buffersize = 0;
  int iret = 0, ipunp = 0, iword = 0;
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1059
  int rtabnum = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1060
1061
1062
1063
1064
1065
1066
1067
  int rcode = 0, level1 = 0, level2 = 0, vdate = 0, vtime = 0;
  DateTime datetime, datetime0;
  int tsID;
  int varID, gridID;
  size_t readsize;
  int nrecords, nrecs, recID, rindex;
  long recsize = 0;
  int warn_numavg = TRUE;
1068
  int tsteptype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1069
  int taxisID = -1;
1070
  taxis_t *taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1071
1072
1073
1074
1075
1076
  int vlistID;
  long unzipsize;
  compvar2_t compVar, compVar0;
  stream_t *streamptr;
  grib_handle *gh = NULL;
  int leveltype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1077
1078
  int pdis = 0, pcat = 0, pnum = 0;
  int param = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1079
1080
1081
1082
1083
1084
  long editionNumber;
  long lpar;
  double dlevel = 0;

  streamptr = stream_to_pointer(streamID);

1085
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097

  streamptr->curTsID = 1;

  fileID  = streamInqFileID(streamID);
  vlistID = streamInqVlist(streamID);
  taxisID = vlistInqTaxis(vlistID);

  gribbuffer = (unsigned char *) streamptr->record->buffer;
  buffersize = streamptr->record->buffersize;
                                          
  tsID = streamptr->rtsteps;
  if ( tsID != 1 )
1098
    Error("Internal problem! unexpeceted timestep %d", tsID+1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139

  taxis = &streamptr->tsteps[tsID].taxis;

  fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);

  cdiCreateRecords(streamID, tsID);

  nrecords = streamptr->tsteps[tsID].nallrecs;
  streamptr->tsteps[1].recIDs = (int *) malloc(nrecords*sizeof(int));
  streamptr->tsteps[1].nrecs = 0;
  for ( recID = 0; recID < nrecords; recID++ )
    streamptr->tsteps[1].recIDs[recID] = -1;
      
  for ( recID = 0; recID < nrecords; recID++ )
    {
      varID = streamptr->tsteps[0].records[recID].varID;
      streamptr->tsteps[tsID].records[recID].position = 
	streamptr->tsteps[0].records[recID].position;
      streamptr->tsteps[tsID].records[recID].size     = 
	streamptr->tsteps[0].records[recID].size;
    }

  rindex = 0;
  while ( TRUE )
    {
      if ( rindex > nrecords ) break;

      recsize = gribGetSize(fileID);
      recpos  = fileGetPos(fileID);
      if ( recsize == 0 )
	{
	  streamptr->ntsteps = 2;
	  break;
	}
      if ( recsize > buffersize )
	{
	  buffersize = recsize;
	  gribbuffer = (unsigned char *) realloc(gribbuffer, (size_t)buffersize);
	}

      readsize = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1140
1141
      rstatus = gribRead(fileID, gribbuffer, &readsize);
      if ( rstatus ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153

      if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
	{
	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
	  if ( (long) buffersize < unzipsize )
	    {
	      buffersize = unzipsize;
	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
	    }
	}

      gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1154
      GRIB_CHECK(grib_set_double(gh, "missingValue", GRIBAPI_MISSVAL), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1155
1156
1157
1158
1159

      GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0);

      if ( editionNumber <= 1 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1160
1161
	  GRIB_CHECK(grib_get_long(gh, "table2Version", &lpar), 0);
	  rtabnum = (int) lpar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1162
1163
	  GRIB_CHECK(grib_get_long(gh, "indicatorOfParameter", &lpar), 0);
	  rcode = (int) lpar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1164

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1165
	  param = cdiEncodeParam(rcode, rtabnum, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1166

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1167
1168
1169
1170
	  status = grib_get_long(gh, "indicatorOfTypeOfLevel", &lpar);
	  if ( status == 0 )
	    {
	      leveltype = (int) lpar;
1171
1172
	      dlevel = grib1GetLevel(gh, leveltype);
	      if ( leveltype == 99 ) leveltype++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1173
1174
1175
1176
1177
1178
1179
1180
1181
	    }
	  else 
	    {
	      leveltype = 0;
	      dlevel = 0;
	    }
	}
      else
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1182
	  GRIB_CHECK(grib_get_long(gh, "discipline", &lpar), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1183
	  pdis = (int) lpar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1184

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1185
	  GRIB_CHECK(grib_get_long(gh, "parameterCategory", &lpar), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1186
	  pcat = (int) lpar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1187

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1188
	  GRIB_CHECK(grib_get_long(gh, "parameterNumber", &lpar), 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1189
1190
	  pnum = (int) lpar;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1191
	  param = cdiEncodeParam(pnum, pcat, pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1192

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1193
1194
1195
1196
	  status = grib_get_long(gh, "typeOfFirstFixedSurface", &lpar);
	  if ( status == 0 )
	    {
	      leveltype = (int) lpar;
1197
1198
	      dlevel = grib2GetLevel(gh, leveltype);
	      if ( leveltype == 99 ) leveltype++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
	    }
	  else 
	    {
	      leveltype = 0;
	      dlevel = 0;
	    }
	}

      level1 = (int) dlevel;
      level2 = 0;

1210
      gribapiGetValidityDateTime(gh, &vdate, &vtime);