#include "fireLib.h"
#define INFINITY 999999999. /* or
close enough */
/* these modify map size & resolution.
*/
static int Rows = 64; /* Number of rows in each map. */
static int Cols = 64;
; /* Number of columns in each map. */
static double CellWd = 220.; /* Cell width (E-W) in feet. */
static double CellHt = 220.; /* Cell height (N-S) in feet. */
/* these set uniform burning conditions.
*/
static size_t Model = 0; /* NFFL 1 */
static double WindSpd = 0; /* mph */
static double WindDir = 0; /* degrees clockwise from north */
static double Slope = 0.0; /* fraction rise / reach */
static double Aspect = 0.0; /* degrees clockwise from north */
static double M1 = 0; /* 1-hr dead fuel moisture */
static double M10 = 0; /* 10-hr dead fuel moisture */
static double M100 = 0; /* 100-hr dead fuel moisture */
static double Mherb = 0; /* Live herbaceous fuel moisture */
static double Mwood = 0; /* Live woody fuel moisture */
static int PrintMap _ANSI_ARGS_((double
*map, char *fileName ));
int main ( int argc, char **argv )
{
/* neighbor's address*/ /* N NE E SE S SW W NW */
static int nCol[8] = { 0, 1, 1, 1, 0, -1, -1, -1};
static int nRow[8] = { 1, 1, 0, -1, -1, -1, 0, 1};
static int nTimes = 0; /* counter for number of time steps */
FuelCatalogPtr catalog; /* fuel catalog handle */
double nDist[8]; /* distance to each neighbor */
double nAzm[8]; /* compass azimuth to each neighbor (0=N) */
double timeNow; /* current time (minutes) */
double timeNext; /* time of next cell ignition (minutes) */
int row, col, cell; /* row, col, and index of current cell */
int nrow, ncol, ncell; /* row, col, and index of neighbor cell */
int n, cells; /* neighbor index, total number of map cells */
size_t modelNumber; /* fuel model number at current cell */
double moisture[6]; /* fuel moisture content at current cell */
double fpm; /* spread rate in direction of neighbor */
double minutes; /* time to spread from cell to neighbor */
double ignTime; /* time neighbor is ignited by current cell */
int atEdge; /* flag indicating fire has reached edge */
size_t *fuelMap; /* ptr to fuel model map */
double *ignMap; /* ptr to ignition time map (minutes) */
double *flMap; /* ptr to flame length map (feet) */
double *slpMap; /* ptr to slope map (rise/reach) */
double *aspMap; /* ptr to aspect map (degrees from north) */
double *wspdMap; /* ptr to wind speed map (ft/min) */
double *wdirMap; /* ptr to wind direction map (deg from north) */
double *m1Map; /* ptr to 1-hr dead fuel moisture map */
double *m10Map; /* ptr to 10-hr dead fuel moisture map */
double *m100Map; /* ptr to 100-hr dead fuel moisture map */
double *mherbMap; /* ptr to live herbaceous fuel moisture map */
double *mwoodMap; /* ptr to live stem fuel moisture map */
/*take user inputs*/
printf("Which fuel model(0-13)
will the fire burn through? ");
scanf("%d", &Model);
printf("What is the current wind speed in mph? ");
scanf("%lf", &WindSpd);
printf("How many degrees clockwise from north is the wind coming
from? ");
scanf("%lf", &WindDir);
printf("What is the average slope? ");
scanf("%lf", &Slope);
printf("How many degrees clockwise from north is the slope coming
from? ");
scanf("%lf", &Aspect);
printf("What is the one hour mosture content? ");
scanf("%f", &M1);
printf("What is the ten hour mosture content? ");
scanf("%f", &M10);
printf("What is the hundred hour mosture content? ");
scanf("%f", &M100);
printf("What is the live fuel mosture content for the area? ");
scanf("%f", &Mherb);
printf("What is the dead fuel mosture content for the area? ");
scanf("%f", &Mwood);
printf("\n");
/* allocate all the maps. */
cells = Rows * Cols;
if ( (ignMap = (double *) calloc(cells, sizeof(double))) == NULL
|| (flMap = (double *) calloc(cells, sizeof(double))) == NULL
|| (slpMap = (double *) calloc(cells, sizeof(double))) == NULL
|| (aspMap = (double *) calloc(cells, sizeof(double))) == NULL
|| (wspdMap = (double *) calloc(cells, sizeof(double))) == NULL
|| (wdirMap = (double *) calloc(cells, sizeof(double))) == NULL
|| (m1Map = (double *) calloc(cells, sizeof(double))) == NULL
|| (m10Map = (double *) calloc(cells, sizeof(double))) == NULL
|| (m100Map = (double *) calloc(cells, sizeof(double))) == NULL
|| (mherbMap = (double *) calloc(cells, sizeof(double))) == NULL
|| (mwoodMap = (double *) calloc(cells, sizeof(double))) == NULL
|| (fuelMap = (size_t *) calloc(cells, sizeof(size_t))) == NULL )
{
fprintf(stderr, "Unable to allocate maps with %d cols and %d rows.\n",
Cols, Rows);
return (1);
}
/*initialize all the maps */
for ( cell=0; cell<cells; cell++ )
{
fuelMap[cell] = Model;
slpMap[cell] = Slope;
aspMap[cell] = Aspect;
wspdMap[cell] = 88. * WindSpd; /* convert mph into ft/min */
wdirMap[cell] = WindDir;
m1Map[cell] = M1;
m10Map[cell] = M10;
m100Map[cell] = M100;
mherbMap[cell] = Mherb;
mwoodMap[cell] = Mwood;
ignMap[cell] = INFINITY;
flMap[cell] = 0.;
}
/* set an ignition time & pattern
(this ignites the middle cell). */
cell = Cols/2 + Cols*(Rows/4);
ignMap[cell] = 100.0;
cell = 2*Cols/3 + Cols*(Rows/4);
ignMap[cell] = 1.0;
/* create a standard fuel model catalog
and a flame length table. */
catalog = Fire_FuelCatalogCreateStandard("Standard", 13);
Fire_FlameLengthTable(catalog, 0, 0);
/* Calculate distance across cell
to each neighbor and its azimuth. */
for ( n=0; n<8; n++ )
{
nDist[n] = sqrt ( nCol[n] * CellWd * nCol[n] * CellWd
+ nRow[n] * CellHt * nRow[n] * CellHt );
nAzm[n] = n * 45.;
}
/* find the earliest (starting) ignition
time. */
for ( timeNext=INFINITY, cell=0; cell<cells; cell++ )
{
if ( ignMap[cell] < timeNext )
timeNext = ignMap[cell];
}
/* loop until no more cells can ignite
or fire reaches an edge. */
atEdge = 0;
while ( timeNext < INFINITY && ! atEdge )
{
timeNow = timeNext;
timeNext = INFINITY;
nTimes++;
/* examine each ignited cell in the
fuel array. */
for ( cell=0, row=0; row<Rows; row++ )
{
for ( col=0; col<Cols; col++, cell++ )
{
/* Skip this cell if it has not ignited. */
if ( ignMap[cell] > timeNow )
{
/* first check if it is the next cell to ignite. */
if ( ignMap[cell] < timeNext )
timeNext = ignMap[cell];
continue;
}
/* flag if the fire has reached the
array edge. */
if ( row==0 || row==Rows-1 || col==0 || col==Cols-1 )
atEdge = 1;
/* determine basic fire behavior
within this cell. */
modelNumber = fuelMap[cell];
moisture[0] = m1Map[cell];
moisture[1] = m10Map[cell];
moisture[2] = m100Map[cell];
moisture[3] = m100Map[cell];
moisture[4] = mherbMap[cell];
moisture[5] = mwoodMap[cell];
Fire_SpreadNoWindNoSlope(catalog, modelNumber, moisture);
Fire_SpreadWindSlopeMax(catalog, modelNumber, wspdMap[cell],
wdirMap[cell], slpMap[cell], aspMap[cell]);
/* examine each unignited neighbor.
*/
for ( n=0; n<8; n++ )
{
/* First find the neighbor's location. */
nrow = row + nRow[n];
ncol = col + nCol[n];
if ( nrow<0 || nrow>=Rows || ncol<0 || ncol>=Cols )
continue;
ncell = ncol + nrow*Cols;
/* Skip this neighbor if it is already
ignited. */
if ( ignMap[ncell] <= timeNow )
continue;
/* Determine time to spread to this
neighbor. */
Fire_SpreadAtAzimuth(catalog, modelNumber, nAzm[n], FIRE_FLAME | FIRE_BYRAMS);
if ( (fpm = Fuel_SpreadAny(catalog, modelNumber)) > Smidgen)
{
minutes = nDist[n] / fpm;
/* Assign neighbor the earliest ignition
time. */
if ( (ignTime = timeNow + minutes) < ignMap[ncell] )
{
ignMap[ncell] = ignTime;
Fire_FlameScorch(catalog, modelNumber, FIRE_FLAME );
flMap[ncell] = Fuel_FlameLength(catalog,modelNumber);
}
/* Keep track of next cell ignition
time. */
if ( ignTime < timeNext )
timeNext = ignTime;
}
} /* next neighbor n */
} /* next source col */
} /* next source row */
} /* next time */
/*print fire outputs*/
printf("The Flame Length is %2.2f feet.\n",
Fuel_FlameLength(catalog, modelNumber));
printf("The spread rate is %3.2f feet per minute.\n",
Fuel_SpreadAny(catalog, modelNumber));
printf("The wind speed is %3.2f miles per hour.\n",
WindSpd);
printf("The fuel model %d was used.\n",
Fuel_Model(catalog, modelNumber));
printf("The heat per square foot of fuel bed is %3.2f BTU.\n",
Fuel_HeatPerUnitArea(catalog, modelNumber));
printf("The fire line intensity at the current azimuth is %3.2f.\n",
Fuel_ByramsIntensity(catalog, modelNumber));
printf("The wind is coming form %3.0f degrees clockwise from north.\n",
WindDir);
getch();
/* if requested, save the ignition & flame length maps. */
if ( argc > 1 )
PrintMap(ignMap, argv[1]);
if ( argc > 2 )
PrintMap(flMap, argv[2]);
return (0);
}
static int PrintMap ( map, fileName
)
double *map;
char *fileName;
{
FILE *fPtr;
int cell, col, row;
if ( (fPtr = fopen(fileName, "w"))
== NULL )
{
printf("Unable to open output map \"%s\".\n", fileName);
return (FIRE_STATUS_ERROR);
}
fprintf(fPtr, "north: %1.0f\nsouth:
%1.0f\neast: %1.0f\nwest: %1.0f\nrows: %d\ncols: %d\n",
(Rows*CellHt), 0., (Cols*CellWd), 0., Rows, Cols);
for ( row=Rows-1; row>=0; row-- )
{
for ( cell=row*Cols, col=0; col<Cols; col++, cell++ )
{
fprintf(fPtr, " %1.0f", (map[cell]==INFINITY) ? 0.0 : map[cell]);
}
fprintf(fPtr, "\n");
}
fclose(fPtr);
return (FIRE_STATUS_OK);
} |