home *** CD-ROM | disk | FTP | other *** search
- /* This program is Copyright (c) 1991 David Allen. It may be freely
- distributed as long as you leave my name and copyright notice on it.
- I'd really like your comments and feedback; send e-mail to
- allen@viewlogic.com, or send us-mail to David Allen, 10 O'Moore
- Avenue, Maynard, MA 01754. */
-
- /* This file contains the routines to compute rainfall. */
-
- #include "const.h"
- #include "clim.h"
-
- /* The input data arrays are l and lm, from main.c, wd, from wind.c,
- and pr, from pressure.c. Output arrays are rm and rn; fr and fs are
- used as temporary storage. */
-
- extern unsigned char l[MAXX][MAXY], lm[MAXX][MAXY], wd[MAXB][MAXX][MAXY];
- extern unsigned char pr[MAXB][MAXX][MAXY];
- unsigned char rn[MAXB][MAXX][MAXY];
- static unsigned char fr[2][MAXX][MAXY], fs[MAXX][MAXY];
-
-
- /* The externs below are parameters defined in main.c; the ints are
- parameters defined here. */
-
- extern int BSIZE, XSIZE, YSIZE;
- int MAXFETCH = 5, RAINCONST = 32, LANDEL = 10, MOUNTDEL = 32, FETCHDEL = 4;
- int NRFDEL = 3, HEQDEL = 32, NRHEQDEL = 24, FLANKDEL = -24, PRINTRAIN = 0;
-
-
- rainpar (s) char *s; {
- /* This function is called by mainpar() in main.c; it simply tests input
- parameter names to see if they are defined in this file. Each of the
- above ints are defined in this file. If the input string matches here,
- the function returns true. */
-
- if (CMP ("MAXFETCH")) getlng (&MAXFETCH, M_RAIN);
- else if (CMP ("RAINCONST")) getlng (&RAINCONST, M_RAIN);
- else if (CMP ("LANDEL")) getlng (&LANDEL, M_RAIN);
- else if (CMP ("MOUNTDEL")) getlng (&MOUNTDEL, M_RAIN);
- else if (CMP ("FETCHDEL")) getlng (&FETCHDEL, M_RAIN);
- else if (CMP ("HEQDEL")) getlng (&HEQDEL, M_RAIN);
- else if (CMP ("NRHEQDEL")) getlng (&NRHEQDEL, M_RAIN);
- else if (CMP ("FLANKDEL")) getlng (&FLANKDEL, M_RAIN);
- else if (CMP ("NRFDEL")) getlng (&NRFDEL, M_RAIN);
- else if (CMP ("PRINTRAIN")) getlng (&PRINTRAIN, M_RAIN);
- else return (0);
- return (1); }
-
-
- raincomp () {
- /* This is the main rain computation function. It calls the functions
- getfetch () and getrain () to do all the work for each buffer, then
- prints out the results if needed. */
-
- register int buf;
-
- for (buf=0; buf<BSIZE; buf++) {
- status (M_RAIN, buf); checkmouse ();
- getfetch (buf); checkmouse (); getrain (buf); }
-
- if (PRINTRAIN) for (buf=0; buf<BSIZE; buf++)
- putmat ("RAIN", buf, PRINTMODE_SCALE, rn[buf], lm); }
-
-
- raindraw (n) int n; { draw (DRAW_GREY, LINE_CORN, rn[n], lm); }
- /* This function calls draw with the right arguments to display rain */
-
-
- fetchinc (x, y, dest) int x, y, dest; {
- /* This is the workhorse function for getfetch(), below. It is called
- several times per square. It changes x to account for wraparound, so it
- won't work as a macro. If y is out of range it does nothing, else it
- "marks" the new square in fr[dest] and increments fs to record the number
- of times the square has been marked. */
-
- if (x == -1) x = XSIZE-1; else if (x == XSIZE) x = 0;
- if ((y == -1) || (y == YSIZE)) return (0);
- fr[dest][x][y] = 1; fs[x][y]++; return (0); }
-
-
- getfetch (buf) int buf; {
- /* "Fetch" is the term that describes how many squares a given wind line
- travels over water. It measures how moist the wind is. The algorithm to
- measure fetch looks like many simultaneous tree walks, where each water
- square is a root square, and every wind edge is a tree edge. A counter
- for each square determines how many times that square is reached during
- the tree walks; that is the fetch. */
-
- register int i, j, k; int src, dest;
-
- /* Initialize the counter fs to zero. Array fr, which records the */
- /* list of active edges in the walks, is set so that all ocean squares */
- /* are active. Also, the result array rn is cleared. */
- for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++) {
- fr[0][i][j] = l[i][j] ? 0 : 1; fs[i][j] = 0; rn[buf][i][j] = 0; }
-
- /* Each time through the loop, each square is examined. If it's */
- /* active, disable the mark in the current time step (thus ensuring */
- /* that when the buffers are flipped, the new destination is empty). */
- /* If the square is a mountain, don't pass the mark, but instead add */
- /* some amount to the square -- implementing rain shadows and rainy */
- /* mountain squares. Finally, for each of the eight cardinal */
- /* directions, if there is wind blowing in that direction, carry a */
- /* marker to that square using fetchinc(), above. */
-
- for (k=0; k<MAXFETCH; k++) {
- src = k % 2; dest = 1 - src;
- for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++) if (fr[src][i][j]) {
- fr[src][i][j] = 0;
- if (l[i][j] == 2) rn[buf][i][j] += MOUNTDEL;
- else switch (wd[buf][i][j]) {
- case N|E: fetchinc (i+1, j-1, dest); break;
- case N|W: fetchinc (i-1, j-1, dest); break;
- case S|E: fetchinc (i+1, j+1, dest); break;
- case S|W: fetchinc (i-1, j+1, dest); break;
- case N: fetchinc (i, j-1, dest); break;
- case S: fetchinc (i, j+1, dest); break;
- case E: fetchinc (i+1, j, dest); break;
- case W: fetchinc (i-1, j, dest); break; } } } }
-
-
- /* This macro is called several times per square by getrain(), below. It
- simply tests the square for several conditions: if the square is on the
- heat equator, itcz is set to one; if the wind blows south in this square,
- it is on the flank of a circular wind zone (and thus less rainy); the local
- rain sum, x, is increased according to the fetch sum in the square. */
- #define RAINTEST(xx,yy) \
- if (pr[buf][xx][yy] == PR_HEQ) itcz = 1; \
- if (wd[buf][xx][yy] & S) flank = 1; \
- x += (fs[xx][yy] * NRFDEL);
-
-
- getrain (buf) int buf; {
- /* Once the fetch array is computed, this function looks at each square to
- determine the amount of rainfall there. The above macro is called five
- times, once for the square and each of its four neighbors; this determines
- whether the square is near the ITCZ or the flank of an air cycle. The
- sum of fetches for the neighbors is also determined. Finally, each of the
- factors is weighted and added to the rainfall value: the local fetch value,
- a land factor, the nearness of the heat equator, and the nearness of a
- flank. Note that while rn is zeroed in getfetch(), it may be increased by
- rain falling on mountains, so it is nonzero when this function is called. */
-
- register int i, j, x; int itcz, flank;
-
- for (i=0; i<XSIZE; i++) for (j=0; j<YSIZE; j++) {
- flank = 0; itcz = 0; x = rn[buf][i][j];
- if (i < XSIZE-1) { RAINTEST (i+1, j) } else { RAINTEST (0, j) }
- if (i) { RAINTEST (i-1, j) } else { RAINTEST (XSIZE-1, j) }
- if (j < YSIZE-1) { RAINTEST (i, j+1) }
- if (j) { RAINTEST (i, j-1) }
- RAINTEST (i, j);
-
- x += (RAINCONST + FETCHDEL * fs[i][j]);
- if (l[i][j]) x += LANDEL;
- if (pr[buf][i][j] == PR_HEQ) x += HEQDEL;
- if (itcz) x += NRHEQDEL;
- if (flank) x += FLANKDEL;
- if (x < 0) x = 0; if (x> 255) x = 255;
- rn[buf][i][j] = x; } }
-