コード例 #1
0
 def __init__(self, site, windTurbines, k=.1, superpositionModel=SquaredSum(),
              deflectionModel=None, turbulenceModel=None):
     """
     Parameters
     ----------
     site : Site
         Site object
     windTurbines : WindTurbines
         WindTurbines object representing the wake generating wind turbines
     k : float, default 0.1
         wake expansion factor
     superpositionModel : SuperpositionModel, default SquaredSum
         Model defining how deficits sum up
     blockage_deficitModel : DeficitModel, default None
         Model describing the blockage(upstream) deficit
     deflectionModel : DeflectionModel, default None
         Model describing the deflection of the wake due to yaw misalignment, sheared inflow, etc.
     turbulenceModel : TurbulenceModel, default None
         Model describing the amount of added turbulence in the wake
     """
     PropagateDownwind.__init__(self, site, windTurbines,
                                wake_deficitModel=NOJDeficit(k),
                                superpositionModel=superpositionModel,
                                deflectionModel=deflectionModel,
                                turbulenceModel=turbulenceModel)
コード例 #2
0
ファイル: gaussian.py プロジェクト: knutss/PyWake
 def __init__(self,
              site,
              windTurbines,
              a=[0.38, 4e-3],
              superpositionModel=SquaredSum(),
              deflectionModel=None,
              turbulenceModel=None,
              groundModel=None):
     """
     Parameters
     ----------
     site : Site
         Site object
     windTurbines : WindTurbines
         WindTurbines object representing the wake generating wind turbines
     superpositionModel : SuperpositionModel, default SquaredSum
         Model defining how deficits sum up
     deflectionModel : DeflectionModel, default None
         Model describing the deflection of the wake due to yaw misalignment, sheared inflow, etc.
     turbulenceModel : TurbulenceModel, default None
         Model describing the amount of added turbulence in the wake
     """
     PropagateDownwind.__init__(self,
                                site,
                                windTurbines,
                                wake_deficitModel=ZongGaussianDeficit(a=a),
                                superpositionModel=superpositionModel,
                                deflectionModel=deflectionModel,
                                turbulenceModel=turbulenceModel,
                                groundModel=groundModel)
コード例 #3
0
 def __init__(self,
              LUT_path,
              site,
              windTurbines,
              rotorAvgModel=RotorCenter(),
              deflectionModel=None,
              turbulenceModel=None):
     """
     Parameters
     ----------
     LUT_path : str
         path to look up tables
     site : Site
         Site object
     windTurbines : WindTurbines
         WindTurbines object representing the wake generating wind turbines
     rotorAvgModel : RotorAvgModel
         Model defining one or more points at the down stream rotors to
         calculate the rotor average wind speeds from.\n
         Defaults to RotorCenter that uses the rotor center wind speed (i.e. one point) only
     deflectionModel : DeflectionModel
         Model describing the deflection of the wake due to yaw misalignment, sheared inflow, etc.
     turbulenceModel : TurbulenceModel
         Model describing the amount of added turbulence in the wake
     """
     PropagateDownwind.__init__(self,
                                site,
                                windTurbines,
                                wake_deficitModel=FugaDeficit(LUT_path),
                                rotorAvgModel=rotorAvgModel,
                                superpositionModel=LinearSum(),
                                deflectionModel=deflectionModel,
                                turbulenceModel=turbulenceModel)
コード例 #4
0
ファイル: gaussian.py プロジェクト: blondelf/PyWake-1
 def __init__(self,
              site,
              windTurbines,
              rotorAvgModel=RotorCenter(),
              superpositionModel=SquaredSum(),
              deflectionModel=None,
              turbulenceModel=None):
     """
     Parameters
     ----------
     site : Site
         Site object
     windTurbines : WindTurbines
         WindTurbines object representing the wake generating wind turbines
     rotorAvgModel : RotorAvgModel
         Model defining one or more points at the down stream rotors to
         calculate the rotor average wind speeds from.\n
         Defaults to RotorCenter that uses the rotor center wind speed (i.e. one point) only
     superpositionModel : SuperpositionModel, default SquaredSum
         Model defining how deficits sum up
     deflectionModel : DeflectionModel, default None
         Model describing the deflection of the wake due to yaw misalignment, sheared inflow, etc.
     turbulenceModel : TurbulenceModel, default None
         Model describing the amount of added turbulence in the wake
     """
     PropagateDownwind.__init__(
         self,
         site,
         windTurbines,
         wake_deficitModel=IEA37SimpleBastankhahGaussianDeficit(),
         rotorAvgModel=rotorAvgModel,
         superpositionModel=superpositionModel,
         deflectionModel=deflectionModel,
         turbulenceModel=turbulenceModel)
コード例 #5
0
ファイル: gcl.py プロジェクト: blondelf/PyWake-1
    def __init__(self, site, windTurbines, rotorAvgModel=RotorCenter(), superpositionModel=LinearSum(),
                 deflectionModel=None, turbulenceModel=None):

        PropagateDownwind.__init__(self, site, windTurbines,
                                   wake_deficitModel=GCLDeficit(use_effective_ws=True, use_effective_ti=True),
                                   rotorAvgModel=rotorAvgModel, superpositionModel=superpositionModel,
                                   deflectionModel=deflectionModel, turbulenceModel=turbulenceModel)
コード例 #6
0
def test_double_wind_farm_model():
    """Check that a new wind farm model does not change results of previous"""
    site = IEA37Site(16)
    x, y = site.initial_position.T
    windTurbines = IEA37_WindTurbines()
    wfm = PropagateDownwind(site, windTurbines, wake_deficitModel=IEA37SimpleBastankhahGaussianDeficit())
    aep_ref = wfm(x, y).aep().sum()
    PropagateDownwind(site, windTurbines, wake_deficitModel=NoWakeDeficit())
    aep = wfm(x, y).aep().sum()
    npt.assert_array_equal(aep, aep_ref)
コード例 #7
0
def test_wake_radius(deficitModel, wake_radius_ref):

    mean_ref = [105, 68, 135, 93, 123]
    # check that ref is reasonable
    npt.assert_allclose(wake_radius_ref, mean_ref, rtol=.5)

    npt.assert_array_almost_equal(deficitModel.wake_radius(
        D_src_il=np.reshape([100, 50, 100, 100, 100], (5, 1)),
        dw_ijlk=np.reshape([500, 500, 1000, 500, 500], (5, 1, 1, 1)),
        ct_ilk=np.reshape([.8, .8, .8, .4, .8], (5, 1, 1)),
        TI_ilk=np.reshape([.1, .1, .1, .1, .05], (5, 1, 1)),
        TI_eff_ilk=np.reshape([.1, .1, .1, .1, .05], (5, 1, 1)))[:, 0, 0, 0],
        wake_radius_ref)

    # Check that it works when called from WindFarmModel
    site = IEA37Site(16)
    windTurbines = IEA37_WindTurbines()
    wfm = PropagateDownwind(site, windTurbines, wake_deficitModel=deficitModel, turbulenceModel=GCLTurbulence())
    wfm(x=[0, 500], y=[0, 0], wd=[30], ws=[10])

    if 0:
        sim_res = wfm([0], [0], wd=[270], ws=10)
        sim_res.flow_map(HorizontalGrid(x=np.arange(-100, 1500, 10))).WS_eff.plot()
        x = np.arange(0, 1500, 10)
        wr = deficitModel.wake_radius(
            D_src_il=np.reshape([130], (1, 1)),
            dw_ijlk=np.reshape(x, (1, len(x), 1, 1)),
            ct_ilk=sim_res.CT.values,
            TI_ilk=np.reshape(sim_res.TI.values, (1, 1, 1)),
            TI_eff_ilk=sim_res.TI_eff.values)[0, :, 0, 0]
        plt.title(deficitModel.__class__.__name__)
        plt.plot(x, wr)
        plt.plot(x, -wr)
        plt.axis('equal')
        plt.show()
コード例 #8
0
def test_fuga_deflection_time_series_gradient_evaluation():

    p = Path(tfp) / "fuga/v80_wake_center_x.csv"
    x, notebook_wake_center = np.array([v.split(",") for v in p.read_text().strip().split("\n")], dtype=float).T

    powerCtFunction = PowerCtTabular([0, 100], [0, 0], 'w', [0.850877, 0.850877])
    wt = WindTurbine(name='', diameter=80, hub_height=70, powerCtFunction=powerCtFunction)

    path = tfp + 'fuga/2MW/Z0=0.00001000Zi=00400Zeta0=0.00E+00'
    site = UniformSite([1, 0, 0, 0], ti=0.075)

    wfm = PropagateDownwind(
        site,
        wt,
        wake_deficitModel=FugaYawDeficit(path),
        deflectionModel=FugaDeflection(path, 'input_par')
    )

    WS = 10

    yaw_ref = np.full((10, 1), 17)
    yaw_step = np.eye(10, 10) * 1e-6 + yaw_ref
    yaw = np.concatenate([yaw_step, yaw_ref], axis=1)
    sim_res = wfm(np.arange(10) * wt.diameter() * 4, [0] * 10, yaw=yaw, wd=[270] * 11, ws=[WS] * 11, time=True)
    print(sim_res)
コード例 #9
0
def test_fuga_wake_center_vs_notebook():

    p = Path(tfp) / "fuga/v80_wake_center_x.csv"
    x, notebook_wake_center = np.array([v.split(",") for v in p.read_text().strip().split("\n")], dtype=float).T

    powerCtFunction = PowerCtTabular([0, 100], [0, 0], 'w', [0.850877, 0.850877])
    wt = WindTurbine(name='', diameter=80, hub_height=70, powerCtFunction=powerCtFunction)

    path = tfp + 'fuga/2MW/Z0=0.00001000Zi=00400Zeta0=0.00E+00'
    site = UniformSite([1, 0, 0, 0], ti=0.075)

    wfm = PropagateDownwind(
        site,
        wt,
        wake_deficitModel=FugaYawDeficit(path),
        deflectionModel=FugaDeflection(path, 'input_par')
    )

    WS = 10
    sim_res = wfm([0], [0], yaw=[17.4493], wd=270, ws=[WS])
    y = wfm.wake_deficitModel.mirror(wfm.wake_deficitModel.y, anti_symmetric=True)
    fm = sim_res.flow_map(XYGrid(x=x[1:], y=y[240:271]))
    fuga_wake_center = [np.interp(0, InterpolatedUnivariateSpline(ws.y, ws.values).derivative()(ws.y), ws.y)
                        for ws in fm.WS_eff.squeeze().T]

    if 0:
        plt.plot(x, notebook_wake_center, label='Notebook deflection')
        plt.plot(x[1:], fuga_wake_center)
        plt.show()
    plt.close('all')
    npt.assert_allclose(fuga_wake_center, notebook_wake_center[1:], atol=.14)
コード例 #10
0
def test_interpolation():
    wts = HornsrevV80()

    path = tfp + 'fuga/2MW/Z0=0.00408599Zi=00400Zeta0=0.00E+00/'
    site = UniformSite([1, 0, 0, 0], ti=0.075)

    plot = 0
    if plot:
        ax1 = plt.gca()
        ax2 = plt.twinx()

    for wdm, n_d_values in (
        (FugaDeficit(path, method='linear'), 4),
        (FugaDeficit(path, method='spline'), 20),
        (FugaYawDeficit(path, method='linear'), 4),
        (FugaYawDeficit(path, method='spline'), 20),
    ):
        wfm = PropagateDownwind(site, wts, wdm)

        sim_res = wfm(x=[0], y=[0], wd=[270], ws=[10], yaw=[[[10]]])
        fm = sim_res.flow_map(XYGrid(x=[200], y=np.arange(-10, 11)))
        fm = sim_res.flow_map(
            XYGrid(x=np.arange(-100, 800, 10), y=np.arange(-10, 11)))

        # linear has 4 line segments with same gradient, while spline has 20 different gradient values
        npt.assert_equal(
            len(np.unique(np.round(np.diff(fm.WS_eff.sel(x=500).squeeze()),
                                   6))), n_d_values)
        if plot:
            ax1.plot(fm.y, fm.WS_eff.sel(x=500).squeeze())
            ax2.plot(fm.y[:-1], np.diff(fm.WS_eff.sel(x=500).squeeze()), '--')

    if plot:
        plt.show()
        plt.close('all')
