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

5
#include <limits.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <string.h>

#include "dmemory.h"

#include "error.h"
#include "file.h"
#include "cdi.h"
14
#include "cdi_int.h"
15
#include "stream_ext.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include "varscan.h"
#include "datetime.h"
#include "extra.h"
#include "vlist.h"


#undef  UNDEFID
#define UNDEFID  CDI_UNDEFID

#define SINGLE_PRECISION  4
#define DOUBLE_PRECISION  8

#if defined (HAVE_LIBEXTRA)

30
31

typedef struct {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
32
  int param;
33
  int level;
34
} extcompvar_t;
35

Uwe Schulzweida's avatar
Uwe Schulzweida committed
36
static
37
int extInqDatatype(int prec, int number)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
38
39
40
{
  int datatype;

41
42
43
44
45
46
47
48
49
50
  if ( number == 2 )
    {
      if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_CPX64;
      else                            datatype = DATATYPE_CPX32;
    }
  else
    {
      if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64;
      else                            datatype = DATATYPE_FLT32;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
51

52
  return datatype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
53
54
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
55
static
56
void extDefDatatype(int datatype, int *prec, int *number)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
57
58
{

59
60
  if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 &&
       datatype != DATATYPE_CPX32 && datatype != DATATYPE_CPX64 )
61
    datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
62

63
64
65
66
  if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
    *number = 2;
  else
    *number = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
67

68
69
70
71
  if ( datatype == DATATYPE_FLT64 || datatype == DATATYPE_CPX64 )
    *prec = DOUBLE_PRECISION;
  else 
    *prec = SINGLE_PRECISION;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
72
73
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
74
/* not used
75
int extInqRecord(stream_t *streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
76
77
78
{
  int status;
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
79
  int icode, ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
80
81
82
  int zaxisID = -1;
  int header[4];
  int vlistID;
83
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
84

85
86
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
87
88
89
90
91

  *varID   = -1;
  *levelID = -1;

  status = extRead(fileID, extp);
92
  if ( status != 0 ) return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
94
95

  extInqHeader(extp, header);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
96
  icode  = header[1];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
97
98
  ilevel = header[2];

Uwe Schulzweida's avatar
Uwe Schulzweida committed
99
  *varID = vlistInqVarID(vlistID, icode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
100

101
  if ( *varID == UNDEFID ) Error("Code %d undefined", icode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
102
103
104
105

  zaxisID = vlistInqVarZaxis(vlistID, *varID);

  *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
106

107
  return 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
108
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
109
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
110

111
void extReadRecord(stream_t *streamptr, double *data, int *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
112
{
113
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
114

115
116
117
118
119
120
121
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
  int tsID    = streamptr->curTsID;
  int vrecID  = streamptr->tsteps[tsID].curRecID;
  int recID   = streamptr->tsteps[tsID].recIDs[vrecID];
  int varID   = streamptr->tsteps[tsID].records[recID].varID;
  off_t recpos = streamptr->tsteps[tsID].records[recID].position;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
122
123
124

  fileSetPos(fileID, recpos, SEEK_SET);

125
126
  int status = extRead(fileID, extp);
  if ( status != 0 ) Error("Failed to read EXTRA record");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
127

128
  int header[4];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
129
130
131
  extInqHeader(extp, header);
  extInqDataDP(extp, data);

132
133
134
  double missval = vlistInqVarMissval(vlistID, varID);
  int gridID  = vlistInqVarGrid(vlistID, varID);
  int size    = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
135

Uwe Schulzweida's avatar
Uwe Schulzweida committed
136
  streamptr->numvals += size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
137
138

  *nmiss = 0;
139
140
  if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
    {
141
      for ( int i = 0; i < size; i++ )
142
143
144
145
146
147
148
149
	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
	  {
	    data[i] = missval;
	    (*nmiss)++;
	  }
    }
  else
    {
150
      for ( int i = 0; i < 2*size; i+=2 )
151
152
153
154
155
156
	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
	  {
	    data[i] = missval;
	    (*nmiss)++;
	  }
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
158
159
}


160
void extCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
161
{
162
  streamFCopyRecord(streamptr2, streamptr1, "EXTRA");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
163
164
165
}


166
void extDefRecord(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
167
{
168
  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
169
  int gridID   = streamptr->record->gridID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
170

171
  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
172
  cdiDecodeParam(streamptr->record->param, &pnum, &pcat, &pdis);
173
174

  int header[4];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
175
  header[0] = streamptr->record->date;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
176
  header[1] = pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
177
  header[2] = streamptr->record->level;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
178
179
  header[3] = gridInqSize(gridID);

180
  extDefDatatype(streamptr->record->prec, &extp->prec, &extp->number);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
181
182
183
184
185

  extDefHeader(extp, header);
}


186
void extWriteRecord(stream_t *streamptr, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
187
{
188
  int fileID = streamptr->fileID;
189
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
190
191
192
193
194

  extDefDataDP(extp, data);
  extWrite(fileID, extp);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
195
static
196
void extAddRecord(stream_t *streamptr, int param, int level, int xysize,
197
		  size_t recsize, off_t position, int prec, int number)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
198
{
199
200
201
202
  int vlistID = streamptr->vlistID;
  int tsID    = streamptr->curTsID;
  int recID   = recordNewEntry(streamptr, tsID);
  record_t *record  = &streamptr->tsteps[tsID].records[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
203

204
205
206
207
  record->size     = recsize;
  record->position = position;
  record->param    = param;
  record->ilevel   = level;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
208

209
210
  grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
  grid_init(grid);
211
  cdiGridTypeInit(grid, GRID_GENERIC, xysize);
212
213
  grid->x.size = xysize;
  grid->y.size = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
214
  struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
215
216
  int gridID = gridAdded.Id;
  if (!gridAdded.isNew) Free(grid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
217
218
219
220
  /*
  if ( level == 0 ) leveltype = ZAXIS_SURFACE;
  else              leveltype = ZAXIS_GENERIC;
  */
221
  int leveltype = ZAXIS_GENERIC;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
222

223
  int varID, levelID = 0;
224
  varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
225
               extInqDatatype(prec, number), &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
226
               NULL, NULL, NULL, NULL, NULL, NULL);
227
228
  record->varID   = (short)varID;
  record->levelID = (short)levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
229

Uwe Schulzweida's avatar
Uwe Schulzweida committed
230
231
  streamptr->tsteps[tsID].nallrecs++;
  streamptr->nrecs++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
232
233

  if ( CDI_Debug )
234
    Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
235
236
}

