예제 #1
0
def test_spline():
    wt_tab = V80()
    wt_spline = V80()
    wt_spline.spline_ct_power(err_tol_factor=1e-2)
    ws_lst = np.arange(3, 25, .001)

    # mean and max error
    assert (wt_tab.power(ws_lst) - wt_spline.power(ws_lst)).mean() < 1
    assert ((wt_tab.power(ws_lst) - wt_spline.power(ws_lst)).max()) < 1400

    # max change of gradient 80 times lower
    assert np.diff(np.diff(wt_spline.power(ws_lst))).max() * 80 < np.diff(np.diff(wt_tab.power(ws_lst))).max()

    ws_pts = [6.99, 7.01]
    dpdu_tab_pts = np.diag(fd(wt_tab.power)(np.array(ws_pts)))
    with use_autograd_in():
        dpdu_spline_pts = np.diag(autograd(wt_spline.power)(np.array(ws_pts)))
    npt.assert_array_almost_equal(dpdu_spline_pts, [205555.17794162, 211859.45965873])

    if 0:
        plt.plot(ws_lst, wt_tab.power(ws_lst))
        plt.plot(ws_lst, wt_spline.power(ws_lst))

        for wt, dpdu_pts, label in [(wt_tab, dpdu_tab_pts, 'V80 tabular'),
                                    (wt_spline, dpdu_spline_pts, 'V80 spline')]:
            for ws, dpdu in zip(ws_pts, dpdu_pts):
                plot_gradients(wt.power(ws), dpdu, ws, label, 1)

        ax = plt.gca().twinx()
        ax.plot(ws_lst, wt.power(ws_lst) - wt_spline.power(ws_lst))
        plt.figure()
        plt.plot(np.diff(np.diff(wt_tab.power(ws_lst))))
        plt.plot(np.diff(np.diff(wt_spline.power(ws_lst))))
        plt.show()
예제 #2
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)
예제 #3
0
def test_method():
    wt_linear = V80()
    wt_pchip = V80(method='pchip')
    wt_spline = V80(method='spline')
    ws_lst = np.arange(3, 25, .001)
    for wt in [wt_linear, wt_pchip, wt_spline]:
        wt.enable_autograd()

    ws_pts = [6.99, 7.01]
    with use_autograd_in():
        dpdu_linear_pts = autograd(wt_linear.power)(np.array(ws_pts))
        dpdu_pchip_pts = autograd(wt_pchip.power)(np.array(ws_pts))
        dpdu_spline_pts = autograd(wt_spline.power)(np.array(ws_pts))

    if 0:
        wt_dp_label_lst = [(wt_linear, dpdu_linear_pts, 'linear'),
                           (wt_pchip, dpdu_pchip_pts, 'pchip'),
                           (wt_spline, dpdu_spline_pts, 'spline')]
        for wt, dpdu_pts, label in wt_dp_label_lst:
            c = plt.plot(ws_lst, wt.power(ws_lst), label=label)[0].get_color()
            gradients.color_dict[label] = c

            for ws, dpdu in zip(ws_pts, dpdu_pts):
                plot_gradients(wt.power(ws), dpdu, ws, label)

        plt.legend()
        plt.figure()
        for wt, dpdu_pts, label in wt_dp_label_lst:
            plt.plot(ws_lst, wt_linear.power(ws_lst) - wt.power(ws_lst), label=label)

        plt.legend()
        plt.ylabel('Power difference wrt. linear')

        plt.figure()
        for wt, dpdu_pts, label in wt_dp_label_lst:
            plt.plot(np.diff(np.diff(wt.power(ws_lst))), label=label)
        plt.ylabel('Change of gradient')
        plt.legend()

        plt.show()

    # mean and max error
    for wt, mean_tol, absmean_tol, max_tol in [(wt_pchip, 213, 2323, 15632),
                                               (wt_spline, 1, 1, 1380)]:
        assert np.abs((wt_linear.power(ws_lst) - wt.power(ws_lst)).mean()) < mean_tol
        assert np.abs((wt_linear.power(ws_lst) - wt.power(ws_lst)).mean()) < absmean_tol
        assert np.abs((wt_linear.power(ws_lst) - wt.power(ws_lst)).max()) < max_tol

    for wt, diff_grad_max, dpdu_pts, ref_dpdu_pts in [(wt_linear, 64, dpdu_linear_pts, [178000.00007264, 236000.00003353]),
                                                      (wt_pchip, 0.2, dpdu_pchip_pts, [
                                                       202520.16516056, 203694.66294614]),
                                                      (wt_spline, 0.8, dpdu_spline_pts, [205555.17794162, 211859.45965873])]:
        assert np.diff(np.diff(wt.power(ws_lst))).max() < diff_grad_max
        npt.assert_array_almost_equal(dpdu_pts, ref_dpdu_pts)
