foxes 1.4__py3-none-any.whl → 1.5__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 (85) hide show
  1. docs/source/conf.py +1 -1
  2. examples/field_data_nc/run.py +1 -1
  3. examples/streamline_wakes/run.py +2 -2
  4. examples/yawed_wake/run.py +3 -1
  5. foxes/algorithms/downwind/downwind.py +5 -5
  6. foxes/algorithms/downwind/models/init_farm_data.py +58 -28
  7. foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
  8. foxes/core/algorithm.py +5 -5
  9. foxes/core/data.py +75 -4
  10. foxes/core/data_calc_model.py +4 -2
  11. foxes/core/engine.py +33 -40
  12. foxes/core/farm_data_model.py +16 -13
  13. foxes/core/model.py +19 -1
  14. foxes/core/point_data_model.py +19 -14
  15. foxes/core/rotor_model.py +1 -0
  16. foxes/core/wake_deflection.py +3 -3
  17. foxes/data/states/point_cloud_100.nc +0 -0
  18. foxes/data/states/weibull_cloud_4.nc +0 -0
  19. foxes/data/states/weibull_grid.nc +0 -0
  20. foxes/engines/dask.py +3 -6
  21. foxes/engines/default.py +2 -2
  22. foxes/engines/numpy.py +11 -10
  23. foxes/engines/pool.py +20 -11
  24. foxes/engines/single.py +8 -6
  25. foxes/input/farm_layout/__init__.py +1 -0
  26. foxes/input/farm_layout/from_arrays.py +68 -0
  27. foxes/input/states/__init__.py +7 -1
  28. foxes/input/states/dataset_states.py +710 -0
  29. foxes/input/states/field_data.py +531 -0
  30. foxes/input/states/multi_height.py +2 -0
  31. foxes/input/states/one_point_flow.py +1 -0
  32. foxes/input/states/point_cloud_data.py +618 -0
  33. foxes/input/states/scan.py +2 -0
  34. foxes/input/states/single.py +2 -0
  35. foxes/input/states/states_table.py +13 -23
  36. foxes/input/states/weibull_sectors.py +182 -77
  37. foxes/input/states/wrg_states.py +1 -1
  38. foxes/input/yaml/dict.py +25 -24
  39. foxes/input/yaml/windio/read_attributes.py +40 -27
  40. foxes/input/yaml/windio/read_farm.py +12 -10
  41. foxes/input/yaml/windio/read_outputs.py +25 -15
  42. foxes/input/yaml/windio/read_site.py +121 -12
  43. foxes/input/yaml/windio/windio.py +22 -10
  44. foxes/input/yaml/yaml.py +1 -0
  45. foxes/models/model_book.py +16 -15
  46. foxes/models/rotor_models/__init__.py +1 -0
  47. foxes/models/rotor_models/centre.py +1 -1
  48. foxes/models/rotor_models/direct_infusion.py +241 -0
  49. foxes/models/turbine_models/calculator.py +16 -3
  50. foxes/models/turbine_models/kTI_model.py +1 -0
  51. foxes/models/turbine_models/lookup_table.py +2 -0
  52. foxes/models/turbine_models/power_mask.py +1 -0
  53. foxes/models/turbine_models/rotor_centre_calc.py +2 -0
  54. foxes/models/turbine_models/sector_management.py +1 -0
  55. foxes/models/turbine_models/set_farm_vars.py +3 -8
  56. foxes/models/turbine_models/table_factors.py +2 -0
  57. foxes/models/turbine_models/thrust2ct.py +1 -0
  58. foxes/models/turbine_models/yaw2yawm.py +2 -0
  59. foxes/models/turbine_models/yawm2yaw.py +2 -0
  60. foxes/models/turbine_types/PCt_file.py +2 -4
  61. foxes/models/turbine_types/PCt_from_two.py +1 -0
  62. foxes/models/turbine_types/__init__.py +1 -0
  63. foxes/models/turbine_types/calculator_type.py +123 -0
  64. foxes/models/turbine_types/null_type.py +1 -0
  65. foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -0
  66. foxes/models/turbine_types/wsti2PCt_from_two.py +3 -1
  67. foxes/output/farm_layout.py +2 -0
  68. foxes/output/farm_results_eval.py +4 -1
  69. foxes/output/flow_plots_2d/flow_plots.py +18 -0
  70. foxes/output/flow_plots_2d/get_fig.py +1 -0
  71. foxes/output/output.py +6 -1
  72. foxes/output/results_writer.py +1 -1
  73. foxes/output/rose_plot.py +10 -0
  74. foxes/output/rotor_point_plots.py +3 -0
  75. foxes/output/state_turbine_map.py +3 -0
  76. foxes/output/turbine_type_curves.py +3 -0
  77. foxes/utils/dict.py +46 -34
  78. foxes/utils/factory.py +2 -2
  79. {foxes-1.4.dist-info → foxes-1.5.dist-info}/METADATA +32 -52
  80. {foxes-1.4.dist-info → foxes-1.5.dist-info}/RECORD +84 -76
  81. foxes/input/states/field_data_nc.py +0 -833
  82. {foxes-1.4.dist-info → foxes-1.5.dist-info}/WHEEL +0 -0
  83. {foxes-1.4.dist-info → foxes-1.5.dist-info}/entry_points.txt +0 -0
  84. {foxes-1.4.dist-info → foxes-1.5.dist-info}/licenses/LICENSE +0 -0
  85. {foxes-1.4.dist-info → foxes-1.5.dist-info}/top_level.txt +0 -0
docs/source/conf.py CHANGED
@@ -68,7 +68,7 @@ intersphinx_mapping = {
68
68
 
69
69
  # The suffix(es) of source filenames.
70
70
  #
71
- source_suffix = {'.rst': 'restructuredtext', '.md': 'restructuredtext'}
71
+ source_suffix = {".rst": "restructuredtext", ".md": "restructuredtext"}
72
72
 
73
73
  # The master toctree document.
74
74
  master_doc = "index"
@@ -70,7 +70,7 @@ if __name__ == "__main__":
70
70
  )
71
71
  args = parser.parse_args()
72
72
 
73
- states = foxes.input.states.FieldDataNC(
73
+ states = foxes.input.states.FieldData(
74
74
  args.file_pattern,
75
75
  output_vars=[FV.WS, FV.WD, FV.TI, FV.RHO],
76
76
  load_mode=args.load_mode,
@@ -97,7 +97,7 @@ if __name__ == "__main__":
97
97
  mbook.turbine_models["set_yawm"].add_var(FV.YAWM, yawm)
98
98
  ymodels = ["set_yawm"]
99
99
 
100
- states = foxes.input.states.FieldDataNC(
100
+ states = foxes.input.states.FieldData(
101
101
  args.file_pattern,
102
102
  states_coord="state",
103
103
  x_coord="x",
@@ -108,7 +108,7 @@ if __name__ == "__main__":
108
108
  var2ncvar={FV.WS: "ws", FV.WD: "wd"},
109
109
  fixed_vars={FV.RHO: 1.225, FV.TI: 0.1},
110
110
  load_mode=args.load_mode,
111
- bounds_error=False,
111
+ interpn_pars=dict(bounds_error=False),
112
112
  )
113
113
 
114
114
  farm = foxes.WindFarm()
@@ -82,7 +82,9 @@ if __name__ == "__main__":
82
82
 
83
83
  # set turbines in yaw
84
84
  yawm = np.array([[args.yawm, args.yawm2]])
85
- mbook.turbine_models["set_yawm"] = foxes.models.turbine_models.SetFarmVars()
85
+ mbook.turbine_models["set_yawm"] = foxes.models.turbine_models.SetFarmVars(
86
+ pre_rotor=True
87
+ )
86
88
  mbook.turbine_models["set_yawm"].add_var(FV.YAWM, yawm)
87
89
 
88
90
  # create states
@@ -477,7 +477,7 @@ class Downwind(Algorithm):
477
477
  # 2) calculate ambient rotor results:
478
478
  mlist.models.append(self.rotor_model)
479
479
  calc_pars.append(calc_parameters.get(mlist.models[-1].name, {}))
480
- calc_pars[-1].update({"store": True})
480
+ calc_pars[-1]["store"] = True
481
481
 
482
482
  # 3) run post-rotor turbine models via farm controller:
483
483
  mlist.models.append(self.farm_controller)
@@ -508,7 +508,7 @@ class Downwind(Algorithm):
508
508
  def _launch_parallel_farm_calc(
509
509
  self,
510
510
  mlist,
511
- *data,
511
+ model_data,
512
512
  outputs=None,
513
513
  normalize=False,
514
514
  **kwargs,
@@ -520,8 +520,8 @@ class Downwind(Algorithm):
520
520
  ----------
521
521
  mlist: foxes.models.FarmDataModelList
522
522
  The model list
523
- data: tuple of xarray.Dataset
524
- The (mdata, fdata) inputs
523
+ model_data: xarray.Dataset
524
+ The initial model data
525
525
  outputs: list of str, optional
526
526
  The output variables, or None for defaults
527
527
  normalize: bool
@@ -538,7 +538,7 @@ class Downwind(Algorithm):
538
538
  """
539
539
  out_vars = self.farm_vars if outputs is None else outputs
540
540
  farm_results = get_engine().run_calculation(
541
- self, mlist, *data, out_vars=out_vars, **kwargs
541
+ self, mlist, model_data, out_vars=out_vars, **kwargs
542
542
  )
543
543
 
544
544
  if normalize:
@@ -74,17 +74,17 @@ class InitFarmData(FarmDataModel):
74
74
  n_states = fdata.n_states
75
75
  n_turbines = algo.n_turbines
76
76
 
77
- # define FV.TXYH as vector [X, Y, H]:
78
- fdata[FV.TXYH] = np.full(
79
- (n_states, n_turbines, 3), np.nan, dtype=config.dtype_double
77
+ # add and set X, Y, H, D:
78
+ fdata.add(
79
+ FV.TXYH,
80
+ np.zeros((n_states, n_turbines, 3), dtype=config.dtype_double),
81
+ (FC.STATE, FC.TURBINE, FC.XYH),
82
+ )
83
+ fdata.add(
84
+ FV.D,
85
+ np.zeros((n_states, n_turbines), dtype=config.dtype_double),
86
+ (FC.STATE, FC.TURBINE),
80
87
  )
81
- fdata.dims[FV.TXYH] = (FC.STATE, FC.TURBINE, FC.XYH)
82
- for i, v in enumerate([FV.X, FV.Y, FV.H]):
83
- fdata[v] = fdata[FV.TXYH][..., i]
84
- fdata.dims[v] = (FC.STATE, FC.TURBINE)
85
-
86
- # set X, Y, H, D:
87
- fdata[FV.D] = np.zeros((n_states, n_turbines), dtype=config.dtype_double)
88
88
  for ti, t in enumerate(algo.farm.turbines):
89
89
  if len(t.xy.shape) == 1:
90
90
  fdata[FV.TXYH][:, ti, :2] = t.xy[None, :]
@@ -103,34 +103,64 @@ class InitFarmData(FarmDataModel):
103
103
  D = algo.farm_controller.turbine_types[ti].D
104
104
  fdata[FV.D][:, ti] = D
105
105
 
106
- # calc WD and YAW at rotor centres:
106
+ # calc WD at rotor centres:
107
107
  svrs = algo.states.output_point_vars(algo)
108
108
  tdata = TData.from_points(points=fdata[FV.TXYH], variables=svrs)
109
109
  sres = algo.states.calculate(algo, mdata, fdata, tdata)
110
- fdata[FV.WD] = sres[FV.WD][:, :, 0]
110
+ fdata.add(
111
+ FV.WD,
112
+ sres[FV.WD][:, :, 0],
113
+ (FC.STATE, FC.TURBINE),
114
+ )
115
+ fdata.add(
116
+ FV.AMB_WD,
117
+ fdata[FV.WD].copy(),
118
+ (FC.STATE, FC.TURBINE),
119
+ )
111
120
  del tdata, sres, svrs
112
121
 
113
- # calculate and inverse:
122
+ # calculate downwind order:
114
123
  order = algo.wake_frame.calc_order(algo, mdata, fdata)
115
124
  ssel = np.zeros_like(order)
116
125
  ssel[:] = np.arange(n_states)[:, None]
117
- fdata[FV.ORDER] = order
118
- fdata[FV.ORDER_SSEL] = ssel
119
- fdata[FV.ORDER_INV] = np.zeros_like(order)
120
- fdata[FV.ORDER_INV][ssel, order] = np.arange(n_turbines)[None, :]
121
126
 
122
127
  # apply downwind order to all data:
123
- fdata[FV.TXYH] = fdata[FV.TXYH][ssel, order]
128
+ for data in [fdata, mdata]:
129
+ for k in data.keys():
130
+ if (
131
+ k not in [FV.X, FV.Y, FV.H]
132
+ and tuple(data.dims[k][:2]) == (FC.STATE, FC.TURBINE)
133
+ and np.any(data[k] != data[k][0, 0, None, None])
134
+ ):
135
+ data[k][:] = data[k][ssel, order]
136
+
137
+ # add derived data:
124
138
  for i, v in enumerate([FV.X, FV.Y, FV.H]):
125
- fdata[v] = fdata[FV.TXYH][..., i]
126
- for v in [FV.D, FV.WD]:
127
- if np.any(fdata[v] != fdata[v][0, 0, None, None]):
128
- fdata[v] = fdata[v][ssel, order]
129
- fdata[FV.YAW] = fdata[FV.WD].copy()
130
- for k in mdata.keys():
131
- if tuple(mdata.dims[k][:2]) == (FC.STATE, FC.TURBINE) and np.any(
132
- mdata[k] != mdata[k][0, 0, None, None]
133
- ):
134
- mdata[k] = mdata[k][ssel, order]
139
+ fdata.add(
140
+ v,
141
+ fdata[FV.TXYH][:, :, i],
142
+ (FC.STATE, FC.TURBINE),
143
+ )
144
+ fdata.add(
145
+ FV.YAW,
146
+ fdata[FV.WD].copy(),
147
+ (FC.STATE, FC.TURBINE),
148
+ )
149
+ fdata.add(
150
+ FV.ORDER,
151
+ order,
152
+ (FC.STATE, FC.TURBINE),
153
+ )
154
+ fdata.add(
155
+ FV.ORDER_SSEL,
156
+ ssel,
157
+ (FC.STATE, FC.TURBINE),
158
+ )
159
+ fdata.add(
160
+ FV.ORDER_INV,
161
+ np.zeros_like(order),
162
+ (FC.STATE, FC.TURBINE),
163
+ )
164
+ fdata[FV.ORDER_INV][ssel, order] = np.arange(n_turbines)[None, :]
135
165
 
136
166
  return {v: fdata[v] for v in self.output_farm_vars(algo)}
@@ -65,5 +65,5 @@ class SetAmbFarmResults(FarmDataModel):
65
65
 
66
66
  """
67
67
  for v in self.vars:
68
- fdata[FV.var2amb[v]] = fdata[v].copy()
68
+ fdata.add(FV.var2amb[v], fdata[v].copy(), fdata.dims[v])
69
69
  return {v: fdata[v] for v in self.output_farm_vars(algo)}
foxes/core/algorithm.py CHANGED
@@ -63,8 +63,8 @@ class Algorithm(Model):
63
63
  self.__farm = farm
64
64
  self.__mbook = mbook
65
65
  self.__dbook = StaticData() if dbook is None else dbook
66
- self.__idata_mem = Dict(name="idata_mem")
67
- self.__chunk_store = Dict(name="chunk_store")
66
+ self.__idata_mem = Dict(_name="idata_mem")
67
+ self.__chunk_store = Dict(_name="chunk_store")
68
68
 
69
69
  if len(engine_pars):
70
70
  if "engine_type" in engine_pars:
@@ -558,7 +558,7 @@ class Algorithm(Model):
558
558
  "n_states": n_states,
559
559
  "n_targets": n_targets,
560
560
  },
561
- name=f"chunk_store_{i0}_{t0}",
561
+ _name=f"chunk_store_{i0}_{t0}",
562
562
  )
563
563
 
564
564
  self.chunk_store[key][name] = data.copy() if copy else data
@@ -638,11 +638,11 @@ class Algorithm(Model):
638
638
  """
639
639
  chunk_store = self.chunk_store
640
640
  if new_chunk_store is None:
641
- self.__chunk_store = Dict(name="chunk_store")
641
+ self.__chunk_store = Dict(_name="chunk_store")
642
642
  elif isinstance(new_chunk_store, Dict):
643
643
  self.__chunk_store = new_chunk_store
644
644
  else:
645
- self.__chunk_store = Dict(name="chunk_store")
645
+ self.__chunk_store = Dict(_name="chunk_store")
646
646
  self.__chunk_store.update(new_chunk_store)
647
647
  return chunk_store
648
648
 
foxes/core/data.py CHANGED
@@ -53,7 +53,7 @@ class Data(Dict):
53
53
  The data container name
54
54
 
55
55
  """
56
- super().__init__(name=name)
56
+ super().__init__(_name=name)
57
57
 
58
58
  self.update(data)
59
59
  self.dims = dims
@@ -109,12 +109,12 @@ class Data(Dict):
109
109
  or the corresponding index
110
110
 
111
111
  """
112
- if FC.STATE not in self:
113
- return None
114
- elif counter:
112
+ if counter:
115
113
  if self.__states_i0 is None:
116
114
  raise KeyError(f"Data '{self.name}': states_i0 requested but not set")
117
115
  return self.__states_i0
116
+ elif FC.STATE not in self:
117
+ return None
118
118
  else:
119
119
  return self[FC.STATE][0]
120
120
 
@@ -394,6 +394,74 @@ class FData(Data):
394
394
  f"FData '{self.name}': Missing '{x}' in sizes, got {sorted(list(self.sizes.keys()))}"
395
395
  )
396
396
 
397
+ @classmethod
398
+ def from_sizes(cls, n_states, n_turbines, *args, callback=None, **kwargs):
399
+ """
400
+ Create Data object from model data
401
+
402
+ Parameters
403
+ ----------
404
+ n_states: int
405
+ The number of states
406
+ n_turbines: int
407
+ The number of turbines
408
+ args: tuple, optional
409
+ Additional parameters for the constructor
410
+ callback: Function, optional
411
+ Function f(data, dims) that manipulates
412
+ the data and dims dicts before construction
413
+ kwargs: dict, optional
414
+ Additional parameters for the constructor
415
+
416
+ Returns
417
+ -------
418
+ data: Data
419
+ The data object
420
+
421
+ """
422
+ data = cls(*args, **kwargs)
423
+ data.sizes[FC.STATE] = n_states
424
+ data.sizes[FC.TURBINE] = n_turbines
425
+
426
+ if callback is not None:
427
+ callback(data, data.dims)
428
+
429
+ return data
430
+
431
+ @classmethod
432
+ def from_mdata(cls, mdata, *args, callback=None, **kwargs):
433
+ """
434
+ Create Data object from model data
435
+
436
+ Parameters
437
+ ----------
438
+ mdata: MData
439
+ The model data
440
+ args: tuple, optional
441
+ Additional parameters for the constructor
442
+ callback: Function, optional
443
+ Function f(data, dims) that manipulates
444
+ the data and dims dicts before construction
445
+ kwargs: dict, optional
446
+ Additional parameters for the constructor
447
+
448
+ Returns
449
+ -------
450
+ data: Data
451
+ The data object
452
+
453
+ """
454
+ data = cls(*args, **kwargs)
455
+ for v in [FC.STATE, FC.TURBINE]:
456
+ data[v] = mdata[v]
457
+ data.dims[v] = mdata.dims[v]
458
+ data.sizes[v] = mdata.sizes[v]
459
+
460
+ if callback is not None:
461
+ callback(data, data.dims)
462
+
463
+ return data
464
+
397
465
  @classmethod
398
466
  def from_dataset(cls, ds, *args, mdata=None, callback=None, **kwargs):
399
467
  """
@@ -427,6 +495,9 @@ class FData(Data):
427
495
  if FC.STATE not in data:
428
496
  data[FC.STATE] = mdata[FC.STATE]
429
497
  dims[FC.STATE] = mdata.dims[FC.STATE]
498
+ if FC.TURBINE not in data:
499
+ data[FC.TURBINE] = mdata[FC.TURBINE]
500
+ dims[FC.TURBINE] = mdata.dims[FC.TURBINE]
430
501
  if callback is not None:
431
502
  callback(data, dims)
432
503
 
@@ -45,8 +45,10 @@ class DataCalcModel(Model):
45
45
  ----------
46
46
  algo: foxes.core.Algorithm
47
47
  The calculation algorithm
48
- data: tuple of foxes.core.Data
49
- The input data
48
+ data: tuple of foxes.core.Data, optional
49
+ The input data, typically either (mdata, fdata) in
50
+ the case of farm calculations, or (mdata, fdata, tdata)
51
+ for point data calculations
50
52
  parameters: dict, optional
51
53
  The calculation parameters
52
54
 
foxes/core/engine.py CHANGED
@@ -6,7 +6,6 @@ from xarray import Dataset
6
6
 
7
7
  from .data import MData, FData, TData
8
8
  from foxes.utils import new_instance
9
- from foxes.config import config
10
9
  import foxes.constants as FC
11
10
 
12
11
  __global_engine_data__ = dict(
@@ -350,8 +349,9 @@ class Engine(ABC):
350
349
 
351
350
  Returns
352
351
  -------
353
- data: list of foxes.core.Data
354
- Either [mdata, fdata] or [mdata, fdata, tdata]
352
+ data: tuple of foxes.core.Data
353
+ The input data for the chunk calculation,
354
+ either (mdata, fdata) or (mdata, fdata, tdata)
355
355
 
356
356
  """
357
357
  # prepare:
@@ -370,51 +370,37 @@ class Engine(ABC):
370
370
  )
371
371
 
372
372
  # create fdata:
373
- if point_data is None:
374
-
375
- def cb(data, dims):
376
- n_states = i1_states - i0_states
377
- for o in set(out_vars).difference(data.keys()):
378
- data[o] = np.full(
379
- (n_states, algo.n_turbines), np.nan, dtype=config.dtype_double
380
- )
381
- dims[o] = (FC.STATE, FC.TURBINE)
382
-
373
+ if farm_data is not None:
374
+ fdata = FData.from_dataset(
375
+ farm_data,
376
+ mdata=mdata,
377
+ s_states=s_states,
378
+ callback=None,
379
+ states_i0=i0_states,
380
+ copy=True,
381
+ )
383
382
  else:
384
- cb = None
385
- fdata = FData.from_dataset(
386
- farm_data,
387
- mdata=mdata,
388
- s_states=s_states,
389
- callback=cb,
390
- states_i0=i0_states,
391
- copy=True,
392
- )
383
+ fdata = FData.from_mdata(
384
+ mdata=mdata,
385
+ states_i0=i0_states,
386
+ )
393
387
 
394
388
  # create tdata:
395
- tdata = None
396
- if point_data is not None:
397
-
398
- def cb(data, dims):
399
- n_states = i1_states - i0_states
400
- n_targets = i1_targets - i0_targets
401
- for o in set(out_vars).difference(data.keys()):
402
- data[o] = np.full(
403
- (n_states, n_targets, 1), np.nan, dtype=config.dtype_double
404
- )
405
- dims[o] = (FC.STATE, FC.TARGET, FC.TPOINT)
406
-
407
- tdata = TData.from_dataset(
389
+ tdata = (
390
+ TData.from_dataset(
408
391
  point_data,
409
392
  mdata=mdata,
410
393
  s_states=s_states,
411
394
  s_targets=s_targets,
412
- callback=cb,
395
+ callback=None,
413
396
  states_i0=i0_states,
414
397
  copy=True,
415
398
  )
399
+ if point_data is not None
400
+ else None
401
+ )
416
402
 
417
- return [d for d in [mdata, fdata, tdata] if d is not None]
403
+ return (mdata, fdata) if tdata is None else (mdata, fdata, tdata)
418
404
 
419
405
  def combine_results(
420
406
  self,
@@ -535,7 +521,14 @@ class Engine(ABC):
535
521
  )
536
522
 
537
523
  @abstractmethod
538
- def run_calculation(self, algo, model, model_data, farm_data, point_data=None):
524
+ def run_calculation(
525
+ self,
526
+ algo,
527
+ model,
528
+ model_data=None,
529
+ farm_data=None,
530
+ point_data=None,
531
+ ):
539
532
  """
540
533
  Runs the model calculation
541
534
 
@@ -543,12 +536,12 @@ class Engine(ABC):
543
536
  ----------
544
537
  algo: foxes.core.Algorithm
545
538
  The algorithm object
546
- model: foxes.core.DataCalcModel
539
+ model: foxes.core.DataCalcModel, optional
547
540
  The model that whose calculate function
548
541
  should be run
549
542
  model_data: xarray.Dataset
550
543
  The initial model data
551
- farm_data: xarray.Dataset
544
+ farm_data: xarray.Dataset, optional
552
545
  The initial farm data
553
546
  point_data: xarray.Dataset, optional
554
547
  The initial point data
@@ -66,28 +66,29 @@ class FarmDataModel(DataCalcModel):
66
66
  """
67
67
  return (FC.STATE, FC.TURBINE)
68
68
 
69
- def ensure_variables(self, algo, mdata, fdata):
69
+ def ensure_output_vars(self, algo, fdata):
70
70
  """
71
- Add variables to fdata, initialized with NaN
71
+ Ensures that the output variables are present in the farm data.
72
72
 
73
73
  Parameters
74
74
  ----------
75
75
  algo: foxes.core.Algorithm
76
76
  The calculation algorithm
77
- mdata: foxes.core.Data
78
- The model data
79
- fdata: foxes.core.Data
77
+ fdata: foxes.core.FData
80
78
  The farm data
81
79
 
82
80
  """
83
- n_states = fdata.n_states
84
- n_turbines = fdata.n_turbines
85
- for v in self.output_farm_vars(algo):
86
- if v not in fdata:
87
- fdata[v] = np.full(
88
- (n_states, n_turbines), np.nan, dtype=config.dtype_double
81
+ for var in self.output_farm_vars(algo):
82
+ if var not in fdata:
83
+ fdata.add(
84
+ var,
85
+ np.full(
86
+ (fdata.n_states, fdata.n_turbines),
87
+ np.nan,
88
+ dtype=config.dtype_double,
89
+ ),
90
+ (FC.STATE, FC.TURBINE),
89
91
  )
90
- fdata.dims[v] = (FC.STATE, FC.TURBINE)
91
92
 
92
93
  @abstractmethod
93
94
  def calculate(self, algo, mdata, fdata):
@@ -264,7 +265,7 @@ class FarmDataModelList(FarmDataModel):
264
265
  The model data
265
266
  fdata: foxes.core.FData
266
267
  The farm data
267
- parameters: list of dict, optional
268
+ parameters: list of dict
268
269
  A list of parameter dicts, one for each model
269
270
 
270
271
  Returns
@@ -274,6 +275,8 @@ class FarmDataModelList(FarmDataModel):
274
275
  Values: numpy.ndarray with shape (n_states, n_turbines)
275
276
 
276
277
  """
278
+ self.ensure_output_vars(algo, fdata)
279
+
277
280
  if parameters is None:
278
281
  parameters = [{}] * len(self.models)
279
282
  elif not isinstance(parameters, list):
foxes/core/model.py CHANGED
@@ -64,12 +64,30 @@ class Model(ABC):
64
64
 
65
65
  Returns
66
66
  -------
67
- str
67
+ vnm: str
68
68
  Model specific variable name
69
69
 
70
70
  """
71
71
  return f"{self.name}_{v}"
72
72
 
73
+ def unvar(self, vnm):
74
+ """
75
+ Translates model specific variable name to origninal variable name.
76
+
77
+ Parameters
78
+ ----------
79
+ vnm: str
80
+ The vamodel specific variable name
81
+
82
+ Returns
83
+ -------
84
+ v: str
85
+ Original variable name
86
+
87
+ """
88
+ lng = len(f"{self.name}_")
89
+ return vnm[lng:] if vnm.startswith(f"{self.name}_") else None
90
+
73
91
  @property
74
92
  def initialized(self):
75
93
  """
@@ -42,30 +42,33 @@ class PointDataModel(DataCalcModel):
42
42
  """
43
43
  return (FC.STATE, FC.TARGET, FC.TPOINT)
44
44
 
45
- def ensure_variables(self, algo, mdata, fdata, tdata):
45
+ def ensure_output_vars(self, algo, tdata):
46
46
  """
47
- Add variables to tdata, initialized with NaN
47
+ Ensures that the output variables are present in the target data.
48
48
 
49
49
  Parameters
50
50
  ----------
51
51
  algo: foxes.core.Algorithm
52
52
  The calculation algorithm
53
- mdata: foxes.core.Data
54
- The model data
55
- fdata: foxes.core.Data
56
- The farm data
57
- tdata: foxes.core.Data
53
+ tdata: foxes.core.TData
58
54
  The target point data
59
55
 
60
56
  """
61
- for v in self.output_point_vars(algo):
62
- if v not in tdata:
63
- tdata[v] = np.full(
64
- (tdata.n_states, tdata.n_targets, tdata.n_tpoints),
65
- np.nan,
66
- dtype=config.dtype_double,
57
+ vrs = set(self.output_point_vars(algo))
58
+ if hasattr(self, "fixed_vars"):
59
+ vrs.update(self.fixed_vars.keys())
60
+
61
+ for var in vrs:
62
+ if var not in tdata:
63
+ tdata.add(
64
+ var,
65
+ np.full(
66
+ (tdata.n_states, tdata.n_targets, tdata.n_tpoints),
67
+ np.nan,
68
+ dtype=config.dtype_double,
69
+ ),
70
+ (FC.STATE, FC.TARGET, FC.TPOINT),
67
71
  )
68
- tdata.dims[v] = (FC.STATE, FC.TARGET, FC.TPOINT)
69
72
 
70
73
  @abstractmethod
71
74
  def calculate(self, algo, mdata, fdata, tdata):
@@ -247,6 +250,8 @@ class PointDataModelList(PointDataModel):
247
250
  (n_states, n_targets, n_tpoints)
248
251
 
249
252
  """
253
+ self.ensure_output_vars(algo, tdata)
254
+
250
255
  if parameters is None:
251
256
  parameters = [{}] * len(self.models)
252
257
  elif not isinstance(parameters, list):
foxes/core/rotor_model.py CHANGED
@@ -362,6 +362,7 @@ class RotorModel(FarmDataModel):
362
362
  numpy.ndarray with results, shape: (n_states, n_turbines)
363
363
 
364
364
  """
365
+ self.ensure_output_vars(algo, fdata)
365
366
 
366
367
  if rpoints is None:
367
368
  rpoints = mdata.get(
@@ -113,13 +113,13 @@ class WakeDeflection(Model):
113
113
  )
114
114
 
115
115
  @classmethod
116
- def new(cls, wframe_type, *args, **kwargs):
116
+ def new(cls, wdefl_type, *args, **kwargs):
117
117
  """
118
118
  Run-time wake deflection model factory.
119
119
 
120
120
  Parameters
121
121
  ----------
122
- wframe_type: str
122
+ wdefl_type: str
123
123
  The selected derived class name
124
124
  args: tuple, optional
125
125
  Additional parameters for constructor
@@ -127,4 +127,4 @@ class WakeDeflection(Model):
127
127
  Additional parameters for constructor
128
128
 
129
129
  """
130
- return new_instance(cls, wframe_type, *args, **kwargs)
130
+ return new_instance(cls, wdefl_type, *args, **kwargs)
Binary file
Binary file
Binary file