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

5
//#define TEST_GROUPS 1
Uwe Schulzweida's avatar
Uwe Schulzweida committed
6

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

#include "dmemory.h"

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


#if  defined  (HAVE_LIBNETCDF)
#  include "netcdf.h"
#endif

29
30
//#define PROJECTION_TEST

Uwe Schulzweida's avatar
Uwe Schulzweida committed
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#undef  UNDEFID
#define UNDEFID  CDI_UNDEFID


void cdfDefGlobalAtts(int streamID);
void cdfDefLocalAtts(int streamID);


#define  X_AXIS  1
#define  Y_AXIS  2
#define  Z_AXIS  3
#define  T_AXIS  4

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

typedef struct {
53
  int      ncid;
54
  int      ignore;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
55
56
57
58
  int      isvar;
  int      islon;
  int      islat;
  int      islev;
59
  int      istime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
60
  int      warn;
61
  int      tsteptype;
62
  int      param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
63
  int      code;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
64
  int      tabnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
65
66
67
68
69
70
71
72
73
74
75
76
  int      bounds;
  int      gridID;
  int      zaxisID;
  int      gridtype;
  int      zaxistype;
  int      xdim;
  int      ydim;
  int      zdim;
  int      xvarid;
  int      yvarid;
  int      zvarid;
  int      tvarid;
77
78
  int      ncoordvars;
  int      coordvarids[4];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
79
80
81
82
83
84
85
86
87
88
89
  int      cellarea;
  int      calendar;
  int      tableID;
  int      truncation;
  int      defmiss;
  int      xtype;
  int      ndims;
  int      gmapid;
  int      positive;
  int      dimids[8];
  int      dimtype[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
90
91
92
  int      chunks[8];
  int      chunked;
  int      chunktype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
94
  int      natts;
  int     *atts;
95
  int      deflate;
96
97
  int      lunsigned;
  int      lvalidrange;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
98
99
100
101
102
  size_t   vlen;
  double  *vdata;
  double   missval;
  double   addoffset;
  double   scalefactor;
103
  double   validrange[2];
104
105
106
107
  char     name[CDI_MAX_NAME];
  char     longname[CDI_MAX_NAME];
  char     stdname[CDI_MAX_NAME];
  char     units[CDI_MAX_NAME];
108
  ensinfo_t   *ensdata;    /* Ensemble information */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
109
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
110
ncvar_t;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
111

112
#ifdef HAVE_LIBNETCDF
113
114
115
116
117
118
119
120
121
static
void strtolower(char *str)
{
  int i, len;

  if ( str )
    {
      len = (int) strlen(str);
      for ( i = 0; i < len; i++ )
122
        str[i] = tolower((int) str[i]);
123
124
125
    }
}

126
127
128
129
static
int get_timeunit(int len, char *ptu)
{
  int timeunit = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
130

131
132
133
134
135
136
137
138
139
140
  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;
    }
141
142
143
144
  else if ( len == 1 )
    {
      if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND;
    }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

  return (timeunit);
}

static
int isTimeUnits(const char *timeunits)
{
  int len, i;
  char *ptu, *tu;
  int timetype = -1;
  int timeunit;
  int status = FALSE;

  len = (int) strlen(timeunits);
  tu = (char *) malloc((len+1)*sizeof(char));
  memcpy(tu, timeunits, (len+1)*sizeof(char));
  ptu = tu;

  for ( i = 0; i < len; i++ ) ptu[i] = tolower((int) ptu[i]);

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

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
171
172
        {
          while ( isspace(*ptu) ) ptu++;
173

174
175
176
177
178
179
180
          if ( memcmp(ptu, "as", 2) == 0 )
            timetype = TAXIS_ABSOLUTE;
          else if ( memcmp(ptu, "since", 5) == 0 )
            timetype = TAXIS_RELATIVE;

          if ( timetype != -1 ) status = TRUE;
        }
181
182
183
184
185
186
187
188
    }

  free(tu);

  return (status);
}

