feat(compat): Add compatibility shim for old mutable field API

Implements compatibility layer to allow old test code to run with new
immutable element design (though fields won't actually update).

src/elements/elements.jl:
- Replaced has_dfield/get_dfield to work with new fields API
- Fixed get_sfield/get_dfield to handle empty Tuple{} fields
- All dfield functions now map to element.fields (immutable NamedTuple)

src/topology/*.jl (seg2, tri3, quad4, tet4, hex8):
- Added nnodes() implementation for each topology type
- Returns corner node count (backwards compatibility)
- Example: nnodes(::Triangle) = 3, nnodes(::Hexahedron) = 8
- Note: Actual node count depends on basis degree in new architecture

Test Results:
- test_topology_standalone.jl: 36/36 tests passing ✓
- Full test suite: 43 errors (same as before)
- Error breakdown:
  * 40+ tests: Problem types not defined (Elasticity, Heat, Mortar)
  * 2 tests: Mesh readers not defined (aster_read_mesh)
  * 1 test: Tries to mutate empty element (test_elasticity_1d)

Next Steps:
- Tests that create empty elements then mutate need rewriting
- Pattern: Element(Seg2, (1,2)) + update!() → not compatible
- New pattern: Element(..., fields=(geometry=X, displacement=u))
- See docs/design/IMMUTABILITY.md for migration guide
This commit is contained in:
Jukka Aho
2025-11-09 18:08:39 +02:00
parent 32451ed978
commit 41e09b2c92
7 changed files with 145 additions and 42 deletions
+8 -4
View File
@@ -11,6 +11,7 @@
JuliaFEM 1.0 adopts **immutable elements with type-stable fields** as a core architectural decision. While this appears counterintuitive (requiring element copies instead of in-place mutation), benchmarks demonstrate **40-130x performance improvement** over the mutable Dict-based approach.
**Key Results:**
- Field access: **40x faster** (1ns vs 45ns per read)
- Assembly loop: **130x faster** (9ns vs 1,124ns per element)
- Large mesh: **120x faster** (0.01ms vs 1.2ms for 1000 elements)
@@ -124,6 +125,7 @@ Memory: 0 bytes
### 4. GPU/HPC Compatibility
**Mutable elements with Dict:**
```julia
struct MutableElement
fields::Dict{Symbol,Any} # POINTER → cannot transfer to GPU
@@ -131,6 +133,7 @@ end
```
**Immutable elements with NamedTuple:**
```julia
struct ImmutableElement{F}
fields::F # All bits types → can transfer to GPU!
@@ -138,6 +141,7 @@ end
```
GPU kernels require:
- No pointers (CPU memory → GPU memory not allowed)
- No dynamic dispatch (GPU can't call CPU functions)
- All data as bits types (can be copied to GPU)
@@ -177,10 +181,10 @@ Run: `julia --project=. benchmarks/element_immutability_benchmark.jl`
### Large Mesh (1000 elements)
| Implementation | Time | Memory |
|---------------|------|--------|
| Mutable | 1.2ms | 1.1 MB |
| Immutable | 0.01ms | 0 KB |
| Implementation | Time | Memory |
|----------------|--------|--------|
| Mutable | 1.2ms | 1.1 MB |
| Immutable | 0.01ms | 0 KB |
**Speedup:** **120x faster**, zero allocations