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.
- foxes/VERSION +1 -1
- foxes/algorithms/downwind/downwind.py +131 -65
- foxes/algorithms/downwind/models/__init__.py +2 -1
- foxes/algorithms/downwind/models/farm_wakes_calc.py +87 -55
- foxes/algorithms/downwind/models/init_farm_data.py +134 -0
- foxes/algorithms/downwind/models/point_wakes_calc.py +54 -65
- foxes/algorithms/downwind/models/{calc_order.py → reorder_farm_output.py} +28 -26
- foxes/algorithms/iterative/iterative.py +100 -51
- foxes/algorithms/iterative/models/convergence.py +3 -3
- foxes/algorithms/iterative/models/farm_wakes_calc.py +55 -48
- foxes/algorithms/sequential/models/seq_state.py +7 -6
- foxes/algorithms/sequential/sequential.py +81 -44
- foxes/constants.py +33 -18
- foxes/core/__init__.py +2 -2
- foxes/core/algorithm.py +31 -12
- foxes/core/data.py +335 -41
- foxes/core/data_calc_model.py +27 -23
- foxes/core/farm_controller.py +27 -28
- foxes/core/farm_data_model.py +26 -4
- foxes/core/model.py +186 -129
- foxes/core/partial_wakes_model.py +84 -81
- foxes/core/point_data_model.py +51 -18
- foxes/core/rotor_model.py +59 -77
- foxes/core/states.py +6 -6
- foxes/core/turbine_model.py +4 -4
- foxes/core/turbine_type.py +24 -0
- foxes/core/vertical_profile.py +3 -3
- foxes/core/wake_frame.py +91 -50
- foxes/core/wake_model.py +74 -43
- foxes/core/wake_superposition.py +29 -26
- foxes/input/farm_layout/__init__.py +1 -0
- foxes/input/farm_layout/from_random.py +49 -0
- foxes/input/states/__init__.py +1 -1
- foxes/input/states/create/__init__.py +1 -0
- foxes/input/states/create/random_abl_states.py +6 -2
- foxes/input/states/create/random_timeseries.py +56 -0
- foxes/input/states/field_data_nc.py +12 -8
- foxes/input/states/multi_height.py +24 -14
- foxes/input/states/scan_ws.py +13 -17
- foxes/input/states/single.py +28 -20
- foxes/input/states/states_table.py +22 -18
- foxes/models/axial_induction_models/betz.py +1 -1
- foxes/models/farm_models/turbine2farm.py +2 -2
- foxes/models/model_book.py +40 -14
- foxes/models/partial_wakes/__init__.py +2 -2
- foxes/models/partial_wakes/axiwake.py +73 -200
- foxes/models/partial_wakes/centre.py +40 -0
- foxes/models/partial_wakes/grid.py +7 -63
- foxes/models/partial_wakes/rotor_points.py +53 -147
- foxes/models/partial_wakes/segregated.py +158 -0
- foxes/models/partial_wakes/top_hat.py +88 -196
- foxes/models/point_models/set_uniform_data.py +4 -4
- foxes/models/point_models/tke2ti.py +4 -4
- foxes/models/point_models/wake_deltas.py +4 -4
- foxes/models/rotor_models/centre.py +15 -19
- foxes/models/rotor_models/grid.py +2 -1
- foxes/models/rotor_models/levels.py +2 -1
- foxes/models/turbine_models/__init__.py +0 -1
- foxes/models/turbine_models/calculator.py +11 -7
- foxes/models/turbine_models/kTI_model.py +13 -11
- foxes/models/turbine_models/lookup_table.py +22 -9
- foxes/models/turbine_models/power_mask.py +81 -51
- foxes/models/turbine_models/rotor_centre_calc.py +17 -20
- foxes/models/turbine_models/sector_management.py +5 -6
- foxes/models/turbine_models/set_farm_vars.py +49 -20
- foxes/models/turbine_models/table_factors.py +5 -5
- foxes/models/turbine_models/thrust2ct.py +9 -5
- foxes/models/turbine_models/yaw2yawm.py +7 -13
- foxes/models/turbine_models/yawm2yaw.py +7 -11
- foxes/models/turbine_types/PCt_file.py +84 -3
- foxes/models/turbine_types/PCt_from_two.py +7 -3
- foxes/models/turbine_types/null_type.py +2 -2
- foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -2
- foxes/models/turbine_types/wsti2PCt_from_two.py +6 -2
- foxes/models/wake_frames/farm_order.py +26 -22
- foxes/models/wake_frames/rotor_wd.py +32 -31
- foxes/models/wake_frames/seq_dynamic_wakes.py +112 -64
- foxes/models/wake_frames/streamlines.py +51 -47
- foxes/models/wake_frames/timelines.py +59 -47
- foxes/models/wake_frames/yawed_wakes.py +63 -40
- foxes/models/wake_models/axisymmetric.py +31 -35
- foxes/models/wake_models/dist_sliced.py +50 -56
- foxes/models/wake_models/gaussian.py +33 -35
- foxes/models/wake_models/induction/rankine_half_body.py +79 -87
- foxes/models/wake_models/induction/rathmann.py +56 -63
- foxes/models/wake_models/induction/self_similar.py +59 -62
- foxes/models/wake_models/ti/crespo_hernandez.py +83 -74
- foxes/models/wake_models/ti/iec_ti.py +65 -75
- foxes/models/wake_models/top_hat.py +60 -69
- foxes/models/wake_models/wake_mirror.py +49 -54
- foxes/models/wake_models/wind/bastankhah14.py +44 -66
- foxes/models/wake_models/wind/bastankhah16.py +84 -111
- foxes/models/wake_models/wind/jensen.py +67 -89
- foxes/models/wake_models/wind/turbopark.py +93 -133
- foxes/models/wake_superpositions/ti_linear.py +33 -27
- foxes/models/wake_superpositions/ti_max.py +33 -27
- foxes/models/wake_superpositions/ti_pow.py +35 -27
- foxes/models/wake_superpositions/ti_quadratic.py +33 -27
- foxes/models/wake_superpositions/ws_linear.py +39 -32
- foxes/models/wake_superpositions/ws_max.py +40 -33
- foxes/models/wake_superpositions/ws_pow.py +39 -32
- foxes/models/wake_superpositions/ws_product.py +35 -28
- foxes/models/wake_superpositions/ws_quadratic.py +39 -32
- foxes/opt/constraints/min_dist.py +1 -1
- foxes/opt/objectives/farm_vars.py +1 -1
- foxes/opt/problems/layout/farm_layout.py +38 -97
- foxes/output/__init__.py +1 -0
- foxes/output/farm_results_eval.py +1 -1
- foxes/output/flow_plots_2d/flow_plots.py +2 -0
- foxes/output/flow_plots_2d/get_fig.py +2 -0
- foxes/output/grids.py +1 -1
- foxes/output/rose_plot.py +3 -3
- foxes/output/rotor_point_plots.py +117 -0
- foxes/output/turbine_type_curves.py +2 -2
- foxes/utils/__init__.py +2 -1
- foxes/utils/load.py +29 -0
- foxes/utils/random_xy.py +56 -0
- foxes/utils/runners/runners.py +13 -1
- foxes/utils/windrose_plot.py +1 -1
- foxes/variables.py +10 -0
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/METADATA +13 -7
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/RECORD +126 -122
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/WHEEL +1 -1
- foxes/models/partial_wakes/distsliced.py +0 -322
- foxes/models/partial_wakes/mapped.py +0 -252
- foxes/models/turbine_models/set_XYHD.py +0 -130
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/LICENSE +0 -0
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/top_level.txt +0 -0
- {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
|
|
74
|
+
def add_wake(
|
|
71
75
|
self,
|
|
72
76
|
algo,
|
|
73
77
|
mdata,
|
|
74
78
|
fdata,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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.
|
|
94
|
+
mdata: foxes.core.MData
|
|
90
95
|
The model data
|
|
91
|
-
fdata: foxes.core.
|
|
96
|
+
fdata: foxes.core.FData
|
|
92
97
|
The farm data
|
|
93
|
-
|
|
94
|
-
The
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
The selection of
|
|
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:
|
|
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
|
|
106
|
-
shape: (
|
|
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:
|
|
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(
|
|
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.
|
|
129
|
+
FC.STATE_TARGET,
|
|
123
130
|
lookup="w",
|
|
124
131
|
algo=algo,
|
|
125
132
|
fdata=fdata,
|
|
126
|
-
|
|
133
|
+
tdata=tdata,
|
|
134
|
+
downwind_index=downwind_index,
|
|
127
135
|
upcast=True,
|
|
128
|
-
|
|
129
|
-
)[sel_sp]
|
|
136
|
+
)[st_sel, None]
|
|
130
137
|
|
|
131
|
-
wake_delta[
|
|
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.
|
|
159
|
+
mdata: foxes.core.MData
|
|
154
160
|
The model data
|
|
155
|
-
fdata: foxes.core.
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
70
|
+
def add_wake(
|
|
67
71
|
self,
|
|
68
72
|
algo,
|
|
69
73
|
mdata,
|
|
70
74
|
fdata,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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.
|
|
90
|
+
mdata: foxes.core.MData
|
|
86
91
|
The model data
|
|
87
|
-
fdata: foxes.core.
|
|
92
|
+
fdata: foxes.core.FData
|
|
88
93
|
The farm data
|
|
89
|
-
|
|
90
|
-
The
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
The selection of
|
|
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:
|
|
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
|
|
102
|
-
shape: (
|
|
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:
|
|
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(
|
|
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[
|
|
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.
|
|
147
|
+
mdata: foxes.core.MData
|
|
142
148
|
The model data
|
|
143
|
-
fdata: foxes.core.
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
69
|
+
def add_wake(
|
|
66
70
|
self,
|
|
67
71
|
algo,
|
|
68
72
|
mdata,
|
|
69
73
|
fdata,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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.
|
|
89
|
+
mdata: foxes.core.MData
|
|
85
90
|
The model data
|
|
86
|
-
fdata: foxes.core.
|
|
91
|
+
fdata: foxes.core.FData
|
|
87
92
|
The farm data
|
|
88
|
-
|
|
89
|
-
The
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
The selection of
|
|
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:
|
|
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
|
|
101
|
-
shape: (
|
|
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:
|
|
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(
|
|
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.
|
|
124
|
+
FC.STATE_TARGET,
|
|
118
125
|
lookup="w",
|
|
119
126
|
algo=algo,
|
|
120
127
|
fdata=fdata,
|
|
121
|
-
|
|
128
|
+
tdata=tdata,
|
|
129
|
+
downwind_index=downwind_index,
|
|
122
130
|
upcast=True,
|
|
123
|
-
|
|
124
|
-
)[sel_sp]
|
|
131
|
+
)[st_sel, None]
|
|
125
132
|
|
|
126
|
-
wake_delta[
|
|
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.
|
|
154
|
+
mdata: foxes.core.MData
|
|
149
155
|
The model data
|
|
150
|
-
fdata: foxes.core.
|
|
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
|
|
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:
|
|
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:
|
|
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.
|
|
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.
|
|
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
|
|
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(
|
|
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
|
|
82
|
+
def update_problem_individual(self, vars_int, vars_float):
|
|
83
83
|
"""
|
|
84
|
-
|
|
84
|
+
Update the algo and other data using
|
|
85
|
+
the latest optimization variables.
|
|
85
86
|
|
|
86
|
-
|
|
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:
|
|
108
|
-
The integer
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
-
|
|
156
|
-
|
|
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
|
-
|
|
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
|
|
116
|
+
The integer variable values, shape: (n_pop, n_vars_int,)
|
|
174
117
|
vars_float: np.array
|
|
175
|
-
The
|
|
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
|
-
|
|
121
|
+
super().update_problem_population(vars_int, vars_float)
|
|
191
122
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
123
|
+
n_pop = len(vars_float)
|
|
124
|
+
n_ostates = self._org_n_states
|
|
125
|
+
n_states = n_pop * n_ostates
|
|
195
126
|
|
|
196
|
-
|
|
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
|
|
@@ -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
|
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.
|
|
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())
|