From 4872a0c10721ffa9c0f76e0e9264749649b2b664 Mon Sep 17 00:00:00 2001 From: "Mads M. Pedersen" <mmpe@dtu.dk> Date: Fri, 1 Jun 2018 10:27:57 +0200 Subject: [PATCH] Added FusedWakeNOJWakeModel + test --- tests/test_fusedwake_models/test_gcl.py | 52 ++++++++---------- tests/test_fusedwake_models/test_noj.py | 32 +++++++++++ tests/test_try_me.py | 8 ++- topfarm/cost_models/fused_wake_wrappers.py | 63 +++++++++++++++------- 4 files changed, 105 insertions(+), 50 deletions(-) create mode 100644 tests/test_fusedwake_models/test_noj.py diff --git a/tests/test_fusedwake_models/test_gcl.py b/tests/test_fusedwake_models/test_gcl.py index c393bd18..0a8bf30a 100644 --- a/tests/test_fusedwake_models/test_gcl.py +++ b/tests/test_fusedwake_models/test_gcl.py @@ -1,43 +1,37 @@ -import os -import unittest - import numpy as np from topfarm.cost_models.fused_wake_wrappers import FusedWakeGCLWakeModel from topfarm.cost_models.utils.aep_calculator import AEPCalculator from topfarm.cost_models.utils.wind_resource import WindResource from tests.test_files import tfp from topfarm._topfarm import TopFarm +import pytest -class TestFusedWakeModels(unittest.TestCase): # unittest version +@pytest.fixture() +def aep_calc(): + # f, A, k = read_lib(fuga_path + 'LUT/Farms/Horns Rev 1\hornsrev_north_only_pm45.lib') + f = [1.0, 0.0, 0.0, 0.0] + A = [9.176929, 9.782334, 9.531809, 9.909545] + k = [2.392578, 2.447266, 2.412109, 2.591797] + wr = WindResource(f, A, k, ti=np.zeros_like(f) + .1) + wm = FusedWakeGCLWakeModel(tfp + "wind_farms/3tb.yml") + return AEPCalculator(wr, wm) - def test_GCL(self): - # f, A, k = read_lib(fuga_path + 'LUT/Farms/Horns Rev 1\hornsrev_north_only_pm45.lib') - f = [1.0, 0.0, 0.0, 0.0] - A = [9.176929, 9.782334, 9.531809, 9.909545] - k = [2.392578, 2.447266, 2.412109, 2.591797] - wr = WindResource(f, A, k, ti=np.zeros_like(f) + .1) - wm = FusedWakeGCLWakeModel(tfp + "wind_farms/3tb.yml") - aep_calc = AEPCalculator(wr, wm) - init_pos = wm.windFarm.pos.T - self.assertEqual(aep_calc(init_pos), 19.85973533524627) - self.assertEqual(aep_calc(np.array([[-500, 0, 500], [0, 0, 0]]).T), 22.31788007605505) +def test_input_shape_must_be_equal(): + wm = FusedWakeGCLWakeModel(tfp + "wind_farms/3tb.yml") + with pytest.raises(AssertionError, message="Shape of no_wake_wdir, no_wake_wsp and no_wake_ti must equal"): + wm(wm.windFarm.pos.T, no_wake_wdir=[[270]], no_wake_wsp=[[8, 9]], no_wake_ti=0.1) - def test_GCL_Topfarm(self): - # f, A, k = read_lib(fuga_path + 'LUT/Farms/Horns Rev 1\hornsrev_north_only_pm45.lib') - f = [1.0, 0.0, 0.0, 0.0] - A = [9.176929, 9.782334, 9.531809, 9.909545] - k = [2.392578, 2.447266, 2.412109, 2.591797] - wr = WindResource(f, A, k, ti=np.zeros_like(f) + .1) - wm = FusedWakeGCLWakeModel(tfp + "wind_farms/3tb.yml") - aep_calc = AEPCalculator(wr, wm) - init_pos = wm.windFarm.pos.T - tf = TopFarm(init_pos, aep_calc.get_TopFarm_cost_component(), 160, init_pos, boundary_type='square') - tf.evaluate() - self.assertEqual(tf.get_cost(), -19.85973533524627) +def test_GCL(aep_calc): + init_pos = aep_calc.wake_model.windFarm.pos.T + assert aep_calc(init_pos) == 19.85973533524627 # tb aligned north-south -> wake + assert aep_calc(np.array([[-500, 0, 500], [0, 0, 0]]).T) == 22.31788007605505 # tb aligned West-East -> no wake -if __name__ == "__main__": - unittest.main() +def test_GCL_Topfarm(aep_calc): + init_pos = aep_calc.wake_model.windFarm.pos.T + tf = TopFarm(init_pos, aep_calc.get_TopFarm_cost_component(), 160, init_pos, boundary_type='square') + tf.evaluate() + assert tf.get_cost() == -19.85973533524627 diff --git a/tests/test_fusedwake_models/test_noj.py b/tests/test_fusedwake_models/test_noj.py new file mode 100644 index 00000000..703a26a6 --- /dev/null +++ b/tests/test_fusedwake_models/test_noj.py @@ -0,0 +1,32 @@ +import pytest + +import numpy as np +from tests.test_files import tfp +from topfarm._topfarm import TopFarm +from topfarm.cost_models.fused_wake_wrappers import FusedWakeNOJWakeModel +from topfarm.cost_models.utils.aep_calculator import AEPCalculator +from topfarm.cost_models.utils.wind_resource import WindResource + + +@pytest.fixture() +def aep_calc(): + # f, A, k = read_lib(fuga_path + 'LUT/Farms/Horns Rev 1\hornsrev_north_only_pm45.lib') + f = [1.0, 0.0, 0.0, 0.0] + A = [9.176929, 9.782334, 9.531809, 9.909545] + k = [2.392578, 2.447266, 2.412109, 2.591797] + wr = WindResource(f, A, k, ti=np.zeros_like(f) + .1) + wm = FusedWakeNOJWakeModel(tfp + "wind_farms/3tb.yml") + return AEPCalculator(wr, wm) + + +def test_GCL(aep_calc): + init_pos = aep_calc.wake_model.windFarm.pos.T + assert aep_calc(init_pos) == 18.90684500124578 + assert aep_calc(np.array([[-500, 0, 500], [0, 0, 0]]).T) == 22.31788007605505 + + +def test_GCL_Topfarm(aep_calc): + init_pos = aep_calc.wake_model.windFarm.pos.T + tf = TopFarm(init_pos, aep_calc.get_TopFarm_cost_component(), 160, init_pos, boundary_type='square') + tf.evaluate() + assert tf.get_cost() == -18.90684500124578 diff --git a/tests/test_try_me.py b/tests/test_try_me.py index 5ede5239..a98000f1 100644 --- a/tests/test_try_me.py +++ b/tests/test_try_me.py @@ -5,6 +5,7 @@ import warnings import mock import pytest import topfarm +import matplotlib.pyplot as plt def get_try_me_modules(): @@ -21,9 +22,14 @@ def get_try_me_modules(): @pytest.mark.parametrize("module", get_try_me_modules()) def test_try_me(module): - # check that all try_me module examples run without errors + # check that all try_me module examples run without errors if os.name == 'posix' and "DISPLAY" not in os.environ: pytest.xfail("No display") print("Checking %s.try_me" % module.__name__) + + def no_show(*args, **kwargs): + pass + plt.show = no_show # disable plt show that requires the use to close the plot + with mock.patch.object(module, "__name__", "__main__"): getattr(module, 'try_me')() diff --git a/topfarm/cost_models/fused_wake_wrappers.py b/topfarm/cost_models/fused_wake_wrappers.py index cfa170aa..18dd10d0 100644 --- a/topfarm/cost_models/fused_wake_wrappers.py +++ b/topfarm/cost_models/fused_wake_wrappers.py @@ -7,11 +7,12 @@ import pytest from fusedwake.WindFarm import WindFarm from fusedwake.gcl.interface import GCL import numpy as np +from fusedwake.noj.interface import NOJ -class FusedWakeGCLWakeModel(object): +class FusedWakeModel(object): - def __init__(self, yml): + def __init__(self, yml, version=None, **kwargs): """Description Parameters @@ -20,37 +21,59 @@ class FusedWakeGCLWakeModel(object): A WindIO `yml` file containing the description of the farm """ self.windFarm = WindFarm(yml=yml) + if version: + self.version = version try: - self.gcl = GCL(WF=self.windFarm, version='fort_gcl') + self.wake_model = self.wake_model_cls(WF=self.windFarm, version=self.version, **kwargs) except ValueError as e: pytest.xfail(str(e)) def __call__(self, turbine_positions, no_wake_wdir, no_wake_wsp, no_wake_ti): - self.gcl.update_position(turbine_positions.T) - - WD, WS, TI = [np.mean(np.atleast_3d(v), 0) for v in [no_wake_wdir, no_wake_wsp, no_wake_ti]] - self.gcl(WS=WS.flatten(), WD=WD.flatten(), TI=TI.flatten()) - p = self.gcl.p_wt + self.wake_model.update_position(turbine_positions.T) + WD, WS, TI = (np.atleast_2d(v) for v in [no_wake_wdir, no_wake_wsp, no_wake_ti]) + assert WD.shape == WS.shape == TI.shape, "Shape of no_wake_wdir, no_wake_wsp and no_wake_ti must equal: %s != %s != %s" % (WD.shape, WS.shape, TI.shape) + if len(WD.shape) == 3: + WD, WS, TI = [np.mean(v, 0) for v in [WD, WS, TI]] + self.run_wake_model(WS, WD, TI) + p = self.wake_model.p_wt p = p.reshape(WD.shape + (self.windFarm.nWT,)) return p.sum(2) # sum over all turbines + def run_wake_model(self, WS, WD, TI): + self.wake_model(WS=WS.flatten(), WD=WD.flatten(), TI=TI.flatten()) + + +class FusedWakeGCLWakeModel(FusedWakeModel): + wake_model_cls = GCL + version = 'fort_gcl' + + +class FusedWakeNOJWakeModel(FusedWakeModel): + wake_model_cls = NOJ + version = 'fort_noj' + def try_me(): if __name__ == '__main__': from fusedwake import fusedwake import os - + import matplotlib.pyplot as plt hornsrev_yml = os.path.dirname(fusedwake.__file__) + "/../examples/hornsrev.yml" - wm = FusedWakeGCLWakeModel(hornsrev_yml) - tb_pos = wm.windFarm.pos - - print(wm(tb_pos.T, no_wake_wdir=270, no_wake_wsp=8, no_wake_ti=0.1)) - - WS_cases = np.arange(4, 12) - WD_cases = np.arange(0, 360, 10) - WS_ms, WD_ms = np.meshgrid(WS_cases, WD_cases) - p = wm(tb_pos.T, WD_ms, WS_ms, np.zeros_like(WS_ms) + .1) - print(p) - + noj, gcl = wake_models = [FusedWakeNOJWakeModel(hornsrev_yml, K=.1), FusedWakeGCLWakeModel(hornsrev_yml)] + tb_pos = noj.windFarm.pos + print(noj(tb_pos.T, no_wake_wdir=270, no_wake_wsp=8, no_wake_ti=0.1)) + + for wm, c in zip(wake_models,'rk'): + WS_cases = np.arange(11, 12) + WD_cases = np.arange(0, 360, 1) + WD_ms, WS_ms = np.meshgrid(WD_cases, WS_cases) + p = wm(tb_pos.T, WD_ms, WS_ms, np.zeros_like(WS_ms) + .1) + plt.xlabel("Wdir") + plt.ylabel("Power") + plt.plot(p.T, color=c, label=wm.wake_model_cls.__name__) + plt.legend() + print(p.sum()) + plt.show() + try_me() -- GitLab