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

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

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

13
14
15
16
17
#if  defined  (HAVE_LIBNETCDF)
#  include <netcdf.h>
#endif


Uwe Schulzweida's avatar
Uwe Schulzweida committed
18
19
20
21
#include "dmemory.h"

#include "cdi.h"
#include "basetime.h"
22
#include "gaussgrid.h"
23
#include "cdi_int.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
24
25
26
27
28
#include "stream_cdf.h"
#include "cdf_int.h"
#include "varscan.h"
#include "vlist.h"

29
30
//#define PROJECTION_TEST

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


35
36
void cdfDefGlobalAtts(stream_t *streamptr);
void cdfDefLocalAtts(stream_t *streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
37
38
39
40
41
42
43


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

44
45
46
#define  POSITIVE_UP    1
#define  POSITIVE_DOWN  2

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

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

120
#ifdef HAVE_LIBNETCDF
121
122
123
124
125
126
127
128
129
130
131
132
static
void strtolower(char *str)
{
  int i, len;

  if ( str )
    {
      len = (int) strlen(str);
      for ( i = 0; i < len; i++ )
        str[i] = tolower((int) str[i]);
    }
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
133

134
135
136
137
static
int get_timeunit(int len, char *ptu)
{
  int timeunit = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
138

139
140
141
142
143
144
145
146
147
148
  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;
    }
149
150
151
152
  else if ( len == 1 )
    {
      if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND;
    }
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

  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 )
179
180
        {
          while ( isspace(*ptu) ) ptu++;
Deike Kleberg's avatar
Deike Kleberg committed
181

182
183
184
185
          if ( memcmp(ptu, "as", 2) == 0 )
            timetype = TAXIS_ABSOLUTE;
          else if ( memcmp(ptu, "since", 5) == 0 )
            timetype = TAXIS_RELATIVE;
186

187
188
          if ( timetype != -1 ) status = TRUE;
        }
189
190
191
192
193
194
195
196
    }

  free(tu);

  return (status);
}

static
197
int splitBasetime(const char *timeunits, taxis_t *taxis)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
198
{
199
  int len, i;
200
  char *ptu, *tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
201
202
203
204
  int year, month, day;
  int hour = 0, minute = 0, second = 0;
  int timetype = TAXIS_ABSOLUTE;
  int rdate = -1, rtime = -1;
205
  int timeunit;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
206

Uwe Schulzweida's avatar
Uwe Schulzweida committed
207
  len = (int) strlen(timeunits);
208
209
210
  tu = (char *) malloc((len+1)*sizeof(char));
  memcpy(tu, timeunits, (len+1)*sizeof(char));
  ptu = tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
211

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

214
215
  timeunit = get_timeunit(len, ptu);
  if ( timeunit == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
216
    {
217
      Message("Unsupported TIMEUNIT: %s!", timeunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
218
219
220
221
222
223
      return (1);
    }

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

226
      if ( memcmp(ptu, "as", 2) == 0 )
227
        timetype = TAXIS_ABSOLUTE;
228
      else if ( memcmp(ptu, "since", 5) == 0 )
229
        timetype = TAXIS_RELATIVE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
230
231
232

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
        {
          while ( isspace(*ptu) ) ptu++;

          if ( timetype == TAXIS_ABSOLUTE )
            {
              if ( memcmp(ptu, "%y%m%d.%f", 9) != 0 && timeunit == TUNIT_DAY )
                {
                  Message("Unsupported format %s for TIMEUNIT day!", ptu);
                  timeunit = -1;
                }
              else if ( memcmp(ptu, "%y%m.%f", 7) != 0 && timeunit == TUNIT_MONTH )
                {
                  Message("Unsupported format %s for TIMEUNIT month!", ptu);
                  timeunit = -1;
                }
            }
          else if ( timetype == TAXIS_RELATIVE )
            {
251
252
253
              int v1, v2, v3;
              v1 = atoi(ptu);
              if ( v1 < 0 ) ptu++;
254
              while ( isdigit((int) *ptu) ) ptu++;
255
              v2 = atoi(++ptu);
256
              while ( isdigit((int) *ptu) ) ptu++;
257
              v3 = atoi(++ptu);
258
259
              while ( isdigit((int) *ptu) ) ptu++;

260
261
262
263
264
              if ( v3 > 999 && v1 < 32 )
                { year = v3; month = v2; day = v1; }
              else
                { year = v1; month = v2; day = v3; }

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
              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 )
                            Message("Seconds not supported in time units!");
                          */
                        }
                    }
                }

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

              if ( CDI_Debug )
Deike Kleberg's avatar
Deike Kleberg committed
296
                Message("rdate = %d  rtime = %d", rdate, rtime);
297
298
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
299
300
301
302
303
    }

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

