Skip to content

Commit e17295c

Browse files
committed
Power curve and power coefficient curve as numpy array and series
1 parent 5a8ee66 commit e17295c

File tree

2 files changed

+148
-53
lines changed

2 files changed

+148
-53
lines changed

tests/test_power_output.py

Lines changed: 99 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,29 @@ def test_power_coefficient_curve(self):
1414
parameters = {'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]),
1515
'density': pd.Series(data=[1.3, 1.3, 1.3]),
1616
'rotor_diameter': 80,
17-
'cp_values': pd.Series([0.3, 0.4, 0.5],
18-
index=[4.0, 5.0, 6.0])}
17+
'power_coefficient_curve_wind_speeds':
18+
pd.Series([4.0, 5.0, 6.0]),
19+
'power_coefficient_curve_values':
20+
pd.Series([0.3, 0.4, 0.5])}
1921

2022
# Tests without density correction:
21-
# Test wind_speed as pd.Series with density as pd.Series and np.array
23+
# Test wind_speed as pd.Series with density and power_coefficient_curve
24+
# as pd.Series and np.array
2225
power_output_exp = pd.Series(data=[0.0, 244615.399, 0.0],
2326
name='feedin_wind_turbine')
2427
assert_series_equal(power_coefficient_curve(**parameters),
2528
power_output_exp)
2629
parameters['density'] = np.array(parameters['density'])
2730
assert_series_equal(power_coefficient_curve(**parameters),
2831
power_output_exp)
29-
# Test wind_speed as np.array with density as np.array and pd.Series
32+
parameters['power_coefficient_curve_values'] = np.array(
33+
parameters['power_coefficient_curve_values'])
34+
parameters['power_coefficient_curve_wind_speeds'] = np.array(
35+
parameters['power_coefficient_curve_wind_speeds'])
36+
assert_series_equal(power_coefficient_curve(**parameters),
37+
power_output_exp)
38+
# Test wind_speed as np.array with density and power_coefficient_curve
39+
# as np.array and pd.Series
3040
power_output_exp = np.array([0.0, 244615.399, 0.0])
3141
parameters['wind_speed'] = np.array(parameters['wind_speed'])
3242
assert_allclose(power_coefficient_curve(**parameters),
@@ -36,9 +46,17 @@ def test_power_coefficient_curve(self):
3646
assert_allclose(power_coefficient_curve(**parameters),
3747
power_output_exp)
3848
assert isinstance(power_coefficient_curve(**parameters), np.ndarray)
49+
parameters['power_coefficient_curve_wind_speeds'] = pd.Series(
50+
data=parameters['power_coefficient_curve_wind_speeds'])
51+
parameters['power_coefficient_curve_values'] = pd.Series(
52+
data=parameters['power_coefficient_curve_values'])
53+
assert_allclose(power_coefficient_curve(**parameters),
54+
power_output_exp)
55+
assert isinstance(power_coefficient_curve(**parameters), np.ndarray)
3956

4057
# Tests with density correction:
41-
# Test wind_speed as np.array with density as pd.Series and np.array
58+
# Test wind_speed as np.array with density and power_coefficient_curve
59+
# as pd.Series and np.array
4260
power_output_exp = np.array([0.0, 262869.785, 0.0])
4361
parameters['density_correction'] = True
4462
assert_allclose(power_coefficient_curve(**parameters),
@@ -48,7 +66,16 @@ def test_power_coefficient_curve(self):
4866
assert_allclose(power_coefficient_curve(**parameters),
4967
power_output_exp)
5068
assert isinstance(power_coefficient_curve(**parameters), np.ndarray)
51-
# Test wind_speed as pd.Series with density as np. array and pd.Series
69+
parameters['power_coefficient_curve_values'] = np.array(
70+
parameters['power_coefficient_curve_values'])
71+
parameters['power_coefficient_curve_wind_speeds'] = np.array(
72+
parameters['power_coefficient_curve_wind_speeds'])
73+
assert_allclose(power_coefficient_curve(**parameters),
74+
power_output_exp)
75+
assert isinstance(power_coefficient_curve(**parameters), np.ndarray)
76+
77+
# Test wind_speed as pd.Series with density and power_coefficient_curve
78+
# as np. array and pd.Series
5279
power_output_exp = pd.Series(data=[0.0, 262869.785, 0.0],
5380
name='feedin_wind_turbine')
5481
parameters['wind_speed'] = pd.Series(data=parameters['wind_speed'])
@@ -57,69 +84,122 @@ def test_power_coefficient_curve(self):
5784
parameters['density'] = pd.Series(data=parameters['density'])
5885
assert_series_equal(power_coefficient_curve(**parameters),
5986
power_output_exp)
87+
parameters['power_coefficient_curve_wind_speeds'] = pd.Series(
88+
data=parameters['power_coefficient_curve_wind_speeds'])
89+
parameters['power_coefficient_curve_values'] = pd.Series(
90+
data=parameters['power_coefficient_curve_values'])
91+
assert_series_equal(power_coefficient_curve(**parameters),
92+
power_output_exp)
6093

61-
# Raise TypeErrors due to wrong type of `density_corr`
94+
# Raise TypeErrors due to wrong type of `density_correction`
6295
with pytest.raises(TypeError):
6396
parameters['density'] = 'wrong_type'
6497
power_coefficient_curve(**parameters)
6598

6699
def test_power_curve(self):
67100
parameters = {'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]),
68-
'p_values': pd.Series([300, 400, 500],
69-
index=[4.0, 5.0, 6.0]),
70101
'density': pd.Series(data=[1.3, 1.3, 1.3]),
71-
'density_correction': False}
102+
'density_correction': False,
103+
'power_curve_wind_speeds':
104+
pd.Series([4.0, 5.0, 6.0]),
105+
'power_curve_values':
106+
pd.Series([300, 400, 500])
107+
}
72108

73109
# Tests without density correction:
74-
# Test wind_speed as pd.Series
110+
# Test wind_speed as pd.Series and power_curve as pd.Series and
111+
# np.array
75112
power_output_exp = pd.Series(data=[0.0, 450.0, 0.0],
76113
name='feedin_wind_turbine')
77114
assert_series_equal(power_curve(**parameters), power_output_exp)
78-
# Test wind_speed as np.array
115+
parameters['power_curve_values'] = np.array(
116+
parameters['power_curve_values'])
117+
parameters['power_curve_wind_speeds'] = np.array(
118+
parameters['power_curve_wind_speeds'])
119+
assert_series_equal(power_curve(**parameters),
120+
power_output_exp)
121+
122+
# Test wind_speed as np.array and power_curve as pd.Series and np.array
79123
power_output_exp = np.array([0.0, 450.0, 0.0])
80124
parameters['wind_speed'] = np.array(parameters['wind_speed'])
81125
assert_allclose(power_curve(**parameters), power_output_exp)
82126
assert isinstance(power_curve(**parameters), np.ndarray)
127+
parameters['power_curve_wind_speeds'] = pd.Series(
128+
data=parameters['power_curve_wind_speeds'])
129+
parameters['power_curve_values'] = pd.Series(
130+
data=parameters['power_curve_values'])
131+
assert_allclose(power_curve(**parameters), power_output_exp)
132+
assert isinstance(power_curve(**parameters), np.ndarray)
83133

84134
# Tests with density correction:
85-
# Test wind_speed as np.array with density as pd.Series and np.array
135+
# Test wind_speed as np.array with density and power_curve as pd.Series
136+
# and np.array
86137
power_output_exp = np.array([0.0, 461.00290572, 0.0])
87138
parameters['density_correction'] = True
88139
assert_allclose(power_curve(**parameters), power_output_exp)
89140
assert isinstance(power_curve(**parameters), np.ndarray)
90141
parameters['density'] = np.array(parameters['density'])
91142
assert_allclose(power_curve(**parameters), power_output_exp)
92143
assert isinstance(power_curve(**parameters), np.ndarray)
93-
# Test wind_speed as pd.Series with density as np. array and pd.Series
144+
parameters['power_curve_values'] = np.array(
145+
parameters['power_curve_values'])
146+
parameters['power_curve_wind_speeds'] = np.array(
147+
parameters['power_curve_wind_speeds'])
148+
assert_allclose(power_curve(**parameters), power_output_exp)
149+
assert isinstance(power_curve(**parameters), np.ndarray)
150+
151+
# Test wind_speed as pd.Series with density and power_curve as
152+
# np. array and pd.Series
94153
power_output_exp = pd.Series(data=[0.0, 461.00290572, 0.0],
95154
name='feedin_wind_turbine')
96155
parameters['wind_speed'] = pd.Series(data=parameters['wind_speed'])
97156
assert_series_equal(power_curve(**parameters), power_output_exp)
98157
parameters['density'] = pd.Series(data=parameters['density'])
99158
assert_series_equal(power_curve(**parameters),
100159
power_output_exp)
160+
parameters['power_curve_wind_speeds'] = pd.Series(
161+
data=parameters['power_curve_wind_speeds'])
162+
parameters['power_curve_values'] = pd.Series(
163+
data=parameters['power_curve_values'])
164+
assert_series_equal(power_curve(**parameters),
165+
power_output_exp)
101166

102-
# Raise TypeErrors due to wrong type of `density_corr`
167+
# Raise TypeErrors due to wrong type of `density_correction`
103168
with pytest.raises(TypeError):
104169
parameters['density'] = 'wrong_type'
105170
power_curve(**parameters)
106171

107172
def test_power_curve_density_correction(self):
108173
parameters = {'wind_speed': pd.Series(data=[2.0, 5.5, 7.0]),
109174
'density': pd.Series(data=[1.3, 1.3, 1.3]),
110-
'p_values': pd.Series([300, 400, 500],
111-
index=[4.0, 5.0, 6.0])}
175+
'power_curve_wind_speeds':
176+
pd.Series([4.0, 5.0, 6.0]),
177+
'power_curve_values':
178+
pd.Series([300, 400, 500])
179+
}
112180

