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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
5

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

#include "dmemory.h"

#include "cdi.h"
#include "basetime.h"
16
#include "gaussgrid.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
17
18
19
20
21
22
23
24
25
26
27
#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

28
29
//#define PROJECTION_TEST

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


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

#define  MAXNAMELEN  256

#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;
  char    name[MAXNAMELEN];
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
50
ncdim_t;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
51
52

typedef struct {
53
  int      ignore;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
54
55
56
57
58
59
  int      isvar;
  int      islon;
  int      islat;
  int      islev;
  int      warn;
  int      timeID;
60
  int      param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
61
  int      code;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
62
  int      tabnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
63
64
65
66
67
68
69
70
71
72
73
74
  int      bounds;
  int      gridID;
  int      zaxisID;
  int      gridtype;
  int      zaxistype;
  int      xdim;
  int      ydim;
  int      zdim;
  int      xvarid;
  int      yvarid;
  int      zvarid;
  int      tvarid;
75
76
  int      ncoordvars;
  int      coordvarids[4];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
77
78
79
80
81
82
83
84
85
86
87
  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
88
89
  int      natts;
  int     *atts;
90
  int      deflate;
91
92
  int      lunsigned;
  int      lvalidrange;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
94
95
96
97
  size_t   vlen;
  double  *vdata;
  double   missval;
  double   addoffset;
  double   scalefactor;
98
  double   validrange[2];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
99
100
101
102
103
  char     name[MAXNAMELEN];
  char     longname[MAXNAMELEN];
  char     stdname[MAXNAMELEN];
  char     units[MAXNAMELEN];
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
104
ncvar_t;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
105

106
107
108
109
110
111
112
113
114
static
void strtolower(char *str)
{
  int i, len;

  if ( str )
    {
      len = (int) strlen(str);
      for ( i = 0; i < len; i++ )
115
        str[i] = tolower((int) str[i]);
116
117
118
    }
}

119
120
121
122
static
int get_timeunit(int len, char *ptu)
{
  int timeunit = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
123

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

  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 )
164
165
        {
          while ( isspace(*ptu) ) ptu++;
166

167
168
169
170
171
172
173
          if ( memcmp(ptu, "as", 2) == 0 )
            timetype = TAXIS_ABSOLUTE;
          else if ( memcmp(ptu, "since", 5) == 0 )
            timetype = TAXIS_RELATIVE;

          if ( timetype != -1 ) status = TRUE;
        }
174
175
176
177
178
179
180
181
    }

  free(tu);

  return (status);
}

static
182
int splitBasetime(const char *timeunits, taxis_t *taxis)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
183
{
184
  int len, i;
185
  char *ptu, *tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
186
187
188
189
  int year, month, day;
  int hour = 0, minute = 0, second = 0;
  int timetype = TAXIS_ABSOLUTE;
  int rdate = -1, rtime = -1;
190
  int timeunit;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
191

Uwe Schulzweida's avatar
Uwe Schulzweida committed
192
  len = (int) strlen(timeunits);
193
194
195
  tu = (char *) malloc((len+1)*sizeof(char));
  memcpy(tu, timeunits, (len+1)*sizeof(char));
  ptu = tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
196

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

199
200
  timeunit = get_timeunit(len, ptu);
  if ( timeunit == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
201
    {
202
      Message("Unsupported TIMEUNIT: %s!", timeunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
203
204
205
206
207
208
      return (1);
    }

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

211
      if ( memcmp(ptu, "as", 2) == 0 )
212
        timetype = TAXIS_ABSOLUTE;
213
      else if ( memcmp(ptu, "since", 5) == 0 )
214
        timetype = TAXIS_RELATIVE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
215
216
217

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
218
219
220
221
222
223
224
        {
          while ( isspace(*ptu) ) ptu++;

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

245
246
247
248
249
              if ( v3 > 999 && v1 < 32 )
                { year = v3; month = v2; day = v1; }
              else
                { year = v1; month = v2; day = v3; }

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
              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 )
269
                            Message("Seconds not supported in time units!");
270
271
272
273
274
275
276
277
278
279
280
                          */
                        }
                    }
                }

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

              if ( CDI_Debug )
