Note
You can download this example as a Jupyter notebook or try it out directly in Google Colab.
7. Interoperability and Input-Output#
This tutorial describes how ASSUME can be used to create market simulations from energy system simulations as well as other market simulations like AMIRIS. A broad comparison towards AMIRIS is submitted to the EEM2024.
This tutorial describes how one can create scenarios from different input sets and use existing scenarios from it.
As a whole, this tutorial covers the following
running a small scenario from CSV folder with the CLI
creating a small simulation from scratch as shown in tutorial 01
load a scenario from an AMIRIS scenario.yaml
load a scenario from a pypsa network
1. Scenario from CLI#
First we need to install assume
[ ]:
!pip install assume-framework
If we run in Google Colab, we need to first clone the ASSUME repository there to access the tutorial data
[ ]:
!git clone https://github.com/assume-framework/assume.git
!cd assume
Now we can use the CLI script to run a simulation - relative to the examples folder
[ ]:
!assume -s example_01a -c tiny -db "sqlite:///database.db"
Protip: with argcomplete - one can create very nice tab completion for python scripts.
Though one has to run eval "$(register-python-argcomplete assume)"
once in the env before
We did not use the postgresql database - therefore we can not use our visualization - lets fix this (if you have postgresql and grafana installed - or available through docker)
[ ]:
!assume -s example_01a -c base -db "postgresql://assume:assume@localhost:5432/assume"
If you have docker at hand, you can see the results on grafana:
2. Run from a script to customize scenario yourself#
This is a more advanced option - though it gives full control on what we are doing here:
[ ]:
import logging
import os
from datetime import datetime, timedelta
import pandas as pd
from dateutil import rrule as rr
from assume import World
from assume.common.forecasts import NaiveForecast
from assume.common.market_objects import MarketConfig, MarketProduct
log = logging.getLogger(__name__)
os.makedirs("./local_db", exist_ok=True)
db_uri = "sqlite:///./local_db/assume_db_min_example.db"
world = World(database_uri=db_uri)
start = datetime(2023, 1, 1)
end = datetime(2023, 3, 31)
index = pd.date_range(
start=start,
end=end + timedelta(hours=24),
freq="h",
)
sim_id = "world_script_simulation"
world.loop.run_until_complete(
world.setup(
start=start,
end=end,
save_frequency_hours=48,
simulation_id=sim_id,
index=index,
)
)
marketdesign = [
MarketConfig(
market_id="EOM",
opening_hours=rr.rrule(rr.HOURLY, interval=24, dtstart=start, until=end),
opening_duration=timedelta(hours=1),
market_mechanism="pay_as_clear",
market_products=[MarketProduct(timedelta(hours=1), 24, timedelta(hours=1))],
additional_fields=["block_id", "link", "exclusive_id"],
)
]
mo_id = "market_operator"
world.add_market_operator(id=mo_id)
for market_config in marketdesign:
world.add_market(market_operator_id=mo_id, market_config=market_config)
world.add_unit_operator("demand_operator")
demand_forecast = NaiveForecast(index, demand=100)
world.add_unit(
id="demand_unit",
unit_type="demand",
unit_operator_id="demand_operator",
unit_params={
"min_power": 0,
"max_power": 1000,
"bidding_strategies": {"EOM": "naive_eom"},
"technology": "demand",
},
forecaster=demand_forecast,
)
world.add_unit_operator("unit_operator")
nuclear_forecast = NaiveForecast(index, availability=1, fuel_price=3, co2_price=0.1)
world.add_unit(
id="nuclear_unit",
unit_type="power_plant",
unit_operator_id="unit_operator",
unit_params={
"min_power": 200,
"max_power": 1000,
"bidding_strategies": {"EOM": "naive_eom"},
"technology": "nuclear",
},
forecaster=nuclear_forecast,
)
world.run()
3. Load AMIRIS scenario#
First we need to download the examples repository from amiris
[ ]:
!cd .. && git clone https://gitlab.com/dlr-ve/esy/amiris/examples.git amiris-examples
Now that we have the repository at the right place, we can run the amiris scenario:
[ ]:
from assume.scenario.loader_amiris import load_amiris_async
from assume import World
scenario = "Simple" # Germany20{15-19}, Austria2019 or Simple
base_path = f"../amiris-examples/{scenario}/"
db_uri = "postgresql://assume:assume@localhost:5432/assume"
# db_uri = "sqlite:///test.db"
world = World(database_uri=db_uri)
world.loop.run_until_complete(
load_amiris_async(
world,
"amiris",
scenario.lower(),
base_path,
)
)
print(f"did load {scenario} - now simulating")
world.run()
We can now look at the results here:
4. Load PyPSA scenario#
[ ]:
import pypsa
# python-dateutil
from dateutil import rrule as rr
from datetime import timedelta
from assume import World, MarketConfig, MarketProduct
from assume.scenario.loader_pypsa import load_pypsa_async
db_uri = "postgresql://assume:assume@localhost:5432/assume"
world = World(database_uri=db_uri)
scenario = "world_pypsa"
study_case = "ac_dc_meshed"
# "pay_as_clear", "redispatch" or "nodal"
market_mechanism = "pay_as_clear"
network = pypsa.examples.ac_dc_meshed(from_master=True)
# network = pypsa.examples.storage_hvdc(True)
# network = pypsa.examples.scigrid_de(True, from_master=True)
start = network.snapshots[0]
end = network.snapshots[-1]
marketdesign = [
MarketConfig(
"EOM",
rr.rrule(rr.HOURLY, interval=1, dtstart=start, until=end),
timedelta(hours=1),
market_mechanism,
[MarketProduct(timedelta(hours=1), 1, timedelta(hours=1))],
additional_fields=["node", "max_power", "min_power"],
maximum_bid_volume=1e9,
maximum_bid_price=1e9,
)
]
default_strategies = {
mc.market_id: (
"naive_redispatch" if mc.market_mechanism == "redispatch" else "naive_eom"
)
for mc in marketdesign
}
from collections import defaultdict
bidding_strategies = defaultdict(lambda: default_strategies)
world.loop.run_until_complete(
load_pypsa_async(
world, scenario, study_case, network, marketdesign, bidding_strategies
)
)
world.run()
Finally one can look at the result from the PyPSA simulation:
This also shows a visualization of the grid.
Conclusion#
In this tutorial, we have shown how different input formats can be used with ASSUME to create interoperability between different energy market simulations. It can also be used to load data from your personal existing simulations created in one of the other cases.