Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • toolbox/WindEnergyToolbox
  • tlbl/WindEnergyToolbox
  • cpav/WindEnergyToolbox
  • frza/WindEnergyToolbox
  • borg/WindEnergyToolbox
  • mmpe/WindEnergyToolbox
  • ozgo/WindEnergyToolbox
  • dave/WindEnergyToolbox
  • mmir/WindEnergyToolbox
  • wluo/WindEnergyToolbox
  • welad/WindEnergyToolbox
  • chpav/WindEnergyToolbox
  • rink/WindEnergyToolbox
  • shfe/WindEnergyToolbox
  • shfe1/WindEnergyToolbox
  • acdi/WindEnergyToolbox
  • angl/WindEnergyToolbox
  • wliang/WindEnergyToolbox
  • mimc/WindEnergyToolbox
  • wtlib/WindEnergyToolbox
  • cmos/WindEnergyToolbox
  • fabpi/WindEnergyToolbox
22 results
Select Git revision
  • 41-dlc-highlevel-fails-on-empty-line-in-dlc-sheet
  • master
  • py23
  • v0.0.1
  • v0.0.2
  • v0.0.5
  • v0.0.6
  • v0.0.7
  • v0.0.8
  • v0.0.9
10 results
Show changes
Showing
with 1261 additions and 39 deletions
This diff is collapsed.
# Update conda ```wetb_py3``` environment and ```wetb```
There are pre-configured miniconda/anaconda python environments installed on
Gorm and Jess at:
```
/home/python/miniconda3/envs/wetb_py3
```
Note that these refer to the home drives of Gorm and Jess respectively and thus
refer to two different directories (but are named the same).
Update the root Anaconda environment:
```
conda update --all
```
Activate the ```wetb_py3``` environment:
```
source activate wetb_py3
```
Update the ```wetb_py3``` environment:
```
conda update --all
```
Pull latest wetb changes and create re-distributable binary wheel package for ```wetb_py3```:
```
cd /home/MET/repositories/tooblox/WindEnergyToolbox
git pull
python setup.py bdist_wheel -d dist/
```
And install the wheel package (```*.whl```)
```
pip install --no-deps -U dist/wetb-X.Y.Z.post0.devXXXXXXXX-cp35m-linux_x86_64.whl
```
The option ```--no-deps``` is used here to avoid pip installing possible newer
versions of packages that should be managed by conda. This only works when all
dependencies of ```wetb``` are met (which is assumed by default for the
```wetb_py3``` environment).
......@@ -2,10 +2,10 @@
name = wetb
summary = Wind Energy Toolbox
author = DTU Wind Energy
author-email = none
author-email = mmpe@dtu.dk
license = GPLv3
home-page = https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox
description-file = README.md
description-file = README
# Add here all kinds of additional classifiers as defined under
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers = Development Status :: 4 - Beta,
......@@ -14,6 +14,8 @@ classifiers = Development Status :: 4 - Beta,
Programming Language :: Python :: 3,
Programming Language :: Python :: 3.3,
Programming Language :: Python :: 3.4,
Programming Language :: Python :: 3.5,
Programming Language :: Python :: 3.6,
Environment :: Console,
Intended Audience :: Education,
Intended Audience :: Science/Research,
......@@ -53,7 +55,7 @@ packages =
# py.test options when running `python setup.py test`
#addopts = tests
[pytest]
[tool:pytest]
# Options for py.test:
# Specify command line options as you would do when invoking py.test directly.
# e.g. --cov-report html (or xml) for html/xml output or --junitxml junit.xml
......@@ -61,6 +63,7 @@ packages =
#addopts =
# --cov wetb --cov-report term-missing
# --verbose
python_files = WindEnergyToolbox/wetb/*
[aliases]
docs = build_sphinx
......
......@@ -8,15 +8,37 @@
http://pyscaffold.readthedocs.org/
"""
import os
import sys
from setuptools import setup
try:
from pypandoc import convert_file
read_md = lambda f: convert_file(f, 'rst', format='md')
except ImportError:
print("warning: pypandoc module not found, could not convert Markdown to RST")
read_md = lambda f: open(f, 'r').read()
import numpy as np
from distutils.extension import Extension
from Cython.Distutils import build_ext
def setup_package():
ex_info = [('wetb.fatigue_tools.rainflowcounting', ['pair_range', 'peak_trough', 'rainflowcount_astm']),
('wetb.signal.filters', ['cy_filters'])]
extlist = [Extension('%s.%s' % (module, n),
[os.path.join(module.replace(".","/"), n)+'.pyx'],
include_dirs=[np.get_include()]) for module, names in ex_info for n in names]
needs_sphinx = {'build_sphinx', 'upload_docs'}.intersection(sys.argv)
sphinx = ['sphinx'] if needs_sphinx else []
setup(setup_requires=['six', 'pyscaffold>=2.5a0,<2.6a0'] + sphinx,
use_pyscaffold=True)
cmdclass = {'build_ext': build_ext},
ext_modules = extlist,
use_pyscaffold=True,
long_description=read_md('README.md'))
if __name__ == "__main__":
......
'''
Created on 29/01/2016
@author: mmpe
'''
import pytest
import os
p = os.path.abspath(os.path.join(os.path.dirname(__file__) + "./../")).replace("\\", "/")
pytest.main(p)
import glob
import unittest
import os
from os.path import dirname, relpath, abspath
def module_strings():
test_file_paths = []
test_file_paths = glob.glob('test_*.py')
#test_file_strings.extend(glob.glob('../wetb/**/test_*.py'))
#for root,_,_ in os.walk("../wetb/"):
for folder, _, _ in os.walk(os.path.abspath(dirname(__file__) + '../wetb/')):
test_file_paths.extend(glob.glob(folder + "/tests/test_*.py"))
return [relpath(s, abspath(dirname(__file__) + "/../")).replace(".py", "").replace(os.path.sep, ".") for s in test_file_paths]
for folder, _, _ in os.walk('../wetb'):
test_file_paths.extend(glob.glob(os.path.join(folder, "tests/test_*.py")))
return [s[3:len(s) - 3].replace(os.path.sep, ".") for s in test_file_paths]
def suite():
modules = module_strings()
suites = []
try:
for s in modules:
suites = []
for s in module_strings():
suites.append(unittest.defaultTestLoader.loadTestsFromName(s))
except:
print ("Failed to import '%s'" % s)
......
......@@ -4,9 +4,9 @@ from __future__ import division
from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
import pkg_resources
test = "TEST"
try:
__version__ = pkg_resources.get_distribution(__name__).version
import pkg_resources
__version__ = pkg_resources.safe_version(pkg_resources.get_distribution(__name__).version)
except:
__version__ = 'unknown'
File moved
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 04 09:24:51 2016
@author: tlbl
"""
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import absolute_import
import numpy as np
class Control(object):
def torque_controller_tuning(self, r0, lambda_opt, ksi_pole_part,
omega_pole_part, j_dt):
"""THIS IS A WIP
"""
# TODO: THIS IS STILL A WIP
i12, i23, i34 = self.select_regions()
# Compute K factor for optimal CP tracking in region 1 as
# K=0.5*rho*A*Cp_opt*R^3/lambda_opt^3
# HAWCStab2/Computation_LIB/compute_controller_input_mod.f90:83-88
# Compute K factor for optimal CP tracking in region 1 as
# K=0.5*rho*A*Cp_opt*R^3/lambda_opt^3
# pi_torque_controller%kfactor=0.d0
# do i=1,iregion2-iregion1-1
# !kfactor=kfactor+0.85d0*kfactor_fit(i)*substructure(3)
# pi_torque_controller%kfactor
# = pi_torque_controller%kfactor
# + kfactor_fit(i)*substructure(3)%opstate(i+iregion1)%r0**3/lambda_opt**3
# enddo
# HAWCStab2/Computation_LIB/compute_controller_input_mod.f90:89
# pi_torque_controller%kfactor =
# pi_torque_controller%kfactor/max(dfloat(iregion2-iregion1-1), 1.d0)
Qg = (r0*r0*r0)/(lambda_opt*lambda_opt*lambda_opt)
# PI generator torque controller in region 2 (constant speed, variable power)
# HAWCStab2/Computation_LIB/compute_controller_input_mod.f90:104-105
# pi_torque_controller%kp = 2.d0*ksi_pole_part*omega_pole_part*j_dt
# pi_torque_controller%ki = omega_pole_part**2*j_dt
pgTorque = 2.0*ksi_pole_part*omega_pole_part*j_dt
igTorque = omega_pole_part**2*j_dt
return Qg, pgTorque, igTorque
def pitch_controller_tuning(self, pitch, I, dQdt, P, Omr, om, csi):
"""
Function to compute the gains of the pitch controller of the Basic DTU
Wind Energy Controller with the pole placement technique implemented
in HAWCStab2.
Parameters
----------
pitch: array
Pitch angle [deg]. The values should only be those of the full load
region.
I: array
Drivetrain inertia [kg*m**2]
dQdt: array
Partial derivative of the aerodynamic torque with respect to the
pitch angle [kNm/deg]. Can be computed with HAWCStab2.
P: float
Rated power [kW]. Set to zero in case of constant torque regulation
Omr: float
Rated rotational speed [rpm]
om: float
Freqeuncy of regulator mode [Hz]
csi: float
Damping ratio of regulator mode
Returns
-------
kp: float
Proportional gain [rad/(rad/s)]
ki: float
Intagral gain [rad/rad]
K1: float
Linear term of the gain scheduling [deg]
K2: float
Quadratic term of the gain shceduling [deg**2]
"""
pitch = pitch * np.pi/180.
I = I * 1e-3
dQdt = dQdt * 180./np.pi
Omr = Omr * np.pi/30.
om = om * 2.*np.pi
# Quadratic fitting of dQdt
A = np.ones([dQdt.shape[0], 3])
A[:, 0] = pitch**2
A[:, 1] = pitch
b = dQdt
ATA = np.dot(A.T, A)
iATA = np.linalg.inv(ATA)
iATAA = np.dot(iATA, A.T)
x = np.dot(iATAA, b)
kp = -(2*csi*om*I[0] - P/(Omr**2))/x[2]
ki = -(om**2*I[0])/x[2]
K1 = x[2]/x[1]*(180./np.pi)
K2 = x[2]/x[0]*(180./np.pi)**2
return kp, ki, K1, K2
def K_omega2(V, P, R, TSR):
Va = np.array(V)
Pa = np.array(P)
Ra = np.array(R)
TSRa = np.array(TSR)
K = Ra**3 * np.mean(Pa/(TSRa*Va)**3)
return K
def select_regions(self, pitch, omega, power):
"""Find indices at wich point the controller should switch between the
different operating mode regions.
Parameters
----------
Returns
------
i12 : int
123 : int
134 : int
"""
i12 = 0
n = len(pitch)
for i in range(n-1):
if (abs(power[i]/power[i+1] - 1.) > 0.01):
if (abs(omega[i] / omega[i+1] - 1.) > 0.01):
i12 = i
break
i23 = n-1
for i in range(i12, n-1):
if (abs(omega[i] / omega[i+1] - 1.) < 0.01):
i23 = i
break
i34 = i23
for i in range(i23, n-1):
if (abs(power[i]/power[i+1] - 1.) > 0.01):
if (abs(omega[i] / omega[i+1] - 1.) < 0.01):
i34 = i+1
return i12, i23, i34
if __name__ == '__main__':
pass
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 04 11:09:43 2016
@author: tlbl
"""
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
from wetb.control import control
import numpy as np
class TestControl(unittest.TestCase):
def setUp(self):
dQdt = np.array([-0.126876918E+03, -0.160463547E+03, -0.211699586E+03,
-0.277209984E+03, -0.351476131E+03, -0.409411354E+03,
-0.427060299E+03, -0.608498644E+03, -0.719141594E+03,
-0.814129630E+03, -0.899248007E+03, -0.981457622E+03,
-0.106667910E+04, -0.114961807E+04, -0.123323210E+04,
-0.131169210E+04, -0.138758236E+04, -0.145930419E+04,
-0.153029102E+04, -0.159737975E+04, -0.166846850E+04])
pitch = np.array([0.2510780000E+00, 0.5350000000E-03, 0.535000000E-03,
0.5350000000E-03, 0.5350000000E-03, 0.535000000E-03,
0.5350000000E-03, 0.3751976000E+01, 0.625255700E+01,
0.8195032000E+01, 0.9857780000E+01, 0.113476710E+02,
0.1271615400E+02, 0.1399768300E+02, 0.152324310E+02,
0.1642177100E+02, 0.1755302300E+02, 0.186442750E+02,
0.1970333100E+02, 0.2073358600E+02, 0.217410280E+02])
I = np.array([0.4394996114E+08, 0.4395272885E+08, 0.4395488725E+08,
0.4395301987E+08, 0.4394561932E+08, 0.4393327166E+08,
0.4391779133E+08, 0.4394706335E+08, 0.4395826989E+08,
0.4396263773E+08, 0.4396412693E+08, 0.4396397777E+08,
0.4396275304E+08, 0.4396076315E+08, 0.4395824699E+08,
0.4395531228E+08, 0.4395201145E+08, 0.4394837798E+08,
0.4394456127E+08, 0.4394060604E+08, 0.4393647769E+08])
self.dQdt = dQdt
self.pitch = pitch
self.I = I
def test_pitch_controller_tuning(self):
crt = control.Control()
P = 0.
Omr = 12.1
om = 0.10
csi = 0.7
i = 5
kp, ki, K1, K2 = crt.pitch_controller_tuning(self.pitch[i:],
self.I[i:],
self.dQdt[i:],
P, Omr, om, csi)
self.assertAlmostEqual(kp, 1.596090243644432, places=10)
self.assertAlmostEqual(ki, 0.71632362627138424, places=10)
self.assertAlmostEqual(K1, 10.01111637532056, places=10)
self.assertAlmostEqual(K2, 599.53659803157643, places=10)
def test_regions(self):
crt = control.Control()
pitch = np.array([0.,-2.,-2.,-2.,-2.,-2.,-2.,-1., 0., ])
omega = np.array([1., 1., 1., 2., 3., 3., 3., 3., 3., ])
power = np.array([1., 2., 3., 4., 5., 6., 7., 7., 7., ])
istart, iend = 0, -1
i1, i2, i3 = crt.select_regions(pitch[istart:iend], omega[istart:iend],
power[istart:iend])
self.assertEqual(i1, 2)
self.assertEqual(i2, 4)
self.assertEqual(i3, 6)
istart, iend = 3, -1
i1, i2, i3 = crt.select_regions(pitch[istart:iend], omega[istart:iend],
power[istart:iend])
self.assertEqual(i1, 0)
self.assertEqual(i2, 1)
self.assertEqual(i3, 3)
istart, iend = 5, -1
i1, i2, i3 = crt.select_regions(pitch[istart:iend], omega[istart:iend],
power[istart:iend])
self.assertEqual(i1, 0)
self.assertEqual(i2, 0)
self.assertEqual(i3, 1)
istart, iend = 6, -1
i1, i2, i3 = crt.select_regions(pitch[istart:iend], omega[istart:iend],
power[istart:iend])
self.assertEqual(i1, 0)
self.assertEqual(i2, 0)
self.assertEqual(i3, 0)
istart, iend = 5, -2
i1, i2, i3 = crt.select_regions(pitch[istart:iend], omega[istart:iend],
power[istart:iend])
self.assertEqual(i1, 0)
self.assertEqual(i2, 0)
self.assertEqual(i3, 1)
istart, iend = 3, -3
i1, i2, i3 = crt.select_regions(pitch[istart:iend], omega[istart:iend],
power[istart:iend])
self.assertEqual(i1, 0)
self.assertEqual(i2, 1)
self.assertEqual(i3, 2)
istart, iend = 2, -4
i1, i2, i3 = crt.select_regions(pitch[istart:iend], omega[istart:iend],
power[istart:iend])
self.assertEqual(i1, 0)
self.assertEqual(i2, 2)
self.assertEqual(i3, 2)
istart, iend = 0, 3
i1, i2, i3 = crt.select_regions(pitch[istart:iend], omega[istart:iend],
power[istart:iend])
self.assertEqual(i1, 0)
self.assertEqual(i2, 0)
self.assertEqual(i3, 2)
if __name__ == "__main__":
unittest.main()
......@@ -24,6 +24,14 @@ from wetb.utils.caching import cache_function
from collections import OrderedDict
#HOURS_PR_20YEAR = 20 * 365 * 24
# hack around FileNotFoundError not being in Python2
try:
FileNotFoundError
except NameError as e:
class FileNotFoundError(OSError):
pass
def Weibull(u, k, start, stop, step):
C = 2 * u / np.sqrt(np.pi)
cdf = lambda x :-np.exp(-(x / C) ** k)
......@@ -36,6 +44,36 @@ def Weibull2(u, k, wsp_lst):
edges = np.r_[wsp_lst[0] - (wsp_lst[1] - wsp_lst[0]) / 2, (wsp_lst[1:] + wsp_lst[:-1]) / 2, wsp_lst[-1] + (wsp_lst[-1] - wsp_lst[-2]) / 2]
return [-cdf(e1) + cdf(e2) for wsp, e1, e2 in zip(wsp_lst, edges[:-1], edges[1:])]
def Weibull_IEC(Vref, Vhub_lst):
"""Weibull distribution according to IEC 61400-1:2005, page 24
Parameters
----------
Vref : int or float
Vref of wind turbine class
Vhub_lst : array_like
Wind speed at hub height. Must be equally spaced.
Returns
-------
nd_array : list of probabilities
Examples
--------
>>> Weibull_IEC(50, [4,6,8])
[ 0.11002961 0.14116891 0.15124155]
"""
Vhub_lst = np.array(Vhub_lst)
#Average wind speed
Vave=.2*Vref
#Rayleigh distribution
Pr = lambda x : 1 - np.exp(-np.pi*(x/(2*Vave))**2)
#Wsp bin edges: [4,6,8] -> [3,5,7,9]
wsp_bin_edges = np.r_[Vhub_lst[0] - (Vhub_lst[1] - Vhub_lst[0]) / 2, (Vhub_lst[1:] + Vhub_lst[:-1]) / 2, Vhub_lst[-1] + (Vhub_lst[-1] - Vhub_lst[-2]) / 2]
#probabilities of 3-5, 5-7, 7-9
return np.array([-Pr(e1) + Pr(e2) for e1, e2 in zip(wsp_bin_edges[:-1], wsp_bin_edges[1:])])
class DLCHighLevel(object):
......@@ -96,9 +134,10 @@ class DLCHighLevel(object):
self.sensor_df.fillna('', inplace=True)
# force headers to lower case
self.sensor_df.columns = [k.lower() for k in self.sensor_df.columns]
for k in ['Name', 'Nr']:
assert k.lower() in self.sensor_df.keys(), "Sensor sheet must have a '%s' column" % k
self.sensor_df = self.sensor_df[self.sensor_df.name!=""]
assert not any(self.sensor_df['name'].duplicated()), "Duplicate sensor names: %s" % ",".join(self.sensor_df['name'][self.sensor_df['name'].duplicated()].values)
for k in ['description', 'unit', 'statistic', 'ultimate', 'fatigue', 'm', 'neql', 'extremeload', 'bearingdamage', 'mindistance', 'maxdistance']:
if k not in self.sensor_df.keys():
......@@ -117,7 +156,9 @@ class DLCHighLevel(object):
def sensor_info(self, sensors=[]):
if sensors != []:
return self.sensor_df[functools.reduce(np.logical_or, [((self.sensor_df.get(f, np.array([""] * len(self.sensor_df.name))).values != "") | (self.sensor_df.name == f)) for f in np.atleast_1d(sensors)])]
sensors = np.atleast_1d(sensors)
empty_column = pd.DataFrame([""] * len(self.sensor_df.name))[0]
return self.sensor_df[functools.reduce(np.logical_or, [((self.sensor_df.get(f, empty_column).values != "") | (self.sensor_df.name == f)) for f in sensors])]
else:
return self.sensor_df
......@@ -141,11 +182,14 @@ class DLCHighLevel(object):
start, step, stop = [float(eval(v, globals(), self.__dict__)) for v in values.lower().split(":")]
values = np.arange(start, stop + step, step)
else:
values = [(eval(v, globals(), self.__dict__)) for v in str(values).lower().replace("/", ",").split(",")]
try:
values = [(eval(v, globals(), self.__dict__)) for v in str(values).lower().replace("/", ",").split(",")]
except SyntaxError:
values = [(eval(v.lstrip('0'), globals(), self.__dict__)) for v in str(values).lower().replace("/", ",").split(",")]
dist = self.dlc_df[dist_key][row]
if str(dist).lower() == "weibull" or str(dist).lower() == "rayleigh":
dist = Weibull2(self.vref * .2, self.shape_k, values)
dist = Weibull_IEC(self.vref, values)
else:
def fmt(v):
if "#" in str(v):
......@@ -161,26 +205,51 @@ class DLCHighLevel(object):
def fatigue_distribution(self):
fatigue_dist = {}
for row, load in enumerate(self.dlc_df['load']):
for row, load in self.dlc_df['load'].iteritems():
if "F" not in str(load).upper():
continue
dlc = self.dlc_df[self.dist_value_keys[0][1]][row]
fatigue_dist[str(dlc)] = [self.distribution(value_key, dist_key, row) for dist_key, value_key in self.dist_value_keys]
return fatigue_dist
def files_dict(self):
if not hasattr(self, "res_folder") or self.res_folder == "":
files = glob.glob(os.path.join(self.res_path, "*.sel")) + glob.glob(os.path.join(self.res_path, "*/*.sel"))
def files_dict(self, files=None):
"""
Parameters
----------
files : list, default=None
When files is None, files_dict will search for files defined in
the res_folder or res_path attribute if the former is absence.
Returns
-------
files_dict : dict
Dictionary holding the file name, total run hours as key, value
pairs.
"""
fatigue_dlcs = self.dlc_df[['F' in str(l).upper() for l in self.dlc_df['load']]]['dlc']
if len(fatigue_dlcs) == 0:
return {}
ext = getattr(self, 'res_ext', ".sel")
if isinstance(files, list):
pass
elif not hasattr(self, "res_folder") or self.res_folder == "":
files = glob.glob(os.path.join(self.res_path, "*"+ext)) + glob.glob(os.path.join(self.res_path, "*/*"+ext))
if len(files)==0:
raise Exception('No *%s files found in:\n%s or\n%s'%(ext, self.res_path, os.path.join(self.res_path, "*/")))
else:
files = []
fatigue_dlcs = self.dlc_df[['F' in str(l).upper() for l in self.dlc_df['load']]]['dlc']
for dlc_id in fatigue_dlcs:
dlc_id = str(dlc_id)
if "%" in self.res_folder:
folder = self.res_folder % dlc_id
else:
folder = self.res_folder
files.extend(glob.glob(os.path.join(self.res_path , folder, "*.sel")))
dlc_files = (glob.glob(os.path.join(self.res_path , folder, "*"+ext)))
if len(dlc_files)==0:
raise Exception('DLC%s included in fatigue analysis, but no *%s files found in:\n%s'%(dlc_id, ext, os.path.join(self.res_path , folder)))
files.extend(dlc_files)
keys = list(zip(*self.dist_value_keys))[1]
fmt = self.format_tag_value
tags = [[fmt(tag.replace(key, "")) for tag, key in zip(os.path.basename(f).split("_"), keys)] for f in files]
......@@ -216,7 +285,7 @@ class DLCHighLevel(object):
total_prop *= prop
return total_prop
def file_hour_lst(self, years=20):
def file_hour_lst(self, years=20, files_dict=None, dist_dict=None):
"""Create a list of (filename, hours_pr_year) that can be used as input for LifeTimeEqLoad
Returns
......@@ -228,8 +297,10 @@ class DLCHighLevel(object):
"""
fh_lst = []
dist_dict = self.fatigue_distribution()
files_dict = self.files_dict()
if dist_dict is None:
dist_dict = self.fatigue_distribution()
if files_dict is None:
files_dict = self.files_dict()
for dlc_id in sorted(dist_dict.keys()):
dlc_id = str(dlc_id)
......@@ -265,7 +336,7 @@ class DLCHighLevel(object):
if files:
f_prob = self.probability(props, files[0], files) / len(files)
f_hours_pr_20year = 365 * 24 * years * f_prob
for f in files:
for f in sorted(files):
fh_lst.append((f, f_hours_pr_20year))
return fh_lst
......@@ -279,10 +350,10 @@ class DLCHighLevel(object):
if __name__ == "__main__":
dlc_hl = DLCHighLevel(r'X:\NREL5MW\dlc.xlsx')
dlc_hl = DLCHighLevel(r'X:\DTU10MW\Q0010\DLC_post_betas1.xlsx')
#print (DLCHighLevelInputFile(r'C:\mmpe\Projects\DLC.xlsx').sensor_info(0, 0, 1)['Name'])
#print (dlc_dict()['64'])
#print (dlc_hl.fatigue_distribution()['64'])
print (dlc_hl.file_hour_lst(r"X:\NREL5MW/C0008/res/"))
print (dlc_hl.file_hour_lst(r"X:\DTU10MW/Q0010/res/"))
No preview for this file type
File added
......@@ -10,7 +10,7 @@ from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
import unittest
from wetb.dlc.high_level import DLCHighLevel, Weibull
from wetb.dlc.high_level import DLCHighLevel, Weibull, Weibull_IEC
import os
import numpy as np
......@@ -26,7 +26,7 @@ class TestDLCHighLevel(unittest.TestCase):
self.assertEqual(os.path.realpath(self.dlc_hl.res_path), os.path.realpath(testfilepath + "res"))
def test_sensor_info(self):
self.assertEqual(list(self.dlc_hl.sensor_info().name), ['MxTB', 'MyTB', 'MxBR', 'PyBT', 'Pitch', 'PitchBearing', 'Tip1TowerDistance', 'TipTowerDistance'])
self.assertEqual(list(self.dlc_hl.sensor_info().name), ['MxTB', 'MyTB', 'MxBR', 'PyBT', 'Power', 'Pitch', 'PitchBearing', 'Tip1TowerDistance', 'TipTowerDistance'])
def test_sensor_info_filter(self):
self.assertEqual(list(self.dlc_hl.sensor_info(['fatigue']).m), [4, 4, 10])
......@@ -48,14 +48,20 @@ class TestDLCHighLevel(unittest.TestCase):
def test_file_hour_lst(self):
f, h = self.dlc_hl.file_hour_lst()[0]
self.assertEqual(os.path.abspath(f), os.path.abspath(testfilepath + 'res/DLC12_IEC61400-1ed3/dlc12_wsp04_wdir350_s3001.sel'))
self.assertEqual(os.path.abspath(f), os.path.abspath(testfilepath + 'res/dlc12_iec61400-1ed3/dlc12_wsp04_wdir350_s3001.sel'))
self.assertEqual(h, .975 * .25 * 0.11002961306549919 / 2 * 20 * 365 * 24)
def test_file_hour_lst_count(self):
f, h = self.dlc_hl.file_hour_lst()[-1]
self.assertEqual(os.path.abspath(f), os.path.abspath(testfilepath + 'res/DLC31_IEC61400-1ed3/dlc31_wsp25_wdir000_s0000.sel'))
self.assertEqual(os.path.abspath(f), os.path.abspath(testfilepath + 'res/dlc31_iec61400-1ed3/dlc31_wsp25_wdir000_s0000.sel'))
self.assertAlmostEqual(h, 0.0087201928 * 1 * (50 / 1100) * 20 * 365 * 24)
def test_file_dict_flex(self):
dlc_hl = DLCHighLevel(testfilepath + 'DLC_test_flex.xlsx')
file_lst = dlc_hl.files_dict()[12][4][350]["files"]
self.assertEqual(len(file_lst),1)
self.assertTrue(file_lst[0].endswith(".int"))
def test_dlc_lst(self):
self.assertEqual(self.dlc_hl.dlc_lst(), ['12', '13', '14', '31'])
......@@ -74,8 +80,14 @@ class TestDLCHighLevel(unittest.TestCase):
self.assertTrue(k in self.dlc_hl.sensor_info().keys(), k)
def test_fail_on_res_not_fount(self):
self.dlc_hl = DLCHighLevel(testfilepath + 'DLC_test.xlsx', fail_on_resfile_not_found=True)
self.assertRaisesRegex(FileNotFoundError, "Result files for dlc='12', wsp='6', wdir='-10' not found")
# hack around FileNotFoundError not being in Python2.7
try:
self.dlc_hl = DLCHighLevel(testfilepath + 'DLC_test.xlsx',
fail_on_resfile_not_found=True)
except Exception as e:
# FileNotFoundError on Py3.3+ inherits from IOError
assert isinstance(e.__cause__, IOError)
# self.assertRaises(FileNotFoundError, "Result files for dlc='12', wsp='6', wdir='-10' not found")
......@@ -103,7 +115,10 @@ class TestDLCHighLevel(unittest.TestCase):
p_tot = np.array([value for key, value in weibull.items()]).sum()
self.assertTrue(np.allclose(p_tot, 1.0))
def test_weibull_IEC(self):
Vref = 50
np.testing.assert_array_almost_equal(Weibull_IEC(Vref, [4,6,8]), [ 0.11002961, 0.14116891, 0.15124155])
if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.testName']
......
......@@ -7,9 +7,10 @@ from __future__ import division
from __future__ import unicode_literals
from __future__ import print_function
from __future__ import absolute_import
from builtins import open
from io import open
from builtins import map
from builtins import range
from builtins import chr
from future import standard_library
standard_library.install_aliases()
import os
......@@ -71,7 +72,6 @@ def load_binary_output(filename):
"""
def fread(fid, n, type):
fmt, nbytes = {'uint8': ('B', 1), 'int16':('h', 2), 'int32':('i', 4), 'float32':('f', 4), 'float64':('d', 8)}[type]
return struct.unpack(fmt * n, fid.read(nbytes * n))
FileFmtID_WithTime = 1 #% File identifiers used in FAST
......