281
                Message("rdate = %d  rtime = %d", rdate, rtime);
282
283
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
284
285
286
287
288
    }

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

289
290
  free(tu);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
291
  if ( CDI_Debug )
292
    Message("timetype = %d  unit = %d", timetype, timeunit);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
293
294
295
296
297
298

  return (0);
}


#if  defined  (HAVE_LIBNETCDF)
299
300
static
void cdfGetAttInt(int fileID, int ncvarid, char *attname, int attlen, int *attint)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
301
{
302
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
303
304
  int *pintatt;

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

307
308
  if ( (int)nc_attlen > attlen )
    pintatt = (int *) malloc(nc_attlen*sizeof(int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
309
  else
310
    pintatt = attint;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
311
312
313

  cdf_get_att_int(fileID, ncvarid, attname, pintatt);

314
315
316
317
318
  if ( (int)nc_attlen > attlen )
    {
      memcpy(attint, pintatt, attlen*sizeof(int));
      free(pintatt);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
319
320
321
322
}
#endif

#if  defined  (HAVE_LIBNETCDF)
323
static void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324
{
325
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
326
327
  double *pdoubleatt;

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

330
331
  if ( (int)nc_attlen > attlen )
    pdoubleatt = (double *) malloc(nc_attlen*sizeof(double));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
332
  else
333
    pdoubleatt = attdouble;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
334
335
336

  cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);

337
338
339
340
341
  if ( (int)nc_attlen > attlen )
    {
      memcpy(attdouble, pdoubleatt, attlen*sizeof(double));
      free(pdoubleatt);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
342
343
344
345
}
#endif

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

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

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

358
      attbuf[nc_attlen++] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
359

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

#if  defined  (HAVE_LIBNETCDF)
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
377
  if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;

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

  return (datatype);
}
#endif

#if  defined  (HAVE_LIBNETCDF)
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_BYTE;
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_BYTE;
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
438
439
440

  return (xtype);
}
#endif


Uwe Schulzweida's avatar
Uwe Schulzweida committed
441
#if  defined  (HAVE_LIBNETCDF)
442
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
443
444
445
void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
{
  int natts, iatt;
446
  int atttype, attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
447
  size_t len;
448
  char attname[1024];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
449
450
451
452
453

  vlistInqNatts(vlistID, varID, &natts);

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

456
      if ( atttype == DATATYPE_TXT )
457
        {
458
459
460
          char *atttxt;
          atttxt = (char *) malloc(attlen*sizeof(char));
          vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
461
462
          len = attlen;
          cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
463
          free(atttxt);
464
        }
465
      else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
466
467
468
469
470
471
472
473
474
475
476
        {
          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);
        }
477
      else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
478
479
480
481
482
483
484
485
486
487
488
        {
          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
489
490
491
492
493
    }
}
#endif


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

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

