Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

less conservative value for the big-M value #905

Merged
merged 6 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 36 additions & 0 deletions flexmeasures/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -777,9 +777,45 @@ def create_test_battery_assets(
),
)
db.session.add(test_battery_sensor_no_prices)

test_small_battery = GenericAsset(
name="Test small battery",
owner=setup_accounts["Prosumer"],
generic_asset_type=battery_type,
latitude=10,
longitude=100,
attributes=dict(
capacity_in_mw=0.01,
max_soc_in_mwh=0.01,
min_soc_in_mwh=0,
soc_in_mwh=0.005,
soc_datetime="2040-01-01T00:00+01",
soc_udi_event_id=203,
market_id=setup_markets["epex_da"].id,
is_consumer=True,
is_producer=True,
can_curtail=True,
can_shift=True,
),
)

test_battery_sensor_small = Sensor(
name="power",
generic_asset=test_small_battery,
event_resolution=timedelta(minutes=15),
unit="MW",
attributes=dict(
daily_seasonality=True,
weekly_seasonality=True,
yearly_seasonality=True,
),
)
db.session.add(test_battery_sensor_small)

return {
"Test battery": test_battery,
"Test battery with no known prices": test_battery_no_prices,
"Test small battery": test_small_battery,
}


Expand Down
12 changes: 5 additions & 7 deletions flexmeasures/data/models/planning/linear_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,12 @@ def device_scheduler( # noqa C901
% (resolution, resolution_c)
)

bigM_columns = ["derivative max", "derivative min", "derivative equals"]
# Compute a good value for M
M = 0.1
for device_constraint in device_constraints:
M = max(
M,
device_constraint["derivative max"].max(),
-device_constraint["derivative min"].min(),
)
M = np.nanmax([np.nanmax(d[bigM_columns].abs()) for d in device_constraints])

# M has to be 1 MW, at least
M = max(M, 1)

# Turn prices per commitment into prices per commitment flow
if len(commitment_downwards_deviation_price) != 0:
Expand Down
12 changes: 9 additions & 3 deletions flexmeasures/data/models/planning/tests/test_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,16 @@ def test_storage_loss_function(


@pytest.mark.parametrize("use_inflexible_device", [False, True])
@pytest.mark.parametrize("battery_name", ["Test battery", "Test small battery"])
def test_battery_solver_day_1(
add_battery_assets, add_inflexible_device_forecasts, use_inflexible_device
add_battery_assets,
add_inflexible_device_forecasts,
use_inflexible_device,
battery_name,
):
epex_da, battery = get_sensors_from_db(add_battery_assets)
epex_da, battery = get_sensors_from_db(
add_battery_assets, battery_name=battery_name
)
tz = pytz.timezone("Europe/Amsterdam")
start = tz.localize(datetime(2015, 1, 1))
end = tz.localize(datetime(2015, 1, 2))
Expand Down Expand Up @@ -997,7 +1003,7 @@ def compute_schedule(flex_model):
compute_schedule(flex_model)


def get_sensors_from_db(battery_assets):
def get_sensors_from_db(battery_assets, battery_name="Test battery"):
# get the sensors from the database
epex_da = Sensor.query.filter(Sensor.name == "epex_da").one_or_none()
battery = battery_assets["Test battery"].sensors[0]
Expand Down