예제 #4
0
def test_GenericWindTurbine_cut_in_out(power_idle, ct_idle):
    ref = V80()
    power_norm = ref.power(15)

    wt = GenericWindTurbine('Generic',
                            ref.diameter(),
                            ref.hub_height(),
                            power_norm / 1e3,
                            turbulence_intensity=0,
                            ws_cutin=3,
                            ws_cutout=25,
                            power_idle=power_idle,
                            ct_idle=ct_idle)
    if 0:
        u = np.arange(0, 30, .1)
        p, ct = wt.power_ct(u)
        plt.plot(u, p / 1e6, label='Generic')

        plt.plot(u, ref.power(u) / 1e6, label=ref.name())

        plt.ylabel('Power [MW]')
        plt.legend()
        ax = plt.twinx()
        ax.plot(u, ct, '--')
        ax.plot(u, ref.ct(u), '--')
        plt.ylabel('Ct')
        plt.show()
    assert wt.ct(2.9) == ct_idle
    assert wt.power(2.9) == power_idle
    assert wt.ct(25.1) == ct_idle
    assert wt.power(25.1) == power_idle
예제 #5
0
def test_time_series_operating_wrong_shape():
    from py_wake.wind_turbines.power_ct_functions import PowerCtFunctionList, PowerCtTabular
    d = np.load(os.path.dirname(examples.__file__) + "/data/time_series.npz")
    wd, ws, ws_std = [d[k][:6 * 24] for k in ['wd', 'ws', 'ws_std']]
    ws += 3
    t = np.arange(6 * 24)
    wt = V80()
    site = Hornsrev1Site()

    # replace powerCtFunction
    wt.powerCtFunction = PowerCtFunctionList(
        key='operating',
        powerCtFunction_lst=[
            PowerCtTabular(ws=[0, 100],
                           power=[0, 0],
                           power_unit='w',
                           ct=[0, 0]),  # 0=No power and ct
            wt.powerCtFunction
        ],  # 1=Normal operation
        default_value=1)
    wfm = NOJ(site, wt)
    x, y = site.initial_position.T
    operating = (t < 48) | (t > 72)
    with pytest.raises(
            ValueError,
            match=
            r"Argument, operating\(shape=\(1, 144\)\), has unsupported shape."
    ):
        wfm(x, y, ws=ws, wd=wd, time=t, operating=[operating])
예제 #6
0
def test_time_series_operating():
    from py_wake.wind_turbines.power_ct_functions import PowerCtFunctionList, PowerCtTabular
    d = np.load(os.path.dirname(examples.__file__) + "/data/time_series.npz")
    wd, ws, ws_std = [d[k][:6 * 24] for k in ['wd', 'ws', 'ws_std']]
    ws += 3
    t = np.arange(6 * 24)
    wt = V80()
    site = Hornsrev1Site()

    # replace powerCtFunction
    wt.powerCtFunction = PowerCtFunctionList(
        key='operating',
        powerCtFunction_lst=[
            PowerCtTabular(ws=[0, 100],
                           power=[0, 0],
                           power_unit='w',
                           ct=[0, 0]),  # 0=No power and ct
            wt.powerCtFunction
        ],  # 1=Normal operation
        default_value=1)
    wfm = NOJ(site, wt)
    x, y = site.initial_position.T
    operating = (t < 48) | (t > 72)
    sim_res = wfm(x, y, ws=ws, wd=wd, time=t, operating=operating)
    npt.assert_array_equal(sim_res.operating[0], operating)
    npt.assert_array_equal(sim_res.Power[:, operating == 0], 0)
    npt.assert_array_equal(sim_res.Power[:, operating != 0] > 0, True)

    operating = np.ones((80, 6 * 24))
    operating[1] = (t < 48) | (t > 72)
    sim_res = wfm(x, y, ws=ws, wd=wd, time=t, operating=operating)
    npt.assert_array_equal(sim_res.operating, operating)
    npt.assert_array_equal(sim_res.Power.values[operating == 0], 0)
    npt.assert_array_equal(sim_res.Power.values[operating != 0] > 0, True)
예제 #7
0
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()
예제 #8
0
def test_yaw_wrong_name():
    wfm = NOJ(Hornsrev1Site(), V80())
    for k in ['yaw_ilk', 'Yaw']:
        with pytest.raises(
                ValueError,
                match=r'Custom \*yaw\*\-keyword arguments not allowed'):
            wfm([0], [0], **{k: [[[30]]]})
예제 #9
0
def test_yaw_tilt(yaw, tilt, cx, cz):
    site = IEA37Site(16)
    x, y = [0], [0]
    windTurbines = V80()

    D = windTurbines.diameter()
    wfm = IEA37SimpleBastankhahGaussian(
        site, windTurbines, deflectionModel=JimenezWakeDeflection())
    x_lst = np.linspace(-200, 1000, 100)
    y_lst = np.linspace(-100, 100, 201)
    z_lst = np.arange(10, 200, 1)

    fm_yz = wfm(x, y, wd=270, ws=10, yaw=yaw,
                tilt=tilt).flow_map(YZGrid(x=5 * D, y=y_lst, z=z_lst))
    fm_xz = wfm(x, y, wd=180, ws=10, yaw=yaw,
                tilt=tilt).flow_map(YZGrid(x=0, y=x_lst, z=z_lst))
    fm_xy = wfm(x, y, wd=270, ws=10, yaw=yaw,
                tilt=tilt).flow_map(XYGrid(x=x_lst))
    if 0:
        axes = plt.subplots(3, 1)[1].flatten()
        fm_xy.plot_wake_map(ax=axes[0])
        axes[0].axvline(5 * D)
        fm_xz.plot_wake_map(ax=axes[1])
        axes[1].axvline(5 * D)
        fm_yz.plot_wake_map(ax=axes[2])
        plt.show()

    wake_center = fm_yz.WS_eff.where(fm_yz.WS_eff == fm_yz.WS_eff.min(),
                                     drop=True).squeeze()
    npt.assert_allclose(wake_center.y, cx, atol=.1)
    npt.assert_allclose(wake_center.h, cz, atol=.24)
예제 #10
0
def test_Mirror(wfm_cls):
    # Compare points in flow map with ws of WT at same position. All2Alliterative failing with NOJ and WT.diameter=0
    # and therefore this cannot be tested above
    site = UniformSite([1], ti=0.1)
    wt = V80()
    wfm = wfm_cls(site,
                  wt,
                  ZongGaussianDeficit(a=[0, 1]),
                  turbulenceModel=STF2017TurbulenceModel(),
                  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], 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)
예제 #11
0
def test_Mirror_flow_map(wfm_cls, groundModel, superpositionModel):
    site = UniformSite([1], ti=0.1)
    wt = V80()
    wfm = NOJ(site, wt, k=.5, superpositionModel=superpositionModel)

    fm_ref = wfm([0, 0 + 1e-20], [0, 0 + 1e-20], wd=0, h=[50, -50]).flow_map(
        YZGrid(x=0, y=np.arange(-100, 100, 1) + .1, z=np.arange(1, 100)))
    fm_ref.plot_wake_map()
    plt.title("Underground WT added manually")

    plt.figure()
    wfm = wfm_cls(site,
                  wt,
                  NOJDeficit(k=.5),
                  groundModel=groundModel,
                  superpositionModel=superpositionModel)
    fm_res = wfm([0], [0], wd=0, h=[50]).flow_map(
        YZGrid(x=0, y=np.arange(-100, 100, 1) + .1, z=np.arange(1, 100)))
    fm_res.plot_wake_map()
    plt.title("With Mirror GroundModel")

    if 0:
        plt.show()
    plt.close()
    npt.assert_array_equal(fm_ref.WS_eff, fm_res.WS_eff)
