foxes 0.5.1__py3-none-any.whl → 0.5.2__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 +41 -46
- foxes/algorithms/downwind/models/point_wakes_calc.py +4 -9
- foxes/algorithms/downwind/models/set_amb_point_results.py +5 -22
- foxes/core/algorithm.py +1 -1
- foxes/core/data_calc_model.py +26 -2
- foxes/core/partial_wakes_model.py +1 -1
- foxes/core/rotor_model.py +36 -2
- foxes/core/turbine_model.py +36 -0
- foxes/core/turbine_type.py +35 -1
- foxes/core/wake_frame.py +39 -3
- foxes/core/wake_model.py +36 -0
- foxes/models/model_book.py +132 -85
- foxes/models/turbine_models/rotor_centre_calc.py +1 -2
- foxes/models/turbine_types/CpCt_file.py +13 -3
- foxes/models/turbine_types/CpCt_from_two.py +14 -4
- foxes/models/vertical_profiles/abl_log_neutral_ws.py +32 -5
- foxes/models/vertical_profiles/abl_log_stable_ws.py +32 -4
- foxes/models/vertical_profiles/abl_log_unstable_ws.py +32 -4
- foxes/models/vertical_profiles/abl_log_ws.py +50 -18
- foxes/models/wake_frames/yawed_wakes.py +15 -9
- foxes/models/wake_models/induction/__init__.py +1 -1
- foxes/models/wake_models/induction/rankine_half_body.py +33 -7
- foxes/models/wake_models/ti/crespo_hernandez.py +6 -1
- foxes/models/wake_models/ti/iec_ti.py +5 -3
- foxes/models/wake_models/wind/__init__.py +2 -2
- foxes/models/wake_models/wind/{bastankhah.py → bastankhah14.py} +11 -14
- foxes/models/wake_models/wind/{porte_agel.py → bastankhah16.py} +24 -16
- foxes/models/wake_models/wind/turbopark.py +11 -22
- foxes/models/wake_superpositions/__init__.py +9 -5
- foxes/models/wake_superpositions/ti_linear.py +134 -0
- foxes/models/wake_superpositions/ti_max.py +134 -0
- foxes/models/wake_superpositions/{ti_superp.py → ti_pow.py} +15 -57
- foxes/models/wake_superpositions/ti_quadratic.py +134 -0
- foxes/models/wake_superpositions/ws_linear.py +170 -0
- foxes/models/wake_superpositions/ws_max.py +173 -0
- foxes/models/wake_superpositions/ws_pow.py +175 -0
- foxes/models/wake_superpositions/{product.py → ws_product.py} +43 -22
- foxes/models/wake_superpositions/ws_quadratic.py +170 -0
- foxes/output/__init__.py +4 -0
- foxes/output/calc_points.py +143 -0
- foxes/output/flow_plots_2d/__init__.py +1 -0
- foxes/output/flow_plots_2d/common.py +104 -1
- foxes/output/flow_plots_2d/flow_plots.py +237 -569
- foxes/output/flow_plots_2d/get_fig.py +183 -0
- foxes/output/flow_plots_2d/seq_flow_ani_plugin.py +0 -1
- foxes/output/grids.py +705 -0
- foxes/output/output.py +58 -11
- foxes/output/results_writer.py +101 -17
- foxes/output/round.py +10 -0
- foxes/output/slice_data.py +900 -0
- foxes/utils/__init__.py +5 -3
- foxes/utils/exec_python.py +56 -0
- foxes/utils/geopandas_utils.py +294 -0
- foxes/utils/pandas_utils.py +175 -0
- foxes/utils/plotly_utils.py +19 -0
- foxes/utils/xarray_utils.py +38 -0
- {foxes-0.5.1.dist-info → foxes-0.5.2.dist-info}/METADATA +1 -1
- {foxes-0.5.1.dist-info → foxes-0.5.2.dist-info}/RECORD +63 -49
- foxes/models/wake_superpositions/linear.py +0 -242
- foxes/models/wake_superpositions/max.py +0 -258
- foxes/models/wake_superpositions/quadratic.py +0 -252
- {foxes-0.5.1.dist-info → foxes-0.5.2.dist-info}/LICENSE +0 -0
- {foxes-0.5.1.dist-info → foxes-0.5.2.dist-info}/WHEEL +0 -0
- {foxes-0.5.1.dist-info → foxes-0.5.2.dist-info}/top_level.txt +0 -0
- {foxes-0.5.1.dist-info → foxes-0.5.2.dist-info}/zip-safe +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from xarray import Dataset
|
|
3
|
+
|
|
4
|
+
import foxes.constants as FC
|
|
5
|
+
import foxes.variables as FV
|
|
6
|
+
from foxes.utils import write_nc
|
|
7
|
+
|
|
8
|
+
from .output import Output
|
|
9
|
+
|
|
10
|
+
class PointCalculator(Output):
|
|
11
|
+
"""
|
|
12
|
+
Computes results at given points
|
|
13
|
+
|
|
14
|
+
Attributes
|
|
15
|
+
----------
|
|
16
|
+
algo: foxes.Algorithm
|
|
17
|
+
The algorithm for point calculation
|
|
18
|
+
farm_results: xarray.Dataset
|
|
19
|
+
The farm results
|
|
20
|
+
|
|
21
|
+
:group: output
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, algo, farm_results, **kwargs):
|
|
26
|
+
"""
|
|
27
|
+
Constructor.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
algo: foxes.Algorithm
|
|
32
|
+
The algorithm for point calculation
|
|
33
|
+
farm_results: xarray.Dataset
|
|
34
|
+
The farm results
|
|
35
|
+
kwargs: dict, optional
|
|
36
|
+
Additional parameters for the base class
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
super().__init__(**kwargs)
|
|
40
|
+
self.algo = algo
|
|
41
|
+
self.farm_results = farm_results
|
|
42
|
+
|
|
43
|
+
def calculate(
|
|
44
|
+
self,
|
|
45
|
+
points,
|
|
46
|
+
*args,
|
|
47
|
+
states_mean=False,
|
|
48
|
+
weight_turbine=0,
|
|
49
|
+
to_file=None,
|
|
50
|
+
write_vars=None,
|
|
51
|
+
write_pars={},
|
|
52
|
+
**kwargs
|
|
53
|
+
):
|
|
54
|
+
"""
|
|
55
|
+
Calculate point results
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
points: numpy.ndarray
|
|
60
|
+
The points, shape: (n_points, 3)
|
|
61
|
+
or (n_states, n_points, 3)
|
|
62
|
+
args: tuple, optional
|
|
63
|
+
Additional arguments for algo.calc_points
|
|
64
|
+
states_mean: bool
|
|
65
|
+
Flag for taking the mean over states
|
|
66
|
+
weight_turbine: int, optional
|
|
67
|
+
Index of the turbine from which to take the weight
|
|
68
|
+
to_file: str, optional
|
|
69
|
+
Path to the output netCDF file
|
|
70
|
+
write_vars: list of str
|
|
71
|
+
The variables to be written to file, or None
|
|
72
|
+
for all
|
|
73
|
+
write_pars: dict, optional
|
|
74
|
+
Additional parameters for write_nc
|
|
75
|
+
kwargs: tuple, optional
|
|
76
|
+
Additional arguments for algo.calc_points
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
point_results: xarray.Dataset
|
|
81
|
+
The point results. The calculated variables have
|
|
82
|
+
dimensions (state, point)
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
if points.shape[-1] == 3 and len(points.shape) == 3:
|
|
86
|
+
pts = points
|
|
87
|
+
p_has_s = True
|
|
88
|
+
elif points.shape[-1] == 3 and len(points.shape) == 2:
|
|
89
|
+
pts = np.zeros([self.algo.n_states] + list(points.shape), dtype=FC.DTYPE)
|
|
90
|
+
pts[:] = points[None, :]
|
|
91
|
+
p_has_s = False
|
|
92
|
+
else:
|
|
93
|
+
raise ValueError(f"Expecting point shape (n_states, n_points, 3) or (n_points, 3), got {points.shape}")
|
|
94
|
+
|
|
95
|
+
pres = self.algo.calc_points(self.farm_results, pts, *args, **kwargs)
|
|
96
|
+
|
|
97
|
+
if states_mean:
|
|
98
|
+
weights = self.farm_results[FV.WEIGHT].to_numpy()[:, weight_turbine]
|
|
99
|
+
pres = Dataset(
|
|
100
|
+
data_vars={
|
|
101
|
+
v: np.einsum('s,sp->p', weights, pres[v].to_numpy())
|
|
102
|
+
for v in pres.data_vars.keys()
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
vrs = list(pres.data_vars.keys()) if write_vars is None else write_vars
|
|
107
|
+
if to_file is not None:
|
|
108
|
+
if states_mean:
|
|
109
|
+
if p_has_s:
|
|
110
|
+
points = np.einsum('s,spd->pd', weights, points)
|
|
111
|
+
dvars = {
|
|
112
|
+
"x": ((FC.POINT,), points[..., 0]),
|
|
113
|
+
"y": ((FC.POINT,), points[..., 1]),
|
|
114
|
+
"z": ((FC.POINT,), points[..., 2])
|
|
115
|
+
}
|
|
116
|
+
dvars.update({v: ((FC.POINT,), pres[v].to_numpy())
|
|
117
|
+
for v in vrs})
|
|
118
|
+
ds = Dataset(data_vars=dvars)
|
|
119
|
+
else:
|
|
120
|
+
if p_has_s:
|
|
121
|
+
dvars = {
|
|
122
|
+
"x": ((FC.STATE, FC.POINT), points[..., 0]),
|
|
123
|
+
"y": ((FC.STATE, FC.POINT), points[..., 1]),
|
|
124
|
+
"z": ((FC.STATE, FC.POINT), points[..., 2])
|
|
125
|
+
}
|
|
126
|
+
else:
|
|
127
|
+
dvars = {
|
|
128
|
+
"x": ((FC.POINT,), points[..., 0]),
|
|
129
|
+
"y": ((FC.POINT,), points[..., 1]),
|
|
130
|
+
"z": ((FC.POINT,), points[..., 2])
|
|
131
|
+
}
|
|
132
|
+
dvars.update({v: ((FC.STATE, FC.POINT), pres[v].to_numpy())
|
|
133
|
+
for v in vrs})
|
|
134
|
+
ds = Dataset(
|
|
135
|
+
coords={FC.STATE: pres[FC.STATE].to_numpy()},
|
|
136
|
+
data_vars=dvars
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
fpath = self.get_fpath(to_file)
|
|
140
|
+
write_nc(ds, fpath, **write_pars)
|
|
141
|
+
|
|
142
|
+
return pres
|
|
143
|
+
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import matplotlib.pyplot as plt
|
|
2
2
|
import numpy as np
|
|
3
3
|
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
|
4
|
+
from xarray import Dataset
|
|
4
5
|
|
|
5
6
|
from foxes.utils import wd2uv
|
|
6
7
|
import foxes.variables as FV
|
|
@@ -213,7 +214,6 @@ def calc_point_results(
|
|
|
213
214
|
**kwargs,
|
|
214
215
|
):
|
|
215
216
|
"""
|
|
216
|
-
|
|
217
217
|
Helper function that calculates results at grid points.
|
|
218
218
|
|
|
219
219
|
Parameters
|
|
@@ -593,3 +593,106 @@ def get_grid_yz(
|
|
|
593
593
|
z_pos,
|
|
594
594
|
g_pts.reshape(n_states, n_pts, 3),
|
|
595
595
|
)
|
|
596
|
+
|
|
597
|
+
round_defaults = {v: 4 for v in FV.__dict__.keys() if isinstance(v, str)}
|
|
598
|
+
round_defaults[FV.WD] = 3
|
|
599
|
+
round_defaults[FV.TI] = 6
|
|
600
|
+
round_defaults[FV.RHO] = 6
|
|
601
|
+
round_defaults[FC.XYH] = 3
|
|
602
|
+
round_defaults.update({FV.var2amb[v]: round_defaults[v] for v in FV.var2amb.keys()})
|
|
603
|
+
|
|
604
|
+
def data2xr(
|
|
605
|
+
x_pos,
|
|
606
|
+
y_pos,
|
|
607
|
+
z_pos,
|
|
608
|
+
point_results,
|
|
609
|
+
vars=None,
|
|
610
|
+
round="auto",
|
|
611
|
+
to_file=None,
|
|
612
|
+
complevel=5,
|
|
613
|
+
verbosity=1,
|
|
614
|
+
):
|
|
615
|
+
"""
|
|
616
|
+
Converts the image data to xarray data
|
|
617
|
+
|
|
618
|
+
Parameter
|
|
619
|
+
---------
|
|
620
|
+
x_pos: numpy.ndarray or float
|
|
621
|
+
The x grid positions, shape: (n_x, 3)
|
|
622
|
+
y_pos: numpy.ndarray or float
|
|
623
|
+
The y grid positions, shape: (n_y, 3)
|
|
624
|
+
z_pos: numpy.ndarray or float
|
|
625
|
+
The z grid positions, shape: (n_z, 3)
|
|
626
|
+
point_results: xarray.Dataset
|
|
627
|
+
Results of calc_points
|
|
628
|
+
vars: list of str, optional
|
|
629
|
+
Variable selection, or None for all
|
|
630
|
+
round: dict, optional
|
|
631
|
+
Round variables to given digits, or 'auto'
|
|
632
|
+
for default
|
|
633
|
+
to_file: str, optional
|
|
634
|
+
Write to nc file
|
|
635
|
+
complevel: int
|
|
636
|
+
The compression level
|
|
637
|
+
verbosity: int
|
|
638
|
+
The verbostiy level, 0 = silent
|
|
639
|
+
|
|
640
|
+
Returns
|
|
641
|
+
-------
|
|
642
|
+
ds: xarray.Dataset
|
|
643
|
+
The xarray data object
|
|
644
|
+
|
|
645
|
+
"""
|
|
646
|
+
if round == "auto":
|
|
647
|
+
round = round_defaults
|
|
648
|
+
if round is not None:
|
|
649
|
+
x_pos = np.round(x_pos, round[FC.XYH])
|
|
650
|
+
y_pos = np.round(y_pos, round[FC.XYH])
|
|
651
|
+
z_pos = np.round(z_pos, round[FC.XYH])
|
|
652
|
+
|
|
653
|
+
if vars is None:
|
|
654
|
+
vars = list(point_results.data_vars.keys())
|
|
655
|
+
data = {}
|
|
656
|
+
for v in vars:
|
|
657
|
+
data[v] = point_results[v].to_numpy()
|
|
658
|
+
if v in round:
|
|
659
|
+
data[v] = np.round(data[v], round[v])
|
|
660
|
+
|
|
661
|
+
allc = [x_pos, y_pos, z_pos]
|
|
662
|
+
allcn = ["x", "y", "z"]
|
|
663
|
+
ci = [i for i, x in enumerate(allc) if isinstance(x, np.ndarray)]
|
|
664
|
+
cj = [i for i in range(3) if i not in ci][0]
|
|
665
|
+
cl = list(reversed([len(allc[i]) for i in ci]))
|
|
666
|
+
cn = list(reversed([allcn[i] for i in ci]))
|
|
667
|
+
|
|
668
|
+
coords = {}
|
|
669
|
+
attrs = {allcn[cj]: allc[cj].to_numpy()}
|
|
670
|
+
if FC.STATE in point_results.coords:
|
|
671
|
+
if point_results.dims[FC.STATE] > 1:
|
|
672
|
+
coords[FC.STATE] = point_results[FC.STATE].to_numpy()
|
|
673
|
+
else:
|
|
674
|
+
attrs[FC.STATE] = str(point_results[FC.STATE][0].to_numpy())
|
|
675
|
+
coords.update({
|
|
676
|
+
allcn[i]: allc[i] for i in reversed(ci)
|
|
677
|
+
})
|
|
678
|
+
|
|
679
|
+
dvars = {}
|
|
680
|
+
for v, d in data.items():
|
|
681
|
+
if len(d.shape) == 1:
|
|
682
|
+
dvars[v] = (cn, np.swapaxes(d.reshape(*cl), 0, 1))
|
|
683
|
+
else:
|
|
684
|
+
dvars[v] = ([FC.STATE] + cn, np.swapaxes(d.reshape(d.shape[0], *cl), 1, 2))
|
|
685
|
+
|
|
686
|
+
ds = Dataset(
|
|
687
|
+
coords=coords,
|
|
688
|
+
data_vars=dvars,
|
|
689
|
+
attrs=attrs
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
if to_file is not None:
|
|
693
|
+
if verbosity > 0:
|
|
694
|
+
print("Writing file", to_file)
|
|
695
|
+
enc = {k: {"zlib": True, "complevel": complevel} for k in ds.data_vars}
|
|
696
|
+
ds.to_netcdf(to_file, encoding=enc)
|
|
697
|
+
|
|
698
|
+
return ds
|