113-
# Test wind_speed as pd.Series with density as pd.Series and np.array
181+
# Test wind_speed as pd.Series with density and power_curve as
182+
# pd.Series and np.array
114183
power_output_exp = [0.0, 461.00290572240806, 0.0]
115184
assert power_curve_density_correction(**parameters) == power_output_exp
116185
parameters['density'] = np.array(parameters['density'])
117186
assert power_curve_density_correction(**parameters) == power_output_exp
187+
parameters['power_curve_values'] = np.array(
188+
parameters['power_curve_values'])
189+
parameters['power_curve_wind_speeds'] = np.array(
190+
parameters['power_curve_wind_speeds'])
191+
assert power_curve_density_correction(**parameters) == power_output_exp
118192

119-
# Test wind_speed as np.array with density as np.array and pd.Series
193+
# Test wind_speed as np.array with density and power_curve as np.array
194+
# and pd.Series
120195
assert power_curve_density_correction(**parameters) == power_output_exp
121196
parameters['density'] = pd.Series(data=parameters['density'])
122197
assert power_curve_density_correction(**parameters) == power_output_exp
198+
parameters['power_curve_wind_speeds'] = pd.Series(
199+
data=parameters['power_curve_wind_speeds'])
200+
parameters['power_curve_values'] = pd.Series(
201+
data=parameters['power_curve_values'])
202+
assert power_curve_density_correction(**parameters) == power_output_exp
123203