예제 #12
0
def test_from_flow_box_2wt():
    site = Hornsrev1Site()
    windTurbines = V80()

    # simulate current and neighbour wt
    wfm = BastankhahGaussian(site, windTurbines)
    wd = np.arange(30)
    sim_res = wfm([0, 0], [0, 500], wd=wd)
    ref_aep = sim_res.aep().sel(wt=0)

    wt_x, wt_y = [0], [0]
    neighbour_x, neighbour_y = [0], [500]

    # make site with effects of neighbour wt
    sim_res = wfm(neighbour_x, neighbour_y, wd=wd)
    e = 100
    box = sim_res.flow_box(x=np.linspace(min(wt_x) - e, max(wt_x) + e, 21),
                           y=np.linspace(min(wt_y) - e, max(wt_y) + e, 21),
                           h=windTurbines.hub_height(windTurbines.types()))
    site = XRSite.from_flow_box(box)

    # Simujlate current wt and compare aep
    wfm = BastankhahGaussian(site, windTurbines)
    sim_res = wfm(wt_x, wt_y, wd=wd)
    aep = sim_res.aep()

    if 0:
        site.ds.WS.sel(ws=10, wd=3).plot()
        windTurbines.plot(wt_x, wt_y)
        windTurbines.plot(neighbour_x, neighbour_y)
        plt.show()

    npt.assert_array_almost_equal(ref_aep, aep.sel(wt=0))
예제 #13
0
def test_GenericWindTurbine():
    for ref, ti, cut_in, cut_out, p_tol, ct_tol in [(V80(), .1, 4, None, 0.03, .14),
                                                    (WindTurbine.from_WAsP_wtg(wtg_path +
                                                                               "Vestas V112-3.0 MW.wtg"), .05, 3, 25, 0.035, .07),
                                                    (DTU10MW(), .05, 4, 25, 0.06, .12)]:

        power_norm = ref.power(np.arange(10, 20)).max()
        wt = GenericWindTurbine('Generic', ref.diameter(), ref.hub_height(), power_norm / 1e3,
                                turbulence_intensity=ti, ws_cutin=cut_in, ws_cutout=cut_out)

        if 0:
            u = np.arange(0, 30, .1)
            p, ct = wt.power_ct(u)
            plt.plot(u, p / 1e6, label='Generic')

            plt.plot(u, ref.power(u) / 1e6, label=ref.name())

            plt.ylabel('Power [MW]')
            plt.legend(loc='center left')
            ax = plt.twinx()
            ax.plot(u, ct, '--')
            ax.plot(u, ref.ct(u), '--')

            ax.set_ylim([0, 1])
            plt.ylabel('Ct')
            plt.show()

        u = np.arange(5, 25)
        p, ct = wt.power_ct(u)
        p_ref, ct_ref = ref.power_ct(u)
        # print(np.abs(p_ref - p).max() / power_norm)
        npt.assert_allclose(p, p_ref, atol=power_norm * p_tol)
        # print(np.abs(ct_ref - ct).max())
        npt.assert_allclose(ct, ct_ref, atol=ct_tol)
예제 #14
0
def test_get_defaults():
    v80 = V80()
    npt.assert_array_equal(np.array(v80.get_defaults(1))[:, 0], [0, 70, 80])
    npt.assert_array_equal(
        np.array(v80.get_defaults(1, h_i=100))[:, 0], [0, 100, 80])
    npt.assert_array_equal(
        np.array(v80.get_defaults(1, d_i=100))[:, 0], [0, 70, 100])
예제 #15
0
def test_GCL_ex80():
    site = Hornsrev1Site()

    x, y = site.initial_position.T
    windTurbines = V80()
    wfm = PropagateDownwind(site,
                            windTurbines,
                            wake_deficitModel=GCLDeficit(),
                            superpositionModel=LinearSum())
    if 0:
        windTurbines.plot(x, y)
        plt.show()

    sim_res = timeit(wfm.__call__,
                     line_profile=0,
                     profile_funcs=[get_dU],
                     verbose=0)(x, y, ws=np.arange(10, 15))[0]

    # test that the result is equal to previuos runs (no evidens that  these number are correct)
    aep_ref = 1055.956615887197
    npt.assert_almost_equal(
        sim_res.aep_ilk(normalize_probabilities=True).sum(), aep_ref, 5)

    sim_res = wfm(x, y, ws=np.arange(3, 10))
    npt.assert_array_almost_equal(
        sim_res.aep_ilk(normalize_probabilities=True).sum(), 261.6143039016946,
        5)
