Model Specifications#
Test system#
All runs use the same single-node OSeMOSYS system, defined in data/system/:
Element |
Value |
|---|---|
Region, year |
|
Fuel |
|
VRE technology |
|
Storage |
|
Storage cost and life |
|
Residual storage |
0.05 kW·yr ( |
Storage energy cap |
1000 kW·yr (non-binding) in the main runs; 0.2 kW·yr in the stress test |
The initial state of charge is a decision variable: StorageLevelStart in config/config.yaml is
not applied. All values are listed with their source in step 2 of the reproduction notebook.
Formulations and model files#
Each formulation has its own folder in models/ with an OSeMOSYS model file and an otoole
configuration template. They share the rest of OSeMOSYS and differ only in the time sets and the
storage equations.
Formulation |
Folder |
Extra time sets / mappings |
SoC equation |
Bounds |
|---|---|---|---|---|
Niet |
|
none beyond |
|
|
Welsch |
|
|
|
|
Kotzur |
|
|
|
|
Novo |
|
|
|
|
All four require the storage to end the year where it started (a refilling constraint: SC8 in
Niet and Novo, SC4 in Kotzur, S15 in Welsch) and cap the total storage capacity at
StorageMaxCapacity (SC3, or SC7 in Welsch). See
About Storage Modelling for what these differences mean in practice.
How the inputs are generated#
workflow/main.py writes the time sets and mappings each formulation needs into
models/Model_<name>/inputs_csv/ (generated, not tracked), copies the shared parameters from
data/system/, and converts everything to a GLPK data file with otoole. Run-specific values
(DaySplit, YearSplit, StorageMaxCapacity, ResidualStorageCapacity) go into a temporary
otoole_config_<name>.run.yaml, so the templates in models/ never change. The steps are
described in Workflow Guide.
Solver#
GLPK 5.0 (glpsol). If GLPK reports a non-optimal result, the run is retried with --nopresol,
--dual and --exact; failed solves are recorded with status FAILED and no capacities.