A Python implementation of the USDA Forest Vegetation Simulator (FVS) supporting 10 regional variants, taper-based volume calculations, and 500+ species configurations for simulating individual tree growth and yield across the United States.
- 10 Regional Variants — Southern, Lake States, Pacific Northwest, West Cascades, Northeast, Central States, ORGANON, and more
- Taper-Based Volume — Clark (Eastern) and Flewelling (Western) taper models with NVEL-compatible merchandising
- 500+ Species Configs — Individual species parameters for height-diameter, bark ratio, crown ratio, and growth
- Individual Tree Growth — Diameter, height, crown ratio, and mortality modeled per tree per cycle
- Stand Management — Thinning from below/above, selection harvest, clearcut, and custom prescriptions
- FIA Integration — Initialize stands directly from Forest Inventory and Analysis plot data
- Export Formats — Yield tables, CSV, Excel, and tree lists
| Variant | Region | Species | Key Species | Volume Model |
|---|---|---|---|---|
| SN | Southern US | 90 | Loblolly Pine, Longleaf Pine, Slash Pine | Clark (R8) |
| LS | Lake States (MI, WI, MN) | 67 | Red Pine, Jack Pine, Sugar Maple | Clark (R9) |
| NE | Northeast (13 states) | 108 | Red Maple, Sugar Maple, Northern Red Oak | Clark (R9) |
| CS | Central States (IL, IN, IA, MO) | 96 | White Oak, Black Walnut, Yellow-Poplar | Clark (R9) |
| PN | Pacific NW Coast (WA, OR) | 39 | Douglas-fir, Western Hemlock, Sitka Spruce | Flewelling |
| WC | West Cascades (OR, WA) | 37 | Douglas-fir, Western Hemlock, Western Red Cedar | Flewelling |
| OP | ORGANON Pacific NW | 18 | Douglas-fir, Red Alder | Flewelling |
| CA | Inland California | — | White Fir, Ponderosa Pine | — |
| OC | ORGANON SW Oregon | — | Douglas-fir, Tanoak | — |
| WS | Western Sierra Nevada | — | White Fir, Giant Sequoia | — |
Variants marked with — use default (SN) infrastructure and are pending full implementation.
pip install fvs-pythonfrom pyfvs import Stand
# Southern loblolly pine plantation
stand = Stand.initialize_planted(
trees_per_acre=500,
site_index=70,
species="LP",
ecounit="M231"
)
stand.grow(years=50)
metrics = stand.get_metrics()
print(f"TPA: {metrics['tpa']:.0f} QMD: {metrics['qmd']:.1f}\" "
f"BA: {metrics['basal_area']:.0f} ft² Volume: {metrics['volume']:.0f} ft³/ac")from pyfvs import Stand
# Pacific Northwest Douglas-fir (PN variant)
stand = Stand.initialize_planted(400, 120, "DF", variant="PN")
stand.grow(years=50)
# ~333 TPA, 14.5" QMD, 383 BA, 15,029 ft³/ac
# Lake States Red Pine (LS variant)
stand = Stand.initialize_planted(500, 65, "RN", variant="LS")
stand.grow(years=50)
# ~459 TPA, 10.4" QMD, 270 BA, 7,774 ft³/ac
# Northeast Red Maple (NE variant)
stand = Stand.initialize_planted(500, 60, "RM", variant="NE")
stand.grow(years=50)
# ~89 BA, 7.4" QMD
# Central States White Oak (CS variant)
stand = Stand.initialize_planted(500, 65, "WO", variant="CS")
stand.grow(years=50)
# ~283 TPA, 8.7" QMD, 117 BA
# ORGANON Douglas-fir (OP variant - highest yield)
stand = Stand.initialize_planted(400, 120, "DF", variant="OP")
stand.grow(years=50)
# ~323 TPA, 18.5" QMD, 601 BA, 28,395 ft³/acstand = Stand.initialize_planted(500, 70, "LP", ecounit="M231")
stand.grow(years=15)
stand.thin_from_below(target_tpa=200)
stand.grow(years=35)from pyfvs import Stand
stand = Stand.initialize_planted(500, 70, "LP", ecounit="M231")
table = stand.grow(years=50, yield_table=True)
print(table)| Age | TPA | QMD | Height | BA | Volume |
|---|---|---|---|---|---|
| 0 | 500 | 0.5 | 1.0 | 0.7 | 0 |
| 10 | 485 | 4.2 | 28.5 | 47 | 892 |
| 20 | 420 | 7.8 | 52.1 | 140 | 3,241 |
| 30 | 310 | 10.4 | 68.3 | 183 | 5,128 |
pyFVS uses a taper-based volume system matching NVEL (National Volume Estimator Library):
| Model | Region | Method |
|---|---|---|
| Clark | Eastern (SN, NE, CS, LS) | 3-segment profile with analytic integration |
| Flewelling | Western (PN, WC, OP) | 4-segment variable-shape profile |
| Combined-variable | Fallback | V = a + b * D²H (Amateis & Burkhart 1987) |
Merchandising supports Scribner Decimal C, International 1/4", and Doyle board-foot rules with per-log bucking.
Stand.initialize_planted() --> Tree objects --> grow() cycles --> mortality / harvest
| |
StandMetrics GrowthModels
Competition HeightDiameter
Mortality CrownRatio
HarvestManager BarkRatio
OutputGenerator TaperVolume
Each Tree uses a size-dependent growth model:
- Small trees (DBH < 1"): Height-driven growth via Chapman-Richards
- Transition (1" - 3"): Weighted blend of small and large tree models
- Large trees (DBH > 3"): Diameter-driven growth via variant-specific DDS equations
Variant-specific diameter growth equations:
| Variant | Equation | Variables |
|---|---|---|
| SN | ln(DDS) | DBH, CR, RELHT, SI, BA, ecounit |
| LS, CS | DDS (linear) | DBH, CR, RELDBH, SI, BA, BAL |
| PN, WC | ln(DDS) | DBH, CR, RELHT, SI, BA, BAL, elevation, slope, aspect |
| NE | BA growth (iterative) | DBH, SI, BAL, CR |
| OP | ln(DG) direct | DBH, CR, SI, BA, BAL |
Species parameters stored in YAML with variant-specific coefficient files in JSON:
src/pyfvs/cfg/
species/*.yaml # SN species configs (90 species)
sn_*.json # SN variant coefficients
ls/species/*.yaml # LS species configs (67 species)
ls/ls_*.json # LS variant coefficients
pn/, wc/, ne/, cs/, op/ # Other variant directories
taper/ # Taper model coefficients
clark_r8_coefficients.json
clark_r9_coefficients.json
flewelling_coefficients.json
# Run all tests (~1000 tests)
uv run pytest
# Run specific variant tests
uv run pytest tests/test_ls_variant.py
uv run pytest tests/test_pn_variant.py
uv run pytest tests/test_taper.py- FVS Documentation — USDA Forest Service
- FVS Essential Guide (GTR-WO-102) — Dixon (2023)
- Clark, A. et al. (1991). Stem profile equations for southern tree species. USDA-FS Research Paper SE-282.
- Flewelling, J.W. (1994). Stem form equation development notes. USDA-FS.
- Amateis, R.L. & Burkhart, H.E. (1987). Tree volume and taper. Forest Science 33(2).
@software{pyfvs2025,
title = {pyFVS: Python Implementation of the Forest Vegetation Simulator},
author = {Mihiar, Christopher},
year = {2025},
url = {https://github.com/mihiarc/pyfvs}
}MIT