I saw a job position with the requirement: “Proficiency in open-source power system tools (e.g. PyPSA, Dispa-SET, or Calliope) and other dispatch-related software.”
Is there anything similar in Julia?
I saw a job position with the requirement: “Proficiency in open-source power system tools (e.g. PyPSA, Dispa-SET, or Calliope) and other dispatch-related software.”
Is there anything similar in Julia?
Yes. Rather than enumerate the many projects, i might just link to
Nice! How, do you think that https://www.callio.pe/ and PowerSimulations.jl compare?
Does PowerSimulations.jl
handle different spacial resultions, e.g. on the national and the city scale?
In the moment, callio looks simpler to me, because you just have .yaml files (for the model) and .csv files (for time series) as input that you have to define. How do you define the input of PowerSimulations.jl ?
This is a question for @jdlara-berkeley
PowerSimulations.jl is an operations simulation engine not an expansion problem. It focuses more on PCM analyses or IRP development. The model resolution will depend on your data.
The inputs to PowerSimulations.jl are defined via system data in PowerSystems.jl you are welcome to check the recent tutorials on how to put the data together Welcome Page · PowerSystems.jl
So is there a Julia package that solves the expansion problem?
We are developing IESopt.jl since 2021, which has been open-sourced this spring (note that the docs are in a different repository). It is quite similar to Calliope in some ways (we use YAML & CSV files in a very similar way, and it’s “no-code” unless you want to do your own constraints, etc.), but our components are considerably more flexible in how a user can create new “technologies” (and it’s JuMP
-based so we are fast ). See this example for a simple (but complete) configuration.
It’s still not exactly “outsider-friendly” since moving all of the (potentially confidential) stuff from our internal repos is quite a long task. But it integrates nicely with other packages that make use of JuMP
models and supports stochastic optimization (via SDDP.jl
or a custom Benders based two-stage mode), multi-objectives (via MultiObjectiveAlgorithms.jl
), custom “model-to-pdf” rendering, etc. Some of these things are already in the open-source version, some of that is still being transferred.
Note that there are others as well, for example:
(sorry for any that I left out, surely an incomplete list)
Basically any full blown “energy system optimization model” will to some extent feature planning (expansion, …) and operational stage(s). Most however are limited to simplified formulations (e.g., “DC-OPF”), but since PowerModels.jl
exists this can be extended (you can, e.g., couple it with an IESopt.jl
model to make use of the more sophisticated formulations that PowerModels.jl
offers - which should be somehow possible for all JuMP
-based models).
edit: if anyone is ever interested, I’m happy to give a short bilateral intro
Nice! Thanks for the detailed reply.
If I compare the github stars:
GenX.jl (GPL) (suggests Julia 1.9) 280
SpineOpt.jl (GPL) (needs also Python) 60
TulipaEnergyModel.jl (Apache) Input: CSV 28
IESopt.jl (MIT) Input: YAML 15
EnergyModelsBase.jl (MIT) Input: Julia 8
But that cannot be the only criteria. I like YAML files as input, for example.
I am looking at this position: “Postdoc Energy and Water System Dispatch under Uncertainty Job Details | TU Delft”
Not so clear to me yet:
Any ideas?
I can’t really speak for the other packages since I’m mostly working with our internal one, Calliope, and PyPSA. I’ll pick ours, but both Calliope and PyPSA work very similarly for the answers.
carriers:
water: {}
electricity: {}
turbine:
type: Unit
inputs: {water: reservoir_upper}
outputs: {water: reservoir_lower, electricity: grid}
conversion: 1 water -> 1 water + <w2h_ratio> electricity
This makes use of a parameter w2h_ratio
that you could set from the outside to describe the 1 \text{m}^3 (or whatever unit you choose for water) to electricity ratio (depending on height, efficiency, etc.).
reservoir_lower:
type: Node
carrier: water
has_state: true
state_lb: 0
state_ub: 1e4
river:
type: Connection
node_from: reservoir_lower
node_to: some_other_reservoir
lb: 0
ub: 500 # an upper bound on the flow
delay: 15 # 15 hours delay between "in" and "out"
Depending on what exactly you mean by “spatially explicit”, yes. That’s what ESMs are used for: Modeling energy systems with a wide range across time and location. You could for example assume that (electricity market) bidding zones for Sweden (just as an example for hydro stuff) exist, which are called SE1
to SE4
.
grid_se1:
type: Node
carrier: electricity
grid_se2:
type: Node
carrier: electricity
transmission_line17:
type: Connection
node_from: grid_se1
node_to: grid_se2
capacity: 1200
That would be a simple “transport model” electricity exchange between the two zones, commonly linked to “NTCs” (net transfer capacities).
transmission_line17:
type: Connection
node_from: grid_se1
node_to: grid_se2
capacity: 0.9 * (1200 + upgrade_tl17:value)
upgrade_tl17:
type: Decision
lb: 0
ub: 500
cost: 17248
This would modify the line to “start” with a capacity of 1200
(assuming that unit is most likely MW_electricity
, allowing the model to extend it by up to 500
, but (additionally) accounting for a simple “safety margin” of 10% of the overall capacity — only allowing 90% to be used. Each MW of additional capacity costs 17248
Euros (or whatever monetary unit you use).
Note that all of this is the most basic way to do stuff like this. You would normally group these basic building blocks like “Nodes” and “Connections” (we call these CoreComponent
s) into more complex assets (e.g., a pumped hydro storage with natural inflow) — we call this template
s. You can then immediately initialize new components from these templates, and the model constructs all underlying components automatically, and connects them as defined.
That allows then loading components from a simple CSV file. Imagine that looking like so:
name | type | w2h_ratio | grid_connection |
---|---|---|---|
plant_foo | HydroReservoirPlant | 0.0124 | se1.grid |
plant_bar | HydroReservoirPlant | 0.0324 | se2.grid |
This uses:
HydroReservoirPlant
that models such a plantw2h_ratio
parametergrid_connection
to specify where the electricity is injectedse1.grid
is a notation that can be used to access (sub)components within other templates, here assuming that there is something called se1
(e.g., of type BiddingZone
), that contains a Node called grid
.I currently do not have a large-scale publicly available model “lying around”, but you can either check out the national scale example from Calliope, any of the pre-configured PyPSA-Eur (or Earth, etc.) models, or one of our examples, e.g.:
As most other large-scale models our formulations are MILP (mostly LP), supporting SOS1/2, or manual piecewise linear formulations. However, since JuMP
makes that rather easy to do, you can — without any change — add custom formulations to the model that are different (e.g., SDPs), as long as you use an appropriate solver (e.g., if you want to model losses inside the waterways between reservoir and turbine, based on flow speed, etc.).
Note: I’ve got a European-scale model from a climate uncertainty study that I can “show” (as in: I can show the config, etc. in a call, but can’t openly share the full thing right now).
Just one final remark, that description explicitly lists an energy system model / framework: OSeMOSYS.
I know, and I know OSeMOSYS, but I think the task is to use the output of an OSeMOSYS model as a starting point and “Test the resilience of planned WEF development pathways under different climate and market uncertainties and so inform constraints for multi-sectoral infrastructure investment planning” etc etc
And I know that OSeMOSYS is quite limited, and we would most likely need more powerful models to achieve the desired results. And the description also explicitly mentions Julia skills as a desired capability.