stream_cdf.c 233 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
#include <ctype.h>
#include <math.h>
#include <float.h>
13
14
15
16
17
18
19
20
21
22
#ifdef HAVE_MMAP
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#ifdef HAVE_LIBPTHREAD
#include <pthread.h>
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
23

24
#include <netcdf.h>
25

Uwe Schulzweida's avatar
Uwe Schulzweida committed
26
27
28
#include "dmemory.h"
#include "cdi.h"
#include "basetime.h"
29
#include "gaussgrid.h"
30
#include "cdi_int.h"
31
#include "cdi_uuid.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
32
#include "stream_cdf.h"
33
#include "cdf.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
34
35
36
37
#include "cdf_int.h"
#include "varscan.h"
#include "vlist.h"

38
39
//#define PROJECTION_TEST

Uwe Schulzweida's avatar
Uwe Schulzweida committed
40
41
42
#undef  UNDEFID
#define UNDEFID  CDI_UNDEFID

Uwe Schulzweida's avatar
Uwe Schulzweida committed
43
#define  BNDS_NAME  "bnds"
44

Uwe Schulzweida's avatar
Uwe Schulzweida committed
45
46
47
48
49
#define  X_AXIS  1
#define  Y_AXIS  2
#define  Z_AXIS  3
#define  T_AXIS  4

50
51
52
#define  POSITIVE_UP    1
#define  POSITIVE_DOWN  2

Uwe Schulzweida's avatar
Uwe Schulzweida committed
53
54
55
56
typedef struct {
  int     ncvarid;
  int     dimtype;
  size_t  len;
57
  char    name[CDI_MAX_NAME];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
58
}
59
ncdim_t;
60
61
62
#define  MAX_COORDVARS  4
#define  MAX_AUXVARS    4

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

static
void strtolower(char *str)
{
  if ( str )
138
    for (size_t i = 0; str[i]; ++i)
139
      str[i] = (char)tolower((int)str[i]);
140
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
141

142
static
143
int get_timeunit(size_t len, const char *ptu)
144
145
{
  int timeunit = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
146

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

162
  return timeunit;
163
164
165
}

static
166
bool isTimeUnits(const char *timeunits)
167
{
168
  bool status = false;
169
170
171
172
173

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

176
  return status;
177
178
179
}

static
180
bool isTimeAxisUnits(const char *timeunits)
181
182
183
184
{
  char *ptu, *tu;
  int timetype = -1;
  int timeunit;
185
  bool status = false;
186

187
  size_t len = strlen(timeunits);
188
  tu = (char *) Malloc((len+1)*sizeof(char));
189
  memcpy(tu, timeunits, (len+1) * sizeof(char));
190
191
  ptu = tu;

192
  for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]);
193
194
195
196
197
198
199

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

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
200
201
        {
          while ( isspace(*ptu) ) ptu++;
Deike Kleberg's avatar
Deike Kleberg committed
202

203
204
205
206
          if ( memcmp(ptu, "as", 2) == 0 )
            timetype = TAXIS_ABSOLUTE;
          else if ( memcmp(ptu, "since", 5) == 0 )
            timetype = TAXIS_RELATIVE;
207

208
          if ( timetype != -1 ) status = true;
209
        }
210
211
    }

212
  Free(tu);
213

214
  return status;
215
216
217
}

static
218
void scanTimeString(const char *ptu, int *rdate, int *rtime)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
219
{
220
  int year = 1, month = 1, day = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
221
  int hour = 0, minute = 0, second = 0;
222
  int v1 = 1, v2 = 1, v3 = 1;
223
224
225
226

  *rdate = 0;
  *rtime = 0;

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  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++;
            }
        }
    }
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

  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
274
275
276
static
int scanTimeUnit(const char *unitstr)
{
277
  size_t len = strlen(unitstr);
278
  int timeunit = get_timeunit(len, unitstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
279
280
281
  if ( timeunit == -1 )
    Message("Unsupported TIMEUNIT: %s!", unitstr);

282
  return timeunit;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
283
284
}

285
286
287
static
void setForecastTime(const char *timestr, taxis_t *taxis)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
288
289
290
  (*taxis).fdate = 0;
  (*taxis).ftime = 0;

291
  int len = (int) strlen(timestr);
292
293
294
295
296
297
298
299
300
301
302
303
  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)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
