foxes 1.2.4__py3-none-any.whl → 1.2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of foxes might be problematic. Click here for more details.

@@ -200,14 +200,14 @@ class MultiHeightStates(States):
200
200
  if not isinstance(self.data_source, pd.DataFrame):
201
201
  self._data_source = get_input_path(self.data_source)
202
202
  if not self.data_source.is_file():
203
- if verbosity:
203
+ if verbosity > 0:
204
204
  print(
205
205
  f"States '{self.name}': Reading static data '{self.data_source}' from context '{STATES}'"
206
206
  )
207
207
  self._data_source = algo.dbook.get_file_path(
208
208
  STATES, self.data_source.name, check_raw=False
209
209
  )
210
- if verbosity:
210
+ if verbosity > 0:
211
211
  print(f"Path: {self.data_source}")
212
212
  elif verbosity:
213
213
  print(f"States '{self.name}': Reading file {self.data_source}")
@@ -627,14 +627,14 @@ class MultiHeightNCStates(MultiHeightStates):
627
627
  if not isinstance(self.data_source, Dataset):
628
628
  self._data_source = get_input_path(self.data_source)
629
629
  if not self.data_source.is_file():
630
- if verbosity:
630
+ if verbosity > 0:
631
631
  print(
632
632
  f"States '{self.name}': Reading static data '{self.data_source}' from context '{STATES}'"
633
633
  )
634
634
  self._data_source = algo.dbook.get_file_path(
635
635
  STATES, self.data_source.name, check_raw=False
636
636
  )
637
- if verbosity:
637
+ if verbosity > 0:
638
638
  print(f"Path: {self.data_source}")
639
639
  elif verbosity:
640
640
  print(f"States '{self.name}': Reading file {self.data_source}")
@@ -217,14 +217,14 @@ class StatesTable(States):
217
217
  else:
218
218
  self._data_source = get_input_path(self.data_source)
219
219
  if not self.data_source.is_file():
220
- if verbosity:
220
+ if verbosity > 0:
221
221
  print(
222
222
  f"States '{self.name}': Reading static data '{self.data_source}' from context '{STATES}'"
223
223
  )
224
224
  self._data_source = algo.dbook.get_file_path(
225
225
  STATES, self.data_source.name, check_raw=False
226
226
  )
227
- if verbosity:
227
+ if verbosity > 0:
228
228
  print(f"Path: {self.data_source}")
229
229
  elif verbosity:
230
230
  print(f"States '{self.name}': Reading file {self.data_source}")
@@ -552,14 +552,14 @@ class TabStates(StatesTable):
552
552
  if self.__tab_data is None:
553
553
  self.__tab_source = get_input_path(self.__tab_source)
554
554
  if not self.__tab_source.is_file():
555
- if verbosity:
555
+ if verbosity > 0:
556
556
  print(
557
557
  f"States '{self.name}': Reading static data '{self.__tab_source}' from context '{STATES}'"
558
558
  )
559
559
  self.__tab_source = algo.dbook.get_file_path(
560
560
  STATES, self.__tab_source.name, check_raw=False
561
561
  )
562
- if verbosity:
562
+ if verbosity > 0:
563
563
  print(f"Path: {self.__tab_source}")
564
564
  elif verbosity:
565
565
  print(f"States '{self.name}': Reading file {self.__tab_source}")
