Skip to content
Snippets Groups Projects
Commit 3a4fc159 authored by Ju Feng's avatar Ju Feng Committed by Mads M. Pedersen
Browse files

Add function to initilize wind_turbines with one or multiple .wtg files....

Add function to initilize wind_turbines with one or multiple .wtg files. Requires using xml.etree.ElementTree, since .wtg file is stored in essence of .xml format.
parent 15ed334b
No related branches found
No related tags found
No related merge requests found
<?xml version="1.0" encoding="UTF-8"?>
<WindTurbineGenerator FormatVersion="1.01" Description="NEG-Micon 2750/92 (2750 kW)" ManufacturerName="" ReferenceURI="" RotorDiameter="92"><Comments></Comments><SuggestedHeights><Height>70.0</Height></SuggestedHeights><PerformanceTable AirDensity="1.225" MaximumNoiseLevel="0.0" DataStatus="Unknown" DataSource="Unknown" ReleaseDate="1899-12-30" ReferenceURI="None" StationaryThrustCoEfficient="0.059"><StartStopStrategy LowSpeedCutOut="4.0" LowSpeedCutIn="4.0" HighSpeedCutIn="25.0" HighSpeedCutOut="25.0"/><Comments></Comments><DataTable><DataPoint WindSpeed="4.0" PowerOutput="55000.0" ThrustCoEfficient="0.871"/><DataPoint WindSpeed="5.0" PowerOutput="185000.0" ThrustCoEfficient="0.853"/><DataPoint WindSpeed="6.0" PowerOutput="369000.0" ThrustCoEfficient="0.841"/><DataPoint WindSpeed="7.0" PowerOutput="619000.0" ThrustCoEfficient="0.841"/><DataPoint WindSpeed="8.0" PowerOutput="941000.0" ThrustCoEfficient="0.833"/><DataPoint WindSpeed="9.0" PowerOutput="1326000.0" ThrustCoEfficient="0.797"/><DataPoint WindSpeed="10.0" PowerOutput="1741000.0" ThrustCoEfficient="0.743"/><DataPoint WindSpeed="11.0" PowerOutput="2133000.0" ThrustCoEfficient="0.635"/><DataPoint WindSpeed="12.0" PowerOutput="2436000.0" ThrustCoEfficient="0.543"/><DataPoint WindSpeed="13.0" PowerOutput="2617000.0" ThrustCoEfficient="0.424"/><DataPoint WindSpeed="14.0" PowerOutput="2702000.0" ThrustCoEfficient="0.324"/><DataPoint WindSpeed="15.0" PowerOutput="2734000.0" ThrustCoEfficient="0.258"/><DataPoint WindSpeed="16.0" PowerOutput="2744000.0" ThrustCoEfficient="0.21"/><DataPoint WindSpeed="17.0" PowerOutput="2747000.0" ThrustCoEfficient="0.175"/><DataPoint WindSpeed="18.0" PowerOutput="2748000.0" ThrustCoEfficient="0.147"/><DataPoint WindSpeed="19.0" PowerOutput="2748000.0" ThrustCoEfficient="0.126"/><DataPoint WindSpeed="20.0" PowerOutput="2750000.0" ThrustCoEfficient="0.109"/><DataPoint WindSpeed="21.0" PowerOutput="2750000.0" ThrustCoEfficient="0.095"/><DataPoint WindSpeed="22.0" PowerOutput="2750000.0" ThrustCoEfficient="0.083"/><DataPoint WindSpeed="23.0" PowerOutput="2750000.0" ThrustCoEfficient="0.074"/><DataPoint WindSpeed="24.0" PowerOutput="2750000.0" ThrustCoEfficient="0.065"/><DataPoint WindSpeed="25.0" PowerOutput="2750000.0" ThrustCoEfficient="0.059"/></DataTable></PerformanceTable></WindTurbineGenerator>
<WindTurbineGenerator FormatVersion="1.01" Description="Vestas V80 (2MW, Offshore)" ManufacturerName="Vestas Wind Systems A/S" ReferenceURI="www.vestas.dk" RotorDiameter="80"><Comments>Address: Smed Sørensens Vej 5|Address: DK-6950 Ringkøbing, Denmark|Phone: +45 96 75 25 75|Fax: +45 96 75 24 36|E-mail: vestas@vestas.dk</Comments><SuggestedHeights><Height>67.0</Height></SuggestedHeights><PerformanceTable AirDensity="1.225" DataStatus="Unknown" DataSource="" ReferenceURI="None" StationaryThrustCoEfficient="0.052"><StartStopStrategy LowSpeedCutOut="4.0" LowSpeedCutIn="4.0" HighSpeedCutIn="25.0" HighSpeedCutOut="25.0"/><Comments>Noise level 106.4 dB(A)</Comments><DataTable><DataPoint WindSpeed="4.0" PowerOutput="66600.0" ThrustCoEfficient="0.818"/><DataPoint WindSpeed="5.0" PowerOutput="154000.0" ThrustCoEfficient="0.806"/><DataPoint WindSpeed="6.0" PowerOutput="282000.0" ThrustCoEfficient="0.804"/><DataPoint WindSpeed="7.0" PowerOutput="460000.0" ThrustCoEfficient="0.805"/><DataPoint WindSpeed="8.0" PowerOutput="696000.0" ThrustCoEfficient="0.806"/><DataPoint WindSpeed="9.0" PowerOutput="996000.0" ThrustCoEfficient="0.807"/><DataPoint WindSpeed="10.0" PowerOutput="1341000.0" ThrustCoEfficient="0.793"/><DataPoint WindSpeed="11.0" PowerOutput="1661000.0" ThrustCoEfficient="0.739"/><DataPoint WindSpeed="12.0" PowerOutput="1866000.0" ThrustCoEfficient="0.709"/><DataPoint WindSpeed="13.0" PowerOutput="1958000.0" ThrustCoEfficient="0.409"/><DataPoint WindSpeed="14.0" PowerOutput="1988000.0" ThrustCoEfficient="0.314"/><DataPoint WindSpeed="15.0" PowerOutput="1997000.0" ThrustCoEfficient="0.249"/><DataPoint WindSpeed="16.0" PowerOutput="1999000.0" ThrustCoEfficient="0.202"/><DataPoint WindSpeed="17.0" PowerOutput="2000000.0" ThrustCoEfficient="0.167"/><DataPoint WindSpeed="18.0" PowerOutput="2000000.0" ThrustCoEfficient="0.14"/><DataPoint WindSpeed="19.0" PowerOutput="2000000.0" ThrustCoEfficient="0.118"/><DataPoint WindSpeed="20.0" PowerOutput="2000000.0" ThrustCoEfficient="0.101"/><DataPoint WindSpeed="21.0" PowerOutput="2000000.0" ThrustCoEfficient="0.088"/><DataPoint WindSpeed="22.0" PowerOutput="2000000.0" ThrustCoEfficient="0.076"/><DataPoint WindSpeed="23.0" PowerOutput="2000000.0" ThrustCoEfficient="0.067"/><DataPoint WindSpeed="24.0" PowerOutput="2000000.0" ThrustCoEfficient="0.059"/><DataPoint WindSpeed="25.0" PowerOutput="2000000.0" ThrustCoEfficient="0.052"/></DataTable></PerformanceTable></WindTurbineGenerator>
import os
wtg_path = os.path.dirname(__file__) + "/"
...@@ -6,6 +6,27 @@ import numpy as np ...@@ -6,6 +6,27 @@ import numpy as np
from py_wake.tests import npt from py_wake.tests import npt
def test_from_WAsP_wtg():
import os
from py_wake.examples.data import wtg_path
from py_wake.wind_turbines import WindTurbines
vestas_v80_wtg = os.path.join(wtg_path, 'Vestas-V80.wtg')
NEG_2750_wtg = os.path.join(wtg_path, 'NEG-Micon-2750.wtg')
wts_wtg = WindTurbines.from_WAsP_wtg([vestas_v80_wtg, NEG_2750_wtg])
assert(wts_wtg.name(types=0) == 'Vestas V80 (2MW, Offshore)')
assert(wts_wtg.diameter(types=0) == 80)
assert(wts_wtg.hub_height(types=0) == 67)
npt.assert_array_equal(wts_wtg.power(np.array([0, 3, 5, 9, 18, 26]), type_i=0), np.array([0, 0, 154000, 996000, 2000000, 0]))
npt.assert_array_equal(wts_wtg.ct(np.array([1, 4, 7, 9, 17, 27]), type_i=0), np.array([0, 0.818, 0.805, 0.807, 0.167, 0]))
assert(wts_wtg.name(types=1) == 'NEG-Micon 2750/92 (2750 kW)')
assert(wts_wtg.diameter(types=1) == 92)
assert(wts_wtg.hub_height(types=1) == 70)
npt.assert_array_equal(wts_wtg.power(np.array([0, 3, 5, 9, 18, 26]), type_i=1), np.array([0, 0, 185000, 1326000, 2748000, 0]))
npt.assert_array_equal(wts_wtg.ct(np.array([1, 4, 7, 9, 17, 27]), type_i=1), np.array([0, 0.871, 0.841, 0.797, 0.175, 0]))
def test_twotype_windturbines(): def test_twotype_windturbines():
from py_wake.wind_turbines import WindTurbines from py_wake.wind_turbines import WindTurbines
v80 = V80() v80 = V80()
......
import numpy as np import numpy as np
import xml.etree.ElementTree as ET
class WindTurbines(): class WindTurbines():
...@@ -158,6 +159,70 @@ class WindTurbines(): ...@@ -158,6 +159,70 @@ class WindTurbines():
ax.legend(loc=1) ax.legend(loc=1)
ax.axis('equal') ax.axis('equal')
@classmethod
def from_WAsP_wtg(cls, wtg_file, power_unit='W'):
""" Parse the one/multiple .wtg file(s) (xml) to initilize an
WindTurbines object.
Parameters
----------
wtg_file : string or a list of string
A string denoting the .wtg file, which is exported from WAsP.
Returns
-------
an object of WindTurbines.
Note: it is assumed that the power_unit inside multiple .wtg files
is the same, i.e., power_unit.
"""
if type(wtg_file) is not list:
wtg_file_list = [wtg_file]
else:
wtg_file_list = wtg_file
names = []
diameters = []
hub_heights = []
ct_funcs = []
power_funcs = []
for wtg_file in wtg_file_list:
tree = ET.parse(wtg_file)
root = tree.getroot()
# Reading data from wtg_file
name = root.attrib['Description']
diameter = np.float(root.attrib['RotorDiameter'])
hub_height = np.float(root.find('SuggestedHeights').find('Height').text)
ws_cutin = np.float(root.find('PerformanceTable').find('StartStopStrategy').attrib['LowSpeedCutIn'])
ws_cutout = np.float(root.find('PerformanceTable').find('StartStopStrategy').attrib['HighSpeedCutOut'])
i_point = 0
for DataPoint in root.iter('DataPoint'):
i_point = i_point + 1
ws = np.float(DataPoint.attrib['WindSpeed'])
Ct = np.float(DataPoint.attrib['ThrustCoEfficient'])
power = np.float(DataPoint.attrib['PowerOutput'])
if i_point == 1:
dt = np.array([[ws, Ct, power]])
else:
dt = np.append(dt, np.array([[ws, Ct, power]]), axis=0)
rated_power = np.max(dt[:, 2])
ws = dt[:, 0]
ct = dt[:, 1]
power = dt[:, 2]
names.append(name)
diameters.append(diameter)
hub_heights.append(hub_height)
ct_funcs.append(lambda u, ws=ws, ct=ct: np.interp(u, ws, ct, left=0, right=0))
power_funcs.append(lambda u, ws=ws, power=power: np.interp(u, ws, power, left=0, right=0))
return cls(names=names, diameters=diameters,
hub_heights=hub_heights, ct_funcs=ct_funcs,
power_funcs=power_funcs, power_unit=power_unit)
class OneTypeWindTurbines(WindTurbines): class OneTypeWindTurbines(WindTurbines):
...@@ -222,6 +287,10 @@ def dummy_thrust(ws_cut_in=3, ws_cut_out=25, ws_rated=12, ct_rated=8 / 9): ...@@ -222,6 +287,10 @@ def dummy_thrust(ws_cut_in=3, ws_cut_out=25, ws_rated=12, ct_rated=8 / 9):
def main(): def main():
if __name__ == '__main__': if __name__ == '__main__':
import os.path
import matplotlib.pyplot as plt
from py_wake.examples.data import wtg_path
wts = WindTurbines(names=['tb1', 'tb2'], wts = WindTurbines(names=['tb1', 'tb2'],
diameters=[80, 120], diameters=[80, 120],
hub_heights=[70, 110], hub_heights=[70, 110],
...@@ -232,7 +301,7 @@ def main(): ...@@ -232,7 +301,7 @@ def main():
power_unit='kW') power_unit='kW')
ws = np.arange(25) ws = np.arange(25)
import matplotlib.pyplot as plt
plt.plot(ws, wts.power(ws, 0), label=wts.name(0)) plt.plot(ws, wts.power(ws, 0), label=wts.name(0))
plt.plot(ws, wts.power(ws, 1), label=wts.name(1)) plt.plot(ws, wts.power(ws, 1), label=wts.name(1))
plt.legend() plt.legend()
...@@ -247,5 +316,27 @@ def main(): ...@@ -247,5 +316,27 @@ def main():
plt.ylim([-50, 150]) plt.ylim([-50, 150])
plt.show() plt.show()
# Exmaple using two wtg files to initialize a wind turbine
# vestas_v80_wtg = './examples/data/Vestas-V80.wtg'
# NEG_2750_wtg = './examples/data/NEG-Micon-2750.wtg'
# data_folder = Path('./examples/data/')
# vestas_v80_wtg = data_folder / 'Vestas-V80.wtg'
# NEG_2750_wtg = data_folder / 'NEG-Micon-2750.wtg'
vestas_v80_wtg = os.path.join(wtg_path, 'Vestas-V80.wtg')
NEG_2750_wtg = os.path.join(wtg_path, 'NEG-Micon-2750.wtg')
wts_wtg = WindTurbines.from_WAsP_wtg([vestas_v80_wtg, NEG_2750_wtg])
ws = np.arange(30)
plt.plot(ws, wts_wtg.power(ws, 0), label=wts_wtg.name(0))
plt.plot(ws, wts_wtg.power(ws, 1), label=wts_wtg.name(1))
plt.legend()
plt.show()
plt.plot(ws, wts_wtg.ct(ws, 0), label=wts_wtg.name(0))
plt.plot(ws, wts_wtg.ct(ws, 1), label=wts_wtg.name(1))
plt.legend()
plt.show()
main() main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment