@@ -3683,19 +3683,7 @@ def get_grid_investments(n, costs, region, length_factor=1.0):
3683
3683
nep_dc = dc_links .query (
3684
3684
"index.str.startswith('DC') or index=='TYNDP2020_1' or index=='TYNDP2020_2' or index=='TYNDP2020_23'"
3685
3685
).index
3686
- dc_expansion = dc_links .p_nom_opt .apply (
3687
- lambda x : get_discretized_value (
3688
- x ,
3689
- post_discretization ["link_unit_size" ]["DC" ],
3690
- post_discretization ["link_threshold" ]["DC" ],
3691
- )
3692
- ) - dc_links .p_nom_min .apply (
3693
- lambda x : get_discretized_value (
3694
- x ,
3695
- post_discretization ["link_unit_size" ]["DC" ],
3696
- post_discretization ["link_threshold" ]["DC" ],
3697
- )
3698
- )
3686
+ dc_expansion = dc_links .p_nom_opt - dc_links .p_nom_min
3699
3687
3700
3688
dc_investments = dc_expansion * dc_links .overnight_cost * 1e-9
3701
3689
# International dc_projects are only accounted with half the costs
@@ -3705,19 +3693,9 @@ def get_grid_investments(n, costs, region, length_factor=1.0):
3705
3693
3706
3694
ac_lines = n .lines [(n .lines .bus0 + n .lines .bus1 ).str .contains (region )]
3707
3695
nep_ac = ac_lines .query ("build_year > 2000" ).index
3708
- ac_expansion = ac_lines .s_nom_opt .apply (
3709
- lambda x : get_discretized_value (
3710
- x ,
3711
- post_discretization ["line_unit_size" ],
3712
- post_discretization ["line_threshold" ],
3713
- )
3714
- ) - n .lines .loc [ac_lines .index ].s_nom_min .apply (
3715
- lambda x : get_discretized_value (
3716
- x ,
3717
- post_discretization ["line_unit_size" ],
3718
- post_discretization ["line_threshold" ],
3719
- )
3720
- )
3696
+ # Assuming the lines are already post-discretized
3697
+ ac_expansion = ac_lines .s_nom_opt - ac_lines .s_nom_min
3698
+
3721
3699
ac_investments = ac_expansion * ac_lines .overnight_cost * 1e-9
3722
3700
# International ac_projects are only accounted with half the costs
3723
3701
ac_investments [
@@ -4458,14 +4436,16 @@ def get_grid_capacity(n, region, year):
4458
4436
)
4459
4437
var ["Length Additions|Electricity|Transmission|DC" ] = (
4460
4438
dc_links .eval ("p_nom_opt - p_nom_min" )
4461
- .floordiv (1995 )
4439
+ .floordiv (995 )
4440
+ .div (2 )
4462
4441
.multiply (dc_links .length )
4463
4442
.sum ()
4464
4443
)
4465
4444
var ["Length Additions|Electricity|Transmission|DC|NEP" ] = (
4466
4445
dc_links .loc [nep_dc ]
4467
4446
.eval ("p_nom_opt - p_nom_min" )
4468
- .floordiv (1995 )
4447
+ .floordiv (995 )
4448
+ .div (2 )
4469
4449
.multiply (dc_links .length )
4470
4450
.sum ()
4471
4451
)
@@ -4483,14 +4463,18 @@ def get_grid_capacity(n, region, year):
4483
4463
)
4484
4464
var ["Length Additions|Electricity|Transmission|AC" ] = (
4485
4465
ac_lines .eval ("s_nom_opt - s_nom_min" )
4486
- .floordiv (1695 )
4466
+ .floordiv (845 )
4467
+ .div (2 )
4468
+ .div (3 ) # Steps of half a `line_unit`, 3 lines are a Trasse
4487
4469
.multiply (ac_lines .length )
4488
4470
.sum ()
4489
4471
)
4490
4472
var ["Length Additions|Electricity|Transmission|AC|NEP" ] = (
4491
4473
ac_lines .loc [nep_ac ]
4492
4474
.eval ("s_nom_opt - s_nom_min" )
4493
- .floordiv (1695 )
4475
+ .floordiv (845 )
4476
+ .div (2 )
4477
+ .div (3 )
4494
4478
.multiply (ac_lines .length )
4495
4479
.sum ()
4496
4480
)
@@ -4536,30 +4520,50 @@ def get_grid_capacity(n, region, year):
4536
4520
4537
4521
4538
4522
def hack_DC_projects (n , n_start , model_year , snakemake , costs ):
4523
+
4539
4524
logger .info (f"Hacking DC projects for year { model_year } " )
4540
- logger .warning (f"Assuming all indices of DC projects start with 'DC' or 'TYNDP'" )
4525
+
4526
+ logger .info (f"Assuming all indices of DC projects start with 'DC' or 'TYNDP'" )
4541
4527
tprojs = n .links .loc [
4542
4528
(n .links .index .str .startswith ("DC" ) | n .links .index .str .startswith ("TYNDP" ))
4543
4529
& ~ n .links .reversed
4544
4530
].index
4545
4531
4546
4532
future_projects = tprojs [n .links .loc [tprojs , "build_year" ] > model_year ]
4533
+
4547
4534
current_projects = tprojs [
4548
4535
(n .links .loc [tprojs , "build_year" ] > (model_year - 5 ))
4549
4536
& (n .links .loc [tprojs , "build_year" ] <= model_year )
4550
4537
]
4551
4538
past_projects = tprojs [n .links .loc [tprojs , "build_year" ] <= (model_year - 5 )]
4552
4539
4540
+ logger .info ("Post-Discretizing DC projects" )
4541
+ # The values in p_nom_opt may already be discretized, here we make sure that
4542
+ # the same logic is applied to p_nom and p_nom_min
4543
+ for attr in ["p_nom_opt" , "p_nom" , "p_nom_min" ]:
4544
+ n .links .loc [tprojs , attr ] = n .links .loc [tprojs , attr ].apply (
4545
+ lambda x : get_discretized_value (
4546
+ x ,
4547
+ snakemake .params .post_discretization ["link_unit_size" ]["DC" ],
4548
+ snakemake .params .post_discretization ["link_threshold" ]["DC" ],
4549
+ )
4550
+ )
4551
+ for proj in tprojs :
4552
+ if not isclose (n .links .loc [proj , "p_nom" ], n_start .links .loc [proj , "p_nom" ]):
4553
+ logger .warning (
4554
+ f"Changed p_nom of { proj } from { n_start .links .loc [proj , 'p_nom' ]} to { n .links .loc [proj , 'p_nom' ]} "
4555
+ )
4556
+
4553
4557
# Future projects should not have any capacity
4554
4558
assert isclose (n .links .loc [future_projects , "p_nom_opt" ], 0 ).all ()
4559
+
4555
4560
# Setting p_nom to 0 such that n.statistics does not compute negative expanded capex or capacity additions
4556
4561
# Setting p_nom_min to 0 for the grid_expansion calculation
4557
4562
# This is ONLY POSSIBLE IN POST-PROCESSING
4558
4563
# We pretend that the model expanded the grid endogenously
4559
4564
n .links .loc [future_projects , "p_nom" ] = 0
4560
4565
n .links .loc [future_projects , "p_nom_min" ] = 0
4561
4566
4562
- # Current projects should have their p_nom_opt bigger or equal to p_nom until the year 2030 (Startnetz that we force in)
4563
4567
if snakemake .params .NEP_year == 2021 :
4564
4568
logger .warning ("Switching DC projects to NEP23 costs post-optimization" )
4565
4569
n .links .loc [current_projects , "overnight_cost" ] = (
@@ -4574,11 +4578,11 @@ def hack_DC_projects(n, n_start, model_year, snakemake, costs):
4574
4578
)
4575
4579
+ costs [0 ].at ["HVDC inverter pair" , "investment" ] / 1e-9
4576
4580
)
4577
-
4581
+ # Current projects should have their p_nom_opt bigger or equal to p_nom until the year 2030 (Startnetz that we force in)
4578
4582
if model_year <= 2030 :
4579
4583
assert (
4580
- n .links .loc [current_projects , "p_nom" ]
4581
- < = n .links .loc [current_projects , "p_nom_opt " ]
4584
+ n .links .loc [current_projects , "p_nom_opt" ] + 0.1
4585
+ > = n .links .loc [current_projects , "p_nom " ]
4582
4586
).all ()
4583
4587
4584
4588
n .links .loc [current_projects , "p_nom" ] -= n_start .links .loc [
@@ -4607,9 +4611,25 @@ def hack_AC_projects(n, n_start, model_year, snakemake):
4607
4611
logger .info (f"Hacking AC projects for year { model_year } " )
4608
4612
4609
4613
# All transmission projects have build_year > 0, this is implicit in the query
4610
- ac_projs = n .lines .query ("@model_year - 5 < build_year <= @model_year" ).index
4614
+ ac_projs = n .lines .query ("build_year > 0" ).index
4615
+ current_projects = n .lines .query (
4616
+ "@model_year - 5 < build_year <= @model_year"
4617
+ ).index
4618
+
4619
+ logger .info ("Post-Discretizing AC projects" )
4620
+
4621
+ for attr in ["s_nom_opt" , "s_nom" , "s_nom_min" ]:
4622
+ # The values in s_nom_opt may already be discretized, here we make sure that
4623
+ # the same logic is applied to s_nom and s_nom_min
4624
+ n .lines .loc [ac_projs , attr ] = n .lines .loc [ac_projs , attr ].apply (
4625
+ lambda x : get_discretized_value (
4626
+ x ,
4627
+ snakemake .params .post_discretization ["line_unit_size" ],
4628
+ snakemake .params .post_discretization ["line_threshold" ],
4629
+ )
4630
+ )
4611
4631
4612
- s_nom_start = n_start .lines .loc [ac_projs , "s_nom" ].apply (
4632
+ s_nom_start = n_start .lines .loc [current_projects , "s_nom" ].apply (
4613
4633
lambda x : get_discretized_value (
4614
4634
x ,
4615
4635
snakemake .params .post_discretization ["line_unit_size" ],
@@ -4619,14 +4639,14 @@ def hack_AC_projects(n, n_start, model_year, snakemake):
4619
4639
4620
4640
if snakemake .params .NEP_year == 2021 :
4621
4641
logger .warning ("Switching AC projects to NEP23 costs post-optimization" )
4622
- n .lines .loc [ac_projs , "overnight_cost" ] *= 772 / 472
4642
+ n .lines .loc [current_projects , "overnight_cost" ] *= 772 / 472
4623
4643
4624
4644
# Eventhough the lines are available to the model from the start,
4625
4645
# we pretend that the lines were in expanded in this year
4626
4646
# s_nom_start is used, because the model may expand lines
4627
4647
# endogenously before that or after that
4628
- n .lines .loc [ac_projs , "s_nom" ] -= s_nom_start
4629
- n .lines .loc [ac_projs , "s_nom_min" ] -= s_nom_start
4648
+ n .lines .loc [current_projects , "s_nom" ] -= s_nom_start
4649
+ n .lines .loc [current_projects , "s_nom_min" ] -= s_nom_start
4630
4650
4631
4651
return n
4632
4652
0 commit comments