Code
SHORT_GRASSRothermel{Float64}("NFFL 1: Short grass (1 ft)")
The Rothermel module implements the Rothermel (1972) surface fire spread model, the foundational model used by most US wildfire behavior systems (BehavePlus, FARSITE, ELMFIRE, etc.).
The model computes the rate of spread (m/min) of a surface fire given:
| Input | Description | Source |
|---|---|---|
| Fuel model | Static fuel bed properties (loading, SAV ratio, heat content, depth, moisture of extinction) | Rothermel struct |
| Moisture | Fuel moisture content per size class | FuelClasses (keyword arg) |
| Wind | Midflame wind speed | Scalar (km/h) |
| Slope | Terrain slope as rise/run | Scalar (fraction) |
The fuel model is a static landscape property while moisture, wind, and slope are dynamic environmental inputs — matching how operational fire behavior systems separate these concerns.
FuelClassesA container for values across the five Rothermel fuel size classes.
Values for the five Rothermel fuel size classes.
d1::T - 1-hr dead fuel (< 0.25 in diameter)d10::T - 10-hr dead fuel (0.25–1.0 in)d100::T - 100-hr dead fuel (1.0–3.0 in)herb::T - Live herbaceouswood::T - Live woodyRothermelThe fuel model struct parameterized by the Rothermel (1972) equations.
Fuel model for the Rothermel (1972) surface fire spread model.
Parameterized by numeric type T (e.g. Float64, Float32, Unitful quantities).
name::String - Descriptionw::FuelClasses{T} - Fuel loading [tons/acre]σ::FuelClasses{T} - Surface-area-to-volume ratio [1/ft]h::FuelClasses{T} - Heat content [BTU/lb]δ::T - Fuel bed depth [ft]Mx::T - Dead fuel moisture of extinction [fraction]See NFFL for the 13 standard fuel models from Anderson (1982).
The 13 standard fuel models from Anderson (1982) are provided as named constants:
| Constant | NFFL | Description | Depth (ft) | Mx |
|---|---|---|---|---|
SHORT_GRASS |
1 | Short grass (1 ft) | 1.0 | 0.12 |
TIMBER_GRASS |
2 | Timber grass/understory | 1.0 | 0.15 |
TALL_GRASS |
3 | Tall grass (2.5 ft) | 2.5 | 0.25 |
CHAPARRAL |
4 | Chaparral (6 ft) | 6.0 | 0.20 |
BRUSH |
5 | Brush (2 ft) | 2.0 | 0.20 |
DORMANT_BRUSH |
6 | Dormant brush/hardwood slash | 2.5 | 0.25 |
SOUTHERN_ROUGH |
7 | Southern rough | 2.5 | 0.40 |
CLOSED_TIMBER_LITTER |
8 | Closed timber litter | 0.2 | 0.30 |
HARDWOOD_LITTER |
9 | Hardwood litter | 0.2 | 0.25 |
TIMBER_UNDERSTORY |
10 | Timber litter/understory | 1.0 | 0.25 |
LIGHT_SLASH |
11 | Light logging slash | 1.0 | 0.15 |
MEDIUM_SLASH |
12 | Medium logging slash | 2.3 | 0.20 |
HEAVY_SLASH |
13 | Heavy logging slash | 3.0 | 0.25 |
The 40 additional fuel models from Scott and Burgan (2005) extend the original 13 NFFL models to cover a wider range of vegetation types. Together with the NFFL models, there are 53 standard fire behavior fuel models.
The models are organized into six groups:
Models marked Dynamic transfer live herbaceous fuel to the dead category based on curing level (determined by live herbaceous moisture). The fuel loads listed are pre-transfer values.
| Constant | Type | Description | Depth (ft) | Mx |
|---|---|---|---|---|
GR1 |
D | Short, sparse, dry climate grass | 0.4 | 0.15 |
GR2 |
D | Low load, dry climate grass | 1.0 | 0.15 |
GR3 |
D | Low load, very coarse, humid climate grass | 2.0 | 0.3 |
GR4 |
D | Moderate load, dry climate grass | 2.0 | 0.15 |
GR5 |
D | Low load, humid climate grass | 1.5 | 0.4 |
GR6 |
D | Moderate load, humid climate grass | 1.5 | 0.4 |
GR7 |
D | High load, dry climate grass | 3.0 | 0.15 |
GR8 |
D | High load, very coarse, humid climate grass | 4.0 | 0.3 |
GR9 |
D | Very high load, humid climate grass | 5.0 | 0.4 |
GS1 |
D | Low load, dry climate grass-shrub | 0.9 | 0.15 |
GS2 |
D | Moderate load, dry climate grass-shrub | 1.5 | 0.15 |
GS3 |
D | Moderate load, humid climate grass-shrub | 1.8 | 0.4 |
GS4 |
D | High load, humid climate grass-shrub | 2.1 | 0.4 |
SH1 |
D | Low load, dry climate shrub | 1.0 | 0.15 |
SH2 |
S | Moderate load, dry climate shrub | 1.0 | 0.15 |
SH3 |
S | Moderate load, humid climate shrub | 2.4 | 0.4 |
SH4 |
S | Low load, humid climate timber-shrub | 3.0 | 0.3 |
SH5 |
S | High load, dry climate shrub | 6.0 | 0.15 |
SH6 |
S | Low load, humid climate shrub | 2.0 | 0.3 |
SH7 |
S | Very high load, dry climate shrub | 6.0 | 0.15 |
SH8 |
S | High load, humid climate shrub | 3.0 | 0.4 |
SH9 |
D | Very high load, humid climate shrub | 4.4 | 0.4 |
TU1 |
D | Light load, dry climate timber-grass-shrub | 0.6 | 0.2 |
TU2 |
S | Moderate load, humid climate timber-shrub | 1.0 | 0.3 |
TU3 |
D | Moderate load, humid climate timber-grass-shrub | 1.3 | 0.3 |
TU4 |
S | Dwarf conifer understory | 0.5 | 0.12 |
TU5 |
S | Very high load, dry climate timber-shrub | 1.0 | 0.25 |
TL1 |
S | Low load, compact conifer litter | 0.2 | 0.3 |
TL2 |
S | Low broadleaf litter | 0.2 | 0.25 |
TL3 |
S | Moderate load conifer litter | 0.3 | 0.2 |
TL4 |
S | Small downed logs | 0.4 | 0.25 |
TL5 |
S | High load conifer litter | 0.6 | 0.25 |
TL6 |
S | Moderate load broadleaf litter | 0.3 | 0.25 |
TL7 |
S | Large downed logs | 0.4 | 0.25 |
TL8 |
S | Long-needle litter | 0.3 | 0.35 |
TL9 |
S | Very high load broadleaf litter | 0.6 | 0.35 |
SB1 |
S | Low activity fuel | 1.0 | 0.25 |
SB2 |
S | Moderate activity fuel or low load blowdown | 1.0 | 0.25 |
SB3 |
S | High activity fuel or moderate load blowdown | 1.2 | 0.25 |
SB4 |
S | High load blowdown | 2.7 | 0.25 |
Rate of spread at a reference condition (wind = 8 km/h, slope = 0, live herbaceous moisture 60%, live woody moisture 90%):
M_sb = FuelClasses(d1=0.06, d10=0.07, d100=0.08, herb=0.60, wood=0.90)
sb40_fuels = [
GR1, GR2, GR3, GR4, GR5, GR6, GR7, GR8, GR9,
GS1, GS2, GS3, GS4,
SH1, SH2, SH3, SH4, SH5, SH6, SH7, SH8, SH9,
TU1, TU2, TU3, TU4, TU5,
TL1, TL2, TL3, TL4, TL5, TL6, TL7, TL8, TL9,
SB1, SB2, SB3, SB4,
]
sb40_labels = [
"GR1","GR2","GR3","GR4","GR5","GR6","GR7","GR8","GR9",
"GS1","GS2","GS3","GS4",
"SH1","SH2","SH3","SH4","SH5","SH6","SH7","SH8","SH9",
"TU1","TU2","TU3","TU4","TU5",
"TL1","TL2","TL3","TL4","TL5","TL6","TL7","TL8","TL9",
"SB1","SB2","SB3","SB4",
]
sb_categories = vcat(
fill("Grass", 9),
fill("Grass-Shrub", 4),
fill("Shrub", 9),
fill("Timber-Understory", 5),
fill("Timber Litter", 9),
fill("Slash-Blowdown", 4),
)
sb_cat_colors = Dict(
"Grass" => :forestgreen,
"Grass-Shrub" => :yellowgreen,
"Shrub" => :goldenrod,
"Timber-Understory" => :peru,
"Timber Litter" => :sienna,
"Slash-Blowdown" => :slategray,
)
ros_sb = [
rate_of_spread(f, moisture=M_sb, wind=8.0, slope=0.0)
for f in sb40_fuels
]
sb_colors = [sb_cat_colors[c] for c in sb_categories]
fig = Figure(size=(900, 400))
ax = Axis(fig[1,1],
xlabel="Fuel Model",
ylabel="Rate of spread (m/min)",
title="Scott & Burgan 40 — Rate of Spread at 8 km/h Wind",
xticks=(1:40, sb40_labels),
xticklabelrotation=pi/3,
xticklabelsize=9)
barplot!(ax, 1:40, ros_sb, color=sb_colors)
sb_cat_names = ["Grass", "Grass-Shrub", "Shrub", "Timber-Understory", "Timber Litter", "Slash-Blowdown"]
elems = [PolyElement(color=sb_cat_colors[c]) for c in sb_cat_names]
Legend(fig[1,2], elems, sb_cat_names, framevisible=false)
figCompute the forward rate of fire spread using the Rothermel (1972) model.
fuel::Rothermel - Fuel modelmoisture::FuelClasses - Moisture content per fuel class [fraction, 0–1]. Use 0.0 for unused classes.wind - Midflame wind speed [km/h]slope - Terrain slope as rise/run [fraction]Forward rate of spread at the fire head [m/min].
Rate of spread at a reference condition (wind = 8 km/h, slope = 0, dead fuel moisture 6–8%):
M_ref = FuelClasses(
d1=0.06, d10=0.07, d100=0.08,
herb=0.0, wood=0.0)
M_live = FuelClasses(
d1=0.06, d10=0.07, d100=0.08,
herb=0.60, wood=0.90)
all_fuels = [
SHORT_GRASS, TIMBER_GRASS, TALL_GRASS,
CHAPARRAL, BRUSH, DORMANT_BRUSH,
SOUTHERN_ROUGH, CLOSED_TIMBER_LITTER,
HARDWOOD_LITTER, TIMBER_UNDERSTORY,
LIGHT_SLASH, MEDIUM_SLASH, HEAVY_SLASH,
]
nffl_labels = string.(1:13)
cat_colors = Dict(
"Grass" => :forestgreen,
"Shrub" => :goldenrod,
"Timber" => :sienna,
"Slash" => :slategray,
)
categories = [
"Grass", "Grass", "Grass",
"Shrub", "Shrub", "Shrub", "Shrub",
"Timber", "Timber", "Timber",
"Slash", "Slash", "Slash",
]
colors = [cat_colors[c] for c in categories]
ros = [
rate_of_spread(f,
moisture=has_live_fuel(f) ? M_live : M_ref,
wind=8.0, slope=0.0)
for f in all_fuels
]
fig = Figure(size=(700, 350))
ax = Axis(fig[1,1],
xlabel="NFFL Model",
ylabel="Rate of spread (m/min)",
title="Rate of Spread at 8 km/h Wind",
xticks=(1:13, nffl_labels))
barplot!(ax, 1:13, ros, color=colors)
cat_names = ["Grass", "Shrub", "Timber", "Slash"]
elems = [PolyElement(color=cat_colors[c])
for c in cat_names]
Legend(fig[1,2], elems, cat_names,
framevisible=false)
figgroups = [
"Grass" => [
("1: Short", SHORT_GRASS),
("2: Timber", TIMBER_GRASS),
("3: Tall", TALL_GRASS),
],
"Shrub" => [
("4: Chaparral", CHAPARRAL),
("5: Brush", BRUSH),
("6: Dormant", DORMANT_BRUSH),
("7: Southern", SOUTHERN_ROUGH),
],
"Timber" => [
("8: Closed", CLOSED_TIMBER_LITTER),
("9: Hardwood", HARDWOOD_LITTER),
("10: Understory", TIMBER_UNDERSTORY),
],
"Slash" => [
("11: Light", LIGHT_SLASH),
("12: Medium", MEDIUM_SLASH),
("13: Heavy", HEAVY_SLASH),
],
]
mph = 0:1:15
mph_to_kmh = 1.60934
fig = Figure(size=(700, 500))
axes = []
for (col, (title, fuels)) in enumerate(groups)
row = col <= 2 ? 1 : 2
c = col <= 2 ? col : col - 2
ax = Axis(fig[row, c],
xlabel="Wind (mph)",
ylabel="ROS (m/min)",
title=title)
push!(axes, ax)
for (label, fuel) in fuels
m = has_live_fuel(fuel) ? M_live : M_ref
r = [
rate_of_spread(fuel,
moisture=m,
wind=w * mph_to_kmh,
slope=0.0)
for w in mph
]
lines!(ax, collect(mph), r, label=label)
end
axislegend(ax, position=:lt, labelsize=10)
end
linkyaxes!(axes...)
figfig = Figure(size=(700, 350))
ax = Axis(fig[1,1],
xlabel="NFFL Model",
ylabel="Fuel loading (tons/acre)",
title="Fuel Loading Breakdown",
xticks=(1:13, nffl_labels))
xs = repeat(1:13, 5)
vals = vcat(
[f.w.d1 for f in all_fuels],
[f.w.d10 for f in all_fuels],
[f.w.d100 for f in all_fuels],
[f.w.herb for f in all_fuels],
[f.w.wood for f in all_fuels],
)
grp = vcat(
fill(1, 13), fill(2, 13), fill(3, 13),
fill(4, 13), fill(5, 13),
)
bar_colors = [
:tomato, :sandybrown, :tan,
:limegreen, :forestgreen,
]
barplot!(ax, xs, vals,
stack=grp,
color=[bar_colors[g] for g in grp])
bar_labels = [
"1-hr dead", "10-hr dead", "100-hr dead",
"Herb", "Wood",
]
elems = [PolyElement(color=c) for c in bar_colors]
Legend(fig[1,2], elems, bar_labels,
framevisible=false)
fig