237
static
238
239
void extScanTimestep1(stream_t *streamptr)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
240
  int header[4];
241
  DateTime datetime0 = { LONG_MIN, LONG_MIN };
Uwe Schulzweida's avatar
Uwe Schulzweida committed
242
  int varID;
243
  off_t recpos = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
244
  long recsize;
245
  int recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
246
  extcompvar_t compVar, compVar0;
247
  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
248

Uwe Schulzweida's avatar
Uwe Schulzweida committed
249
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
250

251
252
  int tsID  = tstepsNewEntry(streamptr);
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
253
254

  if ( tsID != 0 )
255
    Error("Internal problem! tstepsNewEntry returns %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
256

257
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
258

259
  int nrecs = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
260
261
262
  while ( TRUE )
    {
      recpos = fileGetPos(fileID);
263
      int status = extRead(fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
264
265
      if ( status != 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
266
	  streamptr->ntsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
267
268
269
270
271
272
	  break;
	}
      recsize = fileGetPos(fileID) - recpos;

      extInqHeader(extp, header);

273
274
275
276
277
      int vdate   = header[0];
      int vtime   = 0;
      int rcode   = header[1];
      int rlevel  = header[2];
      int rxysize = header[3];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
278

279
      int param = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
280

Uwe Schulzweida's avatar
Uwe Schulzweida committed
281
282
283
284
285
286
287
      if ( nrecs == 0 )
	{
	  datetime0.date = vdate;
	  datetime0.time = vtime;
	}
      else
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
288
	  compVar.param = param;
289
          compVar.level = rlevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
290
291
	  for ( recID = 0; recID < nrecs; recID++ )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
292
	      compVar0.param  = streamptr->tsteps[0].records[recID].param;
293
294
	      compVar0.level = streamptr->tsteps[0].records[recID].ilevel;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
295
	      if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
296
297
	    }
	  if ( recID < nrecs ) break;
298
299
	  DateTime datetime = { .date = vdate, .time = vtime};
	  if ( datetimeCmp(datetime, datetime0) )
300
	    Warning("Inconsistent verification time for code %d level %d", rcode, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
301
302
303
304
305
	}

      nrecs++;

      if ( CDI_Debug )
306
	Message("%4d%8d%4d%8d%8d%6d", nrecs, (int)recpos, rcode, rlevel, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
307

308
      extAddRecord(streamptr, param, rlevel, rxysize, (size_t)recsize, recpos, extp->prec, extp->number);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
309
310
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
311
  streamptr->rtsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
312

313
  cdi_generate_vars(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
314

315
  int taxisID = taxisCreate(TAXIS_ABSOLUTE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
316
  taxis->type  = TAXIS_ABSOLUTE;
317
318
  taxis->vdate = (int)datetime0.date;
  taxis->vtime = (int)datetime0.time;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
319

320
  int vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
321
322
  vlistDefTaxis(vlistID, taxisID);

323
  vlist_check_contents(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324

325
  int nrecords = streamptr->tsteps[0].nallrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
326
  if ( nrecords < streamptr->tsteps[0].recordSize )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
327
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
328
329
      streamptr->tsteps[0].recordSize = nrecords;
      streamptr->tsteps[0].records =
330
        (record_t *) Realloc(streamptr->tsteps[0].records, (size_t)nrecords * sizeof (record_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
331
332
    }

333
  streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
334
  streamptr->tsteps[0].nrecs = nrecords;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
335
  for ( recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
336
    streamptr->tsteps[0].recIDs[recID] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
337

Uwe Schulzweida's avatar
Uwe Schulzweida committed
338
  if ( streamptr->ntsteps == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
339
    {
340
      tsID = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
341
      if ( tsID != streamptr->rtsteps )
342
	Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
343

Uwe Schulzweida's avatar
Uwe Schulzweida committed
344
345
      streamptr->tsteps[tsID-1].next   = TRUE;
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
346
347
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
348
  if ( streamptr->ntsteps == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
349
350
351
    {
      if ( taxis->vdate == 0 && taxis->vtime == 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
352
353
	  streamptr->ntsteps = 0;
	  for ( varID = 0; varID < streamptr->nvars; varID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
354
	    {
355
	      vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
356
357
358
359
360
	    }
	}
    }
}

361
static
362
363
int extScanTimestep2(stream_t *streamptr)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
364
365
366
  int header[4];
  int varID;
  off_t recpos = 0;
367
  int nrecs, recID, rindex;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
368
  extcompvar_t compVar, compVar0;
369
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
370
371

  streamptr->curTsID = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
372

373
374
  int fileID  = streamptr->fileID;
  int vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
375

376
  int tsID = streamptr->rtsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
377
  if ( tsID != 1 )
378
    Error("Internal problem! unexpected timestep %d", tsID+1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
379

380
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
381

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

384
  cdi_create_records(streamptr, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
385

386
  int nrecords = streamptr->tsteps[0].nallrecs;
387
  streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
388
  streamptr->tsteps[1].nrecs = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
389
  for ( recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
390
    streamptr->tsteps[1].recIDs[recID] = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
391
392
393

  for ( recID = 0; recID < nrecords; recID++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
394
      varID = streamptr->tsteps[0].records[recID].varID;
395
      streamptr->tsteps[tsID].records[recID].position =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
396
	streamptr->tsteps[0].records[recID].position;
397
      streamptr->tsteps[tsID].records[recID].size     =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
398
	streamptr->tsteps[0].records[recID].size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
399
400
401
402
403
    }

  for ( rindex = 0; rindex <= nrecords; rindex++ )
    {
      recpos = fileGetPos(fileID);
404
      int status = extRead(fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
405
406
      if ( status != 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
407
	  streamptr->ntsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
408
409
	  break;
	}
410
      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
411
412
413

      extInqHeader(extp, header);

414
415
416
417
      int vdate  = header[0];
      int vtime  = 0;
      int rcode  = header[1];
      int rlevel = header[2];
418
      // rxysize = header[3];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
419

420
      int param = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
421

Uwe Schulzweida's avatar
Uwe Schulzweida committed
422
423
424
425
426
427
428
      if ( rindex == 0 )
	{
	  taxis->type  = TAXIS_ABSOLUTE;
	  taxis->vdate = vdate;
	  taxis->vtime = vtime;
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
429
      compVar.param = param;
430
      compVar.level = rlevel;
431
      bool nextstep = false;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
432
433
      for ( recID = 0; recID < nrecords; recID++ )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
434
	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
435
436
	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
437
	  if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
438
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
439
	      if ( streamptr->tsteps[tsID].records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
440
		{
441
		  nextstep = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
442
443
444
		}
	      else
		{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
445
446
		  streamptr->tsteps[tsID].records[recID].used = TRUE;
		  streamptr->tsteps[tsID].recIDs[rindex] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
447
448
449
450
451
452
		}
	      break;
	    }
	}
      if ( recID == nrecords )
	{
453
	  Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
454
	  return CDI_EUFSTRUCT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
455
456
457
458
459
	}

      if ( nextstep ) break;

      if ( CDI_Debug )
460
	Message("%4d%8d%4d%8d%8d%6d", rindex+1, (int)recpos, rcode, rlevel, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
461

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
464
      compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
465
      compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
466

Uwe Schulzweida's avatar
Uwe Schulzweida committed
467
      if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
468
	{
469
	  Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
470
		  tsID, recID,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
471
		  streamptr->tsteps[tsID].records[recID].param, param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
472
		  streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
473
	  return CDI_EUFSTRUCT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
474
475
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
476
      streamptr->tsteps[1].records[recID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
477
478
479
480
481
    }

  nrecs = 0;
  for ( recID = 0; recID < nrecords; recID++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
482
      if ( ! streamptr->tsteps[tsID].records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
483
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
484
	  varID = streamptr->tsteps[tsID].records[recID].varID;
485
          vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
486
487
488
489
490
491
	}
      else
	{
	  nrecs++;
	}
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
  streamptr->tsteps[tsID].nrecs = nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
493

Uwe Schulzweida's avatar
Uwe Schulzweida committed
494
  streamptr->rtsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
495

Uwe Schulzweida's avatar
Uwe Schulzweida committed
496
  if ( streamptr->ntsteps == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
497
    {
498
      tsID = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
499
      if ( tsID != streamptr->rtsteps )
500
	Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
501

Uwe Schulzweida's avatar
Uwe Schulzweida committed
502
503
      streamptr->tsteps[tsID-1].next   = TRUE;
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
504
505
    }

506
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
507
508
509
}


510
int extInqContents(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511
512
{
  int status = 0;
513
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
514

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

517
518
519
  extScanTimestep1(streamptr);

  if ( streamptr->ntsteps == -1 ) status = extScanTimestep2(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
520
521
522

  fileSetPos(fileID, 0, SEEK_SET);

523
  return status;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
525
}

526
static
527
long extScanTimestep(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528
529
530
531
532
{
  int header[4];
  off_t recpos = 0;
  int recID;
  int rindex, nrecs = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
533
  extcompvar_t compVar, compVar0;
534
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
535
  /*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
536
537
  if ( CDI_Debug )
    {
538
      Message("streamID = %d", streamptr->self);
539
540
541
      Message("cts = %d", streamptr->curTsID);
      Message("rts = %d", streamptr->rtsteps);
      Message("nts = %d", streamptr->ntsteps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
543
  */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
544

Uwe Schulzweida's avatar
Uwe Schulzweida committed
545
546
  int tsID  = streamptr->rtsteps;
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
547

Uwe Schulzweida's avatar
Uwe Schulzweida committed
548
  if ( streamptr->tsteps[tsID].recordSize == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
549
    {
550
      cdi_create_records(streamptr, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
551

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
554
      streamptr->tsteps[tsID].nrecs = nrecs;
555
      streamptr->tsteps[tsID].recIDs = (int *) Malloc((size_t)nrecs * sizeof (int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
556
      for ( recID = 0; recID < nrecs; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
557
	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
558

559
      int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
560

Uwe Schulzweida's avatar
Uwe Schulzweida committed
561
      fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
563
564
565

      for ( rindex = 0; rindex <= nrecs; rindex++ )
	{
	  recpos = fileGetPos(fileID);
566
	  int status = extRead(fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
567
568
	  if ( status != 0 )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
569
	      streamptr->ntsteps = streamptr->rtsteps + 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
570
571
	      break;
	    }
572
	  size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
573
574
575

	  extInqHeader(extp, header);

576
577
578
579
	  int vdate  = header[0];
	  int vtime  = 0;
	  int rcode  = header[1];
	  int rlevel = header[2];
580
	  // rxysize = header[3];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
581

582
	  int param = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
583

584
585
	  // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
	  if ( rindex == nrecs ) continue;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
586
	  recID = streamptr->tsteps[tsID].recIDs[rindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
587
588
589
590
591
592
593

	  if ( rindex == 0 )
	    {
	      taxis->type  = TAXIS_ABSOLUTE;
	      taxis->vdate = vdate;
	      taxis->vtime = vtime;
	    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
594

Uwe Schulzweida's avatar
Uwe Schulzweida committed
595
596
597
	  compVar.param  = param;
          compVar.level  = rlevel;
	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
598
	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
599

Uwe Schulzweida's avatar
Uwe Schulzweida committed
600
	  if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
601
	    {
602
	      Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
603
		      tsID, recID,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
604
		      streamptr->tsteps[tsID].records[recID].param, param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
605
		      streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
606
	      Error("Invalid, unsupported or inconsistent record structure!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
607
608
	    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
609
610
	  streamptr->tsteps[tsID].records[recID].position = recpos;
	  streamptr->tsteps[tsID].records[recID].size = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
611
612

	  if ( CDI_Debug )
613
	    Message("%4d%8d%4d%8d%8d%6d", rindex, (int)recpos, rcode, rlevel, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
614
615
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
616
      streamptr->rtsteps++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
617

Uwe Schulzweida's avatar
Uwe Schulzweida committed
618
      if ( streamptr->ntsteps != streamptr->rtsteps )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
619
	{
620
	  tsID = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
621
	  if ( tsID != streamptr->rtsteps )
622
	    Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
623

Uwe Schulzweida's avatar
Uwe Schulzweida committed
624
625
	  streamptr->tsteps[tsID-1].next   = 1;
	  streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
626
627
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
628
629
      fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
630
631
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
632
  if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
633
    {
634
      Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
635
      streamptr->ntsteps = tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
636
637
    }

638
  return streamptr->ntsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
639
640
641
}


642
int extInqTimestep(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
643
{
644
  int nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
645

Uwe Schulzweida's avatar
Uwe Schulzweida committed
646
  if ( tsID == 0 && streamptr->rtsteps == 0 )
647
    Error("Call to cdiInqContents missing!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
648
649

  if ( CDI_Debug )
650
    Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
651

652
  long ntsteps = UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
653
  while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
654
    ntsteps = extScanTimestep(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
655

Uwe Schulzweida's avatar
Uwe Schulzweida committed
656
  if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
657
658
659
660
661
    {
      nrecs = 0;
    }
  else
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
662
663
      streamptr->curTsID = tsID;
      nrecs = streamptr->tsteps[tsID].nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
664
665
    }

666
  return nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
667
668
669
}


670
void extReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
671
672
{
  int header[4];
673
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
674

675
676
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
677
  /* NOTE: tiles are not supported here! */
678
679
680
681
682
  size_t nlevs = (size_t)streamptr->vars[varID].recordTable[0].nlevs;
  double missval  = vlistInqVarMissval(vlistID, varID);
  int gridID   = vlistInqVarGrid(vlistID, varID);
  size_t gridsize = (size_t)gridInqSize(gridID);
  int tsid     = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
683

684
  if ( CDI_Debug ) Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
685

686
  off_t currentfilepos = fileGetPos(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
687

688
  for ( size_t levID = 0; levID < nlevs; levID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
689
    {
690
      /* NOTE: tiles are not supported here! */
691
692
      int recID = streamptr->vars[varID].recordTable[0].recordID[levID];
      off_t recpos = streamptr->tsteps[tsid].records[recID].position;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
693
      fileSetPos(fileID, recpos, SEEK_SET);
694
      extRead(fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
695
696
697
698
699
700
      extInqHeader(extp, header);
      extInqDataDP(extp, &data[levID*gridsize]);
    }
  fileSetPos(fileID, currentfilepos, SEEK_SET);

  *nmiss = 0;
701
702
  if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
    {
703
      for ( size_t i = 0; i < nlevs*gridsize; i++ )
704
705
706
707
708
709
710
711
	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
	  {
	    data[i] = missval;
	    (*nmiss)++;
	  }
    }
  else
    {
712
      for ( size_t i = 0; i < 2*nlevs*gridsize; i+=2 )
713
714
715
716
717
718
	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
	  {
	    data[i] = missval;
	    (*nmiss)++;
	  }
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
719
720
721
}


722
void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
723
724
{
  int header[4];
725
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
726

727
728
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
729
  /* NOTE: tiles are not supported here! */
730
731
732
733
734
  int nlevs    = streamptr->vars[varID].recordTable[0].nlevs;
  double missval  = vlistInqVarMissval(vlistID, varID);
  int gridID   = vlistInqVarGrid(vlistID, varID);
  int gridsize = gridInqSize(gridID);
  int tsid     = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
735
736

  if ( CDI_Debug )
737
    Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
738

739
  off_t currentfilepos = fileGetPos(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
740

741
  /* NOTE: tiles are not supported here! */
742
743
  int recID = streamptr->vars[varID].recordTable[0].recordID[levID];
  off_t recpos = streamptr->tsteps[tsid].records[recID].position;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
744
  fileSetPos(fileID, recpos, SEEK_SET);
745
  extRead(fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
746
747
  extInqHeader(extp, header);
  extInqDataDP(extp, data);
Thomas Jahns's avatar
Thomas Jahns committed
748

Uwe Schulzweida's avatar
Uwe Schulzweida committed
749
750
751
  fileSetPos(fileID, currentfilepos, SEEK_SET);

  *nmiss = 0;
752
753
  if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
    {
754
      for ( int i = 0; i < gridsize; i++ )
755
756
757
758
759
760
761
762
	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
	  {
	    data[i] = missval;
	    (*nmiss)++;
	  }
    }
  else
    {
763
      for ( int i = 0; i < 2*gridsize; i+=2 )
764
765
766
767
768
769
	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
	  {
	    data[i] = missval;
	    (*nmiss)++;
	  }
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
770
771
772
}


773
void extWriteVarDP(stream_t *streamptr, int varID, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
774
775
{
  int header[4];
776
  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
777

778
  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
779

780
781
782
783
784
785
786
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
  int tsID     = streamptr->curTsID;
  int gridID   = vlistInqVarGrid(vlistID, varID);
  int gridsize = gridInqSize(gridID);
  int zaxisID  = vlistInqVarZaxis(vlistID, varID);
  int nlevs    = zaxisInqSize(zaxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
787
788

  if ( CDI_Debug )
789
    Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
790

791
  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
792
  cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
793

Uwe Schulzweida's avatar
Uwe Schulzweida committed
794
  header[0] = streamptr->tsteps[tsID].taxis.vdate;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
795
  header[1] = pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
796
797
  header[3] = gridInqSize(gridID);

798
  extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
799

800
  for ( int levID = 0;  levID < nlevs; levID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
801
    {
802
      double level = zaxisInqLevel(zaxisID, levID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
803
804
805
806
807
808
809
810
811

      header[2] = (int) level;
      extDefHeader(extp, header);
      extDefDataDP(extp, &data[levID*gridsize]);
      extWrite(fileID, extp);
    }
}


812
void extWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
813
814
{
  int header[4];
815
  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
816

817
818
819
820
821
822
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
  int tsID     = streamptr->curTsID;
  int gridID   = vlistInqVarGrid(vlistID, varID);
  int zaxisID  = vlistInqVarZaxis(vlistID, varID);
  double level = zaxisInqLevel(zaxisID, levID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
823

824
  if ( CDI_Debug ) Message("gridID = %d zaxisID = %d", gridID, zaxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
825

826
  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
827
  cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
828

Uwe Schulzweida's avatar
Uwe Schulzweida committed
829
  header[0] = streamptr->tsteps[tsID].taxis.vdate;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
830
  header[1] = pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
831
832
833
  header[2] = (int) level;
  header[3] = gridInqSize(gridID);

834
  extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
835
836
837
838
839
840
841

  extDefHeader(extp, header);
  extDefDataDP(extp, data);
  extWrite(fileID, extp);
}

#endif /* HAVE_LIBEXTRA */
842
843
844
845
846
847
848
849
850
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */