📄 firelib.c
字号:
Fuel_WindB(catalog,model) = 0.02526 * pow(sigma, 0.54);
c = 7.47 * exp(-0.133 * pow(sigma, 0.55));
e = 0.715 * exp(-0.000359 * sigma);
Fuel_WindK(catalog,model) = c * pow(ratio, -e);
Fuel_WindE(catalog,model) = pow(ratio, e) / c;
/* If no live fuel, we're done. */
if ( lifeLoad[FIRE_LIFE_LIVE] < Smidgen )
return (FuelCat_Status(catalog) = FIRE_STATUS_OK);
/* Fine dead fuel and fine live fuel factors. */
for ( particle=0; particle<Fuel_Particles(catalog,model); particle++ )
{
if ( Fuel_Live(catalog,model,particle) )
fineLive
+= Fuel_Load(catalog,model,particle)
* exp(-500. / Fuel_Savr(catalog,model,particle));
else
Fuel_FineDead(catalog,model)
+= Fuel_Load(catalog,model,particle)
* Fuel_SigmaFactor(catalog,model,particle);
}
/* Live fuel extinction moisture factor. */
if ( fineLive > Smidgen )
Fuel_LiveMextFactor(catalog,model)
= 2.9 * Fuel_FineDead(catalog,model) / fineLive;
/* That's all, folks!. */
return (FuelCat_Status(catalog) = FIRE_STATUS_OK);
}
/*
*******************************************************************************
*
* Fire_SpreadNoWindNoSlope()
*
* Description
* Calculates the fire reaction intensity and no-wind, no-slope spread
* rate given the fuel model, combustion, and moisture regime inputs.
*
* Side Effects
* Updates the following fire behavior variables:
* Fuel_RxIntensity(catalog,model).
* Fuel_HeatPerUnitArea(catalog,model).
* Fuel_Spread0(catalog,model).
* Fuel_SpreadMax(catalog,model) = Fuel_Spread0(catalog,model)
* Fuel_SpreadAny(catalog,model) = Fuel_Spread0(catalog,model)
* Fuel_AzimuthAny(catalog,model) = 0.
* Fuel_AzimuthMax(catalog,model) = 0.
*
* Function Returns
* FIRE_STATUS_OK or FIRE_STATUS_ERROR.
* Return status and error text are stored in the Fire Catalog's buffers.
*
*******************************************************************************
*/
int
Fire_SpreadNoWindNoSlope ( FuelCatalogPtr catalog, size_t model, double moisture[FIRE_MCLASSES] )
// FuelCatalogPtr catalog; /* FuelCatalogData instance pointer */
// size_t model; /* fuel model number [0-maxModels] */
// double moisture[FIRE_MCLASSES]; /* array of fuel moistures (fractions) */
{
size_t mclass, particle, life, nlive;
double wfmd;
double rbQig;
double fdmois;
double qig;
double ratio;
double lifeMoisture[FIRE_LIFE_CATS];
double lifeEtaM[FIRE_LIFE_CATS];
double lifeMext[FIRE_LIFE_CATS];
static size_t TimeLagClass[FIRE_SIZE_CLASSES] = {0, 0, 1, 1, 2, 2};
/* Validate the catalog and fuel model. */
assert(catalog!= NULL && FuelCat_MagicCookie(catalog)==FIRE_CATALOG_MAGIC);
if ( ! Fire_FuelModelExists(catalog,model) )
{
sprintf(FuelCat_Error(catalog),
"Fire_SpreadNoWindNoSlope(): el modelo de combustible %d no existe en el cat醠ogo de combustibles \"%s\".",
model, FuelCat_Name(catalog));
return (FuelCat_Status(catalog) = FIRE_STATUS_ERROR);
}
/* Check if we must recalculate combustion intermediates. */
if ( ! Fuel_CombustionFlag(catalog,model) )
{
Fire_FuelCombustion(catalog,model);
}
/* Otherwise check if the moisture environment has changed. */
else
{
for ( mclass=0; mclass<FIRE_MCLASSES; mclass++ )
if ( ! Equal(moisture[mclass],Fuel_EnvMoisture(catalog,model,mclass)) )
break;
/* If no change in fuel moisture, no more computation is needed. */
if ( mclass == FIRE_MCLASSES )
return (FuelCat_Status(catalog) = FIRE_STATUS_OK);
}
/* Store the new moistures in the fuel's environmental moisture array. */
for ( mclass=0; mclass<FIRE_MCLASSES; mclass++ )
Fuel_EnvMoisture(catalog,model,mclass) = moisture[mclass];
/* Initialize the model's fire behavior variables. */
/* These are calculated by this function. */
Fuel_Spread0(catalog,model) = 0.;
Fuel_RxIntensity(catalog,model) = 0.;
Fuel_HeatPerUnitArea(catalog,model) = 0.;
/* Initialize the model's fire behavior variables. */
/* These are calculated by Fire_SpreadWindSlopeMax(). */
Fuel_SpreadMax(catalog,model) = 0.;
Fuel_AzimuthMax(catalog,model) = 0.;
/* Initialize the model's fire behavior variables. */
/* These are calculated by Fire_SpreadAtAzimuth(). */
Fuel_SpreadAny(catalog,model) = 0.;
Fuel_AzimuthAny(catalog,model) = 0.;
Fuel_ByramsIntensity(catalog,model) = 0.;
Fuel_FlameLength(catalog,model) = 0.;
Fuel_ScorchHeight(catalog,model) = 0.;
/* If no fuel particles, return. */
if (Fuel_Particles(catalog,model) <= 0)
return (FuelCat_Status(catalog) = FIRE_STATUS_OK);
/* Initialize local variables. */
wfmd = fdmois = rbQig = 0.;
for ( life=0; life<FIRE_LIFE_CATS; life++ )
{
lifeMoisture[life] = 0.;
lifeEtaM[life] = 0.;
lifeMext[life] = 0.;
}
/* Assign particle moistures based upon their size class. */
nlive = 0;
for ( particle=0; particle<Fuel_Particles(catalog,model); particle++ )
{
/* if this is a dead fuel, accumulate its wtd fuel moisture. */
if ( Fuel_Live(catalog,model,particle) == FIRE_LIFE_DEAD )
{
mclass = TimeLagClass[Fuel_SizeClass(catalog,model,particle)];
wfmd += moisture[mclass]
* Fuel_SigmaFactor(catalog,model,particle)
* Fuel_Load(catalog,model,particle);
}
else
{
nlive++;
mclass = (Fuel_Type(catalog,model,particle) == FIRE_TYPE_HERB) ?
FIRE_MCLASS_HERB : FIRE_MCLASS_WOOD;
}
/* Assign this particle the fuel moisture for its size class. */
Fuel_Moisture(catalog,model,particle) = moisture[mclass];
}
/* Compute live fuel extinction moisture. */
if ( nlive )
{
fdmois = ( Fuel_FineDead(catalog,model) > Smidgen ) ?
(wfmd / Fuel_FineDead(catalog,model)) : 0.;
lifeMext[FIRE_LIFE_LIVE]
= ((Fuel_LiveMextFactor(catalog,model)
* (1.0 - fdmois/Fuel_Mext(catalog,model))) - 0.226);
if ( lifeMext[FIRE_LIFE_LIVE] < Fuel_Mext(catalog,model) )
lifeMext[FIRE_LIFE_LIVE] = Fuel_Mext(catalog,model);
}
/* Dead fuel extinction moisture is a fuel model input. */
lifeMext[FIRE_LIFE_DEAD] = Fuel_Mext(catalog,model);
/* Compute category weighted moisture and accumulate the rbQig. */
for (particle=0; particle<Fuel_Particles(catalog,model); particle++)
{
qig = 250. + 1116. * Fuel_Moisture(catalog,model,particle);
life = Fuel_Live(catalog,model,particle);
lifeMoisture[life] += Fuel_AreaWtg(catalog,model,particle)
* Fuel_Moisture(catalog,model,particle);
rbQig += qig
* Fuel_AreaWtg(catalog,model,particle)
* Fuel_LifeAreaWtg(catalog,model,life)
* Fuel_SigmaFactor(catalog,model,particle);
}
/* Complete the rbQig calculation. */
rbQig *= Fuel_BulkDensity(catalog,model);
/* Compute moisture damping coeff by life class, and combine with the */
/* life class's rx factor to get the total reaction intensity. */
for (life=0; life<FIRE_LIFE_CATS; life++)
{
ratio = 0.;
if ( lifeMext[life] > Smidgen )
{
ratio = lifeMoisture[life] / lifeMext[life];
lifeEtaM[life] =
1.0 - 2.59*ratio + 5.11*ratio*ratio - 3.52*ratio*ratio*ratio;
}
/* If category moisture exceeds category extinction moisture, */
/* the damping coefficient is zero. */
if ( lifeMoisture[life] >= lifeMext[life] )
lifeEtaM[life] = 0.;
/* Accumulate total reaction intensity. */
Fuel_RxIntensity(catalog,model)
+= Fuel_LifeRxFactor(catalog,model,life)
* lifeEtaM[life];
}
/* Calculate heat per unit area from rx intensity and residence time. */
Fuel_HeatPerUnitArea(catalog,model)
= Fuel_RxIntensity(catalog,model)
* Fuel_ResidenceTime(catalog,model);
/* Calculate no-wind, no-slope spread rate. */
Fuel_Spread0(catalog,model)
= (rbQig > Smidgen)
? Fuel_RxIntensity(catalog,model) * Fuel_PropFlux(catalog,model) / rbQig
: 0.;
/* Re-initialize spread in maximum and any azimuth to no wind-no slope. */
Fuel_SpreadMax(catalog,model) = Fuel_Spread0(catalog,model);
Fuel_SpreadAny(catalog,model) = Fuel_Spread0(catalog,model);
Fuel_AzimuthMax(catalog,model) = Fuel_AzimuthAny(catalog,model) = 0.;
return (FuelCat_Status(catalog) = FIRE_STATUS_OK);
}
/*
*******************************************************************************
*
* Fire_SpreadWindSlopeMax()
*
* Description
* Calculates maximum fire spread rate and direction under the given
* wind-slope conditions. Results depend only upon:
* - no wind-slope spread rate
* - wind speed and direction
* - aspect and slope
*
* Side Effects
* Updates the following variables:
* Fuel_Slope() = slope;
* Fuel_PhiSlope().
* Fuel_Wind() = windFpm;
* Fuel_PhiWind().
* Fuel_Aspect(catalog,model) = aspect;
* Fuel_WindDir(catalog,model) = windDeg;
* Fuel_PhiEffWind(catalog,model) = phiEw;
* Fuel_EffectiveWind(catalog,model) = effectiveWind;
* Fuel_WindLimit(catalog,model) = windLimit;
* Fuel_SpreadMax(catalog,model) = spreadMax;
* Fuel_AzimuthMax(catalog,model) = azimuthMax;
* Fuel_LwRatio(catalog,model) = lwRatio;
* Fuel_Eccentricity(catalog,model) = eccentricity;
*
* Resets Fire_SpreadAtAzimuth() variables:
* Fuel_SpreadAny(catalog,model) = spreadMax;
* Fuel_AzimuthAny(catalog,model) = azimuthMax;
* Fuel_ByramsIntensity(catalog,model) = 0.;
* Fuel_FlameLength(catalog,model) = 0.;
* Fuel_ScorchHeight(catalog,model) = 0.;
*
* Previous Fire_SpreadAtAzimiuth() results become obsolete for this model.
*
* Function Returns
* FIRE_STATUS_OK or FIRE_STATUS_ERROR.
* Return status and error text are stored in the Fire Catalog's buffers.
*
*******************************************************************************
*/
int
Fire_SpreadWindSlopeMax ( FuelCatalogPtr catalog, size_t model, double windFpm, double windDeg, double slope, double aspect )
// FuelCatalogPtr catalog; /* FuelCatalogData instance pointer */
// size_t model; /* fuel model number [0-maxModels] */
// double windFpm; /* wind speed (ft/min) */
// double windDeg; /* wind bearing vector (compass degrees) */
// double slope; /* slope (rise/reach) */
// double aspect; /* aspect (downslope) azimuth (compass deg) */
{
double upslope, azimuthMax, phiEw;
double splitDeg, splitRad;
double slpRate, wndRate, rv, spreadMax;
double x, y, al, a;
double maxWind, effectiveWind, lwRatio, eccentricity;
size_t doEffectiveWind, checkWindLimit, windLimit;
/* Validate the catalog and fuel model. */
assert(catalog!= NULL && FuelCat_MagicCookie(catalog)==FIRE_CATALOG_MAGIC);
if ( ! Fire_FuelModelExists(catalog,model) )
{
sprintf(FuelCat_Error(catalog),
"Fire_SpreadMax(): el modelo de combustible %d no existe en el cat醠ogo de combustibles \"%s\".",
model, FuelCat_Name(catalog));
return (FuelCat_Status(catalog) = FIRE_STATUS_ERROR);
}
/* Recalculate slope factors ONLY if different from previous model input. */
if ( ! Equal(Fuel_Slope(catalog,model),slope) )
{
Fuel_PhiSlope(catalog,model) =
Fuel_SlopeK(catalog,model) * slope * slope;
Fuel_Slope(catalog,model) = slope;
}
/* Recalculate wind factors ONLY if different from previous model input. */
if ( ! Equal(Fuel_WindSpeed(catalog,model),windFpm) )
{
Fuel_PhiWind(catalog,model) = (windFpm < Smidgen) ? 0. :
Fuel_WindK(catalog,model) * pow(windFpm, Fuel_WindB(catalog,model));
Fuel_WindSpeed(catalog,model) = windFpm;
}
/* Combine wind and slope factors. */
phiEw = Fuel_PhiSlope(catalog,model) + Fuel_PhiWind(catalog,model);
windLimit = 0;
lwRatio = 1.;
eccentricity = 0.;
upslope = (aspect>=180.) ? aspect-180. : aspect+180.;
/* Situation 1: no fire spread or reaction intensity. */
if ( Fuel_Spread0(catalog,model) < Smidgen )
{
spreadMax = 0.;
azimuthMax = 0;
/* There IS an effective wind even if there is no fire. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -