stream_cgribex.c 48.4 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

#include <stdio.h>
#include <float.h>  /* FLT_EPSILON */

#include "dmemory.h"
#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
15
#include "stream_grb.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
16

Uwe Schulzweida's avatar
Uwe Schulzweida committed
17
18
19
#if  defined  (HAVE_LIBCGRIBEX)
#  include "cgribex.h"
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
20

Uwe Schulzweida's avatar
Uwe Schulzweida committed
21
extern int cdiInventoryMode;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
22
23

typedef struct {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
24
  int param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
25
26
27
  int level1;
  int level2;
  int ltype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
28
} compvar_t; 
Uwe Schulzweida's avatar
Uwe Schulzweida committed
29
30


Uwe Schulzweida's avatar
Uwe Schulzweida committed
31
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
32
int cgribexGetGridType(int *isec2)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
33
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
34
  /*  static char func[] = "cgribexGetGridType"; */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
35
36
37
38
  int gridtype = 0;

  switch (ISEC2_GridType)
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
39
40
    case  GTYPE_LATLON:
    case  GTYPE_LATLON_ROT:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
42
43
44
      {
	gridtype = GRID_LONLAT;
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
45
    case  GTYPE_LCC:
46
      {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
47
	gridtype = GRID_LCC;
48
49
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
50
    case  GTYPE_GAUSSIAN:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
51
52
53
54
55
56
57
      {
	if ( ISEC2_Reduced )
	  gridtype = GRID_GAUSSIAN_REDUCED;
	else
	  gridtype = GRID_GAUSSIAN;
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
58
    case  GTYPE_SPECTRAL:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
59
60
61
62
      {
	gridtype = GRID_SPECTRAL;
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
63
    case  GTYPE_GME:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
64
65
66
67
68
69
70
71
72
73
74
75
76
77
      {
	gridtype = GRID_GME;
	break;
      }
    default:
      {
	gridtype = GRID_GENERIC;
	break;
      }
    }

  return (gridtype);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
78
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
79
int cgribexGetIsRotated(int *isec2)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
80
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
81
  /*  static char func[] = "cgribexGetIsRotated"; */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
82
83
84
85
86
87
88
89
90
91
92
  int isRotated = 0;

  if ( ISEC2_GridType == 10 )
    {
      isRotated = 1;
    }

  return (isRotated);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
94
int cgribexGetZaxisType(int grb_ltype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
95
{
96
  int zaxistype = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
97

98
  switch ( grb_ltype )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
99
100
101
    {
    case LTYPE_SURFACE:
      {
102
	zaxistype = ZAXIS_SURFACE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
103
104
	break;
      }
105
106
107
108
109
    case LTYPE_MEANSEA:
      {
	zaxistype = ZAXIS_MEANSEA;
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
110
111
112
    case LTYPE_99:
    case LTYPE_ISOBARIC:
      {
113
	zaxistype = ZAXIS_PRESSURE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
114
115
116
117
	break;
      }
    case LTYPE_HEIGHT:
      {
118
	zaxistype = ZAXIS_HEIGHT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
119
120
121
122
	break;
      }
    case LTYPE_ALTITUDE:
      {
123
	zaxistype = ZAXIS_ALTITUDE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
124
125
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
126
127
    case LTYPE_SIGMA:
      {
128
	zaxistype = ZAXIS_SIGMA;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
129
130
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
131
132
133
    case LTYPE_HYBRID:
    case LTYPE_HYBRID_LAYER:
      {
134
	zaxistype = ZAXIS_HYBRID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
135
136
137
138
139
	break;
      }
    case LTYPE_LANDDEPTH:
    case LTYPE_LANDDEPTH_LAYER:
      {
140
	zaxistype = ZAXIS_DEPTH_BELOW_LAND;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
141
142
	break;
      }
143
144
    case LTYPE_ISENTROPIC:
      {
145
	zaxistype = ZAXIS_ISENTROPIC;
146
147
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
148
149
    case LTYPE_SEADEPTH:
      {
150
	zaxistype = ZAXIS_DEPTH_BELOW_SEA;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
151
152
153
154
	break;
      }
    default:
      {
155
	zaxistype = ZAXIS_GENERIC;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
156
157
158
159
	break;
      }
    }

160
  return (zaxistype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
161
162
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
163
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
164
int cgribexGetZaxisHasBounds(int grb_ltype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
165
166
167
{
  int lbounds = 0;

168
  switch (grb_ltype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
169
170
171
172
173
174
175
176
177
178
179
180
    {
    case LTYPE_HYBRID_LAYER:
    case LTYPE_LANDDEPTH_LAYER:
      {
	lbounds = 1;
	break;
      }
    }

  return (lbounds);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
181
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
182
int cgribexGetTimeUnit(int *isec1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
183
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
184
  static char func[] = "cgribexGetTimeUnit";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
185
186
187
188
189
  int timeunit = -1;
  static int lprint = TRUE;

  switch ( ISEC1_TimeUnit )
    {
190
191
192
193
    case ISEC1_TABLE4_MINUTE:  timeunit = TUNIT_MINUTE;  break;
    case ISEC1_TABLE4_QUARTER: timeunit = TUNIT_QUARTER; break;
    case ISEC1_TABLE4_HOUR:    timeunit = TUNIT_HOUR;    break;
    case ISEC1_TABLE4_DAY:     timeunit = TUNIT_DAY;     break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
194
195
196
197
198
199
200
201
202
203
204
205
    default:
      if ( lprint )
	{
	  Message(func, "Time unit %d unsupported", ISEC1_TimeUnit);
	  lprint = FALSE;
	}
    }

  return (timeunit);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
206
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
207
void cgribexAddRecord(int streamID, int param, int *isec1, int *isec2, double *fsec2,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
208
		      int *isec4, long recsize, off_t position, int prec, int ztype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
209
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
210
  static char func[] = "cgribexAddRecord";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
211
  int gridtype;
212
  int zaxistype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
213
  int gridID = CDI_UNDEFID, varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
214
215
216
217
218
  int levelID = 0;
  int tsID, recID;
  int level1, level2;
  int numavg;
  int lbounds = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
219
  record_t *record;
220
  grid_t grid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
221
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
222
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
223
224

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
225
226

  vlistID = streamInqVlist(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
227
  tsID    = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
228
  recID   = recordNewEntry(streamID, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
229
  record  = &streamptr->tsteps[tsID].records[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
230
231
232
233
234
235

  numavg  = ISEC1_AvgNum;

  level1  = ISEC1_Level1;
  level2  = ISEC1_Level2;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
236
  /* fprintf(stderr, "param %d %d %d %d\n", param, level1, level2, ISEC1_LevelType); */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
237
238
239

  (*record).size     = recsize;
  (*record).position = position;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
240
  (*record).param     = param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
241
242
243
244
  (*record).ilevel   = level1;
  (*record).ilevel2  = level2;
  (*record).ltype    = ISEC1_LevelType;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
245
  gridtype = cgribexGetGridType(isec2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
246

Uwe Schulzweida's avatar
Uwe Schulzweida committed
247
  if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
248
249
250
251
252
253
    {
      gridtype = GRID_GAUSSIAN;
      ISEC2_NumLon = 2*ISEC2_NumLat;
      ISEC4_NumValues = ISEC2_NumLon*ISEC2_NumLat;
    }

254
  memset(&grid, 0, sizeof(grid_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
255
256
257
258
259
260
  switch (gridtype)
    {
    case GRID_LONLAT:
    case GRID_GAUSSIAN:
      {
	if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
261
	  Error(func, "numberOfPoints (%d) and gridSize (%d) differ!",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
		ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
	grid.size  = ISEC4_NumValues;
	grid.xsize = ISEC2_NumLon;
	grid.ysize = ISEC2_NumLat;
	grid.xinc  = 0;
	grid.yinc  = 0;
	grid.xdef  = 0;
	/* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
	  {
	    if ( grid.xsize > 1 )
	      {
		if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
		  grid.xinc = ISEC2_LonIncr * 0.001;
		else
		  grid.xinc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid.xsize - 1);

		/* correct xinc if necessary */
		if ( ISEC2_FirstLon == 0 && ISEC2_LastLon > 354000 )
		  {
		    double xinc = 360. / grid.xsize;

		    if ( fabs(grid.xinc-xinc) > 0.0 )
		      {
			grid.xinc = xinc;
			if ( CDI_Debug ) Message(func, "set xinc to %g", grid.xinc);
		      }
		  }
	      }
	    grid.xfirst = ISEC2_FirstLon * 0.001;
	    grid.xlast  = ISEC2_LastLon  * 0.001;
	    grid.xdef   = 2;	    
	  }
	grid.ydef  = 0;
	/* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
	  {
	    if ( grid.ysize > 1 )
	      {
		if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
		  grid.yinc = ISEC2_LatIncr * 0.001;
		else
		  grid.yinc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid.ysize - 1);
	      }
	    grid.yfirst = ISEC2_FirstLat * 0.001;
	    grid.ylast  = ISEC2_LastLat  * 0.001;
	    grid.ydef   = 2;	    
	  }
	break;
      }
    case GRID_GAUSSIAN_REDUCED:
      {
	grid.size   = ISEC4_NumValues;
        grid.rowlon = ISEC2_RowLonPtr;
	grid.ysize  = ISEC2_NumLat;
	grid.xinc  = 0;
	grid.yinc  = 0;
	grid.xdef  = 0;
	/* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */
	  {
	    if ( grid.xsize > 1 )
	      {
		if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
		  grid.xinc = ISEC2_LonIncr * 0.001;
		else
		  grid.xinc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid.xsize - 1);
	      }
	    grid.xfirst = ISEC2_FirstLon * 0.001;
	    grid.xlast  = ISEC2_LastLon  * 0.001;
	    grid.xdef   = 2;	    
	  }
	grid.ydef  = 0;
	/* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */
	  {
	    if ( grid.ysize > 1 )
	      {
		if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
		  grid.yinc = ISEC2_LatIncr * 0.001;
		else
		  grid.yinc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid.ysize - 1);
	      }
	    grid.yfirst = ISEC2_FirstLat * 0.001;
	    grid.ylast  = ISEC2_LastLat  * 0.001;
	    grid.ydef   = 2;	    
	  }
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
347
    case GRID_LCC:
348
349
      {
	if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
350
	  Error(func, "numberOfPoints (%d) and gridSize (%d) differ!",
351
		ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
352

353
354
355
356
	grid.size  = ISEC4_NumValues;
	grid.xsize = ISEC2_NumLon;
	grid.ysize = ISEC2_NumLat;

357
358
	grid.lcc_xinc      = ISEC2_Lambert_dx;
	grid.lcc_yinc      = ISEC2_Lambert_dy;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
359
360
	grid.lcc_originLon = ISEC2_FirstLon * 0.001;
	grid.lcc_originLat = ISEC2_FirstLat * 0.001;
361
362
363
364
365
	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;
366

367
	grid.xdef   = 0;	    
368
369
370
371
	grid.ydef   = 0;

	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
    case GRID_SPECTRAL:
      {
	grid.size  = ISEC4_NumValues;
	grid.trunc = ISEC2_PentaJ;
	break;
      }
    case GRID_GME:
      {
	grid.size  = ISEC4_NumValues;
	grid.nd    = ISEC2_GME_ND;
	grid.ni    = ISEC2_GME_NI;
	grid.ni2   = ISEC2_GME_NI2;
	grid.ni3   = ISEC2_GME_NI3;
	break;
      }
    case GRID_GENERIC:
      {
	grid.size  = ISEC4_NumValues;
	grid.xsize = 0;
	grid.ysize = 0;
	break;
      }
    default:
      {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
396
	Error(func, "%s grid unsupported!", gridNamePtr(gridtype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
397
398
399
400
401
	break;
      }
    }

  grid.isRotated = FALSE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
402
  if ( cgribexGetIsRotated(isec2) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
403
404
405
406
407
408
409
410
411
412
413
414
415
    {
      grid.isRotated = TRUE;
      grid.ypole     = - ISEC2_LatSP * 0.001;
      grid.xpole     =   ISEC2_LonSP * 0.001 - 180;
      grid.angle     = 0;
    }

  grid.xvals = NULL;
  grid.yvals = NULL;
  grid.type  = gridtype;

  gridID = varDefGrid(vlistID, grid, 0);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
416
  zaxistype = cgribexGetZaxisType(ISEC1_LevelType);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
417

418
  if ( zaxistype == ZAXIS_HYBRID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
419
420
421
422
423
424
425
    {
      int vctsize = ISEC2_NumVCP;
      double *vctptr = &fsec2[10];

      varDefVCT(vctsize, vctptr);
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
426
  lbounds = cgribexGetZaxisHasBounds(ISEC1_LevelType);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
427

428
429
  if ( prec > 32 ) prec = DATATYPE_PACK32;
  if ( prec <  0 ) prec = DATATYPE_PACK;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
430

Uwe Schulzweida's avatar
Uwe Schulzweida committed
431
432
  varAddRecord(recID, param, gridID, zaxistype, lbounds, level1, level2,
	       prec, &varID, &levelID, numavg, ISEC1_LevelType, NULL, NULL, NULL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
433
434
435
436

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

437
  varDefZtype(varID, ztype);
438

Uwe Schulzweida's avatar
Uwe Schulzweida committed
439
  if ( varInqInst(varID) == CDI_UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
440
441
442
443
444
    {
      int center, subcenter, instID;
      center    = ISEC1_CenterID;
      subcenter = ISEC1_SubCenterID;
      instID    = institutInq(center, subcenter, NULL, NULL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
445
      if ( instID == CDI_UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
446
447
448
449
	instID = institutDef(center, subcenter, NULL, NULL);
      varDefInst(varID, instID);
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
450
  if ( varInqModel(varID) == CDI_UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
451
452
453
    {
      int modelID;
      modelID = modelInq(varInqInst(varID), ISEC1_ModelID, NULL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
454
      if ( modelID == CDI_UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
455
456
457
458
	modelID = modelDef(varInqInst(varID), ISEC1_ModelID, NULL);
      varDefModel(varID, modelID);
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
459
  if ( varInqTable(varID) == CDI_UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
460
461
    {
      int tableID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
462

Uwe Schulzweida's avatar
Uwe Schulzweida committed
463
      tableID = tableInq(varInqModel(varID), ISEC1_CodeTable, NULL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
464

Uwe Schulzweida's avatar
Uwe Schulzweida committed
465
      if ( tableID == CDI_UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
466
467
468
469
	tableID = tableDef(varInqModel(varID), ISEC1_CodeTable, NULL);
      varDefTable(varID, tableID);
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
470
471
  streamptr->tsteps[tsID].nallrecs++;
  streamptr->nrecs++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
472
473

  if ( CDI_Debug )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
474
475
    Message(func, "varID = %d  param = %d  zaxistype = %d  gridID = %d  levelID = %d",
	    varID, param, zaxistype, gridID, levelID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
476
477
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
478
479

void cgribexScanTimestep1(int streamID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
480
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
481
  static char func[] = "cgribexScanTimestep1";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
482
483
484
485
486
487
488
489
  int *isec0, *isec1, *isec2, *isec3, *isec4;
  double fsec2[512], fsec3[2], *fsec4 = NULL;
  off_t recpos = 0;
  unsigned char *gribbuffer = NULL;
  long buffersize = 0;
  int iret = 0, ipunp = 0, iword = 0;
  int status;
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
490
491
  int param = 0;
  int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
493
494
495
496
497
498
  DateTime datetime, datetime0;
  int tsID;
  int varID;
  size_t readsize;
  int nrecords, nrecs, recID;
  int prec;
  long recsize = 0;
499
  int warn_time = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500
501
502
503
504
  int warn_numavg = TRUE;
  int taxisID = -1;
  int rdate = 0, rtime = 0, tunit = 0, fcast = 0;
  TAXIS *taxis;
  int vlistID;
505
  int ztype;
506
  long unzipsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
507
508
  compvar_t compVar, compVar0;
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
509
510

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511

Uwe Schulzweida's avatar
Uwe Schulzweida committed
512
  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513

Uwe Schulzweida's avatar
Uwe Schulzweida committed
514
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
515

Uwe Schulzweida's avatar
Uwe Schulzweida committed
516
517
518
519
520
  isec0 = streamptr->record->sec0;
  isec1 = streamptr->record->sec1;
  isec2 = streamptr->record->sec2;
  isec3 = streamptr->record->sec3;
  isec4 = streamptr->record->sec4;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
521
522

  tsID  = tstepsNewEntry(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
523
  taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
525
526
527
528
529
530
531
532
533
534
535
536
537

  if ( tsID != 0 )
    Error(func, "Internal problem! tstepsNewEntry returns %d", tsID);

  fileID = streamInqFileID(streamID);

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

      if ( recsize == 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
538
	  streamptr->ntsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
539
540
541
542
543
544
545
546
547
548
549
550
	  break;
	}
      if ( recsize > buffersize )
	{
	  buffersize = recsize;
	  gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
	}

      readsize = recsize;
      status = gribRead(fileID, gribbuffer, &readsize);
      if ( status ) break;

551
      ztype = COMPRESS_NONE;
552
553
      if ( gribGetZip(recsize, gribbuffer, &unzipsize) > 0 )
	{
554
	  ztype = COMPRESS_SZIP;
555
556
557
558
559
560
561
562
	  unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */
	  if ( (long) buffersize < unzipsize )
	    {
	      buffersize = unzipsize;
	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
	    }
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
563
564
565
      gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
	       ipunp, (int *) gribbuffer, recsize, &iword, "J", &iret);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
566
      param = cdiEncodeParam(255, ISEC1_CodeTable, ISEC1_Parameter);
567
568
      if ( ISEC1_LevelType == 100 ) ISEC1_Level1 *= 100;
      if ( ISEC1_LevelType ==  99 ) ISEC1_LevelType = 100;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
569
570
571
      level1   = ISEC1_Level1;
      level2   = ISEC1_Level2;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
572
573
      gribDateTime(isec1, &vdate, &vtime);

574
575
576
577
      if ( ISEC4_NumBits > 0 && ISEC4_NumBits <= 32 )
	prec = ISEC4_NumBits;
      else
        prec = DATATYPE_PACK;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
578
579
580
581
582
583
584

      if ( nrecs == 0 )
	{
	  datetime0.date = vdate;
	  datetime0.time = vtime;
	  rdate = gribRefDate(isec1);
	  rtime = gribRefTime(isec1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
585
	  tunit = cgribexGetTimeUnit(isec1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
586
587
588
589
590
591
	  fcast = gribTimeIsFC(isec1);
	}
      else
	{
	  datetime.date  = vdate;
	  datetime.time  = vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
592
	  compVar.param  = param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
593
594
595
596
597
          compVar.level1 = level1;
          compVar.level2 = level2;
          compVar.ltype  = ISEC1_LevelType;
	  for ( recID = 0; recID < nrecs; recID++ )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
598
	      compVar0.param  = streamptr->tsteps[0].records[recID].param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
599
600
601
	      compVar0.level1 = streamptr->tsteps[0].records[recID].ilevel;
	      compVar0.level2 = streamptr->tsteps[0].records[recID].ilevel2;
	      compVar0.ltype  = streamptr->tsteps[0].records[recID].ltype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
602

Uwe Schulzweida's avatar
Uwe Schulzweida committed
603
	      if ( memcmp(&compVar0, &compVar, sizeof(compvar_t)) == 0 ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
604
	    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
605
606
607
608
609
610
611

	  if ( cdiInventoryMode == 1 )
	    {
	      if ( recID < nrecs ) break;
	      if ( warn_time )
		if ( memcmp(&datetime, &datetime0, sizeof(DateTime)) != 0 )
		  {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
612
		    Warning(func, "Inconsistent verification time (param %d level %d)", param, level1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
613
614
615
616
617
618
619
620
621
		    warn_time = FALSE;
		  }
	    }
	  else
	    {
	      if ( memcmp(&datetime, &datetime0, sizeof(DateTime)) != 0 ) break;

	      if ( recID < nrecs )
		{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
622
		  Warning(func, "Param %d level %d already exist, skipped!", param, level1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
623
624
625
		  continue;
		}
	    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
	}

      if ( ISEC1_AvgNum )
	{
	  if (  taxis->numavg && warn_numavg && (taxis->numavg != ISEC1_AvgNum) )
	    {
	      Message(func, "Change numavg from %d to %d not allowed!",
		      taxis->numavg, ISEC1_AvgNum);
	      warn_numavg = FALSE;
	    }
	  else
	    {
	      taxis->numavg = ISEC1_AvgNum;
	    }
	}

      nrecs++;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
647
      cgribexAddRecord(streamID, param, isec1, isec2, fsec2, isec4, recsize, recpos, prec, ztype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
648
649
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
650
  streamptr->rtsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
651
652
653
654
655

  cdiGenVars(streamID);

  if ( fcast )
    {
656
      taxisID = taxisCreate(TAXIS_RELATIVE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
657
658
659
660
661
662
663
      taxis->type  = TAXIS_RELATIVE;
      taxis->rdate = rdate;
      taxis->rtime = rtime;
      taxis->unit  = tunit;
    }
  else
    {
664
      taxisID = taxisCreate(TAXIS_ABSOLUTE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
665
      taxis->type  = TAXIS_ABSOLUTE;
666
      taxis->unit  = tunit;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
667
668
669
670
671
672
673
674
    }

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
675
676
  nrecords = streamptr->tsteps[0].nallrecs;
  if ( nrecords < streamptr->tsteps[0].recordSize )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
677
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
678
679
      streamptr->tsteps[0].recordSize = nrecords;
      streamptr->tsteps[0].records =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
680
      (record_t *) realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
681
682
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
683
684
  streamptr->tsteps[0].recIDs = (int *) malloc(nrecords*sizeof(int));
  streamptr->tsteps[0].nrecs = nrecords;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
685
  for ( recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
686
    streamptr->tsteps[0].recIDs[recID] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
687

Uwe Schulzweida's avatar
Uwe Schulzweida committed
688
689
  streamptr->record->buffer     = gribbuffer;
  streamptr->record->buffersize = buffersize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
690

Uwe Schulzweida's avatar
Uwe Schulzweida committed
691
  if ( streamptr->ntsteps == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
692
693
    {
      tsID = tstepsNewEntry(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
694
      if ( tsID != streamptr->rtsteps )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
695
696
	Error(func, "Internal error. tsID = %d", tsID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
697
698
      streamptr->tsteps[tsID-1].next   = TRUE;
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
699
700
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
701
  if ( streamptr->ntsteps == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
702
703
704
    {
      if ( taxis->vdate == 0 && taxis->vtime == 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
705
706
	  streamptr->ntsteps = 0;
	  for ( varID = 0; varID < streamptr->nvars; varID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
707
708
709
710
711
712
713
	    {
	      vlistDefVarTime(vlistID, varID, TIME_CONSTANT);
	    }
	}
    }
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
714
715

int cgribexScanTimestep2(int streamID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
716
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
717
  static char func[] = "cgribexScanTimestep2";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
718
719
720
721
722
723
724
725
  int *isec0, *isec1, *isec2, *isec3, *isec4;
  double fsec2[512], fsec3[2], *fsec4 = NULL;
  off_t recpos = 0;
  unsigned char *gribbuffer = NULL;
  long buffersize = 0;
  int iret = 0, ipunp = 0, iword = 0;
  int status;
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
726
727
  int param = 0;
  int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
728
  DateTime datetime, datetime0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
729
730
731
732
733
734
735
736
737
  int tsID;
  int varID, gridID;
  size_t readsize;
  int nrecords, nrecs, recID, rindex;
  long recsize = 0;
  int warn_numavg = TRUE;
  int taxisID = -1;
  TAXIS *taxis;
  int vlistID;
738
  long unzipsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
739
740
  compvar_t compVar, compVar0;
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
741

Uwe Schulzweida's avatar
Uwe Schulzweida committed
742
  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
743

Uwe Schulzweida's avatar
Uwe Schulzweida committed
744
  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
745

Uwe Schulzweida's avatar
Uwe Schulzweida committed
746
747
748
749
750
751
752
  streamptr->curTsID = 1;

  isec0 = streamptr->record->sec0;
  isec1 = streamptr->record->sec1;
  isec2 = streamptr->record->sec2;
  isec3 = streamptr->record->sec3;
  isec4 = streamptr->record->sec4;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
753
754
755
756
757

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
758
759
  gribbuffer = (unsigned char *) streamptr->record->buffer;
  buffersize = streamptr->record->buffersize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
760
                                          
Uwe Schulzweida's avatar
Uwe Schulzweida committed
761
  tsID = streamptr->rtsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
762
763
764
  if ( tsID != 1 )
    Error(func, "Internal problem! unexpeceted timestep %d", tsID+1);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
765
  taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
766

Uwe Schulzweida's avatar
Uwe Schulzweida committed
767
  fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
768
769
770

  cdiCreateRecords(streamID, tsID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
771
772
773
  nrecords = streamptr->tsteps[tsID].nallrecs;
  streamptr->tsteps[1].recIDs = (int *) malloc(nrecords*sizeof(int));
  streamptr->tsteps[1].nrecs = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
774
  for ( recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
775
    streamptr->tsteps[1].recIDs[recID] = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
776
777
778
      
  for ( recID = 0; recID < nrecords; recID++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
779
780
781
782
783
      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;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
784
785
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
786
787
  rindex = 0;
  while ( TRUE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
788
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
789
790
      if ( rindex > nrecords ) break;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
791
792
793
794
      recsize = gribGetSize(fileID);
      recpos  = fileGetPos(fileID);
      if ( recsize == 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
795
	  streamptr->ntsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
796
797
798
799
800
	  break;
	}
      if ( recsize > buffersize )
	{
	  buffersize = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
801
	  gribbuffer = (unsigned char *) realloc(gribbuffer, (size_t)buffersize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
802
803
804
805
806
807
	}

      readsize = recsize;
      status = gribRead(fileID, gribbuffer, &readsize);
      if ( status ) break;

808
809
810
811
812
813
814
815
816
817
      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);
	    }
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
818
819
820
      gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
	       ipunp, (int *) gribbuffer, recsize, &iword, "J", &iret);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
821
      param = cdiEncodeParam(255, ISEC1_CodeTable, ISEC1_Parameter);
822
823
      if ( ISEC1_LevelType == 100 ) ISEC1_Level1 *= 100;
      if ( ISEC1_LevelType ==  99 ) ISEC1_LevelType = 100;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
824
825
826
827
828
829
830
831
832
833
834
835
      level1    = ISEC1_Level1;
      level2    = ISEC1_Level2;

      gribDateTime(isec1, &vdate, &vtime);

      if ( rindex == 0 )
	{
	  if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
	    {
	      taxis->type  = TAXIS_RELATIVE;
	      taxis->rdate = gribRefDate(isec1);
	      taxis->rtime = gribRefTime(isec1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
836
	      taxis->unit  = cgribexGetTimeUnit(isec1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
837
838
839
840
841
842
843
	    }
	  else
	    {
	      taxis->type  = TAXIS_ABSOLUTE;
	    }
	  taxis->vdate = vdate;
	  taxis->vtime = vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
844
845
846

	  datetime0.date = vdate;
	  datetime0.time = vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
	}

      if ( ISEC1_AvgNum )
	{
	  if (  taxis->numavg && warn_numavg &&
		(taxis->numavg != ISEC1_AvgNum) )
	    {
	  /*
	      Message(func, "change numavg from %d to %d not allowed!",
		      taxis->numavg, ISEC1_AvgNum);
	  */
	      warn_numavg = FALSE;
	    }
	  else
	    {
	      taxis->numavg = ISEC1_AvgNum;
	    }
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
866
867
      datetime.date  = vdate;
      datetime.time  = vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
868
      compVar.param  = param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
869
870
871
872
873
      compVar.level1 = level1;
      compVar.level2 = level2;
      compVar.ltype  = ISEC1_LevelType;
      for ( recID = 0; recID < nrecords; recID++ )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
874
	  compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
875
876
877
	  compVar0.level1 = streamptr->tsteps[tsID].records[recID].ilevel;
	  compVar0.level2 = streamptr->tsteps[tsID].records[recID].ilevel2;
	  compVar0.ltype  = streamptr->tsteps[tsID].records[recID].ltype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
878

Uwe Schulzweida's avatar
Uwe Schulzweida committed
879
	  if ( memcmp(&compVar0, &compVar, sizeof(compvar_t)) == 0 ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
880
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
881

Uwe Schulzweida's avatar
Uwe Schulzweida committed
882
883
      if ( recID == nrecords )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
884
	  Warning(func, "Param %d level %d not found at timestep %d!", param, level1, tsID+1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
885
886
887
	  return (CDI_EUFSTRUCT);
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
      if ( cdiInventoryMode == 1 )
	{
	  if ( streamptr->tsteps[tsID].records[recID].used )
	    {
	      break;
	    }
	  else
	    {
	      streamptr->tsteps[tsID].records[recID].used = TRUE;
	      streamptr->tsteps[tsID].recIDs[rindex] = recID;
	    }    
	}
      else
	{
	  if ( streamptr->tsteps[tsID].records[recID].used )
	    {
	      if ( memcmp(&datetime, &datetime0, sizeof(DateTime)) != 0 ) break;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
906
	      Warning(func, "Param %d level %d already exist, skipped!", param, level1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
907
908
909
910
911
912
913
914
	      continue;
	    }
	  else
	    {
	      streamptr->tsteps[tsID].records[recID].used = TRUE;
	      streamptr->tsteps[tsID].recIDs[rindex] = recID;
	    }    
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
915
916

      if ( CDI_Debug )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
917
	Message(func, "%4d %8d %4d %8d %8d %6d", rindex+1, (int)recpos, param, level1, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
918

Uwe Schulzweida's avatar
Uwe Schulzweida committed
919
      streamptr->tsteps[tsID].records[recID].size = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
920

Uwe Schulzweida's avatar
Uwe Schulzweida committed
921
      compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
922
923
924
      compVar0.level1 = streamptr->tsteps[tsID].records[recID].ilevel;
      compVar0.level2 = streamptr->tsteps[tsID].records[recID].ilevel2;
      compVar0.ltype  = streamptr->tsteps[tsID].records[recID].ltype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
925

Uwe Schulzweida's avatar
Uwe Schulzweida committed
926
      if ( memcmp(&compVar0, &compVar, sizeof(compvar_t)) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
927
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
928
	  Message(func, "tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
929
		  tsID, recID,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
930
		  streamptr->tsteps[tsID].records[recID].param, param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
931
		  streamptr->tsteps[tsID].records[recID].ilevel, level1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
932
933
934
	  return (CDI_EUFSTRUCT);
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
935
936
      streamptr->tsteps[1].records[recID].position = recpos;
      varID = streamptr->tsteps[tsID].records[recID].varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
937
938
939
      gridID = vlistInqVarGrid(vlistID, varID);
      if ( gridInqSize(gridID) == 1 && gridInqType(gridID) == GRID_LONLAT )
	{
940
941
	  if ( IS_NOT_EQUAL(gridInqXval(gridID, 0),ISEC2_FirstLon*0.001) ||
	       IS_NOT_EQUAL(gridInqYval(gridID, 0),ISEC2_FirstLat*0.001) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
942
943
	    gridChangeType(gridID, GRID_TRAJECTORY);
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
944
945

      rindex++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
946
947
948
949
950
    }

  nrecs = 0;
  for ( recID = 0; recID < nrecords; recID++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
951
      if ( ! streamptr->tsteps[tsID].records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
952
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
953
	  varID = streamptr->tsteps[tsID].records[recID].varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
954
955
956
957
958
959
960
	  vlistDefVarTime(vlistID, varID, TIME_CONSTANT);
	}
      else
	{
	  nrecs++;
	}
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
961
  streamptr->tsteps[tsID].nrecs = nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
962

Uwe Schulzweida's avatar
Uwe Schulzweida committed
963
  streamptr->rtsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
964

Uwe Schulzweida's avatar
Uwe Schulzweida committed
965
  if ( streamptr->ntsteps == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
966
967
    {
      tsID = tstepsNewEntry(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
968
      if ( tsID != streamptr->rtsteps )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
969
970
	Error(func, "Internal error. tsID = %d", tsID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
971
972
      streamptr->tsteps[tsID-1].next   = TRUE;
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
973
974
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
975
976
  streamptr->record->buffer     = gribbuffer;
  streamptr->record->buffersize = buffersize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
977
978
979
980
981

  return (0);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
982
int cgribexScanTimestep(int streamID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
983
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
984
985
986
987
988
989
990
991
992
  static char func[] = "cgribexScanTimestep";
  int *isec0, *isec1, *isec2, *isec3, *isec4;
  double fsec2[512], fsec3[2], *fsec4 = NULL;
  long recsize = 0;
  off_t recpos = 0;
  unsigned char *gribbuffer;
  long buffersize = 0;
  int iret = 0, ipunp = 0, iword = 0;
  int status;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
993
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
994
995
  int param = 0;
  int level1 = 0, level2 = 0, vdate = 0, vtime = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
  DateTime datetime, datetime0;
  int tsID;
  int vrecID, recID;
  int warn_numavg = TRUE;
  size_t readsize;
  int taxisID = -1;
  TAXIS *taxis;
  int vlistID;
  int rindex, nrecs = 0;
  long unzipsize;
  compvar_t compVar, compVar0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1007
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1008
1009

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1010

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1011
  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1012

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1013
  vlistID = streamInqVlist(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1014

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1015
1016
1017
1018
1019
1020
1021
  if ( CDI_Debug )
    {
      Message(func, "streamID = %d", streamID);
      Message(func, "cts = %d", streamptr->curTsID);
      Message(func, "rts = %d", streamptr->rtsteps);
      Message(func, "nts = %d", streamptr->ntsteps);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1022

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1023
1024
1025
1026
1027
  isec0 = streamptr->record->sec0;
  isec1 = streamptr->record->sec1;
  isec2 = streamptr->record->sec2;
  isec3 = streamptr->record->sec3;
  isec4 = streamptr->record->sec4;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1028

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1029
1030
  tsID  = streamptr->rtsteps;
  taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1031

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1032
1033
1034
1035
  if ( streamptr->tsteps[tsID].recordSize == 0 )
    {
      gribbuffer = (unsigned char *) streamptr->record->buffer;
      buffersize = streamptr->record->buffersize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1036

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1037
      cdiCreateRecords(streamID, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1038

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1039
      nrecs = streamptr->tsteps[1].nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1040

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1041
1042
1043
1044
      streamptr->tsteps[tsID].nrecs = nrecs;
      streamptr->tsteps[tsID].recIDs = (int *) malloc(nrecs*sizeof(int));
      for ( recID = 0; recID < nrecs; recID++ )
	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1045

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1046
      fileID = streamInqFileID(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1047

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1048
      fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1049

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1050
1051
      rindex = 0;
      while ( TRUE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1052
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1053
	  if ( rindex > nrecs ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1054

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
	  recsize = gribGetSize(fileID);
	  recpos  = fileGetPos(fileID);
	  if ( recsize == 0 )
	    {
	      streamptr->ntsteps = streamptr->rtsteps + 1;
	      break;
	    }
	  if ( recsize > buffersize )
	    {
	      buffersize = recsize;
	      gribbuffer = (unsigned char *) realloc(gribbuffer, buffersize);
	    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1067

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
	  readsize = recsize;
	  status = gribRead(fileID, gribbuffer, &readsize);
	  if ( status )
	    {
	      Error(func, "Inconsistent timestep %d (GRIB record %d/%d)!\n", tsID+1, rindex+1,
		    streamptr->tsteps[tsID].recordSize);
	      break;
	    }

	  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);
		}
	    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1086

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1087
1088
	  gribExDP(isec0, isec1, isec2, fsec2, isec3, fsec3, isec4, fsec4,
		   ipunp, (int *) gribbuffer, recsize, &iword, "J", &iret);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1089

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1090
	  param = cdiEncodeParam(255, ISEC1_CodeTable, ISEC1_Parameter);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1091
1092
1093
1094
1095
1096
1097
1098
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
	  if ( ISEC1_LevelType == 100 ) ISEC1_Level1 *= 100;
	  if ( ISEC1_LevelType ==  99 ) ISEC1_LevelType = 100;
	  level1   = ISEC1_Level1;
	  level2   = ISEC1_Level2;

	  gribDateTime(isec1, &vdate, &vtime);

	  if ( rindex == nrecs ) break;

	  if ( rindex == 0 )
	    {
	      taxisID = vlistInqTaxis(vlistID);
	      if ( taxisInqType(taxisID) == TAXIS_RELATIVE )
		{
		  taxis->type  = TAXIS_RELATIVE;
		  taxis->rdate = gribRefDate(isec1);
		  taxis->rtime = gribRefTime(isec1);
		  taxis->unit  = cgribexGetTimeUnit(isec1);
		}
	      else
		{
		  taxis->type  = TAXIS_ABSOLUTE;
		}
	      taxis->vdate = vdate;
	      taxis->vtime = vtime;

	      datetime0.date = vdate;
	      datetime0.time = vtime;
	    }

	  if ( ISEC1_AvgNum )
	    {
	      if (  taxis->numavg && warn_numavg &&
		   (taxis->numavg != ISEC1_AvgNum) )
		{
	      /*
		  Message(func, "Change numavg from %d to %d not allowed!",
			  streamptr->tsteps[tsID].taxis.numavg, ISEC1_AvgNum);
	      */
		  warn_numavg = FALSE;
		}
	      else
		{
		  taxis->numavg = ISEC1_AvgNum;
		}
	    }
	  
	  datetime.date  = vdate;
	  datetime.time  = vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1140
	  compVar.param  = param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1141
1142
1143
1144
1145
1146
          compVar.level1 = level1;
          compVar.level2 = level2;
          compVar.ltype  = ISEC1_LevelType;
	  for ( vrecID = 0; vrecID < nrecs; vrecID++ )
	    {
	      recID   = streamptr->tsteps[1].recIDs[vrecID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1147
	      compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1148
1149
1150
1151
1152
1153
1154
1155
1156
	      compVar0.level1 = streamptr->tsteps[tsID].records[recID].ilevel;
	      compVar0.level2 = streamptr->tsteps[tsID].records[recID].ilevel2;
	      compVar0.ltype  = streamptr->tsteps[tsID].records[recID].ltype;

	      if ( memcmp(&compVar0, &compVar, sizeof(compvar_t)) == 0 ) break;
	    }

	  if ( vrecID == nrecs )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1157
	      Warning(func, "Param %d level %d not available at timestep %d!", param, level1, tsID+1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176

	      if ( cdiInventoryMode == 1 )
		return (CDI_EUFSTRUCT);
	      else
		continue;
	    }

	  if ( cdiInventoryMode == 1 )
	    {
	      streamptr->tsteps[tsID].records[recID].used = TRUE;
	      streamptr->tsteps[tsID].recIDs[rindex] = recID;
	    }
	  else
	    {
	      if ( streamptr->tsteps[tsID].records[recID].used )
		{
		  if ( memcmp(&datetime, &datetime0, sizeof(DateTime)) != 0 ) break;
		  
		  if ( CDI_Debug )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1177
		    Warning(func, "Param %d level %d already exist, skipped!", param, level1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1178
1179
1180
1181
1182
1183
1184
1185
1186

		  continue;
		}
	      else
		{
		  streamptr->tsteps[tsID].records[recID].used = TRUE;
		  streamptr->tsteps[tsID].recIDs[rindex] = recID;
		}    
	    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1187

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1188
	  if ( CDI_Debug )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1189
	    Message(func, "%4d %8d %4d %8d %8d %6d", rindex+1, (int)recpos, param, level1, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1190

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1191
	  compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1192
1193
1194
	  compVar0.level1 = streamptr->tsteps[tsID].records[recID].ilevel;
	  compVar0.level2 = streamptr->tsteps[tsID].records[recID].ilevel2;
	  compVar0.ltype  = streamptr->tsteps[tsID].records[recID].ltype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1195

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1196
1197
	  if ( memcmp(&compVar0, &compVar, sizeof(compvar_t)) != 0 )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1198
	      Message(func, "tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1199
		      tsID, recID,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1200
		      streamptr->tsteps[tsID].records[recID].param, param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1201
1202
1203
1204
1205
1206
		      streamptr->tsteps[tsID].records[recID].ilevel, level1);
	      Error(func, "Invalid, unsupported or inconsistent record structure");
	    }
	  
	  streamptr->tsteps[tsID].records[recID].position = recpos;
	  streamptr->tsteps[tsID].records[recID].size = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1207

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1208
	  if ( CDI_Debug )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1209
	    Message(func, "%4d %8d %4d %8d %8d %6d", rindex, (int)recpos, param, level1, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1210

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1211
1212
	  rindex++;
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1213

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1214
1215
1216
1217
1218
      for ( vrecID = 0; vrecID < nrecs; vrecID++ )
	{
	  recID   = streamptr->tsteps[tsID].recIDs[vrecID];
	  if ( ! streamptr->tsteps[tsID].records[recID].used ) break;
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1219

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1220
1221
      if ( vrecID < nrecs )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1222
1223
	  Warning(func, "Param %d level %d not found at timestep %d!",
		  streamptr->tsteps[tsID].records[recID].param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1224
1225
1226
1227
		  streamptr->tsteps[tsID].records[recID].ilevel,
		  tsID+1);
	  return (CDI_EUFSTRUCT);
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1228

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1229
      streamptr->rtsteps++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1230

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1231
1232
1233
1234
1235
      if ( streamptr->ntsteps != streamptr->rtsteps )
	{
	  tsID = tstepsNewEntry(streamID);
	  if ( tsID != streamptr->rtsteps )
	    Error(func, "Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1236

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1237
1238
1239
	  streamptr->tsteps[tsID-1].next   = 1;
	  streamptr->tsteps[tsID].position = recpos;
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1240

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1241
1242
      fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1243

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1244
1245
1246
      streamptr->record->buffer     = gribbuffer;
      streamptr->record->buffersize = buffersize;
    }
1247

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1248
1249
1250
1251
  if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
    {
      Warning(func, "Incomplete timestep. Stop scanning at timestep %d.\n", tsID);
      streamptr->ntsteps = tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1252
1253
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1254
  return (streamptr->ntsteps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1255
1256
}

1257

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1258
1259