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.

Files changed (66) hide show
  1. foxes/VERSION +1 -1
  2. foxes/algorithms/downwind/downwind.py +60 -46
  3. foxes/algorithms/downwind/models/farm_wakes_calc.py +17 -6
  4. foxes/algorithms/downwind/models/point_wakes_calc.py +13 -45
  5. foxes/algorithms/iterative/iterative.py +1 -1
  6. foxes/algorithms/iterative/models/farm_wakes_calc.py +18 -4
  7. foxes/constants.py +5 -0
  8. foxes/core/__init__.py +2 -1
  9. foxes/core/ground_model.py +254 -0
  10. foxes/core/model.py +3 -2
  11. foxes/core/partial_wakes_model.py +19 -3
  12. foxes/core/states.py +33 -0
  13. foxes/core/wake_model.py +138 -2
  14. foxes/data/__init__.py +1 -1
  15. foxes/data/states/WRF-Timeseries-3000.nc +0 -0
  16. foxes/data/states/windio_timeseries_5000.nc +0 -0
  17. foxes/data/static_data.py +7 -0
  18. foxes/data/windio/DTU_10MW_turbine.yaml +10 -0
  19. foxes/data/windio/__init__.py +0 -0
  20. foxes/data/windio/windio_5turbines_timeseries.yaml +63 -0
  21. foxes/input/states/__init__.py +1 -0
  22. foxes/input/states/multi_height.py +225 -6
  23. foxes/input/windio/__init__.py +6 -1
  24. foxes/input/windio/get_states.py +115 -0
  25. foxes/input/windio/read_attributes.py +321 -0
  26. foxes/input/windio/read_farm.py +163 -0
  27. foxes/input/windio/read_fields.py +164 -0
  28. foxes/input/windio/runner.py +105 -0
  29. foxes/input/windio/windio.py +136 -254
  30. foxes/models/__init__.py +2 -1
  31. foxes/models/ground_models/__init__.py +2 -0
  32. foxes/models/ground_models/no_ground.py +12 -0
  33. foxes/models/ground_models/wake_mirror.py +161 -0
  34. foxes/models/model_book.py +114 -164
  35. foxes/models/partial_wakes/axiwake.py +27 -4
  36. foxes/models/partial_wakes/top_hat.py +26 -4
  37. foxes/models/turbine_types/PCt_file.py +1 -0
  38. foxes/models/turbine_types/PCt_from_two.py +92 -0
  39. foxes/models/wake_frames/yawed_wakes.py +41 -38
  40. foxes/models/wake_models/__init__.py +0 -1
  41. foxes/models/wake_models/induction/__init__.py +1 -0
  42. foxes/models/wake_models/induction/rankine_half_body.py +1 -1
  43. foxes/models/wake_models/induction/vortex_sheet.py +227 -0
  44. foxes/models/wake_models/ti/crespo_hernandez.py +26 -24
  45. foxes/models/wake_models/ti/iec_ti.py +33 -26
  46. foxes/models/wake_models/wind/bastankhah14.py +11 -32
  47. foxes/models/wake_models/wind/bastankhah16.py +30 -34
  48. foxes/models/wake_models/wind/jensen.py +13 -29
  49. foxes/models/wake_models/wind/turbopark.py +31 -61
  50. foxes/models/wake_superpositions/ws_max.py +1 -0
  51. foxes/models/wake_superpositions/ws_pow.py +1 -0
  52. foxes/models/wake_superpositions/ws_quadratic.py +1 -0
  53. foxes/output/grids.py +6 -6
  54. foxes/output/output.py +6 -6
  55. foxes/utils/__init__.py +1 -1
  56. foxes/utils/factory.py +284 -76
  57. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/METADATA +8 -6
  58. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/RECORD +65 -51
  59. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/WHEEL +1 -1
  60. foxes/models/wake_models/wake_mirror.py +0 -196
  61. /foxes/models/{axial_induction_models → axial_induction}/__init__.py +0 -0
  62. /foxes/models/{axial_induction_models → axial_induction}/betz.py +0 -0
  63. /foxes/models/{axial_induction_models → axial_induction}/madsen.py +0 -0
  64. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/LICENSE +0 -0
  65. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/top_level.txt +0 -0
  66. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/zip-safe +0 -0
foxes/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.1
1
+ 0.7.3
@@ -28,6 +28,9 @@ class Downwind(Algorithm):
28
28
  partial_wakes: dict
29
29
  The partial wakes mapping. Key: wake model name,
30
30
  value: foxes.core.PartialWakesModel
31
+ ground_models: dict
32
+ The ground models mapping. Key: wake model name,
33
+ value: foxes.core.GroundModel
31
34
  farm_controller: foxes.core.FarmController
32
35
  The farm controller
33
36
  n_states: int
@@ -65,9 +68,9 @@ class Downwind(Algorithm):
65
68
  rotor_model="centre",
66
69
  wake_frame="rotor_wd",
67
70
  partial_wakes=None,
71
+ ground_models=None,
68
72
  farm_controller="basic_ctrl",
69
73
  chunks={FC.STATE: 1000, FC.POINT: 4000},
70
- wake_mirrors={},
71
74
  mbook=None,
72
75
  dbook=None,
73
76
  verbosity=1,
@@ -93,15 +96,15 @@ class Downwind(Algorithm):
93
96
  partial_wakes: dict, list or str, optional
94
97
  The partial wakes mapping. Key: wake model name,
95
98
  value: partial wake model name
99
+ ground_models: dict, list or str, optional
100
+ The ground models mapping. Key: wake model name,
101
+ value: ground model name
96
102
  farm_controller: str
97
103
  The farm controller. Will be
98
104
  looked up in the model book
99
105
  chunks: dict
100
106
  The chunks choice for running in parallel with dask,
101
107
  e.g. `{"state": 1000}` for chunks of 1000 states
102
- wake_mirrors: dict
103
- Switch on wake mirrors for wake models.
104
- Key: wake model name, value: list of heights
105
108
  mbook: foxes.ModelBook, optional
106
109
  The model book
107
110
  dbook: foxes.DataBook, optional
@@ -129,51 +132,60 @@ class Downwind(Algorithm):
129
132
  for w in wake_models:
130
133
  m = self.mbook.wake_models[w]
131
134
  m.name = w
132
-
133
- # optionally add wake mirrors:
134
- if w in wake_mirrors:
135
- hts = wake_mirrors[w]
136
- if isinstance(m, fm.wake_models.WakeMirror):
137
- if list(m.heights) != list(hts):
138
- raise ValueError(
139
- f"Wake model '{w}' is mirrored with heights {m.heights}, cannot apply WakeMirror with heights {hts}"
135
+ self.wake_models[w] = m
136
+
137
+ def _set_wspecific(descr, target, values, deffunc, mbooks, checkw):
138
+ if values is None:
139
+ values = {}
140
+ if isinstance(values, list) and len(values) == 1:
141
+ values = values[0]
142
+ if isinstance(values, str):
143
+ for w in wake_models:
144
+ try:
145
+ pw = values
146
+ if checkw:
147
+ mbooks[pw].check_wmodel(self.wake_models[w], error=True)
148
+ except TypeError:
149
+ pw = deffunc(self.wake_models[w])
150
+ target[w] = mbooks[pw]
151
+ target[w].name = pw
152
+ elif isinstance(values, list):
153
+ for i, w in enumerate(wake_models):
154
+ if i >= len(values):
155
+ raise IndexError(
156
+ f"Not enough {descr} in list {values}, expecting {len(wake_models)}"
140
157
  )
141
- else:
142
- self.wake_models[w] = fm.wake_models.WakeMirror(m, heights=hts)
143
-
158
+ pw = values[i]
159
+ target[w] = mbooks[pw]
160
+ target[w].name = pw
144
161
  else:
145
- self.wake_models[w] = m
162
+ for w in wake_models:
163
+ if w in values:
164
+ pw = values[w]
165
+ else:
166
+ pw = deffunc(self.wake_models[w])
167
+ target[w] = mbooks[pw]
168
+ target[w].name = pw
146
169
 
147
170
  self.partial_wakes = {}
148
- if partial_wakes is None:
149
- partial_wakes = {}
150
- if isinstance(partial_wakes, list) and len(partial_wakes) == 1:
151
- partial_wakes = partial_wakes[0]
152
- if isinstance(partial_wakes, str):
153
- for w in wake_models:
154
- try:
155
- pw = partial_wakes
156
- except TypeError:
157
- pw = mbook.default_partial_wakes(self.wake_models[w])
158
- self.partial_wakes[w] = self.mbook.partial_wakes[pw]
159
- self.partial_wakes[w].name = pw
160
- elif isinstance(partial_wakes, list):
161
- for i, w in enumerate(wake_models):
162
- if i >= len(partial_wakes):
163
- raise IndexError(
164
- f"Not enough partial wakes in list {partial_wakes}, expecting {len(wake_models)}"
165
- )
166
- pw = partial_wakes[i]
167
- self.partial_wakes[w] = self.mbook.partial_wakes[pw]
168
- self.partial_wakes[w].name = pw
169
- else:
170
- for w in wake_models:
171
- if w in partial_wakes:
172
- pw = partial_wakes[w]
173
- else:
174
- pw = mbook.default_partial_wakes(self.wake_models[w])
175
- self.partial_wakes[w] = self.mbook.partial_wakes[pw]
176
- self.partial_wakes[w].name = pw
171
+ _set_wspecific(
172
+ descr="partial wakes",
173
+ target=self.partial_wakes,
174
+ values=partial_wakes,
175
+ deffunc=mbook.default_partial_wakes,
176
+ mbooks=self.mbook.partial_wakes,
177
+ checkw=True,
178
+ )
179
+
180
+ self.ground_models = {}
181
+ _set_wspecific(
182
+ descr="ground models",
183
+ target=self.ground_models,
184
+ values=ground_models,
185
+ deffunc=lambda w: "no_ground",
186
+ mbooks=self.mbook.ground_models,
187
+ checkw=False,
188
+ )
177
189
 
178
190
  self.farm_controller = self.mbook.farm_controllers[farm_controller]
179
191
  self.farm_controller.name = farm_controller
@@ -227,7 +239,9 @@ class Downwind(Algorithm):
227
239
  for i, m in enumerate(self.farm_controller.pre_rotor_models.models):
228
240
  print(f" {i}) {m.name}: {m} [pre-rotor]")
229
241
  for i, m in enumerate(self.farm_controller.post_rotor_models.models):
230
- print(f" {i+len(self.farm_controller.pre_rotor_models.models)}) {m.name}: {m}")
242
+ print(
243
+ f" {i+len(self.farm_controller.pre_rotor_models.models)}) {m.name}: {m}"
244
+ )
231
245
  print(deco)
232
246
  print()
233
247
 
@@ -75,10 +75,12 @@ class FarmWakesCalculation(FarmDataModel):
75
75
  wdelta = {v: d[s] for v, d in wdeltas.items()}
76
76
  return tdata, wdelta
77
77
 
78
- def _evaluate(tdata, amb_res, weights, wake_res, wdeltas, oi, wmodel, pwake):
78
+ def _evaluate(
79
+ gmodel, tdata, amb_res, weights, wake_res, wdeltas, oi, wmodel, pwake
80
+ ):
79
81
  """Helper function for data evaluation at turbines"""
80
- wres = pwake.finalize_wakes(
81
- algo, mdata, fdata, tdata, amb_res, weights, wdeltas, wmodel, oi
82
+ wres = gmodel.finalize_farm_wakes(
83
+ algo, mdata, fdata, tdata, amb_res, weights, wdeltas, wmodel, oi, pwake
82
84
  )
83
85
 
84
86
  hres = {v: d[:, oi, None] for v, d in wake_res.items()}
@@ -101,8 +103,11 @@ class FarmWakesCalculation(FarmDataModel):
101
103
  run_down = None
102
104
  for wname, wmodel in algo.wake_models.items():
103
105
  pwake = algo.partial_wakes[wname]
106
+ gmodel = algo.ground_models[wname]
104
107
  tdatap = pwake2tdata[pwake.name]
105
- wdeltas = pwake.new_wake_deltas(algo, mdata, fdata, tdatap, wmodel)
108
+ wdeltas = gmodel.new_farm_wake_deltas(
109
+ algo, mdata, fdata, tdatap, wmodel, pwake
110
+ )
106
111
 
107
112
  # downwind:
108
113
  if wmodel.affects_downwind:
@@ -110,6 +115,7 @@ class FarmWakesCalculation(FarmDataModel):
110
115
  for oi in range(n_turbines):
111
116
  if oi > 0:
112
117
  _evaluate(
118
+ gmodel,
113
119
  tdatap,
114
120
  amb_res,
115
121
  weights,
@@ -122,7 +128,9 @@ class FarmWakesCalculation(FarmDataModel):
122
128
 
123
129
  if oi < n_turbines - 1:
124
130
  tdata, wdelta = _get_wdata(tdatap, wdeltas, np.s_[:, oi + 1 :])
125
- pwake.contribute(algo, mdata, fdata, tdata, oi, wdelta, wmodel)
131
+ gmodel.contribute_to_farm_wakes(
132
+ algo, mdata, fdata, tdata, oi, wdelta, wmodel, pwake
133
+ )
126
134
 
127
135
  # upwind:
128
136
  else:
@@ -130,6 +138,7 @@ class FarmWakesCalculation(FarmDataModel):
130
138
  for oi in range(n_turbines - 1, -1, -1):
131
139
  if oi < n_turbines - 1:
132
140
  _evaluate(
141
+ gmodel,
133
142
  tdatap,
134
143
  amb_res,
135
144
  weights,
@@ -142,7 +151,9 @@ class FarmWakesCalculation(FarmDataModel):
142
151
 
143
152
  if oi > 0:
144
153
  tdata, wdelta = _get_wdata(tdatap, wdeltas, np.s_[:, :oi])
145
- pwake.contribute(algo, mdata, fdata, tdata, oi, wdelta, wmodel)
154
+ gmodel.contribute_to_farm_wakes(
155
+ algo, mdata, fdata, tdata, oi, wdelta, wmodel, pwake
156
+ )
146
157
 
147
158
  if run_up is not None and run_down is not None:
148
159
  raise KeyError(
@@ -1,6 +1,7 @@
1
+ import numpy as np
2
+ from foxes.core import PointDataModel, TData
1
3
  import foxes.variables as FV
2
4
  import foxes.constants as FC
3
- from foxes.core import PointDataModel
4
5
 
5
6
 
6
7
  class PointWakesCalculation(PointDataModel):
@@ -86,43 +87,6 @@ class PointWakesCalculation(PointDataModel):
86
87
  """
87
88
  return self.pvars
88
89
 
89
- def contribute(
90
- self,
91
- algo,
92
- mdata,
93
- fdata,
94
- tdata,
95
- downwind_index,
96
- wmodel,
97
- wdeltas,
98
- ):
99
- """
100
- Contribute to wake deltas from source turbines
101
-
102
- Parameters
103
- ----------
104
- algo: foxes.core.Algorithm
105
- The calculation algorithm
106
- mdata: foxes.core.Data
107
- The model data
108
- fdata: foxes.core.Data
109
- The farm data
110
- tdata: foxes.core.Data
111
- The target point data
112
- downwind_index: int
113
- The index in the downwind order
114
- wmodel: foxes.core.WakeModel
115
- The wake model
116
- wdeltas: dict
117
- The wake deltas, are being modified ob the fly.
118
- Key: Variable name str, for which the
119
- wake delta applies, values: numpy.ndarray with
120
- shape (n_states, n_targets, n_tpoints, ...)
121
-
122
- """
123
- wcoos = algo.wake_frame.get_wake_coos(algo, mdata, fdata, tdata, downwind_index)
124
- wmodel.contribute(algo, mdata, fdata, tdata, downwind_index, wcoos, wdeltas)
125
-
126
90
  def calculate(self, algo, mdata, fdata, tdata, downwind_index=None):
127
91
  """ "
128
92
  The main model calculation.
@@ -151,29 +115,33 @@ class PointWakesCalculation(PointDataModel):
151
115
  (n_states, n_targets, n_tpoints)
152
116
 
153
117
  """
154
-
155
118
  res = {}
156
119
  wmodels = (
157
120
  algo.wake_models.values() if self.wake_models is None else self.wake_models
158
121
  )
159
122
  for wmodel in wmodels:
160
- wdeltas = wmodel.new_wake_deltas(algo, mdata, fdata, tdata)
123
+ pwake = algo.partial_wakes[wmodel.name]
124
+ gmodel = algo.ground_models[wmodel.name]
125
+
126
+ wdeltas = gmodel.new_point_wake_deltas(algo, mdata, fdata, tdata, wmodel)
127
+
161
128
  if len(set(self.pvars).intersection(wdeltas.keys())):
162
129
 
163
130
  if downwind_index is None:
164
131
  for oi in range(fdata.n_turbines):
165
- self.contribute(algo, mdata, fdata, tdata, oi, wmodel, wdeltas)
166
-
132
+ gmodel.contribute_to_point_wakes(
133
+ algo, mdata, fdata, tdata, oi, wdeltas, wmodel
134
+ )
167
135
  else:
168
- self.contribute(
169
- algo, mdata, fdata, tdata, downwind_index, wmodel, wdeltas
136
+ gmodel.contribute_to_point_wakes(
137
+ algo, mdata, fdata, tdata, downwind_index, wdeltas, wmodel
170
138
  )
171
139
 
172
140
  for v in self.pvars:
173
141
  if v not in res and v in tdata:
174
142
  res[v] = tdata[v].copy()
175
143
 
176
- wmodel.finalize_wake_deltas(algo, mdata, fdata, res, wdeltas)
144
+ gmodel.finalize_point_wakes(algo, mdata, fdata, res, wdeltas, wmodel)
177
145
 
178
146
  for v in res.keys():
179
147
  if v in wdeltas:
@@ -64,7 +64,7 @@ class Iterative(Downwind):
64
64
  """
65
65
  super().__init__(*args, **kwargs)
66
66
 
67
- self.max_it = 2 * self.farm.n_turbines if max_it is None else max_it
67
+ self.max_it = 2 + self.farm.n_turbines**2 if max_it is None else max_it
68
68
  self.conv_crit = (
69
69
  self.get_model("DefaultConv")() if conv_crit == "default" else conv_crit
70
70
  )
@@ -109,6 +109,7 @@ class FarmWakesCalculation(FarmDataModel):
109
109
  n_turbines = mdata.n_turbines
110
110
  for wname, wmodel in algo.wake_models.items():
111
111
  pwake = algo.partial_wakes[wname]
112
+ gmodel = algo.ground_models[wname]
112
113
  tdatap = pwake2tdata[pwake.name]
113
114
  wdeltas = pwake.new_wake_deltas(algo, mdata, fdata, tdatap, wmodel)
114
115
 
@@ -116,15 +117,28 @@ class FarmWakesCalculation(FarmDataModel):
116
117
 
117
118
  if oi > 0:
118
119
  tdata, wdelta = _get_wdata(tdatap, wdeltas, np.s_[:, :oi])
119
- pwake.contribute(algo, mdata, fdata, tdata, oi, wdelta, wmodel)
120
+ gmodel.contribute_to_farm_wakes(
121
+ algo, mdata, fdata, tdata, oi, wdelta, wmodel, pwake
122
+ )
120
123
 
121
124
  if oi < n_turbines - 1:
122
125
  tdata, wdelta = _get_wdata(tdatap, wdeltas, np.s_[:, oi + 1 :])
123
- pwake.contribute(algo, mdata, fdata, tdata, oi, wdelta, wmodel)
126
+ gmodel.contribute_to_farm_wakes(
127
+ algo, mdata, fdata, tdata, oi, wdelta, wmodel, pwake
128
+ )
124
129
 
125
130
  for oi in range(n_turbines):
126
- wres = pwake.finalize_wakes(
127
- algo, mdata, fdata, tdatap, amb_res, weights, wdeltas, wmodel, oi
131
+ wres = gmodel.finalize_farm_wakes(
132
+ algo,
133
+ mdata,
134
+ fdata,
135
+ tdatap,
136
+ amb_res,
137
+ weights,
138
+ wdeltas,
139
+ wmodel,
140
+ oi,
141
+ pwake,
128
142
  )
129
143
  for v, d in wres.items():
130
144
  if v in wake_res:
foxes/constants.py CHANGED
@@ -15,6 +15,11 @@ STATE = "state"
15
15
  :group: foxes.constants
16
16
  """
17
17
 
18
+ TIME = "time"
19
+ """ Time identifier
20
+ :group: foxes.constants
21
+ """
22
+
18
23
  TURBINE = "turbine"
19
24
  """ Wind turbine identifier
20
25
  :group: foxes.constants
foxes/core/__init__.py CHANGED
@@ -18,7 +18,8 @@ from .farm_controller import FarmController
18
18
  from .turbine import Turbine
19
19
  from .partial_wakes_model import PartialWakesModel
20
20
  from .wake_frame import WakeFrame
21
- from .wake_model import WakeModel, TurbineInductionModel
21
+ from .wake_model import WakeModel, TurbineInductionModel, WakeK
22
22
  from .wake_superposition import WakeSuperposition
23
23
  from .vertical_profile import VerticalProfile
24
24
  from .axial_induction_model import AxialInductionModel
25
+ from .ground_model import GroundModel
@@ -0,0 +1,254 @@
1
+ from .model import Model
2
+
3
+
4
+ class GroundModel(Model):
5
+ """
6
+ Base class for ground models.
7
+ """
8
+
9
+ def new_farm_wake_deltas(
10
+ self,
11
+ algo,
12
+ mdata,
13
+ fdata,
14
+ tdata,
15
+ wmodel,
16
+ pwake,
17
+ ):
18
+ """
19
+ Creates new initial wake deltas, filled
20
+ with zeros.
21
+
22
+ Parameters
23
+ ----------
24
+ algo: foxes.core.Algorithm
25
+ The calculation algorithm
26
+ mdata: foxes.core.Data
27
+ The model data
28
+ fdata: foxes.core.Data
29
+ The farm data
30
+ tdata: foxes.core.Data
31
+ The target point data
32
+ wmodel: foxes.core.WakeModel
33
+ The wake model
34
+ pwake: foxes.core.PartialWakesModel
35
+ The partial wakes model
36
+
37
+ Returns
38
+ -------
39
+ wake_deltas: dict
40
+ Key: variable name, value: The zero filled
41
+ wake deltas, shape: (n_states, n_turbines, n_tpoints, ...)
42
+
43
+ """
44
+ return pwake.new_wake_deltas(algo, mdata, fdata, tdata, wmodel)
45
+
46
+ def contribute_to_farm_wakes(
47
+ self,
48
+ algo,
49
+ mdata,
50
+ fdata,
51
+ tdata,
52
+ downwind_index,
53
+ wake_deltas,
54
+ wmodel,
55
+ pwake,
56
+ ):
57
+ """
58
+ Modifies wake deltas at target points by
59
+ contributions from the specified wake source turbines.
60
+
61
+ Parameters
62
+ ----------
63
+ algo: foxes.core.Algorithm
64
+ The calculation algorithm
65
+ mdata: foxes.core.MData
66
+ The model data
67
+ fdata: foxes.core.FData
68
+ The farm data
69
+ tdata: foxes.core.TData
70
+ The target point data
71
+ downwind_index: int
72
+ The index of the wake causing turbine
73
+ in the downwnd order
74
+ wake_deltas: dict
75
+ The wake deltas. Key: variable name,
76
+ value: numpy.ndarray with shape
77
+ (n_states, n_targets, n_tpoints, ...)
78
+ wmodel: foxes.core.WakeModel
79
+ The wake model
80
+ pwake: foxes.core.PartialWakesModel
81
+ The partial wakes model
82
+
83
+ """
84
+ pwake.contribute(algo, mdata, fdata, tdata, downwind_index, wake_deltas, wmodel)
85
+
86
+ def finalize_farm_wakes(
87
+ self,
88
+ algo,
89
+ mdata,
90
+ fdata,
91
+ tdata,
92
+ amb_res,
93
+ rpoint_weights,
94
+ wake_deltas,
95
+ wmodel,
96
+ downwind_index,
97
+ pwake,
98
+ ):
99
+ """
100
+ Updates the wake_deltas at the selected target
101
+ downwind index.
102
+
103
+ Modifies wake_deltas on the fly.
104
+
105
+ Parameters
106
+ ----------
107
+ algo: foxes.core.Algorithm
108
+ The calculation algorithm
109
+ mdata: foxes.core.MData
110
+ The model data
111
+ fdata: foxes.core.FData
112
+ The farm data
113
+ tdata: foxes.core.Data
114
+ The target point data
115
+ amb_res: dict
116
+ The ambient results at the target points
117
+ of all rotors. Key: variable name, value
118
+ np.ndarray of shape:
119
+ (n_states, n_turbines, n_rotor_points)
120
+ rpoint_weights: numpy.ndarray
121
+ The rotor point weights, shape: (n_rotor_points,)
122
+ wake_deltas: dict
123
+ The wake deltas. Key: variable name,
124
+ value: np.ndarray of shape
125
+ (n_states, n_turbines, n_tpoints)
126
+ wmodel: foxes.core.WakeModel
127
+ The wake model
128
+ downwind_index: int
129
+ The index in the downwind order
130
+
131
+ Returns
132
+ -------
133
+ final_wake_deltas: dict
134
+ The final wake deltas at the selected downwind
135
+ turbines. Key: variable name, value: np.ndarray
136
+ of shape (n_states, n_rotor_points)
137
+
138
+ """
139
+ return pwake.finalize_wakes(
140
+ algo,
141
+ mdata,
142
+ fdata,
143
+ tdata,
144
+ amb_res,
145
+ rpoint_weights,
146
+ wake_deltas,
147
+ wmodel,
148
+ downwind_index,
149
+ )
150
+
151
+ def new_point_wake_deltas(
152
+ self,
153
+ algo,
154
+ mdata,
155
+ fdata,
156
+ tdata,
157
+ wmodel,
158
+ ):
159
+ """
160
+ Creates new empty wake delta arrays.
161
+
162
+ Parameters
163
+ ----------
164
+ algo: foxes.core.Algorithm
165
+ The calculation algorithm
166
+ mdata: foxes.core.MData
167
+ The model data
168
+ fdata: foxes.core.FData
169
+ The farm data
170
+ tdata: foxes.core.TData
171
+ The target point data
172
+ wmodel: foxes.core.WakeModel
173
+ The wake model
174
+
175
+ Returns
176
+ -------
177
+ wake_deltas: dict
178
+ Key: variable name, value: The zero filled
179
+ wake deltas, shape: (n_states, n_targets, n_tpoints, ...)
180
+
181
+ """
182
+ return wmodel.new_wake_deltas(algo, mdata, fdata, tdata)
183
+
184
+ def contribute_to_point_wakes(
185
+ self,
186
+ algo,
187
+ mdata,
188
+ fdata,
189
+ tdata,
190
+ downwind_index,
191
+ wake_deltas,
192
+ wmodel,
193
+ ):
194
+ """
195
+ Modifies wake deltas at target points by
196
+ contributions from the specified wake source turbines.
197
+
198
+ Parameters
199
+ ----------
200
+ algo: foxes.core.Algorithm
201
+ The calculation algorithm
202
+ mdata: foxes.core.MData
203
+ The model data
204
+ fdata: foxes.core.FData
205
+ The farm data
206
+ tdata: foxes.core.TData
207
+ The target point data
208
+ downwind_index: int
209
+ The index of the wake causing turbine
210
+ in the downwnd order
211
+ wake_deltas: dict
212
+ The wake deltas. Key: variable name,
213
+ value: numpy.ndarray with shape
214
+ (n_states, n_targets, n_tpoints, ...)
215
+ wmodel: foxes.core.WakeModel
216
+ The wake model
217
+
218
+ """
219
+ wcoos = algo.wake_frame.get_wake_coos(algo, mdata, fdata, tdata, downwind_index)
220
+ wmodel.contribute(algo, mdata, fdata, tdata, downwind_index, wcoos, wake_deltas)
221
+
222
+ def finalize_point_wakes(
223
+ self,
224
+ algo,
225
+ mdata,
226
+ fdata,
227
+ amb_results,
228
+ wake_deltas,
229
+ wmodel,
230
+ ):
231
+ """
232
+ Finalize the wake calculation.
233
+
234
+ Modifies wake_deltas on the fly.
235
+
236
+ Parameters
237
+ ----------
238
+ algo: foxes.core.Algorithm
239
+ The calculation algorithm
240
+ mdata: foxes.core.MData
241
+ The model data
242
+ fdata: foxes.core.FData
243
+ The farm data
244
+ amb_results: dict
245
+ The ambient results, key: variable name str,
246
+ values: numpy.ndarray with shape
247
+ (n_states, n_targets, n_tpoints)
248
+ wake_deltas: dict
249
+ The wake deltas object at the selected target
250
+ turbines. Key: variable str, value: numpy.ndarray
251
+ with shape (n_states, n_targets, n_tpoints)
252
+
253
+ """
254
+ wmodel.finalize_wake_deltas(algo, mdata, fdata, amb_results, wake_deltas)
foxes/core/model.py CHANGED
@@ -31,8 +31,9 @@ class Model(ABC):
31
31
  self._ids[t] = count(0)
32
32
  self._id = next(self._ids[t])
33
33
 
34
- ext = "" if self._id == 0 else f"{self._id}"
35
- self.name = f"{type(self).__name__}{ext}"
34
+ self.name = f"{type(self).__name__}"
35
+ if self._id > 0:
36
+ self.name += f"_instance{self._id}"
36
37
 
37
38
  self._store = {}
38
39
  self.__initialized = False