DiffEqDevTools.jl is a component package in the DifferentialEquations ecosystem. It provides tools for:
- Convergence testing: Verify that numerical methods achieve their theoretical convergence orders
- Benchmarking: Compare performance and accuracy of different algorithms
- Error approximation: Calculate errors when analytical solutions are unavailable
This package is primarily used for testing and development of differential equation solvers, but can also be useful for end users who want to rigorously validate solver performance for their problems.
using Pkg
Pkg.add("DiffEqDevTools")Or for the development version:
Pkg.add(url="https://github.com/SciML/DiffEqDevTools.jl")Test that a numerical method achieves its expected order of convergence:
using OrdinaryDiffEq, DiffEqDevTools
# Define a problem with known analytical solution
f(u, p, t) = 1.01 * u
u0 = 1 / 2
tspan = (0.0, 1.0)
prob = ODEProblem(f, u0, tspan)
# Test convergence across multiple timesteps
dts = 1 ./ 2 .^ (6:10)
sim = test_convergence(dts, prob, Tsit5())
# Check the estimated convergence order
println("Estimated order: ", sim.𝒪est[:final]) # Should be close to 5For problems without analytical solutions, use analyticless_test_convergence:
# Use a high-accuracy reference solution
dts = 1 ./ 2 .^ (6:9)
test_setup = Dict(:alg => Vern9(), :reltol => 1e-14, :abstol => 1e-14)
sim = analyticless_test_convergence(dts, prob, Tsit5(), test_setup)Compare the efficiency (work vs. accuracy) of different algorithms:
using Plots
abstols = 1 ./ 10 .^ (3:10)
reltols = 1 ./ 10 .^ (3:10)
setups = [
Dict(:alg => Tsit5()),
Dict(:alg => Vern7()),
Dict(:alg => Rodas5())
]
wp = WorkPrecisionSet(prob, abstols, reltols, setups)
plot(wp) # Generates work-precision diagramQuickly compare algorithms at a fixed timestep:
setups = [
Dict(:alg => Euler()),
Dict(:alg => Midpoint()),
Dict(:alg => RK4())
]
shoot = Shootout(prob, setups, dt = 1 / 2^4)
println("Winner: ", shoot.winner)Create reference solutions for computing errors:
# Generate high-accuracy reference
ref_sol = solve(prob, Vern9(), abstol = 1e-14, reltol = 1e-14)
test_sol = TestSolution(ref_sol)
# Use it to compute errors for other solutions
sol = solve(prob, Tsit5(), adaptive = false, dt = 0.1)
err_sol = appxtrue(sol, test_sol)
println("Final error: ", err_sol.errors[:final])DiffEqDevTools also supports convergence testing for SDEs and other stochastic problems:
using StochasticDiffEq
f(du, u, p, t) = (du .= 1.01u)
g(du, u, p, t) = (du .= 0.87u)
prob = SDEProblem(f, g, [1.0], (0.0, 1.0))
dts = (1 / 2) .^ (7:-1:4)
test_dt = 1 / 2^8
sim = analyticless_test_convergence(dts, prob, SRIW1(), test_dt, trajectories = 100)Main Functions:
test_convergence: Test convergence with analytical solutionanalyticless_test_convergence: Test convergence without analytical solutionWorkPrecision,WorkPrecisionSet: Create work-precision diagramsShootout,ShootoutSet: Algorithm comparison at fixed timestepsTestSolution: Wrapper for reference solutionsappxtrue,appxtrue!: Compute errors against reference solutions
Tableau Functions:
deduce_Butcher_tableau: Extract Butcher tableau from an algorithmstability_region: Plot stability region of a methodcheck_tableau: Verify order conditions of a Runge-Kutta tableau- Constructors for various RK tableaus (e.g.,
constructEuler,constructRK4, etc.)
For more detailed documentation, please see the DifferentialEquations.jl documentation. For questions or issues, please visit the Gitter channel or open an issue on GitHub.
Contributions are welcome! Please feel free to submit issues or pull requests. When contributing, please ensure that:
- Code follows the existing style
- Tests are added for new functionality
- Documentation is updated as needed
If you use DiffEqDevTools.jl in your research, please cite the DifferentialEquations.jl project. See CITATION.bib for the BibTeX entry.