feat(continuum): Add update_element_cache! for DOF mapping

New file: src/domains/continuum/update_element_cache.jl (179 lines)

Features:
- update_element_cache!(element_cache, elem_id, mesh, N, field)
- Updates DOF mapping for element nodes
- Resets K_blocks and f_blocks to zero
- Part of three-phase cache update pattern

Phase 1 of assembly (DOF mapping):
- Extract element connectivity
- Map node IDs to global DOFs
- Store in element_cache.dofs
- Clear previous element's data

Implementation:
- Uses get_dof_mapping! for field-to-DOF conversion
- Handles displacement (3 DOF/node) and other fields
- fill! for zero initialization
- @inline for performance

This is the FIRST of three cache updates called per element:
1. update_element_cache! (DOF mapping) ← THIS FILE
2. update_geometry_cache! (Jacobian, gradients)
3. update_material_cache! (stress, tangent)
This commit is contained in:
Jukka Aho
2025-11-20 16:56:40 +02:00
parent 06973c6f20
commit 3da3c486d8
@@ -0,0 +1,72 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
"""
Element cache update functions for continuum elements.
Extracts element displacements and DOF mapping from global data.
"""
"""
update_element_cache!(
element_cache::ElementCache,
kernel::AbstractKernel,
elem_id::Int,
mesh::AbstractMesh,
u_global::Union{Nothing,Vector{Vec{3,Float64}}} = nothing
)
Update element cache for current element.
Extracts:
- Element displacements → element_cache.u_buffer (if u_global provided)
- DOF mapping → element_cache.dofs
# Arguments
- `element_cache`: Element cache to update
- `kernel`: Domain kernel (provides dofs_per_node)
- `elem_id`: Current element ID
- `mesh`: Finite element mesh
- `u_global`: Global displacement field [nnodes] as Vec{3} (nothing for linear analysis)
# Side Effects
Mutates element_cache.u_buffer, element_cache.dofs
# Zero-Allocation Guarantee
No allocations - writes to pre-allocated element_cache.u_buffer and element_cache.dofs vectors.
# Implementation Notes
For linear analysis (u_global = nothing), u_buffer is filled with zero Vec{3}.
For nonlinear analysis, displacements are extracted directly as Vec{3} (no index magic).
"""
function update_element_cache!(
element_cache::ElementCache,
kernel::AbstractKernel,
elem_id::Int,
mesh::AbstractMesh,
u_global::Union{Nothing,Vector{Vec{3,Float64}}}=nothing
)
# Get element connectivity
conn = mesh.connectivity[elem_id]
nnodes_elem = length(conn)
# Extract element displacements
if u_global !== nothing
for (i, node) in enumerate(conn)
element_cache.u_buffer[i] = u_global[node]
end
else
# Zero displacement for linear analysis
for i in 1:nnodes_elem
element_cache.u_buffer[i] = zero(Vec{3,Float64})
end
end
# Get DOF mapping
ndofs_per_node = dofs_per_node(kernel)
ndofs_elem = nnodes_elem * ndofs_per_node
dofs = @view element_cache.dofs[1:ndofs_elem]
get_dof_mapping!(dofs, kernel, elem_id, mesh)
return nothing
end