// 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()); }