SCALE-RM
gtool_netcdf.c
Go to the documentation of this file.
1 #include "netcdf.h"
2 #include "gtool_file.h"
3 
4 #define RMISS -9.9999e+30
5 #define TEPS 1e-6
6 
7 static int32_t ERROR_SUPPRESS = 0;
8 
9 #define CHECK_ERROR(status) \
10  { \
11  if (status != NC_NOERR) { \
12  if ( ! ERROR_SUPPRESS ) { \
13  fprintf(stderr, "Error: at l%d in %s\n", __LINE__, __FILE__); \
14  fprintf(stderr, " %s\n", nc_strerror(status)); \
15  } \
16  return ERROR_CODE; \
17  } \
18  }
19 
20 #define NCTYPE2TYPE(nctype, type) \
21  { \
22  switch ( nctype ) { \
23  case NC_FLOAT: \
24  type = File_REAL4; \
25  break; \
26  case NC_DOUBLE: \
27  type = File_REAL8; \
28  break; \
29  case NC_SHORT: \
30  type = File_INTEGER2; \
31  break; \
32  default: \
33  fprintf(stderr, "unsuppoted data type: %d\n", xtype); \
34  return ERROR_CODE; \
35  } \
36  }
37 
38 #define TYPE2NCTYPE(type, nctype) \
39  { \
40  switch ( type ) { \
41  case File_REAL4: \
42  nctype = NC_FLOAT; \
43  break; \
44  case File_REAL8: \
45  nctype = NC_DOUBLE; \
46  break; \
47  default: \
48  fprintf(stderr, "unsuppoted data type: %d\n", xtype); \
49  return ERROR_CODE; \
50  } \
51  }
52 
53 
54 #define DEFAULT_DEFLATE_LEVEL 2
55 
56 typedef struct {
57  int ncid;
58  char time_units[File_HMID+1];
60 #ifdef NETCDF3
61  int defmode;
62 #endif
63 } fileinfo_t;
64 
65 typedef struct {
66  int ncid;
67  int dimid;
68  int varid;
69  int bndsid;
70  int count;
71  real64_t t;
72  real64_t tint;
73  char name[File_HSHORT+1];
74 } tdim_t;
75 
76 typedef struct {
77  int ncid;
78  int varid;
80  size_t *start;
81  size_t *count;
82 } varinfo_t;
83 
84 // Keep consistency with "File_nfile_max" in gtool_file.f90
85 #define FILE_MAX 512
86 // Keep consistency with "File_nvar_max" in gtool_file.f90
87 #define VAR_MAX 40960
88 
89 static fileinfo_t *files[FILE_MAX];
90 static int nfile = 0;
91 static varinfo_t *vars[VAR_MAX];
92 static int nvar = 0;
93 static tdim_t *tdims[VAR_MAX];
94 static int nt = 0;
95 
96 
97 int32_t file_open( int32_t *fid, // (out)
98  char *fname, // (in)
99  int32_t mode ) // (in)
100 {
101  int ncid;
102  int len;
103  char _fname[File_HLONG+4];
104 
105  if ( nfile >= FILE_MAX ) {
106  fprintf(stderr, "exceed max number of file limit\n");
107  return ERROR_CODE;
108  }
109 
110  len = strlen(fname);
111  strcpy(_fname, fname);
112  if (fname[len-3] != '.' || fname[len-2] != 'n' || fname[len-1] != 'c' )
113  strcat(_fname, ".nc");
114 
115  switch ( mode ) {
116  case File_FREAD:
117  CHECK_ERROR( nc_open(_fname, NC_NOWRITE, &ncid) );
118  break;
119  case File_FWRITE:
120 #ifdef NETCDF3
121  CHECK_ERROR( nc_create(_fname, NC_CLOBBER, &ncid) );
122 #else
123  CHECK_ERROR( nc_create(_fname, NC_CLOBBER|NC_NETCDF4, &ncid) );
124 #endif
125  break;
126  case File_FAPPEND:
127  CHECK_ERROR( nc_open(_fname, NC_WRITE, &ncid) );
128  break;
129  default:
130  fprintf(stderr, "invalid mode type\n");
131  return ERROR_CODE;
132  }
133 
134  files[nfile] = (fileinfo_t*) malloc(sizeof(fileinfo_t));
135  files[nfile]->ncid = ncid;
136  files[nfile]->deflate_level = DEFAULT_DEFLATE_LEVEL;
137 #ifdef NETCDF3
138  files[nfile]->defmode = 1;
139 #endif
140  *fid = nfile;
141  nfile++;
142 
143  return SUCCESS_CODE;
144 }
145 
146 int32_t file_set_option( int32_t fid, // (in)
147  char* filetype, // (in)
148  char* key, // (in)
149  char* val) // (in)
150 {
151  if ( strcmp(filetype, "netcdf") != 0 ) return SUCCESS_CODE;
152 
153  if ( strcmp(key, "deflate_level") == 0 ) {
154  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
155  files[fid]->deflate_level = atoi(val);
156  return SUCCESS_CODE;
157  } else {
158  return ERROR_CODE;
159  }
160 }
161 
162 int32_t file_get_datainfo( datainfo_t *dinfo, // (out)
163  int32_t fid, // (in)
164  char* varname, // (in)
165  int32_t step, // (in)
166  int32_t suppress)// (in)
167 {
168  int ncid, varid;
169  nc_type xtype;
170  int rank;
171  int dimids[MAX_RANK], tdim, uldims[NC_MAX_DIMS];
172  char name[File_HSHORT+1];
173  size_t size;
174  size_t idx[2];
175  int i, n;
176 
177  ERROR_SUPPRESS = suppress;
178 
179  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
180  ncid = files[fid]->ncid;
181  CHECK_ERROR( nc_inq_varid(ncid, varname, &varid) );
182 
183  // fid
184  dinfo->fid = fid;
185  // varname
186  strcpy(dinfo->varname, varname);
187  // description
188  CHECK_ERROR( nc_get_att_text(ncid, varid, "long_name", dinfo->description) );
189  // units
190  CHECK_ERROR( nc_get_att_text(ncid, varid, "units", dinfo->units) );
191  // datatype
192  CHECK_ERROR( nc_inq_vartype(ncid, varid, &xtype) );
193  NCTYPE2TYPE(xtype, dinfo->datatype);
194  // rank
195  CHECK_ERROR( nc_inq_varndims(ncid, varid, &rank) );
196  CHECK_ERROR( nc_inq_vardimid(ncid, varid, dimids) );
197 #ifdef NETCDF3
198  CHECK_ERROR( nc_inq_unlimdim(ncid, uldims) );
199  n = 1;
200 #else
201  CHECK_ERROR( nc_inq_unlimdims(ncid, &n, uldims) );
202 #endif
203  tdim = -1;
204  for ( i=0; i<n; i++ ) {
205  if ( uldims[i] == dimids[0] ) {
206  tdim = uldims[i];
207  break;
208  }
209  }
210  if (rank > MAX_RANK) {
211  fprintf(stderr, "rank exceeds limit: %d\n", rank);
212  return ERROR_CODE;
213  }
214  dinfo->rank = tdim >= 0 ? rank -1 : rank; // do not count time dimension
215  // dim_name and dim_size
216  for (i=0; i<dinfo->rank; i++) {
217  // note: C and Fortran orders are opposit
218  CHECK_ERROR( nc_inq_dim(ncid, dimids[rank-i-1], name, &size) );
219  strncpy(dinfo->dim_name+i*File_HSHORT, name, File_HSHORT);
220  dinfo->dim_size[i] = size;
221  }
222 
223  dinfo->step = step;
224  if ( tdim >= 0 ) {
225  // time_end
226  CHECK_ERROR( nc_inq_dimname(ncid, tdim, name) );
227  CHECK_ERROR( nc_inq_varid(ncid, name, &varid) );
228  idx[0] = step - 1;
229  CHECK_ERROR( nc_get_var1_double(ncid, varid, idx, &(dinfo->time_end)) );
230  // time_start
231  strcat(name, "_bnds");
232  CHECK_ERROR( nc_inq_varid(ncid, name, &varid) );
233  idx[1] = 0;
234  CHECK_ERROR( nc_get_var1_double(ncid, varid, idx, &(dinfo->time_start)) );
235  // units
236  CHECK_ERROR( nc_get_att_text(ncid, varid, "units", dinfo->time_units) );
237  } else {
238  }
239 
240  ERROR_SUPPRESS = 0;
241 
242  return SUCCESS_CODE;
243 }
244 
245 int32_t file_read_data( void *var, // (out)
246  datainfo_t *dinfo, // (in)
247  int32_t precision) // (in)
248 {
249  int ncid, varid;
250  int rank;
251  size_t *start, *count;
252  int i;
253  int status;
254 
255  if ( files[dinfo->fid] == NULL ) return ALREADY_CLOSED_CODE;
256  ncid = files[dinfo->fid]->ncid;
257  CHECK_ERROR( nc_inq_varid(ncid, dinfo->varname, &varid) );
258 
259  CHECK_ERROR( nc_inq_varndims(ncid, varid, &rank) );
260  start = (size_t*) malloc(sizeof(size_t)*rank);
261  count = (size_t*) malloc(sizeof(size_t)*rank);
262  for (i=0; i<dinfo->rank; i++) {
263  // note: C and Fortran orders are opposit
264  start[rank -i-1] = 0;
265  count[rank -i-1] = dinfo->dim_size[i];
266  }
267  if (rank > dinfo->rank) { // have time dimension
268  start[0] = dinfo->step - 1;
269  count[0] = 1;
270  }
271  switch ( precision ) {
272  case 8:
273  status = nc_get_vara_double(ncid, varid, start, count, (double*)var);
274  free(start);
275  free(count);
276  CHECK_ERROR(status);
277  break;
278  case 4:
279  status = nc_get_vara_float(ncid, varid, start, count, (float*)var);
280  free(start);
281  free(count);
282  CHECK_ERROR(status);
283  break;
284  default:
285  free(start);
286  free(count);
287  fprintf(stderr, "unsuppoted data precision: %d\n", precision );
288  return ERROR_CODE;
289  }
290 
291  return SUCCESS_CODE;
292 }
293 
294 int32_t file_get_global_attribute_text( int32_t fid, // (in)
295  char *key, // (in)
296  char *value, // (out)
297  int32_t len ) // (in)
298 {
299  int ncid;
300  size_t l;
301 
302  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
303  ncid = files[fid]->ncid;
304 
305  CHECK_ERROR( nc_inq_attlen(ncid, NC_GLOBAL, key, &l) );
306  if ( len < l+1 ) return ERROR_CODE;
307 
308  CHECK_ERROR( nc_get_att_text(ncid, NC_GLOBAL, key, value) );
309  value[l] = '\0';
310 
311  return SUCCESS_CODE;
312 }
313 
314 int32_t file_get_global_attribute_int( int32_t fid, // (in)
315  char *key, // (in)
316  int *value, // (out)
317  size_t len ) // (in)
318 {
319  int ncid;
320  size_t l;
321 
322  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
323  ncid = files[fid]->ncid;
324 
325  CHECK_ERROR( nc_inq_attlen(ncid, NC_GLOBAL, key, &l) );
326  if ( len < l ) return ERROR_CODE;
327  CHECK_ERROR( nc_get_att_int(ncid, NC_GLOBAL, key, value) );
328 
329  return SUCCESS_CODE;
330 }
331 
332 int32_t file_get_global_attribute_float( int32_t fid, // (in)
333  char *key, // (in)
334  float *value, // (out)
335  size_t len ) // (in)
336 {
337  int ncid;
338  size_t l;
339 
340  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
341  ncid = files[fid]->ncid;
342 
343  CHECK_ERROR( nc_inq_attlen(ncid, NC_GLOBAL, key, &l) );
344  if ( len < l ) return ERROR_CODE;
345  CHECK_ERROR( nc_get_att_float(ncid, NC_GLOBAL, key, value) );
346 
347  return SUCCESS_CODE;
348 }
349 
350 int32_t file_get_global_attribute_double( int32_t fid, // (in)
351  char *key, // (in)
352  double *value, // (out)
353  size_t len ) // (in)
354 {
355  int ncid;
356  size_t l;
357 
358  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
359  ncid = files[fid]->ncid;
360 
361  CHECK_ERROR( nc_inq_attlen(ncid, NC_GLOBAL, key, &l) );
362  if ( len < l ) return ERROR_CODE;
363  CHECK_ERROR( nc_get_att_double(ncid, NC_GLOBAL, key, value) );
364 
365  return SUCCESS_CODE;
366 }
367 
368 int32_t file_set_global_attribute_text( int32_t fid, // (in)
369  char *key, // (in)
370  char *value ) // (in)
371 {
372  int ncid;
373 
374  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
375  ncid = files[fid]->ncid;
376 
377 #ifdef NETCDF3
378  if (files[fid]->defmode == 0) { CHECK_ERROR( nc_redef(ncid) ); files[fid]->defmode = 1; }
379 #endif
380  CHECK_ERROR( nc_put_att_text(ncid, NC_GLOBAL, key, strlen(value), value) );
381 
382  return SUCCESS_CODE;
383 }
384 
385 int32_t file_set_global_attribute_int( int32_t fid, // (in)
386  char *key, // (in)
387  int *value, // (in)
388  size_t len ) // (in)
389 {
390  int ncid;
391 
392  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
393  ncid = files[fid]->ncid;
394 
395 #ifdef NETCDF3
396  if (files[fid]->defmode == 0) { CHECK_ERROR( nc_redef(ncid) ); files[fid]->defmode = 1; }
397 #endif
398  CHECK_ERROR( nc_put_att_int(ncid, NC_GLOBAL, key, NC_INT, len, value) );
399 
400  return SUCCESS_CODE;
401 }
402 
403 int32_t file_set_global_attribute_float( int32_t fid, // (in)
404  char *key, // (in)
405  float *value, // (in)
406  size_t len ) // (in)
407 {
408  int ncid;
409 
410  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
411  ncid = files[fid]->ncid;
412 
413 #ifdef NETCDF3
414  if (files[fid]->defmode == 0) { CHECK_ERROR( nc_redef(ncid) ); files[fid]->defmode = 1; }
415 #endif
416  CHECK_ERROR( nc_put_att_float(ncid, NC_GLOBAL, key, NC_FLOAT, len, value) );
417 
418  return SUCCESS_CODE;
419 }
420 
421 int32_t file_set_global_attribute_double( int32_t fid, // (in)
422  char *key, // (in)
423  double *value, // (in)
424  size_t len ) // (in)
425 {
426  int ncid;
427 
428  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
429  ncid = files[fid]->ncid;
430 
431 #ifdef NETCDF3
432  if (files[fid]->defmode == 0) { CHECK_ERROR( nc_redef(ncid) ); files[fid]->defmode = 1; }
433 #endif
434  CHECK_ERROR( nc_put_att_double(ncid, NC_GLOBAL, key, NC_DOUBLE, len, value) );
435 
436  return SUCCESS_CODE;
437 }
438 
439 int32_t file_set_tunits( int32_t fid, // (in)
440  char *time_units) // (in)
441 {
442  strcpy(files[fid]->time_units, time_units);
443 
444  return SUCCESS_CODE;
445 }
446 
447 int32_t file_set_tattr( int32_t fid, // (in)
448  char *vname, // (in)
449  char *key, // (in)
450  char *val) // (in)
451 {
452  int ncid;
453  int varid;
454  int attid;
455 
456  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
457  ncid = files[fid]->ncid;
458 
459  CHECK_ERROR( nc_inq_varid(ncid, vname, &varid) );
460 
461  if ( nc_inq_attid(ncid, varid, key, &attid) == NC_NOERR ) // check if existed
462  return ALREADY_EXISTED_CODE;
463 
464 #ifdef NETCDF3
465  if (files[fid]->defmode == 0) { CHECK_ERROR( nc_redef(ncid) ); files[fid]->defmode = 1; }
466 #endif
467 
468  CHECK_ERROR( nc_put_att_text(ncid, varid, key, strlen(val), val) );
469 
470  return SUCCESS_CODE;
471 }
472 
473 int32_t file_put_axis( int32_t fid, // (in)
474  char *name, // (in)
475  char *desc, // (in)
476  char *units, // (in)
477  char *dim_name, // (in)
478  int32_t dtype, // (in)
479  void* val, // (in)
480  int32_t size, // (in)
481  int32_t precision) // (in)
482 {
483  int ncid, dimid, varid;
484  nc_type xtype = -1;
485 
486  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
487  ncid = files[fid]->ncid;
488 
489  if ( nc_inq_varid(ncid, name, &varid) == NC_NOERR ) // check if existed
490  return ALREADY_EXISTED_CODE;
491 
492 #ifdef NETCDF3
493  if (files[fid]->defmode == 0) { CHECK_ERROR( nc_redef(ncid) ); files[fid]->defmode = 1; }
494 #endif
495 
496  if ( nc_inq_dimid(ncid, dim_name, &dimid) != NC_NOERR ) // check if existed
497  CHECK_ERROR( nc_def_dim(ncid, dim_name, size, &dimid) );
498 
499  TYPE2NCTYPE(dtype, xtype);
500  CHECK_ERROR( nc_def_var(ncid, name, xtype, 1, &dimid, &varid) );
501  CHECK_ERROR( nc_put_att_text(ncid, varid, "long_name", strlen(desc), desc) );
502  CHECK_ERROR( nc_put_att_text(ncid, varid, "units", strlen(units), units) );
503 
504 #ifdef NETCDF3
505  CHECK_ERROR( nc_enddef(ncid) );
506  files[fid]->defmode = 0;
507 #endif
508 
509  switch ( precision ) {
510  case 8:
511  CHECK_ERROR( nc_put_var_double(ncid, varid, (double*)val) );
512  break;
513  case 4:
514  CHECK_ERROR( nc_put_var_float(ncid, varid, (float*)val) );
515  break;
516  default:
517  fprintf(stderr, "unsuppoted data precision: %d\n", precision);
518  return ERROR_CODE;
519  }
520 
521  return SUCCESS_CODE;
522 }
523 
524 int32_t file_put_associated_coordinates( int32_t fid, // (in)
525  char *name, // (in)
526  char *desc, // (in)
527  char *units, // (in)
528  char **dim_names, // (in)
529  int32_t ndims, // (in)
530  int32_t dtype, // (in)
531  void* val, // (in)
532  int32_t precision) // (in)
533 {
534  int ncid, *dimids, varid;
535  nc_type xtype = -1;
536  int i;
537 
538  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
539  ncid = files[fid]->ncid;
540 
541  if ( nc_inq_varid(ncid, name, &varid) == NC_NOERR ) // check if existed
542  return ALREADY_EXISTED_CODE;
543 
544 #ifdef NETCDF3
545  if (files[fid]->defmode == 0) { CHECK_ERROR( nc_redef(ncid) ); files[fid]->defmode = 1; }
546 #endif
547 
548  dimids = malloc(sizeof(int)*ndims);
549  for (i=0; i<ndims; i++)
550  CHECK_ERROR( nc_inq_dimid(ncid, dim_names[i], dimids+ndims-i-1) );
551 
552  TYPE2NCTYPE(dtype, xtype);
553 
554  CHECK_ERROR( nc_def_var(ncid, name, xtype, ndims, dimids, &varid) );
555  CHECK_ERROR( nc_put_att_text(ncid, varid, "long_name", strlen(desc), desc) );
556  CHECK_ERROR( nc_put_att_text(ncid, varid, "units", strlen(units), units) );
557  free(dimids);
558 
559 #ifdef NETCDF3
560  CHECK_ERROR( nc_enddef(ncid) );
561  files[fid]->defmode = 0;
562 #endif
563 
564  switch ( precision ) {
565  case 8:
566  CHECK_ERROR( nc_put_var_double(ncid, varid, (double*)val) );
567  break;
568  case 4:
569  CHECK_ERROR( nc_put_var_float(ncid, varid, (float*)val) );
570  break;
571  default:
572  fprintf(stderr, "unsuppoted data precision: %d\n", precision);
573  return ERROR_CODE;
574  }
575 
576  return SUCCESS_CODE;
577 }
578 
579 int32_t file_add_variable( int32_t *vid, // (out)
580  int32_t fid, // (in)
581  char *varname, // (in)
582  char *desc, // (in)
583  char *units, // (in)
584  char **dims, // (in)
585  int32_t ndims, // (in)
586  int32_t dtype, // (in)
587  real64_t tint, // (in)
588  int32_t tavg) // (in)
589 {
590  int ncid, varid, acid, *acdimids;
591  int dimids[NC_MAX_DIMS], dimid;
592  char tname[File_HSHORT+1];
593  int tdimid, tvarid;
594  nc_type xtype = -1;
595  char buf[File_HMID+1];
596  int i, j, k, n, m;
597  int nndims;
598  size_t size;
599  double rmiss = RMISS;
600  char coord[File_HMID+1];
601  int has_assoc;
602  int new;
603 
604  if ( nvar >= VAR_MAX ) {
605  fprintf(stderr, "exceed max number of variable limit\n");
606  return ERROR_CODE;
607  }
608 
609  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
610  ncid = files[fid]->ncid;
611 
612  vars[nvar] = (varinfo_t*) malloc(sizeof(varinfo_t));
613  vars[nvar]->ncid = ncid;
614  vars[nvar]->t = NULL;
615  vars[nvar]->start = NULL;
616  vars[nvar]->count = NULL;
617 
618 #ifdef NETCDF3
619  if (files[fid]->defmode == 0) { CHECK_ERROR( nc_redef(ncid) ); files[fid]->defmode = 1; }
620 #endif
621 
622  // get time variable
623  if ( tint > 0.0 ) {
624  for ( i=0; i<nt; i++ ) {
625  if ( tdims[i] != NULL && // still opened
626  tdims[i]->ncid == ncid && // same file
627  tdims[i]->tint == tint ) { // same time interval
628  vars[nvar]->t = tdims[i];
629  break;
630  }
631  }
632  if ( vars[nvar]->t == NULL ) {
633  tdims[nt] = (tdim_t*) malloc(sizeof(tdim_t));
634  tdims[nt]->ncid = ncid;
635  tdims[nt]->count = -1;
636  tdims[nt]->tint = tint;
637  // generate name
638  if ( nt == 0 )
639  strcpy(tname, "time");
640  else
641  sprintf(tname, "time%d", nt);
642  strcpy(tdims[nt]->name, tname);
643  // define time dimension and variable
644  CHECK_ERROR( nc_def_dim(ncid, tname, 0, &tdimid) );
645  tdims[nt]->dimid = tdimid;
646  CHECK_ERROR( nc_def_var(ncid, tname, NC_DOUBLE, 1, &tdimid, &tvarid) );
647  tdims[nt]->varid = tvarid;
648  strcpy(buf, "time");
649  CHECK_ERROR( nc_put_att_text(ncid, tvarid, "long_name", strlen(buf), buf) );
650  CHECK_ERROR( nc_put_att_text(ncid, tvarid, "units", strlen(files[fid]->time_units), files[fid]->time_units) );
651  // define boundary variable
652  if ( nc_inq_dimid(ncid, "nv", &(dimids[1])) != NC_NOERR ) // first called
653  CHECK_ERROR( nc_def_dim(ncid, "nv", 2, &(dimids[1])) ); // number of vertices
654  sprintf(buf, "%s_bnds", tname);
655  CHECK_ERROR( nc_put_att_text(ncid, tvarid, "bounds", strlen(buf), buf) );
656  dimids[0] = tdimid;
657  CHECK_ERROR( nc_def_var(ncid, buf, NC_DOUBLE, 2, dimids, &tvarid) );
658  tdims[nt]->bndsid = tvarid;
659  CHECK_ERROR( nc_put_att_text(ncid, tvarid, "units", strlen(files[fid]->time_units), files[fid]->time_units) );
660 
661  vars[nvar]->t = tdims[nt];
662  nt++;
663  }
664  }
665 
666  // get dimension IDs
667  // note: C and Fortran order are opposit
668  n = ndims;
669  if ( tint > 0.0 ) { // add time dimension
670  dimids[0] = vars[nvar]->t->dimid;
671  ndims++;
672  }
673  for (i=ndims-n; i<ndims; i++) dimids[i] = -1;
674 
675  has_assoc = 0;
676  nndims = 0;
677  for (i=0; i<n; i++) {
678  //printf("%d %s\n", i, dims[i]);
679  if ( nc_inq_dimid(ncid, dims[i], &dimid) == NC_NOERR ) {
680  //printf("not assoc\n");
681  new = 1;
682  for (k=0; k<nndims; k++) {
683  if (dimid == dimids[k]) {
684  new = 0;
685  break;
686  }
687  }
688  if (new) {
689  dimids[ndims-(++nndims)] = dimid;
690  }
691  } else {
692  //printf("assoc\n");
693  CHECK_ERROR( nc_inq_varid(ncid, dims[i], &acid) );
694  CHECK_ERROR( nc_inq_varndims(ncid, acid, &m) );
695  acdimids = (int*) malloc((sizeof(int)*m));
696  CHECK_ERROR( nc_inq_vardimid(ncid, acid, acdimids) );
697  for (j=m-1; j>=0; j--) {
698  new = 1;
699  for (k=0; k<ndims; k++) {
700  if (acdimids[j] == dimids[k]) {
701  new = 0;
702  break;
703  }
704  }
705  if (new) {
706  if ( nndims >= ndims ) {
707  fprintf(stderr, "Error: invalid associated coordinates\n");
708  return ERROR_CODE;
709  }
710  dimids[ndims-(++nndims)] = acdimids[j];
711  //nc_inq_dimname(ncid, acdimids[j], tname);
712  //printf("add %s\n", tname);
713  }
714  }
715  free(acdimids);
716  has_assoc = 1;
717  }
718  }
719  if (nndims != n) {
720  fprintf(stderr, "Error: invalid associated coordinates: %d %d\n", ndims, nndims);
721  return ERROR_CODE;
722  }
723 
724  TYPE2NCTYPE(dtype, xtype);
725  CHECK_ERROR( nc_def_var(ncid, varname, xtype, ndims, dimids, &varid) );
726 
727  // put variable attribute
728  CHECK_ERROR( nc_put_att_text(ncid, varid, "long_name", strlen(desc), desc) );
729  CHECK_ERROR( nc_put_att_text(ncid, varid, "units", strlen(units), units) );
730  CHECK_ERROR( nc_put_att_double(ncid, varid, _FillValue, xtype, 1, &rmiss) );
731  CHECK_ERROR( nc_put_att_double(ncid, varid, "missing_value", xtype, 1, &rmiss) );
732  if ( has_assoc ) {
733  strcpy(coord, dims[0]);
734  for(i=1; i<n; i++) {
735  if (strlen(coord)+strlen(dims[i])+1 < File_HMID) {
736  strcat(coord, " ");
737  strcat(coord, dims[i]);
738  }
739  }
740  if ( ndims > n && strlen(coord)+6 < File_HMID) {
741  strcat(coord, " ");
742  strcat(coord, vars[nvar]->t->name);
743  }
744  CHECK_ERROR( nc_put_att_text(ncid, varid, "coordinates", strlen(coord), coord) );
745  }
746 
747 
748  if ( tavg ) {
749  sprintf(buf, "%s: mean", vars[nvar]->t->name);
750  CHECK_ERROR( nc_put_att_text(ncid, varid, "cell_methods", strlen(buf), buf) );
751  }
752 
753  // set start and count
754  vars[nvar]->start = (size_t*) malloc(sizeof(size_t)*ndims);
755  vars[nvar]->count = (size_t*) malloc(sizeof(size_t)*ndims);
756  for ( i=0; i<ndims; i++ ) {
757  CHECK_ERROR( nc_inq_dimlen(ncid, dimids[i], &size) );
758  vars[nvar]->count[i] = size;
759  vars[nvar]->start[i] = 0;
760  }
761  if ( tint > 0.0 ) vars[nvar]->count[0] = 1;
762 
763 #ifndef NETCDF3
764  // set chunk size and deflate level
765  if ( files[fid]->deflate_level > 0 ) {
766  CHECK_ERROR( nc_def_var_chunking(ncid, varid, NC_CHUNKED, vars[nvar]->count) );
767  CHECK_ERROR( nc_def_var_deflate(ncid, varid, 0, 1, files[fid]->deflate_level) );
768  }
769 #endif
770 
771  vars[nvar]->varid = varid;
772  *vid = nvar;
773  nvar++;
774 
775  return SUCCESS_CODE;
776 }
777 
778 int32_t file_write_data( int32_t fid, // (in)
779  int32_t vid, // (in)
780  void *var, // (in)
781  real64_t t_start, // (in)
782  real64_t t_end, // (in)
783  int32_t precision) // (in)
784 {
785  int ncid, varid;
786 
787  if ( vars[vid] == NULL ) return ALREADY_CLOSED_CODE;
788 
789  ncid = vars[vid]->ncid;
790 
791 #ifdef NETCDF3
792  if ( files[fid]->defmode == 1) { CHECK_ERROR( nc_enddef(ncid) ); files[fid]->defmode = 0; }
793 #endif
794 
795  varid = vars[vid]->varid;
796  if ( vars[vid]->t != NULL ) { // have time dimension
797  if ( vars[vid]->t->count < 0 || // first time
798  t_end > vars[vid]->t->t + TEPS ) { // time goes next step
799  vars[vid]->t->count += 1;
800  vars[vid]->t->t = t_end;
801  size_t index[2];
802  index[0] = vars[vid]->t->count;
803  CHECK_ERROR( nc_put_var1_double(ncid, vars[vid]->t->varid, index, &t_end) );
804  index[1] = 0;
805  CHECK_ERROR( nc_put_var1_double(ncid, vars[vid]->t->bndsid, index, &t_start) );
806  index[1] = 1;
807  CHECK_ERROR( nc_put_var1_double(ncid, vars[vid]->t->bndsid, index, &t_end) );
808  vars[vid]->start[0] = vars[vid]->t->count;
809  } else {
810  size_t nt = vars[vid]->t->count + 1;
811  double t[nt];
812  size_t s[1];
813  int flag, n;
814  s[0] = 0;
815  CHECK_ERROR( nc_get_vara_double(ncid, vars[vid]->t->varid, s, &nt, t) );
816  flag = 1;
817  for(n=nt-1;n>=0;n--) {
818  if ( fabs(t[n]-t_end) < TEPS ) {
819  vars[vid]->start[0] = n;
820  flag = 0;
821  break;
822  }
823  }
824  if ( flag ) {
825  fprintf(stderr, "cannot find time: %f\n", t_end);
826  fprintf(stderr, " time count is : %d, last time is: %f, diff is: %e\n", vars[vid]->t->count < 0, vars[vid]->t->t, vars[vid]->t->t-t_end);
827  fprintf(stderr, " time is: ");
828  for (n=0;n<nt;n++) fprintf(stderr, "%f, ", t[n]);
829  fprintf(stderr, "\n");
830  return ERROR_CODE;
831  }
832  }
833  }
834 
835  switch (precision) {
836  case 8:
837  CHECK_ERROR( nc_put_vara_double(ncid, varid, vars[vid]->start, vars[vid]->count, (double*)var) );
838  break;
839  case 4:
840  CHECK_ERROR( nc_put_vara_float(ncid, varid, vars[vid]->start, vars[vid]->count, (float*)var) );
841  break;
842  default:
843  fprintf(stderr, "unsuppoted data precision: %d\n", precision);
844  return ERROR_CODE;
845  }
846 
847  CHECK_ERROR( nc_sync(ncid) );
848 
849  return SUCCESS_CODE;
850 }
851 
852 int32_t file_close( int32_t fid ) // (in)
853 {
854  int ncid;
855  int i;
856 
857  if ( files[fid] == NULL ) return ALREADY_CLOSED_CODE;
858  ncid = files[fid]->ncid;
859 
860  free( files[fid] );
861  files[fid] = NULL;
862 
863  for (i=0; i<nvar; i++) {
864  if ( vars[i] != NULL && vars[i]->ncid == ncid ) {
865  free( vars[i]->start );
866  free( vars[i]->count );
867  free( vars[i] );
868  vars[i] = NULL;
869  }
870  }
871 
872  for (i=0; i<nt; i++) {
873  if ( tdims[i] != NULL && tdims[i]->ncid == ncid ) {
874  free( tdims[i] );
875  tdims[i] = NULL;
876  }
877  }
878 
879  CHECK_ERROR( nc_close(ncid) );
880 
881  return SUCCESS_CODE;
882 }
int32_t file_set_global_attribute_text(int32_t fid, char *key, char *value)
Definition: gtool_netcdf.c:368
#define File_HMID
Definition: gtool_file.h:12
int32_t dim_size[MAX_RANK]
Definition: gtool_file.h:48
int32_t step
Definition: gtool_file.h:49
#define File_FAPPEND
Definition: gtool_file.h:25
#define FILE_MAX
Definition: gtool_netcdf.c:85
#define File_FREAD
Definition: gtool_file.h:23
int dimid
Definition: gtool_netcdf.c:67
#define MAX_RANK
Definition: gtool_file.h:34
real(dp), parameter, public rmiss
Definition: gtool_file.f90:110
int32_t file_set_tunits(int32_t fid, char *time_units)
Definition: gtool_netcdf.c:439
#define ERROR_CODE
Definition: gtool_file.h:28
int32_t file_set_global_attribute_int(int32_t fid, char *key, int *value, size_t len)
Definition: gtool_netcdf.c:385
#define DEFAULT_DEFLATE_LEVEL
Definition: gtool_netcdf.c:54
int deflate_level
Definition: gtool_netcdf.c:59
int count
Definition: gtool_netcdf.c:70
tdim_t * t
Definition: gtool_netcdf.c:79
char dim_name[File_HSHORT *MAX_RANK]
Definition: gtool_file.h:47
char description[File_HMID]
Definition: gtool_file.h:43
int32_t file_get_global_attribute_text(int32_t fid, char *key, char *value, int32_t len)
Definition: gtool_netcdf.c:294
#define TEPS
Definition: gtool_netcdf.c:5
#define File_HSHORT
Definition: gtool_file.h:11
int32_t file_put_associated_coordinates(int32_t fid, char *name, char *desc, char *units, char **dim_names, int32_t ndims, int32_t dtype, void *val, int32_t precision)
Definition: gtool_netcdf.c:524
real64_t time_start
Definition: gtool_file.h:50
int ncid
Definition: gtool_netcdf.c:66
int32_t file_get_global_attribute_float(int32_t fid, char *key, float *value, size_t len)
Definition: gtool_netcdf.c:332
int32_t file_add_variable(int32_t *vid, int32_t fid, char *varname, char *desc, char *units, char **dims, int32_t ndims, int32_t dtype, real64_t tint, int32_t tavg)
Definition: gtool_netcdf.c:579
#define ALREADY_EXISTED_CODE
Definition: gtool_file.h:31
#define NCTYPE2TYPE(nctype, type)
Definition: gtool_netcdf.c:20
int32_t file_read_data(void *var, datainfo_t *dinfo, int32_t precision)
Definition: gtool_netcdf.c:245
real64_t tint
Definition: gtool_netcdf.c:72
int32_t file_set_global_attribute_float(int32_t fid, char *key, float *value, size_t len)
Definition: gtool_netcdf.c:403
int32_t file_get_datainfo(datainfo_t *dinfo, int32_t fid, char *varname, int32_t step, int32_t suppress)
Definition: gtool_netcdf.c:162
int bndsid
Definition: gtool_netcdf.c:69
int32_t fid
Definition: gtool_file.h:53
int32_t file_set_global_attribute_double(int32_t fid, char *key, double *value, size_t len)
Definition: gtool_netcdf.c:421
#define CHECK_ERROR(status)
Definition: gtool_netcdf.c:9
#define TYPE2NCTYPE(type, nctype)
Definition: gtool_netcdf.c:38
#define ALREADY_CLOSED_CODE
Definition: gtool_file.h:30
#define SUCCESS_CODE
Definition: gtool_file.h:29
int32_t file_put_axis(int32_t fid, char *name, char *desc, char *units, char *dim_name, int32_t dtype, void *val, int32_t size, int32_t precision)
Definition: gtool_netcdf.c:473
#define VAR_MAX
Definition: gtool_netcdf.c:87
int32_t file_close(int32_t fid)
Definition: gtool_netcdf.c:852
char time_units[File_HMID]
Definition: gtool_file.h:52
real64_t time_end
Definition: gtool_file.h:51
size_t * start
Definition: gtool_netcdf.c:80
int32_t file_get_global_attribute_double(int32_t fid, char *key, double *value, size_t len)
Definition: gtool_netcdf.c:350
int32_t file_set_tattr(int32_t fid, char *vname, char *key, char *val)
Definition: gtool_netcdf.c:447
#define File_HLONG
Definition: gtool_file.h:13
int32_t file_open(int32_t *fid, char *fname, int32_t mode)
Definition: gtool_netcdf.c:97
char units[File_HSHORT]
Definition: gtool_file.h:44
#define RMISS
Definition: gtool_netcdf.c:4
int32_t file_get_global_attribute_int(int32_t fid, char *key, int *value, size_t len)
Definition: gtool_netcdf.c:314
real64_t t
Definition: gtool_netcdf.c:71
char varname[File_HSHORT]
Definition: gtool_file.h:42
int32_t file_set_option(int32_t fid, char *filetype, char *key, char *val)
Definition: gtool_netcdf.c:146
int32_t file_write_data(int32_t fid, int32_t vid, void *var, real64_t t_start, real64_t t_end, int32_t precision)
Definition: gtool_netcdf.c:778
size_t * count
Definition: gtool_netcdf.c:81
#define File_FWRITE
Definition: gtool_file.h:24
int32_t datatype
Definition: gtool_file.h:45
int varid
Definition: gtool_netcdf.c:68
int32_t rank
Definition: gtool_file.h:46