stream_cdf.c 191 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;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
91
92
93
94
95
96
97
98
99
100
  size_t   vlen;
  double  *vdata;
  double   missval;
  double   addoffset;
  double   scalefactor;
  char     name[MAXNAMELEN];
  char     longname[MAXNAMELEN];
  char     stdname[MAXNAMELEN];
  char     units[MAXNAMELEN];
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
101
ncvar_t;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
102

103
104
105
106
107
108
109
110
111
static
void strtolower(char *str)
{
  int i, len;

  if ( str )
    {
      len = (int) strlen(str);
      for ( i = 0; i < len; i++ )
112
        str[i] = tolower((int) str[i]);
113
114
115
    }
}

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

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

  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 )
161
162
163
164
165
166
167
168
169
170
        {
          while ( isspace(*ptu) ) ptu++;
          
          if ( memcmp(ptu, "as", 2) == 0 )
            timetype = TAXIS_ABSOLUTE;
          else if ( memcmp(ptu, "since", 5) == 0 )
            timetype = TAXIS_RELATIVE;

          if ( timetype != -1 ) status = TRUE;
        }
171
172
173
174
175
176
177
178
    }

  free(tu);

  return (status);
}

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

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

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

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

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

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

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
215
216
217
218
219
220
221
        {
          while ( isspace(*ptu) ) ptu++;

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

242
243
244
245
246
              if ( v3 > 999 && v1 < 32 )
                { year = v3; month = v2; day = v1; }
              else
                { year = v1; month = v2; day = v3; }

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

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

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

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

286
287
  free(tu);

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

  return (0);
}


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

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

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

  cdf_get_att_int(fileID, ncvarid, attname, pintatt);

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

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

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

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

  cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);

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

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

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

351
  if ( nc_attlen < sizeof(attbuf) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
352
353
354
    {
      cdf_get_att_text(fileID, ncvarid, attname, attbuf);

355
      attbuf[nc_attlen++] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
356

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

#if  defined  (HAVE_LIBNETCDF)
368
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
369
370
int cdfInqDatatype(int xtype)
{
371
  int datatype = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
372

Uwe Schulzweida's avatar
Uwe Schulzweida committed
373
374
375
376
  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;
377
  else if ( xtype == NC_FLOAT  )  datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
378
  else if ( xtype == NC_DOUBLE )  datatype = DATATYPE_FLT64;
379
#if  defined  (HAVE_NETCDF4)
380
381
382
383
384
385
386
  else if ( xtype == NC_LONG   )  datatype = DATATYPE_INT32;
  else if ( xtype == NC_UBYTE  )  datatype = DATATYPE_UINT8;
  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
387
388
389
390
391
392

  return (datatype);
}
#endif

#if  defined  (HAVE_LIBNETCDF)
393
static
394
int cdfDefDatatype(int datatype, int filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
395
396
397
{
  int xtype;

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

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

  return (xtype);
}
#endif


Uwe Schulzweida's avatar
Uwe Schulzweida committed
436
#if  defined  (HAVE_LIBNETCDF)
437
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
438
439
440
void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
{
  int natts, iatt;
441
  int atttype, attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
442
  size_t len;
443
444
  char attname[1024];
  char atttxt[8192];
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
      if ( atttype == DATATYPE_TXT )
453
454
455
456
457
        {
          vlistInqAttTxt(vlistID, varID, attname, sizeof(atttxt), atttxt);
          len = attlen;
          cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
        }
458
      else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
459
460
461
462
463
464
465
466
467
468
469
        {
          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);
        }
470
      else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
471
472
473
474
475
476
477
478
479
480
481
        {
          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
482
483
484
485
486
    }
}
#endif


Uwe Schulzweida's avatar
Uwe Schulzweida committed
487
int cdfCopyRecord(int streamID2, int streamID1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
488
489
{
  double *data;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
490
  int datasize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
491
  int tsID1, tsID2, recID1, recID2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
493
494
  int ivarID, gridID;
  int nmiss;
  int ierr = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
495
  int vlistID1, vlistID2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
496
497
  stream_t *streamptr1;
  stream_t *streamptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
498

Uwe Schulzweida's avatar
Uwe Schulzweida committed
499
500
  streamptr1 = stream_to_pointer(streamID1);
  streamptr2 = stream_to_pointer(streamID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
501

502
503
  stream_check_ptr(__func__, streamptr1);
  stream_check_ptr(__func__, streamptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
504

Uwe Schulzweida's avatar
Uwe Schulzweida committed
505
506
  vlistID1 = streamptr1->vlistID;
  vlistID2 = streamptr2->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
507

Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
509
  tsID1 = streamptr1->curTsID;
  tsID2 = streamptr2->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
510

Uwe Schulzweida's avatar
Uwe Schulzweida committed
511
512
  recID1 = streamptr1->tsteps[tsID1].curRecID;
  recID2 = streamptr2->tsteps[tsID2].curRecID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513

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

  gridID = vlistInqVarGrid(vlistID1, ivarID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517
518
519
520
521
522
523

  datasize = gridInqSize(gridID);      
  /* bug fix for constant netCDF fields */
  if ( datasize < 1048576 ) datasize = 1048576;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
525
  streamReadRecord(streamID1, data, &nmiss);
  streamWriteRecord(streamID2, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
526
527
528
529
530

  free(data);

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

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

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

540
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
541

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

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

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

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

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

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

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

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

  return (ierr);
}

579
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
580
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
581
582
583
584
585
586
587
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
588
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
589
590

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

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

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

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

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

609
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
610
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
611
612
613
614
615
616
617
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
618
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
619
620

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

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

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

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

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

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

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

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

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

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

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

  if ( lwarn )
    {
      lwarn = FALSE;
699
      Warning("netCDF4/Szip compression not available!");
700
701
702
703
704
    }
#endif
}
#endif

705
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
706
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
707
void cdfDefVarMissval(int streamID, int varID, int dtype, int lcheck)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
708
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
709
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
710
711
712
713

  streamptr = stream_to_pointer(streamID);

  if ( streamptr->vars[varID].defmiss == FALSE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
714
715
716
717
718
719
720
721
722
    {
      int fileID;
      int ncvarid;
      double missval;
      int vlistID;
      int xtype;

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

727
      xtype = cdfDefDatatype(dtype, streamptr->filetype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
728
729

      cdf_put_att_double(fileID, ncvarid, "_FillValue", (nc_type) xtype, 1L, &missval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
730
731

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
736
      streamptr->vars[varID].defmiss = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
737
738
    }
}
739
#endif
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
740

741
void cdfWriteRecord(int streamID, const double *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
742
743
744
745
{
#if  defined  (HAVE_LIBNETCDF)
  int varID;
  int levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
746
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
747
748

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
750
751
  varID   = streamptr->record->varID;
  levelID = streamptr->record->levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
752
753

  if ( CDI_Debug )
754
    Message("streamID = %d  varID = %d", streamID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
755
756
757
758
759

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

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
760

Uwe Schulzweida's avatar
Uwe Schulzweida committed
761
762
763
764
int cdfReadRecord(int streamID, double *data, int *nmiss)
{
  int ierr = 0;
  int levelID, varID, tsID, recID, vrecID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
765
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
766
767

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
771
772
773
774
775
  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
776
777
778
779
780
781

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

  return (ierr);
}

782
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
783
784
785
786
787
788
789
void cdfDefTimeValue(int streamID, int tsID)
{
#if  defined  (HAVE_LIBNETCDF)
  int fileID;
  double timevalue;
  int ncvarid;
  size_t index;
790
  taxis_t *taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
791
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
792
793

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
794
795
796
797

  fileID = streamInqFileID(streamID);

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
802
  if ( streamptr->ncmode == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
803
804
    {
      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
805
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
806
807
808
809
    }

  index = tsID;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
813
  ncvarid = streamptr->basetime.ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
814
815
816
817
818
819
  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
820
      ncvarid = streamptr->basetime.ncvarboundsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
821

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
854
  if ( streamptr->basetime.ncvarid != UNDEFID ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
855
856
857

  fileID = streamInqFileID(streamID);

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

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
867
  streamptr->basetime.ncvarid = time_varid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
868

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

871
872
873
874

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
875
876
877
878
  if ( taxis->has_bounds )
    {
      /* fprintf(stderr, "time has bounds\n"); */

879
880
881
      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
882
883
      cdf_def_var(fileID, "time_bnds", NC_DOUBLE, 2, dims, &time_bndsid);

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

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

  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
1001
1002
1003
            {
              dimID = streamptr->xdimID[index];
              break;
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1004
1005
1006
1007
1008
1009
    }

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1010
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1011
1012
1013
1014

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

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1015
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1016
1017
1018
    }

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1019
  streamptr->xdimID[gridindex] = dimID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1020
}
1021
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1022

1023
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
1024
static
1025
void cdfDefSP(int streamID, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1026
1027
1028
1029
{
  /*
  char longname[] = "Spherical harmonic coefficient";
  */
1030
  char axisname[5] = "nspX";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1031
1032
1033
1034
1035
1036
1037
  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
1038
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1039
1040

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050

  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
1051
      if ( streamptr->ydimID[index] != UNDEFID )
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
        {
          gridID0 = vlistGrid(vlistID, index);
          gridtype0 = gridInqType(gridID0);
          if ( gridtype0 == GRID_SPECTRAL )
            {
              dimlen0 = gridInqSize(gridID0)/2;
              if ( dimlen == dimlen0 )
                {
                  dimID = streamptr->ydimID[index];
                  break;
                }
              else
1064
1065
1066
1067
1068
1069
1070
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
                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++;
1126
1127
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1128
1129
1130
1131
1132
1133
1134
    }

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1135
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1136
1137
1138
1139

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

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1140
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1141
1142
1143
    }

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1144
  streamptr->ydimID[gridindex] = dimID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1145
}
1146
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1147

1148
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
1149
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
void cdfDefTrajLon(int streamID, int gridID)
{
  char units[256];
  char longname[256];
  char stdname[256];
  char axisname[256];
  int gridtype, gridindex;
  int dimID = UNDEFID;
  int fileID;
  int dimlen;
  size_t len;
  int ncvarid;
  int vlistID;
  int xtype = NC_DOUBLE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1164
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1165
1166

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

1168
  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1169
1170
1171
1172
1173
1174

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

  gridtype = gridInqType(gridID);
  dimlen = gridInqXsize(gridID);
1175
  if ( dimlen != 1 ) Error("Xsize isn't 1 for %s grid!", gridNamePtr(gridtype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1176
1177

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1178
  ncvarid = streamptr->xdimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1179
1180
1181
1182
1183
1184
1185
1186

  gridInqXname(gridID, axisname);
  gridInqXlongname(gridID, longname);
  gridInqXstdname(gridID, stdname);
  gridInqXunits(gridID, units);

  if ( ncvarid == UNDEFID )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1187
      dimID = streamptr->basetime.ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1188

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