Skip to content
Snippets Groups Projects
Commit 9733117e authored by Mikkel Friis-Møller's avatar Mikkel Friis-Møller
Browse files

Merge branch '14-remove-position-offset-in-pyfuga' into 'master'

Resolve "remove position offset in pyfuga"

Closes #14

See merge request !23
parents c47bcc88 ab463c63
No related branches found
No related tags found
1 merge request!23Resolve "remove position offset in pyfuga"
Pipeline #
'''
Created on 16. apr. 2018
@author: mmpe
'''
from threading import Thread
import threading
import time
import unittest
import numpy as np
import pytest
from topfarm.cost_models.fuga.pascal_dll import PascalDLL
from topfarm.cost_models.fuga.py_fuga import PyFuga
from topfarm.cost_models.fuga.py_fuga import PyFuga, fugalib_path
import os
from topfarm.cost_models.fuga import py_fuga
from topfarm import TopFarm
......@@ -20,31 +12,15 @@ from topfarm import TopFarm
fuga_path = os.path.abspath(os.path.dirname(py_fuga.__file__)) + '/Colonel/'
def _test_parallel(id):
pyFuga = PyFuga()
pyFuga.setup(farm_name='Horns Rev 1',
turbine_model_path=fuga_path + 'LUT/', turbine_model_name='Vestas_V80_(2_MW_offshore)[h=67.00]',
tb_x=[423974, 424033], tb_y=[6151447, 6150889],
mast_position=(0, 0, 70), z0=0.0001, zi=400, zeta0=0,
farms_dir=fuga_path + 'LUT/Farms/', wind_atlas_path='Horns Rev 1\hornsrev0.lib')
print(pyFuga.stdout_filename, id)
for i in range(1):
print(threading.current_thread(), id)
np.testing.assert_array_almost_equal(pyFuga.get_aep([0, 0], [0, 200]), [14.044704, 16.753474, 0.401041, 0.838316])
time.sleep(1)
class Test(unittest.TestCase):
def lib_missing(self):
lib_path = os.path.dirname(py_fuga.__file__) + "/Colonel/FugaLib/FugaLib.%s" % ('so', 'dll')[os.name == 'nt']
def check_lib_exists():
if os.path.isfile(fugalib_path) is False:
pytest.xfail("Fugalib '%s' not found\n" % fugalib_path)
if os.path.isfile(lib_path) is False:
pytest.xfail("Fugalib missing")
raise Warning("Fugalib '%s' not found\n" % lib_path)
return False
def get_fuga(self, tb_x=[423974, 424033], tb_y=[6151447, 6150889]):
@pytest.fixture
def get_fuga():
def _fuga(tb_x=[423974, 424033], tb_y=[6151447, 6150889]):
check_lib_exists()
pyFuga = PyFuga()
pyFuga.setup(farm_name='Horns Rev 1',
turbine_model_path=fuga_path + 'LUT/', turbine_model_name='Vestas_V80_(2_MW_offshore)[h=67.00]',
......@@ -52,74 +28,87 @@ class Test(unittest.TestCase):
mast_position=(0, 0, 70), z0=0.0001, zi=400, zeta0=0,
farms_dir=fuga_path + 'LUT/Farms/', wind_atlas_path='Horns Rev 1/hornsrev_north_only.lib', climate_interpolation=False)
return pyFuga
return _fuga
def testCheckVersion(self):
if self.lib_missing():
return
lib = PascalDLL(fuga_path + "FugaLib/FugaLib.%s" % ('so', 'dll')[os.name == 'nt'])
self.assertRaisesRegex(Exception, "This version of FugaLib supports interface version ", lib.CheckInterfaceVersion, 1)
pyFuga = self.get_fuga() # check that current interface version match
pyFuga.cleanup()
def testSetup(self):
if self.lib_missing():
return
pyFuga = self.get_fuga()
self.assertEqual(pyFuga.get_no_tubines(), 2)
self.assertIn("Loading", pyFuga.log)
# check that new setup resets number of turbines
pyFuga = self.get_fuga()
self.assertEqual(pyFuga.get_no_tubines(), 2)
pyFuga.cleanup()
def testAEP_one_tb(self):
if self.lib_missing():
return
pyFuga = self.get_fuga([0], [0])
np.testing.assert_array_almost_equal(pyFuga.get_aep(np.array([[0], [0]]).T), [7.450272, 7.450272, 0.424962, 1.])
pyFuga.cleanup()
def testAEP(self):
if self.lib_missing():
return
pyFuga = self.get_fuga()
np.testing.assert_array_almost_equal(pyFuga.get_aep(np.array([[0, 200], [0, 0]]).T), [14.866138, 14.900544, 0.423981, 0.997691])
np.testing.assert_array_almost_equal(pyFuga.get_aep_gradients(np.array([[0, 200], [0, 0]]).T), 0)
@pytest.fixture
def pyFuga():
return get_fuga()()
def _test_parallel(i):
pyFuga = get_fuga()()
print(pyFuga.stdout_filename, i)
for _ in range(1):
print(threading.current_thread(), i)
np.testing.assert_array_almost_equal(pyFuga.get_aep(np.array([[0, 0], [0, 200]]).T), [12.124883, 14.900544, 0.3458, 0.813721])
np.testing.assert_array_almost_equal(pyFuga.get_aep_gradients(np.array([[0, 0], [0, 200]]).T), [[-0.001794, 0.001794],
[-0.008126, 0.008126],
[0., 0.]])
np.testing.assert_array_almost_equal(pyFuga.get_aep(np.array([[0, 200], [0, 200]]).T), [14.864909, 14.900544, 0.423946, 0.997608])
np.testing.assert_array_almost_equal(pyFuga.get_aep_gradients(np.array([[0, 200], [0, 200]]).T), [[-5.165553e-06, 5.165553e-06],
[1.599768e-06, -1.599768e-06],
[0.000000e+00, 0.000000e+00]])
pyFuga.cleanup()
def testAEP_topfarm(self):
if self.lib_missing():
return
pyFuga = self.get_fuga()
init_pos = [[0, 0], [200, 0]]
tf = TopFarm(init_pos, pyFuga.get_TopFarm_cost_component(), 160, init_pos, boundary_type='square')
tf.evaluate()
np.testing.assert_array_almost_equal(tf.get_cost(), -14.866138)
def test_pyfuga_cmd(self):
if self.lib_missing():
return
pyFuga = PyFuga()
pyFuga.execute(r'echo "ColonelInit"')
self.assertEqual(pyFuga.log.strip().split("\n")[-1], 'ColonelInit')
time.sleep(1)
def testCheckVersion(get_fuga):
check_lib_exists()
lib = PascalDLL(fuga_path + "FugaLib/FugaLib.%s" % ('so', 'dll')[os.name == 'nt'])
with pytest.raises(Exception, match="This version of FugaLib supports interface version "):
lib.CheckInterfaceVersion(1)
pyFuga = get_fuga() # check that current interface version match
pyFuga.cleanup()
# def test_parallel(self):
# from multiprocessing import Pool
#
# with Pool(5) as p:
# print(p.map(_test_parallel, [1, 2]))
def testSetup(get_fuga):
pyFuga = get_fuga()
assert pyFuga.get_no_turbines() == 2
assert "Loading" in pyFuga.log
# check that new setup resets number of turbines
pyFuga = get_fuga()
assert pyFuga.get_no_turbines() == 2
pyFuga.cleanup()
def testAEP_one_tb(get_fuga):
pyFuga = get_fuga([0], [0])
np.testing.assert_array_almost_equal(pyFuga.get_aep(np.array([[0], [0]]).T), [7.450272, 7.450272, 0.424962, 1.])
pyFuga.cleanup()
def testAEP(pyFuga):
np.testing.assert_array_almost_equal(pyFuga.get_aep(np.array([[0, 200], [0, 0]]).T), [14.866138, 14.900544, 0.423981, 0.997691])
np.testing.assert_array_almost_equal(pyFuga.get_aep_gradients(np.array([[0, 200], [0, 0]]).T), 0)
np.testing.assert_array_almost_equal(pyFuga.get_aep(np.array([[0, 0], [0, 200]]).T), [12.124883, 14.900544, 0.3458, 0.813721])
np.testing.assert_array_almost_equal(pyFuga.get_aep_gradients(np.array([[0, 0], [0, 200]]).T), [[-0.001794, 0.001794],
[-0.008126, 0.008126],
[0., 0.]])
np.testing.assert_array_almost_equal(pyFuga.get_aep(np.array([[0, 200], [0, 200]]).T), [14.864909, 14.900544, 0.423946, 0.997608])
np.testing.assert_array_almost_equal(pyFuga.get_aep_gradients(np.array([[0, 200], [0, 200]]).T), [[-5.165553e-06, 5.165553e-06],
[1.599768e-06, -1.599768e-06],
[0.000000e+00, 0.000000e+00]])
pyFuga.cleanup()
def testLargeOffset(pyFuga):
o = 1.e16
np.testing.assert_array_almost_equal(pyFuga.get_aep(np.array([[0 + o, 0 + o], [0 + o, 200 + o]]).T), [12.124883, 14.900544, 0.3458, 0.813721])
np.testing.assert_array_almost_equal(pyFuga.get_aep_gradients(), [[-0.001794, 0.001794],
[-0.008126, 0.008126],
[0., 0.]])
def testAEP_topfarm(get_fuga):
pyFuga = get_fuga()
init_pos = [[0, 0], [200, 0]]
tf = TopFarm(init_pos, pyFuga.get_TopFarm_cost_component(), 160, init_pos, boundary_type='square')
tf.evaluate()
np.testing.assert_array_almost_equal(tf.get_cost(), -14.866138)
def test_pyfuga_cmd():
check_lib_exists()
pyFuga = PyFuga()
pyFuga.execute(r'echo "ColonelInit"')
assert pyFuga.log.strip().split("\n")[-1] == 'ColonelInit'
if __name__ == "__main__":
unittest.main()
# @pytest.mark.xfail
# def test_parallel():
# from multiprocessing import Pool
# with Pool(5) as p:
# print(p.map(_test_parallel, [1, 2]))
......@@ -19,6 +19,7 @@ c_double_p = POINTER(c_double)
c_int_p = POINTER(ctypes.c_int32)
fuga_path = os.path.abspath(os.path.dirname(__file__)) + '/Colonel/'
fugalib_path = os.path.dirname(__file__) + "/Colonel/FugaLib/FugaLib.%s" % ('so', 'dll')[os.name == 'nt']
class PyFuga(object):
......@@ -29,11 +30,10 @@ class PyFuga(object):
with NamedTemporaryFile() as f:
self.stdout_filename = f.name + "pyfuga.txt"
lib_path = os.path.dirname(__file__) + "/Colonel/FugaLib/FugaLib.%s" % ('so', 'dll')[os.name == 'nt']
if os.path.isfile(lib_path) is False:
raise Exception("Fuga lib cannot be found: '%s'" % lib_path)
if os.path.isfile(fugalib_path) is False:
raise Exception("Fuga lib cannot be found: '%s'" % fugalib_path)
self.lib = PascalDLL(lib_path)
self.lib = PascalDLL(fugalib_path)
self.lib.CheckInterfaceVersion(self.interface_version)
self.lib.Initialize(self.stdout_filename)
......@@ -45,9 +45,8 @@ class PyFuga(object):
self.lib.Setup(float(mast_position[0]), float(mast_position[1]), float(mast_position[2]),
float(z0), float(zi), float(zeta0))
tb_x_ctype = np.array(tb_x, dtype=np.float).ctypes
tb_y_ctype = np.array(tb_y, dtype=np.float).ctypes
assert len(tb_x) == len(tb_y)
tb_x_ctype, tb_y_ctype = self.tb_ctypes(tb_x, tb_y)
self.lib.AddWindFarm(farm_name, turbine_model_path, turbine_model_name,
len(tb_x), tb_x_ctype.data_as(c_double_p), tb_y_ctype.data_as(c_double_p))
......@@ -55,7 +54,7 @@ class PyFuga(object):
assert os.path.isfile(farms_dir + wind_atlas_path), farms_dir + wind_atlas_path
self.lib.SetupWindClimate(farms_dir, wind_atlas_path, climate_interpolation)
#assert len(tb_x) == self.get_no_tubines(), self.log + "\n%d!=%d" % (self.get_no_tubines(),len(tb_x))
assert len(tb_x) == self.get_no_turbines(), self.log + "\n%d!=%d" % (self.get_no_turbines(), len(tb_x))
def cleanup(self):
if hasattr(self, 'lib'):
......@@ -72,16 +71,22 @@ class PyFuga(object):
except Exception:
pass
def get_no_tubines(self):
def get_no_turbines(self):
no_turbines_p = c_int_p(c_int(0))
self.lib.GetNoTurbines(no_turbines_p)
return no_turbines_p.contents.value
def move_turbines(self, tb_x, tb_y):
assert len(tb_x) == len(tb_y) == self.get_no_tubines(), (len(tb_x), len(tb_y), self.get_no_tubines())
tb_x_ctype = np.array(tb_x, dtype=np.float).ctypes
tb_y_ctype = np.array(tb_y, dtype=np.float).ctypes
def tb_ctypes(self, tb_x, tb_y):
assert len(tb_x) == len(tb_y)
# remove mean offset to avoid loosing precision due to high offset
self.tb_x_offset, self.tb_y_offset = np.mean(tb_x), np.mean(tb_y)
tb_x = np.array(tb_x, dtype=np.float) - self.tb_x_offset
tb_y = np.array(tb_y, dtype=np.float) - self.tb_y_offset
return tb_x.ctypes, tb_y.ctypes
def move_turbines(self, tb_x, tb_y):
assert len(tb_x) == len(tb_y) == self.get_no_turbines(), (len(tb_x), len(tb_y), self.get_no_turbines())
tb_x_ctype, tb_y_ctype = self.tb_ctypes(tb_x, tb_y)
self.lib.MoveTurbines(tb_x_ctype.data_as(c_double_p), tb_y_ctype.data_as(c_double_p))
def get_aep(self, turbine_positions=None):
......@@ -92,7 +97,6 @@ class PyFuga(object):
AEPGros_p = c_double_p(c_double(0))
capacity_p = c_double_p(c_double(0))
self.lib.GetAEP(AEPNet_p, AEPGros_p, capacity_p)
#print(tb_x, tb_y, AEPNet_p.contents.value, (15.850434458235156 - AEPNet_p.contents.value) / .000001)
net, gros, cap = [p.contents.value for p in [AEPNet_p, AEPGros_p, capacity_p]]
return (net, gros, cap, net / gros)
......@@ -100,15 +104,14 @@ class PyFuga(object):
if turbine_positions is not None:
self.move_turbines(turbine_positions[:, 0], turbine_positions[:, 1])
n_wt = self.get_no_tubines()
n_wt = self.get_no_turbines()
dAEPdxyz = np.zeros(n_wt), np.zeros(n_wt), np.zeros(n_wt)
dAEPdxyz_ctype = [dAEP.ctypes for dAEP in dAEPdxyz]
self.lib.GetAEPGradients(*[dAEP_ctype.data_as(c_double_p) for dAEP_ctype in dAEPdxyz_ctype])
#print(tb_x, tb_y, dAEPdxyz)
return np.array(dAEPdxyz)
def get_TopFarm_cost_component(self):
n_wt = self.get_no_tubines()
n_wt = self.get_no_turbines()
return AEPCostModelComponent(n_wt,
lambda *args: self.get_aep(*args)[0], # only aep
lambda *args: self.get_aep_gradients(*args)[:2]) # only dAEPdx and dAEPdy
......@@ -118,27 +121,6 @@ class PyFuga(object):
with open(self.stdout_filename) as fid:
return fid.read()
# self.execute("""seed=0
# initialize
# set output file "out.txt"
# load farm "Horns Rev 1"
# 7 point integration off
# meandering off
# insert met mast 0.0 0.0 70.0
# z0=0.0001
# zi=400.0
# zeta0=0.0
# load wakes
# gaussian fit on
# proximity penalty off
# gradients on
# Wind climates interpolation on
# load wind atlas "Horns Rev 1\hornsrev2.lib"
# relative move all turbines -426733.0 -6149501.5
# gradients off
# calculate AEP
# get Farm AEP""")
def execute(self, script):
res = self.lib.ExecuteScript(script.encode())
print("#" + str(res) + "#")
......@@ -153,7 +135,7 @@ def try_me():
mast_position=(0, 0, 70), z0=0.0001, zi=400, zeta0=0,
farms_dir=fuga_path + 'LUT/Farms/', wind_atlas_path='Horns Rev 1\hornsrev.lib')
print(pyFuga.get_no_tubines())
print(pyFuga.get_no_turbines())
print(pyFuga.get_aep(np.array([[0, 0], [0, 1000]])))
print(pyFuga.get_aep(np.array([[0, 1000], [0, 0]])))
print(pyFuga.get_aep_gradients(np.array([[0, 0], [0, 100]])))
......
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