stream_ext.c 24.5 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

#include <stdio.h>
#include <string.h>

#include "dmemory.h"

#include "error.h"
#include "file.h"
#include "cdi.h"
#include "stream_int.h"
#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)

28
29

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
34
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
35
36
37
38
int extInqDatatype(int prec)
{
  int datatype;

39
40
  if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64;
  else                            datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
42
43
44

  return (datatype);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
45
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
46
47
48
49
int extDefDatatype(int datatype)
{
  int prec;

50
51
  if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 )
    datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
52

53
  if ( datatype == DATATYPE_FLT64 ) prec = DOUBLE_PRECISION;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
54
55
56
57
58
  else                              prec = SINGLE_PRECISION;

  return (prec);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
59
/* not used
Uwe Schulzweida's avatar
Uwe Schulzweida committed
60
61
62
63
64
int extInqRecord(int streamID, int *varID, int *levelID)
{
  static char func[] = "extInqRecord";
  int status;
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
65
  int icode, ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
66
67
68
  int zaxisID = -1;
  int header[4];
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
69
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
70
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
71

Uwe Schulzweida's avatar
Uwe Schulzweida committed
72
73
74
  streamptr = stream_to_pointer(streamID);

  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
75
76
77

  vlistID = streamInqVlist(streamID);
  fileID  = streamInqFileID(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
78
  extp    = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
79
80
81
82
83
84
85
86
87

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

  status = extRead(fileID, extp);
  if ( status != 0 ) return (0);

  extInqHeader(extp, header);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
88
  icode  = header[1];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
89
90
  ilevel = header[2];

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
  if ( *varID == UNDEFID ) Error(func, "Code %d undefined", icode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
94
95
96
97
98
99
100

  zaxisID = vlistInqVarZaxis(vlistID, *varID);

  *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
  
  return (1);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
101
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
102
103
104
105
106
107
108
109
110
111
112
113

int extReadRecord(int streamID, double *data, int *nmiss)
{
  static char func[] = "extReadRecord";
  int vlistID, fileID;
  int status;
  int recID, vrecID, tsID;
  off_t recpos;
  int header[4];
  int varID, gridID;
  int i, size;
  double missval;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
114
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
115
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
116
117

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
119
  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
120
121
122

  vlistID = streamInqVlist(streamID);
  fileID  = streamInqFileID(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
123
124
125
126
127
128
  tsID    = streamptr->curTsID;
  vrecID  = streamptr->tsteps[tsID].curRecID;
  recID   = streamptr->tsteps[tsID].recIDs[vrecID];
  recpos  = streamptr->tsteps[tsID].records[recID].position;
  varID   = streamptr->tsteps[tsID].records[recID].varID;
  extp    = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
129
130
131
132
133
134
135
136
137

  fileSetPos(fileID, recpos, SEEK_SET);

  status = extRead(fileID, extp);
  if ( status != 0 ) return (0);

  extInqHeader(extp, header);
  extInqDataDP(extp, data);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
138
  missval = vlistInqVarMissval(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
139
140
  gridID  = vlistInqVarGrid(vlistID, varID);
  size    = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
141

Uwe Schulzweida's avatar
Uwe Schulzweida committed
142
  streamptr->numvals += size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
143
144
145
146
147
148
149
150
151
152
153
154
155

  *nmiss = 0;
  for ( i = 0; i < size; i++ )
    if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
      {
	data[i] = missval;
	(*nmiss)++;
      }

  return (1);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
156
int extCopyRecord(int streamID2, int streamID1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
158
{
  static char func[] = "extCopyRecord";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
159
  int fileID1, fileID2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
160
161
162
163
164
  int tsID, recID, vrecID;
  long recsize;
  off_t recpos;
  int status = 0;
  char *buffer;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
165
166
  stream_t *streamptr1;
  stream_t *streamptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
167

Uwe Schulzweida's avatar
Uwe Schulzweida committed
168
169
  streamptr1 = stream_to_pointer(streamID1);
  streamptr2 = stream_to_pointer(streamID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
170

Uwe Schulzweida's avatar
Uwe Schulzweida committed
171
172
  stream_check_ptr(func, streamptr1);
  stream_check_ptr(func, streamptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
173

Uwe Schulzweida's avatar
Uwe Schulzweida committed
174
175
  fileID1 = streamInqFileID(streamID1);
  fileID2 = streamInqFileID(streamID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
176

Uwe Schulzweida's avatar
Uwe Schulzweida committed
177
178
179
180
181
182
183
  tsID    = streamptr1->curTsID;
  vrecID  = streamptr1->tsteps[tsID].curRecID;
  recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
  recpos  = streamptr1->tsteps[tsID].records[recID].position;
  recsize = streamptr1->tsteps[tsID].records[recID].size;

  fileSetPos(fileID1, recpos, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
184
185
186

  buffer = (char *) malloc(recsize);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
187
  fileRead(fileID1, buffer, recsize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
188

Uwe Schulzweida's avatar
Uwe Schulzweida committed
189
  fileWrite(fileID2, buffer, recsize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
190
191
192
193
194
195
196
197
198
199
200
201
202
203

  free(buffer);

  return (status);
}


int extDefRecord(int streamID)
{
  static char func[] = "extDefRecord";
  int fileID;
  int gridID;
  int header[4];
  int status = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
204
  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
206
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
207
208

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
210
  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
211

212
213
214
  fileID   = streamInqFileID(streamID);
  gridID   = streamptr->record->gridID;
  extp     = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
215

Uwe Schulzweida's avatar
Uwe Schulzweida committed
216
  cdiDecodeParam(streamptr->record->param, &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
217
  header[0] = streamptr->record->date;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
218
  header[1] = pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
219
  header[2] = streamptr->record->level;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
220
221
  header[3] = gridInqSize(gridID);

222
223
  extp->prec   = extDefDatatype(streamptr->record->prec);
  extp->number = streamptr->record->number;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
224
225
226
227
228
229
230
231
232
233
234
235

  extDefHeader(extp, header);

  return (status);
}


int extWriteRecord(int streamID, const double *data)
{
  static char func[] = "extWriteRecord";
  int fileID;
  int status = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
236
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
237
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
238

Uwe Schulzweida's avatar
Uwe Schulzweida committed
239
240
241
  streamptr = stream_to_pointer(streamID);

  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
242
243

  fileID = streamInqFileID(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
244
  extp   = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
245
246
247
248
249
250
251
252

  extDefDataDP(extp, data);

  extWrite(fileID, extp);

  return (status);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
253
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
254
void extAddRecord(int streamID, int param, int level, int xysize,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
255
		  long recsize, off_t position, int prec, int number)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
256
257
258
259
260
261
{
  static char func[] = "extAddRecord";
  int leveltype;
  int gridID = UNDEFID;
  int levelID = 0;
  int tsID, recID, varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
262
  record_t *record;
263
  grid_t grid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
264
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
265
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
266
267

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

  vlistID = streamInqVlist(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
270
  tsID    = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
271
  recID   = recordNewEntry(streamID, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
272
  record  = &streamptr->tsteps[tsID].records[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
273
274
275

  (*record).size     = recsize;
  (*record).position = position;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
276
  (*record).param     = param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
277
278
  (*record).ilevel   = level;

279
  memset(&grid, 0, sizeof(grid_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
280
281
282
283
284
285
286
287
288
289
290
291
292
  grid.type  = GRID_GENERIC;
  grid.size  = xysize;
  grid.xsize = xysize;
  grid.ysize = 0;
  grid.xvals = NULL;
  grid.yvals = NULL;
  gridID = varDefGrid(vlistID, grid, 0);
  /*
  if ( level == 0 ) leveltype = ZAXIS_SURFACE;
  else              leveltype = ZAXIS_GENERIC;
  */
  leveltype = ZAXIS_GENERIC;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
293
  varAddRecord(recID, param, gridID, leveltype, 0, level, 0,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
294
	       extInqDatatype(prec), number, &varID, &levelID, 0, 0, NULL, NULL, NULL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
295
296
297
298

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
299
300
  streamptr->tsteps[tsID].nallrecs++;
  streamptr->nrecs++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
301
302
303
304
305
306
307

  if ( CDI_Debug )
    Message(func, "varID = %d gridID = %d levelID = %d",
	    varID, gridID, levelID);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
308
void extCmpRecord(int streamID, int tsID, int recID, off_t position, int param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
309
310
311
312
313
		  int level, int xysize)
{
  static char func[] = "extCmpRecord";
  int varID = 0;
  int levelID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
314
  record_t *record;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
315
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
316

Uwe Schulzweida's avatar
Uwe Schulzweida committed
317
318
319
  streamptr = stream_to_pointer(streamID);

  record  = &streamptr->tsteps[tsID].records[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
320

Uwe Schulzweida's avatar
Uwe Schulzweida committed
321
  if ( param != (*record).param || level != (*record).ilevel )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
322
323
324
325
326
327
328
    Error(func, "inconsistent timestep");

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
329
  streamptr->vars[varID].level[levelID] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
330

Uwe Schulzweida's avatar
Uwe Schulzweida committed
331
332
  streamptr->tsteps[tsID].nallrecs++;
  streamptr->nrecs++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
333
334
335
336
337
338
339
340
341
342
343
344
345
  */
  if ( CDI_Debug )
    Message(func, "varID = %d levelID = %d", varID, levelID);
}


void extScanTimestep1(int streamID)
{  
  static char func[] = "extScanTimestep1";
  int header[4];
  int status;
  int fileID;
  int rxysize = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
346
347
  int param = 0;
  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
348
349
350
351
352
353
354
355
356
  DateTime datetime, datetime0;
  int tsID;
  int varID;
  long recsize;
  off_t recpos;
  int nrecords, nrecs, recID;
  int taxisID = -1;
  TAXIS *taxis;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
357
358
  extcompvar_t compVar, compVar0;
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
359
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
360
361

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
363
  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
364

Uwe Schulzweida's avatar
Uwe Schulzweida committed
365
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
366

Uwe Schulzweida's avatar
Uwe Schulzweida committed
367
  extp  = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
368
  tsID  = tstepsNewEntry(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
369
  taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
370
371
372
373
374
375
376
377
378
379
380
381
382

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

  fileID = streamInqFileID(streamID);

  nrecs = 0;
  while ( TRUE )
    {
      recpos = fileGetPos(fileID);
      status = extRead(fileID, extp);
      if ( status != 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
383
	  streamptr->ntsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
384
385
386
387
388
389
	  break;
	}
      recsize = fileGetPos(fileID) - recpos;

      extInqHeader(extp, header);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
390
391
392
393
      vdate   = header[0];
      vtime   = 0;
      rcode   = header[1];
      rlevel  = header[2];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
394
395
      rxysize = header[3];

Uwe Schulzweida's avatar
Uwe Schulzweida committed
396
      param = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
397

Uwe Schulzweida's avatar
Uwe Schulzweida committed
398
399
400
401
402
403
404
405
406
      if ( nrecs == 0 )
	{
	  datetime0.date = vdate;
	  datetime0.time = vtime;
	}
      else
	{
	  datetime.date = vdate;
	  datetime.time = vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
407
	  compVar.param = param;
408
          compVar.level = rlevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
409
410
	  for ( recID = 0; recID < nrecs; recID++ )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
411
	      compVar0.param  = streamptr->tsteps[0].records[recID].param;
412
413
	      compVar0.level = streamptr->tsteps[0].records[recID].ilevel;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
414
	      if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
415
416
417
	    }
	  if ( recID < nrecs ) break;
	  if ( memcmp(&datetime, &datetime0, sizeof(DateTime)) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
418
	    Warning(func, "Inconsistent verification time for code %d level %d", rcode, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
419
420
421
422
423
	}

      nrecs++;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
426
      extAddRecord(streamID, param, rlevel, rxysize, recsize, recpos, extp->prec, extp->number);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
427
428
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
429
  streamptr->rtsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
430
431
432

  cdiGenVars(streamID);

433
  taxisID = taxisCreate(TAXIS_ABSOLUTE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
434
435
436
437
438
439
440
441
442
  taxis->type  = TAXIS_ABSOLUTE;
  taxis->vdate = datetime0.date;
  taxis->vtime = datetime0.time;

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

  cdiCheckContents(streamID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
443
444
  nrecords = streamptr->tsteps[0].nallrecs;
  if ( nrecords < streamptr->tsteps[0].recordSize )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
445
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
446
447
      streamptr->tsteps[0].recordSize = nrecords;
      streamptr->tsteps[0].records =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
448
      (record_t *) realloc(streamptr->tsteps[0].records, nrecords*sizeof(record_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
449
450
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
451
452
  streamptr->tsteps[0].recIDs = (int *) malloc(nrecords*sizeof(int));
  streamptr->tsteps[0].nrecs = nrecords;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
453
  for ( recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
454
    streamptr->tsteps[0].recIDs[recID] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
455

Uwe Schulzweida's avatar
Uwe Schulzweida committed
456
  if ( streamptr->ntsteps == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
457
458
    {
      tsID = tstepsNewEntry(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
459
      if ( tsID != streamptr->rtsteps )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
460
461
	Error(func, "Internal error. tsID = %d", tsID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
462
463
      streamptr->tsteps[tsID-1].next   = TRUE;
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
464
465
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
466
  if ( streamptr->ntsteps == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
467
468
469
    {
      if ( taxis->vdate == 0 && taxis->vtime == 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
470
471
	  streamptr->ntsteps = 0;
	  for ( varID = 0; varID < streamptr->nvars; varID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
	    {
	      vlistDefVarTime(vlistID, varID, TIME_CONSTANT);
	    }
	}
    }
}


int extScanTimestep2(int streamID)
{  
  static char func[] = "extScanTimestep2";
  int header[4];
  int status;
  int fileID;
  int rxysize = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
487
488
  int param = 0;
  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
489
490
491
492
493
494
495
496
  int tsID;
  int varID;
  long recsize;
  off_t recpos = 0;
  int nrecords, nrecs, recID, rindex;
  int nextstep;
  TAXIS *taxis;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
497
498
  extcompvar_t compVar, compVar0;
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
499
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
503
504
505
  stream_check_ptr(func, streamptr);

  streamptr->curTsID = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
506
507
508

  fileID  = streamInqFileID(streamID);
  vlistID = streamInqVlist(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
509
  extp    = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
510

Uwe Schulzweida's avatar
Uwe Schulzweida committed
511
  tsID = streamptr->rtsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
512
513
514
  if ( tsID != 1 )
    Error(func, "Internal problem! unexpeceted timestep %d", tsID+1);

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
517
  fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
519
520

  cdiCreateRecords(streamID, tsID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
521
522
523
  nrecords = streamptr->tsteps[0].nallrecs;
  streamptr->tsteps[1].recIDs = (int *) malloc(nrecords*sizeof(int));
  streamptr->tsteps[1].nrecs = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
  for ( recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
525
    streamptr->tsteps[1].recIDs[recID] = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
526
527
528

  for ( recID = 0; recID < nrecords; recID++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
529
530
531
532
533
      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
534
535
536
537
538
539
540
541
    }

  for ( rindex = 0; rindex <= nrecords; rindex++ )
    {
      recpos = fileGetPos(fileID);
      status = extRead(fileID, extp);
      if ( status != 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
	  streamptr->ntsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
543
544
545
546
547
548
549
550
	  break;
	}
      recsize = fileGetPos(fileID) - recpos;

      extInqHeader(extp, header);

      vdate  = header[0];
      vtime  = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
551
      rcode  = header[1];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
552
553
554
      rlevel = header[2];
      rxysize = header[3];

Uwe Schulzweida's avatar
Uwe Schulzweida committed
555
      param = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
556

Uwe Schulzweida's avatar
Uwe Schulzweida committed
557
558
559
560
561
562
563
      if ( rindex == 0 )
	{
	  taxis->type  = TAXIS_ABSOLUTE;
	  taxis->vdate = vdate;
	  taxis->vtime = vtime;
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
564
      compVar.param = param;
565
      compVar.level = rlevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
566
567
568
      nextstep = FALSE;
      for ( recID = 0; recID < nrecords; recID++ )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
569
	  compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
570
571
	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
572
	  if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
573
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
574
	      if ( streamptr->tsteps[tsID].records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
575
576
577
578
579
		{
		  nextstep = TRUE;
		}
	      else
		{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
580
581
		  streamptr->tsteps[tsID].records[recID].used = TRUE;
		  streamptr->tsteps[tsID].recIDs[rindex] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
582
583
584
585
586
587
		}
	      break;
	    }
	}
      if ( recID == nrecords )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
588
	  Warning(func, "Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
589
590
591
592
593
594
	  return (CDI_EUFSTRUCT);
	}

      if ( nextstep ) break;

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
599
      compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
600
      compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
601

Uwe Schulzweida's avatar
Uwe Schulzweida committed
602
      if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
603
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
604
	  Message(func, "tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
605
		  tsID, recID,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
606
		  streamptr->tsteps[tsID].records[recID].param, param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
607
		  streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
608
609
610
	  return (CDI_EUFSTRUCT);
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
611
      streamptr->tsteps[1].records[recID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
612
613
614
615
616
    }

  nrecs = 0;
  for ( recID = 0; recID < nrecords; recID++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
617
      if ( ! streamptr->tsteps[tsID].records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
618
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
619
	  varID = streamptr->tsteps[tsID].records[recID].varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
620
621
622
623
624
625
626
	  vlistDefVarTime(vlistID, varID, TIME_CONSTANT);
	}
      else
	{
	  nrecs++;
	}
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
627
  streamptr->tsteps[tsID].nrecs = nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
628

Uwe Schulzweida's avatar
Uwe Schulzweida committed
629
  streamptr->rtsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
630

Uwe Schulzweida's avatar
Uwe Schulzweida committed
631
  if ( streamptr->ntsteps == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
632
633
    {
      tsID = tstepsNewEntry(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
634
      if ( tsID != streamptr->rtsteps )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
635
636
	Error(func, "Internal error. tsID = %d", tsID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
637
638
      streamptr->tsteps[tsID-1].next   = TRUE;
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
639
640
641
642
643
644
645
646
647
648
649
    }

  return (0);
}


int extInqContents(int streamID)
{
  static char func[] = "extInqContents";
  int fileID;
  int status = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
650
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
651
652

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
654
  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
655
656
657

  fileID = streamInqFileID(streamID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
658
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
659
660
661

  extScanTimestep1(streamID);
 
Uwe Schulzweida's avatar
Uwe Schulzweida committed
662
  if ( streamptr->ntsteps == -1 ) status = extScanTimestep2(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677

  fileSetPos(fileID, 0, SEEK_SET);

  return (status);
}


int extScanTimestep(int streamID)
{
  static char func[] = "extScanTimestep";
  int header[4];
  int status;
  int fileID;
  int tsID;
  int rxysize = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
678
679
  int param = 0;
  int rcode = 0, rlevel = 0, vdate = 0, vtime = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
680
681
682
683
684
  long recsize = 0;
  off_t recpos = 0;
  int recID;
  TAXIS *taxis;
  int rindex, nrecs = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
685
686
  extcompvar_t compVar, compVar0;
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
687
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
688

Uwe Schulzweida's avatar
Uwe Schulzweida committed
689
690
691
  streamptr = stream_to_pointer(streamID);

  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
692
693
694
695

  if ( CDI_Debug )
    {
      Message(func, "streamID = %d", streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
696
697
698
      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
699
700
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
701
  if ( streamptr->rtsteps == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
702
703
    Error(func, "Internal problem! Missing contents.");

Uwe Schulzweida's avatar
Uwe Schulzweida committed
704
705
706
  extp  = streamptr->record->extp;
  tsID  = streamptr->rtsteps;
  taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
707

Uwe Schulzweida's avatar
Uwe Schulzweida committed
708
  if ( streamptr->tsteps[tsID].recordSize == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
709
710
711
    {
      cdiCreateRecords(streamID, tsID);

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
714
715
      streamptr->tsteps[tsID].nrecs = nrecs;
      streamptr->tsteps[tsID].recIDs = (int *) malloc(nrecs*sizeof(int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
716
      for ( recID = 0; recID < nrecs; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
717
	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
718
719
720

      fileID = streamInqFileID(streamID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
721
      fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
722
723
724
725
726
727
728

      for ( rindex = 0; rindex <= nrecs; rindex++ )
	{
	  recpos = fileGetPos(fileID);
	  status = extRead(fileID, extp);
	  if ( status != 0 )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
729
	      streamptr->ntsteps = streamptr->rtsteps + 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
730
731
732
733
734
735
736
737
	      break;
	    }
	  recsize = fileGetPos(fileID) - recpos;

	  extInqHeader(extp, header);

	  vdate  = header[0];
	  vtime  = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
738
	  rcode  = header[1];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
739
740
741
	  rlevel = header[2];
	  rxysize = header[3];

Uwe Schulzweida's avatar
Uwe Schulzweida committed
742
	  param = cdiEncodeParam(rcode, 255, 255);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
743

Uwe Schulzweida's avatar
Uwe Schulzweida committed
744
	  if ( rindex == nrecs ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
745
	  recID = streamptr->tsteps[tsID].recIDs[rindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
746
747
748
749
750
751
752
753

	  if ( rindex == 0 )
	    {
	      taxis->type  = TAXIS_ABSOLUTE;
	      taxis->vdate = vdate;
	      taxis->vtime = vtime;
	    }
	  /*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
754
	  extCmpRecord(streamID, tsID, nrecs, recpos, param, rlevel, rxysize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
755
	  */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
756
757
758
	  compVar.param  = param;
          compVar.level  = rlevel;
	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
759
	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
760

Uwe Schulzweida's avatar
Uwe Schulzweida committed
761
	  if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
762
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
763
	      Message(func, "tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
764
		      tsID, recID,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
765
		      streamptr->tsteps[tsID].records[recID].param, param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
766
		      streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
767
768
769
	      Error(func, "Invalid, unsupported or inconsistent record structure");
	    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
770
771
	  streamptr->tsteps[tsID].records[recID].position = recpos;
	  streamptr->tsteps[tsID].records[recID].size = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
772
773

	  if ( CDI_Debug )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
774
	    Message(func, "%4d%8d%4d%8d%8d%6d", rindex, (int)recpos, rcode, rlevel, vdate, vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
775
776
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
777
      streamptr->rtsteps++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
778

Uwe Schulzweida's avatar
Uwe Schulzweida committed
779
      if ( streamptr->ntsteps != streamptr->rtsteps )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
780
781
	{
	  tsID = tstepsNewEntry(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
782
	  if ( tsID != streamptr->rtsteps )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
783
784
	    Error(func, "Internal error. tsID = %d", tsID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
785
786
	  streamptr->tsteps[tsID-1].next   = 1;
	  streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
787
788
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
789
790
      fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
791
792
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
793
  if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
794
795
    {
      Warning(func, "Incomplete timestep. Stop scanning at timestep %d.\n", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
796
      streamptr->ntsteps = tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
797
798
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
799
  return (streamptr->ntsteps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
800
801
802
803
804
805
806
}


int extInqTimestep(int streamID, int tsID)
{
  static char func[] = "extInqTimestep";
  int ntsteps, nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
807
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
808
809

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
811
  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
812

Uwe Schulzweida's avatar
Uwe Schulzweida committed
813
  if ( tsID == 0 && streamptr->rtsteps == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
814
815
816
    Error(func, "Call to cdiInqContents missing!");

  if ( CDI_Debug )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
817
    Message(func, "tsID = %d rtsteps = %d", tsID, streamptr->rtsteps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
818
819
  
  ntsteps = UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
820
  while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
821
822
    ntsteps = extScanTimestep(streamID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
823
  if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
824
825
826
827
828
    {
      nrecs = 0;
    }
  else
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
829
830
      streamptr->curTsID = tsID;
      nrecs = streamptr->tsteps[tsID].nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
    }

  return (nrecs);
}


void extReadVarDP(int streamID, int varID, double *data, int *nmiss)
{
  static char func[] = "extReadVarDP";
  int vlistID, fileID;
  int levID, nlevs, gridID, gridsize;
  off_t recpos, currentfilepos;
  int header[4];
  int tsid;
  int recID;
  int i;
  int status;
  double missval;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
849
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
850
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
851

Uwe Schulzweida's avatar
Uwe Schulzweida committed
852
853
854
  streamptr = stream_to_pointer(streamID);

  extp     = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
855
856
  vlistID  = streamInqVlist(streamID);
  fileID   = streamInqFileID(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
857
  nlevs    = streamptr->vars[varID].nlevs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
858
859
860
  missval  = vlistInqVarMissval(vlistID, varID);
  gridID   = vlistInqVarGrid(vlistID, varID);
  gridsize = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
861
  tsid     = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
862
863
864
865
866
867
868
869

  if ( CDI_Debug )
    Message(func, "nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);

  currentfilepos = fileGetPos(fileID);

  for (levID = 0; levID < nlevs; levID++)
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
870
871
      recID = streamptr->vars[varID].level[levID];
      recpos = streamptr->tsteps[tsid].records[recID].position;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
      fileSetPos(fileID, recpos, SEEK_SET);
      status = extRead(fileID, extp);
      extInqHeader(extp, header);
      extInqDataDP(extp, &data[levID*gridsize]);
    }
  fileSetPos(fileID, currentfilepos, SEEK_SET);

  *nmiss = 0;
  for ( i = 0; i < nlevs*gridsize; i++ )
    if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
      {
	data[i] = missval;
	(*nmiss)++;
      }
}


void extReadVarSliceDP(int streamID, int varID, int levID, double *data, int *nmiss)
{
  static char func[] = "extReadVarSliceDP";
  int vlistID, fileID;
  int nlevs, gridID, gridsize;
  off_t recpos, currentfilepos;
  int header[4];
  int tsid;
  int recID;
  int i;
  int status;
  double missval;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
901
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
902
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
903
904

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
906
  extp     = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
907
908
  vlistID  = streamInqVlist(streamID);
  fileID   = streamInqFileID(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
909
  nlevs    = streamptr->vars[varID].nlevs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
910
911
912
  missval  = vlistInqVarMissval(vlistID, varID);
  gridID   = vlistInqVarGrid(vlistID, varID);
  gridsize = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
913
  tsid     = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
914
915
916
917
918
919
920

  if ( CDI_Debug )
    Message(func, "nlevs = %d gridID = %d gridsize = %d",
	     nlevs, gridID, gridsize);

  currentfilepos = fileGetPos(fileID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
921
922
  recID = streamptr->vars[varID].level[levID];
  recpos = streamptr->tsteps[tsid].records[recID].position;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
  fileSetPos(fileID, recpos, SEEK_SET);
  status = extRead(fileID, extp);
  extInqHeader(extp, header);
  extInqDataDP(extp, data);
 
  fileSetPos(fileID, currentfilepos, SEEK_SET);

  *nmiss = 0;
  for ( i = 0; i < gridsize; i++ )
    if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
      {
	data[i] = missval;
	(*nmiss)++;
      }
}


void extWriteVarDP(int streamID, int varID, const double *data)
{
  static char func[] = "extWriteVarDP";
  int fileID;
  int levID, nlevs, gridID, gridsize;
  int zaxisID;
  double level;
  int header[4];
  int tsID;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
950
  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
951
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
952
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
953
954

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
955
956
957
958

  if ( CDI_Debug )
    Message(func, "streamID = %d  varID = %d", streamID, varID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
959
  extp     = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
960
961
  vlistID  = streamInqVlist(streamID);
  fileID   = streamInqFileID(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
962
  tsID     = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
963
964
965
966
967
968
969
970
  gridID   = vlistInqVarGrid(vlistID, varID);
  gridsize = gridInqSize(gridID);
  zaxisID  = vlistInqVarZaxis(vlistID, varID);
  nlevs    = zaxisInqSize(zaxisID);

  if ( CDI_Debug )
    Message(func, "nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
971
  cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
972

Uwe Schulzweida's avatar
Uwe Schulzweida committed
973
  header[0] = streamptr->tsteps[tsID].taxis.vdate;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
974
  header[1] = pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
975
976
  header[3] = gridInqSize(gridID);

977
978
  extp->prec   = extDefDatatype(vlistInqVarDatatype(vlistID, varID));
  extp->number = vlistInqVarNumber(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001

  for ( levID = 0;  levID < nlevs; levID++ )
    {
      level = zaxisInqLevel(zaxisID, levID);

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


void extWriteVarSliceDP(int streamID, int varID, int levID, const double *data)
{
  static char func[] = "extWriteVarSliceDP";
  int fileID;
  int gridID;
  int zaxisID;
  double level;
  int header[4];
  int tsID;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1002
  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1003
  extrec_t *extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1004
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1005
1006

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1008
  extp     = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1009
1010
  vlistID  = streamInqVlist(streamID);
  fileID   = streamInqFileID(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1011
  tsID     = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1012
1013
1014
1015
1016
1017
1018
  gridID   = vlistInqVarGrid(vlistID, varID);
  zaxisID  = vlistInqVarZaxis(vlistID, varID);
  level    = zaxisInqLevel(zaxisID, levID);

  if ( CDI_Debug )
    Message(func, "gridID = %d zaxisID = %d", gridID, zaxisID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1019
  cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1020

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1021
  header[0] = streamptr->tsteps[tsID].taxis.vdate;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1022
  header[1] = pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1023
1024
1025
  header[2] = (int) level;
  header[3] = gridInqSize(gridID);

1026
1027
  extp->prec   = extDefDatatype(vlistInqVarDatatype(vlistID, varID));
  extp->number = vlistInqVarNumber(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1028
1029
1030
1031
1032
1033
1034

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

#endif /* HAVE_LIBEXTRA */