Edit June 15 – New simplified R code; see below.
This is something I’ve been working with recently as part of the CCP project, and I thought the code might be useful to others. I should get back into using Git and Github one of these days, but in the meantime, here’s some R code for those who want to play with this and are much too lazy to type out all the coefficients.
The Wotton & Beverly (2007) moisture content (WBmc hereafter) uses some forest stand composition, structure, and condition variables to modify the predicted moisture content estimated by the diurnal FFMC. The ‘generalized pine model’ has served us well for several decades (thank you, Charlie Van Wagner, James Wright, and others), but we’ve suspected for some time that stand factors play a role too. (If you don’t know what I’m talking about here, this probably isn’t for you). Ok, we’re talking about fire danger modelling using the Canadian Forest Fire Danger Rating System, and the FFMC is the Fine Fuel Moisture Code. Brush up on the FWI System basics if needed; here’s the technical report, and here’s the classic and much loved ‘mustache video’ (Intro to FWI System).
The WBmc estimates litter moisture, the most important fuel moisture variable for fire behaviour prediction. Their analysis was based on several thousand measurements from across Canada in the mid-20th century; as with the rest of the CFFDRS, it’s mostly focused on boreal forests, but not exclusively (there’s some BC data and some Great Lakes region data as well). Their model uses the following variables:
FFMC & DMC – by identifying DMC (Duff Moisture Code) as a significant variable , the authors found that drought or moisture in the duff layers (decomposing humus and fermentation layers in the forest floor) actually influences the moisture of the top litter layer. If it’s dry underneath, the litter is drier; if wet underneath, some of that moisture advects to the litter.
Forest stand type – pine, spruce, Douglas-fir (interior), mixedwood, or deciduous; admittedly, this list is limiting, and doesn’t get us entirely away from categorical fuel or vegetation types.
Stand density – light, moderate, or dense stands; unfortunately, these categories aren’t very well defined either, as they were assigned from archived photos; as a working model, I’m using the tentative premise that this variable can be equated with the crown closure classification scheme (from the National Forest Inventory program): light ≈ Sparse (10-25% closure), moderate ≈ Open (26-60% closure), and dense ≈ Dense (61% or greater closure). I recently presented this to Mike Wotton, who said it made sense, but we’ll likely have to do some more field work to investigate this, and that may lead to a more usable continuous variable model for stand density.
Season – spring, summer, or autumn are significant on top of everything else; likely because of the greenup and leaf-out of broadleaf species in the overstory and understory, which add shade and in-stand moisture via evapotranspiration. The script currently uses spring (1), summer (2) and autumn/fall (3) as categories, but these changes don’t happen instantly, as it takes a few days for buds to flush, senescence to set in, etc. So I also added a ‘spring/summer transition’ (sprummer, if you will) option (season = 1.5) as the mean between those seasons. I suppose I should also add a ‘sumautumn’ season (2.5) at some point for the early fall period, but haven’t yet.

