Commit Graph

1256 Commits

Author SHA1 Message Date
Jukka Aho ecfbba65f7 deps: Add CUDA extension support to Project.toml
- [weakdeps] CUDA package for optional GPU support
- [extensions] JuliaFEMCUDAExt loaded when 'using CUDA'
- Zero overhead when CUDA not loaded
- Enables GPU acceleration without mandatory dependency
2025-11-12 01:08:58 +02:00
Jukka Aho 9bbd9879a8 docs(user): Add linear elasticity quickstart tutorial
- Complete cantilever beam example from mesh to visualization
- Gmsh mesh creation with physical groups for BCs
- Material definition (Young's modulus and Poisson's ratio)
- Dirichlet (fixed) and Neumann (pressure) boundary conditions
- ElasticityPhysics problem setup and solve!() call
- Results visualization with stress and displacement
- 361 lines: Step-by-step user tutorial for beginners
2025-11-12 01:08:41 +02:00
Jukka Aho 753ddcc9e5 docs(design): Add GPU physics architecture documentation
- 4 design documents for GPU implementation (2588 lines total)
- gpu_physics_architecture.md: Physics{Elasticity} GPU-first design
- gpu_cpu_backend_architecture.md: Backend selection and dispatch
- gpu_cpu_migration_guide.md: Migration from old API to new
- gpu_elasticity_refactoring.md: Complete refactoring strategy
- Zero CPU-GPU transfer during solve, matrix-free CG
- Elements store geometry, no mesh dependency
- Breaking changes allowed for GPU performance
2025-11-12 01:08:22 +02:00
Jukka Aho 3208904b73 docs(design): Add backend-transparent architecture proposal
- Design principle: users never see CPU/GPU differences
- Three-layer architecture: User API / Backend Abstraction / Implementations
- Auto() backend selection based on hardware availability
- Physics{ElasticityPhysicsType} as single problem type
- Internal conversion between CPU arrays and GPU arrays
- solve!() with automatic dispatch to CPU or GPU backend
- 611 lines: Complete architecture design proposal
2025-11-12 01:07:53 +02:00
Jukka Aho 6a94155a32 docs(book): Add basis function API migration guide
- get_basis_functions() and get_basis_derivatives() recommended
- Separation of concerns: topology and basis as separate parameters
- Side-by-side examples for all common element types
- Complete assembly example showing migration path
- Type-stable implementation with no performance penalty
- 302 lines: Comprehensive migration documentation
2025-11-12 01:07:24 +02:00
Jukka Aho d07220aa76 docs(book): Add nodal assembly concept and architecture
- Alternative to element-by-element assembly for GPU/matrix-free
- Node-by-node loop eliminates atomic operations on GPU
- Spider pattern: nodes couple with 10-30 neighbors not all N
- NodeToElementsMap: inverse connectivity (node → elements)
- get_node_spider() finds coupled nodes for sparse stiffness
- NodalStiffnessContribution: 3×3 blocks per node
- 307 lines: Experimental architecture with working prototype
2025-11-12 01:07:07 +02:00
Jukka Aho 64b148a9bb docs(book): Add J2 perfect plasticity implementation guide
- von Mises yield criterion with kinematic hardening
- Radial return mapping algorithm for plastic correction
- Additive strain decomposition (elastic + plastic)
- Associative flow rule and consistent tangent
- Performance: 76 ns elastic, 108 ns plastic (4.8× faster than AD)
- Zero-allocation elastic path, minimal plastic allocation
- 668 lines: Complete plasticity implementation documentation
2025-11-12 01:06:49 +02:00
Jukka Aho d610754a06 docs(book): Add NeoHookean hyperelastic implementation guide
- Compressible Neo-Hookean strain energy function
- Automatic differentiation for stress and tangent computation
- Dual constructor: Lamé (μ,λ) or engineering (E,ν)
- Total Lagrangian formulation with 2nd Piola-Kirchhoff stress
- Zero-allocation AD via Tensors.jl
- When to use: rubber, large deformation, contact mechanics
- 571 lines: Complete AD-based material model documentation
2025-11-12 01:05:49 +02:00
Jukka Aho 1e8254909c docs(book): Add LinearElastic material implementation guide
- Complete mathematical foundation of Hooke's law in tensor form
- Lamé parameters derived from Young's modulus and Poisson's ratio
- compute_stress() implementation achieving ~25 ns execution
- Fourth-order elasticity tensor with symmetries
- Zero-allocation SIMD-optimized implementation
- Physical constraints and thermodynamic admissibility
- 736 lines: Authoritative implementation documentation
2025-11-12 01:05:33 +02:00
Jukka Aho dc667b37f7 docs(book): Add traditional element assembly implementation guide
- Reference implementation of element-by-element assembly
- ElementAssemblyData and ElementContribution data structures
- Sparse matrix assembly in COO then CSC format
- scatter_to_global!() adds local to global system
- Penalty method for Dirichlet BCs
- Matrix-vector product interface for GMRES
- 479 lines: Complete documentation with examples and tests
2025-11-12 01:05:16 +02:00
Jukka Aho 8e11ab96ee docs(book): Add deformation gradient implementation analysis
- Mathematical derivation of F = I + ∇u for finite strain
- Zero-allocation implementation achieving 34 ns median
- LLVM IR analysis confirms 0 heap allocations
- 92 SIMD vector operations detected
- Small strain vs finite strain formulations
- Comparison with old deprecated eval_dbasis!() API
- 502 lines: Complete performance analysis with benchmarks
2025-11-12 01:04:52 +02:00
Jukka Aho e64ab2df55 feat(gpu): Add CUDA extension with nodal assembly kernels
- JuliaFEMCUDAExt package extension (loaded with 'using CUDA')
- ElasticityDataGPU: All data on device (nodes, elements, BCs, node-to-elem map)
- initialize_gpu_data!() transfers Physics to GPU with renumbering
- nodal_assembly_kernel!() computes stiffness 3×3 blocks per node
- compute_element_stresses_kernel!() element-level stress computation
- apply_surface_traction_kernel!() Neumann BC on surfaces
- apply_dirichlet_kernel!() penalty method for essential BCs
- cg_solve_matfree_gpu!() matrix-free CG solver
- solve_newton_krylov_gpu!() inexact Newton with GMRES-style restart
- initialize_backend(::GPU) and solve_backend!() dispatch methods
- 934 lines: Pure GPU implementation with zero CPU-GPU transfers during solve
2025-11-12 01:04:31 +02:00
Jukka Aho 741da90819 feat(io): Add Gmsh mesh reader for tetrahedral meshes
- GmshMesh struct: nodes, elements, physical_groups storage
- read_gmsh_mesh() parses ASCII format 4.1 (.msh files)
- Extracts Tet4 elements (type 4) and node coordinates
- Reads physical groups for boundary conditions
- get_surface_nodes() placeholder for BC node extraction
- 175 lines: Simple mesh I/O for demos and benchmarks
2025-11-12 01:02:02 +02:00
Jukka Aho 2693bdf545 feat(assembly): Add nodal assembly data structures
- NodeToElementsMap: Inverse connectivity (node → elements touching it)
- ElementNodeInfo: Tracks element ID and local node index
- get_node_spider() finds all nodes coupling with given node
- NodalStiffnessContribution: Storage for 3×3 blocks per node
- matrix_vector_product_nodal() computes K_i*u at single node
- print_spider_info() debugging diagnostics
- 234 lines: Infrastructure for node-by-node assembly
2025-11-12 01:01:45 +02:00
Jukka Aho b4673290af feat(assembly): Add traditional element assembly data structures
- ElementAssemblyData: Global sparse matrix and force vectors
- ElementContribution: Local element contributions before scatter
- scatter_to_global!() adds element matrices to global system
- compute_residual!() calculates r = f_int - f_ext
- apply_dirichlet_bc!() penalty method for essential BCs
- get_dof_indices() node connectivity to global DOF mapping
- matrix_vector_product() sparse K*v multiplication
- 341 lines: Traditional element-by-element assembly infrastructure
2025-11-12 01:01:26 +02:00
Jukka Aho c0a0cc679b feat(backend): Add CPU backend with element assembly and CG solver
- ElasticityDataCPU struct wraps ElementAssemblyData
- initialize_backend() assembles global system from immutable Elements
- compute_element_stiffness() uses Tensors.jl (blocked by get_basis_derivatives)
- cg_solve() implements Conjugate Gradient iterative solver
- Supports Dirichlet boundary conditions from Physics API
- 228 lines: Traditional element assembly approach for CPU
2025-11-12 01:01:08 +02:00
Jukka Aho 40de86d4e4 feat(backend): Add abstract backend system with Auto/GPU/CPU selection
New file src/backend/abstract.jl defining backend abstraction:
- AbstractBackend base type for computation backend
- Auto() automatic backend selection (GPU if available, else CPU)
- GPU() force GPU backend (errors if CUDA unavailable)
- CPU(nthreads) force CPU backend with thread count
- select_backend() chooses concrete backend based on hardware
- AbstractElasticityData for backend-specific data structures
- ElasticitySolution struct for solve results
- solve!() dispatch point with backend parameter
- 241 lines with comprehensive API documentation
2025-11-12 00:59:40 +02:00
Jukka Aho 733c72b688 feat(materials): Add FiniteStrainPlasticity with multiplicative decomposition
New file src/materials/finite_strain_plasticity.jl implementing J2 plasticity for large deformations:
- FiniteStrainPlasticityState storing F_p (plastic deformation gradient), α_bar (backstress), κ
- FiniteStrainPlasticity struct with E, ν, σ_y, H parameters
- Hyperelastic stress response using Neo-Hookean
- Exponential map integration for plastic flow
- Pull-back/push-forward operations for intermediate configuration
- Consistent algorithmic tangent for Newton convergence
- 293 lines with comprehensive finite deformation theory
2025-11-12 00:59:18 +02:00
Jukka Aho 0e1f9778e7 feat(materials): Add PerfectPlasticity with radial return mapping
New file src/materials/perfect_plasticity.jl implementing J2 plasticity:
- PlasticityState struct storing plastic strain ε_p, backstress α, and κ
- PerfectPlasticity struct with E, ν, yield stress σ_y, hardening H
- Von Mises yield function: f = √(3/2)||dev(σ-α)|| - σ_y
- Radial return mapping algorithm for plastic updates
- Elastic predictor / plastic corrector scheme
- Kinematic hardening with backstress evolution
- Consistent tangent modulus for Newton convergence
- 357 lines with comprehensive theory and algorithm documentation
2025-11-12 00:58:57 +02:00
Jukka Aho 1a0066dea0 feat(materials): Add NeoHookean hyperelastic material with automatic differentiation
New file src/materials/neo_hookean.jl implementing simplest hyperelasticity:
- NeoHookean struct with shear modulus μ and Lamé parameter λ
- Convenience constructor from E and ν engineering constants
- strain_energy() computes ψ = μ/2·(I₁-3) - μ·ln(J) + λ/2·ln²(J)
- Stress S = 2·∂ψ/∂C via automatic differentiation
- Tangent 𝔻 = 4·∂²ψ/∂C² via automatic differentiation
- Uses Tensors.jl built-in AD (no ForwardDiff dependency)
- Total Lagrangian formulation with 2nd PK stress
- 253 lines with comprehensive theory documentation
2025-11-12 00:58:39 +02:00
Jukka Aho 8f198752ac feat(materials): Add LinearElastic material model with Tensors.jl
New file src/materials/linear_elastic.jl implementing Hooke's law:
- LinearElastic struct with Young's modulus E and Poisson's ratio ν
- Input validation: E > 0, -1 < ν < 0.5
- Helper functions: λ() and μ() compute Lamé parameters
- compute_stress() implements σ = λ·tr(ε)·I + 2μ·ε
- Tangent modulus: 𝔻 = λ·I⊗I + 2μ·��ˢʸᵐ
- Zero-allocation with SymmetricTensor types
- Simplified interface without state management
- 180 lines with comprehensive documentation
2025-11-12 00:58:23 +02:00
Jukka Aho ac071b5d57 feat(materials): Add AbstractMaterial type hierarchy and interface
New file src/materials/abstract_material.jl defining material model architecture:
- AbstractMaterial base type for all materials
- AbstractElasticMaterial for stateless materials (no history)
- AbstractPlasticMaterial for stateful materials (plastic strain, etc.)
- compute_stress() interface: (material, ε, state_old, Δt) → (σ, 𝔻, state_new)
- State management convention for Newton iterations
- Thread-safe and GPU-compatible design principles
- 229 lines with comprehensive documentation and examples
2025-11-12 00:58:06 +02:00
Jukka Aho 184919131e feat(physics): Add backend-agnostic physics API with BC types
New file src/physics_api.jl defining user-facing elasticity API:
- ElasticityPhysicsType (alias Elasticity) for problem configuration
- DirichletBC struct for prescribed displacements
- NeumannBC struct for surface tractions/pressures
- Physics{P} container for problem with elements and BCs
- Works with both CPU and GPU backends
- 183 lines with comprehensive examples
2025-11-12 00:57:33 +02:00
Jukka Aho 84a1bfec4e feat(physics): Add ElasticityPhysics type with geometric/material nonlinearity
New file src/physics/elasticity.jl:
- ElasticityPhysics struct implementing AbstractPhysics interface
- Formulations: plane_stress, plane_strain, continuum (3D)
- finite_strain flag for Green-Lagrange strain (geometric nonlinearity)
- geometric_stiffness flag for buckling analysis
- Field storage control: store_fields (converged), store_iteration_fields (debug)
- Interface methods: get_unknown_field_name, get_formulation_type, get_unknown_field_dimension
- should_store_field() for selective field storage
- 205 lines with comprehensive documentation and GPU design notes
2025-11-12 00:56:58 +02:00
Jukka Aho 628b902bf5 feat(physics): Add deformation gradient computation with strain formulations
New file src/physics/deformation_gradient.jl:
- compute_deformation_gradient() computes F = I + ∇u at integration points
- StrainFormulation types: FiniteStrain() and SmallStrain()
- Uses Tensors.jl for all tensor operations (Vec, Tensor)
- Zero-allocation design with @inline functions
- GPU-ready immutable operations
- Comprehensive mathematical documentation with references
- 243 lines including commented high-level API for future integration
2025-11-12 00:56:40 +02:00
Jukka Aho 258017922e feat(physics): Add assembly helper functions with Tensors.jl
New file src/physics/assembly_helpers.jl with FEM assembly utilities:
- shape_function_gradients() computes ∇N in current configuration
- compute_strain_from_gradients() small strain ε = sym(∇u)
- compute_green_lagrange_strain() finite strain E = ½(C-I)
- accumulate_stiffness!() adds element stiffness contributions
- accumulate_internal_forces!() computes f_int = ∫σ·∇N dV
- accumulate_external_forces!() computes f_ext = ∫N·b dV
- Zero-allocation design with Tensors.jl Vec and SymmetricTensor
- 331 lines with comprehensive performance documentation
2025-11-12 00:56:19 +02:00
Jukka Aho 4440f86691 feat(physics): Add AbstractPhysics base type and interface
New file src/physics/abstract.jl defining physics system architecture:
- AbstractPhysics base type for all physics implementations
- get_unknown_field_name() returns primary field (displacement, temperature, etc.)
- get_formulation_type() returns :incremental, :total, or :rate
- get_unknown_field_dimension() returns DOFs per node
- assemble!() dispatch point for physics-specific assembly
- Comprehensive docstrings covering multi-physics coupling and GPU compatibility
- 138 lines documenting design philosophy and future extension
2025-11-12 00:56:05 +02:00
Jukka Aho bb68e9de84 feat(geometry): Add Jacobian computation with Tensors.jl
New file src/geometry/jacobian.jl implementing geometric transformations:
- compute_jacobian(X, dN_dξ) computes J = ∂x/∂ξ using tensor products
- physical_derivatives(J, dN_dξ) transforms derivatives to physical space
- Full Tensors.jl integration with Vec and Tensor types
- Zero-allocation tuple-based API for performance
- AbstractVector overloads for compatibility
- Comprehensive docstrings with 2D/3D examples
- 169 lines with mathematical definitions and usage patterns
2025-11-12 00:55:10 +02:00
Jukka Aho 57ca301b86 fix(integration): Fix type inference in integration_points conversion
Modified src/integration/gauss.jl to fix IntegrationPoint creation:
- Changed from generator expression to ntuple for proper type inference
- Collect quad_data first (was zip iterator, cannot be indexed)
- Remove explicit type parameter {D} - let Julia infer from arguments
- Fixes type stability issue in integration point generation
- Maintains zero-allocation design with tuple return
2025-11-12 00:54:35 +02:00
Jukka Aho 1e59eb1bbc feat(integration): Add get_gauss_points! function with Tensors.jl Vec types
New file implementing Gauss quadrature point generation:
- get_gauss_points!(topology, scheme) returns tuple of (weight, Vec{D}) pairs
- Supports all 7 topologies: Segment, Triangle, Quadrilateral, Tetrahedron, Hexahedron, Wedge, Pyramid
- Orders 1-3 for each topology (exact integration up to quintic/cubic)
- Uses Tensors.jl Vec types for coordinates (GPU-friendly, zero-allocation)
- Fully inlined (@inline) for compile-time optimization
- 300 lines of quadrature rules from standard FEM references
2025-11-12 00:53:33 +02:00
Jukka Aho 07f1c690d2 refactor(topology): Update AbstractTopology documentation for separation of concerns
Modified src/topology/topology.jl to reflect new architecture:
- Clarify topology defines geometric shape only, not node count
- Document that node count comes from basis functions
- Add examples showing same topology with different bases (Quad4/8/9)
- Update docstring to reference new topology types (Segment, Triangle, etc.)
- Emphasize corner nodes only in topology API
- Remove references to old node-count-baked types (Tri3, Quad4, etc.)
2025-11-12 00:53:02 +02:00
Jukka Aho a4d5b235ca feat(topology): Add Wedge 3D topology with Wedge6/Wedge15 aliases
New file implementing 3D wedge/prism topology:
- Wedge struct with dim=3, 6 corner nodes (triangular prism)
- reference_coordinates() with bottom triangle at z=-1, top at z=1
- edges() returns 9 edges (3 bottom + 3 top + 3 vertical)
- faces() returns 5 faces (2 triangular ends + 3 quadrilateral sides)
- Backward compatibility aliases: Wedge6 (linear), Wedge15 (quadratic)
- Zero-allocation tuple-based design
2025-11-12 00:52:38 +02:00
Jukka Aho f7d778d960 feat(topology): Add Pyramid 3D topology with Pyr5 alias
New file implementing 3D pyramidal topology:
- Pyramid struct with dim=3, 5 corner nodes (square base + apex)
- reference_coordinates() with base at z=0 and apex at (0,0,1)
- edges() returns 8 edges (4 base + 4 to apex)
- faces() returns 5 faces (1 quadrilateral base + 4 triangular sides)
- Backward compatibility alias: Pyr5 (linear)
- Zero-allocation tuple-based design
2025-11-12 00:52:26 +02:00
Jukka Aho 0231b2e33a feat(topology): Add Hexahedron 3D topology with Hex8/Hex20/Hex27 aliases
New file implementing 3D hexahedral topology:
- Hexahedron struct with dim=3, 8 corner nodes (3D tensor product)
- reference_coordinates() in [-1,1]³ cube
- edges() returns 12 edges, faces() returns 6 quadrilateral faces
- Backward compatibility aliases: Hex8, Hex20 (Serendipity), Hex27 (Lagrange)
- Supports trilinear, serendipity (no interior), and full tensor product bases
- Zero-allocation tuple-based design
2025-11-12 00:52:13 +02:00
Jukka Aho 02e40946ef feat(topology): Add Tetrahedron 3D topology with Tet4/Tet10 aliases
New file implementing 3D tetrahedral topology:
- Tetrahedron struct with dim=3, 4 corner nodes (3D simplex)
- reference_coordinates() at (0,0,0), (1,0,0), (0,1,0), (0,0,1)
- edges() returns 6 edges, faces() returns 4 triangular faces
- Backward compatibility aliases: Tet4 (linear), Tet10 (quadratic)
- Zero-allocation tuple-based design
2025-11-12 00:52:00 +02:00
Jukka Aho 6a5a87daef feat(topology): Add Quadrilateral 2D topology with Quad4/Quad8/Quad9 aliases
New file implementing 2D quadrilateral topology:
- Quadrilateral struct with dim=2, 4 corner nodes at (-1,-1), (1,-1), (1,1), (-1,1)
- edges() returns 4 edges, faces() returns element itself
- Backward compatibility aliases: Quad4, Quad8 (Serendipity), Quad9 (Lagrange)
- Supports bilinear, serendipity (no center), and full tensor product bases
- Zero-allocation tuple-based design
2025-11-12 00:51:47 +02:00
Jukka Aho 1ab8f3f30c feat(topology): Add Triangle 2D topology with Tri3/Tri6/Tri7 aliases
New file implementing 2D triangular topology:
- Triangle struct with dim=2, 3 corner nodes
- reference_coordinates() at (0,0), (1,0), (0,1)
- edges() returns 3 edges, faces() returns element itself
- Backward compatibility aliases: Tri3, Tri6, Tri7 (same topology, different basis)
- Zero-allocation tuple-based design
- Separation: topology is geometric shape, basis determines node count
2025-11-12 00:51:25 +02:00
Jukka Aho f547f547e8 feat(topology): Add Segment 1D topology with Seg2/Seg3 aliases
New file implementing 1D line segment topology:
- Segment struct with dim=1, 2 corner nodes
- reference_coordinates() returns (-1.0,) and (1.0,)
- edges() and faces() for topology connectivity
- Backward compatibility aliases: Seg2, Seg3 (same topology, different basis)
- Zero-allocation design using tuples
- Separation of concerns: topology defines shape, basis determines node count
2025-11-12 00:50:58 +02:00
Jukka Aho e2917cdba8 docs: Add ADR-005 on integration point indices architecture
Document decision to store integration point indices instead of data in Element struct.
Key rationale: Elements should store relationships (indices), not data, for memory
efficiency and consistency with node connectivity pattern. Aligns with nodal assembly
approach and GPU-friendly architecture.
2025-11-12 00:49:17 +02:00
Jukka Aho ba0afce933 docs: Add ADR-004 for zero-allocation integration points API
Architectural Decision Record documenting design of integration points
API for high-performance finite element assembly.

