Skip to content

Commit e8911c9

Browse files
committed
Merge branch 'features/tools' into features/tests
Conflicts: windpowerlib/modelchain.py
2 parents e93807d + de984d0 commit e8911c9

File tree

3 files changed

+122
-41
lines changed

3 files changed

+122
-41
lines changed

doc/modules.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,15 @@ Methods of the ModelChain object.
9393

9494
modelchain.ModelChain.rho_hub
9595
modelchain.ModelChain.v_wind_hub
96-
modelchain.ModelChain.turbine_power_output
96+
modelchain.ModelChain.turbine_power_output
97+
98+
99+
Tools
100+
==============
101+
102+
Additional functions used in the windpowerlib.
103+
104+
.. autosummary::
105+
:toctree: temp/
106+
107+
tools.smallest_difference

windpowerlib/modelchain.py

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
__license__ = "GPLv3"
1010

1111
import logging
12-
from windpowerlib import wind_speed, density, power_output
12+
from windpowerlib import wind_speed, density, power_output, tools
1313

1414

1515
class ModelChain(object):
@@ -133,6 +133,8 @@ def rho_hub(self, weather, data_height):
133133
`temp_air` in K and pressure `pressure` in Pa, as well as
134134
optionally the temperature `temp_air_2` in K at a different height
135135
for interpolation.
136+
If a Dictionary is used the data inside the dictionary has to be of
137+
the types pandas.Series or numpy.array.
136138
data_height : DataFrame or Dictionary
137139
Containing columns or keys with the heights in m for which the
138140
corresponding parameters in `weather` apply.
@@ -147,17 +149,22 @@ def rho_hub(self, weather, data_height):
147149
if 'temp_air_2' not in weather:
148150
weather['temp_air_2'] = None
149151
data_height['temp_air_2'] = None
150-
if data_height['temp_air'] == self.wind_turbine.hub_height:
151-
logging.debug('Using given temperature (at hub height).')
152-
temp_hub = weather['temp_air']
153-
elif data_height['temp_air_2'] == self.wind_turbine.hub_height:
154-
logging.debug('Using given temperature (2) (at hub height).')
155-
temp_hub = weather['temp_air_2']
152+
# Select temperature closer to hub height using smallest_difference()
153+
values = tools.smallest_difference(
154+
data_height['temp_air'], data_height['temp_air_2'],
155+
self.wind_turbine.hub_height, weather['temp_air'],
156+
weather['temp_air_2'])
157+
temp_air_height = values.closest_value
158+
temp_air_closest = values.corresp_value
159+
# Check if temperature data is at hub height.
160+
if temp_air_height == self.wind_turbine.hub_height:
161+
logging.debug('Using given temperature ' + values.logging_string)
162+
temp_hub = temp_air_closest
156163
# Calculation of temperature in K at hub height.
157164
elif self.temperature_model == 'gradient':
158165
logging.debug('Calculating temperature using a temp. gradient.')
159166
temp_hub = density.temperature_gradient(
160-
weather['temp_air'], data_height['temp_air'],
167+
temp_air_closest, temp_air_height,
161168
self.wind_turbine.hub_height)
162169
elif self.temperature_model == 'interpolation':
163170
logging.debug('Calculating temperature using interpolation.')
@@ -200,6 +207,8 @@ def v_wind_hub(self, weather, data_height):
200207
Containing columns or keys with the timeseries for wind speed
201208
`v_wind` in m/s and roughness length `z0` in m, as well as
202209
optionally wind speed `v_wind_2` in m/s at different height.
210+
If a Dictionary is used the data inside the dictionary has to be of
211+
the types pandas.Series or numpy.array.
203212
data_height : DataFrame or Dictionary
204213
Containing columns or keys with the heights in m for which the
205214
corresponding parameters in `weather` apply.
@@ -215,44 +224,31 @@ def v_wind_hub(self, weather, data_height):
215224
with `v_wind` of which data height is closer to hub height.
216225
217226
"""
218-
# Check if wind speed data is at hub height.
219227
if 'v_wind_2' not in weather:
220228
weather['v_wind_2'] = None
221229
data_height['v_wind_2'] = None
222-
if data_height['v_wind'] == self.wind_turbine.hub_height:
223-
logging.debug('Using given wind speed (at hub height).')
224-
v_wind = weather['v_wind']
225-
elif data_height['v_wind_2'] == self.wind_turbine.hub_height:
226-
logging.debug('Using given wind speed (2) (at hub height).')
227-
v_wind = weather['v_wind_2']
230+
# Select wind speed closer to hub height using smallest_difference()
231+
values = tools.smallest_difference(
232+
data_height['v_wind'], data_height['v_wind_2'],
233+
self.wind_turbine.hub_height, weather['v_wind'],
234+
weather['v_wind_2'])
235+
v_wind_height = values.closest_value
236+
v_wind_closest = values.corresp_value
237+
# Check if wind speed data is at hub height.
238+
if v_wind_height == self.wind_turbine.hub_height:
239+
logging.debug('Using given wind speed ' + values.logging_string)
240+
v_wind = v_wind_closest
228241
# Calculation of wind speed in m/s at hub height.
229242
elif self.wind_model == 'logarithmic':
230243
logging.debug('Calculating v_wind using logarithmic wind profile.')
231-
if weather['v_wind_2'] is None:
232-
v_wind = wind_speed.logarithmic_wind_profile(
233-
weather['v_wind'], data_height['v_wind'],
234-
self.wind_turbine.hub_height,
235-
weather['z0'], self.obstacle_height)
236-
else:
237-
if (abs(data_height['v_wind'] -
238-
self.wind_turbine.hub_height) <=
239-
abs(data_height['v_wind_2'] -
240-
self.wind_turbine.hub_height)):
241-
v_wind = wind_speed.logarithmic_wind_profile(
242-
weather['v_wind'], data_height['v_wind'],
243-
self.wind_turbine.hub_height, weather['z0'],
244-
self.obstacle_height)
245-
else:
246-
v_wind = wind_speed.logarithmic_wind_profile(
247-
weather['v_wind_2'], data_height['v_wind_2'],
248-
self.wind_turbine.hub_height, weather['z0'],
249-
self.obstacle_height)
244+
v_wind = wind_speed.logarithmic_wind_profile(
245+
v_wind_closest, v_wind_height, self.wind_turbine.hub_height,
246+
weather['z0'], self.obstacle_height)
250247
elif self.wind_model == 'hellman':
251248
logging.debug('Calculating v_wind using hellman equation.')
252-
v_wind = wind_speed.v_wind_hellman(
253-
weather['v_wind'], data_height['v_wind'],
254-
self.wind_turbine.hub_height,
255-
self.hellman_exp, weather['z0'])
249+
v_wind = wind_speed.v_wind_hellman(v_wind_closest, v_wind_height,
250+
self.wind_turbine.hub_height,
251+
self.hellman_exp, weather['z0'])
256252
else:
257253
raise ValueError("'{0}' is an invalid value.".format(
258254
self.wind_model) + "`wind_model` " +
@@ -335,6 +331,8 @@ def run_model(self, weather, data_height):
335331
`temp_air` in K and pressure `pressure` in Pa, as well as
336332
optionally wind speed `v_wind_2` in m/s and temperature
337333
`temp_air_2` in K at different height for interpolation.
334+
If a Dictionary is used the data inside the dictionary has to be of
335+
the types pandas.Series or numpy.array.
338336
data_height : DataFrame or Dictionary
339337
Containing columns or keys with the heights in m for which the
340338
corresponding parameters in `weather` apply.
@@ -345,8 +343,8 @@ def run_model(self, weather, data_height):
345343
346344
"""
347345
v_wind = self.v_wind_hub(weather, data_height)
348-
rho_hub = None if (self.power_output_model=='p_values' and
349-
self.density_corr==False) \
346+
rho_hub = None if (self.power_output_model == 'p_values' and
347+
self.density_corr is False) \
350348
else self.rho_hub(weather, data_height)
351349
self.power_output = self.turbine_power_output(v_wind, rho_hub)
352350
return self

