read_netcdf_dims_3d.c

Go to the documentation of this file.
00001 /* ***************************************************** */
00002 /* read_netcdf_dims_3d Read NetCDF dimensions.           */
00003 /* read_netcdf_dims_3d.c                                 */
00004 /* ***************************************************** */
00005 /* Author: Christian Page, CERFACS, Toulouse, France.    */
00006 /* ***************************************************** */
00007 /* Date of creation: sep 2008                            */
00008 /* Last date of modification: sep 2008                   */
00009 /* ***************************************************** */
00010 /* Original version: 1.0                                 */
00011 /* Current revision:                                     */
00012 /* ***************************************************** */
00013 /* Revisions                                             */
00014 /* ***************************************************** */
00019 /* LICENSE BEGIN
00020 
00021 Copyright Cerfacs (Christian Page) (2015)
00022 
00023 christian.page@cerfacs.fr
00024 
00025 This software is a computer program whose purpose is to downscale climate
00026 scenarios using a statistical methodology based on weather regimes.
00027 
00028 This software is governed by the CeCILL license under French law and
00029 abiding by the rules of distribution of free software. You can use, 
00030 modify and/ or redistribute the software under the terms of the CeCILL
00031 license as circulated by CEA, CNRS and INRIA at the following URL
00032 "http://www.cecill.info". 
00033 
00034 As a counterpart to the access to the source code and rights to copy,
00035 modify and redistribute granted by the license, users are provided only
00036 with a limited warranty and the software's author, the holder of the
00037 economic rights, and the successive licensors have only limited
00038 liability. 
00039 
00040 In this respect, the user's attention is drawn to the risks associated
00041 with loading, using, modifying and/or developing or reproducing the
00042 software by the user in light of its specific status of free software,
00043 that may mean that it is complicated to manipulate, and that also
00044 therefore means that it is reserved for developers and experienced
00045 professionals having in-depth computer knowledge. Users are therefore
00046 encouraged to load and test the software's suitability as regards their
00047 requirements in conditions enabling the security of their systems and/or 
00048 data to be ensured and, more generally, to use and operate it in the 
00049 same conditions as regards security. 
00050 
00051 The fact that you are presently reading this means that you have had
00052 knowledge of the CeCILL license and that you accept its terms.
00053 
00054 LICENSE END */
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 #include <io.h>
00063 
00065 int
00066 read_netcdf_dims_3d(double **lon, double **lat, double **timeval, char **cal_type, char **time_units,
00067                     int *nlon, int *nlat, int *ntime, info_struct *info, char *coords, char *gridname,
00068                     char *lonname, char *latname, char *dimxname, char *dimyname, char *timename, char *filename) {
00091   int istat; /* Diagnostic status */
00092   int fixtime = FALSE; /* If we fixed time or not */
00093 
00094   size_t dimval; /* Variable used to retrieve dimension length */
00095 
00096   int ncinid; /* NetCDF input file handle ID */
00097   int latinid; /* Latitude variable ID */
00098   int loninid; /* Longitude variable ID */
00099   int timeinid; /* Time variable ID */
00100   nc_type vartype; /* Type of the variable (NC_FLOAT, NC_DOUBLE, etc.) */
00101   int varndims; /* Number of dimensions of variable */
00102   int vardimids[NC_MAX_VAR_DIMS]; /* Variable dimension ids */
00103   int timediminid; /* Time dimension ID */
00104   int londiminid; /* Longitude dimension ID */
00105   int latdiminid; /* Latitude dimension ID */
00106 
00107   size_t start[3]; /* Start position to read */
00108   size_t count[3]; /* Number of elements to read */
00109 
00110   double *tmpd = NULL; /* Temporary buffer to read variable from NetCDF file */
00111 
00112   int i; /* Loop counter */
00113   int j; /* Loop counter */
00114   int t; /* Time loop counter */
00115   int ndims; /* Number of dimensions of latitude and longitude variables, 1 or 2 for 1D and 2D respectively */
00116 
00117   /* Read data in NetCDF file */
00118 
00119   /* Open NetCDF file for reading */
00120   printf("%s: Reading info from NetCDF input file %s\n", __FILE__, filename);
00121   istat = nc_open(filename, NC_NOWRITE, &ncinid);  /* open for reading */
00122   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00123 
00124   /* Get dimensions ID */
00125   istat = nc_inq_dimid(ncinid, timename, &timediminid);  /* get ID for time dimension */
00126   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00127   istat = nc_inq_dimlen(ncinid, timediminid, &dimval); /* get time length */
00128   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00129   *ntime = (int) dimval;
00130 
00131   if ( !strcmp(coords, "1D") ) {
00133     ndims = 1;
00134 
00135     /* Get dimensions length */
00136     istat = nc_inq_dimid(ncinid, dimyname, &latdiminid);  /* get ID for lat dimension */
00137     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00138     istat = nc_inq_dimlen(ncinid, latdiminid, &dimval); /* get lat length */
00139     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00140     *nlat = (int) dimval;
00141     
00142     istat = nc_inq_dimid(ncinid, dimxname, &londiminid);  /* get ID for lon dimension */
00143     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00144     istat = nc_inq_dimlen(ncinid, londiminid, &dimval); /* get lon length */
00145     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00146     *nlon = (int) dimval;
00147   }
00148   else if ( !strcmp(coords, "2D") && !strcmp(gridname, "Latitude_Longitude") ) {
00150     ndims = 2;
00151 
00152     /* Get dimensions length */
00153     istat = nc_inq_dimid(ncinid, dimyname, &latdiminid);  /* get ID for lat dimension */
00154     if (istat != NC_NOERR) {
00155       (void) fprintf(stderr, "%s: Dimension name %s.\n", __FILE__, dimyname);
00156       handle_netcdf_error(istat, __FILE__, __LINE__);
00157     }
00158     istat = nc_inq_dimlen(ncinid, latdiminid, &dimval); /* get lat length */
00159     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00160     *nlat = (int) dimval;
00161     
00162     istat = nc_inq_dimid(ncinid, dimxname, &londiminid);  /* get ID for lon dimension */
00163     if (istat != NC_NOERR) {
00164       (void) fprintf(stderr, "%s: Dimension name %s.\n", __FILE__, dimxname);
00165       handle_netcdf_error(istat, __FILE__, __LINE__);
00166     }
00167     istat = nc_inq_dimlen(ncinid, londiminid, &dimval); /* get lon length */
00168     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00169     *nlon = (int) dimval;
00170   }
00171   else {
00173     ndims = 2;
00174 
00175     /* Get dimensions length */
00176     istat = nc_inq_dimid(ncinid, "y", &latdiminid);  /* get ID for lat dimension */
00177     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00178     istat = nc_inq_dimlen(ncinid, latdiminid, &dimval); /* get lat length */
00179     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00180     *nlat = (int) dimval;
00181     
00182     istat = nc_inq_dimid(ncinid, "x", &londiminid);  /* get ID for lon dimension */
00183     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00184     istat = nc_inq_dimlen(ncinid, londiminid, &dimval); /* get lon length */
00185     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00186     *nlon = (int) dimval;
00187   }
00188   
00189   /* Get time dimension ID */
00190   istat = nc_inq_varid(ncinid, timename, &timeinid);  /* get ID for time variable */
00191   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00192   /* Get time dimensions and type */
00193   istat = nc_inq_var(ncinid, timeinid, (char *) NULL, &vartype, &varndims, vardimids, (int *) NULL); /* get variable information */
00194   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00195   if (varndims != 1) {
00196     (void) fprintf(stderr, "Error NetCDF type and/or dimensions %d != 1.\n", varndims);
00197     istat = ncclose(ncinid);
00198     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00199     return -1;
00200   }
00201 
00202   /* Get dimension ID */
00203   istat = nc_inq_varid(ncinid, latname, &latinid);  /* get ID for lat variable */
00204   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00205   /* Get lat dimensions and type */
00206   istat = nc_inq_var(ncinid, latinid, (char *) NULL, &vartype, &varndims, vardimids, (int *) NULL); /* get variable information */
00207   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);  
00208   if (varndims != ndims) {
00209     (void) fprintf(stderr, "Error NetCDF type and/or dimensions %d != %d.\n", varndims, ndims);
00210     istat = ncclose(ncinid);
00211     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00212     return -1;
00213   }
00214 
00215   /* Get dimension ID */
00216   istat = nc_inq_varid(ncinid, lonname, &loninid);  /* get ID for lon variable */
00217   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00218   /* Get lat dimensions and type */
00219   istat = nc_inq_var(ncinid, loninid, (char *) NULL, &vartype, &varndims, vardimids, (int *) NULL); /* get variable information */
00220   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);  
00221   if (varndims != ndims) {
00222     (void) fprintf(stderr, "Error NetCDF type and/or dimensions %d != %d.\n", varndims, ndims);
00223     istat = ncclose(ncinid);
00224     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00225     return -1;
00226   }
00227 
00228   /* Get time units attributes */
00229   (void) get_attribute_str(time_units, ncinid, timeinid, "units");
00230   (void) get_attribute_str(cal_type, ncinid, timeinid, "calendar");
00231   if ( (*cal_type)[0] == '\0' ) {
00232     (void) free(*cal_type);
00233     (*cal_type) = strdup("standard");
00234   }
00235 
00236   /* Get global attributes */
00237   if (info->title == NULL) {
00238     (void) get_attribute_str(&(info->title), ncinid, NC_GLOBAL, "title");
00239     (void) get_attribute_str(&(info->title_french), ncinid, NC_GLOBAL, "title_french");
00240     (void) get_attribute_str(&(info->summary), ncinid, NC_GLOBAL, "summary");
00241     (void) get_attribute_str(&(info->summary_french), ncinid, NC_GLOBAL, "summary_french");
00242     (void) get_attribute_str(&(info->keywords), ncinid, NC_GLOBAL, "keywords");
00243     (void) get_attribute_str(&(info->processor), ncinid, NC_GLOBAL, "processor");
00244     (void) get_attribute_str(&(info->description), ncinid, NC_GLOBAL, "description");
00245     (void) get_attribute_str(&(info->institution), ncinid, NC_GLOBAL, "institution");
00246     (void) get_attribute_str(&(info->creator_email), ncinid, NC_GLOBAL, "creator_email");
00247     (void) get_attribute_str(&(info->creator_url), ncinid, NC_GLOBAL, "creator_url");
00248     (void) get_attribute_str(&(info->creator_name), ncinid, NC_GLOBAL, "creator_name");
00249     (void) get_attribute_str(&(info->version), ncinid, NC_GLOBAL, "version");
00250     (void) get_attribute_str(&(info->scenario), ncinid, NC_GLOBAL, "scenario");
00251     (void) get_attribute_str(&(info->scenario_co2), ncinid, NC_GLOBAL, "scenario_co2");
00252     (void) get_attribute_str(&(info->model), ncinid, NC_GLOBAL, "model");
00253     (void) get_attribute_str(&(info->institution_model), ncinid, NC_GLOBAL, "institution_model");
00254     (void) get_attribute_str(&(info->country), ncinid, NC_GLOBAL, "country");
00255     (void) get_attribute_str(&(info->member), ncinid, NC_GLOBAL, "member");
00256     (void) get_attribute_str(&(info->downscaling_forcing), ncinid, NC_GLOBAL, "downscaling_forcing");
00257     (void) get_attribute_str(&(info->timestep), ncinid, NC_GLOBAL, "timestep");
00258     (void) get_attribute_str(&(info->contact_email), ncinid, NC_GLOBAL, "contact_email");
00259     (void) get_attribute_str(&(info->contact_name), ncinid, NC_GLOBAL, "contact_name");
00260     (void) get_attribute_str(&(info->other_contact_email), ncinid, NC_GLOBAL, "other_contact_email");
00261     (void) get_attribute_str(&(info->other_contact_name), ncinid, NC_GLOBAL, "other_contact_name");
00262   }
00263 
00265   if ( !strcmp(coords, "1D") ) {
00266     /* Allocate memory and set start and count */
00267     start[0] = 0;
00268     start[1] = 0;
00269     start[2] = 0;
00270     count[0] = (size_t) (*nlat);
00271     count[1] = 0;
00272     count[2] = 0;
00273     (*lat) = (double *) malloc((*nlat) * (*nlon) * sizeof(double));
00274     if ((*lat) == NULL) alloc_error(__FILE__, __LINE__);
00275     tmpd = (double *) malloc((*nlat) * sizeof(double));
00276     if (tmpd == NULL) alloc_error(__FILE__, __LINE__);
00277     
00278     /* Read values from netCDF variable */
00279     istat = nc_get_vara_double(ncinid, latinid, start, count, tmpd);
00280     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00281     for (j=0; j<(*nlat); j++)
00282       for (i=0; i<(*nlon); i++)
00283         (*lat)[i+j*(*nlon)] = tmpd[j];
00284     
00285     /* Allocate memory and set start and count */
00286     start[0] = 0;
00287     start[1] = 0;
00288     start[2] = 0;
00289     count[0] = (size_t) (*nlon);
00290     count[1] = 0;
00291     count[2] = 0;
00292     (*lon) = (double *) malloc((*nlat) * (*nlon) * sizeof(double));
00293     if ((*lon) == NULL) alloc_error(__FILE__, __LINE__);
00294     tmpd = (double *) realloc(tmpd, (*nlon) * sizeof(double));
00295     if (tmpd == NULL) alloc_error(__FILE__, __LINE__);
00296     
00297     /* Read values from netCDF variable */
00298     istat = nc_get_vara_double(ncinid, loninid, start, count, tmpd);
00299     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00300     for (j=0; j<(*nlat); j++)
00301       for (i=0; i<(*nlon); i++)
00302         (*lon)[i+j*(*nlon)] = tmpd[i];
00303 
00304     (void) free(tmpd);
00305     
00306   }
00307   else {  
00308     /* Allocate memory and set start and count */
00309     start[0] = 0;
00310     start[1] = 0;
00311     start[2] = 0;
00312     count[0] = (size_t) (*nlat);
00313     count[1] = (size_t) (*nlon);
00314     count[2] = 0;
00315     (*lat) = (double *) malloc((*nlat) * (*nlon) * sizeof(double));
00316     if ((*lat) == NULL) alloc_error(__FILE__, __LINE__);
00317     
00318     /* Read values from netCDF variable */
00319     istat = nc_get_vara_double(ncinid, latinid, start, count, (*lat));
00320     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00321     
00322     /* Allocate memory and set start and count */
00323     start[0] = 0;
00324     start[1] = 0;
00325     start[2] = 0;
00326     count[0] = (size_t) (*nlat);
00327     count[1] = (size_t) (*nlon);
00328     count[2] = 0;
00329     (*lon) = (double *) malloc((*nlat) * (*nlon) * sizeof(double));
00330     if ((*lon) == NULL) alloc_error(__FILE__, __LINE__);
00331     
00332     /* Read values from netCDF variable */
00333     istat = nc_get_vara_double(ncinid, loninid, start, count, (*lon));
00334     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00335   }
00336 
00337   /* Allocate memory and set start and count */
00338   start[0] = 0;
00339   count[0] = (size_t) (*ntime);
00340   (*timeval) = malloc((*ntime) * sizeof(double));
00341   if ((*timeval) == NULL) alloc_error(__FILE__, __LINE__);
00342 
00343   /* Read values from netCDF variable */
00344   istat = nc_get_vara_double(ncinid, timeinid, start, count, (*timeval));
00345   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00346 
00347   /* Check values of time variable because many times they are all zero. In that case assume a 1 increment and a start at zero. */
00348   for (t=0; t<(*ntime); t++)
00349     if ((*timeval)[t] != 0.0)
00350       break;
00351   if (t == (*ntime)) {
00352     fprintf(stderr, "\n%s: IMPORTANT WARNING: Time variable values all zero!!! Fixing time variable to index value, STARTING at 0...\n\n", __FILE__);
00353     fixtime = TRUE;
00354     for (t=0; t<(*ntime); t++)
00355       (*timeval)[t] = (double) t;
00356   }
00357 
00358   /* Close NetCDF file */
00359   istat = ncclose(ncinid);
00360   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00361 
00362   if (fixtime == FALSE)
00363     /* Success status */
00364     return 0;
00365   else
00366     return 1;
00367 }

Generated on 12 May 2016 for DSCLIM by  doxygen 1.6.1