spot_dist.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /******************************************************************************
  2. * spot_dist.c in ~/r.ros
  3. *
  4. * Returns the maximum spotting distance (in meters) based on:
  5. * 1) Lathrop, Richard G. and Jianping Xu, 1994, A geographic information
  6. * system method to assist evaluating spotting distance in any
  7. * terrain conditions. (in preparation)
  8. *
  9. * |
  10. * |
  11. * |*** z0 = e0 + h0
  12. * | *
  13. * | * firebrand trajetory z: z = z0 - (X/(1.3U))^2
  14. * | * simplified from Chase (1984)
  15. * | *
  16. * | *
  17. * | *
  18. * |\ e0 *
  19. * | \___ __ * /\
  20. * | \__/ \__*_/ \ surface e: from DEM
  21. * . \
  22. * .
  23. *
  24. * |___________________________________ X
  25. *
  26. * 2) Chase, Carolyn, H., 1984, Spotting distance from wind-driven surface
  27. * fires -- ententions of equations for pocket calculators, US Forest
  28. * Service, Res. Note INT-346 , Ogden, Uhta, 21 p.
  29. * 3) Rothermel, Richard, 1991, Predicting behavior and size of crown fires
  30. * in the northern Rocky Mountains, US Forest Service, Res. Paper
  31. * INT-438, 46 p.
  32. ******************************************************************************/
  33. #include <math.h>
  34. #include <grass/raster.h>
  35. #define DATA(map, r, c) (map)[(r) * ncols + (c)]
  36. #define DEG2RAD M_D2R
  37. /*#define DEBUG */
  38. /* Ovendry loading for all sizes (lb/ft^2) */
  39. float w[14] = { 0, 0.034, 0.184, 0.138, 0.736, 0.161, 0.276,
  40. 0.224, 0.230, 0.160, 0.552, 0.529, 1.587, 2.668
  41. };
  42. /* Mean average cover height (assumed the same as current fuel depth (ft) */
  43. float hbar[] = { 0, 1.0, 1.0, 2.5, 6.0, 2.0, 2.5,
  44. 2.5, 0.2, 0.2, 1.0, 1.0, 2.3, 3.0
  45. };
  46. /* A Coeficients in E = IA(.474U)^B (s), where U is wind at 20 ft (mi/h) */
  47. double A[14] = { 0, 545, 709, 429, 301, 235, 242,
  48. 199, 0, 1121, 224, 179, 163, 170
  49. };
  50. /* B Coeficients in E = IA(.474U)^B (s), where U is wind at 20 ft (mi/h) */
  51. double B[14] = { 0, -1.21, -1.32, -1.19, -1.05, -0.92, -0.94,
  52. 0.83, 0, -1.51, -0.89, -0.81, -0.78, -0.79
  53. };
  54. /**
  55. * @brief Compute maximum spotting distance
  56. *
  57. * @param fuel fuel type used in Byram's equation from Rothermel (1991)
  58. * and in Chase (1984) equation for source z
  59. * @param maxros maximal ROS used in Byram's equation
  60. * @param speed wind speed used to compute mean windspeed at 6 meter
  61. * accoring to Chase (1984) influencing the target z
  62. * @param angle direction of maximal ROS, i.e. the direction of spotting
  63. * (if you think that only direction of wind influences the spotting
  64. * then this should be the wind direction)
  65. * @param row0 source cell row
  66. * @param col0 source cell column
  67. * @return maximum spotting distance
  68. */
  69. int spot_dist(int fuel, float maxros, int speed, float angle, int row0,
  70. int col0)
  71. {
  72. /* variables in Chase (1984) (use h0 for z0 which for e0 + h0) */
  73. double h0; /* initial firebrand height (m) */
  74. double E; /* thermal strength (Btu/ft) */
  75. double I; /* mean fire intensity (Btu/ft/s) */
  76. double U; /* mean windspeed at 6 meter (km/h) */
  77. /* variables in Rothermel (1991) */
  78. float R; /* forward rate of spread (ROS) (ft/s) */
  79. /* other variables */
  80. extern CELL *map_elev; /* elevation map array */
  81. extern int nrows, ncols;
  82. extern struct Cell_head window;
  83. double z0; /* initial firebrand elevation (m) */
  84. double z; /* firebrand height (m) */
  85. int row, col; /* a cell under a spotting trajatory */
  86. int S; /* spotting distance on an terrain (m) */
  87. double sqrd; /* distance from cell0 to cell */
  88. double sin_a, cos_a; /* of the wind angle */
  89. double sqr_ns, sqr_ew; /* square resolutions for speed */
  90. int i; /* for advance a step */
  91. if (fuel == 8) /* no spotting from closed timber litter */
  92. return (0);
  93. /* get I from Byram's equation, I = R*w*h, cited in Rothermel (1991) */
  94. R = maxros / 60.0;
  95. I = R * w[fuel] * 8000;
  96. /* get h0 (originally z0) and z0 (e0 + h0) from Chase (1984) */
  97. U = 2 * speed / 88.0;
  98. if (U == 0.0)
  99. E = 0.0; /* to avoid domain error in pow() */
  100. else
  101. E = I * A[fuel] * pow(0.474 * U, B[fuel]);
  102. h0 = 0.3048 * (1.055 * sqrt(E));
  103. U *= 1.609; /* change units to metric */
  104. z0 = DATA(map_elev, row0, col0) + h0;
  105. sin_a = sin(angle * DEG2RAD), cos_a = cos(angle * DEG2RAD);
  106. sqr_ns = window.ns_res * window.ns_res;
  107. sqr_ew = window.ew_res * window.ew_res;
  108. /* vertical change using F=1.3*U*(dz)^.5, simplified from Chase (1984) */
  109. S = 0;
  110. row = row0 - cos_a + 0.5, col = col0 + sin_a + 0.5;
  111. if (row < 0 || row >= nrows || col < 0 || col >= ncols) /* outside */
  112. return (S);
  113. i = 1;
  114. while (1) {
  115. if (row < 0 || row >= nrows) /* outside the region */
  116. break;
  117. if (col < 0 || col >= ncols) /* outside the region */
  118. break;
  119. sqrd = (row - row0) * (row - row0) * sqr_ns
  120. + (col - col0) * (col - col0) * sqr_ew;
  121. z = z0 - sqrd / (1.69 * U * U);
  122. /* actual target elevation is higher then the potential one */
  123. if (DATA(map_elev, row, col) > z) {
  124. #ifdef DEBUG
  125. printf
  126. ("\nA return: m%d U=%d(m/h) h0=%d(m) e0(%d,%d)=%d z=%d(m) e(%d,%d)=%d s=%d(m)",
  127. (int)fuel, (int)U, (int)h0, row0, col0, DATA(map_elev, row0,
  128. col0), (int)z,
  129. row, col, DATA(map_elev, row, col), S);
  130. #endif
  131. return (S);
  132. }
  133. /* advance a step, increase the spotting distance */
  134. S = sqrt((double)sqrd);
  135. #ifdef DEBUG
  136. printf
  137. ("\nm%d U=%d(m/h) h0=%d(m) e0(%d,%d)=%d z=%d(m) e(%d,%d)=%d s=%d(m)",
  138. (int)fuel, (int)U, (int)h0, row0, col0, DATA(map_elev, row0,
  139. col0), (int)z, row,
  140. col, DATA(map_elev, row, col), S);
  141. #endif
  142. i++;
  143. row = row0 - i * cos_a + 0.5, col = col0 + i * sin_a + 0.5;
  144. if (row < 0 || row >= nrows || col < 0 || col >= ncols)
  145. return (S); /* outside the region */
  146. }
  147. return S;
  148. }