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

5
6
#ifdef HAVE_LIBNETCDF

7
//#define TEST_GROUPS 1
Uwe Schulzweida's avatar
Uwe Schulzweida committed
8

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

16
#include <netcdf.h>
17

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

28
29
//#define PROJECTION_TEST

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


34
35
36
37
#if defined HAVE_LIBNETCDF
static void cdfDefGlobalAtts(stream_t *streamptr);
static void cdfDefLocalAtts(stream_t *streamptr);
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
38

Uwe Schulzweida's avatar
Uwe Schulzweida committed
39
#define  BNDS_NAME  "bnds"
40

Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
42
43
44
45
#define  X_AXIS  1
#define  Y_AXIS  2
#define  Z_AXIS  3
#define  T_AXIS  4

46
47
48
#define  POSITIVE_UP    1
#define  POSITIVE_DOWN  2

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

57
58
59
#define  MAX_COORDVARS  4
#define  MAX_AUXVARS    4

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

static
void strtolower(char *str)
{
  if ( str )
131
    for (size_t i = 0; str[i]; ++i)
132
      str[i] = (char)tolower((int)str[i]);
133
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
134

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

140
141
142
143
144
145
146
147
148
149
  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;
    }
150
151
152
153
  else if ( len == 1 )
    {
      if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND;
    }
154
155
156
157
158
159

  return (timeunit);
}

static
int isTimeUnits(const char *timeunits)
160
161
162
163
164
165
166
167
168
169
170
171
172
173
{
  int status = 0;

  if ( strncmp(timeunits, "sec",    3) == 0 ||
       strncmp(timeunits, "minute", 6) == 0 ||
       strncmp(timeunits, "hour",   4) == 0 ||
       strncmp(timeunits, "day",    3) == 0 ||
       strncmp(timeunits, "month",  5) == 0 ) status = 1;

  return (status);
}

static
int isTimeAxisUnits(const char *timeunits)
174
175
176
177
178
179
{
  char *ptu, *tu;
  int timetype = -1;
  int timeunit;
  int status = FALSE;

180
  size_t len = strlen(timeunits);
181
  tu = (char *)xmalloc((len+1)*sizeof(char));
182
  memcpy(tu, timeunits, (len+1) * sizeof(char));
183
184
  ptu = tu;

185
  for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
186
187
188
189
190
191
192

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

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
193
194
        {
          while ( isspace(*ptu) ) ptu++;
Deike Kleberg's avatar
Deike Kleberg committed
195

196
197
198
199
          if ( memcmp(ptu, "as", 2) == 0 )
            timetype = TAXIS_ABSOLUTE;
          else if ( memcmp(ptu, "since", 5) == 0 )
            timetype = TAXIS_RELATIVE;
200

201
202
          if ( timetype != -1 ) status = TRUE;
        }
203
204
205
206
207
208
209
210
    }

  free(tu);

  return (status);
}

static
211
void scanTimeString(const char *ptu, int *rdate, int *rtime)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
212
{
213
  int year = 1, month = 1, day = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
214
  int hour = 0, minute = 0, second = 0;
215
  int v1 = 1, v2 = 1, v3 = 1;
216
217
218
219

  *rdate = 0;
  *rtime = 0;

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  if ( *ptu )
    {
      v1 = atoi(ptu);
      if ( v1 < 0 ) ptu++;
      while ( isdigit((int) *ptu) ) ptu++;
      if ( *ptu )
        {
          v2 = atoi(++ptu);
          while ( isdigit((int) *ptu) ) ptu++;
          if ( *ptu )
            {
              v3 = atoi(++ptu);
              while ( isdigit((int) *ptu) ) ptu++;
            }
        }
    }
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

  if ( v3 > 999 && v1 < 32 )
    { year = v3; month = v2; day = v1; }
  else
    { year = v1; month = v2; day = v3; }

  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);
            }
        }
    }

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
267
268
269
270
static
int scanTimeUnit(const char *unitstr)
{
  int timeunit = -1;
271
  size_t len = strlen(unitstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
272
273
274
275
276
277
278
  timeunit = get_timeunit(len, unitstr);
  if ( timeunit == -1 )
    Message("Unsupported TIMEUNIT: %s!", unitstr);

  return (timeunit);
}

279
280
281
static
void setForecastTime(const char *timestr, taxis_t *taxis)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
282
283
284
285
286
287
  int len;

  (*taxis).fdate = 0;
  (*taxis).ftime = 0;

  len = (int) strlen(timestr);
288
289
290
291
292
293
294
295
296
297
298
299
300
  if ( len == 0 ) return;

  int fdate = 0, ftime = 0;
  scanTimeString(timestr, &fdate, &ftime);

  (*taxis).fdate = fdate;
  (*taxis).ftime = ftime;
}

