-
Notifications
You must be signed in to change notification settings - Fork 202
Description
Issue Description
There is an incorrect variable reference in citylearn/building.py that prevents the Domestic Hot Water (DHW) storage system from updating its state of charge or energy balance. DHW actions are multiplied by self.heating_storage.capacity instead of self.dhw_storage.capacity.
When heating_storage is disabled (as in the 2023 challenge dataset), heating_storage.capacity == 0, causing DHW storage to remain unused even though dhw_storage appears as an active action.
Expected Behavior
When the agent outputs non-zero dhw_storage actions, the DHW tank should charge or discharge according to its configured capacity. Its SOC and energy balance should vary over time.
Actual Behavior
dhw_storageactions have no effect.- DHW SOC stays strictly zero for the entire episode.
- DHW energy balance remains zero.
- All DHW demand is supplied directly by the electric heater.
- Changing one line of code to reference
self.dhw_storage.capacityproduces
the expected non-zero behavior.
Output with original code (incorrect)
DHW Storage SOC: [0. 0. 0. 0. ... 0.]
Output after fixing the line
DHW Storage SOC: [0.9780134 1. 1. 1. ... 0.62974083 1. 0.]
This clearly shows that DHW storage behavior is completely suppressed in the current version.
Steps to Reproduce
-
Use the
citylearn_challenge_2023_phase_1dataset where:dhw_storageis active,heating_storageis inactive → capacity = 0.
-
Create any agent that outputs non-zero
dhw_storageactions. -
Run a full episode and log:
env.buildings[0].dhw_storage.soc
-
Observe that SOC stays zero throughout the entire simulation.
Minimal Reproducible Example
from typing import List
from citylearn.agents.base import Agent
from citylearn.citylearn import CityLearnEnv
class CustomRBC(Agent):
def __init__(self, env: CityLearnEnv, **kwargs):
super().__init__(env, **kwargs)
def predict(self, observations: List[List[float]], deterministic=True):
actions = []
for i, o in enumerate(observations):
available_obs = self.observation_names[i]
available_act = self.action_names[i]
action = [0.0 for _ in range(len(available_act))]
hour = o[available_obs.index('hour')]
if 'dhw_storage' in available_act:
if 6 <= hour <= 9 or 18 <= hour <= 22:
action[available_act.index('dhw_storage')] = -0.2
else:
action[available_act.index('dhw_storage')] = 1.0
actions.append(action)
return actions
env = CityLearnEnv(
schema='citylearn_challenge_2023_phase_1',
central_agent=True,
)
agent = CustomRBC(env)
obs, _ = env.reset(seed=0)
while not env.terminated:
action = agent.predict(obs)
obs, reward, _, _, _ = env.step(action)
print("DHW Storage SOC:", env.buildings[0].dhw_storage.soc)Environment
- CityLearn version: 2.4.2
- Dataset: citylearn_challenge_2023_phase_1
- Operating System: Ubuntu 24.04
- Python version: 3.10.19
- Issue present also in latest
mainbranch at time of reporting.
Root Cause
In building.py around line 1765:
energy = action * self.heating_storage.capacity * self.algorithm_action_based_time_step_hours_ratioThis uses the heating storage capacity even when processing DHW actions.
Possible Solution
Replace the incorrect line with:
energy = action * self.dhw_storage.capacity * self.algorithm_action_based_time_step_hours_ratioThis immediately restores correct DHW storage behavior.
Additional Notes
This bug makes DHW storage unusable in all configurations where heating storage is inactive (capacity = 0), including the official challenge dataset. Fixing it is necessary for agents to learn or implement any DHW shifting strategies.