Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wind-python / windpowerlib / 118

16 Jan 2019 - 13:23 coverage: 96.774% (+0.1%) from 96.629%
118

Pull #32

travis-ci

9181eb84f9c35729a3bad740fb7f9d93?size=18&default=identiconweb-flow
Revert "Delete csv file containing power and cp curves"

This reverts commit 0f9132aa8.
Pull Request #32: Re-activate the removed csv file

13 of 14 new or added lines in 1 file covered. (92.86%)

420 of 434 relevant lines covered (96.77%)

2.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.06
/windpowerlib/power_curves.py
1
"""
2
The ``power_curves`` module contains functions for applying alterations like
3
power curve smoothing or reducing power values by an efficiency to the power
4
curve of a wind turbine, wind farm or wind turbine cluster.
5

6
"""
7

8
__copyright__ = "Copyright oemof developer group"
3×
9
__license__ = "GPLv3"
3×
10

11
import numpy as np
3×
12
import pandas as pd
3×
13
from windpowerlib import tools
3×
14

15

16
def smooth_power_curve(power_curve_wind_speeds, power_curve_values,
17
                       block_width=0.5, wind_speed_range=15.0,
18
                       standard_deviation_method='turbulence_intensity',
19
                       mean_gauss=0, **kwargs):
20
    r"""
21
    Smooths the input power curve values by using a Gauss distribution.
22

23
    The smoothing serves for taking the distribution of wind speeds over space
24
    into account.
25

26
    Parameters
27
    ----------
28
    power_curve_wind_speeds : pandas.Series or numpy.array
29
        Wind speeds in m/s for which the power curve values are provided in
30
        `power_curve_values`.
31
    power_curve_values : pandas.Series or numpy.array
32
        Power curve values corresponding to wind speeds in
33
        `power_curve_wind_speeds`.
34
    block_width : float
35
        Width between the wind speeds in the sum of equation :eq:`power`.
36
        Default: 0.5.
37
    wind_speed_range : float
38
        The sum in the equation below is taken for this wind speed range below
39
        and above the power curve wind speed. Default: 15.0.
40
    standard_deviation_method : string
41
        Method for calculating the standard deviation for the Gauss
42
        distribution. Options: 'turbulence_intensity', 'Staffell_Pfenninger'.
43
        Default: 'turbulence_intensity'.
44
    mean_gauss : float
45
        Mean of the Gauss distribution in
46
        :py:func:`~.tools.gauss_distribution`. Default: 0.
47

48
    Other Parameters
49
    ----------------
50
    turbulence intensity : float, optional
51
        Turbulence intensity at hub height of the wind turbine, wind farm or
52
        wind turbine cluster the power curve is smoothed for.
53

54
    Returns
55
    -------
56
    smoothed_power_curve_df : pd.DataFrame
57
        Smoothed power curve. DataFrame has 'wind_speed' and 'power' columns
58
        with wind speeds in m/s and the corresponding power curve value in W.
59

60
    Notes
61
    -----
62
    The following equation is used to calculated the power curves values of the
63
    smoothed power curve [1]_:
64

65
    .. math:: P_{smoothed}(v_{std}) = \sum\limits_{v_i} \Delta v_i \cdot P(v_i)
66
        \cdot \frac{1}{\sigma \sqrt{2 \pi}}
67
        \exp \left[-\frac{(v_{std} - v_i -\mu)^2}{2 \sigma^2} \right]
68
       :label: power
69

70
    with:
71
        P: power [W], v: wind speed [m/s],
72
        :math:`\sigma`: standard deviation (Gauss), :math:`\mu`: mean (Gauss)
73

74
        :math:`P_{smoothed}` is the smoothed power curve value,
75
        :math:`v_{std}` is the standard wind speed in the power curve,
76
        :math:`\Delta v_i` is the interval length between
77
        :math:`v_\text{i}` and :math:`v_\text{i+1}`
78

79
    Power curve smoothing is applied to take account for the spatial
80
    distribution of wind speed. This way of smoothing power curves is also used
81
    in [2]_ and [3]_.
82

83
    The standard deviation :math:`\sigma` of the above equation can be
84
    calculated by the following methods.
85

86
    'turbulence_intensity' [2]_:
87

88
    .. math:: \sigma = v_\text{std} \sigma_\text{n} = v_\text{std} TI
89

90
    with:
91
        TI: turbulence intensity
92

93
    'Staffell_Pfenninger' [4]_:
94

95
    .. math:: \sigma = 0.6 \cdot 0.2 \cdot v_\text{std}
96

97
    References
98
    ----------
99
    .. [1]  Knorr, K.: "Modellierung von raum-zeitlichen Eigenschaften der
100
             Windenergieeinspeisung f��r wetterdatenbasierte
101
             Windleistungssimulationen". Universit��t Kassel, Diss., 2016,
102
             p. 106
103
    .. [2]  N��rgaard, P. and Holttinen, H.: "A Multi-Turbine and Power Curve
104
             Approach". Nordic Wind Power Conference, 1.���2.3.2004, 2000, p. 5
105
    .. [3]  Kohler, S. and Agricola, A.-Cl. and Seidl, H.:
106
             "dena-Netzstudie II. Integration erneuerbarer Energien in die
107
             deutsche Stromversorgung im Zeitraum 2015 ��� 2020 mit Ausblick
108
             2025". Technical report, 2010.
109
    .. [4]  Staffell, I. and Pfenninger, S.: "Using Bias-Corrected Reanalysis
110
              to Simulate Current and Future Wind Power Output". 2005, p. 11
111

112
    """