コード例 #11
0
def test_fuga_wriggles():
    wts = HornsrevV80()
    path = tfp + 'fuga/2MW/Z0=0.03000000Zi=00401Zeta0=0.00E+00/'
    site = hornsrev1.Hornsrev1Site()
    fuga = PropagateDownwind(site, wts, FugaDeficit(path,
                                                    remove_wriggles=True))

    D = 80
    flow_map_cw = fuga([0], [0], wd=270, ws=10).flow_map(
        HorizontalGrid([0], np.arange(-20 * D, 20 * D)))

    y = np.linspace(-5 * D, 5 * D, 100)

    dw_lst = range(10)
    flow_map_cw_lst = np.array([
        fuga([0], [0], wd=270,
             ws=10).flow_map(HorizontalGrid([dw * D], y)).WS_eff.squeeze()
        for dw in dw_lst
    ])

    if 0:
        for flow_map_cw, dw in zip(flow_map_cw_lst, dw_lst):
            plt.plot(y, flow_map_cw, label="%dD" % dw)
        plt.xlabel('y [m]')
        plt.ylabel('ws [m/s')
        plt.ylim([9.9, 10.1])
        plt.grid()
        plt.legend(loc=1)
        plt.show()
    assert np.all(flow_map_cw_lst > 0)
コード例 #12
0
def test_deficitModel_wake_map_convection(deficitModel, ref):
    site = IEA37Site(16)
    x, y = site.initial_position.T
    windTurbines = IEA37_WindTurbines()

    wf_model = PropagateDownwind(site, windTurbines, wake_deficitModel=deficitModel, superpositionModel=WeightedSum(),
                                 turbulenceModel=GCLTurbulence())

    x_j = np.linspace(-1500, 1500, 200)
    y_j = np.linspace(-1500, 1500, 100)

    flow_map = wf_model(x, y, wd=0, ws=9).flow_map(HorizontalGrid(x_j, y_j))
    X, Y = flow_map.X, flow_map.Y
    Z = flow_map.WS_eff_xylk[:, :, 0, 0]

    mean_ref = [3.2, 4.9, 8., 8.2, 7.9, 7.4, 7., 7., 7.4, 7.9, 8.1, 8.1, 8., 7.8, 7.9, 8.1, 8.4]

    if 0:
        flow_map.plot_wake_map()
        plt.plot(X[49, 100:133:2], Y[49, 100:133:2], '.-')
        windTurbines.plot(x, y)
        plt.figure()
        plt.plot(Z[49, 100:133:2], label='Actual')
        plt.plot(ref, label='Reference')
        plt.plot(mean_ref, label='Mean ref')
        plt.legend()
        plt.show()

    # check that ref is reasonable
    npt.assert_allclose(ref[2:], mean_ref[2:], atol=2.6)

    npt.assert_array_almost_equal(Z[49, 100:133:2], ref, 2)
コード例 #13
0
def test_fuga_downwind():
    wts = HornsrevV80()

    path = tfp + 'fuga/2MW/Z0=0.00408599Zi=00400Zeta0=0.00E+00'
    site = UniformSite([1, 0, 0, 0], ti=0.075)
    wfm_UL = Fuga(path, site, wts)

    wfm_ULT = PropagateDownwind(site, wts, FugaYawDeficit(path))

    (ax1, ax2), (ax3, ax4) = plt.subplots(2, 2)[1]

    def plot(wfm, yaw, ax, min_ws):
        levels = np.arange(6.5, 10.5, .5)
        sim_res = wfm([0], [0], wd=270, ws=10, yaw=[[[yaw]]])
        fm = sim_res.flow_map(XYGrid(x=np.arange(-100, 500, 5)))
        npt.assert_almost_equal(fm.WS_eff.min(), min_ws)
        fm.plot_wake_map(ax=ax, levels=levels)
        fm.min_WS_eff(fm.x, 70).plot(ax=ax, color='r')
        plt.axhline(0, color='k')

    plot(wfm_UL, 0, ax1, 7.15853738)
    plot(wfm_UL, 30, ax2, 7.83219266)
    plot(wfm_ULT, 0, ax3, 7.15853738)
    plot(wfm_ULT, 30, ax4, 8.12261872)

    if 0:
        plt.show()
    plt.close('all')
