From 3e93c14dd4cac4cdba266315b29ed8ef531885b8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:32:22 +0000 Subject: [PATCH] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- config/config.default.yaml | 6 +- scripts/add_electricity.py | 2 +- scripts/prepare_sector_network.py | 11 +-- scripts/solve_network.py | 116 ++++++++++++++++++++---------- 4 files changed, 90 insertions(+), 45 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index c00ca0b3..11890db0 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -240,13 +240,13 @@ renewable: orientation: slope: 35. azimuth: 180. - tracking: horizontal + tracking: horizontal capacity_per_sqkm: 4.43 # 15% higher land usage acc. to NREL corine: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 26, 31, 32] luisa: false # [1111, 1121, 1122, 1123, 1130, 1210, 1221, 1222, 1230, 1241, 1242, 1310, 1320, 1330, 1410, 1421, 1422, 2110, 2120, 2130, 2210, 2220, 2230, 2310, 2410, 2420, 3210, 3320, 3330] natura: true excluder_resolution: 100 - clip_p_max_pu: 1.e-2 + clip_p_max_pu: 1.e-2 hydro: cutout: europe-2013-era5 carriers: [ror, PHS, hydro] @@ -589,7 +589,7 @@ sector: biogas_upgrading_cc: false conventional_generation: OCGT: gas - solar_utility_singla_axis_tracking : true + solar_utility_singla_axis_tracking: true biomass_to_liquid: false biosng: false limit_max_growth: diff --git a/scripts/add_electricity.py b/scripts/add_electricity.py index 31ed1048..374e40aa 100755 --- a/scripts/add_electricity.py +++ b/scripts/add_electricity.py @@ -235,7 +235,7 @@ def load_costs(tech_costs, config, max_hours, Nyears=1.0): + (1 - config["rooftop_share"]) * costs.at["solar-utility", "capital_cost"] ) - costs= costs.rename({'solar-utility single-axis tracking':'solar-hsat'}) + costs = costs.rename({"solar-utility single-axis tracking": "solar-hsat"}) def costs_for_storage(store, link1, link2=None, max_hours=1.0): capital_cost = link1["capital_cost"] + max_hours * store["capital_cost"] diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 20aa8959..f5eecf3d 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -3319,13 +3319,14 @@ def remove_h2_network(n): if "EU H2 Store" in n.stores.index: n.stores.drop("EU H2 Store", inplace=True) + def remove_solar_tracking(n): - for tech in ['solar-hsat']: - print('removing '+tech) - n.mremove("Generator" , n.generators.index[n.generators.carrier==tech]) + for tech in ["solar-hsat"]: + print("removing " + tech) + n.mremove("Generator", n.generators.index[n.generators.carrier == tech]) + - def limit_individual_line_extension(n, maxext): logger.info(f"Limiting new HVAC and HVDC extensions to {maxext} MW") n.lines["s_nom_max"] = n.lines["s_nom"] + maxext @@ -3703,7 +3704,7 @@ if __name__ == "__main__": insert_electricity_distribution_grid(n, costs) if not options["solar_utility_singla_axis_tracking"]: - remove_solar_tracking(n) + remove_solar_tracking(n) maybe_adjust_costs_and_potentials(n, snakemake.params["adjustments"]) diff --git a/scripts/solve_network.py b/scripts/solve_network.py index 8048af61..08521273 100644 --- a/scripts/solve_network.py +++ b/scripts/solve_network.py @@ -31,6 +31,7 @@ import logging import os import re import sys +from functools import reduce import numpy as np import pandas as pd @@ -43,7 +44,6 @@ from _helpers import ( set_scenario_config, update_config_from_wildcards, ) -from functools import reduce from pypsa.descriptors import get_activity_mask from pypsa.descriptors import get_switchable_as_dense as get_as_dense @@ -124,7 +124,14 @@ def add_land_use_constraint_perfect(n): def _add_land_use_constraint(n): # warning: this will miss existing offwind which is not classed AC-DC and has carrier 'offwind' - for carrier in ["solar", "solar rooftop", "solar-hsat", "onwind", "offwind-ac", "offwind-dc"]: + for carrier in [ + "solar", + "solar rooftop", + "solar-hsat", + "onwind", + "offwind-ac", + "offwind-dc", + ]: extendable_i = (n.generators.carrier == carrier) & n.generators.p_nom_extendable n.generators.loc[extendable_i, "p_nom_min"] = 0 @@ -159,7 +166,14 @@ def _add_land_use_constraint_m(n, planning_horizons, config): grouping_years = config["existing_capacities"]["grouping_years_power"] current_horizon = snakemake.wildcards.planning_horizons - for carrier in ["solar", "solar rooftop", "solar-hsat", "onwind", "offwind-ac", "offwind-dc"]: + for carrier in [ + "solar", + "solar rooftop", + "solar-hsat", + "onwind", + "offwind-ac", + "offwind-dc", + ]: extendable_i = (n.generators.carrier == carrier) & n.generators.p_nom_extendable n.generators.loc[extendable_i, "p_nom_min"] = 0 @@ -199,7 +213,8 @@ def _add_land_use_constraint_m(n, planning_horizons, config): n.generators.p_nom_max.clip(lower=0, inplace=True) -def add_solar_potential_constraints(n, config): + +def add_solar_potential_constraints(n, config): """ Add constraint to make sure the sum capacity of all solar technologies (fixed, tracking, ets. ) is below the region potential. Example: @@ -209,51 +224,81 @@ def add_solar_potential_constraints(n, config): The constraint ensures that: solar_p_nom + solar_hsat_p_nom * 1.13 <= 10 GW """ - land_use_factors= { - 'solar-hsat' : config['renewable']['solar']['capacity_per_sqkm']/config['renewable']['solar-hsat']['capacity_per_sqkm'] , - } + land_use_factors = { + "solar-hsat": config["renewable"]["solar"]["capacity_per_sqkm"] + / config["renewable"]["solar-hsat"]["capacity_per_sqkm"], + } gen_index = n.generators[n.generators.p_nom_extendable].index - filters = [("solar", True), ("thermal", False), ("rooftop", False)] ## filter all utility solar generation except solar thermal - solar = reduce(lambda gen_index, f: gen_index[gen_index.str.contains(f[0]) == f[1]], filters, gen_index) - solar_today = n.generators[(n.generators.carrier=='solar') & (n.generators.p_nom_extendable)].index - solar_hsat = n.generators[(n.generators.carrier=='solar-hsat') ].index - land_use = pd.DataFrame(1, index=solar, columns=['land_use_factor']) + filters = [ + ("solar", True), + ("thermal", False), + ("rooftop", False), + ] ## filter all utility solar generation except solar thermal + solar = reduce( + lambda gen_index, f: gen_index[gen_index.str.contains(f[0]) == f[1]], + filters, + gen_index, + ) + solar_today = n.generators[ + (n.generators.carrier == "solar") & (n.generators.p_nom_extendable) + ].index + solar_hsat = n.generators[(n.generators.carrier == "solar-hsat")].index + land_use = pd.DataFrame(1, index=solar, columns=["land_use_factor"]) for key in land_use_factors.keys(): - land_use = land_use.apply(lambda x: (x*land_use_factors[key]) if key in x.name else x, axis=1) + land_use = land_use.apply( + lambda x: (x * land_use_factors[key]) if key in x.name else x, axis=1 + ) rename = {"Generator-ext": "Generator"} if "m" in snakemake.wildcards.clusters: - location = ( - pd.Series([' '.join(i.split(' ')[:2]) for i in n.generators.index], index=n.generators.index) + location = pd.Series( + [" ".join(i.split(" ")[:2]) for i in n.generators.index], + index=n.generators.index, ) - ggrouper= pd.Series(n.generators.loc[solar].index.rename('bus').map(location), index=n.generators.loc[solar].index,).to_xarray() - rhs = (n.generators.loc[solar_today,"p_nom_max"] - .groupby(n.generators.loc[solar_today].index.rename('bus').map(location)).sum() - - n.generators.loc[solar_hsat,"p_nom_opt"] - .groupby(n.generators.loc[solar_hsat].index.rename('bus').map(location)).sum() * land_use_factors['solar-hsat'] ).clip(lower=0) + ggrouper = pd.Series( + n.generators.loc[solar].index.rename("bus").map(location), + index=n.generators.loc[solar].index, + ).to_xarray() + rhs = ( + n.generators.loc[solar_today, "p_nom_max"] + .groupby(n.generators.loc[solar_today].index.rename("bus").map(location)) + .sum() + - n.generators.loc[solar_hsat, "p_nom_opt"] + .groupby(n.generators.loc[solar_hsat].index.rename("bus").map(location)) + .sum() + * land_use_factors["solar-hsat"] + ).clip(lower=0) - else : + else: location = ( n.buses.location if "location" in n.buses.columns else pd.Series(n.buses.index, index=n.buses.index) ) - ggrouper= (n.generators.loc[solar].bus) - rhs = (n.generators.loc[solar_today,"p_nom_max"] - .groupby(n.generators.loc[solar_today].bus.map(location)).sum() - - n.generators.loc[solar_hsat,"p_nom_opt"] - .groupby(n.generators.loc[solar_hsat].bus.map(location)).sum() * land_use_factors['solar-hsat'] ).clip(lower=0) + ggrouper = n.generators.loc[solar].bus + rhs = ( + n.generators.loc[solar_today, "p_nom_max"] + .groupby(n.generators.loc[solar_today].bus.map(location)) + .sum() + - n.generators.loc[solar_hsat, "p_nom_opt"] + .groupby(n.generators.loc[solar_hsat].bus.map(location)) + .sum() + * land_use_factors["solar-hsat"] + ).clip(lower=0) lhs = ( - (n.model["Generator-p_nom"].rename(rename).loc[solar] - *land_use.squeeze().values) - .groupby(ggrouper) - .sum() - ) + ( + n.model["Generator-p_nom"].rename(rename).loc[solar] + * land_use.squeeze().values + ) + .groupby(ggrouper) + .sum() + ) + + print("adding solar rooftop constraints...") + n.model.add_constraints(lhs <= rhs, name="solar_potential") - print('adding solar rooftop constraints...') - n.model.add_constraints(lhs <= rhs, name="solar_potential") def add_co2_sequestration_limit(n, limit=200): """ @@ -918,9 +963,8 @@ def extra_functionality(n, snapshots): if EQ_o := constraints["EQ"]: add_EQ_constraints(n, EQ_o.replace("EQ", "")) - - if config["sector"]['solar_utility_singla_axis_tracking']: - add_solar_potential_constraints(n, config) + if config["sector"]["solar_utility_singla_axis_tracking"]: + add_solar_potential_constraints(n, config) add_battery_constraints(n) add_lossy_bidirectional_link_constraints(n)