foxes 1.1.1__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 (155) hide show
  1. docs/source/conf.py +3 -1
  2. examples/abl_states/run.py +5 -5
  3. examples/dyn_wakes/run.py +2 -2
  4. examples/induction/run.py +5 -5
  5. examples/random_timeseries/run.py +13 -13
  6. examples/scan_row/run.py +12 -7
  7. examples/sector_management/run.py +11 -7
  8. examples/single_state/run.py +5 -5
  9. examples/tab_file/run.py +1 -1
  10. examples/timelines/run.py +1 -1
  11. examples/timeseries/run.py +5 -5
  12. examples/timeseries_slurm/run.py +5 -5
  13. examples/wind_rose/run.py +1 -1
  14. examples/yawed_wake/run.py +5 -5
  15. foxes/__init__.py +13 -2
  16. foxes/algorithms/downwind/downwind.py +21 -6
  17. foxes/algorithms/downwind/models/init_farm_data.py +5 -2
  18. foxes/algorithms/downwind/models/point_wakes_calc.py +0 -1
  19. foxes/algorithms/iterative/iterative.py +1 -1
  20. foxes/algorithms/sequential/sequential.py +5 -4
  21. foxes/config/__init__.py +1 -0
  22. foxes/config/config.py +134 -0
  23. foxes/constants.py +15 -6
  24. foxes/core/algorithm.py +46 -30
  25. foxes/core/axial_induction_model.py +18 -0
  26. foxes/core/data.py +2 -1
  27. foxes/core/engine.py +43 -49
  28. foxes/core/farm_controller.py +22 -3
  29. foxes/core/farm_data_model.py +6 -2
  30. foxes/core/ground_model.py +19 -0
  31. foxes/core/model.py +2 -1
  32. foxes/core/partial_wakes_model.py +9 -21
  33. foxes/core/point_data_model.py +22 -2
  34. foxes/core/rotor_model.py +9 -21
  35. foxes/core/states.py +2 -17
  36. foxes/core/turbine_model.py +2 -18
  37. foxes/core/turbine_type.py +2 -18
  38. foxes/core/vertical_profile.py +8 -20
  39. foxes/core/wake_frame.py +9 -25
  40. foxes/core/wake_model.py +24 -20
  41. foxes/core/wake_superposition.py +19 -0
  42. foxes/data/__init__.py +1 -1
  43. foxes/data/static_data.py +0 -7
  44. foxes/engines/dask.py +4 -3
  45. foxes/engines/single.py +1 -1
  46. foxes/input/__init__.py +1 -1
  47. foxes/input/farm_layout/from_csv.py +3 -1
  48. foxes/input/farm_layout/from_file.py +10 -10
  49. foxes/input/farm_layout/from_json.py +4 -3
  50. foxes/input/farm_layout/grid.py +3 -3
  51. foxes/input/states/__init__.py +1 -1
  52. foxes/input/states/create/random_abl_states.py +5 -3
  53. foxes/input/states/field_data_nc.py +36 -15
  54. foxes/input/states/multi_height.py +26 -15
  55. foxes/input/states/one_point_flow.py +6 -5
  56. foxes/input/states/{scan_ws.py → scan.py} +42 -52
  57. foxes/input/states/single.py +15 -6
  58. foxes/input/states/slice_data_nc.py +18 -12
  59. foxes/input/states/states_table.py +17 -10
  60. foxes/input/yaml/__init__.py +3 -0
  61. foxes/input/yaml/dict.py +381 -0
  62. foxes/input/yaml/windio/__init__.py +4 -0
  63. foxes/input/{windio → yaml/windio}/get_states.py +7 -7
  64. foxes/input/{windio → yaml/windio}/read_attributes.py +61 -40
  65. foxes/input/{windio → yaml/windio}/read_farm.py +34 -43
  66. foxes/input/{windio → yaml/windio}/read_fields.py +11 -10
  67. foxes/input/yaml/windio/read_outputs.py +147 -0
  68. foxes/input/yaml/windio/windio.py +269 -0
  69. foxes/input/yaml/yaml.py +103 -0
  70. foxes/models/partial_wakes/axiwake.py +7 -6
  71. foxes/models/partial_wakes/centre.py +3 -2
  72. foxes/models/partial_wakes/segregated.py +5 -2
  73. foxes/models/point_models/set_uniform_data.py +5 -3
  74. foxes/models/rotor_models/centre.py +2 -2
  75. foxes/models/rotor_models/grid.py +5 -5
  76. foxes/models/rotor_models/levels.py +6 -6
  77. foxes/models/turbine_models/kTI_model.py +3 -1
  78. foxes/models/turbine_models/lookup_table.py +7 -4
  79. foxes/models/turbine_models/power_mask.py +14 -8
  80. foxes/models/turbine_models/sector_management.py +4 -2
  81. foxes/models/turbine_models/set_farm_vars.py +53 -23
  82. foxes/models/turbine_models/table_factors.py +8 -7
  83. foxes/models/turbine_models/yaw2yawm.py +0 -1
  84. foxes/models/turbine_models/yawm2yaw.py +0 -1
  85. foxes/models/turbine_types/CpCt_file.py +6 -3
  86. foxes/models/turbine_types/CpCt_from_two.py +6 -3
  87. foxes/models/turbine_types/PCt_file.py +7 -6
  88. foxes/models/turbine_types/PCt_from_two.py +11 -2
  89. foxes/models/turbine_types/TBL_file.py +3 -4
  90. foxes/models/turbine_types/wsrho2PCt_from_two.py +19 -11
  91. foxes/models/turbine_types/wsti2PCt_from_two.py +19 -11
  92. foxes/models/vertical_profiles/abl_log_neutral_ws.py +1 -1
  93. foxes/models/vertical_profiles/abl_log_stable_ws.py +1 -1
  94. foxes/models/vertical_profiles/abl_log_unstable_ws.py +1 -1
  95. foxes/models/vertical_profiles/abl_log_ws.py +1 -1
  96. foxes/models/wake_frames/dynamic_wakes.py +17 -9
  97. foxes/models/wake_frames/farm_order.py +4 -3
  98. foxes/models/wake_frames/rotor_wd.py +3 -1
  99. foxes/models/wake_frames/seq_dynamic_wakes.py +14 -7
  100. foxes/models/wake_frames/streamlines.py +9 -6
  101. foxes/models/wake_frames/timelines.py +21 -14
  102. foxes/models/wake_frames/yawed_wakes.py +3 -1
  103. foxes/models/wake_models/induction/vortex_sheet.py +0 -1
  104. foxes/models/wake_models/ti/crespo_hernandez.py +2 -1
  105. foxes/models/wake_models/wind/bastankhah14.py +3 -2
  106. foxes/models/wake_models/wind/bastankhah16.py +2 -1
  107. foxes/models/wake_models/wind/turbopark.py +9 -7
  108. foxes/models/wake_superpositions/ws_product.py +0 -1
  109. foxes/output/__init__.py +2 -1
  110. foxes/output/calc_points.py +7 -4
  111. foxes/output/farm_layout.py +30 -18
  112. foxes/output/farm_results_eval.py +61 -38
  113. foxes/output/grids.py +8 -7
  114. foxes/output/output.py +9 -20
  115. foxes/output/plt.py +19 -0
  116. foxes/output/results_writer.py +10 -11
  117. foxes/output/rose_plot.py +448 -224
  118. foxes/output/rotor_point_plots.py +7 -3
  119. foxes/output/slice_data.py +1 -1
  120. foxes/output/state_turbine_map.py +5 -1
  121. foxes/output/state_turbine_table.py +7 -3
  122. foxes/output/turbine_type_curves.py +7 -2
  123. foxes/utils/__init__.py +1 -2
  124. foxes/utils/dict.py +107 -3
  125. foxes/utils/geopandas_utils.py +3 -2
  126. foxes/utils/subclasses.py +69 -0
  127. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/METADATA +18 -18
  128. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/RECORD +145 -145
  129. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/WHEEL +1 -1
  130. foxes-1.2.1.dist-info/entry_points.txt +3 -0
  131. tests/0_consistency/iterative/test_iterative.py +65 -67
  132. tests/0_consistency/partial_wakes/test_partial_wakes.py +58 -61
  133. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +56 -53
  134. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +41 -41
  135. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +34 -34
  136. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +57 -52
  137. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +58 -54
  138. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +80 -76
  139. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +80 -76
  140. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +58 -51
  141. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +101 -103
  142. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +67 -64
  143. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +58 -54
  144. examples/windio/run.py +0 -29
  145. foxes/data/states/windio_timeseries_5000.nc +0 -0
  146. foxes/data/windio/DTU_10MW_turbine.yaml +0 -10
  147. foxes/data/windio/__init__.py +0 -0
  148. foxes/data/windio/windio_5turbines_timeseries.yaml +0 -79
  149. foxes/input/windio/__init__.py +0 -11
  150. foxes/input/windio/read_outputs.py +0 -172
  151. foxes/input/windio/runner.py +0 -183
  152. foxes/input/windio/windio.py +0 -193
  153. foxes/utils/windrose_plot.py +0 -152
  154. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/LICENSE +0 -0
  155. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/top_level.txt +0 -0
foxes/constants.py CHANGED
@@ -1,5 +1,3 @@
1
- import numpy as np
2
-
3
1
  XYH = "xyh"
4
2
  """ The vector (x, y, height)
5
3
  :group: foxes.variables
@@ -126,13 +124,13 @@ STATE_SOURCE_ORDERI = "state-source-orderi"
126
124
  :group: foxes.constants
127
125
  """
128
126
 
129
- DTYPE = np.float64
130
- """ Default data type for floats
127
+ DTYPE = "DTYPE"
128
+ """Identifier for default double data type
131
129
  :group: foxes.constants
132
130
  """
133
131
 
134
- ITYPE = np.int64
135
- """ Default data type for int
132
+ ITYPE = "ITYPE"
133
+ """Identifier for default integer data type
136
134
  :group: foxes.constants
137
135
  """
138
136
 
@@ -184,3 +182,14 @@ POP = "pop"
184
182
  """ Population identifier
185
183
  :group: foxes.constants
186
184
  """
185
+
186
+
187
+ WORK_DIR = "work_dir"
188
+ """Identifier for the working directory
189
+ :group: foxes.constants
190
+ """
191
+
192
+ OUT_DIR = "out_dir"
193
+ """Identifier for the default output directory
194
+ :group: foxes.constants
195
+ """
foxes/core/algorithm.py CHANGED
@@ -4,7 +4,8 @@ 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
+ from foxes.config import config
8
9
  import foxes.constants as FC
9
10
 
10
11
  from .engine import Engine
@@ -33,7 +34,6 @@ class Algorithm(Model):
33
34
  farm,
34
35
  verbosity=1,
35
36
  dbook=None,
36
- engine=None,
37
37
  **engine_pars,
38
38
  ):
39
39
  """
@@ -49,8 +49,6 @@ class Algorithm(Model):
49
49
  The verbosity level, 0 means silent
50
50
  dbook: foxes.DataBook, optional
51
51
  The data book, or None for default
52
- engine: str
53
- The engine class name
54
52
  engine_pars: dict, optional
55
53
  Parameters for the engine constructor
56
54
 
@@ -68,14 +66,22 @@ class Algorithm(Model):
68
66
  self.__idata_mem = Dict(name="idata_mem")
69
67
  self.__chunk_store = Dict(name="chunk_store")
70
68
 
71
- if engine is not None:
72
- e = Engine.new(engine_type=engine, verbosity=verbosity, **engine_pars)
69
+ if len(engine_pars):
70
+ if "engine_type" in engine_pars:
71
+ if "engine" in engine_pars:
72
+ raise KeyError(
73
+ f"{self.name}: Expecting either 'engine' or 'engine_type', not both"
74
+ )
75
+ elif "engine" in engine_pars:
76
+ engine_pars["engine_type"] = engine_pars.pop("engine")
77
+ v = engine_pars.pop("verbosity", verbosity)
78
+ try:
79
+ e = Engine.new(verbosity=v, **engine_pars)
80
+ except TypeError as e:
81
+ print(f"\nError while interpreting engine_pars {engine_pars}\n")
82
+ raise e
73
83
  self.print(f"Algorithm '{self.name}': Selecting engine '{e}'")
74
84
  e.initialize()
75
- elif len(engine_pars):
76
- self.print(
77
- f"Algorithm '{self.name}': Parameter 'engine' is None; ignoring engine parameters {engine_pars}"
78
- )
79
85
 
80
86
  @property
81
87
  def farm(self):
@@ -171,6 +177,28 @@ class Algorithm(Model):
171
177
  if self.verbosity >= vlim:
172
178
  print(*args, **kwargs)
173
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
+
174
202
  def initialize(self):
175
203
  """
176
204
  Initializes the algorithm.
@@ -375,6 +403,12 @@ class Algorithm(Model):
375
403
  else:
376
404
  idata = {"coords": {FC.STATE: states_indices}, "data_vars": {}}
377
405
 
406
+ if len(points.shape) == 2 and points.shape[1] == 3:
407
+ pts = np.zeros((n_states,) + points.shape, dtype=config.dtype_double)
408
+ pts[:] = points[None]
409
+ points = pts
410
+ del pts
411
+
378
412
  if (
379
413
  len(points.shape) != 3
380
414
  or points.shape[0] != n_states
@@ -389,7 +423,7 @@ class Algorithm(Model):
389
423
  )
390
424
  idata["data_vars"][FC.TWEIGHTS] = (
391
425
  (FC.TPOINT,),
392
- np.array([1.0], dtype=FC.DTYPE),
426
+ np.array([1.0], dtype=config.dtype_double),
393
427
  )
394
428
 
395
429
  return xr.Dataset(**idata)
@@ -914,22 +948,4 @@ class Algorithm(Model):
914
948
  Additional parameters for the constructor
915
949
 
916
950
  """
917
-
918
- if algo_type is None:
919
- return None
920
-
921
- allc = all_subclasses(cls)
922
- found = algo_type in [scls.__name__ for scls in allc]
923
-
924
- if found:
925
- for scls in allc:
926
- if scls.__name__ == algo_type:
927
- return scls(*args, **kwargs)
928
-
929
- else:
930
- estr = (
931
- "Algorithm type '{}' is not defined, available types are \n {}".format(
932
- algo_type, sorted([i.__name__ for i in allc])
933
- )
934
- )
935
- 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/data.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import numpy as np
2
2
 
3
3
  from foxes.utils import Dict
4
+ from foxes.config import config
4
5
  import foxes.variables as FV
5
6
  import foxes.constants as FC
6
7
 
@@ -620,7 +621,7 @@ class TData(Data):
620
621
  )
621
622
  data[FC.TARGETS] = points[:, :, None, :]
622
623
  dims[FC.TARGETS] = (FC.STATE, FC.TARGET, FC.TPOINT, FC.XYH)
623
- data[FC.TWEIGHTS] = np.array([1], dtype=FC.DTYPE)
624
+ data[FC.TWEIGHTS] = np.array([1], dtype=config.dtype_double)
624
625
  dims[FC.TWEIGHTS] = (FC.TPOINT,)
625
626
  return cls(data, dims, [FC.STATE, FC.TARGET], name=name, **kwargs)
626
627
 
foxes/core/engine.py CHANGED
@@ -5,7 +5,8 @@ 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
+ from foxes.config import config
9
10
  import foxes.constants as FC
10
11
 
11
12
  __global_engine_data__ = dict(
@@ -246,26 +247,21 @@ class Engine(ABC):
246
247
  if int(n_states / n_chunks_states) > chunk_size_states:
247
248
  n_chunks_states += 1
248
249
  chunk_size_states = int(n_states / n_chunks_states)
249
- chunk_sizes_states = np.full(n_chunks_states, chunk_size_states)
250
- extra = n_states - n_chunks_states * chunk_size_states
251
- if extra > 0:
252
- chunk_sizes_states[-extra:] += 1
253
-
254
- s = np.sum(chunk_sizes_states)
255
- assert (
256
- s == n_states
257
- ), f"States count mismatch: Expecting {n_states}, chunks sum is {s}. Chunks: {[int(c) for c in chunk_sizes_states]}"
258
250
 
259
251
  # determine points chunks:
260
252
  chunk_sizes_targets = [n_targets]
261
253
  if n_targets > 1:
262
254
  if self.chunk_size_points is None:
263
- if n_chunks_states == 1:
264
- n_chunks_targets = min(self.n_procs, n_targets)
265
- chunk_size_targets = max(int(n_targets / self.n_procs), 1)
266
- else:
255
+ if n_targets < max(n_states, 1000):
267
256
  chunk_size_targets = n_targets
268
257
  n_chunks_targets = 1
258
+ else:
259
+ n_chunks_targets = min(self.n_procs, n_targets)
260
+ chunk_size_targets = max(int(n_targets / self.n_procs), 1)
261
+ if self.chunk_size_states is None and n_chunks_states > 1:
262
+ while chunk_size_states * chunk_size_targets > n_targets:
263
+ n_chunks_states += 1
264
+ chunk_size_states = int(n_states / n_chunks_states)
269
265
  else:
270
266
  chunk_size_targets = min(n_targets, self.chunk_size_points)
271
267
  n_chunks_targets = max(int(n_targets / chunk_size_targets), 1)
@@ -282,6 +278,16 @@ class Engine(ABC):
282
278
  s == n_targets
283
279
  ), f"Targets count mismatch: Expecting {n_targets}, chunks sum is {s}. Chunks: {[int(c) for c in chunk_sizes_targets]}"
284
280
 
281
+ chunk_sizes_states = np.full(n_chunks_states, chunk_size_states)
282
+ extra = n_states - n_chunks_states * chunk_size_states
283
+ if extra > 0:
284
+ chunk_sizes_states[-extra:] += 1
285
+
286
+ s = np.sum(chunk_sizes_states)
287
+ assert (
288
+ s == n_states
289
+ ), f"States count mismatch: Expecting {n_states}, chunks sum is {s}. Chunks: {[int(c) for c in chunk_sizes_states]}"
290
+
285
291
  return chunk_sizes_states, chunk_sizes_targets
286
292
 
287
293
  def get_chunk_input_data(
@@ -342,7 +348,7 @@ class Engine(ABC):
342
348
  n_states = i1_states - i0_states
343
349
  for o in set(out_vars).difference(data.keys()):
344
350
  data[o] = np.full(
345
- (n_states, algo.n_turbines), np.nan, dtype=FC.DTYPE
351
+ (n_states, algo.n_turbines), np.nan, dtype=config.dtype_double
346
352
  )
347
353
  dims[o] = (FC.STATE, FC.TURBINE)
348
354
 
@@ -366,7 +372,9 @@ class Engine(ABC):
366
372
  n_states = i1_states - i0_states
367
373
  n_targets = i1_targets - i0_targets
368
374
  for o in set(out_vars).difference(data.keys()):
369
- data[o] = np.full((n_states, n_targets, 1), np.nan, dtype=FC.DTYPE)
375
+ data[o] = np.full(
376
+ (n_states, n_targets, 1), np.nan, dtype=config.dtype_double
377
+ )
370
378
  dims[o] = (FC.STATE, FC.TARGET, FC.TPOINT)
371
379
 
372
380
  tdata = TData.from_dataset(
@@ -538,36 +546,24 @@ class Engine(ABC):
538
546
  """
539
547
 
540
548
  if engine_type is None:
541
- return None
542
- else:
543
- engine_type = dict(
544
- default="DefaultEngine",
545
- threads="ThreadsEngine",
546
- process="ProcessEngine",
547
- xarray="XArrayEngine",
548
- dask="DaskEngine",
549
- multiprocess="MultiprocessEngine",
550
- local_cluster="LocalClusterEngine",
551
- slurm_cluster="SlurmClusterEngine",
552
- mpi="MPIEngine",
553
- ray="RayEngine",
554
- numpy="NumpyEngine",
555
- single="SingleChunkEngine",
556
- ).get(engine_type, engine_type)
557
-
558
- allc = all_subclasses(cls)
559
- found = engine_type in [scls.__name__ for scls in allc]
560
-
561
- if found:
562
- for scls in allc:
563
- if scls.__name__ == engine_type:
564
- return scls(*args, **kwargs)
565
-
566
- else:
567
- estr = "engine type '{}' is not defined, available types are \n {}".format(
568
- engine_type, sorted([i.__name__ for i in allc])
569
- )
570
- raise KeyError(estr)
549
+ engine_type = "default"
550
+
551
+ engine_type = dict(
552
+ default="DefaultEngine",
553
+ threads="ThreadsEngine",
554
+ process="ProcessEngine",
555
+ xarray="XArrayEngine",
556
+ dask="DaskEngine",
557
+ multiprocess="MultiprocessEngine",
558
+ local_cluster="LocalClusterEngine",
559
+ slurm_cluster="SlurmClusterEngine",
560
+ mpi="MPIEngine",
561
+ ray="RayEngine",
562
+ numpy="NumpyEngine",
563
+ single="SingleChunkEngine",
564
+ ).get(engine_type, engine_type)
565
+
566
+ return new_instance(cls, engine_type, *args, **kwargs)
571
567
 
572
568
 
573
569
  def get_engine(error=True, default=True):
@@ -602,9 +598,7 @@ def get_engine(error=True, default=True):
602
598
  default.initialize()
603
599
  return default
604
600
  elif isinstance(default, bool) and default:
605
- engine = Engine.new(
606
- engine_type="DefaultEngine", chunk_size_points=20000, verbosity=0
607
- )
601
+ engine = Engine.new(engine_type="DefaultEngine", verbosity=1)
608
602
  print(f"Selecting '{engine}'")
609
603
  engine.initialize()
610
604
  return engine
@@ -1,10 +1,12 @@
1
1
  import numpy as np
2
2
 
3
+ from foxes.config import config
4
+ import foxes.constants as FC
5
+ from foxes.utils import new_instance
6
+
3
7
  from .farm_data_model import FarmDataModelList, FarmDataModel
4
8
  from .turbine_model import TurbineModel
5
9
  from .turbine_type import TurbineType
6
- import foxes.constants as FC
7
- import foxes.variables as FV
8
10
 
9
11
 
10
12
  class FarmController(FarmDataModel):
@@ -122,7 +124,7 @@ class FarmController(FarmDataModel):
122
124
  tmodels = []
123
125
  tmsels = []
124
126
  mnames = [[m.name for m in mlist] for mlist in models]
125
- tmis = np.zeros(algo.n_turbines, dtype=FC.ITYPE)
127
+ tmis = np.zeros(algo.n_turbines, dtype=config.dtype_int)
126
128
  news = True
127
129
  while news:
128
130
  news = False
@@ -394,3 +396,20 @@ class FarmController(FarmDataModel):
394
396
  """
395
397
  super().finalize(algo, verbosity)
396
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,9 +1,11 @@
1
1
  from abc import abstractmethod
2
2
  import numpy as np
3
3
 
4
- from .data_calc_model import DataCalcModel
4
+ from foxes.config import config
5
5
  import foxes.constants as FC
6
6
 
7
+ from .data_calc_model import DataCalcModel
8
+
7
9
 
8
10
  class FarmDataModel(DataCalcModel):
9
11
  """
@@ -82,7 +84,9 @@ class FarmDataModel(DataCalcModel):
82
84
  n_turbines = fdata.n_turbines
83
85
  for v in self.output_farm_vars(algo):
84
86
  if v not in fdata:
85
- fdata[v] = np.full((n_states, n_turbines), np.nan, dtype=FC.DTYPE)
87
+ fdata[v] = np.full(
88
+ (n_states, n_turbines), np.nan, dtype=config.dtype_double
89
+ )
86
90
  fdata.dims[v] = (FC.STATE, FC.TURBINE)
87
91
 
88
92
  @abstractmethod
@@ -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)
foxes/core/model.py CHANGED
@@ -2,6 +2,7 @@ import numpy as np
2
2
  from abc import ABC
3
3
  from itertools import count
4
4
 
5
+ from foxes.config import config
5
6
  import foxes.constants as FC
6
7
 
7
8
 
@@ -522,7 +523,7 @@ class Model(ABC):
522
523
  if target == FC.STATE_TARGET and tdata.n_tpoints != 1:
523
524
  # find the mean index and round it to nearest integer:
524
525
  sts = tdata.tpoint_mean(FC.STATES_SEL)[:, :, None]
525
- sts = (sts + 0.5).astype(FC.ITYPE)
526
+ sts = (sts + 0.5).astype(config.dtype_int)
526
527
  sel = sts < i0
527
528
  if np.any(sel):
528
529
  if not hasattr(algo, "farm_results_downwind"):
@@ -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)
@@ -1,9 +1,12 @@
1
1
  import numpy as np
2
2
  from abc import abstractmethod
3
3
 
4
- from .data_calc_model import DataCalcModel
4
+ from foxes.config import config
5
+ from foxes.utils import new_instance
5
6
  import foxes.constants as FC
6
7
 
8
+ from .data_calc_model import DataCalcModel
9
+
7
10
 
8
11
  class PointDataModel(DataCalcModel):
9
12
  """
@@ -60,7 +63,7 @@ class PointDataModel(DataCalcModel):
60
63
  tdata[v] = np.full(
61
64
  (tdata.n_states, tdata.n_targets, tdata.n_tpoints),
62
65
  np.nan,
63
- dtype=FC.DTYPE,
66
+ dtype=config.dtype_double,
64
67
  )
65
68
  tdata.dims[v] = (FC.STATE, FC.TARGET, FC.TPOINT)
66
69
 
@@ -261,3 +264,20 @@ class PointDataModelList(PointDataModel):
261
264
  tdata.update(res)
262
265
 
263
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
@@ -1,12 +1,14 @@
1
1
  import numpy as np
2
2
  from abc import abstractmethod
3
3
 
4
+ from foxes.config import config
5
+ from foxes.utils import wd2uv, uv2wd, new_instance
6
+
4
7
  import foxes.variables as FV
5
8
  import foxes.constants as FC
6
- from .farm_data_model import FarmDataModel
7
- from foxes.utils import wd2uv, uv2wd, all_subclasses
8
9
 
9
10
  from .data import TData
11
+ from .farm_data_model import FarmDataModel
10
12
 
11
13
 
12
14
  class RotorModel(FarmDataModel):
@@ -146,14 +148,16 @@ class RotorModel(FarmDataModel):
146
148
  dpoints = self.design_points()
147
149
  D = fdata[FV.D]
148
150
 
149
- rax = np.zeros((n_states, n_turbines, 3, 3), dtype=FC.DTYPE)
151
+ rax = np.zeros((n_states, n_turbines, 3, 3), dtype=config.dtype_double)
150
152
  n = rax[:, :, 0, 0:2]
151
153
  m = rax[:, :, 1, 0:2]
152
154
  n[:] = wd2uv(fdata[FV.YAW], axis=-1)
153
155
  m[:] = np.stack([-n[:, :, 1], n[:, :, 0]], axis=-1)
154
156
  rax[:, :, 2, 2] = 1
155
157
 
156
- points = np.zeros((n_states, n_turbines, n_points, 3), dtype=FC.DTYPE)
158
+ points = np.zeros(
159
+ (n_states, n_turbines, n_points, 3), dtype=config.dtype_double
160
+ )
157
161
  points[:] = fdata[FV.TXYH][:, :, None, :]
158
162
  points[:] += (
159
163
  0.5 * D[:, :, None, None] * np.einsum("stad,pa->stpd", rax, dpoints)
@@ -413,20 +417,4 @@ class RotorModel(FarmDataModel):
413
417
  Additional parameters for constructor
414
418
 
415
419
  """
416
-
417
- if rmodel_type is None:
418
- return None
419
-
420
- allc = all_subclasses(cls)
421
- found = rmodel_type in [scls.__name__ for scls in allc]
422
-
423
- if found:
424
- for scls in allc:
425
- if scls.__name__ == rmodel_type:
426
- return scls(*args, **kwargs)
427
-
428
- else:
429
- estr = "Rotor model type '{}' is not defined, available types are \n {}".format(
430
- rmodel_type, sorted([i.__name__ for i in allc])
431
- )
432
- 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):
@@ -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 .farm_data_model import FarmDataModel
6
6
 
@@ -60,20 +60,4 @@ class TurbineModel(FarmDataModel):
60
60
  Additional parameters for constructor
61
61
 
62
62
  """
63
-
64
- if tmodel_type is None:
65
- return None
66
-
67
- allc = all_subclasses(cls)
68
- found = tmodel_type in [scls.__name__ for scls in allc]
69
-
70
- if found:
71
- for scls in allc:
72
- if scls.__name__ == tmodel_type:
73
- return scls(*args, **kwargs)
74
-
75
- else:
76
- estr = "Turbine model type '{}' is not defined, available types are \n {}".format(
77
- tmodel_type, sorted([i.__name__ for i in allc])
78
- )
79
- raise KeyError(estr)
63
+ return new_instance(cls, tmodel_type, *args, **kwargs)