509
510
  stream_check_ptr(__func__, streamptr1);
  stream_check_ptr(__func__, streamptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511

Uwe Schulzweida's avatar
Uwe Schulzweida committed
512
513
  vlistID1 = streamptr1->vlistID;
  vlistID2 = streamptr2->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
514

Uwe Schulzweida's avatar
Uwe Schulzweida committed
515
516
  tsID1 = streamptr1->curTsID;
  tsID2 = streamptr2->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517

Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
519
  recID1 = streamptr1->tsteps[tsID1].curRecID;
  recID2 = streamptr2->tsteps[tsID2].curRecID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
520

Uwe Schulzweida's avatar
Uwe Schulzweida committed
521
522
523
  ivarID = streamptr1->tsteps[tsID1].records[recID1].varID;

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

525
  datasize = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
526
527
528
529
530
  /* bug fix for constant netCDF fields */
  if ( datasize < 1048576 ) datasize = 1048576;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
531
532
  streamReadRecord(streamID1, data, &nmiss);
  streamWriteRecord(streamID2, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
533
534
535
536
537

  free(data);

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
539
540
541
542
/* not used
int cdfInqRecord(int streamID, int *varID, int *levelID)
{
  int tsID, recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
543
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
544
545

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

547
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
548

Uwe Schulzweida's avatar
Uwe Schulzweida committed
549
550
551
  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
552

Uwe Schulzweida's avatar
Uwe Schulzweida committed
553
554
  if ( streamptr->tsteps[0].curRecID >= 
       streamptr->tsteps[0].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
555
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
556
      streamptr->tsteps[0].curRecID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
557
558
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
559
560
  *varID   = streamptr->tsteps[0].records[recID].varID;
  *levelID = streamptr->tsteps[0].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
561

Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
563
  streamptr->record->varID   = *varID;
  streamptr->record->levelID = *levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
564
565

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

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

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

581
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
582
583
584
585

  return (ierr);
}

586
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
587
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
588
589
590
591
592
593
594
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
595
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
596
597

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
598
599
600
601
602

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

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
603
604
  lonID = streamptr->xdimID[gridindex];
  latID = streamptr->ydimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
605
606
607

  xlon = gridInqXval(gridID, 0);
  xlat = gridInqYval(gridID, 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
608
  tsID = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
609
610
611
612
613
  index = tsID;

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

616
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
617
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
618
619
620
621
622
623
624
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
625
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
626
627

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
628
629
630
631
632

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
636
  tsID = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
637
638
639
640
641
642
643
644
  index = tsID;

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

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

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

  if ( lwarn )
    {
      lwarn = FALSE;
669
      Warning("Deflate compression failed, netCDF4 not available!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
670
671
672
673
674
675
676
677
678
    }
#endif
}
#endif

#if  defined  (HAVE_LIBNETCDF)
static
void cdfDefVarSzip(int ncid, int ncvarid)
{
679
#if  defined  (HAVE_NETCDF4) && defined (NC_SZIP_NN_OPTION_MASK)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
680
681
  int retval;
  /* Set options_mask and bits_per_pixel. */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
682
  int options_mask = NC_SZIP_NN_OPTION_MASK;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
683
684
685
686
687
  int bits_per_pixel = 16;

  if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
    {
      if ( retval == NC_EINVAL )
688
689
690
691
692
693
        {
          static int lwarn = TRUE;

          if ( lwarn )
            {
              lwarn = FALSE;
694
              Warning("netCDF4/Szip compression not compiled in!");
695
            }
696
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
697
      else
698
        Error("nc_def_var_szip failed, status = %d", retval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
699
700
701
702
703
704
705
    }
#else
  static int lwarn = TRUE;

  if ( lwarn )
    {
      lwarn = FALSE;
706
      Warning("netCDF4/Szip compression not available!");
707
708
709
710
711
    }
#endif
}
#endif

712
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
713
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
714
void cdfDefVarMissval(int streamID, int varID, int dtype, int lcheck)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
715
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
716
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
717
718
719
720

  streamptr = stream_to_pointer(streamID);

  if ( streamptr->vars[varID].defmiss == FALSE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
721
722
723
724
725
726
727
728
729
    {
      int fileID;
      int ncvarid;
      double missval;
      int vlistID;
      int xtype;

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

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

736
      cdf_put_att_double(fileID, ncvarid, "_FillValue", (nc_type) xtype, 1, &missval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
737
738

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
743
      streamptr->vars[varID].defmiss = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
744
745
    }
}
746
#endif
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
747

748
void cdfWriteRecord(int streamID, const double *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
749
750
751
752
{
#if  defined  (HAVE_LIBNETCDF)
  int varID;
  int levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
753
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
754
755

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
757
758
  varID   = streamptr->record->varID;
  levelID = streamptr->record->levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
759
760

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

  cdfWriteVarSliceDP(streamID, varID, levelID, data, nmiss);
#endif
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
767

Uwe Schulzweida's avatar
Uwe Schulzweida committed
768
769
770
771
int cdfReadRecord(int streamID, double *data, int *nmiss)
{
  int ierr = 0;
  int levelID, varID, tsID, recID, vrecID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
772
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
773
774

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
778
779
780
781
782
  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
783
784
785
786
787
788

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

  return (ierr);
}

789
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
790
791
792
793
794
795
796
void cdfDefTimeValue(int streamID, int tsID)
{
#if  defined  (HAVE_LIBNETCDF)
  int fileID;
  double timevalue;
  int ncvarid;
  size_t index;
797
  taxis_t *taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
798
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
799
800

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
801
802
803
804

  fileID = streamInqFileID(streamID);

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
809
  if ( streamptr->ncmode == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
810
811
    {
      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
812
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
813
814
815
816
    }

  index = tsID;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
820
  ncvarid = streamptr->basetime.ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
821
822
823
824
825
826
  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
827
      ncvarid = streamptr->basetime.ncvarboundsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
828

Uwe Schulzweida's avatar
Uwe Schulzweida committed
829
      timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
830
831
832
      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
833
      timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
834
835
836
837
838
839
840
841
842
      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
843
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
844
845
846
847
848
849
850
void cdfDefTime(int streamID)
{
#if  defined  (HAVE_LIBNETCDF)
  int fileID;
  int time_varid;
  int time_bndsid;
  int dims[2];
851
  int year, month, day, hour, minute, second;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
852
853
  char unitstr[80];
  char calstr[80];
854
  char tmpstr[256];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
855
  size_t len;
856
  taxis_t *taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
857
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
858
859

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
861
  if ( streamptr->basetime.ncvarid != UNDEFID ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
862
863
864

  fileID = streamInqFileID(streamID);

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
869
  cdf_def_dim(fileID, "time", NC_UNLIMITED, &streamptr->basetime.ncdimid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
870

Uwe Schulzweida's avatar
Uwe Schulzweida committed
871
  dims[0] = streamptr->basetime.ncdimid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
872
873
  cdf_def_var(fileID, "time", NC_DOUBLE, 1, dims, &time_varid);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
874
  streamptr->basetime.ncvarid = time_varid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
875

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

878
879
880
881

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
882
883
884
885
  if ( taxis->has_bounds )
    {
      /* fprintf(stderr, "time has bounds\n"); */

886
887
888
      if ( nc_inq_dimid(fileID, "nb2", &dims[1]) != NC_NOERR )
	cdf_def_dim(fileID, "nb2", 2, &dims[1]);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
889
890
      cdf_def_var(fileID, "time_bnds", NC_DOUBLE, 2, dims, &time_bndsid);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
891
      streamptr->basetime.ncvarboundsid = time_bndsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
892
893
894
895
896

      cdf_put_att_text(fileID, time_varid, "bounds", 9, "time_bnds");
    }

  unitstr[0] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
897
  if ( streamptr->tsteps[0].taxis.type == TAXIS_ABSOLUTE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
898
    {
899
      if ( streamptr->tsteps[0].taxis.unit == TUNIT_YEAR )
900
        sprintf(unitstr, "year as %s", "%Y.%f");
901
      else if ( streamptr->tsteps[0].taxis.unit == TUNIT_MONTH )
902
        sprintf(unitstr, "month as %s", "%Y%m.%f");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
903
      else
904
        sprintf(unitstr, "day as %s", "%Y%m%d.%f");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
905
906
907
908
909
910
911
    }
  else
    {
      int rdate, rtime;
      int timeunit;

      timeunit = taxis->unit;
912
      if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
913
914
915
      rdate    = taxis->rdate;
      rtime    = taxis->rtime;
      if ( rdate == -1 )
916
917
918
919
        {
          rdate  = taxis->vdate;
          rtime  = taxis->vtime;
        }
920

Uwe Schulzweida's avatar
Uwe Schulzweida committed
921
922
      cdiDecodeDate(rdate, &year, &month, &day);
      cdiDecodeTime(rtime, &hour, &minute, &second);
923

924
      if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE;
925
926
927
928
      if ( timeunit == TUNIT_3HOURS  ||
	   timeunit == TUNIT_6HOURS  ||
	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

929
      sprintf(unitstr, "%s since %d-%02d-%02d %02d:%02d:%02d",
930
              tunitNamePtr(timeunit), year, month, day, hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
931
932
933
934
935
936
937
938
939
940
941
942
943
944
    }

  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;

945
946
947
      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
948
949
950
951
952
953
      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 )
954
955
        {
          cdf_put_att_text(fileID, time_varid, "calendar", len, calstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
956

957
958
959
          if ( taxis->has_bounds )
            cdf_put_att_text(fileID, time_bndsid, "calendar", len, calstr);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
960
961
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
962
  if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
963
964
965
966
#endif
}


Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
967
968
969
970
971
972
973
974
975
976
977
void cdfDefTimestep(int streamID, int tsID)
{
  int vlistID;

  vlistID = streamInqVlist(streamID);

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

  cdfDefTimeValue(streamID, tsID);
}

978
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
979
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
980
981
void cdfDefComplex(int streamID, int gridID)
{
982
  char axisname[] = "nc2";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
983
984
985
986
987
988
989
  int index;
  int dimID = UNDEFID;
  int gridID0, gridtype0, gridindex;
  int ngrids;
  int fileID;
  int dimlen;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
990
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
991
992

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
993
994
995
996
997
998
999
1000

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

  ngrids = vlistNgrids(vlistID);

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1001
      if ( streamptr->xdimID[index] != UNDEFID )
1002
1003
1004
        {
          gridID0 = vlistGrid(vlistID, index);
          gridtype0 = gridInqType(gridID0);
1005
          if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER )
1006
1007
1008
1009
1010
            {
              dimID = streamptr->xdimID[index];
              break;
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1011
1012
1013
1014
1015
1016
    }

  if ( dimID == UNDEFID )
    {
      dimlen = 2;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1017
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1018
1019
1020
1021

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

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1022
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1023
1024
1025
    }

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1026
  streamptr->xdimID[gridindex] = dimID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1027
}
1028
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1029

1030
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
1031
static
1032
void cdfDefSP(int streamID, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1033
1034
1035
1036
{
  /*
  char longname[] = "Spherical harmonic coefficient";
  */
1037
  char axisname[5] = "nspX";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1038
1039
1040
1041
1042
1043
1044
  int index, iz = 0;
  int gridID0, gridtype0, gridindex;
  int dimID = UNDEFID;
  int ngrids;
  int fileID;
  int dimlen, dimlen0;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1045
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1046
1047

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057

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

  ngrids = vlistNgrids(vlistID);

  dimlen = gridInqSize(gridID)/2;

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1058
      if ( streamptr->ydimID[index] != UNDEFID )
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
        {
          gridID0 = vlistGrid(vlistID, index);
          gridtype0 = gridInqType(gridID0);
          if ( gridtype0 == GRID_SPECTRAL )
            {
              dimlen0 = gridInqSize(gridID0)/2;
              if ( dimlen == dimlen0 )
                {
                  dimID = streamptr->ydimID[index];
                  break;
                }
              else
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
                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;
    }

  gridindex = vlistGridIndex(vlistID, gridID);
  streamptr->ydimID[gridindex] = dimID;
}
#endif

#if  defined  (HAVE_LIBNETCDF)
static
void cdfDefFC(int streamID, int gridID)
{
  char axisname[5] = "nfcX";
  int index, iz = 0;
  int gridID0, gridtype0, gridindex;
  int dimID = UNDEFID;
  int ngrids;
  int fileID;
  int dimlen, dimlen0;
  int vlistID;
  stream_t *streamptr;

  streamptr = stream_to_pointer(streamID);

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

  ngrids = vlistNgrids(vlistID);

  dimlen = gridInqSize(gridID)/2;

  for ( index = 0; index < ngrids; index++ )
    {
      if ( streamptr->ydimID[index] != UNDEFID )
        {
          gridID0 = vlistGrid(vlistID, index);
          gridtype0 = gridInqType(gridID0);
          if ( gridtype0 == GRID_FOURIER )
            {
              dimlen0 = gridInqSize(gridID0)/2;
              if ( dimlen == dimlen0 )
                {
                  dimID = streamptr->ydimID[index];
                  break;
                }
              else
                iz++;
1133
1134
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1135
1136
1137
1138
1139
1140
1141
    }

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1142
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1143
1144
1145
1146

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

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1147
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1148
1149
1150
    }

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1151
  streamptr->ydimID[gridindex] = dimID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1152
}
1153
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1154

1155
#if  defined  (HAVE_LIBNETCDF)