예제 #16
0
def test_i_time_dependent_WS():
    t = np.arange(4)
    WS_it = t[na] / 10 + np.array([9, 10])[:, na]
    ds = xr.Dataset(
        data_vars={'WS': (('i', 'time'), WS_it), 'P': ('wd', f), 'TI': 0.1},
        coords={'wd': np.linspace(0, 360, len(f), endpoint=False)})
    site = XRSite(ds)
    wfm = NOJ(site, V80())
    sim_res = wfm([0, 200], [0, 0], ws=WS_it.mean(0), wd=np.zeros(4), time=t)
    npt.assert_array_equal(sim_res.WS, WS_it)
예제 #17
0
def test_time_series_aep():

    d = np.load(os.path.dirname(examples.__file__) + "/data/time_series.npz")
    wd, ws = [d[k][::100] for k in ['wd', 'ws']]
    wt = V80()
    site = Hornsrev1Site()
    x, y = site.initial_position.T
    wfm = NOJ(site, wt)
    sim_res = wfm(x, y, ws=ws, wd=wd, time=True, verbose=False)
    npt.assert_allclose(sim_res.aep().sum(), 545, atol=1)
예제 #18
0
def test_yaw():
    v80 = V80()
    yaw = np.deg2rad(np.arange(-30, 31))
    ws = np.zeros_like(yaw) + 8
    P0 = v80.power(ws[0])
    if 0:
        plt.plot(yaw, v80.power(ws, 0, yaw) / P0)
        plt.plot(yaw, np.cos(yaw)**3)
        plt.grid()
        plt.show()
    npt.assert_array_almost_equal(v80.power(ws, 0, yaw) / P0, np.cos(yaw)**3, 2)
예제 #19
0
def test_time_series_override_WD():
    d = np.load(os.path.dirname(examples.__file__) + "/data/time_series.npz")
    wd, ws = [d[k][:6 * 24] for k in ['wd', 'ws']]
    t = pd.date_range("2000-01-01", freq="10T", periods=24 * 6)
    WD_it = (np.arange(80) / 100)[:, na] + wd[na]
    wt = V80()
    site = Hornsrev1Site()
    x, y = site.initial_position.T
    wfm = NOJ(site, wt)
    sim_res = wfm(x, y, ws=ws, wd=wd, time=t, WD=WD_it, verbose=False)
    npt.assert_array_equal(sim_res.WS, ws)
    npt.assert_array_equal(sim_res.WD, WD_it)
    npt.assert_array_equal(sim_res.time, t)
예제 #20
0
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()
예제 #21
0
def test_time_series_values():
    wt = V80()
    site = Hornsrev1Site()
    x, y = site.initial_position.T
    wfm = NOJ(site, wt)
    wd = np.arange(350, 360)
    ws = np.arange(5, 10)
    wd_t, ws_t = [v.flatten() for v in np.meshgrid(wd, ws)]
    sim_res_t = wfm(x, y, ws=ws_t, wd=wd_t, time=True, verbose=False)
    sim_res = wfm(x, y, wd=wd, ws=ws)

    for k in ['WS_eff', 'TI_eff', 'Power', 'CT']:
        npt.assert_array_equal(
            np.moveaxis(sim_res_t[k].values.reshape((80, 5, 10)), 1, 2),
            sim_res[k].values)
예제 #22
0
def test_time_series_override_TI():

    d = np.load(os.path.dirname(examples.__file__) + "/data/time_series.npz")
    wd, ws, ws_std = [d[k][:6 * 24] for k in ['wd', 'ws', 'ws_std']]
    ti = np.minimum(ws_std / ws, .5)
    t = pd.date_range("2000-01-01", freq="10T", periods=24 * 6)
    wt = V80()
    site = Hornsrev1Site()
    x, y = site.initial_position.T
    wfm = NOJ(site, wt)
    sim_res = wfm(x, y, ws=ws, wd=wd, time=t, TI=ti, verbose=False)
    npt.assert_array_equal(sim_res.WS, ws)
    npt.assert_array_equal(sim_res.WD, wd)
    npt.assert_array_equal(sim_res.time, t)
    npt.assert_array_equal(sim_res.TI[0], ti)