windpowerlib/tools.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"""
2+
The ``tools`` module contains a collection of functions used in the
3+
windpowerlib.
4+
5+
"""
6+
7+
__copyright__ = "Copyright oemof developer group"
8+
__license__ = "GPLv3"
9+
10+
import collections
11+
12+
13+
def smallest_difference(value_1, value_2, comp_value, corresp_1, corresp_2):
14+
r"""
15+
Selects the value with the smaller difference to a comparative value.
16+
17+
Additionally returns a corresponding value. This function is for example
18+
used in :py:func:`~.modelchain.v_wind_hub` of the
19+
:class:`~.modelchain.ModelChain` to choose the wind speed data that is
20+
close to the hub height of the examined wind turbine. In this case
21+
`value_1` and `value_2` are the heights of the corresponding wind speed
22+
data sets `corresp_1` and `corresp_2`.
23+
24+
Parameters
25+
----------
26+
value_1 : float
27+
First value of which the difference to `comp_value` will be
28+
compared with the difference to `comp_value` of `value_2`.
29+
value_2 : float
30+
Second value for comparison.
31+
comp_value : float
32+
Comparative value.
33+
corresp_1 : float
34+
Corresponding value to `value_1`.
35+
corresp_2 : float
36+
Corresponding value to `value_2`.
37+
38+
Returns
39+
-------
40+
Tuple(float, float, string)
41+
Value closer to comparing value as float, corresponding value as
42+
float and a string for logging.debug.
43+
"""
44+
if (value_2 is not None and corresp_2 is not None):
45+
if value_1 == comp_value:
46+
closest_value = value_1
47+
logging_string = '(at hub height).'
48+
elif value_2 == comp_value:
49+
closest_value = value_2
50+
logging_string = '(2) (at hub height).'
51+
elif abs(value_1 - comp_value) <= abs(value_2 - comp_value):
52+
closest_value = value_1
53+
logging_string = None
54+
else:
55+
closest_value = value_2
56+
logging_string = None
57+
else:
58+
closest_value = value_1
59+
logging_string = None
60+
if value_1 == comp_value:
61+
logging_string = '(at hub height).'
62+
63+
# Select correponding value
64+
if closest_value == value_1:
65+
corresp_value = corresp_1
66+
else:
67+
corresp_value = corresp_2
68+
# Store values in a named tuple
69+
return_tuple = collections.namedtuple('selected_values',
70+
['closest_value',
71+
'corresp_value', 'logging_string'])
72+
return return_tuple(closest_value, corresp_value, logging_string)

0 commit comments

Comments
 (0)