h2lib-tests 13.2.701__py3-none-any.whl → 13.2.801__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 +212 -7
- h2lib_tests/test_distributed_sections.py +86 -0
- h2lib_tests/test_h2lib.py +0 -7
- h2lib_tests/test_h2rotor.py +17 -1
- h2lib_tests/test_topology_h2lib.py +374 -15
- {h2lib_tests-13.2.701.dist-info → h2lib_tests-13.2.801.dist-info}/METADATA +3 -2
- {h2lib_tests-13.2.701.dist-info → h2lib_tests-13.2.801.dist-info}/RECORD +9 -9
- {h2lib_tests-13.2.701.dist-info → h2lib_tests-13.2.801.dist-info}/WHEEL +0 -0
- {h2lib_tests-13.2.701.dist-info → h2lib_tests-13.2.801.dist-info}/top_level.txt +0 -0
h2lib_tests/conftest.py
CHANGED
@@ -4,12 +4,15 @@ from wetb.hawc2.htc_file import HTCFile
|
|
4
4
|
from wetb.hawc2.mainbody import MainBody
|
5
5
|
from h2lib_tests.test_files import tfp
|
6
6
|
from h2lib._h2lib import H2Lib
|
7
|
+
from hawc2models import IEA22MW
|
7
8
|
|
8
9
|
|
10
|
+
# %% Write HAWC2 models of the DTU 10 MW.
|
11
|
+
|
9
12
|
@pytest.fixture(scope="session")
|
10
13
|
def write_dtu10mw_only_tower():
|
11
14
|
# Start from DTU_10MW_RWT and delete everything except the tower.
|
12
|
-
htc = HTCFile(tfp
|
15
|
+
htc = HTCFile(f"{tfp}DTU_10_MW/htc/DTU_10MW_RWT.htc")
|
13
16
|
htc.set_name("DTU_10MW_RWT_only_tower")
|
14
17
|
for key1 in htc["new_htc_structure"].keys():
|
15
18
|
if key1.startswith("main_body"):
|
@@ -69,7 +72,7 @@ def write_dtu10mw_only_tower_encrypted(write_dtu10mw_only_tower):
|
|
69
72
|
@pytest.fixture(scope="session")
|
70
73
|
def write_dtu10mw_only_blade():
|
71
74
|
# Start from DTU_10MW_RWT and delete everything except the blade.
|
72
|
-
htc = HTCFile(tfp
|
75
|
+
htc = HTCFile(f"{tfp}DTU_10_MW/htc/DTU_10MW_RWT.htc")
|
73
76
|
htc.set_name("DTU_10MW_RWT_only_blade")
|
74
77
|
for key1 in htc["new_htc_structure"].keys():
|
75
78
|
if key1.startswith("main_body"):
|
@@ -177,7 +180,7 @@ def write_dtu10mw_only_blade_rotate_relative():
|
|
177
180
|
# Start from DTU_10MW_RWT and delete everything except the blade and hub.
|
178
181
|
# The blade now rotates because of the relative rotation.
|
179
182
|
# Because of the fix1 constraint, the blade will not rotate after time 0.
|
180
|
-
htc = HTCFile(tfp
|
183
|
+
htc = HTCFile(f"{tfp}DTU_10_MW/htc/DTU_10MW_RWT.htc")
|
181
184
|
htc.set_name("DTU_10MW_RWT_only_blade_rotate_relative")
|
182
185
|
for key1 in (
|
183
186
|
"main_body", # tower
|
@@ -265,7 +268,7 @@ def write_dtu10mw_only_blade_rotate_relative():
|
|
265
268
|
def write_dtu10mw_only_blade_rotate_bearing3():
|
266
269
|
# Start from DTU_10MW_RWT and delete everything except the blade and hub.
|
267
270
|
# The blade now rotates because of the bearing3 between the blade and hub.
|
268
|
-
htc = HTCFile(tfp
|
271
|
+
htc = HTCFile(f"{tfp}DTU_10_MW/htc/DTU_10MW_RWT.htc")
|
269
272
|
htc.set_name("DTU_10MW_RWT_only_blade_rotate_bearing3")
|
270
273
|
for key1 in (
|
271
274
|
"main_body", # tower
|
@@ -376,11 +379,12 @@ def write_dtu10mw_only_blade_high_gravity(
|
|
376
379
|
htc.new_htc_structure.main_body__7.gravity = 100.0
|
377
380
|
mb = MainBody(htc, "blade1")
|
378
381
|
blade_c2def = mb.c2def
|
382
|
+
blade_st = mb.stFile
|
379
383
|
# Somehow the wind and output blocks are back.
|
380
384
|
htc["wind"].delete()
|
381
385
|
htc["output"].delete()
|
382
386
|
htc.save()
|
383
|
-
return htc, blade_c2def
|
387
|
+
return htc, blade_c2def, blade_st
|
384
388
|
|
385
389
|
|
386
390
|
@pytest.fixture(scope="session")
|
@@ -388,17 +392,18 @@ def write_dtu10mw_only_blade_high_gravity_1_body(
|
|
388
392
|
write_dtu10mw_only_blade_high_gravity,
|
389
393
|
):
|
390
394
|
# Start from the write_dtu10mw_only_blade_high_gravity and then set 1 body.
|
391
|
-
htc_ori, _ = write_dtu10mw_only_blade_high_gravity
|
395
|
+
htc_ori, _, _ = write_dtu10mw_only_blade_high_gravity
|
392
396
|
htc = htc_ori.copy()
|
393
397
|
htc.set_name("DTU_10MW_RWT_only_blade_high_gravity_1_body")
|
394
398
|
htc.new_htc_structure.main_body__7.nbodies = 1
|
395
399
|
mb = MainBody(htc, "blade1")
|
396
400
|
blade_c2def = mb.c2def
|
401
|
+
blade_st = mb.stFile
|
397
402
|
# Somehow the wind and output blocks are back.
|
398
403
|
htc["wind"].delete()
|
399
404
|
htc["output"].delete()
|
400
405
|
htc.save()
|
401
|
-
return htc, blade_c2def
|
406
|
+
return htc, blade_c2def, blade_st
|
402
407
|
|
403
408
|
|
404
409
|
@pytest.fixture(scope="session")
|
@@ -429,6 +434,32 @@ def write_dtu10mw_only_blade_high_gravity_deformed(
|
|
429
434
|
return htc, blade_c2def
|
430
435
|
|
431
436
|
|
437
|
+
@pytest.fixture(scope="session")
|
438
|
+
def write_dtu10mw_only_blade_high_gravity_changed_st(
|
439
|
+
write_dtu10mw_only_blade,
|
440
|
+
):
|
441
|
+
# Start from the write_dtu10mw_only_blade and then increase the gravity loading.
|
442
|
+
htc = write_dtu10mw_only_blade.copy()
|
443
|
+
htc.set_name("DTU_10MW_RWT_only_blade_high_gravity_changed_st")
|
444
|
+
htc.new_htc_structure.main_body__7.gravity = 100.0
|
445
|
+
# Change ST
|
446
|
+
mb = MainBody(htc, "blade1")
|
447
|
+
blade_st = mb.stFile
|
448
|
+
rng = np.random.default_rng(seed=582)
|
449
|
+
factor = rng.uniform(low=0.7, high=1.3, size=19)
|
450
|
+
blade_st.main_data_sets[1][1] *= factor
|
451
|
+
# Current directory is hawc2lib/tests/h2lib_tests
|
452
|
+
blade_st.save(f"{tfp}DTU_10_MW/data/changed_st.dat", precision="%28.16e")
|
453
|
+
htc.new_htc_structure.main_body__7.timoschenko_input.filename = "./data/changed_st.dat"
|
454
|
+
# Somehow the wind and output blocks are back.
|
455
|
+
htc["wind"].delete()
|
456
|
+
htc["output"].delete()
|
457
|
+
htc.save()
|
458
|
+
return htc, blade_st
|
459
|
+
|
460
|
+
|
461
|
+
# %% Create H2Lib objects of the DTU 10 MW.
|
462
|
+
|
432
463
|
@pytest.fixture(scope="session")
|
433
464
|
def h2_dtu_10mw_only_tower(write_dtu10mw_only_tower):
|
434
465
|
h2 = H2Lib(suppress_output=True)
|
@@ -592,3 +623,177 @@ def h2_dtu10mw_only_blade_high_gravity_1_body(write_dtu10mw_only_blade_high_grav
|
|
592
623
|
h2.stop_on_error(False)
|
593
624
|
yield h2
|
594
625
|
h2.close()
|
626
|
+
|
627
|
+
|
628
|
+
@pytest.fixture(scope="session")
|
629
|
+
def h2_dtu10mw_only_blade_high_gravity_changed_st(write_dtu10mw_only_blade_high_gravity_changed_st):
|
630
|
+
h2 = H2Lib(suppress_output=True)
|
631
|
+
model_path = f"{tfp}DTU_10_MW/"
|
632
|
+
htc_path = "htc/DTU_10MW_RWT_only_blade_high_gravity_changed_st.htc"
|
633
|
+
h2.add_sensor("mbdy statevec_new blade1 c2def global absolute 90.0 1.0 0.0 0.0") # 1-6
|
634
|
+
h2.add_sensor("mbdy forcevec blade1 1 1 blade1") # 7, 8, 9
|
635
|
+
h2.add_sensor("mbdy momentvec blade1 1 1 blade1") # 10, 11, 12
|
636
|
+
h2.init(htc_path=htc_path, model_path=model_path)
|
637
|
+
h2.stop_on_error(False)
|
638
|
+
yield h2
|
639
|
+
h2.close()
|
640
|
+
|
641
|
+
|
642
|
+
# %% Write HAWC2 models of the IEA 22 MW.
|
643
|
+
|
644
|
+
@pytest.fixture(scope="session")
|
645
|
+
def write_iea22mw_rwt():
|
646
|
+
# Download HAWC2 model from GitHub repo.
|
647
|
+
htc = IEA22MW(folder=f"{tfp}IEA-22-280-RWT",
|
648
|
+
version="5f9bc425bcbda0723a1245bb4e0c1fc5d5439ed3") # Last commit on master from Aug 26, 2025
|
649
|
+
htc.make_onshore()
|
650
|
+
htc.save()
|
651
|
+
return htc
|
652
|
+
|
653
|
+
|
654
|
+
@pytest.fixture(scope="session")
|
655
|
+
def write_iea22mw_only_blade(write_iea22mw_rwt):
|
656
|
+
# Start from IEA-22-280-RWT and delete everything except the blade.
|
657
|
+
# htc = write_iea22mw_rwt.copy()
|
658
|
+
htc = HTCFile(f"{tfp}IEA-22-280-RWT/htc/iea_22mw_rwt.htc")
|
659
|
+
htc.set_name("IEA_22MW_RWT_only_blade")
|
660
|
+
for key1 in htc["new_htc_structure"].keys():
|
661
|
+
if key1.startswith("main_body"):
|
662
|
+
if "blade1" not in htc["new_htc_structure"][key1]["name"].values:
|
663
|
+
htc["new_htc_structure"][key1].delete()
|
664
|
+
if key1 == "orientation":
|
665
|
+
htc["new_htc_structure"][key1].delete()
|
666
|
+
if key1 == "constraint":
|
667
|
+
htc["new_htc_structure"][key1].delete()
|
668
|
+
htc["wind"].delete()
|
669
|
+
htc["aerodrag"].delete()
|
670
|
+
htc["aero"].delete()
|
671
|
+
htc["dll"].delete()
|
672
|
+
htc["output"].delete()
|
673
|
+
|
674
|
+
# Set the blade horizontal, to maximize gravity loading.
|
675
|
+
htc.new_htc_structure.add_section("orientation")
|
676
|
+
htc.new_htc_structure.orientation.add_section("base")
|
677
|
+
htc.new_htc_structure.orientation.base.mbdy = "blade1"
|
678
|
+
htc.new_htc_structure.orientation.base.inipos = [0.0, 0.0, 0.0]
|
679
|
+
htc.new_htc_structure.orientation.base["mbdy_eulerang"] = [90.0, 0.0, 0.0]
|
680
|
+
htc.new_htc_structure.orientation.base.mbdy_eulerang.comments = (
|
681
|
+
"Blade span is horizontal."
|
682
|
+
)
|
683
|
+
|
684
|
+
# Clamp the blade.
|
685
|
+
htc.new_htc_structure.add_section("constraint")
|
686
|
+
htc.new_htc_structure.constraint.add_section("fix0")
|
687
|
+
htc.new_htc_structure.constraint.fix0.mbdy = "blade1"
|
688
|
+
|
689
|
+
# Set low convergence limits.
|
690
|
+
htc.simulation.convergence_limits = [1e2, 1e-5, 1e-07]
|
691
|
+
|
692
|
+
# No output, as we will use add_sensor().
|
693
|
+
|
694
|
+
# Save the new file.
|
695
|
+
htc.save()
|
696
|
+
|
697
|
+
return htc
|
698
|
+
|
699
|
+
|
700
|
+
@pytest.fixture(scope="session")
|
701
|
+
def write_iea22mw_only_blade_high_gravity(write_iea22mw_only_blade):
|
702
|
+
# Start from the write_iea22mw_only_blade and then increase the gravity loading.
|
703
|
+
htc = write_iea22mw_only_blade.copy()
|
704
|
+
htc.set_name("IEA_22MW_RWT_only_blade_high_gravity")
|
705
|
+
htc.new_htc_structure.main_body__8.gravity = 100.0
|
706
|
+
mb = MainBody(htc, "blade1")
|
707
|
+
blade_c2def = mb.c2def
|
708
|
+
blade_st = mb.stFile
|
709
|
+
# Somehow the wind and output blocks are back.
|
710
|
+
htc["wind"].delete()
|
711
|
+
htc["output"].delete()
|
712
|
+
htc.save()
|
713
|
+
return htc, blade_c2def, blade_st
|
714
|
+
|
715
|
+
|
716
|
+
@pytest.fixture(scope="session")
|
717
|
+
def write_iea22mw_only_blade_high_gravity_1_body(
|
718
|
+
write_iea22mw_only_blade_high_gravity,
|
719
|
+
):
|
720
|
+
# Start from the write_dtu10mw_only_blade_high_gravity and then set 1 body.
|
721
|
+
htc_ori, _, _ = write_iea22mw_only_blade_high_gravity
|
722
|
+
htc = htc_ori.copy()
|
723
|
+
htc.set_name("IEA_22MW_RWT_only_blade_high_gravity_1_body")
|
724
|
+
htc.new_htc_structure.main_body__8.nbodies = 1
|
725
|
+
mb = MainBody(htc, "blade1")
|
726
|
+
blade_c2def = mb.c2def
|
727
|
+
blade_st = mb.stFile
|
728
|
+
# Somehow the wind and output blocks are back.
|
729
|
+
htc["wind"].delete()
|
730
|
+
htc["output"].delete()
|
731
|
+
htc.save()
|
732
|
+
return htc, blade_c2def, blade_st
|
733
|
+
|
734
|
+
|
735
|
+
@pytest.fixture(scope="session")
|
736
|
+
def write_iea22mw_only_blade_high_gravity_changed_st(
|
737
|
+
write_iea22mw_only_blade,
|
738
|
+
):
|
739
|
+
# Start from the write_iea22mw_only_blade and then increase the gravity loading.
|
740
|
+
htc = write_iea22mw_only_blade.copy()
|
741
|
+
htc.set_name("IEA_22MW_RWT_only_blade_high_gravity_changed_st")
|
742
|
+
htc.new_htc_structure.main_body__8.gravity = 100.0
|
743
|
+
# Change ST
|
744
|
+
mb = MainBody(htc, "blade1")
|
745
|
+
blade_st = mb.stFile
|
746
|
+
rng = np.random.default_rng(seed=582)
|
747
|
+
# We change all columns except for the curved length.
|
748
|
+
factor = rng.uniform(low=0.7, high=1.3, size=29)
|
749
|
+
blade_st.main_data_sets[1][1][:, 1:] *= factor
|
750
|
+
# Current directory is hawc2lib/tests/h2lib_tests
|
751
|
+
blade_st.save(f"{tfp}IEA-22-280-RWT/data/changed_st_fpm.dat", precision="%28.16e")
|
752
|
+
htc.new_htc_structure.main_body__8.timoschenko_input.filename = "./data/changed_st_fpm.dat"
|
753
|
+
# Somehow the wind and output blocks are back.
|
754
|
+
htc["wind"].delete()
|
755
|
+
htc["output"].delete()
|
756
|
+
htc.save()
|
757
|
+
return htc, blade_st
|
758
|
+
|
759
|
+
|
760
|
+
# %% Create H2Lib objects of the IEA 22 MW.
|
761
|
+
|
762
|
+
@pytest.fixture(scope="session")
|
763
|
+
def h2_iea22mw_only_blade_high_gravity(write_iea22mw_only_blade_high_gravity):
|
764
|
+
h2 = H2Lib(suppress_output=True)
|
765
|
+
model_path = f"{tfp}IEA-22-280-RWT/"
|
766
|
+
htc_path = "htc/IEA_22MW_RWT_only_blade_high_gravity.htc"
|
767
|
+
h2.add_sensor("mbdy statevec_new blade1 c2def global absolute 90.0 1.0 0.0 0.0") # 1-6
|
768
|
+
h2.add_sensor("mbdy forcevec blade1 1 1 blade1") # 7, 8, 9
|
769
|
+
h2.add_sensor("mbdy momentvec blade1 1 1 blade1") # 10, 11, 12
|
770
|
+
h2.init(htc_path=htc_path, model_path=model_path)
|
771
|
+
h2.stop_on_error(False)
|
772
|
+
yield h2
|
773
|
+
h2.close()
|
774
|
+
|
775
|
+
|
776
|
+
@pytest.fixture(scope="session")
|
777
|
+
def h2_iea22mw_only_blade_high_gravity_1_body(write_iea22mw_only_blade_high_gravity_1_body):
|
778
|
+
h2 = H2Lib(suppress_output=True)
|
779
|
+
model_path = f"{tfp}IEA-22-280-RWT/"
|
780
|
+
htc_path = "htc/IEA_22MW_RWT_only_blade_high_gravity_1_body.htc"
|
781
|
+
h2.add_sensor("mbdy statevec_new blade1 c2def global absolute 90.0 1.0 0.0 0.0")
|
782
|
+
h2.init(htc_path=htc_path, model_path=model_path)
|
783
|
+
h2.stop_on_error(False)
|
784
|
+
yield h2
|
785
|
+
h2.close()
|
786
|
+
|
787
|
+
|
788
|
+
@pytest.fixture(scope="session")
|
789
|
+
def h2_iea22mw_only_blade_high_gravity_changed_st(write_iea22mw_only_blade_high_gravity_changed_st):
|
790
|
+
h2 = H2Lib(suppress_output=True)
|
791
|
+
model_path = f"{tfp}IEA-22-280-RWT/"
|
792
|
+
htc_path = "htc/IEA_22MW_RWT_only_blade_high_gravity_changed_st.htc"
|
793
|
+
h2.add_sensor("mbdy statevec_new blade1 c2def global absolute 90.0 1.0 0.0 0.0") # 1-6
|
794
|
+
h2.add_sensor("mbdy forcevec blade1 1 1 blade1") # 7, 8, 9
|
795
|
+
h2.add_sensor("mbdy momentvec blade1 1 1 blade1") # 10, 11, 12
|
796
|
+
h2.init(htc_path=htc_path, model_path=model_path)
|
797
|
+
h2.stop_on_error(False)
|
798
|
+
yield h2
|
799
|
+
h2.close()
|
@@ -6,6 +6,7 @@ from h2lib.distributed_sections import DistributedSections, LinkType
|
|
6
6
|
import numpy as np
|
7
7
|
from numpy import testing as npt
|
8
8
|
import matplotlib.pyplot as plt
|
9
|
+
from wetb.hawc2.htc_file import HTCFile
|
9
10
|
|
10
11
|
|
11
12
|
def test_distributed_sections():
|
@@ -109,3 +110,88 @@ def test_distributed_sections():
|
|
109
110
|
[-0.0, 0.7, -46.2],
|
110
111
|
[-0.0, 2.4, -92.5],
|
111
112
|
[0.0, 3.5, -115.6]], 1)
|
113
|
+
|
114
|
+
|
115
|
+
def test_distributed_sections_static_solver():
|
116
|
+
with H2Lib() as h2:
|
117
|
+
model_path = f"{tfp}DTU_10_MW/"
|
118
|
+
htc_path = f"{tfp}DTU_10_MW/htc/DTU_10MW_RWT_only_tower.htc"
|
119
|
+
h2.init(htc_path=htc_path, model_path=model_path)
|
120
|
+
ds = h2.add_distributed_sections(mainbody_name='tower', section_relative_position=[0, .5, 1])
|
121
|
+
h2.initialize_distributed_sections()
|
122
|
+
|
123
|
+
ax = plt.figure().add_subplot(projection='3d')
|
124
|
+
|
125
|
+
def draw(label, ref):
|
126
|
+
pos = h2.get_mainbody_nodes_state(mainbody_nr=1, state='pos')
|
127
|
+
# print(label, np.round(pos[-1], 4).tolist())
|
128
|
+
npt.assert_array_almost_equal(pos[-1], ref, 4)
|
129
|
+
ax.plot(*pos.T, marker='.', label=label)
|
130
|
+
ax.set_zlim([0, -120])
|
131
|
+
|
132
|
+
pos = h2.get_mainbody_nodes_state(mainbody_nr=1, state='pos')
|
133
|
+
|
134
|
+
draw('initial', [0.0, 0.0, -115.63])
|
135
|
+
|
136
|
+
frc = np.zeros((3, 3))
|
137
|
+
frc[:, 1] = 100000
|
138
|
+
h2.set_distributed_section_force_and_moment(ds, sec_frc=frc, sec_mom=frc * 0)
|
139
|
+
h2.solver_static_run(reset_structure=True)
|
140
|
+
draw('set frc + static solver', [0.0, 1.8295, -115.6123])
|
141
|
+
c2_def = np.concatenate([pos, pos[:, :1]], 1)
|
142
|
+
c2_def[:, 0] = np.r_[np.arange(0, 60, 10), np.arange(50, 0, -10)]
|
143
|
+
h2.set_c2_def('tower', c2_def)
|
144
|
+
draw('set_c2_def', [10.0, 0.1184, -115.6296])
|
145
|
+
h2.solver_static_run(reset_structure=True)
|
146
|
+
draw('static solver', [10.2777, 2.8085, -115.5066])
|
147
|
+
h2.set_distributed_section_force_and_moment(ds, sec_frc=-frc, sec_mom=frc * 0)
|
148
|
+
h2.solver_static_run(reset_structure=True)
|
149
|
+
draw('set -frc + static solver', [10.2859, -2.8064, -115.5011])
|
150
|
+
if 0:
|
151
|
+
plt.legend()
|
152
|
+
plt.show()
|
153
|
+
else:
|
154
|
+
plt.close('all')
|
155
|
+
|
156
|
+
|
157
|
+
def test_set_distributed_section_force_and_moment_coo():
|
158
|
+
with H2Lib() as h2:
|
159
|
+
model_path = f"{tfp}DTU_10_MW/"
|
160
|
+
htc = HTCFile(model_path + "htc/DTU_10MW_RWT_only_tower.htc")
|
161
|
+
htc.new_htc_structure.orientation.base.body_eulerang = 0, 0, 90
|
162
|
+
htc.save(model_path + "htc/DTU_10MW_RWT_only_tower_rot90.htc")
|
163
|
+
print(htc)
|
164
|
+
h2.init(htc_path=htc.filename, model_path=model_path)
|
165
|
+
ds = h2.add_distributed_sections(mainbody_name='tower', section_relative_position=[0, .5, 1])
|
166
|
+
h2.initialize_distributed_sections()
|
167
|
+
|
168
|
+
ax = plt.figure().add_subplot(projection='3d')
|
169
|
+
|
170
|
+
def draw(label, ref):
|
171
|
+
h2.solver_static_run()
|
172
|
+
pos = h2.get_mainbody_nodes_state(mainbody_nr=1, state='pos')
|
173
|
+
print(label, np.round(pos[-1], 4).tolist())
|
174
|
+
ax.plot(*pos.T, marker='.', label=label)
|
175
|
+
npt.assert_array_almost_equal(pos[-1], ref, 4)
|
176
|
+
|
177
|
+
draw('init', [0.0, 0.0, -115.6281])
|
178
|
+
frc = np.zeros((3, 3))
|
179
|
+
frc[:, 1] = 2e6
|
180
|
+
h2.set_distributed_section_force_and_moment(ds, sec_frc=frc, sec_mom=frc * 0)
|
181
|
+
draw('frc_y_global', [-0.0, 34.7544, -109.7119])
|
182
|
+
|
183
|
+
h2.set_distributed_section_force_and_moment(ds, sec_frc=frc, sec_mom=frc * 0, mainbody_coo_nr=1)
|
184
|
+
draw('frc_y_tower', [-34.7545, 0.0, -109.7119])
|
185
|
+
|
186
|
+
if 0:
|
187
|
+
ax.axis('equal')
|
188
|
+
ax.set_zlim([0, -120])
|
189
|
+
ax.set_xlabel('x')
|
190
|
+
ax.set_ylabel('y')
|
191
|
+
ax.set_zlabel('z')
|
192
|
+
ax.plot([0, 0], [0, 10], label='global y')
|
193
|
+
ax.plot([0, -10], [0, 0], label='tower y')
|
194
|
+
ax.legend()
|
195
|
+
plt.show()
|
196
|
+
else:
|
197
|
+
plt.close('all')
|
h2lib_tests/test_h2lib.py
CHANGED
@@ -335,13 +335,6 @@ def test_fail():
|
|
335
335
|
assert h2.get_version() == version # hawc2 still alive
|
336
336
|
stop_code = 0
|
337
337
|
|
338
|
-
# cover get_stop_code, get_stop_message and reset_stop_code_and_message, but
|
339
|
-
# reset_stop_code_and_message is already called, so stop_code and stop_message are 0 and ""
|
340
|
-
assert h2.get_stop_code(stop_code)[0][0] == 0
|
341
|
-
stop_msg = " " * 1024
|
342
|
-
assert h2.get_stop_message(stop_msg)[0][0].strip() == ''
|
343
|
-
h2.reset_stop_code_and_message()
|
344
|
-
|
345
338
|
with MultiH2Lib(2) as h2:
|
346
339
|
# , match=re.escape('H2LibThread process died before or while executing fail(...)')):
|
347
340
|
with pytest.raises(Exception, match='MyError'):
|
h2lib_tests/test_h2rotor.py
CHANGED
@@ -55,11 +55,14 @@ def test_get_mainbody_position_orientation(h2: H2LibThread):
|
|
55
55
|
ax = plt.figure().add_subplot(projection='3d')
|
56
56
|
for name, mainbody_nr in mb_dict.items():
|
57
57
|
pos, ori = h2.get_mainbody_position_orientation(mainbody_nr, mainbody_coo_nr)
|
58
|
-
ax.plot(*pos, 'o', label=name)
|
58
|
+
c = ax.plot(*pos, 'o', label=name)[0].get_color()
|
59
|
+
nodes_pos = h2.get_mainbody_nodes_state(mainbody_nr, state='pos')
|
60
|
+
ax.plot(*nodes_pos.T, '.-', color=c)
|
59
61
|
for (exyz), c in zip(ori, 'rgb'):
|
60
62
|
ax.plot(*np.array([pos, pos + exyz * 10]).T, color=c)
|
61
63
|
plt.axis('equal')
|
62
64
|
plt.legend()
|
65
|
+
plt.gca().set_zlim([0, -200])
|
63
66
|
plt.show()
|
64
67
|
|
65
68
|
pos, ori = h2.get_mainbody_position_orientation(mb_dict['blade2'], 0)
|
@@ -73,6 +76,19 @@ def test_get_mainbody_position_orientation(h2: H2LibThread):
|
|
73
76
|
npt.assert_array_almost_equal(ori, [[0.49826698, 0.03781904, 0.86619844],
|
74
77
|
[0.07556557, 0.99335236, -0.0868386],
|
75
78
|
[-0.86372441, 0.10872359, 0.49209687]], 6)
|
79
|
+
npt.assert_array_almost_equal(
|
80
|
+
h2.get_mainbody_nodes_state(mainbody_nr=mb_dict['blade1'], state='pos', mainbody_coo_nr=0)[-1],
|
81
|
+
[-0.113689, -6.504988, -208.222845], 6)
|
82
|
+
npt.assert_array_almost_equal(
|
83
|
+
h2.get_mainbody_nodes_state(mainbody_nr=mb_dict['blade1'], state='pos', mainbody_coo_nr=mb_dict['blade1'])[-1],
|
84
|
+
[-0.069654, -3.326239, 86.364205], 6)
|
85
|
+
|
86
|
+
npt.assert_array_almost_equal(
|
87
|
+
h2.get_mainbody_nodes_state(mainbody_nr=mb_dict['blade1'], state='vel', mainbody_coo_nr=0)[-1],
|
88
|
+
[-17.787036, 1.8e-05, 0.061966], 6)
|
89
|
+
npt.assert_array_almost_equal(
|
90
|
+
h2.get_mainbody_nodes_state(mainbody_nr=mb_dict['blade1'], state='acc', mainbody_coo_nr=0)[-1],
|
91
|
+
[-0.032976, 0.08213, 11.252719], 6)
|
76
92
|
|
77
93
|
|
78
94
|
def test_induction(h2):
|
@@ -238,6 +238,16 @@ def test_set_orientation_base_speed(h2_dtu_10mw_only_blade):
|
|
238
238
|
)
|
239
239
|
|
240
240
|
|
241
|
+
def test_set_c2_def_too_few_sections(h2_dtu_10mw_only_blade):
|
242
|
+
with pytest.raises(ValueError, match="TOO_FEW_SECTIONS_IN_C2DEF"):
|
243
|
+
h2_dtu_10mw_only_blade.set_c2_def("blade1", np.zeros((1, 4)))
|
244
|
+
|
245
|
+
|
246
|
+
def test_set_c2_def_wrong_number_of_columns(h2_dtu_10mw_only_blade):
|
247
|
+
with pytest.raises(ValueError, match="WRONG_NUMBER_OF_COLUMNS"):
|
248
|
+
h2_dtu_10mw_only_blade.set_c2_def("blade1", np.zeros((2, 6)))
|
249
|
+
|
250
|
+
|
241
251
|
def test_set_c2_def_main_body_not_found(h2_dtu_10mw_only_blade):
|
242
252
|
with pytest.raises(ValueError, match="MAIN_BODY_NOT_FOUND"):
|
243
253
|
h2_dtu_10mw_only_blade.set_c2_def(
|
@@ -246,11 +256,6 @@ def test_set_c2_def_main_body_not_found(h2_dtu_10mw_only_blade):
|
|
246
256
|
)
|
247
257
|
|
248
258
|
|
249
|
-
def test_set_c2_def_too_few_sections(h2_dtu_10mw_only_blade):
|
250
|
-
with pytest.raises(ValueError, match="TOO_FEW_SECTIONS_IN_C2DEF"):
|
251
|
-
h2_dtu_10mw_only_blade.set_c2_def("blade1", np.zeros((1, 4)))
|
252
|
-
|
253
|
-
|
254
259
|
def test_set_c2_def_different_nsec(h2_dtu_10mw_only_blade):
|
255
260
|
with pytest.raises(ValueError, match="DIFFERENT_NSEC"):
|
256
261
|
h2_dtu_10mw_only_blade.set_c2_def(
|
@@ -288,7 +293,7 @@ def test_set_c2_def_blade_static_back_to_original(
|
|
288
293
|
# 4. Revert it to the original one and check that the static solution matches the one from step 2.
|
289
294
|
|
290
295
|
# Get the clamped DTU 10 MW blade subjected to high gravity loading.
|
291
|
-
_, blade_c2def = write_dtu10mw_only_blade_high_gravity
|
296
|
+
_, blade_c2def, _ = write_dtu10mw_only_blade_high_gravity
|
292
297
|
h2 = h2_dtu10mw_only_blade_high_gravity
|
293
298
|
|
294
299
|
# Sensors 1 to 6 are the displacement and rotation of the blade tip.
|
@@ -340,7 +345,7 @@ def test_set_c2_def_blade_static_deformed(
|
|
340
345
|
npt.assert_allclose(blade_tip_actual, blade_tip_desired)
|
341
346
|
|
342
347
|
# Restore c2_def.
|
343
|
-
_, c2def_original = write_dtu10mw_only_blade_high_gravity
|
348
|
+
_, c2def_original, _ = write_dtu10mw_only_blade_high_gravity
|
344
349
|
h2_dtu10mw_only_blade_high_gravity.set_c2_def("blade1", c2def_original)
|
345
350
|
|
346
351
|
|
@@ -351,7 +356,7 @@ def test_set_c2_def_blade_eig_back_to_original(
|
|
351
356
|
):
|
352
357
|
# Get the clamped DTU 10 MW blade.
|
353
358
|
# We use the fixture with high gravity because it also returns c2_def.
|
354
|
-
_, blade_c2def = write_dtu10mw_only_blade_high_gravity
|
359
|
+
_, blade_c2def, _ = write_dtu10mw_only_blade_high_gravity
|
355
360
|
h2 = h2_dtu10mw_only_blade_high_gravity
|
356
361
|
|
357
362
|
# Solve the eigenvalue problem.
|
@@ -383,13 +388,13 @@ def test_set_c2_def_blade_eig_back_to_original(
|
|
383
388
|
npt.assert_allclose(damping_ratios_actual, damping_ratios_desired)
|
384
389
|
|
385
390
|
|
386
|
-
def
|
391
|
+
def test_set_c2_def_blade_inertia_back_to_original(
|
387
392
|
write_dtu10mw_only_blade_high_gravity_1_body,
|
388
393
|
h2_dtu10mw_only_blade_high_gravity_1_body,
|
389
394
|
):
|
390
|
-
# Get the clamped DTU 10 MW blade.
|
395
|
+
# Get the clamped DTU 10 MW blade with only 1 body.
|
391
396
|
# We use the fixture with high gravity because it also returns c2_def.
|
392
|
-
_, blade_c2def = write_dtu10mw_only_blade_high_gravity_1_body
|
397
|
+
_, blade_c2def, _ = write_dtu10mw_only_blade_high_gravity_1_body
|
393
398
|
h2 = h2_dtu10mw_only_blade_high_gravity_1_body
|
394
399
|
|
395
400
|
# Get the inertia properties.
|
@@ -415,7 +420,7 @@ def test_set_c2_def_blade_mass_back_to_original(
|
|
415
420
|
npt.assert_allclose(inertia_actual[i], inertia_desired[i])
|
416
421
|
|
417
422
|
|
418
|
-
def
|
423
|
+
def test_set_c2_def_blade_inertia_deformed(
|
419
424
|
write_dtu10mw_only_blade_high_gravity,
|
420
425
|
write_dtu10mw_only_blade_high_gravity_deformed,
|
421
426
|
h2_dtu10mw_only_blade_high_gravity,
|
@@ -439,7 +444,7 @@ def test_set_c2_def_blade_mass_deformed(
|
|
439
444
|
npt.assert_allclose(inertia_actual[i], inertia_desired[i], rtol=1e-6)
|
440
445
|
|
441
446
|
# Restore c2_def.
|
442
|
-
_, c2def_original = write_dtu10mw_only_blade_high_gravity
|
447
|
+
_, c2def_original, _ = write_dtu10mw_only_blade_high_gravity
|
443
448
|
h2_dtu10mw_only_blade_high_gravity.set_c2_def("blade1", c2def_original)
|
444
449
|
|
445
450
|
|
@@ -469,10 +474,364 @@ def test_set_c2_def_blade_element_deformed(
|
|
469
474
|
npt.assert_allclose(mat_actual[2], mat_desired[2], rtol=1e-10) # damping
|
470
475
|
|
471
476
|
# Restore c2_def.
|
472
|
-
_, c2def_original = write_dtu10mw_only_blade_high_gravity
|
477
|
+
_, c2def_original, _ = write_dtu10mw_only_blade_high_gravity
|
473
478
|
h2_dtu10mw_only_blade_high_gravity.set_c2_def("blade1", c2def_original)
|
474
479
|
|
475
480
|
|
481
|
+
def test_set_st_wrong_number_of_columns(h2_dtu_10mw_only_blade):
|
482
|
+
with pytest.raises(ValueError, match="WRONG_NUMBER_OF_COLUMNS"):
|
483
|
+
h2_dtu_10mw_only_blade.set_st("blade1", np.empty((2, 6)))
|
484
|
+
|
485
|
+
|
486
|
+
def test_set_st_main_body_not_found(h2_dtu_10mw_only_blade):
|
487
|
+
with pytest.raises(ValueError, match="MAIN_BODY_NOT_FOUND"):
|
488
|
+
h2_dtu_10mw_only_blade.set_st("tower", np.empty((2, 19)))
|
489
|
+
|
490
|
+
|
491
|
+
def test_set_st_z_not_continuously_increasing(h2_dtu_10mw_only_blade):
|
492
|
+
with pytest.raises(ValueError, match="ST_Z_NOT_CONTINUOUSLY_INCREASING"):
|
493
|
+
h2_dtu_10mw_only_blade.set_st("blade1", np.zeros((3, 19)))
|
494
|
+
|
495
|
+
|
496
|
+
def test_set_st_uniform_node_distribution(
|
497
|
+
h2_dtu_10mw_only_blade_uniform_node_distribution,
|
498
|
+
):
|
499
|
+
with pytest.raises(NotImplementedError):
|
500
|
+
st = np.zeros((2, 19))
|
501
|
+
st[1, 0] = 1.0
|
502
|
+
h2_dtu_10mw_only_blade_uniform_node_distribution.set_st("blade1", st)
|
503
|
+
|
504
|
+
|
505
|
+
def test_set_st_classic_timoshenko_blade_static_back_to_original(
|
506
|
+
write_dtu10mw_only_blade_high_gravity,
|
507
|
+
h2_dtu10mw_only_blade_high_gravity,
|
508
|
+
):
|
509
|
+
# This test will:
|
510
|
+
# 1. Take the DTU 10 MW blade subjected to high gravity loading.
|
511
|
+
# 2. Compute the static solution.
|
512
|
+
# 3. Change ST a few times and re-compute the static solution.
|
513
|
+
# 4. Revert it to the original one and check that the static solution matches the one from step 2.
|
514
|
+
|
515
|
+
# Get the clamped DTU 10 MW blade subjected to high gravity loading.
|
516
|
+
_, _, blade_st = write_dtu10mw_only_blade_high_gravity
|
517
|
+
h2 = h2_dtu10mw_only_blade_high_gravity
|
518
|
+
|
519
|
+
# Sensors 1 to 6 are the displacement and rotation of the blade tip.
|
520
|
+
# h2.get_sensor_info(1)
|
521
|
+
|
522
|
+
# Run the static solver and get the blade tip position and rotation.
|
523
|
+
h2.solver_static_run(reset_structure=True)
|
524
|
+
blade_tip_desired = h2.get_sensor_values((1, 2, 3, 4, 5, 6))
|
525
|
+
|
526
|
+
# Change blade ST and run the static solver.
|
527
|
+
rng = np.random.default_rng(seed=582)
|
528
|
+
for _ in range(10):
|
529
|
+
factor = rng.uniform(low=0.7, high=1.3, size=19)
|
530
|
+
st_new = factor * blade_st.main_data_sets[1][1]
|
531
|
+
# We do not change z, to prevent ST_Z_NOT_CONTINUOUSLY_INCREASING.
|
532
|
+
st_new[:, 0] = blade_st.main_data_sets[1][1][:, 0]
|
533
|
+
h2.set_st("blade1", st_new)
|
534
|
+
h2.solver_static_run(reset_structure=True)
|
535
|
+
|
536
|
+
# Get new blade displacement.
|
537
|
+
blade_tip_actual = h2.get_sensor_values((1, 2, 3, 4, 5, 6))
|
538
|
+
|
539
|
+
# Must differ from blade_tip_desired.
|
540
|
+
with npt.assert_raises(AssertionError):
|
541
|
+
npt.assert_allclose(blade_tip_actual, blade_tip_desired)
|
542
|
+
|
543
|
+
# Restore blade c2_def.
|
544
|
+
h2.set_st("blade1", blade_st.main_data_sets[1][1])
|
545
|
+
h2.solver_static_run(reset_structure=True)
|
546
|
+
blade_tip_actual = h2.get_sensor_values((1, 2, 3, 4, 5, 6))
|
547
|
+
npt.assert_allclose(blade_tip_actual, blade_tip_desired)
|
548
|
+
|
549
|
+
|
550
|
+
def test_set_st_classic_timoshenko_blade_static_changed_st(
|
551
|
+
write_dtu10mw_only_blade_high_gravity,
|
552
|
+
write_dtu10mw_only_blade_high_gravity_changed_st,
|
553
|
+
h2_dtu10mw_only_blade_high_gravity,
|
554
|
+
h2_dtu10mw_only_blade_high_gravity_changed_st,
|
555
|
+
):
|
556
|
+
# Solve the static problem with the changed ST loaded directly by HAWC2.
|
557
|
+
h2_dtu10mw_only_blade_high_gravity_changed_st.solver_static_run(reset_structure=True)
|
558
|
+
blade_tip_desired = h2_dtu10mw_only_blade_high_gravity_changed_st.get_sensor_values((1, 2, 3, 4, 5, 6))
|
559
|
+
|
560
|
+
# Set ST in the original blade, thus making it equivalent to the changed one.
|
561
|
+
# Then, solve again the static problem.
|
562
|
+
_, st_changed = write_dtu10mw_only_blade_high_gravity_changed_st
|
563
|
+
h2_dtu10mw_only_blade_high_gravity.set_st("blade1", st_changed.main_data_sets[1][1])
|
564
|
+
h2_dtu10mw_only_blade_high_gravity.solver_static_run(reset_structure=True)
|
565
|
+
blade_tip_actual = h2_dtu10mw_only_blade_high_gravity_changed_st.get_sensor_values((1, 2, 3, 4, 5, 6))
|
566
|
+
|
567
|
+
npt.assert_allclose(blade_tip_actual, blade_tip_desired)
|
568
|
+
|
569
|
+
# Restore c2_def.
|
570
|
+
_, _, st_riginal = write_dtu10mw_only_blade_high_gravity
|
571
|
+
h2_dtu10mw_only_blade_high_gravity.set_st("blade1", st_riginal.main_data_sets[1][1])
|
572
|
+
|
573
|
+
|
574
|
+
def test_set_st_classic_timoshenko_inertia_back_to_original(
|
575
|
+
write_dtu10mw_only_blade_high_gravity_1_body,
|
576
|
+
h2_dtu10mw_only_blade_high_gravity_1_body,
|
577
|
+
):
|
578
|
+
# Get the clamped DTU 10 MW blade with only 1 body.
|
579
|
+
# We use the fixture with high gravity because it also returns st.
|
580
|
+
_, _, st = write_dtu10mw_only_blade_high_gravity_1_body
|
581
|
+
h2 = h2_dtu10mw_only_blade_high_gravity_1_body
|
582
|
+
|
583
|
+
# Get the inertia properties.
|
584
|
+
h2.structure_reset()
|
585
|
+
inertia_desired = h2.body_output_mass(0)
|
586
|
+
|
587
|
+
# Change blade density and compute inertia properties.
|
588
|
+
mass_original = st.m()
|
589
|
+
rng = np.random.default_rng(seed=582)
|
590
|
+
for _ in range(10):
|
591
|
+
# Uniformly scale to change the mass.
|
592
|
+
density_new = rng.uniform(low=0.5, high=2.0) * mass_original
|
593
|
+
# Make the blade tip heavier to change center of gravity.
|
594
|
+
density_new *= np.linspace(0.8, 2.5, density_new.size)
|
595
|
+
st.set_value(mset=1, set=1, m=density_new)
|
596
|
+
h2.set_st("blade1", st.main_data_sets[1][1])
|
597
|
+
inertia_actual = h2.body_output_mass(0)
|
598
|
+
|
599
|
+
# Must differ from the desired ones.
|
600
|
+
for i in range(4): # Loop over tuple of arrays.
|
601
|
+
with npt.assert_raises(AssertionError):
|
602
|
+
npt.assert_allclose(inertia_actual[i], inertia_desired[i])
|
603
|
+
|
604
|
+
# Restore ST.
|
605
|
+
st.set_value(mset=1, set=1, m=mass_original)
|
606
|
+
h2.set_st("blade1", st.main_data_sets[1][1])
|
607
|
+
inertia_actual = h2.body_output_mass(0)
|
608
|
+
for i in range(4): # Loop over tuple of arrays.
|
609
|
+
npt.assert_allclose(inertia_actual[i], inertia_desired[i])
|
610
|
+
|
611
|
+
|
612
|
+
def test_set_st_classic_timoshenko_blade_inertia_changed_st(
|
613
|
+
write_dtu10mw_only_blade_high_gravity,
|
614
|
+
write_dtu10mw_only_blade_high_gravity_changed_st,
|
615
|
+
h2_dtu10mw_only_blade_high_gravity,
|
616
|
+
h2_dtu10mw_only_blade_high_gravity_changed_st,
|
617
|
+
):
|
618
|
+
# Revert blades to the undeflected configuration.
|
619
|
+
h2_dtu10mw_only_blade_high_gravity.structure_reset()
|
620
|
+
h2_dtu10mw_only_blade_high_gravity_changed_st.structure_reset()
|
621
|
+
|
622
|
+
# Set ST in the original blade, thus making it equivalent to the changed one.
|
623
|
+
_, st_changed = write_dtu10mw_only_blade_high_gravity_changed_st
|
624
|
+
h2_dtu10mw_only_blade_high_gravity.set_st("blade1", st_changed.main_data_sets[1][1])
|
625
|
+
|
626
|
+
# Compare inertia properties for all bodies.
|
627
|
+
nbdy, _ = h2_dtu10mw_only_blade_high_gravity_changed_st.get_number_of_bodies_and_constraints()
|
628
|
+
for i in range(nbdy):
|
629
|
+
inertia_desired = h2_dtu10mw_only_blade_high_gravity_changed_st.body_output_mass(i)
|
630
|
+
inertia_actual = h2_dtu10mw_only_blade_high_gravity.body_output_mass(i)
|
631
|
+
|
632
|
+
for i in range(4): # Loop over tuple of arrays.
|
633
|
+
npt.assert_allclose(inertia_actual[i], inertia_desired[i])
|
634
|
+
|
635
|
+
# Restore ST.
|
636
|
+
_, _, st_original = write_dtu10mw_only_blade_high_gravity
|
637
|
+
h2_dtu10mw_only_blade_high_gravity.set_st("blade1", st_original.main_data_sets[1][1])
|
638
|
+
|
639
|
+
|
640
|
+
def test_set_st_classic_timoshenko_blade_element_changed_st(
|
641
|
+
write_dtu10mw_only_blade_high_gravity,
|
642
|
+
write_dtu10mw_only_blade_high_gravity_changed_st,
|
643
|
+
h2_dtu10mw_only_blade_high_gravity,
|
644
|
+
h2_dtu10mw_only_blade_high_gravity_changed_st,
|
645
|
+
):
|
646
|
+
# Revert blades to the undeflected configuration.
|
647
|
+
h2_dtu10mw_only_blade_high_gravity.structure_reset()
|
648
|
+
h2_dtu10mw_only_blade_high_gravity_changed_st.structure_reset()
|
649
|
+
|
650
|
+
# Set ST in the original blade, thus making it equivalent to the changed one.
|
651
|
+
_, st_changed = write_dtu10mw_only_blade_high_gravity_changed_st
|
652
|
+
h2_dtu10mw_only_blade_high_gravity.set_st("blade1", st_changed.main_data_sets[1][1])
|
653
|
+
|
654
|
+
# Compare element matrices for all bodies.
|
655
|
+
nelem = h2_dtu10mw_only_blade_high_gravity_changed_st.get_number_of_elements()
|
656
|
+
for ibdy in range(nelem.size):
|
657
|
+
for ielem in range(nelem[ibdy]):
|
658
|
+
mat_desired = h2_dtu10mw_only_blade_high_gravity_changed_st.body_output_element(ibdy, ielem)
|
659
|
+
mat_actual = h2_dtu10mw_only_blade_high_gravity.body_output_element(ibdy, ielem)
|
660
|
+
|
661
|
+
npt.assert_allclose(mat_actual[0], mat_desired[0], rtol=1e-14) # mass
|
662
|
+
npt.assert_allclose(mat_actual[1], mat_desired[1], rtol=1e-14) # stiffness
|
663
|
+
npt.assert_allclose(mat_actual[2], mat_desired[2], rtol=1e-14) # damping
|
664
|
+
|
665
|
+
# Restore ST.
|
666
|
+
_, _, st_original = write_dtu10mw_only_blade_high_gravity
|
667
|
+
h2_dtu10mw_only_blade_high_gravity.set_st("blade1", st_original.main_data_sets[1][1])
|
668
|
+
|
669
|
+
|
670
|
+
def test_set_st_fpm_blade_static_back_to_original(
|
671
|
+
write_iea22mw_only_blade_high_gravity,
|
672
|
+
h2_iea22mw_only_blade_high_gravity,
|
673
|
+
):
|
674
|
+
# This test will:
|
675
|
+
# 1. Take the IEA 22 MW blade subjected to high gravity loading.
|
676
|
+
# 2. Compute the static solution.
|
677
|
+
# 3. Change ST a few times and re-compute the static solution.
|
678
|
+
# 4. Revert it to the original one and check that the static solution matches the one from step 2.
|
679
|
+
|
680
|
+
# Get the clamped IEA 22 MW blade subjected to high gravity loading.
|
681
|
+
_, _, blade_st = write_iea22mw_only_blade_high_gravity
|
682
|
+
h2 = h2_iea22mw_only_blade_high_gravity
|
683
|
+
|
684
|
+
# Sensors 1 to 6 are the displacement and rotation of the blade tip.
|
685
|
+
# h2.get_sensor_info(1)
|
686
|
+
|
687
|
+
# Run the static solver and get the blade tip position and rotation.
|
688
|
+
h2.solver_static_run(reset_structure=True)
|
689
|
+
blade_tip_desired = h2.get_sensor_values((1, 2, 3, 4, 5, 6))
|
690
|
+
|
691
|
+
# Change blade ST and run the static solver.
|
692
|
+
rng = np.random.default_rng(seed=582)
|
693
|
+
for _ in range(10):
|
694
|
+
factor = rng.uniform(low=0.7, high=1.3, size=30)
|
695
|
+
st_new = factor * blade_st.main_data_sets[1][1]
|
696
|
+
# We do not change z, to prevent ST_Z_NOT_CONTINUOUSLY_INCREASING.
|
697
|
+
st_new[:, 0] = blade_st.main_data_sets[1][1][:, 0]
|
698
|
+
h2.set_st("blade1", st_new)
|
699
|
+
h2.solver_static_run(reset_structure=True)
|
700
|
+
|
701
|
+
# Get new blade displacement.
|
702
|
+
blade_tip_actual = h2.get_sensor_values((1, 2, 3, 4, 5, 6))
|
703
|
+
|
704
|
+
# Must differ from blade_tip_desired.
|
705
|
+
with npt.assert_raises(AssertionError):
|
706
|
+
npt.assert_allclose(blade_tip_actual, blade_tip_desired)
|
707
|
+
|
708
|
+
# Restore blade c2_def.
|
709
|
+
h2.set_st("blade1", blade_st.main_data_sets[1][1])
|
710
|
+
h2.solver_static_run(reset_structure=True)
|
711
|
+
blade_tip_actual = h2.get_sensor_values((1, 2, 3, 4, 5, 6))
|
712
|
+
npt.assert_allclose(blade_tip_actual, blade_tip_desired)
|
713
|
+
|
714
|
+
|
715
|
+
def test_set_st_fpm_blade_static_changed_st(
|
716
|
+
write_iea22mw_only_blade_high_gravity,
|
717
|
+
write_iea22mw_only_blade_high_gravity_changed_st,
|
718
|
+
h2_iea22mw_only_blade_high_gravity,
|
719
|
+
h2_iea22mw_only_blade_high_gravity_changed_st,
|
720
|
+
):
|
721
|
+
# Solve the static problem with the changed ST loaded directly by HAWC2.
|
722
|
+
h2_iea22mw_only_blade_high_gravity_changed_st.solver_static_run(reset_structure=True)
|
723
|
+
blade_tip_desired = h2_iea22mw_only_blade_high_gravity_changed_st.get_sensor_values((1, 2, 3, 4, 5, 6))
|
724
|
+
|
725
|
+
# Set ST in the original blade, thus making it equivalent to the changed one.
|
726
|
+
# Then, solve again the static problem.
|
727
|
+
_, st_changed = write_iea22mw_only_blade_high_gravity_changed_st
|
728
|
+
h2_iea22mw_only_blade_high_gravity.set_st("blade1", st_changed.main_data_sets[1][1])
|
729
|
+
h2_iea22mw_only_blade_high_gravity.solver_static_run(reset_structure=True)
|
730
|
+
blade_tip_actual = h2_iea22mw_only_blade_high_gravity_changed_st.get_sensor_values((1, 2, 3, 4, 5, 6))
|
731
|
+
|
732
|
+
npt.assert_allclose(blade_tip_actual, blade_tip_desired)
|
733
|
+
|
734
|
+
# Restore c2_def.
|
735
|
+
_, _, st_riginal = write_iea22mw_only_blade_high_gravity
|
736
|
+
h2_iea22mw_only_blade_high_gravity.set_st("blade1", st_riginal.main_data_sets[1][1])
|
737
|
+
|
738
|
+
|
739
|
+
def test_set_st_fpm_inertia_back_to_original(
|
740
|
+
write_iea22mw_only_blade_high_gravity_1_body,
|
741
|
+
h2_iea22mw_only_blade_high_gravity_1_body,
|
742
|
+
):
|
743
|
+
# Get the clamped DTU 10 MW blade with only 1 body.
|
744
|
+
# We use the fixture with high gravity because it also returns st.
|
745
|
+
_, _, st = write_iea22mw_only_blade_high_gravity_1_body
|
746
|
+
h2 = h2_iea22mw_only_blade_high_gravity_1_body
|
747
|
+
|
748
|
+
# Get the inertia properties.
|
749
|
+
h2.structure_reset()
|
750
|
+
inertia_desired = h2.body_output_mass(0)
|
751
|
+
|
752
|
+
# Change blade density and compute inertia properties.
|
753
|
+
mass_original = st.m()
|
754
|
+
rng = np.random.default_rng(seed=582)
|
755
|
+
for _ in range(10):
|
756
|
+
# Uniformly scale to change the mass.
|
757
|
+
density_new = rng.uniform(low=0.5, high=2.0) * mass_original
|
758
|
+
# Make the blade tip heavier to change center of gravity.
|
759
|
+
density_new *= np.linspace(0.8, 2.5, density_new.size)
|
760
|
+
st.set_value(mset=1, set=1, m=density_new)
|
761
|
+
h2.set_st("blade1", st.main_data_sets[1][1])
|
762
|
+
inertia_actual = h2.body_output_mass(0)
|
763
|
+
|
764
|
+
# Must differ from the desired ones.
|
765
|
+
for i in range(4): # Loop over tuple of arrays.
|
766
|
+
with npt.assert_raises(AssertionError):
|
767
|
+
npt.assert_allclose(inertia_actual[i], inertia_desired[i])
|
768
|
+
|
769
|
+
# Restore ST.
|
770
|
+
st.set_value(mset=1, set=1, m=mass_original)
|
771
|
+
h2.set_st("blade1", st.main_data_sets[1][1])
|
772
|
+
inertia_actual = h2.body_output_mass(0)
|
773
|
+
for i in range(4): # Loop over tuple of arrays.
|
774
|
+
npt.assert_allclose(inertia_actual[i], inertia_desired[i])
|
775
|
+
|
776
|
+
|
777
|
+
def test_set_st_fpm_blade_inertia_changed_st(
|
778
|
+
write_iea22mw_only_blade_high_gravity,
|
779
|
+
write_iea22mw_only_blade_high_gravity_changed_st,
|
780
|
+
h2_iea22mw_only_blade_high_gravity,
|
781
|
+
h2_iea22mw_only_blade_high_gravity_changed_st,
|
782
|
+
):
|
783
|
+
# Revert blades to the undeflected configuration.
|
784
|
+
h2_iea22mw_only_blade_high_gravity.structure_reset()
|
785
|
+
h2_iea22mw_only_blade_high_gravity_changed_st.structure_reset()
|
786
|
+
|
787
|
+
# Set ST in the original blade, thus making it equivalent to the changed one.
|
788
|
+
_, st_changed = write_iea22mw_only_blade_high_gravity_changed_st
|
789
|
+
h2_iea22mw_only_blade_high_gravity.set_st("blade1", st_changed.main_data_sets[1][1])
|
790
|
+
|
791
|
+
# Compare inertia properties for all bodies.
|
792
|
+
nbdy, _ = h2_iea22mw_only_blade_high_gravity_changed_st.get_number_of_bodies_and_constraints()
|
793
|
+
for i in range(nbdy):
|
794
|
+
inertia_desired = h2_iea22mw_only_blade_high_gravity_changed_st.body_output_mass(i)
|
795
|
+
inertia_actual = h2_iea22mw_only_blade_high_gravity.body_output_mass(i)
|
796
|
+
|
797
|
+
for i in range(4): # Loop over tuple of arrays.
|
798
|
+
npt.assert_allclose(inertia_actual[i], inertia_desired[i])
|
799
|
+
|
800
|
+
# Restore ST.
|
801
|
+
_, _, st_original = write_iea22mw_only_blade_high_gravity
|
802
|
+
h2_iea22mw_only_blade_high_gravity.set_st("blade1", st_original.main_data_sets[1][1])
|
803
|
+
|
804
|
+
|
805
|
+
def test_set_st_fpm_blade_element_changed_st(
|
806
|
+
write_iea22mw_only_blade_high_gravity,
|
807
|
+
write_iea22mw_only_blade_high_gravity_changed_st,
|
808
|
+
h2_iea22mw_only_blade_high_gravity,
|
809
|
+
h2_iea22mw_only_blade_high_gravity_changed_st,
|
810
|
+
):
|
811
|
+
# Revert blades to the undeflected configuration.
|
812
|
+
h2_iea22mw_only_blade_high_gravity.structure_reset()
|
813
|
+
h2_iea22mw_only_blade_high_gravity_changed_st.structure_reset()
|
814
|
+
|
815
|
+
# Set ST in the original blade, thus making it equivalent to the changed one.
|
816
|
+
_, st_changed = write_iea22mw_only_blade_high_gravity_changed_st
|
817
|
+
h2_iea22mw_only_blade_high_gravity.set_st("blade1", st_changed.main_data_sets[1][1])
|
818
|
+
|
819
|
+
# Compare element matrices for all bodies.
|
820
|
+
nelem = h2_iea22mw_only_blade_high_gravity_changed_st.get_number_of_elements()
|
821
|
+
for ibdy in range(nelem.size):
|
822
|
+
for ielem in range(nelem[ibdy]):
|
823
|
+
mat_desired = h2_iea22mw_only_blade_high_gravity_changed_st.body_output_element(ibdy, ielem)
|
824
|
+
mat_actual = h2_iea22mw_only_blade_high_gravity.body_output_element(ibdy, ielem)
|
825
|
+
|
826
|
+
npt.assert_allclose(mat_actual[0], mat_desired[0], rtol=1e-14) # mass
|
827
|
+
npt.assert_allclose(mat_actual[1], mat_desired[1], rtol=1e-14) # stiffness
|
828
|
+
npt.assert_allclose(mat_actual[2], mat_desired[2], rtol=1e-14) # damping
|
829
|
+
|
830
|
+
# Restore ST.
|
831
|
+
_, _, st_original = write_iea22mw_only_blade_high_gravity
|
832
|
+
h2_iea22mw_only_blade_high_gravity.set_st("blade1", st_original.main_data_sets[1][1])
|
833
|
+
|
834
|
+
|
476
835
|
def test_set_orientation_relative_main_body_not_found(
|
477
836
|
h2_dtu_10mw_only_blade_rotate_relative,
|
478
837
|
):
|
@@ -606,4 +965,4 @@ def test_set_orientation_relative_static(
|
|
606
965
|
|
607
966
|
if __name__ == "__main__":
|
608
967
|
# pytest.main([__file__])
|
609
|
-
pytest.main([__file__, "-k
|
968
|
+
pytest.main([__file__, "-k test_set_st_fpm_blade_element_changed_st"])
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: h2lib-tests
|
3
|
-
Version: 13.2.
|
4
|
-
Summary: Tests and test_files for test h2lib (13.2.
|
3
|
+
Version: 13.2.801
|
4
|
+
Summary: Tests and test_files for test h2lib (13.2.8)
|
5
5
|
Download-URL:
|
6
6
|
Author: Mads M Pedersen
|
7
7
|
Author-email:
|
@@ -13,6 +13,7 @@ Requires-Dist: pytest-cov
|
|
13
13
|
Requires-Dist: hipersim
|
14
14
|
Requires-Dist: wetb
|
15
15
|
Requires-Dist: h2lib
|
16
|
+
Requires-Dist: Hawc2Models==0.0.4
|
16
17
|
Dynamic: author
|
17
18
|
Dynamic: requires-dist
|
18
19
|
Dynamic: summary
|
@@ -1,16 +1,16 @@
|
|
1
1
|
h2lib_tests/__init__.py,sha256=VjSqfGg8BzdmSjfSFhJh4hZbYZ_cME7xp9EWFKHQphA,61
|
2
|
-
h2lib_tests/conftest.py,sha256=
|
2
|
+
h2lib_tests/conftest.py,sha256=r4p868zCfJ5MMd2hs6XvGaiqu3jYlSR5G0OKAk5WX7Y,29629
|
3
3
|
h2lib_tests/dtu10mw.py,sha256=a7SXfyDwDQPastYKb5CgghOQcYfgO1eTwGrd-H3Enok,4374
|
4
4
|
h2lib_tests/test_calc.py,sha256=VNLfr2J9R2Jy9xTbdZ9dfbQ4dCwr7H7nbZRI3yP69fQ,2152
|
5
|
-
h2lib_tests/test_distributed_sections.py,sha256
|
5
|
+
h2lib_tests/test_distributed_sections.py,sha256=-YqB2GgRWmZMophwubRjRh8y5X6ptAm4xqor9sgDQ30,9042
|
6
6
|
h2lib_tests/test_ellipsys_couplings.py,sha256=mfSTk1IamaKETU6Be8p8W9vA-yostWJl17m5sFlEK3Q,3345
|
7
|
-
h2lib_tests/test_h2lib.py,sha256=
|
8
|
-
h2lib_tests/test_h2rotor.py,sha256=
|
7
|
+
h2lib_tests/test_h2lib.py,sha256=t2jwmXzibej9DQoAkldwWX1MmEmpcV0kp2hLDRV5dbQ,13836
|
8
|
+
h2lib_tests/test_h2rotor.py,sha256=cF3KMdzTyGoZGyihhHCJqdH_n_t2vjS1BPHDaUCk9pU,13918
|
9
9
|
h2lib_tests/test_lin.py,sha256=yydbsMX44ym_MSqR1cbQkqil8qC4icSW_JccPSElGac,6292
|
10
10
|
h2lib_tests/test_mpi.py,sha256=CTT160yc6uZFRr_QNFWxyOwJ-y0qHiIp8jPYs1MQpyg,7111
|
11
11
|
h2lib_tests/test_multiprocessinterface.py,sha256=h2o4havtK6IuMXsplNjGUa3VxOnbpEYGxdrrAKQilj0,1470
|
12
12
|
h2lib_tests/test_static_solver.py,sha256=IuUkKrEoz_EKLCmGQ94CLFgjKPvO20iVx4773JTKO-8,6503
|
13
|
-
h2lib_tests/test_topology_h2lib.py,sha256=
|
13
|
+
h2lib_tests/test_topology_h2lib.py,sha256=g6H4E5OR4b2NlCDTZkOkUds2NyA-9XSG9Vu9Cy7TJw8,40348
|
14
14
|
h2lib_tests/test_files/__init__.py,sha256=9e6ZUPb42e0wf2E1rutdcTM8hROcWFRVPXtZriU3ySw,50
|
15
15
|
h2lib_tests/test_files/my_test_cls.py,sha256=7ZDsFkxrLfOY6q00U5Y-daxfuhATK-K5H04RP-VmQdE,850
|
16
16
|
h2lib_tests/test_files/DTU_10_MW/control/dtu_we_controller.dll,sha256=C5T_CuAFtIuDgCXSYAoNu24yKPwj2nWOeORacJbLN9s,1134592
|
@@ -91,7 +91,7 @@ h2lib_tests/test_files/minimal/res/minimal_mann_turb.hdf5,sha256=Q3cs3bZyplZjBpo
|
|
91
91
|
h2lib_tests/test_files/minimal/turb/hawc2_mann_l33.6_ae0.1000_g3.9_h0_512xd32xd16_2.000x3.00x4.00_s0001_u,sha256=byiorJmXDL6uKFbyfXthHTjJdm6ELvLR2lS202KrhRI,1048576
|
92
92
|
h2lib_tests/test_files/minimal/turb/hawc2_mann_l33.6_ae0.1000_g3.9_h0_512xd32xd16_2.000x3.00x4.00_s0001_v,sha256=cxK5Rfgfm3gyJsEYi_KlmYY8DIIl_G0aizN2jt18Glc,1048576
|
93
93
|
h2lib_tests/test_files/minimal/turb/hawc2_mann_l33.6_ae0.1000_g3.9_h0_512xd32xd16_2.000x3.00x4.00_s0001_w,sha256=xs61jAwhP3fIR1P5Oa8ovEt2baLoF8uCNs6pKIT8L4o,1048576
|
94
|
-
h2lib_tests-13.2.
|
95
|
-
h2lib_tests-13.2.
|
96
|
-
h2lib_tests-13.2.
|
97
|
-
h2lib_tests-13.2.
|
94
|
+
h2lib_tests-13.2.801.dist-info/METADATA,sha256=c2VITTY0PxlaMfuXZrhOsoTeB8MVqNudNxuApGiQAPI,441
|
95
|
+
h2lib_tests-13.2.801.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
96
|
+
h2lib_tests-13.2.801.dist-info/top_level.txt,sha256=WufAL3LO35YJBhWg1AfgTjSld-6l_WuRkXAkNKczUrM,12
|
97
|
+
h2lib_tests-13.2.801.dist-info/RECORD,,
|
File without changes
|
File without changes
|