113
    # Specify normalized standard deviation
114
    if standard_deviation_method == 'turbulence_intensity':
115
        if ('turbulence_intensity' in kwargs and
116
                kwargs['turbulence_intensity'] is not np.nan):
117
            normalized_standard_deviation = kwargs['turbulence_intensity']
3×
118
        else:
119
            raise ValueError("Turbulence intensity must be defined for " +
3×
120
                             "using 'turbulence_intensity' as " +
121
                             "`standard_deviation_method`")
122
    elif standard_deviation_method == 'Staffell_Pfenninger':
123
        normalized_standard_deviation = 0.2
124
    else:
125
        raise ValueError("{} is no valid `standard_deviation_method`. Valid "
3×
126
                         + "options are 'turbulence_intensity', or "
127
                         + "'Staffell_Pfenninger'".format(
128
            standard_deviation_method))
129
    # Initialize list for power curve values
130
    smoothed_power_curve_values = []
131
    # Append wind speeds to `power_curve_wind_speeds`
132
    maximum_value = power_curve_wind_speeds.values[-1] + wind_speed_range
3×
133
    while power_curve_wind_speeds.values[-1] < maximum_value:
134
        power_curve_wind_speeds = power_curve_wind_speeds.append(
3×
135
            pd.Series(power_curve_wind_speeds.iloc[-1] + 0.5,
136
                      index=[power_curve_wind_speeds.index[-1] + 1]))
137
        power_curve_values = power_curve_values.append(
138
            pd.Series(0.0, index=[power_curve_values.index[-1] + 1]))
139
    for power_curve_wind_speed in power_curve_wind_speeds:
3×
140
        # Create array of wind speeds for the sum
141
        wind_speeds_block = (np.arange(
3×
142
            -wind_speed_range, wind_speed_range + block_width, block_width) +
143
            power_curve_wind_speed)
144
        # Get standard deviation for Gauss function
145
        standard_deviation = (
146
            (power_curve_wind_speed * normalized_standard_deviation + 0.6)
147
            if standard_deviation_method is 'Staffell_Pfenninger'
148
            else power_curve_wind_speed * normalized_standard_deviation)
149
        # Get the smoothed value of the power output
150
        if standard_deviation == 0.0:
151
            # The gaussian distribution is not defined for a standard deviation
152
            # of zero. Smoothed power curve value is set to zero.
153
            smoothed_value = 0.0
154
        else:
155
            smoothed_value = sum(
3×
156
                block_width * np.interp(wind_speed, power_curve_wind_speeds,
157
                                        power_curve_values, left=0, right=0) *
158
                tools.gauss_distribution(
159
                    power_curve_wind_speed - wind_speed,
160
                    standard_deviation, mean_gauss)
161
                for wind_speed in wind_speeds_block)
