Skip to content

Commit

Permalink
Merge pull request #40 from firelab/kc-BHP1-994-add-surface-doi-outputs
Browse files Browse the repository at this point in the history
[BHP1-994] Add New Outputs in the Direction of Interest
  • Loading branch information
rjsheperd authored Sep 18, 2024
2 parents 4779bdd + c72b8dc commit 46c0b32
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 68 deletions.
11 changes: 11 additions & 0 deletions src/behave/surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,11 @@ double Surface::getFlameLength(LengthUnits::LengthUnitsEnum flameLengthUnits) co
return LengthUnits::fromBaseUnits(surfaceFire_.getFlameLength(), flameLengthUnits);
}

double Surface::getFlameLengthInDirectionOfInterest(LengthUnits::LengthUnitsEnum flameLengthUnits) const
{
return LengthUnits::fromBaseUnits(surfaceFire_.getFlameLengthInDirectionOfInterest(), flameLengthUnits);
}

double Surface::getBackingFlameLength(LengthUnits::LengthUnitsEnum flameLengthUnits) const
{
return LengthUnits::fromBaseUnits(surfaceFire_.getBackingFlameLength(), flameLengthUnits);
Expand Down Expand Up @@ -265,6 +270,12 @@ double Surface::getFirelineIntensity(FirelineIntensityUnits::FirelineIntensityUn
return FirelineIntensityUnits::fromBaseUnits(surfaceFire_.getFirelineIntensity(), firelineIntensityUnits);
}

double Surface::getFirelineIntensityInDirectionOfInterest(FirelineIntensityUnits::FirelineIntensityUnitsEnum firelineIntensityUnits) const
{
return FirelineIntensityUnits::fromBaseUnits(surfaceFire_.getFirelineIntensityInDirectionOfInterest(),
firelineIntensityUnits);
}

double Surface::getBackingFirelineIntensity(FirelineIntensityUnits::FirelineIntensityUnitsEnum firelineIntensityUnits) const
{
return FirelineIntensityUnits::fromBaseUnits(surfaceFire_.getBackingFirelineIntensity(), firelineIntensityUnits);
Expand Down
2 changes: 2 additions & 0 deletions src/behave/surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,14 @@ class Surface
double getFlameLength(LengthUnits::LengthUnitsEnum flameLengthUnits) const;
double getBackingFlameLength(LengthUnits::LengthUnitsEnum flameLengthUnits) const;
double getFlankingFlameLength(LengthUnits::LengthUnitsEnum flameLengthUnits) const;
double getFlameLengthInDirectionOfInterest(LengthUnits::LengthUnitsEnum flameLengthUnits) const;
double getFireLengthToWidthRatio() const;
double getFireEccentricity() const;
double getHeadingToBackingRatio() const;
double getFirelineIntensity(FirelineIntensityUnits::FirelineIntensityUnitsEnum firelineIntensityUnits) const;
double getBackingFirelineIntensity(FirelineIntensityUnits::FirelineIntensityUnitsEnum firelineIntensityUnits) const;
double getFlankingFirelineIntensity(FirelineIntensityUnits::FirelineIntensityUnitsEnum firelineIntensityUnits) const;
double getFirelineIntensityInDirectionOfInterest(FirelineIntensityUnits::FirelineIntensityUnitsEnum firelineIntensityUnits) const;
double getHeatPerUnitArea(HeatPerUnitAreaUnits::HeatPerUnitAreaUnitsEnum heatPerUnitAreaUnits) const;
double getMidflameWindspeed(SpeedUnits::SpeedUnitsEnum windSpeedUnits) const;
double getResidenceTime(TimeUnits::TimeUnitsEnum timeUnits) const;
Expand Down
160 changes: 101 additions & 59 deletions src/behave/surfaceFire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,22 @@ void SurfaceFire::initializeMembers()
directionOfMaxSpread_ = 0.0;
noWindNoSlopeSpreadRate_ = 0.0;
forwardSpreadRate_ = 0.0;
backingSpreadRate_ = 0.0;
flankingSpreadRate_ = 0.0;
spreadRateInDirectionOfInterest_ = 0.0;
heatPerUnitArea_ = 0.0;
fireLengthToWidthRatio_ = 1.0;
residenceTime_ = 0.0;
reactionIntensity_ = 0.0;
firelineIntensity_ = 0.0;
flameLength_ = 0.0;
forwardFirelineIntensity_ = 0.0;
backingFirelineIntensity_ = 0.0;
flankingFirelineIntensity_ = 0.0;
directionOfInterestFirelineIntensity_ = 0.0;
forwardFlameLength_ = 0.0;
backingFlameLength_ = 0.0;
flankingFlameLength_ = 0.0;
directionOfInterestFlameLength_ = 0.0;
maxFlameLength_ = 0.0;
backingSpreadRate_ = 0.0;
scorchHeight_ = 0.0;

midflameWindSpeed_ = 0.0;
Expand Down Expand Up @@ -120,15 +128,22 @@ void SurfaceFire::memberwiseCopyAssignment(const SurfaceFire& rhs)
directionOfMaxSpread_ = rhs.directionOfMaxSpread_;
noWindNoSlopeSpreadRate_ = rhs.noWindNoSlopeSpreadRate_;
forwardSpreadRate_ = rhs.forwardSpreadRate_;
backingSpreadRate_ = rhs.backingSpreadRate_;
flankingSpreadRate_ = rhs.flankingSpreadRate_;
spreadRateInDirectionOfInterest_ = rhs.spreadRateInDirectionOfInterest_;
heatPerUnitArea_ = rhs.heatPerUnitArea_;
fireLengthToWidthRatio_ = rhs.fireLengthToWidthRatio_;
residenceTime_ = rhs.residenceTime_;
reactionIntensity_ = rhs.reactionIntensity_;
firelineIntensity_ = rhs.firelineIntensity_;
flameLength_ = rhs.flameLength_;
forwardFirelineIntensity_ = rhs.forwardFirelineIntensity_;
backingFirelineIntensity_ = rhs.backingFirelineIntensity_;
flankingFirelineIntensity_ = rhs.flankingFirelineIntensity_;
directionOfInterestFirelineIntensity_ = rhs.directionOfInterestFirelineIntensity_;
forwardFlameLength_ = rhs.forwardFlameLength_;
backingFlameLength_ = rhs.backingFlameLength_;
flankingFlameLength_ = rhs.flankingFlameLength_;
directionOfInterestFlameLength_ = rhs.directionOfInterestFlameLength_;
maxFlameLength_ = rhs.maxFlameLength_;
backingSpreadRate_ = rhs.backingSpreadRate_;
scorchHeight_ = rhs.scorchHeight_;

midflameWindSpeed_ = rhs.midflameWindSpeed_;
Expand All @@ -153,62 +168,81 @@ void SurfaceFire::calculateResidenceTime()
: (384. / sigma));
}