@@ -0,0 +1,189 @@
1
+ import numpy as np
2
+
3
+ from foxes.core.states import States
4
+ from foxes.config import config, get_input_path
5
+ from foxes.utils.wrg_utils import ReaderWRG
6
+ from foxes.data import STATES
7
+ import foxes.variables as FV
8
+ import foxes.constants as FC
9
+
10
+
11
+ class WRGStates(States):
12
+ """
13
+ Ambient states based on WRG data
14
+
15
+ Attributes
16
+ ----------
17
+ wrg_fname: str
18
+ Name of the WRG file
19
+ ws_bins: numpy.ndarray
20
+ The wind speed bins, including
21
+ lower and upper bounds, shape: (n_ws_bins+1,)
22
+ fixed_vars: dict
23
+ Fixed uniform variable values, instead of
24
+ reading from data
25
+ bounds_extra_space: float or str
26
+ The extra space, either float in m,
27
+ or str for units of D, e.g. '2.5D'
28
+
29
+ :group: input.states
30
+
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ wrg_fname,
36
+ ws_bins,
37
+ fixed_vars={},
38
+ bounds_extra_space="1D",
39
+ **kwargs,
40
+ ):
41
+ """
42
+ Constructor
43
+
44
+ Parameters
45
+ ----------
46
+ wrg_fname: str
47
+ Name of the WRG file
48
+ ws_bins: list of float
49
+ The wind speed bins, including
50
+ lower and upper bounds
51
+ fixed_vars: dict
52
+ Fixed uniform variable values, instead of
53
+ reading from data
54
+ bounds_extra_space: float or str, optional
55
+ The extra space, either float in m,
56
+ or str for units of D, e.g. '2.5D'
57
+ kwargs: dict, optional
58
+ Parameters for the base class
59
+
60
+ """
61
+ super().__init__(**kwargs)
62
+ self.wrg_fname = wrg_fname
63
+ self.ws_bins = np.asarray(ws_bins)
64
+ self.fixed_vars = fixed_vars
65
+ self.bounds_extra_space = bounds_extra_space
66
+
67
+ def load_data(self, algo, verbosity=0):
68
+ """
69
+ Load and/or create all model data that is subject to chunking.
70
+
71
+ Such data should not be stored under self, for memory reasons. The
72
+ data returned here will automatically be chunked and then provided
73
+ as part of the mdata object during calculations.
74
+
75
+ Parameters
76
+ ----------
77
+ algo: foxes.core.Algorithm
78
+ The calculation algorithm
79
+ verbosity: int
80
+ The verbosity level, 0 = silent
81
+
82
+ Returns
83
+ -------
84
+ idata: dict
85
+ The dict has exactly two entries: `data_vars`,
86
+ a dict with entries `name_str -> (dim_tuple, data_ndarray)`;
87
+ and `coords`, a dict with entries `dim_name_str -> dim_array`
88
+
89
+ """
90
+ # read wrg file:
91
+ fpath = get_input_path(self.wrg_fname)
92
+ if not fpath.is_file():
93
+ if verbosity > 0:
94
+ print(
95
+ f"States '{self.name}': Reading static data '{self.wrg_fname}' from context '{STATES}'"
96
+ )
97
+ fpath = algo.dbook.get_file_path(STATES, self.wrg_fname, check_raw=False)
98
+ if verbosity > 0:
99
+ print(f"Path: {fpath}")
100
+ elif verbosity:
101
+ print(f"States '{self.name}': Reading file {fpath}")
102
+ wrg = ReaderWRG(fpath)
103
+ self._p0 = np.array([wrg.x0, wrg.y0], dtype=config.dtype_double)
104
+ self._nx = wrg.nx
105
+ self._ny = wrg.ny
106
+ self._ns = wrg.n_sectors
107
+ self._res = wrg.resolution
108
+
109
+ # find bounds:
110
+ if self.bounds_extra_space is not None:
111
+ xy_min, xy_max = algo.farm.get_xy_bounds(
112
+ extra_space=self.bounds_extra_space, algo=algo
113
+ )
114
+ if verbosity > 0:
115
+ print(
116
+ f"States '{self.name}': Restricting to bounds {xy_min} - {xy_max}"
117
+ )
118
+ xy_min -= self._p0
119
+ xy_max -= self._p0
120
+ ij_min = np.asarray(xy_min / self._res, dtype=config.dtype_int)
121
+ ij_max = np.asarray(xy_max / self._res, dtype=config.dtype_int) + 1
122
+ sx = slice(ij_min[0], ij_max[0])
123
+ sy = slice(ij_min[1], ij_max[1])
124
+ else:
125
+ sx = np.s_[:]
126
+ sy = np.s_[:]
127
+
128
+ # store data:
129
+ A = []
130
+ k = []
131
+ fs = []
132
+ for s in range(self._ns):
133
+ A.append(wrg.data[f"A_{s}"].to_numpy().reshape(self._ny, self._nx)[sy, sx])
134
+ k.append(wrg.data[f"k_{s}"].to_numpy().reshape(self._ny, self._nx)[sy, sx])
135
+ fs.append(
136
+ wrg.data[f"fs_{s}"].to_numpy().reshape(self._ny, self._nx)[sy, sx]
137
+ )
138
+ del wrg
139
+ A = np.stack(A, axis=0).T
140
+ k = np.stack(k, axis=0).T
141
+ fs = np.stack(fs, axis=0).T
142
+ self._data = np.stack([A, k, fs], axis=-1) # (x, y, wd, AKfs)
143
+
144
+ # store ws and wd:
145
+ self.WSWD = self.var("WSWD")
146
+ self._wds = np.arange(0.0, 360.0, 360 / self._ns)
147
+ self._wsd = self.ws_bins[1:] - self.ws_bins[:-1]
148
+ self._wss = 0.5 * (self.ws_bins[:-1] + self.ws_bins[1:])
149
+ self._N = len(self._wss) * self._ns
150
+ wswd = np.zeros((len(self._wss), self._ns, 2), dtype=config.dtype_double)
151
+ wswd[..., 0] = self._wss[:, None]
152
+ wswd[..., 1] = self._wds[None, :]
153
+ wswd = wswd.reshape(self._N, 2)
154
+ idata = super().load_data(algo, verbosity)
155
+ idata.coords[self.WSWD] = [self.var(FV.WS), self.var(FV.WD)]
156
+ idata.data_vars[self.WSWD] = ((FC.STATE, self.WSWD), wswd)
157
+
158
+ return idata
159
+
160
+ def size(self):
161
+ """
162
+ The total number of states.
163
+
164
+ Returns
165
+ -------
166
+ int:
167
+ The total number of states
168
+
169
+ """
170
+ return self._N
171
+
172
+ def output_point_vars(self, algo):
173
+ """
174
+ The variables which are being modified by the model.
175
+
176
+ Parameters
177
+ ----------
178
+ algo: foxes.core.Algorithm
179
+ The calculation algorithm
180
+
181
+ Returns
182
+ -------
183
+ output_vars: list of str
184
+ The output variable names
185
+
186
+ """
187
+ ovars = set([FV.WS, FV.WD, FV.WEIGHT])
188
+ ovars.update(self.fixed_vars.values())
189
+ return list(ovars)
@@ -183,12 +183,11 @@ class VortexSheet(TurbineInductionModel):
183
183
  sp_sel = (ct > 1e-8) & (x <= 0)
184
184
  ct_sel = ct[sp_sel]
185
185
  r_sph_sel = r_sph[sp_sel]
186
- D_sel = D[sp_sel]
186
+ R_sel = D[sp_sel] / 2
187
+ xi = r_sph_sel / R_sel
187
188
 
188
189
  if np.any(sp_sel):
189
- blockage = self.induction.ct2a(ct_sel) * (
190
- (1 + 2 * r_sph_sel / D_sel) * (1 + (2 * r_sph_sel / D_sel) ** 2)
191
- ) ** (-0.5)
190
+ blockage = self.induction.ct2a(ct_sel) * (1 + -xi / np.sqrt(1 + xi**2))
192
191
 
193
192
  self._superp.add_wake(
194
193
  algo,
@@ -208,12 +207,10 @@ class VortexSheet(TurbineInductionModel):
208
207
  ) # mirror in rotor plane and inverse blockage, but not directly behind rotor
209
208
  ct_sel = ct[sp_sel]
210
209
  r_sph_sel = r_sph[sp_sel]
211
- D_sel = D[sp_sel]
210
+ R_sel = D[sp_sel] / 2
211
+ xi = r_sph_sel / R_sel
212
212
  if np.any(sp_sel):
213
- blockage = self.induction.ct2a(ct_sel) * (
214
- (1 + 2 * r_sph_sel / D_sel) * (1 + (2 * r_sph_sel / D_sel) ** 2)
215
- ) ** (-0.5)
216
-
213
+ blockage = self.induction.ct2a(ct_sel) * (1 + -xi / np.sqrt(1 + xi**2))
217
214
  self._superp.add_wake(
218
215
  algo,
219
216
  mdata,
foxes/utils/wrg_utils.py CHANGED
@@ -58,13 +58,18 @@ class ReaderWRG:
58
58
  cols[10::3] = cols_sel("Ks", self._n_sectors)
59
59
 
60
60
  self._data = pd.read_csv(
61
- self.fpath, names=cols, skiprows=1, sep="\s+", usecols=range(1, n_cols)
61
+ self.fpath, names=cols, skiprows=1, sep=r"\s+", usecols=range(1, n_cols)
62
62
  )
63
63
 
64
64
  self._data[cols_sel("fs", self._n_sectors)] /= 10
65
65
  self._data[cols_sel("As", self._n_sectors)] /= 10
66
66
  self._data[cols_sel("Ks", self._n_sectors)] /= 100
67
67
 
68
+ if len(self._data.index) != self._nx * self._ny:
69
+ raise ValueError(
70
+ f"Expecting {self._nx * self._ny} rows in data, got {len(self._data.index)}"
71
+ )
72
+
68
73
  @property
69
74
  def data(self):
70
75
  """
