Capacity Factor and potential of Wind power in PyPSA/Atlite

893 views
Skip to first unread message

Emir F

unread,
May 18, 2022, 8:25:29 PM5/18/22
to pypsa
Hi all, 

My name is Emir and I am working on an energy model for Bosnia and Herzegovina, Montenegro, and Serbia. 

I would like to use Atlite in order to assess the potential of wind and solar (in units of capacity, GW for example), in each of the three countries, and calculate the capacity factor with an hourly resolution.

Approach taken:
  1. Downloaded the CLC 2018 Copernicus land, and selected 9 land types which I deemed suitable for construction of wind and solar power plants (i.e. not urban areas, airports, water bodies etc.). 
  2. Followed the tutorial on how to calculate land-use availabilities.
  3. Downloaded the hourly data (wind and solar) from the 2016-2021 period using Atlite. Based on the data, I chose 2020 to be a representative year. 
  4. Ran Atlite for each of the 9 selected land type layers (obtained from Copernicus) separately, in order to get the capacity (MW) and the power generation profile.
  5. Calculated the Capacity Factor for each technology and layer by dividing the hourly data by the maximum hourly power generation. 
Outcome:
The average yearly capacity factors for wind range between 3.3% and 7.8% depending on country and land layer type. These values are very low in comparison to existing wind power plants (Mesihovina, Krnovo, Možura, Jelovača, Podveležje etc.) which have a CF of over 30%. Additionally, the Global Wind Atlas shows respectable numbers for mean wind speed and mean power density (at least in Montenegro and Bosnia and Herzegovina). 

Having the same approach applied on Solar PV gives an average of 19-20% CF, which is more in line with what I would expect of this type of technology in this region. 

Suggestions?
I would appreciate some clarification on why the wind CF are so low and how I could potentially approach this geospatial analysis of wind power in the region to better estimate the potential and capacity factor. 

Best regards,
Emir 

Johannes Hampp

unread,
May 19, 2022, 2:43:48 PM5/19/22
to Emir F, pypsa
Dear Emir,

Currently we are not aware of any issues in atlite which could affect
your results. The capacity factors you cite seem indeed very low for
onshore wind.

It's hard to say if and where you have problems in your workflow to
determine the capacity factors. The resulting capacity factors should be
independent of the land availability, so I recommend you check again how
you calculate the capacity factors (step 5).
Since your CFs are off by a factor of 3-5, maybe you divided by the
rated power of wind turbines one time too often. But that's just a guess.
(For PV the rated power / reference power is 1 kW, so if you are using
the same formula for wind and PV, you might not see the issue arising
for PV).

Even better: Just use the atlite built-in option to calculate the
capacity factor, `capacity_factor=True` for `.pv(...)` and `.wind(...)`.
See this example:

https://atlite.readthedocs.io/en/latest/examples/plotting_with_atlite.html?highlight=capacity_factor#Plot-capacity-factors

Regarding your second question on how to better estimate the potential:
Which problems are you facing exactly? If it is step 4. where you repeat
the calculation for all 9 selected land types: You can specify a list of
land type "codes" for the ExclusionCalculator and only run the analysis
once:

```
excluder.add_raster(CORINE, codes=range(20))
```

(see
https://atlite.readthedocs.io/en/latest/examples/landuse-availability.html )

HTH, Best,
Johannes

Best regards,
Johannes Hampp (he/him)

Justus Liebig University Giessen (JLU)
Center for international Development and Environmental Research (ZEU)

mailto: johanne...@zeu.uni-giessen.de

Senckenbergstr. 3
DE-35392 Giessen
https://uni-giessen.de/zeu

Am 19/05/2022 um 02:25 schrieb Emir F:
> Hi all,
>
> My name is Emir and I am working on an energy model for Bosnia and
> Herzegovina, Montenegro, and Serbia.
>
> I would like to use *Atlite* in order to assess the *potential of wind
> and solar* (in units of capacity, GW for example), in each of the three
> countries, and calculate the *capacity factor* with an hourly resolution.
>
> *_Approach taken:_*
>
> 1. Downloaded the CLC 2018 Copernicus land, and selected 9 land types
> which I deemed suitable for construction of wind and solar power
> plants (i.e. not urban areas, airports, water bodies etc.).
> 2. Followed the tutorial on how to calculate land-use availabilities
> <https://atlite.readthedocs.io/en/latest/examples/landuse-availability.html>.
> 3. Downloaded the hourly data (wind and solar) from the 2016-2021
> period using Atlite. Based on the data, I chose 2020 to be a
> representative year.
> 4. Ran Atlite for each of the 9 selected land type layers (obtained
> from Copernicus) separately, in order to get the capacity (MW) and
> the power generation profile.
> 5. Calculated the Capacity Factor for each technology and layer by
> dividing the hourly data by the maximum hourly power generation.
>
> *_Outcome:_*
> The average yearly capacity factors for wind range between 3.3% and 7.8%
> depending on country and land layer type. These values are very low in
> comparison to existing wind power plants (Mesihovina, Krnovo, Možura,
> Jelovača, Podveležje etc.) which have a CF of over 30%. Additionally,
> the Global Wind Atlas
> <https://globalwindatlas.info/area/Bosnia%20&%20Herzegovina> shows
> respectable numbers for mean wind speed and mean power density (at least
> in Montenegro and Bosnia and Herzegovina).
>
> Having the same approach applied on Solar PV gives an average of 19-20%
> CF, which is more in line with what I would expect of this type of
> technology in this region.
>
> *_Suggestions?_*
> I would appreciate some clarification on why the wind CF are so low and
> how I could potentially approach this geospatial analysis of wind power
> in the region to better estimate the potential and capacity factor.
>
> Best regards,
> Emir
>
> --
> You received this message because you are subscribed to the Google
> Groups "pypsa" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to pypsa+un...@googlegroups.com
> <mailto:pypsa+un...@googlegroups.com>.
> To view this discussion on the web, visit
> https://groups.google.com/d/msgid/pypsa/8159ee81-f428-4cda-ae7f-f689dfe1b2ean%40googlegroups.com
> <https://groups.google.com/d/msgid/pypsa/8159ee81-f428-4cda-ae7f-f689dfe1b2ean%40googlegroups.com?utm_medium=email&utm_source=footer>.

Emir F

unread,
May 20, 2022, 12:57:46 PM5/20/22
to pypsa
I followed the guide that you refer to for UK and Ireland. The first thing that becomes noticeable is that the Capacity factor on the map of UK and Ireland ranges from 0.2-0.8 on the plot legend. Using the same code, but for Serbia for example, gives a range between 0.02-0.16. This is 10 times lower in comparison. I understand that the wind power potential is greater in the UK, but the values for Serbia seem way too low either way. 

This is how I calculated the CF:
  1. Selected an area or country
  2. Downloaded the MW per day plot that is given in the examples that you shared above
  3. Divided each of the 365 values with the maximum value in the time series
  4. Calculated the average of these shares. 

When I selected areas where I knew there were wind power plants built already, the capacity factor was approximately 10%. Below is an example of the CF for Serbia, as you can see the range is low (0.02-0.16) compared to the 0.2-0.8 for UK/Ireland.

Screenshot 2022-05-19 at 17.01.27.png

Johannes Hampp

unread,
May 23, 2022, 3:57:17 AM5/23/22
to Emir F, pypsa
Hi Emir,

Values between 0.02 and 0.16 for the annual CF seem acceptable and in
order. I used an existing cutout based on ERA5 for 2013 which I had
readily available and calculated the CFs for Serbia and neighouring
countries based on natural earth data. I get the results attached, which
are of similar magnitude (0.02 to 0.18 annual CF).

Generally you cannot compare results from atlite for Serbia with those
from Ireland/Great Britain or from the GWA:

Roughness and wind resources of those two islands are very different
from the situation in Serbia.

Compared to GWA, atlite uses ERA5 which has a lower resolution than GWA
and does not apply correction factors as GWA does. Also atlite/ERA5 due
to the low resolution will not catch resources which local wind parks
might leverage; GWA does a better job there as well.
If you plot the Capacity Factors IEC Class I for Serbia in GWA, they are
also relatively low (0.2-0.3). That matches with the generally known
limitations for time-series derived from ERA5.

Some people try to close the gap by normalising their ERA5-derived
time-series using annual GWA values. atlite cannot do that at the
moment. If you are interested in working on this we could help you
implement that feature.

Best,
Johannes


Best regards,
Johannes Hampp (he/him)

Justus Liebig University Giessen (JLU)
Center for international Development and Environmental Research (ZEU)

mailto: johanne...@zeu.uni-giessen.de

Senckenbergstr. 3
DE-35392 Giessen
https://uni-giessen.de/zeu

Am 20/05/2022 um 18:57 schrieb Emir F:
> I followed the guide that you refer to for UK and Ireland. The first
> thing that becomes noticeable is that the Capacity factor on the map of
> UK and Ireland ranges from 0.2-0.8 on the plot legend. Using the same
> code, but for Serbia for example, gives a range between 0.02-0.16. This
> is 10 times lower in comparison. I understand that the wind power
> potential is greater in the UK, but the values for Serbia seem way too
> low either way.
>
> This is how I calculated the CF:
>
> 1. Selected an area or country
> 2. Downloaded the MW per day plot that is given in the examples that
> you shared above
> 3. Divided each of the 365 values with the maximum value in the time series
> 4. Calculated the average of these shares.
>
>
> When I selected areas where I knew there were wind power plants built
> already, the capacity factor was approximately 10%. Below is an example
> of the CF for Serbia, as you can see the range is low (0.02-0.16)
> compared to the 0.2-0.8 for UK/Ireland.
>
> https://uni-giessen.de/zeu <https://uni-giessen.de/zeu>
> <https://groups.google.com/d/msgid/pypsa/8159ee81-f428-4cda-ae7f-f689dfe1b2ean%40googlegroups.com?utm_medium=email&utm_source=footer
> <https://groups.google.com/d/msgid/pypsa/8159ee81-f428-4cda-ae7f-f689dfe1b2ean%40googlegroups.com?utm_medium=email&utm_source=footer>>.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "pypsa" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to pypsa+un...@googlegroups.com
> <mailto:pypsa+un...@googlegroups.com>.
> To view this discussion on the web, visit
> https://groups.google.com/d/msgid/pypsa/f1e521fd-f50d-4bcd-92ef-9886939e2018n%40googlegroups.com
> <https://groups.google.com/d/msgid/pypsa/f1e521fd-f50d-4bcd-92ef-9886939e2018n%40googlegroups.com?utm_medium=email&utm_source=footer>.
capacity_factors.html

Emir F

unread,
May 23, 2022, 11:32:36 AM5/23/22
to pypsa
Hi Johannes,

Thanks for your detailed response and for elaborating on the reasoning. I now have a better understanding of how this process works. The gap between ERA5 and GWA would be interesting to bridge, although I am not sure how to do so. If I could receive some guidance on how to accomplish this for Serbia, then I could apply the same logic to Bosnia and Montenegro on my own.

I appreciate your time and look forward to hearing from you!

Best regards,
Emir Fejzić

Johannes Hampp

unread,
May 30, 2022, 4:53:02 AM5/30/22
to Emir F, pypsa
Hi Emir,

Bridging the GAP between ERA5 and GWA is described e.g. by Gruber et al
(2022) [1] based on annual average wind speeds. They also compared GWA2
with GWA3 and did some validation.
Mattson et al (2021) [2] used a similar approach based on average wind
speeds.

I just recently had the opportunity to talk to a member of the IRENA
modelling team. They are in the process of releasing a tool for
determining PV and wind sites in Africa (AFAIK there will be an
accompanying paper). They use a more complicated approach presumably to
preserve the wind speed distribution (Weibull), implementation without
description can be found here [3]. The approach is more complicated but
can potential addresses the issues identified by Gruber et al. .

All three methods are bias correction for spatial disaggregation where
the original ERA5 resolution is downscaled to (1km)^2 or (250m)^2. If
you don't want to do downscaling (additional effort; unnecessary
depending on what you are working on) you could think about adapting a
very simple and straightforward method based on annual average /
cumulative grid cell values from GWA aggregated on ERA5 raster level.

Hope that helps getting you started, happy to stay in touch as we intend
to work on this as well in the near future and potentially include into
atlite. So any experience sharing is welcome.

Best,
Johannes


[1]
https://www.sciencedirect.com/science/article/pii/S0360544221017680?via%3Dihub
[2] see supplementary materials, pg. 6 "Dual resolutions, wind rescaling
and turbine curves":
https://www.sciencedirect.com/science/article/pii/S2211467X20301590
[3]
https://github.com/bhussain89/Model-Supply-Regions-MSR-Toolset/blob/fa8cc8a39a7659ff66d6ee82443042a45f30b7b9/2.%20Profile%20Generator/Profile_Generator.py#L120-L187
(rather than reverse engineering they might be willing to share a
description of their methodology privately upon request?)
> https://uni-giessen.de/zeu <https://uni-giessen.de/zeu>
> <https://groups.google.com/d/msgid/pypsa/f1e521fd-f50d-4bcd-92ef-9886939e2018n%40googlegroups.com?utm_medium=email&utm_source=footer
> <https://groups.google.com/d/msgid/pypsa/f1e521fd-f50d-4bcd-92ef-9886939e2018n%40googlegroups.com?utm_medium=email&utm_source=footer>>.
>
> --
> You received this message because you are subscribed to the Google
> Groups "pypsa" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to pypsa+un...@googlegroups.com
> <mailto:pypsa+un...@googlegroups.com>.
> To view this discussion on the web, visit
> https://groups.google.com/d/msgid/pypsa/333b5334-9ec0-42ea-968a-4bfc3dfb7e75n%40googlegroups.com
> <https://groups.google.com/d/msgid/pypsa/333b5334-9ec0-42ea-968a-4bfc3dfb7e75n%40googlegroups.com?utm_medium=email&utm_source=footer>.

