Skip to content

Commit 066c1c0

Browse files
committed
Add oswec to regression test suite
Migrate model files from demos/ and add regression test data
1 parent 7c4f714 commit 066c1c0

26 files changed

Lines changed: 556523 additions & 0 deletions
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#!/usr/bin/env python3
2+
"""
3+
OSWEC Decay Regression Test Comparison
4+
5+
This script compares the OSWEC 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", "oswec", "decay", "hc_ref_oswec_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", "oswec", "results", "CHRONO_OSWEC_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+
# OSWEC Decay specific configuration
38+
test_name = "OSWEC Decay Test"
39+
executable_patterns = ["oswec_decay_test", "oswec_decay_test.exe"]
40+
41+
# Define the columns to plot and their configurations
42+
test_configs = [
43+
{
44+
'column_index': 1, # Flap Pitch (radians)
45+
'test_name': f"{test_name} - Flap Pitch",
46+
'y_label': "Flap Pitch (radians)",
47+
'validation_tolerance': (1e-4, 0.02) # OSWEC-specific tolerance
48+
}
49+
]
50+
51+
try:
52+
# Load data for additional OSWEC-specific validations
53+
ref_data = np.loadtxt(ref_file, skiprows=1)
54+
test_data = np.loadtxt(test_file, skiprows=1)
55+
56+
# Show where the plots will be saved
57+
test_file_path = Path(test_file)
58+
plots_dir = test_file_path.parent / "plots"
59+
plots_dir.mkdir(parents=True, exist_ok=True)
60+
print(f"Plots will be saved to: {plots_dir}")
61+
62+
# Create temporary files with interpolated data to match time steps
63+
import tempfile
64+
65+
# Interpolate reference data to match test data time steps
66+
nval = test_data.shape[0]
67+
x = np.linspace(test_data[0, 0], test_data[nval-1, 0], nval)
68+
69+
# Interpolate the flap pitch data (column 1 in reference, column 1 in test)
70+
flapPitchRef = np.interp(x, ref_data[:,0], ref_data[:,1])
71+
72+
# Create interpolated reference data
73+
ref_data_interp = np.column_stack((x, flapPitchRef))
74+
75+
# Create temporary files with interpolated data
76+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as temp_ref:
77+
np.savetxt(temp_ref.name, ref_data_interp, fmt='%.6f')
78+
79+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as temp_test:
80+
# Use only time and flap pitch columns from test data
81+
test_data_interp = np.column_stack((test_data[:,0], test_data[:,1]))
82+
np.savetxt(temp_test.name, test_data_interp, fmt='%.6f')
83+
84+
try:
85+
# Run the multi-column comparison using the template with interpolated data
86+
# Override the plots directory to ensure it's saved in the correct location
87+
import sys as sys_module
88+
sys_module.path.append(os.path.join(os.path.dirname(__file__), '..'))
89+
from compare_template import create_comparison_plot, format_path
90+
91+
# Manually create the comparison plot to control the output directory
92+
for config in test_configs:
93+
column_index = config['column_index']
94+
test_name = config['test_name']
95+
y_label = config['y_label']
96+
97+
# Create data arrays for this column
98+
ref_col_data = np.column_stack((ref_data_interp[:, 0], ref_data_interp[:, column_index]))
99+
test_col_data = np.column_stack((test_data_interp[:, 0], test_data_interp[:, column_index]))
100+
101+
# Create the plot in the correct directory
102+
create_comparison_plot(
103+
ref_col_data, test_col_data, test_name, plots_dir,
104+
ref_file_path=format_path(ref_file),
105+
test_file_path=format_path(test_file),
106+
y_label=y_label,
107+
executable_patterns=executable_patterns
108+
)
109+
110+
# Create dummy results for compatibility
111+
results = [(0.0, 0.0, True)] * len(test_configs)
112+
finally:
113+
# Clean up temporary files
114+
os.unlink(temp_ref.name)
115+
os.unlink(temp_test.name)
116+
117+
# Additional OSWEC-specific validations (from the original script)
118+
nval = test_data.shape[0]
119+
120+
# Resample refData to testData sampling rate
121+
x = np.linspace(test_data[0, 0], test_data[nval-1, 0], nval)
122+
flapPitchRef = np.interp(x, ref_data[:,0], ref_data[:,1])
123+
flapPitchTest = np.interp(x, test_data[:,0], test_data[:,1])
124+
flapPitchComp = flapPitchRef - flapPitchTest
125+
126+
# Frobenius norm - Flap pitch
127+
flapPitchn1 = np.linalg.norm(flapPitchComp)/nval
128+
# infinity norm - Flap pitch
129+
flapPitchn2 = np.linalg.norm(flapPitchComp, np.inf)
130+
131+
if (flapPitchn1 > 1e-4 or flapPitchn2 > 0.02):
132+
print(f"OSWEC validation failed: Flap pitch difference {flapPitchn1:.2e} > 1e-4 or {flapPitchn2:.2e} > 0.02")
133+
sys.exit(1)
134+
135+
# Check if all template comparisons passed
136+
all_passed = all(result[2] for result in results)
137+
138+
if all_passed:
139+
print("OSWEC DECAY TEST PASSED - All comparisons within tolerance")
140+
print(f"Generated plots:")
141+
for config in test_configs:
142+
plot_name = config['test_name'].lower().replace(' ', '_').replace('-', '_')
143+
print(f" - {config['test_name']}: {plots_dir}/{plot_name}_comparison.png")
144+
else:
145+
print("OSWEC DECAY TEST FAILED - Some comparisons outside tolerance")
146+
sys.exit(1)
147+
148+
except Exception as e:
149+
print(f"Error during comparison: {e}")
150+
sys.exit(1)
151+
152+
if __name__ == "__main__":
153+
main()
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#!/usr/bin/env python3
2+
"""
3+
OSWEC Regular Waves Regression Test Comparison (Batch Mode)
4+
5+
This script compares all OSWEC regular waves test results with reference data and generates
6+
comparison plots using the standardized template. It loops over all available result files.
7+
8+
Usage:
9+
python compare_reg_waves.py
10+
"""
11+
12+
import sys
13+
import os
14+
from pathlib import Path
15+
import numpy as np
16+
import glob
17+
import re
18+
19+
# Import the comparison template
20+
sys.path.append(os.path.join(os.path.dirname(__file__), '../utilities'))
21+
from compare_template import create_comparison_plot, format_path
22+
23+
def main():
24+
# Directories
25+
script_dir = Path(__file__).parent
26+
ref_dir = script_dir.parent / "reference_data" / "oswec" / "reg_waves"
27+
# Default build results dir
28+
build_dir = Path(os.environ.get('HYDROCHRONO_BUILD_DIR', 'C:/code/HydroChrono/build'))
29+
# New recommended layout
30+
results_dir = build_dir / "bin" / "tests" / "regression" / "oswec" / "results"
31+
if not results_dir.exists():
32+
# Fallback to older Release layout used previously
33+
results_dir = build_dir / "tests" / "regression" / "Release" / "oswec" / "results" / "oswec" / "regular_waves"
34+
if not results_dir.exists():
35+
print(f"Results directory not found: {results_dir}")
36+
sys.exit(1)
37+
38+
# Find all result files
39+
all_files = [p for p in results_dir.glob("CHRONO_OSWEC_REG_WAVES_*.txt") if not p.stem.endswith("DURATION")]
40+
def wave_num_from_stem(stem: str):
41+
m = re.search(r"_(\d+)$", stem)
42+
return int(m.group(1)) if m else -1
43+
result_files = sorted(all_files, key=lambda p: wave_num_from_stem(p.stem))
44+
if not result_files:
45+
print(f"No result files found in {results_dir}")
46+
sys.exit(1)
47+
48+
# Output directory for plots
49+
plots_dir = results_dir / "plots"
50+
plots_dir.mkdir(parents=True, exist_ok=True)
51+
print(f"Plots will be saved to: {plots_dir}")
52+
53+
# Loop over all result files
54+
for result_file in result_files:
55+
wave_num = result_file.stem.split('_')[-1]
56+
ref_file = ref_dir / f"hc_ref_oswec_reg_waves_{wave_num}.txt"
57+
if not ref_file.exists():
58+
print(f"[WARNING] Reference file not found for wave {wave_num}: {ref_file}. Skipping.")
59+
continue
60+
print(f"\nComparing wave {wave_num}...")
61+
print(f" Reference: {ref_file}")
62+
print(f" Result: {result_file}")
63+
try:
64+
# Load data (skip headers)
65+
ref_data = np.loadtxt(ref_file, skiprows=5)
66+
test_data = np.loadtxt(result_file, skiprows=5)
67+
# Prepare data for plotting (Pitch is column 1)
68+
ref_col_data = np.column_stack((ref_data[:, 0], ref_data[:, 1]))
69+
test_col_data = np.column_stack((test_data[:, 0], test_data[:, 1]))
70+
test_name = f"OSWEC Regular Waves Test - Pitch - Wave {wave_num}"
71+
y_label = "Pitch (radians)"
72+
executable_patterns = ["oswec_reg_waves_test", "oswec_reg_waves_test.exe"]
73+
create_comparison_plot(
74+
ref_col_data, test_col_data, test_name, plots_dir,
75+
ref_file_path=format_path(str(ref_file)),
76+
test_file_path=format_path(str(result_file)),
77+
y_label=y_label,
78+
executable_patterns=executable_patterns
79+
)
80+
print(f" [OK] Plot generated: {plots_dir}/{test_name.lower().replace(' ', '_').replace('-', '_')}_comparison.png")
81+
except Exception as e:
82+
print(f" [ERROR] Failed to compare wave {wave_num}: {e}")
83+
84+
if __name__ == "__main__":
85+
main()
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Wavefront OBJ file exported by Meshmagick (Copyright Ecole Centrale de Nantes)
2+
# File Created: Wed Nov 2 18:29:51 2022
3+
4+
5+
# Vertices: 8
6+
7+
v -0.900000 -9.020000 -0.000000
8+
v -0.900000 -9.020000 1.500000
9+
v -0.900000 9.020000 0.000000
10+
v -0.900000 9.020000 1.500000
11+
v 0.900000 -9.020000 -0.000000
12+
v 0.900000 -9.020000 1.500000
13+
v 0.900000 9.020000 -0.000000
14+
v 0.900000 9.020000 1.500000
15+
16+
17+
18+
# Faces: 12
19+
20+
f 6 8 2
21+
f 2 8 4
22+
f 5 7 6
23+
f 6 7 8
24+
f 1 3 5
25+
f 5 3 7
26+
f 2 4 1
27+
f 1 4 3
28+
f 7 3 8
29+
f 8 3 4
30+
f 1 5 2
31+
f 2 5 6
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
solid base
2+
facet normal 6.982962e-015 0.000000e+000 1.000000e+000
3+
outer loop
4+
vertex 9.000000e-001 -9.020000e+000 1.500000e+000
5+
vertex 9.000000e-001 9.020000e+000 1.500000e+000
6+
vertex -9.000000e-001 -9.020000e+000 1.500000e+000
7+
endloop
8+
endfacet
9+
facet normal 6.982962e-015 0.000000e+000 1.000000e+000
10+
outer loop
11+
vertex -9.000000e-001 -9.020000e+000 1.500000e+000
12+
vertex 9.000000e-001 9.020000e+000 1.500000e+000
13+
vertex -9.000000e-001 9.020000e+000 1.500000e+000
14+
endloop
15+
endfacet
16+
facet normal 1.000000e+000 0.000000e+000 -7.205007e-015
17+
outer loop
18+
vertex 9.000000e-001 -9.020000e+000 6.217249e-015
19+
vertex 9.000000e-001 9.020000e+000 -6.217249e-015
20+
vertex 9.000000e-001 -9.020000e+000 1.500000e+000
21+
endloop
22+
endfacet
23+
facet normal 1.000000e+000 0.000000e+000 -7.205007e-015
24+
outer loop
25+
vertex 9.000000e-001 -9.020000e+000 1.500000e+000
26+
vertex 9.000000e-001 9.020000e+000 -6.217249e-015
27+
vertex 9.000000e-001 9.020000e+000 1.500000e+000
28+
endloop
29+
endfacet
30+
facet normal -6.982962e-015 0.000000e+000 -1.000000e+000
31+
outer loop
32+
vertex -9.000000e-001 -9.020000e+000 6.284666e-015
33+
vertex -9.000000e-001 9.020000e+000 6.284666e-015
34+
vertex 9.000000e-001 -9.020000e+000 -6.284666e-015
35+
endloop
36+
endfacet
37+
facet normal -6.982962e-015 0.000000e+000 -1.000000e+000
38+
outer loop
39+
vertex 9.000000e-001 -9.020000e+000 -6.284666e-015
40+
vertex -9.000000e-001 9.020000e+000 6.284666e-015
41+
vertex 9.000000e-001 9.020000e+000 -6.284666e-015
42+
endloop
43+
endfacet
44+
facet normal -1.000000e+000 0.000000e+000 7.056977e-015
45+
outer loop
46+
vertex -9.000000e-001 -9.020000e+000 1.500000e+000
47+
vertex -9.000000e-001 9.020000e+000 1.500000e+000
48+
vertex -9.000000e-001 -9.020000e+000 -6.284666e-015
49+
endloop
50+
endfacet
51+
facet normal -1.000000e+000 0.000000e+000 7.056977e-015
52+
outer loop
53+
vertex -9.000000e-001 -9.020000e+000 -6.284666e-015
54+
vertex -9.000000e-001 9.020000e+000 1.500000e+000
55+
vertex -9.000000e-001 9.020000e+000 6.284666e-015
56+
endloop
57+
endfacet
58+
facet normal 0.000000e+000 1.000000e+000 0.000000e+000
59+
outer loop
60+
vertex 9.000000e-001 9.020000e+000 -6.284666e-015
61+
vertex -9.000000e-001 9.020000e+000 6.284666e-015
62+
vertex 9.000000e-001 9.020000e+000 1.500000e+000
63+
endloop
64+
endfacet
65+
facet normal 0.000000e+000 1.000000e+000 0.000000e+000
66+
outer loop
67+
vertex 9.000000e-001 9.020000e+000 1.500000e+000
68+
vertex -9.000000e-001 9.020000e+000 6.284666e-015
69+
vertex -9.000000e-001 9.020000e+000 1.500000e+000
70+
endloop
71+
endfacet
72+
facet normal 6.982962e-015 -1.000000e+000 0.000000e+000
73+
outer loop
74+
vertex -9.000000e-001 -9.020000e+000 -6.284666e-015
75+
vertex 9.000000e-001 -9.020000e+000 6.284666e-015
76+
vertex -9.000000e-001 -9.020000e+000 1.500000e+000
77+
endloop
78+
endfacet
79+
facet normal 6.982962e-015 -1.000000e+000 0.000000e+000
80+
outer loop
81+
vertex -9.000000e-001 -9.020000e+000 1.500000e+000
82+
vertex 9.000000e-001 -9.020000e+000 6.284666e-015
83+
vertex 9.000000e-001 -9.020000e+000 1.500000e+000
84+
endloop
85+
endfacet
86+
endsolid

0 commit comments

Comments
 (0)