use plot3d::{
connectivity_fast, read_plot3d_binary, BinaryFormat, Endian, FloatPrecision, FaceRecord,
};
const BLADE0_PATH: &str = "tests/data/blade0.xyz";
const BLOCK_NAMES: [&str; 5] = ["ss_ogrid", "ps_ogrid", "le_wedge", "te_wedge", "passage"];
fn face_key(f: &FaceRecord) -> (usize, [usize; 3], [usize; 3]) {
(
f.block_index,
[f.il.min(f.ih), f.jl.min(f.jh), f.kl.min(f.kh)],
[f.il.max(f.ih), f.jl.max(f.jh), f.kl.max(f.kh)],
)
}
#[test]
fn test_read_blade0() {
if !std::path::Path::new(BLADE0_PATH).exists() {
eprintln!("Skipping: {} not found", BLADE0_PATH);
return;
}
let blocks =
read_plot3d_binary(BLADE0_PATH, BinaryFormat::Raw, FloatPrecision::F64, Endian::Little)
.expect("Failed to read blade0.xyz");
assert_eq!(blocks.len(), 5, "Expected 5 blocks");
for (i, b) in blocks.iter().enumerate() {
println!(
" Block {} ({}): ({}, {}, {})",
i, BLOCK_NAMES[i], b.imax, b.jmax, b.kmax
);
}
assert_eq!((blocks[0].imax, blocks[0].jmax, blocks[0].kmax), (161, 25, 65));
assert_eq!((blocks[1].imax, blocks[1].jmax, blocks[1].kmax), (161, 25, 65));
assert_eq!((blocks[2].imax, blocks[2].jmax, blocks[2].kmax), (21, 33, 65));
assert_eq!((blocks[3].imax, blocks[3].jmax, blocks[3].kmax), (33, 25, 65));
assert_eq!((blocks[4].imax, blocks[4].jmax, blocks[4].kmax), (185, 41, 65));
}
#[test]
fn test_connectivity_no_false_positives() {
if !std::path::Path::new(BLADE0_PATH).exists() {
eprintln!("Skipping: {} not found", BLADE0_PATH);
return;
}
let blocks =
read_plot3d_binary(BLADE0_PATH, BinaryFormat::Raw, FloatPrecision::F64, Endian::Little)
.expect("Failed to read blade0.xyz");
let (matches, outer_faces) = connectivity_fast(&blocks);
println!("\n=== Single-blade connectivity ===");
println!(" Face matches: {}", matches.len());
println!(" Outer faces: {}", outer_faces.len());
for (i, m) in matches.iter().enumerate() {
let b1 = &m.block1;
let b2 = &m.block2;
let n1 = BLOCK_NAMES.get(b1.block_index).unwrap_or(&"?");
let n2 = BLOCK_NAMES.get(b2.block_index).unwrap_or(&"?");
println!(
" Match {}: {} [{},{},{}]-[{},{},{}] <-> {} [{},{},{}]-[{},{},{}] ({} pts)",
i,
n1, b1.il, b1.jl, b1.kl, b1.ih, b1.jh, b1.kh,
n2, b2.il, b2.jl, b2.kl, b2.ih, b2.jh, b2.kh,
m.points.len(),
);
}
let false_positive_faces = [
((0, [0, 0, 0], [160, 0, 64]), (1, [0, 0, 0], [160, 0, 64])),
((0, [0, 24, 0], [160, 24, 64]), (1, [0, 24, 0], [160, 24, 64])),
((0, [0, 0, 0], [160, 24, 0]), (1, [0, 0, 0], [160, 24, 0])),
((0, [0, 0, 64], [160, 24, 64]), (1, [0, 0, 64], [160, 24, 64])),
];
for (fp1, fp2) in &false_positive_faces {
let found = matches.iter().any(|m| {
let k1 = face_key(&m.block1);
let k2 = face_key(&m.block2);
(k1 == *fp1 && k2 == *fp2) || (k1 == *fp2 && k2 == *fp1)
});
assert!(
!found,
"FALSE POSITIVE: block {} [{:?}]-[{:?}] <-> block {} [{:?}]-[{:?}] should NOT match",
fp1.0, fp1.1, fp1.2, fp2.0, fp2.1, fp2.2,
);
}
println!("\n No false positives between SS/PS ogrid.");
let expected_interfaces = [
((0, [0, 0, 0], [0, 24, 64]), (1, [0, 0, 0], [0, 24, 64])),
((0, [160, 0, 0], [160, 24, 64]), (1, [160, 0, 0], [160, 24, 64])),
];
for (exp1, exp2) in &expected_interfaces {
let found = matches.iter().any(|m| {
let k1 = face_key(&m.block1);
let k2 = face_key(&m.block2);
(k1 == *exp1 && k2 == *exp2) || (k1 == *exp2 && k2 == *exp1)
});
assert!(
found,
"MISSING: block {} [{:?}]-[{:?}] <-> block {} [{:?}]-[{:?}] should match",
exp1.0, exp1.1, exp1.2, exp2.0, exp2.1, exp2.2,
);
}
println!(" Expected SS/PS LE/TE matches found.");
println!("\n Outer faces:");
for f in &outer_faces {
let bname = BLOCK_NAMES.get(f.block_index).unwrap_or(&"?");
println!(
" id={:3} {} [{},{},{}]-[{},{},{}]",
f.id.unwrap_or(0),
bname,
f.il, f.jl, f.kl, f.ih, f.jh, f.kh,
);
}
}