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

5
6
#ifdef HAVE_LIBNETCDF

7
//#define TEST_GROUPS 1
Uwe Schulzweida's avatar
Uwe Schulzweida committed
8

9
#include <limits.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <float.h>

16
#include <netcdf.h>
17

Uwe Schulzweida's avatar
Uwe Schulzweida committed
18
19
20
#include "dmemory.h"
#include "cdi.h"
#include "basetime.h"
21
#include "gaussgrid.h"
22
#include "cdi_int.h"
23
#include "cdi_uuid.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
24
#include "stream_cdf.h"
25
#include "cdf.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
26
27
28
29
#include "cdf_int.h"
#include "varscan.h"
#include "vlist.h"

30
//#define PROJECTION_TEST
31
extern int CDI_cmor_mode;
32

Uwe Schulzweida's avatar
Uwe Schulzweida committed
33
34
35
#undef  UNDEFID
#define UNDEFID  CDI_UNDEFID

Uwe Schulzweida's avatar
Uwe Schulzweida committed
36
#define  BNDS_NAME  "bnds"
37

Uwe Schulzweida's avatar
Uwe Schulzweida committed
38
39
40
41
42
#define  X_AXIS  1
#define  Y_AXIS  2
#define  Z_AXIS  3
#define  T_AXIS  4

43
44
45
#define  POSITIVE_UP    1
#define  POSITIVE_DOWN  2

Uwe Schulzweida's avatar
Uwe Schulzweida committed
46
47
48
49
typedef struct {
  int     ncvarid;
  int     dimtype;
  size_t  len;
50
  char    name[CDI_MAX_NAME];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
51
}
52
ncdim_t;
53
54
55
#define  MAX_COORDVARS  4
#define  MAX_AUXVARS    4

Uwe Schulzweida's avatar
Uwe Schulzweida committed
56
typedef struct {
57
  int      ncid;
58
  int      ignore;
Thomas Jahns's avatar
Thomas Jahns committed
59
60
  short    isvar;
  short    islon;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
61
62
  int      islat;
  int      islev;
63
  int      istime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
64
  int      warn;
65
  int      tsteptype;
66
  int      param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
67
  int      code;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
68
  int      tabnum;
69
  int      climatology;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
70
  int      bounds;
71
72
  int      lformula;
  int      lformulaterms;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
73
74
75
76
77
78
79
80
81
82
83
  int      gridID;
  int      zaxisID;
  int      gridtype;
  int      zaxistype;
  int      xdim;
  int      ydim;
  int      zdim;
  int      xvarid;
  int      yvarid;
  int      zvarid;
  int      tvarid;
84
  int      psvarid;
85
  int      ncoordvars;
86
87
88
  int      coordvarids[MAX_COORDVARS];
  int      nauxvars;
  int      auxvarids[MAX_AUXVARS];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
89
90
91
92
  int      cellarea;
  int      calendar;
  int      tableID;
  int      truncation;
93
  int      position;
94
95
  int      defmissval;
  int      deffillval;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
96
97
98
99
100
101
  int      xtype;
  int      ndims;
  int      gmapid;
  int      positive;
  int      dimids[8];
  int      dimtype[8];
102
103
104
  int      chunks[8];
  int      chunked;
  int      chunktype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
105
  int      natts;
106
  int      deflate;
Deike Kleberg's avatar
Deike Kleberg committed
107
108
  int      lunsigned;
  int      lvalidrange;
Thomas Jahns's avatar
Thomas Jahns committed
109
  int     *atts;
110
111
  size_t   vctsize;
  double  *vct;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
112
  double   missval;
113
  double   fillval;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
114
115
  double   addoffset;
  double   scalefactor;
Deike Kleberg's avatar
Deike Kleberg committed
116
  double   validrange[2];
117
118
119
120
  char     name[CDI_MAX_NAME];
  char     longname[CDI_MAX_NAME];
  char     stdname[CDI_MAX_NAME];
  char     units[CDI_MAX_NAME];
121
  char     extra[CDI_MAX_NAME];
122
  ensinfo_t   *ensdata;    /* Ensemble information */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
123
}
124
125
126
127
128
129
ncvar_t;

