2
/******************************************************************************
3
* spot.c in ~/r.spread.fast
5
* This function is for wildfire spread simulation only.
6
* It 1) is an inverse square distance randomization of the maximum
16
* | * p(X) = --- (0 <= X <= max_dist)
25
* |______________________________********_______ X
29
* 2) the maximum spotting distance is derived from simplification of
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 equilibium rate of spread (ROS).
35
* This elapsed time is proportional to the ROS.
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,
43
******************************************************************************/
46
#include <grass/gis.h>
47
#include <grass/raster.h>
50
#include "cell_ptrHa.h"
51
#include "local_proto.h"
57
#define DATA(map, r, c) (map)[(r) * ncols + (c)]
59
void spot(struct costHa *pres_cell, int dir /* direction of forward ROS */ )
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 (%) */
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 */
77
/* Find the (cell) location spotting might reach */
79
land_dist = pick_dist(DATA(map_spotdist, pres_cell->row, pres_cell->col));
81
G_debug(1, "pres_cell(%d, %d): land_dist=%d", pres_cell->row,
82
pres_cell->col, land_dist);
84
land_distc = land_dist / (window.ns_res / 100); /* 100 fac due to cm */
86
if (land_distc < 2) /* no need for adjacent cells */
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 */
92
if (col < 0 || col >= ncols) /* outside the region */
94
if (DATA(map_max, row, col) <= 0) /* a barrier */
97
/* check if ignitable based on probs. modified from Rothermel (1983) */
99
if (DATA(map_mois, row, col) > 17) /* too wet */
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);
106
if (pick_ignite(DATA(map_mois, row, col)) == 0) /* not success */
109
G_debug(1, " post pick_ignite(): land_distc(%d, %d)=%d ",
110
row, col, land_distc);
112
/* travel time by spotting */
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;
118
/* elapsed time to reach the max ROS, proportional to ROS */
120
Te = DATA(map_max, pres_cell->row, pres_cell->col) / 1000 + 1;
122
/* cumulative travel time since start */
124
min_cost = pres_cell->min_cost + spot_cost + Te;
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);
130
update(pres_cell, row, col, (double)dir, min_cost);