stream_ext.c 18.9 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
2
#ifdef HAVE_CONFIG_H
#include "config.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
3
4
5
6
7
8
9
#endif

#include "dmemory.h"

#include "error.h"
#include "file.h"
#include "cdi.h"
10
#include "cdi_int.h"
11
#include "stream_scan.h"
12
#include "stream_ext.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
13
14
15
#include "varscan.h"
#include "datetime.h"
#include "extra.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
16
#include "exse.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
17
18


Uwe Schulzweida's avatar
Uwe Schulzweida committed
19
#ifdef HAVE_LIBEXTRA
Uwe Schulzweida's avatar
Uwe Schulzweida committed
20

21
typedef struct {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
22
  int param;
23
  int level;
24
} extcompvar_t;
25

Uwe Schulzweida's avatar
Uwe Schulzweida committed
26
static
27
int extInqDatatype(int prec, int number)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
28
29
30
{
  int datatype;

31
  if ( number == 2 )
32
    datatype = (prec == EXSE_DOUBLE_PRECISION) ? CDI_DATATYPE_CPX64 : CDI_DATATYPE_CPX32;
33
  else
34
    datatype = (prec == EXSE_DOUBLE_PRECISION) ? CDI_DATATYPE_FLT64 : CDI_DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
35

36
  return datatype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
37
38
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
39
static
40
void extDefDatatype(int datatype, int *prec, int *number)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
42
{

43
44
45
  if ( datatype != CDI_DATATYPE_FLT32 && datatype != CDI_DATATYPE_FLT64 &&
       datatype != CDI_DATATYPE_CPX32 && datatype != CDI_DATATYPE_CPX64 )
    datatype = CDI_DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
46

47
  *number = (datatype == CDI_DATATYPE_CPX32 || datatype == CDI_DATATYPE_CPX64) ? 2 : 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
48

49
  *prec = (datatype == CDI_DATATYPE_FLT64 || datatype == CDI_DATATYPE_CPX64) ? EXSE_DOUBLE_PRECISION : EXSE_SINGLE_PRECISION;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
50
51
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
52
/* not used
53
int extInqRecord(stream_t *streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
54
55
56
{
  int status;
  int fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
57
  int icode, ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
58
59
60
  int zaxisID = -1;
  int header[4];
  int vlistID;
61
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
62

63
64
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
65
66
67
68
69

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

  status = extRead(fileID, extp);
70
  if ( status != 0 ) return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
71
72
73

  extInqHeader(extp, header);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
74
  icode  = header[1];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
75
76
  ilevel = header[2];

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

79
  if ( *varID == CDI_UNDEFID ) Error("Code %d undefined", icode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
80
81
82
83

  zaxisID = vlistInqVarZaxis(vlistID, *varID);

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

85
  return 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
86
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
87
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
88

89
void extReadRecord(stream_t *streamptr, double *data, size_t *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
90
{
91
92
93
94
95
96
97
  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
98
99
100

  fileSetPos(fileID, recpos, SEEK_SET);

101
  void *extp = streamptr->record->exsep;
102
103
  int status = extRead(fileID, extp);
  if ( status != 0 ) Error("Failed to read EXTRA record");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
104

105
  int header[4];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
106
107
108
  extInqHeader(extp, header);
  extInqDataDP(extp, data);

109
110
  double missval = vlistInqVarMissval(vlistID, varID);
  int gridID  = vlistInqVarGrid(vlistID, varID);
111
  size_t size = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
112

Uwe Schulzweida's avatar
Uwe Schulzweida committed
113
  streamptr->numvals += size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
114
115

  *nmiss = 0;
116
117
  if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
    {
118
      for ( size_t i = 0; i < size; i++ )
119
120
121
122
123
124
125
126
	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
	  {
	    data[i] = missval;
	    (*nmiss)++;
	  }
    }
  else
    {
127
      for ( size_t i = 0; i < 2*size; i+=2 )
128
129
130
131
132
133
	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
134
135
136
}


137
void extCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
138
{
139
  streamFCopyRecord(streamptr2, streamptr1, "EXTRA");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
140
141
142
}


143
void extDefRecord(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
144
{
145
146
  Record *record = streamptr->record;

147
  int pdis, pcat, pnum;
148
  cdiDecodeParam(record->param, &pnum, &pcat, &pdis);
149
150

  int header[4];
151
  header[0] = record->date;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
152
  header[1] = pnum;
153
154
  header[2] = record->level;
  int gridID = record->gridID;
155
  cdi_check_gridsize_int_limit("EXTRA", gridInqSize(gridID));
156
  header[3] = (int) gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
157

158
159
  extrec_t *extp = (extrec_t*) record->exsep;
  extDefDatatype(record->prec, &extp->prec, &extp->number);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
160
161
162
163
  extDefHeader(extp, header);
}


164
void extWriteRecord(stream_t *streamptr, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
165
{
166
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
167
  extDefDataDP(extp, data);
168
  extWrite(streamptr->fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
169
170
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
171
static
172
void extAddRecord(stream_t *streamptr, int param, int level, size_t xysize,
173
		  size_t recsize, off_t position, int prec, int number)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
174
{
175
176
177
  int vlistID = streamptr->vlistID;
  int tsID    = streamptr->curTsID;
  int recID   = recordNewEntry(streamptr, tsID);
178
  record_t *record = &streamptr->tsteps[tsID].records[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
179

180
181
182
183
  record->size     = recsize;
  record->position = position;
  record->param    = param;
  record->ilevel   = level;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
184

185
186
  grid_t *grid = (grid_t *)Malloc(sizeof (*grid));
  grid_init(grid);
187
  cdiGridTypeInit(grid, GRID_GENERIC, xysize);
188
189
  grid->x.size = xysize;
  grid->y.size = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
190
  struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0);
191
192
  int gridID = gridAdded.Id;
  if (!gridAdded.isNew) Free(grid);
193

194
  int leveltype = ZAXIS_GENERIC;
195
  int datatype = extInqDatatype(prec, number);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
196

197
  int varID, levelID = 0;
198
  varAddRecord(recID, param, gridID, leveltype, 0, level, 0, 0, 0,
199
               datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1,
200
               NULL, NULL, NULL, NULL, NULL, NULL, 0);
201

202
203
  record->varID   = (short)varID;
  record->levelID = (short)levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
204

Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
206
  streamptr->tsteps[tsID].nallrecs++;
  streamptr->nrecs++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
207
208

  if ( CDI_Debug )
209
    Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
210
211
}

212
static
213
214
void extScanTimestep1(stream_t *streamptr)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
215
  int header[4];
216
  DateTime datetime0 = { LONG_MIN, LONG_MIN };
217
218
  off_t recpos = 0;
  int recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
219
  extcompvar_t compVar, compVar0;
220
  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
221

Uwe Schulzweida's avatar
Uwe Schulzweida committed
222
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
223

224
  int tsID  = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
225
  if ( tsID != 0 )
226
    Error("Internal problem! tstepsNewEntry returns %d", tsID);
227
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
228

229
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
230

231
  int nrecs = 0;
232
  while ( true )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
233
234
    {
      recpos = fileGetPos(fileID);
235
      int status = extRead(fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
236
237
      if ( status != 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
238
	  streamptr->ntsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
239
240
	  break;
	}
241
      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
242
243
244

      extInqHeader(extp, header);

245
246
247
248
249
      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
250

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
253
254
255
256
257
258
259
      if ( nrecs == 0 )
	{
	  datetime0.date = vdate;
	  datetime0.time = vtime;
	}
      else
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
260
	  compVar.param = param;
261
          compVar.level = rlevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
262
263
	  for ( recID = 0; recID < nrecs; recID++ )
	    {
264
	      compVar0.param = streamptr->tsteps[0].records[recID].param;
265
266
	      compVar0.level = streamptr->tsteps[0].records[recID].ilevel;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
267
	      if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
268
269
	    }
	  if ( recID < nrecs ) break;
270
271
	  DateTime datetime = { .date = vdate, .time = vtime};
	  if ( datetimeCmp(datetime, datetime0) )
272
	    Warning("Inconsistent verification time for code %d level %d", rcode, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
273
274
275
276
277
	}

      nrecs++;

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

280
      extAddRecord(streamptr, param, rlevel, rxysize, recsize, recpos, extp->prec, extp->number);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
281
282
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
283
  streamptr->rtsteps = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
284

285
  cdi_generate_vars(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
286

287
  int taxisID = taxisCreate(TAXIS_ABSOLUTE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
288
  taxis->type  = TAXIS_ABSOLUTE;
289
290
  taxis->vdate = (int)datetime0.date;
  taxis->vtime = (int)datetime0.time;
291
292
  taxis->rdate = taxis->vdate;
  taxis->rtime = taxis->vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
293

294
  int vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
295
296
  vlistDefTaxis(vlistID, taxisID);

297
  vlist_check_contents(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
298

299
  int nrecords = streamptr->tsteps[0].nallrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
300
  if ( nrecords < streamptr->tsteps[0].recordSize )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
301
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
302
303
      streamptr->tsteps[0].recordSize = nrecords;
      streamptr->tsteps[0].records =
304
        (record_t *) Realloc(streamptr->tsteps[0].records, (size_t)nrecords * sizeof (record_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
305
306
    }

307
  streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
308
  streamptr->tsteps[0].nrecs = nrecords;
309
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
310
    streamptr->tsteps[0].recIDs[recID] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
311

Uwe Schulzweida's avatar
Uwe Schulzweida committed
312
  if ( streamptr->ntsteps == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
313
    {
314
      int tsID = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
315
      if ( tsID != streamptr->rtsteps )
316
	Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
317

318
      streamptr->tsteps[tsID-1].next   = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
319
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
320
321
    }

322
  streamScanTimeConstAdjust(streamptr, taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
323
324
}

325
static
326
327
int extScanTimestep2(stream_t *streamptr)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
328
329
  int header[4];
  off_t recpos = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
330
  extcompvar_t compVar, compVar0;
331
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
332
333

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

335
336
  int fileID  = streamptr->fileID;
  int vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
337

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

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

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

345
  cdi_create_records(streamptr, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
346

347
  int nrecords = streamptr->tsteps[0].nallrecs;
348
  streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
349
  streamptr->tsteps[1].nrecs = 0;
350
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
351
    streamptr->tsteps[1].recIDs[recID] = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
352

353
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
354
    {
355
      streamptr->tsteps[tsID].records[recID].position =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
356
	streamptr->tsteps[0].records[recID].position;
357
      streamptr->tsteps[tsID].records[recID].size     =
Uwe Schulzweida's avatar
Uwe Schulzweida committed
358
	streamptr->tsteps[0].records[recID].size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
359
360
    }

361
  for ( int rindex = 0; rindex <= nrecords; rindex++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
362
363
    {
      recpos = fileGetPos(fileID);
364
      int status = extRead(fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
365
366
      if ( status != 0 )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
367
	  streamptr->ntsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
368
369
	  break;
	}
370
      size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
371
372
373

      extInqHeader(extp, header);

374
375
376
377
      int vdate  = header[0];
      int vtime  = 0;
      int rcode  = header[1];
      int rlevel = header[2];
378
      // rxysize = header[3];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
379

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
382
383
384
385
386
387
388
      if ( rindex == 0 )
	{
	  taxis->type  = TAXIS_ABSOLUTE;
	  taxis->vdate = vdate;
	  taxis->vtime = vtime;
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
389
      compVar.param = param;
390
      compVar.level = rlevel;
391
      bool nextstep = false;
392
      int recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
393
394
      for ( recID = 0; recID < nrecords; recID++ )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
395
	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
396
397
	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
398
	  if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
399
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
400
	      if ( streamptr->tsteps[tsID].records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
401
		{
402
		  nextstep = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
403
404
405
		}
	      else
		{
406
		  streamptr->tsteps[tsID].records[recID].used = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
407
		  streamptr->tsteps[tsID].recIDs[rindex] = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
408
409
410
411
412
413
		}
	      break;
	    }
	}
      if ( recID == nrecords )
	{
414
	  Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1);
415
	  return CDI_EUFSTRUCT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
416
417
418
419
420
	}

      if ( nextstep ) break;

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
425
      compVar0.param  = streamptr->tsteps[tsID].records[recID].param;
426
      compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
427

Uwe Schulzweida's avatar
Uwe Schulzweida committed
428
      if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
429
	{
430
	  Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
431
		  tsID, recID,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
432
		  streamptr->tsteps[tsID].records[recID].param, param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
433
		  streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
434
	  return CDI_EUFSTRUCT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
435
436
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
437
      streamptr->tsteps[1].records[recID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
438
439
    }

440
441
  int nrecs = 0;
  for ( int recID = 0; recID < nrecords; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
442
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
443
      if ( ! streamptr->tsteps[tsID].records[recID].used )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
444
	{
445
	  int varID = streamptr->tsteps[tsID].records[recID].varID;
446
          vlistDefVarTimetype(vlistID, varID, TIME_CONSTANT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
447
448
449
450
451
452
	}
      else
	{
	  nrecs++;
	}
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
453
  streamptr->tsteps[tsID].nrecs = nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
454

Uwe Schulzweida's avatar
Uwe Schulzweida committed
455
  streamptr->rtsteps = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
456

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

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

467
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
468
469
470
}


471
int extInqContents(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
472
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
473
  streamptr->curTsID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
474

475
476
  extScanTimestep1(streamptr);

477
  int status = (streamptr->ntsteps == -1) ? extScanTimestep2(streamptr) : 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
478

479
  fileSetPos(streamptr->fileID, 0, SEEK_SET);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
480

481
  return status;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
482
483
}

484
static
485
long extScanTimestep(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
486
487
488
489
{
  int header[4];
  off_t recpos = 0;
  int recID;
490
  int nrecs = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
491
  extcompvar_t compVar, compVar0;
492
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
493

Uwe Schulzweida's avatar
Uwe Schulzweida committed
494
495
  int tsID  = streamptr->rtsteps;
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
496

Uwe Schulzweida's avatar
Uwe Schulzweida committed
497
  if ( streamptr->tsteps[tsID].recordSize == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
498
    {
499
      cdi_create_records(streamptr, tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
503
      streamptr->tsteps[tsID].nrecs = nrecs;
504
      streamptr->tsteps[tsID].recIDs = (int *) Malloc((size_t)nrecs * sizeof (int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
505
      for ( recID = 0; recID < nrecs; recID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
506
	streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
507

508
      int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
509

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

512
      for ( int rindex = 0; rindex <= nrecs; rindex++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513
514
	{
	  recpos = fileGetPos(fileID);
515
	  int status = extRead(fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
516
517
	  if ( status != 0 )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
	      streamptr->ntsteps = streamptr->rtsteps + 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
519
520
	      break;
	    }
521
	  size_t recsize = (size_t)(fileGetPos(fileID) - recpos);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
522
523
524

	  extInqHeader(extp, header);

525
526
527
528
	  int vdate  = header[0];
	  int vtime  = 0;
	  int rcode  = header[1];
	  int rlevel = header[2];
529
	  // rxysize = header[3];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
530

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

533
534
	  // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error
	  if ( rindex == nrecs ) continue;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
535
	  recID = streamptr->tsteps[tsID].recIDs[rindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
536
537
538
539
540
541
542

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
544
545
546
	  compVar.param  = param;
          compVar.level  = rlevel;
	  compVar0.param = streamptr->tsteps[tsID].records[recID].param;
547
	  compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
548

Uwe Schulzweida's avatar
Uwe Schulzweida committed
549
	  if ( memcmp(&compVar0, &compVar, sizeof(extcompvar_t)) != 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
550
	    {
551
	      Message("tsID = %d recID = %d param = %3d new %3d  level = %3d new %3d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
552
		      tsID, recID,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
553
		      streamptr->tsteps[tsID].records[recID].param, param,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
554
		      streamptr->tsteps[tsID].records[recID].ilevel, rlevel);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
555
	      Error("Invalid, unsupported or inconsistent record structure!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
556
557
	    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
558
559
	  streamptr->tsteps[tsID].records[recID].position = recpos;
	  streamptr->tsteps[tsID].records[recID].size = recsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
560
561

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
565
      streamptr->rtsteps++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
566

Uwe Schulzweida's avatar
Uwe Schulzweida committed
567
      if ( streamptr->ntsteps != streamptr->rtsteps )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
568
	{
569
	  tsID = tstepsNewEntry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
570
	  if ( tsID != streamptr->rtsteps )
571
	    Error("Internal error. tsID = %d", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
572

573
	  streamptr->tsteps[tsID-1].next   = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
574
	  streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
575
576
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
577
578
      fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET);
      streamptr->tsteps[tsID].position = recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
579
580
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
581
  if ( nrecs > 0 && nrecs < streamptr->tsteps[tsID].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
582
    {
583
      Warning("Incomplete timestep. Stop scanning at timestep %d.", tsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
584
      streamptr->ntsteps = tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
585
586
    }

587
  return streamptr->ntsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
588
589
590
}


591
int extInqTimestep(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
592
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
593
  if ( tsID == 0 && streamptr->rtsteps == 0 )
594
    Error("Call to cdiInqContents missing!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
595
596

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

599
600
  long ntsteps = CDI_UNDEFID;
  while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == CDI_UNDEFID )
601
    ntsteps = extScanTimestep(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
602

603
604
  int nrecs = 0;
  if ( !(tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
605
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
606
607
      streamptr->curTsID = tsID;
      nrecs = streamptr->tsteps[tsID].nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
608
609
    }

610
  return nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
611
612
613
}


614
void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, size_t *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
615
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
616
617
  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);

618
  void *extp = streamptr->record->exsep;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
619

620
621
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
622
  /* NOTE: tiles are not supported here! */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
623
  double missval = vlistInqVarMissval(vlistID, varID);
624
  size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
625
  int tsid     = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
626

627
  off_t currentfilepos = fileGetPos(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
628

629
  /* NOTE: tiles are not supported here! */
630
631
  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
632
  fileSetPos(fileID, recpos, SEEK_SET);
633
  extRead(fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
634
  int header[4];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
635
636
  extInqHeader(extp, header);
  extInqDataDP(extp, data);
Thomas Jahns's avatar
Thomas Jahns committed
637

Uwe Schulzweida's avatar
Uwe Schulzweida committed
638
639
640
  fileSetPos(fileID, currentfilepos, SEEK_SET);

  *nmiss = 0;
641
642
  if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL )
    {
643
      for ( size_t i = 0; i < gridsize; i++ )
644
645
646
647
648
649
650
651
	if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) )
	  {
	    data[i] = missval;
	    (*nmiss)++;
	  }
    }
  else
    {
652
      for ( size_t i = 0; i < 2*gridsize; i+=2 )
653
654
655
656
657
658
	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
659
660
661
}


662
void extReadVarDP(stream_t *streamptr, int varID, double *data, size_t *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
663
664
665
666
{
  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);

  int vlistID = streamptr->vlistID;
667
  size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
668
669
670
671
672
673
674
  size_t nlevs    = (size_t) streamptr->vars[varID].recordTable[0].nlevs;

  for ( size_t levID = 0; levID < nlevs; levID++)
    extReadVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize], nmiss);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
