Skip to content

Commit

Permalink
Add power curves and energy estimation
Browse files Browse the repository at this point in the history
  • Loading branch information
Dmitry Duplyakin committed Feb 23, 2024
1 parent 0d13d2d commit fc6b4aa
Show file tree
Hide file tree
Showing 16 changed files with 2,026 additions and 5 deletions.
9 changes: 5 additions & 4 deletions docs/capabilities_params.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ This page describes how to provide and update the parameters passed in requests
| Capability | Parameters: example and description |
| :---------------- | :------ |
| **Plot monthly averages**<br><br>Start requests with:<br>`https://dw-tap.nrel.gov/monthly?` | * `lat=39.743` -- provide latitude<br>* `lon=-105.147` -- provide longitude<br>* `height=65.00m` -- provide hub height in meters (include `"m"` at the end)<br>* `year=2013` or `year=2012,2023` -- single year in the range 2007-2013 or a comma-seprated list of years from that range (avoid spaces and dashes). If not provided, 2013 is chosen as the year.<br><br> Provide these parameters with desired values in any order separated by `&` signs (avoid spaces)<br><br>Complete example:<br>`https://dw-tap.nrel.gov/monthly?height=65.00m&lat=39.743&lon=-105.147&year=2013`|
| **12x24 (hourly x monthly) summary**<br><br>Start requests with:<br>`https://dw-tap.nrel.gov/12x24?` | * `lat=39.743` -- provide latitude<br>* `lon=-105.147` -- provide longitude<br>* `height=65.00m` -- provide hub height in meters (include `"m"` at the end)<br>* `year=2013` or `year=2012,2023` -- single year in the range 2007-2013 or a comma-seprated list of years from that range (avoid spaces and dashes)<br><br> Provide these parameters with desired values in any order separated by `&` signs (avoid spaces). If not provided, 2013 is chosen as the year.<br><br> Provide these parameters with desired values in any order separated by `&` signs (avoid spaces)<br><br>Complete example:<br>`https://dw-tap.nrel.gov/12x24?height=65.00m&lat=39.743&lon=-105.147&year=2013` |
| **Wind rose**<br><br>Start requests with:<br>`https://dw-tap.nrel.gov/windrose?` | * `lat=39.743` -- provide latitude<br>* `lon=-105.147` -- provide longitude<br>* `height=65.00m` -- provide hub height in meters (include `"m"` at the end)<br>* `year=2013` or `year=2012,2023` -- single year in the range 2007-2013 or a comma-seprated list of years from that range (avoid spaces and dashes)<br><br> Provide these parameters with desired values in any order separated by `&` signs (avoid spaces). If not provided, 2013 is chosen as the year.<br><br> Provide these parameters with desired values in any order separated by `&` signs (avoid spaces)<br><br>Complete example:<br>`https://dw-tap.nrel.gov/windrose?height=65.00m&lat=39.743&lon=-105.147&year=2013` |
| **Raw time series**<br><br>Start requests with:<br>`https://dw-tap.nrel.gov/ts?` | * `lat=39.743` -- provide latitude<br>* `lon=-105.147` -- provide longitude<br>* `height=65.00m` -- provide hub height in meters (include `"m"` at the end)<br>* `year=2013` or `year=2012,2023` -- single year in the range 2007-2013 or a comma-seprated list of years from that range (avoid spaces and dashes)<br><br> Provide these parameters with desired values in any order separated by `&` signs (avoid spaces). If not provided, 2013 is chosen as the year.<br><br> Provide these parameters with desired values in any order separated by `&` signs (avoid spaces)<br><br>Complete example:<br>`https://dw-tap.nrel.gov/ts?height=65.00m&lat=39.743&lon=-105.147&year=2013` |
| **Bias-corrected wind speeds**<br><br>Start requests with:<br>`https://dw-tap.nrel.gov/bc?` | * `lat=39.743` -- provide latitude<br>* `lon=-105.147` -- provide longitude<br>* `height=65.00m` -- provide hub height in meters (include `"m"` at the end)<br>* `year=2013` or `year=2012,2023` -- single year in the range 2007-2013 or a comma-seprated list of years from that range (avoid spaces and dashes)<br><br> Provide these parameters with desired values in any order separated by `&` signs (avoid spaces). If not provided, 2013 is chosen as the year.<br><br> Provide these parameters with desired values in any order separated by `&` signs (avoid spaces)<br><br>Complete example:<br>`https://dw-tap.nrel.gov/bc?height=65.00m&lat=39.743&lon=-105.147&year=2013` |
| **12x24 (hourly x monthly) summary**<br><br>Start requests with:<br>`https://dw-tap.nrel.gov/12x24?` | Parameters: same as above.<br><br>Complete example:<br>`https://dw-tap.nrel.gov/12x24?height=65.00m&lat=39.743&lon=-105.147&year=2013` |
| **Wind rose**<br><br>Start requests with:<br>`https://dw-tap.nrel.gov/windrose?` | Parameters: same as above.<br><br>Complete example:<br>`https://dw-tap.nrel.gov/windrose?height=65.00m&lat=39.743&lon=-105.147&year=2013` |
| **Raw time series**<br><br>Start requests with:<br>`https://dw-tap.nrel.gov/ts?` | Parameters: same as above.<br><br>Complete example:<br>`https://dw-tap.nrel.gov/ts?height=65.00m&lat=39.743&lon=-105.147&year=2013` |
| **Bias-corrected wind speeds**<br><br>Start requests with:<br>`https://dw-tap.nrel.gov/bc?` | Parameters: same as above.<br><br> Complete example:<br>`https://dw-tap.nrel.gov/bc?height=65.00m&lat=39.743&lon=-105.147&year=2013` |
| **Estimate kWh production**<br><br>Start requests with:<br>`https://dw-tap.nrel.gov/kwh?` | Main parameters: same as above. Additional parameter: `pc` can be one of:<br>* `nrel-reference-2.5kW`<br>* `nrel-reference-100kW` (default `pc` if a value is not specified or provied value isn't in the supported list)<br>* `nrel-reference-250kW`<br>* `nrel-reference-2000kW`<br>* `bergey-excel-15`<br>* `eocycle-25`<br>* `northern-100`<br><br> Complete example:<br>`https://dw-tap.nrel.gov/kwh?height=65.00m&lat=39.743&lon=-105.147&year=2013&pc=nrel-reference-100kW` |
80 changes: 80 additions & 0 deletions powercurve.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import pandas as pd
import numpy as np
from scipy import interpolate

class PowerCurve(object):

def __init__(self, power_curve_path):

# Load data and minimal preprocessing

if ".xslx" in power_curve_path:
self.raw_data = pd.read_excel(power_curve_path)
self.raw_data.rename(columns={"Wind Speed (m/s)": "ws", "Turbine Output": "kw"}, inplace=True)
elif ".csv" in power_curve_path:
self.raw_data = pd.read_csv(power_curve_path)
self.raw_data.rename(columns={"Wind Speed (m/s)": "ws", "Turbine Output": "kw"}, inplace=True)
#print(self.raw_data.columns)
else:
raise ValueError("Unsupported powercurve file format (should be .xslx or .csv).")

# Add (0,0) if not there already
if self.raw_data["ws"].min() > 0:
self.raw_data.loc[len(self.raw_data)] = [0, 0]
self.raw_data = self.raw_data.sort_values("ws", ascending=True)
self.raw_data.reset_index(drop=True, inplace=True)

# Create vectors for interpolation
self.interp_x = self.raw_data.ws
self.interp_y = self.raw_data.kw

# Cubic interpolation
#self.powercurve_intrp = interp1d(self.interp_x, self.interp_y, kind='cubic')
# Switched back to linear to avoid bad interpolation with negative values
self.powercurve_intrp = interpolate.interp1d(self.interp_x, self.interp_y, kind='linear')

# Saving a list of instances where windspeeds are higher/lower than what is in the curve
self.above_curve = []
self.below_curve = []

self.max_ws = max(self.raw_data.ws)

self.reset_counters()

def windspeed_to_kw(self, df, ws_column="ws-adjusted", dt_column="datetime", trim=True):
""" Converts wind speed to kw """

# by default round down/up values below or under the range of the curve
if trim:
ws = df[ws_column].apply(lambda x: 0 if x < 0 else x).apply(lambda x: self.max_ws if x > self.max_ws else x)
else:
ws = df[ws_column]

kw = self.powercurve_intrp(ws)

below_curve = df[kw < 0]
above_curve = df[kw > self.max_ws]

self.below_curve.extend(zip(below_curve[dt_column].tolist(), below_curve[ws_column].tolist()))
self.above_curve.extend(zip(above_curve[dt_column].tolist(), above_curve[ws_column].tolist()))

return kw

def reset_counters(self):
self.above_curve = []
self.below_curve = []

def plot(self):
fig = px.line(y=self.powercurve_intrp(self.interp_x), x=self.interp_x,
labels={"x":"Windspeed (m/s)","y":"Power (kW)"})
fig.add_trace(go.Scatter(y=self.interp_y, x=self.interp_x,
mode='markers',
name='Data'))
fig.show()

def kw_to_windspeed(self, df, kw_column="output_power_mean"):
# Sampling a hundred points from the interpolated function
# allows us to invert with an approximate accuracy of 12/100 or 0.1
ws2 = np.linspace(0, 12, num=100)
pc2 = self.powercurve_intrp(ws2)
return df[kw_column].map(lambda x: ws2[np.abs(pc2 - x).argmin()] )
33 changes: 33 additions & 0 deletions powercurves/bergey-excel-15.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Wind Speed (m/s),Turbine Output
1,0
1.51,0
2.01,0
2.52,0
2.99,0.108
3.49,0.328
4.01,0.679
4.51,1.28
5,2.074
5.5,2.878
6,3.824
6.5,4.897
7,6.089
7.49,7.226
8,8.5
8.5,9.731
9,11.265
9.49,12.361
9.99,13.664
10.51,14.502
11.01,15.612
11.48,16.304
11.97,16.876
12.51,17.506
12.99,18.212
13.5,18.942
13.99,19.096
14.48,19.6
15,20.355
15.51,20.251
15.97,20.611
16.47,19.687
36 changes: 36 additions & 0 deletions powercurves/eocycle-25.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Wind Speed (m/s),Turbine Output
3,0.38
3.5,1.24
4,2.28
4.5,3.66
5,5.49
5.5,7.44
6,9.87
6.5,12.71
7,15.55
7.5,18.44
8,21.05
8.5,23.08
9,24.95
9.5,26.44
10,27.64
10.5,28.46
11,28.89
11.5,29.16
12,29.19
12.5,28.91
13,28.77
13.5,27.74
14,26.88
14.5,25.17
15,24.3
15.5,23.48
16,22
16.5,20.53
17,20.2
17.5,19.64
18,19.64
18.5,19.64
19,19.64
19.5,19.64
20,19.64
26 changes: 26 additions & 0 deletions powercurves/northern-100.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Wind Speed (m/s),Turbine Output
1,0
2,0
3,0.5
4,4.1
5,10.5
6,19
7,29.4
8,41
9,54.3
10,66.8
11,77.7
12,86.4
13,92.8
14,97.8
15,100
16,99.9
17,99.2
18,98.4
19,97.5
20,96.8
21,96.4
22,96.3
23,96.8
24,98
25,99.2
27 changes: 27 additions & 0 deletions powercurves/nrel-reference-100kW.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Wind Speed (m/s),Turbine Output
0,0
1,0
2,0
3,3.50595
4,8.3104
5,16.2312
6,28.0476
7,44.5386
8,66.4832
9,94.6607
10,100
11,100
12,100
13,100
14,100
15,100
16,100
17,100
18,100
19,100
20,100
21,100
22,100
23,100
24,100
25,100
27 changes: 27 additions & 0 deletions powercurves/nrel-reference-2.5kW.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Wind Speed (m/s),Turbine Output
0,0
1,0
2,0
3,0.0705428
4,0.167212
5,0.326587
6,0.564342
7,0.896154
8,1.3377
9,1.90465
10,2.5
11,2.5
12,2.5
13,2.5
14,2.5
15,2.5
16,2.5
17,2.5
18,2.5
19,0
20,0
21,0
22,0
23,0
24,0
25,0
27 changes: 27 additions & 0 deletions powercurves/nrel-reference-2000kW.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Wind Speed (m/s),Turbine Output
0,0
1,0
2,0
3,70.119
4,166.208
5,324.625
6,560.952
7,890.771
8,1329.66
9,1893.21
10,2000
11,2000
12,2000
13,2000
14,2000
15,2000
16,2000
17,2000
18,2000
19,2000
20,2000
21,2000
22,2000
23,2000
24,2000
25,2000
27 changes: 27 additions & 0 deletions powercurves/nrel-reference-250kW.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Wind Speed (m/s),Turbine Output
0,0
1,0
2,0
3,8.76487
4,20.776
5,40.5781
6,70.119
7,111.346
8,166.208
9,236.652
10,250
11,250
12,250
13,250
14,250
15,250
16,250
17,250
18,250
19,250
20,250
21,250
22,250
23,250
24,250
25,250
Loading

0 comments on commit fc6b4aa

Please sign in to comment.