Files
rustytorch/crates/specialized/rtx-cfd/tests/mesh_tests.rs
T
2026-03-04 00:08:42 +00:00

218 lines
6.8 KiB
Rust

// TDD: RED phase - Write tests first for mesh module
use nalgebra::Vector3;
use rtx_cfd::mesh::{Cell, Face, Mesh, Node, StructuredMesh, UnstructuredMesh};
use rtx_cfd::traits::MeshEntity;
#[test]
fn test_structured_mesh_creation() {
let mesh = StructuredMesh::new(10, 20, 1.0, 2.0).unwrap();
assert_eq!(mesh.nx(), 10);
assert_eq!(mesh.ny(), 20);
assert_eq!(mesh.nz(), 1); // 2D mesh
assert_eq!(mesh.width(), 1.0);
assert_eq!(mesh.height(), 2.0);
assert_eq!(mesh.depth(), 0.0); // 2D mesh
// Check total number of cells
assert_eq!(mesh.cell_count(), 9 * 19); // (nx-1) * (ny-1)
assert_eq!(mesh.node_count(), 10 * 20); // nx * ny
}
#[test]
fn test_structured_mesh_3d_creation() {
let mesh = StructuredMesh::new_3d(5, 6, 7, 1.0, 2.0, 3.0).unwrap();
assert_eq!(mesh.nx(), 5);
assert_eq!(mesh.ny(), 6);
assert_eq!(mesh.nz(), 7);
assert_eq!(mesh.width(), 1.0);
assert_eq!(mesh.height(), 2.0);
assert_eq!(mesh.depth(), 3.0);
// Check total number of cells and nodes
assert_eq!(mesh.cell_count(), 4 * 5 * 6); // (nx-1) * (ny-1) * (nz-1)
assert_eq!(mesh.node_count(), 5 * 6 * 7); // nx * ny * nz
}
#[test]
fn test_structured_mesh_node_access() {
let mesh = StructuredMesh::new(3, 3, 1.0, 1.0).unwrap();
// Test corner nodes
let node_00 = mesh.get_node(0, 0, 0).unwrap();
assert_eq!(node_00.position(), Vector3::new(0.0, 0.0, 0.0));
let node_22 = mesh.get_node(2, 2, 0).unwrap();
assert_eq!(node_22.position(), Vector3::new(1.0, 1.0, 0.0));
// Test center node
let node_11 = mesh.get_node(1, 1, 0).unwrap();
assert_eq!(node_11.position(), Vector3::new(0.5, 0.5, 0.0));
}
#[test]
fn test_structured_mesh_cell_access() {
let mesh = StructuredMesh::new(3, 3, 1.0, 1.0).unwrap();
// Test cell (0,0) - bottom-left cell
let cell = mesh.get_cell(0, 0, 0).unwrap();
let vertices = cell.vertex_indices();
// Should have 4 vertices for 2D quad cell
assert_eq!(vertices.len(), 4);
// Check cell volume (should be area for 2D)
assert!((cell.volume() - 0.25).abs() < 1e-10); // 0.5 * 0.5 = 0.25
}
#[test]
fn test_structured_mesh_neighbor_connectivity() {
let mesh = StructuredMesh::new(4, 4, 1.0, 1.0).unwrap();
// Get center cell
let cell = mesh.get_cell(1, 1, 0).unwrap();
let neighbors = mesh.get_cell_neighbors(cell.id()).unwrap();
// Should have 4 neighbors in 2D (excluding boundaries)
assert_eq!(neighbors.len(), 4);
}
#[test]
fn test_structured_mesh_boundary_detection() {
let mesh = StructuredMesh::new(3, 3, 1.0, 1.0).unwrap();
// Corner cell should be on boundary
let corner_cell = mesh.get_cell(0, 0, 0).unwrap();
assert!(mesh.is_boundary_cell(corner_cell.id()));
// Center cell should not be on boundary (but for 3x3 grid, all cells are boundary)
// Let's use a larger grid
let large_mesh = StructuredMesh::new(5, 5, 1.0, 1.0).unwrap();
let center_cell = large_mesh.get_cell(1, 1, 0).unwrap();
assert!(!large_mesh.is_boundary_cell(center_cell.id()));
}
#[test]
fn test_unstructured_mesh_creation() {
let mut mesh = UnstructuredMesh::new();
// Add nodes
let node1 = mesh.add_node(Vector3::new(0.0, 0.0, 0.0)).unwrap();
let node2 = mesh.add_node(Vector3::new(1.0, 0.0, 0.0)).unwrap();
let node3 = mesh.add_node(Vector3::new(0.5, 1.0, 0.0)).unwrap();
assert_eq!(mesh.node_count(), 3);
// Add triangular cell
let cell = mesh.add_triangle_cell(node1, node2, node3).unwrap();
assert_eq!(mesh.cell_count(), 1);
// Check cell properties
let cell_obj = mesh.get_cell(cell).unwrap();
assert_eq!(cell_obj.vertex_count(), 3);
assert!(cell_obj.volume() > 0.0); // Triangle should have positive area
}
#[test]
fn test_unstructured_mesh_quadrilateral() {
let mut mesh = UnstructuredMesh::new();
// Add nodes for a quadrilateral
let n1 = mesh.add_node(Vector3::new(0.0, 0.0, 0.0)).unwrap();
let n2 = mesh.add_node(Vector3::new(1.0, 0.0, 0.0)).unwrap();
let n3 = mesh.add_node(Vector3::new(1.0, 1.0, 0.0)).unwrap();
let n4 = mesh.add_node(Vector3::new(0.0, 1.0, 0.0)).unwrap();
let cell = mesh.add_quadrilateral_cell(n1, n2, n3, n4).unwrap();
let cell_obj = mesh.get_cell(cell).unwrap();
assert_eq!(cell_obj.vertex_count(), 4);
assert!((cell_obj.volume() - 1.0).abs() < 1e-10); // Unit square area
}
#[test]
fn test_mesh_refinement() {
let mut mesh = StructuredMesh::new(2, 2, 1.0, 1.0).unwrap();
let original_cell_count = mesh.cell_count();
// Refine the mesh
mesh.refine().unwrap();
// After refinement, should have 4x more cells
assert_eq!(mesh.cell_count(), original_cell_count * 4);
}
#[test]
fn test_node_entity_interface() {
let node = Node::new(0, Vector3::new(1.0, 2.0, 3.0));
assert_eq!(node.id(), 0);
assert_eq!(node.vertex_count(), 1);
assert_eq!(node.vertex_indices(), &[0]);
assert_eq!(node.volume(), 1.0); // Nodes have unit volume by convention
assert_eq!(node.centroid(), Vector3::new(1.0, 2.0, 3.0));
assert_eq!(node.position(), Vector3::new(1.0, 2.0, 3.0));
}
#[test]
fn test_face_entity_interface() {
let face = Face::new(0, vec![0, 1], Vector3::new(0.5, 0.5, 0.0), 1.0);
assert_eq!(face.id(), 0);
assert_eq!(face.vertex_count(), 2);
assert_eq!(face.vertex_indices(), &[0, 1]);
assert_eq!(face.volume(), 1.0); // Face volume is the area
assert_eq!(face.centroid(), Vector3::new(0.5, 0.5, 0.0));
}
#[test]
fn test_cell_entity_interface() {
let cell = Cell::new(0, vec![0, 1, 2, 3], Vector3::new(0.5, 0.5, 0.0), 1.0);
assert_eq!(cell.id(), 0);
assert_eq!(cell.vertex_count(), 4);
assert_eq!(cell.vertex_indices(), &[0, 1, 2, 3]);
assert_eq!(cell.volume(), 1.0);
assert_eq!(cell.centroid(), Vector3::new(0.5, 0.5, 0.0));
}
#[test]
fn test_mesh_validation() {
let mesh = StructuredMesh::new(3, 3, 1.0, 1.0).unwrap();
// Validate mesh topology
assert!(mesh.validate().is_ok());
}
#[test]
fn test_mesh_bounds() {
let mesh = StructuredMesh::new(4, 5, 2.0, 3.0).unwrap();
let bounds = mesh.bounds();
assert_eq!(bounds.min, Vector3::new(0.0, 0.0, 0.0));
assert_eq!(bounds.max, Vector3::new(2.0, 3.0, 0.0));
}
#[test]
fn test_mesh_statistics() {
let mesh = StructuredMesh::new(3, 3, 1.0, 1.0).unwrap();
let stats = mesh.statistics();
assert_eq!(stats.total_cells, 4); // 2x2 cells
assert_eq!(stats.total_nodes, 9); // 3x3 nodes
assert_eq!(stats.boundary_faces > 0, true);
assert!(stats.min_cell_volume > 0.0);
assert!(stats.max_cell_volume > 0.0);
assert!(stats.average_cell_volume > 0.0);
}
#[test]
fn test_invalid_mesh_dimensions() {
// Test invalid dimensions
assert!(StructuredMesh::new(0, 5, 1.0, 1.0).is_err());
assert!(StructuredMesh::new(5, 0, 1.0, 1.0).is_err());
assert!(StructuredMesh::new(5, 5, 0.0, 1.0).is_err());
assert!(StructuredMesh::new(5, 5, 1.0, 0.0).is_err());
}