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 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 + "DTU_10_MW/htc/DTU_10MW_RWT.htc")
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 + "DTU_10_MW/htc/DTU_10MW_RWT.htc")
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 + "DTU_10_MW/htc/DTU_10MW_RWT.htc")
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 + "DTU_10_MW/htc/DTU_10MW_RWT.htc")
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'):
@@ -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 test_set_c2_def_blade_mass_back_to_original(
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 test_set_c2_def_blade_mass_deformed(
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 test_set_c2_def_blade_element_deformed"])
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.701
4
- Summary: Tests and test_files for test h2lib (13.2.7+4-gb779ee7)
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=o9bkMEaB40rr_KSGovy1nuvq2Y09rKfQWxTcTGZ0MfY,21607
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=JtguIddd2nmRyNsy2jqjPFB8E5cGpH2_IVErP1wGPPg,5432
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=LEV1n0Fwa1llQwIM06Mcqr07Y6WOn-j8mNxjzlCEOl0,14219
8
- h2lib_tests/test_h2rotor.py,sha256=yAcG9RDD3uO4g4w8LJnJ3Md_bC-_mBn1--4KHwvlTRc,12963
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=7ZfVjEUYBJacPcFCDi_Qb0LqW6W-0no_zTBUKbNcKQw,23858
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.701.dist-info/METADATA,sha256=-mXXeU5VEAY9tlTcDTGdIrr3YjPISLCZsZpFATvR-cg,417
95
- h2lib_tests-13.2.701.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
96
- h2lib_tests-13.2.701.dist-info/top_level.txt,sha256=WufAL3LO35YJBhWg1AfgTjSld-6l_WuRkXAkNKczUrM,12
97
- h2lib_tests-13.2.701.dist-info/RECORD,,
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,,