get_time_info.c

Go to the documentation of this file.
00001 /* ***************************************************** */
00002 /* get_time_info Get time NetCDF info.                   */
00003 /* get_time_info.c                                       */
00004 /* ***************************************************** */
00005 /* Author: Christian Page, CERFACS, Toulouse, France.    */
00006 /* ***************************************************** */
00007 /* Date of creation: oct 2008                            */
00008 /* Last date of modification: jul 2011                   */
00009 /* ***************************************************** */
00010 /* Original version: 1.0                                 */
00011 /* Current revision: 1.1                                 */
00012 /* ***************************************************** */
00013 /* Revisions                                             */
00014 /* 1.1: Updated for utCalendar2_cal (udunits2)           */
00015 /* ***************************************************** */
00020 /* LICENSE BEGIN
00021 
00022 Copyright Cerfacs (Christian Page) (2015)
00023 
00024 christian.page@cerfacs.fr
00025 
00026 This software is a computer program whose purpose is to downscale climate
00027 scenarios using a statistical methodology based on weather regimes.
00028 
00029 This software is governed by the CeCILL license under French law and
00030 abiding by the rules of distribution of free software. You can use, 
00031 modify and/ or redistribute the software under the terms of the CeCILL
00032 license as circulated by CEA, CNRS and INRIA at the following URL
00033 "http://www.cecill.info". 
00034 
00035 As a counterpart to the access to the source code and rights to copy,
00036 modify and redistribute granted by the license, users are provided only
00037 with a limited warranty and the software's author, the holder of the
00038 economic rights, and the successive licensors have only limited
00039 liability. 
00040 
00041 In this respect, the user's attention is drawn to the risks associated
00042 with loading, using, modifying and/or developing or reproducing the
00043 software by the user in light of its specific status of free software,
00044 that may mean that it is complicated to manipulate, and that also
00045 therefore means that it is reserved for developers and experienced
00046 professionals having in-depth computer knowledge. Users are therefore
00047 encouraged to load and test the software's suitability as regards their
00048 requirements in conditions enabling the security of their systems and/or 
00049 data to be ensured and, more generally, to use and operate it in the 
00050 same conditions as regards security. 
00051 
00052 The fact that you are presently reading this means that you have had
00053 knowledge of the CeCILL license and that you accept its terms.
00054 
00055 LICENSE END */
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 #include <io.h>
00064 
00066 int
00067 get_time_info(time_vect_struct *time_s, double **timeval, char **time_units, char **cal_type, int *ntime, char *filename,
00068               char *varname, int outinfo) {
00082   int istat; /* Diagnostic status */
00083 
00084   size_t dimval; /* Variable used to retrieve dimension length */
00085 
00086   int ncinid; /* NetCDF input file handle ID */
00087   int timediminid; /* Time dimension ID */
00088   int timeinid; /* Time variable ID */
00089   nc_type vartype_time; /* Type of the time variable (NC_FLOAT, NC_DOUBLE, etc.) */
00090 
00091   int varndims; /* Number of dimensions of variable */
00092   int vardimids[NC_MAX_VAR_DIMS]; /* Variable dimension ids */
00093 
00094   size_t start[3]; /* Start position to read */
00095   size_t count[3]; /* Number of elements to read */
00096 
00097   size_t t_len; /* Length of time units attribute string */
00098   ut_system *unitSystem = NULL; /* Unit System (udunits) */
00099   ut_unit *dataunits = NULL; /* Data units (udunits) */
00100 
00101   int t; /* Time loop counter */
00102 
00103   /* Read data in NetCDF file */
00104 
00105   /* Open NetCDF file for reading */
00106   if (outinfo == TRUE)
00107     printf("%s: Opening for reading time information in NetCDF input file %s\n", __FILE__, filename);
00108   istat = nc_open(filename, NC_NOWRITE, &ncinid);  /* open for reading */
00109   if (istat != NC_NOERR) {
00110     (void) fprintf(stderr, "%s: filename = %s\n", __FILE__, filename);
00111     handle_netcdf_error(istat, __FILE__, __LINE__);
00112   }
00113 
00114   /* Get dimensions length and ID */
00115   istat = nc_inq_dimid(ncinid, varname, &timediminid);  /* get ID for time dimension */
00116   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00117   istat = nc_inq_dimlen(ncinid, timediminid, &dimval); /* get time length */
00118   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00119   *ntime = (int) dimval;
00120 
00121   istat = nc_inq_varid(ncinid, varname, &timeinid);  /* get ID for time variable */
00122   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00123 
00124   /* Get time dimensions and type */
00125   istat = nc_inq_var(ncinid, timeinid, (char *) NULL, &vartype_time, &varndims, vardimids, (int *) NULL); /* get variable information */
00126   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00127   
00128   if (varndims != 1) {
00129     (void) fprintf(stderr, "Error NetCDF type and/or dimensions Line %d.\n", __LINE__);
00130     return -1;
00131   }
00132 
00133   /* Allocate memory and set start and count */
00134   start[0] = 0;
00135   count[0] = (size_t) (*ntime);
00136   (*timeval) = malloc((*ntime) * sizeof(double));
00137   if ((*timeval) == NULL) alloc_error(__FILE__, __LINE__);
00138 
00139   /* Read values from netCDF variable */
00140   istat = nc_get_vara_double(ncinid, timeinid, start, count, *timeval);
00141   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00142 
00143   /* Check values of time variable because many times they are all zero. In that case assume a 1 increment and a start at zero. */
00144   for (t=0; t<(*ntime); t++)
00145     if ((*timeval)[t] != 0.0)
00146       break;
00147   if (t == (*ntime)) {
00148     fprintf(stderr, "WARNING: Time variable values all zero!!! Fixing time variable to index value...\n");
00149     for (t=0; t<(*ntime); t++)
00150       (*timeval)[t] = (double) t;
00151   }
00152 
00153   /* Get time units attribute length */
00154   istat = nc_inq_attlen(ncinid, timeinid, "units", &t_len);
00155   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00156   /* Allocate required space before retrieving values */
00157   (*time_units) = (char *) malloc((t_len+1) * sizeof(char));
00158   if ((*time_units) == NULL) alloc_error(__FILE__, __LINE__);
00159   /* Get time units attribute value */
00160   istat = nc_get_att_text(ncinid, timeinid, "units", *time_units);
00161   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00162   /* Correct if time units ends incorrectly with Z */
00163   if ((*time_units)[t_len-2] == 'Z')
00164     (*time_units)[t_len-2] = '\0'; /* null terminate */
00165   else if ((*time_units)[t_len-1] == 'Z')
00166     (*time_units)[t_len-1] = '\0'; /* null terminate */
00167   else
00168     (*time_units)[t_len] = '\0';
00169 
00170   /* Get calendar type attribute length */
00171   istat = nc_inq_attlen(ncinid, timeinid, "calendar", &t_len);
00172   if (istat != NC_NOERR) {
00173     /* If not present, assume standard calendar */
00174     *cal_type = strdup("gregorian");
00175   }
00176   else {
00177     /* Allocate required space before retrieving values */
00178     (*cal_type) = (char *) malloc(t_len + 1);
00179     if ((*cal_type) == NULL) alloc_error(__FILE__, __LINE__);
00180     /* Get calendar type attribute value */
00181     istat = nc_get_att_text(ncinid, timeinid, "calendar", *cal_type);
00182     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00183     (*cal_type)[t_len] = '\0'; /* null terminate */
00184   }
00185 
00186   /* Compute time info and store into easy time structure */
00187   time_s->year = (int *) malloc((*ntime) * sizeof(int));
00188   if (time_s->year == NULL) alloc_error(__FILE__, __LINE__);
00189   time_s->month = (int *) malloc((*ntime) * sizeof(int));
00190   if (time_s->month == NULL) alloc_error(__FILE__, __LINE__);
00191   time_s->day = (int *) malloc((*ntime) * sizeof(int));
00192   if (time_s->day == NULL) alloc_error(__FILE__, __LINE__);
00193   time_s->hour = (int *) malloc((*ntime) * sizeof(int));
00194   if (time_s->hour == NULL) alloc_error(__FILE__, __LINE__);
00195   time_s->minutes = (int *) malloc((*ntime) * sizeof(int));
00196   if (time_s->minutes == NULL) alloc_error(__FILE__, __LINE__);
00197   time_s->seconds = (double *) malloc((*ntime) * sizeof(double));
00198   if (time_s->seconds == NULL) alloc_error(__FILE__, __LINE__);
00199 
00200   /* Initialize udunits */
00201   ut_set_error_message_handler(ut_ignore);
00202   unitSystem = ut_read_xml(NULL);
00203   ut_set_error_message_handler(ut_write_to_stderr);
00204 
00205   dataunits = ut_parse(unitSystem, (*time_units), UT_ASCII);
00206   for (t=0; t<(*ntime); t++) {
00207     istat = utCalendar2_cal((*timeval)[t], dataunits, &(time_s->year[t]), &(time_s->month[t]), &(time_s->day[t]),
00208                             &(time_s->hour[t]), &(time_s->minutes[t]), &(time_s->seconds[t]), *cal_type);
00209     if (istat < 0) {
00210       (void) ut_free(dataunits);
00211       (void) ut_free_system(unitSystem);  
00212       return -1;
00213     }
00214   }
00215 
00216   (void) ut_free(dataunits);
00217   (void) ut_free_system(unitSystem);  
00218 
00220   istat = ncclose(ncinid);
00221   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00222 
00223   /* Success status */
00224   return 0;
00225 }

Generated on 12 May 2016 for DSCLIM by  doxygen 1.6.1