void SurfaceFire::calculateFirelineIntensity(double forwardSpreadRate)
double SurfaceFire::calculateFirelineIntensity(double spreadRate,
SpeedUnits::SpeedUnitsEnum speedUnits,
FirelineIntensityUnits::FirelineIntensityUnitsEnum firelineIntensityUnits)
{
double secondsPerMinute = 60.0; // for converting feet per minute to feet per second
firelineIntensity_ = forwardSpreadRate * reactionIntensity_ * (residenceTime_ / secondsPerMinute);
double firelineIntensity = SpeedUnits::toBaseUnits(spreadRate, speedUnits) * reactionIntensity_ * (residenceTime_ / secondsPerMinute);
return FirelineIntensityUnits::fromBaseUnits(firelineIntensity, firelineIntensityUnits);
}

void SurfaceFire::calculateBackingFireFirelineIntensity(double backingSpreadRate)
void SurfaceFire::calculateFirelineIntensities()
{
double secondsPerMinute = 60.0; // for converting feet per minute to feet per second
backingFirelineIntensity_ = backingSpreadRate * reactionIntensity_ * (residenceTime_ / secondsPerMinute);
}
forwardFirelineIntensity_ = calculateFirelineIntensity(forwardSpreadRate_,
SpeedUnits::FeetPerMinute,
FirelineIntensityUnits::BtusPerFootPerSecond);

