sazirarrwth99 commited on
Commit
7c5ffc3
·
1 Parent(s): a0849be

Upload modelchain_example.py

Browse files
Files changed (1) hide show
  1. modelchain_example.py +324 -0
modelchain_example.py ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ The ``modelchain_example`` module shows a simple usage of the windpowerlib by
3
+ using the :class:`~.modelchain.ModelChain` class. The modelchains are
4
+ implemented to ensure an easy start into the Windpowerlib. They work like
5
+ models that combine all functions provided in the library. Via parameters
6
+ desired functions of the windpowerlib can be selected. For parameters not being
7
+ specified default parameters are used.
8
+
9
+ There are mainly three steps. First you have to import your weather data, then
10
+ you need to specify your wind turbine, and in the last step call the
11
+ windpowerlib functions to calculate the feed-in time series.
12
+
13
+ Install the windpowerlib and optionally matplotlib to see the plots:
14
+
15
+ pip install windpowerlib
16
+ pip install matplotlib
17
+
18
+ Go down to the "run_example()" function to start the example.
19
+
20
+ SPDX-FileCopyrightText: 2019 oemof developer group <[email protected]>
21
+ SPDX-License-Identifier: MIT
22
+ """
23
+ import os
24
+ import pandas as pd
25
+ import requests
26
+ import logging
27
+ from windpowerlib import ModelChain, WindTurbine, create_power_curve
28
+
29
+ try:
30
+ from matplotlib import pyplot as plt
31
+ except ImportError:
32
+ plt = None
33
+
34
+
35
+ def get_weather_data(filename="weather.csv", **kwargs):
36
+ r"""
37
+ Imports weather data from a file.
38
+
39
+ The data include wind speed at two different heights in m/s, air
40
+ temperature in two different heights in K, surface roughness length in m
41
+ and air pressure in Pa. The height in m for which the data applies is
42
+ specified in the second row.
43
+ In case no weather data file exists, an example weather data file is
44
+ automatically downloaded and stored in the same directory as this example.
45
+
46
+ Parameters
47
+ ----------
48
+ filename : str
49
+ Filename of the weather data file. Default: 'weather.csv'.
50
+
51
+ Other Parameters
52
+ ----------------
53
+ datapath : str, optional
54
+ Path where the weather data file is stored.
55
+ Default is the same directory this example is stored in.
56
+
57
+ Returns
58
+ -------
59
+ :pandas:`pandas.DataFrame<frame>`
60
+ DataFrame with time series for wind speed `wind_speed` in m/s,
61
+ temperature `temperature` in K, roughness length `roughness_length`
62
+ in m, and pressure `pressure` in Pa.
63
+ The columns of the DataFrame are a MultiIndex where the first level
64
+ contains the variable name as string (e.g. 'wind_speed') and the
65
+ second level contains the height as integer at which it applies
66
+ (e.g. 10, if it was measured at a height of 10 m). The index is a
67
+ DateTimeIndex.
68
+
69
+ """
70
+
71
+ if "datapath" not in kwargs:
72
+ kwargs["datapath"] = os.path.dirname(__file__)
73
+
74
+ file = os.path.join(kwargs["datapath"], filename)
75
+
76
+ # download example weather data file in case it does not yet exist
77
+ if not os.path.isfile(file):
78
+ logging.debug("Download weather data for example.")
79
+ req = requests.get("https://osf.io/59bqn/download")
80
+ with open(file, "wb") as fout:
81
+ fout.write(req.content)
82
+
83
+ # read csv file
84
+ weather_df = pd.read_csv(
85
+ file,
86
+ index_col=0,
87
+ header=[0, 1],
88
+ date_parser=lambda idx: pd.to_datetime(idx, utc=True),
89
+ )
90
+
91
+ # change time zone
92
+ weather_df.index = weather_df.index.tz_convert("Europe/Berlin")
93
+
94
+ return weather_df
95
+
96
+
97
+ def initialize_wind_turbines():
98
+ r"""
99
+ Initializes three :class:`~.wind_turbine.WindTurbine` objects.
100
+
101
+ This function shows three ways to initialize a WindTurbine object. You can
102
+ either use turbine data from the OpenEnergy Database (oedb) turbine library
103
+ that is provided along with the windpowerlib, as done for the
104
+ 'enercon_e126', or specify your own turbine by directly providing a power
105
+ (coefficient) curve, as done below for 'my_turbine', or provide your own
106
+ turbine data in csv files, as done for 'my_turbine2'.
107
+
108
+ To get a list of all wind turbines for which power and/or power coefficient
109
+ curves are provided execute `
110
+ `windpowerlib.wind_turbine.get_turbine_types()``.
111
+
112
+ Returns
113
+ -------
114
+ Tuple (:class:`~.wind_turbine.WindTurbine`,
115
+ :class:`~.wind_turbine.WindTurbine`,
116
+ :class:`~.wind_turbine.WindTurbine`)
117
+
118
+ """
119
+ # ************************************************************************
120
+ # **** Data is provided in the oedb turbine library **********************
121
+
122
+ enercon_e126 = {
123
+ "turbine_type": "E-126/4200", # turbine type as in register
124
+ "hub_height": 135, # in m
125
+ }
126
+ e126 = WindTurbine(**enercon_e126)
127
+
128
+ # ************************************************************************
129
+ # **** Specification of wind turbine with your own data ******************
130
+ # **** NOTE: power values and nominal power have to be in Watt
131
+
132
+ my_turbine = {
133
+ "nominal_power": 3e6, # in W
134
+ "hub_height": 105, # in m
135
+ "power_curve": pd.DataFrame(
136
+ data={
137
+ "value": [
138
+ p * 1000
139
+ for p in [0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]
140
+ ], # in W
141
+ "wind_speed": [0.0, 3.0, 5.0, 10.0, 15.0, 25.0],
142
+ }
143
+ ), # in m/s
144
+ }
145
+ my_turbine = WindTurbine(**my_turbine)
146
+
147
+ # ************************************************************************
148
+ # **** Specification of wind turbine with data in own file ***************
149
+
150
+ # Read your turbine data from your data file using functions like
151
+ # pandas.read_csv().
152
+ # >>> import pandas as pd
153
+ # >>> my_data = pd.read_csv("path/to/my/data/file")
154
+ # >>> my_power = my_data["my_power"]
155
+ # >>> my_wind_speed = my_data["my_wind_speed"]
156
+
157
+ my_power = pd.Series(
158
+ [0.0, 39000.0, 270000.0, 2250000.0, 4500000.0, 4500000.0]
159
+ )
160
+ my_wind_speed = (0.0, 3.0, 5.0, 10.0, 15.0, 25.0)
161
+
162
+ my_turbine2 = {
163
+ "nominal_power": 6e6, # in W
164
+ "hub_height": 115, # in m
165
+ "power_curve": create_power_curve(
166
+ wind_speed=my_wind_speed, power=my_power
167
+ ),
168
+ }
169
+ my_turbine2 = WindTurbine(**my_turbine2)
170
+
171
+ return my_turbine, e126, my_turbine2
172
+
173
+
174
+ def calculate_power_output(weather, my_turbine, e126, my_turbine2):
175
+ r"""
176
+ Calculates power output of wind turbines using the
177
+ :class:`~.modelchain.ModelChain`.
178
+
179
+ The :class:`~.modelchain.ModelChain` is a class that provides all necessary
180
+ steps to calculate the power output of a wind turbine. You can either use
181
+ the default methods for the calculation steps, as done for 'my_turbine',
182
+ or choose different methods, as done for the 'e126'. Of course, you can
183
+ also use the default methods while only changing one or two of them, as
184
+ done for 'my_turbine2'.
185
+
186
+ Parameters
187
+ ----------
188
+ weather : :pandas:`pandas.DataFrame<frame>`
189
+ Contains weather data time series.
190
+ my_turbine : :class:`~.wind_turbine.WindTurbine`
191
+ WindTurbine object with self provided power curve.
192
+ e126 : :class:`~.wind_turbine.WindTurbine`
193
+ WindTurbine object with power curve from the OpenEnergy Database
194
+ turbine library.
195
+ my_turbine2 : :class:`~.wind_turbine.WindTurbine`
196
+ WindTurbine object with power coefficient curve from example file.
197
+
198
+ """
199
+
200
+ # ************************************************************************
201
+ # **** ModelChain with non-default specifications ************************
202
+ modelchain_data = {
203
+ "wind_speed_model": "logarithmic", # 'logarithmic' (default),
204
+ # 'hellman' or
205
+ # 'interpolation_extrapolation'
206
+ "density_model": "ideal_gas", # 'barometric' (default), 'ideal_gas' or
207
+ # 'interpolation_extrapolation'
208
+ "temperature_model": "linear_gradient", # 'linear_gradient' (def.) or
209
+ # 'interpolation_extrapolation'
210
+ "power_output_model": "power_coefficient_curve", # 'power_curve'
211
+ # (default) or 'power_coefficient_curve'
212
+ "density_correction": True, # False (default) or True
213
+ "obstacle_height": 0, # default: 0
214
+ "hellman_exp": None,
215
+ } # None (default) or None
216
+ # initialize ModelChain with own specifications and use run_model method
217
+ # to calculate power output
218
+ mc_e126 = ModelChain(e126, **modelchain_data).run_model(weather)
219
+ # write power output time series to WindTurbine object
220
+ e126.power_output = mc_e126.power_output
221
+
222
+ # ************************************************************************
223
+ # **** ModelChain with default parameter *********************************
224
+ mc_my_turbine = ModelChain(my_turbine).run_model(weather)
225
+ # write power output time series to WindTurbine object
226
+ my_turbine.power_output = mc_my_turbine.power_output
227
+
228
+ # ************************************************************************
229
+ # **** ModelChain with non-default value for "wind_speed_model" **********
230
+ mc_example_turbine = ModelChain(
231
+ my_turbine2, wind_speed_model="hellman"
232
+ ).run_model(weather)
233
+ my_turbine2.power_output = mc_example_turbine.power_output
234
+
235
+ return
236
+
237
+
238
+ def plot_or_print(my_turbine, e126, my_turbine2):
239
+ r"""
240
+ Plots or prints power output and power (coefficient) curves.
241
+
242
+ Parameters
243
+ ----------
244
+ my_turbine : :class:`~.wind_turbine.WindTurbine`
245
+ WindTurbine object with self provided power curve.
246
+ e126 : :class:`~.wind_turbine.WindTurbine`
247
+ WindTurbine object with power curve from the OpenEnergy Database
248
+ turbine library.
249
+ my_turbine2 : :class:`~.wind_turbine.WindTurbine`
250
+ WindTurbine object with power coefficient curve from example file.
251
+
252
+ """
253
+
254
+ # plot or print turbine power output
255
+ if plt:
256
+ e126.power_output.plot(legend=True, label="Enercon E126")
257
+ my_turbine.power_output.plot(legend=True, label="myTurbine")
258
+ my_turbine2.power_output.plot(legend=True, label="myTurbine2")
259
+ plt.xlabel("Time")
260
+ plt.ylabel("Power in W")
261
+ plt.show()
262
+ else:
263
+ print(e126.power_output)
264
+ print(my_turbine.power_output)
265
+ print(my_turbine2.power_output)
266
+
267
+ # plot or print power curve
268
+ if plt:
269
+ if e126.power_curve is not False:
270
+ e126.power_curve.plot(
271
+ x="wind_speed",
272
+ y="value",
273
+ style="*",
274
+ title="Enercon E126 power curve",
275
+ )
276
+ plt.xlabel("Wind speed in m/s")
277
+ plt.ylabel("Power in W")
278
+ plt.show()
279
+ if my_turbine.power_curve is not False:
280
+ my_turbine.power_curve.plot(
281
+ x="wind_speed",
282
+ y="value",
283
+ style="*",
284
+ title="myTurbine power curve",
285
+ )
286
+ plt.xlabel("Wind speed in m/s")
287
+ plt.ylabel("Power in W")
288
+ plt.show()
289
+ if my_turbine2.power_curve is not False:
290
+ my_turbine2.power_curve.plot(
291
+ x="wind_speed",
292
+ y="value",
293
+ style="*",
294
+ title="myTurbine2 power curve",
295
+ )
296
+ plt.xlabel("Wind speed in m/s")
297
+ plt.ylabel("Power in W")
298
+ plt.show()
299
+ else:
300
+ if e126.power_coefficient_curve is not False:
301
+ print(e126.power_coefficient_curve)
302
+ if e126.power_curve is not False:
303
+ print(e126.power_curve)
304
+
305
+
306
+ def run_example():
307
+ r"""
308
+ Runs the basic example.
309
+
310
+ """
311
+ # You can use the logging package to get logging messages from the
312
+ # windpowerlib. Change the logging level if you want more or less messages:
313
+ # logging.DEBUG -> many messages
314
+ # logging.INFO -> few messages
315
+ logging.getLogger().setLevel(logging.DEBUG)
316
+
317
+ weather = get_weather_data("weather.csv")
318
+ my_turbine, e126, my_turbine2 = initialize_wind_turbines()
319
+ calculate_power_output(weather, my_turbine, e126, my_turbine2)
320
+ plot_or_print(my_turbine, e126, my_turbine2)
321
+
322
+
323
+ if __name__ == "__main__":
324
+ run_example()