Merge pull request #824 from PyPSA/custom-extra-functionality
solve_network: option to inject custom extra functionalities from sou…
This commit is contained in:
commit
e42f8f3d91
@ -640,6 +640,7 @@ solving:
|
|||||||
skip_iterations: true
|
skip_iterations: true
|
||||||
rolling_horizon: false
|
rolling_horizon: false
|
||||||
seed: 123
|
seed: 123
|
||||||
|
custom_extra_functionality: "../data/custom_extra_functionality.py"
|
||||||
# options that go into the optimize function
|
# options that go into the optimize function
|
||||||
track_iterations: false
|
track_iterations: false
|
||||||
min_iterations: 4
|
min_iterations: 4
|
||||||
|
11
data/custom_extra_functionality.py
Normal file
11
data/custom_extra_functionality.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SPDX-FileCopyrightText: : 2023- The PyPSA-Eur Authors
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
|
def custom_extra_functionality(n, snapshots):
|
||||||
|
"""
|
||||||
|
Add custom extra functionality constraints.
|
||||||
|
"""
|
||||||
|
pass
|
@ -6,6 +6,7 @@ options,,,
|
|||||||
-- skip_iterations,bool,"{'true','false'}","Skip iterating, do not update impedances of branches. Defaults to true."
|
-- 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."
|
-- 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.
|
-- 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 relative to ``rules`` directory.
|
||||||
-- 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)
|
-- 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.
|
-- 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.
|
-- 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.
|
||||||
|
|
@ -79,6 +79,11 @@ Upcoming Release
|
|||||||
reconnected to the main Ukrainian grid with the configuration option
|
reconnected to the main Ukrainian grid with the configuration option
|
||||||
`reconnect_crimea`.
|
`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``.
|
||||||
|
|
||||||
* Validate downloads from Zenodo using MD5 checksums. This identifies corrupted
|
* Validate downloads from Zenodo using MD5 checksums. This identifies corrupted
|
||||||
or incomplete downloads.
|
or incomplete downloads.
|
||||||
|
|
||||||
|
@ -28,6 +28,13 @@ def memory(w):
|
|||||||
return int(factor * (10000 + 195 * int(w.clusters)))
|
return int(factor * (10000 + 195 * int(w.clusters)))
|
||||||
|
|
||||||
|
|
||||||
|
def input_custom_extra_functionality(w):
|
||||||
|
path = config["solving"]["options"].get("custom_extra_functionality", False)
|
||||||
|
if path:
|
||||||
|
return workflow.source_path(path)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
# Check if the workflow has access to the internet by trying to access the HEAD of specified url
|
# Check if the workflow has access to the internet by trying to access the HEAD of specified url
|
||||||
def has_internet_access(url="www.zenodo.org") -> bool:
|
def has_internet_access(url="www.zenodo.org") -> bool:
|
||||||
import http.client as http_client
|
import http.client as http_client
|
||||||
|
@ -11,6 +11,7 @@ rule solve_network:
|
|||||||
co2_sequestration_potential=config["sector"].get(
|
co2_sequestration_potential=config["sector"].get(
|
||||||
"co2_sequestration_potential", 200
|
"co2_sequestration_potential", 200
|
||||||
),
|
),
|
||||||
|
custom_extra_functionality=input_custom_extra_functionality,
|
||||||
input:
|
input:
|
||||||
network=RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc",
|
network=RESOURCES + "networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc",
|
||||||
config=RESULTS + "config.yaml",
|
config=RESULTS + "config.yaml",
|
||||||
|
@ -88,6 +88,7 @@ rule solve_sector_network_myopic:
|
|||||||
co2_sequestration_potential=config["sector"].get(
|
co2_sequestration_potential=config["sector"].get(
|
||||||
"co2_sequestration_potential", 200
|
"co2_sequestration_potential", 200
|
||||||
),
|
),
|
||||||
|
custom_extra_functionality=input_custom_extra_functionality,
|
||||||
input:
|
input:
|
||||||
network=RESULTS
|
network=RESULTS
|
||||||
+ "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
+ "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
||||||
|
@ -11,6 +11,7 @@ rule solve_sector_network:
|
|||||||
co2_sequestration_potential=config["sector"].get(
|
co2_sequestration_potential=config["sector"].get(
|
||||||
"co2_sequestration_potential", 200
|
"co2_sequestration_potential", 200
|
||||||
),
|
),
|
||||||
|
custom_extra_functionality=input_custom_extra_functionality,
|
||||||
input:
|
input:
|
||||||
network=RESULTS
|
network=RESULTS
|
||||||
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
||||||
|
@ -118,6 +118,7 @@ rule solve_sector_network_perfect:
|
|||||||
co2_sequestration_potential=config["sector"].get(
|
co2_sequestration_potential=config["sector"].get(
|
||||||
"co2_sequestration_potential", 200
|
"co2_sequestration_potential", 200
|
||||||
),
|
),
|
||||||
|
custom_extra_functionality=input_custom_extra_functionality,
|
||||||
input:
|
input:
|
||||||
network=RESULTS
|
network=RESULTS
|
||||||
+ "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc",
|
+ "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc",
|
||||||
|
@ -26,8 +26,11 @@ Additionally, some extra constraints specified in :mod:`solve_network` are added
|
|||||||
the workflow for all scenarios in the configuration file (``scenario:``)
|
the workflow for all scenarios in the configuration file (``scenario:``)
|
||||||
based on the rule :mod:`solve_network`.
|
based on the rule :mod:`solve_network`.
|
||||||
"""
|
"""
|
||||||
|
import importlib
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -826,6 +829,14 @@ def extra_functionality(n, snapshots):
|
|||||||
add_carbon_budget_constraint(n, snapshots)
|
add_carbon_budget_constraint(n, snapshots)
|
||||||
add_retrofit_gas_boiler_constraint(n, snapshots)
|
add_retrofit_gas_boiler_constraint(n, snapshots)
|
||||||
|
|
||||||
|
if snakemake.params.custom_extra_functionality:
|
||||||
|
source_path = snakemake.params.custom_extra_functionality
|
||||||
|
assert os.path.exists(source_path), f"{source_path} does not exist"
|
||||||
|
sys.path.append(os.path.dirname(source_path))
|
||||||
|
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):
|
def solve_network(n, config, solving, opts="", **kwargs):
|
||||||
set_of_options = solving["solver"]["options"]
|
set_of_options = solving["solver"]["options"]
|
||||||
|
Loading…
Reference in New Issue
Block a user