A least-cost optimisation model of British Columbia's coupled Climate, Land, Energy and Water systems — built on OSeMOSYS, extended with land-use accounting, documented here block by block.
BCNexus identifies technological pathways to meet BC's decarbonization targets — through electrification and alternative carriers such as hydrogen — while accounting for the water, food and land-use implications of expanding electricity supply. It couples three subsystems (Water, Food/land, Energy) to climate.
CapacityOfOneTechnologyUnit is left unused. Activating it turns the model into a MILP (integer unit-builds).Everything is built directly from the GNU MathProg source of the two model files in the DeltaE/BC_Nexus repository. Each card opens in a new tab.
Sets, parameters, variables, objective and all 14 constraint blocks — each with the real constraint labels and condensed code.
Open documentation ↗Exactly what CLEWs adds: one per-mode activity variable, four parameters, and constraints LU1–LU4. The rest is standard OSeMOSYS.
See the difference ↗The only divergence between the two files is storage chronology — timeslice-by-timeslice vs typical-day seasonal storage.
Compare variants ↗How total discounted system cost is assembled — capital, O&M, emission penalties, salvage and storage.
Read the objective ↗The CLEWs heart: LU1–LU4 bound land-use activity per mode in level and in year-on-year rate of change.
Inspect LU1–LU4 ↗Interactive map of the bcnexus Python package and how one run() call turns CSVs into a solved model — click any module or step.
Explore architecture ↗The authoritative model files, otoole configs and run workflow live in the BC_Nexus repository.
Browse the repo ↗CLEWs — Climate, Land, Energy, Water Systems — is an integrated framework and an extension of OSeMOSYS. Rather than optimising energy in isolation, it captures feedbacks between the four domains. Open any node for a detailed explainer (new tab).
The coupling is elegant: land parcels are technologies, the way land is used is a mode of operation, and water and crop products flow as fuels. So land allocation, water demand and agricultural emissions are all expressed through the same energy primitives — no separate sub-models needed.
Each scenario flows through interfacing tools, a model run, and result processing. The documented GNU MathProg file is the Model Script — marked below.
CLEWs models climate, land and water without bespoke sub-models. The trick is representational: every domain is re-expressed in the OSeMOSYS vocabulary of technologies, modes, fuels and activity. A handful of constraints then govern the whole coupled system.
For every fuel — energy or water or crop — production ≥ demand + use + net trade in each timeslice. This single template enforces electricity balance, water availability and crop supply alike.
Activity ≤ installed capacity × capacity factor. Bounds how hard a power plant — or an irrigation scheme, or a field — can operate, tying operation to investment.
Per-mode annual activity is bounded in level (max/min area) and in rate of change (how fast a land use may expand or contract). This is the CLEWs-defining constraint set.
Activity × emission factor is summed and capped annually and over the horizon, and priced into the objective — the climate thread that couples all domains.
Because water and land flows ride on the same balance and capacity equations as energy, the optimiser trades off a tonne of CO₂ saved by wind against one saved by a bioenergy crop — including that crop's land and irrigation-water cost — inside one linear program.
Both files are identical except for how the storage state of charge is tracked in time; both carry the same CLEWs land-use extension. Niet and Kotzur are two of four temporal-representation methods (Cluster, Kotzur, Welsch, Niet) benchmarked in the storage-in-OSeMOSYS study on storage with temporal aggregation — best practices and algorithms.
Classic OSeMOSYS storage.
Typical-day (Kotzur) storage.
When a full year (8760 h) is compressed into a few representative days to keep the optimisation tractable, the storage state of charge must still be chained correctly across those days — otherwise long-duration and seasonal storage is mis-valued. The two variants here are different answers to that problem: Niet keeps an explicit intra-year timeslice chronology, while Kotzur reconstructs inter-day cycling from clustered typical days. The trade-off between accuracy and variable count is exactly what the storage-in-OSeMOSYS framework (Cluster · Kotzur · Welsch · Niet) was built to quantify, using k-means clustering of capacity-factor and demand profiles to pick representative days.
A MathProg OSeMOSYS file is processed in order. Declarations come first (sets and their data), then the objective, the constraints, and finally the solve and result export.
Index domains (years, technologies, fuels, timeslices, regions, modes, storage) and the exogenous data defined over them — costs, demands, efficiencies, emission factors, land limits.
Decision & accounting unknowns the solver chooses; RateOfActivity is the master from which most constraints are built.
A single minimize cost over total discounted system cost — capital, O&M, emission penalties, salvage and storage.
14 blocks: capacity adequacy, energy balance, accounting, storage, costs, capacity/activity limits, reserve margin, RE target, emissions, and land use.
solve; invokes GLPK, then ~30 table tout … OUT "CSV" statements export results for post-processing.
BCNexus does not stand alone. It is one component of an end-to-end, soft-linked modelling workflow for British Columbia that couples capacity expansion, renewable-resource assessment and operational power-system simulation.
A quick path from clone to results, how to contribute changes, and how to reach the developer.
On Linux / WSL with Anaconda:
git clone https://github.com/DeltaE/BC_Nexus cd BC_Nexus conda env create --file env/environment.yaml conda activate bcnexus bash install_bcnexus.sh # or: pip install . bash dashboard.sh # sample results + dashboard
Then configure & run via BCNexus.py or BCNexus.ipynb — pick scenario, storage algorithm (Kotzur/Niet), clustering and solver (gurobi / cbc) and threads.
The standard GitHub flow:
Hitting solver/Gurobi-license or DOT/graphviz setup issues? The wiki's Troubleshooting & Known-issues notes cover the common fixes (incl. the free CBC fallback).
Open pull requests ↗Muhammad Eliasinul Islam (EL) — Delta E+ Research Lab, Simon Fraser University. Co-developer of BCNexus and the storage-in-OSeMOSYS framework.