304
305
  free(tu);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
306
  if ( CDI_Debug )
307
    Message("timetype = %d  unit = %d", timetype, timeunit);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
308
309
310
311

  return (0);
}

312
313
static
void cdfGetAttInt(int fileID, int ncvarid, char *attname, int attlen, int *attint)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
314
{
315
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
316
317
  int *pintatt;

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

320
321
  if ( (int)nc_attlen > attlen )
    pintatt = (int *) malloc(nc_attlen*sizeof(int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
322
  else
323
    pintatt = attint;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324
325
326

  cdf_get_att_int(fileID, ncvarid, attname, pintatt);

327
328
329
330
331
  if ( (int)nc_attlen > attlen )
    {
      memcpy(attint, pintatt, attlen*sizeof(int));
      free(pintatt);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
332
333
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
334
335
static
void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
336
{
337
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
338
339
  double *pdoubleatt;

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

342
343
  if ( (int)nc_attlen > attlen )
    pdoubleatt = (double *) malloc(nc_attlen*sizeof(double));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
344
  else
345
    pdoubleatt = attdouble;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
346
347
348

  cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);

349
350
351
352
353
  if ( (int)nc_attlen > attlen )
    {
      memcpy(attdouble, pdoubleatt, attlen*sizeof(double));
      free(pdoubleatt);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
354
355
}

356
357
static
void cdfGetAttText(int fileID, int ncvarid, char *attname, int attlen, char *atttext)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
358
{
359
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
360
361
  char attbuf[65636];

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

364
  if ( nc_attlen < sizeof(attbuf) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
365
366
367
    {
      cdf_get_att_text(fileID, ncvarid, attname, attbuf);

368
      attbuf[nc_attlen++] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
369

370
371
      if ( (int) nc_attlen > attlen ) nc_attlen = attlen;
      memcpy(atttext, attbuf, nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
372
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
373
374
375
376
  else
    {
      atttext[0] = 0;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
377
378
}

379
380
381
382
383
384
385
386
static
int xtypeIsFloat(int xtype)
{
  int isFloat = FALSE;
  if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
  return isFloat;
}

387
static
Deike Kleberg's avatar
Deike Kleberg committed
388
int cdfInqDatatype(int xtype, int lunsigned)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
389
{
390
  int datatype = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
391

392
#if  defined  (HAVE_NETCDF4)
Deike Kleberg's avatar
Deike Kleberg committed
393
  if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;
394
#endif
Deike Kleberg's avatar
Deike Kleberg committed
395

Uwe Schulzweida's avatar
Uwe Schulzweida committed
396
397
398
399
  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;
400
  else if ( xtype == NC_FLOAT  )  datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
401
  else if ( xtype == NC_DOUBLE )  datatype = DATATYPE_FLT64;
Deike Kleberg's avatar
Deike Kleberg committed
402
#if  defined  (HAVE_NETCDF4)
403
  else if ( xtype == NC_UBYTE  )  datatype = DATATYPE_UINT8;
404
405
406
407
408
409
  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
410
411
412
413

  return (datatype);
}

414
static
415
int cdfDefDatatype(int datatype, int filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
416
417
418
{
  int xtype;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
419
  if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
420
421
422
423
424
425
426
    Error("CDI/netCDF library does not support complex numbers!");

  if ( filetype == FILETYPE_NC4 )
    {
      if      ( datatype == DATATYPE_INT8   ) xtype = NC_BYTE;
      else if ( datatype == DATATYPE_INT16  ) xtype = NC_SHORT;
      else if ( datatype == DATATYPE_INT32  ) xtype = NC_INT;
Deike Kleberg's avatar
Deike Kleberg committed
427
#if  defined  (HAVE_NETCDF4)
428
429
430
431
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_UBYTE;
      else if ( datatype == DATATYPE_UINT16 ) xtype = NC_USHORT;
      else if ( datatype == DATATYPE_UINT32 ) xtype = NC_UINT;
#else
432
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_SHORT;
433
434
435
436
437
438
439
440
441
442
443
      else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
      else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
#endif
      else if ( datatype == DATATYPE_FLT64  ) xtype = NC_DOUBLE;
      else                                    xtype = NC_FLOAT;
    }
  else
    {
      if      ( datatype == DATATYPE_INT8   ) xtype = NC_BYTE;
      else if ( datatype == DATATYPE_INT16  ) xtype = NC_SHORT;
      else if ( datatype == DATATYPE_INT32  ) xtype = NC_INT;
444
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_SHORT;
445
446
447
448
449
      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
450

Uwe Schulzweida's avatar
Uwe Schulzweida committed
451
452
453
  return (xtype);
}

454
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
455
456
457
void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
{
  int natts, iatt;
458
  int atttype, attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
459
  size_t len;
460
  char attname[1024];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
461
462
463
464
465

  vlistInqNatts(vlistID, varID, &natts);

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

468
469
      if ( attlen == 0 ) continue;

470
      if ( atttype == DATATYPE_TXT )
471
        {
Deike Kleberg's avatar
Deike Kleberg committed
472
473
474
          char *atttxt;
          atttxt = (char *) malloc(attlen*sizeof(char));
          vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
475
476
          len = attlen;
          cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
Deike Kleberg's avatar
Deike Kleberg committed
477
          free(atttxt);
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
        }
      else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
        {
          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);
        }
      else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
        {
          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
503
504
505
506
    }
}
#endif

507
int cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
509
{
  double *data;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
510
  int datasize;
Thomas Jahns's avatar
Thomas Jahns committed
511
  int tsID1, recID1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
512
513
514
  int ivarID, gridID;
  int nmiss;
  int ierr = 0;
515
  int memtype = MEMTYPE_DOUBLE;
Thomas Jahns's avatar
Thomas Jahns committed
516
  int vlistID1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517

Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
  vlistID1 = streamptr1->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
519

Uwe Schulzweida's avatar
Uwe Schulzweida committed
520
  tsID1 = streamptr1->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
521

Uwe Schulzweida's avatar
Uwe Schulzweida committed
522
  recID1 = streamptr1->tsteps[tsID1].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

Deike Kleberg's avatar
Deike Kleberg committed
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));

534
535
  cdfReadRecord(streamptr1, data, &nmiss);
  cdf_write_record(streamptr2, 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
/* not used
543
int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
544
545
546
{
  int tsID, recID;

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

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

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

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

  if ( CDI_Debug )
563
    Message("recID = %d  varID = %d  levelID = %d", recID, *varID, *levelID);
564

Uwe Schulzweida's avatar
Uwe Schulzweida committed
565
566
567
  return (recID+1);
}
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
568

Uwe Schulzweida's avatar
Uwe Schulzweida committed
569

570
571
572
int cdfDefRecord(stream_t *streamptr)
{
  int ierr = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
573
574
575
576

  return (ierr);
}

577
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
578
static
579
void cdfWriteGridTraj(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
580
581
582
583
584
585
{
  int tsID, fileID;
  int lonID, latID, gridindex;
  size_t index;
  double xlon, xlat;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
586

587
588
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
589
590

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
591
592
  lonID = streamptr->xdimID[gridindex];
  latID = streamptr->ydimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
593
594
595

  xlon = gridInqXval(gridID, 0);
  xlat = gridInqYval(gridID, 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
596
  tsID = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
597
598
599
600
601
602
  index = tsID;

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

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
603
static
604
void cdfReadGridTraj(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
605
606
607
608
609
610
{
  int tsID, fileID;
  int lonID, latID, gridindex;
  size_t index;
  double xlon, xlat;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
611

612
613
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
614
615

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
619
  tsID = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
620
621
622
623
624
625
626
627
  index = tsID;

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

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

630
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
631
static
632
633
void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level)
{
Deike Kleberg's avatar
Deike Kleberg committed
634
#if  defined  (HAVE_NETCDF4)
635
636
637
638
639
640
641
642
643
  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)))
    {
644
      Error("nc_def_var_deflate failed, status = %d", retval);
645
646
647
648
649
650
651
    }
#else
  static int lwarn = TRUE;

  if ( lwarn )
    {
      lwarn = FALSE;
652
      Warning("Deflate compression failed, netCDF4 not available!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
653
654
655
656
657
    }
#endif
}
#endif

Uwe Schulzweida's avatar
Uwe Schulzweida committed
658
#if  defined(HAVE_LIBNETCDF) && defined(NC_SZIP_NN_OPTION_MASK)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
659
660
661
662
663
static
void cdfDefVarSzip(int ncid, int ncvarid)
{
  int retval;
  /* Set options_mask and bits_per_pixel. */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
664
  int options_mask = NC_SZIP_NN_OPTION_MASK;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
665
666
667
668
669
  int bits_per_pixel = 16;

  if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
    {
      if ( retval == NC_EINVAL )
670
671
672
673
674
675
676
        {
          static int lwarn = TRUE;

          if ( lwarn )
            {
              lwarn = FALSE;
              Warning("netCDF4/Szip compression not compiled in!");
Deike Kleberg's avatar
Deike Kleberg committed
677
            }
678
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
679
      else
680
        Error("nc_def_var_szip failed, status = %d", retval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
681
    }
682
683
684
}
#endif

685
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
686
static
687
void cdfDefVarMissval(stream_t *streamptr, int varID, int dtype, int lcheck)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
688
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
689
  if ( streamptr->vars[varID].defmiss == FALSE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
690
691
692
693
694
695
696
    {
      int fileID;
      int ncvarid;
      double missval;
      int vlistID;
      int xtype;

697
698
      vlistID = streamptr->vlistID;
      fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
699
      ncvarid = streamptr->vars[varID].ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
700
      missval = vlistInqVarMissval(vlistID, varID);
701

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

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

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

708
709
      cdf_put_att_double(fileID, ncvarid, "_FillValue", (nc_type) xtype, 1, &missval);
      cdf_put_att_double(fileID, ncvarid, "missing_value", (nc_type) xtype, 1, &missval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
710

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
713
      streamptr->vars[varID].defmiss = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
714
715
    }
}
716
#endif
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
717

718
void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
719
720
721
722
723
{
#if  defined  (HAVE_LIBNETCDF)
  int varID;
  int levelID;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
724
725
  varID   = streamptr->record->varID;
  levelID = streamptr->record->levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
726

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

729
  cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
730
731
732
#endif
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
733

734
int cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
735
736
737
738
{
  int ierr = 0;
  int levelID, varID, tsID, recID, vrecID;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
741
742
743
744
745
  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
746

747
  cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
748
749
750
751

  return (ierr);
}

752
static
753
void cdfDefTimeValue(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
754
755
756
757
758
759
{
#if  defined  (HAVE_LIBNETCDF)
  int fileID;
  double timevalue;
  int ncvarid;
  size_t index;
760
  taxis_t *taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
761

762
  fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
763
764

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
769
  if ( streamptr->ncmode == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
770
771
    {
      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
772
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
773
774
775
776
    }

  index = tsID;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
780
  ncvarid = streamptr->basetime.ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
781
782
783
784
785
786
  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
787
      ncvarid = streamptr->basetime.ncvarboundsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
788

Uwe Schulzweida's avatar
Uwe Schulzweida committed
789
      timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
790
791
792
      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
793
      timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
794
795
796
797
798
799
800
801
802
      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
}

803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
static
void cdfDefCalendar(int fileID, int ncvarid, int calendar)
{
  size_t len;
  char calstr[80];

  calstr[0] = 0;

  if      ( calendar == CALENDAR_STANDARD )  strcpy(calstr, "standard");
  else if ( calendar == CALENDAR_PROLEPTIC ) strcpy(calstr, "proleptic_gregorian");
  else if ( calendar == CALENDAR_NONE )      strcpy(calstr, "none");
  else if ( calendar == CALENDAR_360DAYS )   strcpy(calstr, "360_day");
  else if ( calendar == CALENDAR_365DAYS )   strcpy(calstr, "365_day");
  else if ( calendar == CALENDAR_366DAYS )   strcpy(calstr, "366_day");

  len = strlen(calstr);

  if ( len ) cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr);
}

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

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

841
  fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
842

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

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

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

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

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

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

856
  streamptr->basetime.ncvarid = time_varid;
Deike Kleberg's avatar
Deike Kleberg committed
857
858
859
860

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

861
862
863
  if ( taxis->longname && taxis->longname[0] )
    cdf_put_att_text(fileID, time_varid, "long_name", strlen(taxis->longname), taxis->longname);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
864
865
866
867
  if ( taxis->has_bounds )
    {
      /* fprintf(stderr, "time has bounds\n"); */

868
869
870
      if ( nc_inq_dimid(fileID, "nb2", &dims[1]) != NC_NOERR )
	cdf_def_dim(fileID, "nb2", 2, &dims[1]);

871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
      if ( taxis->climatology )
        {
          strcpy(tmpstr, "climatology");
          strcat(tmpstr, "_bnds");
          cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);

          streamptr->basetime.ncvarboundsid = time_bndsid;

          cdf_put_att_text(fileID, time_varid, "climatology", strlen(tmpstr), tmpstr);
        }
      else
        {
          strcpy(tmpstr, taxis_name);
          strcat(tmpstr, "_bnds");
          cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
886

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

889
890
          cdf_put_att_text(fileID, time_varid, "bounds", strlen(tmpstr), tmpstr);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
891
892
893
    }

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
918
919
      cdiDecodeDate(rdate, &year, &month, &day);
      cdiDecodeTime(rtime, &hour, &minute, &second);
920

921
      if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE;
922
923
924
925
      if ( timeunit == TUNIT_3HOURS  ||
	   timeunit == TUNIT_6HOURS  ||
	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

926
      sprintf(unitstr, "%s since %d-%02d-%02d %02d:%02d:%02d",
927
              tunitNamePtr(timeunit), year, month, day, hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
928
929
930
931
    }

  len = strlen(unitstr);
  if ( len )
932
933
    {
      cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
934

935
936
937
      if ( taxis->has_bounds )
        cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
938
939
940

  if ( taxis->calendar != -1 )
    {
941
      cdfDefCalendar(fileID, time_varid, taxis->calendar);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
942

943
944
      if ( taxis->has_bounds )
        cdfDefCalendar(fileID, time_bndsid, taxis->calendar);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
945
946
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
947
  if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
948
949
950
951
#endif
}


952
void cdfDefTimestep(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
953
954
955
{
  int vlistID;

956
  vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
957

958
  if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
959

960
  cdfDefTimeValue(streamptr, tsID);
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
961
962
}

963
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
964
static
965
void cdfDefComplex(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
966
{
967
  char axisname[] = "nc2";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
968
969
970
971
972
973
974
  int index;
  int dimID = UNDEFID;
  int gridID0, gridtype0, gridindex;
  int ngrids;
  int fileID;
  int dimlen;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
975

976
977
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
978
979
980
981
982

  ngrids = vlistNgrids(vlistID);

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
983
      if ( streamptr->xdimID[index] != UNDEFID )
984
985
986
        {
          gridID0 = vlistGrid(vlistID, index);
          gridtype0 = gridInqType(gridID0);
987
          if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER )
988
989
990
991
992
            {
              dimID = streamptr->xdimID[index];
              break;
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
993
994
995
996
997
998
    }

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
999
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1000
1001
1002
1003

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

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1004
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1005
1006
1007
    }

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1008
  streamptr->xdimID[gridindex] = dimID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1009
}
1010
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1011

1012
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
1013
static
1014
void cdfDefSP(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1015
1016
1017
1018
{
  /*
  char longname[] = "Spherical harmonic coefficient";
  */
1019
  char axisname[5] = "nspX";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1020
1021
1022
1023
1024
1025
1026
1027
  int index, iz = 0;
  int gridID0, gridtype0, gridindex;
  int dimID = UNDEFID;
  int ngrids;
  int fileID;
  int dimlen, dimlen0;
  int vlistID;

1028
1029
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1030
1031
1032
1033
1034
1035
1036

  ngrids = vlistNgrids(vlistID);

  dimlen = gridInqSize(gridID)/2;

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1037
      if ( streamptr->ydimID[index] != UNDEFID )
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
        {
          gridID0 = vlistGrid(vlistID, index);
          gridtype0 = gridInqType(gridID0);
          if ( gridtype0 == GRID_SPECTRAL )
            {
              dimlen0 = gridInqSize(gridID0)/2;
              if ( dimlen == dimlen0 )
                {
                  dimID = streamptr->ydimID[index];
                  break;
                }
              else
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
                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
1075
void cdfDefFC(stream_t *streamptr, int gridID)
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
{
  char axisname[5] = "nfcX";
  int index, iz = 0;
  int gridID0, gridtype0, gridindex;
  int dimID = UNDEFID;
  int ngrids;
  int fileID;
  int dimlen, dimlen0;
  int vlistID;

1086
1087
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102