Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Appendix A: Solver Parameter Reference

This appendix documents the ODE solver methods, configuration options, and presets available in go-pflow’s solver package.

Solver Methods

Tsit5 (Default)

Tsitouras 5th-order Runge-Kutta with embedded 4th-order error estimator. The recommended solver for nearly all Petri net simulations.

  • Order: 5 (error ~ )
  • Stages: 7
  • Adaptive: Yes (embedded error estimation)
  • Reference: Ch. Tsitouras, “Runge-Kutta pairs of order 5(4) satisfying only the first column simplifying assumption”, Computers & Mathematics with Applications, 62 (2011) 770-775
sol := solver.Solve(prob, solver.Tsit5(), solver.DefaultOptions())

RK45 (Dormand-Prince)

Classic Dormand-Prince 5(4) method. The algorithm behind MATLAB’s ode45. Comparable to Tsit5 with slightly different error estimation characteristics.

  • Order: 5
  • Stages: 7
  • Adaptive: Yes
  • Reference: J.R. Dormand & P.J. Prince, “A family of embedded Runge-Kutta formulae”, Journal of Computational and Applied Mathematics, 6 (1980) 19-26
sol := solver.Solve(prob, solver.RK45(), solver.DefaultOptions())

BS32 (Bogacki-Shampine)

3rd-order method with embedded 2nd-order error estimator. Useful when Tsit5/RK45 are overkill — simpler problems with less stringent accuracy requirements.

  • Order: 3
  • Stages: 4
  • Adaptive: Yes
  • Reference: P. Bogacki & L.F. Shampine, “A 3(2) pair of Runge-Kutta formulas”, Appl. Math. Lett., 2 (1989) 321-325

RK4 (Classic Runge-Kutta)

Fixed-step 4th-order method. No error estimation. Use with Adaptive: false.

  • Order: 4
  • Stages: 4
  • Adaptive: No (fixed step)
  • Use case: Teaching, debugging, when fixed step size is desired

Heun (Improved Euler)

2nd-order predictor-corrector method. Simple and fast.

  • Order: 2
  • Stages: 2
  • Adaptive: No

Euler (Forward Euler)

1st-order method. Primarily for teaching and debugging.

  • Order: 1
  • Stages: 1
  • Adaptive: No
  • Warning: Requires very small step sizes for accuracy

Implicit Euler

For stiff systems where explicit methods require impractically small steps. Uses Newton iteration to solve the implicit step.

sol := solver.ImplicitEuler(prob, solver.StiffOptions())

TRBDF2

Second-order implicit method combining trapezoidal rule with backward differentiation. More accurate than implicit Euler for stiff systems.

sol := solver.TRBDF2(prob, solver.StiffOptions())

SolveImplicit (Auto-Detection)

Automatically detects stiffness and switches between explicit (Tsit5) and implicit (TRBDF2) methods.

sol := solver.SolveImplicit(prob, solver.DefaultOptions())

Configuration Parameters

The Options struct controls solver behavior:

ParameterTypeDescription
Dtfloat64Initial time step
Dtminfloat64Minimum allowed time step
Dtmaxfloat64Maximum allowed time step
Abstolfloat64Absolute error tolerance
Reltolfloat64Relative error tolerance
MaxitersintMaximum number of iterations
AdaptiveboolEnable adaptive step size control

How Adaptive Stepping Works

When Adaptive is true, the solver:

  1. Computes both the 5th-order and 4th-order solutions at each step
  2. Estimates the local error as the difference between them
  3. Computes a scaled error: err = |error| / (Abstol + Reltol * max(|y|, |y_new|))
  4. If err <= 1: accepts the step and grows Dt (up to Dtmax)
  5. If err > 1: rejects the step and shrinks Dt (down to Dtmin)

The step size factor is: factor = 0.9 * (1/err)^(1/(order+1))

Option Presets

General Purpose

PresetDtDtminDtmaxAbstolReltolMaxitersUse Case
DefaultOptions()0.011e-60.11e-61e-3100,000Most problems
JSParityOptions()0.011e-61.01e-61e-3100,000Match JavaScript solver
FastOptions()0.11e-41.01e-21e-21,000Interactive, ~10x speedup
AccurateOptions()0.0011e-80.11e-91e-61,000,000Research, publishing
StiffOptions()0.0011e-100.011e-81e-5500,000Stiff systems

Domain-Specific

PresetDtDtminDtmaxAbstolReltolMaxitersUse Case
GameAIOptions()0.11e-31.01e-21e-2500Move evaluation
EpidemicOptions()0.011e-60.51e-61e-4200,000SIR/SEIR models
WorkflowOptions()0.11e-410.01e-41e-350,000Process simulation
LongRunOptions()0.11e-410.01e-51e-3500,000Extended simulations

Equilibrium Detection

The equilibrium detector stops the simulation early when the system reaches steady state.

Equilibrium Parameters

ParameterTypeDescription
Tolerancefloat64Maximum rate of change to consider as equilibrium
ConsecutiveStepsintNumber of consecutive steps below tolerance required
MinTimefloat64Minimum time before checking for equilibrium
CheckIntervalintCheck every N steps (0 = every step)

Equilibrium Presets

PresetToleranceConsecutiveMinTimeInterval
DefaultEquilibriumOptions()1e-650.110
FastEquilibriumOptions()1e-430.015
StrictEquilibriumOptions()1e-9101.01

Convenience Functions

// Find equilibrium with default settings
state, reached := solver.FindEquilibrium(prob)

// Fast equilibrium (aggressive settings)
state, reached := solver.FindEquilibriumFast(prob)

// Accurate equilibrium (strict settings)
state, reached := solver.FindEquilibriumAccurate(prob)

Combined Option Pairs

For convenience, OptionPair bundles solver and equilibrium options:

pair := solver.GameAIOptionPair()
sol, eq := solver.SolveUntilEquilibrium(prob, solver.Tsit5(), pair.Solver, pair.Equilibrium)

Available pairs: GameAIOptionPair(), EpidemicOptionPair(), WorkflowOptionPair(), LongRunOptionPair().

When to Use Which Solver

SituationSolverOptions
First attempt / don’t knowTsit5()DefaultOptions()
Match browser outputTsit5()JSParityOptions()
Game AI move evaluationTsit5()GameAIOptions()
Interactive / real-timeTsit5()FastOptions()
Publishing resultsTsit5()AccurateOptions()
SIR/SEIR epidemicsTsit5()EpidemicOptions()
Process mining validationTsit5()WorkflowOptions()
System won’t convergeImplicitEuler()StiffOptions()
Auto-detect stiffnessSolveImplicit()DefaultOptions()
Fixed step (teaching)RK4()Adaptive: false

If Tsit5() with DefaultOptions() doesn’t work for your problem, the most common fixes are:

  1. Too slow: Use FastOptions() (trades accuracy for speed)
  2. Inaccurate: Use AccurateOptions() (tighter tolerances)
  3. Unstable/NaN: Use StiffOptions() with ImplicitEuler() (stiff system)
  4. Doesn’t converge: Extend Tspan, increase Maxiters, or check for conservation violations