Files
JuliaFEM.jl/test/test_integration_points_api.jl
T
Jukka Aho b6b5ea4b1a test: Add zero-allocation integration points API validation
- Tests get_gauss_points!() for 5 topology types (Segment, Triangle, Tetrahedron, Quadrilateral, Hexahedron)
- Validates zero allocation property for all quadrature orders
- Verifies return type: NTuple of (Float64, Vec{D}) pairs
- Tests weight summation equals reference element area/volume
- Demonstrates usage in assembly loop with zero allocations
- Includes performance comparison benchmarking
- 151 lines of comprehensive integration points validation
2025-11-11 23:59:32 +02:00

152 lines
4.5 KiB
Julia
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Test: Zero-Allocation Integration Points
# =========================================
using Test
using JuliaFEM
using Tensors
using BenchmarkTools
@testset "Integration Points API" begin
@testset "Zero Allocation" begin
# All integration point queries should allocate zero bytes
@test (@allocated get_gauss_points!(Segment, Gauss{1})) == 0
@test (@allocated get_gauss_points!(Triangle, Gauss{1})) == 0
@test (@allocated get_gauss_points!(Tetrahedron, Gauss{1})) == 0
@test (@allocated get_gauss_points!(Hexahedron, Gauss{2})) == 0
end
@testset "Return Type" begin
# Should return NTuple of (Float64, Vec{D}) pairs
ips = get_gauss_points!(Triangle, Gauss{1})
@test isa(ips, Tuple)
@test length(ips) == 1
w, ξ = ips[1]
@test isa(w, Float64)
@test isa(ξ, Vec{2})
end
@testset "Segment" begin
# 1-point Gauss
ips = get_gauss_points!(Segment, Gauss{1})
@test length(ips) == 1
w, ξ = ips[1]
@test w 2.0
@test ξ[1] 0.0
# 2-point Gauss
ips = get_gauss_points!(Segment, Gauss{2})
@test length(ips) == 2
@test sum(ip[1] for ip in ips) 2.0 # Weights sum to length
end
@testset "Triangle" begin
# 1-point Gauss (centroid)
ips = get_gauss_points!(Triangle, Gauss{1})
@test length(ips) == 1
w, ξ = ips[1]
@test w 0.5 # Area of reference triangle
@test ξ[1] 1 / 3
@test ξ[2] 1 / 3
# 3-point Gauss
ips = get_gauss_points!(Triangle, Gauss{2})
@test length(ips) == 3
@test sum(ip[1] for ip in ips) 0.5
end
@testset "Tetrahedron" begin
# 1-point Gauss (centroid)
ips = get_gauss_points!(Tetrahedron, Gauss{1})
@test length(ips) == 1
w, ξ = ips[1]
@test w 1 / 6 # Volume of reference tetrahedron
@test ξ[1] 0.25
@test ξ[2] 0.25
@test ξ[3] 0.25
# 4-point Gauss
ips = get_gauss_points!(Tetrahedron, Gauss{2})
@test length(ips) == 4
@test sum(ip[1] for ip in ips) 1 / 6
end
@testset "Quadrilateral" begin
# 2×2 Gauss (standard for Q1)
ips = get_gauss_points!(Quadrilateral, Gauss{2})
@test length(ips) == 4
@test sum(ip[1] for ip in ips) 4.0 # Area of reference quad
end
@testset "Hexahedron" begin
# 2×2×2 Gauss (standard for Hex8)
ips = get_gauss_points!(Hexahedron, Gauss{2})
@test length(ips) == 8
@test sum(ip[1] for ip in ips) 8.0 # Volume of reference hex
end
end
@testset "Usage in Assembly Loop" begin
# Demonstrate zero-allocation assembly pattern
function assemble_element_stiffness()
K = 0.0
for (w, ξ) in get_gauss_points!(Triangle, Gauss{2})
# Shape functions
N1 = 1 - ξ[1] - ξ[2]
N2 = ξ[1]
N3 = ξ[2]
# Accumulate (simplified stiffness)
K += w * (N1^2 + N2^2 + N3^2)
end
return K
end
# Should allocate zero
@test (@allocated assemble_element_stiffness()) == 0
# Verify result is consistent
K1 = assemble_element_stiffness()
K2 = assemble_element_stiffness()
@test K1 K2
end
@testset "Performance Comparison" begin
println("\n" * "="^70)
println("PERFORMANCE: Integration Points vs Old Approach")
println("="^70)
# New approach (compile-time, Vec{D})
new_approach() = begin
sum_val = 0.0
for _ in 1:1000
for (w, ξ) in get_gauss_points!(Triangle, Gauss{2})
sum_val += w * sum(ξ)
end
end
return sum_val
end
println("\nNew approach (compile-time + Vec{D}):")
display(@benchmark $new_approach())
println("\n\nExpected: ~1 μs, 0 allocations")
println("="^70)
end
println("\n✓ All integration point tests passed!")
println("\nUsage Example (NEW API):")
println("```julia")
println("# Zero-allocation loop over integration points:")
println("for (weight, ξ) in get_gauss_points!(Triangle, Gauss{2})")
println(" # NEW API (recommended):")
println(" N = get_basis_functions(Triangle(), Lagrange{1}(), ξ)")
println(" dN = get_basis_derivatives(Triangle(), Lagrange{1}(), ξ)")
println(" # ... compute element matrices")
println("end")
println("```")
println()
println("Note: eval_basis! and eval_dbasis! are DEPRECATED.")
println("Use get_basis_functions and get_basis_derivatives instead.")