/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/hydrotrend/hydroweather.c

Go to the documentation of this file.
00001 /*
00002  * HydroWeather.c       Calculates the daily values of T and P for each
00003  *                      altitude bin of the basin.
00004  *
00005  *      Author:         M.D. Morehead   June 1998
00006  *  Author2:    A.J. Kettner    September-October 2002
00007  *                              A.J. Kettner    December 2002
00008  *
00009  * Variable             Def.Location    Type    Units   Usage
00010  * --------             ------------    ----    -----   -----
00011  * darray[]             HydroWeather.c  int             -               day of month array
00012  * dumdbl               various                 double  -               temporary double
00013  * err                  various                 int             -               error flag, halts program
00014  * jj                   various                 int             -               temporary loop counter
00015  * ii                   various                 int             -               temporary loop counter
00016  * ndaysppt             HydroWeather.c  int             -               montly counter for number of days of preci.
00017  * parray[]             HydroWeather.c  double  m               daily precipitation array for a month
00018  * pind                 HydroWeather.c  int             -               parray index
00019  * sump                 various                 double  m               total precipitation
00020  * sumt                 various                 double  degC    total temperature
00021  *
00022  */
00023  
00024 #include <stdlib.h>
00025 #include "hydroclimate.h"
00026 #include "hydrotimeser.h"
00027 #include "hydroparams.h"
00028 #include "hydroinout.h"
00029 #include "hydroreadclimate.h"
00030 #include "hydroalloc_mem.h"
00031 #include "hydrofree_mem.h"
00032 #include "hydrodaysmonths.h"
00033 #include "hydrotrend.h"
00034 #include "hydrornseeds.h"
00035 #define MAXIT (3000)
00036 #define swap_dbl_vec( x , i , j ) { double temp; temp=x[i]; x[i]=x[j]; x[j]=temp; }
00037 typedef int (Cost_fcn)( double*, int );
00038 
00039 /*--------------------
00040  *  Global variables
00041  *--------------------*/
00042 int jj;
00043 
00044 /*--------------------
00045  *  Global functions
00046  *--------------------*/
00047 double *anneal( double *x , int n , Cost_fcn *f , int cost_min, int jj );
00048 int eh_get_fuzzy_int(int y , int z, int jj, int count);
00049 int cost_fcn( double *x , int n );
00050 float hydroran4(long *idum);
00051 
00052 /*-------------------------
00053  *  Start of HydroWeather
00054  *-------------------------*/
00055 int hydroweather(gw_rainfall_etc* gw_rain){
00056 
00057 /*-------------------
00058  *  Local Variables
00059  *-------------------*/
00060 #ifdef DBG
00061 FILE *fid;
00062 #endif
00063 
00064 double dumdbl, parray[31], sumt, sump;
00065 double Tstdcorr;
00066 int darray[31], err, ii, pind, count;
00067 int ndaysppt, daysinmnd;
00068 Cost_fcn cost_fcn;
00069 err = 0;
00070 
00071 /*-----------------------------------------------------------
00072  *  Set a correction ratio for the Tstd values
00073  *  The Tstd's are derived from differnces between monthly
00074  *  values from different years.  We really want the STD of
00075  *  the daily values within a year.  This factor appears to
00076  *  correct this in the proper direction
00077  *-----------------------------------------------------------*/
00078 Tstdcorr = 0.5;
00079 /*--------------------------------------------------------------
00080  *  Get the daily Temperature at the river mouth (sealevel) by 
00081  *  value's (from file).
00082  *--------------------------------------------------------------*/
00083 if (raindatafile == 1)
00084         for( ii=0; ii<daysiy; ii++ )
00085                 Tdaily[ii] = gw_rain->T[yr-syear[ep]][ii];
00086                 
00087 /*-----------------------------------------------------------------
00088  *  Calculate the daily Temperature at the river mouth (sealevel)
00089  *-----------------------------------------------------------------*/
00090 else
00091 //      for( jj=0; jj<12; jj++ ) {
00092         for( jj=Jan; jj<=Dec; jj++ ) {
00093                 sumt = 0;
00094 //              for( ii=daystrm[jj]-1; ii<dayendm[jj]; ii++ ) {
00095                 for( ii=start_of(jj)-1 ; ii<end_of(jj) ; ii++ ) {
00096                         dumdbl = ranarray[nran]; nran++;
00097                         Tdaily[ii] = Tmonth[jj] + Tnomstd[jj][ep] * dumdbl * Tstdcorr;
00098                         sumt += Tdaily[ii];
00099                 } /* end ii-day loop */
00100 //              for( ii=daystrm[jj]-1; ii<dayendm[jj]; ii++ )
00101                 for( ii=start_of(jj)-1 ; ii<end_of(jj) ; ii++ )
00102 //                      Tdaily[ii] = Tdaily[ii] - (sumt/daysim[jj]) + Tmonth[jj];
00103                         Tdaily[ii] = Tdaily[ii]
00104                                    - ( sumt/days_in_month(jj) )
00105                                    + Tmonth[jj];
00106         } /* end jj-month loop */
00107 
00108 /*----------------------------------------------------------------
00109  *  Get the daily Precipitation at the river mouth (sealevel) by 
00110  *  value's (from file).
00111  *----------------------------------------------------------------*/
00112 if (raindatafile == 1)
00113         for( ii=0; ii<daysiy; ii++ )
00114                 Pdaily[ii] = gw_rain->R[yr-syear[ep]][ii];
00115 
00116 /*-------------------------------------------------------------------
00117  *  Calculate the daily Precipitation at the river mouth (sealevel)
00118  *  the skewed distribution is the new and more realistic method
00119  *  Either by file or by climate generator.
00120  *-------------------------------------------------------------------*/
00121 else{
00122    for( jj=0; jj<12; jj++ ) {           /* skewed distribution */
00123 
00124       /*---------------------------------------------------------
00125        *  Generate 31 days worth of skewed distribution numbers
00126        *---------------------------------------------------------*/
00127       err = hydroexpdist(parray,jj);
00128       if(err) fprintf(stderr,"expdist failed in HydroWeather, epoch = %d, year = %d \n", ep+1, yr);
00129 
00130       /*------------------------------------------
00131        *  Randomly shuffle the days of the month
00132        *------------------------------------------*/
00133       err = hydroshuffle(darray,jj);
00134       if(err) fprintf(stderr,"shuffle failed in HydroWeather, epoch = %d, year = %d \n", ep+1, yr);
00135 
00136       /*---------------------------------------------------------------------
00137        *  Assign enough rain days to be just under the monthly rainfall.
00138        *  Assign one less than the # of days in the month, then (if needed)
00139        *  the last day can make up any slack.
00140        *---------------------------------------------------------------------*/
00141       sump = 0.0;
00142       pind = 0;
00143       count = 0;
00144       ndaysppt = 0;
00145 //      while( (sump + parray[pind]) < Pmonth[jj] && pind < daysim[jj]-1 ) {
00146       while( (sump + parray[pind]) < Pmonth[jj] && pind < days_in_month(jj)-1 )
00147       {
00148 //         if( daystrm[jj]+darray[pind]-2 >= daysiy ) {
00149          if( start_of(jj)+darray[pind]-2 >= daysiy ) {
00150             fprintf(stderr,"ERROR in HydroWeather \n");
00151             fprintf(stderr,"   # days exceeded 365, case 1 \n");
00152             exit(1);
00153          }
00154 //         Pdaily[daystrm[jj]+darray[pind]-2] = parray[pind];            
00155          Pdaily[start_of(jj)+darray[pind]-2] = parray[pind];            
00156 //         if (Pdaily[daystrm[jj]+darray[pind]-2] != 0.0)
00157          if (Pdaily[start_of(jj)+darray[pind]-2] != 0.0)
00158             ndaysppt++;
00159          sump += parray[pind];
00160          pind++;
00161          count++;
00162       } /* end while */
00163 
00164       /*--------------------------------------------------------------------
00165        *  add enough rain to another random day (or the last shuffled day)
00166        *  to achieve Pmonth[jj]
00167        *--------------------------------------------------------------------*/
00168 //      if( daystrm[jj]+darray[pind]-2 >= daysiy ) {
00169       if( start_of(jj)+darray[pind]-2 >= daysiy ) {
00170          fprintf(stderr,"ERROR in HydroWeather \n");
00171          fprintf(stderr,"   # days exceeded 365, case 2 \n");
00172          fprintf(stderr,"   # days = daystrm[jj]-2+darray[pind] \n");
00173 //         fprintf(stderr,"   daystrm[jj] = %d \n", daystrm[jj] );
00174          fprintf(stderr,"   daystrm[jj] = %d \n", start_of(jj) );
00175          fprintf(stderr,"   darray[pind] = %d \n", darray[pind] );
00176          exit(1);
00177       }
00178 //      Pdaily[daystrm[jj]+darray[pind]-2] = Pmonth[jj] - sump;
00179       Pdaily[start_of(jj)+darray[pind]-2] = Pmonth[jj] - sump;
00180 //      if (Pdaily[daystrm[jj]+darray[pind]-2] != 0.0)
00181       if (Pdaily[start_of(jj)+darray[pind]-2] != 0.0)
00182           ndaysppt++;
00183 
00184       /*----------------------------------------------------
00185        *  Check to make sure all the rain days stay within
00186        *  reasonable limits.
00187        *----------------------------------------------------*/
00188 //      for( ii=0; ii<daysim[jj]; ii++ ) {
00189       for( ii=0; ii<days_in_month(jj); ii++ ) {
00190 //         if( 0.0 > Pdaily[daystrm[jj]-1+ii] ||
00191 //                   Pdaily[daystrm[jj]-1+ii] > Pmonth[jj]+Pnomstd[jj][ep]*Prange[ep] ) {
00192          if (    Pdaily[start_of(jj)-1+ii] < 0
00193               || Pdaily[start_of(jj)-1+ii] > Pmonth[jj]+Pnomstd[jj][ep]*Prange[ep] ) {
00194             fprintf(stderr," HydroWeather ERROR: A daily rainfall value exceeds limits.");
00195             fprintf(stderr,"    epoch = %d, year = %d, month = %d, day = %d \n",ep+1,yr,jj,ii);
00196             fprintf(stderr,"    Criteria: 0 < P < monthlyP*STD*Prange \n");
00197 //            fprintf(stderr,"    P = %g (from HydroWeather.c)\n", Pdaily[daystrm[jj]-1+ii] );
00198             fprintf(stderr,"    P = %g (from HydroWeather.c)\n", Pdaily[start_of(jj)-1+ii] );
00199             fprintf(stderr,"    monthlyP = %g (from setclimate.c)\n",  Pmonth[jj]);
00200             fprintf(stderr,"    STD = %g (from input file)\n",  Pnomstd[jj][ep]);
00201             fprintf(stderr,"    Prange = %g (from input file)\n",  Prange[ep]);
00202             err = 1;
00203          }
00204       }
00205 
00206      /*----------------------------------------------------------
00207       *  Make the distribution look more natural by grouping
00208       *  the precipitation days (so random distribution becomes
00209       *  more a grouped distribution). This is only done when
00210       *  number of precipitation days is bigger than 2.
00211       *----------------------------------------------------------*/
00212 //      daysinmnd = (daysim[jj] + daystrm[jj])-1;
00213       daysinmnd = (days_in_month(jj) + start_of(jj))-1;
00214       anneal (Pdaily, daysinmnd, &cost_fcn, ndaysppt, jj);
00215    }    /* end the month for loop of skewed distribution*/
00216 } /* end else */   
00217 
00218 #ifdef DBG
00219   if( tblstart[ep] <= yr && yr <= tblend[ep] ) {
00220     if( (fid = fopen("hydro.t","a+")) == NULL) {
00221       printf("  HydroWeather ERROR: Unable to open the temperature file hydro.t \n");
00222       printf("     non-fatal error, continueing. \n\n");
00223     }
00224     else {
00225       fprintf( fid,"%%HydroWeather: Daily predicted temperatures for year %d \n%%\n", yr );
00226       fprintf( fid,"%%Day \t Temperature \n", yr );
00227       fprintf( fid,"%%--- \t ----------- \n", yr );
00228       for(ii=0; ii<daysiy; ii++ )
00229          fprintf( fid,"%d \t %f \n",ii+1,Tdaily[ii]);
00230       fprintf( fid,"%%\n%%\n" );
00231     }
00232     if( (fid = fopen("hydro.pr","a+")) == NULL) {
00233       printf("  HydroWeather ERROR: Unable to open the precipitation file hydro.pr \n");
00234       printf("     non-fatal error, continueing. \n\n");
00235     }
00236     else {
00237       fprintf( fid,"%%HydroWeather: Daily predicted precipitation for year %d \n%%\n", yr );
00238       fprintf( fid,"%%Day \t Precipitation \n", yr );
00239       fprintf( fid,"%%--- \t ------------- \n", yr );
00240       for(ii=0; ii<daysiy; ii++ )
00241          fprintf( fid,"%d \t %f \n",ii+1,Pdaily[ii]);
00242       fprintf( fid,"%%\n%%\n" );
00243     }
00244     fclose(fid);
00245   }
00246 #endif
00247 return(err);
00248 }       /* end of HydroWeather */
00249 
00250 /*-------------------------------------
00251  * Defining area for global functions
00252  *-------------------------------------*/
00253 
00254 /*  FUNCTION TO DISTRIBUTE RAINDAYS IN A MORE "NATURAL WAY" */
00255 double *anneal(double *x, int n, Cost_fcn *f, int cost_min, int jj) {
00256 
00257 /*----------------------------------------------------------
00258  *  This function is ordering the precipitation array in a
00259  *  random way and compair the results of the number of
00260  *  switches with the results from before. The smaller the
00261  *  number, the more the array is grouped. It does it till
00262  *  the boundery cost_min is reached.
00263  *----------------------------------------------------------*/
00264    double cost_before, cost_after;
00265    int i, j, count;
00266    int itr=0, max_itr=MAXIT;
00267    cost_after = 31;
00268    count=0;
00269    do {
00270       cost_before = (*f)(x, n);
00271 //      i = eh_get_fuzzy_int(daystrm[jj], n-1, jj, count);
00272       i = eh_get_fuzzy_int(start_of(jj), n-1, jj, count);
00273       count++;
00274       do
00275 //         j = eh_get_fuzzy_int(daystrm[jj], n-1, jj, count);
00276          j = eh_get_fuzzy_int(start_of(jj), n-1, jj, count);
00277       while (j == i);
00278       swap_dbl_vec(x, i, j);
00279       cost_after = (*f)(x, n);
00280       if (cost_after>cost_before)
00281          swap_dbl_vec(x, i, j);
00282    }
00283    while (cost_after > (double)cost_min && ++itr<max_itr);
00284    return x;
00285 }
00286 
00287 
00288 /* FUNCTION EH_GET_FUZZY_INT */
00289 int eh_get_fuzzy_int(int y , int z, int jj, int count){
00290         double x,dumflt;
00291         
00292 /*---------------------------------------
00293  *  Just getting a array number between
00294  *  the startday of the month and the
00295  *  endday of the month.
00296  *---------------------------------------*/
00297         if ( yr == syear[ep] && jj == 0 && count == 0)
00298                 rnseed4 = -INIT_RAN_NUM_SEED;
00299 
00300         dumflt = hydroran4(&rnseed4);                           /* get a uniform random number [0:1] */
00301         if( 0 > dumflt || dumflt > 1 ){
00302                 fprintf( stderr,"A function in HydroRan4 failed in HydroWeather.c \n");
00303                 fprintf( stderr," \t dumflt = %f: \t setting value to 0.5, jj = %d \n", dumflt, jj);
00304                 dumflt=0.5;
00305         }
00306         x = dumflt;
00307         x = x*(z-y)+y;
00308         return (int)(x+.5);
00309 }
00310 
00311 
00312 /* FUNCTION Cost_fcn */
00313 int cost_fcn( double *x , int n ){
00314 
00315 /*-------------------------------------------------
00316  *  This routine is flagging the precipitation
00317  *  days by giving them a value 1, other days
00318  *  gets a flag value 0. Then it counts how often
00319  *  it switch from a precipitation day to a non-
00320  *  precipitation day and returns that value.
00321  *-------------------------------------------------*/
00322    int i, *j, k;
00323    k = 0;
00324    j = malloc1d(n, int);
00325 
00326 //   for (i=daystrm[jj] ; i<n ; i++){
00327    for (i=start_of(jj) ; i<n ; i++){
00328        if (x[i] > 0.0)
00329            j[i] = 1;
00330        else j[i] = 0;
00331        if (i>start_of(jj))
00332            k += fabs(j[i-1] - j[i]);
00333    }
00334    freematrix1D( (void*) j );
00335    return k;
00336 }

Generated on Fri Jan 4 18:04:14 2008 for sedflux by  doxygen 1.5.2