Files
JuliaFEM.jl/Project.toml
T
Jukka Aho 6a8f8adc1f docs: Benchmark manual vs AD derivatives for Tet10
RESEARCH QUESTION: Should JuliaFEM use hand-calculated derivatives or AD?

Created comprehensive benchmark comparing:
- Manual: Hand-calculated derivatives (traditional FEM)
- AD: Tensors.jl gradient() (automatic differentiation)

RESULTS (AMD Ryzen 9, Julia 1.12.1):
- Manual: 8.7 ns, 0 allocations
- AD:     268.1 ns, 0 allocations
- AD is 30× SLOWER than manual

KEY FINDINGS:
 Both achieve zero allocations (Tensors.jl is well-optimized)
 AD has 30× compute overhead from dual number arithmetic
⚠️  In assembly loops: millions of calls = 10+ seconds extra per solve

RECOMMENDATION:
- Keep manual derivatives for common elements (Tet10, Hex8, Quad4, etc.)
- Use AD for prototyping and rare elements
- Unit test manual vs AD to catch errors
- Future: Generate derivatives symbolically (Symbolics.jl)

WHY NOT AD EVERYWHERE?
Assembly is hottest path in FEM. 30× overhead = unacceptable for
production code. Users will notice the performance difference.

WHY NOT ABANDON AD?
- Excellent for prototyping
- Required for exotic bases (NURBS)
- Perfect for unit testing manual derivatives
- Zero allocations impressive

Files:
- benchmarks/tet10_derivatives_benchmark.jl (runnable benchmark)
- docs/benchmarks/shape_function_derivatives_ad_vs_manual.md (analysis)

Dependencies added: BenchmarkTools

This answers the research question definitively with data.
2025-11-09 03:41:47 +02:00

36 lines
1.2 KiB
TOML

name = "JuliaFEM"
uuid = "f80590ac-b429-510a-8a99-e7c46989f22d"
version = "0.5.2"
author = ["Jukka Aho <ahojukka5@gmail.com>", "Tero Frondelius <tero.frondelius@gmail.com>", "Olli Väinölä"]
[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
Gmsh = "705231aa-382f-11e9-3f0c-b7cb4346fdeb"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Tensors = "48a634ad-e948-5137-8d70-aa71f2a747f4"
[compat]
BenchmarkTools = "1.6.3"
Gmsh = "0.3.1"
Tensors = "≥ 1.0.0"
julia = "1.9"
[extras]
Calculus = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Gmsh = "705231aa-382f-11e9-3f0c-b7cb4346fdeb"
HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"
LightXML = "9c8b4983-aa76-5018-a973-4c85ecc9e179"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
[targets]
test = ["Test", "Statistics", "Gmsh"]