foxes 0.6.2__py3-none-any.whl → 0.7.0.2__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.

Files changed (120) hide show
  1. foxes/VERSION +1 -1
  2. foxes/algorithms/downwind/downwind.py +131 -65
  3. foxes/algorithms/downwind/models/__init__.py +2 -1
  4. foxes/algorithms/downwind/models/farm_wakes_calc.py +87 -55
  5. foxes/algorithms/downwind/models/init_farm_data.py +134 -0
  6. foxes/algorithms/downwind/models/point_wakes_calc.py +54 -65
  7. foxes/algorithms/downwind/models/{calc_order.py → reorder_farm_output.py} +28 -26
  8. foxes/algorithms/iterative/iterative.py +100 -51
  9. foxes/algorithms/iterative/models/convergence.py +3 -3
  10. foxes/algorithms/iterative/models/farm_wakes_calc.py +55 -48
  11. foxes/algorithms/sequential/models/seq_state.py +7 -6
  12. foxes/algorithms/sequential/sequential.py +81 -44
  13. foxes/constants.py +33 -18
  14. foxes/core/__init__.py +2 -2
  15. foxes/core/algorithm.py +31 -12
  16. foxes/core/data.py +335 -41
  17. foxes/core/data_calc_model.py +27 -23
  18. foxes/core/farm_controller.py +27 -28
  19. foxes/core/farm_data_model.py +26 -4
  20. foxes/core/model.py +186 -129
  21. foxes/core/partial_wakes_model.py +84 -81
  22. foxes/core/point_data_model.py +51 -18
  23. foxes/core/rotor_model.py +59 -77
  24. foxes/core/states.py +6 -6
  25. foxes/core/turbine_model.py +4 -4
  26. foxes/core/turbine_type.py +24 -0
  27. foxes/core/vertical_profile.py +3 -3
  28. foxes/core/wake_frame.py +91 -50
  29. foxes/core/wake_model.py +74 -43
  30. foxes/core/wake_superposition.py +29 -26
  31. foxes/input/farm_layout/from_random.py +10 -9
  32. foxes/input/states/create/random_timeseries.py +17 -19
  33. foxes/input/states/field_data_nc.py +12 -8
  34. foxes/input/states/multi_height.py +24 -14
  35. foxes/input/states/scan_ws.py +13 -17
  36. foxes/input/states/single.py +28 -20
  37. foxes/input/states/states_table.py +22 -18
  38. foxes/models/axial_induction_models/betz.py +1 -1
  39. foxes/models/farm_models/turbine2farm.py +2 -2
  40. foxes/models/model_book.py +39 -14
  41. foxes/models/partial_wakes/__init__.py +2 -3
  42. foxes/models/partial_wakes/axiwake.py +73 -200
  43. foxes/models/partial_wakes/centre.py +11 -79
  44. foxes/models/partial_wakes/grid.py +7 -63
  45. foxes/models/partial_wakes/rotor_points.py +53 -147
  46. foxes/models/partial_wakes/segregated.py +158 -0
  47. foxes/models/partial_wakes/top_hat.py +88 -196
  48. foxes/models/point_models/set_uniform_data.py +4 -4
  49. foxes/models/point_models/tke2ti.py +4 -4
  50. foxes/models/point_models/wake_deltas.py +4 -4
  51. foxes/models/rotor_models/centre.py +15 -19
  52. foxes/models/rotor_models/grid.py +2 -1
  53. foxes/models/rotor_models/levels.py +2 -1
  54. foxes/models/turbine_models/__init__.py +0 -1
  55. foxes/models/turbine_models/calculator.py +11 -7
  56. foxes/models/turbine_models/kTI_model.py +13 -11
  57. foxes/models/turbine_models/lookup_table.py +22 -9
  58. foxes/models/turbine_models/power_mask.py +81 -51
  59. foxes/models/turbine_models/rotor_centre_calc.py +17 -20
  60. foxes/models/turbine_models/sector_management.py +5 -6
  61. foxes/models/turbine_models/set_farm_vars.py +49 -20
  62. foxes/models/turbine_models/table_factors.py +5 -5
  63. foxes/models/turbine_models/thrust2ct.py +9 -5
  64. foxes/models/turbine_models/yaw2yawm.py +7 -13
  65. foxes/models/turbine_models/yawm2yaw.py +7 -11
  66. foxes/models/turbine_types/PCt_file.py +84 -3
  67. foxes/models/turbine_types/PCt_from_two.py +7 -3
  68. foxes/models/turbine_types/null_type.py +2 -2
  69. foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -2
  70. foxes/models/turbine_types/wsti2PCt_from_two.py +6 -2
  71. foxes/models/wake_frames/farm_order.py +26 -22
  72. foxes/models/wake_frames/rotor_wd.py +32 -31
  73. foxes/models/wake_frames/seq_dynamic_wakes.py +112 -64
  74. foxes/models/wake_frames/streamlines.py +51 -47
  75. foxes/models/wake_frames/timelines.py +59 -47
  76. foxes/models/wake_frames/yawed_wakes.py +63 -40
  77. foxes/models/wake_models/axisymmetric.py +31 -35
  78. foxes/models/wake_models/dist_sliced.py +50 -56
  79. foxes/models/wake_models/gaussian.py +33 -35
  80. foxes/models/wake_models/induction/rankine_half_body.py +79 -87
  81. foxes/models/wake_models/induction/rathmann.py +56 -63
  82. foxes/models/wake_models/induction/self_similar.py +59 -62
  83. foxes/models/wake_models/ti/crespo_hernandez.py +83 -74
  84. foxes/models/wake_models/ti/iec_ti.py +65 -75
  85. foxes/models/wake_models/top_hat.py +60 -69
  86. foxes/models/wake_models/wake_mirror.py +49 -54
  87. foxes/models/wake_models/wind/bastankhah14.py +44 -66
  88. foxes/models/wake_models/wind/bastankhah16.py +84 -111
  89. foxes/models/wake_models/wind/jensen.py +67 -89
  90. foxes/models/wake_models/wind/turbopark.py +93 -133
  91. foxes/models/wake_superpositions/ti_linear.py +33 -27
  92. foxes/models/wake_superpositions/ti_max.py +33 -27
  93. foxes/models/wake_superpositions/ti_pow.py +35 -27
  94. foxes/models/wake_superpositions/ti_quadratic.py +33 -27
  95. foxes/models/wake_superpositions/ws_linear.py +39 -32
  96. foxes/models/wake_superpositions/ws_max.py +40 -33
  97. foxes/models/wake_superpositions/ws_pow.py +39 -32
  98. foxes/models/wake_superpositions/ws_product.py +35 -28
  99. foxes/models/wake_superpositions/ws_quadratic.py +39 -32
  100. foxes/opt/problems/layout/farm_layout.py +38 -97
  101. foxes/output/__init__.py +1 -0
  102. foxes/output/flow_plots_2d/flow_plots.py +2 -0
  103. foxes/output/rose_plot.py +3 -3
  104. foxes/output/rotor_point_plots.py +117 -0
  105. foxes/output/turbine_type_curves.py +2 -2
  106. foxes/utils/__init__.py +1 -1
  107. foxes/utils/load.py +29 -0
  108. foxes/utils/random_xy.py +11 -10
  109. foxes/utils/runners/runners.py +3 -4
  110. foxes/utils/windrose_plot.py +1 -1
  111. foxes/variables.py +10 -0
  112. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/METADATA +13 -7
  113. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/RECORD +117 -117
  114. foxes/models/partial_wakes/distsliced.py +0 -322
  115. foxes/models/partial_wakes/mapped.py +0 -252
  116. foxes/models/turbine_models/set_XYHD.py +0 -130
  117. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/LICENSE +0 -0
  118. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/WHEEL +0 -0
  119. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/top_level.txt +0 -0
  120. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/zip-safe +0 -0
