int RandUniRange( const long first, const long last) { /*------------------------------------------- return a randomly selected integer between first and last, inclusive. cwb - 12/5/00 cwb - 12/8/03 - just noticed that the previous version only worked with positive numbers and when first < last. Now it works with negative numbers as well as reversed order. Examples: first = 1, last = 10, rand=.5, result = 6 first = 5, last = -1, rand=.5, result = 2 first = -5, last = 5, rand=.5, result = 0 -------------------------------------------*/ long f, l, r; if (first==last) return first; if (first > last) { l = first; f = last; } else { f = first; l = last; } r = l - f + 1; return (long)(RandUni() * r) + f; }
double RandNorm( double mean, double stddev) { /*------------------------------------------- return a random number from normal distribution with mean and stddev characteristics supplied by the user. This routine is adapted from FUNCTION GASDEV in Press, et al., 1986, Numerical Recipes, p203, Press Syndicate, NY. To reset the random number sequence, set _randseed to any negative number prior to calling any function, that depends on RandUni(). cwb - 6/20/00 cwb - 09-Dec-2002 -- FINALLY noticed that gasdev and gset have to be static! might as well set the others. -------------------------------------------*/ static short set = 0; static double v1, v2, r, fac, gset, gasdev; if (!set) { do { v1 = 2.0 * RandUni() -1.0; v2 = 2.0 * RandUni() -1.0; r = v1*v1 + v2*v2; } while( r >= 1.0 ); fac = sqrt(-2.0 *log(r)/r); gset = v1 * fac; gasdev = v2 * fac; set = 1; } else { gasdev = gset; set = 0; } return mean + gasdev * stddev; }
static RealF _add_annuals( const GrpIndex rg, const RealF g_pr, const Bool add_seeds) { /*======================================================*/ /* if add_seeds==FALSE, don't add seeds to the seedbank or * add species, but do calculations required to return a * temporary group relative size for resource allocation. * if add_seeds==TRUE, we should have done the above and now * we really want to add to the biomass and seedbank. * * check regen_ok flag. if true, apply establishment and * add to seedbank. Otherwise, add 0 to seedbank and skip * adding plants this year. We also check probability of establishment to * account for introduction of propagules, in which case * we can't add to the seedbank twice. * * reset group size to account for additions, or 0 if none. */ const RealF PR_0_est = 20.0; /* PR at which no seeds can establish */ IntU i; RealF x, estabs, /* number of estabs predicted by seedbank */ pr_inv, /* inverse of PR as the limit of estabs */ newsize, sumsize; SppIndex sp; GroupType *g; SpeciesType *s; Bool forced; g = RGroup[rg]; assert(g->max_age == 1); if (!g->use_me ) return 0.0; sumsize = 0.0; ForEachGroupSpp(sp,rg,i) { s = Species[sp]; newsize = 0.0; forced = FALSE; if (!add_seeds && RandUni() <= s->seedling_estab_prob) { /* force addition of new propagules */ _add_annual_seedprod(sp, (g->regen_ok) ? g_pr: -1.); forced = TRUE; } x = (g->regen_ok) ? _get_annual_maxestab(sp) : 0.; if ( GT(x, 0.) ) { estabs = (x - (x / PR_0_est * g_pr)) * exp(-g_pr); pr_inv = 1.0 / g_pr; newsize = fmin(pr_inv, estabs); if (add_seeds) { rgroup_AddSpecies( rg, sp); Species_Update_Newsize(sp, newsize ); } } if (add_seeds && !forced) _add_annual_seedprod(sp, (ZRO(x)) ? -1. : g_pr); sumsize += newsize; }
static void _make_disturbance( void) { /*======================================================*/ /* PURPOSE */ /* Generate disturbances, if any, for this year. */ /* HISTORY */ /* Chris Bennett @ LTER-CSU 6/15/2000 */ /*------------------------------------------------------*/ RealF pc; /* probability of colonization if current */ /* disturbance is fecalpat*/ /*new disturbance event generated, if any*/ DisturbEvent event; /*------------------------------------------------------*/ /* Can't have simultaneous disturbances*/ if (Plot.disturbance != NoDisturb) { switch( Plot.disturbance) { case FecalPat: if (Plot.pat_removed) { Plot.disturbed = 0; Plot.pat_removed = FALSE; Plot.disturbance = NoDisturb; } else { pc = Globals.pat.recol[Slope] * Plot.disturbed + Globals.pat.recol[Intcpt]; if (RandUni() <= pc) { Plot.pat_removed = TRUE; /* slight effects for one year*/ Plot.disturbed = 1; } else { Plot.pat_removed = FALSE; Plot.disturbed++; } } break; default: Plot.disturbed = (Plot.disturbed) ? Plot.disturbed -1 : 0; } if (Plot.disturbed == 0) Plot.disturbance = NoDisturb; } /* if the disturbance was expired above, */ /* we can generate a new one immediately*/ if (Plot.disturbance == NoDisturb) { /* pick some type of disturbance (other than none)*/ event = (DisturbEvent) RandUniRange(1, LastDisturb -1); /* make sure this is off unless needed */ Plot.pat_removed = FALSE; switch( event) { case FecalPat: if (!Globals.pat.use) {event=NoDisturb; break;} event = (RandUni() <= Globals.pat.occur) ? event : NoDisturb; if (event == NoDisturb) break; Plot.pat_removed = (RandUni() <= Globals.pat.removal) ? TRUE : FALSE; Plot.disturbed = 0; break; case AntMound: if (!Globals.mound.use) {event=NoDisturb; break;} event = (RandUni() <= Globals.mound.occur) ? event :NoDisturb; if (event == NoDisturb) break; Plot.disturbed = RandUniRange(Globals.mound.minyr, Globals.mound.maxyr); break; case Burrow: if (!Globals.burrow.use) {event=NoDisturb; break;} event = (RandUni() <= Globals.burrow.occur) ? event :NoDisturb; if (event == NoDisturb) break; Plot.disturbed = (Globals.burrow.minyr > 0) ? RandUniRange(1, Globals.burrow.minyr) : 0; break; } Plot.disturbance = event; } }