foxes 1.2__py3-none-any.whl → 1.2.1__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 (57) hide show
  1. examples/abl_states/run.py +5 -5
  2. examples/induction/run.py +5 -5
  3. examples/random_timeseries/run.py +13 -13
  4. examples/scan_row/run.py +12 -7
  5. examples/sector_management/run.py +11 -7
  6. examples/single_state/run.py +5 -5
  7. examples/tab_file/run.py +1 -1
  8. examples/timeseries/run.py +5 -5
  9. examples/timeseries_slurm/run.py +5 -5
  10. examples/wind_rose/run.py +1 -1
  11. examples/yawed_wake/run.py +5 -5
  12. foxes/algorithms/downwind/downwind.py +15 -5
  13. foxes/algorithms/sequential/sequential.py +1 -1
  14. foxes/core/algorithm.py +24 -20
  15. foxes/core/axial_induction_model.py +18 -0
  16. foxes/core/engine.py +2 -14
  17. foxes/core/farm_controller.py +18 -0
  18. foxes/core/ground_model.py +19 -0
  19. foxes/core/partial_wakes_model.py +9 -21
  20. foxes/core/point_data_model.py +18 -0
  21. foxes/core/rotor_model.py +2 -18
  22. foxes/core/states.py +2 -17
  23. foxes/core/turbine_model.py +2 -18
  24. foxes/core/turbine_type.py +2 -18
  25. foxes/core/vertical_profile.py +8 -20
  26. foxes/core/wake_frame.py +2 -20
  27. foxes/core/wake_model.py +19 -20
  28. foxes/core/wake_superposition.py +19 -0
  29. foxes/input/states/__init__.py +1 -1
  30. foxes/input/states/field_data_nc.py +14 -1
  31. foxes/input/states/{scan_ws.py → scan.py} +39 -52
  32. foxes/input/yaml/__init__.py +1 -1
  33. foxes/input/yaml/dict.py +221 -50
  34. foxes/input/yaml/yaml.py +5 -5
  35. foxes/output/__init__.py +2 -1
  36. foxes/output/farm_results_eval.py +57 -35
  37. foxes/output/output.py +2 -18
  38. foxes/output/plt.py +19 -0
  39. foxes/output/rose_plot.py +413 -207
  40. foxes/utils/__init__.py +1 -2
  41. foxes/utils/subclasses.py +69 -0
  42. {foxes-1.2.dist-info → foxes-1.2.1.dist-info}/METADATA +1 -2
  43. {foxes-1.2.dist-info → foxes-1.2.1.dist-info}/RECORD +56 -56
  44. tests/0_consistency/iterative/test_iterative.py +1 -1
  45. tests/0_consistency/partial_wakes/test_partial_wakes.py +1 -1
  46. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +7 -2
  47. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +7 -2
  48. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +7 -2
  49. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +7 -2
  50. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +7 -2
  51. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +7 -3
  52. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +7 -2
  53. foxes/utils/windrose_plot.py +0 -152
  54. {foxes-1.2.dist-info → foxes-1.2.1.dist-info}/LICENSE +0 -0
  55. {foxes-1.2.dist-info → foxes-1.2.1.dist-info}/WHEEL +0 -0
  56. {foxes-1.2.dist-info → foxes-1.2.1.dist-info}/entry_points.txt +0 -0
  57. {foxes-1.2.dist-info → foxes-1.2.1.dist-info}/top_level.txt +0 -0
@@ -137,17 +137,17 @@ if __name__ == "__main__":
137
137
  # results by turbine
138
138
  turbine_results = o.reduce_states(
139
139
  {
140
- FV.AMB_P: "mean",
141
- FV.P: "mean",
142
- FV.AMB_CAP: "mean",
143
- FV.CAP: "mean",
144
- FV.EFF: "mean",
140
+ FV.AMB_P: "weights",
141
+ FV.P: "weights",
142
+ FV.AMB_CAP: "weights",
143
+ FV.CAP: "weights",
145
144
  }
146
145
  )
147
146
  turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
148
147
  algo=algo, annual=True, ambient=True
149
148
  )
150
149
  turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
150
+ turbine_results[FV.EFF] = turbine_results[FV.P] / turbine_results[FV.AMB_P]
151
151
  print("\nResults by turbine:\n")
152
152
  print(turbine_results)
153
153
 
examples/induction/run.py CHANGED
@@ -130,17 +130,17 @@ if __name__ == "__main__":
130
130
  # results by turbine
131
131
  turbine_results = o.reduce_states(
132
132
  {
133
- FV.AMB_P: "mean",
134
- FV.P: "mean",
135
- FV.AMB_CAP: "mean",
136
- FV.CAP: "mean",
137
- FV.EFF: "mean",
133
+ FV.AMB_P: "weights",
134
+ FV.P: "weights",
135
+ FV.AMB_CAP: "weights",
136
+ FV.CAP: "weights",
138
137
  }
139
138
  )
140
139
  turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
141
140
  algo=algo, annual=True, ambient=True
142
141
  )
143
142
  turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
143
+ turbine_results[FV.EFF] = turbine_results[FV.P] / turbine_results[FV.AMB_P]
144
144
  print("\nResults by turbine:\n")
145
145
  print(turbine_results)
146
146
 
@@ -101,21 +101,21 @@ if __name__ == "__main__":
101
101
  ):
102
102
 
103
103
  if not args.nofig:
104
- # fig, axs= plt.subplots(2, 1, figsize=(12,6))
105
- # foxes.output.FarmLayoutOutput(farm).get_figure(ax=axs[0])
104
+ fig = plt.figure(figsize=(14.5, 7))
105
+ ax1 = fig.add_subplot(121)
106
+ ax2 = fig.add_subplot(122, polar=True)
107
+ foxes.output.FarmLayoutOutput(farm).get_figure(fig=fig, ax=ax1)
106
108
 
107
109
  o = foxes.output.StatesRosePlotOutput(states, point=[0.0, 0.0, 100.0])
108
- fig = o.get_figure(
110
+ o.get_figure(
109
111
  16,
110
112
  FV.AMB_WS,
111
113
  [0, 3.5, 6, 10, 15, 20],
112
- figsize=(14.5, 7),
113
- rect=[0.01, 0.05, 0.45, 0.85],
114
+ fig=fig,
115
+ ax=ax2,
116
+ freq_delta=2,
114
117
  )
115
118
 
116
- ax = plt.Axes(fig, rect=[0.3, 0.1, 0.8, 0.8])
117
- fig.add_axes(ax)
118
- foxes.output.FarmLayoutOutput(farm).get_figure(fig=fig, ax=ax)
119
119
  plt.show()
120
120
  plt.close(fig)
121
121
 
@@ -187,17 +187,17 @@ if __name__ == "__main__":
187
187
  # results by turbine
188
188
  turbine_results = o.reduce_states(
189
189
  {
190
- FV.AMB_P: "mean",
191
- FV.P: "mean",
192
- FV.AMB_CAP: "mean",
193
- FV.CAP: "mean",
194
- FV.EFF: "mean",
190
+ FV.AMB_P: "weights",
191
+ FV.P: "weights",
192
+ FV.AMB_CAP: "weights",
193
+ FV.CAP: "weights",
195
194
  }
196
195
  )
197
196
  turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
198
197
  algo=algo, annual=True, ambient=True
199
198
  )
200
199
  turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
200
+ turbine_results[FV.EFF] = turbine_results[FV.P] / turbine_results[FV.AMB_P]
201
201
  print("\nResults by turbine:\n")
202
202
  print(turbine_results)
203
203
 
examples/scan_row/run.py CHANGED
@@ -76,8 +76,13 @@ if __name__ == "__main__":
76
76
  D = ttype.D
77
77
  H = ttype.H
78
78
 
79
- states = foxes.input.states.ScanWS(
80
- ws_list=np.linspace(args.ws0, args.ws1, n_s), wd=270.0, ti=0.08, rho=1.225
79
+ states = foxes.input.states.ScanStates(
80
+ {
81
+ FV.WS: np.linspace(args.ws0, args.ws1, n_s),
82
+ FV.WD: [270],
83
+ FV.TI: [0.08],
84
+ FV.RHO: [1.225],
85
+ }
81
86
  )
82
87
 
83
88
  farm = foxes.WindFarm()
@@ -139,17 +144,17 @@ if __name__ == "__main__":
139
144
  # results by turbine
140
145
  turbine_results = o.reduce_states(
141
146
  {
142
- FV.AMB_P: "mean",
143
- FV.P: "mean",
144
- FV.AMB_CAP: "mean",
145
- FV.CAP: "mean",
146
- FV.EFF: "mean",
147
+ FV.AMB_P: "weights",
148
+ FV.P: "weights",
149
+ FV.AMB_CAP: "weights",
150
+ FV.CAP: "weights",
147
151
  }
148
152
  )
149
153
  turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
150
154
  algo=algo, annual=True, ambient=True
151
155
  )
152
156
  turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
157
+ turbine_results[FV.EFF] = turbine_results[FV.P] / turbine_results[FV.AMB_P]
153
158
  print("\nResults by turbine:\n")
154
159
  print(turbine_results)
155
160
 
@@ -138,25 +138,29 @@ if __name__ == "__main__":
138
138
  print(fr)
139
139
 
140
140
  if not args.nofig:
141
+ fig = plt.figure(figsize=(12, 4))
142
+ ax1 = fig.add_subplot(121, polar=True)
143
+ ax2 = fig.add_subplot(122, polar=True)
144
+
141
145
  o = foxes.output.RosePlotOutput(farm_results)
142
- fig = o.get_figure(
146
+ o.get_figure(
143
147
  16,
144
148
  FV.P,
145
- [100, 1000, 2000, 4000, 5001, 7000],
149
+ [0, 100, 1000, 2000, 4000, 5001, 7000],
146
150
  turbine=0,
147
151
  title="Power turbine 0",
148
- figsize=(12, 6),
149
- rect=[0.05, 0.1, 0.4, 0.8],
152
+ fig=fig,
153
+ ax=ax1,
150
154
  )
151
155
 
152
156
  o = foxes.output.RosePlotOutput(farm_results)
153
- fig = o.get_figure(
157
+ o.get_figure(
154
158
  16,
155
159
  FV.P,
156
- [100, 1000, 2000, 4000, 5001, 7000],
160
+ [0, 100, 1000, 2000, 4000, 5001, 7000],
157
161
  turbine=1,
158
162
  title="Power turbine 1",
159
163
  fig=fig,
160
- rect=[0.35, 0.1, 0.8, 0.8],
164
+ ax=ax2,
161
165
  )
162
166
  plt.show()
@@ -155,17 +155,17 @@ if __name__ == "__main__":
155
155
  # results by turbine
156
156
  turbine_results = o.reduce_states(
157
157
  {
158
- FV.AMB_P: "mean",
159
- FV.P: "mean",
160
- FV.AMB_CAP: "mean",
161
- FV.CAP: "mean",
162
- FV.EFF: "mean",
158
+ FV.AMB_P: "weights",
159
+ FV.P: "weights",
160
+ FV.AMB_CAP: "weights",
161
+ FV.CAP: "weights",
163
162
  }
164
163
  )
165
164
  turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
166
165
  algo=algo, annual=True, ambient=True
167
166
  )
168
167
  turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
168
+ turbine_results[FV.EFF] = turbine_results[FV.P] / turbine_results[FV.AMB_P]
169
169
  print("\nResults by turbine:\n")
170
170
  print(turbine_results)
171
171
 
examples/tab_file/run.py CHANGED
@@ -89,7 +89,7 @@ if __name__ == "__main__":
89
89
  ):
90
90
  if not args.nofig:
91
91
  o = foxes.output.StatesRosePlotOutput(states, point=[0.0, 0.0, 100.0])
92
- fig = o.get_figure(12, FV.AMB_WS, [0, 3.5, 6, 10, 15, 20])
92
+ o.get_figure(12, FV.AMB_WS, [0, 3.5, 6, 10, 15, 20])
93
93
  plt.show()
94
94
 
95
95
  farm = foxes.WindFarm()
@@ -160,17 +160,17 @@ if __name__ == "__main__":
160
160
  # results by turbine
161
161
  turbine_results = o.reduce_states(
162
162
  {
163
- FV.AMB_P: "mean",
164
- FV.P: "mean",
165
- FV.AMB_CAP: "mean",
166
- FV.CAP: "mean",
167
- FV.EFF: "mean",
163
+ FV.AMB_P: "weights",
164
+ FV.P: "weights",
165
+ FV.AMB_CAP: "weights",
166
+ FV.CAP: "weights",
168
167
  }
169
168
  )
170
169
  turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
171
170
  algo=algo, annual=True, ambient=True
172
171
  )
173
172
  turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
173
+ turbine_results[FV.EFF] = turbine_results[FV.P] / turbine_results[FV.AMB_P]
174
174
  print("\nResults by turbine:\n")
175
175
  print(turbine_results)
176
176
 
@@ -162,17 +162,17 @@ if __name__ == "__main__":
162
162
  # results by turbine
163
163
  turbine_results = o.reduce_states(
164
164
  {
165
- FV.AMB_P: "mean",
166
- FV.P: "mean",
167
- FV.AMB_CAP: "mean",
168
- FV.CAP: "mean",
169
- FV.EFF: "mean",
165
+ FV.AMB_P: "weights",
166
+ FV.P: "weights",
167
+ FV.AMB_CAP: "weights",
168
+ FV.CAP: "weights",
170
169
  }
171
170
  )
172
171
  turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
173
172
  algo=algo, annual=True, ambient=True
174
173
  )
175
174
  turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
175
+ turbine_results[FV.EFF] = turbine_results[FV.P] / turbine_results[FV.AMB_P]
176
176
  print("\nResults by turbine:\n")
177
177
  print(turbine_results)
178
178
 
examples/wind_rose/run.py CHANGED
@@ -113,7 +113,7 @@ if __name__ == "__main__":
113
113
 
114
114
  if not args.nofig:
115
115
  o = foxes.output.StatesRosePlotOutput(states, point=[0.0, 0.0, 100.0])
116
- fig = o.get_figure(16, FV.AMB_WS, [0, 3.5, 6, 10, 15, 20])
116
+ o.get_figure(16, FV.AMB_WS, [0, 3.5, 6, 10, 15, 20], add_inf=True)
117
117
  plt.show()
118
118
 
119
119
  time0 = time.time()
@@ -173,17 +173,17 @@ if __name__ == "__main__":
173
173
  # results by turbine
174
174
  turbine_results = o.reduce_states(
175
175
  {
176
- FV.AMB_P: "mean",
177
- FV.P: "mean",
178
- FV.AMB_CAP: "mean",
179
- FV.CAP: "mean",
180
- FV.EFF: "mean",
176
+ FV.AMB_P: "weights",
177
+ FV.P: "weights",
178
+ FV.AMB_CAP: "weights",
179
+ FV.CAP: "weights",
181
180
  }
182
181
  )
183
182
  turbine_results[FV.AMB_YLD] = o.calc_turbine_yield(
184
183
  algo=algo, annual=True, ambient=True
185
184
  )
186
185
  turbine_results[FV.YLD] = o.calc_turbine_yield(algo=algo, annual=True)
186
+ turbine_results[FV.EFF] = turbine_results[FV.P] / turbine_results[FV.AMB_P]
187
187
  print("\nResults by turbine:\n")
188
188
  print(turbine_results)
189
189
 
@@ -311,14 +311,24 @@ class Downwind(Algorithm):
311
311
  """
312
312
  return getattr(mdls, name)
313
313
 
314
- def _print_deco(self, func_name, n_points=None):
314
+ def print_deco(self, func_name=None, n_points=None):
315
315
  """
316
316
  Helper function for printing model names
317
+
318
+ Parameters
319
+ ----------
320
+ func_name: str, optional
321
+ Name of the calling function
322
+ n_points: int, optional
323
+ The number of points
324
+
317
325
  """
318
326
  if self.verbosity > 0:
319
- deco = "-" * 50
327
+ deco = "-" * 60
320
328
  print(f"\n{deco}")
321
- print(f" Running {self.name}: {func_name}")
329
+ print(f" Algorithm: {type(self).__name__}")
330
+ if func_name is not None:
331
+ print(f" Running {self.name}: {func_name}")
322
332
  print(deco)
323
333
  print(f" n_states : {self.n_states}")
324
334
  print(f" n_turbines: {self.n_turbines}")
@@ -538,7 +548,7 @@ class Downwind(Algorithm):
538
548
  self.initialize()
539
549
 
540
550
  # welcome:
541
- self._print_deco("calc_farm")
551
+ self.print_deco("calc_farm")
542
552
 
543
553
  # collect models:
544
554
  if outputs == "default":
@@ -747,7 +757,7 @@ class Downwind(Algorithm):
747
757
 
748
758
  # welcome:
749
759
  points = np.asarray(points)
750
- self._print_deco("calc_points", n_points=points.shape[1])
760
+ self.print_deco("calc_points", n_points=points.shape[1])
751
761
 
752
762
  # collect models and initialize:
753
763
  mlist, calc_pars = self._collect_point_models(
@@ -136,7 +136,7 @@ class Sequential(Iterative):
136
136
  if not self.iterating:
137
137
  if not self.initialized:
138
138
  self.initialize()
139
- self._print_deco("calc_farm")
139
+ self.print_deco("calc_farm")
140
140
 
141
141
  self._inds = self.states0.index()
142
142
  self._weights = self.states0.weights(self)
foxes/core/algorithm.py CHANGED
@@ -4,7 +4,7 @@ from abc import abstractmethod
4
4
 
5
5
  from .model import Model
6
6
  from foxes.data import StaticData
7
- from foxes.utils import Dict, all_subclasses
7
+ from foxes.utils import Dict, new_instance
8
8
  from foxes.config import config
9
9
  import foxes.constants as FC
10
10
 
@@ -177,6 +177,28 @@ class Algorithm(Model):
177
177
  if self.verbosity >= vlim:
178
178
  print(*args, **kwargs)
179
179
 
180
+ def print_deco(self, func_name=None, n_points=None):
181
+ """
182
+ Helper function for printing model names
183
+
184
+ Parameters
185
+ ----------
186
+ func_name: str, optional
187
+ Name of the calling function
188
+ n_points: int, optional
189
+ The number of points
190
+
191
+ """
192
+ if self.verbosity > 0:
193
+ deco = "-" * 60
194
+ print(f"\n{deco}")
195
+ print(f" Algorithm: {type(self).__name__}")
196
+ if func_name is not None:
197
+ print(f" Running {self.name}: {func_name}")
198
+ print(deco)
199
+ print(f" n_states : {self.n_states}")
200
+ print(f" n_turbines: {self.n_turbines}")
201
+
180
202
  def initialize(self):
181
203
  """
182
204
  Initializes the algorithm.
@@ -926,22 +948,4 @@ class Algorithm(Model):
926
948
  Additional parameters for the constructor
927
949
 
928
950
  """
929
-
930
- if algo_type is None:
931
- return None
932
-
933
- allc = all_subclasses(cls)
934
- found = algo_type in [scls.__name__ for scls in allc]
935
-
936
- if found:
937
- for scls in allc:
938
- if scls.__name__ == algo_type:
939
- return scls(*args, **kwargs)
940
-
941
- else:
942
- estr = (
943
- "Algorithm type '{}' is not defined, available types are \n {}".format(
944
- algo_type, sorted([i.__name__ for i in allc])
945
- )
946
- )
947
- raise KeyError(estr)
951
+ return new_instance(cls, algo_type, *args, **kwargs)
@@ -1,5 +1,6 @@
1
1
  from abc import abstractmethod
2
2
 
3
+ from foxes.utils import new_instance
3
4
  from .model import Model
4
5
 
5
6
 
@@ -28,3 +29,20 @@ class AxialInductionModel(Model):
28
29
 
29
30
  """
30
31
  pass
32
+
33
+ @classmethod
34
+ def new(cls, induction_type, *args, **kwargs):
35
+ """
36
+ Run-time axial induction model factory.
37
+
38
+ Parameters
39
+ ----------
40
+ induction_type: str
41
+ The selected derived class name
42
+ args: tuple, optional
43
+ Additional parameters for the constructor
44
+ kwargs: dict, optional
45
+ Additional parameters for the constructor
46
+
47
+ """
48
+ return new_instance(cls, induction_type, *args, **kwargs)
foxes/core/engine.py CHANGED
@@ -5,7 +5,7 @@ from tqdm import tqdm
5
5
  from xarray import Dataset
6
6
 
7
7
  from foxes.core import MData, FData, TData
8
- from foxes.utils import all_subclasses
8
+ from foxes.utils import new_instance
9
9
  from foxes.config import config
10
10
  import foxes.constants as FC
11
11
 
@@ -563,19 +563,7 @@ class Engine(ABC):
563
563
  single="SingleChunkEngine",
564
564
  ).get(engine_type, engine_type)
565
565
 
566
- allc = all_subclasses(cls)
567
- found = engine_type in [scls.__name__ for scls in allc]
568
-
569
- if found:
570
- for scls in allc:
571
- if scls.__name__ == engine_type:
572
- return scls(*args, **kwargs)
573
-
574
- else:
575
- estr = "engine type '{}' is not defined, available types are \n {}".format(
576
- engine_type, sorted([i.__name__ for i in allc])
577
- )
578
- raise KeyError(estr)
566
+ return new_instance(cls, engine_type, *args, **kwargs)
579
567
 
580
568
 
581
569
  def get_engine(error=True, default=True):
@@ -2,6 +2,7 @@ import numpy as np
2
2
 
3
3
  from foxes.config import config
4
4
  import foxes.constants as FC
5
+ from foxes.utils import new_instance
5
6
 
6
7
  from .farm_data_model import FarmDataModelList, FarmDataModel
7
8
  from .turbine_model import TurbineModel
@@ -395,3 +396,20 @@ class FarmController(FarmDataModel):
395
396
  """
396
397
  super().finalize(algo, verbosity)
397
398
  self.turbine_model_names = None
399
+
400
+ @classmethod
401
+ def new(cls, controller_type, *args, **kwargs):
402
+ """
403
+ Run-time farm controller factory.
404
+
405
+ Parameters
406
+ ----------
407
+ controller_type: str
408
+ The selected derived class name
409
+ args: tuple, optional
410
+ Additional parameters for the constructor
411
+ kwargs: dict, optional
412
+ Additional parameters for the constructor
413
+
414
+ """
415
+ return new_instance(cls, controller_type, *args, **kwargs)
@@ -1,3 +1,5 @@
1
+ from foxes.utils import new_instance
2
+
1
3
  from .model import Model
2
4
 
3
5
 
@@ -252,3 +254,20 @@ class GroundModel(Model):
252
254
 
253
255
  """
254
256
  wmodel.finalize_wake_deltas(algo, mdata, fdata, amb_results, wake_deltas)
257
+
258
+ @classmethod
259
+ def new(cls, ground_type, *args, **kwargs):
260
+ """
261
+ Run-time ground model factory.
262
+
263
+ Parameters
264
+ ----------
265
+ ground_type: str
266
+ The selected derived class name
267
+ args: tuple, optional
268
+ Additional parameters for the constructor
269
+ kwargs: dict, optional
270
+ Additional parameters for the constructor
271
+
272
+ """
273
+ return new_instance(cls, ground_type, *args, **kwargs)
@@ -1,6 +1,6 @@
1
1
  from abc import abstractmethod
2
2
 
3
- from foxes.utils import all_subclasses
3
+ from foxes.utils import new_instance
4
4
 
5
5
  from .model import Model
6
6
 
@@ -189,30 +189,18 @@ class PartialWakesModel(Model):
189
189
  pass
190
190
 
191
191
  @classmethod
192
- def new(cls, pwake_type, **kwargs):
192
+ def new(cls, pwakes_type, *args, **kwargs):
193
193
  """
194
- Run-time partial wakes factory.
194
+ Run-time partial wakes model factory.
195
195
 
196
196
  Parameters
197
197
  ----------
198
- pwake_type: str
198
+ pwakes_type: str
199
199
  The selected derived class name
200
+ args: tuple, optional
201
+ Additional parameters for the constructor
202
+ kwargs: dict, optional
203
+ Additional parameters for the constructor
200
204
 
201
205
  """
202
-
203
- if pwake_type is None:
204
- return None
205
-
206
- allc = all_subclasses(cls)
207
- found = pwake_type in [scls.__name__ for scls in allc]
208
-
209
- if found:
210
- for scls in allc:
211
- if scls.__name__ == pwake_type:
212
- return scls(**kwargs)
213
-
214
- else:
215
- estr = "Partial wakes model type '{}' is not defined, available types are \n {}".format(
216
- pwake_type, sorted([i.__name__ for i in allc])
217
- )
218
- raise KeyError(estr)
206
+ return new_instance(cls, pwakes_type, *args, **kwargs)
@@ -2,6 +2,7 @@ import numpy as np
2
2
  from abc import abstractmethod
3
3
 
4
4
  from foxes.config import config
5
+ from foxes.utils import new_instance
5
6
  import foxes.constants as FC
6
7
 
7
8
  from .data_calc_model import DataCalcModel
@@ -263,3 +264,20 @@ class PointDataModelList(PointDataModel):
263
264
  tdata.update(res)
264
265
 
265
266
  return {v: tdata[v] for v in self.output_point_vars(algo)}
267
+
268
+ @classmethod
269
+ def new(cls, model_type, *args, **kwargs):
270
+ """
271
+ Run-time point model factory.
272
+
273
+ Parameters
274
+ ----------
275
+ model_type: str
276
+ The selected derived class name
277
+ args: tuple, optional
278
+ Additional parameters for the constructor
279
+ kwargs: dict, optional
280
+ Additional parameters for the constructor
281
+
282
+ """
283
+ return new_instance(cls, model_type, *args, **kwargs)
foxes/core/rotor_model.py CHANGED
@@ -2,7 +2,7 @@ import numpy as np
2
2
  from abc import abstractmethod
3
3
 
4
4
  from foxes.config import config
5
- from foxes.utils import wd2uv, uv2wd, all_subclasses
5
+ from foxes.utils import wd2uv, uv2wd, new_instance
6
6
 
7
7
  import foxes.variables as FV
8
8
  import foxes.constants as FC
@@ -417,20 +417,4 @@ class RotorModel(FarmDataModel):
417
417
  Additional parameters for constructor
418
418
 
419
419
  """
420
-
421
- if rmodel_type is None:
422
- return None
423
-
424
- allc = all_subclasses(cls)
425
- found = rmodel_type in [scls.__name__ for scls in allc]
426
-
427
- if found:
428
- for scls in allc:
429
- if scls.__name__ == rmodel_type:
430
- return scls(*args, **kwargs)
431
-
432
- else:
433
- estr = "Rotor model type '{}' is not defined, available types are \n {}".format(
434
- rmodel_type, sorted([i.__name__ for i in allc])
435
- )
436
- raise KeyError(estr)
420
+ return new_instance(cls, rmodel_type, *args, **kwargs)
foxes/core/states.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from abc import abstractmethod
2
2
 
3
3
  from .point_data_model import PointDataModel, PointDataModelList
4
- from foxes.utils import all_subclasses
4
+ from foxes.utils import new_instance
5
5
  import foxes.variables as FV
6
6
  import foxes.constants as FC
7
7
 
@@ -163,22 +163,7 @@ class States(PointDataModel):
163
163
  Additional parameters for constructor
164
164
 
165
165
  """
166
-
167
- if states_type is None:
168
- return None
169
-
170
- allc = all_subclasses(cls)
171
- found = states_type in [scls.__name__ for scls in allc]
172
-
173
- if found:
174
- for scls in allc:
175
- if scls.__name__ == states_type:
176
- return scls(*args, **kwargs)
177
- else:
178
- estr = "States type '{}' is not defined, available types are \n {}".format(
179
- states_type, sorted([i.__name__ for i in allc])
180
- )
181
- raise KeyError(estr)
166
+ return new_instance(cls, states_type, *args, **kwargs)
182
167
 
183
168
 
184
169
  class ExtendedStates(States):