static
189
int splitBasetime(const char *timeunits, taxis_t *taxis)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
190
{
191
  int len, i;
192
  char *ptu, *tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
193
194
195
196
  int year, month, day;
  int hour = 0, minute = 0, second = 0;
  int timetype = TAXIS_ABSOLUTE;
  int rdate = -1, rtime = -1;
197
  int timeunit;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
198

Uwe Schulzweida's avatar
Uwe Schulzweida committed
199
  len = (int) strlen(timeunits);
200
201
202
  tu = (char *) malloc((len+1)*sizeof(char));
  memcpy(tu, timeunits, (len+1)*sizeof(char));
  ptu = tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
203

204
205
  for ( i = 0; i < len; i++ ) ptu[i] = tolower((int) ptu[i]);

206
207
  timeunit = get_timeunit(len, ptu);
  if ( timeunit == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
208
    {
209
      Message("Unsupported TIMEUNIT: %s!", timeunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
210
211
212
213
214
215
      return (1);
    }

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

218
      if ( memcmp(ptu, "as", 2) == 0 )
219
        timetype = TAXIS_ABSOLUTE;
220
      else if ( memcmp(ptu, "since", 5) == 0 )
221
        timetype = TAXIS_RELATIVE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
222
223
224

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
225
226
227
228
229
230
231
        {
          while ( isspace(*ptu) ) ptu++;

          if ( timetype == TAXIS_ABSOLUTE )
            {
              if ( memcmp(ptu, "%y%m%d.%f", 9) != 0 && timeunit == TUNIT_DAY )
                {
232
                  Message("Unsupported format %s for TIMEUNIT day!", ptu);
233
234
235
236
                  timeunit = -1;
                }
              else if ( memcmp(ptu, "%y%m.%f", 7) != 0 && timeunit == TUNIT_MONTH )
                {
237
                  Message("Unsupported format %s for TIMEUNIT month!", ptu);
238
239
240
241
242
                  timeunit = -1;
                }
            }
          else if ( timetype == TAXIS_RELATIVE )
            {
243
244
245
              int v1, v2, v3;
              v1 = atoi(ptu);
              if ( v1 < 0 ) ptu++;
246
              while ( isdigit((int) *ptu) ) ptu++;
247
              v2 = atoi(++ptu);
248
              while ( isdigit((int) *ptu) ) ptu++;
249
              v3 = atoi(++ptu);
250
251
              while ( isdigit((int) *ptu) ) ptu++;

252
253
254
255
256
              if ( v3 > 999 && v1 < 32 )
                { year = v3; month = v2; day = v1; }
              else
                { year = v1; month = v2; day = v3; }

257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
              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);
                          /*
                          if ( second != 0 )
276
                            Message("Seconds not supported in time units!");
277
278
279
280
281
282
283
284
285
286
287
                          */
                        }
                    }
                }

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

              if ( CDI_Debug )
288
                Message("rdate = %d  rtime = %d", rdate, rtime);
289
290
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
291
292
293
294
295
    }

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

296
297
  free(tu);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
298
  if ( CDI_Debug )
299
    Message("timetype = %d  unit = %d", timetype, timeunit);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
300
301
302
303

  return (0);
}

