stream_cdf.c 262 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"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
23
24
25
26
27
#include "stream_cdf.h"
#include "cdf_int.h"
#include "varscan.h"
#include "vlist.h"

28
29
//#define PROJECTION_TEST

Uwe Schulzweida's avatar
Uwe Schulzweida committed
30
31
32
33
#undef  UNDEFID
#define UNDEFID  CDI_UNDEFID


34
35
36
37
#if defined HAVE_LIBNETCDF
static void cdfDefGlobalAtts(stream_t *streamptr);
static void cdfDefLocalAtts(stream_t *streamptr);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
38

Uwe Schulzweida's avatar
Uwe Schulzweida committed
39
#define  BNDS_NAME  "bnds"
40

Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
42
43
44
45
#define  X_AXIS  1
#define  Y_AXIS  2
#define  Z_AXIS  3
#define  T_AXIS  4

46
47
48
#define  POSITIVE_UP    1
#define  POSITIVE_DOWN  2

Uwe Schulzweida's avatar
Uwe Schulzweida committed
49
50
51
52
typedef struct {
  int     ncvarid;
  int     dimtype;
  size_t  len;
53
  char    name[CDI_MAX_NAME];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
54
}
55
ncdim_t;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
56

57
58
59
#define  MAX_COORDVARS  4
#define  MAX_AUXVARS    4

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

static
void strtolower(char *str)
{
  if ( str )
134
    for (size_t i = 0; str[i]; ++i)
135
      str[i] = (char)tolower((int)str[i]);
136
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
137

138
static
139
int get_timeunit(size_t len, const char *ptu)
140
141
{
  int timeunit = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
142

143
144
145
146
147
148
149
150
151
152
  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;
    }
153
154
155
156
  else if ( len == 1 )
    {
      if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND;
    }
157
158
159
160
161
162

  return (timeunit);
}

static
int isTimeUnits(const char *timeunits)
163
164
165
166
167
168
169
170
171
172
173
174
175
176
{
  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;

  return (status);
}

static
int isTimeAxisUnits(const char *timeunits)
177
178
179
180
181
182
{
  char *ptu, *tu;
  int timetype = -1;
  int timeunit;
  int status = FALSE;

183
  size_t len = strlen(timeunits);
184
  tu = (char *)xmalloc((len+1)*sizeof(char));
185
  memcpy(tu, timeunits, (len+1) * sizeof(char));
186
187
  ptu = tu;

188
  for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
189
190
191
192
193
194
195

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

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
196
197
        {
          while ( isspace(*ptu) ) ptu++;
Deike Kleberg's avatar
Deike Kleberg committed
198

199
200
201
202
          if ( memcmp(ptu, "as", 2) == 0 )
            timetype = TAXIS_ABSOLUTE;
          else if ( memcmp(ptu, "since", 5) == 0 )
            timetype = TAXIS_RELATIVE;
203

204
205
          if ( timetype != -1 ) status = TRUE;
        }
206
207
208
209
210
211
212
213
    }

  free(tu);

  return (status);
}

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

  *rdate = 0;
  *rtime = 0;

223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  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++;
            }
        }
    }
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
266
267
268
269

  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