예제 #23
0
def test_yaw():
    v80 = V80()
    yaw = np.arange(-30, 31)
    ws = np.zeros_like(yaw) + 8
    P0 = v80.power(ws[0])
    if 0:
        plt.plot(yaw, v80.power(ws, yaw=yaw) / P0)
        plt.plot(yaw, np.cos(np.deg2rad(yaw))**3)
        plt.grid()
        plt.figure()
        plt.plot(yaw, v80.ct(ws, yaw=yaw))
        plt.plot(yaw, v80.ct(ws) * np.cos(np.deg2rad(yaw))**2)
        plt.grid()
        plt.show()
    # Power in cube region
    npt.assert_array_almost_equal(v80.power(ws, yaw=yaw) / P0, np.cos(np.deg2rad(yaw))**3, 2)
    # ct in constant region
    npt.assert_array_almost_equal(v80.ct(ws, yaw=yaw), v80.ct(ws) * np.cos(np.deg2rad(yaw))**2, 3)
예제 #24
0
def test_turning_mean(complex_grid_site, wfm):

    ds = xr.Dataset(
        data_vars={'Turning': (['x', 'y'], np.arange(-2, 4, 1).reshape((2, 3)).T),
                   'Sector_frequency': ('wd', f), 'Weibull_A': ('wd', A), 'Weibull_k': ('wd', k), 'TI': .1},
        coords={'x': [0, 500, 1000], 'y': [0, 500], 'wd': np.linspace(0, 360, len(f), endpoint=False)})
    site = XRSite(ds)

    wt = V80()
    wfm = wfm(site, wt, NOJDeficit())
    sim_res = wfm([500, 500], [100, 400], wd=0, ws=10)
    print(sim_res.Power)
    if 0:
        sim_res.flow_map(XYGrid(y=np.linspace(0, 500, 100))).plot_wake_map()
        plt.show()
    assert sim_res.WS_eff.sel(wt=0).item() < sim_res.WS_eff.sel(wt=1).item()
    fm = sim_res.flow_map(Points([500, 500], [100, 400], [70, 70]))
    assert fm.WS_eff.sel(i=0).item() < fm.WS_eff.sel(i=1).item()
예제 #25
0
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)
예제 #26
0
def test_deflection_model(deflectionModel, dy10d):
    site = IEA37Site(16)
    x, y = [0], [0]
    windTurbines = V80()
    D = windTurbines.diameter()
    wfm = IEA37SimpleBastankhahGaussian(site, windTurbines, deflectionModel=deflectionModel())

    yaw_ilk = np.reshape([-30], (1, 1, 1))

    sim_res = wfm(x, y, yaw=yaw_ilk, wd=270, ws=10)
    fm = sim_res.flow_map(XYGrid(x=np.arange(-D, 10 * D + 10, 10)))
    min_WS_line = fm.min_WS_eff()
    if 0:
        plt.figure(figsize=(14, 3))
        fm.plot_wake_map()
        min_WS_line.plot()
        plt.plot(10 * D, dy10d * D, '.', label="Ref, 10D")
        plt.legend()
        plt.show()

    npt.assert_almost_equal(min_WS_line.interp(x=10 * D).item() / D, dy10d)
예제 #27
0
def test_plot_deflection_grid(deflectionModel):
    site = IEA37Site(16)
    x, y = [0], [0]
    windTurbines = V80()
    D = windTurbines.diameter()
    wfm = IEA37SimpleBastankhahGaussian(site, windTurbines, deflectionModel=deflectionModel())

    yaw_ilk = np.reshape([-30], (1, 1, 1))

    sim_res = wfm(x, y, yaw=yaw_ilk, wd=270, ws=10)
    fm = sim_res.flow_map(XYGrid(x=np.arange(-D, 10 * D + 10, 10)))

    plt.figure(figsize=(14, 3))
    fm.plot_wake_map()
    fm.plot_deflection_grid()
    min_WS_line = fm.min_WS_eff()
    min_WS_line.plot()
    plt.legend()
    plt.title(wfm.deflectionModel)
    if 0:
        plt.show()
    plt.close('all')
