pypsa-eur icon indicating copy to clipboard operation
pypsa-eur copied to clipboard

Correctly enforce existing capacities if build year >= base year

Open lindnemi opened this issue 11 months ago • 1 comments

Describe the Bug

The baseyear in pypsa-ariadne is 2020. We want to enforce capacities that have been build in 2020 or afterwards.

At the moment this is done in add_existing_baseyear.py, just as if the build year was before 2020, by setting p_nom. However, after the optimisation, for some carriers, the optimal capacity is smaller than p_nom. This means that the already existing assets are not used by the model. Why?

  1. A constraint for exisiting capacities is added at https://github.com/PyPSA/pypsa-eur/blob/0a0a35e4a4d8f891be81a05648145a9d14c86dae/scripts/add_existing_baseyear.py#L248-L250

However, for renewable carriers p_nom_min gets reset to 0 in solve_network.py. I would consider this a bug, since that way existing capacities get disregarded. The responsible lines are https://github.com/PyPSA/pypsa-eur/blob/0a0a35e4a4d8f891be81a05648145a9d14c86dae/scripts/solve_network.py#L100-L101 and https://github.com/PyPSA/pypsa-eur/blob/0a0a35e4a4d8f891be81a05648145a9d14c86dae/scripts/solve_network.py#L126-L127

Apparently the behaviour was first introduced in https://github.com/PyPSA/pypsa-eur/pull/728 to limit the land use of renewables.

  1. When i revert this PR the p_nom_lims are correctly carried forward. However, then p_nom_min is still smaller than the p_nom for most carriers, which i understand to be indicative of the existing capacities. And thus, once again p_nom_opt is lower than it should be.

  2. For offwind-ac the situation is actually the opposite and p_nom is smaller than p_nom_min. This might be related to the issue that existing wind capacities get added without a suffix and are thus overlooked

How to Fix

Basically two approaches could work:

  1. set p_nom_min = p_nom

  2. differentiate between enforced assets and optimized assets. then carrier-year would exist twice if build year >= base year.

(and also assign all already existing offwind capacities to offwind-ac and offwind-dc)

I am a bit reluctant to simply go for 1. since it might break other peoples code (??)

lindnemi avatar Mar 13 '24 15:03 lindnemi

With #967 in place and grouping years [2015,2021] all existing capacities seem to be assigned correctly and do not get overwritten by the optimization. However, for the extendable solar-2020 generator, the p_nom is still very high. I thought it would be 0 if all existing capcities are added as solar-2015 and solar-2021. We might get some double counting in n.statistics.installed_capacity because of that. @p-glaum

lindnemi avatar Mar 14 '24 15:03 lindnemi

possibly related to #1016

fneum avatar May 23 '24 19:05 fneum

However, for the extendable solar-2020 generator, the p_nom is still very high. I thought it would be 0 if all existing capcities are added as solar-2015 and solar-2021.

This is indeed the same issue as in #1016. Renewable capacities can be added in two ways:

  1. In rule add_electricity in case the following configuration is used:
electricity:
  estimate_renewable_capacities:
    enable: true
  1. In rule add_existing_baseyear for any model in myopic mode.

Option 1 should be used only for electricity-only models and overnight sector-coupled models. Option 2 is used in any case for myopic pathway sector-coupled models. This is quite error-prone, and we should change it soon. Will be tracked via #1016.

So, the problem occurs if you do options 1 and 2 simultaneously, in which case all existing capacities are added to p_nom of the first planning horizon. This looks worse than it is, since p_nom only affects the model if the components are not extendable, which they are not in this case.

With option 1 disabled one gets in "results/test-sector-myopic/prenetworks-brownfield/elec_s_5_lvopt___2020.nc":

n.generators.query("carrier == 'solar'").groupby("build_year")[["p_nom_min", "p_nom"]].sum()
build_year p_nom_min p_nom
2005 0 385
2010 0 2629
2015 0 1621.6
2020 1009.8 0

With option 1 enabled, one gets:

build_year p_nom_min p_nom
2005 0 385
2010 0 2629
2015 0 1621.6
2020 1009.8 5646.4

which is wrong / double-counting -- yet without effect on the optimisation

fneum avatar May 24 '24 07:05 fneum