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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
5

Uwe Schulzweida's avatar
Uwe Schulzweida committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <float.h>

#include "dmemory.h"

#include "cdi.h"
#include "basetime.h"
#include "util.h"  /* gaussaw */
#include "stream_int.h"
#include "stream_cdf.h"
#include "cdf_int.h"
#include "varscan.h"
#include "vlist.h"


#if  defined  (HAVE_LIBNETCDF)
#  include "netcdf.h"
#endif

#undef  UNDEFID
#define UNDEFID  CDI_UNDEFID


void cdfDefGlobalAtts(int streamID);
void cdfDefLocalAtts(int streamID);

#define  MAXNAMELEN  256

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

typedef struct {
  int     ncvarid;
  int     dimtype;
  size_t  len;
  char    name[MAXNAMELEN];
}
NCDIM;

typedef struct {
51
  int      ignore;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
52
53
54
55
56
57
58
  int      isvar;
  int      islon;
  int      islat;
  int      islev;
  int      warn;
  int      timeID;
  int      code;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
59
  int      tabnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
60
61
62
63
64
65
66
67
68
69
70
71
  int      bounds;
  int      gridID;
  int      zaxisID;
  int      gridtype;
  int      zaxistype;
  int      xdim;
  int      ydim;
  int      zdim;
  int      xvarid;
  int      yvarid;
  int      zvarid;
  int      tvarid;
72
73
  int      ncoordvars;
  int      coordvarids[4];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
74
75
76
77
78
79
80
81
82
83
84
  int      cellarea;
  int      calendar;
  int      tableID;
  int      truncation;
  int      defmiss;
  int      xtype;
  int      ndims;
  int      gmapid;
  int      positive;
  int      dimids[8];
  int      dimtype[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
85
86
  int      natts;
  int     *atts;
87
  int      deflate;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
88
89
90
91
92
93
94
95
96
97
98
99
  size_t   vlen;
  double  *vdata;
  double   missval;
  double   addoffset;
  double   scalefactor;
  char     name[MAXNAMELEN];
  char     longname[MAXNAMELEN];
  char     stdname[MAXNAMELEN];
  char     units[MAXNAMELEN];
}
NCVAR;

100
101
102
103
static
int get_timeunit(int len, char *ptu)
{
  int timeunit = -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  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;
    }

  return (timeunit);
}

static
int isTimeUnits(const char *timeunits)
{
  static char func[] = "isTimeUnits";
  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 )
	{
	  while ( isspace(*ptu) ) ptu++;
	  
	  if ( memcmp(ptu, "as", 2) == 0 )
	    timetype = TAXIS_ABSOLUTE;
	  else if ( memcmp(ptu, "since", 5) == 0 )
	    timetype = TAXIS_RELATIVE;

	  if ( timetype != -1 ) status = TRUE;
	}
    }

  free(tu);

  return (status);
}

static
int splitBasetime(const char *timeunits, TAXIS *taxis)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
161
162
{
  static char func[] = "splitBasetime";
163
  int len, i;
164
  char *ptu, *tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
165
166
167
168
  int year, month, day;
  int hour = 0, minute = 0, second = 0;
  int timetype = TAXIS_ABSOLUTE;
  int rdate = -1, rtime = -1;
169
  int timeunit;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
170

Uwe Schulzweida's avatar
Uwe Schulzweida committed
171
  len = (int) strlen(timeunits);
172
173
174
  tu = (char *) malloc((len+1)*sizeof(char));
  memcpy(tu, timeunits, (len+1)*sizeof(char));
  ptu = tu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
175

176
177
  for ( i = 0; i < len; i++ ) ptu[i] = tolower((int) ptu[i]);

178
179
  timeunit = get_timeunit(len, ptu);
  if ( timeunit == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
180
    {
181
      Message(func, "Unsupported TIMEUNIT: %s!", timeunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
182
183
184
185
186
187
      return (1);
    }

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

190
      if ( memcmp(ptu, "as", 2) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
191
	timetype = TAXIS_ABSOLUTE;
192
      else if ( memcmp(ptu, "since", 5) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
193
194
195
196
197
	timetype = TAXIS_RELATIVE;

      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
      if ( *ptu )
	{
198
	  while ( isspace(*ptu) ) ptu++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
199
200
201

	  if ( timetype == TAXIS_ABSOLUTE )
	    {
202
	      if ( memcmp(ptu, "%y%m%d.%f", 9) != 0 && timeunit == TUNIT_DAY )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
203
204
205
206
		{
		  Message(func, "Unsupported format %s for TIMEUNIT day!", ptu);
		  timeunit = -1;
		}
207
	      else if ( memcmp(ptu, "%y%m.%f", 7) != 0 && timeunit == TUNIT_MONTH )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
208
209
210
211
212
213
214
215
		{
		  Message(func, "Unsupported format %s for TIMEUNIT month!", ptu);
		  timeunit = -1;
		}
	    }
	  else if ( timetype == TAXIS_RELATIVE )
	    {
	      year = atoi(ptu);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
216
	      if ( year < 0 ) ptu++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
	      while ( isdigit((int) *ptu) ) ptu++;
	      month = atoi(++ptu);
	      while ( isdigit((int) *ptu) ) ptu++;
	      day = atoi(++ptu);
	      while ( isdigit((int) *ptu) ) ptu++;

	      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);
240
			  /*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
241
242
			  if ( second != 0 )
			    Message(func, "Seconds not supported in time units!");
243
			  */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
244
245
246
247
			}
		    }
		}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
248
249
	      rdate = cdiEncodeDate(year, month, day);
	      rtime = cdiEncodeTime(hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
250
251
	      (*taxis).rdate = rdate;
	      (*taxis).rtime = rtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
252
253
254

	      if ( CDI_Debug )
		Message(func, "rdate = %d  rtime = %d", rdate, rtime);	      
Uwe Schulzweida's avatar
Uwe Schulzweida committed
255
256
257
258
259
260
261
	    }
	}
    }

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

262
263
  free(tu);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
264
265
266
267
268
269
270
271
  if ( CDI_Debug )
    Message(func, "timetype = %d  unit = %d", timetype, timeunit);

  return (0);
}


