Skip to content

Commit

Permalink
Merge pull request #1221 from yerbol-akhmetov/add_low_voltage
Browse files Browse the repository at this point in the history
Add electricity distribution grid
  • Loading branch information
ekatef authored Dec 12, 2024
2 parents 2091d38 + 853b5be commit deb9198
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 0 deletions.
7 changes: 7 additions & 0 deletions config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,13 @@ sector:
efficiency_heat_biomass_to_elec: 0.9
efficiency_heat_gas_to_elec: 0.9

electricity_distribution_grid: true # adds low voltage buses and shifts AC loads, BEVs, heat pumps, and resistive heaters, micro CHPs to low voltage buses if technologies are present
solar_rooftop: true # adds distribution side customer rooftop PV (only work if electricity_distribution_grid: true)
home_battery: true # adds home batteries to low voltage buses ((only work if electricity_distribution_grid: true)
transmission_efficiency:
electricity distribution grid:
efficiency_static: 0.97 # efficiency of distribution grid (i.e. 3% loses)

dynamic_transport:
enable: false # If "True", then the BEV and FCEV shares are obtained depending on the "Co2L"-wildcard (e.g. "Co2L0.70: 0.10"). If "False", then the shares are obtained depending on the "demand" wildcard and "planning_horizons" wildcard as listed below (e.g. "DF_2050: 0.08")
land_transport_electric_share:
Expand Down
2 changes: 2 additions & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ E.g. if a new rule becomes available describe how to use it `make test` and in o

* Drop vrestil depenedncy `PR #1220 <https://github.com/pypsa-meets-earth/pypsa-earth/pull/1220>`__

* Add electricity distribution grid with solar rooftop and home battery technologies `PR #1221 <https://github.com/pypsa-meets-earth/pypsa-earth/pull/1221>`__

**Minor Changes and bug-fixing**

* The default configuration for `electricity:estimate_renewable_capacities:year` was updated from 2020 to 2023. `PR #1106 <https://github.com/pypsa-meets-earth/pypsa-earth/pull/1106>`__
Expand Down
138 changes: 138 additions & 0 deletions scripts/prepare_sector_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -2629,6 +2629,141 @@ def add_residential(n, costs):
)


def add_electricity_distribution_grid(n, costs):
logger.info("Adding electricity distribution network")
nodes = pop_layout.index

n.madd(
"Bus",
nodes + " low voltage",
location=nodes,
carrier="low voltage",
unit="MWh_el",
)

n.madd(
"Link",
nodes + " electricity distribution grid",
bus0=nodes,
bus1=nodes + " low voltage",
p_nom_extendable=True,
p_min_pu=-1,
carrier="electricity distribution grid",
efficiency=1,
lifetime=costs.at["electricity distribution grid", "lifetime"],
capital_cost=costs.at["electricity distribution grid", "fixed"],
)

# deduct distribution losses from electricity demand as these are included in total load
# https://nbviewer.org/github/Open-Power-System-Data/datapackage_timeseries/blob/2020-10-06/main.ipynb
if (
efficiency := options["transmission_efficiency"]
.get("electricity distribution grid", {})
.get("efficiency_static")
):
logger.info(
f"Deducting distribution losses from electricity demand: {np.around(100*(1-efficiency), decimals=2)}%"
)
n.loads_t.p_set.loc[:, n.loads.carrier == "AC"] *= efficiency

# move AC loads to low voltage buses
ac_loads = n.loads.index[n.loads.carrier == "AC"]
n.loads.loc[ac_loads, "bus"] += " low voltage"

# move industry, rail transport, agriculture and services electricity to low voltage
loads = n.loads.index[n.loads.carrier.str.contains("electricity")]
n.loads.loc[loads, "bus"] += " low voltage"

bevs = n.links.index[n.links.carrier == "BEV charger"]
n.links.loc[bevs, "bus0"] += " low voltage"

v2gs = n.links.index[n.links.carrier == "V2G"]
n.links.loc[v2gs, "bus1"] += " low voltage"

hps = n.links.index[n.links.carrier.str.contains("heat pump")]
n.links.loc[hps, "bus0"] += " low voltage"

rh = n.links.index[n.links.carrier.str.contains("resistive heater")]
n.links.loc[rh, "bus0"] += " low voltage"

mchp = n.links.index[n.links.carrier.str.contains("micro gas")]
n.links.loc[mchp, "bus1"] += " low voltage"

if options.get("solar_rooftop", False):
logger.info("Adding solar rooftop technology")
# set existing solar to cost of utility cost rather the 50-50 rooftop-utility
solar = n.generators.index[n.generators.carrier == "solar"]
n.generators.loc[solar, "capital_cost"] = costs.at["solar-utility", "fixed"]
pop_solar = pop_layout.total.rename(index=lambda x: x + " solar")

# add max solar rooftop potential assuming 0.1 kW/m2 and 20 m2/person,
# i.e. 2 kW/person (population data is in thousands of people) so we get MW
potential = 0.1 * 20 * pop_solar

n.madd(
"Generator",
solar,
suffix=" rooftop",
bus=n.generators.loc[solar, "bus"] + " low voltage",
carrier="solar rooftop",
p_nom_extendable=True,
p_nom_max=potential.loc[solar],
marginal_cost=n.generators.loc[solar, "marginal_cost"],
capital_cost=costs.at["solar-rooftop", "fixed"],
efficiency=n.generators.loc[solar, "efficiency"],
p_max_pu=n.generators_t.p_max_pu[solar],
lifetime=costs.at["solar-rooftop", "lifetime"],
)

if options.get("home_battery", False):
logger.info("Adding home battery technology")
n.add("Carrier", "home battery")

n.madd(
"Bus",
nodes + " home battery",
location=nodes,
carrier="home battery",
unit="MWh_el",
)

n.madd(
"Store",
nodes + " home battery",
bus=nodes + " home battery",
location=nodes,
e_cyclic=True,
e_nom_extendable=True,
carrier="home battery",
capital_cost=costs.at["home battery storage", "fixed"],
lifetime=costs.at["battery storage", "lifetime"],
)

n.madd(
"Link",
nodes + " home battery charger",
bus0=nodes + " low voltage",
bus1=nodes + " home battery",
carrier="home battery charger",
efficiency=costs.at["battery inverter", "efficiency"] ** 0.5,
capital_cost=costs.at["home battery inverter", "fixed"],
p_nom_extendable=True,
lifetime=costs.at["battery inverter", "lifetime"],
)

n.madd(
"Link",
nodes + " home battery discharger",
bus0=nodes + " home battery",
bus1=nodes + " low voltage",
carrier="home battery discharger",
efficiency=costs.at["battery inverter", "efficiency"] ** 0.5,
marginal_cost=options["marginal_cost_storage"],
p_nom_extendable=True,
lifetime=costs.at["battery inverter", "lifetime"],
)


# def add_co2limit(n, Nyears=1.0, limit=0.0):
# print("Adding CO2 budget limit as per unit of 1990 levels of", limit)

Expand Down Expand Up @@ -2950,6 +3085,9 @@ def remove_carrier_related_components(n, carriers_to_drop):
add_residential(n, costs)
add_services(n, costs)

if options.get("electricity_distribution_grid", False):
add_electricity_distribution_grid(n, costs)

sopts = snakemake.wildcards.sopts.split("-")

for o in sopts:
Expand Down

0 comments on commit deb9198

Please sign in to comment.