コード例 #14
0
def test_fuga_downwind_vs_notebook():

    powerCtFunction = PowerCtTabular([0, 100], [0, 0], 'w',
                                     [0.850877, 0.850877])
    wt = WindTurbine(name='',
                     diameter=80,
                     hub_height=70,
                     powerCtFunction=powerCtFunction)

    path = tfp + 'fuga/2MW/Z0=0.00001000Zi=00400Zeta0=0.00E+00'
    site = UniformSite([1, 0, 0, 0], ti=0.075)
    wfm_ULT = PropagateDownwind(site, wt, FugaYawDeficit(path))
    WS = 10
    p = Path(tfp) / "fuga/v80_wake_4d_y_no_deflection.csv"
    y, notebook_deficit_4d = np.array(
        [v.split(",") for v in p.read_text().strip().split("\n")],
        dtype=float).T
    sim_res = wfm_ULT([0], [0], wd=270, ws=WS, yaw=[[[17.4493]]])
    fm = sim_res.flow_map(XYGrid(4 * wt.diameter(), y=y))
    npt.assert_allclose(fm.WS_eff.squeeze() - WS,
                        notebook_deficit_4d,
                        atol=1e-6)

    if 0:
        plt.plot(y, notebook_deficit_4d, label='Notebook deficit 4d')
        plt.plot(y, fm.WS_eff.squeeze() - WS)
        plt.show()
    plt.close('all')
コード例 #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_IEA37_ex16(deficitModel, aep_ref):
    site = IEA37Site(16)
    x, y = site.initial_position.T
    windTurbines = IEA37_WindTurbines()
    wf_model = PropagateDownwind(site,
                                 windTurbines,
                                 wake_deficitModel=deficitModel,
                                 superpositionModel=SquaredSum(),
                                 turbulenceModel=GCLTurbulence())

    aep_ilk = wf_model(x, y, wd=np.arange(0, 360, 22.5),
                       ws=[9.8]).aep_ilk(normalize_probabilities=True)
    aep_MW_l = aep_ilk.sum((0, 2)) * 1000

    # check if ref is reasonable
    aep_est = 16 * 3.35 * 24 * 365 * .8  # n_wt * P_rated * hours_pr_year - 20% wake loss = 375628.8
    npt.assert_allclose(aep_ref[0], aep_est, rtol=.11)
    npt.assert_allclose(aep_ref[1], [
        9500, 8700, 11500, 14300, 21300, 25900, 39600, 44300, 23900, 13900,
        15200, 33000, 72100, 18300, 12500, 8000
    ],
                        rtol=.15)

    npt.assert_almost_equal(aep_MW_l.sum(), aep_ref[0], 5)
    npt.assert_array_almost_equal(aep_MW_l, aep_ref[1], 5)
コード例 #17
0
def test_wake_radius_not_implemented():
    site = IEA37Site(16)
    x, y = site.initial_position.T
    windTurbines = IEA37_WindTurbines()
    wfm = PropagateDownwind(site, windTurbines, wake_deficitModel=NoWakeDeficit(),
                            turbulenceModel=GCLTurbulence())
    with pytest.raises(NotImplementedError, match="wake_radius not implemented for NoWakeDeficit"):
        wfm(x, y)
コード例 #18
0
ファイル: fuga.py プロジェクト: xtoworks/PyWake
 def __init__(self, LUT_path, site, windTurbines, deflectionModel=None, turbulenceModel=None):
     """
     Parameters
     ----------
     LUT_path : str
         path to look up tables
     site : Site
         Site object
     windTurbines : WindTurbines
         WindTurbines object representing the wake generating wind turbines
     deflectionModel : DeflectionModel
         Model describing the deflection of the wake due to yaw misalignment, sheared inflow, etc.
     turbulenceModel : TurbulenceModel
         Model describing the amount of added turbulence in the wake
     """
     PropagateDownwind.__init__(self, site, windTurbines,
                                wake_deficitModel=FugaDeficit(LUT_path), superpositionModel=LinearSum(),
                                deflectionModel=deflectionModel, turbulenceModel=turbulenceModel)
コード例 #19
0
def test_huge_flow_map(wake_deficitModel, deflectionModel, superpositionModel):
    site = IEA37Site(16)
    windTurbines = IEA37_WindTurbines()
    wake_model = PropagateDownwind(site, windTurbines, wake_deficitModel=wake_deficitModel,
                                   superpositionModel=superpositionModel, deflectionModel=deflectionModel,
                                   turbulenceModel=STF2005TurbulenceModel())
    n_wt = 2
    flow_map = wake_model(*site.initial_position[:n_wt].T, wd=0).flow_map(HorizontalGrid(resolution=1000))
    # check that deficit matrix > 10MB (i.e. it enters the memory saving loop)
    assert (np.prod(flow_map.WS_eff_xylk.shape) * n_wt * 8 / 1024**2) > 10
    assert flow_map.WS_eff_xylk.shape == (1000, 1000, 1, 1)