307 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			307 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Feature: Auto-Switching & Stiffness Detection
 | ||
| 
 | ||
| ## Overview
 | ||
| 
 | ||
| Automatic algorithm switching detects when a problem transitions between stiff and non-stiff regimes and switches to the appropriate solver automatically. This is one of the most powerful features for robust, user-friendly ODE solving.
 | ||
| 
 | ||
| **Key Characteristics:**
 | ||
| - Automatic stiffness detection via eigenvalue estimation
 | ||
| - Seamless switching between non-stiff and stiff solvers
 | ||
| - CompositeAlgorithm infrastructure
 | ||
| - Configurable switching criteria
 | ||
| - Basis for DefaultODEAlgorithm (solve without specifying algorithm)
 | ||
| 
 | ||
| ## Why This Feature Matters
 | ||
| 
 | ||
| - **User-friendly**: User doesn't need to know if problem is stiff
 | ||
| - **Robustness**: Handles problems with changing character
 | ||
| - **Efficiency**: Uses fast explicit methods when possible, switches to implicit when needed
 | ||
| - **Production-ready**: Essential for general-purpose library
 | ||
| - **Real problems**: Many problems are "mildly stiff" or transiently stiff
 | ||
| 
 | ||
| ## Dependencies
 | ||
| 
 | ||
| ### Required
 | ||
| 
 | ||
| - [ ] At least one stiff solver (Rosenbrock23 or FBDF)
 | ||
| - [ ] At least two non-stiff solvers (have DP5, Tsit5)
 | ||
| - [ ] BS3 recommended for completeness
 | ||
| 
 | ||
| ### Recommended
 | ||
| 
 | ||
| - [ ] Vern7 for high-accuracy non-stiff
 | ||
| - [ ] Rodas4 or Rodas5P for high-accuracy stiff
 | ||
| - [ ] Multiple controllers (PI, PID)
 | ||
| 
 | ||
| ## Implementation Approach
 | ||
| 
 | ||
| ### Stiffness Detection
 | ||
| 
 | ||
| **Eigenvalue Estimation**:
 | ||
| ```
 | ||
| ρ = ||δf|| / ||δy||
 | ||
| ```
 | ||
| 
 | ||
| Where:
 | ||
| - δy = y_{n+1} - y_n
 | ||
| - δf = f(t_{n+1}, y_{n+1}) - f(t_n, y_n)
 | ||
| - ρ approximates spectral radius of Jacobian
 | ||
| 
 | ||
| **Stiffness ratio**:
 | ||
| ```
 | ||
| S = |ρ * h| / stability_region_size
 | ||
| ```
 | ||
| 
 | ||
| If S > tolerance (e.g., 1.0), problem is stiff.
 | ||
| 
 | ||
| ### Algorithm Switching Logic
 | ||
| 
 | ||
| 1. **Detect stiffness** every few steps
 | ||
| 2. **Switch condition**: Stiffness detected for N consecutive steps
 | ||
| 3. **Switch back**: Non-stiffness detected for M consecutive steps
 | ||
| 4. **Hysteresis**: N < M to avoid chattering
 | ||
| 
 | ||
| Typical values:
 | ||
| - N = 3-5 (switch to stiff solver)
 | ||
| - M = 25-50 (switch back to non-stiff)
 | ||
| 
 | ||
| ### CompositeAlgorithm Structure
 | ||
| 
 | ||
