foxes 0.6.1__py3-none-any.whl → 0.7__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 (129) 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/__init__.py +1 -0
  32. foxes/input/farm_layout/from_random.py +49 -0
  33. foxes/input/states/__init__.py +1 -1
  34. foxes/input/states/create/__init__.py +1 -0
  35. foxes/input/states/create/random_abl_states.py +6 -2
  36. foxes/input/states/create/random_timeseries.py +56 -0
  37. foxes/input/states/field_data_nc.py +12 -8
  38. foxes/input/states/multi_height.py +24 -14
  39. foxes/input/states/scan_ws.py +13 -17
  40. foxes/input/states/single.py +28 -20
  41. foxes/input/states/states_table.py +22 -18
  42. foxes/models/axial_induction_models/betz.py +1 -1
  43. foxes/models/farm_models/turbine2farm.py +2 -2
  44. foxes/models/model_book.py +40 -14
  45. foxes/models/partial_wakes/__init__.py +2 -2
  46. foxes/models/partial_wakes/axiwake.py +73 -200
  47. foxes/models/partial_wakes/centre.py +40 -0
  48. foxes/models/partial_wakes/grid.py +7 -63
  49. foxes/models/partial_wakes/rotor_points.py +53 -147
  50. foxes/models/partial_wakes/segregated.py +158 -0
  51. foxes/models/partial_wakes/top_hat.py +88 -196
  52. foxes/models/point_models/set_uniform_data.py +4 -4
  53. foxes/models/point_models/tke2ti.py +4 -4
  54. foxes/models/point_models/wake_deltas.py +4 -4
  55. foxes/models/rotor_models/centre.py +15 -19
  56. foxes/models/rotor_models/grid.py +2 -1
  57. foxes/models/rotor_models/levels.py +2 -1
  58. foxes/models/turbine_models/__init__.py +0 -1
  59. foxes/models/turbine_models/calculator.py +11 -7
  60. foxes/models/turbine_models/kTI_model.py +13 -11
  61. foxes/models/turbine_models/lookup_table.py +22 -9
  62. foxes/models/turbine_models/power_mask.py +81 -51
  63. foxes/models/turbine_models/rotor_centre_calc.py +17 -20
  64. foxes/models/turbine_models/sector_management.py +5 -6
  65. foxes/models/turbine_models/set_farm_vars.py +49 -20
  66. foxes/models/turbine_models/table_factors.py +5 -5
  67. foxes/models/turbine_models/thrust2ct.py +9 -5
  68. foxes/models/turbine_models/yaw2yawm.py +7 -13
  69. foxes/models/turbine_models/yawm2yaw.py +7 -11
  70. foxes/models/turbine_types/PCt_file.py +84 -3
  71. foxes/models/turbine_types/PCt_from_two.py +7 -3
  72. foxes/models/turbine_types/null_type.py +2 -2
  73. foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -2
  74. foxes/models/turbine_types/wsti2PCt_from_two.py +6 -2
  75. foxes/models/wake_frames/farm_order.py +26 -22
  76. foxes/models/wake_frames/rotor_wd.py +32 -31
  77. foxes/models/wake_frames/seq_dynamic_wakes.py +112 -64
  78. foxes/models/wake_frames/streamlines.py +51 -47
  79. foxes/models/wake_frames/timelines.py +59 -47
  80. foxes/models/wake_frames/yawed_wakes.py +63 -40
  81. foxes/models/wake_models/axisymmetric.py +31 -35
  82. foxes/models/wake_models/dist_sliced.py +50 -56
  83. foxes/models/wake_models/gaussian.py +33 -35
  84. foxes/models/wake_models/induction/rankine_half_body.py +79 -87
  85. foxes/models/wake_models/induction/rathmann.py +56 -63
  86. foxes/models/wake_models/induction/self_similar.py +59 -62
  87. foxes/models/wake_models/ti/crespo_hernandez.py +83 -74
  88. foxes/models/wake_models/ti/iec_ti.py +65 -75
  89. foxes/models/wake_models/top_hat.py +60 -69
  90. foxes/models/wake_models/wake_mirror.py +49 -54
  91. foxes/models/wake_models/wind/bastankhah14.py +44 -66
  92. foxes/models/wake_models/wind/bastankhah16.py +84 -111
  93. foxes/models/wake_models/wind/jensen.py +67 -89
  94. foxes/models/wake_models/wind/turbopark.py +93 -133
  95. foxes/models/wake_superpositions/ti_linear.py +33 -27
  96. foxes/models/wake_superpositions/ti_max.py +33 -27
  97. foxes/models/wake_superpositions/ti_pow.py +35 -27
  98. foxes/models/wake_superpositions/ti_quadratic.py +33 -27
  99. foxes/models/wake_superpositions/ws_linear.py +39 -32
  100. foxes/models/wake_superpositions/ws_max.py +40 -33
  101. foxes/models/wake_superpositions/ws_pow.py +39 -32
  102. foxes/models/wake_superpositions/ws_product.py +35 -28
  103. foxes/models/wake_superpositions/ws_quadratic.py +39 -32
  104. foxes/opt/constraints/min_dist.py +1 -1
  105. foxes/opt/objectives/farm_vars.py +1 -1
  106. foxes/opt/problems/layout/farm_layout.py +38 -97
  107. foxes/output/__init__.py +1 -0
  108. foxes/output/farm_results_eval.py +1 -1
  109. foxes/output/flow_plots_2d/flow_plots.py +2 -0
  110. foxes/output/flow_plots_2d/get_fig.py +2 -0
  111. foxes/output/grids.py +1 -1
  112. foxes/output/rose_plot.py +3 -3
  113. foxes/output/rotor_point_plots.py +117 -0
  114. foxes/output/turbine_type_curves.py +2 -2
  115. foxes/utils/__init__.py +2 -1
  116. foxes/utils/load.py +29 -0
  117. foxes/utils/random_xy.py +56 -0
  118. foxes/utils/runners/runners.py +13 -1
  119. foxes/utils/windrose_plot.py +1 -1
  120. foxes/variables.py +10 -0
  121. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/METADATA +13 -7
  122. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/RECORD +126 -122
  123. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/WHEEL +1 -1
  124. foxes/models/partial_wakes/distsliced.py +0 -322
  125. foxes/models/partial_wakes/mapped.py +0 -252
  126. foxes/models/turbine_models/set_XYHD.py +0 -130
  127. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/LICENSE +0 -0
  128. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/top_level.txt +0 -0
  129. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/zip-safe +0 -0