Decision: Compile-time function returning tuple of (weight, Vec{D})
matching eval_basis! zero-cost abstraction pattern.

Problem context:
- OLD API: Runtime dispatch with mutable struct containing Dict
- Performance penalty: ~50× slower due to type instability
- Allocations: New struct created every query
- Impact: Millions of calls during assembly

Solution properties:
- Compile-time generation (fully inlined)
- Vec{D} from Tensors.jl for FEM math
- Zero allocation (tuples, stack-only)
- Type-stable (all types known at compile time)
- GPU compatible (no heap allocations)

API signature:
get_gauss_points!(::Type{Topology}, ::Type{Gauss{order}})
  → NTuple{N, Tuple{Float64, Vec{D}}}

Alternatives rejected:
- Plain tuples (less convenient for FEM math)
- Store in element (overhead, less flexible)
- Global constants (not composable)
- Runtime dispatch (type-unstable, slow)

Status: Accepted, implemented in src/integration/ (193 lines)
2025-11-12 00:44:29 +02:00
Jukka Aho 25af535745 demo: Add Tet10 CPU test and validation
CPU implementation test for 10-node tetrahedral elements validating
shape functions, derivatives, and assembly against analytical solutions.

Validation tests:
1. Shape function partition of unity (Σ N_i = 1)
2. Shape function derivatives correctness
3. Jacobian computation accuracy
4. Element stiffness matrix symmetry
5. Assembly convergence with mesh refinement
6. Comparison against Tet4 (linear elements)

Tet10 specifics tested:
- 10 shape functions (quadratic)
- 4-point Gauss quadrature
- Curved element geometry
- Mid-edge node positioning

Test problems:
- Patch test (constant strain)
- Pure bending (quadratic strain)
- Manufactured solution (known displacement field)

Expected results:
- Tet10 converges faster than Tet4 (fewer elements needed)
- Tet10 captures bending better (quadratic)
- Tet10 passes patch test exactly

Purpose: Establish correctness before GPU port
Reference for gpu_assembly_tet10.jl validation
2025-11-12 00:29:36 +02:00
Jukka Aho 69e3b131b5 demo: Add nodal assembly GPU implementation
GPU port of nodal assembly strategy with CUDA kernels demonstrating
atomic-free assembly on GPU using node-parallel approach.

GPU kernel design:
- One thread per node (not per element)
- Each thread gathers from touching elements
- No atomic operations (node ownership)
- Coalesced memory access via node ordering

Kernel structure:
- Thread ID maps to node ID
- Loop over elements touching this node
- Loop over element nodes for block contributions
- Compute 3×3 stiffness blocks with Tensors.jl
- Accumulate locally, write once to global

Data layout:
- node_to_elements: CSR-like structure on GPU
- Element data: Array of Structs (immutable elements)
- Node displacement: Flat vector (3*n_nodes)
- Result: Flat vector (3*n_nodes)

Performance characteristics:
- Memory bandwidth bound (not compute bound)
- Benefits from coalescing (sequential node access)
- Scalable to multi-GPU (domain decomposition)
- No synchronization within kernel

Comparison to element assembly:
- Element: N_elem threads, atomic scatter
- Nodal: N_nodes threads, no atomics

Reference: CPU version in nodal_assembly_cpu.jl
2025-11-12 00:29:21 +02:00
Jukka Aho 4040a802e5 demo: Add nodal assembly CPU implementation
CPU implementation of nodal assembly strategy (loop over nodes, not
elements) demonstrating modern assembly approach for FEM.

Nodal assembly concept:
- Traditional: Loop over elements, scatter to nodes (atomics needed on GPU)
- Modern: Loop over nodes, gather from elements (no atomics, better GPU)

Algorithm:

Advantages:
- No atomic operations (each node owned by one thread)
- Natural 3×3 block structure (displacement DOFs)
- Contact-ready (contact is naturally nodal)
- GPU-friendly (coalesced memory access)

Implementation:
- Node-to-elements connectivity graph
- Block-based operations with Tensors.jl
- Zero-allocation assembly loop
- Matrix-free operator for iterative solvers

Reference: docs/src/book/multigpu_nodal_assembly.md
2025-11-12 00:29:03 +02:00
Jukka Aho 0bc41c7cf1 demo: Add Newton-Krylov-Anderson CPU reference implementation
Complete CPU reference implementation of Newton-Krylov solver with
Anderson acceleration for nonlinear elasticity with plasticity.

Solver components:
- Newton outer loop (nonlinear iterations)
- GMRES inner loop (linear solve, matrix-free)
- Anderson acceleration (convergence improvement)
- Adaptive GMRES tolerance (Eisenstat-Walker formula)

Matrix-free strategy:
- No tangent matrix assembly
- Jacobian-vector product via finite differences: J·v ≈ [r(u+ε·v)-r(u)]/ε
- Residual assembly: r(u) = f_int(u) - f_ext
- Each GMRES iteration = 2 residual evaluations

Plasticity handling:
- Radial return mapping at each Gauss point
- Material state tracking (ε_p, α) during iterations
- State update only on Newton convergence
- Von Mises yield criterion with perfect plasticity

Reference for GPU implementation:
- Validates numerical correctness
- Establishes performance baseline
- Documents algorithm flow for GPU port
- Shows data dependencies and kernel opportunities

Problem: 3D elasticity with J2 plasticity, Tet4 mesh
2025-11-12 00:28:45 +02:00
Jukka Aho 3daed70615 demo: Add GPU assembly for Tet10 higher-order elements
GPU implementation for 10-node tetrahedral elements demonstrating
higher-order finite elements with quadratic shape functions.

Tet10 specifics:
- 10 nodes per element (vertices + edge midpoints)
- 4-point Gauss quadrature (order 2)
- Quadratic shape functions (N_i second-order polynomials)
- Shape function derivatives via analytical formulas

Challenges vs Tet4:
- More integration points (4 vs 1)
- More DOFs per element (30 vs 12)
- More complex shape functions
- Larger local stiffness (10×10 vs 4×4 blocks)

GPU kernel modifications:
- Loop over 4 Gauss points instead of 1
- Evaluate quadratic shape functions at each IP
- Accumulate contributions from all IPs
- Scatter 30 DOFs per element (not 12)

Benefits of Tet10:
- Better stress/strain representation
- Fewer elements needed for accuracy
- Curved boundary representation
- Higher convergence rate

Same problem setup: 3D cantilever with steel properties
Test validates GPU higher-order element implementation (430 lines).
2025-11-12 00:28:24 +02:00
Jukka Aho 036331d82e demo: Add Tensors.jl-corrected GPU assembly POC
Corrected GPU assembly using proper Tensors.jl material modeling
instead of plain vectors with manual indexing.

Architectural improvements:
- SymmetricTensor{2,2} for 2D strain and stress
- Material API: compute_stress(material, ε)
- LinearElastic struct with Lamé parameters
- Hooke's law: σ = λ·tr(ε)·I + 2μ·ε (matches theory)
- Clean tensor operations (no manual indexing)

Versus original POC (gpu_assembly_poc.jl):
- OLD: ε = SA[εxx, εyy, γxy] (plain vector)
- NEW: ε = SymmetricTensor{2,2}((εxx, γxy/2, εyy))
- OLD: σ = C * ε (matrix multiply)
- NEW: σ = compute_stress(material, ε) (material API)
- OLD: Manual stress component indexing
- NEW: Tensor operations (Bᵀ·σ via dot product)

Benefits:
- Follows material_modeling.md architecture
- GPU compatible (Tensors.jl works on CUDA)
- Maintainable (material models pluggable)
- Mathematics matches equations

Same test case: 10×10 Quad4, steel, 242 DOFs (468 lines).
2025-11-12 00:28:07 +02:00
Jukka Aho 34027e887f demo: Add initial GPU assembly proof-of-concept
First working GPU assembly implementation (proof-of-concept stage)
demonstrating complete FEM solve staying on GPU for 2D elasticity.

Implementation:
- Element-parallel GPU kernel for Quad4 elements
- 2×2 Gauss quadrature on GPU
- Plain vector approach (before Tensors.jl integration)
- Matrix-free Jacobian-vector product
- Complete Newton-Krylov loop on GPU
- BC enforcement via masking

Test case: 10×10 Quad4 mesh (100 elements, 242 DOFs)
- Material: Steel (E=200 GPa, ν=0.3)
- BC: Fixed left edge, displacement on right edge

Architecture validation:
- GPU assembly matches CPU (error < 1e-15)
- Entire solve stays on GPU (no ping-pong)
- Only transfers: mesh (once) + u0/u_final (boundary)

Note: This is the initial version using plain vectors and manual
indexing. See gpu_assembly_poc_tensors.jl for corrected version
using proper Tensors.jl material API (606 lines).
2025-11-12 00:27:51 +02:00
Jukka Aho 6fd50689b6 demo: Add cantilever physics-based GPU assembly
GPU assembly using physics-aware abstractions (elasticity helper functions)
instead of raw kernel implementation, demonstrating higher-level API.

Architecture difference from cantilever_gmsh_gpu.jl:
- Raw GPU: Direct CUDA kernels with manual indexing
- Physics GPU: Helper functions (compute_strain, compute_stress, etc.)

Physics abstractions:
- compute_jacobian: J = Σ dN ⊗ X (automatic differentiation possible)
- compute_strain: ε = sym(Σ dN ⊗ u) using Tensors.jl
- compute_stress: σ = material(ε) with material API
- compute_residual: r = Σ Bᵀ·σ·w (internal forces)

Benefits:
- More readable (physics equations explicit)
- More maintainable (abstractions hide complexity)
- More extensible (swap materials easily)
- Still GPU-compatible (Tensors.jl works on CUDA)

Trade-offs:
- Slightly higher abstraction overhead
- Depends on Tensors.jl GPU support
- May need careful inlining for performance

Same problem: 10m × 1m × 1m cantilever, Tet4, steel properties
2025-11-12 00:27:26 +02:00
Jukka Aho 0856714ce1 demo: Add cantilever beam GPU assembly with Gmsh
Complete GPU-accelerated FEM solve for 3D cantilever beam using
nodal assembly strategy and matrix-free Newton-Krylov solver.

GPU implementation:
- Gmsh mesh generation (same as CPU version)
- Data transfer to GPU (nodes, connectivity, BC)
- GPU kernels for nodal assembly (element contributions)
- Matrix-free Jacobian-vector product on GPU
- GMRES solver on GPU (Krylov.jl with CuArrays)
- CPU fallback for Anderson acceleration

Problem characteristics:
- Geometry: 10m × 1m × 1m cantilever beam
- Elements: Tet4 from Gmsh
- Material: Steel (E=210 GPa, ν=0.3)
- BC: Fixed left end, tip force on right end

Architecture:
- Single GPU transfer: mesh + BC → GPU at start
- Entire Newton-Krylov loop stays on GPU
- Single result transfer: u_final ← GPU at end
- No ping-pong between CPU and GPU during solve

Demonstrates complete GPU FEM pipeline from meshing to solution
with realistic geometry and material properties.
2025-11-12 00:27:02 +02:00
Jukka Aho cf364576f1 demo: Add cantilever CPU assembly comparison
Compares traditional element assembly vs nodal assembly on CPU for
cantilever beam example, validating assembly equivalence and measuring
performance characteristics.

Comparison:
- Element assembly: Traditional FEM (loop over elements, atomic scatter)
- Nodal assembly: Modern approach (loop over nodes, block operations)

Validation:
- Residual equivalence (element vs nodal assembly)
- Stiffness operator equivalence (matvec comparison)
- Assembly time comparison
- Memory allocation tracking

Problem: Same cantilever beam as cantilever_beam_simple.jl
- Tet4 mesh from Gmsh
- Steel properties
- Fixed left, force on right

Demonstrates CPU assembly strategies before GPU implementation,
establishing baseline for GPU performance comparison.
2025-11-12 00:26:32 +02:00