#if  defined  (HAVE_LIBNETCDF)
272
273
static
void cdfGetAttInt(int fileID, int ncvarid, char *attname, int attlen, int *attint)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
274
275
{
  static char func[] = "cdfGetAttInt";
276
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
277
278
  int *pintatt;

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

281
282
  if ( (int)nc_attlen > attlen )
    pintatt = (int *) malloc(nc_attlen*sizeof(int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
283
  else
284
    pintatt = attint;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
285
286
287

  cdf_get_att_int(fileID, ncvarid, attname, pintatt);

288
289
290
291
292
  if ( (int)nc_attlen > attlen )
    {
      memcpy(attint, pintatt, attlen*sizeof(int));
      free(pintatt);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
293
294
295
296
}
#endif

#if  defined  (HAVE_LIBNETCDF)
297
static void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
298
{
299
300
  static char func[] = "cdfGetAttDouble";
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
301
302
  double *pdoubleatt;

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

305
306
  if ( (int)nc_attlen > attlen )
    pdoubleatt = (double *) malloc(nc_attlen*sizeof(double));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
307
  else
308
    pdoubleatt = attdouble;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
309
310
311

  cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt);

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

#if  defined  (HAVE_LIBNETCDF)
321
322
static
void cdfGetAttText(int fileID, int ncvarid, char *attname, int attlen, char *atttext)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
323
{
324
  size_t nc_attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
325
326
  char attbuf[65636];

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

329
  if ( nc_attlen < sizeof(attbuf) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
330
331
332
    {
      cdf_get_att_text(fileID, ncvarid, attname, attbuf);

333
      attbuf[nc_attlen++] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
334

335
336
      if ( (int) nc_attlen > attlen ) nc_attlen = attlen;
      memcpy(atttext, attbuf, nc_attlen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
337
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
338
339
340
341
  else
    {
      atttext[0] = 0;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
342
343
344
345
346
347
348
349
}
#endif

#if  defined  (HAVE_LIBNETCDF)
int cdfInqDatatype(int xtype)
{
  int datatype;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
350
351
352
353
354
355
  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;
  else if ( xtype == NC_DOUBLE )  datatype = DATATYPE_FLT64;
  else                            datatype = DATATYPE_FLT32;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
356
357
358
359
360
361
362
363
364
365

  return (datatype);
}
#endif

#if  defined  (HAVE_LIBNETCDF)
int cdfDefDatatype(int datatype)
{
  int xtype;

366
  if      ( datatype == DATATYPE_INT8  )  xtype = NC_BYTE;
367
  else if ( datatype == DATATYPE_UINT8 )  xtype = NC_SHORT;
368
  else if ( datatype == DATATYPE_INT16 )  xtype = NC_SHORT;
369
  else if ( datatype == DATATYPE_UINT16 ) xtype = NC_INT;
370
  else if ( datatype == DATATYPE_INT32 )  xtype = NC_INT;
371
  else if ( datatype == DATATYPE_UINT32 ) xtype = NC_INT;
372
  else if ( datatype == DATATYPE_FLT64 )  xtype = NC_DOUBLE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
373
374
375
376
377
378
379
  else                                    xtype = NC_FLOAT;

  return (xtype);
}
#endif


Uwe Schulzweida's avatar
Uwe Schulzweida committed
380
381
382
#if  defined  (HAVE_LIBNETCDF)
void defineAttributes(int vlistID, int varID, int fileID, int ncvarID)
{
383
  static char func[] = "defineAttributes";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
384
  int natts, iatt;
385
  int atttype, attlen;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
386
  size_t len;
387
388
  char attname[1024];
  char atttxt[8192];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
389
390
391
392
393

  vlistInqNatts(vlistID, varID, &natts);

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

396
      if ( atttype == DATATYPE_TXT )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
397
	{
398
	  vlistInqAttTxt(vlistID, varID, attname, sizeof(atttxt), atttxt);
399
400
	  len = attlen;
	  cdf_put_att_text(fileID, ncvarID, attname, len, atttxt);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
401
	}
402
      else if ( atttype == DATATYPE_INT )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
403
	{
404
405
406
407
408
409
	  int *attint;
	  attint = (int *) malloc(attlen*sizeof(int));
	  vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]);
	  len = attlen;
	  cdf_put_att_int(fileID, ncvarID, attname, NC_INT, len, attint);
	  free(attint);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
410
	}
411
      else if ( atttype == DATATYPE_FLT )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
412
	{
413
414
415
416
417
418
	  double *attflt;
	  attflt = (double *) malloc(attlen*sizeof(double));
	  vlistInqAttFlt(vlistID, varID, attname, attlen, attflt);
	  len = attlen;
	  cdf_put_att_double(fileID, ncvarID, attname, NC_DOUBLE, len, attflt);
	  free(attflt);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
419
420
421
422
423
424
	}
    }
}
#endif


Uwe Schulzweida's avatar
Uwe Schulzweida committed
425
int cdfCopyRecord(int streamID2, int streamID1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
426
427
428
{
  static char func[] = "cdfCopyRecord";
  double *data;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
429
  int datasize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
430
  int tsID1, tsID2, recID1, recID2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
431
432
433
  int ivarID, gridID;
  int nmiss;
  int ierr = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
434
  int vlistID1, vlistID2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
435
436
  stream_t *streamptr1;
  stream_t *streamptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
437

Uwe Schulzweida's avatar
Uwe Schulzweida committed
438
439
  streamptr1 = stream_to_pointer(streamID1);
  streamptr2 = stream_to_pointer(streamID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
440

Uwe Schulzweida's avatar
Uwe Schulzweida committed
441
442
  stream_check_ptr(func, streamptr1);
  stream_check_ptr(func, streamptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
443

Uwe Schulzweida's avatar
Uwe Schulzweida committed
444
445
  vlistID1 = streamptr1->vlistID;
  vlistID2 = streamptr2->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
446

Uwe Schulzweida's avatar
Uwe Schulzweida committed
447
448
  tsID1 = streamptr1->curTsID;
  tsID2 = streamptr2->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
449

Uwe Schulzweida's avatar
Uwe Schulzweida committed
450
451
  recID1 = streamptr1->tsteps[tsID1].curRecID;
  recID2 = streamptr2->tsteps[tsID2].curRecID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
452

Uwe Schulzweida's avatar
Uwe Schulzweida committed
453
454
455
  ivarID = streamptr1->tsteps[tsID1].records[recID1].varID;

  gridID = vlistInqVarGrid(vlistID1, ivarID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
456
457
458
459
460
461
462

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
463
464
  streamReadRecord(streamID1, data, &nmiss);
  streamWriteRecord(streamID2, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
465
466
467
468
469

  free(data);

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
471
472
473
474
475
/* not used
int cdfInqRecord(int streamID, int *varID, int *levelID)
{
  static char func[] = "cdfInqRecord";
  int tsID, recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
476
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
477
478

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
480
  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
481

Uwe Schulzweida's avatar
Uwe Schulzweida committed
482
483
484
  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
485

Uwe Schulzweida's avatar
Uwe Schulzweida committed
486
487
  if ( streamptr->tsteps[0].curRecID >= 
       streamptr->tsteps[0].nrecs )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
488
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
489
      streamptr->tsteps[0].curRecID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
490
491
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
493
  *varID   = streamptr->tsteps[0].records[recID].varID;
  *levelID = streamptr->tsteps[0].records[recID].levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
494

Uwe Schulzweida's avatar
Uwe Schulzweida committed
495
496
  streamptr->record->varID   = *varID;
  streamptr->record->levelID = *levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
497
498
499
500
501
502
503
504
505
506
507

  if ( CDI_Debug )
    Message(func, "recID = %d  varID = %d  levelID = %d", recID, *varID, *levelID);
  
  return (recID+1);
}
*/
int cdfDefRecord(int streamID)
{
  static char func[] = "cdfDefRecord";
  int ierr = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
509
510

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511
512
513
514

  if ( CDI_Debug )
    Message(func, "streamID = %d", streamID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
515
  stream_check_ptr(func, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
516
517
518
519

  return (ierr);
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
520
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
521
522
523
524
525
526
527
528
void cdfWriteGridTraj(int streamID, int gridID)
{
#if  defined  (HAVE_LIBNETCDF)
  int tsID, fileID;
  int lonID, latID, gridindex;
  size_t index;
  double xlon, xlat;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
529
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
530
531

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
532
533
534
535
536

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

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
537
538
  lonID = streamptr->xdimID[gridindex];
  latID = streamptr->ydimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
539
540
541

  xlon = gridInqXval(gridID, 0);
  xlat = gridInqYval(gridID, 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
  tsID = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
543
544
545
546
547
548
549
  index = tsID;

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

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
550
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
551
552
553
554
555
556
557
558
void cdfReadGridTraj(int streamID, int gridID)
{
#if  defined  (HAVE_LIBNETCDF)
  int tsID, fileID;
  int lonID, latID, gridindex;
  size_t index;
  double xlon, xlat;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
559
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
560
561

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
563
564
565
566

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
570
  tsID = streamptr->curTsID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
571
572
573
574
575
576
577
578
579
580
581
  index = tsID;

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

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


582
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
583
static
584
585
586
587
588
589
590
591
592
593
594
595
596
void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level)
{
  static char func[] = "cdfDefVarDeflate";
#if  defined  (NC_NETCDF4)
  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)))
    {
597
      Error(func, "nc_def_var_deflate failed, status = %d", retval);
598
599
600
601
602
603
604
    }
#else
  static int lwarn = TRUE;

  if ( lwarn )
    {
      lwarn = FALSE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
605
606
607
608
609
610
611
      Warning(func, "Deflate compression failed, netCDF4 not available!");
    }
#endif
}
#endif

#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
612

Uwe Schulzweida's avatar
Uwe Schulzweida committed
613
614
615
616
617
618
619
static
void cdfDefVarSzip(int ncid, int ncvarid)
{
  static char func[] = "cdfDefVarSzip";
#if  defined  (NC_NETCDF4) && defined (NC_SZIP_NN_OPTION_MASK)
  int retval;
  /* Set options_mask and bits_per_pixel. */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
620
  int options_mask = NC_SZIP_NN_OPTION_MASK;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
  int bits_per_pixel = 16;

  if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel)))
    {
      if ( retval == NC_EINVAL )
	{
	  static int lwarn = TRUE;

	  if ( lwarn )
	    {
	      lwarn = FALSE;
	      Warning(func, "netCDF4/Szip compression not compiled in!");
	    }	  
	}
      else
	Error(func, "nc_def_var_szip failed, status = %d", retval);
    }
#else
  static int lwarn = TRUE;

  if ( lwarn )
    {
      lwarn = FALSE;
      Warning(func, "netCDF4/Szip compression not available!");
645
646
647
648
649
    }
#endif
}
#endif

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
650
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
651
652
653
void cdfDefMissval(int streamID, int varID, int dtype)
{
#if  defined  (HAVE_LIBNETCDF)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
654
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
655
656
657
658

  streamptr = stream_to_pointer(streamID);

  if ( streamptr->vars[varID].defmiss == FALSE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
659
660
661
662
663
664
665
666
667
    {
      int fileID;
      int ncvarid;
      double missval;
      int vlistID;
      int xtype;

      vlistID = streamInqVlist(streamID);
      fileID  = streamInqFileID(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
668
      ncvarid = streamptr->vars[varID].ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
669
      missval = vlistInqVarMissval(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
670
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
671
672
673
674

      xtype = cdfDefDatatype(dtype);

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
681
      streamptr->vars[varID].defmiss = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
682
683
684
685
    }
#endif
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
686

687
void cdfWriteRecord(int streamID, const double *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
688
689
690
691
692
{
#if  defined  (HAVE_LIBNETCDF)
  static char func[] = "cdfWriteRecord";
  int varID;
  int levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
693
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
694
695

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
697
698
  varID   = streamptr->record->varID;
  levelID = streamptr->record->levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
699
700
701
702
703
704
705
706

  if ( CDI_Debug )
    Message(func, "streamID = %d  varID = %d", streamID, varID);

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

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
707

Uwe Schulzweida's avatar
Uwe Schulzweida committed
708
709
710
711
712
int cdfReadRecord(int streamID, double *data, int *nmiss)
{
  static char func[] = "cdfReadRecord";
  int ierr = 0;
  int levelID, varID, tsID, recID, vrecID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
713
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
714
715

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
716
717
718

  if ( CDI_Debug ) Message(func, "streamID = %d", streamID);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
719
720
721
722
723
  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
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

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

  return (ierr);
}


void cdfDefTimeValue(int streamID, int tsID)
{
#if  defined  (HAVE_LIBNETCDF)
  static char func[] = "cdfDefTimeValue";
  int fileID;
  double timevalue;
  int ncvarid;
  size_t index;
  TAXIS *taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
740
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
741
742

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
743
744
745
746
747
748

  fileID = streamInqFileID(streamID);

  if ( CDI_Debug )
    Message(func, "streamID = %d, fileID = %d", streamID, fileID);

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
751
  if ( streamptr->ncmode == 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
752
753
    {
      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
754
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
755
756
757
758
    }

  index = tsID;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
762
  ncvarid = streamptr->basetime.ncvarid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
763
764
765
766
767
768
  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
769
      ncvarid = streamptr->basetime.ncvarboundsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
770

Uwe Schulzweida's avatar
Uwe Schulzweida committed
771
      timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
772
773
774
      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
775
      timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
776
777
778
779
780
781
782
783
784
      start[0] = tsID; count[0] = 1; start[1] = 1; count[1] = 1;
      cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue);
    }
  /*
printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
  */
#endif
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
785
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
786
787
788
789
790
791
792
void cdfDefTime(int streamID)
{
#if  defined  (HAVE_LIBNETCDF)
  int fileID;
  int time_varid;
  int time_bndsid;
  int dims[2];
793
  int year, month, day, hour, minute, second;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
794
795
796
797
  char unitstr[80];
  char calstr[80];
  size_t len;
  TAXIS *taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
798
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
799
800

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
802
  if ( streamptr->basetime.ncvarid != UNDEFID ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
803
804
805

  fileID = streamInqFileID(streamID);

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

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
815
  streamptr->basetime.ncvarid = time_varid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
816

Uwe Schulzweida's avatar
Uwe Schulzweida committed
817
  taxis = &streamptr->tsteps[0].taxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
818
819
820
821
822
823
824
825

  if ( taxis->has_bounds )
    {
      /* fprintf(stderr, "time has bounds\n"); */

      cdf_def_dim(fileID, "tbnds", 2, &dims[1]);
      cdf_def_var(fileID, "time_bnds", NC_DOUBLE, 2, dims, &time_bndsid);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
826
      streamptr->basetime.ncvarboundsid = time_bndsid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
827
828
829
830
831

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

  unitstr[0] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
832
  if ( streamptr->tsteps[0].taxis.type == TAXIS_ABSOLUTE )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
833
    {
834
835
836
      if ( streamptr->tsteps[0].taxis.unit == TUNIT_YEAR )
	sprintf(unitstr, "year as %s", "%Y.%f");
      else if ( streamptr->tsteps[0].taxis.unit == TUNIT_MONTH )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
	sprintf(unitstr, "month as %s", "%Y%m.%f");
      else
	sprintf(unitstr, "day as %s", "%Y%m%d.%f");
    }
  else
    {
      int rdate, rtime;
      int timeunit;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
855
856
      cdiDecodeDate(rdate, &year, &month, &day);
      cdiDecodeTime(rtime, &hour, &minute, &second);
857

858
      if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE;
859
860
      sprintf(unitstr, "%s since %d-%02d-%02d %02d:%02d:%02d",
	      tunitNamePtr(timeunit), year, month, day, hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
861
862
863
864
865
866
867
868
869
870
871
872
873
874
    }

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

  if ( taxis->has_bounds )
    if ( len )
      cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);

  if ( taxis->calendar != -1 )
    {
      calstr[0] = 0;

875
876
877
      if      ( taxis->calendar == CALENDAR_STANDARD )  strcpy(calstr, "standard");
      else if ( taxis->calendar == CALENDAR_PROLEPTIC ) strcpy(calstr, "proleptic_gregorian");
      else if ( taxis->calendar == CALENDAR_NONE )      strcpy(calstr, "none");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
878
879
880
881
882
883
      else if ( taxis->calendar == CALENDAR_360DAYS )   strcpy(calstr, "360_day");
      else if ( taxis->calendar == CALENDAR_365DAYS )   strcpy(calstr, "365_day");
      else if ( taxis->calendar == CALENDAR_366DAYS )   strcpy(calstr, "366_day");

      len = strlen(calstr);
      if ( len )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
884
885
	{
	  cdf_put_att_text(fileID, time_varid, "calendar", len, calstr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
886

Uwe Schulzweida's avatar
Uwe Schulzweida committed
887
888
889
	  if ( taxis->has_bounds )
	    cdf_put_att_text(fileID, time_bndsid, "calendar", len, calstr);
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
890
891
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
892
  if ( streamptr->ncmode == 2 ) cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
893
894
895
896
#endif
}


Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
897
898
899
900
901
902
903
904
905
906
907
908
void cdfDefTimestep(int streamID, int tsID)
{
  int vlistID;

  vlistID = streamInqVlist(streamID);

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

  cdfDefTimeValue(streamID, tsID);
}

static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
909
910
911
912
913
914
915
916
917
918
919
void cdfDefComplex(int streamID, int gridID)
{
#if  defined  (HAVE_LIBNETCDF)
  char axisname[] = "complex";
  int index;
  int dimID = UNDEFID;
  int gridID0, gridtype0, gridindex;
  int ngrids;
  int fileID;
  int dimlen;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
920
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
921
922

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
923
924
925
926
927
928
929
930

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

  ngrids = vlistNgrids(vlistID);

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
931
      if ( streamptr->xdimID[index] != UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
932
933
934
935
936
	{
	  gridID0 = vlistGrid(vlistID, index);
	  gridtype0 = gridInqType(gridID0);
	  if ( gridtype0 == GRID_SPECTRAL )
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
937
	      dimID = streamptr->xdimID[index];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
938
939
940
941
942
943
944
945
946
	      break;
	    }
	}
    }

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

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

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

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
952
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
953
954
955
    }

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
956
  streamptr->xdimID[gridindex] = dimID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
957
958
959
960

#endif
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
961
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
962
963
964
965
966
967
968
969
970
971
972
973
974
975
void cdfDefSpc(int streamID, int gridID)
{
#if  defined  (HAVE_LIBNETCDF)
  /*
  char longname[] = "Spherical harmonic coefficient";
  */
  char axisname[5] = "spcX";
  int index, iz = 0;
  int gridID0, gridtype0, gridindex;
  int dimID = UNDEFID;
  int ngrids;
  int fileID;
  int dimlen, dimlen0;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
976
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
977
978

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
979
980
981
982
983
984
985
986
987
988

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

  ngrids = vlistNgrids(vlistID);

  dimlen = gridInqSize(gridID)/2;

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
989
      if ( streamptr->ydimID[index] != UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
990
991
992
993
994
995
996
997
	{
	  gridID0 = vlistGrid(vlistID, index);
	  gridtype0 = gridInqType(gridID0);
	  if ( gridtype0 == GRID_SPECTRAL )
	    {
	      dimlen0 = gridInqSize(gridID0)/2;
	      if ( dimlen == dimlen0 )
		{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
998
		  dimID = streamptr->ydimID[index];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
		  break;
		}
	      else
		iz++;	
	    }
	}
    }

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

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

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

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

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1021
  streamptr->ydimID[gridindex] = dimID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1022
1023
1024
1025

#endif
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
1026
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
void cdfDefTrajLon(int streamID, int gridID)
{
#if  defined  (HAVE_LIBNETCDF)
  static char func[] = "cdfDefTrajLon";
  char units[256];
  char longname[256];
  char stdname[256];
  char axisname[256];
  int gridtype, gridindex;
  int dimID = UNDEFID;
  int fileID;
  int dimlen;
  size_t len;
  int ncvarid;
  int vlistID;
  int xtype = NC_DOUBLE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1043
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1044
1045

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

1047
  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1048
1049
1050
1051
1052
1053
1054
1055
1056

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

  gridtype = gridInqType(gridID);
  dimlen = gridInqXsize(gridID);
  if ( dimlen != 1 ) Error(func, "Xsize isn't 1 for %s grid!", gridNamePtr(gridtype));

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1057
  ncvarid = streamptr->xdimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1058
1059
1060
1061
1062
1063
1064
1065

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1068
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078

      cdf_def_var(fileID, axisname, (nc_type) xtype, 1, &dimID, &ncvarid);
      if ( (len = strlen(longname)) )
	cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
      if ( (len = strlen(units)) )
	cdf_put_att_text(fileID, ncvarid, "units", len, units);
      if ( (len = strlen(stdname)) )
	cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1079
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1080
1081
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1082
  streamptr->xdimID[gridindex] = ncvarid; /* var ID for trajectory !!! */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1083
1084
1085
1086

#endif
}

Uwe Schulzweida's avatar
cleanup    
Uwe Schulzweida committed
1087
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
void cdfDefTrajLat(int streamID, int gridID)
{
#if  defined  (HAVE_LIBNETCDF)
  static char func[] = "cdfDefTrajLat";
  char units[] = "degrees_north";
  char longname[] = "latitude";
  char stdname[] = "latitude";
  char axisname[] = "tlat";
  int gridtype, gridindex;
  int dimID = UNDEFID;
  int fileID;
  int dimlen;
  size_t len;
  int ncvarid;
  int vlistID;
  int xtype = NC_DOUBLE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1104
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1105
1106

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

1108
  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1109
1110
1111
1112
1113
1114
1115
1116
1117

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

  gridtype = gridInqType(gridID);
  dimlen = gridInqYsize(gridID);
  if ( dimlen != 1 ) Error(func, "Ysize isn't 1 for %s grid!", gridNamePtr(gridtype));

  gridindex = vlistGridIndex(vlistID, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1118
  ncvarid = streamptr->ydimID[gridindex];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1119
1120
1121
1122
1123
1124
1125
1126

  gridInqYname(gridID, axisname);
  gridInqYlongname(gridID, longname);
  gridInqYstdname(gridID, stdname);
  gridInqYunits(gridID, units);

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1129
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139

      cdf_def_var(fileID, axisname, (nc_type) xtype, 1, &dimID, &ncvarid);
      if ( (len = strlen(longname)) )
	cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
      if ( (len = strlen(units)) )
	cdf_put_att_text(fileID, ncvarid, "units", len, units);
      if ( (len = strlen(stdname)) )
	cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1143
  streamptr->ydimID[gridindex] = ncvarid; /* var ID for trajectory !!! */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156

#endif
}


void cdfDefXaxis(int streamID, int gridID)
{
#if  defined  (HAVE_LIBNETCDF)
  static char func[] = "cdfDefXaxis";
  char units[256];
  char longname[256];
  char stdname[256];
  char axisname[256];
1157
1158
  int index, iz = 0;
  /*  int index2; */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1159
1160
1161
1162
1163
1164
1165
  int gridID0, gridtype0, gridindex;
  int dimID = UNDEFID;
  int dimIDs[2];
  int ngrids;
  int fileID;
  int dimlen, dimlen0;
  size_t len;
1166
  int ncdimid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1167
1168
1169
1170
  int ncvarid = UNDEFID, ncbvarid = UNDEFID;
  int nvertex = 2, nvdimID = -1;
  int vlistID;
  int xtype = NC_DOUBLE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1171
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1172
1173

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

1175
  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193

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

  ngrids = vlistNgrids(vlistID);

  dimlen = gridInqXsize(gridID);
  gridindex = vlistGridIndex(vlistID, gridID);

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

  if ( axisname[0] == 0 ) Error(func, "axis name undefined!\n");

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1194
      if ( streamptr->xdimID[index] != UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
	{
	  gridID0 = vlistGrid(vlistID, index);
	  gridtype0 = gridInqType(gridID0);
	  if ( gridtype0 == GRID_GAUSSIAN    ||
	       gridtype0 == GRID_LONLAT      ||
	       gridtype0 == GRID_CURVILINEAR ||
	       gridtype0 == GRID_GENERIC )
	    {
	      dimlen0 = gridInqXsize(gridID0);
	      if ( dimlen == dimlen0 )
1205
1206
		if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) &&
		     IS_EQUAL(gridInqXval(gridID0, dimlen-1), gridInqXval(gridID, dimlen-1)) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1207
		  {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1208
		    dimID = streamptr->xdimID[index];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1209
1210
		    break;
		  }
1211
	      /*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1212
	      for ( index2 = 0; index2 < index; index2++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1213
		if ( streamptr->xdimID[index] == streamptr->xdimID[index2] )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1214
1215
		  break;
	      if ( index2 == index ) iz++;
1216
	      */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1217
1218
1219
1220
1221
1222
	    }
	}
    }

  if ( dimID == UNDEFID )
    {
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
      char axisname0[256];
      char axisname2[256];
      int checkname = FALSE;
      int status;

      /* check that the name is not allready defined */
      checkname = TRUE;
      iz = 0;

      while ( checkname ) 
	{
	  strcpy(axisname2, axisname);
	  if ( iz ) sprintf(&axisname2[strlen(axisname2)], "_%d", iz+1);

1237
1238
	  //status = nc_inq_varid(fileID, axisname2, &ncvarid);
	  status = nc_inq_dimid(fileID, axisname2, &ncdimid);
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
	  if ( status != NC_NOERR )
	    {
	      if ( iz )
		{
		  /* check that the name does not exist for other grids */
		  for ( index = 0; index < ngrids; index++ )
		    {
		      gridID0 = vlistGrid(vlistID, index);
		      if ( gridID != gridID0 )
			{
			  gridInqXname(gridID0, axisname0);
			  if ( strcmp(axisname0, axisname2) == 0 ) break;
			}
		    }
		  if ( index == ngrids ) checkname = FALSE;
		}
	      else
		{
		  checkname = FALSE;
		}
	    }

	  if ( checkname ) iz++;

	  if ( iz > 99 ) break;
	}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1266
1267
      if ( iz ) sprintf(&axisname[strlen(axisname)], "_%d", iz+1);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1268
      if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303

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

      if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) )
	cdf_def_dim(fileID, "nv", nvertex, &nvdimID);

      if ( gridInqXvalsPtr(gridID) )
	{
	  cdf_def_var(fileID, axisname, (nc_type) xtype, 1, &dimID, &ncvarid);
	  if ( (len = strlen(longname)) )
	    cdf_put_att_text(fileID, ncvarid, "long_name", len, longname);
	  if ( (len = strlen(units)) )
	    cdf_put_att_text(fileID, ncvarid, "units", len, units);
	  if ( (len = strlen(stdname)) )
	    cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname);

	  if ( gridInqXboundsPtr(gridID) )
	    {
	      strcat(axisname, "_bounds");
	      dimIDs[0] = dimID;
	      dimIDs[1] = nvdimID;
	      cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid);
	      cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname);
	    }

	  /*
	  if ( gridIsRotated(gridID) )
	    {
	      double north_pole = gridInqXpole(gridID);
	      cdf_put_att_double(fileID, ncvarid, "north_pole", NC_DOUBLE, 1L, &north_pole);
	    }
	  */
	}

      cdf_enddef(fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1304
      streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1305
1306
1307
1308
1309

      if ( ncvarid  != UNDEFID ) cdf_put_var_double(fileID, ncvarid, gridInqXvalsPtr(gridID));
      if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, gridInqXboundsPtr(gridID));
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1310
  streamptr->xdimID[gridindex] = dimID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322

#endif
}

void cdfDefYaxis(int streamID, int gridID)
{
#if  defined  (HAVE_LIBNETCDF)
  static char func[] = "cdfDefYaxis";
  char units[256];
  char longname[256];
  char stdname[256];
  char axisname[256];
1323
1324
  int index, iz = 0;
  /*  int index2; */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1325
1326
1327
1328
1329
1330
1331
  int gridID0, gridtype0, gridindex;
  int dimID = UNDEFID;
  int dimIDs[2];
  int ngrids;
  int fileID;
  int dimlen, dimlen0;
  size_t len;
1332
  int ncdimid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1333
1334
1335
1336
  int ncvarid = UNDEFID, ncbvarid = UNDEFID;
  int nvdimID = -1;
  int vlistID;
  int xtype = NC_DOUBLE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1337
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1338
1339

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

1341
  if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359

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

  ngrids = vlistNgrids(vlistID);

  dimlen = gridInqYsize(gridID);
  gridindex = vlistGridIndex(vlistID, gridID);

  gridInqYname(gridID, axisname);
  gridInqYlongname(gridID, longname);
  gridInqYstdname(gridID, stdname);
  gridInqYunits(gridID, units);

  if ( axisname[0] == 0 ) Error(func, "axis name undefined!\n");

  for ( index = 0; index < ngrids; index++ )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1360
      if ( streamptr->ydimID[index] != UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
	{
	  gridID0 = vlistGrid(vlistID, index);
	  gridtype0 = gridInqType(gridID0);
	  if ( gridtype0 == GRID_GAUSSIAN    ||
	       gridtype0 == GRID_LONLAT      ||
	       gridtype0 == GRID_CURVILINEAR ||
	       gridtype0 == GRID_