def test_from_WindTurbines(): vestas_v80_wtg = WindTurbines.from_WAsP_wtg( os.path.join(wtg_path, 'Vestas-V80.wtg')) NEG_2750_wtg = WindTurbines.from_WAsP_wtg( os.path.join(wtg_path, 'NEG-Micon-2750.wtg')) _test_wts_wtg( WindTurbines.from_WindTurbines([vestas_v80_wtg, NEG_2750_wtg]))
def test_twotype_windturbines(): v80 = V80() def power(ws, types): power = v80.power(ws) # add 10% type 1 turbines power[types == 1] *= 1.1 return power wts = WindTurbines(names=['V80', 'V88'], diameters=[80, 88], hub_heights=[70, 77], ct_funcs=[v80.ct_funcs[0], v80.ct_funcs[0]], power_funcs=[v80.power, lambda ws: v80.power(ws) * 1.1], power_unit='w') import matplotlib.pyplot as plt types0 = [0] * 9 types1 = [0, 0, 0, 1, 1, 1, 0, 0, 0] types2 = [1] * 9 wts.plot(wt9_x, wt9_y, types1) wfm = NOJ(Hornsrev1Site(), wts) npt.assert_almost_equal( wfm(wt9_x, wt9_y, type=types0).aep(), 81.2066072392765) npt.assert_almost_equal( wfm(wt9_x, wt9_y, type=types1).aep(), 83.72420504573488) npt.assert_almost_equal( wfm(wt9_x, wt9_y, type=types2).aep(), 88.87227386796884) if 0: plt.show()
def test_deprecated_from_WindTurbines(): v80 = V80Deprecated() v88 = WindTurbine('V88', 88, 77, powerCtFunction=PowerCtTabular( hornsrev1.power_curve[:, 0], hornsrev1.power_curve[:, 1] * 1.1, 'w', hornsrev1.ct_curve[:, 1])) with pytest.raises( AssertionError, match='from_WindTurbines no longer supports DeprecatedWindTurbines' ): WindTurbines.from_WindTurbines([v80, v88])
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_Mirror_NOJ(): # Compare points in flow map with ws of WT at same position site = UniformSite([1], ti=0.1) V80_D0 = V80() V80_D0._diameters = [0] wt = WindTurbines.from_WindTurbines([V80(), V80_D0]) wfm = NOJ(site, wt, k=.5, groundModel=Mirror()) sim_res = wfm([0], [0], h=[50], wd=0) fm_ref = sim_res.flow_map(YZGrid(x=0, y=np.arange(-70, 0, 20), z=10)) ref = fm_ref.WS_eff_xylk[:, 0, 0, 0].values res = np.array([ wfm([0, 0], [0, y], [50, 10], type=[0, 1], wd=0).WS_eff.sel(wt=1).item() for y in fm_ref.X[0] ]) if 0: fm_res = sim_res.flow_map(YZGrid(x=0, y=np.arange(-100, 10, 1))) fm_res.plot_wake_map() plt.plot(fm_ref.X[0], fm_ref.Y[0], '.') plt.plot(fm_ref.X[0], ref * 10, label='ref, WS*10') plt.plot(fm_ref.X[0], res * 10, label='Res, WS*10') plt.legend() plt.show() plt.close() npt.assert_array_equal(res, ref)
def test_aep_mixed_type(): site = UniformSite([1], ti=0) wt = WindTurbines.from_WindTurbines( [IEA37_WindTurbines(), IEA37_WindTurbines()]) wfm = NOJ(site, wt) sim_res = wfm([0, 500], [0, 0], type=[0, 1], wd=270) npt.assert_almost_equal( sim_res.aep(with_wake_loss=False).sum(), 2 * wfm([0], [0], wd=270).aep(with_wake_loss=False).sum())
def get_wt(power_ct_func): if isinstance(power_ct_func, list): N = len(power_ct_func) return WindTurbines(names=['Test'] * N, diameters=[80] * N, hub_heights=[70] * N, power_ct_funcs=power_ct_func) else: return WindTurbine(name='Test', diameter=80, hub_height=70, powerCtFunction=power_ct_func)
def test_DeprecatedWindTurbines(): v80 = V80Deprecated() for wts in [v80, WindTurbines(names=['V80'], diameters=[80], hub_heights=[70], ct_funcs=v80._ct_funcs, power_funcs=v80._power_funcs, power_unit='w')]: types0 = [0] * 9 for wfm in get_wfms(wts): # wfm = NOJ(Hornsrev1Site(), wts) npt.assert_array_equal(wts.types(), [0]) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types0), 81.2066072392765)
def test_WindTurbines(): u_p, p = np.asarray(hornsrev1.power_curve).T.copy() u_ct, ct = hornsrev1.ct_curve.T npt.assert_array_equal(u_p, u_ct) curve = PowerCtTabular(ws=u_p, power=p, power_unit='w', ct=ct) for wts in [WindTurbine(name='V80', diameter=80, hub_height=70, powerCtFunction=curve), WindTurbines(names=['V80'], diameters=[80], hub_heights=[70], powerCtFunctions=[curve])]: types0 = [0] * 9 for wfm in get_wfms(wts): npt.assert_array_equal(wts.types(), [0]) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types0), 81.2066072392765)
def test_plot_yz2_types(): wt = WindTurbines.from_WindTurbines([IEA37_WindTurbines(), V80()]) yaw_lst = np.array([-30, 0, 30]) for wd in 0, 45, 90: plt.figure() wt.plot_yz(yaw_lst * 20, types=[0, 1, 0], wd=wd, yaw=yaw_lst) for i, yaw in enumerate(yaw_lst): plt.plot([], 'gray', label="WT %d yaw: %d deg" % (i, yaw)) plt.legend() plt.title("WD: %s" % wd) if 0: plt.show() plt.close()
def test_twotype_windturbines(): v80 = V80() v88 = WindTurbine('V88', 88, 77, powerCtFunction=PowerCtTabular( hornsrev1.power_curve[:, 0], hornsrev1.power_curve[:, 1] * 1.1, 'w', hornsrev1.ct_curve[:, 1])) wts = WindTurbines.from_WindTurbines([v80, v88]) types0 = [0] * 9 types1 = [0, 0, 0, 1, 1, 1, 0, 0, 0] types2 = [1] * 9 for wfm in get_wfms(wts): npt.assert_array_equal(wts.types(), [0, 1]) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types0), 81.2066072392765) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types1), 83.72420504573488) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types2), 88.87227386796884)
def test_neighbour_farm_speed(): # import and setup site and windTurbines site = IEA37Site(16) # setup current, neighbour and all positions wt_x, wt_y = site.initial_position.T neighbour_x, neighbour_y = wt_x - 4000, wt_y all_x, all_y = np.r_[wt_x, neighbour_x], np.r_[wt_y, neighbour_y] windTurbines = WindTurbines.from_WindTurbines([IEA37_WindTurbines(), IEA37_WindTurbines()]) windTurbines._names = ["Current wind farm", "Neighbour wind farm"] types = [0] * len(wt_x) + [1] * len(neighbour_x) wf_model = PropagateDownwind(site, windTurbines, wake_deficitModel=BastankhahGaussianDeficit(use_effective_ws=True), superpositionModel=LinearSum()) # Consider wd=270 +/- 30 deg only wd_lst = np.arange(240, 301) sim_res, t = timeit(wf_model, verbose=False)(all_x, all_y, type=types, ws=9.8, wd=wd_lst) if 1: ext = 100 flow_box = wf_model(neighbour_x, neighbour_y, wd=wd_lst).flow_box( x=np.linspace(min(wt_x) - ext, max(wt_x) + ext, 53), y=np.linspace(min(wt_y) - ext, max(wt_y) + ext, 51), h=[100, 110, 120]) wake_site = XRSite.from_flow_box(flow_box) wake_site.save('tmp.nc') else: wake_site = XRSite.load('tmp.nc') wf_model_wake_site = PropagateDownwind(wake_site, windTurbines, wake_deficitModel=BastankhahGaussianDeficit(use_effective_ws=True), superpositionModel=LinearSum()) sim_res_wake_site, _ = timeit(wf_model_wake_site, verbose=False)(wt_x, wt_y, ws=9.8, wd=wd_lst) npt.assert_allclose(sim_res.aep().sel(wt=np.arange(len(wt_x))).sum(), sim_res_wake_site.aep().sum(), rtol=0.0005) npt.assert_array_almost_equal(sim_res.aep().sel(wt=np.arange(len(wt_x))), sim_res_wake_site.aep(), 2)
def test_DeprecatedWindTurbines(): for wts in [ V80Deprecated(), WindTurbines( names=['V80'], diameters=[80], hub_heights=[70], ct_funcs=[ lambda ws: np.interp(ws, hornsrev1.ct_curve[:, 0], hornsrev1.ct_curve[:, 1]) ], power_funcs=[ lambda ws: np.interp(ws, hornsrev1.power_curve[:, 0], hornsrev1.power_curve[:, 1]) ], power_unit='w') ]: types0 = [0] * 9 wfm = NOJ(Hornsrev1Site(), wts) npt.assert_array_equal(wts.types(), [0]) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types0), 81.2066072392765)
aep_ls = sim_res_ls.aep() aep_ms = sim_res_ms.aep() print(aep_ss, aep_ls, aep_ms) # plot wake map for sim_res, aep in [['sim_res_ss', 'aep_ss'], ['sim_res_ls', 'aep_ls'], ['sim_res_ms', 'aep_ms']]: flow_map = locals()[sim_res].flow_map(wd=30, ws=9.8) flow_map.plot_wake_map() flow_map.plot_windturbines() plt.title('%s AEP: %.2f GWh' % (aep, locals()[aep])) plt.show() from py_wake.site import WaspGridSite from py_wake.wind_turbines import WindTurbines import pandas as pd layout = pd.read_table('/Users/luqi/开发/PyWake2_LQ/py_wake/examples/CGN_RD/site/cgn_layout.txt') site_cgn = WaspGridSite.from_wasp_grd('/Users/luqi/开发/PyWake2_LQ/py_wake/examples/CGN_RD/grd', speedup_using_pickle=False) wtg_g4 = WindTurbines.from_WAsP_wtg('/Users/luqi/开发/PyWake2_LQ/py_wake/examples/CGN_RD/power/SWT-4.0-130-CGN 1.223.wtg') type_i, h_i, D_i = wtg_g4.get_defaults(len(layout['X'])) lw = site_cgn.local_wind(np.array(layout['X']), np.array(layout['Y']), h_i) # localwind cgn_model_ss = NOJ(site_cgn, wtg_g4, k=0.05, superpositionModel=SquaredSum()) cgn_sim_res_ss = cgn_model_ss(np.array(layout['X']), np.array(layout['Y'])) cgn_aep_grs = cgn_sim_res_ss.aep(with_wake_loss=False) cgn_aep_net = cgn_sim_res_ss.aep() print(cgn_aep_grs, cgn_aep_net, '%.2f ' % ((1-cgn_aep_net/cgn_aep_grs)*100) + '%') cgn_flow_map = cgn_sim_res_ss.flow_map(wd=30, ws=10) cgn_flow_map.plot_wake_map() cgn_flow_map.plot_windturbines() plt.title('%s AEP: %.2f GWh' % ('CGN NET', cgn_aep_net)) plt.show()
import multiprocessing from py_wake.examples.data.hornsrev1 import Hornsrev1Site, wt_x, wt_y from py_wake import IEA37SimpleBastankhahGaussian from py_wake.tests.check_speed import timeit import numpy as np from py_wake.tests import npt from py_wake.wind_turbines import WindTurbines from py_wake.examples.data import wtg_path wt = WindTurbines.from_WAsP_wtg(wtg_path + "Vestas-V80.wtg") site = Hornsrev1Site() wf_model = IEA37SimpleBastankhahGaussian(site, wt) wd_lst = np.arange(0, 360, 10) def aep_wd(args): x, y, wd = args return wf_model(x, y, wd=wd, ws=None).aep().sum() def aep_all_multiprocessing(pool, x, y): return np.sum(pool.map(aep_wd, [(x, y, i) for i in wd_lst])) def aep_wfm_xy(args): wfm, x, y = args return wfm(x, y, wd=wd_lst).aep().sum() def aep_xy(args):
def get_wfm(grad=True): wt = WindTurbines.from_WAsP_wtg(wtg_path + "Vestas-V80.wtg", ) site = Hornsrev1Site() return IEA37SimpleBastankhahGaussian(site, wt)
def main(obj=False, max_con_on=True): if __name__ == '__main__': start = time.time() try: import matplotlib.pyplot as plt plt.gcf() plot = True except RuntimeError: plot = False # ------ DEFINE WIND TURBINE TYPES, LOCATIONS & STORE METADATA ------- windTurbines = WindTurbines( names=['Ghost_T1', 'T2'], diameters=[40, 84], hub_heights=[70, hornsrev1.HornsrevV80().hub_height()], ct_funcs=[dummy_thrust(ct_rated=0), hornsrev1.HornsrevV80().ct], power_funcs=[ cube_power(power_rated=0), cube_power(power_rated=3000) ], # hornsrev1.HornsrevV80()._power], power_unit='kW') Drotor_vector = windTurbines._diameters power_rated_vec = np.array( [pcurv(25) / 1000 for pcurv in windTurbines._power_funcs]) hub_height_vector = windTurbines._hub_heights x, y = np.meshgrid(range(-840, 840, 420), range(-840, 840, 420)) n_wt = len(x.flatten()) # initial turbine positions and other independent variables ext_vars = {'x': x.flatten(), 'y': y.flatten(), 'obj': obj * 1} capconst = [] if max_con_on: capconst = [ CapacityConstraint(max_capacity=30.01, rated_power_array=power_rated_vec) ] # ---------------- DEFINE SITE & SELECT WAKE MODEL ------------------- # site = UniformWeibullSite(p_wd=[50, 50], a=[9, 9], k=[2.3, 2.3], ti=.1, alpha=0, h_ref=100) site = UniformWeibullSite(p_wd=[100], a=[9], k=[2.3], ti=.1) site.default_ws = [9] # reduce the number of calculations site.default_wd = [0] # reduce the number of calculations wake_model = NOJ(site, windTurbines) AEPCalc = AEPCalculator(wake_model) # ------------- OUTPUTS AEP PER TURBINE & FARM IRR ------------------- def aep_func(x, y, type, obj, **kwargs ): # TODO fix type as input change to topfarm turbinetype out = AEPCalc.calculate_AEP(x_i=x, y_i=y, type_i=type.astype(int)).sum((1, 2)) if obj: # if objective is AEP; output the total Farm_AEP out = np.sum(out) return out * 10**6 def irr_func(aep, type, **kwargs): idx = type.astype(int) return economic_evaluation(Drotor_vector[idx], power_rated_vec[idx], hub_height_vector[idx], aep).calculate_irr() # ----- WRAP AEP AND IRR INTO TOPFARM COMPONENTS AND THEN GROUP ----- aep_comp = CostModelComponent(input_keys=[ topfarm.x_key, topfarm.y_key, topfarm.type_key, ('obj', obj) ], n_wt=n_wt, cost_function=aep_func, output_key="aep", output_unit="GWh", objective=obj, output_val=np.zeros(n_wt), income_model=True) comps = [aep_comp] # AEP component is always in the group if not obj: # if objective is IRR initiate/add irr_comp irr_comp = CostModelComponent(input_keys=[topfarm.type_key, 'aep'], n_wt=n_wt, cost_function=irr_func, output_key="irr", output_unit="%", objective=True) comps.append(irr_comp) group = TopFarmGroup(comps) # - INITIATE THE PROBLEM WITH ONLY TURBINE TYPE AS DESIGN VARIABLES - tf = TopFarmProblem( design_vars={ topfarm.type_key: ([0] * n_wt, 0, len(windTurbines._names) - 1) }, cost_comp=group, driver=EasyRandomSearchDriver(randomize_func=RandomizeAllUniform( [topfarm.type_key]), max_iter=1), # driver=EasySimpleGADriver(max_gen=2, random_state=1), constraints=capconst, # plot_comp=TurbineTypePlotComponent(windTurbines._names), plot_comp=NoPlot(), ext_vars=ext_vars) cost, state, rec = tf.optimize() # view_model(problem, outfile='ex5_n2.html', show_browser=False) end = time.time() print(end - start) # %% # ------------------- OPTIONAL VISUALIZATION OF WAKES ---------------- post_visual, save = False, False if post_visual: # import matplotlib.pyplot as plt for cou, (i, j, k, co, ae) in enumerate( zip(rec['x'], rec['y'], rec['type'], rec['cost'], rec['aep'])): AEPCalc.calculate_AEP(x_i=i, y_i=j, type_i=k) AEPCalc.plot_wake_map(wt_x=i, wt_y=j, wt_type=k, wd=site.default_wd[0], ws=site.default_ws[0], levels=np.arange(2.5, 12, .1)) windTurbines.plot(i, j, types=k) title = f'IRR: {-np.round(co,2)} %, AEP : {round(np.sum(ae))} GWh, ' if "totalcapacity" in rec.keys(): title += f'Total Capacity: {rec["totalcapacity"][cou]} MW' plt.title(title) if save: plt.savefig( r'..\..\..\ima2\obj_AEP_{}_MaxConstraint_{}_{}.png'. format(obj, max_con_on, cou)) plt.show()
from py_wake.site._site import UniformSite from py_wake.tests import npt from py_wake.flow_map import HorizontalGrid from py_wake.wind_turbines import WindTurbines from py_wake.wind_farm_models.engineering_models import All2AllIterative from py_wake.deficit_models.noj import NOJDeficit from py_wake.superposition_models import LinearSum, WeightedSum from py_wake.turbulence_models.stf import STF2017TurbulenceModel from py_wake.wind_turbines.power_ct_functions import PowerCtFunction # Two turbines, 0: Nibe-A, 1:Ct=0 NibeA0 = WindTurbines( names=['Nibe-A'] * 2, diameters=[40] * 2, hub_heights=[50] * 2, # only define for ct powerCtFunctions=[ PowerCtFunction(['ws'], lambda ws, run_only: ws * 0 + 8 / 9, 'w'), PowerCtFunction(['ws'], lambda ws, run_only: ws * 0, 'w') ]) def test_NOJ_Nibe_result(): # Replicate result from: Jensen, Niels Otto. "A note on wind generator interaction." (1983). site = UniformSite([1], 0.1) x_i = [0, 0, 0] y_i = [0, -40, -100] h_i = [50, 50, 50] wfm = All2AllIterative(site, NibeA0,
import pytest import numpy as np from py_wake import NOJ from py_wake.site._site import UniformSite from py_wake.superposition_models import LinearSum, SquaredSum, MaxSum from py_wake.tests import npt from py_wake.wind_turbines import WindTurbines # Two turbines, 0: Nibe-A, 1:Ct=0 NibeA0 = WindTurbines(names=['Nibe-A'] * 2, diameters=[40] * 2, hub_heights=[50] * 2, ct_funcs=[lambda _: 8 / 9, lambda _: 0], power_funcs=[lambda _: 0] * 2, power_unit='w') d02 = 8.1 - 5.7 d12 = 8.1 - 4.90473373 @pytest.mark.parametrize('superpositionModel,res', [(LinearSum(), 8.1 - (d02 + d12)), (SquaredSum(), 8.1 - np.hypot(d02, d12)), (MaxSum(), 8.1 - d12)]) def test_superposition_models(superpositionModel, res): site = UniformSite([1], 0.1) wake_model = NOJ(site, NibeA0, superpositionModel=superpositionModel) x_i = [0, 0, 0] y_i = [0, -40, -100] h_i = [50, 50, 50] WS_eff_ilk = wake_model.calc_wt_interaction(x_i, y_i, h_i, [0, 0, 1], 0.0,
types0 = [0] * 9 types1 = [0, 0, 0, 1, 1, 1, 0, 0, 0] types2 = [1] * 9 for wfm in get_wfms(wts): npt.assert_array_equal(wts.types(), [0, 1]) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types0), 81.2066072392765) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types1), 83.72420504573488) npt.assert_almost_equal(wfm.aep(wt9_x, wt9_y, type=types2), 88.87227386796884) @pytest.mark.parametrize('wts_wtg', [ lambda: WindTurbine.from_WAsP_wtg([os.path.join(wtg_path, 'Vestas-V80.wtg'), os.path.join(wtg_path, 'NEG-Micon-2750.wtg')]), lambda:WindTurbines.from_WindTurbine_lst([WindTurbine.from_WAsP_wtg(os.path.join(wtg_path, 'Vestas-V80.wtg')), WindTurbine.from_WAsP_wtg(os.path.join(wtg_path, 'NEG-Micon-2750.wtg'))])]) def test_wasp_wtg(wts_wtg): wts_wtg = wts_wtg() assert(wts_wtg.name(type=0) == 'Vestas V80 (2MW, Offshore)') assert(wts_wtg.diameter(type=0) == 80) assert(wts_wtg.hub_height(type=0) == 67) npt.assert_array_equal(wts_wtg.power(np.array([0, 3, 3.99, 4, 5, 9, 18, 25, 25.01, 100]), type=0), np.array([0, 0, 0, 66600, 154000, 996000, 2e6, 2e6, 0, 0])) npt.assert_array_equal(wts_wtg.ct(np.array([1, 3.99, 4, 7, 9, 17, 25, 25.01, 100]), type=0), np.array([0.052, 0.052, 0.818, 0.805, 0.807, 0.167, 0.052, 0.052, 0.052])) assert(wts_wtg.name(type=1) == 'NEG-Micon 2750/92 (2750 kW)') assert(wts_wtg.diameter(type=1) == 92) assert(wts_wtg.hub_height(type=1) == 70) npt.assert_array_equal(wts_wtg.power(np.array([0, 3, 3.99, 4, 5, 9, 18, 25, 25.01, 100]), type=1), np.array([0, 0, 0, 55000, 185000, 1326000, 2748000, 2750000, 0, 0]))