stream_cdf.c 201 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
  int      isvar;
  int      islon;
  int      islat;
  int      islev;
  int      warn;
59
  int      tsteptype;
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
#if  defined  (HAVE_NETCDF4)
377
  if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;
378
#endif
379

Uwe Schulzweida's avatar
Uwe Schulzweida committed
380
381
382
383
  if      ( xtype == NC_BYTE   )  datatype = DATATYPE_INT8;
  /* else if ( xtype == NC_CHAR   )  datatype = DATATYPE_UINT8; */
  else if ( xtype == NC_SHORT  )  datatype = DATATYPE_INT16;
  else if ( xtype == NC_INT    )  datatype = DATATYPE_INT32;
384
  else if ( xtype == NC_FLOAT  )  datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
385
  else if ( xtype == NC_DOUBLE )  datatype = DATATYPE_FLT64;
386
#if  defined  (HAVE_NETCDF4)
387
  else if ( xtype == NC_UBYTE  )  datatype = DATATYPE_UINT8;
388
389
390
391
392
393
  else if ( xtype == NC_LONG   )  datatype = DATATYPE_INT32;
  else if ( xtype == NC_USHORT )  datatype = DATATYPE_UINT16;
  else if ( xtype == NC_UINT   )  datatype = DATATYPE_UINT32;
  else if ( xtype == NC_INT64  )  datatype = DATATYPE_FLT64;
  else if ( xtype == NC_UINT64 )  datatype = DATATYPE_FLT64;
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
394
395
396
397
398
399

  return (datatype);
}
#endif

#if  defined  (HAVE_LIBNETCDF)
400
static
401
int cdfDefDatatype(int datatype, int filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
402
403
404
{
  int xtype;

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

408
409
410
411
412
  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;
413
#if  defined  (HAVE_NETCDF4)
414
415
416
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_UBYTE;
      else if ( datatype == DATATYPE_UINT16 ) xtype = NC_USHORT;
      else if ( datatype == DATATYPE_UINT32 ) xtype = NC_UINT;
417
#else
418
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_SHORT;
419
420
      else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
      else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
421
#endif
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;
430
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_SHORT;
431
432
433
434
435
436
      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
437
438
439
440
441
442

  return (xtype);
}
#endif


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

  vlistInqNatts(vlistID, varID, &natts);

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

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


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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
509
510
  streamptr1 = stream_to_pointer(streamID1);
  streamptr2 = stream_to_pointer(streamID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511

512
513
  stream_check_ptr(__func__, streamptr1);
  stream_check_ptr(__func__, streamptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
514

Uwe Schulzweida's avatar
Uwe Schulzweida committed
515
516
  vlistID1 = streamptr1->vlistID;
  vlistID2 = streamptr2->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517

Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
519
  tsID1 = streamptr1->curTsID;
  tsID2 = streamptr2->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
520

Uwe Schulzweida's avatar
Uwe Schulzweida committed
521
522
  recID1 = streamptr1->tsteps[tsID1].curRecID;
  recID2 = streamptr2->tsteps[tsID2].curRecID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
523

Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
525
526
  ivarID = streamptr1->tsteps[tsID1].records[recID1].varID;

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
534
  streamReadRecord(streamID1, data, &nmiss);
535
  stream_write_record(streamID2, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
536
537
538
539
540

  free(data);

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

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

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

550
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
551

Uwe Schulzweida's avatar
Uwe Schulzweida committed
552
553
554
  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
555

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
563
  *varID   = streamptr->tsteps[0].records[recID].varID;
  *levelID = streamptr->tsteps[0].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
564

Uwe Schulzweida's avatar
Uwe Schulzweida committed
565
566
  streamptr->record->varID   = *varID;
  streamptr->record->levelID = *levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
567
568

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

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

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

584
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
585
586
587
588

  return (ierr);
}

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

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
601
602
603
604
605

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

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

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

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

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

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
631
632
633
634
635

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
639
  tsID = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
640
641
642
643
644
645
646
647
  index = tsID;

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

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

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

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

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

  if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
    {
      if ( retval == NC_EINVAL )
691
692
693
694
695
696
        {
          static int lwarn = TRUE;

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

  if ( lwarn )
    {
      lwarn = FALSE;
709
      Warning("netCDF4/Szip compression not available!");
710
711
712
713
714
    }
#endif
}
#endif

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

  streamptr = stream_to_pointer(streamID);

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

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

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

739
      cdf_put_att_double(fileID, ncvarid, "_FillValue", (nc_type) xtype, 1, &missval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
740
741

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

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

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

751
void cdf_write_record(int streamID, int memtype, const void *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
752
753
754
755
{
#if  defined  (HAVE_LIBNETCDF)
  int varID;
  int levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
756
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
757
758

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
760
761
  varID   = streamptr->record->varID;
  levelID = streamptr->record->levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
762
763

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

766
  cdf_write_var_slice(streamID, varID, levelID, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
767
768
769
#endif
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
770

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
781
782
783
784
785
  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
786
787
788
789
790
791

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

  return (ierr);
}

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

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
804
805
806
807

  fileID = streamInqFileID(streamID);

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

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

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

  index = tsID;

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

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
864
  if ( streamptr->basetime.ncvarid != UNDEFID ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
865
866
867

  fileID = streamInqFileID(streamID);

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

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
877
  streamptr->basetime.ncvarid = time_varid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
878

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

881
882
883
884

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

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

889
890
891
      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
892
893
      cdf_def_var(fileID, "time_bnds", NC_DOUBLE, 2, dims, &time_bndsid);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
894
      streamptr->basetime.ncvarboundsid = time_bndsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
895
896
897
898
899

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
924
925
      cdiDecodeDate(rdate, &year, &month, &day);
      cdiDecodeTime(rtime, &hour, &minute, &second);
926

927
      if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE;
928
929
930
931
      if ( timeunit == TUNIT_3HOURS  ||
	   timeunit == TUNIT_6HOURS  ||
	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

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

  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;

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
965
  if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
966
967
968
969
#endif
}


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

  vlistID = streamInqVlist(streamID);

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

  cdfDefTimeValue(streamID, tsID);
}

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

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
996
997
998
999
1000
1001
1002
1003

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

  ngrids = vlistNgrids(vlistID);

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1020
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1021
1022
1023
1024

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

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1025
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1026
1027
1028
    }

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

1033
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
1034
static
1035
void cdfDefSP(int streamID, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1036
1037
1038
1039
{
  /*
  char longname[] = "Spherical harmonic coefficient";
  */
1040
  char axisname[5] = "nspX";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1041
1042
1043
1044
1045
1046
1047
  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
1048
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1049
1050

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

  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
1061
      if ( streamptr->ydimID[index] != UNDEFID )
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
        {
          gridID0 = vlistGrid(vlistID, index);
          gridtype0 = gridInqType(gridID0);
          if ( gridtype0 == GRID_SPECTRAL )
            {
              dimlen0 = gridInqSize(gridID0)/2;
              if ( dimlen == dimlen0 )
                {
                  dimID = streamptr->ydimID[index];
                  break;
                }
              else
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
1133
1134
1135
                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++;
1136
1137
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1138
1139
1140
1141
1142
1143
1144
    }

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1145
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1146
1147
1148
1149

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

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