Rothermel

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.).

How It Works

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.

Types

FuelClasses

A container for values across the five Rothermel fuel size classes.

FuelClasses{T}(; d1, d10, d100, herb, wood)

Values for the five Rothermel fuel size classes.

Fields

  • 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 herbaceous
  • wood::T - Live woody

Rothermel

The fuel model struct parameterized by the Rothermel (1972) equations.

Rothermel{T}(; name, w, σ, h, δ, Mx)

Fuel model for the Rothermel (1972) surface fire spread model.

Parameterized by numeric type T (e.g. Float64, Float32, Unitful quantities).

Fields (US customary units, matching original publications)

  • name::String - Description
  • w::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).

NFFL Fuel Models

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
Code
SHORT_GRASS
Rothermel{Float64}("NFFL 1: Short grass (1 ft)")

Scott & Burgan 40 Fuel Models

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:

  • GR (Grass): 9 models for grasslands, from sparse short grass to very high load humid climate grass
  • GS (Grass-Shrub): 4 models for grass-shrub mixtures
  • SH (Shrub): 9 models for shrublands, from low-load dry climate to very high load humid climate
  • TU (Timber-Understory): 5 models for timber with understory fuels
  • TL (Timber Litter): 9 models for timber litter, from compact conifer to very high load broadleaf
  • SB (Slash-Blowdown): 4 models for logging slash and blowdown debris
Tip

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

Comparing SB40 Fuel Models

Rate of spread at a reference condition (wind = 8 km/h, slope = 0, live herbaceous moisture 60%, live woody moisture 90%):

Code
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)

fig

Fuel Bed Depth Comparison

Code
depths = [f.δ for f in sb40_fuels]

fig = Figure(size=(900, 350))
ax = Axis(fig[1,1],
    xlabel="Fuel Model",
    ylabel="Fuel bed depth (ft)",
    title="Scott & Burgan 40 — Fuel Bed Depth",
    xticks=(1:40, sb40_labels),
    xticklabelrotation=pi/3,
    xticklabelsize=9)
barplot!(ax, 1:40, depths, color=sb_colors)
fig

Rate of Spread

rate_of_spread(fuel::Rothermel; moisture, wind, slope)

Compute the forward rate of fire spread using the Rothermel (1972) model.

Arguments

  • fuel::Rothermel - Fuel model
  • moisture::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]

Returns

Forward rate of spread at the fire head [m/min].

Example

M = FuelClasses(d1=0.06, d10=0.07, d100=0.08, herb=0.0, wood=0.0)
R = rate_of_spread(SHORT_GRASS, moisture=M, wind=8.0, slope=0.0)

Example

M = FuelClasses(d1=0.06, d10=0.07, d100=0.08, herb=0.0, wood=0.0)
rate_of_spread(SHORT_GRASS, moisture=M, wind=8.0, slope=0.0)
31.119112730486354

Effect of Wind Speed

Code
winds = 0:2:30
rates = [
    rate_of_spread(SHORT_GRASS, moisture=M,
        wind=w, slope=0.0)
    for w in winds
]

fig = Figure()
ax = Axis(fig[1,1],
    xlabel="Wind speed (km/h)",
    ylabel="Rate of spread (m/min)",
    title="NFFL 1: Short Grass")
lines!(ax, collect(winds), rates)
fig

Comparing NFFL Models

Rate of spread at a reference condition (wind = 8 km/h, slope = 0, dead fuel moisture 6–8%):

Code
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)

fig

Wind Sensitivity by Fuel Category

Code
groups = [
    "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...)
fig

Fuel Loading by Size Class

Code
fig = 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

References

  • Rothermel, R.C. (1972). A Mathematical Model for Predicting Fire Spread in Wildland Fuels. Res. Paper INT-115, USDA Forest Service.
  • Anderson, H.E. (1982). Aids to Determining Fuel Models for Estimating Fire Behavior. Gen. Tech. Rep. INT-122, USDA Forest Service.
  • Scott, J.H. & Burgan, R.E. (2005). Standard Fire Behavior Fuel Models: A Comprehensive Set for Use with Rothermel’s Surface Fire Spread Model. Gen. Tech. Rep. RMRS-GTR-153, USDA Forest Service.
  • Andrews, P.L. (2018). The Rothermel Surface Fire Spread Model and Associated Developments. Gen. Tech. Rep. RMRS-GTR-371, USDA Forest Service.