@@ -28,13 +28,13 @@ class TurbineModel(FarmDataModel):
28
28
  ----------
29
29
  algo: foxes.core.Algorithm
30
30
  The calculation algorithm
31
- mdata: foxes.core.Data
31
+ mdata: foxes.core.MData
32
32
  The model data
33
- fdata: foxes.core.Data
33
+ fdata: foxes.core.FData
34
34
  The farm data
35
- st_sel: numpy.ndarray of bool
35
+ st_sel: slice or numpy.ndarray of bool
36
36
  The state-turbine selection,
37
- shape: (n_states, n_turbines)
37
+ for shape: (n_states, n_turbines)
38
38
 
39
39
  Returns
40
40
  -------
@@ -60,6 +60,30 @@ class TurbineType(TurbineModel):
60
60
  f"Turbine type '{self.name}': Unkown P_unit '{P_unit}', expecting {list(FC.P_UNITS.keys())}"
61
61
  )
62
62
 
63
+ def __repr__(self):
64
+ a = f"D={self.D}, H={self.H}, P_nominal={self.P_nominal}, P_unit={self.P_unit}"
65
+ return f"{type(self).__name__}({a})"
66
+
67
+ def modify_cutin(self, modify_ct, modify_P):
68
+ """
69
+ Modify the data such that a discontinuity
70
+ at cutin wind speed is avoided
71
+
72
+ Parameters
73
+ ----------
74
+ variable: str
75
+ The target variable
76
+ modify_ct: bool
77
+ Flag for modification of the ct curve
78
+ modify_P: bool
79
+ Flag for modification of the power curve
80
+
81
+ """
82
+ if modify_ct or modify_P:
83
+ raise NotImplementedError(
84
+ f"Turbine type '{self.name}': Continuous cutin not implemented for modify_ct = {modify_ct}, modify_P = {modify_P}"
85
+ )
86
+
63
87
  @classmethod