| ```rust
 | ||
| pub struct CompositeAlgorithm<NonStiff, Stiff> {
 | ||
|     pub nonstiff_alg: NonStiff,
 | ||
|     pub stiff_alg: Stiff,
 | ||
|     pub choice_function: AutoSwitchCache,
 | ||
| }
 | ||
| 
 | ||
| pub struct AutoSwitchCache {
 | ||
|     pub current_algorithm: AlgorithmChoice,
 | ||
|     pub consecutive_stiff: usize,
 | ||
|     pub consecutive_nonstiff: usize,
 | ||
|     pub switch_to_stiff_threshold: usize,
 | ||
|     pub switch_to_nonstiff_threshold: usize,
 | ||
|     pub stiffness_tolerance: f64,
 | ||
| }
 | ||
| 
 | ||
| pub enum AlgorithmChoice {
 | ||
|     NonStiff,
 | ||
|     Stiff,
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| ### Implementation Challenges
 | ||
| 
 | ||
| 1. **State transfer**: When switching, need to transfer state cleanly
 | ||
| 2. **Controller state**: Each algorithm may have different controller state
 | ||
| 3. **Interpolation**: Dense output from previous algorithm
 | ||
| 4. **First step**: Which algorithm to start with?
 | ||
| 
 | ||
| ## Implementation Tasks
 | ||
| 
 | ||
| ### Core Infrastructure
 | ||
| 
 | ||
| - [ ] Define `CompositeAlgorithm` struct
 | ||
|   - [ ] Generic over two integrator types
 | ||
|   - [ ] Store both algorithms
 | ||
|   - [ ] Store switching logic state
 | ||
| 
 | ||
| - [ ] Define `AutoSwitchCache`
 | ||
|   - [ ] Current algorithm choice
 | ||
|   - [ ] Consecutive step counters
 | ||
|   - [ ] Thresholds
 | ||
|   - [ ] Stiffness tolerance
 | ||
| 
 | ||
| - [ ] Implement switching logic
 | ||
|   - [ ] Eigenvalue estimation function
 | ||
|   - [ ] Stiffness detection
 | ||
|   - [ ] Decision to switch
 | ||
|   - [ ] Reset counters appropriately
 | ||
| 
 | ||
| ### Integrator Changes
 | ||
| 
 | ||
| - [ ] Modify `Problem` to work with composite algorithms
 | ||
|   - [ ] May need `IntegratorEnum` or dynamic dispatch
 | ||
|   - [ ] Or: make Problem generic and handle in solve loop
 | ||
| 
 | ||
| - [ ] State transfer mechanism
 | ||
|   - [ ] Transfer y, t from one integrator to other
 | ||
|   - [ ] Transfer/reset controller state
 | ||
|   - [ ] Clear interpolation data
 | ||
| 
 | ||
| - [ ] Solve loop modifications
 | ||
|   - [ ] Check for switch every N steps
 | ||
|   - [ ] Perform switch if needed
 | ||
|   - [ ] Continue with new algorithm
 | ||
| 
 | ||
| ### Eigenvalue Estimation
 | ||
| 
 | ||
| - [ ] Implement basic estimator
 | ||
|   - [ ] Track previous f evaluation
 | ||
|   - [ ] Compute ρ = ||δf|| / ||δy||
 | ||
|   - [ ] Update estimate smoothly (exponential moving average)
 | ||
| 
 | ||
| - [ ] Handle edge cases
 | ||
|   - [ ] Very small ||δy||
 | ||
|   - [ ] First step (no history)
 | ||
|   - [ ] After callback event
 | ||
| 
 | ||
| ### Default Algorithm
 | ||
| 
 | ||
| - [ ] `AutoAlgSwitch` function/constructor
 | ||
|   - [ ] Takes tuple of non-stiff algorithms
 | ||
|   - [ ] Takes tuple of stiff algorithms
 | ||
|   - [ ] Returns CompositeAlgorithm
 | ||
|   - [ ] With default switching parameters
 | ||
| 
 | ||
| - [ ] `DefaultODEAlgorithm` (future)
 | ||
|   - [ ] Analyzes problem
 | ||
|   - [ ] Selects algorithms based on size, tolerance
 | ||
|   - [ ] Returns configured CompositeAlgorithm
 | ||
| 
 | ||
| ### Testing
 | ||
| 
 | ||
| - [ ] **Transiently stiff problem**
 | ||
|   - [ ] Starts non-stiff, becomes stiff, then non-stiff again
 | ||
|   - [ ] Example: Van der Pol with time-varying μ
 | ||
|   - [ ] Verify switches at right times
 | ||
|   - [ ] Verify solution accuracy throughout
 | ||
| 
 | ||
| - [ ] **Always non-stiff problem**
 | ||
|   - [ ] Should never switch to stiff solver
 | ||
|   - [ ] Verify minimal overhead
 | ||
| 
 | ||
| - [ ] **Always stiff problem**
 | ||
|   - [ ] Should switch to stiff early
 | ||
|   - [ ] Stay on stiff solver
 | ||
| 
 | ||
| - [ ] **Chattering prevention**
 | ||
|   - [ ] Problem near stiffness boundary
 | ||
|   - [ ] Verify doesn't switch back and forth rapidly
 | ||
|   - [ ] Hysteresis should prevent chattering
 | ||
| 
 | ||
| - [ ] **State transfer test**
 | ||
|   - [ ] Switch mid-integration
 | ||
|   - [ ] Verify no discontinuity in solution
 | ||
|   - [ ] Interpolation works across switch
 | ||
| 
 | ||
| - [ ] **Comparison test**
 | ||
|   - [ ] Run transient stiff problem three ways:
 | ||
|     - [ ] Auto-switching
 | ||
|     - [ ] Non-stiff only (should fail or be very slow)
 | ||
|     - [ ] Stiff only (should work but possibly slower)
 | ||
|   - [ ] Auto-switching should be nearly optimal
 | ||
| 
 | ||
| ### Benchmarking
 | ||
| 
 | ||
| - [ ] ROBER problem (chemistry, transiently stiff)
 | ||
| - [ ] HIRES problem (atmospheric chemistry)
 | ||
| - [ ] Compare to manual algorithm selection
 | ||
| - [ ] Measure switching overhead
 | ||
| 
 | ||
| ### Documentation
 | ||
| 
 | ||
| - [ ] Explain stiffness detection
 | ||
| - [ ] Document switching thresholds
 | ||
| - [ ] When auto-switching helps vs hurts
 | ||
| - [ ] Examples with different problem types
 | ||
| - [ ] How to configure switching parameters
 | ||
| 
 | ||
| ## Testing Requirements
 | ||
| 
 | ||
| ### Transient Stiffness Test
 | ||
| 
 | ||
| Van der Pol oscillator with time-varying stiffness:
 | ||
| 
 | ||
| ```rust
 | ||
