Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Endogenous transport #960

Draft
wants to merge 64 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
b70aa59
safe transport demand in unit kinetic energy
lisazeyen Mar 1, 2024
548a99f
restructure to links without temperature correction
lisazeyen Mar 1, 2024
bed2ef4
fix p_nom ICE
lisazeyen Mar 1, 2024
8efe43f
add temperature correction
lisazeyen Mar 4, 2024
4ffa702
temperature correction in extra function
lisazeyen Mar 4, 2024
04d3164
adjust p_nom + profile
lisazeyen Mar 4, 2024
4242a08
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 4, 2024
f2ba96e
add color for land transport demand
lisazeyen Mar 4, 2024
d4bdf48
add cyclic shift for EVs
lisazeyen Mar 4, 2024
c14f782
add lifetime to links
lisazeyen Mar 4, 2024
fa935be
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 4, 2024
66257e1
fix bug with cyclic shift
lisazeyen Mar 4, 2024
fb08d16
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 4, 2024
6712e48
fix spelling mistake
lisazeyen Mar 4, 2024
fe51fd7
adjust for temporal aggregation
lisazeyen Mar 4, 2024
ff0093c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 4, 2024
1b6e5dc
adjust for perfect foresight
lisazeyen Mar 4, 2024
3549e68
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 4, 2024
9c93917
add release notes
lisazeyen Mar 4, 2024
a805f5c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 4, 2024
74504a0
add lifetime to BEV
lisazeyen Mar 6, 2024
5bfc64a
Merge branch 'master' into land-transport-fix
lisazeyen Mar 6, 2024
08ea54a
first step adding endogenous transport
lisazeyen Mar 6, 2024
030e7d7
first step add existing
lisazeyen Mar 6, 2024
fe663a5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 6, 2024
e9a8899
add switch to config
lisazeyen Mar 6, 2024
d2f10f7
fix bug add loc
lisazeyen Mar 6, 2024
573cad1
correct naming
lisazeyen Mar 7, 2024
709fd98
add dummy generator for glpk
lisazeyen Mar 7, 2024
0e7a753
change temporal resolution of perfect test run
lisazeyen Mar 7, 2024
0146666
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 7, 2024
1ca0f32
add lifetime and make store extendable
lisazeyen Mar 11, 2024
3bb43e4
rename efficiencies + p_max_pu
lisazeyen Mar 14, 2024
2fabf96
only add build_year for later investment periods
lisazeyen Mar 14, 2024
34dd83c
some fixes
lisazeyen Mar 14, 2024
cf13dd1
Merge branch 'master' into endogenous-transport
lisazeyen Mar 14, 2024
1f76035
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 14, 2024
f762d6f
add constraints for BEV
lisazeyen Mar 14, 2024
de89048
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 14, 2024
69897f6
capital cost divide by efficiency
lisazeyen Mar 26, 2024
7fba3b0
add electrobiofuels
lisazeyen Mar 27, 2024
a913f3b
only make summary if n solved
lisazeyen Mar 30, 2024
3e20c4a
increase resources
lisazeyen Mar 30, 2024
c70baaa
increase price load shedding
lisazeyen Mar 30, 2024
f770875
quick fix for infinity values in energy totals
lisazeyen Mar 30, 2024
6b8caeb
Merge branch 'endogenous-transport' of https://github.com/PyPSA/pypsa…
lisazeyen Mar 30, 2024
d5bb33b
add build year for existing cars
lisazeyen Apr 2, 2024
adc805e
add try except when read in
lisazeyen Apr 2, 2024
6544181
test changes solver settings
lisazeyen Apr 2, 2024
ca17072
Merge branch 'endogenous-transport' of github.com:PyPSA/pypsa-eur int…
lisazeyen Apr 2, 2024
f90be0b
fix typo
lisazeyen Apr 5, 2024
8934682
adjust co2 neutral constraint
lisazeyen Apr 5, 2024
c363988
add cluster settings
lisazeyen Apr 5, 2024
e8e6b73
add split light heavy vehicles
lisazeyen Apr 5, 2024
9429b97
intermediate fix co2 budget
lisazeyen Apr 5, 2024
027a9a5
split between light heavy demand
lisazeyen Apr 5, 2024
5b3746d
fill missing vehicle numbers
lisazeyen Apr 5, 2024
952200f
clean up
lisazeyen Apr 5, 2024
71114d8
correct units
lisazeyen Apr 5, 2024
1a9ce6a
correct units + efficiencies to 100 km
lisazeyen Apr 8, 2024
cf92641
correct unit from kWh/km -> MWh/100 km
lisazeyen Apr 8, 2024
2158f62
fix bug assigning existing
lisazeyen Apr 9, 2024
6fa0e0c
add rule to extract car ages per ct
lisazeyen Apr 9, 2024
da2acf1
add car fleet ages
lisazeyen Apr 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions config/config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,8 @@ sector:
2050: 1.0
district_heating_loss: 0.15
cluster_heat_buses: true
endogenous_transport: true
electrobiofuels: true
bev_dsm_restriction_value: 0.75
bev_dsm_restriction_time: 7
transport_heating_deadband_upper: 20.
Expand Down Expand Up @@ -773,21 +775,22 @@ solving:
threads: 4
method: 2 # barrier
crossover: 0
BarConvTol: 1.e-6
BarConvTol: 1.e-5
FeasibilityTol: 1.e-4
OptimalityTol: 1.e-4
Seed: 123
AggFill: 0
PreDual: 0
GURO_PAR_BARDENSETHRESH: 200
gurobi-numeric-focus:
name: gurobi
NumericFocus: 3 # Favour numeric stability over speed
# NumericFocus: 3 # Favour numeric stability over speed
method: 2 # barrier
crossover: 0 # do not use crossover
BarHomogeneous: 1 # Use homogeneous barrier if standard does not converge
BarConvTol: 1.e-5
FeasibilityTol: 1.e-4
OptimalityTol: 1.e-4
ObjScale: -0.5
# ObjScale: -0.5
threads: 8
Seed: 123
gurobi-fallback: # Use gurobi defaults
Expand Down Expand Up @@ -913,6 +916,7 @@ plotting:
gas pipeline: '#ebbca0'
gas pipeline new: '#a87c62'
# oil
electrobiofuels: '#a1b5ae'
oil: '#c9c9c9'
imported oil: '#a3a3a3'
oil boiler: '#adadad'
Expand Down Expand Up @@ -980,6 +984,7 @@ plotting:
BEV charger: '#baf238'
V2G: '#e5ffa8'
land transport EV: '#baf238'
land transport demand: '#38baf2'
Li ion: '#baf238'
# hot water storage
water tanks: '#e69487'
Expand Down
2 changes: 1 addition & 1 deletion config/test/config.perfect.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ scenario:
clusters:
- 5
sector_opts:
- 8760h-T-H-B-I-A-dist1
- 24h-T-H-B-I-A-dist1
planning_horizons:
- 2030
- 2040
Expand Down
6 changes: 6 additions & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ Release Notes
Upcoming Release
================


