Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
275 changes: 141 additions & 134 deletions src/behave/ignite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,130 +98,133 @@ double Ignite::calculateFuelTemperature()
return fuelTemperature_;
}

double Ignite::calculateLightningIgnitionProbability(FractionUnits::FractionUnitsEnum desiredUnits)
{
/*
* The following assumptions are made by Latham:
* - 20% of negative flashes have continuing current
* - 90% of positive flashes have continuing current
* - Latham and Schlieter found a relative frequency of
* 0.723 negative and 0.277 positive strikes
* - Unknown strikes are therefore p = 0.1446 neg + 0.2493 pos
*/

// Probability of continuing current by charge type (Latham)
static const double ccNeg = 0.2;
static const double ccPos = 0.9;

// Relative frequency by charge type (Latham and Schlieter)
static const double freqNeg = 0.723;
static const double freqPos = 0.277;

// Convert duff depth to cm and restrict to maximum of 10 cm.
double duffDepth = igniteInputs_.getDuffDepth(LengthUnits::Centimeters);

duffDepth *= 2.54;
if (duffDepth > 10.0)
{
duffDepth = 10.0;
}

// use hundred hour moisture as duff moisture and conver to percent and restrict to maximum of 40%.
double fuelMoisture = igniteInputs_.getMoistureHundredHour(FractionUnits::Percent);
if (fuelMoisture > 40.0)
{
fuelMoisture = 40.0;
}

double pPos = 0.0;
double pNeg = 0.0;
double probabilityOfLightningIgnition = 0.0;

IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelType = igniteInputs_.getIgnitionFuelBedType();
switch (fuelType)
{
case IgnitionFuelBedType::PonderosaPineLitter:
{
pPos = 0.92 * exp(-0.087 * fuelMoisture);
pNeg = 1.04 * exp(-0.054 * fuelMoisture);
break;
}
case IgnitionFuelBedType::PunkyWoodRottenChunky:
{
pPos = 0.44 * exp(-0.110 * fuelMoisture);
pNeg = 0.59 * exp(-0.094 * fuelMoisture);
break;
}
case IgnitionFuelBedType::PunkyWoodPowderDeep:
{
pPos = 0.86 * exp(-0.060 * fuelMoisture);
pNeg = 0.90 * exp(-0.056 * fuelMoisture);
break;
}
case IgnitionFuelBedType::PunkWoodPowderShallow:
{
pPos = 0.60 - (0.011 * fuelMoisture);
pNeg = 0.73 - (0.011 * fuelMoisture);
break;
}
case IgnitionFuelBedType::LodgepolePineDuff:
{
pPos = 1.0 / (1.0 + exp(5.13 - 0.68 * duffDepth));
pNeg = 1.0 / (1.0 + exp(3.84 - 0.60 * duffDepth));
break;
}
case IgnitionFuelBedType::DouglasFirDuff:
{
pPos = 1.0 / (1.0 + exp(6.69 - 1.39 * duffDepth));
pNeg = 1.0 / (1.0 + exp(5.48 - 1.28 * duffDepth));
break;
}
case IgnitionFuelBedType::HighAltitudeMixed:
{
pPos = 0.62 * exp(-0.050 * fuelMoisture);
pNeg = 0.80 - (0.014 * fuelMoisture);
break;
}
case IgnitionFuelBedType::PeatMoss:
{
pPos = 0.71 * exp(-0.070 * fuelMoisture);
pNeg = 0.84 * exp(-0.060 * fuelMoisture);
break;
}
}

LightningCharge::LightningChargeEnum charge = igniteInputs_.getLightningChargeType();
switch (charge)
{
case LightningCharge::Negative:
{
probabilityOfLightningIgnition = ccNeg * pNeg;
break;
}
case LightningCharge::Positive:
{
probabilityOfLightningIgnition = ccPos * pPos;
break;
}
case LightningCharge::Unknown:
{
probabilityOfLightningIgnition = freqPos * ccPos * pPos + freqNeg * ccNeg * pNeg;
break;
}
}

// Constrain result
if (probabilityOfLightningIgnition < 0.0)
{
probabilityOfLightningIgnition = 0.0;
}
if (probabilityOfLightningIgnition > 1.0)
{
probabilityOfLightningIgnition = 1.0;
}

return FractionUnits::fromBaseUnits(probabilityOfLightningIgnition, desiredUnits);
}
/* Deprecated as the science is no longer considered reliable.
There is no known method to accurately calculate Probability of Ignition from a lightning strike. */
// double Ignite::calculateLightningIgnitionProbability(FractionUnits::FractionUnitsEnum desiredUnits)
// {
// /*
// * The following assumptions are made by Latham:
// * - 20% of negative flashes have continuing current
// * - 90% of positive flashes have continuing current
// * - Latham and Schlieter found a relative frequency of
// * 0.723 negative and 0.277 positive strikes
// * - Unknown strikes are therefore p = 0.1446 neg + 0.2493 pos
// */
//
// // Probability of continuing current by charge type (Latham)
// static const double ccNeg = 0.2;
// static const double ccPos = 0.9;
//
// // Relative frequency by charge type (Latham and Schlieter)
// static const double freqNeg = 0.723;
// static const double freqPos = 0.277;
//
// // Convert duff depth to cm and restrict to maximum of 10 cm.
// double duffDepth = igniteInputs_.getDuffDepth(LengthUnits::Centimeters);
//
// duffDepth *= 2.54;
// if (duffDepth > 10.0)
// {
// duffDepth = 10.0;
// }
//
// // use hundred hour moisture as duff moisture and conver to percent and restrict to maximum of 40%.
// double fuelMoisture = igniteInputs_.getMoistureHundredHour(FractionUnits::Percent);
// if (fuelMoisture > 40.0)
// {
// fuelMoisture = 40.0;
// }
//
// double pPos = 0.0;
// double pNeg = 0.0;
// double probabilityOfLightningIgnition = 0.0;
//
// IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelType = igniteInputs_.getIgnitionFuelBedType();
// switch (fuelType)
// {
// case IgnitionFuelBedType::PonderosaPineLitter:
// {
// pPos = 0.92 * exp(-0.087 * fuelMoisture);
// pNeg = 1.04 * exp(-0.054 * fuelMoisture);
// break;
// }
// case IgnitionFuelBedType::PunkyWoodRottenChunky:
// {
// pPos = 0.44 * exp(-0.110 * fuelMoisture);
// pNeg = 0.59 * exp(-0.094 * fuelMoisture);
// break;
// }
// case IgnitionFuelBedType::PunkyWoodPowderDeep:
// {
// pPos = 0.86 * exp(-0.060 * fuelMoisture);
// pNeg = 0.90 * exp(-0.056 * fuelMoisture);
// break;
// }
// case IgnitionFuelBedType::PunkWoodPowderShallow:
// {
// pPos = 0.60 - (0.011 * fuelMoisture);
// pNeg = 0.73 - (0.011 * fuelMoisture);
// break;
// }
// case IgnitionFuelBedType::LodgepolePineDuff:
// {
// pPos = 1.0 / (1.0 + exp(5.13 - 0.68 * duffDepth));
// pNeg = 1.0 / (1.0 + exp(3.84 - 0.60 * duffDepth));
// break;
// }
// case IgnitionFuelBedType::DouglasFirDuff:
// {
// pPos = 1.0 / (1.0 + exp(6.69 - 1.39 * duffDepth));
// pNeg = 1.0 / (1.0 + exp(5.48 - 1.28 * duffDepth));
// break;
// }
// case IgnitionFuelBedType::HighAltitudeMixed:
// {
// pPos = 0.62 * exp(-0.050 * fuelMoisture);
// pNeg = 0.80 - (0.014 * fuelMoisture);
// break;
// }
// case IgnitionFuelBedType::PeatMoss:
// {
// pPos = 0.71 * exp(-0.070 * fuelMoisture);
// pNeg = 0.84 * exp(-0.060 * fuelMoisture);
// break;
// }
// }
//
// LightningCharge::LightningChargeEnum charge = igniteInputs_.getLightningChargeType();
// switch (charge)
// {
// case LightningCharge::Negative:
// {
// probabilityOfLightningIgnition = ccNeg * pNeg;
// break;
// }
// case LightningCharge::Positive:
// {
// probabilityOfLightningIgnition = ccPos * pPos;
// break;
// }
// case LightningCharge::Unknown:
// {
// probabilityOfLightningIgnition = freqPos * ccPos * pPos + freqNeg * ccNeg * pNeg;
// break;
// }
// }
//
// // Constrain result
// if (probabilityOfLightningIgnition < 0.0)
// {
// probabilityOfLightningIgnition = 0.0;
// }
// if (probabilityOfLightningIgnition > 1.0)
// {
// probabilityOfLightningIgnition = 1.0;
// }
//
// return FractionUnits::fromBaseUnits(probabilityOfLightningIgnition, desiredUnits);
// }