304
305
306
  int timetype = TAXIS_ABSOLUTE;
  int rdate = -1, rtime = -1;

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

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

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

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

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

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

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

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

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

365
  Free(tu);
366

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

370
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
371
372
}

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

379
380
381
  *attint = 0;

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

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

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

393
      cdf_get_att_int(fileID, ncvarid, attname, pintatt);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
394

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

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

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

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

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

418
      if ( (int)nc_attlen > attlen )
419
        pdoubleatt = (double *) Malloc(nc_attlen * sizeof (double));
420
421
      else
        pdoubleatt = attdouble;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
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));
428
          Free(pdoubleatt);
429
        }
430
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
431
432
}

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

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

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

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

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

467
          size_t ssize = strlen(attbuf) + 1;
468

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

494
  return isText;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
495
496
}

497
498
499
500
static
int xtypeIsFloat(int xtype)
{
  int isFloat = FALSE;
501

502
  if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) isFloat = TRUE;
503

504
505
506
  return isFloat;
}

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

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

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

531
  return datatype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
532
533
}

534

535
void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
536
{
537
  int memtype  = MEMTYPE_DOUBLE;
538
  int vlistID1 = streamptr1->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
539
540
541
542
  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;
543
  int gridID   = vlistInqVarGrid(vlistID1, ivarID);
544
  int datasize = gridInqSize(gridID);
545
  int datatype = vlistInqVarDatatype(vlistID1, ivarID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
546

547
548
549
550
551
552
553
  if ( datatype == DATATYPE_FLT32 ) memtype = MEMTYPE_FLOAT;

  void *data = NULL;
  if ( memtype == MEMTYPE_DOUBLE )
    data = Malloc((size_t)datasize*sizeof(double));
  else
    data = Malloc((size_t)datasize*sizeof(float));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
554

555
  int nmiss;
556
  cdf_read_record(streamptr1, memtype, data, &nmiss);
557
  cdf_write_record(streamptr2, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
558

559
  Free(data);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
560
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
561

Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
/* not used
563
int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
564
565
566
{
  int tsID, recID;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
567
568
569
  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
570

571
  if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
572
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
573
      streamptr->tsteps[0].curRecID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
574
575
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
576
577
  *varID   = streamptr->tsteps[0].records[recID].varID;
  *levelID = streamptr->tsteps[0].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
578

Uwe Schulzweida's avatar
Uwe Schulzweida committed
579
580
  streamptr->record->varID   = *varID;
  streamptr->record->levelID = *levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
581
582

  if ( CDI_Debug )
583
    Message("recID = %d  varID = %d  levelID = %d", recID, *varID, *levelID);
584

Uwe Schulzweida's avatar
Uwe Schulzweida committed
585
586
587
  return (recID+1);
}
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
588

Uwe Schulzweida's avatar
Uwe Schulzweida committed
589

590
void cdfDefRecord(stream_t *streamptr)
591
{
Thomas Jahns's avatar
Thomas Jahns committed
592
  (void)streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
593
594
}

595
#if defined(NC_SZIP_NN_OPTION_MASK)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
596
597
598
599
600
static
void cdfDefVarSzip(int ncid, int ncvarid)
{
  int retval;
  /* Set options_mask and bits_per_pixel. */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
601
  int options_mask = NC_SZIP_NN_OPTION_MASK;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
602
603
604
605
606
  int bits_per_pixel = 16;

  if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
    {
      if ( retval == NC_EINVAL )
607
608
609
610
611
612
        {
          static int lwarn = TRUE;

          if ( lwarn )
            {
              lwarn = FALSE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
613
              Warning("NetCDF4/Szip compression not compiled in!");
Deike Kleberg's avatar
Deike Kleberg committed
614
            }
615
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
616
      else
617
        Error("nc_def_var_szip failed, status = %d", retval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
618
    }
619
620
621
}
#endif

622
static
623
void cdfDefTimeValue(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
624
{
625
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
626
627

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
632
  if ( streamptr->ncmode == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
633
634
    {
      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
635
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
636
637
    }

638
  size_t index = (size_t)tsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
639

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

643
  int ncvarid = streamptr->basetime.ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
644
645
646
647
648
649
  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
650
      ncvarid = streamptr->basetime.ncvarboundsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
651

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
656
      timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
657
      start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
658
659
      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
    }
660
661
662
663
664
665
666
667

  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
668
669
670
671
672
  /*
printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
  */
}

673
674
675
676
677
678
679
680
681
682
683
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
684
685
  if ( nc_inq_dimid(fileID, BNDS_NAME, &dims[1]) != NC_NOERR )
    cdf_def_dim(fileID, BNDS_NAME, 2, &dims[1]);
686
687
688

  if ( taxis->climatology )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
689
690
      strcpy(tmpstr, "climatology_");
      strcat(tmpstr, BNDS_NAME);
691
692
693
694
695
696
697
      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
698
699
      strcat(tmpstr, "_");
      strcat(tmpstr, BNDS_NAME);
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
      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
    {
724
      int timeunit = taxis->unit;
725
      if ( timeunit == -1 ) timeunit = TUNIT_HOUR;
726
727
      int rdate    = taxis->rdate;
      int rtime    = taxis->rtime;
728
729
730
731
732
733
      if ( rdate == -1 )
        {
          rdate  = taxis->vdate;
          rtime  = taxis->vtime;
        }

734
      int year, month, day, hour, minute, second;
735
736
737
      cdiDecodeDate(rdate, &year, &month, &day);
      cdiDecodeTime(rtime, &hour, &minute, &second);

738
739
      if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
      if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
740
741
742
743
      if ( timeunit == TUNIT_3HOURS  ||
	   timeunit == TUNIT_6HOURS  ||
	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

744
      sprintf(unitstr, "%s since %d-%d-%d %02d:%02d:%02d",
745
746
747
              tunitNamePtr(timeunit), year, month, day, hour, minute, second);
    }
}
748
749
750
751
752
753
754
755

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

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

756
757
  if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
  if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
758
759
760
761
762
763
  if ( timeunit == TUNIT_3HOURS  ||
       timeunit == TUNIT_6HOURS  ||
       timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;

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

765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
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);
}

785

786
void cdfDefTime(stream_t* streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
787
788
{
  int time_varid;
789
790
791
  int time_dimid;
  int time_bndsid = -1;
  char unitstr[CDI_MAX_NAME];
792
793
  char tmpstr[CDI_MAX_NAME];
  char default_name[] = "time";
794
  char* taxis_name = default_name;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
795

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

798
  int fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
799

Uwe Schulzweida's avatar
Uwe Schulzweida committed
800
801
  if ( streamptr->ncmode == 0 ) streamptr->ncmode = 1;
  if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
802

803
  taxis_t *taxis = &streamptr->tsteps[0].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
804

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

807
808
  cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &time_dimid);
  streamptr->basetime.ncdimid = time_dimid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
809

810
  cdf_def_var(fileID, taxis_name, NC_DOUBLE, 1, &time_dimid, &time_varid);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
811

812
  streamptr->basetime.ncvarid = time_varid;
Deike Kleberg's avatar
Deike Kleberg committed
813
814
815
816

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

817
818
819
  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
820
821
  if ( taxis->has_bounds )
    {
822
823
      time_bndsid = cdfDefTimeBounds(fileID, time_varid, time_dimid, taxis_name, taxis);
      streamptr->basetime.ncvarboundsid = time_bndsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
824
825
    }

826
  cdfDefTimeUnits(unitstr, &streamptr->tsteps[0].taxis, taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
827

828
  size_t len = strlen(unitstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
829
  if ( len )
830
831
    {
      cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
832
      /*
833
834
      if ( taxis->has_bounds )
        cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
835
      */
836
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
837
838
839

  if ( taxis->calendar != -1 )
    {
840
      cdfDefCalendar(fileID, time_varid, taxis->calendar);
841
      /*
842
843
      if ( taxis->has_bounds )
        cdfDefCalendar(fileID, time_bndsid, taxis->calendar);
844
      */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
846
    }

847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
  if ( taxis->type == TAXIS_FORECAST )
    {
      int leadtimeid;

      cdf_def_var(fileID, "leadtime", NC_DOUBLE, 1, &time_dimid, &leadtimeid);

      streamptr->basetime.leadtimeid = leadtimeid;

      strcpy(tmpstr, "forecast_period");
      cdf_put_att_text(fileID, leadtimeid, "standard_name", strlen(tmpstr), tmpstr);

      strcpy(tmpstr, "Time elapsed since the start of the forecast");
      cdf_put_att_text(fileID, leadtimeid, "long_name", strlen(tmpstr), tmpstr);

      cdfDefForecastTimeUnits(unitstr, taxis->fc_unit);

      len = strlen(unitstr);
      if ( len ) cdf_put_att_text(fileID, leadtimeid, "units", len, unitstr);
    }

867
868
  cdf_put_att_text(fileID, time_varid, "axis", 1, "T");

Uwe Schulzweida's avatar
Uwe Schulzweida committed
869
  if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
870
871
872
}


873
void cdfDefTimestep(stream_t *streamptr, int tsID)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
874
{
875
  int vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
876

877
  if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr);
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
878

879
  cdfDefTimeValue(streamptr, tsID);
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
880
881
882
}

static
883
void cdfDefComplex(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
884
{
885
  char axisname[] = "nc2";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
886
  int dimID = UNDEFID;
887
888
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
889

890
  int ngrids = vlistNgrids(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
891

892
  for ( int index = 0; index < ngrids; index++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
893
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
894
      if ( streamptr->xdimID[index] != UNDEFID )
895
        {
896
897
          int gridID0 = vlistGrid(vlistID, index);
          int gridtype0 = gridInqType(gridID0);
898
          if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER )
899
900
901
902
903
            {
              dimID = streamptr->xdimID[index];
              break;
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
904
905
906
907
    }

  if ( dimID == UNDEFID )
    {
908
      size_t dimlen = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
909

Uwe Schulzweida's avatar
Uwe Schulzweida committed
910
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
911
912
913
914

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

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
915
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
916
917
    }

918
  int gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
919
  streamptr->xdimID[gridindex] = dimID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
920
921
}

922

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
923
static
924
void cdfDefSP(stream_t *streamptr, int gridID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
925
926
927
928
{
  /*
  char longname[] = "Spherical harmonic coefficient";
  */
929
  char axisname[5] = "nspX";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
930
931
932
  int index, iz = 0;
  int dimID = UNDEFID;

933
934
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
935

936
  int ngrids = vlistNgrids(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
937

938
  size_t dimlen = (size_t)gridInqSize(gridID)/2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
939
940
941

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
942
      if ( streamptr->ydimID[index] != UNDEFID )
943
        {
944
945
          int gridID0 = vlistGrid(vlistID, index);
          int gridtype0 = gridInqType(gridID0);
946
947
          if ( gridtype0 == GRID_SPECTRAL )
            {
948
              size_t dimlen0 = (size_t)gridInqSize(gridID0)/2;
949
950
951
952
953
954
              if ( dimlen == dimlen0 )
                {
                  dimID = streamptr->ydimID[index];
                  break;
                }
              else
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
                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;
    }

973
  int gridindex = vlistGridIndex(vlistID, gridID);
974
975
976
  streamptr->ydimID[gridindex] = dimID;
}

977

978
static
979
void cdfDefFC(stream_t *streamptr, int gridID)
980
981
982
983
984
{
  char axisname[5] = "nfcX";
  int index, iz = 0;
  int dimID = UNDEFID;

985
986
  int vlistID = streamptr->vlistID;
  int fileID  = streamptr->fileID;
987

988
  int ngrids = vlistNgrids(vlistID);
Deike Kleberg's avatar