* fix bug in land transport for temperature correction of ICEs and fuel cell cars

* restructure land transport, demand is now attached to one single node, the
different car types (ICE, EV, fuel cell) are modelled as links

* Upgrade to Snakemake v8.5+. This version is the new minimum version required.
To upgrade an existing environment, run ``conda install -c bioconda
snakemake-minimal">=8.5"`` and ``pip install snakemake-storage-plugin-http``
Expand Down
4 changes: 2 additions & 2 deletions rules/build_electricity.smk
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ rule build_renewable_profiles:
benchmarks("build_renewable_profiles_{technology}")
threads: config["atlite"].get("nprocesses", 4)
resources:
mem_mb=config["atlite"].get("nprocesses", 4) * 5000,
mem_mb=config["atlite"].get("nprocesses", 4) * 10000,
wildcard_constraints:
technology="(?!hydro).*", # Any technology other than hydro
conda:
Expand Down Expand Up @@ -481,7 +481,7 @@ rule simplify_network:
benchmarks("simplify_network/elec_s{simpl}")
threads: 1
resources:
mem_mb=12000,
mem_mb=30000,
conda:
"../envs/environment.yaml"
script:
Expand Down
26 changes: 26 additions & 0 deletions rules/build_sector.smk
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,31 @@ rule build_biomass_potentials:
"../scripts/build_biomass_potentials.py"