124204
# Raise TypeError due to density is None
125205
with pytest.raises(TypeError):

windpowerlib/power_output.py

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
import pandas as pd
1212

1313

14-
def power_coefficient_curve(wind_speed, cp_values, rotor_diameter, density,
15-
density_correction=False):
14+
def power_coefficient_curve(wind_speed, power_coefficient_curve_wind_speeds,
15+
power_coefficient_curve_values, rotor_diameter,
16+
density, density_correction=False):
1617
r"""
1718
Calculates the turbine power output using a power coefficient curve.
1819
@@ -26,9 +27,12 @@ def power_coefficient_curve(wind_speed, cp_values, rotor_diameter, density,
2627
----------
2728
wind_speed : pandas.Series or numpy.array
2829
Wind speed at hub height in m/s.
29-
cp_values : pandas.Series
30-
Power coefficient curve of the wind turbine.
31-
Indices are the wind speeds of the power coefficient curve in m/s.
30+
power_coefficient_curve_wind_speeds : pandas.Series or numpy.array
31+
Wind speeds in m/s for which the power coefficients are provided in
32+
`power_coefficient_curve_values`.
33+
power_coefficient_curve_values : pandas.Series or numpy.array
34+
Power coefficients corresponding to wind speeds in
35+
`power_coefficient_curve_wind_speeds`.
3236
rotor_diameter : float
3337
Rotor diameter in m.
3438
density : pandas.Series or numpy.array
@@ -68,16 +72,19 @@ def power_coefficient_curve(wind_speed, cp_values, rotor_diameter, density,
6872
6973
"""
7074
if density_correction is False:
71-
cp_time_series = np.interp(wind_speed, cp_values.index, cp_values,
72-
left=0, right=0)
73-
power_output = (1 / 8 * density * rotor_diameter ** 2 * np.pi
74-
* np.power(wind_speed, 3) * cp_time_series)
75+
power_coefficient_time_series = np.interp(
76+
wind_speed, power_coefficient_curve_wind_speeds,
77+
power_coefficient_curve_values, left=0, right=0)
78+
power_output = (1 / 8 * density * rotor_diameter ** 2 * np.pi *
79+
np.power(wind_speed, 3) *
80+
power_coefficient_time_series)
7581
elif density_correction is True:
76-
p_values = (1 / 8 * 1.225 * rotor_diameter ** 2 * np.pi *
77-
np.power(cp_values.index, 3) * cp_values)
78-
p_values = pd.Series(np.array(p_values), index=cp_values.index)
79-
power_output = power_curve_density_correction(wind_speed, p_values,
80-
density)
82+
power_curve_values = (1 / 8 * 1.225 * rotor_diameter ** 2 * np.pi *
83+
np.power(power_coefficient_curve_wind_speeds, 3) *
84+
power_coefficient_curve_values)
85+
power_output = power_curve_density_correction(
86+
wind_speed, power_coefficient_curve_wind_speeds,
87+
power_curve_values, density)
8188
else:
8289
raise TypeError("'{0}' is an invalid type. ".format(type(
8390
density_correction)) + "`density_correction` must " +
@@ -92,7 +99,8 @@ def power_coefficient_curve(wind_speed, cp_values, rotor_diameter, density,
9299
return power_output
93100

94101

95-
def power_curve(wind_speed, p_values, density=None, density_correction=False):
102+
def power_curve(wind_speed, power_curve_wind_speeds, power_curve_values,
103+
density=None, density_correction=False):
96104
r"""
97105
Calculates the turbine power output using a power curve.
98106
@@ -105,12 +113,15 @@ def power_curve(wind_speed, p_values, density=None, density_correction=False):
105113
----------
106114
wind_speed : pandas.Series or numpy.array
107115
Wind speed at hub height in m/s.
108-
p_values : pandas.Series
109-
Power curve of the wind turbine.
110-
Indices are the wind speeds of the power curve in m/s.
116+
power_curve_wind_speeds : pandas.Series or numpy.array
117+
Wind speeds in m/s for which the power curve values are provided in
118+
`power_curve_values`.
119+
power_curve_values : pandas.Series or numpy.array
120+
Power curve values corresponding to wind speeds in
121+
`power_curve_wind_speeds`.
111122
density : pandas.Series or numpy.array
112123
Density of air at hub height in kg/m³. This parameter is needed
113-
if `density_corr` is True. Default: None.
124+
if `density_correction` is True. Default: None.
114125
density_correction : boolean
115126
If the parameter is True the density corrected power curve is used for
116127
the calculation of the turbine power output. In this case `density`
@@ -129,11 +140,11 @@ def power_curve(wind_speed, p_values, density=None, density_correction=False):
129140
130141
"""
131142
if density_correction is False:
132-
power_output = np.interp(wind_speed, p_values.index, p_values,
133-
left=0, right=0)
143+
power_output = np.interp(wind_speed, power_curve_wind_speeds,
144+
power_curve_values, left=0, right=0)
134145
elif density_correction is True:
135-
power_output = power_curve_density_correction(wind_speed, p_values,
136-
density)
146+
power_output = power_curve_density_correction(
147+
wind_speed, power_curve_wind_speeds, power_curve_values, density)
137148
else:
138149
raise TypeError("'{0}' is an invalid type. ".format(type(
139150
density_correction)) + "`density_correction` must " +
@@ -147,21 +158,24 @@ def power_curve(wind_speed, p_values, density=None, density_correction=False):
147158
return power_output
148159

149160

150-
def power_curve_density_correction(wind_speed, p_values, density):
161+
def power_curve_density_correction(wind_speed, power_curve_wind_speeds,
162+
power_curve_values, density):
151163
r"""
152164
Calculates the turbine power output using a density corrected power curve.
153165
154-
This function is carried out when the parameter `power_output_model` of an
155-
instance of the :class:`~.modelchain.ModelChain` class is 'power_curve'
156-
and the parameter `density_correction` is True.
166+
This function is carried out when the parameter `density_correction` of an
167+
instance of the :class:`~.modelchain.ModelChain` class is True.
157168
158169
Parameters
159170
----------
160171
wind_speed : pandas.Series or numpy.array
161-
Wind speed time series at hub height in m/s.
162-
p_values : pandas.Series
163-
Power curve of the wind turbine.
164-
Indices are the wind speeds of the power curve in m/s.
172+
Wind speed at hub height in m/s.
173+
power_curve_wind_speeds : pandas.Series or numpy.array
174+
Wind speeds in m/s for which the power curve values are provided in
175+
`power_curve_values`.
176+
power_curve_values : pandas.Series or numpy.array
177+
Power curve values corresponding to wind speeds in
178+
`power_curve_wind_speeds`.
165179
density : pandas.Series or numpy.array
166180
Density of air at hub height in kg/m³.
167181
@@ -215,7 +229,8 @@ def power_curve_density_correction(wind_speed, p_values, density):
215229
"density corrected power curve density at hub " +
216230
"height is needed.")
217231
return [(np.interp(wind_speed[i],
218-
p_values.index * (1.225 / density[i])**(
219-
np.interp(p_values.index, [7.5, 12.5], [1/3, 2/3])),
220-
p_values, left=0, right=0))
232+
power_curve_wind_speeds * (1.225 / density[i])**(
233+
np.interp(power_curve_wind_speeds, [7.5, 12.5],
234+
[1/3, 2/3])),
235+
power_curve_values, left=0, right=0))
221236
for i in range(len(wind_speed))]

0 commit comments

Comments
 (0)