304
305
static
void cdfGetAttInt(int fileID, int ncvarid, char *attname, int attlen, int *attint)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
306
{
307
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
308
309
  int *pintatt;

310
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
311

312
313
  if ( (int)nc_attlen > attlen )
    pintatt = (int *) malloc(nc_attlen*sizeof(int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
314
  else
315
    pintatt = attint;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
316
317
318

  cdf_get_att_int(fileID, ncvarid, attname, pintatt);

319
320
321
322
323
  if ( (int)nc_attlen > attlen )
    {
      memcpy(attint, pintatt, attlen*sizeof(int));
      free(pintatt);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324
325
}

326
327
static
void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
328
{
329
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
330
331
  double *pdoubleatt;

332
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
333

334
335
  if ( (int)nc_attlen > attlen )
    pdoubleatt = (double *) malloc(nc_attlen*sizeof(double));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
336
  else
337
    pdoubleatt = attdouble;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
338
339
340

  cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);

341
342
343
344
345
  if ( (int)nc_attlen > attlen )
    {
      memcpy(attdouble, pdoubleatt, attlen*sizeof(double));
      free(pdoubleatt);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
346
347
}

348
349
static
void cdfGetAttText(int fileID, int ncvarid, char *attname, int attlen, char *atttext)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
350
{
351
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
352
353
  char attbuf[65636];

354
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
355

356
  if ( nc_attlen < sizeof(attbuf) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
357
358
359
    {
      cdf_get_att_text(fileID, ncvarid, attname, attbuf);

360
      attbuf[nc_attlen++] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
361

362
363
      if ( (int) nc_attlen > attlen ) nc_attlen = attlen;
      memcpy(atttext, attbuf, nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
364
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
365
366
367
368
  else
    {
      atttext[0] = 0;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
369
370
}

371
static
372
int cdfInqDatatype(int xtype, int lunsigned)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
373
{
374
  int datatype = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
375

376
#if  defined  (HAVE_NETCDF4)
377
  if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;
378
#endif
379

Uwe Schulzweida's avatar
Uwe Schulzweida committed
380
381
382
383
  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;
384
  else if ( xtype == NC_FLOAT  )  datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
385
  else if ( xtype == NC_DOUBLE )  datatype = DATATYPE_FLT64;
386
#if  defined  (HAVE_NETCDF4)
387
  else if ( xtype == NC_UBYTE  )  datatype = DATATYPE_UINT8;
388
389
390
391
392
393
  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
394
395
396
397

  return (datatype);
}

398
static
399
int cdfDefDatatype(int datatype, int filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
400
401
402
{
  int xtype;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
403
  if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
404
    Error("CDI/netCDF library does not support complex numbers!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
405

406
407
408
409
410
  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;
411
#if  defined  (HAVE_NETCDF4)
412
413
414
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_UBYTE;
      else if ( datatype == DATATYPE_UINT16 ) xtype = NC_USHORT;
      else if ( datatype == DATATYPE_UINT32 ) xtype = NC_UINT;
415
#else
416
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_SHORT;
417
418
      else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
      else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
419
#endif
420
421
422
423
424
425
426
427
      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;
428
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_SHORT;
429
430
431
432
433
434
      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
435
436
437
  return (xtype);
}

438
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
439
440
441
void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
{
  int natts, iatt;
442
  int atttype, attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
443
  size_t len;
444
  char attname[1024];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
445
446
447
448
449

  vlistInqNatts(vlistID, varID, &natts);

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

452
453
      if ( attlen == 0 ) continue;

454
      if ( atttype == DATATYPE_TXT )
455
        {
456
457
458
          char *atttxt;
          atttxt = (char *) malloc(attlen*sizeof(char));
          vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
459
460
          len = attlen;
          cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
461
          free(atttxt);
462
        }
463
      else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
464
465
466
467
468
469
470
471
472
473
474
        {
          int *attint;
          attint = (int *) malloc(attlen*sizeof(int));
          vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
          len = attlen;
          if ( atttype == DATATYPE_INT16 )
            cdf_put_att_int(fileID, ncvarID, attname, NC_SHORT, len, attint);
          else
            cdf_put_att_int(fileID, ncvarID, attname, NC_INT, len, attint);
          free(attint);
        }
475
      else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
476
477
478
479
480
481
482
483
484
485
486
        {
          double *attflt;
          attflt = (double *) malloc(attlen*sizeof(double));
          vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
          len = attlen;
          if ( atttype == DATATYPE_FLT32 )
            cdf_put_att_double(fileID, ncvarID, attname, NC_FLOAT, len, attflt);
          else
            cdf_put_att_double(fileID, ncvarID, attname, NC_DOUBLE, len, attflt);
          free(attflt);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
487
488
489
490
    }
}
#endif

Uwe Schulzweida's avatar
Uwe Schulzweida committed
491
int cdfCopyRecord(int streamID2, int streamID1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
493
{
  double *data;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
494
  int datasize;
495
  int tsID1, recID1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
496
497
498
  int ivarID, gridID;
  int nmiss;
  int ierr = 0;
499
  int memtype = MEMTYPE_DOUBLE;
500
  int vlistID1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
501
502
  stream_t *streamptr1;
  stream_t *streamptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
503

Uwe Schulzweida's avatar
Uwe Schulzweida committed
504
505
  streamptr1 = stream_to_pointer(streamID1);
  streamptr2 = stream_to_pointer(streamID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
506

507
508
  stream_check_ptr(__func__, streamptr1);
  stream_check_ptr(__func__, streamptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
509

Uwe Schulzweida's avatar
Uwe Schulzweida committed
510
  vlistID1 = streamptr1->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511

Uwe Schulzweida's avatar
Uwe Schulzweida committed
512
  tsID1 = streamptr1->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513

Uwe Schulzweida's avatar
Uwe Schulzweida committed
514
  recID1 = streamptr1->tsteps[tsID1].curRecID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
515

Uwe Schulzweida's avatar
Uwe Schulzweida committed
516
517
518
  ivarID = streamptr1->tsteps[tsID1].records[recID1].varID;

  gridID = vlistInqVarGrid(vlistID1, ivarID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
519

520
  datasize = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
521
522
523
524
525
  /* bug fix for constant netCDF fields */
  if ( datasize < 1048576 ) datasize = 1048576;

  data = (double *) malloc(datasize*sizeof(double));

Uwe Schulzweida's avatar
Uwe Schulzweida committed
526
  streamReadRecord(streamID1, data, &nmiss);
527
  stream_write_record(streamID2, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528
529
530
531
532

  free(data);

  return (ierr);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
533

Uwe Schulzweida's avatar
Uwe Schulzweida committed
534
535
536
537
/* not used
int cdfInqRecord(int streamID, int *varID, int *levelID)
{
  int tsID, recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
538
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
539
540

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

542
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
543

Uwe Schulzweida's avatar
Uwe Schulzweida committed
544
545
546
  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
547

Uwe Schulzweida's avatar
Uwe Schulzweida committed
548
549
  if ( streamptr->tsteps[0].curRecID >= 
       streamptr->tsteps[0].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
550
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
551
      streamptr->tsteps[0].curRecID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
552
553
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
554
555
  *varID   = streamptr->tsteps[0].records[recID].varID;
  *levelID = streamptr->tsteps[0].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
556

Uwe Schulzweida's avatar
Uwe Schulzweida committed
557
558
  streamptr->record->varID   = *varID;
  streamptr->record->levelID = *levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
559
560

  if ( CDI_Debug )
561
    Message("recID = %d  varID = %d  levelID = %d", recID, *varID, *levelID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
563
564
565
566
567
568
  
  return (recID+1);
}
*/
int cdfDefRecord(int streamID)
{
  int ierr = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
569
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
570
571

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

  if ( CDI_Debug )
574
    Message("streamID = %d", streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
575

576
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
577
578
579
580

  return (ierr);
}

581
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
582
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
583
584
585
586
587
588
589
void cdfWriteGridTraj(int streamID, int gridID)
{
  int tsID, fileID;
  int lonID, latID, gridindex;
  size_t index;
  double xlon, xlat;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
590
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
591
592

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
593
594
595
596
597

  vlistID = streamInqVlist(streamID);
  fileID  = streamInqFileID(streamID);

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
598
599
  lonID = streamptr->xdimID[gridindex];
  latID = streamptr->ydimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
600
601
602

  xlon = gridInqXval(gridID, 0);
  xlat = gridInqYval(gridID, 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
603
  tsID = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
604
605
606
607
608
  index = tsID;

  cdf_put_var1_double(fileID, lonID, &index, &xlon);
  cdf_put_var1_double(fileID, latID, &index, &xlat);
}
609
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
610

611
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
612
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
613
614
615
616
617
618
619
void cdfReadGridTraj(int streamID, int gridID)
{
  int tsID, fileID;
  int lonID, latID, gridindex;
  size_t index;
  double xlon, xlat;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
620
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
621
622

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
623
624
625
626
627

  vlistID = streamInqVlist(streamID);
  fileID  = streamInqFileID(streamID);

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
628
629
  lonID = streamptr->xdimID[gridindex];
  latID = streamptr->ydimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
630

Uwe Schulzweida's avatar
Uwe Schulzweida committed
631
  tsID = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
632
633
634
635
636
637
638
639
  index = tsID;

  cdf_get_var1_double(fileID, lonID, &index, &xlon);
  cdf_get_var1_double(fileID, latID, &index, &xlat);

  gridDefXvals(gridID, &xlon);
  gridDefYvals(gridID, &xlat);
}
640
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
641

642
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
643
static
644
645
void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level)
{
646
#if  defined  (HAVE_NETCDF4)
647
648
649
650
651
652
653
654
655
  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)))
    {
656
      Error("nc_def_var_deflate failed, status = %d", retval);
657
658
659
660
661
662
663
    }
#else
  static int lwarn = TRUE;

  if ( lwarn )
    {
      lwarn = FALSE;
664
      Warning("Deflate compression failed, netCDF4 not available!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
665
666
667
668
669
    }
#endif
}
#endif

670
#if  defined(HAVE_LIBNETCDF) && defined(NC_SZIP_NN_OPTION_MASK)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
671
672
673
674
675
static
void cdfDefVarSzip(int ncid, int ncvarid)
{
  int retval;
  /* Set options_mask and bits_per_pixel. */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
676
  int options_mask = NC_SZIP_NN_OPTION_MASK;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
677
678
679
680
681
  int bits_per_pixel = 16;

  if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
    {
      if ( retval == NC_EINVAL )
682
683
684
685
686
687
        {
          static int lwarn = TRUE;

          if ( lwarn )
            {
              lwarn = FALSE;
688
              Warning("netCDF4/Szip compression not compiled in!");
689
            }
690
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
691
      else
692
        Error("nc_def_var_szip failed, status = %d", retval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
693
    }
694
695
696
}
#endif

697
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
698
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
699
void cdfDefVarMissval(int streamID, int varID, int dtype, int lcheck)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
700
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
701
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
702
703
704
705

  streamptr = stream_to_pointer(streamID);

  if ( streamptr->vars[varID].defmiss == FALSE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
706
707
708
709
710
711
712
713
714
    {
      int fileID;
      int ncvarid;
      double missval;
      int vlistID;
      int xtype;

      vlistID = streamInqVlist(streamID);
      fileID  = streamInqFileID(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
715
      ncvarid = streamptr->vars[varID].ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
716
      missval = vlistInqVarMissval(vlistID, varID);
717
      if ( lcheck && streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
718

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

721
      cdf_put_att_double(fileID, ncvarid, "_FillValue", (nc_type) xtype, 1, &missval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
722
723

      if ( cdiNcMissingValue == 1 )
724
        cdf_put_att_double(fileID, ncvarid, "missing_value", (nc_type) xtype, 1, &missval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
725

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
728
      streamptr->vars[varID].defmiss = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
729
730
    }
}
731
#endif
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
732

733
void cdf_write_record(int streamID, int memtype, const void *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
734
735
736
737
{
#if  defined  (HAVE_LIBNETCDF)
  int varID;
  int levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
738
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
739
740

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
742
743
  varID   = streamptr->record->varID;
  levelID = streamptr->record->levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
744
745

  if ( CDI_Debug )
746
    Message("streamID = %d  varID = %d", streamID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
747

748
  cdf_write_var_slice(streamID, varID, levelID, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
749
750
751
#endif
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
752

Uwe Schulzweida's avatar
Uwe Schulzweida committed
753
754
755
756
int cdfReadRecord(int streamID, double *data, int *nmiss)
{
  int ierr = 0;
  int levelID, varID, tsID, recID, vrecID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
757
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
758
759

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

761
  if ( CDI_Debug ) Message("streamID = %d", streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
762

Uwe Schulzweida's avatar
Uwe Schulzweida committed
763
764
765
766
767
  tsID    = streamptr->curTsID;
  vrecID  = streamptr->tsteps[tsID].curRecID;
  recID   = streamptr->tsteps[tsID].recIDs[vrecID];
  varID   = streamptr->tsteps[tsID].records[recID].varID;
  levelID = streamptr->tsteps[tsID].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
768
769
770
771
772
773

  cdfReadVarSliceDP(streamID, varID, levelID, data, nmiss);

  return (ierr);
}

774
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
775
776
777
778
779
780
781
void cdfDefTimeValue(int streamID, int tsID)
{
#if  defined  (HAVE_LIBNETCDF)
  int fileID;
  double timevalue;
  int ncvarid;
  size_t index;
782
  taxis_t *taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
783
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
784
785

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
786
787
788
789

  fileID = streamInqFileID(streamID);

  if ( CDI_Debug )
790
    Message("streamID = %d, fileID = %d", streamID, fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
791

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
794
  if ( streamptr->ncmode == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
795
796
    {
      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
797
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
798
799
800
801
    }

  index = tsID;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
805
  ncvarid = streamptr->basetime.ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
806
807
808
809
810
811
  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
812
      ncvarid = streamptr->basetime.ncvarboundsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
813

Uwe Schulzweida's avatar
Uwe Schulzweida committed
814
      timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
815
816
817
      start[0] = tsID; count[0] = 1; start[1] = 0; count[1] = 1;
      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
818
      timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
819
820
821
822
823
824
825
826
827
      start[0] = tsID; count[0] = 1; start[1] = 1; count[1] = 1;
      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
    }
  /*
printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
  */
#endif
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
828
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
829
830
831
832
833
834
835
void cdfDefTime(int streamID)
{
#if  defined  (HAVE_LIBNETCDF)
  int fileID;
  int time_varid;
  int time_bndsid;
  int dims[2];
836
  int year, month, day, hour, minute, second;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
837
838
  char unitstr[80];
  char calstr[80];
839
  char tmpstr[CDI_MAX_NAME];
840
841
  char default_name[] = "time";
  char *taxis_name = default_name;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
842
  size_t len;
843
  taxis_t *taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
844
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
846

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
848
  if ( streamptr->basetime.ncvarid != UNDEFID ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
849
850
851

  fileID = streamInqFileID(streamID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
852
  if ( streamptr->ncmode == 0 ) streamptr->ncmode = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
853

Uwe Schulzweida's avatar
Uwe Schulzweida committed
854
  if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
855

856
  taxis = &streamptr->tsteps[0].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
857

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

860
  cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &streamptr->basetime.ncdimid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
861

862
863
  dims[0] = streamptr->basetime.ncdimid;
  cdf_def_var(fileID, taxis_name, NC_DOUBLE, 1, dims, &time_varid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
864

865
  streamptr->basetime.ncvarid = time_varid;
866
867
868
869

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

870
871
872
  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
873
874
875
876
  if ( taxis->has_bounds )
    {
      /* fprintf(stderr, "time has bounds\n"); */

877
878
879
      if ( nc_inq_dimid(fileID, "nb2", &dims[1]) != NC_NOERR )
	cdf_def_dim(fileID, "nb2", 2, &dims[1]);

880
881
882
      strcpy(tmpstr, taxis_name);
      strcat(tmpstr, "_bnds");
      cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
883

Uwe Schulzweida's avatar
Uwe Schulzweida committed
884
      streamptr->basetime.ncvarboundsid = time_bndsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
885

886
      cdf_put_att_text(fileID, time_varid, "bounds", strlen(tmpstr), tmpstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
887
888
889
    }

  unitstr[0] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
890
  if ( streamptr->tsteps[0].taxis.type == TAXIS_ABSOLUTE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
891
    {
892
      if ( streamptr->tsteps[0].taxis.unit == TUNIT_YEAR )
893
        sprintf(unitstr, "year as %s", "%Y.%f");
894
      else if ( streamptr->tsteps[0].taxis.unit == TUNIT_MONTH )
895
        sprintf(unitstr, "month as %s", "%Y%m.%f");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
896
      else
897
        sprintf(unitstr, "day as %s", "%Y%m%d.%f");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
898
899
900
901
902
903
904
    }
  else
    {
      int rdate, rtime;
      int timeunit;

      timeunit = taxis->unit;
905
      if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
906
907
908
      rdate    = taxis->rdate;
      rtime    = taxis->rtime;
      if ( rdate == -1 )
909
910
911
912
        {
          rdate  = taxis->vdate;
          rtime  = taxis->vtime;
        }
913

Uwe Schulzweida's avatar
Uwe Schulzweida committed
914
915
      cdiDecodeDate(rdate, &year, &month, &day);
      cdiDecodeTime(rtime, &hour, &minute, &second);
916

917
      if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE;
918
919
920
921
      if ( timeunit == TUNIT_3HOURS  ||
	   timeunit == TUNIT_6HOURS  ||
	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

922
      sprintf(unitstr, "%s since %d-%02d-%02d %02d:%02d:%02d",
923
              tunitNamePtr(timeunit), year, month, day, hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
924
925
926
927
928
929
930
931
932
933
934
935
936
937
    }

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

  if ( taxis->has_bounds )
    if ( len )
      cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);

  if ( taxis->calendar != -1 )
    {
      calstr[0] = 0;

938
939
940
      if      ( taxis->calendar == CALENDAR_STANDARD )  strcpy(calstr, "standard");
      else if ( taxis->calendar == CALENDAR_PROLEPTIC ) strcpy(calstr, "proleptic_gregorian");
      else if ( taxis->calendar == CALENDAR_NONE )      strcpy(calstr, "none");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
941
942
943
944
945
946
      else if ( taxis->calendar == CALENDAR_360DAYS )   strcpy(calstr, "360_day");
      else if ( taxis->calendar == CALENDAR_365DAYS )   strcpy(calstr, "365_day");
      else if ( taxis->calendar == CALENDAR_366DAYS )   strcpy(calstr, "366_day");

      len = strlen(calstr);
      if ( len )
947
948
        {
          cdf_put_att_text(fileID, time_varid, "calendar", len, calstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
949

950
951
952
          if ( taxis->has_bounds )
            cdf_put_att_text(fileID, time_bndsid, "calendar", len, calstr);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
953
954
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
955
  if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
956
957
958
959
#endif
}


Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
960
961
962
963
964
965
966
967
968
969
970
void cdfDefTimestep(int streamID, int tsID)
{
  int vlistID;

  vlistID = streamInqVlist(streamID);

  if ( vlistHasTime(vlistID) ) cdfDefTime(streamID);

  cdfDefTimeValue(streamID, tsID);
}

971
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
972
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
973
974
void cdfDefComplex(int streamID, int gridID)
{
975
  char axisname[] = "nc2";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
976
977
978
979
980
981
982
  int index;
  int dimID = UNDEFID;
  int gridID0, gridtype0, gridindex;
  int ngrids;
  int fileID;
  int dimlen;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
983
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
984
985

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
986
987
988
989
990
991
992
993

  vlistID = streamInqVlist(streamID);
  fileID  = streamInqFileID(streamID);

  ngrids = vlistNgrids(vlistID);

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
994
      if ( streamptr->xdimID[index] != UNDEFID )
995
996
997
        {
          gridID0 = vlistGrid(vlistID, index);
          gridtype0 = gridInqType(gridID0);
998
          if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER )
999
1000
            {
              dimID = streamptr->xdimID[index];
For faster browsing, not all history is shown. View entire blame