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
@@ -49,6 +49,10 @@ class WSPow(WakeSuperposition):
49
49
  self.lim_low = lim_low
50
50
  self.lim_high = lim_high
51
51
 
52
+ def __repr__(self):
53
+ a = f"pow={self.pow}, scale_amb={self.scale_amb}, lim_low={self.lim_low}, lim_high={self.lim_high}"
54
+ return f"{type(self).__name__}({a})"
55
+
52
56
  def input_farm_vars(self, algo):
53
57
  """
54
58
  The variables which are needed for running
@@ -67,48 +71,51 @@ class WSPow(WakeSuperposition):
67
71
  """
68
72
  return [FV.AMB_REWS] if self.scale_amb else [FV.REWS]
69
73
 
70
- def calc_wakes_plus_wake(
74
+ def add_wake(
71
75
  self,
72
76
  algo,
73
77
  mdata,
74
78
  fdata,
75
- pdata,
76
- states_source_turbine,
77
- sel_sp,
79
+ tdata,
80
+ downwind_index,
81
+ st_sel,
78
82
  variable,
79
83
  wake_delta,
80
84
  wake_model_result,
81
85
  ):
82
86
  """
83
- Add a wake delta to previous wake deltas.
87
+ Add a wake delta to previous wake deltas,
88
+ at rotor points.
84
89
 
85
90
  Parameters
86
91
  ----------
87
92
  algo: foxes.core.Algorithm
88
93
  The calculation algorithm
89
- mdata: foxes.core.Data
94
+ mdata: foxes.core.MData
90
95
  The model data
91
- fdata: foxes.core.Data
96
+ fdata: foxes.core.FData
92
97
  The farm data
93
- pdata: foxes.core.Data
94
- The evaluation point data
95
- states_source_turbine: numpy.ndarray
96
- For each state, one turbine index for the
97
- wake causing turbine. Shape: (n_states,)
98
- sel_sp: numpy.ndarray of bool
99
- The selection of points, shape: (n_states, n_points)
98
+ tdata: foxes.core.TData
99
+ The target point data
100
+ downwind_index: int
101
+ The index of the wake causing turbine
102
+ in the downwnd order
103
+ st_sel: numpy.ndarray of bool
104
+ The selection of targets, shape: (n_states, n_targets)
100
105
  variable: str
101
106
  The variable name for which the wake deltas applies
102
107
  wake_delta: numpy.ndarray
103
- The original wake deltas, shape: (n_states, n_points)
108
+ The original wake deltas, shape:
109
+ (n_states, n_targets, n_tpoints, ...)
104
110
  wake_model_result: numpy.ndarray
105
- The new wake deltas of the selected points,
106
- shape: (n_sel_sp,)
111
+ The new wake deltas of the selected rotors,
112
+ shape: (n_st_sel, n_tpoints, ...)
107
113
 
108
114
  Returns
109
115
  -------
110
116
  wdelta: numpy.ndarray
111
- The updated wake deltas, shape: (n_states, n_points)
117
+ The updated wake deltas, shape:
118
+ (n_states, n_targets, n_tpoints, ...)
112
119
 
113
120
  """
114
121
  if variable not in [FV.REWS, FV.REWS2, FV.REWS3, FV.WS]:
@@ -116,19 +123,19 @@ class WSPow(WakeSuperposition):
116
123
  f"Superposition '{self.name}': Expecting wind speed variable, got {variable}"
117
124
  )
118
125
 
119
- if np.any(sel_sp):
126
+ if np.any(st_sel):
120
127
  scale = self.get_data(
121
128
  FV.AMB_REWS if self.scale_amb else FV.REWS,
122
- FC.STATE_POINT,
129
+ FC.STATE_TARGET,
123
130
  lookup="w",
124
131
  algo=algo,
125
132
  fdata=fdata,
126
- pdata=pdata,
133
+ tdata=tdata,
134
+ downwind_index=downwind_index,
127
135
  upcast=True,
128
- states_source_turbine=states_source_turbine,
129
- )[sel_sp]
136
+ )[st_sel, None]
130
137
 
131
- wake_delta[sel_sp] += np.abs(scale * wake_model_result) ** self.pow
138
+ wake_delta[st_sel] += np.abs(scale * wake_model_result) ** self.pow
132
139
 
133
140
  return wake_delta
134
141
 
@@ -137,7 +144,6 @@ class WSPow(WakeSuperposition):
137
144
  algo,
138
145
  mdata,
139
146
  fdata,
140
- pdata,
141
147
  variable,
142
148
  amb_results,
143
149
  wake_delta,
@@ -150,24 +156,25 @@ class WSPow(WakeSuperposition):
150
156
  ----------
151
157
  algo: foxes.core.Algorithm
152
158
  The calculation algorithm
153
- mdata: foxes.core.Data
159
+ mdata: foxes.core.MData
154
160
  The model data
155
- fdata: foxes.core.Data
161
+ fdata: foxes.core.FData
156
162
  The farm data
157
- pdata: foxes.core.Data
158
- The evaluation point data
159
163
  variable: str
160
164
  The variable name for which the wake deltas applies
161
165
  amb_results: numpy.ndarray
162
- The ambient results, shape: (n_states, n_points)
166
+ The ambient results at targets,
167
+ shape: (n_states, n_targets, n_tpoints)
163
168
  wake_delta: numpy.ndarray
164
- The wake deltas, shape: (n_states, n_points)
169
+ The wake deltas at targets, shape:
170
+ (n_states, n_targets, n_tpoints)
165
171
 
166
172
  Returns
167
173
  -------
168
174
  final_wake_delta: numpy.ndarray
169
175
  The final wake delta, which will be added to the ambient
170
- results by simple plus operation. Shape: (n_states, n_points)
176
+ results by simple plus operation. Shape:
177
+ (n_states, n_targets, n_tpoints)
171
178
 
172
179
  """
173
180
  w = -(wake_delta ** (1 / self.pow))
@@ -45,6 +45,10 @@ class WSProduct(WakeSuperposition):
45
45
  self.lim_low = lim_low
46
46
  self.lim_high = lim_high
47
47
 
48
+ def __repr__(self):
49
+ a = f"lim_low={self.lim_low}, lim_high={self.lim_high}"
50
+ return f"{type(self).__name__}({a})"
51
+
48
52
  def input_farm_vars(self, algo):
49
53
  """
50
54
  The variables which are needed for running
@@ -63,48 +67,51 @@ class WSProduct(WakeSuperposition):
63
67
  """
64
68
  return [FV.AMB_REWS] if self.scale_amb else [FV.REWS]
65
69
 
66
- def calc_wakes_plus_wake(
70
+ def add_wake(
67
71
  self,
68
72
  algo,
69
73
  mdata,
70
74
  fdata,
71
- pdata,
72
- states_source_turbine,
73
- sel_sp,
75
+ tdata,
76
+ downwind_index,
77
+ st_sel,
74
78
  variable,
75
79
  wake_delta,
76
80
  wake_model_result,
77
81
  ):
78
82
  """
79
- Add a wake delta to previous wake deltas.
83
+ Add a wake delta to previous wake deltas,
84
+ at rotor points.
80
85
 
81
86
  Parameters
82
87
  ----------
83
88
  algo: foxes.core.Algorithm
84
89
  The calculation algorithm
85
- mdata: foxes.core.Data
90
+ mdata: foxes.core.MData
86
91
  The model data
87
- fdata: foxes.core.Data
92
+ fdata: foxes.core.FData
88
93
  The farm data
89
- pdata: foxes.core.Data
90
- The evaluation point data
91
- states_source_turbine: numpy.ndarray
92
- For each state, one turbine index for the
93
- wake causing turbine. Shape: (n_states,)
94
- sel_sp: numpy.ndarray of bool
95
- The selection of points, shape: (n_states, n_points)
94
+ tdata: foxes.core.TData
95
+ The target point data
96
+ downwind_index: int
97
+ The index of the wake causing turbine
98
+ in the downwnd order
99
+ st_sel: numpy.ndarray of bool
100
+ The selection of targets, shape: (n_states, n_targets)
96
101
  variable: str
97
102
  The variable name for which the wake deltas applies
98
103
  wake_delta: numpy.ndarray
99
- The original wake deltas, shape: (n_states, n_points)
104
+ The original wake deltas, shape:
105
+ (n_states, n_targets, n_tpoints, ...)
100
106
  wake_model_result: numpy.ndarray
101
- The new wake deltas of the selected points,
102
- shape: (n_sel_sp,)
107
+ The new wake deltas of the selected rotors,
108
+ shape: (n_st_sel, n_tpoints, ...)
103
109
 
104
110
  Returns
105
111
  -------
106
112
  wdelta: numpy.ndarray
107
- The updated wake deltas, shape: (n_states, n_points)
113
+ The updated wake deltas, shape:
114
+ (n_states, n_targets, n_tpoints, ...)
108
115
 
109
116
  """
110
117
  if variable not in [FV.REWS, FV.REWS2, FV.REWS3, FV.WS]:
@@ -112,11 +119,11 @@ class WSProduct(WakeSuperposition):
112
119
  f"Superposition '{self.name}': Expecting wind speed variable, got {variable}"
113
120
  )
114
121
 
115
- if np.any(sel_sp):
122
+ if np.any(st_sel):
116
123
  if np.max(np.abs(wake_delta)) < 1e-14:
117
124
  wake_delta[:] = 1
118
125
 
119
- wake_delta[sel_sp] *= 1 + wake_model_result
126
+ wake_delta[st_sel] *= 1 + wake_model_result
120
127
 
121
128
  return wake_delta
122
129
 
@@ -125,7 +132,6 @@ class WSProduct(WakeSuperposition):
125
132
  algo,
126
133
  mdata,
127
134
  fdata,
128
- pdata,
129
135
  variable,
130
136
  amb_results,
131
137
  wake_delta,
@@ -138,24 +144,25 @@ class WSProduct(WakeSuperposition):
138
144
  ----------
139
145
  algo: foxes.core.Algorithm
140
146
  The calculation algorithm
141
- mdata: foxes.core.Data
147
+ mdata: foxes.core.MData
142
148
  The model data
143
- fdata: foxes.core.Data
149
+ fdata: foxes.core.FData
144
150
  The farm data
145
- pdata: foxes.core.Data
146
- The evaluation point data
147
151
  variable: str
148
152
  The variable name for which the wake deltas applies
149
153
  amb_results: numpy.ndarray
150
- The ambient results, shape: (n_states, n_points)
154
+ The ambient results at targets,
155
+ shape: (n_states, n_targets, n_tpoints)
151
156
  wake_delta: numpy.ndarray
152
- The wake deltas, shape: (n_states, n_points)
157
+ The wake deltas at targets, shape:
158
+ (n_states, n_targets, n_tpoints)
153
159
 
154
160
  Returns
155
161
  -------
156
162
  final_wake_delta: numpy.ndarray
157
163
  The final wake delta, which will be added to the ambient
158
- results by simple plus operation. Shape: (n_states, n_points)
164
+ results by simple plus operation. Shape:
165
+ (n_states, n_targets, n_tpoints)
159
166
 
160
167
  """
161
168
  w = amb_results * (wake_delta - 1)
@@ -44,6 +44,10 @@ class WSQuadratic(WakeSuperposition):
44
44
  self.lim_low = lim_low
45
45
  self.lim_high = lim_high
46
46
 
47
+ def __repr__(self):
48
+ a = f"scale_amb={self.scale_amb}, lim_low={self.lim_low}, lim_high={self.lim_high}"
49
+ return f"{type(self).__name__}({a})"
50
+
47
51
  def input_farm_vars(self, algo):
48
52
  """
49
53
  The variables which are needed for running
@@ -62,48 +66,51 @@ class WSQuadratic(WakeSuperposition):
62
66
  """
63
67
  return [FV.AMB_REWS] if self.scale_amb else [FV.REWS]
64
68
 
65
- def calc_wakes_plus_wake(
69
+ def add_wake(
66
70
  self,
67
71
  algo,
68
72
  mdata,
69
73
  fdata,
70
- pdata,
71
- states_source_turbine,
72
- sel_sp,
74
+ tdata,
75
+ downwind_index,
76
+ st_sel,
73
77
  variable,
74
78
  wake_delta,
75
79
  wake_model_result,
76
80
  ):
77
81
  """
78
- Add a wake delta to previous wake deltas.
82
+ Add a wake delta to previous wake deltas,
83
+ at rotor points.
79
84
 
80
85
  Parameters
81
86
  ----------
82
87
  algo: foxes.core.Algorithm
83
88
  The calculation algorithm
84
- mdata: foxes.core.Data
89
+ mdata: foxes.core.MData
85
90
  The model data
86
- fdata: foxes.core.Data
91
+ fdata: foxes.core.FData
87
92
  The farm data
88
- pdata: foxes.core.Data
89
- The evaluation point data
90
- states_source_turbine: numpy.ndarray
91
- For each state, one turbine index for the
92
- wake causing turbine. Shape: (n_states,)
93
- sel_sp: numpy.ndarray of bool
94
- The selection of points, shape: (n_states, n_points)
93
+ tdata: foxes.core.TData
94
+ The target point data
95
+ downwind_index: int
96
+ The index of the wake causing turbine
97
+ in the downwnd order
98
+ st_sel: numpy.ndarray of bool
99
+ The selection of targets, shape: (n_states, n_targets)
95
100
  variable: str
96
101
  The variable name for which the wake deltas applies
97
102
  wake_delta: numpy.ndarray
98
- The original wake deltas, shape: (n_states, n_points)
103
+ The original wake deltas, shape:
104
+ (n_states, n_targets, n_tpoints, ...)
99
105
  wake_model_result: numpy.ndarray
100
- The new wake deltas of the selected points,
101
- shape: (n_sel_sp,)
106
+ The new wake deltas of the selected rotors,
107
+ shape: (n_st_sel, n_tpoints, ...)
102
108
 
103
109
  Returns
104
110
  -------
105
111
  wdelta: numpy.ndarray
106
- The updated wake deltas, shape: (n_states, n_points)
112
+ The updated wake deltas, shape:
113
+ (n_states, n_targets, n_tpoints, ...)
107
114
 
108
115
  """
109
116
  if variable not in [FV.REWS, FV.REWS2, FV.REWS3, FV.WS]:
@@ -111,19 +118,19 @@ class WSQuadratic(WakeSuperposition):
111
118
  f"Superposition '{self.name}': Expecting wind speed variable, got {variable}"
112
119
  )
113
120
 
114
- if np.any(sel_sp):
121
+ if np.any(st_sel):
115
122
  scale = self.get_data(
116
123
  FV.AMB_REWS if self.scale_amb else FV.REWS,
117
- FC.STATE_POINT,
124
+ FC.STATE_TARGET,
118
125
  lookup="w",
119
126
  algo=algo,
120
127
  fdata=fdata,
121
- pdata=pdata,
128
+ tdata=tdata,
129
+ downwind_index=downwind_index,
122
130
  upcast=True,
123
- states_source_turbine=states_source_turbine,
124
- )[sel_sp]
131
+ )[st_sel, None]
125
132
 
126
- wake_delta[sel_sp] += (scale * wake_model_result) ** 2
133
+ wake_delta[st_sel] += (scale * wake_model_result) ** 2
127
134
 
128
135
  return wake_delta
129
136
 
@@ -132,7 +139,6 @@ class WSQuadratic(WakeSuperposition):
132
139
  algo,
133
140
  mdata,
134
141
  fdata,
135
- pdata,
136
142
  variable,
137
143
  amb_results,
138
144
  wake_delta,
@@ -145,24 +151,25 @@ class WSQuadratic(WakeSuperposition):
145
151
  ----------
146
152
  algo: foxes.core.Algorithm
147
153
  The calculation algorithm
148
- mdata: foxes.core.Data
154
+ mdata: foxes.core.MData
149
155
  The model data
150
- fdata: foxes.core.Data
156
+ fdata: foxes.core.FData
151
157
  The farm data
152
- pdata: foxes.core.Data
153
- The evaluation point data
154
158
  variable: str
155
159
  The variable name for which the wake deltas applies
156
160
  amb_results: numpy.ndarray
157
- The ambient results, shape: (n_states, n_points)
161
+ The ambient results at targets,
162
+ shape: (n_states, n_targets, n_tpoints)
158
163
  wake_delta: numpy.ndarray
159
- The wake deltas, shape: (n_states, n_points)
164
+ The wake deltas at targets, shape:
165
+ (n_states, n_targets, n_tpoints)
160
166
 
161
167
  Returns
162
168
  -------
163
169
  final_wake_delta: numpy.ndarray
164
170
  The final wake delta, which will be added to the ambient
165
- results by simple plus operation. Shape: (n_states, n_points)
171
+ results by simple plus operation. Shape:
172
+ (n_states, n_targets, n_tpoints)
166
173
 
167
174
  """
168
175
  w = -np.sqrt(wake_delta)
@@ -202,7 +202,7 @@ class MinDistConstraint(FarmConstraint):
202
202
  """
203
203
  n_pop = problem_results["n_pop"].values
204
204
  n_states = problem_results["n_org_states"].values
205
- n_turbines = problem_results.dims[FC.TURBINE]
205
+ n_turbines = problem_results.sizes[FC.TURBINE]
206
206
 
207
207
  xy = np.stack(
208
208
  [problem_results[FV.X].to_numpy(), problem_results[FV.Y].to_numpy()],
@@ -208,7 +208,7 @@ class FarmVarObjective(FarmObjective):
208
208
  """
209
209
  n_pop = problem_results["n_pop"].values
210
210
  n_states = problem_results["n_org_states"].values
211
- n_turbines = problem_results.dims[FC.TURBINE]
211
+ n_turbines = problem_results.sizes[FC.TURBINE]
212
212
  data = (
213
213
  problem_results[self.variable]
214
214
  .to_numpy()
@@ -1,11 +1,11 @@
1
1
  import numpy as np
2
2
 
3
- from foxes.opt.core import FarmVarsProblem
3
+ from foxes.opt.core.farm_opt_problem import FarmOptProblem
4
4
  import foxes.variables as FV
5
5
  import foxes.constants as FC
6
6
 
7
7
 
8
- class FarmLayoutOptProblem(FarmVarsProblem):
8
+ class FarmLayoutOptProblem(FarmOptProblem):
9
9
  """
10
10
  The turbine positioning optimization problem
11
11
 
@@ -79,118 +79,59 @@ class FarmLayoutOptProblem(FarmVarsProblem):
79
79
  out[:] = b.p_max()[None, :]
80
80
  return out.reshape(self.n_sel_turbines * 2)
81
81
 
82
- def initialize(self, verbosity=1, **kwargs):
82
+ def update_problem_individual(self, vars_int, vars_float):
83
83
  """
84
- Initialize the object.
84
+ Update the algo and other data using
85
+ the latest optimization variables.
85
86
 
86
- Parameters
87
- ----------
88
- verbosity: int
89
- The verbosity level, 0 = silent
90
- kwargs: dict, optional
91
- Additional parameters for super class init
92
-
93
- """
94
- super().initialize(
95
- pre_rotor_vars=[FV.X, FV.Y],
96
- post_rotor_vars=[],
97
- verbosity=verbosity,
98
- **kwargs,
99
- )
100
-
101
- def opt2farm_vars_individual(self, vars_int, vars_float):
102
- """
103
- Translates optimization variables to farm variables
87
+ This function is called before running the farm
88
+ calculation.
104
89
 
105
90
  Parameters
106
91
  ----------
107
- vars_int: numpy.ndarray
108
- The integer optimization variable values,
109
- shape: (n_vars_int,)
110
- vars_float: numpy.ndarray
111
- The float optimization variable values,
112
- shape: (n_vars_float,)
113
-
114
- Returns
115
- -------
116
- farm_vars: dict
117
- The foxes farm variables. Key: var name,
118
- value: numpy.ndarray with values, shape:
119
- (n_states, n_sel_turbines)
120
-
121
- """
122
- farm_vars = {
123
- FV.X: np.zeros((self.algo.n_states, self.n_sel_turbines), dtype=FC.DTYPE),
124
- FV.Y: np.zeros((self.algo.n_states, self.n_sel_turbines), dtype=FC.DTYPE),
125
- }
126
- xy = vars_float.reshape(self.n_sel_turbines, 2)
127
- farm_vars[FV.X][:] = xy[None, :, 0]
128
- farm_vars[FV.Y][:] = xy[None, :, 1]
129
-
130
- return farm_vars
92
+ vars_int: np.array
93
+ The integer variable values, shape: (n_vars_int,)
94
+ vars_float: np.array
95
+ The float variable values, shape: (n_vars_float,)
131
96
 
132
- def opt2farm_vars_population(self, vars_int, vars_float, n_states):
133
97
  """
134
- Translates optimization variables to farm variables
135
-
136
- Parameters
137
- ----------
138
- vars_int: numpy.ndarray
139
- The integer optimization variable values,
140
- shape: (n_pop, n_vars_int)
141
- vars_float: numpy.ndarray
142
- The float optimization variable values,
143
- shape: (n_pop, n_vars_float)
144
- n_states: int
145
- The number of original (non-pop) states
98
+ super().update_problem_individual(vars_int, vars_float)
146
99
 
147
- Returns
148
- -------
149
- farm_vars: dict
150
- The foxes farm variables. Key: var name,
151
- value: numpy.ndarray with values, shape:
152
- (n_pop, n_states, n_sel_turbines)
100
+ xy = vars_float.reshape(self.n_sel_turbines, 2)
101
+ for i, ti in enumerate(self.sel_turbines):
102
+ t = self.algo.farm.turbines[ti]
103
+ t.xy = xy[i]
153
104
 
105
+ def update_problem_population(self, vars_int, vars_float):
154
106
  """
155
- n_pop = len(vars_float)
156
- farm_vars = {
157
- FV.X: np.zeros((n_pop, n_states, self.n_sel_turbines), dtype=FC.DTYPE),
158
- FV.Y: np.zeros((n_pop, n_states, self.n_sel_turbines), dtype=FC.DTYPE),
159
- }
160
- xy = vars_float.reshape(n_pop, self.n_sel_turbines, 2)
161
- farm_vars[FV.X][:] = xy[:, None, :, 0]
162
- farm_vars[FV.Y][:] = xy[:, None, :, 1]
163
-
164
- return farm_vars
107
+ Update the algo and other data using
108
+ the latest optimization variables.
165
109
 
166
- def finalize_individual(self, vars_int, vars_float, verbosity=1):
167
- """
168
- Finalization, given the champion data.
110
+ This function is called before running the farm
111
+ calculation.
169
112
 
170
113
  Parameters
171
114
  ----------
172
115
  vars_int: np.array
173
- The optimal integer variable values, shape: (n_vars_int,)
116
+ The integer variable values, shape: (n_pop, n_vars_int,)
174
117
  vars_float: np.array
175
- The optimal float variable values, shape: (n_vars_float,)
176
- verbosity: int
177
- The verbosity level, 0 = silent
178
-
179
- Returns
180
- -------
181
- problem_results: Any
182
- The results of the variable application
183
- to the problem
184
- objs: np.array
185
- The objective function values, shape: (n_objectives,)
186
- cons: np.array
187
- The constraints values, shape: (n_constraints,)
118
+ The float variable values, shape: (n_pop, n_vars_float,)
188
119
 
189
120
  """
190
- res, objs, cons = super().finalize_individual(vars_int, vars_float, verbosity)
121
+ super().update_problem_population(vars_int, vars_float)
191
122
 
192
- xy = vars_float.reshape(self.n_sel_turbines, 2)
193
- for i, ti in enumerate(self.sel_turbines):
194
- self.farm.turbines[ti].xy = xy[i]
123
+ n_pop = len(vars_float)
124
+ n_ostates = self._org_n_states
125
+ n_states = n_pop * n_ostates
195
126
 
196
- return res, objs, cons
127
+ xy = vars_float.reshape(n_pop, self.n_sel_turbines, 2)
128
+ sxy = np.zeros(
129
+ (n_pop, n_ostates, self.n_sel_turbines, 2), dtype=vars_float.dtype
130
+ )
131
+ sxy[:] = xy[:, None, :, :]
132
+ sxy = sxy.reshape(n_states, self.n_sel_turbines, 2)
133
+ del xy
134
+
135
+ for i, ti in enumerate(self.sel_turbines):
136
+ t = self.algo.farm.turbines[ti]
137
+ t.xy = sxy[:, i]
foxes/output/__init__.py CHANGED
@@ -13,6 +13,7 @@ from .turbine_type_curves import TurbineTypeCurves
13
13
  from .animation import Animator
14
14
  from .calc_points import PointCalculator
15
15
  from .slice_data import SliceData
16
+ from .rotor_point_plots import RotorPointPlot
16
17
 
17
18
  from .flow_plots_2d import FlowPlots2D, SeqFlowAnimationPlugin
18
19
  from . import grids
@@ -106,7 +106,7 @@ class FarmResultsEval(Output):
106
106
  The results per turbine
107
107
 
108
108
  """
109
- n_turbines = self.results.dims[FC.TURBINE]
109
+ n_turbines = self.results.sizes[FC.TURBINE]
110
110
 
111
111
  rdata = {}
112
112
  for v, op in vars_op.items():
@@ -725,6 +725,7 @@ class FlowPlots2D(SliceData):
725
725
  data_format="numpy",
726
726
  ret_states=True,
727
727
  ret_grid=True,
728
+ x_direction=x_direction,
728
729
  **kwargs,
729
730
  )
730
731
  x_pos, y_pos, z_pos, __ = gdata
@@ -898,6 +899,7 @@ class FlowPlots2D(SliceData):
898
899
  data_format="numpy",
899
900
  ret_states=True,
900
901
  ret_grid=True,
902
+ x_direction=x_direction,
901
903
  **kwargs,
902
904
  )
903
905
  x_pos, y_pos, z_pos, __ = gdata
@@ -150,6 +150,8 @@ def get_fig(
150
150
  hax.set_xlabel(xlabel)
151
151
  hax.set_ylabel(ylabel)
152
152
  hax.set_aspect("equal", adjustable="box")
153
+ hax.set_xlim(x_pos.min(), x_pos.max())
154
+ hax.set_ylim(y_pos.min(), y_pos.max())
153
155
 
154
156
  ttl = None
155
157
  if animated:
foxes/output/grids.py CHANGED
@@ -688,7 +688,7 @@ def data2xr(
688
688
  and isinstance(state_mean, bool)
689
689
  and not state_mean
690
690
  ):
691
- if point_results.dims[FC.STATE] > 1:
691
+ if point_results.sizes[FC.STATE] > 1:
692
692
  coords[FC.STATE] = point_results[FC.STATE].to_numpy()
693
693
  else:
694
694
  attrs[FC.STATE] = str(point_results[FC.STATE][0].to_numpy())