data_to_gregorian_cal.c

Go to the documentation of this file.
00001 /* ***************************************************** */
00002 /* Convert 2D data stored in 360-days or no-leap         */
00003 /* calendars to standard Gregorian calendar.             */
00004 /* data_to_gregorian_cal.c                               */
00005 /* ***************************************************** */
00006 /* Author: Christian Page, CERFACS, Toulouse, France.    */
00007 /* ***************************************************** */
00008 /* Date of creation: oct 2008                            */
00009 /* Last date of modification: dec 2012                   */
00010 /* ***************************************************** */
00011 /* Original version: 1.0                                 */
00012 /* Current revision: 1.2                                 */
00013 /* ***************************************************** */
00014 /* Revisions                                             */
00015 /* 1.2: Fix bug with 360_day calendar and missing Dec 31 */
00016 /* 1.1: Updated for utCalendar2_cal (udunits2)           */
00017 /* ***************************************************** */
00022 /* LICENSE BEGIN
00023 
00024 Copyright Cerfacs (Christian Page) (2015)
00025 
00026 christian.page@cerfacs.fr
00027 
00028 This software is a computer program whose purpose is to downscale climate
00029 scenarios using a statistical methodology based on weather regimes.
00030 
00031 This software is governed by the CeCILL license under French law and
00032 abiding by the rules of distribution of free software. You can use, 
00033 modify and/ or redistribute the software under the terms of the CeCILL
00034 license as circulated by CEA, CNRS and INRIA at the following URL
00035 "http://www.cecill.info". 
00036 
00037 As a counterpart to the access to the source code and rights to copy,
00038 modify and redistribute granted by the license, users are provided only
00039 with a limited warranty and the software's author, the holder of the
00040 economic rights, and the successive licensors have only limited
00041 liability. 
00042 
00043 In this respect, the user's attention is drawn to the risks associated
00044 with loading, using, modifying and/or developing or reproducing the
00045 software by the user in light of its specific status of free software,
00046 that may mean that it is complicated to manipulate, and that also
00047 therefore means that it is reserved for developers and experienced
00048 professionals having in-depth computer knowledge. Users are therefore
00049 encouraged to load and test the software's suitability as regards their
00050 requirements in conditions enabling the security of their systems and/or 
00051 data to be ensured and, more generally, to use and operate it in the 
00052 same conditions as regards security. 
00053 
00054 The fact that you are presently reading this means that you have had
00055 knowledge of the CeCILL license and that you accept its terms.
00056 
00057 LICENSE END */
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 #include <utils.h>
00066 
00068 int
00069 data_to_gregorian_cal_d(double **bufout, double **outtimeval, int *ntimeout, double *bufin,
00070                         double *intimeval, char *tunits_in, char *tunits_out, char *cal_type, int ni, int nj, int ntimein) {
00085   ut_unit *timeslice; /* Time slicing used to compute the new standard calendar */
00086   double val; /* Temporary value */
00087   double curtime; /* Current time */
00088   double ccurtime; /* Current time in non-standard calendar */
00089   
00090   int ref_year; /* A given year */
00091   int ref_month; /* A given month */
00092   int ref_day; /* A given day */
00093   int ref_hour; /* A given hour */
00094   int ref_minutes; /* A given minute */
00095   float ref_seconds; /* A given second */
00096 
00097   int t; /* Time loop counter */
00098   int tt; /* Time loop counter */
00099   int i; /* Loop counter */
00100   int j; /* Loop counter */
00101   int istat; /* Diagnostic status */
00102 
00103   char *utstring = NULL; /* Time unit string */
00104   ut_system *unitSystem = NULL; /* Unit System (udunits) */
00105   ut_unit *dataunit_in = NULL; /* Input data units (udunits) */
00106   ut_unit *dataunit_out = NULL; /* Output data units (udunits) */
00107   cv_converter *conv_in = NULL; /* Converter for time units (udunits) */
00108   ut_unit *tunit = NULL; /* For calculation of offset by time to Epoch */
00109   ut_unit *usecond = NULL; /* Unit of second handle */
00110   double sec_int, sec_intm1; /* Number of seconds since Epoch */
00111 
00112   int *year = NULL; /* Year time vector */
00113   int *month = NULL; /* Month time vector */
00114   int *day = NULL; /* Day time vector */
00115   int *hour = NULL; /* Hour time vector */
00116   int *minutes = NULL; /* Minutes time vector */
00117   double *seconds = NULL; /* Seconds time vector */
00118 
00119   int cyear; /* A given year */
00120   int cmonth; /* A given month */
00121   int cday; /* A given day */
00122   int chour; /* A given hour */
00123   int cminutes; /* A given minute */
00124   double cseconds; /* A given second */
00125 
00126   int sup = 0; /* To indicate supplemental duplicated timestep for end of period out of weird calendars like 360_day */
00127 
00128   /* Initializing */
00129   *bufout = NULL;
00130   *outtimeval = NULL;
00131   *ntimeout = 0;
00132 
00134   if ( !strcmp(cal_type, "standard") || !strcmp(cal_type, "gregorian") ) {
00135     *ntimeout = ntimein;
00136     /* Allocate memory */
00137     (*bufout) = (double *) malloc(ni*nj*(*ntimeout) * sizeof(double));
00138     if ( (*bufout) == NULL) alloc_error(__FILE__, __LINE__);
00139     (*outtimeval) = (double *) malloc((*ntimeout) * sizeof(double));
00140     if ( (*outtimeval) == NULL) alloc_error(__FILE__, __LINE__);
00141 
00142     /* Loop over all times and gridpoints */
00143     for (t=0; t<(*ntimeout); t++) {
00144       for (j=0; j<nj; j++)
00145         for (i=0; i<ni; i++)
00146           /* Get value */
00147           (*bufout)[i+j*ni+t*ni*nj] = (double) bufin[i+j*ni+t*ni*nj];
00148       /* Construct time vector */
00149       (*outtimeval)[t] = (double) intimeval[t];
00150     }
00151   }
00152   else {
00155     /* Allocate memory */
00156     year = (int *) malloc(ntimein * sizeof(int));
00157     if (year == NULL) alloc_error(__FILE__, __LINE__);
00158     month = (int *) malloc(ntimein * sizeof(int));
00159     if (month == NULL) alloc_error(__FILE__, __LINE__);
00160     day = (int *) malloc(ntimein * sizeof(int));
00161     if (day == NULL) alloc_error(__FILE__, __LINE__);
00162     hour = (int *) malloc(ntimein * sizeof(int));
00163     if (hour == NULL) alloc_error(__FILE__, __LINE__);
00164     minutes = (int *) malloc(ntimein * sizeof(int));
00165     if (minutes == NULL) alloc_error(__FILE__, __LINE__);
00166     seconds = (double *) malloc(ntimein * sizeof(double));
00167     if (seconds == NULL) alloc_error(__FILE__, __LINE__);
00168 
00169     /* Initialize udunits */
00170     ut_set_error_message_handler(ut_ignore);
00171     unitSystem = ut_read_xml(NULL);
00172     ut_set_error_message_handler(ut_write_to_stderr);
00173 
00174     /* Generate time units strings */
00175     dataunit_in = ut_parse(unitSystem, tunits_in, UT_ASCII);
00176     dataunit_out = ut_parse(unitSystem, tunits_out, UT_ASCII);
00177 
00178     /* Loop over all times */
00179     for (t=0; t<ntimein; t++) {
00180       /* Calculate date using non-standard calendar */
00181       istat = utCalendar2_cal(intimeval[t], dataunit_in, &(year[t]), &(month[t]), &(day[t]), &(hour[t]), &(minutes[t]), &(seconds[t]),
00182                               cal_type);
00183       if (istat < 0) {
00184         (void) free(year);
00185         (void) free(month);
00186         (void) free(day);
00187         (void) free(hour);
00188         (void) free(minutes);
00189         (void) free(seconds);
00190         (void) ut_free(dataunit_in);
00191         (void) ut_free(dataunit_out);
00192         (void) ut_free_system(unitSystem);  
00193         return -1;
00194       }
00195 #if DEBUG > 7
00196       istat = utInvCalendar2_cal((year[t]), (month[t]), (day[t]), (hour[t]), (minutes[t]), (seconds[t]), dataunit_in, &ccurtime, cal_type);
00197       printf("%s: %d %lf %lf %d %d %d %d %d %lf\n",__FILE__,t,intimeval[t],ccurtime,year[t],month[t],day[t],hour[t],minutes[t],seconds[t]);
00198       if (istat < 0) {
00199         (void) free(year);
00200         (void) free(month);
00201         (void) free(day);
00202         (void) free(hour);
00203         (void) free(minutes);
00204         (void) free(seconds);
00205         (void) ut_free(dataunit_in);
00206         (void) ut_free(dataunit_out);
00207         (void) ut_free_system(unitSystem);  
00208         return -1;
00209       }
00210 #endif
00211       /* Check that we really have daily data */
00212       if (t > 0) {
00213         /* Prepare converter for basis seconds since Epoch */
00214         usecond = ut_get_unit_by_name(unitSystem, "second");
00215         tunit = ut_offset_by_time(usecond, ut_encode_time(1970, 1, 1, 0, 0, 0.0));
00216         /* Generate converter */
00217         conv_in = ut_get_converter(dataunit_in, tunit);
00218         /* Seconds since Epoch */
00219         sec_int = cv_convert_double(conv_in, intimeval[t]);
00220         sec_intm1 = cv_convert_double(conv_in, intimeval[t-1]);
00221         if ( (sec_int - sec_intm1) != 86400.0 ) {
00222           (void) fprintf(stderr,
00223                          "%s: Fatal error: only daily data can be an input. Found %d seconds between timesteps %d and %d!\n",
00224                          __FILE__, (int) (sec_int - sec_intm1), t-1, t);          
00225           (void) free(year);
00226           (void) free(month);
00227           (void) free(day);
00228           (void) free(hour);
00229           (void) free(minutes);
00230           (void) free(seconds);
00231           (void) ut_free(usecond);
00232           (void) ut_free(tunit);
00233           (void) ut_free(usecond);
00234           (void) ut_free(dataunit_in);
00235           (void) ut_free(dataunit_out);
00236           (void) cv_free(conv_in);
00237           (void) ut_free_system(unitSystem);
00238           return -10;
00239         }
00240       }
00241     }
00242 
00243     /* For noleap/365-day or 360-day calendar types */
00244     if ( !strcmp(cal_type, "noleap") || !strcmp(cal_type, "365_day") || !strcmp(cal_type, "360_day") ) {
00245 
00246       /* Compute the new output total timesteps (days) in a standard year */
00247       /*
00248        * NB: The following specification gives both
00249        * the start time and the sampling interval (1 day). 
00250        */
00251 
00252       /* Set 1 day as a timestep to compute number of days in standard calendar */
00253       utstring = (char *) malloc(1000 * sizeof(char));
00254       if (utstring == NULL) alloc_error(__FILE__, __LINE__);
00255       (void) sprintf(utstring, "1 day since %d-%d-%d", year[0], month[0], day[0]);
00256       timeslice = ut_parse(unitSystem, utstring, UT_ASCII);
00257       (void) free(utstring);
00258 
00259       /* Set end period date */
00260       ref_year = year[ntimein-1];
00261       ref_month = month[ntimein-1];
00262       ref_day = day[ntimein-1];
00263       /* End Dec 31st and not Dec 30th... for 360-days calendar */
00264       if (!strcmp(cal_type, "360_day") &&
00265           (ref_month == 1 || ref_month == 3 || ref_month == 5 || ref_month == 7 || ref_month == 8 || ref_month == 10 || ref_month == 12)
00266           && ref_day == 30) {
00267         ref_day = 31;
00268         sup = 1;
00269       }
00270       ref_hour = hour[ntimein-1];
00271       ref_minutes = 0;
00272       ref_seconds = 0.0;
00273     
00274       /* Get number of timesteps (days) */
00275       istat = utInvCalendar2(ref_year, ref_month, ref_day, ref_hour, ref_minutes, ref_seconds, timeslice, &val);
00276       *ntimeout = (int) val + 1;
00277 
00278       /* Allocate memory */
00279       (*bufout) = (double *) malloc(ni*nj*(*ntimeout) * sizeof(double));
00280       if ( (*bufout) == NULL) alloc_error(__FILE__, __LINE__);
00281       (*outtimeval) = (double *) malloc((*ntimeout) * sizeof(double));
00282       if ( (*outtimeval) == NULL) alloc_error(__FILE__, __LINE__);
00283 
00284       /* Set start period date */
00285       ref_year = year[0];
00286       ref_month = month[0];
00287       ref_day = day[0];
00288       ref_hour = hour[0];
00289       ref_minutes = 0;
00290       ref_seconds = 0.0;
00291 
00292       /* Loop over all times */
00293       for (t=0; t<(*ntimeout); t++) {
00294         /* Get current day */
00295         istat = utInvCalendar2(ref_year, ref_month, ref_day+t, ref_hour, ref_minutes, ref_seconds, dataunit_out, &curtime);
00296         /* Get standard calendar date from output time units */
00297         istat = utCalendar2(curtime, dataunit_out, &cyear, &cmonth, &cday, &chour, &cminutes, &cseconds);
00298         /* Get corresponding time units in special calendar type */
00299         istat = utInvCalendar2_cal(cyear, cmonth, cday, chour, cminutes, cseconds, dataunit_in, &ccurtime, cal_type);
00300         /* Find that time in the input time vector */
00301         for (tt=0; tt<ntimein; tt++) {
00302           if ((int) ccurtime == (int) intimeval[tt]) {
00303             /* Found it */
00304             for (j=0; j<nj; j++)
00305               for (i=0; i<ni; i++)
00306                 (*bufout)[i+j*ni+t*ni*nj] = (double) bufin[i+j*ni+tt*ni*nj];
00307             /* Get current day with hour, minutes and seconds at 00:00:00 */
00308             istat = utInvCalendar2(ref_year, ref_month, ref_day+t, 0, 0, 0.0, dataunit_out, &curtime);
00309             /* Construct new time vector */
00310             (*outtimeval)[t] = (double) curtime;
00311             /* Exit loop */
00312             tt = ntimein+10;
00313           }
00314         }
00315         if ( (sup == 1) && (tt < (ntimein+10)) ) {
00316           /* Copy it */
00317           for (j=0; j<nj; j++)
00318             for (i=0; i<ni; i++)
00319               (*bufout)[i+j*ni+t*ni*nj] = (double) bufin[i+j*ni+(ntimein-1)*ni*nj];
00320           /* Get current day with hour, minutes and seconds at 00:00:00 */
00321           istat = utInvCalendar2(ref_year, ref_month, ref_day+t, 0, 0, 0.0, dataunit_out, &curtime);
00322           /* Construct new time vector */
00323           (*outtimeval)[t] = (double) curtime;
00324           tt = ntimein+10;
00325         }
00326         if (tt < (ntimein+10)) {
00327           /* We didn't found the time in the input time vector... */
00328           (void) fprintf(stderr, "%s: Cannot generate new time vector!! Algorithm internal error!\n", __FILE__);
00329           (void) free(year);
00330           (void) free(month);
00331           (void) free(day);
00332           (void) free(hour);
00333           (void) free(minutes);
00334           (void) free(seconds);
00335           (void) ut_free(timeslice);
00336           (void) ut_free(dataunit_in);
00337           (void) ut_free(dataunit_out);
00338           (void) ut_free_system(unitSystem);  
00339           return -11;
00340         }
00341       }
00342     }
00343     else {
00344       /* Non-supported calendar */
00345       (void) fprintf(stderr, "%s: not-supported calendar. Sorry!\n", __FILE__);
00346       (void) free(year);
00347       (void) free(month);
00348       (void) free(day);
00349       (void) free(hour);
00350       (void) free(minutes);
00351       (void) free(seconds);
00352       (void) ut_free(dataunit_in);
00353       (void) ut_free(dataunit_out);
00354       (void) ut_free_system(unitSystem);  
00355       return -1;
00356     }
00357 
00358     /* Free memory */
00359     (void) free(year);
00360     (void) free(month);
00361     (void) free(day);
00362     (void) free(hour);
00363     (void) free(minutes);
00364     (void) free(seconds);
00365     
00366     /* Terminate udunits */
00367     (void) ut_free(dataunit_in);
00368     (void) ut_free(dataunit_out);
00369     (void) ut_free_system(unitSystem);  
00370   }
00371 
00372   /* Success status */
00373   return 0;
00374 }
00375 
00377 int
00378 data_to_gregorian_cal_f(float **bufout, double **outtimeval, int *ntimeout, float *bufin,
00379                         double *intimeval, char *tunits_in, char *tunits_out, char *cal_type, int ni, int nj, int ntimein) {
00394   ut_unit *timeslice; /* Time slicing used to compute the new standard calendar */
00395   double val; /* Temporary value */
00396   double curtime; /* Current time */
00397   double ccurtime; /* Current time in non-standard calendar */
00398   
00399   int ref_year; /* A given year */
00400   int ref_month; /* A given month */
00401   int ref_day; /* A given day */
00402   int ref_hour; /* A given hour */
00403   int ref_minutes; /* A given minute */
00404   double ref_seconds; /* A given second */
00405 
00406   int t; /* Time loop counter */
00407   int tt; /* Time loop counter */
00408   int i; /* Loop counter */
00409   int j; /* Loop counter */
00410   int istat; /* Diagnostic status */
00411 
00412   char *utstring = NULL; /* Time unit string */
00413   ut_system *unitSystem = NULL; /* Unit System (udunits) */
00414   ut_unit *dataunit_in = NULL; /* Input data units (udunits) */
00415   ut_unit *dataunit_out = NULL; /* Output data units (udunits) */
00416   cv_converter *conv_in = NULL; /* Converter for time units (udunits) */
00417   ut_unit *tunit = NULL; /* For calculation of offset by time to Epoch */
00418   ut_unit *usecond = NULL; /* Unit of second handle */
00419   double sec_int, sec_intm1; /* Number of seconds since Epoch */
00420 
00421   int *year = NULL; /* Year time vector */
00422   int *month = NULL; /* Month time vector */
00423   int *day = NULL; /* Day time vector */
00424   int *hour = NULL; /* Hour time vector */
00425   int *minutes = NULL; /* Minutes time vector */
00426   double *seconds = NULL; /* Seconds time vector */
00427 
00428   int cyear; /* A given year */
00429   int cmonth; /* A given month */
00430   int cday; /* A given day */
00431   int chour; /* A given hour */
00432   int cminutes; /* A given minute */
00433   double cseconds; /* A given second */
00434 
00435   int sup = 0; /* To indicate supplemental duplicated timestep for end of period out of weird calendars like 360_day */
00436 
00437   /* Initializing */
00438   *bufout = NULL;
00439   *outtimeval = NULL;
00440   *ntimeout = 0;
00441 
00443   if ( !strcmp(cal_type, "standard") || !strcmp(cal_type, "gregorian") ) {
00444     *ntimeout = ntimein;
00445     /* Allocate memory */
00446     (*bufout) = (float *) malloc(ni*nj*(*ntimeout) * sizeof(float));
00447     if ( (*bufout) == NULL) alloc_error(__FILE__, __LINE__);
00448     (*outtimeval) = (double *) malloc((*ntimeout) * sizeof(double));
00449     if ( (*outtimeval) == NULL) alloc_error(__FILE__, __LINE__);
00450 
00451     /* Loop over all times and gridpoints */
00452     for (t=0; t<(*ntimeout); t++) {
00453       for (j=0; j<nj; j++)
00454         for (i=0; i<ni; i++)
00455           /* Get value */
00456           (*bufout)[i+j*ni+t*ni*nj] = (float) bufin[i+j*ni+t*ni*nj];
00457       /* Construct time vector */
00458       (*outtimeval)[t] = (double) intimeval[t];
00459     }
00460   }
00461   else {
00464     /* Allocate memory */
00465     year = (int *) malloc(ntimein * sizeof(int));
00466     if (year == NULL) alloc_error(__FILE__, __LINE__);
00467     month = (int *) malloc(ntimein * sizeof(int));
00468     if (month == NULL) alloc_error(__FILE__, __LINE__);
00469     day = (int *) malloc(ntimein * sizeof(int));
00470     if (day == NULL) alloc_error(__FILE__, __LINE__);
00471     hour = (int *) malloc(ntimein * sizeof(int));
00472     if (hour == NULL) alloc_error(__FILE__, __LINE__);
00473     minutes = (int *) malloc(ntimein * sizeof(int));
00474     if (minutes == NULL) alloc_error(__FILE__, __LINE__);
00475     seconds = (double *) malloc(ntimein * sizeof(double));
00476     if (seconds == NULL) alloc_error(__FILE__, __LINE__);
00477 
00478     /* Initialize udunits */
00479     ut_set_error_message_handler(ut_ignore);
00480     unitSystem = ut_read_xml(NULL);
00481     ut_set_error_message_handler(ut_write_to_stderr);
00482 
00483     /* Generate time units strings */
00484     dataunit_in = ut_parse(unitSystem, tunits_in, UT_ASCII);
00485     dataunit_out = ut_parse(unitSystem, tunits_out, UT_ASCII);
00486 
00487     /* Loop over all times */
00488     for (t=0; t<ntimein; t++) {
00489       /* Calculate date using non-standard calendar */
00490       istat = utCalendar2_cal(intimeval[t], dataunit_in, &(year[t]), &(month[t]), &(day[t]), &(hour[t]), &(minutes[t]), &(seconds[t]),
00491                               cal_type);
00492       if (istat < 0) {
00493         (void) free(year);
00494         (void) free(month);
00495         (void) free(day);
00496         (void) free(hour);
00497         (void) free(minutes);
00498         (void) free(seconds);
00499         (void) ut_free(dataunit_in);
00500         (void) ut_free(dataunit_out);
00501         (void) ut_free_system(unitSystem);  
00502         return -1;
00503       }
00504 #if DEBUG > 7
00505       istat = utInvCalendar2_cal((year[t]), (month[t]), (day[t]), (hour[t]), (minutes[t]), (seconds[t]), dataunit_in, &ccurtime, cal_type);
00506       printf("%s: %d %lf %lf %d %d %d %d %d %lf\n",__FILE__,t,intimeval[t],ccurtime,year[t],month[t],day[t],hour[t],minutes[t],seconds[t]);
00507       if (istat < 0) {
00508         (void) free(year);
00509         (void) free(month);
00510         (void) free(day);
00511         (void) free(hour);
00512         (void) free(minutes);
00513         (void) free(seconds);
00514         (void) ut_free(dataunit_in);
00515         (void) ut_free(dataunit_out);
00516         (void) ut_free_system(unitSystem);  
00517         return -1;
00518       }
00519 #endif
00520       /* Check that we really have daily data */
00521       if (t > 0) {
00522         /* Prepare converter for basis seconds since Epoch */
00523         usecond = ut_get_unit_by_name(unitSystem, "second");
00524         tunit = ut_offset_by_time(usecond, ut_encode_time(1970, 1, 1, 0, 0, 0.0));
00525         /* Generate converter */
00526         conv_in = ut_get_converter(dataunit_in, tunit);
00527         /* Seconds since Epoch */
00528         sec_int = cv_convert_double(conv_in, intimeval[t]);
00529         sec_intm1 = cv_convert_double(conv_in, intimeval[t-1]);
00530         if ( (sec_int - sec_intm1) != 86400.0 ) {
00531           (void) fprintf(stderr,
00532                          "%s: Fatal error: only daily data can be an input. Found %d seconds between timesteps %d and %d!\n",
00533                          __FILE__, (int) (sec_int - sec_intm1), t-1, t);          
00534           (void) free(year);
00535           (void) free(month);
00536           (void) free(day);
00537           (void) free(hour);
00538           (void) free(minutes);
00539           (void) free(seconds);
00540           (void) ut_free(usecond);
00541           (void) ut_free(tunit);
00542           (void) ut_free(usecond);
00543           (void) ut_free(dataunit_in);
00544           (void) ut_free(dataunit_out);
00545           (void) cv_free(conv_in);
00546           (void) ut_free_system(unitSystem);
00547           return -10;
00548         }
00549       }
00550     }
00551 
00552     /* For noleap/365-day or 360-day calendar types */
00553     if ( !strcmp(cal_type, "noleap") || !strcmp(cal_type, "365_day") || !strcmp(cal_type, "360_day") ) {
00554 
00555       /* Compute the new output total timesteps (days) in a standard year */
00556       /*
00557        * NB: The following specification gives both
00558        * the start time and the sampling interval (1 day). 
00559        */
00560 
00561       /* Set 1 day as a timestep to compute number of days in standard calendar */
00562       utstring = (char *) malloc(1000 * sizeof(char));
00563       if (utstring == NULL) alloc_error(__FILE__, __LINE__);
00564       (void) sprintf(utstring, "1 day since %d-%d-%d", year[0], month[0], day[0]);
00565       timeslice = ut_parse(unitSystem, utstring, UT_ASCII);
00566       (void) free(utstring);
00567 
00568       /* Set end period date */
00569       ref_year = year[ntimein-1];
00570       ref_month = month[ntimein-1];
00571       ref_day = day[ntimein-1];
00572       /* End Dec 31st and not Dec 30th... for 360-days calendar */
00573       if (!strcmp(cal_type, "360_day") &&
00574           (ref_month == 1 || ref_month == 3 || ref_month == 5 || ref_month == 7 || ref_month == 8 || ref_month == 10 || ref_month == 12) 
00575           && ref_day == 30) {
00576         ref_day = 31;
00577         sup = 1;
00578       }
00579       ref_hour = hour[ntimein-1];
00580       ref_minutes = 0;
00581       ref_seconds = 0.0;
00582     
00583       /* Get number of timesteps (days) */
00584       istat = utInvCalendar2(ref_year, ref_month, ref_day, ref_hour, ref_minutes, ref_seconds, timeslice, &val);
00585       *ntimeout = (int) val + 1;
00586 
00587       /* Allocate memory */
00588       (*bufout) = (float *) malloc(ni*nj*(*ntimeout) * sizeof(float));
00589       if ( (*bufout) == NULL) alloc_error(__FILE__, __LINE__);
00590       (*outtimeval) = (double *) malloc((*ntimeout) * sizeof(double));
00591       if ( (*outtimeval) == NULL) alloc_error(__FILE__, __LINE__);
00592 
00593       /* Set start period date */
00594       ref_year = year[0];
00595       ref_month = month[0];
00596       ref_day = day[0];
00597       ref_hour = hour[0];
00598       ref_minutes = 0;
00599       ref_seconds = 0.0;
00600 
00601       /* Loop over all times */
00602       for (t=0; t<(*ntimeout); t++) {
00603         /* Get current day */
00604         istat = utInvCalendar2(ref_year, ref_month, ref_day+t, ref_hour, ref_minutes, ref_seconds, dataunit_out, &curtime);
00605         /* Get standard calendar date from output time units */
00606         istat = utCalendar2(curtime, dataunit_out, &cyear, &cmonth, &cday, &chour, &cminutes, &cseconds);
00607         /* Get corresponding time units in special calendar type */
00608         istat = utInvCalendar2_cal(cyear, cmonth, cday, chour, cminutes, cseconds, dataunit_in, &ccurtime, cal_type);
00609         /* Find that time in the input time vector */
00610         for (tt=0; tt<ntimein; tt++) {
00611           if ((int) ccurtime == (int) intimeval[tt]) {
00612             /* Found it */
00613             for (j=0; j<nj; j++)
00614               for (i=0; i<ni; i++)
00615                 (*bufout)[i+j*ni+t*ni*nj] = (float) bufin[i+j*ni+tt*ni*nj];
00616             /* Get current day with hour, minutes and seconds at 00:00:00 */
00617             istat = utInvCalendar2(ref_year, ref_month, ref_day+t, 0, 0, 0.0, dataunit_out, &curtime);
00618             /* Construct new time vector */
00619             (*outtimeval)[t] = (double) curtime;
00620             /* Exit loop */
00621             tt = ntimein+10;
00622           }
00623         }
00624         if ( (sup == 1) && (tt < (ntimein+10)) ) {
00625           /* Copy it */
00626           for (j=0; j<nj; j++)
00627             for (i=0; i<ni; i++)
00628               (*bufout)[i+j*ni+t*ni*nj] = (float) bufin[i+j*ni+(ntimein-1)*ni*nj];
00629           /* Get current day with hour, minutes and seconds at 00:00:00 */
00630           istat = utInvCalendar2(ref_year, ref_month, ref_day+t, 0, 0, 0.0, dataunit_out, &curtime);
00631           /* Construct new time vector */
00632           (*outtimeval)[t] = (double) curtime;
00633           tt = ntimein+10;
00634         }
00635         if (tt < (ntimein+10)) {
00636           /* We didn't found the time in the input time vector... */
00637           (void) fprintf(stderr, "%s: Cannot generate new time vector!! Algorithm internal error!\n", __FILE__);
00638           (void) free(year);
00639           (void) free(month);
00640           (void) free(day);
00641           (void) free(hour);
00642           (void) free(minutes);
00643           (void) free(seconds);
00644           (void) ut_free(timeslice);
00645           (void) ut_free(dataunit_in);
00646           (void) ut_free(dataunit_out);
00647           (void) ut_free_system(unitSystem);  
00648           return -11;
00649         }
00650       }
00651     }
00652     else {
00653       /* Non-supported calendar */
00654       (void) fprintf(stderr, "%s: not-supported calendar. Sorry!\n", __FILE__);
00655       (void) free(year);
00656       (void) free(month);
00657       (void) free(day);
00658       (void) free(hour);
00659       (void) free(minutes);
00660       (void) free(seconds);
00661       (void) ut_free(dataunit_in);
00662       (void) ut_free(dataunit_out);
00663       (void) ut_free_system(unitSystem);  
00664       return -1;
00665     }
00666 
00667     /* Free memory */
00668     (void) free(year);
00669     (void) free(month);
00670     (void) free(day);
00671     (void) free(hour);
00672     (void) free(minutes);
00673     (void) free(seconds);
00674     
00675     /* Terminate udunits */
00676     (void) ut_free(dataunit_in);
00677     (void) ut_free(dataunit_out);
00678     (void) ut_free_system(unitSystem);  
00679   }
00680 
00681   /* Success status */
00682   return 0;
00683 }

Generated on 12 May 2016 for DSCLIM by  doxygen 1.6.1