Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
87ba266
rolling horision fucntion and forecast first version
Manish-Khanra Apr 7, 2026
ffa070b
Merge branch 'main' of https://github.com/assume-framework/assume int…
Manish-Khanra Apr 21, 2026
e6043ab
test and documentation
Manish-Khanra Apr 22, 2026
b7ca3eb
Merge branch 'main' of https://github.com/assume-framework/assume int…
Manish-Khanra Apr 30, 2026
6e63cb5
changes as per reviewer's remarks
Manish-Khanra Apr 30, 2026
d1f3732
Merge branch 'main' of https://github.com/assume-framework/assume int…
Manish-Khanra May 18, 2026
6310d09
Unknown DSM component technology fix
Manish-Khanra May 18, 2026
7575332
replaced hasattr with is not None
Manish-Khanra May 18, 2026
b95a4fc
Merge branch 'main' of https://github.com/assume-framework/assume int…
Manish-Khanra May 22, 2026
fa4365c
Revision 2.0
Manish-Khanra May 22, 2026
52da6f6
loader_csv: refactor steelplant registration
maurerle May 23, 2026
ec47e0a
update changes from todays discussion
maurerle May 29, 2026
809bb16
removed all reduncancies
Manish-Khanra Jun 1, 2026
3146b92
Merge branch 'main' of https://github.com/assume-framework/assume int…
Manish-Khanra Jun 3, 2026
4b54d25
Remove dead adaptive-price logic from DSM loader
Manish-Khanra Jun 3, 2026
6ed0de6
Add network notebook execution and pypsa dependency installation for …
Manish-Khanra Jun 3, 2026
ae32acd
Add conditional pytest tests for Python 3.14 to skip network requirem…
Manish-Khanra Jun 3, 2026
60bac63
Merge branch 'main' of https://github.com/assume-framework/assume int…
Manish-Khanra Jun 30, 2026
8fe99ea
Fix Read the Docs build: replace deprecated mambaforge-4.10 with mini…
Manish-Khanra Jun 30, 2026
1532cec
Merge branch 'main' of https://github.com/assume-framework/assume int…
Manish-Khanra Jun 30, 2026
caea887
Merge branch 'main' of https://github.com/assume-framework/assume int…
Manish-Khanra Jun 30, 2026
7df7932
Merge branch 'main' of https://github.com/assume-framework/assume int…
Manish-Khanra Jun 30, 2026
3e3ab25
Fix and Tests for rolling-horizon DSM state carryover across windows
Manish-Khanra Jul 1, 2026
557b5f2
Use standard unit attrs for rolling-horizon strategy detection.
maurerle Jul 13, 2026
caf315c
Add shared helper for unit-prefixed forecast CSV columns.
maurerle Jul 13, 2026
7bdbf71
Sync electricity price to units in DsmUnitForecaster.update.
maurerle Jul 13, 2026
9a11606
Read electricity prices from the forecaster instead of copying to units.
maurerle Jul 13, 2026
4a45ec9
Revert "Add conditional pytest tests for Python 3.14 to skip network …
maurerle Jul 13, 2026
8a8b5da
Revert "Add network notebook execution and pypsa dependency installat…
maurerle Jul 13, 2026
2dff6bf
Merge remote-tracking branch 'origin/main' into rolling_horizon_dsm
maurerle Jul 13, 2026
0695921
!fixup run pre-commit
maurerle Jul 13, 2026
892f84e
Rolling horizon dsm (#804)
Manish-Khanra Jul 14, 2026
8f9f699
add csv exporting functionality of scenario setup to check and rerun …
mthede Jul 7, 2026
00af521
fix examples (redispatch, nodal_clearing) in pypsa loader
mthede Jul 7, 2026
e56578c
fix: resolve bidding strategy naming and demand capacity sign in expo…
maurerle Jul 8, 2026
5016fa7
refactor: extract scenario exporting functionality to scenario/export…
maurerle Jul 8, 2026
0e8ae15
test: add unit tests for world exporting scenario
maurerle Jul 8, 2026
9a39935
adjusted forecast exporter and added a corresponding test
reinecfi Jul 9, 2026
22e8d3f
skip exporting stored timeseries in unit, small fixes
mthede Jul 9, 2026
fc6ab77
fix dsm unit export for industrial units
mthede Jul 9, 2026
d70b7cd
handle dsm specific attributes
mthede Jul 13, 2026
84c3c71
do not write default location as (0.0, 0.0) coordinates
mthede Jul 13, 2026
5666f76
normalize starting costs back to € / MW (as in input data format)
mthede Jul 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 44 additions & 13 deletions assume/common/forecaster.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ def __init__(
forecast_registries: dict[str, dict] = None,
congestion_signal: ForecastSeries = 0.0,
renewable_utilisation_signal: ForecastSeries = 0.0,
electricity_price: ForecastSeries = 0.0,
electricity_price: ForecastSeries = None,
):
super().__init__(
index=index,
Expand All @@ -495,7 +495,10 @@ def __init__(

# FIXME: currently default is series while calculations are dict of series
self.congestion_signal = self._to_series(congestion_signal)
self.electricity_price = self._to_series(electricity_price)
if electricity_price is None:
self.electricity_price = self._to_series(self.price.get("EOM", 0))
else:
self.electricity_price = self._to_series(electricity_price)
self.renewable_utilisation_signal = self._to_series(
renewable_utilisation_signal
)
Expand Down Expand Up @@ -663,7 +666,11 @@ def update(self, *args, **kwargs):
*args,
**kwargs,
)
self.congestion_signal = self._dict_to_series(self.congestion_signal)
self.congestion_signal = (
self._dict_to_series(self.congestion_signal)
if isinstance(self.congestion_signal, dict)
else self._to_series(self.congestion_signal)
)

renewable_utilisation_update_algorithm_name = self.forecast_algorithms.get(
"update_renewable_utilisation", "renewable_utilisation_default"
Expand All @@ -677,19 +684,31 @@ def update(self, *args, **kwargs):
*args,
**kwargs,
)
self.renewable_utilisation_signal = self._dict_to_series(
self.renewable_utilisation_signal
self.renewable_utilisation_signal = (
self._dict_to_series(self.renewable_utilisation_signal)
if isinstance(self.renewable_utilisation_signal, dict)
else self._to_series(self.renewable_utilisation_signal)
)

if "EOM" in self.price:
self.electricity_price = self.price["EOM"]


class SteelplantForecaster(DsmUnitForecaster):
"""Forecaster for steelplant units.

Provides all DSM forecasts (see :class:`DsmUnitForecaster`) plus fuel prices.
Provides all DSM forecasts (see :class:`DsmUnitForecaster`) plus fuel prices and steel demand.
After initialization, DSM signals are copied to the unit and ``setup_model()`` is called.

Supports three operational strategies:
1. **Profile-guided**: If ``normalized_load_profile`` is provided, production follows the profile shape.
2. **Min-demand**: If hourly minimum demand (``steel_demand``) is provided, meets per-hour minimums.
3. **Cost-optimized**: If neither is provided, minimizes cost without shape constraints.

Attributes:
fuel_prices (dict[str, ForecastSeries]): Map of fuel type to forecasted fuel prices.
steel_demand (ForecastSeries): Per-timestep steel production demand (optional).
normalized_load_profile (ForecastSeries): Normalized profile to guide production shape (optional).
"""

def __init__(
Expand All @@ -704,6 +723,8 @@ def __init__(
congestion_signal: ForecastSeries = 0.0,
renewable_utilisation_signal: ForecastSeries = 0.0,
electricity_price: ForecastSeries = None,
steel_demand: ForecastSeries = None,
normalized_load_profile: ForecastSeries = None,
):
super().__init__(
index=index,
Expand All @@ -717,6 +738,14 @@ def __init__(
electricity_price=electricity_price,
)
self.fuel_prices = self._dict_to_series(fuel_prices)
self.steel_demand = (
self._to_series(steel_demand) if steel_demand is not None else None
)
self.normalized_load_profile = (
self._to_series(normalized_load_profile)
if normalized_load_profile is not None
else None
)

def get_price(self, fuel: str) -> FastSeries:
if fuel not in self.fuel_prices:
Expand All @@ -737,12 +766,18 @@ def initialize(
initializing_unit,
)

initializing_unit.electricity_price = self.electricity_price
# Always set standard DSM signals
initializing_unit.congestion_signal = self.congestion_signal
initializing_unit.renewable_utilisation_signal = (
self.renewable_utilisation_signal
)

if self.steel_demand is not None:
initializing_unit.steel_demand_per_timestep = self.steel_demand

if self.normalized_load_profile is not None:
initializing_unit.normalized_load_profile = self.normalized_load_profile

initializing_unit.setup_model()


Expand Down Expand Up @@ -814,7 +849,6 @@ def initialize(
initializing_unit,
)

initializing_unit.electricity_price = self.electricity_price
initializing_unit.congestion_signal = self.congestion_signal
initializing_unit.renewable_utilisation_signal = (
self.renewable_utilisation_signal
Expand Down Expand Up @@ -908,16 +942,14 @@ def initialize(
initializing_unit,
)

initializing_unit.electricity_price = self.electricity_price
initializing_unit.setup_model(presolve=True)


class HydrogenForecaster(DsmUnitForecaster):
"""Forecaster for hydrogen units.

Provides all DSM forecasts (see :class:`DsmUnitForecaster`) plus hydrogen-specific
timeseries. After initialization, electricity price is copied to the unit and
``setup_model()`` is called.
timeseries. After initialization, ``setup_model()`` is called on the unit.

Attributes:
hydrogen_demand (ForecastSeries): Forecasted hydrogen demand.
Expand All @@ -934,7 +966,7 @@ def __init__(
availability: ForecastSeries = 1,
market_prices: dict[str, ForecastSeries] = None,
residual_load: dict[str, ForecastSeries] = None,
electricity_price: ForecastSeries = 0.0,
electricity_price: ForecastSeries = None,
):
super().__init__(
index=index,
Expand Down Expand Up @@ -962,7 +994,6 @@ def initialize(
initializing_unit,
)

initializing_unit.electricity_price = self.electricity_price
# initializing_unit.congestion_signal = self.congestion_signal
# initializing_unit.renewable_utilisation_signal = self.renewable_utilisation_signal

Expand Down
Loading
Loading