162
        # Add value to list - add zero if `smoothed_value` is nan as Gauss
163
        # distribution for a standard deviation of zero.
164
        smoothed_power_curve_values.append(smoothed_value)
165
    # Create smoothed power curve data frame
166
    smoothed_power_curve_df = pd.DataFrame(
3×
167
        data=[list(power_curve_wind_speeds.values),
168
              smoothed_power_curve_values]).transpose()
169
    # Rename columns of the data frame
170
    smoothed_power_curve_df.columns = ['wind_speed', 'power']
171
    return smoothed_power_curve_df
172

173

174
def wake_losses_to_power_curve(power_curve_wind_speeds, power_curve_values,
175
                               wind_farm_efficiency,
176
                               wake_losses_model='power_efficiency_curve'):
177
    r"""
178
    Reduces the power values of a power curve by an efficiency (curve).
179

180
    Parameters
181
    ----------
182
    power_curve_wind_speeds : pandas.Series or numpy.array
183
        Wind speeds in m/s for which the power curve values are provided in
184
        `power_curve_values`.
185
    power_curve_values : pandas.Series or numpy.array
186
        Power curve values corresponding to wind speeds in
187
        `power_curve_wind_speeds`.
188
    wind_farm_efficiency : float or pd.DataFrame
189
        Efficiency of the wind farm. Either constant (float) or efficiency
190
        curve (pd.DataFrame) containing 'wind_speed' and 'efficiency' columns
191
        with wind speeds in m/s and the corresponding dimensionless wind farm
192
        efficiency (reduction of power). Default: None.
193
    wake_losses_model : String
194
        Defines the method for taking wake losses within the farm into
195
        consideration. Options: 'power_efficiency_curve',
196
        'constant_efficiency'. Default: 'power_efficiency_curve'.
197

198
    Returns
199
    -------
200
    power_curve_df : pd.DataFrame
201
        Power curve with power values reduced by a wind farm efficiency.
202
        DataFrame has 'wind_speed' and 'power' columns with wind speeds in m/s
203
        and the corresponding power curve value in W.
204

205
    """
206
    # Create power curve DataFrame
207
    power_curve_df = pd.DataFrame(
208
        data=[list(power_curve_wind_speeds),
209
              list(power_curve_values)]).transpose()
210
    # Rename columns of DataFrame
211
    power_curve_df.columns = ['wind_speed', 'power']
212
    if wake_losses_model == 'constant_efficiency':
213
        if not isinstance(wind_farm_efficiency, float):
3×
214
            raise TypeError("'wind_farm_efficiency' must be float if " +
3×
215
                            "`wake_losses_model�� is '{}' but is {}".format(
216
                                wake_losses_model, wind_farm_efficiency))
217
        power_curve_df['power'] = power_curve_values * wind_farm_efficiency
218
    elif wake_losses_model == 'power_efficiency_curve':
219
        if (not isinstance(wind_farm_efficiency, dict) and
3×
220
                not isinstance(wind_farm_efficiency, pd.DataFrame)):
221
            raise TypeError(
2×
222
                "'wind_farm_efficiency' must be pd.DataFrame if " +
223
                "`wake_losses_model�� is '{}' but is {}".format(
224
                    wake_losses_model, wind_farm_efficiency))
225
        df = pd.concat([power_curve_df.set_index('wind_speed'),
226
                        wind_farm_efficiency.set_index('wind_speed')], axis=1)
227
        # Add column with reduced power (nan values of efficiency are interpolated)
228
        df['reduced_power'] = df['power'] * df['efficiency'].interpolate(
229
            method='index')
230
        reduced_power = df['reduced_power'].dropna()
3×
231
        power_curve_df = pd.DataFrame([reduced_power.index,
232
                                       reduced_power.values]).transpose()
233
        power_curve_df.columns = ['wind_speed', 'power']
3×
234
    else:
235
        raise ValueError(
2×
236
            "`wake_losses_model` is {} but should be ".format(
237
                wake_losses_model) +
238
            "'constant_efficiency' or 'power_efficiency_curve'")
239
    return power_curve_df
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2023 Coveralls, Inc