64
88
  def new(cls, ttype_type, *args, **kwargs):
65
89
  """
@@ -27,14 +27,14 @@ class VerticalProfile(Model):
27
27
  return []
28
28
 
29
29
  @abstractmethod
30
- def calculate(self, data, heights):
30
+ def calculate(self, tdata, heights):
31
31
  """
32
32
  Run the profile calculation.
33
33
 
34
34
  Parameters
35
35
  ----------
36
- data: dict
37
- The input data
36
+ tdata: dict
37
+ The target point data
38
38
  heights: numpy.ndarray
39
39
  The evaluation heights
40
40
 
foxes/core/wake_frame.py CHANGED
@@ -51,29 +51,36 @@ class WakeFrame(Model):
51
51
  pass
52
52
 
53
53
  @abstractmethod
54
- def get_wake_coos(self, algo, mdata, fdata, pdata, states_source_turbine):
54
+ def get_wake_coos(
55
+ self,
56
+ algo,
57
+ mdata,
58
+ fdata,
59
+ tdata,
60
+ downwind_index,
61
+ ):
55
62
  """
56
- Calculate wake coordinates.
63
+ Calculate wake coordinates of rotor points.
57
64
 
58
65
  Parameters
59
66
  ----------
60
67
  algo: foxes.core.Algorithm
61
68
  The calculation algorithm
62
- mdata: foxes.core.Data
69
+ mdata: foxes.core.MData
63
70
  The model data
64
- fdata: foxes.core.Data
71
+ fdata: foxes.core.FData
65
72
  The farm data
66
- pdata: foxes.core.Data
67
- The evaluation point data
68
- states_source_turbine: numpy.ndarray
69
- For each state, one turbine index for the
70
- wake causing turbine. Shape: (n_states,)
73
+ tdata: foxes.core.TData
74
+ The target point data
75
+ downwind_index: int
76
+ The index of the wake causing turbine
77
+ in the downwnd order
71
78
 
72
79
  Returns
73
80
  -------
74
81
  wake_coos: numpy.ndarray
75
82
  The wake frame coordinates of the evaluation
76
- points, shape: (n_states, n_points, 3)
83
+ points, shape: (n_states, n_targets, n_tpoints, 3)
77
84
 
78
85
  """
79
86
  pass
@@ -82,10 +89,12 @@ class WakeFrame(Model):
82
89
  self,
83
90
  algo,
84
91
  variable,
85
- states_source_turbine,
92
+ downwind_index,
86
93
  fdata,
87
- pdata,
94
+ tdata,
95
+ target,
88
96
  states0=None,
97
+ upcast=False,
89
98
  ):
90
99
  """
91
100
  Return data that is required for computing the
@@ -97,27 +106,61 @@ class WakeFrame(Model):
97
106
  The algorithm, needed for data from previous iteration
98
107
  variable: str
99
108
  The variable, serves as data key
100
- states_source_turbine: numpy.ndarray
101
- For each state, one turbine index for the
102
- wake causing turbine. Shape: (n_states,)
103
- fdata: foxes.core.Data
109
+ downwind_index: int, optional
110
+ The index in the downwind order
111
+ fdata: foxes.core.FData
104
112
  The farm data
105
- pdata: foxes.core.Data
106
- The evaluation point data
113
+ tdata: foxes.core.TData
114
+ The target point data
115
+ target: str, optional
116
+ The dimensions identifier for the output,
117
+ FC.STATE_TURBINE, FC.STATE_TARGET,
118
+ FC.STATE_TARGET_TPOINT
107
119
  states0: numpy.ndarray, optional
108
120
  The states of wake creation
121
+ upcast: bool
122
+ Flag for ensuring targets dimension,
123
+ otherwise dimension 1 is entered
124
+
125
+ Returns
126
+ -------
127
+ data: numpy.ndarray
128
+ Data for wake modelling, shape:
129
+ (n_states, n_turbines) or (n_states, n_target)
130
+ dims: tuple
131
+ The data dimensions
109
132
 
110
133
  """
