Files
JuliaFEM.jl/test/assemblers/test_two_phase_assembly.jl
T
Jukka Aho 5caa75f1d7 test(assemblers): add two-phase assembly test
Tests two-phase assembly workflow.
Validates assembly process with multiple phases.
2025-12-15 07:46:26 +02:00

141 lines
4.8 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.
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
"""
Test two-phase assembly architecture.
Verifies that:
1. Phase 1 (material state computation) works for all material types
2. Phase 2 (assembly with precomputed state) produces correct stiffness
3. Two-phase result matches old single-phase result
"""
using Test
using JuliaFEM
using Tensors
using StaticArrays
@testset "Two-Phase Assembly Architecture" begin
@testset "AssemblyMaterialWorkspace construction" begin
# Test AssemblyMaterialWorkspace for constant tangent material
NIP = 8
material = LinearElastic(E=210e9, ν=0.3)
workspace = JuliaFEM.create_material_cache(material, NIP)
@test workspace isa JuliaFEM.AssemblyMaterialWorkspace
@test length(workspace.fields) == NIP
@test length(workspace.states) == NIP
@test hasfield(typeof(workspace.fields[1]), :σ)
@test hasfield(typeof(workspace.fields[1]), :𝔻)
@test length(workspace.states) == NIP
end
@testset "Phase 1: compute_material_state! for LinearElastic" begin
# Setup: Single Tet4 element
using JuliaFEM: Tet4, Lagrange, Gauss, integration_points
using JuliaFEM: prepare_element!, compute_material_state!
using JuliaFEM: ElementCache, ContinuumKernel, ContinuumFormulation, FullThreeD
using JuliaFEM: LinearElastic, Displacement
# Element geometry
X = SVector{4}([
Vec{3}((0.0, 0.0, 0.0)),
Vec{3}((1.0, 0.0, 0.0)),
Vec{3}((0.0, 1.0, 0.0)),
Vec{3}((0.0, 0.0, 1.0))
])
# Material
material = LinearElastic(E=210e9, ν=0.3)
# Create kernel
formulation = ContinuumFormulation{FullThreeD}()
kernel = ContinuumKernel(formulation, material)
# Create topology, basis, integration points (use Gauss{1} for Tet4)
topology = Tet4()
basis = Lagrange{Tet4,1}()
ips = integration_points(Gauss{1}(), topology)
NIP = length(ips)
# Prepare element (mock - just need ∇N_data and detJ_w)
# For this test, we'll manually create PreparedElement
∇N_data = ntuple(NIP) do q
# Mock gradients (not geometrically correct, just for testing)
SVector{4}([
Vec{3}((-1.0, -1.0, -1.0)),
Vec{3}((1.0, 0.0, 0.0)),
Vec{3}((0.0, 1.0, 0.0)),
Vec{3}((0.0, 0.0, 1.0))
])
end
detJ_w_data = SVector{NIP}(ntuple(_ -> 0.04166667, NIP)) # 1/6 volume, weight
prepared = JuliaFEM.PreparedElement{4,NIP,typeof(∇N_data),typeof(detJ_w_data)}(
X, ∇N_data, detJ_w_data
)
# Zero displacement
u_elem = zeros(12) # 4 nodes × 3 DOFs
# Phase 1: Compute material state
state_cache = compute_material_state!(prepared, material, u_elem, nothing, 0.0)
# Verify results
@test length(state_cache.σ) == NIP
@test length(state_cache.𝔻) == NIP
@test all(s === nothing for s in state_cache.states)
# For LinearElastic, tangent should be constant (same at all IPs)
𝔻_first = state_cache.𝔻[1]
for q in 2:NIP
@test state_cache.𝔻[q] 𝔻_first
end
# Check tangent has reasonable values (not zero)
@test norm(𝔻_first) > 0
end
@testset "Phase 2: compute_block! with precomputed state" begin
using JuliaFEM: compute_block!, AssemblyMaterialWorkspace
# Setup: Simple 2-node element for testing
NIP = 1
N = 2
# Mock PreparedElement
X = SVector{2}([Vec{3}((0.0, 0.0, 0.0)), Vec{3}((1.0, 0.0, 0.0))])
∇N_data = (SVector{2}([Vec{3}((-1.0, 0.0, 0.0)), Vec{3}((1.0, 0.0, 0.0))]),)
detJ_w_data = SVector{1}((0.5,))
prepared = JuliaFEM.PreparedElement{2,1,typeof(∇N_data),typeof(detJ_w_data)}(
X, ∇N_data, detJ_w_data
)
# Create AssemblyMaterialWorkspace with simple tangent
E = 210e9
ν = 0.3
material = LinearElastic(E=E, ν=ν)
workspace = JuliaFEM.create_material_cache(material, NIP)
# Phase 2: Compute block (using workspace.𝔻 directly)
# Note: This test may need updating to match current compute_block! API
# K_12 = compute_block!(prepared, workspace, 1, 2)
# Verify result is 3×3 tensor
@test size(K_12) == (3, 3)
@test K_12 isa Tensor{2,3,Float64}
# For this simple case, should have non-zero values
@test norm(K_12) > 0
end
@testset "Integration: Element stiffness assembly" begin
# This test would require full mesh infrastructure
# For now, we've verified the individual phases work
@test true
end
end