diff --git a/src/behave/ignite.cpp b/src/behave/ignite.cpp index 164cbc3..a62500e 100644 --- a/src/behave/ignite.cpp +++ b/src/behave/ignite.cpp @@ -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) { @@ -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) @@ -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() { diff --git a/src/behave/ignite.h b/src/behave/ignite.h index bebc161..fd2c6ef 100644 --- a/src/behave/ignite.h +++ b/src/behave/ignite.h @@ -43,7 +43,9 @@ 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); @@ -51,12 +53,13 @@ class Ignite 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); @@ -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 diff --git a/src/behave/igniteInputs.cpp b/src/behave/igniteInputs.cpp index 0bb2093..e0ab89c 100644 --- a/src/behave/igniteInputs.cpp +++ b/src/behave/igniteInputs.cpp @@ -31,8 +31,7 @@ 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); @@ -40,7 +39,6 @@ void IgniteInputs::updateIgniteInputs(double moistureOneHour, double moistureHun setSunShade(sunShade, sunShadeUnits); fuelBedType_ = fuelBedType; setDuffDepth(duffDepth, duffDepthUnits); - lightningChargeType_ = lightningChargeType; } void IgniteInputs::setMoistureOneHour(double moistureOneHour, FractionUnits::FractionUnitsEnum moistureUnits) @@ -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) { @@ -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_; +// } diff --git a/src/behave/igniteInputs.h b/src/behave/igniteInputs.h index c583a64..e19616c 100644 --- a/src/behave/igniteInputs.h +++ b/src/behave/igniteInputs.h @@ -65,8 +65,7 @@ class IgniteInputs 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); void setMoistureHundredHour(double hundredHourMoisture, FractionUnits::FractionUnitsEnum moistureUnits); void setMoistureOneHour(double moistureOneHour, FractionUnits::FractionUnitsEnum moistureUnits); @@ -75,7 +74,7 @@ class IgniteInputs void setIgnitionFuelBedType(IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelBedType_); void setDuffDepth(double duffDepth, LengthUnits::LengthUnitsEnum lengthUnits); - void setLightningChargeType(LightningCharge::LightningChargeEnum lightningChargeType); + // void setLightningChargeType(LightningCharge::LightningChargeEnum lightningChargeType); double getAirTemperature(TemperatureUnits::TemperatureUnitsEnum desiredUnits); double getMoistureOneHour(FractionUnits::FractionUnitsEnum desiredUnits); @@ -83,7 +82,7 @@ class IgniteInputs double getSunShade(FractionUnits::FractionUnitsEnum desiredUnits); IgnitionFuelBedType::IgnitionFuelBedTypeEnum getIgnitionFuelBedType(); double getDuffDepth(LengthUnits::LengthUnitsEnum desiredUnits); - LightningCharge::LightningChargeEnum getLightningChargeType(); + // LightningCharge::LightningChargeEnum getLightningChargeType(); protected: double moistureOneHour_; diff --git a/src/testBehave/testBehave.cpp b/src/testBehave/testBehave.cpp index 4f45e17..71ea688 100644 --- a/src/testBehave/testBehave.cpp +++ b/src/testBehave/testBehave.cpp @@ -1506,12 +1506,9 @@ void testIgniteModule(TestInfo& testInfo, BehaveRun& behaveRun) double sunShade = 50.0; // Percent IgnitionFuelBedType::IgnitionFuelBedTypeEnum fuelBedType = IgnitionFuelBedType::DouglasFirDuff; double duffDepth = 6.0; // inches - LightningCharge::LightningChargeEnum lightningChargeType = LightningCharge::Unknown; double observedFirebrandIgnitionProbability = 0; - double observedLightningIgnitionProbability = 0; double expectedFirebrandIgnitionProbability = 0; - double expectedLightningIgnitionProbability = 0; FractionUnits::FractionUnitsEnum mositureUnits = FractionUnits::Percent; TemperatureUnits::TemperatureUnitsEnum temperatureUnits = TemperatureUnits::Fahrenheit; @@ -1519,41 +1516,30 @@ void testIgniteModule(TestInfo& testInfo, BehaveRun& behaveRun) LengthUnits::LengthUnitsEnum duffDepthUnits = LengthUnits::Inches; expectedFirebrandIgnitionProbability = 0.54831705; - expectedLightningIgnitionProbability = 0.39362018; behaveRun.ignite.updateIgniteInputs(moistureOneHour, moistureHundredHour, mositureUnits, airTemperature, - temperatureUnits, sunShade, sunShadeUnits, fuelBedType, duffDepth, duffDepthUnits, lightningChargeType); + temperatureUnits, sunShade, sunShadeUnits, fuelBedType, duffDepth, duffDepthUnits); testName = "Test firebrand ignition probability for Douglas fir duff"; observedFirebrandIgnitionProbability = behaveRun.ignite.calculateFirebrandIgnitionProbability(FractionUnits::Fraction); reportTestResult(testInfo, testName, observedFirebrandIgnitionProbability, expectedFirebrandIgnitionProbability, error_tolerance); - testName = "Test lightning ignition probability for Douglas fir duff"; - observedLightningIgnitionProbability = behaveRun.ignite.calculateLightningIgnitionProbability(FractionUnits::Fraction); - reportTestResult(testInfo, testName, observedLightningIgnitionProbability, expectedLightningIgnitionProbability, error_tolerance); - moistureOneHour = 7.0; moistureHundredHour = 9.0; airTemperature = 90; // Fahrenheit sunShade = 25.0; // Percent fuelBedType = IgnitionFuelBedType::LodgepolePineDuff; duffDepth = 8.0; // inches - lightningChargeType = LightningCharge::Negative; expectedFirebrandIgnitionProbability = 50.717573; - expectedLightningIgnitionProbability = 17.931991; behaveRun.ignite.updateIgniteInputs(moistureOneHour, moistureHundredHour, mositureUnits, airTemperature, - temperatureUnits, sunShade, sunShadeUnits, fuelBedType, duffDepth, duffDepthUnits, lightningChargeType); + temperatureUnits, sunShade, sunShadeUnits, fuelBedType, duffDepth, duffDepthUnits); testName = "Test firebrand ignition probability for Lodgepole pine duff"; observedFirebrandIgnitionProbability = behaveRun.ignite.calculateFirebrandIgnitionProbability(FractionUnits::Percent); reportTestResult(testInfo, testName, observedFirebrandIgnitionProbability, expectedFirebrandIgnitionProbability, error_tolerance); - testName = "Test lightning ignition probability for Lodgepole pine duff"; - observedLightningIgnitionProbability = behaveRun.ignite.calculateLightningIgnitionProbability(FractionUnits::Percent); - reportTestResult(testInfo, testName, observedLightningIgnitionProbability, expectedLightningIgnitionProbability, error_tolerance); - std::cout << "Finished testing Ignite module\n\n"; }