void SurfaceFire::calculateFlankingFireFirelineIntensity(double flankingSpreadRate)
{
double secondsPerMinute = 60.0; // for converting feet per minute to feet per second
flankingFirelineIntensity_ = flankingSpreadRate * reactionIntensity_ * (residenceTime_ / secondsPerMinute);
backingFirelineIntensity_ = calculateFirelineIntensity(backingSpreadRate_,
SpeedUnits::FeetPerMinute,
FirelineIntensityUnits::BtusPerFootPerSecond);

flankingFirelineIntensity_ = calculateFirelineIntensity(flankingSpreadRate_,
SpeedUnits::FeetPerMinute,
FirelineIntensityUnits::BtusPerFootPerSecond);

directionOfInterestFirelineIntensity_ = calculateFirelineIntensity(spreadRateInDirectionOfInterest_,
SpeedUnits::FeetPerMinute,
FirelineIntensityUnits::BtusPerFootPerSecond);
}

void SurfaceFire::skipCalculationForZeroLoad()
{
initializeMembers();
}

void SurfaceFire::calculateFlameLength()
double SurfaceFire::calculateFlameLength(double firelineIntensity,
FirelineIntensityUnits::FirelineIntensityUnitsEnum firelineIntensityUnits,
LengthUnits::LengthUnitsEnum flameLengthUnits)
{
firelineIntensity = FirelineIntensityUnits::toBaseUnits(firelineIntensity, firelineIntensityUnits);


// Byram 1959, Albini 1976
flameLength_ = ((firelineIntensity_ < 1.0e-07)
? (0.0)
: (0.45 * pow(firelineIntensity_, 0.46)));
double flameLength = ((firelineIntensity < 1.0e-07)
? (0.0)
: (0.45 * pow(firelineIntensity, 0.46)));
return LengthUnits::fromBaseUnits(flameLength, flameLengthUnits);
}

void SurfaceFire::calculateBackingFlameLength()
void SurfaceFire::calculateFlameLengths()
{
// Byram 1959, Albini 1976
backingFlameLength_ = ((backingFirelineIntensity_ < 1.0e-07)
? (0.0)
: (0.45 * pow(backingFirelineIntensity_, 0.46)));
}
forwardFlameLength_ = calculateFlameLength(forwardFirelineIntensity_,
FirelineIntensityUnits::BtusPerFootPerSecond,
LengthUnits::Feet);

void SurfaceFire::calculateFlankingFlameLength()
{
// Byram 1959, Albini 1976
flankingFlameLength_ = ((flankingFirelineIntensity_ < 1.0e-07)
? (0.0)
: (0.45 * pow(flankingFirelineIntensity_, 0.46)));
backingFlameLength_ = calculateFlameLength(backingFirelineIntensity_,
FirelineIntensityUnits::BtusPerFootPerSecond,
LengthUnits::Feet);

flankingFlameLength_ = calculateFlameLength(flankingFirelineIntensity_,
FirelineIntensityUnits::BtusPerFootPerSecond,
LengthUnits::Feet);

directionOfInterestFlameLength_ = calculateFlameLength(directionOfInterestFirelineIntensity_,
FirelineIntensityUnits::BtusPerFootPerSecond,
LengthUnits::Feet);
}

