py-wake
Advanced tools
| import pytest | ||
| from py_wake import np | ||
| from py_wake.tests import npt | ||
| from py_wake.utils.most import phi, psi, phi_eps | ||
| def test_phi(): | ||
| zeta = np.linspace(-.1, .1, 11) | ||
| # print(list(np.round(phi(zeta), 3))) | ||
| if 0: | ||
| plt.plot(zeta, phi(zeta)) | ||
| plt.show() | ||
| npt.assert_array_almost_equal(phi(zeta), [0.764, 0.792, 0.825, 0.867, 0.922, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5], 3) | ||
| def test_psi(): | ||
| zeta = np.linspace(-.1, .1, 51) | ||
| # print(list(np.round(psi(zeta[::5]), 3))) | ||
| # print(list(np.round(psi(zeta[::5], 'Wilson'), 3))) | ||
| if 0: | ||
| plt.plot(zeta, psi(zeta)) | ||
| plt.plot(zeta, psi(zeta, 'Wilson'), label='Wilson') | ||
| plt.legend() | ||
| plt.show() | ||
| npt.assert_array_almost_equal(psi(zeta[::5]), | ||
| [0.326, 0.276, 0.221, 0.159, 0.087, 0.0, -0.1, -0.2, -0.3, -0.4, -0.5], 3) | ||
| npt.assert_array_almost_equal(psi(zeta[::5], 'Wilson'), | ||
| [2.541, 2.488, 2.427, 2.355, 2.261, 0.0, -0.1, -0.2, -0.3, -0.4, -0.5], 3) | ||
| def test_phi_eps(): | ||
| zeta = np.linspace(-.1, .1, 11) | ||
| # print(list(np.round(phi_eps(zeta), 3))) | ||
| if 0: | ||
| plt.plot(zeta, phi_eps(zeta)) | ||
| plt.show() | ||
| npt.assert_array_almost_equal(phi_eps(zeta), [1.1, 1.08, 1.06, 1.04, 1.02, 1.0, 1.08, 1.16, 1.24, 1.32, 1.4], 3) |
| from py_wake import np | ||
| def phi(zeta, Cm1=5, Cm2=-19.3): | ||
| """ | ||
| Monin-Obukhov Similarity Theory function of normalized wind shear | ||
| """ | ||
| zeta = np.atleast_1d(zeta) | ||
| e = np.where((zeta <= 0), -.25, 1) # avoid warning when Cm2*zeta<-1 | ||
| return np.where(zeta <= 0, (1 + Cm2 * zeta)**e, 1 + Cm1 * zeta) | ||
| def psi(zeta, unstable='', Cm1=5, Cm2=-19.3): | ||
| """ | ||
| Monin-Obukhov Similarity Theory function of integrated normalized wind shear | ||
| """ | ||
| zeta = np.atleast_1d(zeta) | ||
| aux = phi(zeta, Cm1=Cm1, Cm2=Cm2)**-1 | ||
| if unstable == 'Wilson': | ||
| psi_n = np.where( | ||
| zeta < 0, | ||
| 3 * np.log(1 + np.sqrt(1 + 3.6 * np.abs(zeta)**(2.0 / 3.0))), | ||
| 1.0 - 1.0 / aux | ||
| ) | ||
| else: | ||
| aux2 = (1.0 + aux)**2 * (1 + aux**2) | ||
| rhs = -np.log(8.0 / aux2) - 2.0 * np.arctan(Cm2 * zeta / aux2) | ||
| psi_n = np.where(zeta < 0, rhs, 1.0 - 1.0 / aux) | ||
| psi_n = np.where(zeta == 0, 0.0, psi_n) | ||
| return psi_n | ||
| def phi_eps(zeta, Cm1=5): | ||
| """ | ||
| Monin-Obukhov Similarity Theory function of normalized dissipation of turbulent kinetic energy | ||
| """ | ||
| zeta = np.atleast_1d(zeta) | ||
| return np.where(zeta <= 0, 1.0 - zeta, 1.0 + (Cm1 - 1) * zeta) |
+1
-1
| Metadata-Version: 2.4 | ||
| Name: py_wake | ||
| Version: 2.6.12 | ||
| Version: 2.6.13 | ||
| Summary: Open source static wake modeling framework from DTU | ||
@@ -5,0 +5,0 @@ Author: DTU Wind Energy |
@@ -547,3 +547,3 @@ from numpy import newaxis as na | ||
| sigma_ijlk = self.sigma_ijlk(D_src_il=D_src_il, dw_ijlk=dw_ijlk, ct_ilk=ct_ilk, **kwargs) | ||
| return 2. * sigma_ijlk | ||
| return 2. * sigma_ijlk * D_src_il[:, na, :, na] | ||
@@ -550,0 +550,0 @@ |
@@ -43,2 +43,4 @@ # -*- coding: utf-8 -*- | ||
| method=method, | ||
| ws_cutin=3., | ||
| ws_cutout=25., | ||
| ), | ||
@@ -52,3 +54,3 @@ ) | ||
| print('Hub height', wt.hub_height()) | ||
| ws = np.arange(3, 25) | ||
| ws = np.arange(0., 30.) | ||
| import matplotlib.pyplot as plt | ||
@@ -55,0 +57,0 @@ plt.plot(ws, wt.power(ws), '.-', label='power [W]') |
| from py_wake import np | ||
| from py_wake.utils.most import phi, psi, phi_eps | ||
| from numpy import newaxis as na | ||
@@ -38,7 +39,10 @@ from abc import abstractmethod, ABC | ||
| class LogShear(Shear): | ||
| def __init__(self, h_ref=100, z0=.03, interp_method='nearest'): | ||
| class MOSTShear(Shear): | ||
| def __init__(self, h_ref=100, z0=.03, h_zeta=0.0, Cm1=5.0, Cm2=-19.3, interp_method='nearest'): | ||
| self.h_ref = h_ref | ||
| from py_wake.site._site import get_sector_xr | ||
| self.z0 = get_sector_xr(z0, "Roughness length") | ||
| self.h_zeta = h_zeta | ||
| self.Cm1 = Cm1 | ||
| self.Cm2 = Cm2 | ||
| self.interp_method = interp_method | ||
@@ -49,5 +53,10 @@ | ||
| z0 = self.z0.interp_ilk(localWind.coords, interp_method=self.interp_method) | ||
| return np.log(h[:, na, na] / z0) / np.log(self.h_ref / z0) * WS_ilk | ||
| L_inv = self.h_zeta / self.h_ref # 1 / Obukhov length | ||
| return (np.log(h[:, na, na] / z0) - psi(h[:, na, na] * L_inv, Cm1=self.Cm1, Cm2=self.Cm2)) / (np.log(self.h_ref / z0) - psi(self.h_zeta, Cm1=self.Cm1, Cm2=self.Cm2)) * WS_ilk | ||
| class LogShear(MOSTShear): | ||
| def __init__(self, h_ref=100, z0=.03, interp_method='nearest'): | ||
| MOSTShear.__init__(self, h_ref=h_ref, z0=z0, interp_method=interp_method) | ||
| # ====================================================================================================================== | ||
@@ -54,0 +63,0 @@ # Potentially the code below can be used to implement power/log shear interpolation between grid layers |
@@ -101,11 +101,11 @@ import pytest | ||
| (BlondelSuperGaussianDeficit2020(), | ||
| (338236.360935599, [8184.10433669, 7688.07418809, 11210.94605493, 13517.06684326, | ||
| 18220.2151193, 24405.81513366, 38658.43467216, 39081.04378946, | ||
| 20623.94292847, 12206.04086561, 14690.26714648, 31821.77172395, | ||
| 61172.26772292, 17636.16264219, 12053.55253044, 7066.65523799])), | ||
| (338152.7016942268, [8189.0455, 7674.43768, 11216.04157, 13506.83034, 18220.11534, | ||
| 24387.33256, 38676.00541, 39011.72486, 20636.39466, 12230.83007, | ||
| 14672.93813, 31809.40211, 61171.95556, 17629.30719, 12039.33385, | ||
| 7081.00688])), | ||
| (BlondelSuperGaussianDeficit2023(), | ||
| (355892.77826332045, [8979.31725425, 8180.44857196, 11292.09175721, 13964.6406542, | ||
| 20066.69629875, 25213.93451452, 38938.24743865, 41583.94690748, | ||
| 22627.8794807, 12933.21646472, 14824.4675625, 32363.56815599, | ||
| 67336.57050905, 17936.43536356, 12163.66569231, 7487.65163747])) | ||
| (356158.2866576972, [9017.94626, 8157.37254, 11335.5033, 13956.83138, 20062.42899, | ||
| 25199.83443, 39087.94241, 41466.64377, 22725.22458, 13069.53946, | ||
| 14778.90386, 32362.67185, 67308.64964, 17935.93862, 12126.28009, | ||
| 7566.57547])) | ||
| ]) | ||
@@ -272,2 +272,3 @@ def test_IEA37_ex16(deficitModel, aep_ref): | ||
| (TurboGaussianDeficit(), [76.674176, 41.548202, 83.096405, 64.831198, 76.143396]), | ||
| (BlondelSuperGaussianDeficit2023(), [83.792707, 60.896354, 121.792707, 67.967813, 69.792707]) | ||
| ]) | ||
@@ -307,5 +308,8 @@ def test_wake_radius(deficitModel, wake_radius_ref): | ||
| dw_ijlk=np.reshape(x, (1, len(x), 1, 1)), | ||
| h_ilk=np.reshape(70, (1, 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] | ||
| TI_eff_ilk=sim_res.TI_eff.values, | ||
| type_il=np.reshape(0, (1, 1)) | ||
| )[0, :, 0, 0] | ||
| ax1.set_title(deficitModel.__class__.__name__) | ||
@@ -639,3 +643,3 @@ ax1.plot(x, wr) | ||
| sim_res = wfm([0, .1, .2], [0, 200, 400], wd=[270, 90], ws=10, type=[0, 1, 2]) | ||
| fm = sim_res.flow_map(Points(x=[200, 200, 200], y=[0, 200, 400], h=[110, 110, 110])) | ||
| fm = sim_res.flow_map(Points(x=[200, 200, 200], y=[0, 200, 400], h=[110, 110, 110]), wd=sim_res.wd, ws=sim_res.ws) | ||
| npt.assert_allclose(fm.WS_eff[:, 1], [3.4, 6.1, 7.5], atol=.1) | ||
@@ -642,0 +646,0 @@ if 0: |
@@ -51,4 +51,4 @@ from py_wake import np | ||
| sim_res = wake_model(wt_x, wt_y, wd=[30], ws=[10]) | ||
| flow_map70 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=70)) | ||
| flow_map73 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=73)) | ||
| flow_map70 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=70), memory_GB=0.5) | ||
| flow_map73 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=73), memory_GB=0.5) | ||
@@ -131,4 +131,4 @@ X, Y = flow_map70.XY | ||
| sim_res = wake_model(wt_x, wt_y, wd=[30], ws=[10]) | ||
| flow_map70 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=70)) | ||
| flow_map73 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=73)) | ||
| flow_map70 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=70), memory_GB=0.5) | ||
| flow_map73 = sim_res.flow_map(HorizontalGrid(x_j, y_j, h=73), memory_GB=0.5) | ||
@@ -135,0 +135,0 @@ X, Y = flow_map70.XY |
@@ -153,3 +153,30 @@ from py_wake import np | ||
| # Test MOST shear, stable. | ||
| # WS_eff_star does not change since we not change the actual simulation using Site with MOSTShear and LUTs with stability | ||
| aDControl2 = ADControl.from_lut([dataset, lut2], wts, ws_cutin=4, ws_cutout=25, dws=1.0, cal_TI=0.06, cal_zeta=0.5) | ||
| ellipsys_power, WS_eff_star, ct_star = get_Ellipsys_equivalent_output(simres, aDControl2) | ||
| # print(ct_star.flatten()) | ||
| # print(ellipsys_power.flatten() * 1e-6) | ||
| CTstar_expected = [1.32895893, 1.33159161, 1.36637959, 1.32630388, 1.36116655, 1.36639816, 1.36463016] | ||
| power_expected = [1.34531419, 1.33329859, 0.72796236, 1.35150555, 1.060569, 0.72981311, 0.56473626] | ||
| npt.assert_array_almost_equal(ellipsys_power.flatten() * 1e-6, power_expected, 6) | ||
| npt.assert_array_almost_equal(WS_eff_star.flatten(), UAD_expected, 6) | ||
| npt.assert_array_almost_equal(ct_star.flatten(), CTstar_expected, 6) | ||
| # Test MOST shear, unstable | ||
| aDControl2 = ADControl.from_lut([dataset, lut2], wts, ws_cutin=4, ws_cutout=25, dws=1.0, cal_TI=0.06, cal_zeta=-0.5) | ||
| ellipsys_power, WS_eff_star, ct_star = get_Ellipsys_equivalent_output(simres, aDControl2) | ||
| # print(ct_star.flatten()) | ||
| # print(ellipsys_power.flatten() * 1e-6) | ||
| CTstar_expected = [1.3254684, 1.32682915, 1.36065434, 1.32318215, 1.35620019, 1.36067278, 1.35891729] | ||
| power_expected = [1.33938202, 1.32595377, 0.72335257, 1.34597418, 1.05462423, 0.72519153, 0.56109148] | ||
| npt.assert_array_almost_equal(ellipsys_power.flatten() * 1e-6, power_expected, 6) | ||
| npt.assert_array_almost_equal(WS_eff_star.flatten(), UAD_expected, 6) | ||
| npt.assert_array_almost_equal(ct_star.flatten(), CTstar_expected, 6) | ||
| def test_rans_lut_multi_wd_ws(): | ||
@@ -156,0 +183,0 @@ # move turbine 1 600 300 |
@@ -22,4 +22,2 @@ from py_wake.flow_map import HorizontalGrid, YZGrid, Points, XYGrid, XZGrid | ||
| from py_wake.site._site import UniformSite | ||
| from py_wake.ground_models.ground_models import Mirror | ||
| from py_wake.deficit_models.selfsimilarity import SelfSimilarityDeficit2020 | ||
@@ -58,4 +56,4 @@ | ||
| superpositionModel=SquaredSum()) | ||
| simulation_result = wind_farm_model(x, y, wd=[0, 270], ws=[6, 8, 10], mode=0) | ||
| fm = simulation_result.flow_map(XYGrid(resolution=3)) | ||
| sim_res = wind_farm_model(x, y, wd=[0, 270], ws=[6, 8, 10], mode=0) | ||
| fm = sim_res.flow_map(XYGrid(resolution=3), wd=sim_res.wd, ws=sim_res.ws) | ||
| npt.assert_array_almost_equal(fm.power_xylk(mode=1).sum(['wd', 'ws']).isel(h=0), | ||
@@ -319,2 +317,40 @@ [[7030000., 6378864., 7029974.], | ||
| def test_flow_map_point_chunks(): | ||
| wfm = IEA37CaseStudy1(16) | ||
| x, y = wfm.site.initial_position.T | ||
| sim_res = wfm(x, y, wd=np.arange(0, 360, 30), ws=10) | ||
| # wfm.verbose = True | ||
| # j chunks | ||
| fm1 = sim_res.flow_map(XYGrid(resolution=500), wd=270) | ||
| fm2 = sim_res.flow_map(XYGrid(resolution=500), wd=270, memory_GB=0.005) | ||
| fm3 = sim_res.flow_map(XYGrid(resolution=500), wd=270, memory_GB=0.005, n_cpu=4) | ||
| npt.assert_array_equal(fm1.WS_eff, fm2.WS_eff) | ||
| npt.assert_array_equal(fm1.WS_eff, fm3.WS_eff) | ||
| # wd chunks | ||
| fm4 = sim_res.flow_map(XYGrid(resolution=50), wd=270) | ||
| fm5 = sim_res.flow_map(XYGrid(resolution=50), wd=sim_res.wd) | ||
| fm6 = sim_res.flow_map(XYGrid(resolution=50), wd=sim_res.wd, memory_GB=0.002) | ||
| fm7 = sim_res.flow_map(XYGrid(resolution=50), wd=sim_res.wd, memory_GB=0.002, n_cpu=4) | ||
| npt.assert_array_equal(fm4.WS_eff, fm5.WS_eff.sel(wd=[270])) | ||
| npt.assert_array_equal(fm5.WS_eff, fm6.WS_eff) | ||
| npt.assert_array_equal(fm5.WS_eff, fm7.WS_eff) | ||
| # both wd and j chunks | ||
| fm8 = sim_res.flow_map(XYGrid(resolution=50), wd=sim_res.wd, memory_GB=0.0005) | ||
| fm9 = sim_res.flow_map(XYGrid(resolution=50), wd=sim_res.wd, memory_GB=0.0005, n_cpu=4) | ||
| npt.assert_array_equal(fm5.WS_eff, fm8.WS_eff) | ||
| npt.assert_array_equal(fm5.WS_eff, fm9.WS_eff) | ||
| sim_res.flow_map(XYGrid(resolution=50), wd=sim_res.wd[:1], n_cpu=4) | ||
| sim_res.flow_map(XYGrid(resolution=50), wd=sim_res.wd[:2], n_cpu=4) | ||
| sim_res.flow_map(XYGrid(resolution=50), wd=sim_res.wd[:], n_cpu=4) | ||
| if 0: | ||
| fm1.plot_wake_map() | ||
| plt.show() | ||
| def test_aep_map(): | ||
@@ -327,3 +363,3 @@ wfm = IEA37CaseStudy1(16) | ||
| aep_map = sim_res.aep_map(grid, normalize_probabilities=True) | ||
| fm = sim_res.flow_map(grid) | ||
| fm = sim_res.flow_map(grid, wd=sim_res.wd, ws=sim_res.ws) | ||
| npt.assert_array_almost_equal(fm.aep_xy(normalize_probabilities=True).sel(h=110), aep_map) | ||
@@ -363,3 +399,3 @@ | ||
| fm = sim_res.flow_map(grid) | ||
| fm = sim_res.flow_map(grid, ws=sim_res.ws, wd=sim_res.wd) | ||
| npt.assert_array_almost_equal(fm.aep_xy(normalize_probabilities=True).sel(h=110), aep_map) | ||
@@ -366,0 +402,0 @@ |
@@ -218,4 +218,5 @@ from numpy import nan | ||
| fm_ref = wfm([0, 0 + 1e-20], [0, 0 + 1e-20], wd=[0, 5], h=[50, -50] | ||
| ).flow_map(YZGrid(x=0, y=np.arange(-100, 100, 1) + .1, z=np.arange(1, 100))) | ||
| sim_res_ref = wfm([0, 0 + 1e-20], [0, 0 + 1e-20], wd=[0, 5], h=[50, -50] | ||
| ) | ||
| fm_ref = sim_res_ref.flow_map(YZGrid(x=0, y=np.arange(-100, 100, 1) + .1, z=np.arange(1, 100)), wd=sim_res_ref.wd) | ||
| fm_ref.plot_wake_map() | ||
@@ -227,3 +228,4 @@ plt.title("Underground WT added manually") | ||
| superpositionModel=LinearSum()) | ||
| fm_res = wfm([0], [0], wd=[0, 5], h=[50]).flow_map(YZGrid(x=0, y=np.arange(-100, 100, 1) + .1, z=np.arange(1, 100))) | ||
| sim_res = wfm([0], [0], wd=[0, 5], h=[50]) | ||
| fm_res = sim_res.flow_map(YZGrid(x=0, y=np.arange(-100, 100, 1) + .1, z=np.arange(1, 100)), wd=sim_res.wd) | ||
| fm_res.plot_wake_map() | ||
@@ -230,0 +232,0 @@ plt.title("With Mirror GroundModel") |
@@ -1,2 +0,3 @@ | ||
| from py_wake.site.shear import PowerShear, LogShear | ||
| from py_wake.site.shear import PowerShear, MOSTShear, LogShear | ||
| from py_wake.utils.most import psi | ||
| from py_wake import np | ||
@@ -15,5 +16,5 @@ from py_wake.tests import npt | ||
| if 0: | ||
| plt.plot(WS.sel(wd=0, ws=10), WS.h, label='alpha=0.1') | ||
| plt.plot(WS.sel(wd=0, ws=10), h_lst, label='alpha=0.1') | ||
| plt.plot((h_lst / 70)**0.1 * 10, h_lst, ':') | ||
| plt.plot(WS.sel(wd=180, ws=12), WS.h, label='alpha=0.2') | ||
| plt.plot(WS.sel(wd=180, ws=12), h_lst, label='alpha=0.2') | ||
| plt.plot((h_lst / 70)**0.2 * 12, h_lst, ':') | ||
@@ -26,2 +27,23 @@ plt.legend() | ||
| def test_most_shear(): | ||
| h_lst = np.arange(10, 100, 10) | ||
| h_zetas = [-0.5, 0.0, 0.5] | ||
| for h_zeta in h_zetas: | ||
| L_inv = h_zeta / 70.0 | ||
| site = UniformSite([1], .1, shear=MOSTShear(70, h_zeta=h_zeta, z0=[.02, 2], Cm1=5.0, Cm2=-16.0)) | ||
| WS = site.local_wind(x=h_lst * 0, y=h_lst * 0, h=h_lst, wd=[0, 180], ws=[10, 12]).WS | ||
| if 0: | ||
| plt.plot(WS.sel(wd=0, ws=10), h_lst, label='z0=0.02, h_zeta=%g' % h_zeta) | ||
| plt.plot((np.log(h_lst / 0.02) - psi(h_lst * L_inv, Cm1=5.0, Cm2=-16.0)) / (np.log(70.0 / 0.02) - psi(h_zeta, Cm1=5.0, Cm2=-16.0)) * 10.0, h_lst, ':') | ||
| plt.plot(WS.sel(wd=180, ws=12), h_lst, label='z0=2, h_zeta=%g' % h_zeta) | ||
| plt.plot((np.log(h_lst / 2) - psi(h_lst * L_inv, Cm1=5.0, Cm2=-16.0)) / (np.log(70.0 / 2) - psi(h_zeta, Cm1=5.0, Cm2=-16.0)) * 12.0, h_lst, ':') | ||
| if h_zeta == h_zetas[-1]: | ||
| plt.legend() | ||
| plt.show() | ||
| npt.assert_array_equal(WS.sel(wd=0, ws=10), (np.log(h_lst / 0.02) - psi(h_lst * L_inv, Cm1=5.0, Cm2=-16.0)) / (np.log(70.0 / 0.02) - psi(h_zeta, Cm1=5.0, Cm2=-16.0)) * 10) | ||
| npt.assert_array_equal(WS.sel(wd=180, ws=12), (np.log(h_lst / 2) - psi(h_lst * L_inv, Cm1=5.0, Cm2=-16.0)) / (np.log(70.0 / 2) - psi(h_zeta, Cm1=5.0, Cm2=-16.0)) * 12) | ||
| def test_log_shear(): | ||
@@ -34,5 +56,5 @@ | ||
| if 0: | ||
| plt.plot(WS.sel(wd=0, ws=10), WS.h, label='z0=0.02') | ||
| plt.plot(WS.sel(wd=0, ws=10), h_lst, label='z0=0.02') | ||
| plt.plot(np.log(h_lst / 0.02) / np.log(70 / 0.02) * 10, h_lst, ':') | ||
| plt.plot(WS.sel(wd=180, ws=12), WS.h, label='z0=2') | ||
| plt.plot(WS.sel(wd=180, ws=12), h_lst, label='z0=2') | ||
| plt.plot(np.log(h_lst / 2) / np.log(70 / 2) * 12, h_lst, ':') | ||
@@ -39,0 +61,0 @@ plt.legend() |
@@ -158,4 +158,4 @@ import pytest | ||
| npt.assert_array_almost_equal(sim_res_a2a.WS_eff.sel(wt=8), sim_res_pdw.WS_eff.sel(wt=8)) | ||
| fm_a2a = sim_res_a2a.flow_map(Points(wt9_x[-1:], wt9_y[-1:], [70])) | ||
| fm_pdw = sim_res_a2a.flow_map(Points(wt9_x[-1:], wt9_y[-1:], [70])) | ||
| fm_a2a = sim_res_a2a.flow_map(Points(wt9_x[-1:], wt9_y[-1:], [70]), wd=sim_res_a2a.wd, ws=sim_res_a2a.ws) | ||
| fm_pdw = sim_res_a2a.flow_map(Points(wt9_x[-1:], wt9_y[-1:], [70]), wd=sim_res_pdw.wd, ws=sim_res_pdw.ws) | ||
| npt.assert_array_almost_equal(sim_res_a2a.WS_eff.sel(wt=8).squeeze(), fm_a2a.WS_eff) | ||
@@ -162,0 +162,0 @@ npt.assert_array_almost_equal(sim_res_a2a.WS_eff.sel(wt=8).squeeze(), fm_pdw.WS_eff) |
@@ -39,27 +39,2 @@ import os | ||
| def test_phi(): | ||
| zeta = np.linspace(-.1, .1, 11) | ||
| # print(list(np.round(phi(zeta), 3))) | ||
| if 0: | ||
| plt.plot(zeta, phi(zeta)) | ||
| plt.show() | ||
| npt.assert_array_almost_equal(phi(zeta), [0.764, 0.792, 0.825, 0.867, 0.922, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5], 3) | ||
| def test_psi(): | ||
| zeta = np.linspace(-.1, .1, 51) | ||
| # print(list(np.round(psi(zeta[::5]), 3))) | ||
| # print(list(np.round(psi(zeta[::5], 'Wilson'), 3))) | ||
| if 0: | ||
| plt.plot(zeta, psi(zeta)) | ||
| plt.plot(zeta, psi(zeta, 'Wilson'), label='Wilson') | ||
| plt.legend() | ||
| plt.show() | ||
| npt.assert_array_almost_equal(psi(zeta[::5]), | ||
| [0.326, 0.276, 0.221, 0.159, 0.087, 0.0, -0.1, -0.2, -0.3, -0.4, -0.5], 3) | ||
| npt.assert_array_almost_equal(psi(zeta[::5], 'Wilson'), | ||
| [2.541, 2.488, 2.427, 2.355, 2.261, 0.0, -0.1, -0.2, -0.3, -0.4, -0.5], 3) | ||
| def test_z0_from_TI(): | ||
@@ -66,0 +41,0 @@ if 0: |
@@ -18,3 +18,3 @@ from numpy import newaxis as na | ||
| from py_wake.site.distance import StraightDistance | ||
| from py_wake.site.shear import LogShear, PowerShear, Shear | ||
| from py_wake.site.shear import LogShear, PowerShear, Shear, MOSTShear | ||
| from py_wake.superposition_models import SuperpositionModel, AddedTurbulenceSuperpositionModel | ||
@@ -228,3 +228,4 @@ from py_wake.tests import npt | ||
| model = {PowerShear: PowerShear(h_ref=100, alpha=.1), | ||
| LogShear: LogShear(h_ref=100, z0=.03)}[model] | ||
| LogShear: LogShear(h_ref=100, z0=.03), | ||
| MOSTShear: MOSTShear(h_ref=100, z0=.03, h_zeta=0.0)}[model] | ||
| check_gradients(lambda site, wt, s=Hornsrev1Site(shear=model): PropagateDownwind( | ||
@@ -231,0 +232,0 @@ s, wt, wake_deficitModel=BastankhahGaussianDeficit(), |
| import os | ||
| import warnings | ||
@@ -7,9 +8,15 @@ from autograd.numpy.numpy_boxes import ArrayBox | ||
| import matplotlib.pyplot as plt | ||
| from py_wake import np | ||
| from py_wake.deficit_models.deficit_model import WakeDeficitModel, BlockageDeficitModel | ||
| from py_wake.deficit_models.gaussian import IEA37SimpleBastankhahGaussianDeficit | ||
| from py_wake.deficit_models.noj import NOJDeficit | ||
| from py_wake.deflection_models.deflection_model import DeflectionModel | ||
| from py_wake.examples.data.ParqueFicticio._parque_ficticio import ParqueFicticioSite | ||
| from py_wake.examples.data.hornsrev1 import Hornsrev1Site, V80 | ||
| from py_wake.examples.data.iea37._iea37 import IEA37Site, IEA37_WindTurbines | ||
| from py_wake.flow_map import XYGrid | ||
| from py_wake.ground_models.ground_models import GroundModel | ||
| from py_wake.rotor_avg_models.area_overlap_model import AreaOverlapAvgModel | ||
| from py_wake.rotor_avg_models.gaussian_overlap_model import GaussianOverlapAvgModel | ||
| from py_wake.rotor_avg_models.rotor_avg_model import RotorAvgModel | ||
@@ -28,13 +35,4 @@ from py_wake.site._site import Site | ||
| from py_wake.wind_farm_models.engineering_models import PropagateDownwind, All2AllIterative, EngineeringWindFarmModel | ||
| from py_wake.wind_farm_models.wind_farm_model import WindFarmModel | ||
| from py_wake.examples.data.hornsrev1 import Hornsrev1Site, V80 | ||
| from py_wake.rotor_avg_models.gaussian_overlap_model import GaussianOverlapAvgModel | ||
| from py_wake.rotor_avg_models.area_overlap_model import AreaOverlapAvgModel | ||
| from py_wake.deficit_models.noj import NOJDeficit | ||
| import warnings | ||
| from py_wake.flow_map import XYGrid | ||
| import matplotlib.pyplot as plt | ||
| @pytest.mark.parametrize('v,dtype,dtype32', [(5., float, np.float32), | ||
@@ -41,0 +39,0 @@ (5 + 0j, complex, np.complex64)]) |
@@ -99,7 +99,2 @@ import pytest | ||
| def test_when_ct_idle_fails(): | ||
| wt = IEA34_130_1WT_Surrogate() | ||
| sim_res = All2AllIterative(Hornsrev1Site(), wt, NOJDeficit(), turbulenceModel=STF2017TurbulenceModel())([0], [0], ) | ||
| def test_not_converge(): | ||
@@ -106,0 +101,0 @@ class RandomRathmann(Rathmann): |
@@ -277,3 +277,3 @@ import pytest | ||
| warnings.simplefilter('ignore', UserWarning) | ||
| ws_eff = sim_res.flow_map().WS_eff.interp( | ||
| ws_eff = sim_res.flow_map(wd=sim_res.wd, ws=sim_res.ws).WS_eff.interp( | ||
| x=('z', [-100, -300, 100]), y=('z', [-300, 100, 300]), wd=('z', [0, 90, 180])).squeeze().values | ||
@@ -290,3 +290,3 @@ npt.assert_array_equal(ws_eff[0], ws_eff) | ||
| sim_res = wfm(x=[[[0, 0, 0]], [[100, 200, 300]]], y=np.zeros((2, 1, 3)), wd=[270], ws=[8, 9, 10]) | ||
| ws_eff = sim_res.flow_map().WS_eff.interp(x=400, y=0).squeeze() | ||
| ws_eff = sim_res.flow_map(wd=sim_res.wd, ws=sim_res.ws).WS_eff.interp(x=400, y=0).squeeze() | ||
| npt.assert_array_almost_equal(ws_eff, [4.06513, 4.117601, 3.830711]) | ||
@@ -293,0 +293,0 @@ if 0: |
@@ -9,2 +9,3 @@ import os | ||
| from py_wake.utils import gradients | ||
| from py_wake.utils.most import phi, psi | ||
| from scipy.special import lambertw | ||
@@ -307,28 +308,3 @@ from scipy.optimize import fsolve | ||
| Cm1 = 5 | ||
| Cm2 = -19.3 | ||
| def phi(zeta): | ||
| zeta = np.atleast_1d(zeta) | ||
| e = np.where((zeta <= 0), -.25, 1) # avoid warning when Cm2*zeta<-1 | ||
| return np.where(zeta <= 0, (1 + Cm2 * zeta)**e, 1 + Cm1 * zeta) | ||
| def psi(zeta, unstable=''): | ||
| zeta = np.atleast_1d(zeta) | ||
| ind = zeta < 0 | ||
| psi_n = np.zeros(zeta.shape) | ||
| aux = phi(zeta)**-1 | ||
| if unstable == 'Wilson': | ||
| psi_n[ind] = 3 * np.log((1 + (1 + 3.6 * np.abs(zeta[ind])**(2 / 3))**.5)) | ||
| else: | ||
| aux2 = (1.0 + aux[ind])**2 * (1 + aux[ind]**2) | ||
| psi_n[ind] = -np.log(8.0 / aux2) - 2.0 * np.arctan(Cm2 * zeta[ind] / aux2) | ||
| psi_n[~ind] = 1 - aux[~ind]**-1 | ||
| psi_n[zeta == 0] = 0 | ||
| return psi_n | ||
| def z0(TI, zref, zeta0, z0_limit=1e-5): | ||
| def z0(TI, zref, zeta0, z0_limit=1e-5, Cm1=5): | ||
| zeros = np.atleast_1d((np.asarray(TI) + np.asarray(zref) + np.asarray(zeta0)) * 0) | ||
@@ -365,3 +341,3 @@ TI, zref, zeta0 = zeros + TI, zeros + zref, zeros + zeta0 | ||
| def ti(z0, zref, zeta0): | ||
| def ti(z0, zref, zeta0, Cm1=5): | ||
| zeros = np.atleast_1d((np.asarray(z0) + np.asarray(zref) + np.asarray(zeta0)) * 0) | ||
@@ -368,0 +344,0 @@ z0, zref, zeta0 = zeros + z0, zeros + zref, zeros + zeta0 |
@@ -5,3 +5,3 @@ import multiprocessing | ||
| import gc | ||
| import os | ||
| from itertools import starmap | ||
@@ -56,2 +56,26 @@ pool_dict = {} | ||
| def get_map_func(n_cpu, verbose, desc='', unit='it'): | ||
| n_cpu = n_cpu or multiprocessing.cpu_count() | ||
| if n_cpu > 1: | ||
| map_func = get_pool_map(n_cpu) | ||
| else: | ||
| from tqdm import tqdm | ||
| def map_func(f, iter): | ||
| return tqdm(map(f, iter), desc=desc, unit=unit, total=len(iter), disable=not verbose) | ||
| return map_func | ||
| def get_starmap_func(n_cpu, verbose, desc='', unit='it', leave=True): | ||
| n_cpu = n_cpu or multiprocessing.cpu_count() | ||
| if n_cpu > 1: | ||
| map_func = get_pool_starmap(n_cpu) | ||
| else: | ||
| from tqdm import tqdm | ||
| def map_func(f, iter): | ||
| return starmap(f, tqdm(iter, desc=desc, unit=unit, total=len(iter), disable=not verbose, leave=leave)) | ||
| return map_func | ||
| atexit.register(close_pools) |
@@ -8,2 +8,3 @@ import xarray as xr | ||
| from pathlib import Path | ||
| from py_wake.utils.most import phi, psi, phi_eps | ||
@@ -68,5 +69,5 @@ | ||
| @staticmethod | ||
| def from_lut(lut, windTurbines, ws_cutin, ws_cutout, dws, cal_TI, | ||
| def from_lut(lut, windTurbines, ws_cutin, ws_cutout, dws, cal_TI, cal_zeta=0.0, | ||
| rotorAvgModel=EllipSysPolygonRotorAvg(n_r=9, n_theta=32), | ||
| density=1.225, cmu=0.03, kappa=0.4): | ||
| density=1.225, cmu=0.03, kappa=0.4, Cm1=5.0, Cm2=-16.0): | ||
| """Calculcate ADControl object containing CPstar, CTstar = f(UAD) directly from single wake RANS-LUT | ||
@@ -107,4 +108,6 @@ | ||
| uStar_UH = cal_TI * np.sqrt(1.5 * np.sqrt(cmu)) | ||
| # z0 = zRef / (np.exp(kappa / uStar_UH) - 1) | ||
| phim = phi(cal_zeta, Cm1=Cm1, Cm2=Cm2) | ||
| psim = psi(cal_zeta, Cm1=Cm1, Cm2=Cm2) | ||
| phieps = phi_eps(cal_zeta, Cm1=Cm1) | ||
| uStar_UH = cal_TI * np.sqrt(1.5 * np.sqrt(cmu)) * phieps ** -0.25 * phim ** 0.25 | ||
@@ -136,6 +139,6 @@ types = np.arange(len(lut_U)) | ||
| # PWE: z0 is added to h_j and zH | ||
| # logshear = np.log(h_j / z0) / np.log(zRef / z0) | ||
| z0 = zH / (np.exp(kappa / uStar_UH) - 1) | ||
| logshear = np.log(h_j / z0) / np.log(zH / z0) | ||
| U = logshear[na, :] - 1.0 + Udata.interp(ct=cts, kwargs={"fill_value": "extrapolate"}).values | ||
| z0 = zH / (np.exp(kappa / uStar_UH + psim) - 1) | ||
| L_inv = cal_zeta / zH # 1 / Obukhov length | ||
| mostshear = (np.log(h_j / z0) - psi(h_j * L_inv, Cm1=Cm1, Cm2=Cm2)) / (np.log(zH / z0) - psim) | ||
| U = mostshear[na, :] - 1.0 + Udata.interp(ct=cts, kwargs={"fill_value": "extrapolate"}).values | ||
| UAD = ws * np.sum(np.reshape(U, (len(ws), -1)) * weights, axis=1) | ||
@@ -142,0 +145,0 @@ ratio = ws / UAD |
@@ -89,3 +89,4 @@ from py_wake.wind_farm_models.engineering_models import PropagateDownwind | ||
| windFarmModel.windTurbines = self.windTurbines | ||
| fm = windFarmModel([0], [0]).flow_map(XYGrid(y=-self.x, x=0)) | ||
| sim_res = windFarmModel([0], [0]) | ||
| fm = sim_res.flow_map(XYGrid(y=-self.x, x=0), wd=sim_res.wd, ws=sim_res.ws) | ||
| wd = (fm.wd.values + 180) % 360 - 180 | ||
@@ -92,0 +93,0 @@ ws = (fm.WS_eff / fm.ws).squeeze() |
+16
-3
| # file generated by setuptools-scm | ||
| # don't change, don't track in version control | ||
| __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"] | ||
| __all__ = [ | ||
| "__version__", | ||
| "__version_tuple__", | ||
| "version", | ||
| "version_tuple", | ||
| "__commit_id__", | ||
| "commit_id", | ||
| ] | ||
@@ -12,4 +19,6 @@ TYPE_CHECKING = False | ||
| VERSION_TUPLE = Tuple[Union[int, str], ...] | ||
| COMMIT_ID = Union[str, None] | ||
| else: | ||
| VERSION_TUPLE = object | ||
| COMMIT_ID = object | ||
@@ -20,4 +29,8 @@ version: str | ||
| version_tuple: VERSION_TUPLE | ||
| commit_id: COMMIT_ID | ||
| __commit_id__: COMMIT_ID | ||
| __version__ = version = '2.6.12' | ||
| __version_tuple__ = version_tuple = (2, 6, 12) | ||
| __version__ = version = '2.6.13' | ||
| __version_tuple__ = version_tuple = (2, 6, 13) | ||
| __commit_id__ = commit_id = None |
@@ -18,2 +18,4 @@ from abc import abstractmethod | ||
| from py_wake.deficit_models.no_wake import NoWakeDeficit | ||
| from py_wake.utils.parallelization import get_map_func, get_starmap_func | ||
| import multiprocessing | ||
@@ -310,11 +312,8 @@ | ||
| def _get_flow_l(self, model_kwargs, l, wt_x_ilk, wt_y_ilk, wt_h_ilk, lw_j, wd, WD_ilk): | ||
| def _get_flow_l(self, model_kwargs, wt_x_ilk, wt_y_ilk, wt_h_ilk, x_j, y_j, h_j, wd, WD_ilk, WS_jlk, TI_jlk): | ||
| wt_z_ilk = self.site.elevation(wt_x_ilk, wt_y_ilk) | ||
| z_j = self.site.elevation(lw_j.x, lw_j.y) | ||
| self.site.distance.setup(wt_x_ilk, wt_y_ilk, wt_h_ilk, wt_z_ilk, (lw_j.x, lw_j.y, lw_j.h, z_j)) | ||
| z_j = self.site.elevation(x_j, y_j) | ||
| self.site.distance.setup(wt_x_ilk, wt_y_ilk, wt_h_ilk, wt_z_ilk, (x_j, y_j, h_j, z_j)) | ||
| dw_ijlk, hcw_ijlk, dh_ijlk = self.site.distance(wd_l=wd, WD_ilk=WD_ilk) | ||
| WS_jlk = lw_j.WS_ilk[:, [l, slice(0, 1)][lw_j.WS_ilk.shape[1] == 1]] | ||
| TI_jlk = lw_j.TI_ilk[:, [l, slice(0, 1)][lw_j.TI_ilk.shape[1] == 1]] | ||
| if self.wec != 1: | ||
@@ -384,6 +383,7 @@ hcw_ijlk = hcw_ijlk / self.wec | ||
| TI_eff_jlk = None | ||
| model_kwargs.clear() | ||
| return WS_eff_jlk, TI_eff_jlk | ||
| def _aep_map(self, x_j, y_j, h_j, type_j, sim_res_data): | ||
| lw_j, WS_eff_jlk, _ = self._flow_map(x_j, y_j, h_j, sim_res_data) | ||
| def _aep_map(self, x_j, y_j, h_j, type_j, sim_res_data, memory_GB=1, n_cpu=1): | ||
| lw_j, WS_eff_jlk, _ = self._flow_map(x_j, y_j, h_j, sim_res_data, memory_GB=memory_GB, n_cpu=n_cpu) | ||
| power_kwargs = {} | ||
@@ -398,25 +398,39 @@ if 'type' in (self.windTurbines.powerCtFunction.required_inputs + | ||
| def _flow_map(self, x_j, y_j, h_j, sim_res_data, D_dst=0): | ||
| def _flow_map(self, x_j, y_j, h_j, sim_res_data, D_dst=0, memory_GB=1, n_cpu=1): | ||
| """call this function via SimulationResult.flow_map""" | ||
| arg_funcs, lw_j, wd, WD_il = self.get_map_args(x_j, y_j, h_j, sim_res_data, D_dst=D_dst) | ||
| I, J, L, K = arg_funcs['IJLK']() | ||
| if I == 0: | ||
| return (lw_j, np.broadcast_to(lw_j.WS_ilk, (len(x_j), L, K)).astype(float), | ||
| np.broadcast_to(lw_j.TI_ilk, (len(x_j), L, K)).astype(float)) | ||
| n_cpu = n_cpu or multiprocessing.cpu_count() | ||
| # *6=dx_ijlk, dy_ijlk, dz_ijlk, dh_ijlk, deficit, blockage | ||
| size_GB = I * J * L * K * np.array([]).itemsize * 6 * n_cpu / 1024**3 | ||
| min_wd_chunks = np.minimum(n_cpu, L) | ||
| wd_chunks = int(np.clip(np.ceil(size_GB / memory_GB), min_wd_chunks, L)) | ||
| min_j_chunks = np.minimum(int(np.ceil(n_cpu / wd_chunks)), J) | ||
| j_chunks = int(np.clip(np.ceil(size_GB / wd_chunks / memory_GB), min_j_chunks, J)) | ||
| size_gb = I * J * L * K * 8 / 1024**3 | ||
| wd_chunks = int(np.minimum(np.maximum(int(size_gb // 1), 1), L)) | ||
| wd_i = np.round(np.linspace(0, L, wd_chunks + 1)).astype(int) | ||
| l_iter = tqdm([slice(i0, i1) for i0, i1 in zip(wd_i[:-1], wd_i[1:])], disable=L <= 1 or not self.verbose, | ||
| desc='Calculate flow map', unit='wd') | ||
| map_func = get_starmap_func(n_cpu=n_cpu, verbose=wd_chunks + j_chunks > 2 and self.verbose, desc='Calculate flow map', | ||
| unit='wd', leave=0) | ||
| wt_x_ilk, wt_y_ilk, wt_h_ilk = [sim_res_data[k].ilk() for k in ['x', 'y', 'h']] | ||
| WS_eff_jlk, TI_eff_jlk = zip(*[self._get_flow_l( | ||
| {k: arg_funcs[k](l) for k in arg_funcs}, | ||
| l, | ||
| *[(v, v[:, l])[np.shape(v)[1] == L] for v in [wt_x_ilk, wt_y_ilk, wt_h_ilk]], | ||
| lw_j, wd[l], WD_il[:, l]) | ||
| for l in l_iter]) | ||
| WS_eff_jlk = np.concatenate(WS_eff_jlk, 1) | ||
| xyh_j_lst = list(zip(*[np.array_split(x_j, j_chunks), | ||
| np.array_split(y_j, j_chunks), | ||
| np.array_split(h_j, j_chunks)])) | ||
| l_iter = [({k: arg_funcs[k](l) for k in arg_funcs}, | ||
| *[(v, v[:, slice(l[0], l[-1] + 1)])[np.shape(v)[1] == L] for v in [wt_x_ilk, wt_y_ilk, wt_h_ilk]], | ||
| x_j_, y_j_, h_j_, wd[l], WD_il[:, l], | ||
| lw_j.WS_ilk[:, (l, [0])[lw_j.WS_ilk.shape[1] == 1]], | ||
| lw_j.TI_ilk[:, (l, [0])[lw_j.TI_ilk.shape[1] == 1]]) | ||
| for l in np.array_split(np.arange(L).astype(int), wd_chunks) | ||
| for x_j_, y_j_, h_j_ in xyh_j_lst] | ||
| WS_eff_jlk, TI_eff_jlk = zip(*map_func(self._get_flow_l, l_iter)) | ||
| WS_eff_jlk = np.concatenate([np.concatenate(WS_eff_jlk[i * j_chunks:(i + 1) * j_chunks], 0) | ||
| for i in range(wd_chunks)], 1) | ||
| if self.turbulenceModel: | ||
| TI_eff_jlk = np.concatenate(TI_eff_jlk, 1) | ||
| TI_eff_jlk = np.concatenate([np.concatenate(TI_eff_jlk[i * j_chunks:(i + 1) * j_chunks], 0) | ||
| for i in range(wd_chunks)], 1) | ||
| else: | ||
@@ -909,9 +923,13 @@ TI_eff_jlk = np.zeros_like(WS_eff_jlk) + lw_j.TI_ilk | ||
| ct_ilk = self.windTurbines.ct(ws=WS_eff_ilk, **wt_kwargs) | ||
| try: | ||
| if hasattr(self.windTurbines.powerCtFunction, 'ct_idle'): | ||
| ct_ilk_idle = np.ones_like(WS_ILK) * self.windTurbines.powerCtFunction.ct_idle | ||
| else: | ||
| ct_ilk_idle = self.windTurbines.ct(ws=0.1 * np.ones_like(WS_ILK), **wt_kwargs) | ||
| except BaseException: | ||
| ct_ilk_idle = 0 | ||
| if hasattr(self.windTurbines.powerCtFunction, 'ct_idle') and \ | ||
| self.windTurbines.powerCtFunction.ct_idle is not None: | ||
| ct_ilk_idle = np.ones_like(WS_ILK) * self.windTurbines.powerCtFunction.ct_idle | ||
| else: | ||
| def get_ct(ws): | ||
| return self.windTurbines.ct(ws=ws * np.ones_like(WS_ILK), **wt_kwargs) | ||
| ct_ilk_idle = np.min([get_ct(ws) for ws in np.arange(0, 26)], 0) | ||
| unstable_lk = np.zeros((L, K), dtype=bool) | ||
@@ -918,0 +936,0 @@ ioff = np.broadcast_to(ct_ilk, (I, L, K)) < -1 # index of off/idling turbines |
@@ -12,3 +12,3 @@ from abc import abstractmethod, ABC | ||
| import multiprocessing | ||
| from py_wake.utils.parallelization import get_pool_map, get_pool_starmap | ||
| from py_wake.utils.parallelization import get_pool_map, get_pool_starmap, get_map_func | ||
| from py_wake.utils.functions import arg2ilk | ||
@@ -292,10 +292,3 @@ from py_wake.utils.gradients import autograd | ||
| ws_i = np.linspace(0, len(ws) + 1, ws_chunks + 1).astype(int) | ||
| if n_cpu > 1: | ||
| map_func = get_pool_map(n_cpu) | ||
| else: | ||
| from tqdm import tqdm | ||
| def map_func(f, iter): | ||
| return tqdm(map(f, iter), total=len(iter), disable=not self.verbose) | ||
| if time is False: | ||
@@ -338,3 +331,3 @@ # (wd x ws) matrix | ||
| return map_func, arg_lst, wd_chunks, ws_chunks | ||
| return get_map_func(n_cpu, self.verbose), arg_lst, wd_chunks, ws_chunks | ||
@@ -721,3 +714,3 @@ def _aep_chunk_wrapper(self, aep_function, | ||
| def aep_map(self, grid=None, wd=None, ws=None, type=0, normalize_probabilities=False, n_cpu=1, wd_chunks=None): # @ReservedAssignment | ||
| def aep_map(self, grid=None, wd=None, ws=None, type=0, normalize_probabilities=False, memory_GB=1, n_cpu=1): # @ReservedAssignment | ||
| X, Y, x_j, y_j, h_j, plane = self._get_grid(grid) | ||
@@ -728,21 +721,3 @@ wd, ws = self._wd_ws(wd, ws) | ||
| setattr(sim_res, k, getattr(self, k)) | ||
| n_cpu = n_cpu or multiprocessing.cpu_count() | ||
| wd_chunks = np.minimum(wd_chunks or n_cpu, len(wd)) | ||
| if n_cpu != 1: | ||
| n_cpu = n_cpu or multiprocessing.cpu_count() | ||
| map = get_pool_starmap(n_cpu) # @ReservedAssignment | ||
| if len(wd) >= n_cpu: | ||
| # chunkification more efficient on wd than j | ||
| wd_i = np.linspace(0, len(wd), n_cpu + 1).astype(int) | ||
| args_lst = [[x_j, y_j, h_j, type, sim_res.sel(wd=wd[i0:i1])] for i0, i1 in zip(wd_i[:-1], wd_i[1:])] | ||
| aep_lst = map(self.windFarmModel._aep_map, args_lst) | ||
| aep_j = np.sum(aep_lst, 0) | ||
| else: | ||
| j_i = np.linspace(0, len(x_j), n_cpu + 1).astype(int) | ||
| args_lst = [[xyh_j[i0:i1] for xyh_j in [x_j, y_j, h_j]] + [type, sim_res] | ||
| for i0, i1 in zip(j_i[:-1], j_i[1:])] | ||
| aep_lst = map(self.windFarmModel._aep_map, args_lst) | ||
| aep_j = np.concatenate(aep_lst) | ||
| else: | ||
| aep_j = self.windFarmModel._aep_map(x_j, y_j, h_j, type, sim_res) | ||
| aep_j = self.windFarmModel._aep_map(x_j, y_j, h_j, type, sim_res, n_cpu, memory_GB) | ||
| if normalize_probabilities: | ||
@@ -762,3 +737,3 @@ lw_j = self.windFarmModel.site.local_wind(x=x_j, y=y_j, h=h_j, wd=wd, ws=ws) | ||
| def flow_map(self, grid=None, wd=None, ws=None, time=None, D_dst=0): | ||
| def flow_map(self, grid=None, wd=None, ws=None, time=None, D_dst=0, memory_GB=1, n_cpu=1): | ||
| """Return a FlowMap object with WS_eff and TI_eff of all grid points | ||
@@ -773,3 +748,3 @@ | ||
| The simulation result must include the requested wind directions. | ||
| If None, an weighted average of all wind directions from the simulation results will be computed. | ||
| If None, a flow map with only the first wind direction in the simulation results will be computed. | ||
| Note, computing a flow map with multiple wind directions may be slow | ||
@@ -783,3 +758,12 @@ ws : int, float, array_like or None | ||
| at which the deficits will be averaged | ||
| memory_GB : int or float, optional | ||
| If the additional memory needed to compute the flow map is assumed to exceed `memory_GB` GB using | ||
| simple models, then the flow map is split into a number of wind direction and/or point chunks to | ||
| reduce the memory consumption. | ||
| The default is 1 GB | ||
| n_cpu : int or None, otional | ||
| Number of CPUs used to compute the flow map. | ||
| If None, all available CPUs are used. | ||
| Default is 1. | ||
| Note, that for in many cases 1 CPU are the faster option | ||
| See Also | ||
@@ -790,6 +774,10 @@ -------- | ||
| X, Y, x_j, y_j, h_j, plane = self._get_grid(grid) | ||
| wd, ws = self._wd_ws(wd, ws) | ||
| if 'time' in self: | ||
| sim_res = self.sel(time=(time, slice(time))[time is None]) | ||
| else: | ||
| if wd is None: | ||
| wd = self.wd[[0]] | ||
| if ws is None: | ||
| ws = self.ws[[0]] | ||
| wd, ws = self._wd_ws(wd, ws) | ||
| sim_res = self.sel(wd=wd, ws=ws) | ||
@@ -799,3 +787,4 @@ for k in self.__slots__: | ||
| lw_j, WS_eff_jlk, TI_eff_jlk = self.windFarmModel._flow_map(x_j, y_j, h_j, sim_res, D_dst=D_dst) | ||
| lw_j, WS_eff_jlk, TI_eff_jlk = self.windFarmModel._flow_map( | ||
| x_j, y_j, h_j, sim_res, D_dst=D_dst, memory_GB=memory_GB, n_cpu=n_cpu) | ||
| return FlowMap(sim_res, X, Y, lw_j, WS_eff_jlk, TI_eff_jlk, plane=plane) | ||
@@ -802,0 +791,0 @@ |
@@ -8,4 +8,28 @@ from py_wake import np | ||
| from xarray.core.dataarray import DataArray | ||
| import matplotlib.pyplot as plt | ||
| from matplotlib.patches import Circle | ||
| # Create a qualitative color map for plotting the turbines. | ||
| # Play with the seed to change the order of the colors. | ||
| # Alternatively: | ||
| # - Select a metric from https://en.wikipedia.org/wiki/Color_difference, for example LAB. | ||
| # - Maximize distance between each color and the next. | ||
| # See https://matplotlib.org/stable/users/explain/colors/colormaps.html#qualitative | ||
| rng = np.random.default_rng(seed=99) | ||
| cmap = np.concatenate(( | ||
| np.array([[0.0, 0.0, 0.0]]), # Black is always first. | ||
| np.array(plt.get_cmap("Dark2").colors), # This is already perceptually different. | ||
| rng.permutation( | ||
| np.concatenate(( | ||
| np.array([[0.5, 0.5, 0.5]]), # grey | ||
| np.array(plt.get_cmap("tab20b").colors)[4:, :], # Skip the first colors because they are blue. | ||
| np.array(plt.get_cmap("tab20c").colors)[4:12, :]), # Keep orange and green. | ||
| axis=0), | ||
| axis=0)), | ||
| axis=0) | ||
| # Display the color map. | ||
| # from matplotlib.colors import ListedColormap | ||
| # ListedColormap(colors=cmap) | ||
| class WindTurbines(): | ||
@@ -148,3 +172,2 @@ """Set of multiple type wind turbines""" | ||
| """ | ||
| import matplotlib.pyplot as plt | ||
| if types is None: | ||
@@ -159,7 +182,6 @@ types = np.zeros_like(x).astype(int) | ||
| markers = np.array(list("213v^<>o48spP*hH+xXDd|_")) | ||
| colors = ['k', 'gray', 'r', 'g'] * 5 | ||
| from matplotlib.patches import Circle | ||
| assert len(x) == len(y) | ||
| # Yaw and tilt can be a scalar or wd-dependent vector, therefore we cannot use full_like. | ||
| yaw = np.zeros_like(x) + yaw | ||
@@ -171,4 +193,6 @@ tilt = np.zeros_like(x) + tilt | ||
| for i, (x_, y_, r, t, yaw_, tilt_) in enumerate(zip(x, y, R, types, yaw, tilt)): | ||
| # Take the color for the current turbine type. | ||
| color = cmap[t % cmap.shape[0], :] | ||
| if wd is None or len(np.atleast_1d(wd)) > 1: | ||
| circle = Circle((x_, y_), r, ec=colors[t], fc="None") | ||
| circle = Circle((x_, y_), r, ec=color, fc="None") | ||
| ax.add_artist(circle) | ||
@@ -179,9 +203,10 @@ ax.plot(x_, y_, 'None', ) | ||
| circle = Ellipse((x_, y_), 2 * r * np.sin(np.deg2rad(tilt_)), 2 * r, | ||
| angle=90 - wd_ + yaw_, ec=colors[t], fc="None") | ||
| angle=90 - wd_ + yaw_, ec=color, fc="None") | ||
| ax.add_artist(circle) | ||
| ax.plot(x_, y_, '.', color=colors[t]) | ||
| ax.plot(x_, y_, '.', color=color) | ||
| for t, m, c in zip(np.unique(types), markers, colors): | ||
| for t, m in zip(np.unique(types), markers): | ||
| color = cmap[t % cmap.shape[0], :] | ||
| # ax.plot(np.asarray(x)[types == t], np.asarray(y)[types == t], '%sk' % m, label=self._names[int(t)]) | ||
| ax.plot([], [], '2', color=colors[t], label=self._names[int(t)]) | ||
| ax.plot([], [], '2', color=color, label=self._names[int(t)]) | ||
@@ -208,3 +233,2 @@ for i, (x_, y_, r) in enumerate(zip(x, y, R)): | ||
| """ | ||
| import matplotlib.pyplot as plt | ||
| if z is None: | ||
@@ -258,3 +282,2 @@ z = np.zeros_like(y) | ||
| def plot_power_ct(self, ax=None, ws=np.linspace(0, 25, 1000), **wt_kwargs): | ||
| import matplotlib.pyplot as plt | ||
| if ax is None: | ||
@@ -406,3 +429,2 @@ ax = plt.gca().figure.axes[0] | ||
| import os.path | ||
| import matplotlib.pyplot as plt | ||
| from py_wake.examples.data import wtg_path | ||
@@ -409,0 +431,0 @@ |
+30
-28
@@ -9,7 +9,7 @@ docs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
| py_wake/superposition_models.py,sha256=mlZSy-T6YiAhdSgAu-reP1YECRsPpgHh8GDCfPAsZ6w,10124 | ||
| py_wake/version.py,sha256=OY-1DNhKffui4Swj0cq2tuFWkmx_rnd-2Lfa_jvuhjI,513 | ||
| py_wake/version.py,sha256=Vi-fvuY4jNLmkjfsZxZ_bieoAIk2n0J8Fd96j6hAUrI,706 | ||
| py_wake/deficit_models/__init__.py,sha256=w1S4F3FmAgtwqGO90fASYoqxOb6SsgjbasiD3V8_1uk,709 | ||
| py_wake/deficit_models/deficit_model.py,sha256=BQ8vJ-Nlw4CDWHdqIkNtbAc52OOwfEi4n6P0Vmg8bLg,10255 | ||
| py_wake/deficit_models/fuga.py,sha256=Jhi52MpvF7-KTk62dZfdLLUf4piCslwIBJTr7N17Hng,13863 | ||
| py_wake/deficit_models/gaussian.py,sha256=CZ06AQbCLumKiIlbhlbrvV0MhmC24Q826kR81yNiLdc,36094 | ||
| py_wake/deficit_models/gaussian.py,sha256=_ntryBrucuo9EMSLnyJH3dt9mM9SnB0DxP9wzH_w7Zo,36119 | ||
| py_wake/deficit_models/gcl.py,sha256=o4b9NRe9rSUJ8PmD3OOD5gOpYY6LBY2OXQfrhh7EBns,8988 | ||
@@ -249,3 +249,3 @@ py_wake/deficit_models/hybridinduction.py,sha256=dtfO5Ms0-t2X16XsigiKovKKDnVHG2ntRe8Jmv6CahY,4864 | ||
| py_wake/examples/data/iea22mw/__init__.py,sha256=gPlxM_vbhAU2JCls9szxXXgWGZZBSFHqTfx8eD1XREo,127 | ||
| py_wake/examples/data/iea22mw/iea_22_rwt.py,sha256=whJtpu5I4wj4BkqLKG1WhELzpjRnNyMaiQVBq_j-iYI,1918 | ||
| py_wake/examples/data/iea22mw/iea_22_rwt.py,sha256=PYj4tdkr1WWHcizB9GC0Ne3DRl4MaTFXHOHJLlSq0d0,1980 | ||
| py_wake/examples/data/iea34_130rwt/__init__.py,sha256=fpJDB-Zu8PENaHqRHzqXnimryNwfrz5aom_gOylYb7Y,76 | ||
@@ -289,3 +289,3 @@ py_wake/examples/data/iea34_130rwt/_iea34_130rwt.py,sha256=sEn7pxZY_tU3Zq-Mp8-xV7rWmVizGZArD_3pIKyib24,11310 | ||
| py_wake/site/jit_streamline_distance.py,sha256=a2FVowV8cjUb-U18riZ4k2NskGPP0KSyqL4w621A2X8,4925 | ||
| py_wake/site/shear.py,sha256=B5zJZ72mZXEAJE2uVt1n22lGNAMBqz_7gOlzeDoIIUE,3708 | ||
| py_wake/site/shear.py,sha256=OGU2eQCuZ7H3hAjAbATK9ZXqIWBFjDazp9dmKumDnSw,4213 | ||
| py_wake/site/wasp_grid_site.py,sha256=81zqtUIwCAUHaZdgnNvzazBjEIPYk22Gr6r7IQzmsZk,10190 | ||
@@ -296,6 +296,6 @@ py_wake/site/xrsite.py,sha256=-Kr2LMx0dpKI-ke4z3hbRyv-GWulLntjkSU-nY1LWIA,19887 | ||
| py_wake/tests/notebook.py,sha256=21RVNXcqRCy6b3GoRcKxR5E0IGV2d9U6BaqqOKZ8f8Y,6804 | ||
| py_wake/tests/test_flow_map.py,sha256=eAfFrYUjYsSgVgyE92CgRVWAWcVXn1uExB41lbUx_gU,18766 | ||
| py_wake/tests/test_flow_map.py,sha256=8lQzTxsQp4xUKkdRGkmdS80wYbN5QcwsYpOSJ0z_vhM,20290 | ||
| py_wake/tests/test_main.py,sha256=aouzNZBMsqrRitG9HfEOCPx8Fe6IH0mM_eIyeQ_TqnM,1853 | ||
| py_wake/tests/test_notebooks.py,sha256=805s9rBBr1dWEtapvK2BwrfWUPSWWiA48Dz-cwciObI,1956 | ||
| py_wake/tests/test_superposition_models.py,sha256=y3PL7o5amDJEMYLRd8hbYvEYnFVxWAPxLdoBGMkAAKE,8683 | ||
| py_wake/tests/test_superposition_models.py,sha256=dxcgeB_LXn1USv_4QNRuyjL83Cy0qhV1yPdJN6enRj4,8759 | ||
| py_wake/tests/test_deficit_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
@@ -305,7 +305,7 @@ py_wake/tests/test_deficit_models/test_BastankhahGaussian.py,sha256=rXMkNTHirHBAKWhRtWCOpZqzX0KX5d2w1ACwAHlEXKo,1069 | ||
| py_wake/tests/test_deficit_models/test_blockage_models.py,sha256=guS3PX7YdNfI1Po4JzEhGu6BT6ODSxEBR6fBIMUorko,11856 | ||
| py_wake/tests/test_deficit_models/test_deficit_models.py,sha256=_0k0qy2sZ-0xtRe8L4ubTBxXVOEOdSxtQHJIZaDZKC8,33855 | ||
| py_wake/tests/test_deficit_models/test_fuga.py,sha256=f1s3ow3-MalL-cc56tXdpHpkzOjEBEaRxhfyL7KFb9c,24709 | ||
| py_wake/tests/test_deficit_models/test_deficit_models.py,sha256=vwwj3lSs_4kWCl55-qVs0-3bwdmUT7ZXICpVAuZSfRU,33990 | ||
| py_wake/tests/test_deficit_models/test_fuga.py,sha256=zuWx-oAThjYGdubhX9c-dR8-wsnBJMTi7uA6R17_kos,24769 | ||
| py_wake/tests/test_deficit_models/test_gcl.py,sha256=i2mIAoNUnGswJ8xXVjjHVw9Imgzhs6thfI8zkgLCt04,1189 | ||
| py_wake/tests/test_deficit_models/test_noj.py,sha256=qJVv3q3Lp_QILFn-6xdslWevvR4Dmnx0AWj39XCIdXw,5495 | ||
| py_wake/tests/test_deficit_models/test_rans_lut.py,sha256=BUeKMEs3A0cPBpwxA2UFSHT01M5rYPFr4HKuFCILtAk,16073 | ||
| py_wake/tests/test_deficit_models/test_rans_lut.py,sha256=rfvT0178DfxA52wlscSDL56tJapBVI_BJu1CnWGkCQA,17738 | ||
| py_wake/tests/test_deficit_models/test_selfsimilarity.py,sha256=mI5DUstBbaC36JQ-eCOMrE88jubvZjb3tp_DUQQzU2Y,4446 | ||
@@ -326,3 +326,3 @@ py_wake/tests/test_deflection_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
| py_wake/tests/test_ground_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
| py_wake/tests/test_ground_models/test_mirror.py,sha256=J398XITtpQK3SBlb5McKdp65vr8fGZKuV7B_4LfEz1I,12316 | ||
| py_wake/tests/test_ground_models/test_mirror.py,sha256=9iGzqUiAxA_LR8QpRUQEnmRUurP4HQFLItLlUWrMRxo,12407 | ||
| py_wake/tests/test_input_modifier_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
@@ -342,3 +342,3 @@ py_wake/tests/test_input_modifier_models/test_input_modifier.py,sha256=di-von3D1MClAO8uOBYjqi6esOTkxLIJKyb1G6BEYbk,5473 | ||
| py_wake/tests/test_sites/test_iea37_readers.py,sha256=nEoXISd3M7USxJe4PFBI2wUlLTjiL6NEnXMvFWHzwxo,1427 | ||
| py_wake/tests/test_sites/test_shear_models.py,sha256=9ACZyKdrE8V-DAdn1cZa7f1drO1L15q-SBCldAPw-qY,2700 | ||
| py_wake/tests/test_sites/test_shear_models.py,sha256=g4zg1QCvl2WQY6f10BiRlBAnyJyaaQRVpeiLnkNT4SU,4053 | ||
| py_wake/tests/test_sites/test_site.py,sha256=NZ_gm8LvHwY0PYVeJbXjtUONjSGaoNCZQ8Q8Z938rrU,11267 | ||
@@ -353,3 +353,3 @@ py_wake/tests/test_sites/test_wasp_grid_site.py,sha256=8Swf470l8PdI9FRs-yF27S4pP7X08kXRFTZCK1YYNlU,15686 | ||
| py_wake/tests/test_utils/test_elliptic.py,sha256=hxyfSIJcdmNgvFxMOqmAV383sO__-0B0sgAKeBBnTNA,1749 | ||
| py_wake/tests/test_utils/test_fuga_utils.py,sha256=OfCoWhIMu29DPR2DUstbyKPjGfCd4Cx6OOJ8RH-TQVM,3165 | ||
| py_wake/tests/test_utils/test_fuga_utils.py,sha256=6YYCrngD4bA9XJdIQqMxMTQ-GmwOybrKSll1IANLB6A,2260 | ||
| py_wake/tests/test_utils/test_gpu_utils.py,sha256=vTVMTLrb9KKr7bHr-AbZZwytV9fhqABq0cn9K4-pt1I,1292 | ||
@@ -359,5 +359,6 @@ py_wake/tests/test_utils/test_gradient_utils.py,sha256=phZtdTCg64KgjTvyK4n_HHssPJCYAlJUUHUc9GRWBlU,15810 | ||
| py_wake/tests/test_utils/test_layouts.py,sha256=9soiopXExIdV1jxSnoG6te_54qbxfRGEd3AdpoGmpNM,1199 | ||
| py_wake/tests/test_utils/test_model_gradients.py,sha256=9m_qcK-12huEfGXXhVjgNhoE9qFD4P-ZmpvBROWAS0k,12506 | ||
| py_wake/tests/test_utils/test_model_gradients.py,sha256=Rni1JhZWB_gOmK-aBNFR7bi8q5VlqKX3ftgA6Nbgmc0,12587 | ||
| py_wake/tests/test_utils/test_model_utils.py,sha256=219lb_0_74xshlw2lKdEgTyPGSRXe8F-uplifqpRdnM,3847 | ||
| py_wake/tests/test_utils/test_numpy.py,sha256=z2MLCUPg01IhsR3tO9H8rubsP9VzR1RBLt3elvsUHCw,7612 | ||
| py_wake/tests/test_utils/test_most.py,sha256=WG2Ng8T1mcmIAsP23OnQeGCoVQ9D8NEX-2fmhH4tMd8,1311 | ||
| py_wake/tests/test_utils/test_numpy.py,sha256=zcjmLyL19eQEW0uxRz81LueCceGm8zG0-wH6VxEIj5c,7544 | ||
| py_wake/tests/test_utils/test_parallelization.py,sha256=VxxcU58DrwxNyXkl2R00ipf0TUwVJg4Qj7rz8JjEjFo,434 | ||
@@ -373,3 +374,3 @@ py_wake/tests/test_utils/test_plotting.py,sha256=tCmEUdvZinzcFMiBGRth8MbFKuVSxQFDuPNh762GBps,286 | ||
| py_wake/tests/test_wind_farm_models/test_all2all.py,sha256=KCTignc2zVwIPcoJD2gU0fHqdwnppKmjDY-BsfKIa-M,1556 | ||
| py_wake/tests/test_wind_farm_models/test_all2allIterative.py,sha256=efxyDoAP2U5BhVz0Om6D7ixyWvBISHgzkfVIC_OY9t8,5755 | ||
| py_wake/tests/test_wind_farm_models/test_all2allIterative.py,sha256=P1e_7rMbCxeiSL8J-scZHux4UdPpWRec79yGayn5bok,5567 | ||
| py_wake/tests/test_wind_farm_models/test_enginering_wind_farm_model.py,sha256=IvbRInNWqnC8FVk8A-IwmDiYOZ3oGNR4Z8drlRHHpnk,28773 | ||
@@ -381,3 +382,3 @@ py_wake/tests/test_wind_farm_models/test_memory_usage.py,sha256=nDGlWHDNVAUrZZD9BOOC-AluRWKuHCLiljp3m8ZofJs,2016 | ||
| py_wake/tests/test_wind_farm_models/test_simulation_result.py,sha256=VoffAnO6EwA4J_4-AbgoCgrU5Lbj-3f_HbC-YeBVav8,1496 | ||
| py_wake/tests/test_wind_farm_models/test_wind_farm_model.py,sha256=YkJeOdfgbE6FxYFMkkAJvTpfWatUej1w0taKoOLRQdc,14408 | ||
| py_wake/tests/test_wind_farm_models/test_wind_farm_model.py,sha256=hsv11zdQD4X5p1aB09vOiJKJx1ZxlqqzZ1QnqBDoUB8,14464 | ||
| py_wake/tests/test_windturbines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
@@ -398,3 +399,3 @@ py_wake/tests/test_windturbines/test_generic_wind_turbines.py,sha256=nIACFm-5iqM_bsIZxFpifGFp9S3zoF4CTwInPTmhz7I,5502 | ||
| py_wake/utils/floris_wrapper.py,sha256=aEaDMo9kLtYyPGKkpwVjAV10iSC3GvhSkbr2rM7ndvE,1401 | ||
| py_wake/utils/fuga_utils.py,sha256=WRAo0wcR1nuUAGtRv7cZAlQE3sAhUFQ1zYRhWxZx22s,15586 | ||
| py_wake/utils/fuga_utils.py,sha256=2V49V9jjm0H7JC0ph1-0sgVcvCBiLGNjpZPxyRIkWfg,14955 | ||
| py_wake/utils/functions.py,sha256=YiQTF-JBX00Oi8kvbYMeP8zGiCi90qbz8Zhc-N6lrEs,1966 | ||
@@ -408,8 +409,9 @@ py_wake/utils/generic_power_ct_curves.py,sha256=kY8z7a4qZ8fBxYBYS5ULC8j0wlE_LHxPxLPH5LDQO_Y,3957 | ||
| py_wake/utils/model_utils.py,sha256=JYC1xYuJ5U720Tc7_jB_iDFvYaRZ_WlN-Py0JPOho_M,15389 | ||
| py_wake/utils/most.py,sha256=9DEZ5C06qdttfGdfUCyaFCGt-YT8xPnQ3URIuHpbcdE,1208 | ||
| py_wake/utils/notebook_extensions.py,sha256=E0UOiQ1AAMaIbnnzsyj-gGv8oRWD8wAvHsj2BN10LXU,704 | ||
| py_wake/utils/numpy_utils.py,sha256=I9URsvF0ALXOFwdlkTK-mQLul0d-5wLjSWuEeAmE5ZU,3192 | ||
| py_wake/utils/parallelization.py,sha256=5xl2TozyilPJJvNObd8hLTWALa0oYl_d2C1d1261ECQ,1321 | ||
| py_wake/utils/parallelization.py,sha256=7eCsS-2A26N8P8dmdkX2d7eW4jy0jQoFOcPxA24DbcU,2082 | ||
| py_wake/utils/plotting.py,sha256=zXharIIWIwl-E0Xh2JP3qAnYEEAKGJidQcldhRd0dRo,568 | ||
| py_wake/utils/profiling.py,sha256=GuE0UcQaZ3KsVnklLHSDFpCc0jQ4fixh0VREwA3aHQ0,4618 | ||
| py_wake/utils/rans_lut_utils.py,sha256=QRKW8yVmFmvqftbTDgJlkyc0r3WXQRayI3u4qSIeSvA,11129 | ||
| py_wake/utils/rans_lut_utils.py,sha256=nQut0o1agTcP-vAumQ9DjITtO5oJUD0NB4S0nVhApoQ,11381 | ||
| py_wake/utils/streamline.py,sha256=NSiA7acgkeh8iUepqalvSt7XhWS7U4POvoZq2LZCaIc,2172 | ||
@@ -422,10 +424,10 @@ py_wake/utils/tensorflow_surrogate_utils.py,sha256=QdIPqxoYiuXFvieHQyP-TE6gS8syXbxoUZ1liCBFil0,7198 | ||
| py_wake/validation/lillgrund.py,sha256=WI0pWg9mvAvWqWKGL-YKbX8AoQTdb-8AglguYI6JiE8,4135 | ||
| py_wake/validation/validation.py,sha256=V__7l8nOJhTB0gqc8aVQkzBEQilOBsgc3jMLAH1TKVM,20522 | ||
| py_wake/validation/validation.py,sha256=jJBBlNSHlb49s4MI0THkMV3nhYVEUOSbr8afr3rX7Ho,20578 | ||
| py_wake/validation/validation_lib.py,sha256=C_Rf-51ZjMlGdlDFha8JF4t0ByJY9zFrPtmDQU0t1Uo,27559 | ||
| py_wake/wind_farm_models/__init__.py,sha256=cl0nC9vqhXgpRuaCFkQpDET2Yyzbwnd5Kv2wgZHUI6E,137 | ||
| py_wake/wind_farm_models/engineering_models.py,sha256=rIWn0rbF7iWtygbTy4ksJYyieokZw6RQO_g4uaVKgjk,59553 | ||
| py_wake/wind_farm_models/engineering_models.py,sha256=V9Ebkm2uMz0mo4iyzu_ELT4pEMn7qs-uRsJi-q_esbI,60738 | ||
| py_wake/wind_farm_models/minimalistic_wind_farm_model.py,sha256=geyeFlxI71PPs19pDSWDaQgiSyxaJqNTcuXI1he93_0,11124 | ||
| py_wake/wind_farm_models/wind_farm_model.py,sha256=uKfD3vVELU9e2Ys96M-u-xJIbk9WqJKBKCquY9GaG9Q,42251 | ||
| py_wake/wind_farm_models/wind_farm_model.py,sha256=7_Bcwlca0Q-EmoFcsM8vFtlQhV-dEcByTtY5LLUlsA4,41812 | ||
| py_wake/wind_turbines/__init__.py,sha256=w1D9rLfxk7m_UdrqbVVokWwAikxIzeRh6Wb9zVT2Mhs,145 | ||
| py_wake/wind_turbines/_wind_turbines.py,sha256=8KpGPdAg7u3rgoYbj3TKq1illG_g9e7BzThHnb1eT7o,17950 | ||
| py_wake/wind_turbines/_wind_turbines.py,sha256=IAIaERtPtRR6QwhHweKC1Vqi8IYqjBV2ebmaby2Mqqo,19010 | ||
| py_wake/wind_turbines/generic_wind_turbines.py,sha256=SiV-hganUn9TO8ItM8ZPVuJ0BqKIuig5-vA6miSGJeY,9456 | ||
@@ -435,6 +437,6 @@ py_wake/wind_turbines/power_ct_functions.py,sha256=CjWKehvop9kMPclU54pFp_hRG7_3bqCx16cJlz5QduU,22663 | ||
| py_wake/wind_turbines/wind_turbines_deprecated.py,sha256=HpNmBR8CJL4-8JBaygDI0t086qfw5bR2DOQI8Ox4AZ4,6250 | ||
| py_wake-2.6.12.dist-info/licenses/LICENSE,sha256=XE2CGPqQgzSXqIajXpAVYJ5SRNmaWOIeMePK6MocsuY,1084 | ||
| py_wake-2.6.12.dist-info/METADATA,sha256=HNp-tDeJKjgOZA7a3IBOUS1L3BOkSf6FDdsYcncg9I0,3596 | ||
| py_wake-2.6.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91 | ||
| py_wake-2.6.12.dist-info/top_level.txt,sha256=GsaXU4YwyMkZZ6dkb4h0FMc5RaLIT2Qns_YoScKoXdk,20 | ||
| py_wake-2.6.12.dist-info/RECORD,, | ||
| py_wake-2.6.13.dist-info/licenses/LICENSE,sha256=XE2CGPqQgzSXqIajXpAVYJ5SRNmaWOIeMePK6MocsuY,1084 | ||
| py_wake-2.6.13.dist-info/METADATA,sha256=fpTWS7ZgV4KrfCqxIDfNfV-qTxPc295iQmBlADMgfpg,3596 | ||
| py_wake-2.6.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91 | ||
| py_wake-2.6.13.dist-info/top_level.txt,sha256=GsaXU4YwyMkZZ6dkb4h0FMc5RaLIT2Qns_YoScKoXdk,20 | ||
| py_wake-2.6.13.dist-info/RECORD,, |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.