# Test gradient properties for all elements using Test using StaticArrays, Tensors include("../../src/topology/api.jl") include("../../src/topology/segments.jl") include("../../src/topology/triangles.jl") include("../../src/topology/quadrilaterals.jl") include("../../src/topology/tetrahedra.jl") include("../../src/topology/hexahedra.jl") include("../../src/topology/pyramids.jl") include("../../src/topology/wedges.jl") include("../../src/basis/api.jl") include("../../src/basis/basis_generated.jl") @testset "Gradient Properties" begin @testset "Linear elements - constant gradients" begin # Tri3 gradients should be constant everywhere dN1 = get_basis_derivatives(Tri3(), Lagrange{1}(), Vec{2}((0.2, 0.3))) dN2 = get_basis_derivatives(Tri3(), Lagrange{1}(), Vec{2}((0.5, 0.4))) for i in 1:3 @test dN1[i] ≈ dN2[i] atol = 1e-14 end # Tet4 gradients should be constant everywhere dN1 = get_basis_derivatives(Tet4(), Lagrange{1}(), Vec{3}((0.1, 0.2, 0.3))) dN2 = get_basis_derivatives(Tet4(), Lagrange{1}(), Vec{3}((0.2, 0.1, 0.4))) for i in 1:4 @test dN1[i] ≈ dN2[i] atol = 1e-14 end end @testset "Sum of gradients = 0 (rigid body motion)" begin # For any basis, sum of all gradients should be zero vector # (ensures constant field has zero gradient) # 1D dN = get_basis_derivatives(Seg2(), Lagrange{1}(), Vec{1}((0.3,))) @test sum(dN)[1] ≈ 0.0 atol = 1e-14 # 2D dN = get_basis_derivatives(Tri6(), Lagrange{2}(), Vec{2}((0.3, 0.4))) sum_grad = sum(dN) @test sum_grad[1] ≈ 0.0 atol = 1e-14 @test sum_grad[2] ≈ 0.0 atol = 1e-14 dN = get_basis_derivatives(Quad9(), Lagrange{2}(), Vec{2}((0.5, -0.5))) sum_grad = sum(dN) @test sum_grad[1] ≈ 0.0 atol = 1e-14 @test sum_grad[2] ≈ 0.0 atol = 1e-14 # 3D dN = get_basis_derivatives(Hex27(), Lagrange{2}(), Vec{3}((0.2, 0.3, -0.1))) sum_grad = sum(dN) @test sum_grad[1] ≈ 0.0 atol = 1e-14 @test sum_grad[2] ≈ 0.0 atol = 1e-14 @test sum_grad[3] ≈ 0.0 atol = 1e-14 end @testset "Gradient return types" begin # Test that gradients have correct Vec type dN = get_basis_derivatives(Tri3(), Lagrange{1}(), Vec{2}((0.5, 0.25))) @test dN isa SVector{3,Vec{2,Float64}} @test dN[1] isa Vec{2,Float64} dN = get_basis_derivatives(Hex8(), Lagrange{1}(), Vec{3}((0.0, 0.0, 0.0))) @test dN isa SVector{8,Vec{3,Float64}} @test dN[1] isa Vec{3,Float64} end @testset "Numerical gradient check (finite differences)" begin # Simple finite difference check for Quad4 h = 1e-8 xi = Vec{2}((0.3, 0.4)) # Analytical gradient dN = get_basis_derivatives(Quad4(), Lagrange{1}(), xi) # Finite difference in u-direction N_plus = get_basis_functions(Quad4(), Lagrange{1}(), Vec{2}((xi[1] + h, xi[2]))) N_minus = get_basis_functions(Quad4(), Lagrange{1}(), Vec{2}((xi[1] - h, xi[2]))) dN_u_fd = (N_plus - N_minus) / (2h) for i in 1:4 @test dN[i][1] ≈ dN_u_fd[i] atol = 1e-6 end end end