read_large_scale_fields.c

Go to the documentation of this file.
00001 /* ***************************************************** */
00002 /* read_large_scale_fields Read large-scale fields data  */
00003 /* from input files.                                     */
00004 /* read_large_scale_fields.c                             */
00005 /* ***************************************************** */
00006 /* Author: Christian Page, CERFACS, Toulouse, France.    */
00007 /* ***************************************************** */
00008 /* Date of creation: oct 2008                            */
00009 /* Last date of modification: oct 2008                   */
00010 /* ***************************************************** */
00011 /* Original version: 1.0                                 */
00012 /* Current revision:                                     */
00013 /* ***************************************************** */
00014 /* Revisions                                             */
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 <dsclim.h>
00064 
00066 int
00067 read_large_scale_fields(data_struct *data) {
00074   int istat; /* Diagnostic status */
00075   int i; /* Loop counter */
00076   int t; /* Time loop counter */
00077   int cat; /* Field category loop counter */
00078   double *buf = NULL; /* Temporary data buffer */
00079   double *time_ls = NULL; /* Temporary time information buffer */
00080   double *lat = NULL; /* Temporary latitude buffer for main large-scale fields */
00081   double *lon = NULL; /* Temporary longitude buffer for main large-scale fields */
00082   char **cal_type; /* Calendar type (udunits) */
00083   char **time_units; /* Time units (udunits) */
00084   double longitude_min; /* Domain bounding box minimum longitude */
00085   double longitude_max; /* Domain bounding box maximum longitude */
00086   double latitude_min; /* Domain bounding box minimum latitude */
00087   double latitude_max; /* Domain bounding box maximum latitude */
00088   int ntime; /* Number of times dimension */
00089   int nlon; /* Longitude dimension for main large-scale fields */
00090   int nlat; /* Latitude dimension for main large-scale fields */
00091   int ntime_file; /* Number of times dimension in input file */
00092   int nlon_file; /* Longitude dimension for main large-scale fields in input file */
00093   int nlat_file; /* Latitude dimension for main large-scale fields in input file */
00094   
00095   int year_begin; /* When fixing time units, year to use as start date. */
00096 
00097   cal_type = (char **) malloc(NCAT * sizeof(char *));
00098   if (cal_type == NULL) alloc_error(__FILE__, __LINE__);
00099   time_units = (char **) malloc(NCAT * sizeof(char *));
00100   if (time_units == NULL) alloc_error(__FILE__, __LINE__);
00101 
00102   /* Loop over all large-scale field categories */
00103   for (cat=0; cat<NCAT; cat++) {
00104 
00105     cal_type[cat] = NULL;
00106     time_units[cat] = NULL;
00107 
00108     /* Select proper domain given large-scale field category */
00109     if (cat == 0 || cat == 1) {
00110       longitude_min = data->conf->longitude_min;
00111       longitude_max = data->conf->longitude_max;
00112       latitude_min = data->conf->latitude_min;
00113       latitude_max = data->conf->latitude_max;
00114     }
00115     else {
00116       longitude_min = data->conf->secondary_longitude_min;
00117       longitude_max = data->conf->secondary_longitude_max;
00118       latitude_min = data->conf->secondary_latitude_min;
00119       latitude_max = data->conf->secondary_latitude_max;
00120     }
00121 
00122     /* Free memory for loop and set pointers to NULL for realloc */
00123     if (data->field[cat].time_ls != NULL) {
00124       (void) free(data->field[cat].time_ls);
00125       data->field[cat].time_ls = NULL;
00126     }
00127     if (data->field[cat].lat_ls != NULL) {
00128       (void) free(data->field[cat].lat_ls);
00129       data->field[cat].lat_ls = NULL;
00130     }
00131     if (data->field[cat].lon_ls != NULL)  {
00132       (void) free(data->field[cat].lon_ls);
00133       data->field[cat].lon_ls = NULL;
00134     }
00135 
00136     /* Loop over large-scale fields */
00137     for (i=0; i<data->field[cat].n_ls; i++) {
00138       /* Retrieve dimensions if time buffer is not already set for this field category */
00139       if (data->field[cat].time_ls == NULL) {
00140         istat = read_netcdf_dims_3d(&lon, &lat, &time_ls, &(cal_type[cat]), &(time_units[cat]), &nlon, &nlat, &ntime,
00141                                     data->info, data->field[cat].proj[i].coords, data->field[cat].proj[i].name,
00142                                     data->field[cat].data[i].lonname, data->field[cat].data[i].latname,
00143                                     data->field[cat].data[i].dimxname, data->field[cat].data[i].dimyname,
00144                                     data->field[cat].data[i].timename,
00145                                     data->field[cat].data[i].filename_ls);
00146         if (istat < 0) {
00147           /* In case of failure */
00148           (void) free(lon);
00149           (void) free(lat);
00150           (void) free(time_ls);
00151           (void) free(time_units[cat]);
00152           (void) free(cal_type[cat]);
00153           return istat;
00154         }
00155         /* Adjust time units if we want to fix time (set in the configuration file) */
00156         if (data->conf->fixtime == TRUE) {
00157           if (cat == FIELD_LS || cat == SEC_FIELD_LS)
00158             year_begin = data->conf->year_begin_other;
00159           else
00160             year_begin = data->conf->year_begin_ctrl;
00161           if (istat != 1) {
00162             (void) fprintf(stderr, "\n%s: IMPORTANT WARNING: Time variable values all zero!!! Fixing time variable to index value, STARTING at 0...\n\n", __FILE__);
00163             for (t=0; t<ntime; t++)
00164               time_ls[t] = (double) t;
00165           }
00166           (void) fprintf(stdout, "%s: Fixing time units using start date %d-01-01 12:00:00.\n", __FILE__, year_begin);
00167           time_units[cat] = realloc(time_units[cat], 500 * sizeof(char));
00168           if (time_units[cat] == NULL) alloc_error(__FILE__, __LINE__);
00169           /* days since 1950-01-01 12:00:00 */
00170           (void) sprintf(time_units[cat], "days since %d-01-01 12:00:00", year_begin);
00171         }
00172       }
00173 
00174       /* For standard calendar data */
00175       if ( !strcmp(cal_type[cat], "gregorian") || !strcmp(cal_type[cat], "standard") ) {
00176         
00177         /* Read data */
00178         istat = read_netcdf_var_3d(&buf, data->field[cat].data[i].info, &(data->field[cat].proj[i]),
00179                                    data->field[cat].data[i].filename_ls,
00180                                    data->field[cat].data[i].nomvar_ls,
00181                                    data->field[cat].data[i].dimxname, data->field[cat].data[i].dimyname, data->field[cat].data[i].timename,
00182                                    &nlon_file, &nlat_file, &ntime_file, TRUE);
00183         if (nlon != nlon_file || nlat != nlat_file || ntime != ntime_file) {
00184           (void) fprintf(stderr, "%s: Problems in dimensions! nlat=%d nlat_file=%d nlon=%d nlon_file=%d ntime=%d ntime_file=%d\n",
00185                          __FILE__, nlat, nlat_file, nlon, nlon_file, ntime, ntime_file);
00186           istat = -1;
00187         }
00188         if (istat != 0) {
00189           /* In case of failure */
00190           (void) free(buf);
00191           (void) free(lon);
00192           (void) free(lat);
00193           (void) free(time_ls);
00194           (void) free(time_units[cat]);
00195           (void) free(cal_type[cat]);
00196           return istat;
00197         }
00198         
00199         /* Extract subdomain of spatial fields */
00200         if (data->field[cat].lon_ls != NULL) {
00201           (void) free(data->field[cat].lon_ls);
00202           data->field[cat].lon_ls = NULL;
00203         }
00204         if (data->field[cat].lat_ls != NULL) {
00205           (void) free(data->field[cat].lat_ls);
00206           data->field[cat].lat_ls = NULL;
00207         }
00208         if (data->field[cat].data[i].field_ls != NULL) {
00209           (void) free(data->field[cat].data[i].field_ls);
00210           data->field[cat].data[i].field_ls = NULL;
00211         }
00212 
00213         /* Extraction of subdomain */
00214         (void) extract_subdomain(&(data->field[cat].data[i].field_ls), &(data->field[cat].lon_ls), &(data->field[cat].lat_ls),
00215                                  &(data->field[cat].nlon_ls), &(data->field[cat].nlat_ls), buf, lon, lat,
00216                                  longitude_min, longitude_max, latitude_min, latitude_max, nlon, nlat, ntime);
00217         (void) free(buf);
00218 
00219         /* Save number of times dimension */
00220         data->field[cat].ntime_ls = ntime;
00221 
00222         /* If time info not already retrieved for this category, get time information and generate time structure */
00223         if (data->field[cat].time_ls == NULL) {
00224           data->field[cat].time_ls = (double *) malloc(data->field[cat].ntime_ls * sizeof(double));
00225           if (data->field[cat].time_ls == NULL) alloc_error(__FILE__, __LINE__);
00226           if ( strcmp(time_units[cat], data->conf->time_units) )
00227             (void) change_date_origin(data->field[cat].time_ls, data->conf->time_units, time_ls, time_units[cat], ntime);
00228           else
00229             for (t=0; t<data->field[cat].ntime_ls; t++)
00230               data->field[cat].time_ls[t] = time_ls[t];
00231           istat = compute_time_info(data->field[cat].time_s, data->field[cat].time_ls, data->conf->time_units, data->conf->cal_type,
00232                                     data->field[cat].ntime_ls);
00233         }
00234       }
00235       else {
00236         /* Non-standard calendar type */
00237 
00238         double *dummy = NULL;
00239 
00240         /* Free memory if previously allocated */
00241         if (data->field[cat].lon_ls != NULL) {
00242           (void) free(data->field[cat].lon_ls);
00243           data->field[cat].lon_ls = NULL;
00244         }
00245         if (data->field[cat].lat_ls != NULL) {
00246           (void) free(data->field[cat].lat_ls);
00247           data->field[cat].lat_ls = NULL;
00248         }
00249         if (data->field[cat].data[i].field_ls != NULL) {
00250           (void) free(data->field[cat].data[i].field_ls);
00251           data->field[cat].data[i].field_ls = NULL;
00252         }
00253         /* Read data and fix calendar */
00254         istat = read_netcdf_var_3d(&(data->field[cat].data[i].field_ls), data->field[cat].data[i].info,
00255                                    &(data->field[cat].proj[i]), data->field[cat].data[i].filename_ls,
00256                                    data->field[cat].data[i].nomvar_ls,
00257                                    data->field[cat].data[i].dimxname, data->field[cat].data[i].dimyname, data->field[cat].data[i].timename,
00258                                    &nlon_file, &nlat_file, &ntime_file, TRUE);
00259         if (nlon != nlon_file || nlat != nlat_file || ntime != ntime_file) {
00260           (void) fprintf(stderr, "%s: Problems in dimensions! nlat=%d nlat_file=%d nlon=%d nlon_file=%d ntime=%d ntime_file=%d\n",
00261                          __FILE__, nlat, nlat_file, nlon, nlon_file, ntime, ntime_file);
00262           istat = -1;
00263         }
00264         if (istat != 0) {
00265           /* In case of failure */
00266           (void) free(lon);
00267           (void) free(lat);
00268           (void) free(time_ls);
00269           (void) free(time_units[cat]);
00270           (void) free(cal_type[cat]);
00271           return istat;
00272         }
00273 
00274         /* Extract subdomain of spatial fields */
00275         (void) extract_subdomain(&buf, &(data->field[cat].lon_ls), &(data->field[cat].lat_ls),
00276                                  &(data->field[cat].nlon_ls), &(data->field[cat].nlat_ls), data->field[cat].data[i].field_ls, lon, lat,
00277                                  longitude_min, longitude_max, latitude_min, latitude_max, nlon, nlat, ntime);
00278         (void) free(data->field[cat].data[i].field_ls);
00279 
00280         /* Adjust calendar to standard calendar */
00281         istat = data_to_gregorian_cal_d(&(data->field[cat].data[i].field_ls), &dummy, &(data->field[cat].ntime_ls),
00282                                         buf, time_ls, time_units[cat], data->conf->time_units,
00283                                         cal_type[cat], data->field[cat].nlon_ls, data->field[cat].nlat_ls, ntime);
00284         if (istat < 0) {
00285           /* In case of failure */
00286           (void) free(lon);
00287           (void) free(lat);
00288           (void) free(time_ls);
00289           (void) free(time_units[cat]);
00290           (void) free(cal_type[cat]);
00291           (void) free(buf);
00292           (void) free(data->field[cat].lon_ls);
00293           (void) free(data->field[cat].lat_ls);
00294           (void) free(data->field[cat].data[i].field_ls);
00295           return istat;
00296         }
00297         if (data->field[cat].time_ls == NULL) {
00298           data->field[cat].time_ls = (double *) malloc(data->field[cat].ntime_ls * sizeof(double));
00299           if (data->field[cat].time_ls == NULL) alloc_error(__FILE__, __LINE__);
00300           for (t=0; t<data->field[cat].ntime_ls; t++)
00301             data->field[cat].time_ls[t] = dummy[t];
00302           istat = compute_time_info(data->field[cat].time_s, data->field[cat].time_ls, data->conf->time_units, data->conf->cal_type,
00303                                     data->field[cat].ntime_ls);
00304         }
00305         (void) free(dummy);
00306         (void) free(buf);
00307       }
00308     }
00309     /* Free memory */
00310     if (lat != NULL) {
00311       (void) free(lat);
00312       lat = NULL;
00313     }
00314     if (lon != NULL) {
00315       (void) free(lon);
00316       lon = NULL;
00317     }
00318     if (time_ls != NULL) {
00319       (void) free(time_ls);
00320       time_ls = NULL;
00321     }
00322     if (time_units[cat] != NULL) {
00323       (void) free(time_units[cat]);
00324       time_units[cat] = NULL;
00325     }
00326     if (cal_type[cat] != NULL) {
00327       (void) free(cal_type[cat]);
00328       cal_type[cat] = NULL;
00329     }
00330   }
00331 
00332   (void) free(time_units);
00333   (void) free(cal_type);
00334 
00335   /* Diagnostic status */
00336   return 0;
00337 }

Generated on 12 May 2016 for DSCLIM by  doxygen 1.6.1