''' Created on 16/06/2014 @author: MMPE ''' from __future__ import division from __future__ import unicode_literals from __future__ import print_function from __future__ import absolute_import from future import standard_library standard_library.install_aliases() from scipy.optimize.optimize import fmin import numpy as np def _z_u(z_u_lst): z = np.array([z for z, _ in z_u_lst]) u = np.array([np.mean(np.array([u])[:]) for _, u in z_u_lst]) return z, u def power_shear(alpha, z_ref, u_ref): """Power shear Parameters ---------- alpha : int or float The alpha shear parameter z_ref : int or float The reference height u_ref : int or float The wind speed of the reference height Returns ------- power_shear : function Function returning for wsp at input heights: f(height) -> wsp Example -------- >>> power_shear(.5, 70, 9)([20,50,70]) [ 4.81070235 7.60638829 9. ] """ return lambda z: u_ref * (np.array(z) / z_ref) ** alpha def fit_power_shear(z_u_lst): """Estimate power shear parameter, alpha, from the mean wind at hub height and one additional height Parameters ---------- z_u_lst : [(z_ref, u_z_ref), (z1, u_z1)] - z_ref: Reference height\n - u_z_ref: Wind speeds or mean wind speed at z_ref - z1: another height - u_z1: Wind speeds or mean wind speeds at z1 Returns ------- alpha : float power shear parameter Example -------- >>> fit_power_shear([(85, 9.0), (21, 4.47118)]) 0.50036320835 """ z, u = _z_u(z_u_lst) z_hub, u_hub = z[0], u[0] alpha, _ = np.polyfit(np.log(z / z_hub), np.log(u / u_hub), 1) return alpha def fit_power_shear_ref(z_u_lst, z_ref, plt=None): """Estimate power shear parameter, alpha, from two or more specific reference heights using polynomial fit. Parameters ---------- z_u_lst : [(z1, u_z1), (z2, u_z2),...] - z1: Some height - u_z1: Wind speeds or mean wind speed at z1 - z2: another height - u_z2: Wind speeds or mean wind speeds at z2 z_ref : float or int Reference height (hub height) plt : matplotlib.pyplot (or similar) or None Used to plot result if not None Returns ------- alpha : float power shear parameter u_ref : float Wind speed at reference height Example -------- >>> fit_power_shear_ref([(85, 8.88131), (21, 4.41832)], 87.13333) [ 0.49938238 8.99192568] """ def shear_error(x, z_u_lst, z_ref): alpha, u_ref = x return np.nansum([(u - u_ref * (z / z_ref) ** alpha) ** 2 for z, u in z_u_lst]) z_u_lst = [(z, np.mean(u)) for z, u in z_u_lst] alpha, u_ref = fmin(shear_error, (.1, 10), (z_u_lst, z_ref), disp=False) if plt: z, u = list(zip(*z_u_lst)) plt.plot(u, z, '.') z = np.linspace(min(z), max(z), 100) plt.plot(power_shear(alpha, z_ref, u_ref)(z), z) plt.margins(.1) if alpha == .1 and u_ref == 10: # Initial conditions return np.nan, np.nan return alpha, u_ref def log_shear(u_star, z0): """logarithmic shear Parameters ---------- u_star : int or float Friction velocity z0 : int or float Surface roughness [m] Returns ------- log_shear : function f(z,L=None) -> wsp z : int, float or array_like The heights of interest L : int, float or array_like, optional The corresponding Monin-Obukhov length Example -------- >>> shear = log_shear(1, 10) >>> shear([20, 50, 70]) [ 1.73286795 4.02359478 4.86477537] """ K = 0.4 # von Karmans constant def log_shear(z, Obukhov_length=None): if Obukhov_length is None: return u_star / K * (np.log(np.array(z) / z0)) else: return u_star / K * (np.log(z / z0) - stability_term(z, z0, Obukhov_length)) return log_shear def stability_term(z, z0, L): """Calculate the stability term for the log shear Not validated!!! """ zL = z / L def phi_us(zL): return (1 + 16 * np.abs(zL)) ** (-1 / 4) # unstable def phi_s(zL): return 1 + 5 * zL # stable phi = np.zeros_like(zL) + np.nan for m, f in [(((-2 <= zL) & (zL <= 0)), phi_us), (((0 < zL) & (zL <= 1)), phi_s)]: phi[m] = f(zL[m]) f = L / z * (1 - phi) psi = np.cumsum(np.r_[0, (f[1:] + f[:-1]) / 2 * np.diff(z / L)]) return psi def fit_log_shear(z_u_lst, include_R=False): """Estimate log shear parameter, u_star and z0 Parameters ---------- z_u_lst : [(z1, u_z1), (z2, u_z2),...] - z1: Some height - u_z1: Wind speeds or mean wind speed at z1 - z2: another height - u_z2: Wind speeds or mean wind speeds at z2 include_R : boolean, optional If True, the R^2 error is returned Returns ------- u_star : float friction velocity z0 : float Surface roughness [m] Example -------- >>> fit_log_shear([(85, 8.88131), (21, 4.41832)]) [ 0.49938238 8.99192568] """ # def shear_error(x, z_u_lst): # u_star, z0 = x # return np.sum([(np.mean(u) - log_shear(u_star, z0, z)) ** 2 for z, u in z_u_lst]) # return fmin(shear_error, (1, 1), (z_u_lst,), disp=False) z, U = _z_u(z_u_lst) a, b = np.polyfit(np.log(z), U, 1) kappa = 0.4 if include_R: return a * kappa, np.exp(-b / a), sum((U - (a * np.log(z) + b)) ** 2) return a * kappa, np.exp(-b / a) if __name__ == '__main__': from matplotlib.pyplot import plot, show z = np.arange(0, 211) for alpha, c in zip([0.00001, 1, 2], ['r', 'b', 'g']): u = power_shear(alpha, 120, 10)(z) plot(u, z, c) plot(u.mean(), 120, c + '.') plot([8.5, 11], [120, 120]) show()