Files
JuliaFEM.jl/test/assemblers/test_partitioning_zero_alloc.jl
T

65 lines
2.7 KiB
Julia

# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
"""
Partition staging buffers (`BitVector` masks + scratch vectors) must stay
allocation-free in tight loops once workspace is allocated — same contract as
the DOF-based assembler regressions.
"""
using Test
using InteractiveUtils: @allocated
using JuliaFEM
using JuliaFEM: create_elements!, @DOFSet, DOF, Displacement, Vertex
using JuliaFEM: brick_hex_partition_slabs, element_indices_for_part
using JuliaFEM: sum_element_dof_slots, mark_referenced_dofs!, collect_true_indices!
using JuliaFEM: fill_referenced_dof_indices!, ghost_dof_mask!, node_partition_owner_min!
using JuliaFEM: mark_owned_vertex_field_dofs!
@testset "partitioning workspace hot path — zero allocations" begin
nx, ny, nz = 4, 3, 3
mesh = create_structured_box_mesh(Hex8; nx = nx, ny = ny, nz = nz)
S = @DOFSet{u::DOF{Displacement{3}, Vertex}}
elements, handler = create_elements!(mesh, Element{Hex8, Lagrange{1}, S})
layout = brick_hex_partition_slabs(nx, ny, nz, 3; axis = :z)
ndof = handler.total_dofs
nnodes = length(mesh.nodes)
ep = element_indices_for_part(layout, 2)
@test sum_element_dof_slots(elements, ep) > 0
mask_a = falses(ndof)
mask_b = falses(ndof)
mask_c = falses(ndof)
dof_buf = Vector{Int}(undef, ndof)
node_own = Vector{Int}(undef, nnodes)
node_partition_owner_min!(node_own, layout, mesh)
mark_referenced_dofs!(mask_a, elements, ep, ndof)
collect_true_indices!(dof_buf, mask_a)
fill_referenced_dof_indices!(dof_buf, mask_b, elements, ep, ndof)
mark_owned_vertex_field_dofs!(mask_b, handler, node_own, 2)
ghost_dof_mask!(mask_c, mask_a, mask_b)
# Warm LLVM / caches
for _ in 1:3
fill!(mask_a, false)
mark_referenced_dofs!(mask_a, elements, ep, ndof)
collect_true_indices!(dof_buf, mask_a)
fill!(mask_b, false)
fill_referenced_dof_indices!(dof_buf, mask_b, elements, ep, ndof)
node_partition_owner_min!(node_own, layout, mesh)
fill!(mask_b, false)
mark_owned_vertex_field_dofs!(mask_b, handler, node_own, 2)
ghost_dof_mask!(mask_c, mask_a, mask_b)
end
@test (@allocated mark_referenced_dofs!(mask_a, elements, ep, ndof)) == 0
@test (@allocated collect_true_indices!(dof_buf, mask_a)) == 0
@test (@allocated fill_referenced_dof_indices!(dof_buf, mask_b, elements, ep, ndof)) == 0
@test (@allocated node_partition_owner_min!(node_own, layout, mesh)) == 0
@test (@allocated mark_owned_vertex_field_dofs!(mask_b, handler, node_own, 2)) == 0
@test (@allocated ghost_dof_mask!(mask_c, mask_a, mask_b)) == 0
@test (@allocated sum_element_dof_slots(elements, ep)) == 0
end