Skip to content

Commit ad7daff

Browse files
committed
Move density correction to _p_curve_density_corr()
1 parent 869d7e9 commit ad7daff

File tree

2 files changed

+77
-115
lines changed

2 files changed

+77
-115
lines changed

windpowerlib/modelchain.py

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -265,39 +265,20 @@ def turbine_power_output(self, wind_speed, density):
265265
raise TypeError("Cp values of " +
266266
self.wind_turbine.turbine_name +
267267
" are missing.")
268-
if self.density_corr is False:
269-
logging.debug('Calculating power output using cp curve.')
270-
output = power_output.power_coefficient_curve(
271-
wind_speed, density, self.wind_turbine.rotor_diameter,
272-
self.wind_turbine.cp_values)
273-
elif self.density_corr is True:
274-
logging.debug('Calculating power output using density ' +
275-
'corrected cp curve.')
276-
output = power_output.cp_curve_density_corr(
277-
wind_speed, density, self.wind_turbine.rotor_diameter,
278-
self.wind_turbine.cp_values)
279-
else:
280-
raise TypeError("'{0}' is an invalid type.".format(type(
281-
self.density_corr)) + "`density_corr` must " +
282-
"be Boolean (True or False).")
268+
logging.debug('Calculating power output using cp curve.')
269+
output = power_output.power_coefficient_curve(
270+
wind_speed, self.wind_turbine.cp_values,
271+
self.wind_turbine.rotor_diameter, density,
272+
self.density_corr)
283273
elif self.power_output_model == 'p_values':
284274
if self.wind_turbine.p_values is None:
285275
raise TypeError("P values of " +
286276
self.wind_turbine.turbine_name +
287277
" are missing.")
288-
if self.density_corr is False:
289-
logging.debug('Calculating power output using power curve.')
290-
output = power_output.power_curve(wind_speed,
291-
self.wind_turbine.p_values)
292-
elif self.density_corr is True:
293-
logging.debug('Calculating power output using density ' +
294-
'corrected power curve.')
295-
output = power_output.p_curve_density_corr(
296-
wind_speed, density, self.wind_turbine.p_values)
297-
else:
298-
raise TypeError("'{0}' is an invalid type.".format(type(
299-
self.density_corr)) + "`density_corr` must " +
300-
"be Boolean (True or False).")
278+
logging.debug('Calculating power output using power curve.')
279+
output = power_output.power_curve(
280+
wind_speed, self.wind_turbine.p_values, density,
281+
self.density_corr)
301282
else:
302283
raise ValueError("'{0}' is an invalid value.".format(
303284
self.power_output_model) +

windpowerlib/power_output.py

Lines changed: 68 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,30 @@
1111
import pandas as pd
1212

1313

14-
def power_coefficient_curve(wind_speed, density, rotor_diameter, cp_values):
14+
def power_coefficient_curve(wind_speed, cp_values,
15+
rotor_diameter, density, density_corr=False):
1516
r"""
1617
Calculates the turbine power output using a power coefficient curve.
1718
1819
This function is carried out when the parameter `power_output_model` of an
19-
instance of the :class:`~.modelchain.ModelChain` class is 'cp_values' and
20-
the parameter `density_corr` is False.
20+
instance of the :class:`~.modelchain.ModelChain` class is 'cp_values'. If
21+
the parameter `density_corr` is True the density corrected power curve
22+
(:py:func:`~._p_curve_density_corr`) is used.
2123
2224
Parameters
2325
----------
2426
wind_speed : pandas.Series or numpy.array
2527
Wind speed at hub height in m/s.
26-
density : pandas.Series or numpy.array
27-
Density of air at hub height in kg/m³.
28-
rotor_diameter : float
29-
Rotor diameter in m.
3028
cp_values : pandas.Series
3129
Power coefficient curve of the wind turbine.
3230
Indices are the wind speeds of the power coefficient curve in m/s.
31+
rotor_diameter : float
32+
Rotor diameter in m.
33+
density : pandas.Series or numpy.array
34+
Density of air at hub height in kg/m³.
35+
density_corr : boolean
36+
If the parameter is True the density corrected power curve is used for
37+
the calculation of the turbine power output. Default: False.
3338
3439
Returns
3540
-------
@@ -39,7 +44,8 @@ def power_coefficient_curve(wind_speed, density, rotor_diameter, cp_values):
3944
4045
Notes
4146
-----
42-
The following equation is used [1]_, [2]_:
47+
The following equation is used if the parameter `density_corr` is False
48+
[1]_, [2]_:
4349
4450
.. math:: P=\frac{1}{8}\cdot\rho_{hub}\cdot d_{rotor}^{2}
4551
\cdot\pi\cdot v_{wind}^{3}\cdot cp\left(v_{wind}\right)
@@ -60,71 +66,38 @@ def power_coefficient_curve(wind_speed, density, rotor_diameter, cp_values):
6066
Wirtschaftlichkeit". 4. Auflage, Springer-Verlag, 2008, p. 542
6167
6268
"""
63-
cp_time_series = np.interp(wind_speed, cp_values.index, cp_values,
64-
left=0, right=0)
65-
# Convert density to np.array if wind_speed is np.array
66-
if isinstance(wind_speed, np.ndarray) and isinstance(density, pd.Series):
67-
density = np.array(density)
68-
power_output = (1 / 8 * density * rotor_diameter ** 2 * np.pi
69-
* np.power(wind_speed, 3) * cp_time_series)
70-
# Power_output as pd.Series if v_wind is pd.Series
69+
if density_corr is False:
70+
cp_time_series = np.interp(wind_speed, cp_values.index, cp_values,
71+
left=0, right=0)
72+
power_output = (1 / 8 * density * rotor_diameter ** 2 * np.pi
73+
* np.power(wind_speed, 3) * cp_time_series)
74+
elif density_corr is True:
75+
p_values = (1 / 8 * 1.225 * rotor_diameter ** 2 * np.pi *
76+
np.power(cp_values.index, 3) * cp_values)
77+
p_values = pd.Series(np.array(p_values), index=cp_values.index)
78+
power_output = _p_curve_density_corr(wind_speed, density, p_values)
79+
else:
80+
raise TypeError("'{0}' is an invalid type.".format(type(
81+
density_corr)) + "`density_corr` must be Boolean " +
82+
"(True or False).")
83+
84+
# Power_output as pd.Series if wind_speed is pd.Series (else: np.array)
7185
if isinstance(wind_speed, pd.Series):
7286
power_output = pd.Series(data=power_output, index=wind_speed.index,
7387
name='feedin_wind_turbine')
88+
else:
89+
power_output = np.array(power_output)
7490
return power_output
7591

7692

77-
def cp_curve_density_corr(wind_speed, density, rotor_diameter, cp_values):
78-
r"""
79-
Calculates the turbine power output using a density corrected power
80-
coefficient curve.
81-
82-
This function is carried out when the parameter `power_output_model` of an
83-
instance of the :class:`~.modelchain.ModelChain` class
84-
is 'cp_values' and the parameter `density_corr` is True.
85-
86-
Parameters
87-
----------
88-
wind_speed : pandas.Series or numpy.array
89-
Wind speed at hub height in m/s.
90-
density : pandas.Series or numpy.array
91-
Density of air at hub height in kg/m³.
92-
rotor_diameter : float
93-
Rotor diameter in m.
94-
cp_values : pandas.Series
95-
Power coefficient curve of the wind turbine.
96-
Indices are the wind speeds of the power coefficient curve in m/s.
97-
98-
Returns
99-
-------
100-
pandas.Series or numpy.array
101-
Electrical power of the wind turbine in W.
102-
Data type depends on type of `wind_speed`.
103-
104-
Notes
105-
-----
106-
See :py:func:`cp_curve` for further information on how the power values
107-
are calculated and :py:func:`p_curve_density_corr` for further
108-
information on how the density correction is implemented.
109-
110-
It is assumed that the power output for wind speeds above the maximum
111-
and below the minimum wind speed given in the power coefficient curve is
112-
zero.
113-
114-
"""
115-
p_values = (1 / 8 * 1.225 * rotor_diameter ** 2 * np.pi *
116-
np.power(cp_values.index, 3) * cp_values)
117-
p_values = pd.Series(np.array(p_values), index=cp_values.index)
118-
return p_curve_density_corr(wind_speed, density, p_values)
119-
120-
121-
def power_curve(wind_speed, p_values):
93+
def power_curve(wind_speed, p_values, density=None, density_corr=False):
12294
r"""
12395
Calculates the turbine power output using a power curve.
12496
12597
This function is carried out when the parameter `power_output_model` of an
126-
instance of the :class:`~.modelchain.ModelChain` class is 'p_values' and
127-
the parameter `density_corr` is False.
98+
instance of the :class:`~.modelchain.ModelChain` class is 'p_values'. If
99+
the parameter `density_corr` is True the density corrected power curve
100+
(:py:func:`~._p_curve_density_corr`) is used.
128101
129102
Parameters
130103
----------
@@ -133,6 +106,13 @@ def power_curve(wind_speed, p_values):
133106
p_values : pandas.Series
134107
Power curve of the wind turbine.
135108
Indices are the wind speeds of the power curve in m/s.
109+
density : pandas.Series or numpy.array
110+
Density of air at hub height in kg/m³. This parameter is needed
111+
if `density_corr` is True. Default: None.
112+
density_corr : boolean
113+
If the parameter is True the density corrected power curve is used for
114+
the calculation of the turbine power output. In this case `density`
115+
cannot be None. Default: False.
136116
137117
Returns
138118
-------
@@ -146,16 +126,25 @@ def power_curve(wind_speed, p_values):
146126
and below the minimum wind speed given in the power curve is zero.
147127
148128
"""
149-
power_output = np.interp(wind_speed, p_values.index, p_values,
150-
left=0, right=0)
151-
# Power_output as pd.Series if wind_speed is pd.Series
129+
if density_corr is False:
130+
power_output = np.interp(wind_speed, p_values.index, p_values,
131+
left=0, right=0)
132+
elif density_corr is True:
133+
power_output = _p_curve_density_corr(wind_speed, p_values, density)
134+
else:
135+
raise TypeError("'{0}' is an invalid type.".format(type(
136+
density_corr)) + "`density_corr` must be Boolean " +
137+
"(True or False).")
138+
# Power_output as pd.Series if wind_speed is pd.Series (else: np.array)
152139
if isinstance(wind_speed, pd.Series):
153140
power_output = pd.Series(data=power_output, index=wind_speed.index,
154141
name='feedin_wind_turbine')
142+
else:
143+
power_output = np.array(power_output)
155144
return power_output
156145

157146

158-
def p_curve_density_corr(wind_speed, density, p_values):
147+
def _p_curve_density_corr(wind_speed, p_values, density):
159148
r"""
160149
Calculates the turbine power output using a density corrected power curve.
161150
@@ -167,17 +156,16 @@ def p_curve_density_corr(wind_speed, density, p_values):
167156
----------
168157
wind_speed : pandas.Series or numpy.array
169158
Wind speed time series at hub height in m/s.
170-
density : pandas.Series or numpy.array
171-
Density of air at hub height in kg/m³.
172159
p_values : pandas.Series
173160
Power curve of the wind turbine.
174161
Indices are the wind speeds of the power curve in m/s.
162+
density : pandas.Series or numpy.array
163+
Density of air at hub height in kg/m³.
175164
176165
Returns
177166
-------
178-
pandas.Series or numpy.array
167+
list
179168
Electrical power output of the wind turbine in W.
180-
Data type depends on type of `wind_speed`.
181169
182170
Notes
183171
-----
@@ -219,19 +207,12 @@ def p_curve_density_corr(wind_speed, density, p_values):
219207
at Reiner Lemoine Institute, 2014, p. 13
220208
221209
"""
222-
# Convert density to np.array if wind_speed is np.array
223-
if isinstance(wind_speed, np.ndarray) and isinstance(density, pd.Series):
224-
density = np.array(density)
225-
power_output = [(np.interp(wind_speed[i],
226-
p_values.index * (1.225 / density[i])**(
227-
np.interp(p_values.index,
228-
[7.5, 12.5], [1/3, 2/3])),
229-
p_values, left=0, right=0))
230-
for i in range(len(wind_speed))]
231-
# Power_output as pd.Series if wind_speed is pd.Series
232-
if isinstance(wind_speed, pd.Series):
233-
power_output = pd.Series(data=power_output, index=wind_speed.index,
234-
name='feedin_wind_turbine')
235-
else:
236-
power_output = np.array(power_output)
237-
return power_output
210+
if density is None:
211+
raise TypeError("`density` is None. For the calculation with a " +
212+
"density corrected power curve density at hub height" +
213+
"is needed.")
214+
return[(np.interp(wind_speed[i],
215+
p_values.index * (1.225 / density[i])**(
216+
np.interp(p_values.index, [7.5, 12.5], [1/3, 2/3])),
217+
p_values, left=0, right=0))
218+
for i in range(len(wind_speed))]

0 commit comments

Comments
 (0)