Skip to content

Commit c98c7a0

Browse files
committed
Add RM3 regression test
Migrate the RM3 model files from demos/ and add regression test reference data.
1 parent 066c1c0 commit c98c7a0

14 files changed

Lines changed: 21253 additions & 0 deletions

File tree

tests/regression/reference_data/rm3/decay/hc_ref_rm3_decay.txt

Lines changed: 4001 additions & 0 deletions
Large diffs are not rendered by default.

tests/regression/reference_data/rm3/reg_waves/hc_ref_rm3_reg_waves.txt

Lines changed: 4001 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
#!/usr/bin/env python3
2+
"""
3+
RM3 Decay Regression Test Comparison
4+
5+
This script compares the RM3 decay test results with reference data and generates
6+
comparison plots using the standardized template.
7+
8+
Usage:
9+
python compare_decay.py <reference_file> <test_file>
10+
"""
11+
12+
import sys
13+
import os
14+
from pathlib import Path
15+
import numpy as np
16+
17+
# Import the comparison template
18+
sys.path.append(os.path.join(os.path.dirname(__file__), '../utilities'))
19+
from compare_template import run_multi_column_comparison
20+
21+
def main():
22+
if len(sys.argv) == 1 or (len(sys.argv) == 3 and sys.argv[1] == 'default'):
23+
# Use default reference and result file locations
24+
ref_file = os.path.join(os.path.dirname(__file__), "..", "reference_data", "rm3", "decay", "hc_ref_rm3_decay.txt")
25+
26+
# Find the result file
27+
build_dir = os.environ.get('HYDROCHRONO_BUILD_DIR', 'C:/code/HydroChrono/build')
28+
test_file = os.path.join(build_dir, "bin", "tests", "regression", "rm3", "results", "CHRONO_RM3_DECAY.txt")
29+
elif len(sys.argv) == 3:
30+
ref_file = sys.argv[1]
31+
test_file = sys.argv[2]
32+
else:
33+
print("Usage: python compare_decay.py <reference_file> <test_file>")
34+
print(" or: python compare_decay.py default")
35+
sys.exit(1)
36+
37+
# RM3 Decay specific configuration
38+
test_name = "RM3 Decay Test"
39+
executable_patterns = ["rm3_decay_test", "rm3_decay_test.exe"]
40+
41+
# Define the columns to plot and their configurations
42+
test_configs = [
43+
{
44+
'column_index': 1, # Float Heave
45+
'test_name': f"{test_name} - Float Heave",
46+
'y_label': "Float Heave (m)",
47+
'validation_tolerance': (1e-4, 0.02) # RM3-specific tolerance
48+
},
49+
{
50+
'column_index': 2, # Spar Heave
51+
'test_name': f"{test_name} - Spar Heave",
52+
'y_label': "Spar Heave (m)",
53+
'validation_tolerance': (1e-4, 0.02) # RM3-specific tolerance
54+
}
55+
]
56+
57+
try:
58+
# Load data for additional RM3-specific validations
59+
ref_data = np.loadtxt(ref_file, skiprows=1)
60+
test_data = np.loadtxt(test_file, skiprows=1)
61+
62+
# Show where the plots will be saved
63+
test_file_path = Path(test_file)
64+
plots_dir = test_file_path.parent / "plots"
65+
plots_dir.mkdir(parents=True, exist_ok=True)
66+
print(f"Plots will be saved to: {plots_dir}")
67+
68+
# Create temporary files with interpolated data to match time steps
69+
import tempfile
70+
71+
# Interpolate reference data to match test data time steps
72+
nval = test_data.shape[0]
73+
x = np.linspace(test_data[0, 0], test_data[nval-1, 0], nval)
74+
75+
# Interpolate the float heave and spar heave data
76+
floatHeaveRef = np.interp(x, ref_data[:,0], ref_data[:,1])
77+
sparHeaveRef = np.interp(x, ref_data[:,0], ref_data[:,2])
78+
79+
# Create interpolated reference data
80+
ref_data_interp = np.column_stack((x, floatHeaveRef, sparHeaveRef))
81+
82+
# Create temporary files with interpolated data
83+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as temp_ref:
84+
np.savetxt(temp_ref.name, ref_data_interp, fmt='%.6f')
85+
86+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as temp_test:
87+
np.savetxt(temp_test.name, test_data, fmt='%.6f')
88+
89+
try:
90+
# Override the plots directory to ensure it's saved in the correct location
91+
import sys as sys_module
92+
sys_module.path.append(os.path.join(os.path.dirname(__file__), '..'))
93+
from compare_template import create_comparison_plot, format_path
94+
95+
# Manually create the comparison plot to control the output directory
96+
for config in test_configs:
97+
column_index = config['column_index']
98+
test_name = config['test_name']
99+
y_label = config['y_label']
100+
101+
# Create data arrays for this column
102+
ref_col_data = np.column_stack((ref_data_interp[:, 0], ref_data_interp[:, column_index]))
103+
test_col_data = np.column_stack((test_data[:, 0], test_data[:, column_index]))
104+
105+
# Create the plot in the correct directory
106+
create_comparison_plot(
107+
ref_col_data, test_col_data, test_name, plots_dir,
108+
ref_file_path=format_path(ref_file),
109+
test_file_path=format_path(test_file),
110+
y_label=y_label,
111+
executable_patterns=executable_patterns
112+
)
113+
114+
# Create dummy results for compatibility
115+
results = [(0.0, 0.0, True)] * len(test_configs)
116+
finally:
117+
# Clean up temporary files
118+
os.unlink(temp_ref.name)
119+
os.unlink(temp_test.name)
120+
121+
# Additional RM3-specific validations (from the original script)
122+
nval = test_data.shape[0]
123+
124+
# Resample refData to testData sampling rate
125+
x = np.linspace(test_data[0, 0], test_data[nval-1, 0], nval)
126+
127+
# Compare the float heave
128+
floatHeaveRef = np.interp(x, ref_data[:,0], ref_data[:,1])
129+
floatHeaveTest = np.interp(x, test_data[:,0], test_data[:,1])
130+
floatHeaveComp = floatHeaveRef - floatHeaveTest
131+
132+
# Compare the spar heave
133+
sparHeaveRef = np.interp(x, ref_data[:,0], ref_data[:,2])
134+
sparHeaveTest = np.interp(x, test_data[:,0], test_data[:,2])
135+
sparHeaveComp = sparHeaveRef - sparHeaveTest
136+
137+
# Frobenius norm - Float Heave
138+
floatHeaven1 = np.linalg.norm(floatHeaveComp)/nval
139+
# infinity norm - Float Heave
140+
floatHeaven2 = np.linalg.norm(floatHeaveComp, np.inf)
141+
142+
# Frobenius norm - Spar Heave
143+
sparHeaven1 = np.linalg.norm(sparHeaveComp)/nval
144+
# infinity norm - Spar Heave
145+
sparHeaven2 = np.linalg.norm(sparHeaveComp, np.inf)
146+
147+
if (floatHeaven1 > 1e-4 or floatHeaven2 > 0.02 or sparHeaven1 > 1e-4 or sparHeaven2 > 0.02):
148+
print(f"RM3 validation failed: Float heave difference {floatHeaven1:.2e} > 1e-4 or {floatHeaven2:.2e} > 0.02")
149+
print(f"RM3 validation failed: Spar heave difference {sparHeaven1:.2e} > 1e-4 or {sparHeaven2:.2e} > 0.02")
150+
sys.exit(1)
151+
152+
# Check if all template comparisons passed
153+
all_passed = all(result[2] for result in results)
154+
155+
if all_passed:
156+
print("RM3 DECAY TEST PASSED - All comparisons within tolerance")
157+
print(f"Generated plots:")
158+
for config in test_configs:
159+
plot_name = config['test_name'].lower().replace(' ', '_').replace('-', '_')
160+
print(f" - {config['test_name']}: {plots_dir}/{plot_name}_comparison.png")
161+
else:
162+
print("RM3 DECAY TEST FAILED - Some comparisons outside tolerance")
163+
sys.exit(1)
164+
165+
except Exception as e:
166+
print(f"Error during comparison: {e}")
167+
sys.exit(1)
168+
169+
if __name__ == "__main__":
170+
main()
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#!/usr/bin/env python3
2+
"""
3+
RM3 Regular Waves Regression Test Comparison
4+
5+
This script compares the RM3 regular waves test results with reference data and generates
6+
comparison plots using the standardized template.
7+
8+
Usage:
9+
python compare_reg_waves.py <reference_file> <test_file>
10+
"""
11+
12+
import sys
13+
import os
14+
from pathlib import Path
15+
import numpy as np
16+
17+
# Import the comparison template
18+
sys.path.append(os.path.join(os.path.dirname(__file__), '../utilities'))
19+
from compare_template import run_multi_column_comparison
20+
21+
def main():
22+
if len(sys.argv) == 1 or (len(sys.argv) == 3 and sys.argv[1] == 'default'):
23+
# Use default reference and result file locations
24+
ref_file = os.path.join(os.path.dirname(__file__), "..", "reference_data", "rm3", "reg_waves", "hc_ref_rm3_reg_waves.txt")
25+
26+
# Find the result file
27+
build_dir = os.environ.get('HYDROCHRONO_BUILD_DIR', 'C:/code/HydroChrono/build')
28+
test_file = os.path.join(build_dir, "bin", "tests", "regression", "rm3", "results", "CHRONO_RM3_REG_WAVES.txt")
29+
elif len(sys.argv) == 3:
30+
ref_file = sys.argv[1]
31+
test_file = sys.argv[2]
32+
else:
33+
print("Usage: python compare_reg_waves.py <reference_file> <test_file>")
34+
print(" or: python compare_reg_waves.py default")
35+
sys.exit(1)
36+
37+
# RM3 Regular Waves specific configuration
38+
test_name = "RM3 Regular Waves Test"
39+
executable_patterns = ["rm3_reg_waves_test", "rm3_reg_waves_test.exe"]
40+
41+
# Define the columns to plot and their configurations
42+
test_configs = [
43+
{
44+
'column_index': 1, # Float Heave
45+
'test_name': f"{test_name} - Float Heave",
46+
'y_label': "Float Heave (m)",
47+
'validation_tolerance': (1e-4, 0.02) # RM3-specific tolerance
48+
},
49+
{
50+
'column_index': 2, # Plate Heave
51+
'test_name': f"{test_name} - Plate Heave",
52+
'y_label': "Plate Heave (m)",
53+
'validation_tolerance': (1e-4, 0.02) # RM3-specific tolerance
54+
},
55+
{
56+
'column_index': 3, # Float Drift
57+
'test_name': f"{test_name} - Float Drift",
58+
'y_label': "Float Drift (m)",
59+
'validation_tolerance': (1e-4, 0.02) # RM3-specific tolerance
60+
}
61+
]
62+
63+
try:
64+
# Load data for additional RM3-specific validations
65+
ref_data = np.loadtxt(ref_file, skiprows=1) # Skip header line
66+
test_data = np.loadtxt(test_file, skiprows=1) # Skip header line
67+
68+
# Show where the plots will be saved
69+
test_file_path = Path(test_file)
70+
plots_dir = test_file_path.parent / "plots"
71+
plots_dir.mkdir(parents=True, exist_ok=True)
72+
print(f"Plots will be saved to: {plots_dir}")
73+
74+
# Create temporary files with interpolated data to match time steps
75+
import tempfile
76+
77+
# Interpolate reference data to match test data time steps
78+
nval = test_data.shape[0]
79+
x = np.linspace(test_data[0, 0], test_data[nval-1, 0], nval)
80+
81+
# Interpolate the float heave, plate heave, and float drift data
82+
floatHeaveRef = np.interp(x, ref_data[:,0], ref_data[:,1])
83+
plateHeaveRef = np.interp(x, ref_data[:,0], ref_data[:,2])
84+
floatDriftRef = np.interp(x, ref_data[:,0], ref_data[:,3])
85+
86+
# Create interpolated reference data
87+
ref_data_interp = np.column_stack((x, floatHeaveRef, plateHeaveRef, floatDriftRef))
88+
89+
# Create temporary files with interpolated data
90+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as temp_ref:
91+
np.savetxt(temp_ref.name, ref_data_interp, fmt='%.6f')
92+
93+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as temp_test:
94+
np.savetxt(temp_test.name, test_data, fmt='%.6f')
95+
96+
try:
97+
# Override the plots directory to ensure it's saved in the correct location
98+
import sys as sys_module
99+
sys_module.path.append(os.path.join(os.path.dirname(__file__), '..'))
100+
from compare_template import create_comparison_plot, format_path
101+
102+
# Manually create the comparison plot to control the output directory
103+
for config in test_configs:
104+
column_index = config['column_index']
105+
test_name = config['test_name']
106+
y_label = config['y_label']
107+
108+
# Create data arrays for this column
109+
ref_col_data = np.column_stack((ref_data_interp[:, 0], ref_data_interp[:, column_index]))
110+
test_col_data = np.column_stack((test_data[:, 0], test_data[:, column_index]))
111+
112+
# Create the plot in the correct directory
113+
create_comparison_plot(
114+
ref_col_data, test_col_data, test_name, plots_dir,
115+
ref_file_path=format_path(ref_file),
116+
test_file_path=format_path(test_file),
117+
y_label=y_label,
118+
executable_patterns=executable_patterns
119+
)
120+
121+
# Create dummy results for compatibility
122+
results = [(0.0, 0.0, True)] * len(test_configs)
123+
finally:
124+
# Clean up temporary files
125+
os.unlink(temp_ref.name)
126+
os.unlink(temp_test.name)
127+
128+
# Additional RM3-specific validations
129+
nval = test_data.shape[0]
130+
131+
# Resample refData to testData sampling rate
132+
x = np.linspace(test_data[0, 0], test_data[nval-1, 0], nval)
133+
134+
# Compare float heave
135+
floatHeaveRef = np.interp(x, ref_data[:,0], ref_data[:,1])
136+
floatHeaveTest = np.interp(x, test_data[:,0], test_data[:,1])
137+
floatHeaveComp = floatHeaveRef - floatHeaveTest
138+
139+
# Compare plate heave
140+
plateHeaveRef = np.interp(x, ref_data[:,0], ref_data[:,2])
141+
plateHeaveTest = np.interp(x, test_data[:,0], test_data[:,2])
142+
plateHeaveComp = plateHeaveRef - plateHeaveTest
143+
144+
# Compare float drift
145+
floatDriftRef = np.interp(x, ref_data[:,0], ref_data[:,3])
146+
floatDriftTest = np.interp(x, test_data[:,0], test_data[:,3])
147+
floatDriftComp = floatDriftRef - floatDriftTest
148+
149+
# Frobenius norm - Float Heave
150+
floatHeaven1 = np.linalg.norm(floatHeaveComp)/nval
151+
# infinity norm - Float Heave
152+
floatHeaven2 = np.linalg.norm(floatHeaveComp, np.inf)
153+
154+
# Frobenius norm - Plate Heave
155+
plateHeaven1 = np.linalg.norm(plateHeaveComp)/nval
156+
# infinity norm - Plate Heave
157+
plateHeaven2 = np.linalg.norm(plateHeaveComp, np.inf)
158+
159+
# Frobenius norm - Float Drift
160+
floatDriftn1 = np.linalg.norm(floatDriftComp)/nval
161+
# infinity norm - Float Drift
162+
floatDriftn2 = np.linalg.norm(floatDriftComp, np.inf)
163+
164+
if (floatHeaven1 > 1e-4 or floatHeaven2 > 0.02 or
165+
plateHeaven1 > 1e-4 or plateHeaven2 > 0.02 or
166+
floatDriftn1 > 1e-4 or floatDriftn2 > 0.02):
167+
print(f"RM3 validation failed: Float heave difference {floatHeaven1:.2e} > 1e-4 or {floatHeaven2:.2e} > 0.02")
168+
print(f"RM3 validation failed: Plate heave difference {plateHeaven1:.2e} > 1e-4 or {plateHeaven2:.2e} > 0.02")
169+
print(f"RM3 validation failed: Float drift difference {floatDriftn1:.2e} > 1e-4 or {floatDriftn2:.2e} > 0.02")
170+
sys.exit(1)
171+
172+
# Check if all template comparisons passed
173+
all_passed = all(result[2] for result in results)
174+
175+
if all_passed:
176+
print("RM3 REGULAR WAVES TEST PASSED - All comparisons within tolerance")
177+
print(f"Generated plots:")
178+
for config in test_configs:
179+
plot_name = config['test_name'].lower().replace(' ', '_').replace('-', '_')
180+
print(f" - {config['test_name']}: {plots_dir}/{plot_name}_comparison.png")
181+
else:
182+
print("RM3 REGULAR WAVES TEST FAILED - Some comparisons outside tolerance")
183+
sys.exit(1)
184+
185+
except Exception as e:
186+
print(f"Error during comparison: {e}")
187+
sys.exit(1)
188+
189+
if __name__ == "__main__":
190+
main()

0 commit comments

Comments
 (0)