rule build_existing_car_ages:
input:
ACEA_report=storage(
"https://www.acea.auto/files/ACEA-Report-Vehicles-on-European-roads-.pdf",
keep_local=True,
),
output:
car_ages=resources(
"car_ages.csv"
),
truck_ages=resources(
"truck_ages.csv"
),
threads: 1
resources:
mem_mb=1000,
log:
logs("build_existing_car_ages.log"),
benchmark:
benchmarks("build_existing_car_ages")
conda:
"../envs/environment.yaml"
script:
"../scripts/build_existing_car_ages.py"

rule build_biomass_transport_costs:
input:
transport_cost_data=storage(
Expand Down Expand Up @@ -735,6 +760,7 @@ rule build_transport_demand:
transport_data=resources("transport_data.csv"),
traffic_data_KFZ="data/bundle-sector/emobility/KFZ__count",
traffic_data_Pkw="data/bundle-sector/emobility/Pkw__count",
traffic_data_Lkw="data/bundle-sector/emobility/Lkw__count",
temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"),
output:
transport_demand=resources("transport_demand_s{simpl}_{clusters}.csv"),
Expand Down
2 changes: 2 additions & 0 deletions rules/solve_myopic.smk
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ rule add_existing_baseyear:
existing_capacities=config_provider("existing_capacities"),
costs=config_provider("costs"),
input:
car_ages=resources("car_ages.csv"),
truck_ages=resources("truck_ages.csv"),
network=RESULTS
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
powerplants=resources("powerplants.csv"),
Expand Down
5 changes: 4 additions & 1 deletion rules/solve_perfect.smk
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ rule add_existing_baseyear:
existing_capacities=config_provider("existing_capacities"),
costs=config_provider("costs"),
input:
car_ages=resources("car_ages.csv"),
truck_ages=resources("truck_ages.csv"),
network=RESULTS
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
powerplants=resources("powerplants.csv"),
Expand Down Expand Up @@ -113,7 +115,8 @@ rule solve_sector_network_perfect:
+ "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc",
threads: solver_threads
resources:
mem_mb=config_provider("solving", "mem"),
mem_mb=config_provider("solving", "mem_mb"),
runtime=config_provider("solving", "runtime", default="24h"),
shadow:
"shallow"
log:
Expand Down
11 changes: 10 additions & 1 deletion scripts/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,9 +570,18 @@ def update_config_from_wildcards(config, w, inplace=True):

if "CCL" in opts:
config["solving"]["constraints"]["CCL"] = True


co2_budget = {
"1p5": 34.2 , # 25.7 # Budget in Gt CO2 for 1.5 for Europe, global 420 Gt, assuming per capita share
"1p6": 43.259666 , # 35 # Budget in Gt CO2 for 1.6 for Europe, global 580 Gt
"1p7": 51.4, # 45 # Budget in Gt CO2 for 1.7 for Europe, global 800 Gt
"2p0": 69.778 , # 73.9 # Budget in Gt CO2 for 2 for Europe, global 1170 Gt
}
eq_value = get_opt(opts, r"^EQ+\d*\.?\d+(c|)")
for o in opts:
m = re.match(r"^\d+p\d$", o, re.IGNORECASE)
if m is not None:
config["co2_budget"]= co2_budget[m.group(0)]
if eq_value is not None:
config["solving"]["constraints"]["EQ"] = eq_value
elif "EQ" in o:
Expand Down
77 changes: 73 additions & 4 deletions scripts/add_existing_baseyear.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@
update_config_from_wildcards,
)
from add_electricity import sanitize_carriers
from prepare_sector_network import cluster_heat_buses, define_spatial, prepare_costs
from prepare_sector_network import (
cluster_heat_buses,
define_spatial,
get,
prepare_costs,
)