static
void strtolower(char *str)
{
  if ( str )
130
    for (size_t i = 0; str[i]; ++i)
131
      str[i] = (char)tolower((int)str[i]);
132
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
133

134
static
135
int get_timeunit(size_t len, const char *ptu)
136
137
{
  int timeunit = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
138

139
140
141
142
143
144
145
146
147
148
  if ( len > 2 )
    {
      if      ( memcmp(ptu, "sec",    3) == 0 )          timeunit = TUNIT_SECOND;
      else if ( memcmp(ptu, "minute", 6) == 0 )          timeunit = TUNIT_MINUTE;
      else if ( memcmp(ptu, "hour",   4) == 0 )          timeunit = TUNIT_HOUR;
      else if ( memcmp(ptu, "day",    3) == 0 )          timeunit = TUNIT_DAY;
      else if ( memcmp(ptu, "month",  5) == 0 )          timeunit = TUNIT_MONTH;
      else if ( memcmp(ptu, "calendar_month", 14) == 0 ) timeunit = TUNIT_MONTH;
      else if ( memcmp(ptu, "year",   4) == 0 )          timeunit = TUNIT_YEAR;
    }
149
150
151
152
  else if ( len == 1 )
    {
      if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND;
    }
153

154
  return timeunit;
155
156
157
158
}

static
int isTimeUnits(const char *timeunits)
159
160
161
162
163
164
165
166
167
{
  int status = 0;

  if ( strncmp(timeunits, "sec",    3) == 0 ||
       strncmp(timeunits, "minute", 6) == 0 ||
       strncmp(timeunits, "hour",   4) == 0 ||
       strncmp(timeunits, "day",    3) == 0 ||
       strncmp(timeunits, "month",  5) == 0 ) status = 1;

168
  return status;
169
170
171
172
}

static
int isTimeAxisUnits(const char *timeunits)
173
174
175
176
177
178
{
  char *ptu, *tu;
  int timetype = -1;
  int timeunit;
  int status = FALSE;

179
  size_t len = strlen(timeunits);
180
  tu = (char *) Malloc((len+1)*sizeof(char));
181
  memcpy(tu, timeunits, (len+1) * sizeof(char));
182
183
  ptu = tu;

184
  for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
185
186
187
188
189
190
191

  timeunit = get_timeunit(len, ptu);
  if ( timeunit != -1 )
    {

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
192
193
        {
          while ( isspace(*ptu) ) ptu++;
Deike Kleberg's avatar
Deike Kleberg committed
194

195
196
197
198
          if ( memcmp(ptu, "as", 2) == 0 )
            timetype = TAXIS_ABSOLUTE;
          else if ( memcmp(ptu, "since", 5) == 0 )
            timetype = TAXIS_RELATIVE;
199

200
201
          if ( timetype != -1 ) status = TRUE;
        }
202
203
    }

204
  Free(tu);
205

206
  return status;
207
208
209
}

static
210
void scanTimeString(const char *ptu, int *rdate, int *rtime)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
211
{
212
  int year = 1, month = 1, day = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
213
  int hour = 0, minute = 0, second = 0;
214
  int v1 = 1, v2 = 1, v3 = 1;
215
216
217
218

  *rdate = 0;
  *rtime = 0;

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  if ( *ptu )
    {
      v1 = atoi(ptu);
      if ( v1 < 0 ) ptu++;
      while ( isdigit((int) *ptu) ) ptu++;
      if ( *ptu )
        {
          v2 = atoi(++ptu);
          while ( isdigit((int) *ptu) ) ptu++;
          if ( *ptu )
            {
              v3 = atoi(++ptu);
              while ( isdigit((int) *ptu) ) ptu++;
            }
        }
    }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

  if ( v3 > 999 && v1 < 32 )
    { year = v3; month = v2; day = v1; }
  else
    { year = v1; month = v2; day = v3; }

  while ( isspace((int) *ptu) ) ptu++;

  if ( *ptu )
    {
      while ( ! isdigit((int) *ptu) ) ptu++;

      hour = atoi(ptu);
      while ( isdigit((int) *ptu) ) ptu++;
      if ( *ptu == ':' )
        {
          ptu++;
          minute = atoi(ptu);
          while ( isdigit((int) *ptu) ) ptu++;
          if ( *ptu == ':' )
            {
              ptu++;
              second = atoi(ptu);
            }
        }
    }

  *rdate = cdiEncodeDate(year, month, day);
  *rtime = cdiEncodeTime(hour, minute, second);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
266
267
268
static
int scanTimeUnit(const char *unitstr)
{
269
  size_t len = strlen(unitstr);
270
  int timeunit = get_timeunit(len, unitstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
271
272
273
  if ( timeunit == -1 )
    Message("Unsupported TIMEUNIT: %s!", unitstr);

274
  return timeunit;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
275
276
}

277
278
279
static
void setForecastTime(const char *timestr, taxis_t *taxis)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
280
281
282
  (*taxis).fdate = 0;
  (*taxis).ftime = 0;

283
  int len = (int) strlen(timestr);
284
285
286
287
288
289
290
291
292
293
294
295
  if ( len == 0 ) return;

  int fdate = 0, ftime = 0;
  scanTimeString(timestr, &fdate, &ftime);

  (*taxis).fdate = fdate;
  (*taxis).ftime = ftime;
}

static
int setBaseTime(const char *timeunits, taxis_t *taxis)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
296
297
298
  int timetype = TAXIS_ABSOLUTE;
  int rdate = -1, rtime = -1;

299
  size_t len = strlen(timeunits);
300
  char *tu = (char *) Malloc((len+1) * sizeof (char));
301
  memcpy(tu, timeunits, (len+1) * sizeof (char));
302
  char *ptu = tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
303

304
  for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]);