@@ -77,3 +82,81 @@ class ReaderWRG:
77
82
 
78
83
  """
79
84
  return self._data
85
+
86
+ @property
87
+ def nx(self):
88
+ """
89
+ The number of points in x direction
90
+
91
+ Returns
92
+ -------
93
+ n: int
94
+ The number of points in x direction
95
+
96
+ """
97
+ return self._nx
98
+
99
+ @property
100
+ def ny(self):
101
+ """
102
+ The number of points in y direction
103
+
104
+ Returns
105
+ -------
106
+ n: int
107
+ The number of points in y direction
108
+
109
+ """
110
+ return self._ny
111
+
112
+ @property
113
+ def x0(self):
114
+ """
115
+ The lower left x coordinate
116
+
117
+ Returns
118
+ -------
119
+ x: float
120
+ The lower left x coordinate
121
+
122
+ """
123
+ return self._utmx0
124
+
125
+ @property
126
+ def y0(self):
127
+ """
128
+ The lower left y coordinate
129
+
130
+ Returns
131
+ -------
132
+ y: float
133
+ The lower left y coordinate
134
+
135
+ """
136
+ return self._utmy0
137
+
138
+ @property
139
+ def n_sectors(self):
140
+ """
141
+ The number of wind direction sectors
142
+
143
+ Returns
144
+ -------
145
+ n: int
146
+ The number of wind direction sectors
147
+
148
+ """
149
+ return self._n_sectors
150
+
151
+ @property
152
+ def resolution(self):
153
+ """
154
+ The horizontal resolution
155
+
156
+ Returns
157
+ -------
158
+ res: float
159
+ The horizontal resolution
160
+
161
+ """
162
+ return self._res
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foxes
3
- Version: 1.2.4
3
+ Version: 1.2.5
4
4
  Summary: Farm Optimization and eXtended yield Evaluation Software
5
5
  Author: Jonas Schulte
6
6
  Maintainer: Jonas Schulte
@@ -94,6 +94,8 @@ Requires-Dist: ipykernel; extra == "doc"
94
94
  Requires-Dist: ipywidgets; extra == "doc"
95
95
  Requires-Dist: m2r2; extra == "doc"
96
96
  Requires-Dist: lxml_html_clean; extra == "doc"
97
+ Requires-Dist: dask; extra == "doc"
98
+ Requires-Dist: distributed; extra == "doc"
97
99
  Provides-Extra: dev
98
100
  Requires-Dist: flake8; extra == "dev"
99
101
  Requires-Dist: pytest; extra == "dev"
@@ -111,11 +111,12 @@ foxes/input/farm_layout/ring.py,sha256=ghfLkVVQciWDJJNqGs4jZVnM0XCII9ae3hAh9Wb49
111
111
  foxes/input/farm_layout/row.py,sha256=Bx9woFNkXbFXJg51GX2p2PbVgdxV3Ckxr-3TkB04PS4,1198
112
112
  foxes/input/states/__init__.py,sha256=Xkjr0Tn3jKEBcIk3GA1dRVzTDIX9Xco-Y23X-LUV-GA,526
113
113
  foxes/input/states/field_data_nc.py,sha256=LSSW6Q4Ica3gl9CuBuRm7wqKtYZpvOLGzTVqv8ylFm4,29429
114
- foxes/input/states/multi_height.py,sha256=ECKARj0tJ-Bzih8wiii_sy34HjfTAP4QCvLo4Fh7Ruk,23810
114
+ foxes/input/states/multi_height.py,sha256=Bf14Kz_ke9LP314617qgYtGXSbBpEZKnFnfjNyh9sjc,23826
115
115
  foxes/input/states/one_point_flow.py,sha256=TuMYGSHz3nOwN3gdWxbQNRHzKmtVtV4AbnHTJ6dVceA,17787
116
116
  foxes/input/states/scan.py,sha256=43CnJl-iRUbRrJCtu-u6Na5DDY19_184myD6ScMfcFA,6101
117
117
  foxes/input/states/single.py,sha256=jwcZ2quljXS9cDyYbf3wgvbYUe6umqNfyfvRdylYbC0,6137
118
- foxes/input/states/states_table.py,sha256=HrsX2DVID1SbopBaevfq1HqkDtpH2mtfqslxYNDpNC8,20465
118
+ foxes/input/states/states_table.py,sha256=pUpdhRGYmBvZD9kFQxXvUMP6oWPfiKsGhxX7m209SkE,20481
119
+ foxes/input/states/wrg_states.py,sha256=29HBfLaK40GvNNZ2F9hX2iVh3P7AXdRW05By2WO-xjg,5915
119
120
  foxes/input/states/create/__init__.py,sha256=Ocqzmr9SOefeAvGX5DgawsPXfNdGzWOZ2ssvtqEmtAo,134
120
121
  foxes/input/states/create/random_abl_states.py,sha256=LFCA19TCInXmB2FbKDaOkqCDsN0eOUIp34yzR2NQjtQ,3425
121
122
  foxes/input/states/create/random_timeseries.py,sha256=gJpaQ4nEXxOjI4hp3xjNcVbCsmZUm-brXUxoqDb63WE,1266
@@ -205,7 +206,7 @@ foxes/models/wake_models/induction/rankine_half_body.py,sha256=LKYNAiamULPLQeohl
205
206
  foxes/models/wake_models/induction/rathmann.py,sha256=SFLqMFjcwSM2zSdyK8M60q8pB98ffixDWuvhRH5FYwE,7751
206
207
  foxes/models/wake_models/induction/self_similar.py,sha256=q7PM8mLjH8BW2_Qev_3yoAwchRy8cCoG6ps6mlYnIGQ,8444
207
208
  foxes/models/wake_models/induction/self_similar2020.py,sha256=D8yQxa5NQFII2gvKggcbJvuSDnrIRSy0Q5aCC3DoTPc,1634
208
- foxes/models/wake_models/induction/vortex_sheet.py,sha256=TYPXzlbcx8IMy3_Nbw4bY_mMWpSqST0JGwL1mJf4He8,7357
209
+ foxes/models/wake_models/induction/vortex_sheet.py,sha256=aUTUr4NOiIXnQtzzde1Y6dNNP_chk3m_YcetuAovTfw,7270
209
210
  foxes/models/wake_models/ti/__init__.py,sha256=EOlqFHL2mzcKGFRZqlVYTiqGJqPb6dx7I5UWUDshy2U,125
210
211
  foxes/models/wake_models/ti/crespo_hernandez.py,sha256=GcRqWw2EjAka3Ss0If-HM-gkxJlV7Omm-5oyqF1-y0M,8933
211
212
  foxes/models/wake_models/ti/iec_ti.py,sha256=8efoMQibs8zolXF7iZALggdFL6fHeRdL5ikztRjxENI,7006
@@ -264,7 +265,7 @@ foxes/utils/subclasses.py,sha256=wCfhuialpBOQOPMwNbaplkVmf60vR9AIkY_o3tdkgXI,173
264
265
  foxes/utils/tab_files.py,sha256=H50IpLaqffJn9A51orCGc4fOhCOzoNUYDUKek4OAayU,1811
265
266
  foxes/utils/two_circles.py,sha256=xkj-SA_x-VXY7KtmSU4lcV4gFdplyhU3sBAC9vTdkF4,2810
266
267
  foxes/utils/wind_dir.py,sha256=6W0njWDvnIdOOjwqcMr64MW9ApjdtFA75blVUxirPMo,2823
267
- foxes/utils/wrg_utils.py,sha256=3T6NkznU1_nc5bTaq-rEuBRFeBPjqP4XnEhwhQArKnk,2019
268
+ foxes/utils/wrg_utils.py,sha256=PsaOIKx3WrHekJPeJMHzMfTYoEXkOAV51QjRbGjobGQ,3534
268
269
  foxes/utils/xarray_utils.py,sha256=6VLTAitXTK6W5zlBTadWwN05qmq_TlEDpUCx227JxtY,1677
269
270
  foxes/utils/abl/__init__.py,sha256=ijn-ubLLlqqH6tTAXFRmBAxJZmVBlTEmtx1cdCCtG4I,135
270
271
  foxes/utils/abl/neutral.py,sha256=E4DEhvXvw74BPrYr1MjQjeIaoz6ZOTWVlqScKflm-0M,1358
@@ -303,9 +304,9 @@ tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py,sha256=nwI
303
304
  tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py,sha256=a7CQS-_Mnz3NynaTv1OY1CZ10iAqa7E3YxmkbDtoshw,2590
304
305
  tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py,sha256=s6FbEdpiIdHYmdD8S85_NhLH-S3EOinXvw8RHmR2QOU,2122
305
306
  tests/3_examples/test_examples.py,sha256=rS2Dz04ktbS6v3TRDr96AkWGypr5u49jihqbEmGFmRU,694
306
- foxes-1.2.4.dist-info/LICENSE,sha256=bBCH6mYTPzSepk2s2UUZ3II_ZYXrn1bnSqB85-aZHxU,1071
307
- foxes-1.2.4.dist-info/METADATA,sha256=vAXcCQux4WPpc196ZFrNyXhyDNKBVL8PETlRB824oiM,8811
308
- foxes-1.2.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
309
- foxes-1.2.4.dist-info/entry_points.txt,sha256=KuS44FRH5NnMw201A8Btr76eNRKr2UOoKHjejAsqKwE,123
310
- foxes-1.2.4.dist-info/top_level.txt,sha256=G7oHApEz5nc-iP__XsPcvjYe_NyXGmKMUMPHi3C3x6I,26
311
- foxes-1.2.4.dist-info/RECORD,,
307
+ foxes-1.2.5.dist-info/LICENSE,sha256=bBCH6mYTPzSepk2s2UUZ3II_ZYXrn1bnSqB85-aZHxU,1071
308
+ foxes-1.2.5.dist-info/METADATA,sha256=t7Ic8ZLWemygBNxnjuLMopK0uz_rI943L00tjHMgEE4,8890
309
+ foxes-1.2.5.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
310
+ foxes-1.2.5.dist-info/entry_points.txt,sha256=KuS44FRH5NnMw201A8Btr76eNRKr2UOoKHjejAsqKwE,123
311
+ foxes-1.2.5.dist-info/top_level.txt,sha256=G7oHApEz5nc-iP__XsPcvjYe_NyXGmKMUMPHi3C3x6I,26
312
+ foxes-1.2.5.dist-info/RECORD,,
File without changes
File without changes