예제 #28
0
import matplotlib.pyplot as plt
import numpy as np
from autograd import numpy as anp
from py_wake.examples.data.iea37 import iea37_reader
from py_wake.examples.data.iea37._iea37 import IEA37_WindTurbines
from py_wake.utils.gradients import use_autograd_in, autograd, plot_gradients, fd, cs
from py_wake.tests import npt
from py_wake.wind_turbines import WindTurbines
from py_wake import wind_turbines
from py_wake.examples.data.hornsrev1 import V80
import pytest


@pytest.mark.parametrize('obj', [wind_turbines, WindTurbines, V80().power, wind_turbines.__dict__])
def test_use_autograd_in(obj):
    assert wind_turbines.np == np
    with use_autograd_in([obj]):
        assert wind_turbines.np == anp
    assert wind_turbines.np == np


def test_gradients():
    wt = IEA37_WindTurbines()
    with use_autograd_in([WindTurbines, iea37_reader]):
        ws_lst = np.arange(3, 25, .1)

        ws_pts = np.array([3., 6., 9., 12.])
        dpdu_lst = np.diag(autograd(wt.power)(ws_pts))
        if 0:
            plt.plot(ws_lst, wt.power(ws_lst))
            for dpdu, ws in zip(dpdu_lst, ws_pts):
예제 #29
0
def main():
    if __name__ == '__main__':
        try:
            import matplotlib.pyplot as plt
            plt.gcf()
            plot_comp = XYPlotComp
            plot = True
        except RuntimeError:
            plot_comp = NoPlot
            plot = False
        # ------------------------ INPUTS ------------------------

        # ------------------------ DEFINE WIND RESOURCE ------------------------
        # wind resource info (wdir frequency, weibull a and k)
        f = [
            3.597152, 3.948682, 5.167395, 7.000154, 8.364547, 6.43485,
            8.643194, 11.77051, 15.15757, 14.73792, 10.01205, 5.165975
        ]
        a = [
            9.176929, 9.782334, 9.531809, 9.909545, 10.04269, 9.593921,
            9.584007, 10.51499, 11.39895, 11.68746, 11.63732, 10.08803
        ]
        k = [
            2.392578, 2.447266, 2.412109, 2.591797, 2.755859, 2.595703,
            2.583984, 2.548828, 2.470703, 2.607422, 2.626953, 2.326172
        ]
        site = UniformWeibullSite(p_wd=f, a=a, k=k, ti=0.075)
        wt = V80()

        # ------------------------ setup problem ____---------------------------
        rot_diam = 80.0  # rotor diameter [m]
        init_pos = np.array([(0, 2 * rot_diam), (0, 0),
                             (0, -2 * rot_diam)])  # initial turbine positions
        b = 2 * rot_diam + 10  # boundary size
        boundary = [(-b, -b), (-b, b), (b, b),
                    (b, -b)]  # corners of wind farm boundary
        min_spacing = 2.0 * rot_diam  # minimum spacing between turbines [m]

        # ------------------------ OPTIMIZATION ------------------------

        def get_tf(windFarmModel):
            return TopFarmProblem(design_vars=dict(zip('xy', init_pos.T)),
                                  cost_comp=PyWakeAEPCostModelComponent(
                                      windFarmModel,
                                      n_wt=3,
                                      ws=10,
                                      wd=np.arange(0, 360, 12)),
                                  constraints=[
                                      SpacingConstraint(min_spacing),
                                      XYBoundaryConstraint(boundary)
                                  ],
                                  driver=EasyScipyOptimizeDriver(),
                                  plot_comp=plot_comp())

        # GCL: define the wake model and optimization problem
        tf_gcl = get_tf(GCL(site, wt))

        # NOJ: define the wake model and optimization problem
        tf_noj = get_tf(NOJ(site, wt))

        # run the optimization
        cost_gcl, state_gcl, recorder_gcl = tf_gcl.optimize()
        cost_noj, state_noj, recorder_noj = tf_noj.optimize()

        # ------------------------ POST-PROCESS ------------------------

        # get the optimized locations
        opt_gcl = tf_gcl.turbine_positions
        opt_noj = tf_noj.turbine_positions

        # create the array of costs for easier printing
        costs = np.diag([cost_gcl, cost_noj])
        costs[0, 1] = tf_noj.evaluate(state_gcl)[0]  # noj cost of gcl locs
        costs[1, 0] = tf_gcl.evaluate(state_noj)[0]  # gcl cost of noj locs

        # ------------------------ PRINT STATS ------------------------

        aep_diffs = 200 * (costs[:, 0] - costs[:, 1]) / (costs[:, 0] +
                                                         costs[:, 1])
        loc_diffs = 200 * (costs[0, :] - costs[1, :]) / (costs[0, :] +
                                                         costs[1, :])

        print('\nComparison of cost models vs. optimized locations:')
        print('\nCost    |    GCL_aep      NOJ_aep')
        print('---------------------------------')
        print(f'GCL_loc |{costs[0,0]:11.2f} {costs[0,1]:11.2f}' +
              f'   ({aep_diffs[0]:.2f}%)')
        print(f'NOJ_loc |{costs[1,0]:11.2f} {costs[1,1]:11.2f}' +
              f'   ({aep_diffs[1]:.2f}%)')
        print(f'             ({loc_diffs[0]:.2f}%)     ({loc_diffs[1]:.2f}%)')

        # ------------------------ PLOT (if possible) ------------------------
        if plot:

            # initialize the figure and axes
            fig = plt.figure(1, figsize=(7, 5))
            plt.clf()
            ax = plt.axes()

            # plot the boundary and desired locations
            ax.add_patch(Polygon(boundary, fill=False,
                                 label='Boundary'))  # boundary
            ax.plot(init_pos[:, 0], init_pos[:, 1], 'xk', label='Initial')
            ax.plot(opt_gcl[:, 0], opt_gcl[:, 1], 'o', label='GCL')
            ax.plot(opt_noj[:, 0], opt_noj[:, 1], '^', label='NOJ')

            # make a few adjustments to the plot
            ax.autoscale_view()  # autoscale the boundary
            plt.legend(bbox_to_anchor=(0., 1.02, 1., .102),
                       loc=3,
                       ncol=4,
                       mode='expand',
                       borderaxespad=0.)  # add a legend
            plt.tight_layout()  # zoom the plot in
            plt.axis('off')  # remove the axis

            # save the png
            folder, file = os.path.split(__file__)
            fig.savefig(folder + "/figures/" + file.replace('.py', '.png'))
