1 
2 /******************************************************************************
3  *	spot.c 		in ~/r.spread.fast
4  *
5  *  	This function is for wildfire spread simulation only.
6  *	It 1) is an inverse square distance randomization of the maximum
7  * 	   spotting distance;
8  *
9  *		| p(X)
10  *		|
11  *		|*
12  *		|*
13  *		|
14  *		| *
15  *		|  			1
16  *		|   *		p(X) = ---	(0 <= X <= max_dist)
17  *		|    *		       X^2
18  *		|      *
19  *		|	 *
20  *		|	   *
21  *		|	      *
22  *		|		 *
23  *		|		     *
24  *		|			  *
25  *		|______________________________********_______  X
26  *						      ^
27  *						     max_dist
28  *
29  * 	2) the maximum spotting distance is derived from simplification of
30  *	   Chase (1984);
31  *	3) the landing firebrand may ignite spread based on fine fuel
32  *	   moisture dictated probability simplified from Rothermel (1983);
33  *	4) spotting travel time is proportional to but slower than windspeed;
34  *	5) there is an elapsed time to reach equilibrium rate of spread (ROS).
35  *	   This elapsed time is proportional to the ROS.
36  * Refs:
37  * Chase, C. H., 1984, Spotting distance from wind-driven surface fires --
38  * 	ententions of equations for pocket calculators, US Forest Service, Res.
39  *	Note INT-346, Ogden, Uhta, 27 p.
40  * Rothermel, R. C., 1983, How to predict the spread and intensity of forest
41  *	and range fires. US Forest Service, Gen. Tech. Rep. INT-143. Ogden,
42  *	Utha, 161 p.
43  ******************************************************************************/
44 #include <stdio.h>
45 #include <math.h>
46 #include <grass/gis.h>
47 #include <grass/raster.h>
48 #include "cmd_line.h"
49 #include "costHa.h"
50 #include "cell_ptrHa.h"
51 #include "local_proto.h"
52 
53 #ifndef PI
54 #define PI M_PI
55 #endif
56 
57 #define DATA(map, r, c)		(map)[(r) * ncols + (c)]
58 
spot(struct costHa * pres_cell,int dir)59 void spot(struct costHa *pres_cell, int dir /* direction of forward ROS */ )
60 {
61     extern CELL *map_max;	/* max ROS (cm/min) */
62     extern CELL *map_spotdist;	/* max spotting distance (m) */
63     extern CELL *map_velocity;	/* midflame windspeed (ft/min) */
64     extern CELL *map_mois;	/* fuel moisture (%) */
65 
66     /*      extern float    PI; */
67     extern int nrows, ncols;
68     extern struct Cell_head window;
69     float spot_cost;		/* spotting travel time (min) */
70     float min_cost;		/* min cumulative time (min) */
71     float U;			/* wind speed at 6m (m/min) */
72     float Te;			/* time to reach max ROS (min) */
73     int land_dist;		/* stochastic landing dist (m) */
74     int land_distc;		/* land_dist in cell counts */
75     int row, col;
76 
77     /* Find the (cell) location spotting might reach */
78 
79     land_dist = pick_dist(DATA(map_spotdist, pres_cell->row, pres_cell->col));
80 
81     G_debug(1, "pres_cell(%d, %d): land_dist=%d", pres_cell->row,
82 	   pres_cell->col, land_dist);
83 
84     land_distc = land_dist / (window.ns_res / 100);	/* 100 fac due to cm */
85 
86     if (land_distc < 2)		/* no need for adjacent cells */
87 	return;
88     row = pres_cell->row - land_distc * cos((dir % 360) * PI / 180) + 0.5;
89     col = pres_cell->col + land_distc * sin((dir % 360) * PI / 180) + 0.5;
90     if (row < 0 || row >= nrows)	/* outside the region */
91 	return;
92     if (col < 0 || col >= ncols)	/* outside the region */
93 	return;
94     if (DATA(map_max, row, col) <= 0)	/* a barrier */
95 	return;
96 
97     /* check if ignitable based on probs. modified from Rothermel (1983) */
98 
99     if (DATA(map_mois, row, col) > 17)	/* too wet */
100 	return;
101 
102     G_debug(1,
103       "	pre pick_ignite(): land_distc(%d, %d)=%d dir=%d PI=%.2f (dir%%360)*PI/180=%.2f",
104 	  row, col, land_distc, dir, PI, (dir % 360) * PI / 180);
105 
106     if (pick_ignite(DATA(map_mois, row, col)) == 0)	/* not success */
107 	return;
108 
109     G_debug(1, "	post pick_ignite(): land_distc(%d, %d)=%d ",
110 	   row, col, land_distc);
111 
112     /* travel time by spotting */
113 
114     U = 0.305 * DATA(map_velocity, pres_cell->row, pres_cell->col);
115     /*NOTE: use value at midflame */
116     spot_cost = land_dist / U;
117 
118     /* elapsed time to reach the max ROS, proportional to ROS */
119 
120     Te = DATA(map_max, pres_cell->row, pres_cell->col) / 1000 + 1;
121 
122     /* cumulative travel time since start */
123 
124     min_cost = pres_cell->min_cost + spot_cost + Te;
125 
126     /* update it to the to_cell */
127     G_debug(1, "		min_cost=%.2f: pres=%.2f spot=%.2f Te=%.2f",
128 	   min_cost, pres_cell->min_cost, spot_cost, Te);
129 
130     update(pres_cell, row, col, (double)dir, min_cost);
131 }
132