# Power system modeling

**URL:** <https://discourse.julialang.org/t/power-system-modeling/123823>\
**Category:** General Usage\
**Tags:** question\
**Created:** [December 13, 2024, 6:35pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823 "2024-12-13T18:35:53Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [December 13, 2024, 6:35pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/1 "2024-12-13T18:35:53Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [December 13, 2024, 6:45pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/2 "2024-12-13T18:45:44Z")

</div>

Yes. Rather than enumerate the many projects, i might just link to

> **[Open Energy Modeling at JuMP-dev](https://jump.dev/open-energy-modeling/2024/09/19/open-energy-models/)**
>
> In July 2024, we held JuMP-dev 2024, the seventh edition of our annual developer workshop. As part of the workshop, we sought talks from a number of groups who use JuMP to build open energy models. Motivated by our recently announced Open Energy...

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [December 13, 2024, 7:47pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/3 "2024-12-13T19:47:27Z")

</div>

Nice! How, do you think that [https://www.callio.pe/](https://www.callio.pe/) and [PowerSimulations.jl](https://github.com/NREL-Sienna/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 ?

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [December 13, 2024, 11:22pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/4 "2024-12-13T23:22:11Z")

</div>

This is a question for @jdlara-berkeley

---

<div class="post-metadata">

**Author:** ![jdlara-berkeley](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jdlara-berkeley/32/4096_2.png) [@jdlara-berkeley](https://discourse.julialang.org/u/jdlara-berkeley)\
**Post date:** [December 14, 2024, 12:42am UTC](https://discourse.julialang.org/t/power-system-modeling/123823/5 "2024-12-14T00:42:35Z")

</div>

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](https://nrel-sienna.github.io/PowerSystems.jl/stable/)

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [December 15, 2024, 1:20pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/6 "2024-12-15T13:20:46Z")

</div>

> [@jdlara-berkeley](#):
>
> [PowerSimulations.jl](https://juliahub.com/ui/Packages/General/PowerSimulations) is an operations simulation engine not an expansion problem

So is there a Julia package that solves the expansion problem?

---

<div class="post-metadata">

**Author:** ![sstroemer](https://avatars.discourse-cdn.com/v4/letter/s/a88e4f/32.png) [@sstroemer](https://discourse.julialang.org/u/sstroemer)\
**Post date:** [December 15, 2024, 4:17pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/7 "2024-12-15T16:17:11Z")

</div>

> [@ufechner7](#):
>
> So is there a Julia package that solves the expansion problem?

We are developing [IESopt.jl](https://github.com/ait-energy/IESopt.jl) since 2021, which has been open-sourced this spring (note that [the docs](https://ait-energy.github.io/iesopt/) are in a different repository). It is quite similar to [Calliope](https://www.callio.pe/) 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](https://ait-energy.github.io/iesopt/notebooks/first_model.html#final-config-file) 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:

- [Tulipa](https://github.com/TulipaEnergy/TulipaEnergyModel.jl)
- [GenX](https://github.com/GenXProject/GenX.jl)
- [SpineOpt](https://github.com/spine-tools/SpineOpt.jl)
- [EnergyModelsX](https://github.com/EnergyModelsX)

_(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

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [December 15, 2024, 5:18pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/8 "2024-12-15T17:18:56Z")

</div>

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](https://careers.tudelft.nl/job/Delft-Postdoc-Energy-and-Water-System-Dispatch-under-Uncertainty-2628-CD/809508502/)”

Not so clear to me yet:

- how to do water dispatch with these software packages
- how to build “spatially explicit” models (OK, I see [GitHub - EnergyModelsX/EnergyModelsGeography.jl](https://github.com/EnergyModelsX/EnergyModelsGeography.jl) , but can the other tools also be used to create “spatially explicit” models?)  
I found this article [A spatially explicit planning approach for power systems with a high share of renewable energy sources - ScienceDirect](https://www.sciencedirect.com/science/article/pii/S0306261919319208) about “spatially explicit” planning, but still no idea how to include this aspect using the existing power system dispatch modelling packages.

Any ideas?

---

<div class="post-metadata">

**Author:** ![sstroemer](https://avatars.discourse-cdn.com/v4/letter/s/a88e4f/32.png) [@sstroemer](https://discourse.julialang.org/u/sstroemer)\
**Post date:** [December 15, 2024, 11:15pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/9 "2024-12-15T23:15:07Z")

</div>

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.

* * *

> [@ufechner7](#):
>
> how to do water dispatch with these software packages

1. You introduce two energy carriers (without any specifics)

```yaml
carriers:
  water: {}
  electricity: {}

```

1. Discharging water from, e.g., a reservoir could then be done by creating a basic “turbine” like this

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

1. It further assumes (besides others) that there is a “lower reservoir”, which could look like this (if we assume a fixed capacity of 10000 units of water)

```yaml
reservoir_lower:
  type: Node
  carrier: water
  has_state: true
  state_lb: 0
  state_ub: 1e4

```

1. If you want to extend that to a cascade you could include that the water flows along a “river”:

```yaml
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"

```

* * *

> [@ufechner7](#):
>
> how to build “spatially explicit” models

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

1. You can then create unique grid nodes for these, e.g., by doing:

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

1. Now let’s say you are interested in a transmission expansion model. Then you could do modify the line to

```yaml
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:

- A user defined template `HydroReservoirPlant` that models such a plant
- Sets unique values for their `w2h_ratio` parameter
- Assumes the template has a further parameter called `grid_connection` to specify where the electricity is injected
- Using `se1.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`.

---

<div class="post-metadata">

**Author:** ![sstroemer](https://avatars.discourse-cdn.com/v4/letter/s/a88e4f/32.png) [@sstroemer](https://discourse.julialang.org/u/sstroemer)\
**Post date:** [December 15, 2024, 11:22pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/10 "2024-12-15T23:22:44Z")

</div>

I currently do not have a large-scale publicly available model “lying around”, but you can either check out the [national scale](https://calliope.readthedocs.io/en/stable/user/tutorials_01_national.html) example from Calliope, any of the pre-configured PyPSA-Eur (or Earth, etc.) models, or one of our examples, e.g.:

- Creating models with multiple locations fully from CSV files [[config](https://github.com/ait-energy/IESopt.jl/blob/main/assets/examples/09_csv_only.iesopt.yaml)]
- Creating models which dynamically load (or don’t) components based on a set of regions/countries defined [[config](https://github.com/ait-energy/IESopt.jl/blob/main/assets/examples/47_disable_components.iesopt.yaml)]

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

---

<div class="post-metadata">

**Author:** ![sstroemer](https://avatars.discourse-cdn.com/v4/letter/s/a88e4f/32.png) [@sstroemer](https://discourse.julialang.org/u/sstroemer)\
**Post date:** [December 15, 2024, 11:26pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/11 "2024-12-15T23:26:35Z")

</div>

> [@ufechner7](#):
>
> I am looking at this position: “[Postdoc Energy and Water System Dispatch under Uncertainty Job Details | TU Delft](https://careers.tudelft.nl/job/Delft-Postdoc-Energy-and-Water-System-Dispatch-under-Uncertainty-2628-CD/809508502/)”

Just one final remark, that description explicitly lists an energy system model / framework: [**OSeMOSYS**](http://www.osemosys.org/).

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [December 15, 2024, 11:34pm UTC](https://discourse.julialang.org/t/power-system-modeling/123823/12 "2024-12-15T23:34:05Z")

</div>

> [@sstroemer](#):
>
> Just one final remark, that description explicitly lists an energy system model / framework: [**OSeMOSYS**](http://www.osemosys.org/).

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.