logger = logging.getLogger(__name__)
cc = coco.CountryConverter()
Expand Down Expand Up @@ -55,6 +60,67 @@ def add_build_year_to_new_assets(n, baseyear):
c.pnl[attr] = c.pnl[attr].rename(columns=rename)


def add_existing_land_transport(baseyear, options):
# today ICE capacity assuming all internal combustion
share = get(options["land_transport_ice_share"], baseyear)
ice_i = n.links[n.links.carrier == "land transport oil"].index
p_nom = n.links.loc[ice_i, "p_nom"] / share
efficiency = n.links_t.efficiency[ice_i]
p_max_pu = n.links_t.p_max_pu[ice_i]

car_ages = pd.read_csv(snakemake.input.car_ages, index_col=[0]).iloc[:,:-2]
car_ages.columns = car_ages.columns.astype(int)
# group data in 5 years interval
interval = 5
# mapping forward (mapping backward would be year//5*5)
group_mapping = {year: year//interval*interval+4 for year in car_ages.columns}

grouped = car_ages.T.groupby(group_mapping).sum().T

pop_layout = pd.read_csv(snakemake.input.clustered_pop_layout, index_col=0)

grouped = (grouped.reindex(pop_layout.ct)
.fillna(grouped.mean()).set_index(pop_layout.index))

for build_year in grouped.columns:
df = n.links.loc[ice_i]
df = df[df.lifetime + build_year > baseyear]
if df.empty:
continue
share = grouped[build_year]
df["build_year"] = build_year
df["p_nom"] = p_nom.mul(share.values)
df["p_nom_extendable"] = False
df.rename(
index=lambda x: x.replace(f"-{baseyear}", f"-{build_year}"), inplace=True
)
profile = p_max_pu.rename(
columns=lambda x: x.replace(f"-{baseyear}", f"-{build_year}"))
eff = efficiency.rename(
columns=lambda x: x.replace(f"-{baseyear}", f"-{build_year}"))

n.madd(
"Link",
df.index,
bus0=df.bus0,
bus1=df.bus1,
bus2=df.bus2,
carrier=df.carrier,
efficiency=eff,
capital_cost=df.capital_cost,
marginal_cost=df.marginal_cost,
efficiency2=df.efficiency2,
p_nom_extendable=False,
p_nom=df.p_nom,
p_min_pu=profile,
p_max_pu=profile,
build_year=df.build_year,
lifetime=df.lifetime,
)

n.links.loc[ice_i, "p_nom"] = 0


def add_existing_renewables(df_agg):
"""
Append existing renewables to the df_agg pd.DataFrame with the conventional
Expand Down Expand Up @@ -553,13 +619,13 @@ def add_heating_capacities_installed_before_baseyear(

snakemake = mock_snakemake(
"add_existing_baseyear",
# configfiles="config/test/config.myopic.yaml",
# configfiles="config/config.myopic.yaml",
simpl="",
clusters="37",
ll="v1.0",
opts="",
sector_opts="8760-T-H-B-I-A-dist1",
planning_horizons=2020,
sector_opts="49sn-T-H-B-I-A-dist1",
planning_horizons=2025,
)

configure_logging(snakemake)
Expand Down Expand Up @@ -619,6 +685,9 @@ def add_heating_capacities_installed_before_baseyear(
if options.get("cluster_heat_buses", False):
cluster_heat_buses(n)

if options["endogenous_transport"]:
add_existing_land_transport(baseyear, options)

n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))

sanitize_carriers(n, snakemake.config)
Expand Down
Loading