| // μ(t) = 100 for t < 20
 | ||
| // μ(t) = 1 for 20 <= t < 40
 | ||
| // μ(t) = 100 for t >= 40
 | ||
| ```
 | ||
| 
 | ||
| Expected behavior:
 | ||
| - Start with non-stiff (or quickly switch to stiff)
 | ||
| - Switch to non-stiff around t=20
 | ||
| - Switch back to stiff around t=40
 | ||
| - Solution remains accurate throughout
 | ||
| 
 | ||
| Track:
 | ||
| - When switches occur
 | ||
| - Number of switches
 | ||
| - Total steps with each algorithm
 | ||
| 
 | ||
| ### ROBER Problem
 | ||
| 
 | ||
| Robertson chemical kinetics:
 | ||
| ```
 | ||
| y1' = -0.04*y1 + 1e4*y2*y3
 | ||
| y2' = 0.04*y1 - 1e4*y2*y3 - 3e7*y2²
 | ||
| y3' = 3e7*y2²
 | ||
| ```
 | ||
| 
 | ||
| Very stiff initially, becomes less stiff.
 | ||
| 
 | ||
| Expected: Should start with (or quickly switch to) stiff solver.
 | ||
| 
 | ||
| ## References
 | ||
| 
 | ||
| 1. **Stiffness Detection**:
 | ||
|    - Shampine, L.F. (1977)
 | ||
|    - "Stiffness and Non-stiff Differential Equation Solvers, II"
 | ||
|    - Applied Numerical Mathematics
 | ||
| 
 | ||
| 2. **Auto-switching Algorithms**:
 | ||
|    - Hairer & Wanner (1996), "Solving ODEs II", Section IV.3
 | ||
|    - Discussion of when to use stiff solvers
 | ||
| 
 | ||
| 3. **Julia Implementation**:
 | ||
|    - `OrdinaryDiffEq.jl/lib/OrdinaryDiffEqDefault/src/default_alg.jl`
 | ||
|    - `AutoAlgSwitch` and `default_autoswitch` functions
 | ||
| 
 | ||
| 4. **MATLAB's ode45/ode15s switching**:
 | ||
|    - MATLAB documentation on automatic solver selection
 | ||
| 
 | ||
| ## Complexity Estimate
 | ||
| 
 | ||
| **Effort**: Large (15-25 hours)
 | ||
| - Composite algorithm infrastructure: 6-8 hours
 | ||
| - Stiffness detection: 4-6 hours
 | ||
| - Switching logic and state transfer: 5-8 hours
 | ||
| - Testing and tuning: 4-6 hours
 | ||
| 
 | ||
| **Risk**: Medium-High
 | ||
| - Complexity in state transfer
 | ||
| - Getting switching criteria right requires tuning
 | ||
| - Interaction with controllers needs care
 | ||
| - Edge cases (callbacks during switch, etc.)
 | ||
| 
 | ||
| ## Success Criteria
 | ||
| 
 | ||
| - [ ] Handles transiently stiff problems automatically
 | ||
| - [ ] Switches at appropriate times
 | ||
| - [ ] No chattering between algorithms
 | ||
| - [ ] Solution accuracy maintained across switches
 | ||
| - [ ] Overhead < 10% on problems that don't need switching
 | ||
| - [ ] Performance within 20% of manual optimal selection
 | ||
| - [ ] Documentation complete with examples
 | ||
| - [ ] Robust to edge cases
 | ||
| 
 | ||
| ## Future Enhancements
 | ||
| 
 | ||
| - [ ] More sophisticated stiffness detection
 | ||
|   - [ ] Multiple detection methods
 | ||
|   - [ ] Learning from past behavior
 | ||
| 
 | ||
| - [ ] Multi-algorithm selection
 | ||
|   - [ ] More than 2 algorithms (low/medium/high accuracy)
 | ||
|   - [ ] Tolerance-based selection
 | ||
| 
 | ||
| - [ ] Automatic tolerance selection
 | ||
| 
 | ||
| - [ ] Problem analysis at start
 | ||
|   - [ ] Estimate problem size effect
 | ||
|   - [ ] Sparsity detection
 | ||
|   - [ ] Initial algorithm recommendation
 | ||
| 
 | ||
| - [ ] DefaultODEAlgorithm with full analysis
 | ||
|   - [ ] Based on problem size, tolerance, mass matrix, etc.
 | 
