h2lib 0.0.3__cp39-cp39-win_amd64.whl → 13.0.705__cp39-cp39-win_amd64.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.
h2lib/HAWC2Lib.dll ADDED
Binary file
h2lib/__init__.py ADDED
@@ -0,0 +1,15 @@
1
+ import sys
2
+ import os
3
+ from ._h2lib import H2Lib, MultiH2Lib
4
+ from ._version import __version__, h2lib_version, hawc2_version
5
+ # try:
6
+ # from ._version import __version__
7
+ # if __version__ == 'unknown':
8
+ # f = os.path.abspath(os.path.dirname(__file__) + '/../../update_version.py')
9
+ # if os.path.isfile(f):
10
+ # os.system(f'{sys.executable} {f}')
11
+ # import importlib
12
+ # importlib.reload(_version)
13
+ # from ._version import __version__, h2lib_version, hawc2_version
14
+ # except BaseException:
15
+ # pass
h2lib/_h2lib.py ADDED
@@ -0,0 +1,346 @@
1
+ from contextlib import contextmanager
2
+ from h2lib.dll_wrapper import DLLWrapper
3
+ from h2lib.h2lib_signatures import H2LibSignatures
4
+ import os
5
+ import sys
6
+
7
+ from multiclass_interface.multiprocess_interface import MultiProcessClassInterface, ProcessClass
8
+ import numpy as np
9
+
10
+
11
+ def H2Lib(suppress_output=False, subprocess=True):
12
+ H2 = [H2LibThread, H2LibProcess][subprocess]
13
+ return H2(suppress_output=suppress_output)
14
+
15
+
16
+ class H2LibThread(H2LibSignatures, DLLWrapper):
17
+ _model_path = '.'
18
+ _aero_sections_data_shape = {}
19
+
20
+ def __init__(self, suppress_output=True, filename=None, cwd='.'):
21
+ if filename is None:
22
+ if os.name == 'nt':
23
+ filename = os.path.dirname(__file__) + '/HAWC2Lib.dll'
24
+ else:
25
+ filename = os.path.dirname(__file__) + '/HAWC2Lib.so' # pragma: no cover
26
+ # doubles the speed of single instances and 2N of N instances on linux
27
+ os.environ['MKL_THREADING_LAYER'] = 'sequential'
28
+ filename = os.path.abspath(filename)
29
+ library_bin = os.path.abspath(os.path.join(os.path.dirname(sys.executable), '../Library/bin'))
30
+ if os.path.isdir(library_bin): # pragma: no cover
31
+ os.add_dll_directory(library_bin)
32
+ DLLWrapper.__init__(self, filename, cwd=cwd, cdecl=True)
33
+ self.suppress_output = suppress_output
34
+ self._initialized = False
35
+ self.time = 0
36
+
37
+ @property
38
+ def model_path(self):
39
+ return self._model_path
40
+
41
+ def __enter__(self):
42
+ return self
43
+
44
+ def __exit__(self, exc_type, exc_val, exc_tb):
45
+ self.close()
46
+
47
+ def close(self):
48
+ if self._initialized:
49
+ self.finalize()
50
+ DLLWrapper.close(self)
51
+ return "closed h2lib"
52
+
53
+ def getState(self):
54
+ return H2LibSignatures.getState(self, restype=np.int32)[1]
55
+
56
+ def work(self, time):
57
+ """Return number of loops"""
58
+ return H2LibSignatures.work(self, np.float64(time), restype=np.int64)[1]
59
+
60
+ def loop(self, N):
61
+ """Return time to compute N loops"""
62
+ return H2LibSignatures.loop(self, int(N), restype=np.float64)[1]
63
+
64
+ def get_version(self):
65
+ s = " " * 255
66
+ return H2LibSignatures.get_version(self, s)[0][0].strip()
67
+
68
+ def get_wind_speed(self, pos_g):
69
+ return self.get_lib_function('get_wind_speed')(np.asarray(pos_g, dtype=np.float64),
70
+ np.asarray([0, 0, 0], dtype=np.float64))[0][1]
71
+
72
+ def get_uvw(self, pos_g):
73
+ vx, vy, vz = self.get_wind_speed(pos_g)
74
+ return [vy, vx, -vz]
75
+
76
+ def get_time(self):
77
+ return np.round(H2LibSignatures.get_time(self, time=0.)[0][0], 6)
78
+
79
+ def read_input(self, htc_path='htc/input_hawc.htc', model_path='.'):
80
+ self._model_path = model_path
81
+ self.cwd = self.model_path
82
+ return H2LibSignatures.read_input(self, htc_path)
83
+
84
+ def init(self, htc_path=None, model_path='.'):
85
+ assert not hasattr(self, '_init_result'), "init called twice"
86
+ if htc_path is not None:
87
+ self.read_input(htc_path, model_path)
88
+ r = H2LibSignatures.init(self)
89
+ self._initialized = True
90
+ return r
91
+
92
+ def step(self):
93
+ self.time = np.round(H2LibSignatures.step(self, restype=np.float64)[1], 6)
94
+ return self.time
95
+
96
+ def run(self, time):
97
+ self.time = np.round(H2LibSignatures.run(self, np.float64(time), restype=np.float64)[1], 6)
98
+ return self.time
99
+
100
+ def add_sensor(self, sensor_line):
101
+ """Add sensor to hawc2. The sensor will be accessible from h2lib but will not show up in the output file of HAWC2
102
+ Note, that some sensors consist of multiple HAWC2 sensors, e.g. "wind free_wind" which has a Vx, Vy and Vz sensors
103
+
104
+ Parameters
105
+ ----------
106
+ Sensor_line : str
107
+ Sensor line as used in the output sections in HAWC2. See How2Hawc2
108
+
109
+ Returns
110
+ -------
111
+ index_lst : list
112
+ List of sensor index(es). These index(es) can be used to call get_sensor_info or get_sensor_values
113
+ """
114
+ if ";" not in sensor_line:
115
+ sensor_line += ";"
116
+ index_start, index_stop = 0, 0
117
+ index_start, index_stop = H2LibSignatures.add_sensor(self, sensor_line.lower(), index_start, index_stop)[0][1:]
118
+ return tuple(range(index_start, index_stop + 1))
119
+
120
+ def get_sensor_info(self, id):
121
+ "return name, unit, description"
122
+ if isinstance(id, tuple):
123
+ return [self.get_sensor_info(i) for i in id]
124
+ return [s[:-1].strip() # remove null termination
125
+ for s in H2LibSignatures.get_sensor_info(self, id, name=" " * 30, unit=" " * 10, desc=" " * 512)[0][1:]]
126
+
127
+ def get_sensor_values(self, id_lst):
128
+ """Get sensor values from HAWC2
129
+
130
+ Parameters
131
+ ----------
132
+ id_lst : array_like or int
133
+ list of sensor ids
134
+
135
+ Returns
136
+ -------
137
+ values : array_like or float
138
+ """
139
+ if isinstance(id_lst, int):
140
+ return self.get_sensor_values([id_lst])[0]
141
+ values = np.zeros(len(id_lst), dtype=np.float64)
142
+ id_lst = np.array(id_lst, dtype=np.int64)
143
+ return H2LibSignatures.get_sensor_values(self, id_lst, values, len(id_lst))[0][1]
144
+
145
+ def set_variable_sensor_value(self, id, value):
146
+ return H2LibSignatures.set_variable_sensor_value(self, id, np.float64(value))
147
+
148
+ def init_windfield(self, Nxyz, dxyz, box_offset_yz, transport_speed):
149
+ """Initialize wind field which afterwards can be set using set_windfield
150
+
151
+
152
+ x: direction of wind
153
+ y: horizontal to the left when looking along x
154
+ z: vertical up
155
+
156
+ Parameters
157
+ ----------
158
+ Nxyz : (int, int, int)
159
+ Number of points in wind field
160
+ dxyz : (float, float, float)
161
+ Distance between wind field points
162
+ box_offset_yz : (float, float)
163
+ Box offset in y and z, relative to hawc2 origo. Note this is in met coordinates as described above
164
+ To set a wind field of size 200x80x80, such that the center is located at hawc2 coordinate (0,0,-70),
165
+ box_offset_yz must be (-40,30)
166
+ Note that the wind field size is (Nxyz)-1*dxyz
167
+ transport_speed : float
168
+ Box transport speed
169
+
170
+ Notes
171
+ -----
172
+ The wind field will be transported in the hawc2 global y-direction with the transport speed,
173
+ In HAWC2:
174
+ - shear format is set to 0 (which also means that the mean wind (transport speed) is not added)
175
+ - turbformat is set to 1 (mann), but the buffer should be filled manually via set_windfield
176
+ - center_pos0 is set such that the lower right corner (when looking along global y) is located at box_offset_yz
177
+ - windfield_rotations is set to (0,0,0), i.e. the wind is aligned with y, and w points up (opposite global z)
178
+ - scaling is disabled
179
+ - the buffer is interpolated in the standard way, i.e. it is mirrored in the lateral and vertical direction and
180
+ repeated in the longitudinal direction
181
+
182
+ """
183
+ return H2LibSignatures.init_windfield(self, np.array(Nxyz, dtype=np.int64), np.array(dxyz, dtype=np.float64),
184
+ np.array(box_offset_yz, dtype=np.float64), np.float64(transport_speed))
185
+
186
+ def set_windfield(self, uvw, box_offset_x, time=None):
187
+ """Set wind field, must be called after init_windfield and init
188
+
189
+ Parameters
190
+ ----------
191
+ uvw : array_like, dims=(3,Nx,Ny,Nz)
192
+ wind field components including mean wind speed, shear etc.
193
+ box_offset_x : float
194
+ Offset in x direction at the <time>
195
+ To set a wind field of size 200x80x80, such that the front plane (largest x) is located
196
+ at hawc2 coordinate (0,20,-70), i.e. 20m downstream of origo, set box_offset_x=-180
197
+ Note that the wind field size is (Nxyz)-1*dxyz
198
+ Note also that the end plane (x=0) will be located in -180 and repeated in 20+dx
199
+ time : float, optional
200
+ Time at which the the last plane (x=0) is at x=box_offset_x
201
+ If None, default, time is set to the current time in HAWC2
202
+
203
+ Notes
204
+ -----
205
+ uvw must be scaled in advance to the right turbulence level
206
+ and should contain mean wind, shear, gusts, direction change etc.
207
+ and uvw(:,1) is the back plane of the turbulence box, while uvw(:,Nx) is the front plane
208
+ """
209
+ if time is None:
210
+ time = self.get_time()
211
+ return H2LibSignatures.set_windfield(self, np.asarray(uvw, dtype=np.float32),
212
+ np.float64(box_offset_x), np.float64(time))
213
+
214
+ # ===================================================================================================================
215
+ # H2rotor
216
+ # ===================================================================================================================
217
+
218
+ def get_rotor_dims(self):
219
+ return [[self.get_nSections(r, b) for b in range(self.get_nblades(r))]
220
+ for r in range(self.get_nrotors())]
221
+
222
+ def get_nrotors(self):
223
+ return H2LibSignatures.get_nrotors(self, restype=np.int64)[1]
224
+
225
+ def get_nblades(self, rotor=0):
226
+ return H2LibSignatures.get_nblades(self, rotor + 1, restype=np.int64)[1]
227
+
228
+ def get_nSections(self, rotor=0, blade=0):
229
+ return H2LibSignatures.get_nSections(self, rotor + 1, blade + 1, restype=np.int64)[1]
230
+
231
+ def get_diameter(self, rotor=0):
232
+ return H2LibSignatures.get_diameter(self, rotor + 1, restype=np.float64)[1]
233
+
234
+ def aero_sections_data_shape(self, rotor):
235
+ if rotor not in self._aero_sections_data_shape:
236
+ self._aero_sections_data_shape[rotor] = (self.get_nblades(rotor), self.get_nSections(rotor), 3)
237
+ return self._aero_sections_data_shape[rotor]
238
+
239
+ def get_aerosections_position(self, rotor=0):
240
+ position = np.zeros(self.aero_sections_data_shape(rotor), dtype=np.float64, order='F')
241
+ return H2LibSignatures.get_aerosections_position(self, rotor + 1, position)[0][1]
242
+
243
+ def set_aerosections_windspeed(self, uvw, rotor=0):
244
+ return H2LibSignatures.set_aerosections_windspeed(self, rotor + 1, uvw)
245
+
246
+ def get_aerosections_forces(self, rotor=0):
247
+ shape = self.aero_sections_data_shape(rotor)
248
+ Fxyz = np.zeros(shape, dtype=np.float64, order='F')
249
+ return H2LibSignatures.get_aerosections_forces(self, rotor + 1, Fxyz)[0][1]
250
+
251
+ def get_aerosections_moments(self, rotor=0):
252
+ shape = self.aero_sections_data_shape(rotor)
253
+ Mxyz = np.zeros(shape, dtype=np.float64, order='F')
254
+ return H2LibSignatures.get_aerosections_moments(self, rotor + 1, Mxyz)[0][1]
255
+
256
+ def get_bem_grid_dim(self, rotor=0):
257
+ """returns (nazi, nrad)"""
258
+ return H2LibSignatures.get_bem_grid_dim(self, rotor + 1, 0, 0)[0][1:]
259
+
260
+ def get_bem_grid(self, rotor=0):
261
+ """returns azi, rad"""
262
+ nazi, nrad = self.get_bem_grid_dim(rotor)
263
+ return H2LibSignatures.get_bem_grid(self, rotor + 1,
264
+ np.zeros(nazi, dtype=np.float64, order='F'),
265
+ np.zeros(nrad, dtype=np.float64, order='F'))[0][1:]
266
+
267
+ def get_induction_polargrid(self, rotor=0):
268
+ nazi, nrad = self.get_bem_grid_dim(rotor)
269
+ induction = np.zeros((nazi, nrad), dtype=np.float64, order='F')
270
+ return H2LibSignatures.get_induction_polargrid(self, rotor + 1, induction)[0][1]
271
+
272
+ def get_induction_axisymmetric(self, rotor=0):
273
+ nrad = self.get_bem_grid_dim(rotor)[1]
274
+ induction = np.zeros(nrad, dtype=np.float64)
275
+ return H2LibSignatures.get_induction_axisymmetric(self, rotor + 1, induction)[0][1]
276
+
277
+ def get_induction_rotoravg(self, rotor=0):
278
+ induction = np.float64(0)
279
+ return H2LibSignatures.get_induction_rotoravg(self, rotor + 1, induction)[0][1]
280
+
281
+ def get_rotor_orientation(self, rotor=0, deg=False):
282
+ """return yaw, tilt, azi(of first blade) in rad(default) or deg"""
283
+ r = H2LibSignatures.get_rotor_orientation(self, rotor=rotor + 1, yaw=0., tilt=0., azi=0.)[0][1:]
284
+ if deg:
285
+ return np.rad2deg(r)
286
+ else:
287
+ return r
288
+
289
+ def get_rotor_position(self, rotor=0):
290
+ return H2LibSignatures.get_rotor_position(self, rotor=rotor + 1, position=np.zeros(3, dtype=np.float64))[0][1]
291
+
292
+ def get_rotor_avg_wsp(self, coo=1, rotor=0):
293
+ """Returns the rotor averaged wind speed in global(coo=1, default) or rotor(coo=2) coordinates."""
294
+ assert self.time > 0
295
+ wsp = np.zeros(3, dtype=np.float64)
296
+ return H2LibSignatures.get_rotor_avg_wsp(self, coo=coo, rotor=rotor + 1, wsp=wsp)[0][2]
297
+
298
+ def get_rotor_avg_uvw(self, rotor=0):
299
+ vx, vy, vz = self.get_rotor_avg_wsp(1, rotor)
300
+ return [vy, vx, -vz]
301
+
302
+
303
+ @contextmanager
304
+ def set_LD_LIBRARY_PATH():
305
+ _file__ = np.__file__
306
+ old = os.environ.get('LD_LIBRARY_PATH', "")
307
+
308
+ if '/lib/' in _file__: # pragma: no cover (only on linux)
309
+ lib_path = _file__[:_file__.index("/lib/") + 5]
310
+ os.environ['LD_LIBRARY_PATH'] = f'{lib_path}:{old}'
311
+
312
+ try:
313
+ yield
314
+ finally:
315
+ os.environ['LD_LIBRARY_PATH'] = old
316
+
317
+
318
+ class H2LibProcess(ProcessClass, H2LibThread):
319
+ def __init__(self, suppress_output, filename=None, cwd='.'):
320
+ with set_LD_LIBRARY_PATH():
321
+ ProcessClass.__init__(self, cls=H2LibThread, cls_attrs=set(dir(H2LibThread)) - set(dir(ProcessClass)))
322
+ self(suppress_output=suppress_output, filename=filename, cwd=cwd)
323
+
324
+
325
+ def MultiH2Lib(N, filename=None, cwd='.', suppress_output=False):
326
+
327
+ if not hasattr(suppress_output, '__len__'):
328
+ suppress_output = [suppress_output] * N
329
+ args = [(suppress_output[i], filename, cwd) for i in range(N)]
330
+
331
+ with set_LD_LIBRARY_PATH():
332
+ from multiclass_interface import mpi_interface
333
+ if mpi_interface.size > 1: # pragma: no cover
334
+ # try:
335
+ # with H2LibThread(filename):
336
+ # pass
337
+ # # LD_LIBRARY_PATH is set. Run H2LibThread directly in mpi processes
338
+ # cls = H2LibThread
339
+ # except OSError:
340
+ # # Set LD_LIBRARY_PATH in mpi workers and run H2LibThread from the workers via ProcessClass
341
+ # cls = H2LibProcess
342
+ from multiclass_interface.mpi_interface import MPIClassInterface
343
+ cls = H2LibProcess
344
+ return MPIClassInterface(cls, args)
345
+ else:
346
+ return MultiProcessClassInterface(H2LibThread, args)
h2lib/_version.py ADDED
@@ -0,0 +1,4 @@
1
+ # This file is autogenerated and should not be modified manually
2
+ __version__ = '13.0.705'
3
+ h2lib_version = '13.0.705'
4
+ hawc2_version = '13.0.9'