00001 /* 00002 * HydroRandom.c (See HydroRan2.c also.) 00003 * 00004 * Generates a large array of normally distributed 00005 * deviates with zero mean and unit variance. Other 00006 * routines sequentially pluck numbers from this array. 00007 * 00008 * The numbers are stored in ranarray, and indexed by nran. 00009 * 00010 * This enables the program to generate all the random 00011 * numbers it needs (for a year) all at once. 00012 * 00013 * Author: M.D. Morehead (June 1998) 00014 * Author2: S.D. Peckham (September 2001) 00015 * Author3: A.J. Kettner (September 2002) 00016 * 00017 * 00018 * Variable Def.Location Type Units Usage 00019 * -------- ------------ ---- ----- ----- 00020 * dumlong HydroRandom.c long - random number generator variable 00021 * err various int - error flag, halts program 00022 * fac HydroRandom.c float - random number generator variable 00023 * ii various int - temporary loop counter 00024 * jj various int - temporary loop counter 00025 * rmin HydroRandom.c double - random number generator stats 00026 * rmax HydroRandom.c double - random number generator stats 00027 * rsum HydroRandom.c double - random number generator stats 00028 * rsq HydroRandom.c float - random number generator variable 00029 * unival[] HydroRandom.c float - random number generator variable 00030 * v1 HydroRandom.c float - random number generator variable 00031 * v2 HydroRandom.c float - random number generator variable 00032 * 00033 */ 00034 00035 #include <math.h> 00036 #include <stdio.h> 00037 #include "hydroinout.h" 00038 #include "hydroparams.h" 00039 #include "hydroalloc_mem.h" 00040 #include "hydrofree_mem.h" 00041 #include "hydrornseeds.h" 00042 00043 long rnseed = INIT_RAN_NUM_SEED; 00044 long rnseed3 = INIT_RAN_NUM_SEED; 00045 long rnseed4 = INIT_RAN_NUM_SEED; 00046 long rnseed5 = INIT_RAN_NUM_SEED; 00047 00048 /*------------------------ 00049 * Start of HydroRandom 00050 *------------------------*/ 00051 int hydrorandom() 00052 { 00053 00054 /*------------------- 00055 * Local Variables 00056 *-------------------*/ 00057 float hydroran2(long *idum); 00058 float fac, rsq, v1, v2, *unival; 00059 double rsum; 00060 int err, ii, jj; 00061 err = 0; 00062 00063 /*-------------------------- 00064 * Reset the nran counter 00065 *--------------------------*/ 00066 nran = 0; 00067 /* 00068 * First generate a set of uniform random numbers in [0.0, 1.0]. 00069 * ran2 is from "Numerical Recipes in C", p282, 2nd ed. 00070 * For the first deviate, use rnseed as the seed, making sure that 00071 * it is negative, this initializes ran2 appropriately. 00072 * For subsequent years, use the generated seed; dumlong should not 00073 * be altered between successive deviates in a sequence. 00074 */ 00075 if (yr == syear[ep] ){ 00076 rnseed = -INIT_RAN_NUM_SEED; 00077 } 00078 unival = malloc1d( 2*maxran, float ); 00079 for (ii=0; ii<2*maxran; ii++) { 00080 unival[ii] = hydroran2(&rnseed); 00081 } 00082 00083 /* 00084 * Next generate Gaussian distributed deviates. 00085 * The routine returns two random numbers for each pass, 00086 * so loop through the array at a step of 2. 00087 * GASDEV, From "Numerical Recipes in C", p.289, 2nd ed. 00088 */ 00089 jj = 0; 00090 for (ii=0; ii<maxran-1; ii+=2){ 00091 do { 00092 v1 = 2.0 * unival[jj] - 1.0; 00093 v2 = 2.0 * unival[jj+1] - 1.0; 00094 rsq = sq(v1) + sq(v2); 00095 jj+=2; 00096 } while( rsq >= 1.0 || rsq == 0.0 ); 00097 fac = sqrt(-2.0*log(rsq)/rsq); 00098 ranarray[ii] = (double)v1*fac; 00099 ranarray[ii+1] = (double)v2*fac; 00100 } 00101 00102 /*------------------- 00103 * Check the stats 00104 *-------------------*/ 00105 rmin = 0; 00106 rmax = 0; 00107 rsum = 0; 00108 for (ii=0; ii<maxran-1; ii+=2) { 00109 rmin = mn(rmin, ranarray[ii]); 00110 rmax = mx(rmax, ranarray[ii]); 00111 rsum += ranarray[ii]; 00112 } 00113 /*------------------- 00114 * Optional report 00115 *-------------------*/ 00116 #ifdef DBG 00117 fprintf(fidlog," HydroRandom.c: Random Number generator statistics for year %d. \n",yr ); 00118 fprintf(fidlog," number of values generated \t = %d \n", dumlong*0.5); 00119 fprintf(fidlog," minimum value generated \t = %f \n", rmin); 00120 fprintf(fidlog," maximum value generated \t = %f \n", rmax); 00121 fprintf(fidlog," mean value generated \t = %f \n\n", rsum/(double)dumlong*0.5); 00122 #endif 00123 freematrix1D( (void*) unival ); 00124 return(err); 00125 } /* end of HydroRandom */ 00126 00127