foxes 0.7.1__py3-none-any.whl → 0.7.3__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.
- foxes/VERSION +1 -1
- foxes/algorithms/downwind/downwind.py +60 -46
- foxes/algorithms/downwind/models/farm_wakes_calc.py +17 -6
- foxes/algorithms/downwind/models/point_wakes_calc.py +13 -45
- foxes/algorithms/iterative/iterative.py +1 -1
- foxes/algorithms/iterative/models/farm_wakes_calc.py +18 -4
- foxes/constants.py +5 -0
- foxes/core/__init__.py +2 -1
- foxes/core/ground_model.py +254 -0
- foxes/core/model.py +3 -2
- foxes/core/partial_wakes_model.py +19 -3
- foxes/core/states.py +33 -0
- foxes/core/wake_model.py +138 -2
- foxes/data/__init__.py +1 -1
- foxes/data/states/WRF-Timeseries-3000.nc +0 -0
- foxes/data/states/windio_timeseries_5000.nc +0 -0
- foxes/data/static_data.py +7 -0
- foxes/data/windio/DTU_10MW_turbine.yaml +10 -0
- foxes/data/windio/__init__.py +0 -0
- foxes/data/windio/windio_5turbines_timeseries.yaml +63 -0
- foxes/input/states/__init__.py +1 -0
- foxes/input/states/multi_height.py +225 -6
- foxes/input/windio/__init__.py +6 -1
- foxes/input/windio/get_states.py +115 -0
- foxes/input/windio/read_attributes.py +321 -0
- foxes/input/windio/read_farm.py +163 -0
- foxes/input/windio/read_fields.py +164 -0
- foxes/input/windio/runner.py +105 -0
- foxes/input/windio/windio.py +136 -254
- foxes/models/__init__.py +2 -1
- foxes/models/ground_models/__init__.py +2 -0
- foxes/models/ground_models/no_ground.py +12 -0
- foxes/models/ground_models/wake_mirror.py +161 -0
- foxes/models/model_book.py +114 -164
- foxes/models/partial_wakes/axiwake.py +27 -4
- foxes/models/partial_wakes/top_hat.py +26 -4
- foxes/models/turbine_types/PCt_file.py +1 -0
- foxes/models/turbine_types/PCt_from_two.py +92 -0
- foxes/models/wake_frames/yawed_wakes.py +41 -38
- foxes/models/wake_models/__init__.py +0 -1
- foxes/models/wake_models/induction/__init__.py +1 -0
- foxes/models/wake_models/induction/rankine_half_body.py +1 -1
- foxes/models/wake_models/induction/vortex_sheet.py +227 -0
- foxes/models/wake_models/ti/crespo_hernandez.py +26 -24
- foxes/models/wake_models/ti/iec_ti.py +33 -26
- foxes/models/wake_models/wind/bastankhah14.py +11 -32
- foxes/models/wake_models/wind/bastankhah16.py +30 -34
- foxes/models/wake_models/wind/jensen.py +13 -29
- foxes/models/wake_models/wind/turbopark.py +31 -61
- foxes/models/wake_superpositions/ws_max.py +1 -0
- foxes/models/wake_superpositions/ws_pow.py +1 -0
- foxes/models/wake_superpositions/ws_quadratic.py +1 -0
- foxes/output/grids.py +6 -6
- foxes/output/output.py +6 -6
- foxes/utils/__init__.py +1 -1
- foxes/utils/factory.py +284 -76
- {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/METADATA +8 -6
- {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/RECORD +65 -51
- {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/WHEEL +1 -1
- foxes/models/wake_models/wake_mirror.py +0 -196
- /foxes/models/{axial_induction_models → axial_induction}/__init__.py +0 -0
- /foxes/models/{axial_induction_models → axial_induction}/betz.py +0 -0
- /foxes/models/{axial_induction_models → axial_induction}/madsen.py +0 -0
- {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/LICENSE +0 -0
- {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/top_level.txt +0 -0
- {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/zip-safe +0 -0
foxes/output/grids.py
CHANGED
|
@@ -108,12 +108,12 @@ def get_grid_xy(
|
|
|
108
108
|
n_states = farm_results[FV.H].shape[0]
|
|
109
109
|
|
|
110
110
|
# get base rectangle:
|
|
111
|
-
x_min = xmin if xmin is not None else farm_results[FV.X].min() - xspace
|
|
112
|
-
y_min = ymin if ymin is not None else farm_results[FV.Y].min() - yspace
|
|
113
|
-
z_min = z if z is not None else farm_results[FV.H].min()
|
|
114
|
-
x_max = xmax if xmax is not None else farm_results[FV.X].max() + xspace
|
|
115
|
-
y_max = ymax if ymax is not None else farm_results[FV.Y].max() + yspace
|
|
116
|
-
z_max = z if z is not None else farm_results[FV.H].max()
|
|
111
|
+
x_min = xmin if xmin is not None else farm_results[FV.X].min().to_numpy() - xspace
|
|
112
|
+
y_min = ymin if ymin is not None else farm_results[FV.Y].min().to_numpy() - yspace
|
|
113
|
+
z_min = z if z is not None else farm_results[FV.H].min().to_numpy()
|
|
114
|
+
x_max = xmax if xmax is not None else farm_results[FV.X].max().to_numpy() + xspace
|
|
115
|
+
y_max = ymax if ymax is not None else farm_results[FV.Y].max().to_numpy() + yspace
|
|
116
|
+
z_max = z if z is not None else farm_results[FV.H].max().to_numpy()
|
|
117
117
|
|
|
118
118
|
x_pos, x_res = np.linspace(
|
|
119
119
|
x_min,
|
foxes/output/output.py
CHANGED
|
@@ -97,13 +97,13 @@ class Output:
|
|
|
97
97
|
print(n)
|
|
98
98
|
|
|
99
99
|
@classmethod
|
|
100
|
-
def new(cls,
|
|
100
|
+
def new(cls, output_type, *args, **kwargs):
|
|
101
101
|
"""
|
|
102
102
|
Run-time output model factory.
|
|
103
103
|
|
|
104
104
|
Parameters
|
|
105
105
|
----------
|
|
106
|
-
|
|
106
|
+
output_type: string
|
|
107
107
|
The selected derived class name
|
|
108
108
|
args: tuple, optional
|
|
109
109
|
Additional parameters for the constructor
|
|
@@ -112,19 +112,19 @@ class Output:
|
|
|
112
112
|
|
|
113
113
|
"""
|
|
114
114
|
|
|
115
|
-
if
|
|
115
|
+
if output_type is None:
|
|
116
116
|
return None
|
|
117
117
|
|
|
118
118
|
allc = all_subclasses(cls)
|
|
119
|
-
found =
|
|
119
|
+
found = output_type in [scls.__name__ for scls in allc]
|
|
120
120
|
|
|
121
121
|
if found:
|
|
122
122
|
for scls in allc:
|
|
123
|
-
if scls.__name__ ==
|
|
123
|
+
if scls.__name__ == output_type:
|
|
124
124
|
return scls(*args, **kwargs)
|
|
125
125
|
|
|
126
126
|
else:
|
|
127
127
|
estr = "Output type '{}' is not defined, available types are \n {}".format(
|
|
128
|
-
|
|
128
|
+
output_type, sorted([i.__name__ for i in allc])
|
|
129
129
|
)
|
|
130
130
|
raise KeyError(estr)
|
foxes/utils/__init__.py
CHANGED
|
@@ -7,7 +7,7 @@ from .pandas_utils import PandasFileHelper
|
|
|
7
7
|
from .xarray_utils import write_nc
|
|
8
8
|
from .subclasses import all_subclasses
|
|
9
9
|
from .dict import Dict
|
|
10
|
-
from .factory import Factory, FDict
|
|
10
|
+
from .factory import Factory, FDict, WakeKFactory
|
|
11
11
|
from .data_book import DataBook
|
|
12
12
|
from .cubic_roots import cubic_roots
|
|
13
13
|
from .geopandas_utils import read_shp, shp2csv, read_shp_polygons, shp2geom2d
|
foxes/utils/factory.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from .dict import Dict
|
|
2
|
+
import foxes.variables as FV
|
|
3
|
+
|
|
2
4
|
|
|
3
5
|
class Factory:
|
|
4
6
|
"""
|
|
5
|
-
Constructs objects from a choice of allowed
|
|
7
|
+
Constructs objects from a choice of allowed
|
|
6
8
|
constructor parameters
|
|
7
|
-
|
|
9
|
+
|
|
8
10
|
Attributes
|
|
9
11
|
----------
|
|
10
12
|
base: class
|
|
@@ -22,25 +24,26 @@ class Factory:
|
|
|
22
24
|
Hints for print_toc, only for variables for which the
|
|
23
25
|
options are functions or missing
|
|
24
26
|
options: dict
|
|
25
|
-
For each variable, e.g. A, B or C, the list or dict
|
|
27
|
+
For each variable, e.g. A, B or C, the list or dict
|
|
26
28
|
or function that maps a str to the actual value
|
|
27
29
|
|
|
28
30
|
:group: utils
|
|
29
|
-
|
|
31
|
+
|
|
30
32
|
"""
|
|
33
|
+
|
|
31
34
|
def __init__(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
self,
|
|
36
|
+
base,
|
|
37
|
+
name_template,
|
|
38
|
+
args=(),
|
|
39
|
+
kwargs={},
|
|
40
|
+
var2arg={},
|
|
41
|
+
hints={},
|
|
42
|
+
**options,
|
|
43
|
+
):
|
|
41
44
|
"""
|
|
42
45
|
Constructor.
|
|
43
|
-
|
|
46
|
+
|
|
44
47
|
Parameters
|
|
45
48
|
----------
|
|
46
49
|
base: class
|
|
@@ -58,9 +61,9 @@ class Factory:
|
|
|
58
61
|
Hints for print_toc, only for variables for which the
|
|
59
62
|
options are functions or missing
|
|
60
63
|
options: dict
|
|
61
|
-
For each variable, e.g. A, B or C, the list or dict
|
|
64
|
+
For each variable, e.g. A, B or C, the list or dict
|
|
62
65
|
or function that maps a str to the actual value
|
|
63
|
-
|
|
66
|
+
|
|
64
67
|
"""
|
|
65
68
|
self.base = base
|
|
66
69
|
self.name_template = name_template
|
|
@@ -69,17 +72,21 @@ class Factory:
|
|
|
69
72
|
self.var2arg = var2arg
|
|
70
73
|
self.hints = hints
|
|
71
74
|
|
|
72
|
-
parts = name_template.split(">")
|
|
73
|
-
if len(parts) < 2:
|
|
74
|
-
raise ValueError(f"Factory '{name_template}': Expecting at least one variable in template, pattern '<..>'")
|
|
75
|
-
|
|
76
75
|
self._vars = []
|
|
77
76
|
self._pre = []
|
|
77
|
+
parts = name_template.split(">")
|
|
78
|
+
|
|
78
79
|
for i, p in enumerate(parts):
|
|
79
80
|
if i < len(parts) - 1:
|
|
80
81
|
parts2 = p.split("<")
|
|
81
82
|
if len(parts2) != 2:
|
|
82
|
-
raise ValueError(
|
|
83
|
+
raise ValueError(
|
|
84
|
+
f"Factory '{name_template}': incomplete pattern brackets '<..>' between variables, e.g. '_'"
|
|
85
|
+
)
|
|
86
|
+
if i > 0 and len(parts2[0]) == 0:
|
|
87
|
+
raise ValueError(
|
|
88
|
+
f"Factory '{name_template}': Missing seperator like '_' in template between variables '{self._vars[-1]}' and '{parts[1]}'"
|
|
89
|
+
)
|
|
83
90
|
self._pre.append(parts2[0])
|
|
84
91
|
self._vars.append(parts2[1])
|
|
85
92
|
else:
|
|
@@ -89,34 +96,42 @@ class Factory:
|
|
|
89
96
|
for vi, v in enumerate(self.variables):
|
|
90
97
|
p = self._pre[vi]
|
|
91
98
|
if vi < len(self.variables) - 1 and p == "":
|
|
92
|
-
raise ValueError(
|
|
93
|
-
|
|
99
|
+
raise ValueError(
|
|
100
|
+
f"Factory '{name_template}': Require indicator before variable '{v}' in template, e.g. '{v}<{v}>'"
|
|
101
|
+
)
|
|
102
|
+
|
|
94
103
|
self.options = Dict(name=f"{self._pre[0]}_options")
|
|
95
|
-
for v, o
|
|
104
|
+
for v, o in options.items():
|
|
96
105
|
if v not in self.variables:
|
|
97
|
-
raise KeyError(
|
|
106
|
+
raise KeyError(
|
|
107
|
+
f"Factory '{name_template}': Variable '{v}' found in options, but not in template"
|
|
108
|
+
)
|
|
98
109
|
if isinstance(o, list) or isinstance(o, tuple):
|
|
99
110
|
o = {str(k): k for k in o}
|
|
100
111
|
if isinstance(o, dict):
|
|
101
112
|
for k in o.keys():
|
|
102
113
|
if not isinstance(k, str):
|
|
103
|
-
raise TypeError(
|
|
114
|
+
raise TypeError(
|
|
115
|
+
f"Factory '{name_template}': Found option for variable '{v}' that is not a str, {k}"
|
|
116
|
+
)
|
|
104
117
|
self.options[v] = Dict(name=f"{self._pre[0]}_options_{v}", **o)
|
|
105
118
|
elif hasattr(o, "__call__"):
|
|
106
119
|
self.options[v] = o
|
|
107
120
|
else:
|
|
108
|
-
raise ValueError(
|
|
109
|
-
|
|
121
|
+
raise ValueError(
|
|
122
|
+
f"Factory '{name_template}': Variable '{v}' has option of type '{type(v).__name__}'. Only list, tuple, dict or function are supported"
|
|
123
|
+
)
|
|
124
|
+
|
|
110
125
|
@property
|
|
111
126
|
def name_prefix(self):
|
|
112
127
|
"""
|
|
113
128
|
The beginning of the name template
|
|
114
|
-
|
|
129
|
+
|
|
115
130
|
Returns
|
|
116
131
|
-------
|
|
117
132
|
nbase: str
|
|
118
133
|
The beginning of the name template
|
|
119
|
-
|
|
134
|
+
|
|
120
135
|
"""
|
|
121
136
|
return self._pre[0]
|
|
122
137
|
|
|
@@ -124,30 +139,30 @@ class Factory:
|
|
|
124
139
|
def name_suffix(self):
|
|
125
140
|
"""
|
|
126
141
|
The ending of the name template
|
|
127
|
-
|
|
142
|
+
|
|
128
143
|
Returns
|
|
129
144
|
-------
|
|
130
145
|
nbase: str
|
|
131
146
|
The ending of the name template
|
|
132
|
-
|
|
147
|
+
|
|
133
148
|
"""
|
|
134
149
|
return self._pre[-1]
|
|
135
|
-
|
|
150
|
+
|
|
136
151
|
@property
|
|
137
152
|
def variables(self):
|
|
138
153
|
"""
|
|
139
154
|
The list of variables
|
|
140
|
-
|
|
155
|
+
|
|
141
156
|
Returns
|
|
142
157
|
-------
|
|
143
158
|
vrs: list of str
|
|
144
159
|
The variables
|
|
145
|
-
|
|
160
|
+
|
|
146
161
|
"""
|
|
147
162
|
return self._vars
|
|
148
|
-
|
|
163
|
+
|
|
149
164
|
def __str__(self):
|
|
150
|
-
"""
|
|
165
|
+
"""String representation"""
|
|
151
166
|
s = f"{self.name_template}: {self.base.__name__} with"
|
|
152
167
|
for k, d in self.kwargs.items():
|
|
153
168
|
s += f"\n {k}={d}"
|
|
@@ -157,11 +172,11 @@ class Factory:
|
|
|
157
172
|
else:
|
|
158
173
|
s += f"\n {v}={self.hints.get(v, '(value)')}"
|
|
159
174
|
return s
|
|
160
|
-
|
|
175
|
+
|
|
161
176
|
def check_match(self, name):
|
|
162
177
|
"""
|
|
163
178
|
Tests if a name matches the template
|
|
164
|
-
|
|
179
|
+
|
|
165
180
|
Parameters
|
|
166
181
|
----------
|
|
167
182
|
name: str
|
|
@@ -171,7 +186,7 @@ class Factory:
|
|
|
171
186
|
-------
|
|
172
187
|
success: bool
|
|
173
188
|
True if the template is matched
|
|
174
|
-
|
|
189
|
+
|
|
175
190
|
"""
|
|
176
191
|
data_str = name
|
|
177
192
|
for vi in range(len(self.variables)):
|
|
@@ -182,7 +197,7 @@ class Factory:
|
|
|
182
197
|
return False
|
|
183
198
|
data_str = data_str[j:]
|
|
184
199
|
|
|
185
|
-
q = self._pre[vi+1]
|
|
200
|
+
q = self._pre[vi + 1]
|
|
186
201
|
if q != "":
|
|
187
202
|
i = data_str.find(q)
|
|
188
203
|
j = i + len(q)
|
|
@@ -190,47 +205,42 @@ class Factory:
|
|
|
190
205
|
return False
|
|
191
206
|
else:
|
|
192
207
|
data_str = ""
|
|
193
|
-
|
|
208
|
+
|
|
194
209
|
return True
|
|
195
210
|
|
|
196
211
|
def construct(self, name):
|
|
197
212
|
"""
|
|
198
213
|
Create an object of the base class.
|
|
199
|
-
|
|
214
|
+
|
|
200
215
|
Parameters
|
|
201
216
|
----------
|
|
202
217
|
name: str
|
|
203
218
|
The name, matching the template
|
|
204
|
-
|
|
219
|
+
|
|
205
220
|
Returns
|
|
206
221
|
-------
|
|
207
222
|
obj: object
|
|
208
223
|
The instance of the base class
|
|
209
|
-
|
|
224
|
+
|
|
210
225
|
"""
|
|
211
|
-
|
|
226
|
+
j = 0
|
|
212
227
|
wlist = []
|
|
213
|
-
for
|
|
214
|
-
p
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if q != "":
|
|
223
|
-
i = data_str.find(q)
|
|
224
|
-
j = i + len(q)
|
|
225
|
-
if i < 0 or len(data_str) <= j:
|
|
226
|
-
raise ValueError(f"Factory '{self.name_template}': Name '{name}' not matching template")
|
|
227
|
-
wlist.append(data_str[:i])
|
|
228
|
+
for pi, p in enumerate(self._pre):
|
|
229
|
+
if len(p) > 0:
|
|
230
|
+
i = name[j:].find(p)
|
|
231
|
+
if i < 0 or (pi == 0 and i > 0):
|
|
232
|
+
raise ValueError(
|
|
233
|
+
f"Factory '{self.name_template}': Name '{name}' not matching template"
|
|
234
|
+
)
|
|
235
|
+
w = name[j : j + i]
|
|
236
|
+
j += i + len(p)
|
|
228
237
|
else:
|
|
229
|
-
|
|
230
|
-
|
|
238
|
+
w = name[j:]
|
|
239
|
+
if pi > 0:
|
|
240
|
+
wlist.append(w)
|
|
231
241
|
|
|
232
242
|
kwargs = {}
|
|
233
|
-
for vi, v in enumerate(self.variables):
|
|
243
|
+
for vi, v in enumerate(self.variables):
|
|
234
244
|
w = self.var2arg.get(v, v)
|
|
235
245
|
data = wlist[vi]
|
|
236
246
|
if v in self.options:
|
|
@@ -246,24 +256,206 @@ class Factory:
|
|
|
246
256
|
|
|
247
257
|
return self.base(*self.args, **kwargs)
|
|
248
258
|
|
|
259
|
+
|
|
260
|
+
class WakeKFactory:
|
|
261
|
+
"""
|
|
262
|
+
A factory that automatically handles
|
|
263
|
+
wake_k parameters
|
|
264
|
+
|
|
265
|
+
Attributes
|
|
266
|
+
----------
|
|
267
|
+
factories: list of Factory
|
|
268
|
+
The individual factories
|
|
269
|
+
|
|
270
|
+
:group: utils
|
|
271
|
+
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
def __init__(self, base, name_template, *args, hints={}, **kwargs):
|
|
275
|
+
"""
|
|
276
|
+
Constructor.
|
|
277
|
+
|
|
278
|
+
Parameters
|
|
279
|
+
----------
|
|
280
|
+
base: class
|
|
281
|
+
The class of which objects are to be created
|
|
282
|
+
name_template: str
|
|
283
|
+
The name template, e.g. 'name_<A>_<B>_<C>' for
|
|
284
|
+
variables A, B, C. Indicate wake_k part by '_[wake_k]'
|
|
285
|
+
args: tuple, optional
|
|
286
|
+
Additional arguments for Factory
|
|
287
|
+
hints: dict
|
|
288
|
+
Hints for print_toc, only for variables for which the
|
|
289
|
+
options are functions or missing
|
|
290
|
+
kwargs: dict
|
|
291
|
+
Additional arguments for Factory
|
|
292
|
+
|
|
293
|
+
"""
|
|
294
|
+
self._base = base
|
|
295
|
+
self._kwargs = kwargs
|
|
296
|
+
self._template0 = name_template
|
|
297
|
+
self.factories = []
|
|
298
|
+
|
|
299
|
+
i0 = name_template.find("_[wake_k]")
|
|
300
|
+
i1 = i0 + len("_[wake_k]")
|
|
301
|
+
kw = kwargs.pop("kwargs", {})
|
|
302
|
+
|
|
303
|
+
if i0 < 0:
|
|
304
|
+
raise ValueError(
|
|
305
|
+
f"String '_[wake_k]' not found in name template '{name_template}'"
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
# add case ka, kb:
|
|
309
|
+
t = name_template[:i0] + "_ka<ka>_kb<kb>"
|
|
310
|
+
if len(name_template) > i1:
|
|
311
|
+
t += name_template[i1:]
|
|
312
|
+
h = hints.copy()
|
|
313
|
+
h["ka"] = "(Value, e.g. 04 for 0.4)"
|
|
314
|
+
h["kb"] = "(Value, e.g. 001 for 0.01)"
|
|
315
|
+
kw["ti_var"] = FV.TI
|
|
316
|
+
self.factories.append(
|
|
317
|
+
Factory(
|
|
318
|
+
base,
|
|
319
|
+
t,
|
|
320
|
+
*args,
|
|
321
|
+
hints=h,
|
|
322
|
+
kwargs=kw.copy(),
|
|
323
|
+
**kwargs,
|
|
324
|
+
ka=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
325
|
+
kb=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
326
|
+
)
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
# add case ambient ka, kb:
|
|
330
|
+
t = name_template[:i0] + "_ambka<ka>_kb<kb>"
|
|
331
|
+
if len(name_template) > i1:
|
|
332
|
+
t += name_template[i1:]
|
|
333
|
+
h = hints.copy()
|
|
334
|
+
h["ka"] = "(Value, e.g. 04 for 0.4)"
|
|
335
|
+
h["kb"] = "(Value, e.g. 001 for 0.01)"
|
|
336
|
+
kw["ti_var"] = FV.AMB_TI
|
|
337
|
+
self.factories.append(
|
|
338
|
+
Factory(
|
|
339
|
+
base,
|
|
340
|
+
t,
|
|
341
|
+
*args,
|
|
342
|
+
hints=h,
|
|
343
|
+
kwargs=kw.copy(),
|
|
344
|
+
**kwargs,
|
|
345
|
+
ka=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
346
|
+
kb=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
347
|
+
)
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
# add case ka:
|
|
351
|
+
t = name_template[:i0] + "_ka<ka>"
|
|
352
|
+
if len(name_template) > i1:
|
|
353
|
+
t += name_template[i1:]
|
|
354
|
+
h = hints.copy()
|
|
355
|
+
h["ka"] = "(Value, e.g. 04 for 0.4)"
|
|
356
|
+
kw["ti_var"] = FV.TI
|
|
357
|
+
self.factories.append(
|
|
358
|
+
Factory(
|
|
359
|
+
base,
|
|
360
|
+
t,
|
|
361
|
+
*args,
|
|
362
|
+
hints=h,
|
|
363
|
+
kwargs=kw.copy(),
|
|
364
|
+
**kwargs,
|
|
365
|
+
ka=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
366
|
+
)
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
# add case ka:
|
|
370
|
+
t = name_template[:i0] + "_ambka<ka>"
|
|
371
|
+
if len(name_template) > i1:
|
|
372
|
+
t += name_template[i1:]
|
|
373
|
+
h = hints.copy()
|
|
374
|
+
h["ka"] = "(Value, e.g. 04 for 0.4)"
|
|
375
|
+
kw["ti_var"] = FV.AMB_TI
|
|
376
|
+
self.factories.append(
|
|
377
|
+
Factory(
|
|
378
|
+
base,
|
|
379
|
+
t,
|
|
380
|
+
*args,
|
|
381
|
+
hints=h,
|
|
382
|
+
kwargs=kw.copy(),
|
|
383
|
+
**kwargs,
|
|
384
|
+
ka=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
385
|
+
)
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
# add case k:
|
|
389
|
+
t = name_template[:i0] + "_k<k>"
|
|
390
|
+
if len(name_template) > i1:
|
|
391
|
+
t += name_template[i1:]
|
|
392
|
+
h = hints.copy()
|
|
393
|
+
h["k"] = "(Value, e.g. 004 for 0.04)"
|
|
394
|
+
kw["ti_var"] = FV.TI
|
|
395
|
+
self.factories.append(
|
|
396
|
+
Factory(
|
|
397
|
+
base,
|
|
398
|
+
t,
|
|
399
|
+
*args,
|
|
400
|
+
hints=h,
|
|
401
|
+
kwargs=kw.copy(),
|
|
402
|
+
**kwargs,
|
|
403
|
+
k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
404
|
+
)
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
# add case without k:
|
|
408
|
+
t = name_template[:i0]
|
|
409
|
+
if len(name_template) > i1:
|
|
410
|
+
t += name_template[i1:]
|
|
411
|
+
kw["ti_var"] = FV.TI
|
|
412
|
+
self.factories.append(
|
|
413
|
+
Factory(
|
|
414
|
+
base,
|
|
415
|
+
t,
|
|
416
|
+
*args,
|
|
417
|
+
hints=hints,
|
|
418
|
+
kwargs=kw.copy(),
|
|
419
|
+
**kwargs,
|
|
420
|
+
)
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
def __str__(self):
|
|
424
|
+
"""String representation"""
|
|
425
|
+
s = f"{self._template0}: {self._base.__name__} with"
|
|
426
|
+
for k, d in self._kwargs.items():
|
|
427
|
+
s += f"\n {k}={d}"
|
|
428
|
+
f0 = self.factories[-1]
|
|
429
|
+
for v in f0.variables:
|
|
430
|
+
if v in f0.options and isinstance(f0.options[v], dict):
|
|
431
|
+
s += f"\n {v} from {list(f0.options[v])}"
|
|
432
|
+
else:
|
|
433
|
+
s += f"\n {v}={f0.hints.get(v, '(value)')}"
|
|
434
|
+
s += (
|
|
435
|
+
f"\n [wake_k]=(None or k<k> or ka<ka> or ka<ka>_kb<kb>, e.g. 004 for 0.04)"
|
|
436
|
+
)
|
|
437
|
+
return s
|
|
438
|
+
|
|
439
|
+
|
|
249
440
|
class FDict(Dict):
|
|
250
441
|
"""
|
|
251
442
|
A dictionary with factory support
|
|
252
|
-
|
|
443
|
+
|
|
253
444
|
Attributes
|
|
254
445
|
----------
|
|
255
446
|
store_created: bool
|
|
256
447
|
Flag for storing created objects
|
|
257
448
|
factories: list of foxes.utils.Factory
|
|
258
449
|
The factories
|
|
259
|
-
|
|
450
|
+
|
|
260
451
|
:group: utils
|
|
261
|
-
|
|
452
|
+
|
|
262
453
|
"""
|
|
454
|
+
|
|
263
455
|
def __init__(self, *args, store_created=True, **kwargs):
|
|
264
456
|
"""
|
|
265
457
|
Constructor.
|
|
266
|
-
|
|
458
|
+
|
|
267
459
|
Parameters
|
|
268
460
|
----------
|
|
269
461
|
args: tuple, optional
|
|
@@ -272,30 +464,32 @@ class FDict(Dict):
|
|
|
272
464
|
Flag for storing created objects
|
|
273
465
|
kwargs: dict, optional
|
|
274
466
|
Parameters for the base class
|
|
275
|
-
|
|
467
|
+
|
|
276
468
|
"""
|
|
277
469
|
super().__init__(*args, **kwargs)
|
|
278
470
|
self.store_created = store_created
|
|
279
471
|
self.factories = []
|
|
280
472
|
|
|
281
|
-
def add_factory(self, *args, **kwargs):
|
|
473
|
+
def add_factory(self, *args, factory=None, **kwargs):
|
|
282
474
|
"""
|
|
283
|
-
|
|
284
|
-
|
|
475
|
+
Adds a Factory object.
|
|
476
|
+
|
|
285
477
|
Parameters
|
|
286
478
|
----------
|
|
287
479
|
args: tuple, optional
|
|
288
480
|
Parameters for the Factory constructor
|
|
481
|
+
factory: Factory, optional
|
|
482
|
+
The factory object
|
|
289
483
|
kwargs: dict, optional
|
|
290
484
|
Parameters for the Factory constructor
|
|
291
|
-
|
|
485
|
+
|
|
292
486
|
"""
|
|
293
|
-
f = Factory(*args, **kwargs)
|
|
487
|
+
f = Factory(*args, **kwargs) if factory is None else factory
|
|
294
488
|
i = len(self.factories)
|
|
295
489
|
for gi in range(len(self.factories) - 1, -1, -1):
|
|
296
490
|
g = self.factories[gi]
|
|
297
491
|
if (
|
|
298
|
-
g.name_prefix == f.name_prefix
|
|
492
|
+
g.name_prefix == f.name_prefix
|
|
299
493
|
and g.name_suffix == f.name_suffix
|
|
300
494
|
and len(f.variables) > len(g.variables)
|
|
301
495
|
):
|
|
@@ -306,6 +500,21 @@ class FDict(Dict):
|
|
|
306
500
|
else:
|
|
307
501
|
self.factories.insert(i, f)
|
|
308
502
|
|
|
503
|
+
def add_k_factory(self, *args, **kwargs):
|
|
504
|
+
"""
|
|
505
|
+
Adds a WakeKFactory.
|
|
506
|
+
|
|
507
|
+
Parameters
|
|
508
|
+
----------
|
|
509
|
+
args: tuple, optional
|
|
510
|
+
Parameters for the Factory constructor
|
|
511
|
+
kwargs: dict, optional
|
|
512
|
+
Parameters for the Factory constructor
|
|
513
|
+
|
|
514
|
+
"""
|
|
515
|
+
for f in WakeKFactory(*args, **kwargs).factories:
|
|
516
|
+
self.add_factory(factory=f)
|
|
517
|
+
|
|
309
518
|
def __contains__(self, key):
|
|
310
519
|
found = super().__contains__(key)
|
|
311
520
|
if not found:
|
|
@@ -330,4 +539,3 @@ class FDict(Dict):
|
|
|
330
539
|
k = ", ".join(sorted(list(self.keys())))
|
|
331
540
|
e = f"{self.name}: Cannot find key '{key}', also no factory matches. Known keys: {k}. Known factories: {[f.name_template for f in self.factories]}"
|
|
332
541
|
raise KeyError(e)
|
|
333
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: foxes
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.3
|
|
4
4
|
Summary: Farm Optimization and eXtended yield Evaluation Software
|
|
5
5
|
Author: Fraunhofer IWES
|
|
6
6
|
Author-email: jonas.schmidt@iwes.fraunhofer.de
|
|
@@ -17,16 +17,18 @@ Requires-Python: >=3.8
|
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
19
|
Requires-Dist: matplotlib
|
|
20
|
-
Requires-Dist: numpy
|
|
20
|
+
Requires-Dist: numpy <2
|
|
21
|
+
Requires-Dist: pandas
|
|
21
22
|
Requires-Dist: xarray
|
|
22
|
-
Requires-Dist: dask
|
|
23
|
+
Requires-Dist: dask
|
|
24
|
+
Requires-Dist: distributed
|
|
23
25
|
Requires-Dist: scipy
|
|
24
26
|
Requires-Dist: netcdf4
|
|
25
27
|
Requires-Dist: windrose
|
|
26
28
|
Requires-Dist: iwopy >=0.1.4
|
|
27
29
|
Requires-Dist: pyarrow
|
|
28
30
|
Provides-Extra: all
|
|
29
|
-
Requires-Dist: windio >=1
|
|
31
|
+
Requires-Dist: windio >=1 ; extra == 'all'
|
|
30
32
|
Requires-Dist: flake8 ; extra == 'all'
|
|
31
33
|
Requires-Dist: pytest ; extra == 'all'
|
|
32
34
|
Requires-Dist: pymoo >=0.6 ; extra == 'all'
|
|
@@ -45,7 +47,7 @@ Requires-Dist: ipywidgets ; extra == 'doc'
|
|
|
45
47
|
Requires-Dist: m2r2 ; extra == 'doc'
|
|
46
48
|
Requires-Dist: lxml-html-clean ; extra == 'doc'
|
|
47
49
|
Provides-Extra: io
|
|
48
|
-
Requires-Dist: windio >=1
|
|
50
|
+
Requires-Dist: windio >=1 ; extra == 'io'
|
|
49
51
|
Provides-Extra: scripts
|
|
50
52
|
Provides-Extra: test
|
|
51
53
|
Requires-Dist: flake8 ; extra == 'test'
|
|
@@ -170,7 +172,7 @@ The supported Python versions are:
|
|
|
170
172
|
- `Python 3.11`
|
|
171
173
|
- `Python 3.12`
|
|
172
174
|
|
|
173
|
-
### Preparation
|
|
175
|
+
### Preparation (optional)
|
|
174
176
|
|
|
175
177
|
It is strongly recommend to use the `libmamba` dependency solver instead of the default solver. Install it once by
|
|
176
178
|
|