Breakthrough-Energy / REISE.jl

Renewable Energy Integration Simulation Engine
https://breakthrough-energy.github.io/docs/
MIT License
30 stars 22 forks source link

PCM results for europe grid are inconsistent with constraints #197

Open jenhagg opened 1 year ago

jenhagg commented 1 year ago

:beetle:

Bug summary

When we run a PCM for europe_tub, the results are wrong, even though the problem is feasible. In particular, the power generated for renewables (resources with a time series profile) exceeds the available amount (as specified by the profile).

Code for reproduction

Run a pcm with grid model europe_tub and reduction=128 (not necessarily unique to the 128 network, but that's what we've been testing with). This can be observed with the following code. NOTE: this requires changing the blob container used by powersimdata to one with the europe test results.

import matplotlib.pyplot as plt
from powersimdata import Scenario

s = Scenario(70)
pg = s.get_pg()

def plot_gentype_util(gentype):
    profile = s.get_gentype_profile(gentype)
    pg_sum = pg[profile.columns].sum(axis=1)
    gen_sum = profile.sum(axis=1)
    (pg_sum / gen_sum).plot()
    plt.title(gentype)
    plt.show()

plot_gentype_util("onwind")
plot_gentype_util("offwind-ac")
plot_gentype_util("offwind-dc")

Actual outcome

The ratio of pg / profile is greater than one (up to 5-10).

Expected outcome

We should have pg < profile for each hour.

Environment

This was done using https://github.com/Breakthrough-Energy/plug

Additional context

The problem is likely due to constructing profile_resources_idx in such a way that the range of indices for each resource is over the full range of plant ids. We read in case.genid from grid.plant.index, and map for example profile_resources_idx["offwind-ac"] to a list which has the right number of indices, but values not aligned with the profile.

They should be ordered based on the index of those plants in the wind.csv profile columns, rather than grid.plant.index. These indices are used in loop.jl and model.jl to set constraints.

Additionally, in loop.jl we are using a range of 1:length(sets.profile_resources_idx[g]) instead of the values themselves, which means we always read from the beginning of the profile, instead of a selection of columns corresponding to the given resource.

NOTE: this is only an issue when a profile has multiple types, e.g. wind -> [onwind, offwind-ac, offwind-dc]. This is also a recent issue, not affecting historical scenarios.