cffdrs / cffdrs_r

FWI and FBP components of CFFDRS in R
GNU General Public License v2.0
13 stars 6 forks source link

[CFFDRS R Question]: RSI Calculation for M3/4 Fuel Types #47

Closed gagreene closed 2 months ago

gagreene commented 2 months ago

Contact Details

map.n.trowel@gmail.com

What happened?

Question

When calculating RSI for M3/4 fuel types, the revised Wotton et al. (2009) equations (29, 31) suggest integrating a ratio of RSI_M3-100% and RSI_D1, as follows:

image image

In rate_of_spread.r, I noticed that RSI_D1 is calculated using the ISI generated under the 100% dead fir scenario (lines 101-110), rather than using an ISI value generated under the D1 scenario.

Can you explain why this is the case?

Assuming a true mixedwood stand, where RSI_D1 is meant to represent the leafless aspen component, it seems to me that, to adequately capture the relationships suggested by equations 29 and 31, RSI_M3-100% should be calculated using ISI under the 100% dead fir scenario, and RSI_D1 should be calculated using ISI under the D1 scenario. While the differences are minimal, they do exist.

Thanks for any feedback you can provide!

Relevant log output

No response

Approvals Process

jordan-evens commented 2 months ago

Not sure if there's some confusion about RSI vs ISI since you say:

should be calculated using ISI under the 100% dead fir scenario, and RSI_D1 should be calculated using ISI under the D1 scenario.

but the ISI is the same for all fuel types because it's a fire weather index. RSI is the initial ROS calculation, which is the result of rate_of_spread()

You're looking at this I believe: https://github.com/cffdrs/cffdrs_r/blob/7c9748a2e2fbfa33487dca0bc05446c2edbb42b5/R/rate_of_spread.r#L101-L110

The RSI for M3 100% is calculated with: https://github.com/cffdrs/cffdrs_r/blob/7c9748a2e2fbfa33487dca0bc05446c2edbb42b5/R/rate_of_spread.r#L95-99

  RSI_m3 <- ifelse(
    FUELTYPE %in% c("M3"),
    as.numeric(a[["M3"]] * ((1 - exp(-b[["M3"]] * ISI))**c0[["M3"]])),
    RSI_m3
  )
  # Eq. 29 (Wotton et. al 2009)
  RSI <- ifelse(
    FUELTYPE %in% c("M3"),
    (PDF / 100 * RSI_m3
      + (1 - PDF / 100) *
        rate_of_spread(
          rep("D1", length(ISI)),
          ISI, NoBUI, FMC, SFC, PC, PDF, CC, CBH
        )),
    RSI
  )

That boils down to RSI_m3 <- as.numeric(a[["M3"]] * ((1 - exp(-b[["M3"]] * ISI))**c0[["M3"]])) is the RSI with M3-100% PDF / 100 * RSI_m3 is the first term of eq 39 RSI_d1 <- rate_of_spread(rep("D1", length(ISI)), ISI, NoBUI, FMC, SFC, PC, PDF, CC, CBH) is just the D1 rate of spread So (1 - PDF / 100) * RSI_d1 is the second term of eq 39

We could clean up the recusive call to rate_of_spread and call rate_of_spread_extended to at least get rid of the call to the deprecated funciton, but since rate_of_spread ignores whatever doesn't apply to the fuel you give it (D1 in this case) it will just give you the ROS for D1.

I believe everything is working as intended, but if you still see an issue can you please clarify what you mean and link to the lines you're referring to right in your comment so we can see exactly what you mean?

gagreene commented 2 months ago

Apologies for not clarifying the issue directly. What I was saying comes down to the ISI calculations used by CFFBPS. With default inputs, ISI ends up being calculated three times:

ISF is calculated using the fuel type specific rate of spread parameters a, b, c (Table 6, FCFDG 1992). Because of this, the final ISI value is specific to each fuel type, which results in a different ISI for each fuel type. I will use the fbp function in the cffdrs R package to demonstrate this...

Using the same input parameters, this is ISI for M3: image

This is ISI for D1: image

So my question is, why use the ISI for M3 (100% dead fir) to calculate RSI for D1? When I originally compiled all these equations back in 2017, my brain instinctively assumed RSI for D1 would use the ISI for D1. I'm wondering if there was precedent set for this in the original CFFBPS C code? Just trying to understand, mostly for my own knowledge.

Thanks for any insights you can provide!

RobBryce commented 2 months ago

@gagreene - The C++ WISE implementation can be found starting on line 403 in https://github.com/WISE-Developers/WISE_FBP_Module/blob/main/cpp/isf.cpp with references to the 2004 FBP update note. This code was heavily reviewed and tested over a decade ago.

jordan-evens commented 2 months ago

Sorry I'm just not following what you're saying - I have no idea what CFFBPS is and you're not linking to any code so I have no idea what you're looking at.

ISZ != ISF != ISI

These may derive from similar a formula, but they are not the same thing. If you return the ISF instead of the ISI as the ISI column and then feed that back in to calculate things again I would expect that you would get a different result, because ISI is the Initial Spread Index, which is a Fire Weather Index variable, which is completely independent of fuel type.

ISZ - (Slope-Adjusted ISI I'm assuming) is not the same as ISI because it is local to the slope that you are calculating things on, given the WS, WD, SLOPE, and RAZ that you have there.

ISF - (Fuel-Adjusted ISI I'm assuming) would be related to how much spread a certain slope will cause in a certain fuel type, which is dependent on the amount of slope and the type of fuel.

gagreene commented 2 months ago

Thanks @RobBryce! I will look through the code.

@jordan-evens I will try to fit in time this week to give proper code references to how ISI is being calculated in the cffdrs R package.

And as reference for the terms, I was trying to use the same terms used in FCFDG 1992:

image

CFFBPS = Canadian Forest Fire Behaivour Prediction System

jordan-evens commented 2 months ago

I looked around in the code and I think what you're referring to is that the WSV is calculated with the FUELTYPE (which would be M-3) here: https://github.com/cffdrs/cffdrs_r/blob/7c9748a2e2fbfa33487dca0bc05446c2edbb42b5/R/fire_behaviour_prediction.r#L288-L289 And then that goes into the ISI function and then the ROS function here: https://github.com/cffdrs/cffdrs_r/blob/7c9748a2e2fbfa33487dca0bc05446c2edbb42b5/R/fire_behaviour_prediction.r#L303-L305

If that's what you mean then yeah that seems very weird. Part of the confusion is that this code keeps writing over variables and by line 303 it should probably be called ISZ/ISF and not ISI.

Thinking about it though, it kind of makes sense on a basic level, because if the fire is being pushed through the M-3 stand based on the rate of travel in M-3, then it would be going through the D-1 stand at the same pace. ISI is not strictly rate of spread, but it's being derived from the WSV value, which is adjusted based on the M-3 fuel type's effect based on slope. I don't understand how all the math would sort out there exactly, so that's a question for someone else.

Is that at least the point you were trying to make? Or is it something else still?

gagreene commented 2 months ago

@jordan-evens Correct, that's the point I was trying to make. The ISF calculation is what makes WSV different between the fuel types. Here's an example using the spreadsheet I built for FBP calcs...

WSV with standard ISF calculations: image

WSV with the same ISF for all fuel types: image

I guess this is more of a "sciency" question than anything - just trying to understand why it would be done one way over another. This might be a better question for Marty or Dan Perrakis. Thanks for working through that with me!

BadgerOnABike commented 1 month ago

If you end up getting more info please do post it here too. I'd be curious Dan's take on it all. Marty has been retired for a while, but may still be watching and thinking about these kinds of problems!