예제 #30
0
@pytest.mark.parametrize(
    'case,wt,dpdu_ref,dctdu_ref',
    [('CubePowerSimpleCt',
      WindTurbine('Test', 130, 110,
                  CubePowerSimpleCt(4, 25, 9.8, 3.35e6, 'W', 8 / 9, 0, [])),
      lambda ws_pts: np.where((ws_pts > 4) & (ws_pts <= 9.8), 3 * 3350000 *
                              (ws_pts - 4)**2 / (9.8 - 4)**3, 0), lambda
      ws_pts: [0, 0, 0, 2 * 12 * 0.0038473376423514938 + -0.1923668821175747]),
     ('CubePowerSimpleCt_MW',
      WindTurbine('Test', 130, 110,
                  CubePowerSimpleCt(4, 25, 9.8, 3.35, 'MW', 8 / 9, 0, [])),
      lambda ws_pts: np.where((ws_pts > 4) & (ws_pts <= 9.8), 3 * 3350000 *
                              (ws_pts - 4)**2 / (9.8 - 4)**3, 0), lambda
      ws_pts: [0, 0, 0, 2 * 12 * 0.0038473376423514938 + -0.1923668821175747]),
     ('PowerCtTabular_linear', V80(), [
         66600.00000931, 178000.00001444, 344999.99973923, 91999.99994598
     ], [0.818, 0.001, -0.014, -0.3]),
     ('PowerCtTabular_pchip', V80(method='pchip'), [
         58518.7948, 148915.03267974, 320930.23255814, 127003.36700337
     ], [1.21851, 0., 0., -0.05454545]),
     ('PowerCtTabular_spline', V80(method='spline'), [
         69723.7929, 158087.18190692, 324012.9604669, 156598.55856862
     ], [8.176490e-01, -3.31076624e-05, -7.19353708e-03, -1.66006862e-01]),
     ('PowerCtTabular_kW',
      get_wt(PowerCtTabular(
          v80_upct[0], v80_upct[1] / 1000, 'kW', v80_upct[2])), [
              66600.00000931, 178000.00001444, 344999.99973923, 91999.99994598
          ], [0.818, 0.001, -0.014, -0.3]),
     ('PowerCtFunctionList',
      get_wt(