h2lib-tests 13.1.506__py3-none-any.whl → 13.1.1701__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- h2lib_tests/conftest.py +373 -0
- h2lib_tests/test_ellipsys_couplings.py +4 -4
- h2lib_tests/test_files/DTU_10_MW/htc/DTU_10MW_RWT.htc +2 -2
- h2lib_tests/test_files/DTU_10_MW/htc/DTU_10MW_RWT_no_aerodrag.htc +670 -0
- h2lib_tests/test_files/DTU_10_MW/htc/DTU_10MW_RWT_yaw_acturator.htc +1 -1
- h2lib_tests/test_h2lib.py +23 -0
- h2lib_tests/test_h2rotor.py +108 -2
- h2lib_tests/test_lin.py +191 -0
- h2lib_tests/test_mpi.py +1 -1
- h2lib_tests/test_static_solver.py +56 -29
- h2lib_tests/test_topology_h2lib.py +171 -39
- {h2lib_tests-13.1.506.dist-info → h2lib_tests-13.1.1701.dist-info}/METADATA +2 -3
- {h2lib_tests-13.1.506.dist-info → h2lib_tests-13.1.1701.dist-info}/RECORD +15 -13
- {h2lib_tests-13.1.506.dist-info → h2lib_tests-13.1.1701.dist-info}/WHEEL +1 -1
- h2lib_tests/test_write_htc.py +0 -126
- {h2lib_tests-13.1.506.dist-info → h2lib_tests-13.1.1701.dist-info}/top_level.txt +0 -0
h2lib_tests/test_h2lib.py
CHANGED
@@ -328,3 +328,26 @@ def test_fail():
|
|
328
328
|
# , match=re.escape('H2LibThread process died before or while executing fail(...)')):
|
329
329
|
with pytest.raises(Exception):
|
330
330
|
h2.fail('MyError')
|
331
|
+
|
332
|
+
|
333
|
+
def test_dont_stop(capfd):
|
334
|
+
# This test is the same as test_error(), but instead we disable stop.
|
335
|
+
model_path = tfp + "minimal/"
|
336
|
+
htc = HTCFile(model_path + 'htc/minimal_mann_turb.htc')
|
337
|
+
htc.wind.scale_time_start = 200
|
338
|
+
htc.wind.turb_format = 1
|
339
|
+
htc.wind.mann.dont_scale = 0
|
340
|
+
htc.set_name('tmp')
|
341
|
+
htc.save()
|
342
|
+
|
343
|
+
with H2Lib() as h2:
|
344
|
+
h2.stop_on_error(False)
|
345
|
+
h2.init('htc/tmp.htc', model_path)
|
346
|
+
out, err = capfd.readouterr()
|
347
|
+
assert "*** ERROR *** Turbulence scale_time_start >= simulation length" in out
|
348
|
+
|
349
|
+
with MultiH2Lib(2) as h2:
|
350
|
+
h2.stop_on_error(False)
|
351
|
+
h2.init('htc/tmp.htc', model_path)
|
352
|
+
out, err = capfd.readouterr()
|
353
|
+
assert "*** ERROR *** Turbulence scale_time_start >= simulation length" in out
|
h2lib_tests/test_h2rotor.py
CHANGED
@@ -4,10 +4,11 @@ from numpy import testing as npt
|
|
4
4
|
import pytest
|
5
5
|
from wetb.gtsdf import gtsdf
|
6
6
|
|
7
|
-
from h2lib_tests.dtu10mw import DTU10MW
|
7
|
+
from h2lib_tests.dtu10mw import DTU10MW, DTU10MWRotor, DTU10MWSimple
|
8
8
|
from h2lib_tests.test_files import tfp
|
9
9
|
import matplotlib.pyplot as plt
|
10
10
|
import numpy as np
|
11
|
+
from wetb.hawc2.at_time_file import AtTimeFile
|
11
12
|
|
12
13
|
|
13
14
|
def get_h2(htc_path='htc/DTU_10MW_RWT.htc'):
|
@@ -115,7 +116,7 @@ def test_rotor_avg_windspeed():
|
|
115
116
|
|
116
117
|
def test_aerosections():
|
117
118
|
plot = False
|
118
|
-
h2 = get_h2()
|
119
|
+
h2 = get_h2(htc_path='htc/DTU_10MW_RWT_no_aerodrag.htc')
|
119
120
|
# blade 1, global coo, r>30
|
120
121
|
pos_ids = [h2.add_sensor(f'aero position 3 1 {xyz} 30')[0] for xyz in [1, 2, 3]]
|
121
122
|
wsp_ids = [h2.add_sensor(f'aero windspeed 3 1 {xyz} 30')[0] for xyz in [1, 2, 3]]
|
@@ -173,6 +174,111 @@ def test_aerosections():
|
|
173
174
|
h2.close()
|
174
175
|
|
175
176
|
|
177
|
+
def test_compare_aerosection_coupling():
|
178
|
+
"""Compare simulations with 1) htc wind and 2) similar wind set to aerodynamic sections
|
179
|
+
|
180
|
+
- yaw=20, tilt=10, cone=5
|
181
|
+
- two blades (to check that xyz/uvw are not mixed up with number of blades)
|
182
|
+
- stiff structure, fixed rotor speed and pitch
|
183
|
+
- linear shear and no turb
|
184
|
+
- aero_calc=1, induction=0, tiploss=0, dynstall=2
|
185
|
+
- aerodrag turned off (requires wind speed at aerodrag sections, not implemented yet)
|
186
|
+
"""
|
187
|
+
dtu10 = DTU10MWSimple(rotor_speed=.6, pitch=0, nbodies=1)
|
188
|
+
dtu10.set_stiff()
|
189
|
+
|
190
|
+
dtu10.set_wind(8, tint=0, turb_format=0, shear=(4, .01))
|
191
|
+
dtu10.set_tilt_cone_yaw(tilt=10, cone=5, yaw=20)
|
192
|
+
# remove third blade
|
193
|
+
dtu10.aero.nblades = 2
|
194
|
+
dtu10.aero.link__3.delete()
|
195
|
+
|
196
|
+
dtu10.aerodrag.delete()
|
197
|
+
|
198
|
+
T = 20
|
199
|
+
dtu10.set_time(0, T)
|
200
|
+
dtu10.set_aero(aero_calc=1, induction=0, tiploss=0, dynstall=2)
|
201
|
+
|
202
|
+
for coo in [3, 4]:
|
203
|
+
for xyz in [1, 2, 3]:
|
204
|
+
dtu10.output.add_sensor('aero', 'windspeed', [coo, 1, xyz, 72, 1])
|
205
|
+
for coo in [3]:
|
206
|
+
for xyz in [1, 2, 3]:
|
207
|
+
dtu10.output.add_sensor('aero', 'position', [coo, 1, xyz, 72, 1])
|
208
|
+
|
209
|
+
# At time sensors
|
210
|
+
at = dtu10.add_section(f'output_at_time aero {T}')
|
211
|
+
at.filename = "tmp1_at"
|
212
|
+
for sensor in ['vrel', 'alfa', 'alfadot', 'cl', 'cd', 'cm', 'lift', 'drag', 'moment', 'ct_local', 'cq_local', 'tiploss_f',
|
213
|
+
'chord', 'inflow_angle', 'dcldalfa', 'dcddalfa', 'twist']:
|
214
|
+
at.add_sensor('', sensor, [1])
|
215
|
+
|
216
|
+
for sensor in ['inipos']:
|
217
|
+
for xyz in [1, 2, 3]:
|
218
|
+
at.add_sensor('', sensor, [1, xyz])
|
219
|
+
for sensor in ['secforce', 'secmoment', 'int_moment', 'int_force', 'position', 'velocity', 'acceleration', 'induc',
|
220
|
+
'windspeed']:
|
221
|
+
for coo in [1, 2, 3, 4]:
|
222
|
+
for xyz in [1, 2, 3]:
|
223
|
+
at.add_sensor('', sensor, [1, xyz, coo])
|
224
|
+
|
225
|
+
dtu10.set_name('tmp1')
|
226
|
+
dtu10.save()
|
227
|
+
with H2Lib(suppress_output=True) as h2:
|
228
|
+
h2.init(dtu10.filename, dtu10.modelpath)
|
229
|
+
h2.run(T)
|
230
|
+
|
231
|
+
dtu10.wind.wsp = 20 # ensure htc wind speed is different and induction is large in case it by mistake is not turned off
|
232
|
+
at.filename = "tmp2_at"
|
233
|
+
dtu10.set_name('tmp2')
|
234
|
+
dtu10.save()
|
235
|
+
|
236
|
+
with H2Lib(suppress_output=True) as h2:
|
237
|
+
h2.init(dtu10.filename, dtu10.modelpath)
|
238
|
+
last_pos_gl_xyz = np.array(h2.get_aerosections_position(), order='F')
|
239
|
+
while h2.time < T:
|
240
|
+
pos_gl_xyz = np.array(h2.get_aerosections_position(), order='F')
|
241
|
+
uvw = np.asfortranarray(pos_gl_xyz * 0)
|
242
|
+
dpos_gl_xyz = (pos_gl_xyz - last_pos_gl_xyz)
|
243
|
+
next_pos_gl_xyz = pos_gl_xyz + dpos_gl_xyz
|
244
|
+
uvw[:, :, 0] = (-next_pos_gl_xyz[:, :, 2] - 119) * .01 + 8
|
245
|
+
last_pos_gl_xyz = pos_gl_xyz.copy()
|
246
|
+
h2.set_aerosections_windspeed(uvw)
|
247
|
+
h2.step()
|
248
|
+
|
249
|
+
time, data1, info = gtsdf.load(tfp + 'DTU_10_MW/res/tmp1.hdf5')
|
250
|
+
time, data2, info = gtsdf.load(tfp + 'DTU_10_MW/res/tmp2.hdf5')
|
251
|
+
# exclude first time step where position extrapolation is not active
|
252
|
+
for n, c1, c2 in zip(info['attribute_names'], data1[1:].T, data2[1:].T):
|
253
|
+
if n not in ['WSP gl. coo.,Vx', 'WSP gl. coo.,Vy', 'WSP gl. coo.,Vz']: # nan
|
254
|
+
max_rel_err = np.abs(c2 - c1).max() / np.maximum(np.abs(c2).max(), 1)
|
255
|
+
try:
|
256
|
+
assert max_rel_err < 0.00001, n
|
257
|
+
except BaseException:
|
258
|
+
if 0:
|
259
|
+
plt.title(n)
|
260
|
+
plt.plot(c1)
|
261
|
+
plt.plot(c2)
|
262
|
+
plt.plot((c1 - c2))
|
263
|
+
plt.show()
|
264
|
+
raise
|
265
|
+
|
266
|
+
at1 = AtTimeFile(tfp + 'DTU_10_MW/tmp1_at.dat')
|
267
|
+
at2 = AtTimeFile(tfp + 'DTU_10_MW/tmp2_at.dat')
|
268
|
+
for n, c1, c2 in zip(at1.attribute_names, at1.data.T, at2.data.T):
|
269
|
+
npt.assert_allclose(c2, c1, atol=1e-6, rtol=0.0001, err_msg=n)
|
270
|
+
try:
|
271
|
+
assert max_rel_err < 0.00001, n
|
272
|
+
except BaseException:
|
273
|
+
if 1:
|
274
|
+
plt.title(n)
|
275
|
+
plt.plot(c1)
|
276
|
+
plt.plot(c2)
|
277
|
+
plt.plot(c1 - c2)
|
278
|
+
plt.show()
|
279
|
+
raise
|
280
|
+
|
281
|
+
|
176
282
|
def test_iea15MW():
|
177
283
|
with H2Lib(suppress_output=True) as h2:
|
178
284
|
h2.read_input(htc_path='htc/IEA_15MW_RWT_Onshore.htc', model_path=tfp + 'IEA-15-240-RWT-Onshore')
|
h2lib_tests/test_lin.py
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
Test the system-eigenanalysis.
|
4
|
+
|
5
|
+
@author: ricriv
|
6
|
+
"""
|
7
|
+
|
8
|
+
# Here we are relying on the default behavior of pytest, which is to execute
|
9
|
+
# the tests in the same order that they are specified.
|
10
|
+
# If one day this will not be the case anymore, we can enforce the order by
|
11
|
+
# using the solution proposed at: https://stackoverflow.com/a/77793427/3676517
|
12
|
+
|
13
|
+
import pytest
|
14
|
+
|
15
|
+
import numpy as np
|
16
|
+
from numpy import testing as npt
|
17
|
+
|
18
|
+
from h2lib._h2lib import H2Lib
|
19
|
+
from h2lib_tests.test_files import tfp
|
20
|
+
|
21
|
+
|
22
|
+
def test_system_not_linearized_1(h2_dtu_10mw_only_blade):
|
23
|
+
with pytest.raises(RuntimeError, match="SYSTEM_NOT_LINEARIZED"):
|
24
|
+
h2_dtu_10mw_only_blade.do_system_eigenanalysis(2)
|
25
|
+
|
26
|
+
|
27
|
+
def test_system_not_linearized_2(h2_dtu_10mw_only_blade):
|
28
|
+
with pytest.raises(RuntimeError, match="SYSTEM_NOT_LINEARIZED"):
|
29
|
+
h2_dtu_10mw_only_blade.get_system_eigenvalues_and_eigenvectors(2, 2)
|
30
|
+
|
31
|
+
|
32
|
+
def test_system_not_linearized_3(h2_dtu_10mw_only_blade):
|
33
|
+
with pytest.raises(RuntimeError, match="SYSTEM_NOT_LINEARIZED"):
|
34
|
+
h2_dtu_10mw_only_blade.get_system_matrices(312, 156)
|
35
|
+
|
36
|
+
|
37
|
+
def test_linearize(h2_dtu_10mw_only_blade):
|
38
|
+
n_tdofs, n_rdofs = h2_dtu_10mw_only_blade.linearize()
|
39
|
+
assert n_rdofs == 26 * 6 # = number of nodes * 6
|
40
|
+
assert n_tdofs == 26 * 6 * 2 # times 2 because of speed.
|
41
|
+
|
42
|
+
|
43
|
+
def test_too_many_modes(h2_dtu_10mw_only_blade):
|
44
|
+
with pytest.raises(ValueError, match="TOO_MANY_MODES_REQUESTED"):
|
45
|
+
h2_dtu_10mw_only_blade.do_system_eigenanalysis(n_modes=1000)
|
46
|
+
|
47
|
+
|
48
|
+
def test_sys_eig_not_done(h2_dtu_10mw_only_blade):
|
49
|
+
with pytest.raises(RuntimeError, match="SYSTEM_EIGENANALYSIS_NOT_DONE"):
|
50
|
+
h2_dtu_10mw_only_blade.get_system_eigenvalues_and_eigenvectors(2, 2)
|
51
|
+
|
52
|
+
|
53
|
+
def test_sys_eig_no_damping(h2_dtu_10mw_only_blade):
|
54
|
+
natural_frequencies = h2_dtu_10mw_only_blade.do_system_eigenanalysis(
|
55
|
+
n_modes=4, include_damping=False
|
56
|
+
)
|
57
|
+
# Test against: result at the time of writing.
|
58
|
+
npt.assert_allclose(
|
59
|
+
natural_frequencies,
|
60
|
+
np.array([0.610409, 0.930466, 1.739094, 2.761632]),
|
61
|
+
rtol=1e-6,
|
62
|
+
)
|
63
|
+
|
64
|
+
|
65
|
+
def test_sys_eig_no_damping_wrong_n_modes(h2_dtu_10mw_only_blade):
|
66
|
+
with pytest.raises(ValueError, match="TOO_MANY_MODES_REQUESTED"):
|
67
|
+
h2_dtu_10mw_only_blade.get_system_eigenvalues_and_eigenvectors(
|
68
|
+
1000, 156
|
69
|
+
)
|
70
|
+
|
71
|
+
|
72
|
+
def test_sys_eig_no_damping_wrong_ny(h2_dtu_10mw_only_blade):
|
73
|
+
with pytest.raises(ValueError, match="WRONG_REDUCED_DOF"):
|
74
|
+
h2_dtu_10mw_only_blade.get_system_eigenvalues_and_eigenvectors(4, 2)
|
75
|
+
|
76
|
+
|
77
|
+
def test_sys_eig_no_damping_eigv(h2_dtu_10mw_only_blade):
|
78
|
+
n_modes = 4
|
79
|
+
n_rdofs = 156
|
80
|
+
eig_val, eig_vec = (
|
81
|
+
h2_dtu_10mw_only_blade.get_system_eigenvalues_and_eigenvectors(
|
82
|
+
n_modes, n_rdofs, include_damping=False
|
83
|
+
)
|
84
|
+
)
|
85
|
+
assert eig_val.size == n_modes
|
86
|
+
assert eig_vec.shape == (n_modes, n_rdofs)
|
87
|
+
assert eig_val.dtype == np.float64
|
88
|
+
assert eig_vec.dtype == np.float64
|
89
|
+
npt.assert_allclose(
|
90
|
+
eig_val,
|
91
|
+
np.array([3.83531, 5.846293, 10.927047, 17.351849]),
|
92
|
+
)
|
93
|
+
|
94
|
+
|
95
|
+
def test_sys_eig_with_damping(h2_dtu_10mw_only_blade):
|
96
|
+
freq, damp = h2_dtu_10mw_only_blade.do_system_eigenanalysis(
|
97
|
+
n_modes=4, include_damping=True
|
98
|
+
)
|
99
|
+
# Test against: result at the time of writing.
|
100
|
+
npt.assert_allclose(
|
101
|
+
freq, np.array([0.610409, 0.930468, 1.739098, 2.761702]), rtol=1e-6
|
102
|
+
)
|
103
|
+
npt.assert_allclose(
|
104
|
+
damp, np.array([0.004826, 0.004758, 0.013395, 0.014194]), atol=1e-6
|
105
|
+
)
|
106
|
+
|
107
|
+
|
108
|
+
def test_sys_eig_with_damping_eigv(h2_dtu_10mw_only_blade):
|
109
|
+
n_modes = 4
|
110
|
+
n_rdofs = 156
|
111
|
+
eig_val, eig_vec = (
|
112
|
+
h2_dtu_10mw_only_blade.get_system_eigenvalues_and_eigenvectors(
|
113
|
+
n_modes, n_rdofs, include_damping=True
|
114
|
+
)
|
115
|
+
)
|
116
|
+
assert eig_val.size == n_modes
|
117
|
+
assert eig_vec.shape == (n_modes, 2 * n_rdofs)
|
118
|
+
assert eig_val.dtype == np.complex128
|
119
|
+
assert eig_vec.dtype == np.complex128
|
120
|
+
npt.assert_allclose(
|
121
|
+
eig_val,
|
122
|
+
np.array(
|
123
|
+
[
|
124
|
+
-0.01851 - 3.835266j,
|
125
|
+
-0.027817 - 5.846237j,
|
126
|
+
-0.146367 - 10.926094j,
|
127
|
+
-0.246296 - 17.350536j,
|
128
|
+
]
|
129
|
+
),
|
130
|
+
atol=1e-6,
|
131
|
+
)
|
132
|
+
|
133
|
+
|
134
|
+
def test_get_system_matrices_wrong_nt(h2_dtu_10mw_only_blade):
|
135
|
+
with pytest.raises(ValueError, match="WRONG_TOTAL_DOF"):
|
136
|
+
h2_dtu_10mw_only_blade.get_system_matrices(300, 156)
|
137
|
+
|
138
|
+
|
139
|
+
def test_get_system_matrices_wrong_nr(h2_dtu_10mw_only_blade):
|
140
|
+
with pytest.raises(ValueError, match="WRONG_REDUCED_DOF"):
|
141
|
+
h2_dtu_10mw_only_blade.get_system_matrices(312, 150)
|
142
|
+
|
143
|
+
|
144
|
+
def test_get_system_matrices(h2_dtu_10mw_only_blade):
|
145
|
+
n_rdofs = 26 * 6
|
146
|
+
n_tdofs = 2 * n_rdofs
|
147
|
+
M, C, K, R = h2_dtu_10mw_only_blade.get_system_matrices(n_tdofs, n_rdofs)
|
148
|
+
assert M.shape == (n_rdofs, n_rdofs)
|
149
|
+
assert C.shape == (n_rdofs, n_rdofs)
|
150
|
+
assert K.shape == (n_rdofs, n_rdofs)
|
151
|
+
assert R.shape == (n_tdofs, n_rdofs)
|
152
|
+
|
153
|
+
|
154
|
+
def test_sys_eig_encrypted(h2_dtu_10mw_only_tower_encrypted):
|
155
|
+
n_tdofs, n_rdofs = h2_dtu_10mw_only_tower_encrypted.linearize()
|
156
|
+
n_modes = 4
|
157
|
+
freq, damp = h2_dtu_10mw_only_tower_encrypted.do_system_eigenanalysis(
|
158
|
+
n_modes=n_modes, include_damping=True
|
159
|
+
)
|
160
|
+
eig_val = h2_dtu_10mw_only_tower_encrypted.get_system_eigenvalues_and_eigenvectors(
|
161
|
+
n_modes=n_modes, n_rdofs=n_rdofs, include_damping=True
|
162
|
+
)
|
163
|
+
npt.assert_allclose(
|
164
|
+
freq,
|
165
|
+
np.array([0.770592, 0.770592, 3.449993, 3.449993]),
|
166
|
+
rtol=1e-6,
|
167
|
+
)
|
168
|
+
|
169
|
+
npt.assert_allclose(
|
170
|
+
damp,
|
171
|
+
np.array([0.010006, 0.010006, 0.044675, 0.044675]),
|
172
|
+
atol=1e-6,
|
173
|
+
)
|
174
|
+
npt.assert_allclose(
|
175
|
+
eig_val,
|
176
|
+
np.array(
|
177
|
+
[
|
178
|
+
-0.048444 - 4.84153j,
|
179
|
+
-0.048444 - 4.84153j,
|
180
|
+
-0.968409 - 21.6553j,
|
181
|
+
-0.968409 - 21.6553j,
|
182
|
+
]
|
183
|
+
),
|
184
|
+
atol=1e-6,
|
185
|
+
)
|
186
|
+
|
187
|
+
|
188
|
+
def test_test_get_system_matrices_encrypted(h2_dtu_10mw_only_tower_encrypted):
|
189
|
+
n_tdofs, n_rdofs = h2_dtu_10mw_only_tower_encrypted.linearize()
|
190
|
+
with pytest.raises(RuntimeError, match="STRUCTURE_IS_CONFIDENTIAL"):
|
191
|
+
h2_dtu_10mw_only_tower_encrypted.get_system_matrices(n_tdofs, n_rdofs)
|
h2lib_tests/test_mpi.py
CHANGED
@@ -110,7 +110,7 @@ def ellipsys_mpi_dummy_workflow():
|
|
110
110
|
|
111
111
|
with MultiH2Lib(N, suppress_output=True) as h2:
|
112
112
|
el = Ellipsys()
|
113
|
-
htc = HTCFile(tfp + 'DTU_10_MW/htc/
|
113
|
+
htc = HTCFile(tfp + 'DTU_10_MW/htc/DTU_10MW_RWT_no_aerodrag.htc')
|
114
114
|
for i in range(N):
|
115
115
|
htc.set_name(f'wt{i}')
|
116
116
|
htc.save()
|
@@ -18,31 +18,6 @@ from numpy import testing as npt
|
|
18
18
|
from h2lib._h2lib import H2Lib
|
19
19
|
from h2lib_tests.test_files import tfp
|
20
20
|
|
21
|
-
from .test_write_htc import (
|
22
|
-
write_dtu10mw_only_blade,
|
23
|
-
write_dtu10mw_only_blade_low_max_iter,
|
24
|
-
)
|
25
|
-
|
26
|
-
|
27
|
-
@pytest.fixture(scope="module")
|
28
|
-
def h2_dtu_10mw_only_blade(write_dtu10mw_only_blade):
|
29
|
-
h2 = H2Lib(suppress_output=True)
|
30
|
-
model_path = f"{tfp}DTU_10_MW/"
|
31
|
-
htc_path = "htc/DTU_10MW_RWT_only_blade.htc"
|
32
|
-
h2.init(htc_path=htc_path, model_path=model_path)
|
33
|
-
yield h2
|
34
|
-
h2.close()
|
35
|
-
|
36
|
-
|
37
|
-
@pytest.fixture(scope="module")
|
38
|
-
def h2_dtu10mw_only_blade_low_max_iter(write_dtu10mw_only_blade_low_max_iter):
|
39
|
-
h2 = H2Lib(suppress_output=True)
|
40
|
-
model_path = f"{tfp}DTU_10_MW/"
|
41
|
-
htc_path = "htc/DTU_10MW_RWT_only_blade_low_max_iter.htc"
|
42
|
-
h2.init(htc_path=htc_path, model_path=model_path)
|
43
|
-
yield h2
|
44
|
-
h2.close()
|
45
|
-
|
46
21
|
|
47
22
|
def test_solver_static_update_no_init(h2_dtu_10mw_only_blade):
|
48
23
|
with pytest.raises(RuntimeError, match="STATIC_SOLVER_NOT_INITIALIZED"):
|
@@ -77,7 +52,13 @@ def test_solver_static_delete(h2_dtu_10mw_only_blade):
|
|
77
52
|
h2_dtu_10mw_only_blade.solver_static_delete()
|
78
53
|
|
79
54
|
|
80
|
-
def
|
55
|
+
def test_static_solver_run_fail(h2_dtu10mw_only_blade_low_max_iter):
|
56
|
+
with pytest.raises(RuntimeError, match="STATIC_SOLVER_DID_NOT_CONVERGE"):
|
57
|
+
h2_dtu10mw_only_blade_low_max_iter.solver_static_run()
|
58
|
+
|
59
|
+
|
60
|
+
def test_static_solver_run_1(h2_dtu_10mw_only_blade):
|
61
|
+
# Use gravity to deflect the clamped blade.
|
81
62
|
# Add a sensor for the blade root moment, in this case only due to gravity.
|
82
63
|
id = h2_dtu_10mw_only_blade.add_sensor("mbdy momentvec blade1 1 1 blade1")
|
83
64
|
|
@@ -93,6 +74,52 @@ def test_static_solver_run(h2_dtu_10mw_only_blade):
|
|
93
74
|
)
|
94
75
|
|
95
76
|
|
96
|
-
def
|
97
|
-
with
|
98
|
-
|
77
|
+
def test_static_solver_run_2(h2_dtu_10mw_only_blade_rotate_base):
|
78
|
+
# Apply centrifugal loading with the base command.
|
79
|
+
# Add a sensor for the blade root force, in this case only due to centrifugal force.
|
80
|
+
id = h2_dtu_10mw_only_blade_rotate_base.add_sensor("mbdy forcevec blade1 1 1 blade1")
|
81
|
+
|
82
|
+
# Run the static solver.
|
83
|
+
h2_dtu_10mw_only_blade_rotate_base.solver_static_run()
|
84
|
+
|
85
|
+
# Do 1 step to get the output.
|
86
|
+
h2_dtu_10mw_only_blade_rotate_base.step()
|
87
|
+
val = h2_dtu_10mw_only_blade_rotate_base.get_sensor_values(id)
|
88
|
+
# Test against: result at the time of writing.
|
89
|
+
npt.assert_allclose(
|
90
|
+
val, np.array([10879.129998, 383.43168, 989.68145])
|
91
|
+
)
|
92
|
+
|
93
|
+
|
94
|
+
def test_static_solver_run_3(h2_dtu_10mw_only_blade_rotate_relative):
|
95
|
+
# Apply centrifugal loading with the relative command.
|
96
|
+
# Add a sensor for the blade root force, in this case only due to centrifugal force.
|
97
|
+
id = h2_dtu_10mw_only_blade_rotate_relative.add_sensor("mbdy forcevec blade1 1 1 blade1")
|
98
|
+
|
99
|
+
# Run the static solver.
|
100
|
+
h2_dtu_10mw_only_blade_rotate_relative.solver_static_run()
|
101
|
+
|
102
|
+
# Do 1 step to get the output.
|
103
|
+
h2_dtu_10mw_only_blade_rotate_relative.step()
|
104
|
+
val = h2_dtu_10mw_only_blade_rotate_relative.get_sensor_values(id)
|
105
|
+
# Test against: result at the time of writing.
|
106
|
+
npt.assert_allclose(
|
107
|
+
val, np.array([10879.083576, 383.430039, 989.67935])
|
108
|
+
)
|
109
|
+
|
110
|
+
|
111
|
+
def test_static_solver_run_4(h2_dtu_10mw_only_blade_rotate_bearing3):
|
112
|
+
# Apply centrifugal loading with the bearing3 command.
|
113
|
+
# Add a sensor for the blade root moment, in this case only due to centrifugal force.
|
114
|
+
id = h2_dtu_10mw_only_blade_rotate_bearing3.add_sensor("mbdy momentvec blade1 1 1 blade1")
|
115
|
+
|
116
|
+
# Run the static solver.
|
117
|
+
h2_dtu_10mw_only_blade_rotate_bearing3.solver_static_run()
|
118
|
+
|
119
|
+
# Do 1 step to get the output.
|
120
|
+
h2_dtu_10mw_only_blade_rotate_bearing3.step()
|
121
|
+
val = h2_dtu_10mw_only_blade_rotate_bearing3.get_sensor_values(id)
|
122
|
+
# Test against: result at the time of writing.
|
123
|
+
npt.assert_allclose(
|
124
|
+
val, np.array([-3094.986918, 115414.095937, 325.296806])
|
125
|
+
)
|