Skip to content

Commit

Permalink
Fix loader and examples (#399)
Browse files Browse the repository at this point in the history
## Description
- check if availability_df containt values >1 and warn user if so
- fix these values automatically by normalizing them
- also check in the power plant itself when calculating max_power if
availability is larger than max_power
- restructure examples for easier understanding
- pack all feature example to example_01 and all learning to example_02
- add a full year DRL scenario from the fit paper
- all year examples are now as example_03

## Checklist
Please check all applicable items:

- [x] Code changes are sufficiently documented (docstrings, inline
comments, `doc` folder updates)
- [ ] New unit tests added for new features or bug fixes
- [x] Existing tests pass with the changes
- [x] Reinforcement learning examples are operational (for DRL-related
changes)
- [x] Code tested with both local and Docker databases
- [x] Code follows project style guidelines and best practices
- [x] Changes are backwards compatible, or deprecation notices added
- [ ] New dependencies added to `pyproject.toml`
- [x] A note for the release notes `doc/release_notes.rst` of the
upcoming release is included
- [x] Consent to release this PR's code under the GNU Affero General
Public License v3.0

---------

Co-authored-by: kim-mskw <kim.miskiw@kit.edu>
Co-authored-by: Florian Maurer <maurer@fh-aachen.de>
  • Loading branch information
3 people authored Aug 8, 2024
1 parent 8b7d076 commit efea877
Show file tree
Hide file tree
Showing 104 changed files with 430,620 additions and 228,969 deletions.
25 changes: 25 additions & 0 deletions assume/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,3 +538,28 @@ def create_nodal_incidence_matrix(lines, buses):
incidence_matrix[j, i] = -line["s_nom"]

return pd.DataFrame(incidence_matrix, index=nodes, columns=nodes)


def normalize_availability(powerplants_df, availability_df):
# Create a copy of the availability dataframe to avoid modifying the original
normalized_df = availability_df.copy()

# Iterate through each column in the availability dataframe
for column in normalized_df.columns:
# Check if any value in the column is greater than 1
if (normalized_df[column] > 1).any():
try:
# Get the max_power for the current unit from the powerplants dataframe
max_power = powerplants_df.loc[column, "max_power"]

# Normalize the entire column
normalized_df[column] = normalized_df[column] / max_power

# Ensure all values are between 0 and 1
normalized_df[column] = normalized_df[column].clip(0, 1)
except KeyError:
logger.warning(
f"Unit '{column}' not found in powerplants dataframe. Skipping normalization for this unit."
)

return normalized_df
21 changes: 19 additions & 2 deletions assume/scenario/loader_csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
from assume.common.exceptions import AssumeException
from assume.common.forecasts import CsvForecaster, Forecaster
from assume.common.market_objects import MarketConfig, MarketProduct
from assume.common.utils import adjust_unit_operator_for_learning, convert_to_rrule_freq
from assume.common.utils import (
adjust_unit_operator_for_learning,
convert_to_rrule_freq,
normalize_availability,
)
from assume.strategies import BaseStrategy
from assume.world import World

Expand Down Expand Up @@ -54,6 +58,8 @@ def load_file(
df = None

if file_name in config:
if config[file_name] is None:
return None
file_path = f"{path}/{config[file_name]}"
else:
file_path = f"{path}/{file_name}.csv"
Expand Down Expand Up @@ -372,7 +378,7 @@ def read_units(
bidding_strategies = {
key.split("bidding_")[1]: unit_params[key]
for key in unit_params.keys()
if key.startswith("bidding_")
if key.startswith("bidding_") and unit_params[key]
}
unit_params["bidding_strategies"] = bidding_strategies
operator_id = adjust_unit_operator_for_learning(
Expand Down Expand Up @@ -454,6 +460,17 @@ def load_config_and_create_forecaster(
availability = load_file(
path=path, config=config, file_name="availability_df", index=index
)
# check if availability contains any values larger than 1 and raise a warning
if availability is not None and availability.max().max() > 1:
# warn the user that the availability contains values larger than 1
# and normalize the availability
logger.warning(
"Availability contains values larger than 1. This is not allowed. "
"The availability will be normalized automatically. "
"The quality of the automatic normalization is not guaranteed."
)
availability = normalize_availability(powerplant_units, availability)

electricity_prices_df = load_file(
path=path, config=config, file_name="electricity_prices", index=index
)
Expand Down
10 changes: 7 additions & 3 deletions assume/units/powerplant.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,9 +334,13 @@ def calculate_min_max_power(
# min_power should be at least the heat demand at that time
min_power = min_power.clip(lower=heat_demand)

max_power = (
self.forecaster.get_availability(self.id)[start:end_excl] * self.max_power
)
available_power = self.forecaster.get_availability(self.id)[start:end_excl]
# check if available power is larger than max_power and raise an error if so
if (available_power > self.max_power).any():
raise ValueError(
f"Available power is larger than max_power for unit {self.id} at time {start}."
)
max_power = available_power * self.max_power
# provide reserve for capacity_pos
max_power = max_power - self.outputs["capacity_pos"][start:end_excl]
# remove what has already been bid
Expand Down
2 changes: 1 addition & 1 deletion assume_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,6 @@ def cli(args=None):
if __name__ == "__main__":
cli()

# args = "-s example_02 -db postgresql://assume:assume@localhost:5432/assume"
# args = "-s example_03 -db postgresql://assume:assume@localhost:5432/assume"

# cli(args.split(" "))
2 changes: 1 addition & 1 deletion compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ services:
build: .
depends_on:
- assume_db
command: -s example_02 -db "postgresql://assume:assume@assume_db:5432/assume"
command: -s example_03 -db "postgresql://assume:assume@assume_db:5432/assume"

# to run the simulation distributed with MQTT
mqtt-broker:
Expand Down
246 changes: 221 additions & 25 deletions docs/source/example_simulations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,233 @@
.. SPDX-License-Identifier: AGPL-3.0-or-later
Example Simulations
=====================
===================

While the modeller can define her own input data for the simulation, we provide some example simulations to get started.
Here you can find an overview of the different exampels provided. Below you find an exhaustive table explaining the different examples.
ASSUME provides a range of example simulations to help users understand and explore various market scenarios. These examples demonstrate different features and configurations, from small-scale setups to large, real-world simulations. Below is an overview of the available examples, followed by a more detailed explanation of their key features.

Overview of Example Simulations
-------------------------------

============================= ============================= =====================================================
example name input files description
============================= ============================= =====================================================
small example_01a Small Simulation (4 actors) with single hour bidding.
small_dam example_01a Small simulation with 24 hour bidding.
small_with_opt_clearing example_01a Small simulation with optimization clearing instead of pay_as_clear.
small_with_BB example_01d Small Simulation with Block Bids and complex clearing.
small_with_vre example_01b Small simulation with variable renewable energy.
small_learning_1 example_02a A small study with roughly 7 power plants, where 1 power plant is equiped with a learning bidding strategy and can learn to exert market power. [1]
small_learning_2 example_02b A small study with roughly 11 power plants, where 5 power plants are equiped with a learning bidding strategy and learn that they do not have market power anymore. [1]
small_learning_3 example_02c A small study with roughly 16 power plants, where 10 power plants are equiped with a learning bidding strategy and learn that they do not have market power anymore. [1]
============================= ============================= =====================================================
.. list-table::
:header-rows: 1
:widths: 30 30 40

The following table categorizes the different provided examples in a more detailed manner. We included the main features of ASSUME in the table.
* - Example Name
- Input Files
- Description
* - small
- example_01a
- Basic simulation with 4 actors and single-hour bidding.
* - small_dam
- example_01a
- Day-ahead market simulation with 24-hour bidding.
* - small_with_opt_clearing
- example_01a
- Demonstrates optimization-based market clearing.
* - small_with_vre
- example_01b
- Introduces variable renewable energy sources.
* - small_with_vre_and_storage
- example_01c
- Showcases renewable energy and storage units.
* - small_with_BB_and_LB
- example_01c
- Illustrates block bids and linked bids usage.
* - small_with_vre_and_storage_and_complex_clearing
- example_01c
- Combines VRE, storage, and complex clearing mechanisms.
* - small_with_crm
- example_01c
- Includes Control Reserve Market (CRM).
* - small_with_redispatch
- example_01d
- Demonstrates redispatch scenarios.
* - small_with_nodal_clearing
- example_01d
- Features nodal market clearing.
* - small_with_zonal_clearing
- example_01d
- Implements zonal market clearing.
* - market_study_eom
- example_01f
- Showcases comparison of single market to multi market. Case 1 in [3]_
* - market_study_eom_and_ltm
- example_01f
- Showcases simulation with EOM and LTM market. Case 2 in [3]_
* - small_learning_1
- example_02a
- 7 power plants, 1 with learning bidding strategy. Case 1 in [1]_
* - small_learning_2
- example_02b
- 11 power plants, 5 with learning bidding strategy. Case 2 in [1]_
* - small_learning_3
- example_02c
- 16 power plants, 10 with learning bidding strategy. Case 3 in [1]_
* - learning_with_complex_bids
- example_02d
- Learning strategies with complex bidding.
* - large_2019_eom
- example_03
- Full-year German power market simulation (EOM only). [2]_
* - large_2019_eom_crm
- example_03
- Full-year German power market simulation (EOM + CRM). [2]_
* - large_2019_day_ahead
- example_03
- Full-year German day-ahead market simulation. [2]_
* - large_2019_with_DSM
- example_03
- Full-year German market simulation with Demand Side Management. [2]_
* - large_2019_rl
- example_03a
- Full-year 2021 German market simulation with reinforcement learning with modified power plants list. [1]_
* - large_2021_rl
- example_03b
- Full-year 2021 German market simulation with reinforcement learning with modified power plants list. [1]_

Detailed Features of Example Simulations
----------------------------------------

============================== =============== =============== =================== ====================== ============= ============= ================= ============== =============
example name Country Generation Tech Generation Volume Demand Tech Demand Volume Markets Bidding Strategy Grid Further Infos
============================== =============== =============== =================== ====================== ============= ============= ================= ============== =============
small_learning_1 Germany conventional 12,500 MW fixed inflexible 1,000,000 MW EoM Learning, Naive No Resembles Case 1 from [1]
small_learning_2 Germany conventional 12,500 MW fixed inflexible 1,000,000 MW EoM Learning, Naive No Resembles Case 2 from [1]
small_learning_3 Germany conventional 12,500 MW fixed inflexible 1,000,000 MW EoM Learning, Naive No Resembles Case 3 from [1]
============================== =============== =============== =================== ====================== ============= ============= ================= ============== =============
The following table provides a more in-depth look at key examples, highlighting their specific characteristics and configurations.

.. list-table::
:header-rows: 1
:widths: 15 10 15 15 15 10 10 15 10 15

* - Example Name
- Country
- Generation Tech
- Generation Volume
- Demand Tech
- Demand Volume
- Markets
- Bidding Strategy
- Grid
- Further Info
* - small_learning_1
- Germany
- Conventional
- 12,500 MW
- Fixed inflexible
- 1,000,000 MW
- EOM
- Learning, Naive
- No
- Case 1 from [1]_
* - small_learning_2
- Germany
- Conventional
- 12,500 MW
- Fixed inflexible
- 1,000,000 MW
- EOM
- Learning, Naive
- No
- Case 2 from [1]_
* - small_learning_3
- Germany
- Conventional
- 12,500 MW
- Fixed inflexible
- 1,000,000 MW
- EOM
- Learning, Naive
- No
- Case 3 from [1]_
* - large_2019_eom
- Germany
- Conv., VRE
- Full 2019 data
- Fixed inflexible
- Full 2019 data
- EOM
- Various
- No
- Based on [2]_
* - large_2019_eom_crm
- Germany
- Conv., VRE
- Full 2019 data
- Fixed inflexible
- Full 2019 data
- EOM, CRM
- Various
- No
- Based on [2]_
* - large_2019_day_ahead
- Germany
- Conv., VRE
- Full 2019 data
- Fixed inflexible
- Full 2019 data
- DAM
- Various
- No
- Based on [2]_
* - large_2019_with_DSM
- Germany
- Conv., VRE
- Full 2019 data
- Fixed, Flexible (DSM)
- Full 2019 data
- EOM
- Various
- No
- Based on [2]_
* - large_2019_rl
- Germany
- Conv., VRE
- Full 2019 data
- Fixed inflexible
- Full 2019 data
- EOM
- RL, Various
- No
- Based on [1]_
* - large_2021_rl
- Germany
- Conv., VRE
- Full 2021 data
- Fixed inflexible
- Full 2021 data
- EOM
- RL, Various
- No
- Based on [1]_

Note: Conv. = Conventional, VRE = Variable Renewable Energy, EOM = Energy-Only Market, CRM = Control Reserve Market, DAM = Day-Ahead Market, RL = Reinforcement Learning, DSM = Demand Side Management

Key Features of Example Simulations
-----------------------------------

1. Small-scale examples (small_*):

- Designed for easier understanding of specific features and configurations.
- Demonstrate various market mechanisms, bidding strategies, and technologies.
- Useful for learning ASSUME's basic functionalities and exploring specific market aspects.

2. Learning-enabled examples (small_learning_*, learning_with_complex_bids):

- Showcase the integration of learning algorithms in bidding strategies.
- Illustrate how agents can adapt their behavior in different market conditions.
- small_learning_1, small_learning_2, and small_learning_3 directly correspond to Cases 1, 2, and 3, respectively, in the publication by Harder et al. [1]_.
- Demonstrate practical applications of reinforcement learning in energy markets.

3. Large-scale examples (large_2019_*, large_2021_rl):

- Represent real-world scenarios based on the German power market in 2019 and 2021.
- Include full demand and renewable generation profiles, major generation units, and storage facilities.
- Demonstrate different market configurations (EOM, CRM, DAM) and their impacts.
- The large_2019_with_DSM example incorporates steel plants as flexible demand side units, showcasing Demand Side Management capabilities.
- large_2019_rl and large_2021_rl examples apply reinforcement learning techniques to full-year market simulations, as presented in [1]_. In this examples, the power plant units with a capacity of less then 300 MW were aggregated into larger units to increase the learning speed.
- Based on comprehensive research presented in [1]_ and [2]_, offering insights into complex market dynamics and the application of advanced learning techniques in different market years.

These examples provide a diverse range of scenarios, allowing users to explore various aspects of energy market simulation, from basic concepts to complex, real-world applications and advanced learning strategies.

References
-----------
[1] Harder, Nick & Qussous, Ramiz & Weidlich, Anke. (2023). Fit for purpose: Modeling wholesale electricity markets realistically with multi-agent deep reinforcement learning. Energy and AI. 14. 100295. 10.1016/j.egyai.2023.100295.
----------
.. [1] Harder, N.; Qussous, R.; Weidlich, A. Fit for purpose: Modeling wholesale electricity markets realistically with multi-agent deep reinforcement learning. *Energy and AI* **2023**. 14. 100295. https://doi.org/10.1016/j.egyai.2023.100295.
.. [2] Qussous, R.; Harder, N.; Weidlich, A. Understanding Power Market Dynamics by Reflecting Market Interrelations and Flexibility-Oriented Bidding Strategies. *Energies* **2022**, *15*, 494. https://doi.org/10.3390/en15020494
.. [3] Maurer, F.; Miskiw, K.; Ramirez, R.; Harder, N.; Sander, V.; Lehnhoff, S. Abstraction of Energy Markets and Policies - Application in an Agent-Based Modeling Toolbox. *Energy Informatics* **2023**, http://doi.org/10.1007/978-3-031-48652-4_10
5 changes: 5 additions & 0 deletions docs/source/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ Upcoming Release 0.4.0
- Added `zones_identifier` to the configuration file and `zone_id` to the `buses.csv`, and refactored the complex market
clearing algorithm to incorporate zone information, ensuring that bids submitted with a specific node are
matched to the corresponding market zone.
- If any values in the availability_df.csv file are larger than 1, the framework will now warn the user
and run a method to normalize the values to [0, 1].
- Examples have been restructed to easier orientation and understanding: example_01.. cover all feature demonstration examples,
example_02.. cover all learning examples, example_03.. cover all full year examples

**Bug Fixes:**

Expand All @@ -49,6 +53,7 @@ Upcoming Release 0.4.0
- Fixed complex clearing with pyomo>=6.7
- Resolved various issues with learning and policy saving
- Fixed missing market dispatch values in day-ahead markets
- Added a check for availability_df.csv file to check for any values larger than 1

**Other Changes:**

Expand Down
Loading

0 comments on commit efea877

Please sign in to comment.