675
void extWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
676
{
677
678
  if ( CDI_Debug ) Message("streamID = %d  varID = %d  levID = %d", streamptr->self, varID, levID);

679
680
681
  int vlistID  = streamptr->vlistID;
  int fileID   = streamptr->fileID;
  int tsID     = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
682

683
  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
684
  cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
685

Uwe Schulzweida's avatar
Uwe Schulzweida committed
686
  int header[4];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
687
  header[0] = streamptr->tsteps[tsID].taxis.vdate;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
688
  header[1] = pnum;
689
  header[2] = (int)(zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID));
690
  int gridID = vlistInqVarGrid(vlistID, varID);
691
  cdi_check_gridsize_int_limit("EXTRA", gridInqSize(gridID));
692
  header[3] = (int) gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
693

Uwe Schulzweida's avatar
Uwe Schulzweida committed
694
  extrec_t *extp = (extrec_t*) streamptr->record->exsep;
695
  extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
696
  extDefHeader(extp, header);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
697

Uwe Schulzweida's avatar
Uwe Schulzweida committed
698
699
  extDefDataDP(extp, data);
  extWrite(fileID, extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
700
701
702
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
703
void extWriteVarDP(stream_t *streamptr, int varID, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
704
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
705
  if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
706

Uwe Schulzweida's avatar
Uwe Schulzweida committed
707
  int vlistID = streamptr->vlistID;
708
  size_t gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
709
  size_t nlevs    = (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
710

Uwe Schulzweida's avatar
Uwe Schulzweida committed
711
  for ( size_t levID = 0;  levID < nlevs; levID++ )
Thomas Jahns's avatar
Thomas Jahns committed
712
    extWriteVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize]);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
713
714
715
}

#endif /* HAVE_LIBEXTRA */
716

717
718
719
720
721
722
723
724
725
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */