pypsa-meets-earth / pypsa-earth

PyPSA-Earth: A flexible Python-based open optimisation model to study energy system futures around the world.
https://pypsa-earth.readthedocs.io/en/latest/
218 stars 173 forks source link

Alternative clustering leads to wrong bus-shape assignment #700

Open cpschau opened 1 year ago

cpschau commented 1 year ago

Checklist

Describe the Bug

weird_gadm_shape_elec_s png

weird_gadm_shape png

if 'elec_s_' in os.path.basename(output[0]) and which == "regions_onshore": gadm_shapes = gpd.read_file(inputs.gadm_shapes) regions["geometry"] = regions.apply(lambda r: gadm_shapes.loc[gadm_shapes.GADM_ID == busmap.loc[r.name][:-3], "geometry"].item(), axis=1 )

weird_gadm_shape_onshore_shapes

ekatef commented 1 year ago

@cschau-ieg, thanks a lot for the detailed report. Very nice plots!

Absolutely agree that if something gets wrong during network simplification, it should be fixed there. A couple of clarification questions:

1) Could you please explain in a bit more details why buses assignment in the first picture is wrong? Is each bus in fact outside of the corresponding shape?

2) Agree that regarding merging four GADM regions doesn't look right, but do not quite understand in which way it is connected with the assignment. Could you please explain in a bit more details?

cpschau commented 1 year ago

Hey @ekatef ,

  1. You are exactly right! All the buses lie outside their corresponding shape. These buses can be either contained in another onshore shape (green and red marker in first plot) or outside the onshore regions (black and blue marker)
  2. In the second plot the depicted shape even includes seven GADM regions, which are merged at the stage of network clustering. I think that this behaviour is caused by the geopandas function dissolve, which in our case merges the geometries of the GeoDataframe regions according to the busmap, which is provided as an argument of the function. So let's assume that the buses b_1 and b_2 are contained in the shape s_1 and so it is correctly specified in the busmap. However, the row of the Geodataframe regions (which originates from regions_onshore_elec_s.geojson) assigns b_1 implicitly to a different false shape s_2 in its geometry column. Now, after regions.dissolve(busmap, aggfunc) is executed, s_1 will comprise of the geometries of s_1 and s_2.
ekatef commented 1 year ago

@cschau-ieg, thanks a lot for the detailed explanations! The issue looks really interesting, and some detailed debugging seems to be needed to resolve it. Let's try to tackle that step-by-step:

First of all, I'd do couple of safety checks:

  1. Could you please ensure that the problem still persists if you update the repo? Quite recently there were some fixes related to processing GADM shapes.
  2. Just in case, it could be also helpful to re-start the workflow from the cleaned repo (meaning that all the workflow output is removed from the project folders) and

I recognise that it sounds almost idiotic, but in many cases works surprisingly well. Saying from personal experience ;)

  1. Going further, it's worth to check that busmap_for_gadm_clusters (is included into clustering_for_n_clusters which is actually defined in cluster_network script) locates each bus correctly in simplify_network and cluster_network.

I fear there might be some issues with tolerance of the buses of shapes coordinates. So, it's crucial to understand what is going on when the buses are being matched against the onshore/offshore shapes

cpschau commented 1 year ago

Thank you for the recommendation, @ekatef! Updating and cleaning the repo indeed improved the situation. Nonetheless, there is still one shape anomaly occuring for the region of the outlier bus, which is depicted in the third figure of the first post. I plotted them again, so the intersections become visible.

weird_gadm_shape_3

davide-f commented 7 months ago

FYI I experienced this issue with Africa as well, but in my case the issue is that some countries are missing for some reasons. That may be due to problems in simplify_network or before.

Update: the problem is in remove_stubs