void SurfaceFire::calculateScorchHeight()
{
const double airTemperature = surfaceInputs_->getAirTemperature(TemperatureUnits::Fahrenheit);
const double windSpeed = surfaceInputs_->getWindSpeed(SpeedUnits::MilesPerHour);
scorchHeight_ = ((firelineIntensity_ < 1.0e-07)
scorchHeight_ = ((forwardFirelineIntensity_ < 1.0e-07)
? (0.0)
: ((63.0 / (140.0 - airTemperature))
* pow(firelineIntensity_, 1.166667)
/ sqrt(firelineIntensity_ + (windSpeed * windSpeed * windSpeed))
* pow(forwardFirelineIntensity_, 1.166667)
/ sqrt(forwardFirelineIntensity_ + (windSpeed * windSpeed * windSpeed))
));
}

Expand Down Expand Up @@ -259,35 +293,36 @@ double SurfaceFire::calculateForwardSpreadRate(int fuelModelNumber, bool hasDire
backingSpreadRate_ = size_->getBackingSpreadRate(SpeedUnits::FeetPerMinute);
flankingSpreadRate_ = size_->getFlankingSpreadRate(SpeedUnits::FeetPerMinute);

calculateHeatPerUnitArea();
calculateFirelineIntensity(forwardSpreadRate_);
calculateBackingFireFirelineIntensity(backingSpreadRate_);
calculateFlankingFireFirelineIntensity(flankingSpreadRate_);
if (hasDirectionOfInterest) // If needed, calculate spread rate in arbitrary direction of interest
{
spreadRateInDirectionOfInterest_ = calculateSpreadRateAtVector(directionOfInterest, directionMode);
}
else
{
spreadRateInDirectionOfInterest_ = forwardSpreadRate_;
}

calculateFlameLength();
calculateBackingFlameLength();
calculateFlankingFlameLength();
calculateHeatPerUnitArea();
calculateFirelineIntensities();
calculateFlameLengths();

bool isUsingWesternAspen = surfaceInputs_->getIsUsingWesternAspen();
if (isUsingWesternAspen)
{
surfaceFuelbedIntermediates_.calculateWesternAspenMortality(flameLength_);
surfaceFuelbedIntermediates_.calculateWesternAspenMortality(forwardFlameLength_);
}

maxFlameLength_ = getFlameLength(); // Used by SAFETY Module
maxFlameLength_ = forwardFlameLength_; // Used by SAFETY Module
calculateHeatSource();

if (hasDirectionOfInterest) // If needed, calculate spread rate in arbitrary direction of interest
if (hasDirectionOfInterest)
{
spreadRateInDirectionOfInterest_ = calculateSpreadRateAtVector(directionOfInterest, directionMode);
return spreadRateInDirectionOfInterest_;
}
else
{
spreadRateInDirectionOfInterest_ = forwardSpreadRate_;
return forwardSpreadRate_;
}

calculateHeatSource();

return spreadRateInDirectionOfInterest_;
}

double SurfaceFire::calculateSpreadRateAtVector(double directionOfInterest, SurfaceFireSpreadDirectionMode::SurfaceFireSpreadDirectionModeEnum directionMode)
Expand Down Expand Up @@ -334,11 +369,8 @@ double SurfaceFire::calculateSpreadRateAtVector(double directionOfInterest, Surf
double cosBeta = cos(radians);
double sinBeta = sin(radians);

rosVector = (g * cos(radians)) + sqrt((f * f * cosBeta * cosBeta) + (h * h * sinBeta * sinBeta));

// rosVector perpendicular to perimeter at angle beta used to calculate fireline intensity and flame length
calculateFirelineIntensity(rosVector);
calculateFlameLength();
rosVector = (g * cos(radians)) + sqrt((f * f * cosBeta * cosBeta) + (h * h * sinBeta * sinBeta));

if (directionMode == SurfaceFireSpreadDirectionMode::FromIgnitionPoint)
{
Expand Down Expand Up @@ -566,7 +598,7 @@ double SurfaceFire::convertDirectionOfSpreadToRelativeToNorth(double directionOf

double SurfaceFire::getFirelineIntensity() const
{
return firelineIntensity_;
return forwardFirelineIntensity_;
}

double SurfaceFire::getBackingFirelineIntensity() const
Expand All @@ -579,9 +611,14 @@ double SurfaceFire::getFlankingFirelineIntensity() const
return flankingFirelineIntensity_;
}

double SurfaceFire::getFirelineIntensityInDirectionOfInterest() const
{
return directionOfInterestFirelineIntensity_;
}

double SurfaceFire::getFlameLength() const
{
return flameLength_;
return forwardFlameLength_;
}

double SurfaceFire::getBackingFlameLength() const
Expand All @@ -594,6 +631,11 @@ double SurfaceFire::getFlankingFlameLength() const
return flankingFlameLength_;
}

double SurfaceFire::getFlameLengthInDirectionOfInterest() const
{
return directionOfInterestFlameLength_;
}

double SurfaceFire::getMaxFlameLength() const
{
return maxFlameLength_;
Expand Down Expand Up @@ -904,12 +946,12 @@ void SurfaceFire::setEffectiveWindSpeed(double effectiveWindSpeed)

void SurfaceFire::setFirelineIntensity(double firelineIntensity)
{
firelineIntensity_ = firelineIntensity;
forwardFirelineIntensity_ = firelineIntensity;
}

void SurfaceFire::setFlameLength(double flameLength)
{
flameLength_ = flameLength;
forwardFlameLength_ = flameLength;
}

void SurfaceFire::setFireLengthToWidthRatio(double lengthToWidthRatio)
Expand Down
23 changes: 15 additions & 8 deletions src/behave/surfaceFire.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,11 @@ class SurfaceFire
double getFirelineIntensity() const;
double getBackingFirelineIntensity() const;
double getFlankingFirelineIntensity() const;
double getFirelineIntensityInDirectionOfInterest() const;
double getFlameLength() const;
double getBackingFlameLength() const;
double getFlankingFlameLength() const;
double getFlameLengthInDirectionOfInterest() const;
double getMaxFlameLength() const;
double getFireLengthToWidthRatio() const;
double getFireEccentricity() const;
Expand Down Expand Up @@ -135,6 +137,7 @@ class SurfaceFire

protected:
// Protected setters accessible to friend classes

void setDirectionOfMaxSpread(double directionOFMaxSpread);
void setEffectiveWindSpeed(double effectiveWindSpeed);
void setFirelineIntensity(double firelineIntensity);
Expand All @@ -157,12 +160,14 @@ class SurfaceFire
void calculateHeatSource();

void calculateResidenceTime();
void calculateFirelineIntensity(double forwardSpreadRate);
void calculateBackingFireFirelineIntensity(double backingSpreadRate);
void calculateFlankingFireFirelineIntensity(double flankingSpreadRate);
void calculateFlameLength();
void calculateBackingFlameLength();
void calculateFlankingFlameLength();
double calculateFirelineIntensity(double forwardSpreadRate,
SpeedUnits::SpeedUnitsEnum speedUnits,
FirelineIntensityUnits::FirelineIntensityUnitsEnum firelineIntensityUnits);
void calculateFirelineIntensities();
double calculateFlameLength(double firelineIntensity,
FirelineIntensityUnits::FirelineIntensityUnitsEnum firelineIntensityUnits,
LengthUnits::LengthUnitsEnum flameLengthUnits);
void calculateFlameLengths();
void calculateScorchHeight();
void calculateWindSpeedLimit();
void calculateDirectionOfMaxSpread();
Expand Down Expand Up @@ -198,13 +203,15 @@ class SurfaceFire
double fireLengthToWidthRatio_;
double residenceTime_;
double reactionIntensity_;
double firelineIntensity_;
double forwardFirelineIntensity_;
double backingFirelineIntensity_;
double flankingFirelineIntensity_;
double directionOfInterestFirelineIntensity_;
double maxFlameLength_; // Flame length computed from spread rate in max direction, used in SAFETY
double flameLength_;
double forwardFlameLength_;
double backingFlameLength_;
double flankingFlameLength_;
double directionOfInterestFlameLength_;
double heatSource_;
double scorchHeight_;

Expand Down
2 changes: 1 addition & 1 deletion src/testBehave/testBehave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,7 @@ void testDirectionOfInterest(TestInfo& testInfo, BehaveRun& behaveRun)
reportTestResult(testInfo, testName, observedSpreadRateInDirectionOfInterest, expectedSpreadRateInDirectionOfInterest, error_tolerance);

testName = "Test perimeter spread direction mode upslope oriented mode, 20 foot wind, direction of interest 90 degrees from upslope, 45 degree wind flame length";
observedFlameLengthInDirectionOfInterest = roundToSixDecimalPlaces(behaveRun.surface.getFlameLength(LengthUnits::Feet));
observedFlameLengthInDirectionOfInterest = roundToSixDecimalPlaces(behaveRun.surface.getFlameLengthInDirectionOfInterest(LengthUnits::Feet));
expectedFlameLengthInDirectionOfInterest = 6.5981480000000001;
reportTestResult(testInfo, testName, observedFlameLengthInDirectionOfInterest, expectedFlameLengthInDirectionOfInterest, error_tolerance);

Expand Down

0 comments on commit 46c0b32

Please sign in to comment.