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