(From Wotton & Beverly 2007; International Journal of Wildland Fire 16:463-472)
There are main effects and interaction effects associated with most of those variables, which alter the relationships at different variable levels. In most cases the interactions make sense, but not always. For instance, stand density is significant, with light and moderate density stands having lower mc than dense stands in most conditions. This makes good sense – sun and wind can penetrate lower density stands more easily and contribute to more rapid drying of the litter. But the effect diminishes under very dry conditions. This also makes sense, as several studies have found that overstory density can slow down in-stand drying, but under the droughtiest conditions, the stand effect disappears almost completely. See Whitehead et al. (2008) for a good example from BC.
So the problem here is that above FFMC 93 or so, the density effect actually reverses, where the dense stands start having lower moisture than the light or moderate density stands (above FFMC 96.5, the light density factor also reverses, where light stands start having higher moisture than moderate stands). These are almost certainly a factor of sample size, as there were few measurements in light and dense stands, particularly under the driest conditions. It’s also important to note that the highest FFMC in the range of data was 96.
So we’ll have to explore some better options for extreme-FFMC conditions, but for now, the best option is probably to stick with the ‘moderate’ stand density parameter for FFMC > 93.0.
In the meantime, here’s the R code and a spreadsheet version. The most annoying part of working with the code is typing out all of the coefficients. There are a couple of ways the authors present the models, including one with interaction factors and a simpler one with individual coefficients, though greater in number (in the Appendix, 45 different equations are listed with all combinations of the categorical factors). I’ve used the latter, even though it might have been quicker to do it the other way. Anyhow, at least I’ve done that for you (typing out coefficients), even though you may find your own code more slick than what I’ve come up with. Along the way we need FFMC and DMC moisture content functions, so those are in there too.
So here it is in a ‘copy/paste’ format. I’ll get it up on GitHub one of these days. Or just use the Excel version, WBmc-calcs.xlsx.
WBmc_calcs.xlsx
#Wotton-Beverly (2007) moisture content model, for adjusting the FFMC estimate
#using stand, density, season, and DMC variables.
#Requires FFMC, DMC, stand (1:5; deciduous, Douglas-fir, mixedwood, pine, spruce),
#density (1:3; light, mod, dense), season (1:3; spr, sum, fall)
#season==1.5 represents spring/summer transition (uses half of spring, half of summer estimate)
#D.Perrakis, June 2020; daniel.perrakis@canada.ca
#base R - no packages required
#create WB-mc function
#FFMC, DMC, stand, density, season
wbmc<-function(ffmc, dmc, stand, density, season) {
#Get coefficients
WBCoTr1 <-c(
0.7299,0.0202,0.7977,0.8517,0.7391,
0.4387,-0.271,0.5065,0.5605,0.4479,
-0.2449,-0.9546,-0.1771,-0.1231,-0.2357,
0.1348,-0.5749,0.2026,0.2566,0.144,
-0.1564,-0.8661,-0.0886,-0.0346,-0.1472,
-0.84,-1.5497,-0.7722,-0.7182,-0.8308,
0.1601,-0.55,0.2279,0.2819,0.1693,
-0.1311,-0.8408,-0.0633,-0.0093,-0.1219,
-0.8147,-1.5244,-0.7469,-0.6929,-0.8055)
WBCoTr2 <- c(
0.5221,0.6264,0.5042,0.3709,0.4285,
0.7133,0.8176,0.6954,0.5621,0.6197,
1.0462,1.1505,1.0283,0.895,0.9526,
0.8691,0.9734,0.8512,0.7179,0.7755,
1.0603,1.1646,1.0424,0.9091,0.9667,
1.3932,1.4975,1.3753,1.242,1.2996,
0.9495,1.0538,0.9316,0.7983,0.8559,
1.1407,1.245,1.1228,0.9895,1.0471,
1.4736,1.5779,1.4557,1.3224,1.38)
co3 <- 0.002232
#Create data frame for pulling coefs
WBCo <-data.frame("co1"=WBCoTr1, "co2"=WBCoTr2)
#Spring and Summer coefs for 'sprummer' model
co_sp <- WBCo[1:15,]
co_su <- WBCo[16:30,]
#define mcF, mcD, ex.mod intermediate functions
mcF<-function(ffmc){
147.2*(101-ffmc)/(59.5+ffmc)
}
mcD<-function(dmc) {
20+exp(-(dmc-244.72)/43.43)
}
ex.mod<-function(s1, s2, s3, ffmc, dmc) {
exp(s1+s2*log(mcF(ffmc))+s3*mcD(dmc))
}
if(season==1.5) {
#spring
c1.sprD=co_sp[(density*5-4):(density*5), 1]
c2.sprD=co_sp[(density*5-4):(density*5), 2]
c1=c1.sprD[stand]
c2=c2.sprD[stand]
mc.spr=ex.mod(c1, c2, co3, ffmc, dmc)
#summer
c1.sumD=co_su[(density*5-4):(density*5), 1]
c2.sumD=co_su[(density*5-4):(density*5), 2]
c3=c1.sumD[stand]
c4=c2.sumD[stand]
mc.sum=ex.mod(c3, c4, co3, ffmc, dmc)
#final 'sprummer' mc calc
return(mean(c(mc.spr, mc.sum)))
#for all others - spring, summer or fall
} else {
c1a=WBCo$co1[(season*15-14):(season*15)]
c2a=WBCo$co2[(season*15-14):(season*15)]
c1b=c1a[(density*5-4):(density*5)]
c2b=c2a[(density*5-4):(density*5)]
c1c=c1b[stand]
c2c=c2b[stand]
return(ex.mod(c1c, c2c, co3, ffmc, dmc))
}
}
#[End]
#
#mcF, mcD functions on their own to get estimated #moisture contents from FFMC, DMC
mcF<-function(ffmc){
147.2*(101-ffmc)/(59.5+ffmc)
}
mcD<-function(dmc) {
20+exp(-(dmc-244.72)/43.43)
}
#[End]
#Works as far as I can tell
#e.g. FFMC 90, DMC 55, pine stand (4), moderate #density (2), summer (2); then compare with #sprummer and spring:
#
#(Text below represents the R console, not code, #so don't copy it!
> wbmc(90, 55, 4, 2, 2)
[1] 10.50674
> wbmc(90, 55, 4, 2, 1.5)
[1] 9.420716
> wbmc(90, 55, 4, 2, 1)
[1] 8.334695
#Also, FFMC model alone, for comparison
> mcF(90)
[1] 10.83077