static
int setBaseTime(const char *timeunits, taxis_t *taxis)
{
  char *ptu, *tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
301
302
  int timetype = TAXIS_ABSOLUTE;
  int rdate = -1, rtime = -1;
303
  int timeunit;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
304

305
  size_t len = strlen(timeunits);
306
  tu = (char *)xmalloc((len+1) * sizeof (char));
307
  memcpy(tu, timeunits, (len+1) * sizeof (char));
308
  ptu = tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
309

310
  for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]);
311

312
313
  timeunit = get_timeunit(len, ptu);
  if ( timeunit == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
314
    {
315
      Message("Unsupported TIMEUNIT: %s!", timeunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
316
317
318
319
320
321
      return (1);
    }

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

324
      if ( memcmp(ptu, "as", 2) == 0 )
325
        timetype = TAXIS_ABSOLUTE;
326
      else if ( memcmp(ptu, "since", 5) == 0 )
327
        timetype = TAXIS_RELATIVE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
328
329
330

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
        {
          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 )
            {
349
              scanTimeString(ptu, &rdate, &rtime);
350
351
352
353
354

              (*taxis).rdate = rdate;
              (*taxis).rtime = rtime;

              if ( CDI_Debug )
Deike Kleberg's avatar
Deike Kleberg committed
355
                Message("rdate = %d  rtime = %d", rdate, rtime);
356
357
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
358
359
360
361
362
    }

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

363
364
  free(tu);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
365
  if ( CDI_Debug )
366
    Message("timetype = %d  unit = %d", timetype, timeunit);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
367
368
369
370

  return (0);
}

371
372
static
void cdfGetAttInt(int fileID, int ncvarid, char *attname, int attlen, int *attint)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
373
{
374
  nc_type atttype;
375
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
376

377
378
379
  *attint = 0;

  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
380
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
381

382
383
384
385
386
387
388
389
  if ( atttype != NC_CHAR )
    {
      int *pintatt = NULL;

      if ( (int)nc_attlen > attlen )
        pintatt = (int *) malloc(nc_attlen * sizeof (int));
      else
        pintatt = attint;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
390

391
      cdf_get_att_int(fileID, ncvarid, attname, pintatt);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
392

393
394
395
396
397
      if ( (int)nc_attlen > attlen )
        {
          memcpy(attint, pintatt, (size_t)attlen * sizeof (int));
          free(pintatt);
        }
398
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
399
400
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
401
402
static
void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
403
{
404
  nc_type atttype;
405
  size_t nc_attlen;
406
407

  *attdouble = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
408

409
  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
410
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
411

412
413
414
  if ( atttype != NC_CHAR )
    {
      double *pdoubleatt = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
415

416
417
418
419
      if ( (int)nc_attlen > attlen )
        pdoubleatt = (double *) malloc(nc_attlen * sizeof (double));
      else
        pdoubleatt = attdouble;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
420

421
422
423
424
425
426
427
      cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);

      if ( (int)nc_attlen > attlen )
        {
          memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double));
          free(pdoubleatt);
        }
428
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
429
430
}

431
432
static
void cdfGetAttText(int fileID, int ncvarid, char *attname, int attlen, char *atttext)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
433
{
434
  nc_type atttype;
435
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
436

437
  cdf_inq_atttype(fileID, ncvarid, attname, &atttype);
438
  cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
439

440
  if ( atttype == NC_CHAR )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
441
    {
442
443
444
445
      char attbuf[65636];
      if ( nc_attlen < sizeof(attbuf) )
        {
          cdf_get_att_text(fileID, ncvarid, attname, attbuf);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
446

447
          if ( (int) nc_attlen > (attlen-1) ) nc_attlen = (size_t)(attlen-1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
448

449
          attbuf[nc_attlen++] = 0;
450
451
452
453
454
455
          memcpy(atttext, attbuf, nc_attlen);
        }
      else
        {
          atttext[0] = 0;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
456
    }
457
458
#if  defined  (HAVE_NETCDF4)
  else if ( atttype == NC_STRING )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
459
    {
460
461
462
463
464
      if ( nc_attlen == 1 )
        {
          char *attbuf = NULL;
          cdf_get_att_string(fileID, ncvarid, attname, &attbuf);

465
          size_t ssize = strlen(attbuf) + 1;
466

467
468
469
          if ( ssize > (size_t)attlen ) ssize = (size_t)attlen;
          memcpy(atttext, attbuf, ssize);
          atttext[ssize - 1] = 0;
470
471
472
473
474
475
          free(attbuf);
        }
      else
        {
          atttext[0] = 0;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
476
    }
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
#endif
}

static
int xtypeIsText(int xtype)
{
  int isText = FALSE;

  if ( xtype == NC_CHAR )
    isText = TRUE;
#if  defined  (HAVE_NETCDF4)
  else if ( xtype == NC_STRING )
    isText = TRUE;
#endif

  return (isText);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
493
494
}

495
496
497
498
static
int xtypeIsFloat(int xtype)
{
  int isFloat = FALSE;
499

500
  if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
501

502
503
504
  return isFloat;
}

505
static
Deike Kleberg's avatar
Deike Kleberg committed
506
int cdfInqDatatype(int xtype, int lunsigned)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
507
{
508
  int datatype = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
509

510
#if  defined  (HAVE_NETCDF4)
Deike Kleberg's avatar
Deike Kleberg committed
511
  if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE;
512
#endif
Deike Kleberg's avatar
Deike Kleberg committed
513

Uwe Schulzweida's avatar
Uwe Schulzweida committed
514
515
516
517
  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;
518
  else if ( xtype == NC_FLOAT  )  datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
519
  else if ( xtype == NC_DOUBLE )  datatype = DATATYPE_FLT64;
Deike Kleberg's avatar
Deike Kleberg committed
520
#if  defined  (HAVE_NETCDF4)
521
  else if ( xtype == NC_UBYTE  )  datatype = DATATYPE_UINT8;
522
523
524
525
526
527
  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
528
529
530
531

  return (datatype);
}

532
static
533
int cdfDefDatatype(int datatype, int filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
534
535
536
{
  int xtype;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
537
  if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
538
539
540
541
542
543
544
    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
545
#if  defined  (HAVE_NETCDF4)
546
547
548
549
      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
550
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_SHORT;
551
552
553
554
555
556
557
558
559
560
561
      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;
562
      else if ( datatype == DATATYPE_UINT8  ) xtype = NC_SHORT;
563
564
565
566
567
      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
568

Uwe Schulzweida's avatar
Uwe Schulzweida committed
569
570
571
  return (xtype);
}

572
573
574
575
576
static inline void *
resizeBuf(void **buf, size_t *bufSize, size_t reqSize)
{
  if (reqSize > *bufSize)
    {
577
      *buf = xrealloc(*buf, reqSize);
578
579
      *bufSize = reqSize;
    }
580
  return *buf;
581
582
}

583
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
584
585
586
void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
{
  int natts, iatt;
587
  int atttype, attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
588
  size_t len;
589
  char attname[CDI_MAX_NAME+1];
590
591
  void *attBuf = NULL;
  size_t attBufSize = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
592
593
594
595
596

  vlistInqNatts(vlistID, varID, &natts);

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

599
600
      if ( attlen == 0 ) continue;

601
      if ( atttype == DATATYPE_TXT )
602
        {
603
604
          size_t attSize = (size_t)attlen*sizeof(char);
          char *atttxt = (char *)resizeBuf(&attBuf, &attBufSize, attSize);
Deike Kleberg's avatar
Deike Kleberg committed
605
          vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt);
606
          len = (size_t)attlen;
607
608
609
610
          cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
        }
      else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 )
        {
611
612
          size_t attSize = (size_t)attlen*sizeof(int);
          int *attint = (int *)resizeBuf(&attBuf, &attBufSize, attSize);
613
          vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
614
          len = (size_t)attlen;
615
          cdf_put_att_int(fileID, ncvarID, attname, atttype == DATATYPE_INT16 ? NC_SHORT : NC_INT, len, attint);
616
617
618
        }
      else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 )
        {
619
620
          size_t attSize = (size_t)attlen * sizeof(double);
          double *attflt = (double *)resizeBuf(&attBuf, &attBufSize, attSize);
621
          vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
622
          len = (size_t)attlen;
623
          cdf_put_att_double(fileID, ncvarID, attname, atttype == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE, len, attflt);
624
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
625
    }
626
  free(attBuf);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
627
628
}

629

630
void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
631
{
632
  int memtype  = MEMTYPE_DOUBLE;
633
  int vlistID1 = streamptr1->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
634
635
636
637
  int tsID     = streamptr1->curTsID;
  int vrecID   = streamptr1->tsteps[tsID].curRecID;
  int recID    = streamptr1->tsteps[tsID].recIDs[vrecID];
  int ivarID   = streamptr1->tsteps[tsID].records[recID].varID;
638
  int gridID   = vlistInqVarGrid(vlistID1, ivarID);
639
  int datasize = gridInqSize(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
640

641
  double *data = (double *)xmalloc((size_t)datasize * sizeof (double));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
642

643
  int nmiss;
644
645
  cdfReadRecord(streamptr1, data, &nmiss);
  cdf_write_record(streamptr2, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
646
647
648

  free(data);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
649

Uwe Schulzweida's avatar
Uwe Schulzweida committed
650
/* not used
651
int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
652
653
654
{
  int tsID, recID;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
655
656
657
  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
658

659
  if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
660
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
661
      streamptr->tsteps[0].curRecID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
662
663
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
664
665
  *varID   = streamptr->tsteps[0].records[recID].varID;
  *levelID = streamptr->tsteps[0].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
666

Uwe Schulzweida's avatar
Uwe Schulzweida committed
667
668
  streamptr->record->varID   = *varID;
  streamptr->record->levelID = *levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
669
670

  if ( CDI_Debug )
671
    Message("recID = %d  varID = %d  levelID = %d", recID, *varID, *levelID);
672

Uwe Schulzweida's avatar
Uwe Schulzweida committed
673
674
675
  return (recID+1);
}
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
676

Uwe Schulzweida's avatar
Uwe Schulzweida committed
677

678
void cdfDefRecord(stream_t *streamptr)
679
{
Thomas Jahns's avatar
Thomas Jahns committed
680
  (void)streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
681
682
}

683

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
684
static
685
void cdfWriteGridTraj(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
686
{
687
688
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
689

690
691
692
  int gridindex = vlistGridIndex(vlistID, gridID);
  int lonID = streamptr->xdimID[gridindex],
    latID = streamptr->ydimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
693

694
695
696
697
  double xlon = gridInqXval(gridID, 0),
    xlat = gridInqYval(gridID, 0);
  int tsID = streamptr->curTsID;
  size_t index = (size_t)tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
698
699
700
701
702

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

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
703
static
704
void cdfReadGridTraj(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
705
{
706
707
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
708

709
710
711
  int gridindex = vlistGridIndex(vlistID, gridID);
  int lonID = streamptr->xdimID[gridindex];
  int latID = streamptr->ydimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
712

713
714
  int tsID = streamptr->curTsID;
  size_t index = (size_t)tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
715

716
  double xlon, xlat;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
717
718
719
720
721
722
723
  cdf_get_var1_double(fileID, lonID, &index, &xlon);
  cdf_get_var1_double(fileID, latID, &index, &xlat);

  gridDefXvals(gridID, &xlon);
  gridDefYvals(gridID, &xlat);
}

724

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
725
static
726
727
void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level)
{
Deike Kleberg's avatar
Deike Kleberg committed
728
#if  defined  (HAVE_NETCDF4)
729
730
731
732
733
734
735
736
737
  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)))
    {
738
      Error("nc_def_var_deflate failed, status = %d", retval);
739
740
741
742
743
744
745
    }
#else
  static int lwarn = TRUE;

  if ( lwarn )
    {
      lwarn = FALSE;
746
      Warning("Deflate compression failed, netCDF4 not available!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
747
748
749
750
    }
#endif
}

751
752

#if defined(NC_SZIP_NN_OPTION_MASK)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
753
754
755
756
757
static
void cdfDefVarSzip(int ncid, int ncvarid)
{
  int retval;
  /* Set options_mask and bits_per_pixel. */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
758
  int options_mask = NC_SZIP_NN_OPTION_MASK;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
759
760
761
762
763
  int bits_per_pixel = 16;

  if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
    {
      if ( retval == NC_EINVAL )
764
765
766
767
768
769
770
        {
          static int lwarn = TRUE;

          if ( lwarn )
            {
              lwarn = FALSE;
              Warning("netCDF4/Szip compression not compiled in!");
Deike Kleberg's avatar
Deike Kleberg committed
771
            }
772
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
773
      else
774
        Error("nc_def_var_szip failed, status = %d", retval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
775
    }
776
777
778
}
#endif

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
779
static
780
void cdfDefVarMissval(stream_t *streamptr, int varID, int dtype, int lcheck)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
781
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
782
  if ( streamptr->vars[varID].defmiss == FALSE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
783
784
785
786
787
788
789
    {
      int fileID;
      int ncvarid;
      double missval;
      int vlistID;
      int xtype;

790
791
      vlistID = streamptr->vlistID;
      fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
792
      ncvarid = streamptr->vars[varID].ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
793
      missval = vlistInqVarMissval(vlistID, varID);
794

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

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

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

801
802
      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
803

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
806
      streamptr->vars[varID].defmiss = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
807
808
    }
}
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
809

810

811
void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
812
813
814
815
{
  int varID;
  int levelID;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
816
817
  varID   = streamptr->record->varID;
  levelID = streamptr->record->levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
818

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

821
  cdf_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
822
823
}

824
void cdfReadRecord(stream_t *streamptr, double *data, int *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
825
{
826
  if ( CDI_Debug ) Message("streamID = %d", streamptr->self);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
827

828
829
830
831
832
  int tsID    = streamptr->curTsID;
  int vrecID  = streamptr->tsteps[tsID].curRecID;
  int recID   = streamptr->tsteps[tsID].recIDs[vrecID];
  int varID   = streamptr->tsteps[tsID].records[recID].varID;
  int levelID = streamptr->tsteps[tsID].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
833

834
  cdfReadVarSliceDP(streamptr, varID, levelID, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
835
836
}

837
static
838
void cdfDefTimeValue(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
839
{
840
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
841
842

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

845
  taxis_t *taxis = &streamptr->tsteps[tsID].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
846

Uwe Schulzweida's avatar
Uwe Schulzweida committed
847
  if ( streamptr->ncmode == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
848
849
    {
      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
850
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
851
852
    }

853
  size_t index = (size_t)tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
854

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

858
  int ncvarid = streamptr->basetime.ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
859
860
861
862
863
864
  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
865
      ncvarid = streamptr->basetime.ncvarboundsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
866

Uwe Schulzweida's avatar
Uwe Schulzweida committed
867
      timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
868
      start[0] = (size_t)tsID; count[0] = 1; start[1] = 0; count[1] = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
869
870
      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
871
      timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
872
      start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
873
874
      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
    }
875
876
877
878
879
880
881
882

  ncvarid = streamptr->basetime.leadtimeid;
  if ( taxis->type == TAXIS_FORECAST && ncvarid != UNDEFID )
    {
      timevalue = taxis->fc_period;
      cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
883
884
885
886
887
  /*
printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
  */
}

888
889
890
891
892
893
894
895
896
897
898
static
int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, char* taxis_name, taxis_t* taxis)
{
  int time_bndsid = -1;
  int dims[2];
  char tmpstr[CDI_MAX_NAME];

  dims[0] = nctimedimid;

  /* fprintf(stderr, "time has bounds\n"); */

Uwe Schulzweida's avatar
Uwe Schulzweida committed
899
900
  if ( nc_inq_dimid(fileID, BNDS_NAME, &dims[1]) != NC_NOERR )
    cdf_def_dim(fileID, BNDS_NAME, 2, &dims[1]);
901
902
903

  if ( taxis->climatology )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
904
905
      strcpy(tmpstr, "climatology_");
      strcat(tmpstr, BNDS_NAME);
906
907
908
909
910
911
912
      cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);

      cdf_put_att_text(fileID, nctimevarid, "climatology", strlen(tmpstr), tmpstr);
    }
  else
    {
      strcpy(tmpstr, taxis_name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
913
914
      strcat(tmpstr, "_");
      strcat(tmpstr, BNDS_NAME);
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
      cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);

      cdf_put_att_text(fileID, nctimevarid, "bounds", strlen(tmpstr), tmpstr);
    }

  return (time_bndsid);
}

static
void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis)
{
  unitstr[0] = 0;

  if ( taxis0->type == TAXIS_ABSOLUTE )
    {
      if ( taxis0->unit == TUNIT_YEAR )
        sprintf(unitstr, "year as %s", "%Y.%f");
      else if ( taxis0->unit == TUNIT_MONTH )
        sprintf(unitstr, "month as %s", "%Y%m.%f");
      else
        sprintf(unitstr, "day as %s", "%Y%m%d.%f");
    }
  else
    {
      int year, month, day, hour, minute, second;
      int rdate, rtime;
      int timeunit;

      timeunit = taxis->unit;
      if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
      rdate    = taxis->rdate;
      rtime    = taxis->rtime;
      if ( rdate == -1 )
        {
          rdate  = taxis->vdate;
          rtime  = taxis->vtime;
        }

      cdiDecodeDate(rdate, &year, &month, &day);
      cdiDecodeTime(rtime, &hour, &minute, &second);

956
957
      if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
      if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
958
959
960
961
962
963
964
965
      if ( timeunit == TUNIT_3HOURS  ||
	   timeunit == TUNIT_6HOURS  ||
	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

      sprintf(unitstr, "%s since %d-%02d-%02d %02d:%02d:%02d",
              tunitNamePtr(timeunit), year, month, day, hour, minute, second);
    }
}
966
967
968
969
970
971
972
973

static
void cdfDefForecastTimeUnits(char *unitstr, int timeunit)
{
  unitstr[0] = 0;

  if ( timeunit == -1 ) timeunit = TUNIT_HOUR;

974
975
  if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
  if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
976
977
978
979
980
981
  if ( timeunit == TUNIT_3HOURS  ||
       timeunit == TUNIT_6HOURS  ||
       timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

  sprintf(unitstr, "%s", tunitNamePtr(timeunit));
}
982

983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
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);
For faster browsing, not all history is shown. View entire blame