void Ignite::setAirTemperature(double airTemperature, TemperatureUnits::TemperatureUnitsEnum temperatureUnites)
{
Expand Down Expand Up @@ -253,18 +256,19 @@ void Ignite::setDuffDepth(double duffDepth, LengthUnits::LengthUnitsEnum lengthU
igniteInputs_.setDuffDepth(duffDepth, lengthUnits);
}

void Ignite::setLightningChargeType(LightningCharge::LightningChargeEnum lightningChargeType)
{
igniteInputs_.setLightningChargeType(lightningChargeType);
}
/* Deprecated as the science is no longer considered reliable.
There is no known method to accurately calculate Probability of Ignition from a lightning strike. */
// void Ignite::setLightningChargeType(LightningCharge::LightningChargeEnum lightningChargeType)
// {
// igniteInputs_.setLightningChargeType(lightningChargeType);
// }

void Ignite::updateIgniteInputs(double moistureOneHour, double moistureHundredHour, FractionUnits::FractionUnitsEnum moistureUnits,
double airTemperature, TemperatureUnits::TemperatureUnitsEnum temperatureUnits, double sunShade, FractionUnits::FractionUnitsEnum sunShadeUnits,
IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelBedType, double duffDepth, LengthUnits::LengthUnitsEnum duffDepthUnits,
LightningCharge::LightningChargeEnum lightningChargeType)
IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelBedType, double duffDepth, LengthUnits::LengthUnitsEnum duffDepthUnits)
{
igniteInputs_.updateIgniteInputs(moistureOneHour, moistureHundredHour, moistureUnits, airTemperature,
temperatureUnits, sunShade, sunShadeUnits, fuelBedType, duffDepth, duffDepthUnits, lightningChargeType);
temperatureUnits, sunShade, sunShadeUnits, fuelBedType, duffDepth, duffDepthUnits);
}

