diff --git a/test/mesh/test_structured.jl b/test/mesh/test_structured.jl deleted file mode 100644 index 708d606..0000000 --- a/test/mesh/test_structured.jl +++ /dev/null @@ -1,292 +0,0 @@ -# This file is a part of JuliaFEM. -# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md - -using Test -using JuliaFEM -using Tensors - -@testset "Structured mesh generation" begin - @testset "Unit cube - single element" begin - mesh = create_unit_cube_mesh(Hex8) - - # Should have 8 nodes (corners of unit cube) - @test nnodes_total(mesh) == 8 - - # Should have 1 element - @test nelements(mesh) == 1 - - # Check corner coordinates (in IJK storage order: i fastest, then j, then k) - @test mesh.nodes[1] ≈ Vec(0.0, 0.0, 0.0) # i=1, j=1, k=1 - @test mesh.nodes[2] ≈ Vec(1.0, 0.0, 0.0) # i=2, j=1, k=1 - @test mesh.nodes[3] ≈ Vec(0.0, 1.0, 0.0) # i=1, j=2, k=1 - @test mesh.nodes[4] ≈ Vec(1.0, 1.0, 0.0) # i=2, j=2, k=1 - @test mesh.nodes[5] ≈ Vec(0.0, 0.0, 1.0) # i=1, j=1, k=2 - @test mesh.nodes[6] ≈ Vec(1.0, 0.0, 1.0) # i=2, j=1, k=2 - @test mesh.nodes[7] ≈ Vec(0.0, 1.0, 1.0) # i=1, j=2, k=2 - @test mesh.nodes[8] ≈ Vec(1.0, 1.0, 1.0) # i=2, j=2, k=2 - - # Check connectivity - @test length(mesh.connectivity[1]) == 8 - - # Check element sets - @test haskey(mesh.element_sets, :all) - @test length(mesh.element_sets[:all]) == 1 - - # Check node sets exist - @test haskey(mesh.node_sets, :all) - @test haskey(mesh.node_sets, :xmin) - @test haskey(mesh.node_sets, :xmax) - @test haskey(mesh.node_sets, :ymin) - @test haskey(mesh.node_sets, :ymax) - @test haskey(mesh.node_sets, :zmin) - @test haskey(mesh.node_sets, :zmax) - - println("Unit cube (1 element): OK") - end - - @testset "Unit cube - 2×2×2 elements" begin - mesh = create_unit_cube_mesh(Hex8, nx=2, ny=2, nz=2) - - # Should have (2+1)³ = 27 nodes - @test nnodes_total(mesh) == 27 - - # Should have 2³ = 8 elements - @test nelements(mesh) == 8 - - # Check that all elements have 8 nodes - for conn in mesh.connectivity - @test length(conn) == 8 - end - - # Check boundary node sets - xmin_nodes = mesh.node_sets[:xmin] - @test length(xmin_nodes) == 9 # 3×3 face - - # All xmin nodes should have x ≈ 0.0 - for node_id in xmin_nodes - @test mesh.nodes[node_id][1] ≈ 0.0 - end - - # All xmax nodes should have x ≈ 1.0 - xmax_nodes = mesh.node_sets[:xmax] - @test length(xmax_nodes) == 9 - for node_id in xmax_nodes - @test mesh.nodes[node_id][1] ≈ 1.0 - end - - println("Unit cube (2³ elements): OK") - end - - @testset "Structured box - custom dimensions" begin - # Create 10×2×2 box - mesh = create_structured_box_mesh(Hex8, - xmin=0.0, xmax=10.0, nx=5, - ymin=0.0, ymax=2.0, ny=2, - zmin=0.0, zmax=2.0, nz=2) - - # Should have (5+1)×(2+1)×(2+1) = 6×3×3 = 54 nodes - @test nnodes_total(mesh) == 54 - - # Should have 5×2×2 = 20 elements - @test nelements(mesh) == 20 - - # Check domain bounds - all_x = [node[1] for node in mesh.nodes] - all_y = [node[2] for node in mesh.nodes] - all_z = [node[3] for node in mesh.nodes] - - @test minimum(all_x) ≈ 0.0 - @test maximum(all_x) ≈ 10.0 - @test minimum(all_y) ≈ 0.0 - @test maximum(all_y) ≈ 2.0 - @test minimum(all_z) ≈ 0.0 - @test maximum(all_z) ≈ 2.0 - - println("Structured box (custom dimensions): OK") - end - - @testset "Structured box - uniform spacing" begin - # Create mesh with known spacing - mesh = create_structured_box_mesh(Hex8, - xmin=0.0, xmax=4.0, nx=4, - ymin=0.0, ymax=3.0, ny=3, - zmin=0.0, zmax=2.0, nz=2) - - # Check uniform spacing - # X spacing should be 1.0 - x_coords = sort(unique([node[1] for node in mesh.nodes])) - @test length(x_coords) == 5 - for i in 2:length(x_coords) - @test x_coords[i] - x_coords[i-1] ≈ 1.0 - end - - # Y spacing should be 1.0 - y_coords = sort(unique([node[2] for node in mesh.nodes])) - @test length(y_coords) == 4 - for i in 2:length(y_coords) - @test y_coords[i] - y_coords[i-1] ≈ 1.0 - end - - # Z spacing should be 1.0 - z_coords = sort(unique([node[3] for node in mesh.nodes])) - @test length(z_coords) == 3 - for i in 2:length(z_coords) - @test z_coords[i] - z_coords[i-1] ≈ 1.0 - end - - println("Uniform spacing verification: OK") - end - - @testset "Cantilever mesh" begin - mesh = create_cantilever_mesh(Hex8, - length=10.0, width=2.0, height=2.0, - nx=10, ny=2, nz=2) - - # Should have (10+1)×(2+1)×(2+1) = 11×3×3 = 99 nodes - @test nnodes_total(mesh) == 99 - - # Should have 10×2×2 = 40 elements - @test nelements(mesh) == 40 - - # Check dimensions - all_x = [node[1] for node in mesh.nodes] - all_y = [node[2] for node in mesh.nodes] - all_z = [node[3] for node in mesh.nodes] - - @test maximum(all_x) - minimum(all_x) ≈ 10.0 - @test maximum(all_y) - minimum(all_y) ≈ 2.0 - @test maximum(all_z) - minimum(all_z) ≈ 2.0 - - # Boundary node sets should exist - @test haskey(mesh.node_sets, :xmin) # Fixed end - @test haskey(mesh.node_sets, :xmax) # Free end - - # Fixed end should have 3×3 = 9 nodes - @test length(mesh.node_sets[:xmin]) == 9 - - println("Cantilever mesh: OK") - end - - @testset "Thin plate mesh" begin - mesh = create_thin_plate_mesh(Hex8, - length=10.0, width=10.0, thickness=0.1, - nx=5, ny=5, nz=1) - - # Should have (5+1)×(5+1)×(1+1) = 6×6×2 = 72 nodes - @test nnodes_total(mesh) == 72 - - # Should have 5×5×1 = 25 elements - @test nelements(mesh) == 25 - - # Check thickness - all_z = [node[3] for node in mesh.nodes] - @test maximum(all_z) - minimum(all_z) ≈ 0.1 - - # Top and bottom surfaces - @test haskey(mesh.node_sets, :zmin) - @test haskey(mesh.node_sets, :zmax) - - # Each surface should have 6×6 = 36 nodes - @test length(mesh.node_sets[:zmin]) == 36 - @test length(mesh.node_sets[:zmax]) == 36 - - println("Thin plate mesh: OK") - end - - @testset "Anisotropic mesh" begin - # Fine in X, coarse in Y and Z - mesh = create_structured_box_mesh(Hex8, - xmin=0.0, xmax=10.0, nx=20, - ymin=0.0, ymax=1.0, ny=2, - zmin=0.0, zmax=1.0, nz=2) - - # Should have (20+1)×(2+1)×(2+1) = 21×3×3 = 189 nodes - @test nnodes_total(mesh) == 189 - - # Should have 20×2×2 = 80 elements - @test nelements(mesh) == 80 - - # X should have finer spacing than Y and Z - x_coords = sort(unique([node[1] for node in mesh.nodes])) - y_coords = sort(unique([node[2] for node in mesh.nodes])) - z_coords = sort(unique([node[3] for node in mesh.nodes])) - - x_spacing = x_coords[2] - x_coords[1] - y_spacing = y_coords[2] - y_coords[1] - z_spacing = z_coords[2] - z_coords[1] - - @test x_spacing ≈ 0.5 - @test y_spacing ≈ 0.5 - @test z_spacing ≈ 0.5 - - @test length(x_coords) == 21 # Fine - @test length(y_coords) == 3 # Coarse - @test length(z_coords) == 3 # Coarse - - println("Anisotropic mesh: OK") - end - - @testset "Connectivity validation" begin - mesh = create_unit_cube_mesh(Hex8, nx=2, ny=2, nz=2) - - # Every element should have 8 unique nodes - for (elem_id, conn) in enumerate(mesh.connectivity) - @test length(conn) == 8 - @test length(unique(conn)) == 8 # All nodes unique - - # All node indices should be valid - for node_id in conn - @test 1 ≤ node_id ≤ nnodes_total(mesh) - end - end - - # Check that mesh validation passes - @test validate(mesh) == true - - println("Connectivity validation: OK") - end - - @testset "Integration with refinement" begin - # Create coarse mesh, then refine - coarse = create_cantilever_mesh(Hex8, - length=10.0, width=2.0, height=2.0, - nx=2, ny=1, nz=1) - - @test nelements(coarse) == 2 - - # Refine 2 levels - refined = refine(coarse, LongestEdgeBisection(2)) - - # Should have more elements - @test nelements(refined) > nelements(coarse) - @test nelements(refined) == 8 # 2 → 4 → 8 - - println("Integration with refinement: OK") - end - - @testset "Convergence study pattern" begin - # Simulate typical convergence study - results = [] - - for n in [1, 2, 4, 8] - mesh = create_unit_cube_mesh(Hex8, nx=n, ny=n, nz=n) - - n_elem = nelements(mesh) - n_nodes = nnodes_total(mesh) - n_dofs = 3 * n_nodes - - push!(results, (n=n, elements=n_elem, nodes=n_nodes, dofs=n_dofs)) - end - - # Check that refinement increases mesh size correctly - @test results[1].elements == 1 # 1³ - @test results[2].elements == 8 # 2³ - @test results[3].elements == 64 # 4³ - @test results[4].elements == 512 # 8³ - - println("Convergence study pattern:") - for r in results - println(" n=$(r.n): $(r.elements) elements, $(r.nodes) nodes, $(r.dofs) DOFs") - end - end -end