From 8a11bdb4b132f6803485c01c2d222cad8e9d3c66 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Fri, 29 Dec 2023 17:19:19 +0100 Subject: [PATCH] solve_network: option to inject custom extra functionalities from source file --- config/config.default.yaml | 1 + doc/configtables/solving.csv | 1 + doc/release_notes.rst | 5 +++++ rules/solve_myopic.smk | 3 +++ rules/solve_overnight.smk | 3 +++ rules/solve_perfect.smk | 3 +++ scripts/solve_network.py | 7 +++++++ 7 files changed, 23 insertions(+) diff --git a/config/config.default.yaml b/config/config.default.yaml index a6df173b..0ff742e7 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -627,6 +627,7 @@ solving: skip_iterations: true rolling_horizon: false seed: 123 + custom_extra_functionality: "data/custom_extra_functionality.py" # options that go into the optimize function track_iterations: false min_iterations: 4 diff --git a/doc/configtables/solving.csv b/doc/configtables/solving.csv index 45d50d84..9d47c043 100644 --- a/doc/configtables/solving.csv +++ b/doc/configtables/solving.csv @@ -6,6 +6,7 @@ options,,, -- skip_iterations,bool,"{'true','false'}","Skip iterating, do not update impedances of branches. Defaults to true." -- rolling_horizon,bool,"{'true','false'}","Whether to optimize the network in a rolling horizon manner, where the snapshot range is split into slices of size `horizon` which are solved consecutively." -- seed,--,int,Random seed for increased deterministic behaviour. +-- custom_extra_functionality,--,str,Path to a Python file with custom extra functionality code to be injected into the solving rules of the workflow. -- track_iterations,bool,"{'true','false'}",Flag whether to store the intermediate branch capacities and objective function values are recorded for each iteration in ``network.lines['s_nom_opt_X']`` (where ``X`` labels the iteration) -- min_iterations,--,int,Minimum number of solving iterations in between which resistance and reactence (``x/r``) are updated for branches according to ``s_nom_opt`` of the previous run. -- max_iterations,--,int,Maximum number of solving iterations in between which resistance and reactence (``x/r``) are updated for branches according to ``s_nom_opt`` of the previous run. diff --git a/doc/release_notes.rst b/doc/release_notes.rst index d7931f0e..a7644682 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -54,6 +54,11 @@ Upcoming Release reconnected to the main Ukrainian grid with the configuration option `reconnect_crimea`. +* Add option to reference an additional source file where users can specify + custom ``extra_functionality`` constraints in the configuration file. The + default setting points to an empty hull at + ``data/custom_extra_functionality.py``. + **Bugs and Compatibility** diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index 8a93d24a..217547b9 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -88,6 +88,9 @@ rule solve_sector_network_myopic: co2_sequestration_potential=config["sector"].get( "co2_sequestration_potential", 200 ), + custom_extra_functionality=workflow.source_path( + config["solver"]["options"].get("custom_extra_functionality", "") + ), input: network=RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", diff --git a/rules/solve_overnight.smk b/rules/solve_overnight.smk index c7700760..8ac56db8 100644 --- a/rules/solve_overnight.smk +++ b/rules/solve_overnight.smk @@ -11,6 +11,9 @@ rule solve_sector_network: co2_sequestration_potential=config["sector"].get( "co2_sequestration_potential", 200 ), + custom_extra_functionality=workflow.source_path( + config["solver"]["options"].get("custom_extra_functionality", "") + ), input: network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index ef4e367d..322ced8d 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -118,6 +118,9 @@ rule solve_sector_network_perfect: co2_sequestration_potential=config["sector"].get( "co2_sequestration_potential", 200 ), + custom_extra_functionality=workflow.source_path( + config["solver"]["options"].get("custom_extra_functionality", "") + ), input: network=RESULTS + "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", diff --git a/scripts/solve_network.py b/scripts/solve_network.py index ff2a2f23..539c4e72 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -26,7 +26,9 @@ Additionally, some extra constraints specified in :mod:`solve_network` are added the workflow for all scenarios in the configuration file (``scenario:``) based on the rule :mod:`solve_network`. """ +import importlib import logging +import os import re import numpy as np @@ -792,6 +794,11 @@ def extra_functionality(n, snapshots): add_carbon_budget_constraint(n, snapshots) add_retrofit_gas_boiler_constraint(n, snapshots) + if snakemake.params.custom_extra_functionality: + source_path = snakemake.params.custom_extra_functionality + module_name = os.path.splitext(os.path.basename(source_path))[0] + module = importlib.import_module(module_name) + module.custom_extra_functionality(n, snapshots) def solve_network(n, config, solving, opts="", **kwargs): set_of_options = solving["solver"]["options"]