218 lines
6.8 KiB
Rust
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());
|
|
}
|