111
134
  n_states = fdata.n_states
112
- n_points = pdata.n_points
113
- s = np.arange(n_states) if states0 is None else states0
114
-
115
- out = np.zeros((n_states, n_points), dtype=FC.DTYPE)
116
- out[:] = fdata[variable][s, states_source_turbine][:, None]
135
+ s = np.s_[:] if states0 is None else states0
136
+
137
+ if not upcast:
138
+ if target == FC.STATE_TARGET_TPOINT:
139
+ out = fdata[variable][s, downwind_index, None, None]
140
+ dims = (FC.STATE, 1, 1)
141
+ else:
142
+ out = fdata[variable][s, downwind_index, None]
143
+ dims = (FC.STATE, 1)
144
+ elif target == FC.STATE_TURBINE:
145
+ out = np.zeros((n_states, fdata.n_turbines), dtype=FC.DTYPE)
146
+ out[:] = fdata[variable][s, downwind_index, None]
147
+ dims = (FC.STATE, FC.TURBINE)
148
+ elif target == FC.STATE_TARGET:
149
+ out = np.zeros((n_states, tdata.n_targets), dtype=FC.DTYPE)
150
+ out[:] = fdata[variable][s, downwind_index, None]
151
+ dims = (FC.STATE, FC.TARGET)
152
+ elif target == FC.STATE_TARGET_TPOINT:
153
+ out = np.zeros((n_states, tdata.n_targets, tdata.n_tpoints), dtype=FC.DTYPE)
154
+ out[:] = fdata[variable][s, downwind_index, None, None]
155
+ dims = (FC.STATE, FC.TARGET, FC.TPOINT)
156
+ else:
157
+ raise ValueError(
158
+ f"Unsupported target '{target}', expcting '{FC.STATE_TURBINE}', '{FC.STATE_TARGET}', {FC.STATE_TARGET_TPOINT}"
159
+ )
117
160
 
118
- return out
161
+ return out, dims
119
162
 
