adjust param accessing in cluster, simplify and build_elec script
This commit is contained in:
parent
12b9356245
commit
45cac01ea3
@ -316,16 +316,14 @@ rule add_electricity:
|
|||||||
|
|
||||||
rule simplify_network:
|
rule simplify_network:
|
||||||
params:
|
params:
|
||||||
clustering=config["clustering"],
|
simplify_network=config["clustering"]["simplify_network"],
|
||||||
max_hours=config["electricity"]["max_hours"],
|
aggregation_strategies=config["clustering"].get("aggregation_strategies", {}),
|
||||||
|
focus_weights=config.get("focus_weights", None),
|
||||||
|
renewable_carriers=config["electricity"]["renewable_carriers"],
|
||||||
costs=config["costs"],
|
costs=config["costs"],
|
||||||
renewable=config["renewable"],
|
max_hours=config["electricity"]["max_hours"],
|
||||||
length_factor=config["lines"]["length_factor"],
|
length_factor=config["lines"]["length_factor"],
|
||||||
p_max_pu=config["links"].get("p_max_pu", 1.0),
|
p_max_pu=config["links"].get("p_max_pu", 1.0),
|
||||||
exclude_carriers=config["clustering"]["simplify_network"].get(
|
|
||||||
"exclude_carriers", []
|
|
||||||
),
|
|
||||||
focus_weights=config.get("focus_weights", None),
|
|
||||||
solver_name=config["solving"]["solver"]["name"],
|
solver_name=config["solving"]["solver"]["name"],
|
||||||
input:
|
input:
|
||||||
network=RESOURCES + "networks/elec.nc",
|
network=RESOURCES + "networks/elec.nc",
|
||||||
@ -353,14 +351,16 @@ rule simplify_network:
|
|||||||
|
|
||||||
rule cluster_network:
|
rule cluster_network:
|
||||||
params:
|
params:
|
||||||
solver_name=config["solving"]["solver"]["name"],
|
cluster_network=config["clustering"]["cluster_network"],
|
||||||
max_hours=config["electricity"]["max_hours"],
|
aggregation_strategies=config["clustering"].get("aggregation_strategies", {}),
|
||||||
|
custom_busmap=config["enable"].get("custom_busmap", False),
|
||||||
|
focus_weights=config.get("focus_weights", None),
|
||||||
|
renewable_carriers=config["electricity"]["renewable_carriers"],
|
||||||
conventional_carriers=config["electricity"].get("conventional_carriers", []),
|
conventional_carriers=config["electricity"].get("conventional_carriers", []),
|
||||||
costs=config["costs"],
|
costs=config["costs"],
|
||||||
|
max_hours=config["electricity"]["max_hours"],
|
||||||
length_factor=config["lines"]["length_factor"],
|
length_factor=config["lines"]["length_factor"],
|
||||||
renewable=config["renewable"],
|
solver_name=config["solving"]["solver"]["name"],
|
||||||
clustering=config["clustering"],
|
|
||||||
custom_busmap=config["enable"].get("custom_busmap", False),
|
|
||||||
input:
|
input:
|
||||||
network=RESOURCES + "networks/elec_s{simpl}.nc",
|
network=RESOURCES + "networks/elec_s{simpl}.nc",
|
||||||
regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}.geojson",
|
regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}.geojson",
|
||||||
|
@ -726,23 +726,23 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
costs = load_costs(
|
costs = load_costs(
|
||||||
snakemake.input.tech_costs,
|
snakemake.input.tech_costs,
|
||||||
snakemake.params["costs"],
|
snakemake.params.costs,
|
||||||
snakemake.params["electricity"]["max_hours"],
|
snakemake.params.electricity["max_hours"],
|
||||||
Nyears,
|
Nyears,
|
||||||
)
|
)
|
||||||
ppl = load_powerplants(snakemake.input.powerplants)
|
ppl = load_powerplants(snakemake.input.powerplants)
|
||||||
|
|
||||||
if "renewable_carriers" in snakemake.params["electricity"]:
|
if "renewable_carriers" in snakemake.params.electricity:
|
||||||
renewable_carriers = set(snakemake.params["electricity"]["renewable_carriers"])
|
renewable_carriers = set(snakemake.params.electricity["renewable_carriers"])
|
||||||
else:
|
else:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Missing key `renewable_carriers` under config entry `electricity`. "
|
"Missing key `renewable_carriers` under config entry `electricity`. "
|
||||||
"In future versions, this will raise an error. "
|
"In future versions, this will raise an error. "
|
||||||
"Falling back to carriers listed under `renewable`."
|
"Falling back to carriers listed under `renewable`."
|
||||||
)
|
)
|
||||||
renewable_carriers = snakemake.params["renewable"]
|
renewable_carriers = snakemake.params.renewable
|
||||||
|
|
||||||
extendable_carriers = snakemake.params["electricity"]["extendable_carriers"]
|
extendable_carriers = snakemake.params.electricity["extendable_carriers"]
|
||||||
if not (set(renewable_carriers) & set(extendable_carriers["Generator"])):
|
if not (set(renewable_carriers) & set(extendable_carriers["Generator"])):
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"No renewables found in config entry `extendable_carriers`. "
|
"No renewables found in config entry `extendable_carriers`. "
|
||||||
@ -750,18 +750,18 @@ if __name__ == "__main__":
|
|||||||
"Falling back to all renewables."
|
"Falling back to all renewables."
|
||||||
)
|
)
|
||||||
|
|
||||||
conventional_carriers = snakemake.params["electricity"]["conventional_carriers"]
|
conventional_carriers = snakemake.params.electricity["conventional_carriers"]
|
||||||
|
|
||||||
attach_load(
|
attach_load(
|
||||||
n,
|
n,
|
||||||
snakemake.input.regions,
|
snakemake.input.regions,
|
||||||
snakemake.input.load,
|
snakemake.input.load,
|
||||||
snakemake.input.nuts3_shapes,
|
snakemake.input.nuts3_shapes,
|
||||||
snakemake.params["countries"],
|
snakemake.params.countries,
|
||||||
snakemake.params["scaling_factor"],
|
snakemake.params.scaling_factor,
|
||||||
)
|
)
|
||||||
|
|
||||||
update_transmission_costs(n, costs, snakemake.params["length_factor"])
|
update_transmission_costs(n, costs, snakemake.params.length_factor)
|
||||||
|
|
||||||
conventional_inputs = {
|
conventional_inputs = {
|
||||||
k: v for k, v in snakemake.input.items() if k.startswith("conventional_")
|
k: v for k, v in snakemake.input.items() if k.startswith("conventional_")
|
||||||
@ -772,7 +772,7 @@ if __name__ == "__main__":
|
|||||||
ppl,
|
ppl,
|
||||||
conventional_carriers,
|
conventional_carriers,
|
||||||
extendable_carriers,
|
extendable_carriers,
|
||||||
snakemake.params["conventional"],
|
snakemake.params.conventional,
|
||||||
conventional_inputs,
|
conventional_inputs,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -782,11 +782,11 @@ if __name__ == "__main__":
|
|||||||
snakemake.input,
|
snakemake.input,
|
||||||
renewable_carriers,
|
renewable_carriers,
|
||||||
extendable_carriers,
|
extendable_carriers,
|
||||||
snakemake.params["length_factor"],
|
snakemake.params.length_factor,
|
||||||
)
|
)
|
||||||
|
|
||||||
if "hydro" in renewable_carriers:
|
if "hydro" in renewable_carriers:
|
||||||
para = snakemake.params["renewable"]["hydro"]
|
para = snakemake.params.renewable["hydro"]
|
||||||
attach_hydro(
|
attach_hydro(
|
||||||
n,
|
n,
|
||||||
costs,
|
costs,
|
||||||
@ -797,7 +797,7 @@ if __name__ == "__main__":
|
|||||||
**para,
|
**para,
|
||||||
)
|
)
|
||||||
|
|
||||||
if "estimate_renewable_capacities" not in snakemake.params["electricity"]:
|
if "estimate_renewable_capacities" not in snakemake.params.electricity:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Missing key `estimate_renewable_capacities` under config entry `electricity`. "
|
"Missing key `estimate_renewable_capacities` under config entry `electricity`. "
|
||||||
"In future versions, this will raise an error. "
|
"In future versions, this will raise an error. "
|
||||||
@ -805,18 +805,18 @@ if __name__ == "__main__":
|
|||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
"estimate_renewable_capacities_from_capacity_stats"
|
"estimate_renewable_capacities_from_capacity_stats"
|
||||||
in snakemake.params["electricity"]
|
in snakemake.params.electricity
|
||||||
):
|
):
|
||||||
estimate_renewable_caps = {
|
estimate_renewable_caps = {
|
||||||
"enable": True,
|
"enable": True,
|
||||||
**snakemake.params["electricity"][
|
**snakemake.params.electricity[
|
||||||
"estimate_renewable_capacities_from_capacity_stats"
|
"estimate_renewable_capacities_from_capacity_stats"
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
estimate_renewable_caps = {"enable": False}
|
estimate_renewable_caps = {"enable": False}
|
||||||
else:
|
else:
|
||||||
estimate_renewable_caps = snakemake.params["electricity"][
|
estimate_renewable_caps = snakemake.params.electricity[
|
||||||
"estimate_renewable_capacities"
|
"estimate_renewable_capacities"
|
||||||
]
|
]
|
||||||
if "enable" not in estimate_renewable_caps:
|
if "enable" not in estimate_renewable_caps:
|
||||||
@ -832,18 +832,18 @@ if __name__ == "__main__":
|
|||||||
"Falling back to whether `renewable_capacities_from_opsd` is non-empty."
|
"Falling back to whether `renewable_capacities_from_opsd` is non-empty."
|
||||||
)
|
)
|
||||||
from_opsd = bool(
|
from_opsd = bool(
|
||||||
snakemake.params["electricity"].get("renewable_capacities_from_opsd", False)
|
snakemake.params.electricity.get("renewable_capacities_from_opsd", False)
|
||||||
)
|
)
|
||||||
estimate_renewable_caps["from_opsd"] = from_opsd
|
estimate_renewable_caps["from_opsd"] = from_opsd
|
||||||
|
|
||||||
if estimate_renewable_caps["enable"]:
|
if estimate_renewable_caps["enable"]:
|
||||||
if estimate_renewable_caps["from_opsd"]:
|
if estimate_renewable_caps["from_opsd"]:
|
||||||
tech_map = snakemake.params["electricity"]["estimate_renewable_capacities"][
|
tech_map = snakemake.params.electricity["estimate_renewable_capacities"][
|
||||||
"technology_mapping"
|
"technology_mapping"
|
||||||
]
|
]
|
||||||
attach_OPSD_renewables(n, tech_map)
|
attach_OPSD_renewables(n, tech_map)
|
||||||
estimate_renewable_capacities(
|
estimate_renewable_capacities(
|
||||||
n, snakemake.params["electricity"], snakemake.params["countries"]
|
n, snakemake.params.electricity, snakemake.params.countries
|
||||||
)
|
)
|
||||||
|
|
||||||
update_p_nom_max(n)
|
update_p_nom_max(n)
|
||||||
|
@ -309,7 +309,7 @@ if __name__ == "__main__":
|
|||||||
p_nom_max = capacities / max_cap_factor
|
p_nom_max = capacities / max_cap_factor
|
||||||
else:
|
else:
|
||||||
raise AssertionError(
|
raise AssertionError(
|
||||||
'params key `potential` should be one of "simple" '
|
'Config key `potential` should be one of "simple" '
|
||||||
f'(default) or "conservative", not "{p_nom_max_meth}"'
|
f'(default) or "conservative", not "{p_nom_max_meth}"'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ def get_feature_for_hac(n, buses_i=None, feature=None):
|
|||||||
if "offwind" in carriers:
|
if "offwind" in carriers:
|
||||||
carriers.remove("offwind")
|
carriers.remove("offwind")
|
||||||
carriers = np.append(
|
carriers = np.append(
|
||||||
carriers, network.generators.carrier.filter(like="offwind").unique()
|
carriers, n.generators.carrier.filter(like="offwind").unique()
|
||||||
)
|
)
|
||||||
|
|
||||||
if feature.split("-")[1] == "cap":
|
if feature.split("-")[1] == "cap":
|
||||||
@ -463,26 +463,18 @@ if __name__ == "__main__":
|
|||||||
snakemake = mock_snakemake("cluster_network", simpl="", clusters="5")
|
snakemake = mock_snakemake("cluster_network", simpl="", clusters="5")
|
||||||
configure_logging(snakemake)
|
configure_logging(snakemake)
|
||||||
|
|
||||||
|
params = snakemake.params
|
||||||
|
solver_name = snakemake.config["solving"]["solver"]["name"]
|
||||||
|
|
||||||
n = pypsa.Network(snakemake.input.network)
|
n = pypsa.Network(snakemake.input.network)
|
||||||
|
|
||||||
focus_weights = snakemake.config.get("focus_weights", None)
|
exclude_carriers = params.cluster_network["exclude_carriers"]
|
||||||
|
|
||||||
renewable_carriers = pd.Index(
|
|
||||||
[
|
|
||||||
tech
|
|
||||||
for tech in n.generators.carrier.unique()
|
|
||||||
if tech in snakemake.params["renewable"]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
exclude_carriers = snakemake.params["clustering"]["cluster_network"].get(
|
|
||||||
"exclude_carriers", []
|
|
||||||
)
|
|
||||||
aggregate_carriers = set(n.generators.carrier) - set(exclude_carriers)
|
aggregate_carriers = set(n.generators.carrier) - set(exclude_carriers)
|
||||||
if snakemake.wildcards.clusters.endswith("m"):
|
if snakemake.wildcards.clusters.endswith("m"):
|
||||||
n_clusters = int(snakemake.wildcards.clusters[:-1])
|
n_clusters = int(snakemake.wildcards.clusters[:-1])
|
||||||
conventional = set(snakemake.params["conventional_carriers"])
|
aggregate_carriers = set(params.conventional_carriers).intersection(
|
||||||
aggregate_carriers = conventional.intersection(aggregate_carriers)
|
aggregate_carriers
|
||||||
|
)
|
||||||
elif snakemake.wildcards.clusters == "all":
|
elif snakemake.wildcards.clusters == "all":
|
||||||
n_clusters = len(n.buses)
|
n_clusters = len(n.buses)
|
||||||
else:
|
else:
|
||||||
@ -496,13 +488,12 @@ if __name__ == "__main__":
|
|||||||
n, busmap, linemap, linemap, pd.Series(dtype="O")
|
n, busmap, linemap, linemap, pd.Series(dtype="O")
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
line_length_factor = snakemake.params["length_factor"]
|
|
||||||
Nyears = n.snapshot_weightings.objective.sum() / 8760
|
Nyears = n.snapshot_weightings.objective.sum() / 8760
|
||||||
|
|
||||||
hvac_overhead_cost = load_costs(
|
hvac_overhead_cost = load_costs(
|
||||||
snakemake.input.tech_costs,
|
snakemake.input.tech_costs,
|
||||||
snakemake.params["costs"],
|
params.costs,
|
||||||
snakemake.params["max_hours"],
|
params.max_hours,
|
||||||
Nyears,
|
Nyears,
|
||||||
).at["HVAC overhead", "capital_cost"]
|
).at["HVAC overhead", "capital_cost"]
|
||||||
|
|
||||||
@ -513,16 +504,16 @@ if __name__ == "__main__":
|
|||||||
).all() or x.isnull().all(), "The `potential` configuration option must agree for all renewable carriers, for now!"
|
).all() or x.isnull().all(), "The `potential` configuration option must agree for all renewable carriers, for now!"
|
||||||
return v
|
return v
|
||||||
|
|
||||||
aggregation_strategies = snakemake.params["clustering"].get(
|
|
||||||
"aggregation_strategies", {}
|
|
||||||
)
|
|
||||||
# translate str entries of aggregation_strategies to pd.Series functions:
|
# translate str entries of aggregation_strategies to pd.Series functions:
|
||||||
aggregation_strategies = {
|
aggregation_strategies = {
|
||||||
p: {k: getattr(pd.Series, v) for k, v in aggregation_strategies[p].items()}
|
p: {
|
||||||
for p in aggregation_strategies.keys()
|
k: getattr(pd.Series, v)
|
||||||
|
for k, v in params.aggregation_strategies[p].items()
|
||||||
|
}
|
||||||
|
for p in params.aggregation_strategies.keys()
|
||||||
}
|
}
|
||||||
|
|
||||||
custom_busmap = snakemake.params["custom_busmap"]
|
custom_busmap = params.custom_busmap
|
||||||
if custom_busmap:
|
if custom_busmap:
|
||||||
custom_busmap = pd.read_csv(
|
custom_busmap = pd.read_csv(
|
||||||
snakemake.input.custom_busmap, index_col=0, squeeze=True
|
snakemake.input.custom_busmap, index_col=0, squeeze=True
|
||||||
@ -530,21 +521,18 @@ if __name__ == "__main__":
|
|||||||
custom_busmap.index = custom_busmap.index.astype(str)
|
custom_busmap.index = custom_busmap.index.astype(str)
|
||||||
logger.info(f"Imported custom busmap from {snakemake.input.custom_busmap}")
|
logger.info(f"Imported custom busmap from {snakemake.input.custom_busmap}")
|
||||||
|
|
||||||
cluster_config = snakemake.config.get("clustering", {}).get(
|
|
||||||
"cluster_network", {}
|
|
||||||
)
|
|
||||||
clustering = clustering_for_n_clusters(
|
clustering = clustering_for_n_clusters(
|
||||||
n,
|
n,
|
||||||
n_clusters,
|
n_clusters,
|
||||||
custom_busmap,
|
custom_busmap,
|
||||||
aggregate_carriers,
|
aggregate_carriers,
|
||||||
line_length_factor,
|
params.length_factor,
|
||||||
aggregation_strategies,
|
params.aggregation_strategies,
|
||||||
snakemake.params["solver_name"],
|
solver_name,
|
||||||
cluster_config.get("algorithm", "hac"),
|
params.cluster_network["algorithm"],
|
||||||
cluster_config.get("feature", "solar+onwind-time"),
|
params.cluster_network["feature"],
|
||||||
hvac_overhead_cost,
|
hvac_overhead_cost,
|
||||||
focus_weights,
|
params.focus_weights,
|
||||||
)
|
)
|
||||||
|
|
||||||
update_p_nom_max(clustering.network)
|
update_p_nom_max(clustering.network)
|
||||||
|
@ -149,17 +149,17 @@ def simplify_network_to_380(n):
|
|||||||
return n, trafo_map
|
return n, trafo_map
|
||||||
|
|
||||||
|
|
||||||
def _prepare_connection_costs_per_link(n, costs, renewable_param, length_factor_param):
|
def _prepare_connection_costs_per_link(n, costs, renewable_carriers, length_factor):
|
||||||
if n.links.empty:
|
if n.links.empty:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
connection_costs_per_link = {}
|
connection_costs_per_link = {}
|
||||||
|
|
||||||
for tech in renewable_param:
|
for tech in renewable_carriers:
|
||||||
if tech.startswith("offwind"):
|
if tech.startswith("offwind"):
|
||||||
connection_costs_per_link[tech] = (
|
connection_costs_per_link[tech] = (
|
||||||
n.links.length
|
n.links.length
|
||||||
* length_factor_param
|
* length_factor
|
||||||
* (
|
* (
|
||||||
n.links.underwater_fraction
|
n.links.underwater_fraction
|
||||||
* costs.at[tech + "-connection-submarine", "capital_cost"]
|
* costs.at[tech + "-connection-submarine", "capital_cost"]
|
||||||
@ -175,14 +175,14 @@ def _compute_connection_costs_to_bus(
|
|||||||
n,
|
n,
|
||||||
busmap,
|
busmap,
|
||||||
costs,
|
costs,
|
||||||
renewable_param,
|
renewable_carriers,
|
||||||
length_factor_param,
|
length_factor,
|
||||||
connection_costs_per_link=None,
|
connection_costs_per_link=None,
|
||||||
buses=None,
|
buses=None,
|
||||||
):
|
):
|
||||||
if connection_costs_per_link is None:
|
if connection_costs_per_link is None:
|
||||||
connection_costs_per_link = _prepare_connection_costs_per_link(
|
connection_costs_per_link = _prepare_connection_costs_per_link(
|
||||||
n, costs, renewable_param, length_factor_param
|
n, costs, renewable_carriers, length_factor
|
||||||
)
|
)
|
||||||
|
|
||||||
if buses is None:
|
if buses is None:
|
||||||
@ -276,10 +276,10 @@ def _aggregate_and_move_components(
|
|||||||
def simplify_links(
|
def simplify_links(
|
||||||
n,
|
n,
|
||||||
costs,
|
costs,
|
||||||
renewable_param,
|
renewables,
|
||||||
length_factor_param,
|
length_factor,
|
||||||
p_max_pu_param,
|
p_max_pu,
|
||||||
exclude_carriers_param,
|
exclude_carriers,
|
||||||
output,
|
output,
|
||||||
aggregation_strategies=dict(),
|
aggregation_strategies=dict(),
|
||||||
):
|
):
|
||||||
@ -333,7 +333,7 @@ def simplify_links(
|
|||||||
busmap = n.buses.index.to_series()
|
busmap = n.buses.index.to_series()
|
||||||
|
|
||||||
connection_costs_per_link = _prepare_connection_costs_per_link(
|
connection_costs_per_link = _prepare_connection_costs_per_link(
|
||||||
n, costs, renewable_param, length_factor_param
|
n, costs, renewables, length_factor
|
||||||
)
|
)
|
||||||
connection_costs_to_bus = pd.DataFrame(
|
connection_costs_to_bus = pd.DataFrame(
|
||||||
0.0, index=n.buses.index, columns=list(connection_costs_per_link)
|
0.0, index=n.buses.index, columns=list(connection_costs_per_link)
|
||||||
@ -355,8 +355,8 @@ def simplify_links(
|
|||||||
n,
|
n,
|
||||||
busmap,
|
busmap,
|
||||||
costs,
|
costs,
|
||||||
renewable_param,
|
renewables,
|
||||||
length_factor_param,
|
length_factor,
|
||||||
connection_costs_per_link,
|
connection_costs_per_link,
|
||||||
buses,
|
buses,
|
||||||
)
|
)
|
||||||
@ -378,8 +378,8 @@ def simplify_links(
|
|||||||
/ lengths.sum()
|
/ lengths.sum()
|
||||||
* n.links.loc[all_links, "underwater_fraction"]
|
* n.links.loc[all_links, "underwater_fraction"]
|
||||||
),
|
),
|
||||||
p_max_pu=p_max_pu_param,
|
p_max_pu=p_max_pu,
|
||||||
p_min_pu=-p_max_pu_param,
|
p_min_pu=-p_max_pu,
|
||||||
underground=False,
|
underground=False,
|
||||||
under_construction=False,
|
under_construction=False,
|
||||||
)
|
)
|
||||||
@ -407,7 +407,7 @@ def simplify_links(
|
|||||||
connection_costs_to_bus,
|
connection_costs_to_bus,
|
||||||
output,
|
output,
|
||||||
aggregation_strategies=aggregation_strategies,
|
aggregation_strategies=aggregation_strategies,
|
||||||
exclude_carriers=exclude_carriers_param,
|
exclude_carriers=exclude_carriers,
|
||||||
)
|
)
|
||||||
return n, busmap
|
return n, busmap
|
||||||
|
|
||||||
@ -415,34 +415,29 @@ def simplify_links(
|
|||||||
def remove_stubs(
|
def remove_stubs(
|
||||||
n,
|
n,
|
||||||
costs,
|
costs,
|
||||||
renewable_param,
|
renewable_carriers,
|
||||||
length_factor_param,
|
length_factor,
|
||||||
clustering_param,
|
simplify_network,
|
||||||
exclude_carriers_param,
|
|
||||||
output,
|
output,
|
||||||
aggregation_strategies=dict(),
|
aggregation_strategies=dict(),
|
||||||
):
|
):
|
||||||
logger.info("Removing stubs")
|
logger.info("Removing stubs")
|
||||||
|
|
||||||
across_borders = clustering_param["simplify_network"].get(
|
across_borders = simplify_network["remove_stubs_across_borders"]
|
||||||
"remove_stubs_across_borders", True
|
|
||||||
)
|
|
||||||
matching_attrs = [] if across_borders else ["country"]
|
matching_attrs = [] if across_borders else ["country"]
|
||||||
busmap = busmap_by_stubs(n, matching_attrs)
|
busmap = busmap_by_stubs(n, matching_attrs)
|
||||||
|
|
||||||
connection_costs_to_bus = _compute_connection_costs_to_bus(
|
connection_costs_to_bus = _compute_connection_costs_to_bus(
|
||||||
n, busmap, costs, renewable_param, length_factor_param
|
n, busmap, costs, renewable_carriers, length_factor
|
||||||
)
|
)
|
||||||
|
|
||||||
exclude_carriers = clustering_param["simplify_network"].get("exclude_carriers", [])
|
|
||||||
|
|
||||||
_aggregate_and_move_components(
|
_aggregate_and_move_components(
|
||||||
n,
|
n,
|
||||||
busmap,
|
busmap,
|
||||||
connection_costs_to_bus,
|
connection_costs_to_bus,
|
||||||
output,
|
output,
|
||||||
aggregation_strategies=aggregation_strategies,
|
aggregation_strategies=aggregation_strategies,
|
||||||
exclude_carriers=exclude_carriers,
|
exclude_carriers=simplify_network["exclude_carriers"],
|
||||||
)
|
)
|
||||||
|
|
||||||
return n, busmap
|
return n, busmap
|
||||||
@ -504,32 +499,23 @@ def aggregate_to_substations(n, aggregation_strategies=dict(), buses_i=None):
|
|||||||
def cluster(
|
def cluster(
|
||||||
n,
|
n,
|
||||||
n_clusters,
|
n_clusters,
|
||||||
focus_weights_param,
|
focus_weights,
|
||||||
renewable_param,
|
solver_name,
|
||||||
solver_name_param,
|
|
||||||
algorithm="hac",
|
algorithm="hac",
|
||||||
feature=None,
|
feature=None,
|
||||||
aggregation_strategies=dict(),
|
aggregation_strategies=dict(),
|
||||||
):
|
):
|
||||||
logger.info(f"Clustering to {n_clusters} buses")
|
logger.info(f"Clustering to {n_clusters} buses")
|
||||||
|
|
||||||
renewable_carriers = pd.Index(
|
|
||||||
[
|
|
||||||
tech
|
|
||||||
for tech in n.generators.carrier.unique()
|
|
||||||
if tech.split("-", 2)[0] in renewable_param
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
clustering = clustering_for_n_clusters(
|
clustering = clustering_for_n_clusters(
|
||||||
n,
|
n,
|
||||||
n_clusters,
|
n_clusters,
|
||||||
custom_busmap=False,
|
custom_busmap=False,
|
||||||
aggregation_strategies=aggregation_strategies,
|
aggregation_strategies=aggregation_strategies,
|
||||||
solver_name=solver_name_param,
|
solver_name=solver_name,
|
||||||
algorithm=algorithm,
|
algorithm=algorithm,
|
||||||
feature=feature,
|
feature=feature,
|
||||||
focus_weights=focus_weights_param,
|
focus_weights=focus_weights,
|
||||||
)
|
)
|
||||||
|
|
||||||
return clustering.network, clustering.busmap
|
return clustering.network, clustering.busmap
|
||||||
@ -542,77 +528,69 @@ if __name__ == "__main__":
|
|||||||
snakemake = mock_snakemake("simplify_network", simpl="")
|
snakemake = mock_snakemake("simplify_network", simpl="")
|
||||||
configure_logging(snakemake)
|
configure_logging(snakemake)
|
||||||
|
|
||||||
n = pypsa.Network(snakemake.input.network)
|
params = snakemake.params
|
||||||
|
solver_name = snakemake.config["solving"]["solver"]["name"]
|
||||||
|
|
||||||
|
n = pypsa.Network(snakemake.input.network)
|
||||||
|
Nyears = n.snapshot_weightings.objective.sum() / 8760
|
||||||
|
|
||||||
aggregation_strategies = snakemake.params["clustering"].get(
|
|
||||||
"aggregation_strategies", {}
|
|
||||||
)
|
|
||||||
# translate str entries of aggregation_strategies to pd.Series functions:
|
# translate str entries of aggregation_strategies to pd.Series functions:
|
||||||
aggregation_strategies = {
|
aggregation_strategies = {
|
||||||
p: {k: getattr(pd.Series, v) for k, v in aggregation_strategies[p].items()}
|
p: {
|
||||||
for p in aggregation_strategies.keys()
|
k: getattr(pd.Series, v)
|
||||||
|
for k, v in params.aggregation_strategies[p].items()
|
||||||
|
}
|
||||||
|
for p in params.aggregation_strategies.keys()
|
||||||
}
|
}
|
||||||
|
|
||||||
n, trafo_map = simplify_network_to_380(n)
|
n, trafo_map = simplify_network_to_380(n)
|
||||||
|
|
||||||
Nyears = n.snapshot_weightings.objective.sum() / 8760
|
|
||||||
|
|
||||||
technology_costs = load_costs(
|
technology_costs = load_costs(
|
||||||
snakemake.input.tech_costs,
|
snakemake.input.tech_costs,
|
||||||
snakemake.params["costs"],
|
params.costs,
|
||||||
snakemake.params["max_hours"],
|
params.max_hours,
|
||||||
Nyears,
|
Nyears,
|
||||||
)
|
)
|
||||||
|
|
||||||
n, simplify_links_map = simplify_links(
|
n, simplify_links_map = simplify_links(
|
||||||
n,
|
n,
|
||||||
technology_costs,
|
technology_costs,
|
||||||
snakemake.params["renewable"],
|
params.renewable_carriers,
|
||||||
snakemake.params["length_factor"],
|
params.length_factor,
|
||||||
snakemake.params["p_max_pu"],
|
params.p_max_pu,
|
||||||
snakemake.params["exclude_carriers"],
|
params.simplify_network["exclude_carriers"],
|
||||||
snakemake.output,
|
snakemake.output,
|
||||||
aggregation_strategies,
|
aggregation_strategies,
|
||||||
)
|
)
|
||||||
|
|
||||||
busmaps = [trafo_map, simplify_links_map]
|
busmaps = [trafo_map, simplify_links_map]
|
||||||
|
|
||||||
cluster_param = snakemake.params["clustering"]["simplify_network"]
|
if params.simplify_network["remove_stubs"]:
|
||||||
if cluster_param.get("remove_stubs", True):
|
|
||||||
n, stub_map = remove_stubs(
|
n, stub_map = remove_stubs(
|
||||||
n,
|
n,
|
||||||
technology_costs,
|
technology_costs,
|
||||||
snakemake.params["renewable"],
|
params.renewable_carriers,
|
||||||
snakemake.params["length_factor"],
|
params.length_factor,
|
||||||
snakemake.params["clustering"],
|
params.simplify_network,
|
||||||
snakemake.params["exclude_carriers"],
|
|
||||||
snakemake.output,
|
snakemake.output,
|
||||||
aggregation_strategies=aggregation_strategies,
|
aggregation_strategies=aggregation_strategies,
|
||||||
)
|
)
|
||||||
busmaps.append(stub_map)
|
busmaps.append(stub_map)
|
||||||
|
|
||||||
if cluster_param.get("to_substations", False):
|
if params.simplify_network["to_substations"]:
|
||||||
n, substation_map = aggregate_to_substations(n, aggregation_strategies)
|
n, substation_map = aggregate_to_substations(n, aggregation_strategies)
|
||||||
busmaps.append(substation_map)
|
busmaps.append(substation_map)
|
||||||
|
|
||||||
# treatment of outliers (nodes without a profile for considered carrier):
|
# treatment of outliers (nodes without a profile for considered carrier):
|
||||||
# all nodes that have no profile of the given carrier are being aggregated to closest neighbor
|
# all nodes that have no profile of the given carrier are being aggregated to closest neighbor
|
||||||
if (
|
if params.simplify_network["algorithm"] == "hac":
|
||||||
snakemake.config.get("clustering", {})
|
carriers = params.simplify_network["feature"].split("-")[0].split("+")
|
||||||
.get("cluster_network", {})
|
|
||||||
.get("algorithm", "hac")
|
|
||||||
== "hac"
|
|
||||||
or cluster_param.get("algorithm", "hac") == "hac"
|
|
||||||
):
|
|
||||||
carriers = (
|
|
||||||
cluster_param.get("feature", "solar+onwind-time").split("-")[0].split("+")
|
|
||||||
)
|
|
||||||
for carrier in carriers:
|
for carrier in carriers:
|
||||||
buses_i = list(
|
buses_i = list(
|
||||||
set(n.buses.index) - set(n.generators.query("carrier == @carrier").bus)
|
set(n.buses.index) - set(n.generators.query("carrier == @carrier").bus)
|
||||||
)
|
)
|
||||||
logger.info(
|
logger.info(
|
||||||
f"clustering preparaton (hac): aggregating {len(buses_i)} buses of type {carrier}."
|
f"clustering preparation (hac): aggregating {len(buses_i)} buses of type {carrier}."
|
||||||
)
|
)
|
||||||
n, busmap_hac = aggregate_to_substations(n, aggregation_strategies, buses_i)
|
n, busmap_hac = aggregate_to_substations(n, aggregation_strategies, buses_i)
|
||||||
busmaps.append(busmap_hac)
|
busmaps.append(busmap_hac)
|
||||||
@ -621,11 +599,10 @@ if __name__ == "__main__":
|
|||||||
n, cluster_map = cluster(
|
n, cluster_map = cluster(
|
||||||
n,
|
n,
|
||||||
int(snakemake.wildcards.simpl),
|
int(snakemake.wildcards.simpl),
|
||||||
snakemake.params["focus_weights"],
|
params.focus_weights,
|
||||||
snakemake.params["renewable"],
|
solver_name,
|
||||||
snakemake.params["solver_name"],
|
params.simplify_network["algorithm"],
|
||||||
cluster_param.get("algorithm", "hac"),
|
params.simplify_network["feature"],
|
||||||
cluster_param.get("feature", None),
|
|
||||||
aggregation_strategies,
|
aggregation_strategies,
|
||||||
)
|
)
|
||||||
busmaps.append(cluster_map)
|
busmaps.append(cluster_map)
|
||||||
|
Loading…
Reference in New Issue
Block a user