double Ignite::getAirTemperature(TemperatureUnits::TemperatureUnitsEnum desiredUnits)
Expand Down Expand Up @@ -302,10 +306,13 @@ double Ignite::getDuffDepth(LengthUnits::LengthUnitsEnum desiredUnits)
return igniteInputs_.getDuffDepth(desiredUnits);
}

LightningCharge::LightningChargeEnum Ignite::getLightningChargeType()
{
return igniteInputs_.getLightningChargeType();
}

/* Deprecated as the science is no longer considered reliable.
There is no known method to accurately calculate Probability of Ignition from a lightning strike. */
// LightningCharge::LightningChargeEnum Ignite::getLightningChargeType()
// {
// return igniteInputs_.getLightningChargeType();
// }

bool Ignite::isFuelDepthNeeded()
{
Expand Down
15 changes: 10 additions & 5 deletions src/behave/ignite.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,23 @@ class Ignite
void initializeMembers();

double calculateFirebrandIgnitionProbability(FractionUnits::FractionUnitsEnum desiredUnits);
double calculateLightningIgnitionProbability(FractionUnits::FractionUnitsEnum desiredUnits);
/* Code is deprecated as the science is no longer considered reliable.
There is no known method to accurately calculate Probability of Ignition from a lightning strike. */
// double calculateLightningIgnitionProbability(FractionUnits::FractionUnitsEnum desiredUnits);

void setMoistureOneHour(double moistureOneHour, FractionUnits::FractionUnitsEnum moistureUnits);
void setMoistureHundredHour(double moistureHundredHour, FractionUnits::FractionUnitsEnum moistureUnits);
void setAirTemperature(double airTemperature, TemperatureUnits::TemperatureUnitsEnum temperatureUnites);
void setSunShade(double sunShade, FractionUnits::FractionUnitsEnum sunShadeUnits);
void setDuffDepth(double duffDepth, LengthUnits::LengthUnitsEnum lengthUnits);
void setIgnitionFuelBedType(IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelBedType_);
void setLightningChargeType(LightningCharge::LightningChargeEnum lightningChargeType);
/* Code is deprecated as the science is no longer considered reliable.
There is no known method to accurately calculate Probability of Ignition from a lightning strike. */
// void setLightningChargeType(LightningCharge::LightningChargeEnum lightningChargeType);

void updateIgniteInputs(double moistureOneHour, double moistureHundredHour, FractionUnits::FractionUnitsEnum moistureUnits,
double airTemperature, TemperatureUnits::TemperatureUnitsEnum temperatureUnits, double sunShade, FractionUnits::FractionUnitsEnum sunShadeUnits,
IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelBedType, double duffDepth, LengthUnits::LengthUnitsEnum duffDepthUnits,
LightningCharge::LightningChargeEnum lightningChargeType);
IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelBedType, double duffDepth, LengthUnits::LengthUnitsEnum duffDepthUnits);

