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
@@ -157,7 +157,7 @@ class LookupTable(TurbineModel):
157
157
  return super().load_data(algo, verbosity)
158
158
 
159
159
  def calculate(self, algo, mdata, fdata, st_sel):
160
- """ "
160
+ """
161
161
  The main model calculation.
162
162
 
163
163
  This function is executed on a single chunk of data,
@@ -167,13 +167,13 @@ class LookupTable(TurbineModel):
167
167
  ----------
168
168
  algo: foxes.core.Algorithm
169
169
  The calculation algorithm
170
- mdata: foxes.core.Data
170
+ mdata: foxes.core.MData
171
171
  The model data
172
- fdata: foxes.core.Data
172
+ fdata: foxes.core.FData
173
173
  The farm data
174
- st_sel: numpy.ndarray of bool
174
+ st_sel: slice or numpy.ndarray of bool
175
175
  The state-turbine selection,
176
- shape: (n_states, n_turbines)
176
+ for shape: (n_states, n_turbines)
177
177
 
178
178
  Returns
179
179
  -------
@@ -182,15 +182,28 @@ class LookupTable(TurbineModel):
182
182
  Values: numpy.ndarray with shape (n_states, n_turbines)
183
183
 
184
184
  """
185
+ data = {
186
+ v: self.get_data(
187
+ self.input_vars[0],
188
+ FC.STATE_TURBINE,
189
+ lookup="fs",
190
+ fdata=fdata,
191
+ upcast=True,
192
+ )[st_sel]
193
+ for v in self.input_vars
194
+ }
195
+ dims = {
196
+ v: ("_z") if len(data[v].shape) == 1 else ("_z", "_u")
197
+ for v in self.input_vars
198
+ }
185
199
  indata = {
186
200
  v: xr.DataArray(
187
- self.get_data(
188
- v, FC.STATE_TURBINE, lookup="fs", fdata=fdata, upcast=True
189
- )[st_sel],
190
- dims=["_z"],
201
+ data[v],
202
+ dims=dims[v],
191
203
  )
192
204
  for v in self.input_vars
193
205
  }
206
+ del data, dims
194
207
 
195
208
  odata = self._data.interp(**indata, **self._xargs)
196
209
 
@@ -24,12 +24,16 @@ class PowerMask(TurbineModel):
24
24
  The wind speed variable for power lookup
25
25
  factor_P: float
26
26
  The power unit factor, e.g. 1000 for kW
27
+ P_lim: float
28
+ Threshold power delta for boosts
29
+ induction: foxes.core.AxialInductionModel
30
+ The induction model
27
31
 
28
32
  :group: models.turbine_models
29
33
 
30
34
  """
31
35
 
32
- def __init__(self, var_ws_P=FV.REWS3, factor_P=1.0e3):
36
+ def __init__(self, var_ws_P=FV.REWS3, factor_P=1.0e3, P_lim=100, induction="Betz"):
33
37
  """
34
38
  Constructor.
35
39
 
@@ -39,12 +43,25 @@ class PowerMask(TurbineModel):
39
43
  The wind speed variable for power lookup
40
44
  factor_P: float
41
45
  The power unit factor, e.g. 1000 for kW
46
+ P_lim: float
47
+ Threshold power delta for boosts
48
+ induction: foxes.core.AxialInductionModel or str
49
+ The induction model
42
50
 
43
51
  """
44
52
  super().__init__()
45
53
 
46
54
  self.var_ws_P = var_ws_P
47
55
  self.factor_P = factor_P
56
+ self.P_lim = P_lim
57
+ self.induction = induction
58
+
59
+ def __repr__(self):
60
+ iname = (
61
+ self.induction if isinstance(self.induction, str) else self.induction.name
62
+ )
63
+ a = f"var_ws_P={self.var_ws_P}, P_lim={self.P_lim}, induction={iname}"
64
+ return f"{type(self).__name__}({a})"
48
65
 
49
66
  def output_farm_vars(self, algo):
50
67
  """
@@ -63,6 +80,18 @@ class PowerMask(TurbineModel):
63
80
  """
64
81
  return [FV.P, FV.CT]
65
82
 
83
+ def sub_models(self):
84
+ """
85
+ List of all sub-models
86
+
87
+ Returns
88
+ -------
89
+ smdls: list of foxes.core.Model
90
+ All sub models
91
+
92
+ """
93
+ return [self.induction]
94
+
66
95
  def initialize(self, algo, verbosity=0):
67
96
  """
68
97
  Initializes the model.
@@ -75,6 +104,8 @@ class PowerMask(TurbineModel):
75
104
  The verbosity level, 0 = silent
76
105
 
77
106
  """
107
+ if isinstance(self.induction, str):
108
+ self.induction = algo.mbook.axial_induction[self.induction]
78
109
  super().initialize(algo, verbosity)
79
110
 
80
111
  self._P_rated = []
@@ -87,35 +118,68 @@ class PowerMask(TurbineModel):
87
118
  self._P_rated.append(Pnom)
88
119
  self._P_rated = np.array(self._P_rated, dtype=FC.DTYPE)
89
120
 
90
- @classmethod
91
- def update_P_ct(cls, data, max_P, rated_P, factor_P, var_ws=FV.REWS3, P_lim=100):
121
+ def calculate(self, algo, mdata, fdata, st_sel):
122
+ """
123
+ The main model calculation.
124
+
125
+ This function is executed on a single chunk of data,
126
+ all computations should be based on numpy arrays.
127
+
128
+ Parameters
129
+ ----------
130
+ algo: foxes.core.Algorithm
131
+ The calculation algorithm
132
+ mdata: foxes.core.MData
133
+ The model data
134
+ fdata: foxes.core.FData
135
+ The farm data
136
+ st_sel: slice or numpy.ndarray of bool
137
+ The state-turbine selection,
138
+ for shape: (n_states, n_turbines)
139
+
140
+ Returns
141
+ -------
142
+ results: dict
143
+ The resulting data, keys: output variable str.
144
+ Values: numpy.ndarray with shape (n_states, n_turbines)
145
+
146
+ """
147
+ # prepare:
148
+ P = fdata[FV.P]
149
+ max_P = fdata[FV.MAX_P]
150
+ P_rated = self._P_rated[None, :]
151
+
92
152
  # select power entries for which this is active:
93
- P = data[FV.P]
94
- sel = ~np.isnan(max_P) & (
95
- ((max_P < rated_P) & (P > max_P))
96
- | ((max_P > rated_P) & (P > rated_P - P_lim))
153
+ sel = np.zeros((fdata.n_states, fdata.n_turbines), dtype=bool)
154
+ sel[st_sel] = True
155
+ sel = (
156
+ sel
157
+ & ~np.isnan(max_P)
158
+ & (
159
+ ((max_P < P_rated) & (P > max_P))
160
+ | ((max_P > P_rated) & (P > P_rated - self.P_lim))
161
+ )
97
162
  )
98
163
  if np.any(sel):
99
164
  # apply selection:
100
165
  max_P = max_P[sel]
101
- ws = data[var_ws][sel]
102
- rho = data[FV.RHO][sel]
103
- r = data[FV.D][sel] / 2
166
+ ws = fdata[self.var_ws_P][sel]
167
+ rho = fdata[FV.RHO][sel]
168
+ r = fdata[FV.D][sel] / 2
104
169
  P = P[sel]
105
- ct = data[FV.CT][sel]
106
- ct[ct > 1.0] = 1.0
170
+ ct = fdata[FV.CT][sel]
107
171
 
108
172
  # calculate power efficiency e of turbine
109
173
  # e is the ratio of the cp derived from the power curve
110
174
  # and the theoretical cp from the turbine induction
111
- cp = P / (0.5 * ws**3 * rho * np.pi * r**2) * factor_P
112
- a = 0.5 * (1 - np.sqrt(1 - ct))
175
+ cp = P / (0.5 * ws**3 * rho * np.pi * r**2) * self.factor_P
176
+ a = self.induction.ct2a(ct)
113
177
  cp_a = 4 * a**3 - 8 * a**2 + 4 * a
114
178
  e = cp / cp_a
115
179
  del cp, a, cp_a, ct, P
116
180
 
117
181
  # calculating new cp for changed power
118
- cp = max_P / (0.5 * ws**3 * rho * np.pi * r**2) * factor_P
182
+ cp = max_P / (0.5 * ws**3 * rho * np.pi * r**2) * self.factor_P
119
183
 
120
184
  # find roots:
121
185
  N = len(cp)
@@ -130,43 +194,9 @@ class PowerMask(TurbineModel):
130
194
  del a0, a1, a2, a3, rts
131
195
 
132
196
  # set results:
133
- P = data[FV.P]
134
- ct = data[FV.CT]
197
+ P = fdata[FV.P]
198
+ ct = fdata[FV.CT]
135
199
  P[sel] = max_P
136
200
  ct[sel] = 4 * a * (1 - a)
137
201
 
138
- def calculate(self, algo, mdata, fdata, st_sel):
139
- """ "
140
- The main model calculation.
141
-
142
- This function is executed on a single chunk of data,
143
- all computations should be based on numpy arrays.
144
-
145
- Parameters
146
- ----------
147
- algo: foxes.core.Algorithm
148
- The calculation algorithm
149
- mdata: foxes.core.Data
150
- The model data
151
- fdata: foxes.core.Data
152
- The farm data
153
- st_sel: numpy.ndarray of bool
154
- The state-turbine selection,
155
- shape: (n_states, n_turbines)
156
-
157
- Returns
158
- -------
159
- results: dict
160
- The resulting data, keys: output variable str.
161
- Values: numpy.ndarray with shape (n_states, n_turbines)
162
-
163
- """
164
-
165
- # prepare:
166
- max_P = fdata[FV.MAX_P]
167
- rated_P = self._P_rated[None, :]
168
-
169
- # calculate:
170
- self.update_P_ct(fdata, max_P, rated_P, self.factor_P, var_ws=self.var_ws_P)
171
-
172
202
  return {FV.P: fdata[FV.P], FV.CT: fdata[FV.CT]}
@@ -82,7 +82,7 @@ class RotorCentreCalc(TurbineModel):
82
82
  return list(self.calc_vars.keys())
83
83
 
84
84
  def calculate(self, algo, mdata, fdata, st_sel):
85
- """ "
85
+ """
86
86
  The main model calculation.
87
87
 
88
88
  This function is executed on a single chunk of data,
@@ -92,13 +92,13 @@ class RotorCentreCalc(TurbineModel):
92
92
  ----------
93
93
  algo: foxes.core.Algorithm
94
94
  The calculation algorithm
95
- mdata: foxes.core.Data
95
+ mdata: foxes.core.MData
96
96
  The model data
97
- fdata: foxes.core.Data
97
+ fdata: foxes.core.FData
98
98
  The farm data
99
- st_sel: numpy.ndarray of bool
99
+ st_sel: slice or numpy.ndarray of bool
100
100
  The state-turbine selection,
101
- shape: (n_states, n_turbines)
101
+ for shape: (n_states, n_turbines)
102
102
 
103
103
  Returns
104
104
  -------
@@ -107,29 +107,26 @@ class RotorCentreCalc(TurbineModel):
107
107
  Values: numpy.ndarray with shape (n_states, n_turbines)
108
108
 
109
109
  """
110
- # prepare point data:
111
- pdata = {FC.POINTS: fdata[FV.TXYH]}
112
- dims = {FC.POINTS: (FC.STATE, FC.POINT, FC.XYH)}
113
- for v in self.calc_vars.values():
114
- pdata[v] = np.zeros_like(pdata[FC.POINTS][:, :, 0])
115
- dims[v] = (FC.STATE, FC.POINT)
116
- pdata = Data(
117
- name=f"{self.name}_pdata",
118
- data=pdata,
119
- dims=dims,
120
- loop_dims=[FC.STATE, FC.POINT],
110
+ # prepare target point data:
111
+ tdata = Data.from_points(
112
+ fdata[FV.TXYH],
113
+ data={
114
+ v: np.zeros_like(fdata[FV.X][:, :, None])
115
+ for v in self.calc_vars.values()
116
+ },
117
+ dims={v: (FC.STATE, FC.TARGET, FC.TPOINT) for v in self.calc_vars.values()},
118
+ name=f"{self.name}_tdata",
121
119
  )
122
- del dims
123
120
 
124
121
  # run ambient calculation:
125
- res = algo.states.calculate(algo, mdata, fdata, pdata)
122
+ res = algo.states.calculate(algo, mdata, fdata, tdata)
126
123
  for v, a in FV.var2amb.items():
127
124
  if v in res:
128
125
  res[a] = res[v].copy()
129
- pdata.update(res)
126
+ tdata.update(res)
130
127
 
131
128
  # run wake calculation:
132
- res = self._wcalc.calculate(algo, mdata, fdata, pdata)
129
+ res = self._wcalc.calculate(algo, mdata, fdata, tdata)
133
130
 
134
131
  # extract results:
135
132
  out = {v: fdata[v] for v in self.calc_vars.keys()}
@@ -162,7 +162,7 @@ class SectorManagement(TurbineModel):
162
162
  return self._tvars
163
163
 
164
164
  def calculate(self, algo, mdata, fdata, st_sel):
165
- """ "
165
+ """
166
166
  The main model calculation.
167
167
 
168
168
  This function is executed on a single chunk of data,
@@ -172,13 +172,13 @@ class SectorManagement(TurbineModel):
172
172
  ----------
173
173
  algo: foxes.core.Algorithm
174
174
  The calculation algorithm
175
- mdata: foxes.core.Data
175
+ mdata: foxes.core.MData
176
176
  The model data
177
- fdata: foxes.core.Data
177
+ fdata: foxes.core.FData
178
178
  The farm data
179
- st_sel: numpy.ndarray of bool
179
+ st_sel: slice or numpy.ndarray of bool
180
180
  The state-turbine selection,
181
- shape: (n_states, n_turbines)
181
+ for shape: (n_states, n_turbines)
182
182
 
183
183
  Returns
184
184
  -------
@@ -187,7 +187,6 @@ class SectorManagement(TurbineModel):
187
187
  Values: numpy.ndarray with shape (n_states, n_turbines)
188
188
 
189
189
  """
190
-
191
190
  # prepare:
192
191
  n_trbs = len(self._trbs)
193
192
  if n_trbs == fdata.n_turbines and np.all(
@@ -2,6 +2,7 @@ import numpy as np
2
2
 
3
3
  from foxes.core import TurbineModel
4
4
  import foxes.constants as FC
5
+ import foxes.variables as FV
5
6
 
6
7
 
7
8
  class SetFarmVars(TurbineModel):
@@ -118,7 +119,7 @@ class SetFarmVars(TurbineModel):
118
119
  return idata
119
120
 
120
121
  def calculate(self, algo, mdata, fdata, st_sel):
121
- """ "
122
+ """
122
123
  The main model calculation.
123
124
 
124
125
  This function is executed on a single chunk of data,
@@ -128,13 +129,13 @@ class SetFarmVars(TurbineModel):
128
129
  ----------
129
130
  algo: foxes.core.Algorithm
130
131
  The calculation algorithm
131
- mdata: foxes.core.Data
132
+ mdata: foxes.core.MData
132
133
  The model data
133
- fdata: foxes.core.Data
134
+ fdata: foxes.core.FData
134
135
  The farm data
135
- st_sel: numpy.ndarray of bool
136
+ st_sel: slice or numpy.ndarray of bool
136
137
  The state-turbine selection,
137
- shape: (n_states, n_turbines)
138
+ for shape: (n_states, n_turbines)
138
139
 
139
140
  Returns
140
141
  -------
@@ -143,23 +144,51 @@ class SetFarmVars(TurbineModel):
143
144
  Values: numpy.ndarray with shape (n_states, n_turbines)
144
145
 
145
146
  """
146
- n_states = fdata.n_states
147
- n_turbines = fdata.n_turbines
148
- allt = np.all(st_sel)
147
+ if self.pre_rotor:
148
+ order = np.s_[:]
149
+ ssel = np.s_[:]
150
+ else:
151
+ order = fdata[FV.ORDER]
152
+ ssel = fdata[FV.ORDER_SSEL]
153
+
154
+ bsel = np.zeros((fdata.n_states, fdata.n_turbines), dtype=bool)
155
+ bsel[st_sel] = True
149
156
 
150
157
  for v in self.vars:
151
- data = mdata[self.var(v)]
158
+ data = mdata[self.var(v)][ssel, order]
152
159
  hsel = ~np.isnan(data)
153
- hallt = np.all(hsel)
154
-
155
- if allt and hallt:
156
- fdata[v][:] = data
157
-
158
- else:
159
- if v not in fdata:
160
- fdata[v] = np.full((n_states, n_turbines), np.nan, dtype=FC.DTYPE)
161
-
162
- tsel = st_sel & hsel
163
- fdata[v][tsel] = data[tsel]
160
+ tsel = bsel & hsel
161
+
162
+ # special case of turbine positions:
163
+ if v in [FV.X, FV.Y]:
164
+ i = [FV.X, FV.Y].index(v)
165
+ for ti in np.where(tsel)[1]:
166
+ t = algo.farm.turbines[ti]
167
+ if len(t.xy.shape) == 1:
168
+ xy = np.zeros((algo.n_states, 2), dtype=FC.DTYPE)
169
+ xy[:] = t.xy[None, :]
170
+ t.xy = xy
171
+ i0 = fdata.states_i0()
172
+ hsel = tsel[:, ti]
173
+ ssel = i0 + np.where(hsel)[0]
174
+ t.xy[ssel, i] = data[hsel, ti]
175
+
176
+ # special case of rotor diameter and hub height:
177
+ if v in [FV.D, FV.H]:
178
+ for ti in np.where(tsel)[1]:
179
+ t = algo.farm.turbines[ti]
180
+ x = np.zeros(algo.n_states, dtype=FC.DTYPE)
181
+ if v == FV.D:
182
+ x[:] = t.D
183
+ t.D = x
184
+ else:
185
+ x[:] = t.H
186
+ t.H = x
187
+ i0 = fdata.states_i0()
188
+ hsel = tsel[:, ti]
189
+ ssel = i0 + np.where(hsel)[0]
190
+ x[ssel] = data[hsel, ti]
191
+
192
+ fdata[v][tsel] = data[tsel]
164
193
 
165
194
  return {v: fdata[v] for v in self.vars}
@@ -117,7 +117,7 @@ class TableFactors(TurbineModel):
117
117
  self._data = self._data.to_numpy(FC.DTYPE)
118
118
 
119
119
  def calculate(self, algo, mdata, fdata, st_sel):
120
- """ "
120
+ """
121
121
  The main model calculation.
122
122
 
123
123
  This function is executed on a single chunk of data,
@@ -127,13 +127,13 @@ class TableFactors(TurbineModel):
127
127
  ----------
128
128
  algo: foxes.core.Algorithm
129
129
  The calculation algorithm
130
- mdata: foxes.core.Data
130
+ mdata: foxes.core.MData
131
131
  The model data
132
- fdata: foxes.core.Data
132
+ fdata: foxes.core.FData
133
133
  The farm data
134
- st_sel: numpy.ndarray of bool
134
+ st_sel: slice or numpy.ndarray of bool
135
135
  The state-turbine selection,
136
- shape: (n_states, n_turbines)
136
+ for shape: (n_states, n_turbines)
137
137
 
138
138
  Returns
139
139
  -------
@@ -35,6 +35,10 @@ class Thrust2Ct(TurbineModel):
35
35
  self.thrust_var = thrust_var
36
36
  self.WSCT = var_ws_ct
37
37
 
38
+ def __repr__(self):
39
+ a = f"thrust_var={self.thrust_var}, var_ws_ct={self.WSCT}"
40
+ return f"{type(self).__name__}({a})"
41
+
38
42
  def output_farm_vars(self, algo):
39
43
  """
40
44
  The variables which are being modified by the model.
@@ -53,7 +57,7 @@ class Thrust2Ct(TurbineModel):
53
57
  return [FV.CT]
54
58
 
55
59
  def calculate(self, algo, mdata, fdata, st_sel):
56
- """ "
60
+ """
57
61
  The main model calculation.
58
62
 
59
63
  This function is executed on a single chunk of data,
@@ -63,13 +67,13 @@ class Thrust2Ct(TurbineModel):
63
67
  ----------
64
68
  algo: foxes.core.Algorithm
65
69
  The calculation algorithm
66
- mdata: foxes.core.Data
70
+ mdata: foxes.core.MData
67
71
  The model data
68
- fdata: foxes.core.Data
72
+ fdata: foxes.core.FData
69
73
  The farm data
70
- st_sel: numpy.ndarray of bool
74
+ st_sel: slice or numpy.ndarray of bool
71
75
  The state-turbine selection,
72
- shape: (n_states, n_turbines)
76
+ for shape: (n_states, n_turbines)
73
77
 
74
78
  Returns
75
79
  -------
@@ -1,5 +1,3 @@
1
- import numpy as np
2
-
3
1
  from foxes.core import TurbineModel
4
2
  import foxes.variables as FV
5
3
  import foxes.constants as FC
@@ -33,7 +31,7 @@ class YAW2YAWM(TurbineModel):
33
31
  return [FV.YAWM]
34
32
 
35
33
  def calculate(self, algo, mdata, fdata, st_sel):
36
- """ "
34
+ """
37
35
  The main model calculation.
38
36
 
39
37
  This function is executed on a single chunk of data,
@@ -43,13 +41,13 @@ class YAW2YAWM(TurbineModel):
43
41
  ----------
44
42
  algo: foxes.core.Algorithm
45
43
  The calculation algorithm
46
- mdata: foxes.core.Data
44
+ mdata: foxes.core.MData
47
45
  The model data
48
- fdata: foxes.core.Data
46
+ fdata: foxes.core.FData
49
47
  The farm data
50
- st_sel: numpy.ndarray of bool
48
+ st_sel: slice or numpy.ndarray of bool
51
49
  The state-turbine selection,
52
- shape: (n_states, n_turbines)
50
+ for shape: (n_states, n_turbines)
53
51
 
54
52
  Returns
55
53
  -------
@@ -58,12 +56,8 @@ class YAW2YAWM(TurbineModel):
58
56
  Values: numpy.ndarray with shape (n_states, n_turbines)
59
57
 
60
58
  """
61
- yaw = self.get_data(
62
- FV.YAW, FC.STATE_TURBINE, lookup="f", fdata=fdata, upcast=True
63
- )[st_sel]
64
- wd = self.get_data(
65
- FV.WD, FC.STATE_TURBINE, lookup="f", fdata=fdata, upcast=True
66
- )[st_sel]
59
+ yaw = fdata[FV.YAW][st_sel]
60
+ wd = fdata[FV.WD][st_sel]
67
61
 
68
62
  yawm = fdata[FV.YAWM]
69
63
  yawm[st_sel] = delta_wd(wd, yaw)
@@ -32,7 +32,7 @@ class YAWM2YAW(TurbineModel):
32
32
  return [FV.YAW]
33
33
 
34
34
  def calculate(self, algo, mdata, fdata, st_sel):
35
- """ "
35
+ """
36
36
  The main model calculation.
37
37
 
38
38
  This function is executed on a single chunk of data,
@@ -42,13 +42,13 @@ class YAWM2YAW(TurbineModel):
42
42
  ----------
43
43
  algo: foxes.core.Algorithm
44
44
  The calculation algorithm
45
- mdata: foxes.core.Data
45
+ mdata: foxes.core.MData
46
46
  The model data
47
- fdata: foxes.core.Data
47
+ fdata: foxes.core.FData
48
48
  The farm data
49
- st_sel: numpy.ndarray of bool
49
+ st_sel: slice or numpy.ndarray of bool
50
50
  The state-turbine selection,
51
- shape: (n_states, n_turbines)
51
+ for shape: (n_states, n_turbines)
52
52
 
53
53
  Returns
54
54
  -------
@@ -57,12 +57,8 @@ class YAWM2YAW(TurbineModel):
57
57
  Values: numpy.ndarray with shape (n_states, n_turbines)
58
58
 
59
59
  """
60
- yawm = self.get_data(
61
- FV.YAWM, FC.STATE_TURBINE, lookup="f", fdata=fdata, upcast=True
62
- )[st_sel]
63
- wd = self.get_data(
64
- FV.WD, FC.STATE_TURBINE, lookup="f", fdata=fdata, upcast=True
65
- )[st_sel]
60
+ yawm = fdata[FV.YAWM][st_sel]
61
+ wd = fdata[FV.WD][st_sel]
66
62
 
67
63
  yaw = fdata[FV.YAW]
68
64
  yaw[st_sel] = np.mod(wd + yawm, 360.0)