120
- def get_centreline_points(self, algo, mdata, fdata, states_source_turbine, x):
163
+ def get_centreline_points(self, algo, mdata, fdata, downwind_index, x):
121
164
  """
122
165
  Gets the points along the centreline for given
123
166
  values of x.
@@ -126,13 +169,12 @@ class WakeFrame(Model):
126
169
  ----------
127
170
  algo: foxes.core.Algorithm
128
171
  The calculation algorithm
129
- mdata: foxes.core.Data
172
+ mdata: foxes.core.MData
130
173
  The model data
131
- fdata: foxes.core.Data
174
+ fdata: foxes.core.FData
132
175
  The farm data
133
- states_source_turbine: numpy.ndarray
134
- For each state, one turbine index for the
135
- wake causing turbine. Shape: (n_states,)
176
+ downwind_index: int
177
+ The index in the downwind order
136
178
  x: numpy.ndarray
137
179
  The wake frame x coordinates, shape: (n_states, n_points)
138
180
 
@@ -151,7 +193,7 @@ class WakeFrame(Model):
151
193
  algo,
152
194
  mdata,
153
195
  fdata,
154
- states_source_turbine,
196
+ downwind_index,
155
197
  variables,
156
198
  x,
157
199
  dx,
@@ -166,13 +208,12 @@ class WakeFrame(Model):
166
208
  ----------
167
209
  algo: foxes.core.Algorithm
168
210
  The calculation algorithm
169
- mdata: foxes.core.Data
211
+ mdata: foxes.core.MData
170
212
  The model data
171
- fdata: foxes.core.Data
213
+ fdata: foxes.core.FData
172
214
  The farm data
173
- states_source_turbine: numpy.ndarray
174
- For each state, one turbine index for the
175
- wake causing turbine. Shape: (n_states,)
215
+ downwind_index: int
216
+ The index in the downwind order
176
217
  variables: list of str
177
218
  The variables to be integrated
178
219
  x: numpy.ndarray
@@ -208,22 +249,22 @@ class WakeFrame(Model):
208
249
  xs = np.arange(xmin, xmin + n_ix * dx, dx)
209
250
  xpts = np.zeros((n_states, n_steps), dtype=FC.DTYPE)
210
251
  xpts[:] = xs[None, 1:]
211
- pts = self.get_centreline_points(
212
- algo, mdata, fdata, states_source_turbine, xpts
213
- )
252
+ pts = self.get_centreline_points(algo, mdata, fdata, downwind_index, xpts)
214
253
 
215
254
  # run ambient calculation:
216
- pdata = Data.from_points(
255
+ tdata = Data.from_points(
217
256
  pts,
218
- data={v: np.full((n_states, n_steps), np.nan, dtype=FC.DTYPE) for v in vrs},
219
- dims={v: (FC.STATE, FC.POINT) for v in vrs},
257
+ data={
258
+ v: np.full((n_states, n_steps, 1), np.nan, dtype=FC.DTYPE) for v in vrs
259
+ },
260
+ dims={v: (FC.STATE, FC.TARGET, FC.TPOINT) for v in vrs},
220
261
  )
221
- res = algo.states.calculate(algo, mdata, fdata, pdata)
222
- pdata.update(res)
262
+ res = algo.states.calculate(algo, mdata, fdata, tdata)
263
+ tdata.update(res)
223
264
  amb2var = algo.get_model("SetAmbPointResults")()
224
265
  amb2var.initialize(algo, verbosity=0)
225
- res = amb2var.calculate(algo, mdata, fdata, pdata)
226
- pdata.update(res)
266
+ res = amb2var.calculate(algo, mdata, fdata, tdata)
267
+ tdata.update(res)
227
268
  del res, amb2var
228
269
 
229
270
  # find out if all vars ambient:
@@ -237,16 +278,16 @@ class WakeFrame(Model):
237
278
  if not ambient:
238
279
  wcalc = algo.get_model("PointWakesCalculation")(wake_models=wake_models)
239
280
  wcalc.initialize(algo, verbosity=0)
240
- wsrc = states_source_turbine if self_wake else None
241
- res = wcalc.calculate(algo, mdata, fdata, pdata, states_source_turbine=wsrc)
242
- pdata.update(res)
281
+ wsrc = downwind_index if self_wake else None
282
+ res = wcalc.calculate(algo, mdata, fdata, tdata, downwind_index=wsrc)
283
+ tdata.update(res)
243
284
  del wcalc, res
244
285
 
245
286
  # collect integration results:
246
287
  iresults = np.zeros((n_states, n_ix, n_vars), dtype=FC.DTYPE)
247
288
  for vi, v in enumerate(variables):
248
289
  for i in range(n_steps):
249
- iresults[:, i + 1, vi] = iresults[:, i, vi] + pdata[v][:, i] * dx
290
+ iresults[:, i + 1, vi] = iresults[:, i, vi] + tdata[v][:, i, 0] * dx
250
291
 
251
292
  # interpolate to x of interest:
252
293
  qts = np.zeros((n_states, n_points, 2), dtype=FC.DTYPE)
foxes/core/wake_model.py CHANGED
@@ -1,6 +1,9 @@
1
1
  from abc import abstractmethod
2
+ import numpy as np
2
3
 
3
4
  from foxes.utils import all_subclasses
5
+ import foxes.variables as FV
6
+ import foxes.constants as FC
4
7
 
5
8
  from .model import Model
6
9
 
@@ -13,70 +16,79 @@ class WakeModel(Model):
13
16
 
14
17
  """
15
18
 
16
- @abstractmethod
17
- def init_wake_deltas(self, algo, mdata, fdata, pdata, wake_deltas):
19
+ @property
20
+ def affects_downwind(self):
21
+ """
22
+ Flag for downwind or upwind effects
23
+ on other turbines
24
+
25
+ Returns
26
+ -------
27
+ dwnd: bool
28
+ Flag for downwind effects by this model
29
+
18
30
  """
19
- Initialize wake delta storage.
31
+ return True
20
32
 
21
- They are added on the fly to the wake_deltas dict.
33
+ def new_wake_deltas(self, algo, mdata, fdata, tdata):
34
+ """
35
+ Creates new empty wake delta arrays.
22
36
 
23
37
  Parameters
24
38
  ----------
25
39
  algo: foxes.core.Algorithm
26
40
  The calculation algorithm
27
- mdata: foxes.core.Data
41
+ mdata: foxes.core.MData
28
42
  The model data
29
- fdata: foxes.core.Data
43
+ fdata: foxes.core.FData
30
44
  The farm data
31
- pdata: foxes.core.Data
32
- The evaluation point data
45
+ tdata: foxes.core.TData
46
+ The target point data
47
+
48
+ Returns
49
+ -------
33
50
  wake_deltas: dict
34
- The wake deltas storage, add wake deltas
35
- on the fly. Keys: Variable name str, for which the
36
- wake delta applies, values: numpy.ndarray with
37
- shape (n_states, n_points, ...)
51
+ Key: variable name, value: The zero filled
52
+ wake deltas, shape: (n_states, n_turbines, n_rpoints, ...)
38
53
 
39
54
  """
40
- pass
55
+ return {FV.WS: np.zeros_like(tdata[FC.TARGETS][..., 0])}
41
56
 
42
57
  @abstractmethod
43
- def contribute_to_wake_deltas(
58
+ def contribute(
44
59
  self,
45
60
  algo,
46
61
  mdata,
47
62
  fdata,
48
- pdata,
49
- states_source_turbine,
63
+ tdata,
64
+ downwind_index,
50
65
  wake_coos,
51
66
  wake_deltas,
52
67
  ):
53
68
  """
54
- Calculate the contribution to the wake deltas
55
- by this wake model.
56
-
57
- Modifies wake_deltas on the fly.
69
+ Modifies wake deltas at target points by
70
+ contributions from the specified wake source turbines.
58
71
 
59
72
  Parameters
60
73
  ----------
61
74
  algo: foxes.core.Algorithm
62
75
  The calculation algorithm
63
- mdata: foxes.core.Data
76
+ mdata: foxes.core.MData
64
77
  The model data
65
- fdata: foxes.core.Data
78
+ fdata: foxes.core.FData
66
79
  The farm data
67
- pdata: foxes.core.Data
68
- The evaluation point data
69
- states_source_turbine: numpy.ndarray
70
- For each state, one turbine index for the
71
- wake causing turbine. Shape: (n_states,)
80
+ tdata: foxes.core.TData
81
+ The target point data
82
+ downwind_index: int
83
+ The index of the wake causing turbine
84
+ in the downwnd order
72
85
  wake_coos: numpy.ndarray
73
86
  The wake frame coordinates of the evaluation
74
- points, shape: (n_states, n_points, 3)
87
+ points, shape: (n_states, n_targets, n_tpoints, 3)
75
88
  wake_deltas: dict
76
- The wake deltas, are being modified ob the fly.
77
- Key: Variable name str, for which the
78
- wake delta applies, values: numpy.ndarray with
79
- shape (n_states, n_points, ...)
89
+ The wake deltas. Key: variable name,
90
+ value: numpy.ndarray with shape
91
+ (n_states, n_targets, n_tpoints, ...)
80
92
 
81
93
  """
82
94
  pass
@@ -86,7 +98,6 @@ class WakeModel(Model):
86
98
  algo,
87
99
  mdata,
88
100
  fdata,
89
- pdata,
90
101
  amb_results,
91
102
  wake_deltas,
92
103
  ):
@@ -99,21 +110,18 @@ class WakeModel(Model):
99
110
  ----------
100
111
  algo: foxes.core.Algorithm
101
112
  The calculation algorithm
102
- mdata: foxes.core.Data
113
+ mdata: foxes.core.MData
103
114
  The model data
104
- fdata: foxes.core.Data
115
+ fdata: foxes.core.FData
105
116
  The farm data
106
- pdata: foxes.core.Data
107
- The evaluation point data
108
117
  amb_results: dict
109
118
  The ambient results, key: variable name str,
110
- values: numpy.ndarray with shape (n_states, n_points)
119
+ values: numpy.ndarray with shape
120
+ (n_states, n_targets, n_tpoints)
111
121
  wake_deltas: dict
112
- The wake deltas, are being modified ob the fly.
113
- Key: Variable name str, for which the wake delta
114
- applies, values: numpy.ndarray with shape
115
- (n_states, n_points, ...) before evaluation,
116
- numpy.ndarray with shape (n_states, n_points) afterwards
122
+ The wake deltas object at the selected target
123
+ turbines. Key: variable str, value: numpy.ndarray
124
+ with shape (n_states, n_targets, n_tpoints)
117
125
 
118
126
  """
119
127
  pass
@@ -152,3 +160,26 @@ class WakeModel(Model):
152
160
  )
153
161
  )
154
162
  raise KeyError(estr)
163
+
164
+
165
+ class TurbineInductionModel(WakeModel):
166
+ """
167
+ Abstract base class for turbine induction models.
168
+
169
+ :group: core
170
+
171
+ """
172
+
173
+ @property
174
+ def affects_downwind(self):
175
+ """
176
+ Flag for downwind or upwind effects
177
+ on other turbines
178
+
179
+ Returns
180
+ -------
181
+ dwnd: bool
182
+ Flag for downwind effects by this model
183
+
184
+ """
185
+ return False
@@ -17,48 +17,51 @@ class WakeSuperposition(Model):
17
17
  """
18
18
 
19
19
  @abstractmethod