Tommaso Ficara

unread,
Sep 7, 2022, 8:37:34 AM9/7/22
to pypsa
Dear Johannes and Emir, 

with great interest I am following this conversation.  Indeed  the low resolution of ERA5 is a problem that I am facing as well when trying to get realistic capacity factors for wind power generation from the atlite framework. The 30x30 km resolution "hides" greater wind power generation potentials that would be concentrated in smaller areas. 
Has any progress been done in the implementation of higher resolution frameworks (GWA) in atlite? Any help would be really appreciated. 

Thanks in advance, 

Best regards, 
Tommaso 

Johannes Hampp

unread,
Oct 7, 2022, 1:57:35 PM10/7/22
to Tommaso Ficara, pypsa
Dear Tommaso,

As far as I know there is no general implementation ERA5 correction
using GWA in atlite yet.

I know of one master student who is doing a project in that direction
but I haven't been in contact with that person lately so I don't know
about their progress.

Maybe Emir has better news?

Best,
Johannes

Best regards,
Johannes Hampp (he/him)

Justus Liebig University Giessen (JLU)
Center for international Development and Environmental Research (ZEU)

mailto: johanne...@zeu.uni-giessen.de

Senckenbergstr. 3
DE-35392 Giessen
https://uni-giessen.de/zeu

> <https://groups.google.com/d/msgid/pypsa/333b5334-9ec0-42ea-968a-4bfc3dfb7e75n%40googlegroups.com?utm_medium=email&utm_source=footer
> <https://groups.google.com/d/msgid/pypsa/333b5334-9ec0-42ea-968a-4bfc3dfb7e75n%40googlegroups.com?utm_medium=email&utm_source=footer>>.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "pypsa" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to pypsa+un...@googlegroups.com
> <mailto:pypsa+un...@googlegroups.com>.
> To view this discussion on the web, visit
> https://groups.google.com/d/msgid/pypsa/47559faa-4298-4f5e-a746-19c062b420fdn%40googlegroups.com
> <https://groups.google.com/d/msgid/pypsa/47559faa-4298-4f5e-a746-19c062b420fdn%40googlegroups.com?utm_medium=email&utm_source=footer>.

Olivier Deforche

unread,
Mar 21, 2023, 3:04:53 PM3/21/23
to pypsa
Dear, I am trying to do the same as mentioned above: converting the Era5 weather data to the respective capacity factors for each datapoint. However, I want to have hourly resolution. If I use the functions pv.() and wind.() with capacity_factor=True, the temporal mean gets calculated (which I do not want). You mention above in step 5 that you divide it with the maximum hourly power generation. I was wondering where you get this data and whether it gives an accurate capacity factor that way? Or if anyone else has a different proposition to convert this data. Thanks! Olivier

Matthew Smith

unread,
Mar 23, 2023, 7:14:02 AM3/23/23
to pypsa
Hi Oliver,

There may be a more efficient way. But I modified the example here to apply to every grid cell in the cutout.

