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

  1. running a small scenario from CSV folder with the CLI

  2. creating a small simulation from scratch as shown in tutorial 01

  3. load a scenario from an AMIRIS scenario.yaml

  4. 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:

http://localhost:3000/?orgId=1&var-simulation=example_01a_base&from=1546300800000&to=1548892800000&refresh=5s

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:

http://localhost:3000/d/mQ3Lvkr4k/assume3a-main-overview?orgId=1&var-simulation=amiris_simple&from=1609459200000&to=1609545600000&refresh=5s

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