mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-09-20 01:59:59 +00:00
docs: Reorganize documentation into three-tier structure
**Three Manuals for Three Audiences:** 1. **User Manual** (docs/user/) - "Just Get It Done" - For end users, engineers, students - Simple, practical, step-by-step - Quick start, tutorials, examples, troubleshooting - Philosophy: Show me how to solve my problem 2. **Contributor Manual** (docs/contributor/) - "Show Me the Code" - For developers, contributors, advanced users - Technical, detailed, design rationale - Testing, architecture, performance, CI/CD - Philosophy: Explain HOW and WHY 3. **The JuliaFEM Book** (docs/book/) - "Let Me Show You How I Think" - For researchers, theory nerds, and Jukka - Comprehensive, educational, opinionated, personal - Math foundations, design philosophy, history, research - Philosophy: Mix theory, code, and personal experience **Reorganization:** - Moved: TESTING_PHILOSOPHY.md → contributor/testing_philosophy.md - Moved: STATUS.md → contributor/status.md - Moved: TEST_FIXES_NEEDED.md → contributor/test_fixes_needed.md - Moved: lagrange_basis_functions.md → book/lagrange_basis_functions.md - Moved: benchmarks/ → book/benchmarks/ - Created: docs/README.md (main index explaining structure) - Created: README.md in each section explaining audience and contents - Updated: All references in scripts and source files **Naming:** All docs now lowercase (testing_philosophy not TESTING_PHILOSOPHY) **Benefits:** - Clear separation of concerns - Users don't get overwhelmed with implementation details - Contributors get technical depth - Book preserves deep theory and personal insights - Each manual optimized for its audience **Next:** Populate each section with appropriate content
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
# JuliaFEM Contributor Manual
|
||||
|
||||
**Audience:** Developers, contributors, advanced users who want to extend or modify JuliaFEM.
|
||||
|
||||
This manual is **technical and detailed** - it explains HOW the code works and WHY we made certain design choices.
|
||||
|
||||
## What's Here
|
||||
|
||||
- **Testing Philosophy:** How and why we test
|
||||
- **Code Style:** Conventions and best practices
|
||||
- **Architecture:** Module structure, data flow, key abstractions
|
||||
- **Performance:** Zero-allocation design, profiling, benchmarking
|
||||
- **Adding Elements:** How to implement new element types
|
||||
- **CI/CD:** Continuous integration, releases, versioning
|
||||
- **Git Workflow:** Branching, commits, pull requests
|
||||
|
||||
## What's NOT Here
|
||||
|
||||
- User tutorials (see `docs/user/` for that)
|
||||
- Deep mathematical theory (see `docs/book/` for that)
|
||||
- "How do I solve problem X?" (that's user docs)
|
||||
|
||||
## Philosophy
|
||||
|
||||
**"Show me the code AND tell me why."**
|
||||
|
||||
We assume you:
|
||||
- Know Julia reasonably well
|
||||
- Understand FEM basics
|
||||
- Want to add features or fix bugs
|
||||
- Care about performance and correctness
|
||||
- Need to understand design rationale
|
||||
|
||||
## Before Contributing
|
||||
|
||||
1. Read [Testing Philosophy](testing_philosophy.md)
|
||||
2. Understand [Architecture](architecture.md)
|
||||
3. Follow [Code Style](code_style.md)
|
||||
4. Check [Performance Guidelines](performance.md)
|
||||
5. Review [Git Workflow](git_workflow.md)
|
||||
|
||||
## Key Principles
|
||||
|
||||
- **Type stability:** No `Any`, no `Dict` without types
|
||||
- **Zero allocations:** Hot paths should allocate nothing
|
||||
- **Immutability:** Prefer `struct` over `mutable struct`
|
||||
- **Composition:** Use tuples and free functions, not OOP hierarchies
|
||||
- **Explicit:** No magic, user knows what happens
|
||||
- **Test first:** Write tests before fixing bugs
|
||||
|
||||
---
|
||||
|
||||
**Start here:** [Testing Philosophy](testing_philosophy.md) | [Architecture Overview](architecture.md)
|
||||
@@ -0,0 +1,95 @@
|
||||
# JuliaFEM Revival Status - November 8, 2025
|
||||
|
||||
## ✅ SUCCESS: Package Loads!
|
||||
|
||||
JuliaFEM now loads successfully on Julia 1.12.1:
|
||||
```bash
|
||||
julia> using JuliaFEM
|
||||
✓ JuliaFEM loads successfully
|
||||
Exported names: 171
|
||||
```
|
||||
|
||||
## Fixed Issues
|
||||
|
||||
### 1. Element Type Signature Errors (CRITICAL)
|
||||
**Problem:** Element type changed from `Element{Basis}` to `Element{M, Basis} where M`
|
||||
**Fixed in:**
|
||||
- `vendor/FEMBase.jl/src/FEMBase.jl` - Added AbstractBasis import
|
||||
- `vendor/FEMBase.jl/src/elements_lagrange.jl` - Fixed Poi1 subtyping
|
||||
- `vendor/FEMBeam.jl/src/beam3d.jl` - 3 function signatures
|
||||
- `vendor/MortarContact2D.jl/src/mortar2d.jl` - 2 functions
|
||||
- `vendor/MortarContact2D.jl/src/contact2d.jl` - 3 functions
|
||||
- `vendor/MortarContact2DAD.jl/src/mortar2dad.jl` - 1 function
|
||||
- `vendor/MortarContact2DAD.jl/src/contact2dad.jl` - 1 function
|
||||
- `src/problems_mortar_3d.jl` - 2 functions (M renamed to FS to avoid conflict)
|
||||
- `src/problems_contact_3d.jl` - 3 functions (M renamed to FS)
|
||||
- `src/io.jl` - 15 dispatch functions
|
||||
|
||||
### 2. Merge Conflicts (Issue #250 from 2019)
|
||||
**Fixed in:**
|
||||
- `test/runtests.jl` - Removed conflict markers
|
||||
- `src/problems_elasticity.jl` - Resolved and simplified
|
||||
|
||||
### 3. Missing Package Dependencies
|
||||
**Fixed:**
|
||||
- Created `vendor/MortarContact2DAD.jl/Project.toml`
|
||||
- Updated `Manifest.toml` to use local vendor packages
|
||||
|
||||
### 4. Parallel Assembly Code
|
||||
**Fixed:**
|
||||
- Removed references to non-existent `problem.assemble_parallel` field
|
||||
- Simplified to use non-threaded assembly (threading can be added back later)
|
||||
|
||||
## Test Status
|
||||
|
||||
**Test Suite:** 5 passed, 51 errored (but package loads!)
|
||||
|
||||
The errors are due to deeper API incompatibilities with Julia 1.12:
|
||||
- Method signature mismatches (e.g., `jacobian` function)
|
||||
- Some tests expect features from incomplete multithreading branch
|
||||
- API evolution over 6+ years (Julia 0.6 → 1.12)
|
||||
|
||||
## What Works
|
||||
|
||||
✅ Package installation and loading
|
||||
✅ All vendor packages compile
|
||||
✅ No type signature errors
|
||||
✅ Core data structures intact
|
||||
✅ 171 symbols exported
|
||||
✅ Basic FEM infrastructure present
|
||||
|
||||
## Next Steps for Full Revival
|
||||
|
||||
1. **Fix jacobian/geometry method mismatches** - Update vendor/FEMBasis for Julia 1.12
|
||||
2. **Fix remaining test errors** - Systematic fixes for API changes
|
||||
3. **Add threading infrastructure** - Properly implement parallel assembly
|
||||
4. **Update documentation** - Reflect Julia 1.12 compatibility
|
||||
5. **Benchmark performance** - Establish baseline vs old version
|
||||
|
||||
## Key Learnings
|
||||
|
||||
- Multi-package ecosystems are maintenance nightmares (see llm/TECHNICAL_VISION.md)
|
||||
- Type stability critical: Dict-based fields caused 100× slowdown
|
||||
- Git history cleanup successful: 99MB → 9.8MB (90% reduction)
|
||||
- Vendor packages approach works for development
|
||||
|
||||
## Files Modified
|
||||
|
||||
**Critical fixes (this session):**
|
||||
- 10 source files with Element type fixes
|
||||
- 2 merge conflict resolutions
|
||||
- 2 dependency files (Project.toml, Manifest.toml)
|
||||
- 1 assembly simplification
|
||||
|
||||
**Scripts created:**
|
||||
- `test.sh` - Test runner
|
||||
- `fix_src_element_types.py` - Automated type fixing
|
||||
|
||||
## Conclusion
|
||||
|
||||
**Mission accomplished:** JuliaFEM loads on modern Julia!
|
||||
|
||||
While tests have errors, the **fundamental blocker (type signatures) is resolved**.
|
||||
The package is now in a state where systematic fixing of remaining issues can proceed.
|
||||
|
||||
The 51 test errors are fixable - they're API evolution issues, not architectural problems.
|
||||
@@ -0,0 +1,106 @@
|
||||
# Test Fixes Needed
|
||||
|
||||
**Date:** November 8, 2025
|
||||
**Status:** 5 passing, 49 failing (infrastructure now in place)
|
||||
|
||||
## Summary
|
||||
|
||||
Tests are failing due to API evolution between Julia 0.6/1.0 (2018) and Julia 1.12 (2025), not fundamental architectural problems. Package loads successfully and core functionality works.
|
||||
|
||||
## Main Issues
|
||||
|
||||
### 1. Missing `aster_read_mesh` (14 tests)
|
||||
**Problem:** Tests use `aster_read_mesh()` from IO submodule, but it requires HDF5
|
||||
**Files affected:** Most 3D elasticity tests, med file tests
|
||||
**Fix options:**
|
||||
- A) Add HDF5 as optional dependency (Julia 1.9+ package extensions)
|
||||
- B) Skip tests that need .med files for now
|
||||
- C) Convert test meshes to .inp format (ABAQUS, which we support)
|
||||
|
||||
**Recommendation:** Option C - convert test meshes to .inp format
|
||||
|
||||
### 2. `eval_basis!` Signature Mismatch (2 tests)
|
||||
**Problem:** `eval_basis!(::Type{Seg2}, ::Matrix, ::Tuple{Float64})`
|
||||
**Current:** `eval_basis!(::Seg2, ::Vector, ::Tuple{Float64}, time::Float64)`
|
||||
**Location:** `vendor/FEMBasis.jl`
|
||||
|
||||
**Fix:** Update signature in FEMBasis or fix call sites
|
||||
|
||||
### 3. `jacobian` Signature Mismatch (~20 tests)
|
||||
**Problem:** Tests call `jacobian(element_type, X, xi)` with old signatures
|
||||
**Current API:** Different parameter order or types
|
||||
**Location:** `vendor/FEMBasis.jl/src/jacobian.jl`
|
||||
|
||||
**Fix:** Consolidate FEMBasis into src/basis/ with modern API
|
||||
|
||||
### 4. `allocate_buffer` Missing (2 tests)
|
||||
**Problem:** `allocate_buffer(::Problem{Elasticity}, ::Vector{Element})`
|
||||
**Status:** Method doesn't exist in current codebase
|
||||
**Fix:** Either restore method or update tests to not need it
|
||||
|
||||
### 5. `Analysis` Missing (5 tests) - ✅ FIXED
|
||||
**Status:** Now exported, these tests should pass
|
||||
|
||||
### 6. Statistics Package Missing (1 test) - ✅ FIXED
|
||||
**Status:** Now in test dependencies
|
||||
|
||||
## Test Categories
|
||||
|
||||
### ✅ Passing (5 tests)
|
||||
- Virtual work test
|
||||
- Contact 2D/3D tests
|
||||
- Mortar 2D tests
|
||||
- Heat transfer (basic)
|
||||
|
||||
### ❌ Failing - Missing HDF5 (~14 tests)
|
||||
- test_elasticity_2d_nonlinear_with_surface_load.jl
|
||||
- test_elasticity_3d_unit_block.jl
|
||||
- test_elasticity_med_pyr5_point_load.jl
|
||||
- test_elasticity_plane_strain.jl
|
||||
- test_elasticity_pyr5_point_load.jl
|
||||
- Many more...
|
||||
|
||||
### ❌ Failing - API Mismatches (~30 tests)
|
||||
- eval_basis! signature (2)
|
||||
- jacobian signature (~20)
|
||||
- allocate_buffer missing (2)
|
||||
- Various others (6)
|
||||
|
||||
## Action Plan
|
||||
|
||||
### Phase 1: Low-Hanging Fruit (1-2 hours)
|
||||
1. ✅ Export Analysis types
|
||||
2. ✅ Add Statistics to test deps
|
||||
3. ⏳ Skip/comment out HDF5-dependent tests temporarily
|
||||
4. ⏳ Re-run tests, see how many pass
|
||||
|
||||
### Phase 2: API Fixes (4-6 hours)
|
||||
1. Fix `eval_basis!` signature in FEMBasis
|
||||
2. Fix `jacobian` signature in FEMBasis
|
||||
3. Either restore `allocate_buffer` or update tests
|
||||
4. Fix any remaining signature mismatches
|
||||
|
||||
### Phase 3: Mesh Conversion (2-4 hours)
|
||||
1. Find all .med test meshes
|
||||
2. Convert to .inp format using Code Aster or similar
|
||||
3. Update test files to use .inp instead of .med
|
||||
4. Re-run tests
|
||||
|
||||
### Phase 4: Verify All Pass (1 hour)
|
||||
1. Run full test suite
|
||||
2. Fix any remaining issues
|
||||
3. Update CI to run tests automatically
|
||||
4. Celebrate! 🎉
|
||||
|
||||
## Expected Outcome
|
||||
|
||||
After these fixes:
|
||||
- ~40+ tests should pass (out of 56 total)
|
||||
- CI will catch regressions automatically
|
||||
- Good foundation for further consolidation work
|
||||
|
||||
## Notes
|
||||
|
||||
The fact that package loads and 5 tests pass is actually very good news - it means the core architecture is sound. These are just API compatibility issues that accumulated over 6 years of Julia evolution.
|
||||
|
||||
Most fixes are mechanical (update signatures) rather than requiring deep understanding of the algorithms.
|
||||
@@ -0,0 +1,789 @@
|
||||
# JuliaFEM Testing Philosophy
|
||||
|
||||
**Date:** November 9, 2025
|
||||
**Goal:** 99% code coverage with educational, fast, well-structured tests
|
||||
**Tool:** Literate.jl for test-as-documentation
|
||||
|
||||
---
|
||||
|
||||
## Core Principles
|
||||
|
||||
### 1. Tests as Teaching Material
|
||||
|
||||
**Every test should teach something.**
|
||||
|
||||
Tests are not just validation - they're the **primary way users learn JuliaFEM**. When someone asks "How do I solve an elasticity problem?", the answer should be: "Look at `test/tutorials/elasticity_basics.jl`"
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- Users learn by example (better than API docs)
|
||||
- Tests stay current (if API changes, tests must update)
|
||||
- Documentation never lies (it's tested code!)
|
||||
- Newcomers can contribute tests (learning exercise)
|
||||
|
||||
### 2. Literate.jl for Test-Driven Documentation
|
||||
|
||||
Use Literate.jl to write tests as narrative documents:
|
||||
|
||||
```julia
|
||||
# # Solving Your First Elasticity Problem
|
||||
#
|
||||
# This tutorial shows how to solve a simple 2D elasticity problem.
|
||||
# We'll create a square block, apply boundary conditions, and solve.
|
||||
|
||||
using JuliaFEM
|
||||
using Test
|
||||
|
||||
# ## Step 1: Create the Geometry
|
||||
#
|
||||
# First, define the nodes of a unit square:
|
||||
|
||||
X = Dict(
|
||||
1 => [0.0, 0.0],
|
||||
2 => [1.0, 0.0],
|
||||
3 => [1.0, 1.0],
|
||||
4 => [0.0, 1.0]
|
||||
)
|
||||
|
||||
# ## Step 2: Create Elements
|
||||
#
|
||||
# Create a single Quad4 element:
|
||||
|
||||
element = Element(Quad4, (1, 2, 3, 4))
|
||||
update!(element, "geometry", X)
|
||||
|
||||
# ... and so on
|
||||
```
|
||||
|
||||
**Output:** Same file generates both test (runs in CI) and documentation (builds HTML).
|
||||
|
||||
### 3. Structured Test Hierarchy
|
||||
|
||||
Organize tests to match learning progression:
|
||||
|
||||
```text
|
||||
test/
|
||||
├── tutorials/ # Literate.jl files (test + docs)
|
||||
│ ├── 01_fundamentals/
|
||||
│ │ ├── creating_elements.jl
|
||||
│ │ ├── fields_and_updates.jl
|
||||
│ │ ├── reading_meshes.jl
|
||||
│ │ └── basis_functions.jl
|
||||
│ ├── 02_linear_problems/
|
||||
│ │ ├── elasticity_1d.jl
|
||||
│ │ ├── elasticity_2d.jl
|
||||
│ │ ├── heat_transfer.jl
|
||||
│ │ └── boundary_conditions.jl
|
||||
│ ├── 03_nonlinear_problems/
|
||||
│ │ ├── large_deformation.jl
|
||||
│ │ ├── plasticity.jl
|
||||
│ │ └── contact_basics.jl
|
||||
│ ├── 04_advanced/
|
||||
│ │ ├── contact_2d.jl
|
||||
│ │ ├── contact_3d.jl
|
||||
│ │ ├── mortar_methods.jl
|
||||
│ │ └── friction.jl
|
||||
│ └── 05_parallel/
|
||||
│ ├── threading.jl
|
||||
│ ├── gpu_assembly.jl
|
||||
│ └── distributed.jl
|
||||
├── unit/ # Fast unit tests (not Literate)
|
||||
│ ├── basis/
|
||||
│ ├── assembly/
|
||||
│ └── solvers/
|
||||
├── verification/ # Known analytical solutions
|
||||
│ ├── timoshenko_beam.jl
|
||||
│ ├── hertz_contact.jl
|
||||
│ └── cook_membrane.jl
|
||||
└── runtests.jl # Test runner
|
||||
```
|
||||
|
||||
### 4. Fast Tests First
|
||||
|
||||
**Test pyramid:**
|
||||
|
||||
```text
|
||||
/\
|
||||
/ \ Integration tests (slow, few)
|
||||
/____\
|
||||
/ \ Tutorial tests (medium, some)
|
||||
/________\
|
||||
/ \ Unit tests (fast, many)
|
||||
/__________\
|
||||
```
|
||||
|
||||
**Timing targets:**
|
||||
|
||||
- Unit tests: < 5 minutes (run during development)
|
||||
- Tutorial tests: < 15 minutes (run before commits)
|
||||
- Full suite: < 30 minutes (run in CI)
|
||||
|
||||
**Strategy:**
|
||||
|
||||
- Use realistic meshes in tutorials (~10 elements: not too trivial, not too slow)
|
||||
- Test correctness with analytical solutions, not big problems
|
||||
- Profile and optimize slow tests
|
||||
- Mark slow tests with `@testset "slow: hertz_contact"` (skip during dev)
|
||||
- Co-locate mesh files with tests (no shared `/test/meshes/` directory)
|
||||
- Include mesh generation recipes (show how mesh was created for reproducibility)
|
||||
|
||||
### 5. Coverage-Driven Development
|
||||
|
||||
**Target: 99% code coverage**
|
||||
|
||||
Every function should have:
|
||||
|
||||
1. **Happy path test** - normal usage
|
||||
2. **Edge case tests** - empty input, single element, etc.
|
||||
3. **Error tests** - what happens with bad input?
|
||||
|
||||
**Process:**
|
||||
|
||||
1. Write tutorial (covers main API)
|
||||
2. Check coverage report
|
||||
3. Add unit tests for uncovered lines
|
||||
4. Repeat until 99%+
|
||||
|
||||
**Tools:**
|
||||
|
||||
- Coverage.jl (built into Julia)
|
||||
- LocalCoverage.jl (for local checks)
|
||||
- Codecov (in CI, we set this up yesterday)
|
||||
|
||||
---
|
||||
|
||||
## Test Structure Details
|
||||
|
||||
### Tutorial Tests (Literate.jl)
|
||||
|
||||
**Template:**
|
||||
|
||||
```julia
|
||||
# # Tutorial Title
|
||||
#
|
||||
# Brief description of what this tutorial teaches.
|
||||
# Prerequisites: what the reader should know first.
|
||||
|
||||
using JuliaFEM
|
||||
using Test
|
||||
|
||||
# ## Section 1: Concept Explanation
|
||||
#
|
||||
# Explain the concept in prose, with equations if needed:
|
||||
#
|
||||
# The strain-displacement relationship is:
|
||||
# ```math
|
||||
# ε = \frac{1}{2}(∇u + ∇u^T)
|
||||
# ```
|
||||
|
||||
# Code demonstrating the concept
|
||||
element = Element(Quad4, (1,2,3,4))
|
||||
|
||||
# ## Section 2: Building Up
|
||||
#
|
||||
# Step-by-step construction of a working example
|
||||
|
||||
# ... code ...
|
||||
|
||||
# ## Section 3: Validation
|
||||
#
|
||||
# Test that the result is correct (this is still a test!)
|
||||
|
||||
@testset "Elasticity 2D" begin
|
||||
@test isapprox(u_computed, u_analytical, rtol=1e-6)
|
||||
end
|
||||
|
||||
# ## Discussion
|
||||
#
|
||||
# What did we learn? What can we do next?
|
||||
# Links to related tutorials.
|
||||
```
|
||||
|
||||
**Generation:**
|
||||
|
||||
```julia
|
||||
using Literate
|
||||
Literate.markdown("test/tutorials/01_fundamentals/creating_elements.jl",
|
||||
"docs/src/tutorials/")
|
||||
Literate.notebook("test/tutorials/01_fundamentals/creating_elements.jl",
|
||||
"docs/notebooks/")
|
||||
```
|
||||
|
||||
### Unit Tests (Fast Validation)
|
||||
|
||||
**Purpose:** Test individual functions in isolation
|
||||
**Style:** Concise, no narrative
|
||||
**Location:** `test/unit/`
|
||||
|
||||
```julia
|
||||
@testset "Basis Functions - Quad4" begin
|
||||
@testset "Evaluation at ξ=0, η=0" begin
|
||||
N = eval_basis(Quad4, (0.0, 0.0))
|
||||
@test N ≈ [0.25, 0.25, 0.25, 0.25]
|
||||
end
|
||||
|
||||
@testset "Derivatives" begin
|
||||
dN = eval_dbasis(Quad4, (0.0, 0.0))
|
||||
@test size(dN) == (2, 4)
|
||||
end
|
||||
|
||||
@testset "Edge case: extreme ξ" begin
|
||||
N = eval_basis(Quad4, (1.0, 1.0))
|
||||
@test N[3] ≈ 1.0
|
||||
@test sum(N) ≈ 1.0
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### Verification Tests (Known Solutions)
|
||||
|
||||
**Purpose:** Validate against analytical solutions or published results
|
||||
**Style:** Brief explanation + reference
|
||||
**Location:** `test/verification/`
|
||||
|
||||
```julia
|
||||
# Timoshenko Beam - Verification Test
|
||||
#
|
||||
# Reference: Timoshenko & Goodier, "Theory of Elasticity", 3rd Ed.
|
||||
# Problem: Cantilever beam with end load
|
||||
# Analytical solution available for tip displacement
|
||||
|
||||
using JuliaFEM, Test
|
||||
|
||||
# Problem parameters from reference
|
||||
L = 10.0 # Length
|
||||
h = 1.0 # Height
|
||||
E = 200e3 # Young's modulus
|
||||
ν = 0.3 # Poisson's ratio
|
||||
P = 100.0 # End load
|
||||
|
||||
# ... setup and solve ...
|
||||
|
||||
# Analytical solution
|
||||
u_tip_analytical = P*L^3 / (3*E*I)
|
||||
|
||||
@testset "Timoshenko Beam Verification" begin
|
||||
@test isapprox(u_tip_computed, u_tip_analytical, rtol=0.01)
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Roadmap
|
||||
|
||||
### Phase 1: Infrastructure (Week 1) ✅ IN PROGRESS
|
||||
|
||||
**Goal:** Set up Literate.jl integration and test structure
|
||||
|
||||
**Tasks:**
|
||||
|
||||
1. ✅ Create `test/tutorials/` directory structure
|
||||
2. ✅ Create new test runner (`test/runtests_new.jl`) with environment control
|
||||
3. ✅ Add Gmsh.jl to test dependencies
|
||||
4. ✅ Tutorial 1: Creating elements (5 tests passing)
|
||||
5. ✅ Tutorial 2: Reading Gmsh meshes (72 tests passing, with recipe and co-located .msh)
|
||||
6. ⏳ Tutorial 4: 1-element validation (priority for Issue #265)
|
||||
7. ⏳ Tutorial 3: Basis functions
|
||||
8. ⏳ Add Literate.jl to `docs/Project.toml`
|
||||
9. ⏳ Update `docs/make.jl` to process tutorials
|
||||
10. ⏳ Add coverage tools (LocalCoverage.jl)
|
||||
|
||||
**Status:** 77/77 tests passing (Tutorial 1: 5, Tutorial 2: 72)
|
||||
|
||||
**Deliverable:** Running CI that executes tutorials and reports coverage
|
||||
|
||||
### Phase 2: Core Tutorials (Week 2-3)
|
||||
|
||||
**Goal:** Write 10-15 fundamental tutorials covering main API
|
||||
|
||||
**Priority order:**
|
||||
|
||||
1. ✅ Creating elements and updating fields ⭐ (Done: 5 tests passing)
|
||||
2. ✅ Reading meshes (Gmsh .msh format) ⭐ (Done: 72 tests passing)
|
||||
3. **1-element validation tests** ⭐⭐ (Next: helps others validate FEM software, see Issue #265)
|
||||
4. Basis functions and integration ⭐
|
||||
5. Simple 2D elasticity (10 elements) ⭐
|
||||
6. Boundary conditions (Dirichlet)
|
||||
7. Surface loads and tractions
|
||||
8. Heat transfer basics
|
||||
9. Assembly process
|
||||
10. Solving linear systems
|
||||
|
||||
**Note on mesh format:** We use **Gmsh** (via Gmsh.jl) instead of ABAQUS because:
|
||||
|
||||
- No license required (accessible to everyone)
|
||||
- Julia native package (Gmsh.jl)
|
||||
- Modern, actively developed
|
||||
- Programmatic mesh generation (reproducible)
|
||||
- Co-located mesh files with test files (self-contained tests)
|
||||
|
||||
**Success metric:** 60%+ code coverage from tutorials alone
|
||||
|
||||
### Phase 3: Advanced Tutorials (Week 4-5)
|
||||
|
||||
**Goal:** Cover advanced features
|
||||
|
||||
**Topics:**
|
||||
|
||||
1. Nonlinear elasticity (large deformation)
|
||||
2. Contact mechanics basics (2D)
|
||||
3. Mortar methods
|
||||
4. 3D contact
|
||||
5. Material models
|
||||
|
||||
**Success metric:** 80%+ coverage
|
||||
|
||||
### Phase 4: Unit Tests (Week 6)
|
||||
|
||||
**Goal:** Fill coverage gaps with fast unit tests
|
||||
|
||||
**Process:**
|
||||
|
||||
1. Generate coverage report: `julia --code-coverage=user test/runtests.jl`
|
||||
2. Analyze: `using Coverage; LCOV.writefile("coverage.info", process_folder())`
|
||||
3. Find uncovered lines
|
||||
4. Write unit tests for each uncovered function
|
||||
5. Repeat until 99%+
|
||||
|
||||
**Success metric:** 99% coverage, < 5 min unit test runtime
|
||||
|
||||
### Phase 5: Verification (Week 7)
|
||||
|
||||
**Goal:** Validate against known solutions
|
||||
|
||||
**Tests:**
|
||||
|
||||
1. Timoshenko beam (bending)
|
||||
2. Hertz contact (2D)
|
||||
3. Cook's membrane (stress concentration)
|
||||
4. Patch tests (element validation)
|
||||
5. Manufactured solutions
|
||||
|
||||
**Success metric:** All verification tests pass with < 1% error
|
||||
|
||||
### Phase 6: Documentation (Week 8)
|
||||
|
||||
**Goal:** Polish and publish
|
||||
|
||||
**Tasks:**
|
||||
|
||||
1. Review all tutorial narratives
|
||||
2. Add figures and visualizations
|
||||
3. Cross-link tutorials
|
||||
4. Build documentation locally
|
||||
5. Deploy to GitHub Pages
|
||||
6. Write README.md guide to tutorials
|
||||
|
||||
**Success metric:** Beautiful, usable documentation website
|
||||
|
||||
---
|
||||
|
||||
## Test Runner Design
|
||||
|
||||
### `test/runtests.jl`
|
||||
|
||||
```julia
|
||||
using Test, JuliaFEM
|
||||
|
||||
# Determine what to run based on environment
|
||||
const RUN_UNIT = get(ENV, "JULIAFEM_TEST_UNIT", "true") == "true"
|
||||
const RUN_TUTORIALS = get(ENV, "JULIAFEM_TEST_TUTORIALS", "true") == "true"
|
||||
const RUN_SLOW = get(ENV, "JULIAFEM_TEST_SLOW", "false") == "true"
|
||||
const RUN_VERIFICATION = get(ENV, "JULIAFEM_TEST_VERIFICATION", "true") == "true"
|
||||
|
||||
# Fast unit tests (always run)
|
||||
if RUN_UNIT
|
||||
@testset "Unit Tests" begin
|
||||
include("unit/basis/test_quad4.jl")
|
||||
include("unit/basis/test_seg2.jl")
|
||||
# ... more unit tests
|
||||
end
|
||||
end
|
||||
|
||||
# Tutorial tests (run in CI, optional locally)
|
||||
if RUN_TUTORIALS
|
||||
@testset "Tutorials" begin
|
||||
# These are also documentation!
|
||||
include("tutorials/01_fundamentals/creating_elements.jl")
|
||||
include("tutorials/01_fundamentals/reading_meshes.jl")
|
||||
include("tutorials/02_linear_problems/elasticity_2d.jl")
|
||||
# ... more tutorials
|
||||
end
|
||||
end
|
||||
|
||||
# Slow integration tests (CI only by default)
|
||||
if RUN_SLOW
|
||||
@testset "Slow Tests" begin
|
||||
include("verification/hertz_contact.jl")
|
||||
# Large mesh tests
|
||||
end
|
||||
end
|
||||
|
||||
# Verification tests
|
||||
if RUN_VERIFICATION
|
||||
@testset "Verification" begin
|
||||
include("verification/timoshenko_beam.jl")
|
||||
include("verification/cook_membrane.jl")
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
|
||||
```bash
|
||||
# During development (fast, < 5 min)
|
||||
julia --project=. -e 'using Pkg; Pkg.test()'
|
||||
|
||||
# Before commit (< 15 min)
|
||||
JULIAFEM_TEST_TUTORIALS=true julia --project=. test/runtests.jl
|
||||
|
||||
# Full CI run (< 30 min)
|
||||
JULIAFEM_TEST_SLOW=true julia --project=. test/runtests.jl
|
||||
|
||||
# Only unit tests (< 2 min)
|
||||
JULIAFEM_TEST_TUTORIALS=false julia --project=. test/runtests.jl
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Coverage Workflow
|
||||
|
||||
### Local Development
|
||||
|
||||
```bash
|
||||
# 1. Run tests with coverage
|
||||
julia --project=. --code-coverage=user test/runtests.jl
|
||||
|
||||
# 2. Generate coverage report
|
||||
julia --project=. -e '
|
||||
using Coverage
|
||||
coverage = process_folder()
|
||||
covered = length(filter(c -> c.coverage > 0, coverage))
|
||||
total = length(coverage)
|
||||
println("Coverage: $(round(100*covered/total, digits=2))%")
|
||||
LCOV.writefile("coverage.info", coverage)
|
||||
'
|
||||
|
||||
# 3. View in browser (requires genhtml from lcov package)
|
||||
genhtml coverage.info -o coverage/
|
||||
firefox coverage/index.html
|
||||
```
|
||||
|
||||
### GitHub Actions CI
|
||||
|
||||
Already set up yesterday! Codecov will:
|
||||
|
||||
- Track coverage over time
|
||||
- Comment on PRs with coverage changes
|
||||
- Show which lines are uncovered
|
||||
- Badge in README.md
|
||||
|
||||
---
|
||||
|
||||
## Writing Style Guide
|
||||
|
||||
### For Tutorials (Literate.jl)
|
||||
|
||||
**Do:**
|
||||
|
||||
- ✅ Explain **why**, not just **what**
|
||||
- ✅ Use realistic examples (~10 elements, not too simple or too complex)
|
||||
- ✅ Include mathematical notation where helpful
|
||||
- ✅ Show output/results
|
||||
- ✅ Link to related tutorials
|
||||
- ✅ Test the actual result (still a test!)
|
||||
- ✅ Co-locate mesh files with test files (self-contained)
|
||||
- ✅ Include mesh generation recipe (show how mesh was created)
|
||||
|
||||
**Don't:**
|
||||
|
||||
- ❌ Assume prior knowledge (explain or link)
|
||||
- ❌ Use large meshes (slow tests)
|
||||
- ❌ Skip explanation (this is documentation!)
|
||||
- ❌ Test implementation details (test behavior)
|
||||
|
||||
### For Unit Tests
|
||||
|
||||
**Do:**
|
||||
|
||||
- ✅ Test one thing per `@testset`
|
||||
- ✅ Use descriptive test names
|
||||
- ✅ Test edge cases (empty, single, many)
|
||||
- ✅ Test error conditions (`@test_throws`)
|
||||
- ✅ Be concise (no prose needed)
|
||||
|
||||
**Don't:**
|
||||
|
||||
- ❌ Mix multiple concepts in one test
|
||||
- ❌ Use real-world complex examples
|
||||
- ❌ Duplicate tutorial content
|
||||
|
||||
---
|
||||
|
||||
## Migration Plan for Existing Tests
|
||||
|
||||
### Current State (56 test files)
|
||||
|
||||
Many old tests are:
|
||||
|
||||
- Poorly documented
|
||||
- Using outdated API
|
||||
- Slow (large meshes)
|
||||
- Not structured for learning
|
||||
|
||||
### Migration Strategy
|
||||
|
||||
**Don't delete old tests immediately!** Instead:
|
||||
|
||||
1. **Categorize:** Is it tutorial material, unit test, or verification?
|
||||
2. **Rewrite:** Create new version following philosophy
|
||||
3. **Verify:** Ensure new test covers same functionality
|
||||
4. **Archive:** Move old test to `test/archive/` with note
|
||||
5. **Delete:** After new tests run successfully in CI
|
||||
|
||||
**Example:**
|
||||
|
||||
```text
|
||||
test/test_elasticity_2d_linear_with_surface_load.jl (old)
|
||||
→ test/tutorials/02_linear_problems/elasticity_2d.jl (new, Literate)
|
||||
→ test/archive/test_elasticity_2d_linear_with_surface_load.jl.old (keep for reference)
|
||||
→ delete after 1 month if no issues
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
### Quantitative
|
||||
|
||||
- **Coverage:** 99%+ by end of Phase 4
|
||||
- **Speed:** < 5 min unit tests, < 30 min full suite
|
||||
- **Count:** 15+ tutorials, 100+ unit tests
|
||||
|
||||
### Qualitative
|
||||
|
||||
- **Can a new user learn JuliaFEM from tutorials alone?** (Ask someone!)
|
||||
- **Are tutorials referenced in issue discussions?** ("See tutorial X")
|
||||
- **Do contributors write tests first?** (TDD culture)
|
||||
- **Is documentation always up-to-date?** (Literate.jl ensures it)
|
||||
|
||||
---
|
||||
|
||||
## Special: 1-Element Validation Tests
|
||||
|
||||
### Motivation (Issue #265)
|
||||
|
||||
In 2019, JuliaFEM was used to **validate another FEM software**. A user computed a reference solution with JuliaFEM and compared it against their own implementation. This is a powerful use case we should embrace!
|
||||
|
||||
### Design Philosophy
|
||||
|
||||
**Goal:** Create 1-element tests that can be:
|
||||
|
||||
1. **Hand-calculated** - Simple enough to verify by hand
|
||||
2. **Exact** - Integer or simple fractional results (no floating-point ambiguity)
|
||||
3. **Reference-quality** - Others can use to validate their FEM code
|
||||
4. **Educational** - Show the math, not just code
|
||||
|
||||
### Example Pattern
|
||||
|
||||
```julia
|
||||
# # 1-Element Validation: Quad4 Elasticity
|
||||
#
|
||||
# This tutorial computes the stiffness matrix for a single Quad4 element
|
||||
# under plane stress conditions. The solution can be verified by hand.
|
||||
#
|
||||
# **Use case:** Validating FEM implementations (see Issue #265)
|
||||
#
|
||||
# ## Problem Setup
|
||||
#
|
||||
# Geometry: Unit square [0,1] × [0,1]
|
||||
# Material: E = 100.0, ν = 0.3 (simple values)
|
||||
# Element: Single Quad4 with nodes at corners
|
||||
#
|
||||
# ## Hand Calculation
|
||||
#
|
||||
# For Quad4 under plane stress, the stiffness matrix has structure:
|
||||
# ... detailed derivation ...
|
||||
#
|
||||
# Expected K[1,1] = ... (show calculation)
|
||||
|
||||
using JuliaFEM, Test
|
||||
|
||||
# Define nodes (unit square)
|
||||
nodes = Dict(
|
||||
1 => [0.0, 0.0],
|
||||
2 => [1.0, 0.0],
|
||||
3 => [1.0, 1.0],
|
||||
4 => [0.0, 1.0]
|
||||
)
|
||||
|
||||
# Create element
|
||||
element = Element(Quad4, (1, 2, 3, 4))
|
||||
update!(element, "geometry", nodes)
|
||||
update!(element, "youngs modulus", 100.0)
|
||||
update!(element, "poissons ratio", 0.3)
|
||||
|
||||
# Assemble stiffness matrix
|
||||
K = assemble_stiffness_matrix(element)
|
||||
|
||||
# Validate against hand calculation
|
||||
@testset "1-Element Validation: Quad4 Stiffness" begin
|
||||
# Check specific entries that we calculated by hand
|
||||
@test K[1,1] ≈ 42.5 # Hand calculated value
|
||||
@test K[1,2] ≈ 10.0 # Hand calculated value
|
||||
# ... more validations
|
||||
|
||||
# Symmetry check
|
||||
@test issymmetric(K)
|
||||
|
||||
# Positive definite check (all eigenvalues > 0, after BC)
|
||||
# ... (need to apply constraints first)
|
||||
end
|
||||
```
|
||||
|
||||
### Benefits
|
||||
|
||||
1. **Validation tool** - Others can use JuliaFEM as reference
|
||||
2. **Debugging aid** - If basic case fails, know where to look
|
||||
3. **Educational** - Shows the math behind FEM
|
||||
4. **Confidence** - Proves implementation is correct
|
||||
5. **Regression test** - Any refactoring must pass these
|
||||
|
||||
### Implementation Priority
|
||||
|
||||
**High priority** - These tests are foundational. Should be in Tutorial 4 (before basis functions).
|
||||
|
||||
**Coverage:** Create 1-element tests for each element type:
|
||||
|
||||
- Seg2 (1D bar)
|
||||
- Tri3 (2D triangle)
|
||||
- Quad4 (2D quadrilateral)
|
||||
- Tet4 (3D tetrahedron)
|
||||
- Hex8 (3D hexahedron)
|
||||
|
||||
---
|
||||
|
||||
## Questions to Resolve
|
||||
|
||||
### 1. Literate.jl Execution Strategy
|
||||
|
||||
**Option A:** Tutorials are in `test/tutorials/`, executed by `Pkg.test()`
|
||||
|
||||
- Pro: Ensures tutorials always work
|
||||
- Con: Slows down test suite
|
||||
|
||||
**Option B:** Tutorials are in `docs/tutorials/`, executed by docs build
|
||||
|
||||
- Pro: Fast test suite
|
||||
- Con: Tutorials might break without noticing
|
||||
|
||||
**Recommendation:** Option A (tutorials in test/), with `RUN_TUTORIALS` env var
|
||||
|
||||
### 2. Visualization in Tutorials
|
||||
|
||||
Should tutorials include plots/visualizations?
|
||||
|
||||
**Option A:** Yes, using Makie.jl or similar
|
||||
|
||||
- Pro: Very educational, shows results
|
||||
- Con: Heavy dependency, slow to precompile
|
||||
|
||||
**Option B:** No plots in tests, but show code in docs
|
||||
|
||||
- Pro: Fast tests
|
||||
- Con: Less visual learning
|
||||
|
||||
**Recommendation:** Option B initially, add plots later as optional
|
||||
|
||||
### 3. Mesh Files ✅ DECIDED
|
||||
|
||||
**Decision:** Use Gmsh.jl for mesh generation (Option B)
|
||||
|
||||
**Rationale:**
|
||||
|
||||
- No license required (ABAQUS needs license, not accessible)
|
||||
- No heavy dependencies (HDF5/MED format requires HDF5.jl)
|
||||
- Programmatic generation (reproducible, can show recipe)
|
||||
- Modern and well-maintained
|
||||
- Julia native integration
|
||||
|
||||
**Implementation Pattern:**
|
||||
|
||||
1. Create `*_recipe.jl` script showing how mesh was generated
|
||||
2. Run recipe to generate `*.msh` file
|
||||
3. Commit both recipe and .msh file to repository
|
||||
4. Test reads the .msh file (fast, reliable)
|
||||
5. Users can see recipe to understand mesh structure
|
||||
|
||||
**Example:**
|
||||
|
||||
```text
|
||||
test/tutorials/01_fundamentals/
|
||||
├── reading_gmsh_meshes.jl # The actual test
|
||||
├── reading_gmsh_meshes.msh # Pre-generated mesh (committed)
|
||||
└── reading_gmsh_meshes_recipe.jl # Shows how mesh was created
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- Self-contained tests (mesh next to test file)
|
||||
- Reproducible (recipe shows exactly how to recreate)
|
||||
- Fast (don't generate mesh in CI, just read it)
|
||||
- Educational (recipe teaches mesh generation)
|
||||
- Accessible (no external software needed to run tests)
|
||||
|
||||
---
|
||||
|
||||
## Next Steps (This Week)
|
||||
|
||||
### Immediate (November 9, 2025)
|
||||
|
||||
1. ✅ Create this document (done!)
|
||||
2. ✅ Create tutorial directory structure
|
||||
3. ✅ Write first tutorial (creating elements - 5 tests passing)
|
||||
4. ✅ Write second tutorial (reading Gmsh meshes - 72 tests passing)
|
||||
5. ✅ Create new test runner (`test/runtests_new.jl`)
|
||||
6. 🔄 **Now: Tutorial 4 - 1-element validation** (priority for Issue #265)
|
||||
7. ⏳ Tutorial 3 - Basis functions
|
||||
8. ⏳ Add Literate.jl to docs dependencies
|
||||
9. ⏳ Update `docs/make.jl` for HTML generation
|
||||
|
||||
### This Week (Week 1 - November 9-15, 2025)
|
||||
|
||||
**Completed:**
|
||||
|
||||
1. ✅ Tutorial 1: Creating elements and fields (5 tests)
|
||||
2. ✅ Tutorial 2: Reading Gmsh meshes (72 tests)
|
||||
|
||||
**In Progress:**
|
||||
3. 🔄 Tutorial 4: 1-element validation (priority - helps validate other FEM software)
|
||||
4. 🔄 Tutorial 3: Basis functions and integration
|
||||
|
||||
**Planned:**
|
||||
5. Tutorial 5: Simple 2D elasticity (10 elements, use Tutorial 2 mesh)
|
||||
6. Set up coverage workflow locally
|
||||
7. Test Literate.jl → HTML generation
|
||||
8. Update CI to run new test structure
|
||||
|
||||
**Target:** 5 tutorials by end of week (currently 2/5)
|
||||
|
||||
### Next Week
|
||||
|
||||
Continue writing tutorials, aim for 10 total by end of week.
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
**This is a complete overhaul of testing strategy** - from "fix 49 failing tests" to "build educational test suite that reaches 99% coverage."
|
||||
|
||||
**Timeline:** ~8 weeks for full implementation
|
||||
**Effort:** Significant, but creates lasting value
|
||||
**Benefit:** Tests become documentation, documentation is always tested
|
||||
|
||||
**Philosophy:** Tests are not a chore - they're the best way to teach users how to use JuliaFEM.
|
||||
|
||||
---
|
||||
|
||||
**Status:** 📋 Planning complete, ready to implement
|
||||
**Next:** Get your feedback, then start Phase 1
|
||||
Reference in New Issue
Block a user