h2lib 13.0.604__cp38-cp38-win_amd64.whl → 13.0.705__cp38-cp38-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 CHANGED
Binary file
h2lib/_h2lib.py CHANGED
@@ -1,42 +1,34 @@
1
- import os
2
- import numpy as np
1
+ from contextlib import contextmanager
3
2
  from h2lib.dll_wrapper import DLLWrapper
4
3
  from h2lib.h2lib_signatures import H2LibSignatures
5
- from h2lib.utils import MultiProcessInterface, ProcessClass
6
- from contextlib import contextmanager
7
-
4
+ import os
5
+ import sys
8
6
 
9
- @contextmanager
10
- def set_LD_LIBRARY_PATH():
11
- old = os.environ.get('LD_LIBRARY_PATH', "")
12
- if '/lib/' in __file__: # pragma: no cover (only on linux)
13
- lib_path = __file__[:__file__.index("/lib/") + 5]
14
- os.environ['LD_LIBRARY_PATH'] = f'{lib_path}:{old}'
15
- try:
16
- yield
17
- finally:
18
- os.environ['LD_LIBRARY_PATH'] = old
7
+ from multiclass_interface.multiprocess_interface import MultiProcessClassInterface, ProcessClass
8
+ import numpy as np
19
9
 
20
10
 
21
11
  def H2Lib(suppress_output=False, subprocess=True):
22
- if subprocess:
23
- with set_LD_LIBRARY_PATH():
24
- return H2LibProcess(suppress_output=suppress_output)
25
- else:
26
- return H2LibThread(suppress_output=suppress_output)
12
+ H2 = [H2LibThread, H2LibProcess][subprocess]
13
+ return H2(suppress_output=suppress_output)
27
14
 
28
15
 
29
16
  class H2LibThread(H2LibSignatures, DLLWrapper):
30
17
  _model_path = '.'
31
18
  _aero_sections_data_shape = {}
32
19
 
33
- def __init__(self, filename=None, cwd='.', suppress_output=True):
20
+ def __init__(self, suppress_output=True, filename=None, cwd='.'):
34
21
  if filename is None:
35
22
  if os.name == 'nt':
36
23
  filename = os.path.dirname(__file__) + '/HAWC2Lib.dll'
37
24
  else:
38
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'
39
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)
40
32
  DLLWrapper.__init__(self, filename, cwd=cwd, cdecl=True)
41
33
  self.suppress_output = suppress_output
42
34
  self._initialized = False
@@ -46,23 +38,32 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
46
38
  def model_path(self):
47
39
  return self._model_path
48
40
 
49
- # def __enter__(self):
50
- # return self
51
- #
52
- # def __exit__(self, exc_type, exc_val, exc_tb):
53
- # self.close()
41
+ def __enter__(self):
42
+ return self
43
+
44
+ def __exit__(self, exc_type, exc_val, exc_tb):
45
+ self.close()
54
46
 
55
47
  def close(self):
56
48
  if self._initialized:
57
49
  self.finalize()
58
50
  DLLWrapper.close(self)
51
+ return "closed h2lib"
59
52
 
60
53
  def getState(self):
61
54
  return H2LibSignatures.getState(self, restype=np.int32)[1]
62
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
+
63
64
  def get_version(self):
64
65
  s = " " * 255
65
- return H2LibSignatures.get_version(self, s)[0][0]
66
+ return H2LibSignatures.get_version(self, s)[0][0].strip()
66
67
 
67
68
  def get_wind_speed(self, pos_g):
68
69
  return self.get_lib_function('get_wind_speed')(np.asarray(pos_g, dtype=np.float64),
@@ -97,17 +98,49 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
97
98
  return self.time
98
99
 
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
+ """
100
114
  if ";" not in sensor_line:
101
115
  sensor_line += ";"
102
- return H2LibSignatures.add_sensor(self, sensor_line, restype=np.int64)[1]
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))
103
119
 
104
120
  def get_sensor_info(self, id):
105
121
  "return name, unit, description"
122
+ if isinstance(id, tuple):
123
+ return [self.get_sensor_info(i) for i in id]
106
124
  return [s[:-1].strip() # remove null termination
107
125
  for s in H2LibSignatures.get_sensor_info(self, id, name=" " * 30, unit=" " * 10, desc=" " * 512)[0][1:]]
108
126
 
109
- def get_sensor_value(self, id):
110
- return H2LibSignatures.get_sensor_value(self, id, restype=np.float64)[1]
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]
111
144
 
112
145
  def set_variable_sensor_value(self, id, value):
113
146
  return H2LibSignatures.set_variable_sensor_value(self, id, np.float64(value))
@@ -175,7 +208,7 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
175
208
  """
176
209
  if time is None:
177
210
  time = self.get_time()
178
- return H2LibSignatures.set_windfield(self, np.asarray(uvw, dtype=np.float64),
211
+ return H2LibSignatures.set_windfield(self, np.asarray(uvw, dtype=np.float32),
179
212
  np.float64(box_offset_x), np.float64(time))
180
213
 
181
214
  # ===================================================================================================================
@@ -199,12 +232,12 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
199
232
  return H2LibSignatures.get_diameter(self, rotor + 1, restype=np.float64)[1]
200
233
 
201
234
  def aero_sections_data_shape(self, rotor):
202
- if not rotor in self._aero_sections_data_shape:
235
+ if rotor not in self._aero_sections_data_shape:
203
236
  self._aero_sections_data_shape[rotor] = (self.get_nblades(rotor), self.get_nSections(rotor), 3)
204
237
  return self._aero_sections_data_shape[rotor]
205
238
 
206
239
  def get_aerosections_position(self, rotor=0):
207
- position = np.zeros(self.aero_sections_data_shape(rotor), dtype=np.float64)
240
+ position = np.zeros(self.aero_sections_data_shape(rotor), dtype=np.float64, order='F')
208
241
  return H2LibSignatures.get_aerosections_position(self, rotor + 1, position)[0][1]
209
242
 
210
243
  def set_aerosections_windspeed(self, uvw, rotor=0):
@@ -212,12 +245,12 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
212
245
 
213
246
  def get_aerosections_forces(self, rotor=0):
214
247
  shape = self.aero_sections_data_shape(rotor)
215
- Fxyz = np.zeros(shape, dtype=np.float64)
248
+ Fxyz = np.zeros(shape, dtype=np.float64, order='F')
216
249
  return H2LibSignatures.get_aerosections_forces(self, rotor + 1, Fxyz)[0][1]
217
250
 
218
251
  def get_aerosections_moments(self, rotor=0):
219
252
  shape = self.aero_sections_data_shape(rotor)
220
- Mxyz = np.zeros(shape, dtype=np.float64)
253
+ Mxyz = np.zeros(shape, dtype=np.float64, order='F')
221
254
  return H2LibSignatures.get_aerosections_moments(self, rotor + 1, Mxyz)[0][1]
222
255
 
223
256
  def get_bem_grid_dim(self, rotor=0):
@@ -228,11 +261,12 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
228
261
  """returns azi, rad"""
229
262
  nazi, nrad = self.get_bem_grid_dim(rotor)
230
263
  return H2LibSignatures.get_bem_grid(self, rotor + 1,
231
- np.zeros(nazi, dtype=np.float64), np.zeros(nrad, dtype=np.float64))[0][1:]
264
+ np.zeros(nazi, dtype=np.float64, order='F'),
265
+ np.zeros(nrad, dtype=np.float64, order='F'))[0][1:]
232
266
 
233
267
  def get_induction_polargrid(self, rotor=0):
234
268
  nazi, nrad = self.get_bem_grid_dim(rotor)
235
- induction = np.zeros((nazi, nrad), dtype=np.float64)
269
+ induction = np.zeros((nazi, nrad), dtype=np.float64, order='F')
236
270
  return H2LibSignatures.get_induction_polargrid(self, rotor + 1, induction)[0][1]
237
271
 
238
272
  def get_induction_axisymmetric(self, rotor=0):
@@ -240,6 +274,10 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
240
274
  induction = np.zeros(nrad, dtype=np.float64)
241
275
  return H2LibSignatures.get_induction_axisymmetric(self, rotor + 1, induction)[0][1]
242
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
+
243
281
  def get_rotor_orientation(self, rotor=0, deg=False):
244
282
  """return yaw, tilt, azi(of first blade) in rad(default) or deg"""
245
283
  r = H2LibSignatures.get_rotor_orientation(self, rotor=rotor + 1, yaw=0., tilt=0., azi=0.)[0][1:]
@@ -262,15 +300,47 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
262
300
  return [vy, vx, -vz]
263
301
 
264
302
 
265
- class H2LibProcess(ProcessClass, H2LibThread):
266
- def __init__(self, suppress_output):
267
- ProcessClass.__init__(self, cls=H2LibThread, cls_attrs=set(dir(H2LibThread)) - set(dir(ProcessClass)))
268
- self(suppress_output=suppress_output)
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
269
316
 
270
317
 
271
- class MultiH2Lib(MultiProcessInterface, H2LibThread):
272
- def __init__(self, N, filename=None, cwd='.', suppress_output=False):
273
- if not hasattr(suppress_output, '__len__'):
274
- suppress_output = [suppress_output] * N
318
+ class H2LibProcess(ProcessClass, H2LibThread):
319
+ def __init__(self, suppress_output, filename=None, cwd='.'):
275
320
  with set_LD_LIBRARY_PATH():
276
- MultiProcessInterface.__init__(self, H2LibThread, [(filename, cwd, suppress_output[i]) for i in range(N)])
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 CHANGED
@@ -1,4 +1,4 @@
1
1
  # This file is autogenerated and should not be modified manually
2
- __version__ = '13.0.604'
3
- h2lib_version = '13.0.604'
4
- hawc2_version = '13.0.6+5-g438f4c5'
2
+ __version__ = '13.0.705'
3
+ h2lib_version = '13.0.705'
4
+ hawc2_version = '13.0.9'
h2lib/dll_wrapper.py CHANGED
@@ -6,9 +6,7 @@ import platform
6
6
  import os
7
7
  import ctypes
8
8
  from _ctypes import POINTER
9
- from ctypes import c_int, c_double, c_char, c_char_p, c_long
10
- import tempfile
11
- import shutil
9
+ from ctypes import c_int, c_double, c_char, c_char_p, c_long, c_longlong
12
10
  from contextlib import contextmanager
13
11
  try:
14
12
  from ctypes import windll
@@ -21,6 +19,7 @@ c_int_p = POINTER(ctypes.c_long)
21
19
  c_long_p = POINTER(ctypes.c_longlong)
22
20
 
23
21
  c_double_p = POINTER(ctypes.c_double)
22
+ c_float_p = POINTER(ctypes.c_float)
24
23
 
25
24
  in_use = []
26
25
 
@@ -70,17 +69,88 @@ def cwd(f):
70
69
  return wrap
71
70
 
72
71
 
72
+ def wrap(self, f, *args, **kwargs):
73
+ c_args = []
74
+ args = list(args)
75
+ for i, arg in enumerate(args):
76
+ if isinstance(arg, (list, tuple)):
77
+ if all([isinstance(e, int) for e in arg]):
78
+ # default to int64 which is default on linux but not windows
79
+ args[i] = np.array(arg, dtype=np.int64)
80
+ else:
81
+ args[i] = np.array(arg)
82
+ if isinstance(args[i], np.ndarray):
83
+
84
+ if self.fortran:
85
+ if not args[i].flags.f_contiguous:
86
+ sys.stderr.write(f'argument {i} for {f.__name__} not f_contiguous\n')
87
+ else:
88
+ if not args[i].flags.c_contiguous:
89
+ sys.stderr.write(f'argument {i} for {f.__name__} not c_contiguous\n')
90
+
91
+ args[i] = np.require(args[i], requirements=['C', 'F'][self.fortran])
92
+
93
+ for arg in args:
94
+ if isinstance(arg, int):
95
+ c_args.append(c_long_p(c_longlong(arg)))
96
+ elif isinstance(arg, float):
97
+ c_args.append(c_double_p(c_double(arg)))
98
+ elif isinstance(arg, str):
99
+ c_args.append(c_char_p(arg.encode('cp1252')))
100
+ # c_args.append(c_int_p(c_int(len(arg))))
101
+
102
+ elif isinstance(arg, np.ndarray):
103
+ if arg.dtype in [np.int32]:
104
+ c_args.append(arg.ctypes.data_as(c_int_p))
105
+ elif arg.dtype in [np.int64]:
106
+ c_args.append(arg.ctypes.data_as(c_long_p))
107
+ elif arg.dtype == np.float64:
108
+ c_args.append(arg.ctypes.data_as(c_double_p))
109
+ elif arg.dtype == np.float32:
110
+ c_args.append(arg.ctypes.data_as(c_float_p))
111
+ else:
112
+ raise NotImplementedError(arg.dtype)
113
+
114
+ else:
115
+ # raise NotImplementedError(arg.__class__.__name__)
116
+ c_args.append(arg)
117
+ if 'restype' in kwargs:
118
+ restype = kwargs['restype']
119
+ if hasattr(restype, 'dtype'):
120
+ restype = np.ctypeslib.as_ctypes_type(restype)
121
+ f.restype = restype
122
+ with chdir(self.cwd):
123
+ if self.suppress_output:
124
+ with SuppressStream(sys.stdout), SuppressStream(sys.stderr):
125
+ res = f(*c_args)
126
+ else:
127
+ res = f(*c_args)
128
+ ret_args = []
129
+ for arg in args:
130
+ c_arg = c_args.pop(0)
131
+ if isinstance(arg, (int, float)):
132
+ ret_args.append(c_arg.contents.value)
133
+ elif isinstance(arg, (str)):
134
+ ret_args.append(c_arg.value.decode('cp1252'))
135
+ # c_args.pop(0)
136
+ elif isinstance(arg, np.ndarray):
137
+ ret_args.append(arg)
138
+ else:
139
+ raise NotImplementedError(arg.__class__.__name__)
140
+ return ret_args, res
141
+
142
+
73
143
  class DLLWrapper(object):
74
144
  def __init__(self, filename, cwd='.', cdecl=True, fortran=True):
75
145
  self.filename = str(filename)
76
146
  if os.path.abspath(self.filename) in in_use:
77
147
  raise Exception(f'{os.path.abspath(self.filename)} already in use in current process.')
78
- in_use.append(os.path.abspath(self.filename))
79
148
  self.cwd = cwd
80
149
  self.cdecl = cdecl
81
150
  self.fortran = fortran
82
151
  self.suppress_output = False
83
152
  self.open()
153
+ in_use.append(os.path.abspath(self.filename))
84
154
  atexit.register(self.close)
85
155
 
86
156
  @staticmethod
@@ -124,9 +194,10 @@ class DLLWrapper(object):
124
194
  def open(self):
125
195
  assert os.path.isfile(self.filename), os.path.abspath(self.filename)
126
196
  if self.cdecl:
127
- if tuple(map(int, platform.python_version().split('.'))) < (3, 8):
197
+ try:
198
+ # python < (3, 8) and > 3.10?:
128
199
  self.lib = ct.CDLL(self.filename)
129
- else:
200
+ except BaseException:
130
201
  self.lib = ct.CDLL(self.filename, winmode=ctypes.DEFAULT_MODE)
131
202
  else:
132
203
  self.lib = windll.LoadLibrary(self.filename)
@@ -148,82 +219,17 @@ class DLLWrapper(object):
148
219
  # self.close()
149
220
  # return False
150
221
 
151
- def __getattribute__(self, name):
152
- try:
153
- return object.__getattribute__(self, name)
154
- except AttributeError:
155
- if name == 'lib':
156
- raise Exception("DLL not loaded. Run using: 'with dll: ...'")
157
- return self.get_lib_function(name)
222
+ def __getattr__(self, name):
223
+ if name == 'lib':
224
+ raise Exception("DLL not loaded. Run using: 'with dll: ...'")
225
+ return self.get_lib_function(name)
158
226
 
159
227
  def get_lib_function(self, name):
160
228
  try:
161
229
  f = getattr(self.lib, name)
162
230
  except AttributeError as e:
163
231
  raise AttributeError("Attribute '%s' not found in dll ('%s')" % (name, self.filename))
164
-
165
- def wrap(*args, **kwargs):
166
- c_args = []
167
- args = list(args)
168
- for i, arg in enumerate(args):
169
- if isinstance(arg, (list, tuple)):
170
- if all([isinstance(e, int) for e in arg]):
171
- # default to int64 which is default on linux but not windows
172
- args[i] = np.array(arg, dtype=np.int64)
173
- else:
174
- args[i] = np.array(arg)
175
- if isinstance(args[i], np.ndarray):
176
- if self.fortran:
177
- args[i] = np.asfortranarray(args[i])
178
- else:
179
- args[i] = np.ascontiguousarray(args[i])
180
- for arg in args:
181
- if isinstance(arg, int):
182
- c_args.append(c_int_p(c_int(arg)))
183
- elif isinstance(arg, float):
184
- c_args.append(c_double_p(c_double(arg)))
185
- elif isinstance(arg, str):
186
- c_args.append(c_char_p(arg.encode('cp1252')))
187
- # c_args.append(c_int_p(c_int(len(arg))))
188
-
189
- elif isinstance(arg, np.ndarray):
190
- if arg.dtype in [np.int32]:
191
- c_args.append(arg.ctypes.data_as(c_int_p))
192
- elif arg.dtype in [np.int64]:
193
- c_args.append(arg.ctypes.data_as(c_long_p))
194
- elif arg.dtype == np.float64:
195
- c_args.append(arg.ctypes.data_as(c_double_p))
196
- else:
197
- raise NotImplementedError(arg.dtype)
198
-
199
- else:
200
- # raise NotImplementedError(arg.__class__.__name__)
201
- c_args.append(arg)
202
- if 'restype' in kwargs:
203
- restype = kwargs['restype']
204
- if hasattr(restype, 'dtype'):
205
- restype = np.ctypeslib.as_ctypes_type(restype)
206
- f.restype = restype
207
- with chdir(self.cwd):
208
- if self.suppress_output:
209
- with SuppressStream(sys.stdout), SuppressStream(sys.stderr):
210
- res = f(*c_args)
211
- else:
212
- res = f(*c_args)
213
- ret_args = []
214
- for arg in args:
215
- c_arg = c_args.pop(0)
216
- if isinstance(arg, (int, float)):
217
- ret_args.append(c_arg.contents.value)
218
- elif isinstance(arg, (str)):
219
- ret_args.append(c_arg.value.decode('cp1252'))
220
- # c_args.pop(0)
221
- elif isinstance(arg, np.ndarray):
222
- ret_args.append(arg)
223
- else:
224
- raise NotImplementedError(arg.__class__.__name__)
225
- return ret_args, res
226
- return wrap
232
+ return lambda *args, **kwargs: wrap(self, f, *args, **kwargs)
227
233
 
228
234
  def version(self, function_name='get_version'):
229
235
  try:
@@ -309,7 +315,7 @@ class Type2DllWrapper(DLLWrapper):
309
315
  arg2 = np.zeros(n2, dtype=ct.c_double, order='F')
310
316
 
311
317
  f(arg1, arg2)
312
- return(arg2)
318
+ return arg2
313
319
 
314
320
  def init(self):
315
321
  n1, n2 = self.arraysizes_init