testcalendar.c

Go to the documentation of this file.
00001 /* ********************************************************* */
00002 /* testcalendar Test calendar conversion functions.          */
00003 /* testcalendar.c                                            */
00004 /* ********************************************************* */
00005 /* Author: Christian Page, CERFACS, Toulouse, France.        */
00006 /* ********************************************************* */
00011 /* LICENSE BEGIN
00012 
00013 Copyright Cerfacs (Christian Page) (2015)
00014 
00015 christian.page@cerfacs.fr
00016 
00017 This software is a computer program whose purpose is to downscale climate
00018 scenarios using a statistical methodology based on weather regimes.
00019 
00020 This software is governed by the CeCILL license under French law and
00021 abiding by the rules of distribution of free software. You can use, 
00022 modify and/ or redistribute the software under the terms of the CeCILL
00023 license as circulated by CEA, CNRS and INRIA at the following URL
00024 "http://www.cecill.info". 
00025 
00026 As a counterpart to the access to the source code and rights to copy,
00027 modify and redistribute granted by the license, users are provided only
00028 with a limited warranty and the software's author, the holder of the
00029 economic rights, and the successive licensors have only limited
00030 liability. 
00031 
00032 In this respect, the user's attention is drawn to the risks associated
00033 with loading, using, modifying and/or developing or reproducing the
00034 software by the user in light of its specific status of free software,
00035 that may mean that it is complicated to manipulate, and that also
00036 therefore means that it is reserved for developers and experienced
00037 professionals having in-depth computer knowledge. Users are therefore
00038 encouraged to load and test the software's suitability as regards their
00039 requirements in conditions enabling the security of their systems and/or 
00040 data to be ensured and, more generally, to use and operate it in the 
00041 same conditions as regards security. 
00042 
00043 The fact that you are presently reading this means that you have had
00044 knowledge of the CeCILL license and that you accept its terms.
00045 
00046 LICENSE END */
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 #ifdef HAVE_CONFIG_H
00055 #include <config.h>
00056 #endif
00057 
00059 #define _GNU_SOURCE
00060 
00061 /* C standard includes */
00062 #ifdef HAVE_SYS_TYPES_H
00063 #include <sys/types.h>
00064 #endif
00065 #ifdef HAVE_SYS_STAT_H
00066 #include <sys/stat.h>
00067 #endif
00068 #ifdef HAVE_FCNTL_H
00069 #include <fcntl.h>
00070 #endif
00071 #ifdef HAVE_UNSTD_H
00072 #include <unistd.h>
00073 #endif
00074 #ifdef HAVE_STDIO_H
00075 #include <stdio.h>
00076 #endif
00077 #ifdef HAVE_STRING_H
00078 #include <string.h>
00079 #endif
00080 #ifdef HAVE_STDLIB_H
00081 #include <stdlib.h>
00082 #endif
00083 #ifdef HAVE_MATH_H
00084 #include <math.h>
00085 #endif
00086 #ifdef HAVE_TIME_H
00087 #include <time.h>
00088 #endif
00089 #ifdef HAVE_LIBGEN_H
00090 #include <libgen.h>
00091 #endif
00092 
00093 #include <zlib.h>
00094 #include <hdf5.h>
00095 #include <netcdf.h>
00096 
00097 #include <utils.h>
00098 
00100 void show_usage(char *pgm);
00101 void handle_netcdf_error(int status, int lineno);
00102 
00104 int main(int argc, char **argv)
00105 {
00113   int nlat;
00114   int nlon;
00115   int ntime;
00116 
00117   size_t dimval;
00118   int i;
00119 
00120   char *filein = NULL;
00121   char *fileout = NULL;
00122 
00123   int istat, ncinid, ncoutid;
00124   int varinid, timeinid, timediminid, loninid, londiminid, latinid, latdiminid;
00125   int varoutid, timeoutid, timedimoutid, lonoutid, londimoutid, latoutid, latdimoutid;
00126   nc_type vartype_main;
00127   nc_type vartype_time;
00128   int varndims;
00129   int vardimids[NC_MAX_VAR_DIMS];    /* dimension ids */
00130 
00131   size_t start[3];
00132   size_t count[3];
00133 
00134   size_t t_len;
00135   char *time_units = NULL;
00136   char *cal_type = NULL;
00137   char cal_type_out[500];
00138 
00139   char attname[1000];
00140   int natts;
00141   float fillvaluef;
00142   double fillvalued;
00143 
00144   void *psl = NULL;
00145   double *timein = NULL;
00146   double *lat = NULL;
00147   double *lon = NULL;
00148 
00149   double *psloutd = NULL;
00150   float *psloutf = NULL;
00151   double *outtimeval = NULL;
00152   int ntimeout;
00153 
00154   /* Print BEGIN banner */
00155   (void) banner(basename(argv[0]), "1.0", "BEGIN");
00156 
00157   /* Get command-line arguments and set appropriate variables */
00158   for (i=1; i<argc; i++) {
00159     if ( !strcmp(argv[i], "-h") ) {
00160       (void) show_usage(basename(argv[0]));
00161       (void) banner(basename(argv[0]), "OK", "END");
00162       return 0;
00163     }
00164     else if ( !strcmp(argv[i], "-i") ) {
00165       filein = (char *) malloc((strlen(argv[++i])+1) * sizeof(char));
00166       if (filein == NULL) alloc_error(__FILE__, __LINE__);
00167       (void) strcpy(filein, argv[i]);
00168     }
00169     else if ( !strcmp(argv[i], "-o") ) {
00170       fileout = (char *) malloc((strlen(argv[++i])+1) * sizeof(char));
00171       if (fileout == NULL) alloc_error(__FILE__, __LINE__);
00172       (void) strcpy(fileout, argv[i]);
00173     }
00174     else {
00175       (void) fprintf(stderr, "%s:: Wrong arg %s.\n\n", basename(argv[0]), argv[i]);
00176       (void) show_usage(basename(argv[0]));
00177       (void) banner(basename(argv[0]), "ABORT", "END");
00178       (void) abort();
00179     }
00180   }
00181 
00182   /* Read data in NetCDF file */
00183   istat = nc_open(filein, NC_NOWRITE, &ncinid);  /* open for reading */
00184   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00185 
00186   istat = nc_inq_dimid(ncinid, "time", &timediminid);  /* get ID for time dimension */
00187   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00188   istat = nc_inq_dimlen(ncinid, timediminid, &dimval); /* get time length */
00189   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00190   ntime = (int) dimval;
00191 
00192   istat = nc_inq_dimid(ncinid, "lat", &latdiminid);  /* get ID for lat dimension */
00193   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00194   istat = nc_inq_dimlen(ncinid, latdiminid, &dimval); /* get lat length */
00195   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00196   nlat = (int) dimval;
00197 
00198   istat = nc_inq_dimid(ncinid, "lon", &londiminid);  /* get ID for lon dimension */
00199   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00200   istat = nc_inq_dimlen(ncinid, londiminid, &dimval); /* get lon length */
00201   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00202   nlon = (int) dimval;
00203   
00204   istat = nc_inq_varid(ncinid, "time", &timeinid);  /* get ID for time variable */
00205   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00206   istat = nc_inq_varid(ncinid, "lat", &latinid);  /* get ID for lat variable */
00207   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00208   istat = nc_inq_varid(ncinid, "lon", &loninid);  /* get ID for lon variable */
00209   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00210 
00211   istat = nc_inq_varid(ncinid, "psl", &varinid); /* get psl variable ID */
00212   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00213 
00215   /* Allocate memory and set start and count */
00216   start[0] = 0;
00217   count[0] = (size_t) nlat;
00218   lat = (double *) malloc(nlat * sizeof(double));
00219   if (lat == NULL) alloc_error(__FILE__, __LINE__);
00220 
00221   /* Read values from netCDF variable */
00222   istat = nc_get_vara_double(ncinid, latinid, start, count, lat);
00223   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00224 
00225   /* Allocate memory and set start and count */
00226   start[0] = 0;
00227   count[0] = (size_t) nlon;
00228   lon = (double *) malloc(nlon * sizeof(double));
00229   if (lon == NULL) alloc_error(__FILE__, __LINE__);
00230 
00231   /* Read values from netCDF variable */
00232   istat = nc_get_vara_double(ncinid, loninid, start, count, lon);
00233   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00234   
00235   /* Get time dimensions and type */
00236   istat = nc_inq_var(ncinid, timeinid, (char *) NULL, &vartype_time, &varndims, vardimids, (int *) NULL); /* get variable information */
00237   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00238   
00239   if (varndims != 1) {
00240     (void) fprintf(stderr, "Error NetCDF type and/or dimensions.\n");
00241     (void) banner(basename(argv[0]), "ABORT", "END");
00242     (void) abort();
00243   }
00244 
00245   /* Allocate memory and set start and count */
00246   start[0] = 0;
00247   count[0] = (size_t) ntime;
00248   timein = malloc(ntime * sizeof(double));
00249   if (timein == NULL) alloc_error(__FILE__, __LINE__);
00250 
00251   /* Read values from netCDF variable */
00252   istat = nc_get_vara_double(ncinid, timeinid, start, count, timein);
00253   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00254   
00257   /* Get variable information */
00258   istat = nc_inq_var(ncinid, varinid, (char *) NULL, &vartype_main, &varndims, vardimids, (int *) NULL);
00259   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00260 
00261   if (varndims != 3) {
00262     (void) fprintf(stderr, "Error NetCDF type and/or dimensions.\n");
00263     (void) banner(basename(argv[0]), "ABORT", "END");
00264     (void) abort();
00265   }
00266 
00267   /* Allocate memory and set start and count */
00268   start[0] = 0;
00269   start[1] = 0;
00270   start[2] = 0;
00271   count[0] = (size_t) ntime;
00272   count[1] = (size_t) nlat;
00273   count[2] = (size_t) nlon;
00274   /* Allocate memory */
00275   if (vartype_main == NC_DOUBLE)
00276     psl = calloc(nlat*nlon*ntime, sizeof(double));
00277   else if (vartype_main == NC_FLOAT)
00278     psl = calloc(nlat*nlon*ntime, sizeof(float));
00279   else {
00280     (void) fprintf(stderr, "Error NetCDF variable type for main variable.\n");
00281     (void) banner(basename(argv[0]), "ABORT", "END");
00282     (void) abort();
00283   }    
00284   if (psl == NULL) alloc_error(__FILE__, __LINE__);
00285 
00286   /* Read values from netCDF variable */
00287   printf("%s: Reading data from input file %s.\n", __FILE__, filein);
00288   istat = nc_get_vara(ncinid, varinid, start, count, psl);
00289   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00290 
00291   /* Get time units attribute length */
00292   istat = nc_inq_attlen(ncinid, timeinid, "units", &t_len);
00293   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00294   /* Allocate required space before retrieving values */
00295   time_units = (char *) malloc(t_len + 1);
00296   if (time_units == NULL) alloc_error(__FILE__, __LINE__);
00297   /* Get time units attribute value */
00298   istat = nc_get_att_text(ncinid, timeinid, "units", time_units);
00299   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00300   time_units[t_len] = '\0'; /* null terminate */
00301 
00302   /* Get calendar type attribute length */
00303   istat = nc_inq_attlen(ncinid, timeinid, "calendar", &t_len);
00304   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00305   /* Allocate required space before retrieving values */
00306   cal_type = (char *) malloc(t_len + 1);
00307   if (cal_type == NULL) alloc_error(__FILE__, __LINE__);
00308   /* Get calendar type attribute value */
00309   istat = nc_get_att_text(ncinid, timeinid, "calendar", cal_type);
00310   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00311   cal_type[t_len] = '\0'; /* null terminate */
00312 
00314   outtimeval = NULL;
00315   if (vartype_main == NC_FLOAT) {
00316     psloutf = NULL;
00317     (void) data_to_gregorian_cal_f(&psloutf, &outtimeval, &ntimeout, psl, timein, time_units, "days since 1900-01-01 00:00:00",
00318                                    "noleap", nlon, nlat, ntime);
00319   }
00320   else {
00321     psloutd = NULL;
00322     (void) data_to_gregorian_cal_d(&psloutd, &outtimeval, &ntimeout, psl, timein, time_units, "days since 1900-01-01 00:00:00",
00323                                    "noleap", nlon, nlat, ntime);
00324   }
00325 
00326   (void) fprintf(stderr, "Input time units: %s\n", time_units);
00327   (void) fprintf(stderr, "Output time units: days since 1900-01-01 00:00:00\n");
00328 
00330   /* Create and open output file */
00331   istat = nc_create(fileout, NC_CLOBBER, &ncoutid);
00332   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00333 
00334   /* Set dimensions */
00335   istat = nc_def_dim(ncoutid, "time", NC_UNLIMITED, &timedimoutid);
00336   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00337   istat = nc_def_dim(ncoutid, "lat", nlat, &latdimoutid);
00338   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00339   istat = nc_def_dim(ncoutid, "lon", nlon, &londimoutid);
00340   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00341 
00342   /* Define dimensions variables */
00343   vardimids[0] = latdimoutid;
00344   istat = nc_def_var(ncoutid, "lat", NC_DOUBLE, 1, vardimids, &latoutid);
00345   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00346   vardimids[0] = londimoutid;
00347   istat = nc_def_var(ncoutid, "lon", NC_DOUBLE, 1, vardimids, &lonoutid);
00348   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00349   vardimids[0] = timedimoutid;
00350   istat = nc_def_var(ncoutid, "time", NC_DOUBLE, 1, vardimids, &timeoutid);
00351   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00352 
00353   /* Define main output variable */
00354   vardimids[0] = timedimoutid;
00355   vardimids[1] = latdimoutid;
00356   vardimids[2] = londimoutid;
00357   istat = nc_def_var(ncoutid, "psl", vartype_main, 3, vardimids, &varoutid);
00358   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00359 
00360   /* Copy lat attributes */
00361   istat = nc_inq_varnatts(ncinid, latinid, &natts);
00362   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00363   for (i=0; i<natts; i++) {
00364     istat = nc_inq_attname(ncinid, latinid, i, attname);
00365     if (istat == NC_NOERR) {
00366       istat = nc_copy_att(ncinid, latinid, attname, ncoutid, latoutid);
00367       if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00368     }
00369     else
00370       (void) handle_netcdf_error(istat, __LINE__);
00371   }
00372 
00373   /* Copy lon attributes */
00374   istat = nc_inq_varnatts(ncinid, loninid, &natts);
00375   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00376   for (i=0; i<natts; i++) {
00377     istat = nc_inq_attname(ncinid, loninid, i, attname);
00378     if (istat == NC_NOERR) {
00379       istat = nc_copy_att(ncinid, loninid, attname, ncoutid, lonoutid);
00380       if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00381     }
00382     else
00383       (void) handle_netcdf_error(istat, __LINE__);
00384   }
00385 
00386   /* Copy time attributes */
00387   istat = nc_inq_varnatts(ncinid, timeinid, &natts);
00388   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00389   for (i=0; i<natts; i++) {
00390     istat = nc_inq_attname(ncinid, timeinid, i, attname);
00391     if (istat == NC_NOERR) {
00392       printf("Time attribute: %s\n", attname);
00393       if ( !strcmp(attname, "calendar") ) {
00394         /* Change calendar type to standard */
00395         (void) strcat(cal_type_out, "standard");
00396         istat = nc_put_att_text(ncoutid, timeoutid, "calendar", strlen(cal_type_out), cal_type_out);
00397       }
00398       else
00399         /* Other time attributes */
00400         istat = nc_copy_att(ncinid, timeinid, attname, ncoutid, timeoutid);
00401       if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00402     }
00403     else
00404       (void) handle_netcdf_error(istat, __LINE__);
00405   }
00406 
00407   /* Copy main variable attributes */
00408   istat = nc_inq_varnatts(ncinid, varinid, &natts);
00409   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00410   for (i=0; i<natts; i++) {
00411     istat = nc_inq_attname(ncinid, varinid, i, attname);
00412     if (istat == NC_NOERR) {
00413       printf("Main variable attribute: %s\n", attname);
00414       if ( !strcmp(attname, "_FillValue") || !strcmp(attname, "missing_value") ) {
00415         if (vartype_main == NC_FLOAT) {
00416           istat = nc_get_att_float(ncinid, varoutid, attname, &fillvaluef);
00417           if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00418           istat = nc_put_att_float(ncoutid, varoutid, attname, NC_FLOAT, 1, &fillvaluef);
00419           if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00420         }
00421         else if (vartype_main == NC_DOUBLE) {
00422           istat = nc_get_att_double(ncinid, varoutid, attname, &fillvalued);
00423           if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00424           istat = nc_put_att_double(ncoutid, varoutid, attname, NC_DOUBLE, 1, &fillvalued);
00425           if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00426         }
00427         else {
00428           (void) fprintf(stderr, "Error NetCDF variable type for main variable.\n");
00429           (void) banner(basename(argv[0]), "ABORT", "END");
00430           (void) abort();
00431         }
00432       }
00433       else {
00434         istat = nc_copy_att(ncinid, varinid, attname, ncoutid, varoutid);
00435         if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00436       }
00437     }
00438     else
00439       (void) handle_netcdf_error(istat, __LINE__);
00440   }
00441 
00442   /* End definition mode */
00443   istat = nc_enddef(ncoutid);
00444   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00445 
00446   /* Write dimensions variables to NetCDF output file */
00447   start[0] = 0;
00448   count[0] = (size_t) nlat;
00449   count[1] = 0;
00450   count[2] = 0;
00451   istat = nc_put_vara_double(ncoutid, latoutid, start, count, lat);
00452   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00453   count[0] = (size_t) nlon;
00454   istat = nc_put_vara_double(ncoutid, lonoutid, start, count, lon);
00455   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00456   count[0] = (size_t) ntimeout;
00457   istat = nc_put_vara_double(ncoutid, timeoutid, start, count, outtimeval);
00458   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00459   for (i=0; i<ntimeout; i++)
00460     printf("Output Time Dimension values. index=%d time=%lf\n",i,outtimeval[i]);
00461 
00462   /* Write variable to NetCDF output file */
00463   start[0] = 0;
00464   start[1] = 0;
00465   start[2] = 0;
00466   count[0] = (size_t) ntimeout;
00467   count[1] = (size_t) nlat;
00468   count[2] = (size_t) nlon;
00469   printf("%s: Writing data to output file %s.\n", __FILE__, fileout);
00470   if (vartype_main == NC_FLOAT)
00471     istat = nc_put_vara_float(ncoutid, varoutid, start, count, psloutf);
00472   else
00473     istat = nc_put_vara_double(ncoutid, varoutid, start, count, psloutd);
00474   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00475 
00477   /* Close the intput netCDF file. */
00478   istat = ncclose(ncinid);
00479   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00480 
00481   /* Close the output netCDF file. */
00482   istat = ncclose(ncoutid);
00483   if (istat != NC_NOERR) handle_netcdf_error(istat, __LINE__);
00484 
00485   (void) free(psl);
00486   if (vartype_main == NC_FLOAT)
00487     (void) free(psloutf);
00488   else
00489     (void) free(psloutd);
00490   (void) free(outtimeval);
00491   (void) free(lon);
00492   (void) free(lat);
00493   (void) free(timein);
00494   (void) free(cal_type);
00495   (void) free(time_units);
00496   (void) free(filein);
00497   (void) free(fileout);
00498 
00499   /* Print END banner */
00500   (void) banner(basename(argv[0]), "OK", "END");
00501 
00502   return 0;
00503 }
00504 
00505 
00509 void show_usage(char *pgm) {
00514   (void) fprintf(stderr, "%s: usage:\n", pgm);
00515   (void) fprintf(stderr, "-i: input NetCDF file\n");
00516   (void) fprintf(stderr, "-o: output NetCDF file\n");
00517   (void) fprintf(stderr, "-h: help\n");
00518 
00519 }
00520 
00521 /* Handle error */
00522 void handle_netcdf_error(int status, int lineno)
00523 {
00524   if (status != NC_NOERR) {
00525     fprintf(stderr, "Line: %d Error %d: %s\n", lineno, status, nc_strerror(status));
00526     exit(-1);
00527   }
00528 }

Generated on 12 May 2016 for DSCLIM by  doxygen 1.6.1