Skip to content
Snippets Groups Projects
stf.py 3.21 KiB
Newer Older
from py_wake.turbulence_model import TurbulenceModel, MaxSum
import numpy as np
from numpy import newaxis as na
from py_wake.wake_models.noj import NOJ


class STFTurbulenceModel(MaxSum, TurbulenceModel):
    args4addturb = ['dw_jl', 'cw_jl', 'D_src_l', 'ct_lk', 'TI_lk']

    def calc_added_turbulence(self, dw_jl, cw_jl, D_src_l, ct_lk, TI_lk):
        """ Calculate the added turbulence intensity at locations specified by
        downstream distances (dw_jl) and crosswind distances (cw_jl)
        caused by the wake of a turbine (diameter: D_src_l, thrust coefficient: Ct_lk).

        Returns
        -------
        TI_eff_jlk: array:float
            Effective turbulence intensity [-]
        """
        s_jl = dw_jl / D_src_l
        # In the standard (see page 78), the maximal added TI is calculated as
        # TI_add = 0.9/(1.5 + 0.3*d*sqrt(V_hub/c))
        # where d is the downwind distance normalised by rotor diameter, c=1.0m/s
        # Here it is assumed Ct = 7/V_hub (see Eq. (3.12) of ST Frandsen's thesis)
        # thus, when using the acutal Ct, the function will be tranformed into:
        # TI_add = 0.9/(1.5 + 0.8*d/sqrt(Ct))

        TI_add_jlk = 0.9 / (1.5 + 0.8 * (dw_jl / D_src_l[na])[:, :, na] / np.sqrt(ct_lk)[na])

        with np.warnings.catch_warnings():
            np.warnings.filterwarnings('ignore', r'divide by zero encountered in true_divide')

            # Theta_w is the characteristic view angle defined in Eq. (3.18) of
            # ST Frandsen's thesis
            theta_w = (180.0 / np.pi * np.arctan(1 / s_jl) + 10) / 2

            # thetq denotes the acutally view angles
            theta = np.arctan(cw_jl / dw_jl) * 180.0 / np.pi

        # weights_jl = np.where(theta < 3 * theta_w, np.exp(-(theta / theta_w)**2), 0)
        weights_jl = np.where(theta < theta_w, np.exp(-(theta / theta_w)**2), 0)

        # the way effective added TI is calculated is derived from Eqs. (3.16-18)
        # in ST Frandsen's thesis
        TI_add_jlk = weights_jl[:, :, na] * (np.sqrt(TI_add_jlk**2 + TI_lk[na]**2) - TI_lk[na])
        return TI_add_jlk


class NOJ_STF(NOJ, STFTurbulenceModel):
    pass


def main():
    if __name__ == '__main__':

        from py_wake.aep_calculator import AEPCalculator
        from py_wake.examples.data.iea37 import iea37_path
        from py_wake.examples.data.iea37._iea37 import IEA37Site
        from py_wake.examples.data.iea37._iea37 import IEA37_WindTurbines
        from py_wake.wake_models.noj import NOJ
        # setup site, turbines and wakemodel
        site = IEA37Site(16)
        x, y = site.initial_position.T
        windTurbines = IEA37_WindTurbines()

        class NOJ_STF(NOJ, STFTurbulenceModel):
            pass

        wake_model = NOJ_STF(windTurbines)

        # calculate AEP
        aep_calculator = AEPCalculator(site, windTurbines, wake_model)
        aep = aep_calculator.calculate_AEP(x, y)[0].sum()

        # plot wake mape
        import matplotlib.pyplot as plt

        X, Y, Z = aep_calculator.ti_map(wt_x=x, wt_y=y, wd=[0], ws=[9])
        c = plt.contourf(X, Y, Z, levels=100, cmap='Blues')
        plt.colorbar(c, label='turbulence intensity [m/s]')
        plt.title('AEP: %.2f GWh' % aep)
        windTurbines.plot(x, y)
        plt.show()


main()