270
271
272
273
static
int scanTimeUnit(const char *unitstr)
{
  int timeunit = -1;
274
  size_t len = strlen(unitstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
275
276
277
278
279
280
281
  timeunit = get_timeunit(len, unitstr);
  if ( timeunit == -1 )
    Message("Unsupported TIMEUNIT: %s!", unitstr);

  return (timeunit);
}

282
283
284
static
void setForecastTime(const char *timestr, taxis_t *taxis)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
285
286
287
288
289
290
  int len;

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

  len = (int) strlen(timestr);
291
292
293
294
295
296
297
298
299
300
301
302
303
  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)
{
  char *ptu, *tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
304
305
  int timetype = TAXIS_ABSOLUTE;
  int rdate = -1, rtime = -1;
306
  int timeunit;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
307

308
  size_t len = strlen(timeunits);
309
  tu = (char *)xmalloc((len+1) * sizeof (char));
310
  memcpy(tu, timeunits, (len+1) * sizeof (char));
311
  ptu = tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
312

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

315
316
  timeunit = get_timeunit(len, ptu);
  if ( timeunit == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
317
    {
318
      Message("Unsupported TIMEUNIT: %s!", timeunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
319
320
321
322
323
324
      return (1);
    }

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

327
      if ( memcmp(ptu, "as", 2) == 0 )
328
        timetype = TAXIS_ABSOLUTE;
329
      else if ( memcmp(ptu, "since", 5) == 0 )
330
        timetype = TAXIS_RELATIVE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
331
332
333

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
        {
          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 )
            {
352
              scanTimeString(ptu, &rdate, &rtime);
353
354
355
356
357

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

              if ( CDI_Debug )
Deike Kleberg's avatar
Deike Kleberg committed
358
                Message("rdate = %d  rtime = %d", rdate, rtime);
359
360
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
361
362
363
364
365
    }

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

366
367
  free(tu);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
368
  if ( CDI_Debug )
369
    Message("timetype = %d  unit = %d", timetype, timeunit);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
370
371
372
373

  return (0);
}

374
375
static
void cdfGetAttInt(int fileID, int ncvarid, char *attname, int attlen, int *attint)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
376
{
377
  nc_type atttype;
378
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
379

380
381
382
  *attint = 0;

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

385
386
387
388
389
390
391
392
  if ( atttype != NC_CHAR )
    {
      int *pintatt = NULL;

      if ( (int)nc_attlen > attlen )
        pintatt = (int *) malloc(nc_attlen * sizeof (int));
      else
        pintatt = attint;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
393

394
      cdf_get_att_int(fileID, ncvarid, attname, pintatt);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
395

396
397
398
399
400
      if ( (int)nc_attlen > attlen )
        {
          memcpy(attint, pintatt, (size_t)attlen * sizeof (int));
          free(pintatt);
        }
401
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
402
403
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
404
405
static
void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
406
{
407
  nc_type atttype;
408
  size_t nc_attlen;
409
410

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

412
  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
413
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
414

415
416
417
  if ( atttype != NC_CHAR )
    {
      double *pdoubleatt = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
418

419
420
421
422
      if ( (int)nc_attlen > attlen )
        pdoubleatt = (double *) malloc(nc_attlen * sizeof (double));
      else
        pdoubleatt = attdouble;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
423

424
425
426
427
428
429
430
      cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);

      if ( (int)nc_attlen > attlen )
        {
          memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double));
          free(pdoubleatt);
        }
431
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
432
433
}

434
435
static
void cdfGetAttText(int fileID, int ncvarid, char *attname, int attlen, char *atttext)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
436
{
437
  nc_type atttype;
438
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
439

440
  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
441
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
442

443
  if ( atttype == NC_CHAR )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
444
    {
445
446
447
448
      char attbuf[65636];
      if ( nc_attlen < sizeof(attbuf) )
        {
          cdf_get_att_text(fileID, ncvarid, attname, attbuf);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
449

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

452
          attbuf[nc_attlen++] = 0;
453
454
455
456
457
458
          memcpy(atttext, attbuf, nc_attlen);
        }
      else
        {
          atttext[0] = 0;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
459
    }
460
461
#if  defined  (HAVE_NETCDF4)
  else if ( atttype == NC_STRING )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
462
    {
463
464
465
466
467
      if ( nc_attlen == 1 )
        {
          char *attbuf = NULL;
          cdf_get_att_string(fileID, ncvarid, attname, &attbuf);

468
          size_t ssize = strlen(attbuf) + 1;
469

470
471
472
          if ( ssize > (size_t)attlen ) ssize = (size_t)attlen;
          memcpy(atttext, attbuf, ssize);
          atttext[ssize - 1] = 0;
473
474
475
476
477
478
          free(attbuf);
        }
      else
        {
          atttext[0] = 0;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
479
    }
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
#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

495
  return isText;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
496
497
}

498
499
500
501
static
int xtypeIsFloat(int xtype)
{
  int isFloat = FALSE;
502

503
  if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
504

505
506
507
  return isFloat;
}

508
static
Deike Kleberg's avatar
Deike Kleberg committed
509
int cdfInqDatatype(int xtype, int lunsigned)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
510
{
511
  int datatype = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
512

513
#if  defined  (HAVE_NETCDF4)
Deike Kleberg's avatar
Deike Kleberg committed
514
  if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;
515
#endif
Deike Kleberg's avatar
Deike Kleberg committed
516

Uwe Schulzweida's avatar
Uwe Schulzweida committed
517
518
519
520
  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;
521
  else if ( xtype == NC_FLOAT  )  datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
522
  else if ( xtype == NC_DOUBLE )  datatype = DATATYPE_FLT64;
Deike Kleberg's avatar
Deike Kleberg committed
523
#if  defined  (HAVE_NETCDF4)
524
  else if ( xtype == NC_UBYTE  )  datatype = DATATYPE_UINT8;
525
526
527
528
529
530
  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
531
532
533
534

  return (datatype);
}

535
static
536
int cdfDefDatatype(int datatype, int filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
537
538
539
{
  int xtype;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
540
  if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
541
542
543
544
545
546
547
    Error("CDI/netCDF library does not support complex numbers!");

  if ( filetype == FILETYPE_NC4 )
    {
      if      ( datatype == DATATYPE_INT8   ) xtype = NC_BYTE;
      else if ( datatype == DATATYPE_INT16  ) xtype = NC_SHORT;
      else if ( datatype == DATATYPE_INT32  ) xtype = NC_INT;
Deike Kleberg's avatar
Deike Kleberg committed
548
#if  defined  (HAVE_NETCDF4)
549
550
551
552
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_UBYTE;
      else if ( datatype == DATATYPE_UINT16 ) xtype = NC_USHORT;
      else if ( datatype == DATATYPE_UINT32 ) xtype = NC_UINT;
#else
553
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_SHORT;
554
555
556
557
558
559
560
561
562
563
564
      else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
      else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
#endif
      else if ( datatype == DATATYPE_FLT64  ) xtype = NC_DOUBLE;
      else                                    xtype = NC_FLOAT;
    }
  else
    {
      if      ( datatype == DATATYPE_INT8   ) xtype = NC_BYTE;
      else if ( datatype == DATATYPE_INT16  ) xtype = NC_SHORT;
      else if ( datatype == DATATYPE_INT32  ) xtype = NC_INT;
565
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_SHORT;
566
567
568
569
570
      else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
      else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
      else if ( datatype == DATATYPE_FLT64  ) xtype = NC_DOUBLE;
      else                                    xtype = NC_FLOAT;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
571

Uwe Schulzweida's avatar
Uwe Schulzweida committed
572
573
574
  return (xtype);
}

575
576
577
578
579
static inline void *
resizeBuf(void **buf, size_t *bufSize, size_t reqSize)
{
  if (reqSize > *bufSize)
    {
580
      *buf = xrealloc(*buf, reqSize);
581
582
      *bufSize = reqSize;
    }
583
  return *buf;
584
585
}

586
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
587
588
589
void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
{
  int natts, iatt;
590
  int atttype, attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
591
  size_t len;
592
  char attname[CDI_MAX_NAME+1];
593
594
  void *attBuf = NULL;
  size_t attBufSize = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
595
596
597
598
599

  vlistInqNatts(vlistID, varID, &natts);

  for ( iatt = 0; iatt < natts; iatt++ )
    {
600
      vlistInqAtt(vlistID, varID, iatt, attname, &atttype, &attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
601

602
603
      if ( attlen == 0 ) continue;

604
      if ( atttype == DATATYPE_TXT )
605
        {
606
607
          size_t attSize = (size_t)attlen*sizeof(char);
          char *atttxt = (char *)resizeBuf(&attBuf, &attBufSize, attSize);
Deike Kleberg's avatar
Deike Kleberg committed
608
          vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
609
          len = (size_t)attlen;
610
611
612
613
          cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
        }
      else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
        {
614
615
          size_t attSize = (size_t)attlen*sizeof(int);
          int *attint = (int *)resizeBuf(&attBuf, &attBufSize, attSize);
616
          vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
617
          len = (size_t)attlen;
618
          cdf_put_att_int(fileID, ncvarID, attname, atttype == DATATYPE_INT16 ? NC_SHORT : NC_INT, len, attint);
619
620
621
        }
      else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
        {
622
623
          size_t attSize = (size_t)attlen * sizeof(double);
          double *attflt = (double *)resizeBuf(&attBuf, &attBufSize, attSize);
624
          vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
625
          len = (size_t)attlen;
626
627
628
629
630
631
632
          if ( atttype == DATATYPE_FLT32 )
            {
              float attflt_sp[len];
              for ( size_t i = 0; i < len; ++i ) attflt_sp[i] = attflt[i];
              cdf_put_att_float(fileID, ncvarID, attname, NC_FLOAT, len, attflt_sp);
            }
          else
633
            cdf_put_att_double(fileID, ncvarID, attname, NC_DOUBLE, len, attflt);
634
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
635
    }
636
  free(attBuf);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
637
638
}

639

640
void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
641
{
642
  int memtype  = MEMTYPE_DOUBLE;
643
  int vlistID1 = streamptr1->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
644
645
646
647
  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;
648
  int gridID   = vlistInqVarGrid(vlistID1, ivarID);
649
  int datasize = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
650

651
  double *data = (double *)xmalloc((size_t)datasize * sizeof (double));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
652

653
  int nmiss;
654
655
  cdfReadRecord(streamptr1, data, &nmiss);
  cdf_write_record(streamptr2, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
656
657
658

  free(data);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
659

Uwe Schulzweida's avatar
Uwe Schulzweida committed
660
/* not used
661
int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
662
663
664
{
  int tsID, recID;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
665
666
667
  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
668

669
  if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
670
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
671
      streamptr->tsteps[0].curRecID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
672
673
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
674
675
  *varID   = streamptr->tsteps[0].records[recID].varID;
  *levelID = streamptr->tsteps[0].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
676

Uwe Schulzweida's avatar
Uwe Schulzweida committed
677
678
  streamptr->record->varID   = *varID;
  streamptr->record->levelID = *levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
679
680

  if ( CDI_Debug )
681
    Message("recID = %d  varID = %d  levelID = %d", recID, *varID, *levelID);
682

Uwe Schulzweida's avatar
Uwe Schulzweida committed
683
684
685
  return (recID+1);
}
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
686

Uwe Schulzweida's avatar
Uwe Schulzweida committed
687

688
void cdfDefRecord(stream_t *streamptr)
689
{
Thomas Jahns's avatar
Thomas Jahns committed
690
  (void)streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
691
692
}

693

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
694
static
695
void cdfWriteGridTraj(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
696
{
697
698
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
699

700
701
702
  int gridindex = vlistGridIndex(vlistID, gridID);
  int lonID = streamptr->xdimID[gridindex],
    latID = streamptr->ydimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
703

704
705
706
707
  double xlon = gridInqXval(gridID, 0),
    xlat = gridInqYval(gridID, 0);
  int tsID = streamptr->curTsID;
  size_t index = (size_t)tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
708
709
710
711
712

  cdf_put_var1_double(fileID, lonID, &index, &xlon);
  cdf_put_var1_double(fileID, latID, &index, &xlat);
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
713
static
714
void cdfReadGridTraj(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
715
{
716
717
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
718

719
720
721
  int gridindex = vlistGridIndex(vlistID, gridID);
  int lonID = streamptr->xdimID[gridindex];
  int latID = streamptr->ydimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
722

723
724
  int tsID = streamptr->curTsID;
  size_t index = (size_t)tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
725

726
  double xlon, xlat;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
727
728
729
730
731
732
733
  cdf_get_var1_double(fileID, lonID, &index, &xlon);
  cdf_get_var1_double(fileID, latID, &index, &xlat);

  gridDefXvals(gridID, &xlon);
  gridDefYvals(gridID, &xlat);
}

734

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
735
static
736
737
void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level)
{
Deike Kleberg's avatar
Deike Kleberg committed
738
#if  defined  (HAVE_NETCDF4)
739
740
741
742
743
744
745
746
747
  int retval;
  /* Set chunking, shuffle, and deflate. */
  int shuffle = 1;
  int deflate = 1;

  if ( deflate_level < 1 || deflate_level > 9 ) deflate_level = 1;

  if ((retval = nc_def_var_deflate(ncid, ncvarid, shuffle, deflate, deflate_level)))
    {
748
      Error("nc_def_var_deflate failed, status = %d", retval);
749
750
751
752
753
754
755
    }
#else
  static int lwarn = TRUE;

  if ( lwarn )
    {
      lwarn = FALSE;
756
      Warning("Deflate compression failed, netCDF4 not available!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
757
758
759
760
    }
#endif
}

761
762

#if defined(NC_SZIP_NN_OPTION_MASK)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
763
764
765
766
767
static
void cdfDefVarSzip(int ncid, int ncvarid)
{
  int retval;
  /* Set options_mask and bits_per_pixel. */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
768
  int options_mask = NC_SZIP_NN_OPTION_MASK;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
769
770
771
772
773
  int bits_per_pixel = 16;

  if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
    {
      if ( retval == NC_EINVAL )
774
775
776
777
778
779
780
        {
          static int lwarn = TRUE;

          if ( lwarn )
            {
              lwarn = FALSE;
              Warning("netCDF4/Szip compression not compiled in!");
Deike Kleberg's avatar
Deike Kleberg committed
781
            }
782
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
783
      else
784
        Error("nc_def_var_szip failed, status = %d", retval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
785
    }
786
787
788
}
#endif

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
789
static
790
void cdfDefVarMissval(stream_t *streamptr, int varID, int dtype, int lcheck)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
791
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
792
  if ( streamptr->vars[varID].defmiss == FALSE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
793
794
795
796
797
798
799
    {
      int fileID;
      int ncvarid;
      double missval;
      int vlistID;
      int xtype;

800
801
      vlistID = streamptr->vlistID;
      fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
802
      ncvarid = streamptr->vars[varID].ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
803
      missval = vlistInqVarMissval(vlistID, varID);
804

805
      if ( lcheck && streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
806

807
      xtype = cdfDefDatatype(dtype, streamptr->filetype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
808

809
      if ( xtype == NC_BYTE && missval > 127 && missval < 256 ) xtype = NC_INT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
810

811
812
      cdf_put_att_double(fileID, ncvarid, "_FillValue", (nc_type) xtype, 1, &missval);
      cdf_put_att_double(fileID, ncvarid, "missing_value", (nc_type) xtype, 1, &missval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
813

814
      if ( lcheck && streamptr->ncmode == 2 ) cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
815

Uwe Schulzweida's avatar
Uwe Schulzweida committed
816
      streamptr->vars[varID].defmiss = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
817
818
    }
}
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
819

820

821
void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
822
823
824
825
{
  int varID;
  int levelID;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
826
827
  varID   = streamptr->record->varID;
  levelID = streamptr->record->levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
828

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

831
  cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
832
833
}

834
void cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
835
{
836
  if ( CDI_Debug ) Message("streamID = %d", streamptr->self);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
837

838
839
840
841
842
  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;
  int levelID = streamptr->tsteps[tsID].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
843

844
  cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
846
}

847
static
848
void cdfDefTimeValue(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
849
{
850
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
851
852

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
857
  if ( streamptr->ncmode == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
858
859
    {
      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
860
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
861
862
    }

863
  size_t index = (size_t)tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
864

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

868
  int ncvarid = streamptr->basetime.ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
869
870
871
872
873
874
  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
875
      ncvarid = streamptr->basetime.ncvarboundsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
876

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
881
      timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
882
      start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
883
884
      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
    }
885
886
887
888
889
890
891
892

  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
893
894
895
896
897
  /*
printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
  */
}

898
899
900
901
902
903
904
905
906
907
908
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
909
910
  if ( nc_inq_dimid(fileID, BNDS_NAME, &dims[1]) != NC_NOERR )
    cdf_def_dim(fileID, BNDS_NAME, 2, &dims[1]);
911
912
913

  if ( taxis->climatology )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
914
915
      strcpy(tmpstr, "climatology_");
      strcat(tmpstr, BNDS_NAME);
916
917
918
919
920
921
922
      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
923
924
      strcat(tmpstr, "_");
      strcat(tmpstr, BNDS_NAME);
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
      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
    {
949
      int timeunit = taxis->unit;
950
      if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
951
952
      int rdate    = taxis->rdate;
      int rtime    = taxis->rtime;
953
954
955
956
957
958
      if ( rdate == -1 )
        {
          rdate  = taxis->vdate;
          rtime  = taxis->vtime;
        }

959
      int year, month, day, hour, minute, second;
960
961
962
      cdiDecodeDate(rdate, &year, &month, &day);
      cdiDecodeTime(rtime, &hour, &minute, &second);

963
964
      if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
      if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
965
966
967
968
969
970
971
972
      if ( timeunit == TUNIT_3HOURS  ||
	   timeunit == TUNIT_6HOURS  ||
	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

      sprintf(unitstr, "%s since %d-%02d-%02d %02d:%02d:%02d",
              tunitNamePtr(timeunit), year, month, day, hour, minute, second);
    }
}
973
974
975
976
977
978
979
980

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

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

981
982
  if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
  if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
983
984
985
986
987
988
  if ( timeunit == TUNIT_3HOURS  ||
       timeunit == TUNIT_6HOURS  ||
       timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

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

990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
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);
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
1010
static
1011
void cdfDefTime(stream_t* streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1012
1013
{
  int time_varid;
1014
1015
1016
  int time_dimid;
  int time_bndsid = -1;
  char unitstr[CDI_MAX_NAME];
1017
1018
  char tmpstr[CDI_MAX_NAME];
  char default_name[] = "time";
1019
  char* taxis_name = default_name;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1020

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

1023
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1024

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1025
1026
  if ( streamptr->ncmode == 0 ) streamptr->ncmode = 1;
  if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1027

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

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

1032
1033
  cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &time_dimid);
  streamptr->basetime.ncdimid = time_dimid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1034

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

1037
  streamptr->basetime.ncvarid = time_varid;
Deike Kleberg's avatar
Deike Kleberg committed
1038
1039
1040
1041

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