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;
   }
예제 #4
0
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;

   }

}