py-wake
Advanced tools
| from py_wake.utils.streamline import VectorField3D | ||
| import numpy as np | ||
| from scipy.interpolate._rgi import RegularGridInterpolator as RGI | ||
| from py_wake.site.xrsite import XRSite | ||
| from py_wake.site.streamline_distance import StreamlineDistance | ||
| def wrf2pywake(ds, TI=None): | ||
| if 'west_east' in ds: | ||
| ds = ds.rename(west_east='x', south_north='y', height='h') | ||
| if 'TI' not in ds: | ||
| if TI is None: | ||
| TI = np.sqrt(2 / 3 * ds['TKE']) / ds['WS'] | ||
| ds['TI'] = TI | ||
| return ds[['WD', 'WS', 'TI']].transpose('x', 'y', 'h', 'time') | ||
| class WRFVectorField(VectorField3D): | ||
| def __init__(self, ds): | ||
| ds = wrf2pywake(ds) | ||
| self.ds = ds | ||
| grid = [ds.x.values, ds.y.values, ds.h.values, np.arange(len(ds.time))] | ||
| theta = np.deg2rad(270 - ds.WD.values) | ||
| Vx, Vy = np.cos(theta) * ds.WS.values, np.sin(theta) * ds.WS.values | ||
| values = np.moveaxis([Vx, Vy], 0, -1) | ||
| self.mean_values = np.mean(values, (1, 2, 3)) | ||
| self.interp = RGI(grid, values, bounds_error=False) | ||
| def __call__(self, wd, time, x, y, h): | ||
| time = np.broadcast_to(time, x.shape) | ||
| Vx, Vy = np.transpose(self.interp(np.array([x, y, h, time]).T)) | ||
| return np.array([Vx, Vy, Vx * 0]).T | ||
| class WRFSite(XRSite): | ||
| def __init__(self, ds, TI=None, streamlines=True): | ||
| if streamlines: | ||
| distance = StreamlineDistance(WRFVectorField(ds)) | ||
| else: | ||
| distance = None | ||
| ds = wrf2pywake(ds, TI) | ||
| ds['P'] = 1 | ||
| ds['datetime'] = ds.time | ||
| ds['time'] = np.arange(len(ds.time)) | ||
| ds['ws'] = [0] | ||
| XRSite.__init__(self, ds, distance=distance) |
| from py_wake.examples.data.hornsrev1 import Hornsrev1WRFSite, V80 | ||
| from py_wake.tests import npt | ||
| import numpy as np | ||
| import matplotlib.pyplot as plt | ||
| import pytest | ||
| from py_wake.wind_farm_models.engineering_models import PropagateDownwind, All2AllIterative | ||
| from py_wake.deficit_models.noj import NOJLocalDeficit | ||
| from py_wake.flow_map import XYGrid | ||
| @pytest.mark.parametrize('streamlines,ref', [(False, [548.22095, 26.745916]), | ||
| (True, [586.881971, -182.716646])]) | ||
| def test_Hornsrev1WRFSite(streamlines, ref): | ||
| site = Hornsrev1WRFSite(time_slice=slice(f"2020-04-27 12:00", f"2020-04-27"), streamlines=streamlines) | ||
| wts = V80() | ||
| x, y = site.initial_position[:4].T | ||
| h = wts.hub_height() | ||
| t = 10 | ||
| p = site.ds.interp(x=x[0], y=y[0], h=70).isel(time=t) | ||
| npt.assert_array_almost_equal([p.WS.item(), p.WD.item(), p.TI.item()], [5.566621, 348.0761, 0.04780247], 4) | ||
| t = 9 | ||
| dw, cw = [v[0, 1, 0, 0] for v in site.distance(x[:2], y[:2], x[:2] * 0 + h, wd_l=[0], time=[t])[:2]] | ||
| if 0: | ||
| X, Y = np.meshgrid(site.ds.x.values, site.ds.y.values) | ||
| theta = np.deg2rad(270 - site.ds.WD) | ||
| WS = site.ds.WS | ||
| Vx, Vy = np.cos(theta) * WS, np.sin(theta) * WS | ||
| site.ds.WS.isel(time=t).interp(h=h).plot.contourf(cmap='Blues_r', x='x') | ||
| wts.plot(x[:2], y[:2], wt_number=0) | ||
| plt.quiver(X, Y, Vx.isel(time=t).interp(h=h).values.T, Vy.isel(time=t).interp(h=h).values.T) | ||
| if streamlines: | ||
| streamlines = site.distance.vectorField.stream_lines(np.array([0]), time=[t], | ||
| start_points=np.array([x[:1], y[:1], [h]]).T, | ||
| dw_stop=np.array([4000])) | ||
| plt.plot(streamlines[0][:, 0], streamlines[0][:, 1]) | ||
| plt.plot([x[0], x[0] + cw], [y[0], y[0] - dw]) | ||
| plt.xlim([x[0] - 4000, x[0] + 4000]) | ||
| plt.ylim([y[0] - 4000, y[0] + 4000]) | ||
| plt.show() | ||
| npt.assert_array_almost_equal([dw, cw], ref) | ||
| for cls in [PropagateDownwind, All2AllIterative]: | ||
| wfm = cls(site, wts, NOJLocalDeficit(use_effective_ti=False)) | ||
| sim_res = wfm(x, y, wd=[0, 10, 20], ws=[10, 10, 10], time=True) | ||
| fm = sim_res.flow_map(XYGrid(resolution=20)) | ||
| npt.assert_array_equal(fm.wd, [0, 10, 20]) | ||
| fm = sim_res.flow_map(XYGrid(resolution=20), time=1) | ||
| npt.assert_array_equal(fm.wd, [10]) |
| from py_wake.utils.maps import dk_coast | ||
| import matplotlib.pyplot as plt | ||
| from py_wake.tests import npt | ||
| import pytest | ||
| @pytest.mark.parametrize('crs,bounds', [(None, [7., 54., 14., 58.]), | ||
| ('EPSG:25832', [381782.654552, 5983532.157506, 827373.774988, 6432168.470282])]) | ||
| def test_dk_coast(crs, bounds): | ||
| dk = dk_coast(crs) | ||
| npt.assert_array_almost_equal(dk.total_bounds, bounds) | ||
| dk.plot() | ||
| if 0: | ||
| plt.show() | ||
| plt.close('all') |
| import os | ||
| import geopandas as gpd | ||
| from py_wake.tests import ptf | ||
| import zipfile | ||
| def dk_coast(crs=None): | ||
| f = ptf('maps/dk_coast.zip', known_hash='c6b90f62fddec4134762d41777dbfcc50122d8d1a0d2fa0e49a0601382aaecff') | ||
| with zipfile.ZipFile(f, 'r') as zip_ref: | ||
| zip_ref.extractall(os.path.dirname(f)) | ||
| f = os.path.join(os.path.dirname(f), 'dk_coast/dk_coast.shp') | ||
| dk = gpd.read_file(f) | ||
| if crs: | ||
| dk = dk.to_crs(crs) | ||
| return dk | ||
| def main(): | ||
| if __name__ == '__main__': | ||
| import matplotlib.pyplot as plt | ||
| dk = dk_coast() | ||
| plt.show() | ||
| main() |
+3
-1
| Metadata-Version: 2.4 | ||
| Name: py_wake | ||
| Version: 2.6.14 | ||
| Version: 2.6.15 | ||
| Summary: Open source static wake modeling framework from DTU | ||
@@ -30,2 +30,4 @@ Author: DTU Wind Energy | ||
| Requires-Dist: pooch | ||
| Requires-Dist: windkit | ||
| Requires-Dist: geopandas | ||
| Provides-Extra: test | ||
@@ -32,0 +34,0 @@ Requires-Dist: pytest; extra == "test" |
@@ -0,3 +1,9 @@ | ||
| import warnings | ||
| import xarray as xr | ||
| from py_wake import np | ||
| from py_wake.site._site import UniformWeibullSite | ||
| from py_wake.site.wrf import WRFSite | ||
| from py_wake.tests import ptf | ||
| from py_wake.wind_turbines import WindTurbine | ||
@@ -108,2 +114,21 @@ from py_wake.wind_turbines.power_ct_functions import PowerCtTabular | ||
| class Hornsrev1WRFSite(WRFSite): | ||
| """WRF Site covering Hornsrev1 for April 2020""" | ||
| def __init__(self, time_slice=slice("2020-04-01 00:00", "2020-04-30"), streamlines=True): | ||
| wrf_ds = xr.load_dataset(ptf('wrf/Hornsrev1_2020_04.nc', | ||
| known_hash='65f7f774f6b67bb89870b7978a601b945aaf9bb17894351e6e607fdbcdbc8973')) | ||
| WRFSite.__init__(self, wrf_ds.sel(time=time_slice), streamlines=streamlines) | ||
| try: | ||
| import windkit as wk | ||
| xy_crs = wk.spatial.create_dataset(wt_x, wt_y, 70, "EPSG:25832") | ||
| crs = wk.spatial.get_crs(wrf_ds) | ||
| xy_crs = wk.spatial.reproject(xy_crs, crs) | ||
| wt_x_crs, wt_y_crs = xy_crs.west_east.values, xy_crs.south_north.values | ||
| self.initial_position = np.array([wt_x_crs, wt_y_crs]).T | ||
| except BaseException: | ||
| warnings.warn('windkit not available. Could not reproject initial position to current crs') | ||
| def main(): | ||
@@ -110,0 +135,0 @@ wt = V80() |
@@ -192,3 +192,4 @@ from py_wake import np | ||
| # c = data.isel(h=0).plot(levels=levels, cmap=cmap, ax=ax, add_colorbar=plot_colorbar) | ||
| c = ax.contourf(self.X / n, self.Y / n, data.squeeze().values, levels=levels, cmap=cmap) | ||
| c = ax.contourf(self.X / n, self.Y / n, data.squeeze().values, levels=levels, cmap=cmap, | ||
| ) | ||
| if plot_colorbar: | ||
@@ -195,0 +196,0 @@ plt.colorbar(c, label=clabel, ax=ax, cax=cax) |
@@ -7,8 +7,5 @@ import warnings | ||
| from py_wake import np | ||
| from py_wake.deficit_models.noj import NOJ | ||
| from py_wake.examples.data.hornsrev1 import V80 | ||
| from py_wake.examples.data.ParqueFicticio._parque_ficticio import ParqueFicticioSite | ||
| from py_wake.flow_map import XYGrid | ||
| from py_wake.site.distance import StraightDistance | ||
| from py_wake.utils.model_utils import DeprecatedModel | ||
| from py_wake.utils.streamline import VectorField3D | ||
@@ -34,3 +31,3 @@ | ||
| def __call__(self, src_x_ilk, src_y_ilk, src_h_ilk, wd_l=None, WD_ilk=None, time=None, dst_xyh_jlk=None): | ||
| def __call__(self, src_x_ilk, src_y_ilk, src_h_ilk, time, wd_l=None, WD_ilk=None, dst_xyh_jlk=None): | ||
| (src_x_ilk, src_y_ilk, src_h_ilk), (dst_x_jlk, dst_y_jlk, dst_h_jlk) = self.get_pos( | ||
@@ -40,6 +37,5 @@ src_x_ilk, src_y_ilk, src_h_ilk, wd_l, WD_ilk, dst_xyh_jlk) | ||
| start_points_m = np.moveaxis([v[:, :, 0].flatten() for v in [src_x_ilk, src_y_ilk, src_h_ilk]], 0, -1) | ||
| dw_ijlk, hcw_ijlk, dh_ijlk = StraightDistance.__call__(self, src_x_ilk, src_y_ilk, src_h_ilk, wd_l=wd_l, | ||
| dst_xyh_jlk=dst_xyh_jlk) | ||
| I, J, L, K = dw_ijlk.shape | ||
| src_z_ilk = self.site.elevation(src_x_ilk, src_y_ilk) | ||
@@ -52,7 +48,10 @@ dst_z_jlk = self.site.elevation(dst_x_jlk, dst_y_jlk) | ||
| dz_ijlk = np.broadcast_to(dz_ijlk, dw_ijlk.shape) + 0. | ||
| I, J, L, K = dw_ijlk.shape | ||
| dw_mj, hcw_mj, dh_mj, dz_mj = [np.moveaxis(v, 1, 2).reshape(I * L, J) | ||
| for v in [dw_ijlk, hcw_ijlk, dh_ijlk, dz_ijlk]] | ||
| start_points_m = np.moveaxis([np.broadcast_to(v[:, :, 0], (I, L)).flatten() | ||
| for v in [src_x_ilk, src_y_ilk, src_h_ilk]], 0, -1) | ||
| wd_m = np.tile(wd_l, I) | ||
| if time is not False: | ||
| time = np.tile(time, I) | ||
@@ -85,2 +84,4 @@ stream_lines = self.vectorField.stream_lines(wd_m, time=time, start_points=start_points_m, dw_stop=dw_mj.max(1), | ||
| if __name__ == '__main__': | ||
| from py_wake.deficit_models.noj import NOJ | ||
| from py_wake.examples.data.hornsrev1 import V80 | ||
@@ -87,0 +88,0 @@ wt = V80() |
@@ -203,3 +203,3 @@ from py_wake import np | ||
| else: | ||
| ds_tmp = xr.merge([ds_tmp, xr.Dataset({var_name: da})]) | ||
| ds_tmp = xr.merge([ds_tmp, xr.Dataset({var_name: da})], join='outer', compat='no_conflicts') | ||
@@ -206,0 +206,0 @@ if first: |
@@ -9,2 +9,3 @@ from pathlib import Path | ||
| import xarray as xr | ||
| import shutil | ||
| npt = numpy.testing | ||
@@ -27,1 +28,5 @@ WindFarmModel.verbose = False | ||
| return ret | ||
| def clear_ptf(): | ||
| shutil.rmtree(Path.home() / 'PyWakeTestFiles') |
@@ -1,26 +0,34 @@ | ||
| from py_wake import np | ||
| from py_wake.examples.data.hornsrev1 import HornsrevV80, V80 | ||
| import contextlib | ||
| import io | ||
| import warnings | ||
| from pathlib import Path | ||
| import matplotlib.pyplot as plt | ||
| import pytest | ||
| from numpy import newaxis as na | ||
| from scipy.optimize._minpack_py import curve_fit | ||
| from py_wake import Fuga, np | ||
| from py_wake.deficit_models.fuga import ( | ||
| FugaBlockage, | ||
| FugaDeficit, | ||
| FugaMultiLUTDeficit, | ||
| FugaYawDeficit, | ||
| ) | ||
| from py_wake.examples.data import hornsrev1 | ||
| from py_wake.examples.data.hornsrev1 import V80, HornsrevV80 | ||
| from py_wake.flow_map import HorizontalGrid, XYGrid, XZGrid | ||
| from py_wake.site._site import UniformSite | ||
| from py_wake.tests import npt | ||
| from py_wake.tests.test_files import tfp | ||
| from py_wake import Fuga | ||
| from py_wake.examples.data import hornsrev1 | ||
| import matplotlib.pyplot as plt | ||
| from py_wake.deficit_models.fuga import FugaBlockage, FugaDeficit, FugaYawDeficit, \ | ||
| FugaMultiLUTDeficit | ||
| from py_wake.flow_map import HorizontalGrid, XYGrid, XZGrid | ||
| from py_wake.utils import fuga_utils | ||
| from py_wake.utils.fuga_utils import FugaUtils | ||
| from py_wake.utils.grid_interpolator import GridInterpolator | ||
| from py_wake.wind_farm_models.engineering_models import PropagateDownwind, All2AllIterative | ||
| import pytest | ||
| from pathlib import Path | ||
| from py_wake.wind_turbines.power_ct_functions import PowerCtTabular, CubePowerSimpleCt | ||
| from py_wake.utils.profiling import timeit | ||
| from py_wake.wind_farm_models.engineering_models import ( | ||
| All2AllIterative, | ||
| PropagateDownwind, | ||
| ) | ||
| from py_wake.wind_turbines._wind_turbines import WindTurbine, WindTurbines | ||
| from py_wake.utils.profiling import timeit | ||
| import warnings | ||
| from py_wake.utils import fuga_utils | ||
| from py_wake.utils.fuga_utils import FugaUtils | ||
| from numpy import newaxis as na | ||
| from scipy.optimize._minpack_py import curve_fit | ||
| import contextlib | ||
| import io | ||
| from py_wake.wind_turbines.power_ct_functions import CubePowerSimpleCt, PowerCtTabular | ||
@@ -471,13 +479,13 @@ | ||
| fm = sim_res.flow_map(XYGrid(x=400, y=np.linspace(-310, 310), h=70)) | ||
| for t in sim_res.time: | ||
| da = sim_res.sel(time=t) | ||
| ti = ['z0=0.00001000_z69.2-93.4', 'z0=0.01703452_z68.5-92.5'][da.TI.item() >= .12] | ||
| # print(fuga_utils.z0(da.TI.item(), 70, da.zeta0.item())) | ||
| deficit = FugaDeficit( | ||
| tfp + | ||
| f"fuga/2MW/multilut/LUTs_Zeta0={da.zeta0.item():4.2e}_16_32_D80_zhub70_zi{da.zi.item():d}_{ti}_UL_nx128_ny128_dx20.0_dy5.0.nc", | ||
| smooth2zero_x=None, smooth2zero_y=None) | ||
| wfm_ref = All2AllIterative(UniformSite(), V80(), wake_deficitModel=deficit, blockage_deficitModel=deficit) | ||
| fm_ref = wfm_ref([0], [0], wd=270, ws=10,).flow_map(XYGrid(x=400, y=np.linspace(-310, 310), h=70)) | ||
| fm = sim_res.flow_map(XYGrid(x=400, y=np.linspace(-310, 310), h=70)) | ||
| for t in sim_res.time: | ||
| da = sim_res.sel(time=t) | ||
| ti = ['z0=0.00001000_z69.2-93.4', 'z0=0.01703452_z68.5-92.5'][da.TI.item() >= .12] | ||
| # print(fuga_utils.z0(da.TI.item(), 70, da.zeta0.item())) | ||
| deficit = FugaDeficit( | ||
| tfp + | ||
| f"fuga/2MW/multilut/LUTs_Zeta0={da.zeta0.item():4.2e}_16_32_D80_zhub70_zi{da.zi.item():d}_{ti}_UL_nx128_ny128_dx20.0_dy5.0.nc", | ||
| smooth2zero_x=None, smooth2zero_y=None) | ||
| wfm_ref = All2AllIterative(UniformSite(), V80(), wake_deficitModel=deficit, blockage_deficitModel=deficit) | ||
| fm_ref = wfm_ref([0], [0], wd=270, ws=10,).flow_map(XYGrid(x=400, y=np.linspace(-310, 310), h=70)) | ||
@@ -484,0 +492,0 @@ |
@@ -0,18 +1,19 @@ | ||
| import matplotlib.pyplot as plt | ||
| import xarray as xr | ||
| from py_wake import np | ||
| from py_wake.wind_turbines import WindTurbine | ||
| from py_wake.deficit_models.rans_lut import RANSLUT, RANSLUTDemoDeficit | ||
| from py_wake.examples.data import hornsrev1 | ||
| from py_wake.examples.data.hornsrev1 import HornsrevV80 | ||
| from py_wake.flow_map import HorizontalGrid | ||
| from py_wake.site._site import UniformSite | ||
| from py_wake.tests import npt, ptf | ||
| import matplotlib.pyplot as plt | ||
| from py_wake.deficit_models.rans_lut import RANSLUT, RANSLUTDemoDeficit | ||
| from py_wake.flow_map import HorizontalGrid | ||
| from py_wake.turbulence_models.rans_lut_turb import RANSLUTDemoTurbulence | ||
| from py_wake.utils.grid_interpolator import GridInterpolator | ||
| from py_wake.wind_farm_models.engineering_models import All2AllIterative | ||
| from py_wake.utils.profiling import timeit | ||
| import xarray as xr | ||
| from py_wake.utils.rans_lut_utils import ADControl, get_Ellipsys_equivalent_output | ||
| from py_wake.turbulence_models.rans_lut_turb import RANSLUTDemoTurbulence | ||
| from py_wake.wind_farm_models.engineering_models import All2AllIterative | ||
| from py_wake.wind_turbines import WindTurbine | ||
| from py_wake.wind_turbines._wind_turbines import WindTurbines | ||
| from py_wake.wind_turbines.power_ct_functions import PowerCtTabular | ||
| from py_wake.examples.data import hornsrev1 | ||
| from py_wake.wind_turbines._wind_turbines import WindTurbines | ||
@@ -280,3 +281,3 @@ | ||
| hornsrev1.power_curve[:, 0], hornsrev1.power_curve[:, 1], 'w', hornsrev1.ct_curve[:, 1])) | ||
| wts = WindTurbine.from_WindTurbines([v80, v120]) | ||
| wts = WindTurbines.from_WindTurbine_lst([v80, v120]) | ||
@@ -283,0 +284,0 @@ wfm = RANSLUT([ds, lut_V120], UniformSite(ti=0.075 * 0.8), wts) |
@@ -324,3 +324,4 @@ import warnings | ||
| sim_res = wfm(x, y, wd=wd, ws=10) | ||
| dw = site.distance(x, y, x * 0 + wt.hub_height(), wd_l=wd, WD_ilk=np.repeat(wd[na, na], len(x), 0))[0][:, :, 0, 0] | ||
| dw = site.distance(x, y, x * 0 + wt.hub_height(), | ||
| wd_l=wd, WD_ilk=np.repeat(wd[na, na], len(x), 0), time=False)[0][:, :, 0, 0] | ||
| # streamline downwind distance (positive numbers, upper triangle) cannot be shorter than | ||
@@ -334,5 +335,6 @@ # straight line distances in opposite direction (negative numbers, lower triangle) | ||
| y=np.linspace(site.ds.y[0].item(), site.ds.y[-1].item(), 500))) | ||
| x, y = x[6:], y[6:] | ||
| stream_lines = vf3d.stream_lines(wd=np.full(x.shape, wd), start_points=np.array([x, y, np.full(x.shape, 70)]).T, | ||
| dw_stop=y - 6504700) | ||
| if 0: | ||
| dw_stop=np.full(x.shape, 2000)) | ||
| if 1: | ||
| fm.plot_wake_map() | ||
@@ -361,3 +363,3 @@ for sl in stream_lines: | ||
| dw = site.distance(wt_x, wt_y, wt_x * 0 + wt.hub_height(), wd_l=wd, | ||
| WD_ilk=np.repeat(wd[na, na], len(wt_x), 0))[0][:, :, 0, 0] | ||
| WD_ilk=np.repeat(wd[na, na], len(wt_x), 0), time=False)[0][:, :, 0, 0] | ||
| # streamline downwind distance (positive numbers, upper triangle) cannot be shorter than | ||
@@ -364,0 +366,0 @@ # straight line distances in opposite direction (negative numbers, lower triangle) |
@@ -0,6 +1,9 @@ | ||
| from pathlib import Path | ||
| import pytest | ||
| from py_wake import np | ||
| from py_wake.tests import clear_ptf, ptf | ||
| from py_wake.utils.check_input import check_input | ||
| from py_wake import np | ||
| from pathlib import Path | ||
| from py_wake.tests import ptf | ||
| import time | ||
@@ -24,3 +27,11 @@ | ||
| def test_ptf(): | ||
| assert Path(ptf('test.txt', | ||
| 'ecd71870d1963316a97e3ac3408c9835ad8cf0f3c1bc703527c30265534f75ae')).read_text() == 'test123' | ||
| f = Path(ptf('test.txt', 'ecd71870d1963316a97e3ac3408c9835ad8cf0f3c1bc703527c30265534f75ae')) | ||
| assert f.read_text() == 'test123' | ||
| for _ in range(3): | ||
| try: | ||
| clear_ptf() | ||
| break | ||
| except Exception: | ||
| time.sleep(0.5) | ||
| assert f.exists() is False | ||
| assert f.parent.exists() is False |
@@ -21,7 +21,3 @@ import os | ||
| from py_wake.wind_farm_models.external_wind_farm_models import ( | ||
| ExternalWFMWindFarm, | ||
| ExternalWindFarm, | ||
| ExternalXRAbsWindFarm, | ||
| ExternalXRRelWindFarm, | ||
| ) | ||
| ExternalWFMWindFarm, ExternalXRAbsWindFarm, ExternalXRRelWindFarm) | ||
| from py_wake.wind_turbines import WindTurbines | ||
@@ -28,0 +24,0 @@ |
@@ -1,13 +0,15 @@ | ||
| import time | ||
| import ctypes | ||
| import functools | ||
| import sys | ||
| from py_wake import np | ||
| import gc | ||
| import linecache | ||
| import os | ||
| import psutil | ||
| import ctypes | ||
| import linecache | ||
| import sys | ||
| import time | ||
| import warnings | ||
| import psutil | ||
| from py_wake import np | ||
| def timeit(func, min_time=0, min_runs=1, verbose=False, line_profile=False, profile_funcs=[]): | ||
@@ -18,5 +20,5 @@ @functools.wraps(func) | ||
| lp_wrapper = line_timeit(func, profile_funcs) | ||
| t = time.time() | ||
| t = time.perf_counter() | ||
| res, lp = lp_wrapper(*args, **kwargs) | ||
| t = time.time() - t | ||
| t = time.perf_counter() - t | ||
| if verbose: | ||
@@ -27,8 +29,8 @@ lp.print_stats() | ||
| t_lst = [] | ||
| time_start = time.time() | ||
| time_start = time.perf_counter() | ||
| for i in range(100000): | ||
| t0 = time.time_ns() | ||
| t0 = time.perf_counter_ns() | ||
| res = func(*args, **kwargs) | ||
| t_lst.append((time.time_ns() - t0) * 1e-9) | ||
| if (time.time() - time_start) > min_time and len(t_lst) >= min_runs: | ||
| t_lst.append((time.perf_counter_ns() - t0) * 1e-9) | ||
| if (time.perf_counter() - time_start) > min_time and len(t_lst) >= min_runs: | ||
| break | ||
@@ -35,0 +37,0 @@ |
@@ -6,2 +6,3 @@ import xarray as xr | ||
| from py_wake.utils.grid_interpolator import GridInterpolator | ||
| from scipy.interpolate import RegularGridInterpolator as RGI | ||
@@ -13,4 +14,5 @@ | ||
| self.da = da | ||
| self.interpolator = GridInterpolator( | ||
| [da.wd.values, da.x.values, da.y.values, da.h.values], da.values, method='linear') | ||
| # self.interpolator = GridInterpolator( | ||
| # [da.wd.values, da.x.values, da.y.values, da.h.values], da.values, method='linear', bounds='limit') | ||
| self.interpolator = RGI([da.wd.values, da.x.values, da.y.values, da.h.values], da.values, bounds_error=False) | ||
| vy = property(lambda self: self.da.sel(v_xyz=0)) | ||
@@ -24,3 +26,3 @@ vx = property(lambda self: self.da.sel(v_xyz=1)) | ||
| def __call__(self, wd, time, x, y, h): | ||
| return self.interpolator(np.array([np.atleast_1d(v) for v in [wd, x, y, h]]).T, bounds='limit') | ||
| return self.interpolator(np.array([np.atleast_1d(v) for v in [wd, x, y, h]]).T) | ||
@@ -37,19 +39,16 @@ @staticmethod | ||
| def stream_lines(self, wd, start_points, dw_stop, time=None, step_size=20): | ||
| def stream_lines(self, wd, start_points, dw_stop, time=False, step_size=20): | ||
| # print(np.shape(wd), np.shape(start_points), time) | ||
| if time is None: | ||
| wd = np.full(len(start_points), wd) | ||
| time = wd * 0 | ||
| # else: | ||
| # if len(start_points) == 1: | ||
| # # 1 start point, multiple wd/time | ||
| # start_points = np.broadcast_to(start_points, (len(wd), 3)) | ||
| # elif len(time) == 1: | ||
| # time = wd * 0 + time | ||
| stream_lines = [start_points] | ||
| m = np.arange(len(wd)) | ||
| co, si = np.cos(np.deg2rad(270 - wd)), np.sin(np.deg2rad(270 - wd)) | ||
| for _ in range(1000): | ||
| t = time | ||
| for i in range(int(np.max(dw_stop) * 2 / step_size)): | ||
| p = stream_lines[-1].copy() | ||
| v = self(wd[m], time[m], p[m, 0], p[m, 1], p[m, 2]) | ||
| if time is not False: | ||
| t = time[m] | ||
| v = self(wd[m], t, p[m, 0], p[m, 1], p[m, 2]) | ||
| mnan = np.any(np.isnan(v), 1) | ||
| if np.any(mnan): | ||
| v[mnan] = np.array([co[m][mnan], si[m][mnan], co[m][mnan] * 0]).T | ||
| v = v / (np.sqrt(np.sum(v**2, -1)) / step_size)[:, na] # normalize vector distance to step_size | ||
@@ -56,0 +55,0 @@ p[m] += v |
@@ -31,5 +31,5 @@ # file generated by setuptools-scm | ||
| __version__ = version = '2.6.14' | ||
| __version_tuple__ = version_tuple = (2, 6, 14) | ||
| __version__ = version = '2.6.15' | ||
| __version_tuple__ = version_tuple = (2, 6, 15) | ||
| __commit_id__ = commit_id = None |
@@ -323,3 +323,3 @@ from abc import abstractmethod | ||
| dw_ijlk, hcw_ijlk, dh_ijlk = self.site.distance(wt_x_ilk, wt_y_ilk, wt_h_ilk, wd_l=wd, WD_ilk=WD_ilk, | ||
| time=model_kwargs.get('time', None), dst_xyh_jlk=(x_jl, y_jl, h_jl)) | ||
| time=model_kwargs.get('time', False), dst_xyh_jlk=(x_jl, y_jl, h_jl)) | ||
@@ -442,4 +442,4 @@ if self.wec != 1: | ||
| x_jl[js, ls], y_jl[js, ls], np.broadcast_to(h_jl, x_jl.shape)[js, ls], 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]]) | ||
| lw_j.WS_ilk[(j, [0])[lw_j.WS_ilk.shape[0] == 1]][:, (l, [0])[lw_j.WS_ilk.shape[1] == 1]], | ||
| lw_j.TI_ilk[(j, [0])[lw_j.TI_ilk.shape[0] == 1]][:, (l, [0])[lw_j.TI_ilk.shape[1] == 1]]) | ||
@@ -743,3 +743,3 @@ l_iter = [get_jl_args(j, l) | ||
| *[get_pos(kwargs[k + '_ilk'], i_wt_l, i_wd_l)[na] for k in 'xyh'], wd_l=wd, WD_ilk=WD_mk[m][na], | ||
| dst_xyh_jlk=dst_xyh_jlk) | ||
| time=kwargs.get('time', False), dst_xyh_jlk=dst_xyh_jlk) | ||
@@ -943,3 +943,3 @@ for inputModidifierModel in self.inputModifierModels: | ||
| self, wd, dw_order_indices_ld, WD_ilk=WD_ilk, WS_ilk=WS_ilk, TI_ilk=TI_ilk, | ||
| WS_eff_ilk=WS_eff_ilk, TI_eff_ilk=TI_eff_ilk, D_i=D_i, I=I, L=L, K=K, **kwargs)[0] | ||
| WS_eff_ilk=WS_eff_ilk, TI_eff_ilk=TI_eff_ilk, D_i=D_i, I=I, L=L, K=K, time=time, **kwargs)[0] | ||
| self.blockage_deficitModel = blockage_deficitModel | ||
@@ -959,3 +959,4 @@ elif np.all(WS_eff_ilk == 0): | ||
| dst_xyh_jlk = [kwargs[k + '_ilk'] for k in 'xyh'] | ||
| dw_iilk, hcw_iilk, dh_iilk = self.site.distance(*[kwargs[k + '_ilk'] for k in 'xyh'], wd_l=wd, WD_ilk=WD_ilk) | ||
| dw_iilk, hcw_iilk, dh_iilk = self.site.distance(*[kwargs[k + '_ilk'] for k in 'xyh'], | ||
| wd_l=wd, WD_ilk=WD_ilk, time=time) | ||
| kwargs['WD_ilk'] = WD_ilk | ||
@@ -962,0 +963,0 @@ |
@@ -75,3 +75,3 @@ from abc import ABC, abstractmethod | ||
| def __call__(self, i, l, deficit_jlk, WS_jlk, WS_eff_ilk, | ||
| WD_ilk, dst_xyh_jlk, IJLK, dw_ijlk, hcw_ijlk, dh_ijlk, **_): | ||
| WD_ilk, dst_xyh_jlk, IJLK, dw_ijlk, hcw_ijlk, dh_ijlk, time=False, **_): | ||
| I, J, L, K = IJLK | ||
@@ -86,3 +86,3 @@ WD_l = np.round(WD_ilk[np.minimum(i, len(WD_ilk) - 1), :, 0]) | ||
| wd_lst = WD_l[m_lst] | ||
| sim_res = self.wfm(**{**self.wfm_kwargs, 'ws': ws_lst, 'wd': np.sort(np.unique(wd_lst))}) | ||
| sim_res = self.wfm(**{**self.wfm_kwargs, 'ws': ws_lst, 'wd': np.sort(np.unique(wd_lst)), 'time': time}) | ||
| from py_wake.site.streamline_distance import StreamlineDistance | ||
@@ -207,13 +207,12 @@ if isinstance(self.wfm.site.distance, StreamlineDistance): | ||
| wf_h = windFarmModel.windTurbines.hub_height(type) | ||
| deficit = [] | ||
| for wd in tqdm(sim_res.wd.values, disable=1): | ||
| theta = np.deg2rad(270 - wd) | ||
| co, si = np.cos(theta), np.sin(theta) | ||
| x_j = co * dw - hcw * si + wf_x | ||
| y_j = si * dw + hcw * co + wf_y | ||
| h_j = dh + wf_h | ||
| lw_j, WS_eff_jlk, TI_eff_jlk = windFarmModel._flow_map(x_j[:, na], y_j[:, na], h_j[:, na], sim_res.localWind, | ||
| wd, sim_res.ws, sim_res) | ||
| deficit.append(lw_j.WS_ilk - WS_eff_jlk) | ||
| deficit = np.moveaxis(deficit, 0, 1).reshape(X.shape + (len(sim_res.wd), len(sim_res.ws))) | ||
| theta = np.deg2rad(270 - sim_res.wd.values) | ||
| co, si = np.cos(theta), np.sin(theta) | ||
| x_jl = co[na] * dw[:, na] - hcw[:, na] * si[na] + wf_x | ||
| y_jl = si[na] * dw[:, na] + hcw[:, na] * co[na] + wf_y | ||
| h_jl = dh[:, na] + wf_h | ||
| lw_j, WS_eff_jlk, TI_eff_jlk = windFarmModel._flow_map(x_jl, y_jl, h_jl, sim_res.localWind, | ||
| sim_res.wd.values, sim_res.ws, sim_res) | ||
| deficit = (lw_j.WS_ilk - WS_eff_jlk).reshape(X.shape + (len(sim_res.wd), len(sim_res.ws))) | ||
| ds = xr.Dataset({'deficit': (['x', 'y', 'h', 'wd', 'ws'], deficit)}, | ||
@@ -220,0 +219,0 @@ coords=dict(x=grid_xyh[0], y=grid_xyh[1], h=grid_xyh[2], wd=sim_res.wd, ws=sim_res.ws)) |
+24
-20
@@ -7,5 +7,5 @@ docs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
| py_wake/__init__.py,sha256=-0bNwPpZWQXG-_zE_7hFRoJeG0SRBuDeGM9n5aFWgS0,1188 | ||
| py_wake/flow_map.py,sha256=zUFPSUQZmxW5LwFTOiBdaL9fPRJxt87UGGemc_PGl3o,22411 | ||
| py_wake/flow_map.py,sha256=pZCV-mbPDtVLuvdGejKJhUnR52VorJ7fobP10Oj7ZL4,22441 | ||
| py_wake/superposition_models.py,sha256=mlZSy-T6YiAhdSgAu-reP1YECRsPpgHh8GDCfPAsZ6w,10124 | ||
| py_wake/version.py,sha256=7zrBk63M80mRuOeY6dfWyf-ZQjC6DN9bM1NV1oUDz0Q,706 | ||
| py_wake/version.py,sha256=Y_kUiwIfdfJcl4d1EVlpBvcQ85D9f1ATuvVihYhIFyg,706 | ||
| py_wake/deficit_models/__init__.py,sha256=w1S4F3FmAgtwqGO90fASYoqxOb6SsgjbasiD3V8_1uk,709 | ||
@@ -39,3 +39,3 @@ py_wake/deficit_models/deficit_model.py,sha256=iLb9wUO8wDeYAEBAoAlS2W4Q4B16ZSO0L4DhVq3NxYQ,10280 | ||
| py_wake/examples/data/__init__.py,sha256=2aH-lJ5vWthT6dhoSyMlepji2ouqkM1sv3vx8fXC0N4,105 | ||
| py_wake/examples/data/hornsrev1.py,sha256=9g-pY49bVywA8786PHMen_gXfD5f9BfxqMPDGv1JHek,5402 | ||
| py_wake/examples/data/hornsrev1.py,sha256=Sn4Rvk-aIn23-QCq7I7tb--tIKJnrDRGOwx1VyAsH1s,6468 | ||
| py_wake/examples/data/lillgrund.py,sha256=lMsrmj7zQLXY-nfk7NGmW7ZsmhmMdXLAm0Il6NugwwE,4418 | ||
@@ -290,6 +290,7 @@ py_wake/examples/data/time_series.npz,sha256=FObvNeaHVznq0BHqiE7dTlp2S1I-CCaysljcpLh5fAI,765098 | ||
| py_wake/site/shear.py,sha256=OGU2eQCuZ7H3hAjAbATK9ZXqIWBFjDazp9dmKumDnSw,4213 | ||
| py_wake/site/streamline_distance.py,sha256=Qbjv2GCrPzxFlAp6ev5UhQGPfq2CVyFDzcK4iAHWkP0,4434 | ||
| py_wake/site/wasp_grid_site.py,sha256=81zqtUIwCAUHaZdgnNvzazBjEIPYk22Gr6r7IQzmsZk,10190 | ||
| py_wake/site/streamline_distance.py,sha256=01NdwM__ITY0w4kWavUx1arKxCvtc42cEteugQhN7mo,4518 | ||
| py_wake/site/wasp_grid_site.py,sha256=d-vonrkXMuVVgbq9OG0ri3XHYekdDfvfjdndkigCOrQ,10227 | ||
| py_wake/site/wrf.py,sha256=l2ziX34vcdxf2xgH3GiGxCdslgJldR8ZUd7BoZqxxEY,1653 | ||
| py_wake/site/xrsite.py,sha256=-Kr2LMx0dpKI-ke4z3hbRyv-GWulLntjkSU-nY1LWIA,19887 | ||
| py_wake/tests/__init__.py,sha256=HTCM3UcCGSo3Fibes8XFPV5mI3KzDsafM888VrqS29I,917 | ||
| py_wake/tests/__init__.py,sha256=-YOzxrKhc4yGKHFLkjCX7YHO-8Km_E65UCtlKNs3Z1Y,1001 | ||
| py_wake/tests/check_speed.py,sha256=8zPwap754HSH3Pns_CqBYUK6pwlmNvGVX2xC5u5ZBk8,2530 | ||
@@ -306,6 +307,6 @@ py_wake/tests/notebook.py,sha256=21RVNXcqRCy6b3GoRcKxR5E0IGV2d9U6BaqqOKZ8f8Y,6804 | ||
| py_wake/tests/test_deficit_models/test_deficit_models.py,sha256=vIe5H_cX0rZ-V1bD3I4FWgnaeR1qy6NGc-uCefA9qhI,34083 | ||
| py_wake/tests/test_deficit_models/test_fuga.py,sha256=zuWx-oAThjYGdubhX9c-dR8-wsnBJMTi7uA6R17_kos,24769 | ||
| py_wake/tests/test_deficit_models/test_fuga.py,sha256=kFa_D4mt5P7NpESPOAE8f3KBaWq8zFFTyQfqqmhZNiA,24824 | ||
| 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=jA8h7Fp4euRvjQNrfnT-gqLGofZNwjQElKBuJnbcIpE,17130 | ||
| py_wake/tests/test_deficit_models/test_rans_lut.py,sha256=gpskfpoK6HBpW-8dFB5dHgD5NKtrZle_2q8ftx8fmlM,17135 | ||
| py_wake/tests/test_deficit_models/test_selfsimilarity.py,sha256=mI5DUstBbaC36JQ-eCOMrE88jubvZjb3tp_DUQQzU2Y,4446 | ||
@@ -339,3 +340,3 @@ py_wake/tests/test_deflection_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
| py_wake/tests/test_sites/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
| py_wake/tests/test_sites/test_distances.py,sha256=VKox97PB3HmHNH0MO9IbVLiniolY2ffwqz9pNrGiu6M,16338 | ||
| py_wake/tests/test_sites/test_distances.py,sha256=fsDoPw7gFBu4w7Rze0wvO15XwWsb0ylm0uyoRyrseGY,16420 | ||
| py_wake/tests/test_sites/test_iea37_readers.py,sha256=nEoXISd3M7USxJe4PFBI2wUlLTjiL6NEnXMvFWHzwxo,1427 | ||
@@ -345,2 +346,3 @@ py_wake/tests/test_sites/test_shear_models.py,sha256=g4zg1QCvl2WQY6f10BiRlBAnyJyaaQRVpeiLnkNT4SU,4053 | ||
| py_wake/tests/test_sites/test_wasp_grid_site.py,sha256=miNHoOVFt31YqM0Auo97GkAfQ86eyUvc_xkoVO86xEA,15662 | ||
| py_wake/tests/test_sites/test_wrf.py,sha256=5tKl0MCaaAqkinj5Cw06d45NZ9kLJPbMzMbGVU9jb74,2460 | ||
| py_wake/tests/test_sites/test_xrsite.py,sha256=3lASkg3Cdv-MQwrXZRuGqQDGONy6pzRdLOurQTneKGI,31239 | ||
@@ -351,3 +353,3 @@ py_wake/tests/test_turbulence_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
| py_wake/tests/test_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
| py_wake/tests/test_utils/test_check_input.py,sha256=PP38AIp7bEH4vIhSpsz_4Nqn6msLvNWjMMXkR17vzuU,911 | ||
| py_wake/tests/test_utils/test_check_input.py,sha256=cgevOjDcCie0UhijMQIJjef6vcyTjXlwFJ6e5_ic0nc,1127 | ||
| py_wake/tests/test_utils/test_elliptic.py,sha256=hxyfSIJcdmNgvFxMOqmAV383sO__-0B0sgAKeBBnTNA,1749 | ||
@@ -359,2 +361,3 @@ py_wake/tests/test_utils/test_fuga_utils.py,sha256=6YYCrngD4bA9XJdIQqMxMTQ-GmwOybrKSll1IANLB6A,2260 | ||
| py_wake/tests/test_utils/test_layouts.py,sha256=9soiopXExIdV1jxSnoG6te_54qbxfRGEd3AdpoGmpNM,1199 | ||
| py_wake/tests/test_utils/test_maps.py,sha256=GPmATBxFtH-y6u6uZNFNbrrXNobKLz4tsiACly7hO8c,486 | ||
| py_wake/tests/test_utils/test_model_gradients.py,sha256=JHZ-uZfNDW-O8sNTssBmE-EJR_XDSAan1OmCtaSROhE,12638 | ||
@@ -376,3 +379,3 @@ py_wake/tests/test_utils/test_model_utils.py,sha256=219lb_0_74xshlw2lKdEgTyPGSRXe8F-uplifqpRdnM,3847 | ||
| py_wake/tests/test_wind_farm_models/test_enginering_wind_farm_model.py,sha256=IvbRInNWqnC8FVk8A-IwmDiYOZ3oGNR4Z8drlRHHpnk,28773 | ||
| py_wake/tests/test_wind_farm_models/test_external_windfarms.py,sha256=MszAdqFAhnQyxbIXABMc-qgGmZ6y_vsL-XMDleiiKVU,12489 | ||
| py_wake/tests/test_wind_farm_models/test_external_windfarms.py,sha256=A6MHjEZiDIgTRoXOkWvjC6CbyqlJAUa_QlfPcAUSFu4,12457 | ||
| py_wake/tests/test_wind_farm_models/test_memory_usage.py,sha256=nDGlWHDNVAUrZZD9BOOC-AluRWKuHCLiljp3m8ZofJs,2016 | ||
@@ -407,2 +410,3 @@ py_wake/tests/test_wind_farm_models/test_minimalistic_model.py,sha256=Nmu7eNldVD_m_G7bmsOf8eUGkYf_bF5kUhNwFWF9fj8,1566 | ||
| py_wake/utils/layouts.py,sha256=YHV1FwZJECBjTqqYIi8ipVIOefXYoWS7AarK7ND048M,998 | ||
| py_wake/utils/maps.py,sha256=cvz1j14Is_EdsXX4wkautCXm_OcDaSwDk4a6JJdhGs4,593 | ||
| py_wake/utils/model_utils.py,sha256=CkdZ38hwCkmyfTO5x6iwAgrVi3o0hOohDVZ213ti_Uw,15350 | ||
@@ -414,5 +418,5 @@ py_wake/utils/most.py,sha256=9DEZ5C06qdttfGdfUCyaFCGt-YT8xPnQ3URIuHpbcdE,1208 | ||
| py_wake/utils/plotting.py,sha256=zXharIIWIwl-E0Xh2JP3qAnYEEAKGJidQcldhRd0dRo,568 | ||
| py_wake/utils/profiling.py,sha256=GuE0UcQaZ3KsVnklLHSDFpCc0jQ4fixh0VREwA3aHQ0,4618 | ||
| py_wake/utils/profiling.py,sha256=g6aDNtZg_7lcxUg4WdAawGMysaoZW87iPyTWwiPvWdA,4668 | ||
| py_wake/utils/rans_lut_utils.py,sha256=-zs25tCdg2heaoCjyEDdk0vSDTImdhjtTpbDH_YEClI,12423 | ||
| py_wake/utils/streamline.py,sha256=hFIvkHsdUPLzySvQYdpX6DEUMaz5NayQBEg2fuppPh4,2574 | ||
| py_wake/utils/streamline.py,sha256=VjpEESETjxvYQwv11--FtL0Z9oX4EG87qyLYpss3Krc,2657 | ||
| py_wake/utils/tensorflow_surrogate_utils.py,sha256=QdIPqxoYiuXFvieHQyP-TE6gS8syXbxoUZ1liCBFil0,7198 | ||
@@ -427,4 +431,4 @@ py_wake/utils/weibull.py,sha256=cD1SIyXHEn17IQueZnsy9-upo2oZivVCpYOWka-_DsE,1262 | ||
| py_wake/wind_farm_models/__init__.py,sha256=cl0nC9vqhXgpRuaCFkQpDET2Yyzbwnd5Kv2wgZHUI6E,137 | ||
| py_wake/wind_farm_models/engineering_models.py,sha256=heyGqJroRPO_BjRaMf1QeEyu-kpiUkxntQTw4r5VfeA,63601 | ||
| py_wake/wind_farm_models/external_wind_farm_models.py,sha256=8Qjkzf9w9RFSVr7AHEE3wPtgiwlsZue4SGlBhb1w32k,12649 | ||
| py_wake/wind_farm_models/engineering_models.py,sha256=6Ab-eDX3_ZIeHAmJ_qD8OtlWVWo5V75tvp6rPKu6O7I,63786 | ||
| py_wake/wind_farm_models/external_wind_farm_models.py,sha256=QRSwdq45J4hwmYANBCv87HFGAho04_gkTWY9rUUUazM,12587 | ||
| py_wake/wind_farm_models/minimalistic_wind_farm_model.py,sha256=9BepPjAo_WDMcG4feUQo7YDY2WSFJOpNMmzgT0yNBn4,11160 | ||
@@ -438,6 +442,6 @@ py_wake/wind_farm_models/wind_farm_model.py,sha256=QvYmeqAVz2QyrjH21VEt1T52lJS2NQcTq3cW-W1qUFQ,42814 | ||
| py_wake/wind_turbines/wind_turbines_deprecated.py,sha256=HpNmBR8CJL4-8JBaygDI0t086qfw5bR2DOQI8Ox4AZ4,6250 | ||
| py_wake-2.6.14.dist-info/licenses/LICENSE,sha256=XE2CGPqQgzSXqIajXpAVYJ5SRNmaWOIeMePK6MocsuY,1084 | ||
| py_wake-2.6.14.dist-info/METADATA,sha256=GTsCfUqg3V5gNXNjdrnN3JYWPDYHOun_fqN0ZCqDdj0,3596 | ||
| py_wake-2.6.14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91 | ||
| py_wake-2.6.14.dist-info/top_level.txt,sha256=GsaXU4YwyMkZZ6dkb4h0FMc5RaLIT2Qns_YoScKoXdk,20 | ||
| py_wake-2.6.14.dist-info/RECORD,, | ||
| py_wake-2.6.15.dist-info/licenses/LICENSE,sha256=XE2CGPqQgzSXqIajXpAVYJ5SRNmaWOIeMePK6MocsuY,1084 | ||
| py_wake-2.6.15.dist-info/METADATA,sha256=SSQCWVa8eKVPv3uF5TFb3P6jgVBLU_g6yIjM3bgWEoA,3644 | ||
| py_wake-2.6.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91 | ||
| py_wake-2.6.15.dist-info/top_level.txt,sha256=GsaXU4YwyMkZZ6dkb4h0FMc5RaLIT2Qns_YoScKoXdk,20 | ||
| py_wake-2.6.15.dist-info/RECORD,, |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.