20
- def calc_wakes_plus_wake(
20
+ def add_wake(
21
21
  self,
22
22
  algo,
23
23
  mdata,
24
24
  fdata,
25
- pdata,
26
- states_source_turbine,
27
- sel_sp,
25
+ tdata,
26
+ downwind_index,
27
+ st_sel,
28
28
  variable,
29
29
  wake_delta,
30
30
  wake_model_result,
31
31
  ):
32
32
  """
33
- Add a wake delta to previous wake deltas.
33
+ Add a wake delta to previous wake deltas,
34
+ at rotor points.
34
35
 
35
36
  Parameters
36
37
  ----------
37
38
  algo: foxes.core.Algorithm
38
39
  The calculation algorithm
39
- mdata: foxes.core.Data
40
+ mdata: foxes.core.MData
40
41
  The model data
41
- fdata: foxes.core.Data
42
+ fdata: foxes.core.FData
42
43
  The farm data
43
- pdata: foxes.core.Data
44
- The evaluation point data
45
- states_source_turbine: numpy.ndarray
46
- For each state, one turbine index for the
47
- wake causing turbine. Shape: (n_states,)
48
- sel_sp: numpy.ndarray of bool
49
- The selection of points, shape: (n_states, n_points)
44
+ tdata: foxes.core.TData
45
+ The target point data
46
+ downwind_index: int
47
+ The index of the wake causing turbine
48
+ in the downwnd order
49
+ st_sel: numpy.ndarray of bool
50
+ The selection of targets, shape: (n_states, n_targets)
50
51
  variable: str
51
52
  The variable name for which the wake deltas applies
52
53
  wake_delta: numpy.ndarray
53
- The original wake deltas, shape: (n_states, n_points)
54
+ The original wake deltas, shape:
55
+ (n_states, n_targets, n_tpoints, ...)
54
56
  wake_model_result: numpy.ndarray
55
- The new wake deltas of the selected points,
56
- shape: (n_sel_sp,)
57
+ The new wake deltas of the selected rotors,
58
+ shape: (n_st_sel, n_tpoints, ...)
57
59
 
58
60
  Returns
59
61
  -------
60
62
  wdelta: numpy.ndarray
61
- The updated wake deltas, shape: (n_states, n_points)
63
+ The updated wake deltas, shape:
64
+ (n_states, n_targets, n_tpoints, ...)
62
65
 
63
66
  """
64
67
  pass
@@ -69,7 +72,6 @@ class WakeSuperposition(Model):
69
72
  algo,
70
73
  mdata,
71
74
  fdata,
72
- pdata,
73
75
  variable,
74
76
  amb_results,
75
77
  wake_delta,
@@ -82,24 +84,25 @@ class WakeSuperposition(Model):
82
84
  ----------
83
85
  algo: foxes.core.Algorithm
84
86
  The calculation algorithm
85
- mdata: foxes.core.Data
87
+ mdata: foxes.core.MData
86
88
  The model data
87
- fdata: foxes.core.Data
89
+ fdata: foxes.core.FData
88
90
  The farm data
89
- pdata: foxes.core.Data
90
- The evaluation point data
91
91
  variable: str
92
92
  The variable name for which the wake deltas applies
93
93
  amb_results: numpy.ndarray
94
- The ambient results, shape: (n_states, n_points)
94
+ The ambient results at targets,
95
+ shape: (n_states, n_targets, n_tpoints)
95
96
  wake_delta: numpy.ndarray
96
- The wake deltas, shape: (n_states, n_points)
97
+ The wake deltas at targets, shape:
98
+ (n_states, n_targets, n_tpoints)
97
99
 
98
100
  Returns
99
101
  -------
100
102
  final_wake_delta: numpy.ndarray
101
103
  The final wake delta, which will be added to the ambient
102
- results by simple plus operation. Shape: (n_states, n_points)
104
+ results by simple plus operation. Shape:
105
+ (n_states, n_targets, n_tpoints)
103
106
 
104
107
  """
105
108
  pass
@@ -8,3 +8,4 @@ from .from_json import add_from_json
8
8
  from .from_csv import add_from_csv
9
9
  from .from_file import add_from_file
10
10
  from .from_df import add_from_df
11
+ from .from_random import add_random
@@ -0,0 +1,49 @@
1
+ import numpy as np
2
+
3
+ from foxes.utils import random_xy_square
4
+ from foxes.core import Turbine
5
+
6
+
7
+ def add_random(
8
+ farm,
9
+ n_turbines,
10
+ min_dist,
11
+ centre=[0, 0],
12
+ seed=None,
13
+ verbosity=1,
14
+ **turbine_parameters,
15
+ ):
16
+ """
17
+ Add turbines that lie randomly within a square
18
+
19
+ Parameters
20
+ ----------
21
+ farm: foxes.WindFarm
22
+ The wind farm
23
+ n_turbines: int
24
+ The number of turbines
25
+ min_dist: float
26
+ The minimal distance between turbines
27
+ centre: array-like
28
+ The (x, y) coordinates of the mean
29
+ seed: int, optional
30
+ The random seed
31
+ verbosity: int
32
+ The verbosity level, 0 = silent
33
+ turbine_parameters: dict, optional
34
+ Additional parameters are forwarded to the WindFarm.add_turbine().
35
+
36
+ :group: input.farm_layout
37
+
38
+ """
39
+ xy = random_xy_square(n_turbines, min_dist, seed=seed, verbosity=verbosity)
40
+ xy += np.array(centre)[None, :]
41
+
42
+ for i in range(len(xy)):
43
+ farm.add_turbine(
44
+ Turbine(
45
+ xy=xy[i],
46
+ **turbine_parameters,
47
+ ),
48
+ verbosity=verbosity,
49
+ )
@@ -8,4 +8,4 @@ from .states_table import StatesTable, Timeseries, TabStates
8
8
  from .field_data_nc import FieldDataNC
9
9
  from .multi_height import MultiHeightStates, MultiHeightTimeseries
10
10
 
11
- from .create import create_random_abl_states
11
+ from . import create
@@ -1 +1,2 @@
1
1
  from .random_abl_states import create_random_abl_states, write_random_abl_states
2
+ from .random_timeseries import random_timseries_data