@@ -1,322 +0,0 @@
1
- import numpy as np
2
-
3
- from foxes.core import PartialWakesModel, Data
4
- from foxes.models.wake_models.dist_sliced import DistSlicedWakeModel
5
- from foxes.models.rotor_models.grid import GridRotor
6
- from foxes.utils import wd2uv, uv2wd
7
- import foxes.variables as FV
8
- import foxes.constants as FC
9
-
10
-
11
- class PartialDistSlicedWake(PartialWakesModel):
12
- """
13
- Partial wakes for distance sliced wake models,
14
- making use of their structure.
15
-
16
- The evaluations are optinally done on a grid rotor
17
- that can differ from the algorithm's rotor model.
18
-
19
- Attributes
20
- ----------
21
- rotor_model: foxes.core.RotorModel
22
- The rotor model, default is the one from the algorithm
23
- grotor: foxes.models.rotor_models.GridRotor
24
- The grid rotor model
25
-
26
- :group: models.partial_wakes
27
-
28
- """
29
-
30
- def __init__(
31
- self, n=None, wake_models=None, wake_frame=None, rotor_model=None, **kwargs
32
- ):
33
- """
34
- Constructor.
35
-
36
- Parameters
37
- ----------
38
- n: int, optional
39
- The `GridRotor`'s `n` parameter
40
- wake_models: list of foxes.core.WakeModel, optional
41
- The wake models, default are the ones from the algorithm
42
- wake_frame: foxes.core.WakeFrame, optional
43
- The wake frame, default is the one from the algorithm
44
- rotor_model: foxes.core.RotorModel, optional
45
- The rotor model, default is the one from the algorithm
46
- kwargs: dict, optional
47
- Additional parameters for the `GridRotor`
48
-
49
- """
50
- super().__init__(wake_models, wake_frame)
51
-
52
- self.rotor_model = rotor_model
53
- self.grotor = None if n is None else GridRotor(n=n, calc_vars=[], **kwargs)
54
-
55
- def __repr__(self):
56
- if self.grotor is not None:
57
- return super().__repr__() + f"(n={self.grotor.n})"
58
- elif self.rotor_model is not None and isinstance(self.rotor_model, GridRotor):
59
- return super().__repr__() + f"(n={self.rotor_model.n})"
60
- else:
61
- return super().__repr__()
62
-
63
- def initialize(self, algo, verbosity=0):
64
- """
65
- Initializes the model.
66
-
67
- Parameters
68
- ----------
69
- algo: foxes.core.Algorithm
70
- The calculation algorithm
71
- verbosity: int
72
- The verbosity level, 0 = silent
73
-
74
- """
75
- if self.rotor_model is None:
76
- self.rotor_model = algo.rotor_model
77
- if self.grotor is None:
78
- self.grotor = self.rotor_model
79
-
80
- super().initialize(algo, verbosity)
81
-
82
- for w in self.wake_models:
83
- if not isinstance(w, DistSlicedWakeModel):
84
- raise TypeError(
85
- f"Partial wakes '{self.name}': Cannot be applied to wake model '{w.name}', since not an DistSlicedWakeModel"
86
- )
87
-
88
- self.YZ = self.var("YZ")
89
- self.W = self.var(FV.WEIGHT)
90
-
91
- def sub_models(self):
92
- """
93
- List of all sub-models
94
-
95
- Returns
96
- -------
97
- smdls: list of foxes.core.Model
98
- Names of all sub models
99
-
100
- """
101
- return super().sub_models() + [self.rotor_model, self.grotor]
102
-
103
- def new_wake_deltas(self, algo, mdata, fdata):
104
- """
105
- Creates new initial wake deltas, filled
106
- with zeros.
107
-
108
- Parameters
109
- ----------
110
- algo: foxes.core.Algorithm
111
- The calculation algorithm
112
- mdata: foxes.core.Data
113
- The model data
114
- fdata: foxes.core.Data
115
- The farm data
116
-
117
- Returns
118
- -------
119
- wake_deltas: dict
120
- Keys: Variable name str, values: any
121
- pdata: foxes.core.Data
122
- The evaluation point data
123
-
124
- """
125
-
126
- n_states = fdata.n_states
127
- n_rpoints = self.grotor.n_rotor_points()
128
- n_points = fdata.n_turbines * n_rpoints
129
- points = self.grotor.get_rotor_points(algo, mdata, fdata).reshape(
130
- n_states, n_points, 3
131
- )
132
- pdata = Data.from_points(points=points)
133
-
134
- wake_deltas = {}
135
- for w in self.wake_models:
136
- w.init_wake_deltas(algo, mdata, fdata, pdata, wake_deltas)
137
-
138
- return wake_deltas, pdata
139
-
140
- def contribute_to_wake_deltas(
141
- self,
142
- algo,
143
- mdata,
144
- fdata,
145
- pdata,
146
- states_source_turbine,
147
- wake_deltas,
148
- ):
149
- """
150
- Modifies wake deltas by contributions from the
151
- specified wake source turbines.
152
-
153
- Parameters
154
- ----------
155
- algo: foxes.core.Algorithm
156
- The calculation algorithm
157
- mdata: foxes.core.Data
158
- The model data
159
- fdata: foxes.core.Data
160
- The farm data
161
- pdata: foxes.core.Data
162
- The evaluation point data
163
- states_source_turbine: numpy.ndarray of int
164
- For each state, one turbine index corresponding
165
- to the wake causing turbine. Shape: (n_states,)
166
- wake_deltas: Any
167
- The wake deltas object created by the
168
- `new_wake_deltas` function
169
-
170
- """
171
-
172
- # calc x-coordinates of rotor centres:
173
- hpdata = Data.from_points(points=fdata[FV.TXYH])
174
- x = self.wake_frame.get_wake_coos(
175
- algo, mdata, fdata, hpdata, states_source_turbine
176
- )[:, :, 0]
177
-
178
- # evaluate grid rotor:
179
- n_states = fdata.n_states
180
- n_turbines = fdata.n_turbines
181
- n_rpoints = self.grotor.n_rotor_points()
182
- n_points = fdata.n_turbines * n_rpoints
183
- wcoos = self.wake_frame.get_wake_coos(
184
- algo, mdata, fdata, pdata, states_source_turbine
185
- )
186
- yz = wcoos.reshape(n_states, n_turbines, n_rpoints, 3)[:, :, :, 1:3]
187
- del wcoos
188
-
189
- # evaluate wake models:
190
- for w in self.wake_models:
191
- wdeltas, sp_sel = w.calc_wakes_spsel_x_yz(
192
- algo, mdata, fdata, hpdata, states_source_turbine, x, yz
193
- )
194
-
195
- wsps = np.zeros((n_states, n_turbines, n_rpoints), dtype=bool)
196
- wsps[:] = sp_sel[:, :, None]
197
- wsps = wsps.reshape(n_states, n_points)
198
-
199
- for v, wdel in wdeltas.items():
200
- d = np.zeros((n_states, n_turbines, n_rpoints), dtype=FC.DTYPE)
201
- d[sp_sel] = wdel
202
- d = d.reshape(n_states, n_points)[wsps]
203
-
204
- try:
205
- superp = w.superp[v]
206
- except KeyError:
207
- raise KeyError(
208
- f"Model '{self.name}': Missing wake superposition entry for variable '{v}' in wake model '{w.name}', found {sorted(list(w.superp.keys()))}"
209
- )
210
-
211
- wake_deltas[v] = superp.calc_wakes_plus_wake(
212
- algo,
213
- mdata,
214
- fdata,
215
- pdata,
216
- states_source_turbine,
217
- wsps,
218
- v,
219
- wake_deltas[v],
220
- d,
221
- )
222
-
223
- def evaluate_results(
224
- self,
225
- algo,
226
- mdata,
227
- fdata,
228
- pdata,
229
- wake_deltas,
230
- states_turbine,
231
- amb_res=None,
232
- ):
233
- """
234
- Updates the farm data according to the wake
235
- deltas.
236
-
237
- Parameters
238
- ----------
239
- algo: foxes.core.Algorithm
240
- The calculation algorithm
241
- mdata: foxes.core.Data
242
- The model data
243
- fdata: foxes.core.Data
244
- The farm data
245
- Modified in-place by this function
246
- pdata: foxes.core.Data
247
- The evaluation point data
248
- wake_deltas: Any
249
- The wake deltas object, created by the
250
- `new_wake_deltas` function and filled
251
- by `contribute_to_wake_deltas`
252
- states_turbine: numpy.ndarray of int
253
- For each state, the index of one turbine
254
- for which to evaluate the wake deltas.
255
- Shape: (n_states,)
256
- amb_res: dict, optional
257
- Ambient states results. Keys: var str, values:
258
- numpy.ndarray of shape (n_states, n_points)
259
-
260
- """
261
- rweights = algo.rotor_model.from_data_or_store(FC.RWEIGHTS, algo, mdata)
262
- rpoints = algo.rotor_model.from_data_or_store(FC.RPOINTS, algo, mdata)
263
- n_states, n_turbines, n_rpoints, __ = rpoints.shape
264
-
265
- amb_res_in = amb_res is not None
266
- if not amb_res_in:
267
- amb_res = algo.rotor_model.from_data_or_store(
268
- FC.AMB_RPOINT_RESULTS, algo, mdata
269
- )
270
-
271
- wweights = self.grotor.rotor_point_weights()
272
- n_wpoints = self.grotor.n_rotor_points()
273
- n_states, n_turbines, n_rpoints, __ = rpoints.shape
274
- st_sel = (np.arange(n_states), states_turbine)
275
-
276
- uv = None
277
- if (FV.WS in amb_res and FV.WD not in amb_res) or (
278
- FV.WS not in amb_res and FV.WD in amb_res
279
- ):
280
- raise KeyError(
281
- f"Model '{self.name}': Missing one of the variables '{FV.WS}', '{FV.WD}' in ambient rotor results: {list(amb_res.keys())}"
282
- )
283
-
284
- elif FV.WD in amb_res and np.any(
285
- np.min(amb_res[FV.WD], axis=2) != np.max(amb_res[FV.WD], axis=2)
286
- ):
287
- wd = amb_res[FV.WD].reshape(n_states, n_turbines, n_rpoints)[st_sel]
288
- ws = amb_res[FV.WS].reshape(n_states, n_turbines, n_rpoints)[st_sel]
289
- uv = wd2uv(wd, ws, axis=-1)
290
- uv = np.einsum("spd,p->sd", uv, rweights)
291
- del ws, wd
292
-
293
- wres = {}
294
- for v, ares in amb_res.items():
295
- if v == FV.WS and uv is not None:
296
- wres[v] = np.linalg.norm(uv, axis=-1)
297
- elif v == FV.WD and uv is not None:
298
- wres[v] = uv2wd(uv, axis=-1)
299
- else:
300
- wres[v] = ares.reshape(n_states, n_turbines, n_rpoints)[st_sel]
301
- wres[v] = np.einsum("sp,p->s", wres[v], rweights)
302
- wres[v] = wres[v][:, None]
303
- del uv
304
-
305
- wdel = {}
306
- for v, d in wake_deltas.items():
307
- wdel[v] = d.reshape(n_states, n_turbines, n_wpoints)[st_sel]
308
- for w in self.wake_models:
309
- w.finalize_wake_deltas(algo, mdata, fdata, pdata, wres, wdel)
310
- for v in wdel.keys():
311
- wdel[v] = np.einsum("sp,p->s", wdel[v], wweights)[:, None]
312
-
313
- for v in wres.keys():
314
- if v in wake_deltas:
315
- wres[v] += wdel[v]
316
- if amb_res_in:
317
- amb_res[v][st_sel] = wres[v]
318
- wres[v] = wres[v][:, None]
319
-
320
- self.rotor_model.eval_rpoint_results(
321
- algo, mdata, fdata, wres, np.array([1.0]), states_turbine=states_turbine
322
- )
@@ -1,252 +0,0 @@
1
- from copy import deepcopy
2
-
3
- from foxes.core import PartialWakesModel
4
- from foxes.models.partial_wakes.rotor_points import RotorPoints
5
- from foxes.models.partial_wakes.top_hat import PartialTopHat
6
- from foxes.models.partial_wakes.axiwake import PartialAxiwake
7
- from foxes.models.partial_wakes.distsliced import PartialDistSlicedWake
8
- from foxes.models.wake_models.top_hat import TopHatWakeModel
9
- from foxes.models.wake_models.dist_sliced import DistSlicedWakeModel
10
- from foxes.models.wake_models.axisymmetric import AxisymmetricWakeModel
11
- import foxes.constants as FC
12
-
13
-
14
- class Mapped(PartialWakesModel):
15
- """
16
- Partial wake models depending on the wake model (type).
17
-
18
- This is required if more than one wake models are
19
- used and different partial wake models should be invoked.
20
-
21
- Attributes
22
- ----------
23
- wname2pwake: dict
24
- Mapping from wake model name to partial wakes.
25
- Key: model name str, value: Tuple of length 2,
26
- (Partial wake class name, parameter dict)
27
- wtype2pwake: dict
28
- Mapping from wake model class name to partial wakes.
29
- Key: wake model class name str, value: Tuple of length 2,
30
- (Partial wake class name, parameter dict)
31
-
32
- :group: models.partial_wakes
33
-
34
- """
35
-
36
- def __init__(
37
- self, wname2pwake={}, wtype2pwake=None, wake_models=None, wake_frame=None
38
- ):
39
- """
40
- Constructor.
41
-
42
- Parameters
43
- ----------
44
- wname2pwake: dict, optional
45
- Mapping from wake model name to partial wakes.
46
- Key: model name str, value: Tuple of length 2,
47
- (Partial wake class name, parameter dict)
48
- wtype2pwake: dict, optional
49
- Mapping from wake model class name to partial wakes.
50
- Key: wake model class name str, value: Tuple of length 2,
51
- (Partial wake class name, parameter dict)
52
- wake_models: list of foxes.core.WakeModel, optional
53
- The wake models, default are the ones from the algorithm
54
- wake_frame: foxes.core.WakeFrame, optional
55
- The wake frame, default is the one from the algorithm
56
-
57
- """
58
- super().__init__(wake_models, wake_frame)
59
-
60
- self.wname2pwake = wname2pwake
61
-
62
- if wtype2pwake is None:
63
- self.wtype2pwake = {
64
- TopHatWakeModel: (PartialTopHat.__name__, {}),
65
- AxisymmetricWakeModel: (PartialAxiwake.__name__, {"n": 6}),
66
- DistSlicedWakeModel: (PartialDistSlicedWake.__name__, {"n": 9}),
67
- }
68
- else:
69
- self.wtype2pwake = wtype2pwake
70
-
71
- self._pwakes = None
72
-
73
- def initialize(self, algo, verbosity=0):
74
- """
75
- Initializes the model.
76
-
77
- Parameters
78
- ----------
79
- algo: foxes.core.Algorithm
80
- The calculation algorithm
81
- verbosity: int
82
- The verbosity level, 0 = silent
83
-
84
- """
85
- self.wake_models = algo.wake_models if self._wmodels is None else self._wmodels
86
- self.wake_frame = algo.wake_frame if self._wframe is None else self._wframe
87
-
88
- pws = {}
89
- for w in self.wake_models:
90
- pdat = None
91
- if w.name in self.wname2pwake:
92
- pdat = deepcopy(self.wname2pwake[w.name])
93
-
94
- if pdat is None:
95
- for pwcls, tdat in self.wtype2pwake.items():
96
- if isinstance(w, pwcls):
97
- pdat = deepcopy(tdat)
98
- break
99
-
100
- if pdat is None:
101
- pdat = (RotorPoints.__name__, {})
102
-
103
- pname = pdat[0]
104
- if pname not in pws:
105
- pws[pname] = pdat[1]
106
- pws[pname]["wake_models"] = []
107
- pws[pname]["wake_frame"] = self.wake_frame
108
- pws[pname]["wake_models"].append(w)
109
-
110
- self._pwakes = []
111
- for pname, pars in pws.items():
112
- if verbosity:
113
- print(
114
- f"Partial wakes '{self.name}': Applying {pname} to {[w.name for w in pars['wake_models']]}"
115
- )
116
- self._pwakes.append(PartialWakesModel.new(pname, **pars))
117
-
118
- super().initialize(algo, verbosity)
119
-
120
- def sub_models(self):
121
- """
122
- List of all sub-models
123
-
124
- Returns
125
- -------
126
- smdls: list of foxes.core.Model
127
- Names of all sub models
128
-
129
- """
130
- return super().sub_models() + self._pwakes
131
-
132
- def new_wake_deltas(self, algo, mdata, fdata):
133
- """
134
- Creates new initial wake deltas, filled
135
- with zeros.
136
-
137
- Parameters
138
- ----------
139
- algo: foxes.core.Algorithm
140
- The calculation algorithm
141
- mdata: foxes.core.Data
142
- The model data
143
- fdata: foxes.core.Data
144
- The farm data
145
-
146
- Returns
147
- -------
148
- wake_deltas: dict
149
- Keys: Variable name str, values: any
150
- pdata: foxes.core.Data
151
- The evaluation point data
152
-
153
- """
154
- wdeltas = []
155
- pdatas = []
156
- for pw in self._pwakes:
157
- w, p = pw.new_wake_deltas(algo, mdata, fdata)
158
- wdeltas.append(w)
159
- pdatas.append(p)
160
-
161
- return wdeltas, pdatas
162
-
163
- def contribute_to_wake_deltas(
164
- self,
165
- algo,
166
- mdata,
167
- fdata,
168
- pdata,
169
- states_source_turbine,
170
- wake_deltas,
171
- ):
172
- """
173
- Modifies wake deltas by contributions from the
174
- specified wake source turbines.
175
-
176
- Parameters
177
- ----------
178
- algo: foxes.core.Algorithm
179
- The calculation algorithm
180
- mdata: foxes.core.Data
181
- The model data
182
- fdata: foxes.core.Data
183
- The farm data
184
- pdata: foxes.core.Data
185
- The evaluation point data
186
- states_source_turbine: numpy.ndarray of int
187
- For each state, one turbine index corresponding
188
- to the wake causing turbine. Shape: (n_states,)
189
- wake_deltas: Any
190
- The wake deltas object created by the
191
- `new_wake_deltas` function
192
-
193
- """
194
- for pwi, pw in enumerate(self._pwakes):
195
- pw.contribute_to_wake_deltas(
196
- algo, mdata, fdata, pdata[pwi], states_source_turbine, wake_deltas[pwi]
197
- )
198
-
199
- def evaluate_results(
200
- self,
201
- algo,
202
- mdata,
203
- fdata,
204
- pdata,
205
- wake_deltas,
206
- states_turbine,
207
- amb_res=None,
208
- ):
209
- """
210
- Updates the farm data according to the wake
211
- deltas.
212
-
213
- Parameters
214
- ----------
215
- algo: foxes.core.Algorithm
216
- The calculation algorithm
217
- mdata: foxes.core.Data
218
- The model data
219
- fdata: foxes.core.Data
220
- The farm data
221
- Modified in-place by this function
222
- pdata: foxes.core.Data
223
- The evaluation point data
224
- wake_deltas: Any
225
- The wake deltas object, created by the
226
- `new_wake_deltas` function and filled
227
- by `contribute_to_wake_deltas`
228
- states_turbine: numpy.ndarray of int
229
- For each state, the index of one turbine
230
- for which to evaluate the wake deltas.
231
- Shape: (n_states,)
232
- amb_res: dict, optional
233
- Ambient states results. Keys: var str, values:
234
- numpy.ndarray of shape (n_states, n_points)
235
-
236
- """
237
- if amb_res is None:
238
- ares = algo.rotor_model.from_data_or_store(
239
- FC.AMB_RPOINT_RESULTS, algo, mdata
240
- ).copy()
241
- amb_res = {v: d.copy() for v, d in ares.items()}
242
-
243
- for pwi, pw in enumerate(self._pwakes):
244
- pw.evaluate_results(
245
- algo,
246
- mdata,
247
- fdata,
248
- pdata[pwi],
249
- wake_deltas[pwi],
250
- states_turbine,
251
- amb_res=amb_res,
252
- )
@@ -1,130 +0,0 @@
1
- import numpy as np
2
-
3
- from foxes.core import TurbineModel
4
- import foxes.variables as FV
5
- import foxes.constants as FC
6
-
7
-
8
- class SetXYHD(TurbineModel):
9
- """
10
- Sets basic turbine data, from
11
- turbine object to farm data.
12
-
13
- Attributes
14
- ----------
15
- set_XY: bool
16
- Flag for (x,y) data
17
- set_H: bool
18
- Flag for height data
19
- set_D: bool
20
- Flag for rotor diameter data
21
-
22
- :group: models.turbine_models
23
-
24
- """
25
-
26
- def __init__(self, set_XY=True, set_H=True, set_D=True):
27
- """
28
- Constructor.
29
-
30
- Parameters
31
- ----------
32
- set_XY: bool
33
- Flag for (x,y) data
34
- set_H: bool
35
- Flag for height data
36
- set_D: bool
37
- Flag for rotor diameter data
38
-
39
- """
40
- super().__init__()
41
-
42
- self.set_XY = set_XY
43
- self.set_H = set_H
44
- self.set_D = set_D
45
-
46
- def output_farm_vars(self, algo):
47
- """
48
- The variables which are being modified by the model.
49
-
50
- Parameters
51
- ----------
52
- algo: foxes.core.Algorithm
53
- The calculation algorithm
54
-
55
- Returns
56
- -------
57
- output_vars: list of str
58
- The output variable names
59
-
60
- """
61
- ovars = []
62
- if self.set_XY:
63
- ovars.append(FV.X)
64
- ovars.append(FV.Y)
65
- if self.set_H:
66
- ovars.append(FV.H)
67
- if self.set_D:
68
- ovars.append(FV.D)
69
- return ovars
70
-
71
- def calculate(self, algo, mdata, fdata, st_sel):
72
- """ "
73
- The main model calculation.
74
-
75
- This function is executed on a single chunk of data,
76
- all computations should be based on numpy arrays.
77
-
78
- Parameters
79
- ----------
80
- algo: foxes.core.Algorithm
81
- The calculation algorithm
82
- mdata: foxes.core.Data
83
- The model data
84
- fdata: foxes.core.Data
85
- The farm data
86
- st_sel: numpy.ndarray of bool
87
- The state-turbine selection,
88
- shape: (n_states, n_turbines)
89
-
90
- Returns
91
- -------
92
- results: dict
93
- The resulting data, keys: output variable str.
94
- Values: numpy.ndarray with shape (n_states, n_turbines)
95
-
96
- """
97
- n_states = mdata.n_states
98
- n_turbines = algo.n_turbines
99
-
100
- if self.set_XY or self.set_H:
101
- fdata[FV.TXYH] = np.full((n_states, n_turbines, 3), np.nan, dtype=FC.DTYPE)
102
- if self.set_XY:
103
- fdata[FV.X] = fdata[FV.TXYH][..., 0]
104
- fdata[FV.Y] = fdata[FV.TXYH][..., 1]
105
- if self.set_H:
106
- fdata[FV.H] = fdata[FV.TXYH][..., 2]
107
-
108
- for ti in range(n_turbines):
109
- ssel = st_sel[:, ti]
110
- if np.any(ssel):
111
- if np.all(ssel):
112
- ssel = np.s_[:]
113
-
114
- if self.set_XY:
115
- fdata[FV.X][ssel, ti] = algo.farm.turbines[ti].xy[0]
116
- fdata[FV.Y][ssel, ti] = algo.farm.turbines[ti].xy[1]
117
-
118
- if self.set_H:
119
- H = algo.farm.turbines[ti].H
120
- if H is None:
121
- H = algo.farm_controller.turbine_types[ti].H
122
- fdata[FV.H][ssel, ti] = H
123
-
124
- if self.set_D:
125
- D = algo.farm.turbines[ti].D
126
- if D is None:
127
- D = algo.farm_controller.turbine_types[ti].D
128
- fdata[FV.D][ssel, ti] = D
129
-
130
- return {v: fdata[v] for v in self.output_farm_vars(algo)}
File without changes