spot_dist.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 0.017453292
  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. int spot_dist(int fuel, float maxros, int speed, float angle, int row0,
  55. int col0)
  56. {
  57. /* variables in Chase (1984) (use h0 for z0 which for e0 + h0) */
  58. double h0; /* initial firebrand height (m) */
  59. double E; /* thermal strength (Btu/ft) */
  60. double I; /* mean fire intensity (Btu/ft/s) */
  61. double U; /* mean windspeed at 6 meter (km/h) */
  62. /* variables in Rothermel (1991) */
  63. float R; /* forward rate of spread (ROS) (ft/s) */
  64. /* other variables */
  65. extern CELL *map_elev; /* elevation map array */
  66. extern int nrows, ncols;
  67. extern struct Cell_head window;
  68. double z0; /* initial firebrand elevation (m) */
  69. double z; /* firebrand height (m) */
  70. int row, col; /* a cell under a spotting trajatory */
  71. int S; /* spotting distance on an terrain (m) */
  72. double sqrd; /* distance from cell0 to cell */
  73. double sin_a, cos_a; /* of the wind angle */
  74. double sqr_ns, sqr_ew; /* square resolutions for speed */
  75. int i; /* for advance a step */
  76. if (fuel == 8) /* no spotting from closed timber litter */
  77. return (0);
  78. /* get I from Byram's equation, I = R*w*h, cited in Rothermel (1991) */
  79. R = maxros / 60.0;
  80. I = R * w[fuel] * 8000;
  81. /* get h0 (originally z0) and z0 (e0 + h0) from Chase (1984) */
  82. U = 2 * speed / 88.0;
  83. if (U == 0.0)
  84. E = 0.0; /* to avoid domain error in pow() */
  85. else
  86. E = I * A[fuel] * pow(0.474 * U, B[fuel]);
  87. h0 = 0.3048 * (1.055 * sqrt(E));
  88. U *= 1.609; /* change units to metric */
  89. z0 = DATA(map_elev, row0, col0) + h0;
  90. sin_a = sin(angle * DEG2RAD), cos_a = cos(angle * DEG2RAD);
  91. sqr_ns = window.ns_res * window.ns_res;
  92. sqr_ew = window.ew_res * window.ew_res;
  93. /* vertical change using F=1.3*U*(dz)^.5, simplified from Chase (1984) */
  94. S = 0;
  95. row = row0 - cos_a + 0.5, col = col0 + sin_a + 0.5;
  96. if (row < 0 || row >= nrows || col < 0 || col >= ncols) /* outside */
  97. return (S);
  98. i = 1;
  99. while (1) {
  100. if (row < 0 || row >= nrows) /* outside the region */
  101. break;
  102. if (col < 0 || col >= ncols) /* outside the region */
  103. break;
  104. sqrd = (row - row0) * (row - row0) * sqr_ns
  105. + (col - col0) * (col - col0) * sqr_ew;
  106. z = z0 - sqrd / (1.69 * U * U);
  107. if (DATA(map_elev, row, col) > z) {
  108. #ifdef DEBUG
  109. printf
  110. ("\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)",
  111. (int)fuel, (int)U, (int)h0, row0, col0, DATA(map_elev, row0,
  112. col0), (int)z,
  113. row, col, DATA(map_elev, row, col), S);
  114. #endif
  115. return (S);
  116. }
  117. /* advance a step */
  118. S = sqrt((double)sqrd);
  119. #ifdef DEBUG
  120. printf
  121. ("\nm%d U=%d(m/h) h0=%d(m) e0(%d,%d)=%d z=%d(m) e(%d,%d)=%d s=%d(m)",
  122. (int)fuel, (int)U, (int)h0, row0, col0, DATA(map_elev, row0,
  123. col0), (int)z, row,
  124. col, DATA(map_elev, row, col), S);
  125. #endif
  126. i++;
  127. row = row0 - i * cos_a + 0.5, col = col0 + i * sin_a + 0.5;
  128. if (row < 0 || row >= nrows || col < 0 || col >= ncols)
  129. return (S); /* outside the region */
  130. }
  131. return S;
  132. }