From 1a6ba963db609cc70373bbd9007e230ed19c6778 Mon Sep 17 00:00:00 2001 From: Thomas Wolgast Date: Thu, 28 Nov 2024 17:36:26 +0100 Subject: [PATCH] Bugfix: Correct sampling in LoadShedding and MaxRenewable env --- opfgym/envs/load_shedding.py | 31 ++++++++++++++++++++----------- opfgym/envs/max_renewable.py | 15 ++++++++++----- opfgym/opf_env.py | 2 +- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/opfgym/envs/load_shedding.py b/opfgym/envs/load_shedding.py index 3753dce..2938afd 100644 --- a/opfgym/envs/load_shedding.py +++ b/opfgym/envs/load_shedding.py @@ -45,18 +45,31 @@ def __init__(self, simbench_network_name='1-MV-comm--2-sw', # Define the RL problem # See all load power values, sgen max active power... - obs_keys = [('sgen', 'p_mw', net.sgen.index), - ('load', 'max_p_mw', net.load.index), - ('load', 'q_mvar', net.load.index), - ('storage', 'p_mw', net.storage.index[~net.storage.controllable]), - ('poly_cost', 'cp1_eur_per_mw', net.poly_cost.index), - ('pwl_cost', 'cp1_eur_per_mw', net.pwl_cost.index)] + obs_keys = [ + ('sgen', 'p_mw', net.sgen.index), + ('load', 'max_p_mw', net.load.index), + ('load', 'q_mvar', net.load.index), + ('storage', 'p_mw', net.storage.index[~net.storage.controllable]), + ('poly_cost', 'cp1_eur_per_mw', net.poly_cost.index), + ('pwl_cost', 'cp1_eur_per_mw', net.pwl_cost.index) + ] + + # TODO: This is a workaround. Better would be to have identical obs and state keys. + state_keys = [ + ('sgen', 'p_mw', net.sgen.index), + ('load', 'p_mw', net.load.index), + ('load', 'q_mvar', net.load.index), + ('storage', 'p_mw', net.storage.index[~net.storage.controllable]), + # ('poly_cost', 'cp1_eur_per_mw', net.poly_cost.index), # Separately sampled in _sampling(), see below + # ('pwl_cost', 'cp1_eur_per_mw', net.pwl_cost.index) + ] # Control active power of loads and storages act_keys = [('load', 'p_mw', net.load.index[net.load.controllable]), ('storage', 'p_mw', net.storage.index[net.storage.controllable])] - super().__init__(net, act_keys, obs_keys, profiles=profiles, + super().__init__(net, act_keys, obs_keys, state_keys=state_keys, + profiles=profiles, *args, **kwargs) def _define_opf(self, simbench_network_name, *args, **kwargs): @@ -104,10 +117,6 @@ def _define_opf(self, simbench_network_name, *args, **kwargs): net.ext_grid['vm_pu'] = 1.0 - # Required for data sampling - net.load['mean_max_p_mw'] = net.load['mean_p_mw'] - net.load['std_dev_max_p_mw'] = net.load['std_dev_p_mw'] - return net, profiles def _sampling(self, *args, **kwargs): diff --git a/opfgym/envs/max_renewable.py b/opfgym/envs/max_renewable.py index 6df6488..8ffa56b 100644 --- a/opfgym/envs/max_renewable.py +++ b/opfgym/envs/max_renewable.py @@ -42,13 +42,22 @@ def __init__(self, simbench_network_name='1-HV-mixed--1-sw', ('storage', 'p_mw', net.storage.index[~net.storage.controllable]) ] + # TODO: This is a workaround. Better would be to have identical obs and state keys. + state_keys = [ + ('sgen', 'p_mw', net.sgen.index), + ('load', 'p_mw', net.load.index), + ('load', 'q_mvar', net.load.index), + ('storage', 'p_mw', net.storage.index[~net.storage.controllable]) + ] + # ... and control all sgens' active power values + some storage systems act_keys = [ ('sgen', 'p_mw', net.sgen.index[net.sgen.controllable]), ('storage', 'p_mw', net.storage.index[net.storage.controllable]) ] - super().__init__(net, act_keys, obs_keys, profiles=profiles, + super().__init__(net, act_keys, obs_keys, state_keys=state_keys, + profiles=profiles, *args, **kwargs) def _define_opf(self, simbench_network_name, *args, **kwargs): @@ -81,10 +90,6 @@ def _define_opf(self, simbench_network_name, *args, **kwargs): net.sgen['max_q_mvar'] = 0.0 net.sgen['min_q_mvar'] = 0.0 - # Required for data sampling - net.sgen['mean_max_p_mw'] = net.sgen['mean_p_mw'] - net.sgen['std_dev_max_p_mw'] = net.sgen['std_dev_p_mw'] - # OPF objective: Maximize active power feed-in to external grid active_power_costs = 30/1000 # /1000 to achieve smaller scale for idx in net.sgen.index: diff --git a/opfgym/opf_env.py b/opfgym/opf_env.py index f47e40e..64caaca 100644 --- a/opfgym/opf_env.py +++ b/opfgym/opf_env.py @@ -285,7 +285,7 @@ def _sample_normal(self, relative_std=None, truncated=False, assert sample_new, 'Currently only implemented for sample_new=True' for unit_type, column, idxs in self.state_keys: if 'res_' in unit_type or 'poly_cost' in unit_type: - continue + continue df = self.net[unit_type].loc[idxs] mean = df[f'mean_{column}']