h2lib 13.1.505__py3-none-win_amd64.whl → 13.1.901__py3-none-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 +0 -0
- h2lib/_h2lib.py +355 -49
- h2lib/_version.py +3 -3
- h2lib/dll_wrapper.py +21 -1
- h2lib/h2lib_signatures.py +98 -7
- {h2lib-13.1.505.dist-info → h2lib-13.1.901.dist-info}/METADATA +2 -2
- h2lib-13.1.901.dist-info/RECORD +10 -0
- {h2lib-13.1.505.dist-info → h2lib-13.1.901.dist-info}/WHEEL +1 -1
- h2lib-13.1.505.dist-info/RECORD +0 -10
- {h2lib-13.1.505.dist-info → h2lib-13.1.901.dist-info}/top_level.txt +0 -0
h2lib/HAWC2Lib.dll
CHANGED
Binary file
|
h2lib/_h2lib.py
CHANGED
@@ -6,6 +6,27 @@ import sys
|
|
6
6
|
|
7
7
|
from multiclass_interface.multiprocess_interface import MultiProcessClassInterface, ProcessClass
|
8
8
|
import numpy as np
|
9
|
+
from pathlib import Path
|
10
|
+
|
11
|
+
_ERROR_CODES = {
|
12
|
+
1: ValueError("WRONG_NUMBER_OF_COLUMNS"),
|
13
|
+
2: ValueError("MAIN_BODY_NOT_FOUND"),
|
14
|
+
3: RuntimeError("NOT_IMPLEMENTED_ERROR"),
|
15
|
+
4: RuntimeError("STRUCTURE_IS_CONFIDENTIAL"),
|
16
|
+
5: IndexError("BODY_DOES_NOT_EXIST"),
|
17
|
+
6: IndexError("ELEMENT_DOES_NOT_EXIST"),
|
18
|
+
7: ValueError("WRONG_NUMBER_OF_BODIES"),
|
19
|
+
100: RuntimeError("STATIC_SOLVER_DID_NOT_CONVERGE"),
|
20
|
+
101: RuntimeError("STATIC_SOLVER_NOT_INITIALIZED"),
|
21
|
+
300: ValueError("TOO_FEW_SECTIONS_IN_C2DEF"),
|
22
|
+
301: ValueError("BEAM_TOO_SHORT"),
|
23
|
+
302: ValueError("DIFFERENT_NSEC"),
|
24
|
+
700: RuntimeError("SYSTEM_NOT_LINEARIZED"),
|
25
|
+
701: RuntimeError("SYSTEM_EIGENANALYSIS_NOT_DONE"),
|
26
|
+
702: ValueError("TOO_MANY_MODES_REQUESTED"),
|
27
|
+
703: ValueError("WRONG_TOTAL_DOF"),
|
28
|
+
704: ValueError("WRONG_REDUCED_DOF")
|
29
|
+
}
|
9
30
|
|
10
31
|
|
11
32
|
def H2Lib(suppress_output=False, subprocess=True):
|
@@ -26,9 +47,11 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
|
|
26
47
|
# doubles the speed of single instances and 2N of N instances on linux
|
27
48
|
os.environ['MKL_THREADING_LAYER'] = 'sequential'
|
28
49
|
filename = os.path.abspath(filename)
|
29
|
-
|
30
|
-
|
31
|
-
|
50
|
+
p = Path(np.__file__).parents
|
51
|
+
for i in range(2, 4):
|
52
|
+
if (p[i] / 'Library/bin').exists():
|
53
|
+
os.add_dll_directory(p[i] / 'Library/bin')
|
54
|
+
break
|
32
55
|
DLLWrapper.__init__(self, filename, cwd=cwd, cdecl=True)
|
33
56
|
self.suppress_output = suppress_output
|
34
57
|
self._initialized = False
|
@@ -98,6 +121,213 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
|
|
98
121
|
self.time = np.round(H2LibSignatures.run(self, np.float64(time), restype=np.float64)[1], 6)
|
99
122
|
return self.time
|
100
123
|
|
124
|
+
def linearize(self):
|
125
|
+
"""
|
126
|
+
Linearize the system, as done by the system eigen-analysis.
|
127
|
+
|
128
|
+
Returns
|
129
|
+
-------
|
130
|
+
n_tdofs : int
|
131
|
+
Total number of degrees of freedom in the system.
|
132
|
+
n_rdofs : int
|
133
|
+
Number of degrees of freedom in the reduced order system.
|
134
|
+
|
135
|
+
"""
|
136
|
+
n_tdofs = -1
|
137
|
+
n_rdofs = -1
|
138
|
+
res = H2LibSignatures.linearize(self, n_tdofs, n_rdofs)[0]
|
139
|
+
return res
|
140
|
+
|
141
|
+
def do_system_eigenanalysis(self, n_modes, include_damping=True):
|
142
|
+
"""
|
143
|
+
Do the system eigen-analysis.
|
144
|
+
|
145
|
+
Parameters
|
146
|
+
----------
|
147
|
+
n_modes : int
|
148
|
+
Number of modes to output.
|
149
|
+
include_damping : bool, optional
|
150
|
+
`True` to include damping, `False` otherwise. The default is `True`.
|
151
|
+
|
152
|
+
Raises
|
153
|
+
------
|
154
|
+
RuntimeError
|
155
|
+
Call `linearize` first.
|
156
|
+
ValueError
|
157
|
+
If too many modes are requested.
|
158
|
+
|
159
|
+
Returns
|
160
|
+
-------
|
161
|
+
natural_frequencies : (n_modes,) ndarray
|
162
|
+
Natural frequencies, in Hz.
|
163
|
+
damping_ratios : (n_modes,) ndarray
|
164
|
+
Damping ratios (nondimensional).
|
165
|
+
Only returned if `include_damping=True`.
|
166
|
+
|
167
|
+
"""
|
168
|
+
natural_frequencies = np.zeros((n_modes,), dtype=np.float64, order="F")
|
169
|
+
damping_ratios = np.zeros((n_modes,), dtype=np.float64, order="F")
|
170
|
+
error_code = -1
|
171
|
+
|
172
|
+
_, _, natural_frequencies, damping_ratios, error_code = (
|
173
|
+
H2LibSignatures.do_system_eigenanalysis(
|
174
|
+
self,
|
175
|
+
include_damping,
|
176
|
+
n_modes,
|
177
|
+
natural_frequencies,
|
178
|
+
damping_ratios,
|
179
|
+
error_code,
|
180
|
+
)[0]
|
181
|
+
)
|
182
|
+
|
183
|
+
if error_code > 0:
|
184
|
+
raise _ERROR_CODES[error_code]
|
185
|
+
|
186
|
+
if include_damping:
|
187
|
+
return natural_frequencies, damping_ratios
|
188
|
+
else:
|
189
|
+
return natural_frequencies
|
190
|
+
|
191
|
+
def get_system_eigenvalues_and_eigenvectors(
|
192
|
+
self, n_modes, n_rdofs, include_damping=True
|
193
|
+
):
|
194
|
+
"""
|
195
|
+
Get the system eigenvalues and eigenvectors from system_eigenanalysis.
|
196
|
+
|
197
|
+
This function must be called after `do_system_eigenanalysis`, with the same value of `include_damping`.
|
198
|
+
|
199
|
+
Parameters
|
200
|
+
----------
|
201
|
+
n_modes : int
|
202
|
+
Number of modes to output.
|
203
|
+
n_rdofs : int
|
204
|
+
Number of degrees of freedom in the reduced order system.
|
205
|
+
As returned by `linearize`.
|
206
|
+
include_damping : bool, optional
|
207
|
+
`True` to include damping, `False` otherwise. The default is `True`.
|
208
|
+
|
209
|
+
Raises
|
210
|
+
------
|
211
|
+
RuntimeError
|
212
|
+
If the structure is confidential or if `linearize` and `do_system_eigenanalysis` have not been called first.
|
213
|
+
ValueError
|
214
|
+
Either `n_modes` or `n_rdofs` is wrong.
|
215
|
+
|
216
|
+
Returns
|
217
|
+
-------
|
218
|
+
eigenvalues : (n_modes,) ndarray
|
219
|
+
Eigenvalues. Real array without damping and complex array otherwise.
|
220
|
+
eigenvectors : (n_modes, ny)
|
221
|
+
Eigenvectors. Real array without damping and complex array otherwise.
|
222
|
+
Only returned if the structure is not confidential.
|
223
|
+
|
224
|
+
"""
|
225
|
+
if include_damping:
|
226
|
+
ny = 2 * n_rdofs
|
227
|
+
dtype = np.complex128
|
228
|
+
f = H2LibSignatures.get_system_eigval_eigvec_with_damping
|
229
|
+
else:
|
230
|
+
ny = n_rdofs
|
231
|
+
dtype = np.float64
|
232
|
+
f = H2LibSignatures.get_system_eigval_eigvec_without_damping
|
233
|
+
|
234
|
+
error_code = -1
|
235
|
+
eigenvalues = np.zeros((n_modes,), dtype=dtype, order="F")
|
236
|
+
eigenvectors = np.zeros((n_modes, ny), dtype=dtype, order="F")
|
237
|
+
|
238
|
+
_, _, eigenvalues, eigenvectors, error_code = f(
|
239
|
+
self, n_modes, ny, eigenvalues, eigenvectors, error_code
|
240
|
+
)[0]
|
241
|
+
|
242
|
+
if error_code > 0:
|
243
|
+
if error_code == 4:
|
244
|
+
# The structure is confidential.
|
245
|
+
# The eigenvectors have not been returned by the Fortran code.
|
246
|
+
return eigenvalues
|
247
|
+
else:
|
248
|
+
raise _ERROR_CODES[error_code]
|
249
|
+
|
250
|
+
return eigenvalues, eigenvectors
|
251
|
+
|
252
|
+
def solver_static_init(self):
|
253
|
+
"""
|
254
|
+
Initialize the static solver.
|
255
|
+
|
256
|
+
Returns
|
257
|
+
-------
|
258
|
+
None.
|
259
|
+
|
260
|
+
"""
|
261
|
+
H2LibSignatures.solver_static_init(self)
|
262
|
+
|
263
|
+
def solver_static_update(self):
|
264
|
+
"""
|
265
|
+
Update the static solver.
|
266
|
+
|
267
|
+
Raises
|
268
|
+
------
|
269
|
+
RuntimeError
|
270
|
+
If the static solver has not been initialized. Call `solver_static_init()` first.
|
271
|
+
|
272
|
+
Returns
|
273
|
+
-------
|
274
|
+
None.
|
275
|
+
|
276
|
+
"""
|
277
|
+
error_code = -1
|
278
|
+
error_code = H2LibSignatures.solver_static_update(self, error_code)[0][0]
|
279
|
+
if error_code > 0:
|
280
|
+
raise _ERROR_CODES[error_code]
|
281
|
+
|
282
|
+
def solver_static_solve(self):
|
283
|
+
"""
|
284
|
+
Compute the static solution.
|
285
|
+
|
286
|
+
Raises
|
287
|
+
------
|
288
|
+
RuntimeError
|
289
|
+
If the static solver has not been initialized. Call `solver_static_init()` first.
|
290
|
+
|
291
|
+
Returns
|
292
|
+
-------
|
293
|
+
None.
|
294
|
+
|
295
|
+
"""
|
296
|
+
error_code = -1
|
297
|
+
error_code = H2LibSignatures.solver_static_solve(self, error_code)[0][0]
|
298
|
+
if error_code > 0:
|
299
|
+
raise _ERROR_CODES[error_code]
|
300
|
+
|
301
|
+
def solver_static_delete(self):
|
302
|
+
"""
|
303
|
+
Delete the static solver.
|
304
|
+
|
305
|
+
Returns
|
306
|
+
-------
|
307
|
+
None.
|
308
|
+
|
309
|
+
"""
|
310
|
+
H2LibSignatures.solver_static_delete(self)
|
311
|
+
|
312
|
+
def solver_static_run(self):
|
313
|
+
"""
|
314
|
+
Run the complete static solver algorithm.
|
315
|
+
|
316
|
+
Raises
|
317
|
+
------
|
318
|
+
RuntimeError
|
319
|
+
If the static solver has not converged.
|
320
|
+
|
321
|
+
Returns
|
322
|
+
-------
|
323
|
+
None.
|
324
|
+
|
325
|
+
"""
|
326
|
+
error_code = -1
|
327
|
+
error_code = H2LibSignatures.solver_static_run(self, error_code)[0][0]
|
328
|
+
if error_code > 0:
|
329
|
+
raise _ERROR_CODES[error_code]
|
330
|
+
|
101
331
|
def add_sensor(self, sensor_line):
|
102
332
|
"""Add sensor to hawc2. The sensor will be accessible from h2lib but will not show up in the output file of HAWC2
|
103
333
|
Note, that some sensors consist of multiple HAWC2 sensors, e.g. "wind free_wind" which has a Vx, Vy and Vz sensors
|
@@ -146,6 +376,76 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
|
|
146
376
|
def set_variable_sensor_value(self, id, value):
|
147
377
|
return H2LibSignatures.set_variable_sensor_value(self, id, np.float64(value))
|
148
378
|
|
379
|
+
def set_orientation_base(
|
380
|
+
self,
|
381
|
+
main_body_name,
|
382
|
+
mbdy_eulerang_table=None,
|
383
|
+
angles_in_deg=True,
|
384
|
+
reset_orientation=False,
|
385
|
+
mbdy_ini_rotvec_d1=None,
|
386
|
+
):
|
387
|
+
"""
|
388
|
+
Set an orientation / base command.
|
389
|
+
|
390
|
+
Function equivalent to the HAWC2 command orientation / base.
|
391
|
+
For further details see the HAWC2 documentation.
|
392
|
+
We assume that this base is already present in the htc file,
|
393
|
+
and therefore modify it here instead of creating a new one.
|
394
|
+
|
395
|
+
Parameters
|
396
|
+
----------
|
397
|
+
main_body_name : str
|
398
|
+
Main body name. Same as HAWC2 `mbdy` parameter.
|
399
|
+
mbdy_eulerang_table : (:, 3) ndarray, optional
|
400
|
+
A sequence of Euler angles, one per row.
|
401
|
+
Equivalent to HAWC2 command `mbdy_eulerang`.
|
402
|
+
A 1D array with 3 elements will be interpreted as 1 row.
|
403
|
+
This table is additive with respect to the orientation / base command in the htc file,
|
404
|
+
unless the flag `reset_orientation` is used.
|
405
|
+
The default is `[0, 0, 0]`, which means that the base is coincident with the global frame.
|
406
|
+
angles_in_deg : bool, optional
|
407
|
+
`True` if the angles in `mbdy_eulerang_table` are provided in degrees.
|
408
|
+
`False` if they are in radians.
|
409
|
+
The default is `True`.
|
410
|
+
reset_orientation : bool, optional,
|
411
|
+
If `True` this function will reset the orientation to the global frame
|
412
|
+
before applying `mbdy_eulerang_table`. The default is `False`.
|
413
|
+
mbdy_ini_rotvec_d1 : (4) ndarray, optional
|
414
|
+
Angular velocity. First 3 elements for the direction and last for the magnitude.
|
415
|
+
Equivalent to HAWC2 command `mbdy_ini_rotvec_d1`.
|
416
|
+
The default is 0 speed.
|
417
|
+
|
418
|
+
Raises
|
419
|
+
------
|
420
|
+
ValueError
|
421
|
+
If the orientation / base command cannot be found.
|
422
|
+
|
423
|
+
Returns
|
424
|
+
-------
|
425
|
+
None.
|
426
|
+
|
427
|
+
"""
|
428
|
+
if mbdy_eulerang_table is None:
|
429
|
+
mbdy_eulerang_table = np.zeros((1, 3), dtype=np.float64, order="F")
|
430
|
+
if mbdy_ini_rotvec_d1 is None:
|
431
|
+
mbdy_ini_rotvec_d1 = np.zeros((4,), dtype=np.float64, order="F")
|
432
|
+
# 1D arrays are converted to 2D with 1 row.
|
433
|
+
mbdy_eulerang_table = np.atleast_2d(mbdy_eulerang_table)
|
434
|
+
error_code = -1
|
435
|
+
error_code = H2LibSignatures.set_orientation_base(
|
436
|
+
self,
|
437
|
+
main_body_name,
|
438
|
+
np.asfortranarray(mbdy_eulerang_table.astype(np.float64)),
|
439
|
+
mbdy_eulerang_table.shape[0],
|
440
|
+
angles_in_deg,
|
441
|
+
reset_orientation,
|
442
|
+
np.asfortranarray(mbdy_ini_rotvec_d1.astype(np.float64)),
|
443
|
+
error_code,
|
444
|
+
)[0][-1]
|
445
|
+
|
446
|
+
if error_code > 0:
|
447
|
+
raise _ERROR_CODES[error_code]
|
448
|
+
|
149
449
|
def init_windfield(self, Nxyz, dxyz, box_offset_yz, transport_speed):
|
150
450
|
"""Initialize wind field which afterwards can be set using set_windfield
|
151
451
|
|
@@ -302,26 +602,6 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
|
|
302
602
|
vx, vy, vz = self.get_rotor_avg_wsp(1, rotor)
|
303
603
|
return [vy, vx, -vz]
|
304
604
|
|
305
|
-
def init_static_solver(self):
|
306
|
-
"""
|
307
|
-
Initialize the static solver.
|
308
|
-
|
309
|
-
Raises
|
310
|
-
------
|
311
|
-
RuntimeError
|
312
|
-
If the static solver has already been initialized.
|
313
|
-
|
314
|
-
Returns
|
315
|
-
-------
|
316
|
-
None.
|
317
|
-
|
318
|
-
"""
|
319
|
-
error_code = H2LibSignatures.init_static_solver(self, restype=np.int64)[1]
|
320
|
-
if error_code > 0:
|
321
|
-
if error_code == 102:
|
322
|
-
raise RuntimeError("STATIC_SOLVER_ALREADY_INITIALIZED")
|
323
|
-
raise RuntimeError(error_code) # pragma: no cover
|
324
|
-
|
325
605
|
def get_number_of_bodies_and_constraints(self):
|
326
606
|
"""
|
327
607
|
Get number of bodies and constraints.
|
@@ -352,9 +632,7 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
|
|
352
632
|
0
|
353
633
|
]
|
354
634
|
if error_code > 0:
|
355
|
-
|
356
|
-
raise RuntimeError("STRUCTURE_IS_CONFIDENTIAL")
|
357
|
-
raise RuntimeError(error_code) # pragma: no cover
|
635
|
+
raise _ERROR_CODES[error_code]
|
358
636
|
return nbdy, ncst
|
359
637
|
|
360
638
|
def get_number_of_elements(self):
|
@@ -380,15 +658,9 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
|
|
380
658
|
self, nbdy, nelem, error_code
|
381
659
|
)[0]
|
382
660
|
|
383
|
-
if error_code > 0:
|
384
|
-
|
385
|
-
|
386
|
-
# get this error from get_number_of_bodies_and_constraints().
|
387
|
-
raise RuntimeError("STRUCTURE_IS_CONFIDENTIAL") # pragma: no cover
|
388
|
-
elif error_code == 7: # pragma: no cover
|
389
|
-
# This cannot happen because we call get_number_of_bodies_and_constraints().
|
390
|
-
raise ValueError("WRONG_NUMBER_OF_BODIES") # pragma: no cover
|
391
|
-
raise RuntimeError(error_code) # pragma: no cover
|
661
|
+
if error_code > 0: # pragma: no cover
|
662
|
+
# This cannot happen because exceptions are raised by get_number_of_bodies_and_constraints().
|
663
|
+
raise _ERROR_CODES[error_code] # pragma: no cover
|
392
664
|
return nelem
|
393
665
|
|
394
666
|
def get_timoshenko_location(self, ibdy, ielem):
|
@@ -441,14 +713,7 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
|
|
441
713
|
0
|
442
714
|
]
|
443
715
|
if error_code > 0:
|
444
|
-
|
445
|
-
raise RuntimeError("STRUCTURE_IS_CONFIDENTIAL")
|
446
|
-
elif error_code == 5:
|
447
|
-
raise IndexError("BODY_DOES_NOT_EXIST")
|
448
|
-
elif error_code == 6:
|
449
|
-
raise IndexError("ELEMENT_DOES_NOT_EXIST")
|
450
|
-
raise RuntimeError(error_code) # pragma: no cover
|
451
|
-
|
716
|
+
raise _ERROR_CODES[error_code]
|
452
717
|
return l, r1, r12, tes
|
453
718
|
|
454
719
|
def get_body_rotation_tensor(self, ibdy):
|
@@ -479,14 +744,55 @@ class H2LibThread(H2LibSignatures, DLLWrapper):
|
|
479
744
|
self, ibdy + 1, amat, error_code
|
480
745
|
)[0]
|
481
746
|
if error_code > 0:
|
482
|
-
|
483
|
-
raise RuntimeError("STRUCTURE_IS_CONFIDENTIAL")
|
484
|
-
elif error_code == 5:
|
485
|
-
raise IndexError("BODY_DOES_NOT_EXIST")
|
486
|
-
raise RuntimeError(error_code) # pragma: no cover
|
487
|
-
|
747
|
+
raise _ERROR_CODES[error_code]
|
488
748
|
return amat
|
489
749
|
|
750
|
+
def get_system_matrices(self, n_tdofs, n_rdofs):
|
751
|
+
"""
|
752
|
+
Get the system structural matrices computed during the system_eigenanalysis.
|
753
|
+
|
754
|
+
This function must be called after `linearize()`.
|
755
|
+
|
756
|
+
Parameters
|
757
|
+
----------
|
758
|
+
n_tdofs : int
|
759
|
+
Total number of degrees of freedom in the system.
|
760
|
+
n_rdofs : int
|
761
|
+
Number of degrees of freedom in the reduced order system.
|
762
|
+
|
763
|
+
Raises
|
764
|
+
------
|
765
|
+
RuntimeError
|
766
|
+
If the linearizetion has not been done or the structure is confidential.
|
767
|
+
ValueError
|
768
|
+
If the total or reduced number of degrees of freedom is wrong.
|
769
|
+
|
770
|
+
Returns
|
771
|
+
-------
|
772
|
+
M : (n_rdofs, n_rdofs) ndarray
|
773
|
+
Mass matrix.
|
774
|
+
C : (n_rdofs, n_rdofs) ndarray
|
775
|
+
Damping matrix.
|
776
|
+
K : (n_rdofs, n_rdofs) ndarray
|
777
|
+
Stiffness matrix.
|
778
|
+
R : (n_tdofs, n_rdofs) ndarray
|
779
|
+
Transformation between reduced and all DOFs.
|
780
|
+
|
781
|
+
"""
|
782
|
+
M = np.zeros((n_rdofs, n_rdofs), dtype=np.float64, order="F")
|
783
|
+
C = np.zeros((n_rdofs, n_rdofs), dtype=np.float64, order="F")
|
784
|
+
K = np.zeros((n_rdofs, n_rdofs), dtype=np.float64, order="F")
|
785
|
+
R = np.zeros((n_tdofs, n_rdofs), dtype=np.float64, order="F")
|
786
|
+
error_code = -1
|
787
|
+
|
788
|
+
_, _, M, C, K, R, error_code = H2LibSignatures.get_system_matrices(
|
789
|
+
self, n_tdofs, n_rdofs, M, C, K, R, error_code
|
790
|
+
)[0]
|
791
|
+
|
792
|
+
if error_code > 0:
|
793
|
+
raise _ERROR_CODES[error_code]
|
794
|
+
return M, C, K, R
|
795
|
+
|
490
796
|
|
491
797
|
@contextmanager
|
492
798
|
def set_LD_LIBRARY_PATH():
|
h2lib/_version.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
# This file is autogenerated and should not be modified manually
|
2
|
-
__version__ = '13.1.
|
3
|
-
h2lib_version = '13.1.
|
4
|
-
hawc2_version = '13.1.5
|
2
|
+
__version__ = '13.1.901'
|
3
|
+
h2lib_version = '13.1.901'
|
4
|
+
hawc2_version = '13.1.9+5-g2026dd7'
|
h2lib/dll_wrapper.py
CHANGED
@@ -6,7 +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, c_longlong
|
9
|
+
from ctypes import c_int, c_double, c_char, c_char_p, c_long, c_longlong, Structure
|
10
10
|
from contextlib import contextmanager
|
11
11
|
import tempfile
|
12
12
|
try:
|
@@ -22,6 +22,24 @@ c_long_p = POINTER(ctypes.c_longlong)
|
|
22
22
|
c_double_p = POINTER(ctypes.c_double)
|
23
23
|
c_float_p = POINTER(ctypes.c_float)
|
24
24
|
|
25
|
+
|
26
|
+
# Add support for complex numbers to ctypes.
|
27
|
+
# This solution is copied from: https://stackoverflow.com/a/65743183/3676517
|
28
|
+
class c_double_complex(Structure):
|
29
|
+
"""complex is a c structure
|
30
|
+
https://docs.python.org/3/library/ctypes.html#module-ctypes suggests
|
31
|
+
to use ctypes.Structure to pass structures (and, therefore, complex)
|
32
|
+
"""
|
33
|
+
|
34
|
+
_fields_ = [("real", c_double), ("imag", c_double)]
|
35
|
+
|
36
|
+
@property
|
37
|
+
def value(self):
|
38
|
+
return self.real + 1j * self.imag # fields declared above
|
39
|
+
|
40
|
+
|
41
|
+
c_double_complex_p = POINTER(c_double_complex)
|
42
|
+
|
25
43
|
in_use = []
|
26
44
|
|
27
45
|
|
@@ -109,6 +127,8 @@ def wrap(self, f, *args, **kwargs):
|
|
109
127
|
c_args.append(arg.ctypes.data_as(c_double_p))
|
110
128
|
elif arg.dtype == np.float32:
|
111
129
|
c_args.append(arg.ctypes.data_as(c_float_p))
|
130
|
+
elif arg.dtype == np.complex128:
|
131
|
+
c_args.append(arg.ctypes.data_as(c_double_complex_p))
|
112
132
|
else:
|
113
133
|
raise NotImplementedError(arg.dtype)
|
114
134
|
|
h2lib/h2lib_signatures.py
CHANGED
@@ -6,11 +6,21 @@ from h2lib.dll_wrapper import DLLWrapper
|
|
6
6
|
class H2LibSignatures():
|
7
7
|
def add_sensor(self, sensor_line, index_start, index_stop):
|
8
8
|
'''subroutine add_sensor(sensor_line, index_start, index_stop) bind(C, name="add_sensor")
|
9
|
-
integer*8 :: index_start, index_stop
|
9
|
+
integer*8 :: index_start, index_stop
|
10
10
|
character(kind=c_char, len=1), intent(in) :: sensor_line(1024)
|
11
11
|
end subroutine'''
|
12
12
|
return self.get_lib_function('add_sensor')(sensor_line, index_start, index_stop)
|
13
13
|
|
14
|
+
def do_system_eigenanalysis(self, include_damping, n_modes, natural_frequencies, damping_ratios, error_code):
|
15
|
+
'''subroutine do_system_eigenanalysis(include_damping, n_modes, natural_frequencies, damping_ratios, error_code) &
|
16
|
+
logical(kind=c_bool), intent(in) :: include_damping
|
17
|
+
integer(kind=4), intent(in) :: n_modes
|
18
|
+
real(kind=c_double), dimension(n_modes), intent(out) :: natural_frequencies
|
19
|
+
real(kind=c_double), dimension(n_modes), intent(out) :: damping_ratios
|
20
|
+
integer(kind=8), intent(out) :: error_code
|
21
|
+
end subroutine'''
|
22
|
+
return self.get_lib_function('do_system_eigenanalysis')(include_damping, n_modes, natural_frequencies, damping_ratios, error_code)
|
23
|
+
|
14
24
|
def echo_version(self, ):
|
15
25
|
'''subroutine echo_version() BIND(C, NAME='echo_version')
|
16
26
|
!DEC$ ATTRIBUTES DLLEXPORT :: echo_version
|
@@ -218,6 +228,38 @@ end subroutine'''
|
|
218
228
|
end subroutine'''
|
219
229
|
return self.get_lib_function('get_sensor_values')(ids, values, n)
|
220
230
|
|
231
|
+
def get_system_eigval_eigvec_with_damping(self, n_modes, ny, eigenvalues, eigenvectors, error_code):
|
232
|
+
'''subroutine get_system_eigval_eigvec_with_damping(n_modes, ny, eigenvalues, eigenvectors, error_code) &
|
233
|
+
integer(kind=4), intent(in) :: n_modes
|
234
|
+
integer(kind=4), intent(in) :: ny
|
235
|
+
complex(kind=c_double_complex), dimension(n_modes), intent(out) :: eigenvalues
|
236
|
+
complex(kind=c_double_complex), dimension(ny, n_modes), intent(out) :: eigenvectors
|
237
|
+
integer(kind=8), intent(out) :: error_code
|
238
|
+
end subroutine'''
|
239
|
+
return self.get_lib_function('get_system_eigval_eigvec_with_damping')(n_modes, ny, eigenvalues, eigenvectors, error_code)
|
240
|
+
|
241
|
+
def get_system_eigval_eigvec_without_damping(self, n_modes, ny, eigenvalues, eigenvectors, error_code):
|
242
|
+
'''subroutine get_system_eigval_eigvec_without_damping(n_modes, ny, eigenvalues, eigenvectors, error_code) &
|
243
|
+
integer(kind=4), intent(in) :: n_modes
|
244
|
+
integer(kind=4), intent(in) :: ny
|
245
|
+
real(kind=c_double), dimension(n_modes), intent(out) :: eigenvalues
|
246
|
+
real(kind=c_double), dimension(ny, n_modes), intent(out) :: eigenvectors
|
247
|
+
integer(kind=8), intent(out) :: error_code
|
248
|
+
end subroutine'''
|
249
|
+
return self.get_lib_function('get_system_eigval_eigvec_without_damping')(n_modes, ny, eigenvalues, eigenvectors, error_code)
|
250
|
+
|
251
|
+
def get_system_matrices(self, n_tdofs, n_rdofs, M, C, K, R, error_code):
|
252
|
+
'''subroutine get_system_matrices(n_tdofs, n_rdofs, M, C, K, R, error_code) &
|
253
|
+
integer(kind=4), intent(in) :: n_tdofs
|
254
|
+
integer(kind=4), intent(in) :: n_rdofs
|
255
|
+
real(kind=c_double), dimension(n_rdofs, n_rdofs), intent(out) :: M
|
256
|
+
real(kind=c_double), dimension(n_rdofs, n_rdofs), intent(out) :: C
|
257
|
+
real(kind=c_double), dimension(n_rdofs, n_rdofs), intent(out) :: K
|
258
|
+
real(kind=c_double), dimension(n_tdofs, n_rdofs), intent(out) :: R
|
259
|
+
integer(kind=8), intent(out) :: error_code
|
260
|
+
end subroutine'''
|
261
|
+
return self.get_lib_function('get_system_matrices')(n_tdofs, n_rdofs, M, C, K, R, error_code)
|
262
|
+
|
221
263
|
def get_time(self, time):
|
222
264
|
'''subroutine
|
223
265
|
subroutine'''
|
@@ -247,12 +289,6 @@ end subroutine'''
|
|
247
289
|
end subroutine'''
|
248
290
|
return self.get_lib_function('init')()
|
249
291
|
|
250
|
-
def init_static_solver(self, restype):
|
251
|
-
'''function init_static_solver() result(error_code) &
|
252
|
-
!DEC$ ATTRIBUTES DLLEXPORT :: init_static_solver
|
253
|
-
end function'''
|
254
|
-
return self.get_lib_function('init_static_solver')(restype=restype)
|
255
|
-
|
256
292
|
def init_windfield(self, Nxyz, dxyz, box_offset_yz, transport_speed):
|
257
293
|
'''subroutine init_windfield(Nxyz, dxyz, box_offset_yz, transport_speed) bind(C, name="init_windfield")
|
258
294
|
integer*8, dimension(3), intent(in) :: Nxyz
|
@@ -260,6 +296,13 @@ end function'''
|
|
260
296
|
end subroutine'''
|
261
297
|
return self.get_lib_function('init_windfield')(Nxyz, dxyz, box_offset_yz, transport_speed)
|
262
298
|
|
299
|
+
def linearize(self, n_tdofs, n_rdofs):
|
300
|
+
'''subroutine linearize(n_tdofs, n_rdofs) bind(C, name="linearize")
|
301
|
+
integer(kind=8), intent(out) :: n_tdofs
|
302
|
+
integer(kind=8), intent(out) :: n_rdofs
|
303
|
+
end subroutine'''
|
304
|
+
return self.get_lib_function('linearize')(n_tdofs, n_rdofs)
|
305
|
+
|
263
306
|
def loop(self, N, restype):
|
264
307
|
'''function loop(N) bind(C, Name='loop')
|
265
308
|
!DEC$ ATTRIBUTES DLLEXPORT :: loop
|
@@ -312,6 +355,20 @@ end function'''
|
|
312
355
|
end subroutine'''
|
313
356
|
return self.get_lib_function('set_aerosections_windspeed')(rotor, uvw)
|
314
357
|
|
358
|
+
def set_orientation_base(self, main_body_name,
|
359
|
+
mbdy_eulerang_table, n_rows, angles_in_deg, reset_orientation, mbdy_ini_rotvec_d1,
|
360
|
+
error_code):
|
361
|
+
'''subroutine set_orientation_base(main_body_name,&
|
362
|
+
character(kind=c_char, len=1), dimension(256), intent(in) :: main_body_name
|
363
|
+
integer(kind=4), intent(in) :: n_rows
|
364
|
+
logical, intent(in) :: angles_in_deg
|
365
|
+
logical, intent(in) :: reset_orientation
|
366
|
+
real(kind=c_double), dimension(4), intent(in) :: mbdy_ini_rotvec_d1
|
367
|
+
end subroutine'''
|
368
|
+
return self.get_lib_function('set_orientation_base')(main_body_name,
|
369
|
+
mbdy_eulerang_table, n_rows, angles_in_deg, reset_orientation, mbdy_ini_rotvec_d1,
|
370
|
+
error_code)
|
371
|
+
|
315
372
|
def set_variable_sensor_value(self, id, value):
|
316
373
|
'''subroutine set_variable_sensor_value(id, value) bind(C, name="set_variable_sensor_value")
|
317
374
|
integer*8, intent(in) :: id
|
@@ -326,6 +383,36 @@ end function'''
|
|
326
383
|
end subroutine'''
|
327
384
|
return self.get_lib_function('set_windfield')(uvw, box_offset_x, time)
|
328
385
|
|
386
|
+
def solver_static_delete(self, ):
|
387
|
+
'''subroutine solver_static_delete() &
|
388
|
+
!DEC$ ATTRIBUTES DLLEXPORT :: solver_static_delete
|
389
|
+
end subroutine'''
|
390
|
+
return self.get_lib_function('solver_static_delete')()
|
391
|
+
|
392
|
+
def solver_static_init(self, ):
|
393
|
+
'''subroutine solver_static_init() &
|
394
|
+
!DEC$ ATTRIBUTES DLLEXPORT :: solver_static_init
|
395
|
+
end subroutine'''
|
396
|
+
return self.get_lib_function('solver_static_init')()
|
397
|
+
|
398
|
+
def solver_static_run(self, error_code):
|
399
|
+
'''subroutine solver_static_run(error_code) bind(C, name="solver_static_run")
|
400
|
+
integer(8), intent(out) :: error_code
|
401
|
+
end subroutine'''
|
402
|
+
return self.get_lib_function('solver_static_run')(error_code)
|
403
|
+
|
404
|
+
def solver_static_solve(self, error_code):
|
405
|
+
'''subroutine solver_static_solve(error_code) &
|
406
|
+
integer*8, intent(out) :: error_code
|
407
|
+
end subroutine'''
|
408
|
+
return self.get_lib_function('solver_static_solve')(error_code)
|
409
|
+
|
410
|
+
def solver_static_update(self, error_code):
|
411
|
+
'''subroutine solver_static_update(error_code) &
|
412
|
+
integer*8, intent(out) :: error_code
|
413
|
+
end subroutine'''
|
414
|
+
return self.get_lib_function('solver_static_update')(error_code)
|
415
|
+
|
329
416
|
def sqr2(self, val):
|
330
417
|
'''subroutine sqr2(val) BIND(C, NAME='sqr2')
|
331
418
|
integer, intent(inout) :: val
|
@@ -362,5 +449,9 @@ end function'''
|
|
362
449
|
def write_output(self, ):
|
363
450
|
'''subroutine write_output() bind(C, name="write_output")
|
364
451
|
!DEC$ ATTRIBUTES DLLEXPORT :: write_output
|
452
|
+
logical :: firstcall
|
453
|
+
integer :: nr, dummy=1
|
454
|
+
character*10 :: status = 'close';
|
455
|
+
Type (Toutvar) :: ov_dummy
|
365
456
|
end subroutine'''
|
366
457
|
return self.get_lib_function('write_output')()
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: h2lib
|
3
|
-
Version: 13.1.
|
4
|
-
Summary: Python interface to HAWC2 (13.1.5
|
3
|
+
Version: 13.1.901
|
4
|
+
Summary: Python interface to HAWC2 (13.1.9+5-g2026dd7)
|
5
5
|
Download-URL:
|
6
6
|
Author: Mads M. Pedersen, S.G.Horcas and N.G.Ramos
|
7
7
|
Author-email: mmpe@dtu.dk
|
@@ -0,0 +1,10 @@
|
|
1
|
+
h2lib/HAWC2Lib.dll,sha256=sIZhsbsubvdSV1FYMFwm3o182LX443SmME3ak8QwLWM,30803968
|
2
|
+
h2lib/__init__.py,sha256=f3fO4I6IEFRM9LaV2O3w9Pioj3GPI8qRl7P5Tg5ONtE,528
|
3
|
+
h2lib/_h2lib.py,sha256=povKoDnyzYF2xET29CxkBYKSYJc5yRjn7J4Xdw8qTow,30363
|
4
|
+
h2lib/_version.py,sha256=36To1Vn7m9W0-ewELpaoXNd4wDAXEYhnaDUyBw5QI-k,157
|
5
|
+
h2lib/dll_wrapper.py,sha256=CfuRfDPEmmfYlEGKUmiXiuMhNiMcf24ripPHgqd8CiE,12761
|
6
|
+
h2lib/h2lib_signatures.py,sha256=BknUitXekKaOH9reEHDnBPN-ThAHFeHnfdD41UlJ8Y8,21780
|
7
|
+
h2lib-13.1.901.dist-info/METADATA,sha256=IEbAB9rC-p8IT1nmtagD7xSRUhaY0l7vAZNYqeZg5_U,738
|
8
|
+
h2lib-13.1.901.dist-info/WHEEL,sha256=62QJgqtUFevqILau0n0UncooEMoOyVCKVQitJpcuCig,101
|
9
|
+
h2lib-13.1.901.dist-info/top_level.txt,sha256=y_a-tUqphEZQ_0nsWSMaSb21P8Lsd8hUxUdE9g2Dcbk,6
|
10
|
+
h2lib-13.1.901.dist-info/RECORD,,
|
h2lib-13.1.505.dist-info/RECORD
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
h2lib/HAWC2Lib.dll,sha256=IGuHPScAOZ_H6Mar3pcaZkYvWdZ1-8-s3JoJj2hNQcQ,30576128
|
2
|
-
h2lib/__init__.py,sha256=f3fO4I6IEFRM9LaV2O3w9Pioj3GPI8qRl7P5Tg5ONtE,528
|
3
|
-
h2lib/_h2lib.py,sha256=itCf0sXkdYekNLg9fFu_zi9n_pCV660SvbRoD8clPDk,20558
|
4
|
-
h2lib/_version.py,sha256=-tWFhe0RjnHTZr6S5BuRysb-EOM4i5jWwSA5k18ne1E,157
|
5
|
-
h2lib/dll_wrapper.py,sha256=RC5_gJ1cwHXVfUaSvmsatyQrvks-aZJFAiXrG4B-FEI,12061
|
6
|
-
h2lib/h2lib_signatures.py,sha256=j0TL8Zv6kX18F28X5cdzTlwQd1ZKiyg_zVBRqdOCPhY,16858
|
7
|
-
h2lib-13.1.505.dist-info/METADATA,sha256=sd7TmknyNYz91Xig6ZUbYZFT6WymETsemf0x-dX9kTo,738
|
8
|
-
h2lib-13.1.505.dist-info/WHEEL,sha256=3vidnDuZ-QSnHIxLhNbI1gIM-KgyEcMHuZuv1mWPd_Q,101
|
9
|
-
h2lib-13.1.505.dist-info/top_level.txt,sha256=y_a-tUqphEZQ_0nsWSMaSb21P8Lsd8hUxUdE9g2Dcbk,6
|
10
|
-
h2lib-13.1.505.dist-info/RECORD,,
|
File without changes
|