double getAirTemperature(TemperatureUnits::TemperatureUnitsEnum desiredUnits);
double getFuelTemperature(TemperatureUnits::TemperatureUnitsEnum desiredUnits);
Expand All @@ -65,7 +68,9 @@ class Ignite
double getSunShade(FractionUnits::FractionUnitsEnum desiredUnits);
double getDuffDepth(LengthUnits::LengthUnitsEnum desiredUnits);
IgnitionFuelBedType::IgnitionFuelBedTypeEnum getFuelBedType();
LightningCharge::LightningChargeEnum getLightningChargeType();
/* Code is deprecated as the science is no longer considered reliable.
There is no known method to accurately calculate Probability of Ignition from a lightning strike. */
// LightningCharge::LightningChargeEnum getLightningChargeType();

// isFuelDepthNeeded() can be used in applications to determine whether user input of fuel bed depth is
// neccessary based on the current value of fuel bed used by the ignite module
Expand Down
24 changes: 13 additions & 11 deletions src/behave/igniteInputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,14 @@ void IgniteInputs::initializeMembers()

void IgniteInputs::updateIgniteInputs(double moistureOneHour, double moistureHundredHour, FractionUnits::FractionUnitsEnum moistureUnits,
double airTemperature, TemperatureUnits::TemperatureUnitsEnum temperatureUnits, double sunShade, FractionUnits::FractionUnitsEnum sunShadeUnits,
IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelBedType, double duffDepth, LengthUnits::LengthUnitsEnum duffDepthUnits,
LightningCharge::LightningChargeEnum lightningChargeType)
IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelBedType, double duffDepth, LengthUnits::LengthUnitsEnum duffDepthUnits)
{
setMoistureOneHour(moistureOneHour, moistureUnits);
setMoistureHundredHour(moistureHundredHour, moistureUnits);
setAirTemperature(airTemperature, temperatureUnits);
setSunShade(sunShade, sunShadeUnits);
fuelBedType_ = fuelBedType;
setDuffDepth(duffDepth, duffDepthUnits);
lightningChargeType_ = lightningChargeType;
}

void IgniteInputs::setMoistureOneHour(double moistureOneHour, FractionUnits::FractionUnitsEnum moistureUnits)
Expand Down Expand Up @@ -73,10 +71,12 @@ void IgniteInputs::setDuffDepth(double duffDepth, LengthUnits::LengthUnitsEnum l
duffDepth_ = LengthUnits::toBaseUnits(duffDepth, lengthUnits);
}

void IgniteInputs::setLightningChargeType(LightningCharge::LightningChargeEnum lightningChargeType)
{
lightningChargeType_ = lightningChargeType;
}
/* Code is deprecated as the science is no longer considered reliable.
There is no known method to accurately calculate Probability of Ignition from a lightning strike. */
// void IgniteInputs::setLightningChargeType(LightningCharge::LightningChargeEnum lightningChargeType)
// {
// lightningChargeType_ = lightningChargeType;
//}

double IgniteInputs::getAirTemperature(TemperatureUnits::TemperatureUnitsEnum desiredUnits)
{
Expand Down Expand Up @@ -108,7 +108,9 @@ double IgniteInputs::getDuffDepth(LengthUnits::LengthUnitsEnum desiredUnits)
return LengthUnits::fromBaseUnits(duffDepth_,desiredUnits);
}

LightningCharge::LightningChargeEnum IgniteInputs::getLightningChargeType()
{
return lightningChargeType_;
}
/* Code is deprecated as the science is no longer considered reliable.
There is no known method to accurately calculate Probability of Ignition from a lightning strike. */
// LightningCharge::LightningChargeEnum IgniteInputs::getLightningChargeType()
// {
// return lightningChargeType_;
// }
Loading
Loading