h2lib 13.1.301__cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.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.so 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,347 @@
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.write_output()
50
+ self.finalize()
51
+ DLLWrapper.close(self)
52
+ return "closed h2lib"
53
+
54
+ def getState(self):
55
+ return H2LibSignatures.getState(self, restype=np.int32)[1]
56
+
57
+ def work(self, time):
58
+ """Return number of loops"""
59
+ return H2LibSignatures.work(self, np.float64(time), restype=np.int64)[1]
60
+
61
+ def loop(self, N):
62
+ """Return time to compute N loops"""
63
+ return H2LibSignatures.loop(self, int(N), restype=np.float64)[1]
64
+
65
+ def get_version(self):
66
+ s = " " * 255
67
+ return H2LibSignatures.get_version(self, s)[0][0].strip()
68
+
69
+ def get_wind_speed(self, pos_g):
70
+ return self.get_lib_function('get_wind_speed')(np.asarray(pos_g, dtype=np.float64),
71
+ np.asarray([0, 0, 0], dtype=np.float64))[0][1]
72
+
73
+ def get_uvw(self, pos_g):
74
+ vx, vy, vz = self.get_wind_speed(pos_g)
75
+ return [vy, vx, -vz]
76
+
77
+ def get_time(self):
78
+ return np.round(H2LibSignatures.get_time(self, time=0.)[0][0], 6)
79
+
80
+ def read_input(self, htc_path='htc/input_hawc.htc', model_path='.'):
81
+ self._model_path = model_path
82
+ self.cwd = self.model_path
83
+ return H2LibSignatures.read_input(self, htc_path)
84
+
85
+ def init(self, htc_path=None, model_path='.'):
86
+ assert not hasattr(self, '_init_result'), "init called twice"
87
+ if htc_path is not None:
88
+ self.read_input(htc_path, model_path)
89
+ r = H2LibSignatures.init(self)
90
+ self._initialized = True
91
+ return r
92
+
93
+ def step(self):
94
+ self.time = np.round(H2LibSignatures.step(self, restype=np.float64)[1], 6)
95
+ return self.time
96
+
97
+ def run(self, time):
98
+ self.time = np.round(H2LibSignatures.run(self, np.float64(time), restype=np.float64)[1], 6)
99
+ return self.time
100
+
101
+ def add_sensor(self, sensor_line):
102
+ """Add sensor to hawc2. The sensor will be accessible from h2lib but will not show up in the output file of HAWC2
103
+ Note, that some sensors consist of multiple HAWC2 sensors, e.g. "wind free_wind" which has a Vx, Vy and Vz sensors
104
+
105
+ Parameters
106
+ ----------
107
+ Sensor_line : str
108
+ Sensor line as used in the output sections in HAWC2. See How2Hawc2
109
+
110
+ Returns
111
+ -------
112
+ index_lst : list
113
+ List of sensor index(es). These index(es) can be used to call get_sensor_info or get_sensor_values
114
+ """
115
+ if ";" not in sensor_line:
116
+ sensor_line += ";"
117
+ index_start, index_stop = 0, 0
118
+ index_start, index_stop = H2LibSignatures.add_sensor(self, sensor_line.lower(), index_start, index_stop)[0][1:]
119
+ return tuple(range(index_start, index_stop + 1))
120
+
121
+ def get_sensor_info(self, id):
122
+ "return name, unit, description"
123
+ if isinstance(id, tuple):
124
+ return [self.get_sensor_info(i) for i in id]
125
+ return [s[:-1].strip() # remove null termination
126
+ for s in H2LibSignatures.get_sensor_info(self, id, name=" " * 30, unit=" " * 10, desc=" " * 512)[0][1:]]
127
+
128
+ def get_sensor_values(self, id_lst):
129
+ """Get sensor values from HAWC2
130
+
131
+ Parameters
132
+ ----------
133
+ id_lst : array_like or int
134
+ list of sensor ids
135
+
136
+ Returns
137
+ -------
138
+ values : array_like or float
139
+ """
140
+ if isinstance(id_lst, int):
141
+ return self.get_sensor_values([id_lst])[0]
142
+ values = np.zeros(len(id_lst), dtype=np.float64)
143
+ id_lst = np.array(id_lst, dtype=np.int64)
144
+ return H2LibSignatures.get_sensor_values(self, id_lst, values, len(id_lst))[0][1]
145
+
146
+ def set_variable_sensor_value(self, id, value):
147
+ return H2LibSignatures.set_variable_sensor_value(self, id, np.float64(value))
148
+
149
+ def init_windfield(self, Nxyz, dxyz, box_offset_yz, transport_speed):
150
+ """Initialize wind field which afterwards can be set using set_windfield
151
+
152
+
153
+ x: direction of wind
154
+ y: horizontal to the left when looking along x
155
+ z: vertical up
156
+
157
+ Parameters
158
+ ----------
159
+ Nxyz : (int, int, int)
160
+ Number of points in wind field
161
+ dxyz : (float, float, float)
162
+ Distance between wind field points
163
+ box_offset_yz : (float, float)
164
+ Box offset in y and z, relative to hawc2 origo. Note this is in met coordinates as described above
165
+ To set a wind field of size 200x80x80, such that the center is located at hawc2 coordinate (0,0,-70),
166
+ box_offset_yz must be (-40,30)
167
+ Note that the wind field size is (Nxyz)-1*dxyz
168
+ transport_speed : float
169
+ Box transport speed
170
+
171
+ Notes
172
+ -----
173
+ The wind field will be transported in the hawc2 global y-direction with the transport speed,
174
+ In HAWC2:
175
+ - shear format is set to 0 (which also means that the mean wind (transport speed) is not added)
176
+ - turbformat is set to 1 (mann), but the buffer should be filled manually via set_windfield
177
+ - center_pos0 is set such that the lower right corner (when looking along global y) is located at box_offset_yz
178
+ - windfield_rotations is set to (0,0,0), i.e. the wind is aligned with y, and w points up (opposite global z)
179
+ - scaling is disabled
180
+ - the buffer is interpolated in the standard way, i.e. it is mirrored in the lateral and vertical direction and
181
+ repeated in the longitudinal direction
182
+
183
+ """
184
+ return H2LibSignatures.init_windfield(self, np.array(Nxyz, dtype=np.int64), np.array(dxyz, dtype=np.float64),
185
+ np.array(box_offset_yz, dtype=np.float64), np.float64(transport_speed))
186
+
187
+ def set_windfield(self, uvw, box_offset_x, time=None):
188
+ """Set wind field, must be called after init_windfield and init
189
+
190
+ Parameters
191
+ ----------
192
+ uvw : array_like, dims=(3,Nx,Ny,Nz)
193
+ wind field components including mean wind speed, shear etc.
194
+ box_offset_x : float
195
+ Offset in x direction at the <time>
196
+ To set a wind field of size 200x80x80, such that the front plane (largest x) is located
197
+ at hawc2 coordinate (0,20,-70), i.e. 20m downstream of origo, set box_offset_x=-180
198
+ Note that the wind field size is (Nxyz)-1*dxyz
199
+ Note also that the end plane (x=0) will be located in -180 and repeated in 20+dx
200
+ time : float, optional
201
+ Time at which the the last plane (x=0) is at x=box_offset_x
202
+ If None, default, time is set to the current time in HAWC2
203
+
204
+ Notes
205
+ -----
206
+ uvw must be scaled in advance to the right turbulence level
207
+ and should contain mean wind, shear, gusts, direction change etc.
208
+ and uvw(:,1) is the back plane of the turbulence box, while uvw(:,Nx) is the front plane
209
+ """
210
+ if time is None:
211
+ time = self.get_time()
212
+ return H2LibSignatures.set_windfield(self, np.asarray(uvw, dtype=np.float32),
213
+ np.float64(box_offset_x), np.float64(time))
214
+
215
+ # ===================================================================================================================
216
+ # H2rotor
217
+ # ===================================================================================================================
218
+
219
+ def get_rotor_dims(self):
220
+ return [[self.get_nSections(r, b) for b in range(self.get_nblades(r))]
221
+ for r in range(self.get_nrotors())]
222
+
223
+ def get_nrotors(self):
224
+ return H2LibSignatures.get_nrotors(self, restype=np.int64)[1]
225
+
226
+ def get_nblades(self, rotor=0):
227
+ return H2LibSignatures.get_nblades(self, rotor + 1, restype=np.int64)[1]
228
+
229
+ def get_nSections(self, rotor=0, blade=0):
230
+ return H2LibSignatures.get_nSections(self, rotor + 1, blade + 1, restype=np.int64)[1]
231
+
232
+ def get_diameter(self, rotor=0):
233
+ return H2LibSignatures.get_diameter(self, rotor + 1, restype=np.float64)[1]
234
+
235
+ def aero_sections_data_shape(self, rotor):
236
+ if rotor not in self._aero_sections_data_shape:
237
+ self._aero_sections_data_shape[rotor] = (self.get_nblades(rotor), self.get_nSections(rotor), 3)
238
+ return self._aero_sections_data_shape[rotor]
239
+
240
+ def get_aerosections_position(self, rotor=0):
241
+ position = np.zeros(self.aero_sections_data_shape(rotor), dtype=np.float64, order='F')
242
+ return H2LibSignatures.get_aerosections_position(self, rotor + 1, position)[0][1]
243
+
244
+ def set_aerosections_windspeed(self, uvw, rotor=0):
245
+ return H2LibSignatures.set_aerosections_windspeed(self, rotor + 1, np.asarray(uvw, np.float64))
246
+
247
+ def get_aerosections_forces(self, rotor=0):
248
+ shape = self.aero_sections_data_shape(rotor)
249
+ Fxyz = np.zeros(shape, dtype=np.float64, order='F')
250
+ return H2LibSignatures.get_aerosections_forces(self, rotor + 1, Fxyz)[0][1]
251
+
252
+ def get_aerosections_moments(self, rotor=0):
253
+ shape = self.aero_sections_data_shape(rotor)
254
+ Mxyz = np.zeros(shape, dtype=np.float64, order='F')
255
+ return H2LibSignatures.get_aerosections_moments(self, rotor + 1, Mxyz)[0][1]
256
+
257
+ def get_bem_grid_dim(self, rotor=0):
258
+ """returns (nazi, nrad)"""
259
+ return H2LibSignatures.get_bem_grid_dim(self, rotor + 1, 0, 0)[0][1:]
260
+
261
+ def get_bem_grid(self, rotor=0):
262
+ """returns azi, rad"""
263
+ nazi, nrad = self.get_bem_grid_dim(rotor)
264
+ return H2LibSignatures.get_bem_grid(self, rotor + 1,
265
+ np.zeros(nazi, dtype=np.float64, order='F'),
266
+ np.zeros(nrad, dtype=np.float64, order='F'))[0][1:]
267
+
268
+ def get_induction_polargrid(self, rotor=0):
269
+ nazi, nrad = self.get_bem_grid_dim(rotor)
270
+ induction = np.zeros((nazi, nrad), dtype=np.float64, order='F')
271
+ return H2LibSignatures.get_induction_polargrid(self, rotor + 1, induction)[0][1]
272
+
273
+ def get_induction_axisymmetric(self, rotor=0):
274
+ nrad = self.get_bem_grid_dim(rotor)[1]
275
+ induction = np.zeros(nrad, dtype=np.float64)
276
+ return H2LibSignatures.get_induction_axisymmetric(self, rotor + 1, induction)[0][1]
277
+
278
+ def get_induction_rotoravg(self, rotor=0):
279
+ induction = np.float64(0)
280
+ return H2LibSignatures.get_induction_rotoravg(self, rotor + 1, induction)[0][1]
281
+
282
+ def get_rotor_orientation(self, rotor=0, deg=False):
283
+ """return yaw, tilt, azi(of first blade) in rad(default) or deg"""
284
+ r = H2LibSignatures.get_rotor_orientation(self, rotor=rotor + 1, yaw=0., tilt=0., azi=0.)[0][1:]
285
+ if deg:
286
+ return np.rad2deg(r)
287
+ else:
288
+ return r
289
+
290
+ def get_rotor_position(self, rotor=0):
291
+ return H2LibSignatures.get_rotor_position(self, rotor=rotor + 1, position=np.zeros(3, dtype=np.float64))[0][1]
292
+
293
+ def get_rotor_avg_wsp(self, coo=1, rotor=0):
294
+ """Returns the rotor averaged wind speed in global(coo=1, default) or rotor(coo=2) coordinates."""
295
+ assert self.time > 0
296
+ wsp = np.zeros(3, dtype=np.float64)
297
+ return H2LibSignatures.get_rotor_avg_wsp(self, coo=coo, rotor=rotor + 1, wsp=wsp)[0][2]
298
+
299
+ def get_rotor_avg_uvw(self, rotor=0):
300
+ vx, vy, vz = self.get_rotor_avg_wsp(1, rotor)
301
+ return [vy, vx, -vz]
302
+
303
+
304
+ @contextmanager
305
+ def set_LD_LIBRARY_PATH():
306
+ _file__ = np.__file__
307
+ old = os.environ.get('LD_LIBRARY_PATH', "")
308
+
309
+ if '/lib/' in _file__: # pragma: no cover (only on linux)
310
+ lib_path = _file__[:_file__.index("/lib/") + 5]
311
+ os.environ['LD_LIBRARY_PATH'] = f'{lib_path}:{old}'
312
+
313
+ try:
314
+ yield
315
+ finally:
316
+ os.environ['LD_LIBRARY_PATH'] = old
317
+
318
+
319
+ class H2LibProcess(ProcessClass, H2LibThread):
320
+ def __init__(self, suppress_output, filename=None, cwd='.'):
321
+ with set_LD_LIBRARY_PATH():
322
+ ProcessClass.__init__(self, cls=H2LibThread, cls_attrs=set(dir(H2LibThread)) - set(dir(ProcessClass)))
323
+ self(suppress_output=suppress_output, filename=filename, cwd=cwd)
324
+
325
+
326
+ def MultiH2Lib(N, filename=None, cwd='.', suppress_output=False):
327
+
328
+ if not hasattr(suppress_output, '__len__'):
329
+ suppress_output = [suppress_output] * N
330
+ args = [(suppress_output[i], filename, cwd) for i in range(N)]
331
+
332
+ with set_LD_LIBRARY_PATH():
333
+ from multiclass_interface import mpi_interface
334
+ if mpi_interface.mpi: # pragma: no cover
335
+ # try:
336
+ # with H2LibThread(filename):
337
+ # pass
338
+ # # LD_LIBRARY_PATH is set. Run H2LibThread directly in mpi processes
339
+ # cls = H2LibThread
340
+ # except OSError:
341
+ # # Set LD_LIBRARY_PATH in mpi workers and run H2LibThread from the workers via ProcessClass
342
+ # cls = H2LibProcess
343
+ from multiclass_interface.mpi_interface import MPIClassInterface
344
+ cls = H2LibProcess
345
+ return MPIClassInterface(cls, args)
346
+ else:
347
+ 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.1.301'
3
+ h2lib_version = '13.1.301'
4
+ hawc2_version = '13.1.3'
h2lib/dll_wrapper.py ADDED
@@ -0,0 +1,329 @@
1
+ import numpy as np
2
+ from numpy.ctypeslib import ndpointer
3
+ import ctypes as ct
4
+ import _ctypes
5
+ import platform
6
+ import os
7
+ import ctypes
8
+ from _ctypes import POINTER
9
+ from ctypes import c_int, c_double, c_char, c_char_p, c_long, c_longlong
10
+ from contextlib import contextmanager
11
+ try:
12
+ from ctypes import windll
13
+ except ImportError:
14
+ pass
15
+ import sys
16
+ from pathlib import Path
17
+ import atexit
18
+ c_int_p = POINTER(ctypes.c_long)
19
+ c_long_p = POINTER(ctypes.c_longlong)
20
+
21
+ c_double_p = POINTER(ctypes.c_double)
22
+ c_float_p = POINTER(ctypes.c_float)
23
+
24
+ in_use = []
25
+
26
+
27
+ class SuppressStream(object):
28
+
29
+ def __init__(self, stream=sys.stderr):
30
+ self.orig_stream_fileno = stream.fileno()
31
+ self.stream = stream
32
+
33
+ def __enter__(self):
34
+ # save stream file descriptor
35
+ self.orig_stream_dup = os.dup(self.orig_stream_fileno)
36
+ self.devnull = open(os.devnull, 'w')
37
+ self.stream.flush()
38
+ os.dup2(self.devnull.fileno(), self.orig_stream_fileno)
39
+
40
+ def __exit__(self, type, value, traceback):
41
+ os.close(self.orig_stream_fileno)
42
+ os.dup2(self.orig_stream_dup, self.orig_stream_fileno)
43
+ os.close(self.orig_stream_dup)
44
+ self.devnull.flush()
45
+ self.devnull.close()
46
+
47
+
48
+ def suppress_output(f):
49
+ def wrap(*args, **kwargs):
50
+ if 'verbose' not in kwargs or not kwargs.pop('verbose'):
51
+ with SuppressStream(sys.stdout), SuppressStream(sys.stderr):
52
+ f(*args, **kwargs)
53
+ else:
54
+ f(*args, **kwargs)
55
+ return wrap
56
+
57
+
58
+ @contextmanager
59
+ def chdir(path):
60
+ oldpwd = os.getcwd()
61
+ os.chdir(path)
62
+ try:
63
+ yield
64
+ finally:
65
+ os.chdir(oldpwd)
66
+
67
+
68
+ def cwd(f):
69
+ def wrap(self, *args, **kwargs):
70
+ with chdir(self.model_path):
71
+ f(self, *args, **kwargs)
72
+ return wrap
73
+
74
+
75
+ def wrap(self, f, *args, **kwargs):
76
+ c_args = []
77
+ args = list(args)
78
+ for i, arg in enumerate(args):
79
+ if isinstance(arg, (list, tuple)):
80
+ if all([isinstance(e, int) for e in arg]):
81
+ # default to int64 which is default on linux but not windows
82
+ args[i] = np.array(arg, dtype=np.int64)
83
+ else:
84
+ args[i] = np.array(arg)
85
+ if isinstance(args[i], np.ndarray):
86
+
87
+ if self.fortran:
88
+ if not args[i].flags.f_contiguous:
89
+ sys.stderr.write(f'argument {i} for {f.__name__} not f_contiguous\n')
90
+ else:
91
+ if not args[i].flags.c_contiguous:
92
+ sys.stderr.write(f'argument {i} for {f.__name__} not c_contiguous\n')
93
+
94
+ args[i] = np.require(args[i], requirements=['C', 'F'][self.fortran])
95
+
96
+ for arg in args:
97
+ if isinstance(arg, int):
98
+ c_args.append(c_long_p(c_longlong(arg)))
99
+ elif isinstance(arg, float):
100
+ c_args.append(c_double_p(c_double(arg)))
101
+ elif isinstance(arg, str):
102
+ c_args.append(c_char_p(arg.encode('cp1252')))
103
+ # c_args.append(c_int_p(c_int(len(arg))))
104
+
105
+ elif isinstance(arg, np.ndarray):
106
+ if arg.dtype in [np.int32]:
107
+ c_args.append(arg.ctypes.data_as(c_int_p))
108
+ elif arg.dtype in [np.int64]:
109
+ c_args.append(arg.ctypes.data_as(c_long_p))
110
+ elif arg.dtype == np.float64:
111
+ c_args.append(arg.ctypes.data_as(c_double_p))
112
+ elif arg.dtype == np.float32:
113
+ c_args.append(arg.ctypes.data_as(c_float_p))
114
+ else:
115
+ raise NotImplementedError(arg.dtype)
116
+
117
+ else:
118
+ # raise NotImplementedError(arg.__class__.__name__)
119
+ c_args.append(arg)
120
+ if 'restype' in kwargs:
121
+ restype = kwargs['restype']
122
+ if hasattr(restype, 'dtype'):
123
+ restype = np.ctypeslib.as_ctypes_type(restype)
124
+ f.restype = restype
125
+ with chdir(self.cwd):
126
+ if self.suppress_output:
127
+ with SuppressStream(sys.stdout), SuppressStream(sys.stderr):
128
+ res = f(*c_args)
129
+ else:
130
+ res = f(*c_args)
131
+ ret_args = []
132
+ for arg in args:
133
+ c_arg = c_args.pop(0)
134
+ if isinstance(arg, (int, float)):
135
+ ret_args.append(c_arg.contents.value)
136
+ elif isinstance(arg, (str)):
137
+ ret_args.append(c_arg.value.decode('cp1252'))
138
+ # c_args.pop(0)
139
+ elif isinstance(arg, np.ndarray):
140
+ ret_args.append(arg)
141
+ else:
142
+ raise NotImplementedError(arg.__class__.__name__)
143
+ return ret_args, res
144
+
145
+
146
+ class DLLWrapper(object):
147
+ def __init__(self, filename, cwd='.', cdecl=True, fortran=True):
148
+ self.filename = str(filename)
149
+ if os.path.abspath(self.filename) in in_use:
150
+ raise Exception(f'{os.path.abspath(self.filename)} already in use in current process.')
151
+ self.cwd = cwd
152
+ self.cdecl = cdecl
153
+ self.fortran = fortran
154
+ self.suppress_output = False
155
+ self.open()
156
+ in_use.append(os.path.abspath(self.filename))
157
+ atexit.register(self.close)
158
+
159
+ @staticmethod
160
+ def find_dll(path, name):
161
+ p = Path(path)
162
+
163
+ # if sys.platform == "win32":
164
+ # prefixes = ['']
165
+ # if sys.maxsize > 2**32:
166
+ # suffixes = ['.dll', '_64.dll']
167
+ # else:
168
+ # suffixes = ['.dll']
169
+ # elif sys.platform == 'linux':
170
+ # prefixes = ['lib','']
171
+ # suffixes = ['.so']
172
+ # else:
173
+ # raise NotImplementedError()
174
+
175
+ dll_lst = []
176
+ file_patterns = ['*%s*.dll' % name, '*%s*.so' % name]
177
+ for fp in file_patterns:
178
+ dll_lst.extend(list(p.glob("**/" + fp)))
179
+
180
+ def use_first(dll_lst):
181
+ f = str(dll_lst[0])
182
+ print("Using ", os.path.abspath(f))
183
+ return DLLWrapper(f)
184
+
185
+ if len(dll_lst) == 1:
186
+ return use_first(dll_lst)
187
+ elif len(dll_lst) > 1:
188
+ # check if excluding dlls in hawc2-binary, i.e. "hawc2-<platform>" results in one dll
189
+ dll_lst2 = [d for d in dll_lst if not str(d).startswith('hawc2-')]
190
+ if len(dll_lst2) == 1:
191
+ return use_first(dll_lst2)
192
+ raise FileExistsError("Multiple dlls found:\n" + "\n".join([str(p) for p in dll_lst]))
193
+ else:
194
+ raise FileNotFoundError("No " + " or ".join(file_patterns) +
195
+ " files found in " + os.path.abspath(p.absolute()))
196
+
197
+ def open(self):
198
+ assert os.path.isfile(self.filename), os.path.abspath(self.filename)
199
+ if self.cdecl:
200
+ try:
201
+ # python < (3, 8) and > 3.10?:
202
+ self.lib = ct.CDLL(self.filename)
203
+ except BaseException:
204
+ self.lib = ct.CDLL(self.filename, winmode=ctypes.DEFAULT_MODE)
205
+ else:
206
+ self.lib = windll.LoadLibrary(self.filename)
207
+
208
+ def close(self):
209
+ if "FreeLibrary" in dir(_ctypes):
210
+ _ctypes.FreeLibrary(self.lib._handle)
211
+ else:
212
+ _ctypes.dlclose(self.lib._handle)
213
+ del self.lib
214
+ atexit.unregister(self.close)
215
+ in_use.remove(os.path.abspath(self.filename))
216
+
217
+ # def __enter__(self):
218
+ # self.open()
219
+ # return self
220
+ #
221
+ # def __exit__(self, type, value, traceback):
222
+ # self.close()
223
+ # return False
224
+
225
+ def __getattr__(self, name):
226
+ if name == 'lib':
227
+ raise Exception("DLL not loaded. Run using: 'with dll: ...'")
228
+ return self.get_lib_function(name)
229
+
230
+ def get_lib_function(self, name):
231
+ try:
232
+ f = getattr(self.lib, name)
233
+ except AttributeError as e:
234
+ raise AttributeError("Attribute '%s' not found in dll ('%s')" % (name, self.filename))
235
+ return lambda *args, **kwargs: wrap(self, f, *args, **kwargs)
236
+
237
+ def version(self, function_name='get_version'):
238
+ try:
239
+ f = getattr(self.lib, function_name)
240
+ f.argtypes = [c_char_p, c_long]
241
+ s = "".ljust(255)
242
+ arg = c_char_p(s.encode('utf-8'))
243
+ f(arg, len(s))
244
+ return arg.value.decode().strip()
245
+ except AttributeError:
246
+ if function_name == 'get_version':
247
+ return self.version('version')
248
+
249
+ def getFileProperties(self):
250
+ if sys.platform != "win32":
251
+ raise OSError("Only supported for Windows")
252
+ import win32api
253
+ fname = self.filename
254
+
255
+ # ==============================================================================
256
+ """
257
+ Read all properties of the given file return them as a dictionary.
258
+ """
259
+ propNames = ('Comments', 'InternalName', 'ProductName',
260
+ 'CompanyName', 'LegalCopyright', 'ProductVersion',
261
+ 'FileDescription', 'LegalTrademarks', 'PrivateBuild',
262
+ 'FileVersion', 'OriginalFilename', 'SpecialBuild')
263
+
264
+ props = {'FixedFileInfo': None, 'StringFileInfo': None, 'FileVersion': None}
265
+
266
+ try:
267
+ # backslash as parm returns dictionary of numeric info corresponding to VS_FIXEDFILEINFO struc
268
+ fixedInfo = win32api.GetFileVersionInfo(fname, '\\')
269
+ props['FixedFileInfo'] = fixedInfo
270
+ props['FileVersion'] = "%d.%d.%d.%d" % (fixedInfo['FileVersionMS'] / 65536,
271
+ fixedInfo['FileVersionMS'] % 65536, fixedInfo['FileVersionLS'] / 65536,
272
+ fixedInfo['FileVersionLS'] % 65536)
273
+
274
+ # \VarFileInfo\Translation returns list of available (language, codepage)
275
+ # pairs that can be used to retreive string info. We are using only the first pair.
276
+ lang, codepage = win32api.GetFileVersionInfo(fname, '\\VarFileInfo\\Translation')[0]
277
+
278
+ # any other must be of the form \StringfileInfo\%04X%04X\parm_name, middle
279
+ # two are language/codepage pair returned from above
280
+
281
+ strInfo = {}
282
+ for propName in propNames:
283
+ strInfoPath = u'\\StringFileInfo\\%04X%04X\\%s' % (lang, codepage, propName)
284
+ # print str_info
285
+ strInfo[propName] = win32api.GetFileVersionInfo(fname, strInfoPath)
286
+
287
+ props['StringFileInfo'] = strInfo
288
+ except BaseException:
289
+ pass
290
+
291
+ return props
292
+
293
+
294
+ class Type2DllWrapper(DLLWrapper):
295
+ def __init__(self, filename, dll_subroutine_init, dll_subroutine_update,
296
+ arraysizes_init, arraysizes_update,
297
+ init_array):
298
+ super().__init__(filename)
299
+ self.dll_subroutine_init = dll_subroutine_init
300
+ self.dll_subroutine_update = dll_subroutine_update
301
+ self.arraysizes_init = arraysizes_init
302
+ self.arraysizes_update = arraysizes_update
303
+ self.init_array = init_array
304
+
305
+ def open(self):
306
+ DLLWrapper.open(self)
307
+ self.init()
308
+
309
+ def call(self, name, array, n1, n2):
310
+ f = getattr(self.lib, name)
311
+ f.argtypes = [ndpointer(shape=n1, dtype=ct.c_double, flags='FORTRAN'),
312
+ ndpointer(shape=n2, dtype=ct.c_double, flags='FORTRAN')]
313
+ f.restype = None
314
+
315
+ pad_array = np.zeros(n1)
316
+ pad_array[:len(array)] = array
317
+ arg1 = np.array(pad_array, dtype=ct.c_double, order='F')
318
+ arg2 = np.zeros(n2, dtype=ct.c_double, order='F')
319
+
320
+ f(arg1, arg2)
321
+ return arg2
322
+
323
+ def init(self):
324
+ n1, n2 = self.arraysizes_init
325
+ return self.call(self.dll_subroutine_init, self.init_array, n1, n2)
326
+
327
+ def update(self, array):
328
+ n1, n2 = self.arraysizes_update
329
+ return self.call(self.dll_subroutine_update, array, n1, n2)
@@ -0,0 +1,324 @@
1
+ # noqa
2
+
3
+ from h2lib.dll_wrapper import DLLWrapper
4
+
5
+
6
+ class H2LibSignatures():
7
+ def add_sensor(self, sensor_line, index_start, index_stop):
8
+ '''subroutine add_sensor(sensor_line, index_start, index_stop) bind(C, name="add_sensor")
9
+ integer*8 :: index_start, index_stop, i
10
+ character(kind=c_char, len=1), intent(in) :: sensor_line(1024)
11
+ end subroutine'''
12
+ return self.get_lib_function('add_sensor')(sensor_line, index_start, index_stop)
13
+
14
+ def echo_version(self, ):
15
+ '''subroutine echo_version() BIND(C, NAME='echo_version')
16
+ !DEC$ ATTRIBUTES DLLEXPORT :: echo_version
17
+ !GCC$ ATTRIBUTES DLLEXPORT :: echo_version
18
+ type (tbuildinfo) :: b
19
+ end subroutine'''
20
+ return self.get_lib_function('echo_version')()
21
+
22
+ def extern_write_log(self, c_msg, n, dll_name, error, warning):
23
+ '''subroutine extern_write_log(c_msg, n, dll_name, error, warning) bind(C, name="extern_write_log")
24
+ integer, intent(in) :: n
25
+ character(kind=c_char, len=1), intent(in) :: c_msg(n)
26
+ character(kind=c_char), intent(in) :: dll_name(50)
27
+ logical(kind=c_bool), intent(in), optional :: error, warning
28
+ character(kind=c_char, len=1), intent(in) :: c_msg(n_msg)
29
+ integer, intent(in) :: n_msg
30
+ character(kind=c_char), intent(in) :: dll_name(50)
31
+ character(len=50) :: n
32
+ logical(kind=c_bool), intent(in), optional :: error, warning
33
+ end subroutine'''
34
+ return self.get_lib_function('extern_write_log')(c_msg, n, dll_name, error, warning)
35
+
36
+ def fail(self, str_arr): # pragma: no cover
37
+ '''subroutine fail(str_arr) bind(C, name='fail')
38
+ character(kind=c_char, len=1), intent(inout) :: str_arr(255)
39
+ end subroutine'''
40
+ return self.get_lib_function('fail')(str_arr)
41
+
42
+ def finalize(self, ):
43
+ '''SUBROUTINE finalize() bind(C, name="finalize")
44
+ !DEC$ ATTRIBUTES DLLEXPORT :: finalize
45
+ integer:: i
46
+ real*4:: T2
47
+ END SUBROUTINE'''
48
+ return self.get_lib_function('finalize')()
49
+
50
+ def getSquare(self, val, restype):
51
+ '''function getSquare(val) result(valSquared) BIND(C, NAME='getSquare')
52
+ !DEC$ ATTRIBUTES DLLEXPORT :: getSquare
53
+ real(RK), intent(in) :: val
54
+ real(RK) :: valSquared
55
+ end function'''
56
+ return self.get_lib_function('getSquare')(val, restype=restype)
57
+
58
+ def getState(self, restype):
59
+ '''function getState() result(val) BIND(C, NAME='getState')
60
+ !DEC$ ATTRIBUTES DLLEXPORT :: getState
61
+ integer :: val
62
+ end function'''
63
+ return self.get_lib_function('getState')(restype=restype)
64
+
65
+ def get_aerosections_forces(self, rotor, Fxyz):
66
+ '''subroutine get_aerosections_forces(rotor, Fxyz) bind(C, name='get_aerosections_forces')
67
+ integer*8, intent(in) :: rotor
68
+ real(c_double),intent(out)::Fxyz(rotors_gl%rotor(rotor)%nbld, rotors_gl%rotor(rotor)%blade(1)%nsec, 3)
69
+ end subroutine'''
70
+ return self.get_lib_function('get_aerosections_forces')(rotor, Fxyz)
71
+
72
+ def get_aerosections_moments(self, rotor, Mxyz):
73
+ '''subroutine get_aerosections_moments(rotor, Mxyz) bind(C, name='get_aerosections_moments')
74
+ integer*8, intent(in) :: rotor
75
+ real(c_double),intent(out):: Mxyz(rotors_gl%rotor(rotor)%nbld, rotors_gl%rotor(rotor)%blade(1)%nsec, 3)
76
+ end subroutine'''
77
+ return self.get_lib_function('get_aerosections_moments')(rotor, Mxyz)
78
+
79
+ def get_aerosections_position(self, rotor, position):
80
+ '''subroutine get_aerosections_position(rotor, position) bind(C, name="get_aerosections_position")
81
+ integer*8, intent(in) :: rotor
82
+ real(c_double),intent(out) :: position(rotors_gl%rotor(rotor)%nbld, rotors_gl%rotor(rotor)%blade(1)%nsec, 3)
83
+ end subroutine'''
84
+ return self.get_lib_function('get_aerosections_position')(rotor, position)
85
+
86
+ def get_bem_grid(self, rotor, azi, rad):
87
+ '''subroutine get_bem_grid(rotor, azi, rad) bind(C, name="get_bem_grid")
88
+ integer*8, intent(in) :: rotor
89
+ real(c_double), intent(out) :: azi(rotors_gl%rotor(rotor)%dyn_induc%bem%nazi)
90
+ real(c_double), intent(out) :: rad(rotors_gl%rotor(rotor)%dyn_induc%bem%nrad)
91
+ end subroutine'''
92
+ return self.get_lib_function('get_bem_grid')(rotor, azi, rad)
93
+
94
+ def get_bem_grid_dim(self, rotor, nazi, nrad):
95
+ '''subroutine get_bem_grid_dim(rotor, nazi, nrad) bind(C, name="get_bem_grid_dim")
96
+ integer*8, intent(in) :: rotor
97
+ integer*8, intent(out) :: nazi, nrad
98
+ end subroutine'''
99
+ return self.get_lib_function('get_bem_grid_dim')(rotor, nazi, nrad)
100
+
101
+ def get_diameter(self, rotor, restype):
102
+ '''function get_diameter(rotor) bind(C, name="get_diameter")
103
+ !DEC$ ATTRIBUTES DLLEXPORT :: get_diameter
104
+ integer*8, intent(in) :: rotor
105
+ Type (Taerorotor),pointer :: rotor_p
106
+ real(c_double) :: get_diameter
107
+ end function'''
108
+ return self.get_lib_function('get_diameter')(rotor, restype=restype)
109
+
110
+ def get_induction_axisymmetric(self, rotor, induction):
111
+ '''subroutine get_induction_axisymmetric(rotor, induction) bind(C, name="get_induction_axisymmetric")
112
+ integer*8, intent(in) :: rotor
113
+ real(c_double),intent(out) :: induction(rotors_gl%rotor(rotor)%dyn_induc%bem%nrad)
114
+ end subroutine'''
115
+ return self.get_lib_function('get_induction_axisymmetric')(rotor, induction)
116
+
117
+ def get_induction_polargrid(self, rotor, induction):
118
+ '''subroutine get_induction_polargrid(rotor, induction) bind(C, name="get_induction_polargrid")
119
+ integer*8, intent(in) :: rotor
120
+ real(c_double),intent(out) :: induction(rotors_gl%rotor(rotor)%dyn_induc%bem%nazi, rotors_gl%rotor(rotor)%dyn_induc%bem%nrad)
121
+ end subroutine'''
122
+ return self.get_lib_function('get_induction_polargrid')(rotor, induction)
123
+
124
+ def get_induction_rotoravg(self, rotor, induction):
125
+ '''subroutine get_induction_rotoravg(rotor, induction) bind(C, name="get_induction_rotoravg")
126
+ !DEC$ ATTRIBUTES DLLEXPORT :: get_induction_rotoravg
127
+ integer*8, intent(in) :: rotor
128
+ real(c_double), intent(out) :: induction
129
+ end subroutine'''
130
+ return self.get_lib_function('get_induction_rotoravg')(rotor, induction)
131
+
132
+ def get_nSections(self, rotor, blade, restype):
133
+ '''function get_nSections(rotor, blade) bind(C, name="get_nSections")
134
+ !DEC$ ATTRIBUTES DLLEXPORT :: get_nSections
135
+ integer*8, intent(in) :: rotor, blade
136
+ integer*8 :: get_nSections
137
+ end function'''
138
+ return self.get_lib_function('get_nSections')(rotor, blade, restype=restype)
139
+
140
+ def get_nblades(self, rotor, restype):
141
+ '''function get_nblades(rotor) bind(C, name="get_nblades")
142
+ !DEC$ ATTRIBUTES DLLEXPORT :: get_nblades
143
+ integer*8, intent(in) :: rotor
144
+ integer*8 :: get_nblades
145
+ end function'''
146
+ return self.get_lib_function('get_nblades')(rotor, restype=restype)
147
+
148
+ def get_nrotors(self, restype):
149
+ '''function get_nrotors() bind(C, name="get_nrotors")
150
+ !DEC$ ATTRIBUTES DLLEXPORT :: get_nrotors
151
+ integer*8 :: get_nrotors
152
+ end function'''
153
+ return self.get_lib_function('get_nrotors')(restype=restype)
154
+
155
+ def get_rotor_avg_wsp(self, coo, rotor, wsp):
156
+ '''subroutine get_rotor_avg_wsp(coo, rotor, wsp) bind(C, name="get_rotor_avg_wsp")
157
+ integer*8, intent(in) :: rotor
158
+ integer*8, intent(in) :: coo ! 1: global, 2: rotor
159
+ real(c_double), dimension(3):: wsp
160
+ end subroutine'''
161
+ return self.get_lib_function('get_rotor_avg_wsp')(coo, rotor, wsp)
162
+
163
+ def get_rotor_orientation(self, rotor, yaw, tilt, azi):
164
+ '''subroutine get_rotor_orientation(rotor, yaw, tilt, azi) bind(C, name="get_rotor_orientation")
165
+ !DEC$ ATTRIBUTES DLLEXPORT :: get_rotor_orientation
166
+ integer*8, intent(in) :: rotor
167
+ real(c_double), intent(out) :: yaw, tilt, azi
168
+ end subroutine'''
169
+ return self.get_lib_function('get_rotor_orientation')(rotor, yaw, tilt, azi)
170
+
171
+ def get_rotor_position(self, rotor, position):
172
+ '''subroutine get_rotor_position(rotor, position) bind(C, name="get_rotor_position")
173
+ !DEC$ ATTRIBUTES DLLEXPORT :: get_rotor_position
174
+ integer*8, intent(in) :: rotor
175
+ real(c_double), dimension(3), intent(out) :: position
176
+ !DEC$ ATTRIBUTES DLLEXPORT :: get_rotor_avg_wsp
177
+ integer*8, intent(in) :: rotor
178
+ integer*8, intent(in) :: coo ! 1: global, 2: rotor
179
+ end subroutine'''
180
+ return self.get_lib_function('get_rotor_position')(rotor, position)
181
+
182
+ def get_sensor_info(self, id, name, unit, desc):
183
+ '''subroutine get_sensor_info(id, name, unit, desc) bind(C, name="get_sensor_info")
184
+ integer*8, intent(in) :: id
185
+ character(kind=c_char, len=1), intent(out) :: name(30), unit(10), desc(512)
186
+ end subroutine'''
187
+ return self.get_lib_function('get_sensor_info')(id, name, unit, desc)
188
+
189
+ def get_sensor_values(self, ids, values, n):
190
+ '''subroutine get_sensor_values(ids, values, n) bind(C, name="get_sensor_values")
191
+ integer*8, intent(in) :: n
192
+ integer*8, intent(in) :: ids(n)
193
+ real(c_double), intent(out) :: values(n)
194
+ end subroutine'''
195
+ return self.get_lib_function('get_sensor_values')(ids, values, n)
196
+
197
+ def get_time(self, time):
198
+ '''subroutine
199
+ subroutine'''
200
+ return self.get_lib_function('get_time')(time)
201
+
202
+ def get_version(self, s):
203
+ '''subroutine get_version(s) BIND(C, NAME='get_version')
204
+ character(kind=c_char, len=1), intent(inout) :: s(255)
205
+ end subroutine'''
206
+ return self.get_lib_function('get_version')(s)
207
+
208
+ def init(self, ):
209
+ '''subroutine init() bind(C, name="init")
210
+ !DEC$ ATTRIBUTES DLLEXPORT :: init
211
+ end subroutine'''
212
+ return self.get_lib_function('init')()
213
+
214
+ def init_windfield(self, Nxyz, dxyz, box_offset_yz, transport_speed):
215
+ '''subroutine init_windfield(Nxyz, dxyz, box_offset_yz, transport_speed) bind(C, name="init_windfield")
216
+ integer*8, dimension(3), intent(in) :: Nxyz
217
+ real*8 :: transport_speed
218
+ end subroutine'''
219
+ return self.get_lib_function('init_windfield')(Nxyz, dxyz, box_offset_yz, transport_speed)
220
+
221
+ def loop(self, N, restype):
222
+ '''function loop(N) bind(C, Name='loop')
223
+ !DEC$ ATTRIBUTES DLLEXPORT :: loop
224
+ integer*8, intent(in) :: N
225
+ real(c_double) :: loop,a
226
+ integer*8 :: i, j
227
+ end function'''
228
+ return self.get_lib_function('loop')(N, restype=restype)
229
+
230
+ def myfunction(self, int, dbl, restype):
231
+ '''function myfunction(int, dbl) bind(C, name='myfunction')
232
+ !DEC$ ATTRIBUTES DLLEXPORT :: myfunction
233
+ integer*8, intent(in) :: int
234
+ real(c_double), intent(in) :: dbl
235
+ real(c_double) :: myfunction
236
+ end function'''
237
+ return self.get_lib_function('myfunction')(int, dbl, restype=restype)
238
+
239
+ def mysubroutine(self, str_arr, dbl_arr):
240
+ '''subroutine mysubroutine(str_arr, dbl_arr) bind(C, name='mysubroutine')
241
+ character(kind=c_char, len=1), intent(inout) :: str_arr(20)
242
+ real(c_double), intent(inout), dimension(2) :: dbl_arr
243
+ end subroutine'''
244
+ return self.get_lib_function('mysubroutine')(str_arr, dbl_arr)
245
+
246
+ def read_input(self, htc_path):
247
+ '''subroutine read_input(htc_path) bind(C, name="read_input")
248
+ character(kind=c_char, len=1), intent(in) :: htc_path(1024)
249
+ end subroutine'''
250
+ return self.get_lib_function('read_input')(htc_path)
251
+
252
+ def run(self, time, restype):
253
+ '''function run(time) bind(C, name='run')
254
+ !DEC$ ATTRIBUTES DLLEXPORT :: run
255
+ real(c_double), intent(in) :: time
256
+ real(c_double) :: run, eps
257
+ end function'''
258
+ return self.get_lib_function('run')(time, restype=restype)
259
+
260
+ def setState(self, val):
261
+ '''subroutine setState(val) BIND(C, NAME='setState')
262
+ integer, intent(in) :: val
263
+ end subroutine'''
264
+ return self.get_lib_function('setState')(val)
265
+
266
+ def set_aerosections_windspeed(self, rotor, uvw):
267
+ '''subroutine set_aerosections_windspeed(rotor, uvw) bind(C, name="set_aerosections_windspeed")
268
+ integer*8, intent(in) :: rotor
269
+ real(c_double),intent(in) :: uvw(rotors_gl%rotor(rotor)%nbld, rotors_gl%rotor(rotor)%blade(1)%nsec, 3)
270
+ end subroutine'''
271
+ return self.get_lib_function('set_aerosections_windspeed')(rotor, uvw)
272
+
273
+ def set_variable_sensor_value(self, id, value):
274
+ '''subroutine set_variable_sensor_value(id, value) bind(C, name="set_variable_sensor_value")
275
+ integer*8, intent(in) :: id
276
+ real(c_double) :: value
277
+ end subroutine'''
278
+ return self.get_lib_function('set_variable_sensor_value')(id, value)
279
+
280
+ def set_windfield(self, uvw, box_offset_x, time):
281
+ '''subroutine set_windfield(uvw, box_offset_x, time) bind(C, name="set_windfield")
282
+ real*4, intent(in) :: uvw(3, gwsd%TMOD%buffer_points_x,gwsd%TMOD%buffer_points_y,gwsd%TMOD%buffer_points_z)
283
+ real*8, intent(in):: box_offset_x, time
284
+ end subroutine'''
285
+ return self.get_lib_function('set_windfield')(uvw, box_offset_x, time)
286
+
287
+ def sqr2(self, val):
288
+ '''subroutine sqr2(val) BIND(C, NAME='sqr2')
289
+ integer, intent(inout) :: val
290
+ end subroutine'''
291
+ return self.get_lib_function('sqr2')(val)
292
+
293
+ def step(self, restype):
294
+ '''function step() bind(C, name='step')
295
+ !DEC$ ATTRIBUTES DLLEXPORT :: step
296
+ real(c_double) :: step
297
+ end function'''
298
+ return self.get_lib_function('step')(restype=restype)
299
+
300
+ def test_hdf5(self, ):
301
+ '''subroutine test_hdf5() BIND(C, NAME='test_hdf5')
302
+ !DEC$ ATTRIBUTES DLLEXPORT :: test_hdf5
303
+ INTEGER :: hdferr ! Error flag
304
+ CHARACTER(9) :: filename = 'test.hdf5'
305
+ INTEGER(HID_T) :: file_id ! File identifier
306
+ INTEGER(HID_T) :: H5_Create_file,H5_Open_file ! File identifier
307
+ type(c_ptr) :: x
308
+ end subroutine'''
309
+ return self.get_lib_function('test_hdf5')()
310
+
311
+ def work(self, time, restype):
312
+ '''function work(time) bind(C, Name='work')
313
+ !DEC$ ATTRIBUTES DLLEXPORT :: work
314
+ real(c_double), intent(in) :: time
315
+ real*4 :: start_time, t
316
+ integer*8 :: N, work
317
+ end function'''
318
+ return self.get_lib_function('work')(time, restype=restype)
319
+
320
+ def write_output(self, ):
321
+ '''subroutine write_output() bind(C, name="write_output")
322
+ !DEC$ ATTRIBUTES DLLEXPORT :: write_output
323
+ end subroutine'''
324
+ return self.get_lib_function('write_output')()
@@ -0,0 +1,21 @@
1
+ Metadata-Version: 2.1
2
+ Name: h2lib
3
+ Version: 13.1.301
4
+ Summary: Python interface to HAWC2 (13.1.3)
5
+ Download-URL:
6
+ Author: Mads M. Pedersen, S.G.Horcas and N.G.Ramos
7
+ Author-email: mmpe@dtu.dk
8
+ Maintainer:
9
+ Maintainer-email:
10
+ Project-URL: Documentation, https://hawc2.pages.windenergy.dtu.dk/HAWC2Lib/
11
+ Project-URL: Source, https://gitlab.windenergy.dtu.dk/HAWC2/HAWC2Lib
12
+ Project-URL: Tracker, https://gitlab.windenergy.dtu.dk/HAWC2/HAWC2Lib/-/issues
13
+ Requires-Dist: numpy
14
+ Requires-Dist: intel-fortran-rt ==2021.3.0
15
+ Requires-Dist: mkl ==2021.3.0
16
+ Requires-Dist: multiclass-interface >=1.5
17
+ Provides-Extra: mpi
18
+ Requires-Dist: mpi4py ; extra == 'mpi'
19
+ Provides-Extra: test
20
+ Requires-Dist: h2lib-tests ; extra == 'test'
21
+
@@ -0,0 +1,10 @@
1
+ h2lib/HAWC2Lib.so,sha256=lTo-MTGmuWWut6obARXJbwm0aUaRRavZ66_H-otJ4Fw,37990888
2
+ h2lib/__init__.py,sha256=YyJWPF22nu9ZoxkrE3ghngT9n_hl-HiAEflnZ_Ay8Q4,513
3
+ h2lib/_h2lib.py,sha256=J9eWeJTaHUEmwF5St6ce4YWquteEXNQiUWOs9hb_tII,14643
4
+ h2lib/_version.py,sha256=dpn5IZTgXLYpPqs-tx0TObc9Xbe3GmH3UCI4D3FFX68,142
5
+ h2lib/dll_wrapper.py,sha256=PxyK19SV-dO_-Fl8T6dnvKKxLFbDBzkUT1_igh38K4I,11593
6
+ h2lib/h2lib_signatures.py,sha256=wxIHaQ9adni1Vm5oOgXlsh1ULnGUPi6-GLnWtQ6gty4,14408
7
+ h2lib-13.1.301.dist-info/METADATA,sha256=X-AP77gfxWZD7SGOa7L47_c8zpFB7M1lDTjLSRf01r4,706
8
+ h2lib-13.1.301.dist-info/WHEEL,sha256=nLg6JJzHN_0h05ClOJeXqTjuASxRDcfhtJhPJzBnKyI,151
9
+ h2lib-13.1.301.dist-info/top_level.txt,sha256=y_a-tUqphEZQ_0nsWSMaSb21P8Lsd8hUxUdE9g2Dcbk,6
10
+ h2lib-13.1.301.dist-info/RECORD,,
@@ -0,0 +1,6 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (71.1.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp312-cp312-manylinux_2_17_x86_64
5
+ Tag: cp312-cp312-manylinux2014_x86_64
6
+
@@ -0,0 +1 @@
1
+ h2lib