Skip to content
Snippets Groups Projects
Commit 22e35740 authored by mads's avatar mads
Browse files
parents 42e801b8 a5a37442
No related branches found
No related tags found
No related merge requests found
...@@ -3,4 +3,5 @@ Developers ...@@ -3,4 +3,5 @@ Developers
========== ==========
* Mads Mølgaard Pedersen * Mads Mølgaard Pedersen
* David Verelst * David R.S. Verelst
* Carlo Tibaldi
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 20 10:11:06 2015
@author: tlbl
"""
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals
from __future__ import absolute_import
# arctan and pi are required because they are in the formulas that are
# evaluated
from numpy import floor, arctan, pi
import pandas as pd
import xlrd
def multi_for(iterables):
"""
Routine to create list with combination of elements.
"""
if not iterables:
yield ()
else:
for item in iterables[0]:
for rest_tuple in multi_for(iterables[1:]):
yield (item,) + rest_tuple
class GeneralDLC(object):
"""
Basic class to generate the DLC spreadsheets. It contains routines to
handle the different types of tags.
* Constants: are fixed in the current DLC, e.g. reference turbulence\
intensity, rotor radius, reference wind speed, ....
* Variables: define the number of cases in a DLC through their combination\
e.g. wind speed, number of turbulence seeds, yaw angle, ....
* Functions: depend on other tags e.g turbulence intensity, file name, ....
"""
def __init__(self):
pass
def remove_from_dict(self, non_defaults, defaults):
for key in non_defaults.keys():
try:
del defaults[key]
except:
pass
return defaults
def add_variables_tag(self, dlc, variables, variables_order):
cases_len = []
for tag in variables_order:
dlc[tag] = []
v = variables[tag]
for i in range(len(v)-1):
try:
v.remove('')
except:
pass
if tag == '[seed]':
cases_len.append(int(v[0]))
else:
cases_len.append(len(v))
cases_index = multi_for(list(map(range, cases_len)))
for irow, row in enumerate(cases_index):
counter = floor(irow/len(variables['[wsp]']))+1
for icol, col in enumerate(row):
if variables_order[icol] == '[seed]':
value = '%4.4i' % (1000*counter + row[variables_order.index('[wsp]')]+1)
else:
value = variables[variables_order[icol]][col]
if not isinstance(value, float) and not isinstance(value, int):
value = str(value)
dlc[variables_order[icol]].append(value)
def add_constants_tag(self, dlc, constants):
for key in constants.keys():
dlc[key] = [constants[key]]*len(dlc['[wsp]'])
def sort_formulas(self, formulas):
# sort formulas based on their dependency
keys_list = sorted(formulas)
for i in range(len(keys_list)):
for ikey, key in enumerate(keys_list):
formula = formulas[key]
for ikey2, key2 in enumerate(keys_list):
if key2 in formula:
if ikey < ikey2:
keys_list.pop(ikey)
keys_list.insert(ikey2, key)
break
return keys_list
def eval_formulas(self, dlc):
for key in dlc.keys():
if isinstance(dlc[key][0], str):
if "[" in dlc[key][0]:
for key2 in dlc.keys():
for iformula, formula in enumerate(dlc[key]):
if key2 in formula:
dlc[key][iformula] = dlc[key][iformula].replace(key2, '%s'%dlc[key2][iformula])
for iformula, formula in enumerate(dlc[key]):
formula = formula.replace(',', '.')
formula = formula.replace(';', ',')
dlc[key][iformula] = eval(formula)
def add_formulas(self, dlc, formulas):
keys_list = self.sort_formulas(formulas)
for fkey in keys_list:
flist = []
for i in range(len(dlc['[wsp]'])):
formula = formulas[fkey]
for key in dlc.keys():
if key in formula:
if formula[0] == '"':
if key == '[wsp]' or key == '[gridgustdelay]':
fmt = '%2.2i'
elif key == '[wdir]' or key == '[G_phi0]':
fmt = '%3.3i'
else:
fmt = '%4.4i'
formula = formula.replace(key, fmt % int(dlc[key][i]))
elif key in formula:
formula = formula.replace(key, '%s' % dlc[key][i])
formula = formula.replace(',', '.')
formula = formula.replace(';', ',')
flist.append(eval(formula))
dlc[fkey] = flist
class GenerateDLCCases(GeneralDLC):
"""
Class to generate Excell sheets for each DLB case starting from a single
Excell sheet.
Parameters
----------
filename: str
Name of the excel spreadsheet containing the definition of all the
cases to generate.
folder: str
Name of the folder in which to save the DLB cases.
Example
-------
DLB = GenerateDLCCases()
DLB.execute()
"""
def execute(self, filename='DLCs.xlsx', folder=''):
book = xlrd.open_workbook(filename)
nsheets = book.nsheets
# Loop through all the sheets. Each sheet correspond to a DLC.
for isheet in range(1, nsheets):
# Read all the initialization constants and functions in the
# first sheet
general_constants = {}
general_functions = {}
sheet = book.sheets()[0]
for i in range(1, sheet.ncols):
if sheet.cell_value(9, i) != '':
general_constants[str(sheet.cell_value(9, i))] = \
sheet.cell_value(10, i)
if sheet.cell_value(13, i) != '':
general_functions[str(sheet.cell_value(13, i))] = \
sheet.cell_value(14, i)
sheet = book.sheets()[isheet]
print('Sheet #%i' % isheet, sheet.name)
# Read the actual sheet.
constants = {}
variables = {}
formulas = {}
variables_order = []
# Loop through the columns
for i in range(sheet.ncols):
if sheet.cell_value(1, i) is not None:
tag = str(sheet.cell_value(1, i))
if tag is not '':
if sheet.cell_value(0, i) == 'C':
constants[tag] = sheet.cell_value(2, i)
if sheet.cell_value(0, i) == 'V':
variables_order.append(tag)
variables[tag] = \
[sheet.cell_value(j, i) for j in range(2, sheet.nrows)]
if sheet.cell_value(0, i) == 'F':
formulas[tag] = str(sheet.cell_value(2, i))
dlc = {}
general_constants = self.remove_from_dict(variables,
general_constants)
general_constants = self.remove_from_dict(constants,
general_constants)
general_functions = self.remove_from_dict(formulas,
general_functions)
self.add_variables_tag(dlc, variables, variables_order)
self.add_constants_tag(dlc, general_constants)
self.add_constants_tag(dlc, constants)
self.add_formulas(dlc, formulas)
self.add_formulas(dlc, general_functions)
self.eval_formulas(dlc)
df = pd.DataFrame(dlc)
df.to_excel(folder+sheet.name+'.xls', index=False)
class RunTest():
"""
Class to perform basic testing of the GenerateDLCCases class. It writes the
spreadsheets and compare them with a reference set.
"""
def execute(self):
from pandas.util.testing import assert_frame_equal
a = GenerateDLCCases()
a.execute()
book = xlrd.open_workbook('DLCs.xlsx')
nsheets = book.nsheets
for isheet in range(1, nsheets):
sheet = book.sheets()[isheet]
print('Sheet #%i' % isheet, sheet.name)
book1 = pd.read_excel('Reference/'+sheet.name+'.xlsx')
book2 = pd.read_excel(sheet.name+'.xls')
book2 = book2[book1.columns]
assert_frame_equal(book1, book2, check_dtype=False)
if __name__ == '__main__':
DLB = GenerateDLCCases()
DLB.execute()
pass
...@@ -320,8 +320,10 @@ def excel_stabcon(proot, fext='xlsx', pignore=None, sheet=0, ...@@ -320,8 +320,10 @@ def excel_stabcon(proot, fext='xlsx', pignore=None, sheet=0,
tags_dict['[res_dir]'] = 'res/%s/' % dlc_case tags_dict['[res_dir]'] = 'res/%s/' % dlc_case
tags_dict['[log_dir]'] = 'logfiles/%s/' % dlc_case tags_dict['[log_dir]'] = 'logfiles/%s/' % dlc_case
tags_dict['[htc_dir]'] = 'htc/%s/' % dlc_case tags_dict['[htc_dir]'] = 'htc/%s/' % dlc_case
tags_dict['[case_id]'] = tags_dict['[Case id.]'] if '[Case id.]' in tags_dict.keys():
tags_dict['[time_stop]'] = tags_dict['[time stop]'] tags_dict['[case_id]'] = tags_dict['[Case id.]']
if '[time stop]' in tags_dict.keys():
tags_dict['[time_stop]'] = tags_dict['[time stop]']
try: try:
tags_dict['[turb_base_name]'] = tags_dict['[Turb base name]'] tags_dict['[turb_base_name]'] = tags_dict['[Turb base name]']
except KeyError: except KeyError:
......
...@@ -838,13 +838,20 @@ class Plots(object): ...@@ -838,13 +838,20 @@ class Plots(object):
subplots = mplutils.subplots subplots = mplutils.subplots
fig, axes = subplots(nrows=nrows, ncols=ncols, dpi=dpi, figsize=size) fig, axes = subplots(nrows=nrows, ncols=ncols, dpi=dpi, figsize=size)
axes = axes.ravel() if isinstance(axes, np.ndarray):
axes = axes.ravel()
else:
axes = [axes]
if title is not None: if title is not None:
fig.suptitle(title) fig.suptitle(title)
return fig, axes return fig, axes
def set_axes_label_grid(self, axes, setlegend=False): def set_axes_label_grid(self, axes, setlegend=False):
for ax in axes.ravel():
if isinstance(axes, np.ndarray):
axes = axes.ravel()
for ax in axes:
if setlegend: if setlegend:
leg = ax.legend(loc='best') leg = ax.legend(loc='best')
if leg is not None: if leg is not None:
...@@ -861,7 +868,7 @@ class Plots(object): ...@@ -861,7 +868,7 @@ class Plots(object):
def distribution(self, results, labels, title, channels, x_ax='pos_z', def distribution(self, results, labels, title, channels, x_ax='pos_z',
xlabel='Z-coordinate [m]', nrows=2, ncols=4, size=(16, 5), xlabel='Z-coordinate [m]', nrows=2, ncols=4, size=(16, 5),
i0=1): i0=1, iplot_legend=0, legloc='best'):
""" """
Compare blade distribution results Compare blade distribution results
""" """
...@@ -874,7 +881,10 @@ class Plots(object): ...@@ -874,7 +881,10 @@ class Plots(object):
radius2 = res2[x_ax].values radius2 = res2[x_ax].values
fig, axes = self.new_fig(title=title, nrows=nrows, ncols=ncols, size=size) fig, axes = self.new_fig(title=title, nrows=nrows, ncols=ncols, size=size)
axesflat = axes.flatten() if isinstance(axes, np.ndarray):
axesflat = axes.ravel()
else:
axesflat = axes
for i, chan in enumerate(channels): for i, chan in enumerate(channels):
ax = axesflat[i] ax = axesflat[i]
ax.plot(radius1, res1[chan].values, color=self.h2c, ax.plot(radius1, res1[chan].values, color=self.h2c,
...@@ -919,11 +929,11 @@ class Plots(object): ...@@ -919,11 +929,11 @@ class Plots(object):
# if err.max() > 50: # if err.max() > 50:
# axr.set_ylim([0, 35]) # axr.set_ylim([0, 35])
# use axr for the legend, but only for the first plot # use axr for the legend, but only for defined plot
if i == 0: if i == iplot_legend:
lines = ax.lines + axr.lines lines = ax.lines + axr.lines
labels = [l.get_label() for l in lines] labels = [l.get_label() for l in lines]
leg = axr.legend(lines, labels, loc='best') leg = axr.legend(lines, labels, loc=legloc)
leg.get_frame().set_alpha(0.5) leg.get_frame().set_alpha(0.5)
# x-label only on the last row # x-label only on the last row
...@@ -960,7 +970,8 @@ class Plots(object): ...@@ -960,7 +970,8 @@ class Plots(object):
self.save_fig(fig, axes, fname) self.save_fig(fig, axes, fname)
def h2_blade_distribution(self, fname_1, fname_2, title, labels, n0=0, def h2_blade_distribution(self, fname_1, fname_2, title, labels, n0=0,
df_stats1=None, df_stats2=None): df_stats1=None, df_stats2=None,
iplot_legend=0, legloc='best'):
""" """
Compare blade distribution aerodynamics of two HAWC2 cases. Compare blade distribution aerodynamics of two HAWC2 cases.
""" """
...@@ -975,11 +986,13 @@ class Plots(object): ...@@ -975,11 +986,13 @@ class Plots(object):
x_ax='pos_z', xlabel='Z-coordinate [m]', x_ax='pos_z', xlabel='Z-coordinate [m]',
nrows=self.dist_nrows, nrows=self.dist_nrows,
ncols=self.dist_ncols, ncols=self.dist_ncols,
size=self.dist_size) size=self.dist_size,
iplot_legend=iplot_legend, legloc=legloc)
return fig, axes return fig, axes
def hs_blade_distribution(self, fname_1, fname_2, title, labels, n0=0): def hs_blade_distribution(self, fname_1, fname_2, title, labels, n0=0,
iplot_legend=0, legloc='best'):
res1 = self.load_hs(fname_1) res1 = self.load_hs(fname_1)
res2 = self.load_hs(fname_2) res2 = self.load_hs(fname_2)
...@@ -992,12 +1005,14 @@ class Plots(object): ...@@ -992,12 +1005,14 @@ class Plots(object):
x_ax='pos_z', xlabel='Z-coordinate [m]', x_ax='pos_z', xlabel='Z-coordinate [m]',
nrows=self.dist_nrows, nrows=self.dist_nrows,
ncols=self.dist_ncols, ncols=self.dist_ncols,
size=self.dist_size) size=self.dist_size,
iplot_legend=iplot_legend, legloc=legloc)
return fig, axes return fig, axes
def blade_distribution(self, fname_h2, fname_hs2, title, n0=0, def blade_distribution(self, fname_h2, fname_hs2, title, n0=0,
h2_df_stats=None, fname_h2_tors=None): h2_df_stats=None, fname_h2_tors=None,
iplot_legend=0, legloc='best'):
"""Compare aerodynamics, blade deflections between HAWC2 and HAWCStab2. """Compare aerodynamics, blade deflections between HAWC2 and HAWCStab2.
This is based on HAWCSTab2 *.ind files, and an HAWC2 output_at_time This is based on HAWCSTab2 *.ind files, and an HAWC2 output_at_time
output file. output file.
...@@ -1029,11 +1044,13 @@ class Plots(object): ...@@ -1029,11 +1044,13 @@ class Plots(object):
x_ax='pos_z', xlabel='Z-coordinate [m]', x_ax='pos_z', xlabel='Z-coordinate [m]',
nrows=self.dist_nrows, nrows=self.dist_nrows,
ncols=self.dist_ncols, ncols=self.dist_ncols,
size=self.dist_size) size=self.dist_size,
iplot_legend=iplot_legend, legloc=legloc)
return fig, axes return fig, axes
def blade_distribution2(self, fname_h2, fname_hs2, title, n0=0): def blade_distribution2(self, fname_h2, fname_hs2, title, n0=0,
iplot_legend=0, legloc='best'):
"""Compare aerodynamics, blade deflections between HAWC2 and HAWCStab2. """Compare aerodynamics, blade deflections between HAWC2 and HAWCStab2.
This is based on HAWCSTab2 *.ind files, and an HAWC2 output_at_time This is based on HAWCSTab2 *.ind files, and an HAWC2 output_at_time
output file. output file.
...@@ -1050,7 +1067,8 @@ class Plots(object): ...@@ -1050,7 +1067,8 @@ class Plots(object):
fig, axes = self.distribution(res, labels, title, channels, fig, axes = self.distribution(res, labels, title, channels,
x_ax='pos_z', xlabel='Z-coordinate [m]', x_ax='pos_z', xlabel='Z-coordinate [m]',
nrows=3, ncols=4, size=(16, 12)) nrows=3, ncols=4, size=(16, 12),
iplot_legend=iplot_legend, legloc=legloc)
return fig, axes return fig, axes
...@@ -1066,7 +1084,8 @@ class Plots(object): ...@@ -1066,7 +1084,8 @@ class Plots(object):
# POWER --------------------------------------------------------------- # POWER ---------------------------------------------------------------
ax = axes[0] ax = axes[0]
ax.set_title('Power [kW]') ax.set_ylabel('Power [kW]')
ax.set_xlabel('Wind speed [m/s]')
# HAWC2 # HAWC2
keys = ['P_aero', 'P_mech'] keys = ['P_aero', 'P_mech']
lss = [self.h2ls, '--', ':'] lss = [self.h2ls, '--', ':']
...@@ -1103,7 +1122,8 @@ class Plots(object): ...@@ -1103,7 +1122,8 @@ class Plots(object):
# THRUST -------------------------------------------------------------- # THRUST --------------------------------------------------------------
ax = axes[1] ax = axes[1]
ax.set_title('Thrust [kN]') ax.set_ylabel('Thrust [kN]')
ax.set_xlabel('Wind speed [m/s]')
keys = ['T_aero', 'T_shafttip'] keys = ['T_aero', 'T_shafttip']
lss = [self.h2ls, '--', ':'] lss = [self.h2ls, '--', ':']
# HAWC2 # HAWC2
...@@ -1125,6 +1145,7 @@ class Plots(object): ...@@ -1125,6 +1145,7 @@ class Plots(object):
axr.plot(wind_hs, err, color=self.errc, ls=self.errls, alpha=0.6, axr.plot(wind_hs, err, color=self.errc, ls=self.errls, alpha=0.6,
label=self.errlab + ' T$_{aero}$') label=self.errlab + ' T$_{aero}$')
ax.set_xlim([wind_h2.min(), wind_h2.max()]) ax.set_xlim([wind_h2.min(), wind_h2.max()])
ax.set_xlabel('Wind speed [m/s]')
# legends # legends
lines, labels = ax.get_legend_handles_labels() lines, labels = ax.get_legend_handles_labels()
...@@ -1158,7 +1179,8 @@ class Plots(object): ...@@ -1158,7 +1179,8 @@ class Plots(object):
yerr2 = res2.pwr_h2_std[key] yerr2 = res2.pwr_h2_std[key]
ax.errorbar(wind2, res2.pwr_h2_mean[key].values, color=self.hsc, yerr=yerr2, ax.errorbar(wind2, res2.pwr_h2_mean[key].values, color=self.hsc, yerr=yerr2,
marker=self.hsms, ls=self.hsls, label=labels[1], alpha=0.7) marker=self.hsms, ls=self.hsls, label=labels[1], alpha=0.7)
ax.set_title('Power [kW]') ax.set_ylabel('Power [kW]')
ax.set_xlabel('Wind speed [m/s]')
# relative errors on the right axes # relative errors on the right axes
axr = ax.twinx() axr = ax.twinx()
assert np.allclose(wind1, wind2) assert np.allclose(wind1, wind2)
...@@ -1191,7 +1213,8 @@ class Plots(object): ...@@ -1191,7 +1213,8 @@ class Plots(object):
err = np.abs(1.0 - (qq1 / qq2))*100.0 err = np.abs(1.0 - (qq1 / qq2))*100.0
axr.plot(wind1, err, color=self.errc, ls=self.errls, alpha=0.6, axr.plot(wind1, err, color=self.errc, ls=self.errls, alpha=0.6,
label=self.errlab) label=self.errlab)
ax.set_title('Thrust [kN]') ax.set_ylabel('Thrust [kN]')
ax.set_xlabel('Wind speed [m/s]')
axes = self.set_axes_label_grid(axes, setlegend=True) axes = self.set_axes_label_grid(axes, setlegend=True)
# # use axr for the legend # # use axr for the legend
...@@ -1221,7 +1244,8 @@ class Plots(object): ...@@ -1221,7 +1244,8 @@ class Plots(object):
alpha=0.9, color=self.h2c, ls=self.h2ls, marker=self.h2ms) alpha=0.9, color=self.h2c, ls=self.h2ls, marker=self.h2ms)
ax.plot(wind2, res2.pwr_hs['P_aero'].values, label=labels[1], ax.plot(wind2, res2.pwr_hs['P_aero'].values, label=labels[1],
alpha=0.7, color=self.hsc, ls=self.hsls, marker=self.hsms) alpha=0.7, color=self.hsc, ls=self.hsls, marker=self.hsms)
ax.set_title('Power [kW]') ax.set_ylabel('Power [kW]')
ax.set_xlabel('Wind speed [m/s]')
# relative errors on the right axes # relative errors on the right axes
axr = ax.twinx() axr = ax.twinx()
assert np.allclose(wind1, wind2) assert np.allclose(wind1, wind2)
...@@ -1245,7 +1269,8 @@ class Plots(object): ...@@ -1245,7 +1269,8 @@ class Plots(object):
err = np.abs(1.0 - (qq1 / qq2))*100.0 err = np.abs(1.0 - (qq1 / qq2))*100.0
axr.plot(wind1, err, color=self.errc, ls=self.errls, alpha=0.6, axr.plot(wind1, err, color=self.errc, ls=self.errls, alpha=0.6,
label=self.errlab) label=self.errlab)
ax.set_title('Thrust [kN]') ax.set_ylabel('Thrust [kN]')
ax.set_xlabel('Wind speed [m/s]')
axes = self.set_axes_label_grid(axes, setlegend=True) axes = self.set_axes_label_grid(axes, setlegend=True)
# # use axr for the legend # # use axr for the legend
......
...@@ -291,73 +291,6 @@ class hs2_control_tuning(object): ...@@ -291,73 +291,6 @@ class hs2_control_tuning(object):
setattr(self.aero_damp, 'Ko2', 0.0) setattr(self.aero_damp, 'Ko2', 0.0)
class tests(unittest.TestCase):
"""
"""
def setUp(self):
self.fpath_linear = 'data/controller_input_linear.txt'
self.fpath_quadratic = 'data/controller_input_quadratic.txt'
def test_cmb_df(self):
fname1 = 'data/campbell_wind.cmb'
speed, freq, damp = results().load_cmb(fname1)
df = results().load_cmb_df(fname1)
#mods = freq.shape[1]
ops = freq.shape[0]
self.assertEqual(len(speed), ops)
for k in range(ops):
df_oper = df[df['wind_ms']==speed[k]]
np.testing.assert_allclose(freq[k,:], df_oper['Fd_hz'].values)
np.testing.assert_allclose(damp[k,:], df_oper['damp_ratio'].values)
np.testing.assert_allclose(np.arange(1,len(df_oper)+1), df_oper['mode'])
self.assertEqual(len(df_oper['wind_ms'].unique()), 1)
self.assertEqual(df_oper['wind_ms'].unique()[0], speed[k])
def test_linear_file(self):
hs2 = hs2_control_tuning()
hs2.read_parameters(self.fpath_linear)
self.assertEqual(hs2.pi_gen_reg1.K, 0.108313E+07)
self.assertEqual(hs2.pi_gen_reg2.I, 0.307683E+08)
self.assertEqual(hs2.pi_gen_reg2.Kp, 0.135326E+08)
self.assertEqual(hs2.pi_gen_reg2.Ki, 0.303671E+07)
self.assertEqual(hs2.pi_pitch_reg3.Kp, 0.276246E+01)
self.assertEqual(hs2.pi_pitch_reg3.Ki, 0.132935E+01)
self.assertEqual(hs2.pi_pitch_reg3.K1, 5.79377)
self.assertEqual(hs2.pi_pitch_reg3.K2, 0.0)
self.assertEqual(hs2.aero_damp.Kp2, 0.269403E+00)
self.assertEqual(hs2.aero_damp.Ko1, -4.21472)
self.assertEqual(hs2.aero_damp.Ko2, 0.0)
def test_quadratic_file(self):
hs2 = hs2_control_tuning()
hs2.read_parameters(self.fpath_quadratic)
self.assertEqual(hs2.pi_gen_reg1.K, 0.108313E+07)
self.assertEqual(hs2.pi_gen_reg2.I, 0.307683E+08)
self.assertEqual(hs2.pi_gen_reg2.Kp, 0.135326E+08)
self.assertEqual(hs2.pi_gen_reg2.Ki, 0.303671E+07)
self.assertEqual(hs2.pi_pitch_reg3.Kp, 0.249619E+01)
self.assertEqual(hs2.pi_pitch_reg3.Ki, 0.120122E+01)
self.assertEqual(hs2.pi_pitch_reg3.K1, 7.30949)
self.assertEqual(hs2.pi_pitch_reg3.K2, 1422.81187)
self.assertEqual(hs2.aero_damp.Kp2, 0.240394E-01)
self.assertEqual(hs2.aero_damp.Ko1, -1.69769)
self.assertEqual(hs2.aero_damp.Ko2, -15.02688)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
# Wind [m/s] 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
0.400000E+01 0.228933E+00 0.233973E+00 0.762776E+00 0.965817E+00 0.136002E+01 0.149639E+01 0.159423E+01 0.202127E+01 0.204610E+01 0.208646E+01 0.388822E+00 0.966751E+01 0.102903E+01 0.118873E+01 0.224277E+02 0.237007E+01 0.156716E+02 0.304645E+01 0.155964E+02 0.431867E+01
0.500000E+01 0.228944E+00 0.234004E+00 0.763301E+00 0.966955E+00 0.136149E+01 0.149576E+01 0.159339E+01 0.202086E+01 0.204910E+01 0.208435E+01 0.400712E+00 0.973227E+01 0.106285E+01 0.133466E+01 0.224476E+02 0.237088E+01 0.156581E+02 0.304886E+01 0.155855E+02 0.426180E+01
0.600000E+01 0.228950E+00 0.233713E+00 0.764151E+00 0.968410E+00 0.136286E+01 0.149520E+01 0.159243E+01 0.202039E+01 0.205218E+01 0.208226E+01 0.406516E+00 0.960985E+01 0.113674E+01 0.151399E+01 0.224486E+02 0.236761E+01 0.156309E+02 0.304953E+01 0.155767E+02 0.419995E+01
0.700000E+01 0.228969E+00 0.233943E+00 0.765058E+00 0.970449E+00 0.136386E+01 0.149485E+01 0.159148E+01 0.201989E+01 0.205516E+01 0.208023E+01 0.410362E+00 0.956280E+01 0.125579E+01 0.172544E+01 0.225723E+02 0.236204E+01 0.156830E+02 0.304991E+01 0.156414E+02 0.414330E+01
0.800000E+01 0.228981E+00 0.235547E+00 0.751657E+00 0.984742E+00 0.133566E+01 0.150181E+01 0.159480E+01 0.201923E+01 0.205065E+01 0.207803E+01 0.425543E+00 0.105481E+02 0.134744E+01 0.175350E+01 0.276486E+02 0.245076E+01 0.183743E+02 0.308534E+01 0.187826E+02 0.426964E+01
0.900000E+01 0.228996E+00 0.236970E+00 0.738114E+00 0.999088E+00 0.128575E+01 0.150896E+01 0.159184E+01 0.201868E+01 0.203967E+01 0.207649E+01 0.441459E+00 0.114513E+02 0.139929E+01 0.171638E+01 0.337118E+02 0.249114E+01 0.211607E+02 0.312301E+01 0.222187E+02 0.437718E+01
0.100000E+02 0.229012E+00 0.238179E+00 0.724468E+00 0.101353E+01 0.118278E+01 0.151608E+01 0.157955E+01 0.201827E+01 0.201894E+01 0.207574E+01 0.457749E+00 0.123038E+02 0.140490E+01 0.162917E+01 0.404780E+02 0.248329E+01 0.238259E+02 0.316032E+01 0.259943E+02 0.445668E+01
0.110000E+02 0.229026E+00 0.239178E+00 0.710773E+00 0.102810E+01 0.108411E+01 0.152309E+01 0.156056E+01 0.201801E+01 0.198169E+01 0.207582E+01 0.473968E+00 0.131326E+02 0.136375E+01 0.150699E+01 0.411061E+02 0.243142E+01 0.257758E+02 0.319485E+01 0.301264E+02 0.449558E+01
0.120000E+02 0.229021E+00 0.239633E+00 0.708997E+00 0.103066E+01 0.107780E+01 0.153402E+01 0.154335E+01 0.202064E+01 0.193052E+01 0.209214E+01 0.486960E+00 0.135941E+02 0.114255E+01 0.126920E+01 0.382470E+02 0.216812E+01 0.252810E+02 0.312680E+01 0.310102E+02 0.472517E+01
0.130000E+02 0.229026E+00 0.239785E+00 0.708960E+00 0.103053E+01 0.107743E+01 0.154125E+01 0.153408E+01 0.202211E+01 0.189783E+01 0.210716E+01 0.503753E+00 0.138570E+02 0.104718E+01 0.114424E+01 0.366660E+02 0.198152E+01 0.247994E+02 0.309199E+01 0.311264E+02 0.489292E+01
0.140000E+02 0.229030E+00 0.239833E+00 0.708652E+00 0.103012E+01 0.107707E+01 0.154680E+01 0.152747E+01 0.202305E+01 0.187153E+01 0.212208E+01 0.514565E+00 0.140661E+02 0.100617E+01 0.106417E+01 0.355180E+02 0.183957E+01 0.244292E+02 0.307265E+01 0.311685E+02 0.500880E+01
0.150000E+02 0.229055E+00 0.240017E+00 0.708136E+00 0.102951E+01 0.107701E+01 0.155133E+01 0.152248E+01 0.202372E+01 0.184933E+01 0.213830E+01 0.544804E+00 0.143364E+02 0.996830E+00 0.101040E+01 0.345994E+02 0.173088E+01 0.241219E+02 0.306084E+01 0.311506E+02 0.500600E+01
0.160000E+02 0.229071E+00 0.239853E+00 0.707432E+00 0.102872E+01 0.107759E+01 0.155510E+01 0.151899E+01 0.202423E+01 0.183087E+01 0.215318E+01 0.578800E+00 0.145899E+02 0.100993E+01 0.975174E+00 0.338448E+02 0.165052E+01 0.238541E+02 0.305342E+01 0.310630E+02 0.477124E+01
0.170000E+02 0.229085E+00 0.239595E+00 0.706561E+00 0.102777E+01 0.107867E+01 0.155827E+01 0.151662E+01 0.202463E+01 0.181533E+01 0.216331E+01 0.609440E+00 0.148314E+02 0.103970E+01 0.954033E+00 0.331993E+02 0.159293E+01 0.236152E+02 0.304854E+01 0.309315E+02 0.446567E+01
0.180000E+02 0.229100E+00 0.239299E+00 0.705540E+00 0.102667E+01 0.108022E+01 0.156096E+01 0.151516E+01 0.202495E+01 0.180218E+01 0.217047E+01 0.642610E+00 0.150961E+02 0.108264E+01 0.943946E+00 0.326383E+02 0.155714E+01 0.234027E+02 0.304542E+01 0.307706E+02 0.420507E+01
0.190000E+02 0.229100E+00 0.238941E+00 0.704393E+00 0.102545E+01 0.108151E+01 0.156324E+01 0.151377E+01 0.202521E+01 0.178960E+01 0.217609E+01 0.645467E+00 0.152863E+02 0.113498E+01 0.942057E+00 0.321266E+02 0.153398E+01 0.232221E+02 0.304319E+01 0.306240E+02 0.398727E+01
0.200000E+02 0.229117E+00 0.238524E+00 0.703123E+00 0.102411E+01 0.108297E+01 0.156518E+01 0.151271E+01 0.202543E+01 0.177816E+01 0.218066E+01 0.680310E+00 0.155290E+02 0.119543E+01 0.947265E+00 0.316630E+02 0.153812E+01 0.230628E+02 0.304242E+01 0.304641E+02 0.381123E+01
0.210000E+02 0.229136E+00 0.238084E+00 0.701736E+00 0.102265E+01 0.108452E+01 0.156681E+01 0.151186E+01 0.202562E+01 0.176741E+01 0.218452E+01 0.719375E+00 0.158119E+02 0.126269E+01 0.958046E+00 0.312303E+02 0.156212E+01 0.229212E+02 0.304250E+01 0.302974E+02 0.366667E+01
0.220000E+02 0.229147E+00 0.237523E+00 0.700230E+00 0.102107E+01 0.108627E+01 0.156814E+01 0.151132E+01 0.202577E+01 0.175757E+01 0.218779E+01 0.754378E+00 0.161008E+02 0.133578E+01 0.973260E+00 0.308276E+02 0.160451E+01 0.227919E+02 0.304323E+01 0.301112E+02 0.354965E+01
0.230000E+02 0.229161E+00 0.236848E+00 0.698611E+00 0.101939E+01 0.108881E+01 0.156918E+01 0.151172E+01 0.202590E+01 0.174988E+01 0.219054E+01 0.796036E+00 0.163966E+02 0.141457E+01 0.992719E+00 0.304529E+02 0.166798E+01 0.226548E+02 0.304454E+01 0.298809E+02 0.345932E+01
0.240000E+02 0.229178E+00 0.236114E+00 0.696892E+00 0.101760E+01 0.109145E+01 0.156999E+01 0.151235E+01 0.202601E+01 0.174276E+01 0.219296E+01 0.838889E+00 0.167029E+02 0.149901E+01 0.101590E+01 0.301033E+02 0.175021E+01 0.225316E+02 0.304628E+01 0.296496E+02 0.338727E+01
0.250000E+02 0.229186E+00 0.235316E+00 0.695102E+00 0.101572E+01 0.109457E+01 0.157057E+01 0.151364E+01 0.202611E+01 0.173710E+01 0.219518E+01 0.859064E+00 0.169785E+02 0.159098E+01 0.104301E+01 0.297783E+02 0.184710E+01 0.224109E+02 0.304806E+01 0.293981E+02 0.333190E+01
PI generator torque controller in region 1 (variable speed, variable power), starting at istate = 3
K = 0.108313E+07 [Nm/(rad/s)^2]
PI generator torque controller in region 2 (constant speed, variable power)
I = 0.307683E+08 [kg*m^2]
Kp = 0.135326E+08 [Nm/(rad/s)]
Ki = 0.303671E+07 [Nm/rad]
PI pitch angle controller in region 3 (constant speed, constant power)
Kp = 0.276246E+01 [rad/(rad/s)]
Ki = 0.132935E+01 [rad/rad]
K1 = 5.79377 [deg] (dq/dtheta = -159.47784 kNm/deg)
Additional terms due to the Aerodynamic damping
Kp2 = 0.269403E+00 [rad/(rad/s)]
Ko1 = -4.21472 [deg] (dq/domega = 2461.64665 kNm/(rad/s))
PI generator torque controller in region 1 (variable speed, variable power), starting at istate = 3
K = 0.108313E+07 [Nm/(rad/s)^2]
PI generator torque controller in region 2 (constant speed, variable power)
I = 0.307683E+08 [kg*m^2]
Kp = 0.135326E+08 [Nm/(rad/s)]
Ki = 0.303671E+07 [Nm/rad]
PI pitch angle controller in region 3 (constant speed, constant power)
Kp = 0.249619E+01 [rad/(rad/s)]
Ki = 0.120122E+01 [rad/rad]
K1 = 7.30949 [deg], K2 = 1422.81187 [deg^2] (dq/dtheta = -176.48944 kNm/deg)
Additional terms due to the Aerodynamic damping
Kp2 = 0.240394E-01 [rad/(rad/s)]
Ko1 = -1.69769 [deg], Ko2 = -15.02688 [deg^2] (dq/domega = 243.08924 kNm/(rad/s))
'''
Created on 05/11/2015
@author: MMPE
'''
from __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
import unittest
import os
import numpy as np
from wetb.prepost.hawcstab2 import results, hs2_control_tuning
class Tests(unittest.TestCase):
"""
"""
def setUp(self):
self.fpath_linear = os.path.join(os.path.dirname(__file__),
'data/controller_input_linear.txt')
self.fpath_quad = os.path.join(os.path.dirname(__file__),
'data/controller_input_quadratic.txt')
def test_cmb_df(self):
fname1 = os.path.join(os.path.dirname(__file__),
'data/campbell_diagram.cmb')
speed, freq, damp = results().load_cmb(fname1)
df = results().load_cmb_df(fname1)
#mods = freq.shape[1]
ops = freq.shape[0]
self.assertEqual(len(speed), ops)
for k in range(ops):
df_oper = df[df['wind_ms']==speed[k]]
np.testing.assert_allclose(freq[k,:], df_oper['Fd_hz'].values)
np.testing.assert_allclose(damp[k,:], df_oper['damp_ratio'].values)
np.testing.assert_allclose(np.arange(1,len(df_oper)+1), df_oper['mode'])
self.assertEqual(len(df_oper['wind_ms'].unique()), 1)
self.assertEqual(df_oper['wind_ms'].unique()[0], speed[k])
def test_linear_file(self):
hs2 = hs2_control_tuning()
hs2.read_parameters(self.fpath_linear)
self.assertEqual(hs2.pi_gen_reg1.K, 0.108313E+07)
self.assertEqual(hs2.pi_gen_reg2.I, 0.307683E+08)
self.assertEqual(hs2.pi_gen_reg2.Kp, 0.135326E+08)
self.assertEqual(hs2.pi_gen_reg2.Ki, 0.303671E+07)
self.assertEqual(hs2.pi_pitch_reg3.Kp, 0.276246E+01)
self.assertEqual(hs2.pi_pitch_reg3.Ki, 0.132935E+01)
self.assertEqual(hs2.pi_pitch_reg3.K1, 5.79377)
self.assertEqual(hs2.pi_pitch_reg3.K2, 0.0)
self.assertEqual(hs2.aero_damp.Kp2, 0.269403E+00)
self.assertEqual(hs2.aero_damp.Ko1, -4.21472)
self.assertEqual(hs2.aero_damp.Ko2, 0.0)
def test_quadratic_file(self):
hs2 = hs2_control_tuning()
hs2.read_parameters(self.fpath_quad)
self.assertEqual(hs2.pi_gen_reg1.K, 0.108313E+07)
self.assertEqual(hs2.pi_gen_reg2.I, 0.307683E+08)
self.assertEqual(hs2.pi_gen_reg2.Kp, 0.135326E+08)
self.assertEqual(hs2.pi_gen_reg2.Ki, 0.303671E+07)
self.assertEqual(hs2.pi_pitch_reg3.Kp, 0.249619E+01)
self.assertEqual(hs2.pi_pitch_reg3.Ki, 0.120122E+01)
self.assertEqual(hs2.pi_pitch_reg3.K1, 7.30949)
self.assertEqual(hs2.pi_pitch_reg3.K2, 1422.81187)
self.assertEqual(hs2.aero_damp.Kp2, 0.240394E-01)
self.assertEqual(hs2.aero_damp.Ko1, -1.69769)
self.assertEqual(hs2.aero_damp.Ko2, -15.02688)
if __name__ == "__main__":
unittest.main()
'''
Created on 05/11/2015
@author: MMPE
'''
from __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
import unittest
import os
import numpy as np
from wetb.prepost.windIO import LoadResults
class TestsLoadResults(unittest.TestCase):
def setUp(self):
self.respath = os.path.join(os.path.dirname(__file__),
'../../hawc2/tests/test_files/hawc2io/')
self.fascii = 'Hawc2ascii'
self.fbin = 'Hawc2bin'
def loadresfile(self, resfile):
res = LoadResults(self.respath, resfile)
self.assertTrue(hasattr(res, 'sig'))
self.assertEqual(res.Freq, 40.0)
self.assertEqual(res.N, 800)
self.assertEqual(res.Nch, 28)
self.assertEqual(res.Time, 20.0)
self.assertEqual(res.sig.shape, (800, 28))
return res
def test_load_ascii(self):
res = self.loadresfile(self.fascii)
self.assertEqual(res.FileType, 'ASCII')
def test_load_binary(self):
res = self.loadresfile(self.fbin)
self.assertEqual(res.FileType, 'BINARY')
def test_compare_ascii_bin(self):
res_ascii = LoadResults(self.respath, self.fascii)
res_bin = LoadResults(self.respath, self.fbin)
for k in range(res_ascii.sig.shape[1]):
np.testing.assert_allclose(res_ascii.sig[:,k], res_bin.sig[:,k],
rtol=1e-02, atol=0.001)
def test_unified_chan_names(self):
res = LoadResults(self.respath, self.fascii, readdata=False)
self.assertFalse(hasattr(res, 'sig'))
np.testing.assert_array_equal(res.ch_df.index.values, np.arange(0,28))
self.assertEqual(res.ch_df.ch_name.values[0], 'Time')
self.assertEqual(res.ch_df.ch_name.values[27],
'windspeed-global-Vy--2.50-1.00--52.50')
if __name__ == "__main__":
unittest.main()
...@@ -27,14 +27,12 @@ __version__ = '0.5' ...@@ -27,14 +27,12 @@ __version__ = '0.5'
import os import os
import copy import copy
import unittest
import struct import struct
import math import math
from time import time from time import time
import codecs import codecs
import scipy import scipy
import scipy.io as sio
import scipy.integrate as integrate import scipy.integrate as integrate
import array import array
import numpy as np import numpy as np
...@@ -130,9 +128,8 @@ class LoadResults(object): ...@@ -130,9 +128,8 @@ class LoadResults(object):
# remove .log, .dat, .sel extensions who might be accedental left # remove .log, .dat, .sel extensions who might be accedental left
if file_name[-4:] in ['.htc','.sel','.dat','.log']: if file_name[-4:] in ['.htc','.sel','.dat','.log']:
file_name = file_name[:-4] file_name = file_name[:-4]
# FIXME: since HAWC2 will always have lower case output files, convert
# any wrongly used upper case letters to lower case here self.file_name = file_name
self.file_name = file_name.lower()
self.read_sel() self.read_sel()
# create for any supported channel the # create for any supported channel the
# continue if the file has been succesfully read # continue if the file has been succesfully read
...@@ -824,6 +821,8 @@ class LoadResults(object): ...@@ -824,6 +821,8 @@ class LoadResults(object):
channelinfo['pos'] = (x, y, z) channelinfo['pos'] = (x, y, z)
channelinfo['units'] = units channelinfo['units'] = units
channelinfo['chi'] = ch channelinfo['chi'] = ch
channelinfo['sensortype'] = 'windspeed'
channelinfo['component'] = direction[1:]
# WIND SPEED AT BLADE # WIND SPEED AT BLADE
# 0: WSP Vx, glco, R= 61.5 # 0: WSP Vx, glco, R= 61.5
...@@ -1013,19 +1012,34 @@ class LoadResults(object): ...@@ -1013,19 +1012,34 @@ class LoadResults(object):
# TODO: general signal method, this is not HAWC2 specific, move out # TODO: general signal method, this is not HAWC2 specific, move out
def calc_fatigue(self, signal, no_bins=46, m=[3, 4, 6, 8, 10, 12], neq=1): def calc_fatigue(self, signal, no_bins=46, m=[3, 4, 6, 8, 10, 12], neq=1):
""" """
signal is 1D Parameters
----------
signal: 1D array
One dimentional array containing the signal.
no_bins: int
Number of bins for the binning of the amplitudes.
m: list
Values of the slope of the SN curve.
neq: int
Number of equivalent cycles
Returns
-------
eq: list
Damage equivalent loads for each m value.
""" """
try: try:
sig_rf = rainflow_astm(signal) sig_rf = rainflow_astm(signal)
except: except (TypeError) as e:
print(e)
return [] return []
if len(sig_rf) < 1 and not sig_rf: if len(sig_rf) < 1 and not sig_rf:
return [] return []
hist_data, x, bin_avg = rfc_hist(sig_rf, no_bins) hist_data, x, bin_avg = rfc_hist(sig_rf, no_bins)
m = np.atleast_1d(m) m = np.atleast_1d(m)
eq = [] eq = []
...@@ -1855,154 +1869,6 @@ class Bladed(object): ...@@ -1855,154 +1869,6 @@ class Bladed(object):
return df return df
class Tests(unittest.TestCase):
def setUp(self):
pass
def print_test_info(self):
pass
def test_reshaped(self):
"""
Make sure we correctly reshape the array instead of the manual
index reassignments
"""
fpath = 'data/turb_s100_3.00w.bin'
fid = open(fpath, 'rb')
turb = np.fromfile(fid, 'float32', 32*32*8192)
turb.shape
fid.close()
u = np.zeros((8192,32,32))
for i in range(8192):
for j in range(32):
for k in range(32):
u[i,j,k] = turb[ i*1024 + j*32 + k]
u2 = np.reshape(turb, (8192, 32, 32))
self.assertTrue(np.alltrue(np.equal(u, u2)))
def test_headers(self):
fpath = 'data/'
basename = 'turb_s100_3.00_refoctave_header'
fid = open(fpath + basename + '.wnd', 'rb')
R1 = struct.unpack("h",fid.read(2))[0]
R2 = struct.unpack("h",fid.read(2))[0]
turb = struct.unpack("i",fid.read(4))[0]
lat = struct.unpack("f",fid.read(4))[0]
# last line
fid.seek(100)
LongVertComp = struct.unpack("f",fid.read(4))[0]
fid.close()
basename = 'turb_s100_3.00_python_header'
fid = open(fpath + basename + '.wnd', 'rb')
R1_p = struct.unpack("h",fid.read(2))[0]
R2_p = struct.unpack("h",fid.read(2))[0]
turb_p = struct.unpack("i",fid.read(4))[0]
lat_p = struct.unpack("f",fid.read(4))[0]
# last line
fid.seek(100)
LongVertComp_p = struct.unpack("f",fid.read(4))[0]
fid.close()
self.assertEqual(R1, R1_p)
self.assertEqual(R2, R2_p)
self.assertEqual(turb, turb_p)
self.assertEqual(lat, lat_p)
self.assertEqual(LongVertComp, LongVertComp_p)
def test_write_bladed(self):
fpath = 'data/'
turb = Turbulence()
# write with Python
basename = 'turb_s100_3.00'
turb.write_bladed(fpath, basename, shape=(8192,32,32))
python = turb.read_bladed(fpath, basename)
# load octave
basename = 'turb_s100_3.00_refoctave'
octave = turb.read_bladed(fpath, basename)
# float versions of octave
basename = 'turb_s100_3.00_refoctave_float'
fid = open(fpath + basename + '.wnd', 'rb')
octave32 = np.fromfile(fid, 'float32', 8192*32*32*3)
# find the differences
nr_diff = (python-octave).__ne__(0).sum()
print(nr_diff)
print(nr_diff/len(python))
self.assertTrue(np.alltrue(python == octave))
def test_turbdata(self):
shape = (8192,32,32)
fpath = 'data/'
basename = 'turb_s100_3.00_refoctave'
fid = open(fpath + basename + '.wnd', 'rb')
# check the last element of the header
fid.seek(100)
print(struct.unpack("f",fid.read(4))[0])
# save in a list using struct
items = (os.path.getsize(fpath + basename + '.wnd')-104)/2
data_list = [struct.unpack("h",fid.read(2))[0] for k in range(items)]
fid.seek(104)
data_16 = np.fromfile(fid, 'int16', shape[0]*shape[1]*shape[2]*3)
fid.seek(104)
data_8 = np.fromfile(fid, 'int8', shape[0]*shape[1]*shape[2]*3)
self.assertTrue(np.alltrue( data_16 == data_list ))
self.assertFalse(np.alltrue( data_8 == data_list ))
def test_compare_octave(self):
"""
Compare the results from the original script run via octave
"""
turb = Turbulence()
iu, iv, iw = turb.convert2bladed('data/', 'turb_s100_3.00',
shape=(8192,32,32))
res = sio.loadmat('data/workspace.mat')
# increase tolerances, values have a range up to 5000-10000
# and these values will be written to an int16 format for BLADED!
self.assertTrue(np.allclose(res['iu'], iu, rtol=1e-03, atol=1e-2))
self.assertTrue(np.allclose(res['iv'], iv, rtol=1e-03, atol=1e-2))
self.assertTrue(np.allclose(res['iw'], iw, rtol=1e-03, atol=1e-2))
def test_allindices(self):
"""
Verify that all indices are called
"""
fpath = 'data/turb_s100_3.00w.bin'
fid = open(fpath, 'rb')
turb = np.fromfile(fid, 'float32', 32*32*8192)
turb.shape
fid.close()
check = []
for i in range(8192):
for j in range(32):
for k in range(32):
check.append(i*1024 + j*32 + k)
qq = np.array(check)
qdiff = np.diff(qq)
self.assertTrue(np.alltrue(np.equal(qdiff, np.ones(qdiff.shape))))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() pass
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment