Commit Graph

211 Commits

Author SHA1 Message Date
Jukka Aho 48a6bcad9f docs(repository_layout): describe legacy as optional 0.x-adjacent API
Replace Pre-2.0 wording with legacy module note aligned with 0.x default surface.
2026-05-09 16:28:42 +03:00
Jukka Aho d4fcbad8f1 docs: Add AGENTS entrypoint and repository layout guide
Introduce root-level AGENTS.md as the architecture and workflow summary for
humans and coding agents. Add docs/src/repository_layout.md as a placement
and anti-pattern reference for sources, tests, scripts, and gitignored trees.

- AGENTS.md links deep docs and states 2.0 invariants
- repository_layout.md includes .cursor/ as gitignored local tooling
2026-05-09 16:21:31 +03:00
Jukka Aho 3bdbde3326 docs: Refresh README and contributing guide for post-reset API
Replace outdated badges and roadmap prose with the current 2.0 focus areas,
installation notes, and pointers to AGENTS.md. Rewrite CONTRIBUTING as a
concise fork/test/layer-contract checklist aligned with the repo layout.

- README: drop stale Travis/Gitter stack; document legacy module caveat
- CONTRIBUTING: remove Quarto front matter; link architecture_layers checker
2026-05-09 16:21:06 +03:00
Jukka Aho b4a2caa31e docs(snippet): Add minimal elasticity quickstart source
Runnable 4×4×4 Hex8 linear elasticity assembly used as the Documenter/README
minimal example source of truth; returns (; ndofs, nnz_stiffness).

- Intended for @literalinclude, test/docs, and scripts/verify_docs_quickstart.jl
2026-05-09 16:04:40 +03:00
Jukka Aho 02b41db2e4 chore(docs): add .gitignore for docs directory
Add .gitignore to ignore Manifest.toml in docs directory

- Ignore Manifest.toml (generated file, should not be committed)
2025-12-12 23:05:47 +02:00
Jukka Aho 2b24cbadba docs(index): update documentation landing page
Modernize index page with comprehensive overview and quick start
guide. Replace simple contents page with informative landing page.

- Add overview section describing JuliaFEM.jl
- Add key features section highlighting capabilities
- Add installation instructions
- Add quick start example code
- Update contributing section with GitHub link
- Add license information
- Remove old contents listing
2025-12-12 23:04:39 +02:00
Jukka Aho 108c881687 docs(api): reorganize API documentation structure
Reorganize API documentation with organized sections for better
navigation and discoverability.

- Add structured sections: Elements, Physics, Fields, Formulations,
  Materials, Mesh, Topology, Basis Functions, DOF System, Solvers
- Include key types and functions in each section
- Change title from "API documentation" to "API Reference"
- Keep index at the end for complete reference
2025-12-12 23:04:14 +02:00
Jukka Aho 7125a617f8 refactor(docs): simplify make.jl to modern Documenter.jl build
Simplify documentation build script to generate API docs only.
Remove legacy code for generating examples, packages, and guides.

- Replace complex build system with simple Documenter.jl setup
- Generate markdown output for Quarto integration
- Build directly to juliafem.github.io/api/ directory
- Remove functions: copy_docs, add_page!, generate_* functions
- Use DocumenterMarkdown format instead of HTML
2025-12-12 23:03:50 +02:00
Jukka Aho c7b0283822 chore(docs): add JuliaFEM dependency to Project.toml
Add JuliaFEM package as dependency for documentation build

- Add JuliaFEM to [deps] section
- Add relative path source for JuliaFEM in [sources]
2025-12-12 23:03:21 +02:00
Jukka Aho 038222ce98 chore: remove docs files moved to website repository
Remove documentation files from docs/ directory as they have
been moved to juliafem.github.io/ according to the website
structure. Manual documentation now lives in the website
repository directly.

Removed files:
- docs/book/adr-004-integration-points-api.md
- docs/book/adr-005-element-integration-point-indices.md
- docs/book/deformation_gradient_implementation.md
- docs/book/design/backend_transparent_architecture.md
- docs/book/design/gmres_algorithm_gpu.md
- docs/book/design/matrix_free_dirichlet_bc.md
- docs/book/element_assembly_implementation.md
- docs/book/linear_elastic_implementation.md
- docs/book/migration-guide-basis-api.md
- docs/book/neo_hookean_implementation.md
- docs/book/perfect_plasticity_implementation.md
2025-12-12 22:59:15 +02:00
Jukka Aho f0353699b0 chore: removed files from docs
Removed files from docs directory:

- docs/badges.jl
- docs/book/nodal_assembly_concept.md
- docs/build_api.jl
- docs/build_doctests.jl
- docs/build_lint.jl
- docs/build_notebooks.jl
- docs/build_unittests.jl
- docs/src/contributor/coding_standards.md
- docs/src/contributor/guides/gpu_elasticity_quickstart.md
- docs/src/contributor/guides/gpu_nodal_assembly_quickstart.md
- docs/src/contributor/guides/quick_reference_gpu.md
- docs/src/contributor/README.md
- docs/src/contributor/status.md
- docs/src/contributor/test_fixes_needed.md
- docs/src/contributor/testing_philosophy.md
- docs/src/examples.md
- docs/src/features.md
- docs/src/links.md
- docs/src/user/elasticity_quickstart.md
- docs/src/user/README.md
- docs/src/user/system_architecture.md
2025-12-12 22:01:57 +02:00
Jukka Aho cee336a476 chore: remove docs/src/book directory
Remove docs/src/book directory as it has been moved to another
repository

- Remove docs/src/book/ directory and all contents
- 40 files removed including documentation and design docs
2025-12-12 21:44:34 +02:00
Jukka Aho 64056da96a docs(adr): Revise ADR-002 - topology includes node count parameter
Major revision of ADR-002 based on implementation experience.

Decision change:
- OLD (Nov 9): Topology without node count (pure geometry)
- NEW (Nov 13): Topology with node count type parameter

Rationale:
Node count comes from MESH FILES, not from basis choice. When reading
Abaqus .inp, Code Aster .med, or GMSH .msh files, the mesh explicitly
specifies node count in element connectivity:
  - Hex element (1,2,...,8) → 8 nodes
  - Hex element (1,2,...,20) → 20 nodes
  - Hex element (1,2,...,27) → 27 nodes

The mesh reader knows node count BEFORE basis functions are selected.
Therefore, topology must include node count: Hexahedron{N}.

New design:
  struct Hexahedron{N} <: AbstractTopology end
  const Hex8 = Hexahedron{8}
  const Hex20 = Hexahedron{20}

This maintains type stability (N known at compile time) while
acknowledging that N originates from mesh data, not basis choice.

Supersedes: ADR-002 (November 9, 2025)
2025-11-15 02:21:47 +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 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 3d5a3d8c1a docs: Remove old blog/ and design/ directories
- Delete docs/blog/ directory (files moved to docs/src/book/blog/)
- Delete docs/design/ directory (files moved to docs/src/book/design/)
- Cleanup after three-tier documentation reorganization
- Old locations no longer needed after migration to docs/src/ structure
2025-11-10 22:22:29 +02:00
Jukka Aho 8c1be1b5a8 docs: Move user manual to docs/src/user/
- Relocate docs/user/ to docs/src/user/
- Contains user-facing documentation:
  - README.md (user manual index)
  - system_architecture.md (system overview)
- Part of three-tier docs reorganization following Documenter.jl standard
- Completes migration to docs/src/ structure
2025-11-10 22:22:00 +02:00
Jukka Aho fb732efd1b docs: Move contributor manual to docs/src/contributor/
- Relocate docs/contributor/ to docs/src/contributor/
- Add three GPU quickstart guides (renamed from UPPERCASE to snake_case):
  - gpu_elasticity_quickstart.md
  - gpu_nodal_assembly_quickstart.md
  - quick_reference_gpu.md
- Part of three-tier docs reorganization following Documenter.jl standard
- All files now under docs/src/ for automatic rendering
2025-11-10 22:21:43 +02:00
Jukka Aho edc4d5f63e docs: Move immutability blog post to docs/src/book/blog/
- Relocate docs/blog/immutability_performance.md to docs/src/book/blog/
- Comprehensive guide on immutable material models with Tensors.jl
- Covers LinearElastic, NeoHookean, PerfectPlasticity implementations
- Includes full benchmarks: 5× speedup for linear, 21× for plasticity
- Zero allocation performance validated
- Part of three-tier docs reorganization under standard docs/src/ structure
2025-11-10 22:21:15 +02:00
Jukka Aho 5bfd30e9a9 docs: Move book README to docs/src/book/ following Documenter.jl standard
- Relocate docs/book/README.md to docs/src/book/README.md
- Follows standard Julia documentation structure where all source files live under docs/src/
- File contains YAML header and book philosophy/structure overview
- Part of three-tier documentation reorganization (user/contributor/book)
2025-11-10 22:20:40 +02:00
Jukka Aho 46b0cd3927 docs(book): Add comprehensive Gmsh to physics tutorial
New file: docs/book/gmsh_tutorial.md (544 lines)

Complete educational resource addressing Issue #183:

Step 1: Mesh Generation with Gmsh
- Why Gmsh (features, academic adoption)
- .geo file syntax and concepts
- Mesh generation commands
- Understanding .msh format

Step 2: Weak Formulation (Theory)
- Strong form → weak form derivation
- Galerkin approximation
- M du/dt + K u = f system

Step 3: FEM Assembly in JuliaFEM
- Loading meshes
- Creating problems and elements
- Boundary conditions (Dirichlet, Neumann)
- Assembly process internals

Step 4: Extracting Matrices (Issue #183 core answer)
- How to get K, M, f after assembly
- Why extract (5 use cases)
- Integration with DifferentialEquations.jl
- Complete working example

Step 5: Method of Lines
- PDE → ODE spatial discretization strategy
- Separation of space/time concerns
- Modularity benefits

Plus: Comparison (built-in vs external), Extensions (nonlinear, 3D,
parallel, GPU), Troubleshooting, References

Demonstrates 'laboratory not fortress' philosophy
2025-11-09 23:24:15 +02:00
Jukka Aho 5f10390a01 docs(design): Add YAML frontmatter to IMMUTABILITY.md
- Converted header metadata to YAML frontmatter format
- Added categories and tags for documentation site compatibility
- Preserved all existing content (only header format changed)
- Status: IMPLEMENTED, Phase: Phase 1B
- Links to benchmark: element_immutability_benchmark.jl
2025-11-09 21:02:49 +02:00
Jukka Aho 7370863806 docs(blog): Add TL;DR version of immutability performance article
New 139-line quick-reference article covering:
- Side-by-side code comparisons (mutable vs immutable)
- 130x speedup summary with key metrics
- Type stability explanation with timing breakdown
- Compiler optimization differences
- Real-world impact table (2.4s → 0.02s)
- Mental model shift (1990s C++ → 2025 modern compilers)
- Quick command to run benchmark
- Links to full article for details
2025-11-09 21:02:21 +02:00
Jukka Aho ad80533334 docs(blog): Add O(n) vs O(1) scaling analysis to immutability article
- Comprehensive section on struct size scaling (1-5000 fields)
- Confirms crossover at 100 fields (800 bytes) for updates
- Shows immutable wins for access/iteration at ALL sizes
- Explains why constants matter more than Big-O
- Typical FEM elements (5-50 fields) well below crossover
- Updated FAQ with scaling questions
- Added references to struct_size_scaling.jl benchmark
- System: Intel Xeon Gold 6326, 32 cores, 503 GB RAM
2025-11-09 21:01:12 +02:00
Jukka Aho 41e09b2c92 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
2025-11-09 18:08:39 +02:00
Jukka Aho 32451ed978 docs(design): Add immutability design doc with comprehensive benchmark
Created comprehensive documentation and benchmark demonstrating why immutable
elements with type-stable fields are 40-130x faster than mutable Dict-based
elements.

benchmarks/element_immutability_benchmark.jl:
- Compares mutable (Dict) vs immutable (NamedTuple) implementations
- Measures field access, updates, assembly loops, large-scale meshes
- Results: 40x faster field access, 130x faster assembly, zero allocations

docs/design/IMMUTABILITY.md:
- Explains counterintuitive API change: element = update(element, ...)
- Benchmarks show 40-130x speedup despite 'copying' elements
- Key insight: Type stability >> mutation, compiler optimizes away copies
- Migration guide: old mutable API → new immutable API
- GPU/HPC rationale: Only bits types work on GPU (no pointers)

Key Results:
- Field access: 1ns vs 45ns (40x faster)
- Assembly: 9ns vs 1124ns per element (130x faster)
- Large mesh: 0.01ms vs 1.2ms for 1000 elements (120x faster)
- Memory: 0 allocations vs 70,000 allocations
- GPU: Compatible (bits types) vs Incompatible (pointers)

This documents a fundamental architectural decision for JuliaFEM 1.0.
2025-11-09 17:51:34 +02:00
Jukka Aho 7f4c2b28ce docs: Nodal assembly with immutable element fields
Design for handling both nodal and element fields in nodal assembly:

Architecture:
- Nodes have geometry (immutable)
- Elements have connectivity + fields (immutable struct)
- Nodal fields: displacement, temperature, contact pressure
- Element fields: integration point data (σ, ε_plastic, α, C)

Update pattern:
- Create new field containers (NamedTuples)
- Create new elements with updated fields
- Shallow copy element vector, replace elements
- All immutable (GPU-compatible, thread-safe)

GPU kernel:
- Loops over nodes (nodal assembly)
- Accesses nodal_fields for global quantities
- Accesses element.fields for integration point data
- Gathers from connected elements (node_to_elements)
- No atomic operations (each node owns DOFs)

Material state update:
- Process elements in parallel (Threads.@threads)
- Extract nodal displacements from solution
- Compute strains at integration points
- Run material model (plasticity, damage, etc.)
- Create new elements with updated state
- Return new problem with updated fields

Newton iteration:
- Residual uses element.fields.C (current tangent)
- GMRES with matrix-free matvec (nodal assembly)
- Material update after each iteration
- All data structures immutable throughout

Benchmarks show creating new containers ~1000× faster than deepcopy
2025-11-09 16:18:06 +02:00
Jukka Aho a8495bdc4a docs: Nodal assembly pattern advantages and validation
Explains why JuliaFEM uses nodal assembly instead of element assembly:

Five major advantages:
1. No atomic operations on GPU (each node writes to own DOFs)
2. Contact mechanics is natural (forces at nodes, not elements)
3. Clean domain decomposition (explicit node ownership for MPI)
4. Better cache locality (sequential node processing)
5. Adaptive refinement easier (local node operations)

Key data structure:
- NodeSet contains nodes + elements + node_to_elements connectivity
- Inverse connectivity enables gathering from connected elements
- Fields accessed via node_set.fields (type-stable)

Algorithm:
- Loop over nodes (not elements)
- Each node gathers contributions from connected elements
- Direct write to owned DOFs (no race conditions)
- Perfect for matrix-free Krylov methods

Validated with demo:
- CPU/GPU results match exactly (0.0 relative error)
- Average 3.24 elements per node (efficient gathering)
- Natural integration with contact mechanics

Compares to traditional element assembly:
- Element: scatter to nodes (atomic ops, cache misses)
- Nodal: gather from elements (no atomics, better cache)
2025-11-09 16:17:17 +02:00
Jukka Aho ded16ee1dc docs: Multi-GPU nodal assembly algorithm design
Complete algorithm for GPU-resident FEM solver with nodal assembly:
- Data partitioning by node ownership (domain decomposition)
- GPU-resident data structures (nodes, elements, connectivity, state)
- Three GPU kernels: residual, matvec, state update
- MPI communication patterns for interface nodes
- Full Newton-GMRES loop on GPU (data stays resident)

Architecture:
- Each GPU owns subset of nodes (exclusive ownership)
- Ghost elements copied for gathering during assembly
- node_to_elements connectivity enables nodal assembly
- No atomic operations (each GPU writes to owned DOFs only)

Key features:
- Data moves to GPU once at start, back once at end
- GMRES iterations entirely on GPU (Arnoldi steps)
- Material state updates on GPU (integration points)
- MPI exchanges only for interface DOFs between iterations
- O(N) memory per GPU (matrix-free)

Handles nonlinearity:
- Element state contains σ, ε_plastic, α, C (tangent)
- Residual kernel uses current stress/tangent
- State update kernel after convergence
- Natural for contact mechanics (nodal forces)

Status: Design document for future GPU implementation
2025-11-09 16:16:43 +02:00
Jukka Aho 552d701c5a docs: Matrix-free Krylov pattern with ElementSet
Explains the correct pattern for matrix-vector products in Krylov methods:
- Fields accessed through element_set (not passed separately)
- GPU kernel computes y=K*x (not K itself)
- O(N) memory (vs O(N²) for stored matrix)
- Type-stable field access (compile-time types)

Key insights:
- GMRES needs matvec operation, not the matrix
- ElementSet contains elements + fields together
- Zero allocations with immutable connectivity/fields
- Natural pattern for contact mechanics (nodal updates)
- Material state separate from field parameters

Compares old vs new approach:
- Old: Dict{String,Any} in element (type-unstable)
- New: NamedTuple in ElementSet (type-stable)
- Old: O(N²) matrix storage
- New: O(N) matrix-free operator

Validated with gpu_elementset_matvec_demo.jl:
- GPU/CPU results match exactly
- Fields accessed naturally through element_set
- Returns y vector (what Krylov methods need)
2025-11-09 16:16:13 +02:00
Jukka Aho 38d5749218 docs: Design document for element field architecture
Analyzes field storage patterns and recommends ElementSet approach:
- Element has NO field type parameter (simpler type)
- ElementSet groups elements + shared fields
- Fields can be NamedTuple, struct, any type-stable container
- Embraces immutability (GPU-compatible, thread-safe)
- Separates mutable state from immutable parameters

Design rationale:
- Benchmarks show NamedTuple gives 9-92× speedup vs Dict
- Immutability enables GPU execution without copying
- Creating new containers ~1000× faster than deepcopy
- Matches physical reality (material properties per set)

Compares three options:
1. Fields as type parameter (type proliferation)
2. ElementSet pattern (RECOMMENDED)
3. Hybrid approach (too complex)

Addresses common concerns:
- Time-dependent fields (use interpolation)
- Material state (separate mutable arrays)
- Custom field types (any type-stable container works)

Status: Ready for implementation
2025-11-09 16:15:52 +02:00
Jukka Aho 81f4f85f3e feat(gpu): Multi-GPU MPI benchmark with nodal assembly
Implements working GPU-accelerated nodal assembly with MPI domain decomposition:
- Matrix-free matvec operation on GPU (y = A*x without assembling A)
- 2-6× speedup vs CPU multi-threading (114-302 Mnodes/s)
- Scales to 343K nodes / 1M DOFs with acceptable communication overhead
- CSR format for GPU-friendly node-to-elements connectivity
- Global-to-local index remapping for partition consistency

Key components:
- benchmarks/multigpu_mpi_benchmark.jl: Full MPI+CUDA implementation (555 lines)
- benchmarks/multigpu_results_2025-11-09.md: Detailed performance analysis
- docs/book/gpu_benchmark_milestone.md: Comprehensive tutorial documentation

Performance results (NVIDIA RTX A2000 12GB, 2 MPI ranks):
- 30³ mesh: 114.84 Mnodes/s, 29% communication overhead
- 50³ mesh: 130.64 Mnodes/s, 61% communication overhead
- 70³ mesh: 301.83 Mnodes/s, 51% communication overhead

Architecture validated: Nodal assembly + matrix-free + GPU = fast and scalable.
Foundation complete for production FEM solver (needs: real stiffness, GMRES, preconditioner).
2025-11-09 15:59:00 +02:00
Jukka Aho 5fb972c355 docs: Remove duplicate title from documentation README
Remove duplicate "JuliaFEM Documentation" header (line 11) and add blank lines
for consistent list formatting in three-manual organization document.

Changes:
- Line 11: Removed duplicate H1 title (already in frontmatter)
- Lines 22, 41, 61, 110: Added blank lines before list items for markdown clarity
- Maintains three-audience structure: Users, Contributors, Researchers
- Preserves content organization and cross-reference section

This is a formatting-only change to improve readability. No content modified.
2025-11-09 11:11:05 +02:00
Jukka Aho be076d968a docs(book): Add concise type-stability rationale for field storage
Create 299-line focused design rationale explaining why type stability is essential
for CPU/GPU/MPI performance, without mandating specific storage patterns.

Executive summary (lines 16-26):
- v0.5.1 Dict{String,Any}: 9-92× performance degradation
- Type-unstable code CANNOT run on GPUs
- Significant MPI communication overhead
- Document does NOT prescribe storage location
- Demonstrates why type stability at access points is essential
- Key: Storage pattern matters less than type inference

Problem analysis (lines 28-67):
- Type instability definition: Runtime dispatch when type unknown at compile time
- Why it matters: 10-100× slower CPU, GPU compilation fails, MPI serialization
- Measured impact table: 9-92× speedup, 0 allocations with type stability
- Critical: Zero allocations required for GPU kernels

Design requirements (lines 69-136):
1. Type stability at access points (compiler must infer types)
   - Fields could be element-local, global arrays, or arguments
   - Access pattern must be type-stable regardless
2. Zero allocations in hot paths (GPU/MPI requirement)
   - Assembly loop must allocate nothing
3. Contiguous memory layout (GPU/MPI optimization)
   - CUDA transfers contiguous arrays directly
4. Immutable where possible (safe parallelism)
   - Thread-safe reads without locks

Demonstrated solutions (lines 138-201) - EXAMPLES, not mandates:
1. NamedTuple container: Simple, type-stable, immutable
2. Struct with typed fields: Explicit, self-documenting
3. Passed as arguments: Maximum type stability, explicit dependencies
- All three achieve type stability
- Choice depends on use case, not performance

GPU and MPI rationale (lines 203-237):
- GPU execution: CUDA requires all code type-stable
- Mock demonstration in benchmarks/gpu_mpi_mock.jl
- MPI communication: Typed arrays use fast memcpy vs slow serialization
- Type stability enables identical code for CPU/GPU

Recommendations (lines 239-256):
- Use type-stable access patterns (REQUIRED)
- Prefer immutable data structures (threading/GPU)
- Pre-allocate caches (zero allocations)
- Use contiguous arrays (GPU/MPI transfer)
- Profile with @btime (verify zero allocations)
- Does NOT mandate: Storage location, container type, dynamic vs static

Validation (lines 258-275):
- benchmarks/field_storage_comparison.jl: 9-92× CPU speedup
- benchmarks/gpu_mpi_mock.jl: GPU/MPI patterns
- benchmarks/VALIDATION_RESULTS.md: Summary table

Conclusion (lines 277-299):
- Type stability is fundamental requirement, not implementation detail
- Enables: High CPU performance, GPU execution, efficient MPI, safe threading
- v1.0 must ensure type stability at access points
- Storage pattern is secondary concern (memory, cache, API)
- Next steps: Review, benchmark, choose pattern, implement, validate CUDA

Key difference from v1: Shorter (299 vs 1114 lines), focused on WHY not HOW,
explicitly states storage pattern is flexible, emphasizes GPU/MPI requirements.

Platform: Julia 1.12.1, November 9, 2025
Series: The JuliaFEM Book, Chapter 5
Status: Design rationale with validated measurements
2025-11-09 11:10:37 +02:00
Jukka Aho 4809fe1633 docs(book): Add comprehensive zero-allocation field storage design
Create 1114-line design document exploring type-stable field storage to eliminate
Dict{String,Any} performance penalty from JuliaFEM v0.5.1.

Executive summary (lines 16-34):
- Measured results: 9-92× speedup over Dict, zero allocations in hot paths
- Constant field: 19.2ns → 2.1ns (9× faster, 0 allocs)
- Nodal field: 262ns, 3 allocs → 6.5ns, 0 allocs (40× faster)
- Cached interpolation: 2.6μs, 50 allocs → 53ns, 0 allocs (49× faster)
- Assembly (1000 elem): 109μs, 4000 allocs → 1.2μs, 0 allocs (92× faster)
- Type stability enables GPU execution and efficient MPI
- Validation: benchmarks/field_storage_comparison.jl

Problem analysis (lines 36-90):
- v0.5.1 Dict{String,Any} causes type instability
- Runtime dispatch overhead: ~50ns per access
- Interpolation: 127 allocations from type conversions
- Root cause: Any type prevents compiler optimization
- Impact: 100× slower than type-stable equivalent

Design constraints (lines 92-158):
1. Type stability - Julia must infer types at compile time
2. Zero allocations in hot paths (assembly loop critical)
3. Immutability for thread-safety by default
4. Preserve interpolation philosophy (nodal → Gauss points)
5. Element sets share properties (not per-element)

Solution 1: NamedTuple + Typed Fields (lines 160-456) - RECOMMENDED
- Field types: ConstantField{T}, NodalField{T}, ElementField{T,N}, TimeField{T,F}
- Zero-size constants, Matrix{T} for nodal, SVector for DG elements
- Accessor functions: value(f::ConstantField), value(f::NodalField, node_ids)
- Benchmarks: 9× (constant), 40× (nodal), 59× (interp), 49× (cached), 92× (assembly)
- Complete implementations with @inline, @view for zero allocation
- InterpolationCache struct for zero-allocation hot path

Solution 2: Macro-Generated Structs (lines 458-611)
- @fields macro for generating typed field containers
- Explicit field definitions with @constant, @nodal, @element, @temporal
- Generated constructors, accessors, validation
- Pros: Self-documenting, optimal code, extensible
- Cons: More complex, maintenance burden
- Decision: Start with NamedTuple, add macro if needed

Solution 3: Element Set Architecture (lines 613-774)
- ElementSet{E,F} groups elements sharing common properties
- Fields belong to sets, not individual elements
- Matches mesh organization and user mental model
- Zero-allocation assembly with shared fields
- Benchmark: 10× faster than per-element Dict, near-zero allocations

Implementation strategy (lines 776-940):
- Phase 1: Prototype and benchmark (week 1)
  * BenchmarkTools suite with performance assertions
  * Target: <5ns field access, <100ns interpolation, 0 allocs assembly
- Phase 2: Integration (weeks 2-3)
  * Update Element struct (remove fields, belongs to ElementSet)
  * Update Problem struct (vector of ElementSets)
  * Update assembly functions
- Phase 3: Migration and deprecation (week 4)
  * Deprecation warnings for old API
  * Update all examples to typed fields
  * Performance verification
- Phase 4: Documentation (week 5)
  * Architecture docs, tutorials, migration guide

Validation checklist (lines 942-974):
- Field type prototypes, access benchmarks (<5ns, 0 allocs)
- Interpolation benchmarks (<100ns, 0 allocs)
- Assembly benchmarks (0 allocs in loop)
- Threading tests, DG tests, vs v0.5.1 comparison (10× faster)
- Update Element/Problem structs, implement ElementSet
- Examples, CI benchmarks, documentation

Decision record (lines 976-1004):
- Decision: Use NamedTuple of typed field structs for v1.0
- Rationale: 10-50× speedup, type stability, simple (~200 LOC), immutable
- Breaking change: element.fields[name] deprecated
- Migration: Use ElementSet with NamedTuple fields
- Performance requirements: <5ns access, <100ns interp, 0 allocs assembly
- Status: Proposal ready for implementation

Complete benchmark suite (lines 1006-1114):
- Full executable benchmark code with 5 tests
- OLD (Dict) vs NEW (Typed) comparisons
- Mock element and basis functions
- Interpolation with/without cache
- Assembly loop (1000 elements)
- Summary showing 9-92× speedup validation
- Reproduction instructions

Platform: Julia 1.12.1, November 9, 2025
Series: The JuliaFEM Book, Chapter 5
Status: Proposal (validated by benchmarks)
2025-11-09 11:09:19 +02:00
Jukka Aho 9a55257ba7 docs(blog): Add Literate.jl blog post on Krylov+nodal assembly philosophy
Create 415-line blog post combining technical demonstration with philosophical
vision for JuliaFEM v1.0 nodal assembly architecture.

Content structure:
- Lines 1-32: Why Krylov+nodal is brilliant for contact mechanics
  * Contact is inherently nodal (constraints at nodes, not elements)
  * Krylov only needs matvec (never forms global matrix)
  * Nodal assembly provides natural row-by-row interface
  * O(N) memory vs O(N²) for traditional element assembly

- Lines 34-73: Controversial hypothesis about nodal material modeling
  * Claims material state should be at nodes, not integration points
  * Argues integration points constrain physics to numerical method
  * Variational consistency, physical meaning, scalability arguments
  * "I will show them they're wrong" - experimental vision

- Lines 75-95: GMRES advantage for unsymmetric systems
  * Material nonlinearity, contact, large deformation all unsymmetric
  * GMRES solves positive definite unsymmetric systems
  * O(N·iter) time, O(N) memory vs O(N³)/O(N²) for direct solvers

- Lines 97-415: Working GMRES demonstration on 10×10 unsymmetric system
  * Problem setup: Positive definite but unsymmetric matrix (lines 105-145)
  * Nodal assembly pattern: get_row() interface (lines 147-193)
  * Simplified GMRES implementation (lines 195-282)
  * Execution and verification (lines 284-318)
  * Results: Converged in 10 iterations, 6.28×10⁻¹⁶ relative error
  * Key insights section explaining significance (lines 320-365)
  * Development roadmap: Immediate → Near-term → Long-term → Vision (lines 367-401)
  * Conclusion: Philosophical statement about nodal correctness (lines 403-415)

Technical validation:
- Matrix: 10×10, eigenvalues [9.94, 38.06], condition number 3.83
- Nodal matvec: 1.59×10⁻¹⁴ error vs direct computation
- GMRES: 10 iterations to convergence
- Solution accuracy: 1.23×10⁻¹⁴ absolute error, 6.28×10⁻¹⁶ relative

Dependencies: LinearAlgebra, Random, Printf

Format: Literate.jl (# # for section headers, # for narrative)
Target: Blog post for JuliaFEM v1.0 development documentation
Tone: Opinionated, controversial, technically rigorous
2025-11-09 11:06:43 +02:00
Jukka Aho f2b306f68e docs(book): Add nodal assembly and multi-GPU strategy document
New 588-line comprehensive strategic document explaining winning architecture:

Executive Summary (lines 1-19):
- Key results demonstrated on real hardware
- 9-92× CPU speedup, GPU kernel compilation, MPI working, Krylov convergence
- Multi-GPU workflow validated end-to-end

Problem: Traditional FEM doesn't scale (lines 21-59):
- v0.5.1 limitations: global matrix O(N²) memory, direct solver O(N³) time
- Scalability ceiling ~100K DOF
- Cannot scale: memory N², time N³

Solution: Nodal + Matrix-Free + Multi-GPU (lines 61-193):
- Architecture diagram with MPI ranks and local GPUs
- Three pillars: nodal assembly (row-by-row), matrix-free (matvec only), multi-GPU with MPI
- Each pillar explained with code examples and advantages

Why type stability required (lines 195-241):
- GPU kernel compilation: concrete types required, abstract fails
- MPI fast path: typed buffers vs slow serialization
- Krylov solvers: matrix-free operators need concrete types
- Demonstrated with code examples

Performance characteristics (lines 243-289):
- Complexity analysis: O(N²)→O(N) memory, O(N³)→O(N·k) time
- Scalability comparison table: 10K→10M DOF
- Demonstrated results: 10×10 system, 9 iterations, 7.73×10⁻¹⁴ error

Contact mechanics killer app (lines 291-340):
- Why nodal assembly natural for contact (contact is nodal not element-based)
- Contact workflow: detect→assemble→solve→update
- Element-based assembly is mismatch for contact

Implementation strategy v1.0 (lines 342-407):
- Phase 1: Foundation (complete) - type-stable design, GPU/MPI demos, Krylov validation
- Phase 2: Core implementation - nodal assembly API, matrix-free operator, GPU accel, MPI distribution
- Phase 3: Contact integration - detection, contribution to rows, iterative solve

Comparison with other strategies (lines 409-455):
- Global matrix assembly: dead end for scalability
- Element-based matrix-free: works but suboptimal for contact
- Nodal + matrix-free + multi-GPU (ours): best for large-scale contact

Validation and evidence (lines 457-533):
- Three demonstrations: gpu_mpi_demo, krylov_mpi_gpu_demo, field_storage_comparison
- Real-world applicability: LAMMPS, GROMACS use similar patterns
- Why traditional FEM codes don't do this: legacy constraints

Conclusion (lines 535-588):
- Five validated achievements proving path forward
- Not speculation: working code on real hardware
- Path is clear: type stability foundation, nodal assembly pattern, Krylov+MPI solver
- Related documentation links

Purpose: Strategic justification for v1.0 architecture with real evidence
2025-11-09 10:52:38 +02:00
Jukka Aho 0cfe966063 docs(book): Add ADR-002 for topology without hardcoded node counts
Architecture Decision Record documenting topology/basis separation (292 lines):

- Explains decision to remove node counts from topology types
- Documents topology = pure geometry, basis determines node count
- Shows old Code Aster anti-pattern (TRIA3, TRIA6, QUAD4, QUAD8)
- Describes new design: Triangle + Lagrange{Triangle, P}
- Rationale: mathematical correctness, separation of concerns
- Enables edge/face DOFs (Nédélec, Raviart-Thomas)
- Eliminates combinatorial explosion (8 topologies vs hundreds)
- Consequences: extensible, correct, but breaking change
- Implementation strategy and migration plan
- Includes proper YAML front matter for book chapter
2025-11-09 09:33:41 +02:00
Jukka Aho d8fc224c42 docs(book): Add ADR-002 for topology without hardcoded node counts
New Architecture Decision Record for the comprehensive book (292 lines):

- Documents decision to remove node counts from topology types
- Explains topology = pure geometry, basis determines node count
- Shows old Code Aster anti-pattern (TRIA3, TRIA6, QUAD4, QUAD8)
- Describes new design: Triangle + Lagrange{Triangle, P}
- Rationale: mathematical correctness, separation of concerns
- Enables edge/face DOFs (Nédélec, Raviart-Thomas)
- Eliminates combinatorial explosion (8 topologies vs hundreds)
- Consequences: extensible, correct, but breaking change
- Implementation strategy and migration plan
- Backwards compatibility via aliases and shims
2025-11-09 09:31:45 +02:00
Jukka Aho 5e210187d8 docs(architecture): Complete rewrite explaining topology vs basis separation
Major documentation update (380 additions, 167 deletions):

- Explained topology is pure geometry (NO hardcoded node counts)
- Clarified basis determines BOTH polynomial degree AND node count
- Distinguished node count (connectivity) vs DOF count (unknowns)
- Added examples: Nedelec (edge DOFs), Raviart-Thomas (face DOFs)
- Documented Lagrange{Topology, P} parametric architecture
- Showed why Tri3/Quad4/Tet10 names are anti-pattern
- Updated all code examples to use new architecture
- Explained Serendipity vs full Lagrange tensor products
- Added performance implications and trade-offs
- Showed how one Triangle topology works for P1/P2/P3/Nedelec/etc
2025-11-09 09:29:58 +02:00