66__copyright__ = "Copyright oemof developer group"
77__license__ = "GPLv3"
88
9- import logging
109import os
1110import pandas as pd
1211
1817from windpowerlib import modelchain
1918from windpowerlib import wind_turbine as wt
2019
21- # Feel free to remove or change these lines
22- # import warnings
23- # warnings.simplefilter(action="ignore", category=RuntimeWarning)
20+ # You can use the logging package to get logging messages from the windpowerlib
21+ # Change the logging level if you want more or less messages
22+ import logging
2423logging .getLogger ().setLevel (logging .DEBUG )
2524
2625
27- def read_weather_data (filename , datetime_column = 'time_index' ,
28- ** kwargs ):
26+ def get_weather_data (filename , datetime_column = 'time_index' , ** kwargs ):
2927 r"""
30- Fetches weather data from a file.
28+ Imports weather data from a file and specifies height of weather data .
3129
32- The files are located in the example folder of the windpowerlib.
30+ The data include wind speed at two different heights in m/s, air
31+ temperature in two different heights in K, surface roughness length in m
32+ and air pressure in Pa.
3333
3434 Parameters
3535 ----------
3636 filename : string
3737 Filename of the weather data file.
3838 datetime_column : string
39- Name of the datetime column of the weather DataFrame.
39+ Name of the datetime column of the weather DataFrame.
40+ Default: 'time_index'.
4041
4142 Other Parameters
4243 ----------------
@@ -46,93 +47,215 @@ def read_weather_data(filename, datetime_column='time_index',
4647
4748 Returns
4849 -------
49- pandas.DataFrame
50+ Tuple (pd.DataFrame, dictionary)
51+ `weather` DataFrame contains weather data time series.
52+ `data_height` dictionary contains height for which corresponding
53+ weather data applies.
54+
55+ """
56+ def read_weather_data (filename , datetime_column = 'time_index' ,
57+ ** kwargs ):
58+ r"""
59+ Fetches weather data from a file.
60+
61+ The file is located in the example folder of the windpowerlib.
62+
63+ Parameters
64+ ----------
65+ filename : string
66+ Filename of the weather data file.
67+ datetime_column : string
68+ Name of the datetime column of the weather DataFrame.
69+
70+ Other Parameters
71+ ----------------
72+ datapath : string, optional
73+ Path where the weather data file is stored.
74+ Default: 'windpowerlib/example'.
75+
76+ Returns
77+ -------
78+ pandas.DataFrame
79+ Contains weather data time series.
80+
81+ """
82+ if 'datapath' not in kwargs :
83+ kwargs ['datapath' ] = os .path .join (os .path .split (
84+ os .path .dirname (__file__ ))[0 ], 'example' )
85+
86+ file = os .path .join (kwargs ['datapath' ], filename )
87+ df = pd .read_csv (file )
88+ return df .set_index (pd .to_datetime (df [datetime_column ])).tz_localize (
89+ 'UTC' ).tz_convert ('Europe/Berlin' ).drop (datetime_column , 1 )
90+
91+ # read weather data from csv
92+ weather = read_weather_data (filename = filename ,
93+ datetime_column = datetime_column , ** kwargs )
94+
95+ # dictionary specifying the height for which the weather data applies
96+ # data in m
97+ data_height = {
98+ 'pressure' : 0 ,
99+ 'temp_air' : 2 ,
100+ 'v_wind' : 10 ,
101+ 'temp_air_2' : 10 ,
102+ 'v_wind_2' : 80 }
103+
104+ return (weather , data_height )
105+
106+
107+ # TODO markdown for code snippet
108+ def initialise_wind_turbines ():
109+ r"""
110+ Initialises two :class:`~.wind_turbine.WindTurbine` objects.
111+
112+ Function shows two ways to initialise a WindTurbine object. You can either
113+ specify your own turbine, as done below for 'myTurbine', or fetch power
114+ and/or power coefficient curve data from data files provided by the
115+ windpowerlib, as done for the 'enerconE126'. Execute
116+ windpowerlib.wind_turbine.get_turbine_types() or
117+ windpowerlib.wind_turbine.get_turbine_types(filename='cp_curves.csv')
118+ to get a list of all wind turbines for which power or power coefficient
119+ curves, respectively, are provided.
120+
121+ Returns
122+ -------
123+ Tuple (WindTurbine, WindTurbine)
124+
125+ """
126+
127+ # specification of own wind turbine (Note: power coefficient values and
128+ # nominal power have to be in Watt)
129+ myTurbine = {
130+ 'turbine_name' : 'myTurbine' ,
131+ 'nominal_power' : 3e6 , # in W
132+ 'hub_height' : 105 , # in m
133+ 'd_rotor' : 90 , # in m
134+ 'p_values' : pd .DataFrame (
135+ data = {'p' : [p * 1000 for p in
136+ [0.0 , 26.0 , 180.0 , 1500.0 , 3000.0 , 3000.0 ]]}, # in W
137+ index = [0.0 , 3.0 , 5.0 , 10.0 , 15.0 , 25.0 ]) # in m/s
138+ }
139+ # initialise WindTurbine object
140+ my_turbine = wt .WindTurbine (** myTurbine )
141+
142+ # specification of wind turbine where power curve is provided
143+ # if you want to use the power coefficient curve add {'fetch_curve': 'cp'}
144+ # to the dictionary
145+ enerconE126 = {
146+ 'turbine_name' : 'ENERCON E 126 7500' , # turbine name as in register
147+ 'hub_height' : 135 , # in m
148+ 'd_rotor' : 127 # in m
149+ }
150+ # initialise WindTurbine object
151+ e126 = wt .WindTurbine (** enerconE126 )
152+
153+ return (my_turbine , e126 )
154+
155+
156+ def calculate_power_output (weather , data_height , my_turbine , e126 ):
157+ r"""
158+ Calculates power output of wind turbines using the
159+ :class:`~.modelchain.ModelChain`.
160+
161+ The :class:`~.modelchain.ModelChain` is a class that provides all necessary
162+ steps to calculate the power output of a wind turbine. You can either use
163+ the default methods for the calculation steps, as done for 'my_turbine',
164+ or choose different methods, as done for the 'e126'.
165+
166+ Parameters
167+ ----------
168+ weather : pd.DataFrame
50169 Contains weather data time series.
170+ data_height : dictionary
171+ Contains height for which corresponding weather data applies.
172+ my_turbine : WindTurbine
173+ WindTurbine object with self provided power curve.
174+ e126 : WindTurbine
175+ WindTurbine object with power curve from data file provided by the
176+ windpowerlib.
51177
52178 """
53- if 'datapath' not in kwargs :
54- kwargs ['datapath' ] = os .path .join (os .path .split (
55- os .path .dirname (__file__ ))[0 ], 'example' )
56-
57- file = os .path .join (kwargs ['datapath' ], filename )
58- df = pd .read_csv (file )
59- return df .set_index (pd .to_datetime (df [datetime_column ])).tz_localize (
60- 'UTC' ).tz_convert ('Europe/Berlin' ).drop (datetime_column , 1 )
61-
62- # Read weather data from csv
63- weather = read_weather_data ('weather.csv' )
64-
65- # Specification of the weather data set CoastDat2 (example data)
66- data_height = {
67- 'pressure' : 0 ,
68- 'temp_air' : 2 ,
69- 'v_wind' : 10 ,
70- 'temp_air_2' : 10 ,
71- 'v_wind_2' : 80 }
72-
73- # Specifications of the wind turbines
74- enerconE126 = {
75- 'hub_height' : 135 ,
76- 'd_rotor' : 127 ,
77- 'fetch_curve' : 'p' , # 'p' for p-curve and 'cp' for cp-curve
78- 'turbine_name' : 'ENERCON E 126 7500' } # Turbine name as in register. Use
79- # wind_turbine.get_turbine_types()
80- # for a full list.
81- vestasV90 = {
82- 'hub_height' : 105 ,
83- 'd_rotor' : 90 ,
84- 'fetch_curve' : 'p' ,
85- 'turbine_name' : 'VESTAS V 90 3000' }
86-
87- # Initialize WindTurbine objects
88- e126 = wt .WindTurbine (** enerconE126 )
89- v90 = wt .WindTurbine (** vestasV90 )
90-
91- # Specifications of the modelchain data
92- modelchain_data = {
93- 'obstacle_height' : 0 ,
94- 'wind_model' : 'logarithmic' , # 'logarithmic' or 'hellman'
95- 'rho_model' : 'ideal_gas' , # 'barometric' or 'ideal_gas'
96- 'power_output_model' : 'p_values' , # 'p_values' or 'cp_values'
97- 'density_corr' : False , # True or False
98- 'hellman_exp' : None } # Float or None
99-
100- # Calculate turbine power output
101- mc_e126 = modelchain .ModelChain (e126 , ** modelchain_data ).run_model (
102- weather , data_height )
103- e126 .power_output = mc_e126 .power_output
104- mc_v90 = modelchain .ModelChain (v90 , ** modelchain_data ).run_model (
105- weather , data_height )
106- v90 .power_output = mc_v90 .power_output
107-
108- # Plot turbine power output
109- if plt :
110- e126 .power_output .plot (legend = True , label = 'Enercon E126' )
111- v90 .power_output .plot (legend = True , label = 'Vestas V90' )
112- plt .show ()
113- else :
114- print (e126 .power_output )
115- print (v90 .power_output )
116-
117- # Plot power (coefficient) curves
118- if plt :
119- if e126 .cp_values is not None :
120- e126 .cp_values .plot (style = '*' , title = 'Enercon E126' )
121- plt .show ()
122- if e126 .p_values is not None :
123- e126 .p_values .plot (style = '*' , title = 'Enercon E126' )
124- plt .show ()
125- if v90 .cp_values is not None :
126- v90 .cp_values .plot (style = '*' , title = 'Vestas V90' )
127- plt .show ()
128- if v90 .p_values is not None :
129- v90 .p_values .plot (style = '*' , title = 'Vestas V90' )
179+
180+ # power output calculation for my_turbine
181+ # initialise ModelChain with default parameters and use run_model method
182+ # to calculate power output
183+ mc_my_turbine = modelchain .ModelChain (my_turbine ).run_model (
184+ weather , data_height )
185+ # write power output timeseries to WindTurbine object
186+ my_turbine .power_output = mc_my_turbine .power_output
187+
188+ # power output calculation for e126
189+ # own specifications for ModelChain setup
190+ modelchain_data = {
191+ 'obstacle_height' : 0 , # default: 0
192+ 'wind_model' : 'logarithmic' , # 'logarithmic' (default) or 'hellman'
193+ 'rho_model' : 'ideal_gas' , # 'barometric' (default) or 'ideal_gas'
194+ 'power_output_model' : 'p_values' , # 'p_values' (default) or
195+ # 'cp_values'
196+ 'density_corr' : True , # False (default) or True
197+ 'hellman_exp' : None } # None (default) or None
198+ # initialise ModelChain with own specifications and use run_model method
199+ # to calculate power output
200+ mc_e126 = modelchain .ModelChain (e126 , ** modelchain_data ).run_model (
201+ weather , data_height )
202+ # write power output timeseries to WindTurbine object
203+ e126 .power_output = mc_e126 .power_output
204+
205+ return
206+
207+
208+ def plot_or_print (my_turbine , e126 ):
209+ r"""
210+ Plots or prints power output and power (coefficient) curves.
211+
212+ Parameters
213+ ----------
214+ my_turbine : WindTurbine
215+ WindTurbine object with self provided power curve.
216+ e126 : WindTurbine
217+ WindTurbine object with power curve from data file provided by the
218+ windpowerlib.
219+
220+ """
221+
222+ # plot or print turbine power output
223+ if plt :
224+ e126 .power_output .plot (legend = True , label = 'Enercon E126' )
225+ my_turbine .power_output .plot (legend = True , label = 'myTurbine' )
130226 plt .show ()
131- else :
132- if e126 .cp_values is not None :
133- print ("The cp value at a wind speed of 5 m/s: {0}" .format (
134- e126 .cp_values .cp [5.0 ]))
135- if e126 .p_values is not None :
136- print ("The P value at a wind speed of 5 m/s: {0}" .format (
137- e126 .p_values .P [5.0 ]))
138- logging .info ('Done!' )
227+ else :
228+ print (e126 .power_output )
229+ print (my_turbine .power_output )
230+
231+ # plot or print power (coefficient) curve
232+ if plt :
233+ if e126 .cp_values is not None :
234+ e126 .cp_values .plot (style = '*' , title = 'Enercon E126' )
235+ plt .show ()
236+ if e126 .p_values is not None :
237+ e126 .p_values .plot (style = '*' , title = 'Enercon E126' )
238+ plt .show ()
239+ if my_turbine .cp_values is not None :
240+ my_turbine .cp_values .plot (style = '*' , title = 'myTurbine' )
241+ plt .show ()
242+ if my_turbine .p_values is not None :
243+ my_turbine .p_values .plot (style = '*' , title = 'myTurbine' )
244+ plt .show ()
245+ else :
246+ if e126 .cp_values is not None :
247+ print (e126 .cp_values )
248+ if e126 .p_values is not None :
249+ print ("The P value at a wind speed of 5 m/s: {0}" .format (
250+ e126 .p_values .P [5.0 ]))
251+
252+
253+ def run_basic_example ():
254+ weather , data_height = get_weather_data ('weather.csv' )
255+ my_turbine , e126 = initialise_wind_turbines ()
256+ calculate_power_output (weather , data_height , my_turbine , e126 )
257+ plot_or_print (my_turbine , e126 )
258+
259+
260+ if __name__ == "__main__" :
261+ run_basic_example ()
0 commit comments