305

306
  int timeunit = get_timeunit(len, ptu);
307
  if ( timeunit == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
308
    {
309
      Message("Unsupported TIMEUNIT: %s!", timeunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
310
311
312
313
314
315
      return (1);
    }

  while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
  if ( *ptu )
    {
316
      while ( isspace(*ptu) ) ptu++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
317

318
      if ( memcmp(ptu, "as", 2) == 0 )
319
        timetype = TAXIS_ABSOLUTE;
320
      else if ( memcmp(ptu, "since", 5) == 0 )
321
        timetype = TAXIS_RELATIVE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
322
323
324

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
        {
          while ( isspace(*ptu) ) ptu++;

          if ( timetype == TAXIS_ABSOLUTE )
            {
              if ( memcmp(ptu, "%y%m%d.%f", 9) != 0 && timeunit == TUNIT_DAY )
                {
                  Message("Unsupported format %s for TIMEUNIT day!", ptu);
                  timeunit = -1;
                }
              else if ( memcmp(ptu, "%y%m.%f", 7) != 0 && timeunit == TUNIT_MONTH )
                {
                  Message("Unsupported format %s for TIMEUNIT month!", ptu);
                  timeunit = -1;
                }
            }
          else if ( timetype == TAXIS_RELATIVE )
            {
343
              scanTimeString(ptu, &rdate, &rtime);
344
345
346
347
348

              (*taxis).rdate = rdate;
              (*taxis).rtime = rtime;

              if ( CDI_Debug )
Deike Kleberg's avatar
Deike Kleberg committed
349
                Message("rdate = %d  rtime = %d", rdate, rtime);
350
351
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
352
353
354
355
356
    }

  (*taxis).type = timetype;
  (*taxis).unit = timeunit;

357
  Free(tu);
358

Uwe Schulzweida's avatar
Uwe Schulzweida committed
359
  if ( CDI_Debug )
360
    Message("timetype = %d  unit = %d", timetype, timeunit);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
361

362
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
363
364
}

365
static
Oliver Heidmann's avatar
Oliver Heidmann committed
366
void cdfGetAttInt(int fileID, int ncvarid, const char *attname, int attlen, int *attint)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
367
{
368
  nc_type atttype;
369
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
370

371
372
373
  *attint = 0;

  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
374
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
375

376
377
378
379
380
  if ( atttype != NC_CHAR )
    {
      int *pintatt = NULL;

      if ( (int)nc_attlen > attlen )
381
        pintatt = (int *) Malloc(nc_attlen * sizeof (int));
382
383
      else
        pintatt = attint;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
384

385
      cdf_get_att_int(fileID, ncvarid, attname, pintatt);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
386

387
388
389
      if ( (int)nc_attlen > attlen )
        {
          memcpy(attint, pintatt, (size_t)attlen * sizeof (int));
390
          Free(pintatt);
391
        }
392
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
393
394
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
395
396
static
void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
397
{
398
  nc_type atttype;
399
  size_t nc_attlen;
400
401

  *attdouble = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
402

403
  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
404
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
405

406
407
408
  if ( atttype != NC_CHAR )
    {
      double *pdoubleatt = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
409

410
      if ( (int)nc_attlen > attlen )
411
        pdoubleatt = (double *) Malloc(nc_attlen * sizeof (double));
412
413
      else
        pdoubleatt = attdouble;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
414

415
416
417
418
419
      cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);

      if ( (int)nc_attlen > attlen )
        {
          memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double));
420
          Free(pdoubleatt);
421
        }
422
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
423
424
}

425
static
426
void cdfGetAttText(int fileID, int ncvarid,const char *attname, int attlen, char *atttext)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
427
{
428
  nc_type atttype;
429
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
430

431
  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
432
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
433

434
  if ( atttype == NC_CHAR )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
435
    {
436
437
438
439
      char attbuf[65636];
      if ( nc_attlen < sizeof(attbuf) )
        {
          cdf_get_att_text(fileID, ncvarid, attname, attbuf);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
440

441
          if ( (int) nc_attlen > (attlen-1) ) nc_attlen = (size_t)(attlen-1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
442

443
          attbuf[nc_attlen++] = 0;
444
445
446
447
448
449
          memcpy(atttext, attbuf, nc_attlen);
        }
      else
        {
          atttext[0] = 0;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
450
    }
451
452
#if  defined  (HAVE_NETCDF4)
  else if ( atttype == NC_STRING )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
453
    {
454
455
456
457
458
      if ( nc_attlen == 1 )
        {
          char *attbuf = NULL;
          cdf_get_att_string(fileID, ncvarid, attname, &attbuf);

459
          size_t ssize = strlen(attbuf) + 1;
460

461
462
463
          if ( ssize > (size_t)attlen ) ssize = (size_t)attlen;
          memcpy(atttext, attbuf, ssize);
          atttext[ssize - 1] = 0;
464
          Free(attbuf);
465
466
467
468
469
        }
      else
        {
          atttext[0] = 0;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
470
    }
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
#endif
}

static
int xtypeIsText(int xtype)
{
  int isText = FALSE;

  if ( xtype == NC_CHAR )
    isText = TRUE;
#if  defined  (HAVE_NETCDF4)
  else if ( xtype == NC_STRING )
    isText = TRUE;
#endif

486
  return isText;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
487
488
}

489
490
491
492
static
int xtypeIsFloat(int xtype)
{
  int isFloat = FALSE;
493

494
  if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
495

496
497
498
  return isFloat;
}

499
static
Deike Kleberg's avatar
Deike Kleberg committed
500
int cdfInqDatatype(int xtype, int lunsigned)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
501
{
502
  int datatype = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
503

504
#if  defined  (HAVE_NETCDF4)
Deike Kleberg's avatar
Deike Kleberg committed
505
  if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;
506
#endif
Deike Kleberg's avatar
Deike Kleberg committed
507

Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
509
510
511
  if      ( xtype == NC_BYTE   )  datatype = DATATYPE_INT8;
  /* else if ( xtype == NC_CHAR   )  datatype = DATATYPE_UINT8; */
  else if ( xtype == NC_SHORT  )  datatype = DATATYPE_INT16;
  else if ( xtype == NC_INT    )  datatype = DATATYPE_INT32;
512
  else if ( xtype == NC_FLOAT  )  datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513
  else if ( xtype == NC_DOUBLE )  datatype = DATATYPE_FLT64;
Deike Kleberg's avatar
Deike Kleberg committed
514
#if  defined  (HAVE_NETCDF4)
515
  else if ( xtype == NC_UBYTE  )  datatype = DATATYPE_UINT8;
516
517
518
519
520
521
  else if ( xtype == NC_LONG   )  datatype = DATATYPE_INT32;
  else if ( xtype == NC_USHORT )  datatype = DATATYPE_UINT16;
  else if ( xtype == NC_UINT   )  datatype = DATATYPE_UINT32;
  else if ( xtype == NC_INT64  )  datatype = DATATYPE_FLT64;
  else if ( xtype == NC_UINT64 )  datatype = DATATYPE_FLT64;
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
522

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

526

527
void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528
{
529
  int memtype  = MEMTYPE_DOUBLE;
530
  int vlistID1 = streamptr1->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
531
532
533
534
  int tsID     = streamptr1->curTsID;
  int vrecID   = streamptr1->tsteps[tsID].curRecID;
  int recID    = streamptr1->tsteps[tsID].recIDs[vrecID];
  int ivarID   = streamptr1->tsteps[tsID].records[recID].varID;
535
  int gridID   = vlistInqVarGrid(vlistID1, ivarID);
536
  int datasize = gridInqSize(gridID);
537
  int datatype = vlistInqVarDatatype(vlistID1, ivarID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
538

539
540
541
542
543
544
545
  if ( datatype == DATATYPE_FLT32 ) memtype = MEMTYPE_FLOAT;

  void *data = NULL;
  if ( memtype == MEMTYPE_DOUBLE )
    data = Malloc((size_t)datasize*sizeof(double));
  else
    data = Malloc((size_t)datasize*sizeof(float));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
546

547
  int nmiss;
548
  cdf_read_record(streamptr1, memtype, data, &nmiss);
549
  cdf_write_record(streamptr2, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
550

551
  Free(data);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
552
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
553

Uwe Schulzweida's avatar
Uwe Schulzweida committed
554
/* not used
555
int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
556
557
558
{
  int tsID, recID;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
559
560
561
  recID = streamptr->tsteps[0].curRecID++;
  printf("cdfInqRecord recID %d %d\n", recID, streamptr->tsteps[0].curRecID);
  printf("cdfInqRecord tsID %d\n", streamptr->curTsID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
562

563
  if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
564
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
565
      streamptr->tsteps[0].curRecID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
566
567
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
568
569
  *varID   = streamptr->tsteps[0].records[recID].varID;
  *levelID = streamptr->tsteps[0].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
570

Uwe Schulzweida's avatar
Uwe Schulzweida committed
571
572
  streamptr->record->varID   = *varID;
  streamptr->record->levelID = *levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
573
574

  if ( CDI_Debug )
575
    Message("recID = %d  varID = %d  levelID = %d", recID, *varID, *levelID);
576

Uwe Schulzweida's avatar
Uwe Schulzweida committed
577
578
579
  return (recID+1);
}
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
580

Uwe Schulzweida's avatar
Uwe Schulzweida committed
581

582
void cdfDefRecord(stream_t *streamptr)
583
{
Thomas Jahns's avatar
Thomas Jahns committed
584
  (void)streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
585
586
}

587
#if defined(NC_SZIP_NN_OPTION_MASK)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
588
589
590
591
592
static
void cdfDefVarSzip(int ncid, int ncvarid)
{
  int retval;
  /* Set options_mask and bits_per_pixel. */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
593
  int options_mask = NC_SZIP_NN_OPTION_MASK;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
594
595
596
597
598
  int bits_per_pixel = 16;

  if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
    {
      if ( retval == NC_EINVAL )
599
600
601
602
603
604
605
        {
          static int lwarn = TRUE;

          if ( lwarn )
            {
              lwarn = FALSE;
              Warning("netCDF4/Szip compression not compiled in!");
Deike Kleberg's avatar
Deike Kleberg committed
606
            }
607
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
608
      else
609
        Error("nc_def_var_szip failed, status = %d", retval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
610
    }
611
612
613
}
#endif

614
static
615
void cdfDefTimeValue(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
616
{
617
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
618
619

  if ( CDI_Debug )
620
    Message("streamID = %d, fileID = %d", streamptr->self, fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
621

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
624
  if ( streamptr->ncmode == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
625
626
    {
      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
627
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
628
629
    }

630
  size_t index = (size_t)tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
631

632
  double timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis);
633
  if ( CDI_Debug ) Message("tsID = %d  timevalue = %f", tsID, timevalue);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
634

635
  int ncvarid = streamptr->basetime.ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
636
637
638
639
640
641
  cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);

  if ( taxis->has_bounds )
    {
      size_t start[2], count[2];

Uwe Schulzweida's avatar
Uwe Schulzweida committed
642
      ncvarid = streamptr->basetime.ncvarboundsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
643

Uwe Schulzweida's avatar
Uwe Schulzweida committed
644
      timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
645
      start[0] = (size_t)tsID; count[0] = 1; start[1] = 0; count[1] = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
646
647
      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
648
      timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
649
      start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
650
651
      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
    }
652
653
654
655
656
657
658
659

  ncvarid = streamptr->basetime.leadtimeid;
  if ( taxis->type == TAXIS_FORECAST && ncvarid != UNDEFID )
    {
      timevalue = taxis->fc_period;
      cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
660
661
662
663
664
  /*
printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
  */
}

665
666
667
668
669
670
671
672
673
674
675
static
int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, char* taxis_name, taxis_t* taxis)
{
  int time_bndsid = -1;
  int dims[2];
  char tmpstr[CDI_MAX_NAME];

  dims[0] = nctimedimid;

  /* fprintf(stderr, "time has bounds\n"); */

Uwe Schulzweida's avatar
Uwe Schulzweida committed
676
677
  if ( nc_inq_dimid(fileID, BNDS_NAME, &dims[1]) != NC_NOERR )
    cdf_def_dim(fileID, BNDS_NAME, 2, &dims[1]);
678
679
680

  if ( taxis->climatology )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
681
682
      strcpy(tmpstr, "climatology_");
      strcat(tmpstr, BNDS_NAME);
683
684
685
686
687
688
689
      cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);

      cdf_put_att_text(fileID, nctimevarid, "climatology", strlen(tmpstr), tmpstr);
    }
  else
    {
      strcpy(tmpstr, taxis_name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
690
691
      strcat(tmpstr, "_");
      strcat(tmpstr, BNDS_NAME);
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
      cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);

      cdf_put_att_text(fileID, nctimevarid, "bounds", strlen(tmpstr), tmpstr);
    }

  return (time_bndsid);
}

static
void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis)
{
  unitstr[0] = 0;

  if ( taxis0->type == TAXIS_ABSOLUTE )
    {
      if ( taxis0->unit == TUNIT_YEAR )
        sprintf(unitstr, "year as %s", "%Y.%f");
      else if ( taxis0->unit == TUNIT_MONTH )
        sprintf(unitstr, "month as %s", "%Y%m.%f");
      else
        sprintf(unitstr, "day as %s", "%Y%m%d.%f");
    }
  else
    {
716
      int timeunit = taxis->unit;
717
      if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
718
719
      int rdate    = taxis->rdate;
      int rtime    = taxis->rtime;
720
721
722
723
724
725
      if ( rdate == -1 )
        {
          rdate  = taxis->vdate;
          rtime  = taxis->vtime;
        }

726
      int year, month, day, hour, minute, second;
727
728
729
      cdiDecodeDate(rdate, &year, &month, &day);
      cdiDecodeTime(rtime, &hour, &minute, &second);

730
731
      if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
      if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
732
733
734
735
      if ( timeunit == TUNIT_3HOURS  ||
	   timeunit == TUNIT_6HOURS  ||
	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

736
      sprintf(unitstr, "%s since %d-%d-%d %02d:%02d:%02d",
737
738
739
              tunitNamePtr(timeunit), year, month, day, hour, minute, second);
    }
}
740
741
742
743
744
745
746
747

static
void cdfDefForecastTimeUnits(char *unitstr, int timeunit)
{
  unitstr[0] = 0;

  if ( timeunit == -1 ) timeunit = TUNIT_HOUR;

748
749
  if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
  if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
750
751
752
753
754
755
  if ( timeunit == TUNIT_3HOURS  ||
       timeunit == TUNIT_6HOURS  ||
       timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

  sprintf(unitstr, "%s", tunitNamePtr(timeunit));
}
756

757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
static
void cdfDefCalendar(int fileID, int ncvarid, int calendar)
{
  size_t len;
  char calstr[80];

  calstr[0] = 0;

  if      ( calendar == CALENDAR_STANDARD )  strcpy(calstr, "standard");
  else if ( calendar == CALENDAR_PROLEPTIC ) strcpy(calstr, "proleptic_gregorian");
  else if ( calendar == CALENDAR_NONE )      strcpy(calstr, "none");
  else if ( calendar == CALENDAR_360DAYS )   strcpy(calstr, "360_day");
  else if ( calendar == CALENDAR_365DAYS )   strcpy(calstr, "365_day");
  else if ( calendar == CALENDAR_366DAYS )   strcpy(calstr, "366_day");

  len = strlen(calstr);

  if ( len ) cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr);
}

777

778
void cdfDefTime(stream_t* streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
779
780
{
  int time_varid;
781
782
783
  int time_dimid;
  int time_bndsid = -1;
  char unitstr[CDI_MAX_NAME];
784
785
  char tmpstr[CDI_MAX_NAME];
  char default_name[] = "time";
786
  char* taxis_name = default_name;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
787

Uwe Schulzweida's avatar
Uwe Schulzweida committed
788
  if ( streamptr->basetime.ncvarid != UNDEFID ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
789

790
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
791

Uwe Schulzweida's avatar
Uwe Schulzweida committed
792
793
  if ( streamptr->ncmode == 0 ) streamptr->ncmode = 1;
  if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
794

795
  taxis_t *taxis = &streamptr->tsteps[0].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
796

797
  if ( taxis->name && taxis->name[0] ) taxis_name = taxis->name;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
798

799
800
  cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &time_dimid);
  streamptr->basetime.ncdimid = time_dimid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
801

802
  cdf_def_var(fileID, taxis_name, NC_DOUBLE, 1, &time_dimid, &time_varid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
803

804
  streamptr->basetime.ncvarid = time_varid;
Deike Kleberg's avatar
Deike Kleberg committed
805
806
807
808

  strcpy(tmpstr, "time");
  cdf_put_att_text(fileID, time_varid, "standard_name", strlen(tmpstr), tmpstr);

809
810
811
  if ( taxis->longname && taxis->longname[0] )
    cdf_put_att_text(fileID, time_varid, "long_name", strlen(taxis->longname), taxis->longname);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
812
813
  if ( taxis->has_bounds )
    {
814
815
      time_bndsid = cdfDefTimeBounds(fileID, time_varid, time_dimid, taxis_name, taxis);
      streamptr->basetime.ncvarboundsid = time_bndsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
816
817
    }

818
  cdfDefTimeUnits(unitstr, &streamptr->tsteps[0].taxis, taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
819

820
  size_t len = strlen(unitstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
821
  if ( len )
822
823
    {
      cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
824
      /*
825
826
      if ( taxis->has_bounds )
        cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
827
      */
828
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
829
830
831

  if ( taxis->calendar != -1 )
    {
832
      cdfDefCalendar(fileID, time_varid, taxis->calendar);
833
      /*
834
835
      if ( taxis->has_bounds )
        cdfDefCalendar(fileID, time_bndsid, taxis->calendar);
836
      */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
837
838
    }

839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
  if ( taxis->type == TAXIS_FORECAST )
    {
      int leadtimeid;

      cdf_def_var(fileID, "leadtime", NC_DOUBLE, 1, &time_dimid, &leadtimeid);

      streamptr->basetime.leadtimeid = leadtimeid;

      strcpy(tmpstr, "forecast_period");
      cdf_put_att_text(fileID, leadtimeid, "standard_name", strlen(tmpstr), tmpstr);

      strcpy(tmpstr, "Time elapsed since the start of the forecast");
      cdf_put_att_text(fileID, leadtimeid, "long_name", strlen(tmpstr), tmpstr);

      cdfDefForecastTimeUnits(unitstr, taxis->fc_unit);

      len = strlen(unitstr);
      if ( len ) cdf_put_att_text(fileID, leadtimeid, "units", len, unitstr);
    }

859
860
  cdf_put_att_text(fileID, time_varid, "axis", 1, "T");

Uwe Schulzweida's avatar
Uwe Schulzweida committed
861
  if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
862
863
864
}


865
void cdfDefTimestep(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
866
{
867
  int vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
868

869
  if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
870

871
  cdfDefTimeValue(streamptr, tsID);
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
872
873
874
}

static
875
void cdfDefComplex(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
876
{
877
  char axisname[] = "nc2";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
878
  int dimID = UNDEFID;
879
880
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
881

882
  int ngrids = vlistNgrids(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
883

884
  for ( int index = 0; index < ngrids; index++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
885
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
886
      if ( streamptr->xdimID[index] != UNDEFID )
887
        {
888
889
          int gridID0 = vlistGrid(vlistID, index);
          int gridtype0 = gridInqType(gridID0);
890
          if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER )
891
892
893
894
895
            {
              dimID = streamptr->xdimID[index];
              break;
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
896
897
898
899
    }

  if ( dimID == UNDEFID )
    {
900
      size_t dimlen = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
901

Uwe Schulzweida's avatar
Uwe Schulzweida committed
902
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
903
904
905
906

      cdf_def_dim(fileID, axisname, dimlen, &dimID);

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
907
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
908
909
    }

910
  int gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
911
  streamptr->xdimID[gridindex] = dimID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
912
913
}

914

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
915
static
916
void cdfDefSP(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
917
918
919
920
{
  /*
  char longname[] = "Spherical harmonic coefficient";
  */
921
  char axisname[5] = "nspX";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
922
923
924
  int index, iz = 0;
  int dimID = UNDEFID;

925
926
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
927

928
  int ngrids = vlistNgrids(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
929

930
  size_t dimlen = (size_t)gridInqSize(gridID)/2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
931
932
933

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
934
      if ( streamptr->ydimID[index] != UNDEFID )
935
        {
936
937
          int gridID0 = vlistGrid(vlistID, index);
          int gridtype0 = gridInqType(gridID0);
938
939
          if ( gridtype0 == GRID_SPECTRAL )
            {
940
              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
941
942
943
944
945
946
              if ( dimlen == dimlen0 )
                {
                  dimID = streamptr->ydimID[index];
                  break;
                }
              else
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
                iz++;
            }
        }
    }

  if ( dimID == UNDEFID )
    {
      if ( iz == 0 ) axisname[3] = '\0';
      else           sprintf(&axisname[3], "%1d", iz+1);

      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);

      cdf_def_dim(fileID, axisname, dimlen, &dimID);

      cdf_enddef(fileID);
      streamptr->ncmode = 2;
    }

965
  int gridindex = vlistGridIndex(vlistID, gridID);
966
967
968
  streamptr->ydimID[gridindex] = dimID;
}

969

970
static
971
void cdfDefFC(stream_t *streamptr, int gridID)
972
973
974
975
976
{
  char axisname[5] = "nfcX";
  int index, iz = 0;
  int dimID = UNDEFID;

977
978
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
979

980
  int ngrids = vlistNgrids(vlistID);
981

982
  size_t dimlen = (size_t)gridInqSize(gridID)/2;
983
984
985
986
987

  for ( index = 0; index < ngrids; index++ )
    {
      if ( streamptr->ydimID[index] != UNDEFID )
        {
988
989
          int gridID0 = vlistGrid(vlistID, index);
          int gridtype0 = gridInqType(gridID0);
990
991
          if ( gridtype0 == GRID_FOURIER )
            {
992
              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
993
994
995
996
997
998
999
              if ( dimlen == dimlen0 )
                {
                  dimID = streamptr->ydimID[index];
                  break;
                }
              else
                iz++;
1000
1001
            }
        }