#### PRODUCE 8760 HOURLY TIMESERIES FOR EVERY GRID SQUARE IN THE CUTOUT

### First we create a xarray duplicating that of the cutout. We will assign a capacity value of 1 MW to each grid square.
### When we feed this into the cutout, it will know to produce an hourly timeseries for each gridsquare

# Filter the cutout as per your requirements
WindCO_2017 = cutout.sel(time=cutout.coords["time"].dt.year.isin([2017]))

# Get the x and y coordinates from the cutout object as numpy arrays
x = WindCO_2017.coords['x'].values
y = WindCO_2017.coords['y'].values

# Use np.meshgrid to create a grid of x and y coordinates
xx, yy = np.meshgrid(x, y)

# Use np.ravel to flatten the grid arrays into one-dimensional arrays
xx = xx.ravel()
yy = yy.ravel()

# Use pd.DataFrame to create a pandas dataframe with columns for x, y and capacity
df = pd.DataFrame({'x': xx, 'y': yy, 'capacity': 1})

# Create a column with the combined xy coordinate to be the future column name for the results
df['XY'] = df['x'].astype(str).str.cat(df['y'].astype(str), sep=',')

# Turn this into a GeoDataFrame, like a pandas dataframe but with a geography attribute
sites = gpd.GeoDataFrame(df)

# Set the XY column as the index
sites = gpd.GeoDataFrame(sites).set_index('XY')

# Creates the xarray to feed into the cutout function. Basically creating an x y grid with capacity as the value.
layout = xr.DataArray(sites.set_index(['y', 'x']).capacity.unstack())

# the cutout.grid() function here returns the underlying grid the cutout uses, as a GeoDataFrame object. We're pulling this out just so we can get the right geography
# it is needed to feed in the capacity of each grid as seperate sites it seems
cells = WindCO_2017.grid

# here the cells grid is merged here. This ensures the column name will be preserved as the XY value
cells_generation = sites.merge(cells, how='inner').rename(pd.Series(sites.index))

# This is the cutout.wind() function which otherwise just returns annual average capacity factors. By feeding in the layour and shape attribute, it produces the timeseries
power_generation = WindCO_2017.wind(turbine_config, layout=layout, shapes=cells_generation.geometry)

# Here I convert it to a pandas data frame so the data is easier to work with
df = power_generation.to_pandas()
df.head()

Message has been deleted
Message has been deleted

Olivier Deforche

unread,
Apr 4, 2023, 8:40:26 AM4/4/23
to pypsa
Dear Matts,

Thank you for the help, it works exactly as you mentioned! I have two remaining questions concerning the data:

1) I want to include the nature data base to take this into account for the capacity factors as in the example that can be found via the following link:  https://atlite.readthedocs.io/en/latest/examples/plotting_with_atlite.html?highlight=capacity_factor#Plot-capacity-factors. I already tried this with each data point coordinate instead of country without success.

2) I want to have the data as a new NetCDF4 file in 3d with dimensions: time, longitude, latitude. Now, it has only two dimensions: time, and the coordinate. I tried splitting this, but this takes quite some. You can find my code below!

Thank you in advance!

Best regards,
Olivier
Schermafbeelding 2023-04-04 095108.png
Message has been deleted

Claire Halloran

unread,
Aug 11, 2023, 12:53:10 PM8/11/23
to pypsa
Hi Oliver,

I was able to split the dataarray into 3 dimensions by replacing the shape dimension with a pandas MultiIndex made from the cutout.grid and then using xarray's unstack function. Here's my code:

# use the uniform capacity layout function from atlite
layout = cutout.uniform_layout()

hourly_wind = cutout.wind(
    turbine = 'Vestas_V90_3MW',
    layout=layout,
    shapes=cutout.grid.geometry
    )

# create multiindex from cutout grid
multiindex = pd.MultiIndex.from_frame(pd.DataFrame(cutout.grid.drop(columns='geometry')))

# replace shape index with unstackable MultiIndex and unstack
hourly_wind = hourly_wind.assign_coords({'dim_0':multiindex}).unstack()

From there you can save the hourly_wind dataarray as a NetCDF or another data format. I hope this is helpful for you and anyone else who is wondering how to use atlite to calculate hourly capacity factor a grid of lat-lon coordinates!

Warmly,
Claire
Reply all
Reply to author
Forward
0 new messages