Note
Go to the end to download the full example code.
2.4.9 Solver comparison
This example shows how to set up solvers explicitly and how to extract diagnostic information.

/home/docs/checkouts/readthedocs.org/user_builds/py-pde/checkouts/0.50.0/examples/advanced_pdes/solver_comparison.py:30: UserWarning: `ExplicitSolver` is deprecated. Use `EulerSolver` or `RungeKuttaSolver`.
run_solver(pde.ExplicitSolver(eq), "explicit Euler"),
Diagnostic information for explicit Euler solver:
{'controller': {'mpi_run': False, 't_start': 0, 't_end': 1.0, 'profiler': {'solver': 0.3550170890000004, 'tracker': 4.817899999665087e-05, 'compilation': 0.0005167019999987588}, 'solver_start': '2025-12-15 15:14:37.345883+00:00', 'successful': True, 'stop_reason': 'Reached final time', 'solver_duration': '0:00:00.355111', 't_final': 1.0}, 'package_version': 'unknown', 'solver': {'class': 'EulerSolver', 'pde_class': 'DiffusionPDE', 'dt_statistics': {'min': inf, 'max': -inf, 'mean': 0, 'std': np.float64(nan), 'count': 0}, 'scheme': 'euler', 'dt': 0.001, 'dt_adaptive': False, 'steps': 1000, 'post_step_data': None, 'stochastic': False}}
/home/docs/checkouts/readthedocs.org/user_builds/py-pde/checkouts/0.50.0/examples/advanced_pdes/solver_comparison.py:32: UserWarning: `ExplicitSolver` is deprecated. Use `EulerSolver` or `RungeKuttaSolver`.
pde.ExplicitSolver(eq, scheme="runge-kutta", adaptive=True),
Diagnostic information for explicit, adaptive Runge-Kutta solver:
{'controller': {'mpi_run': False, 't_start': 0, 't_end': 1.0, 'profiler': {'solver': 0.017653444000004015, 'tracker': 3.425999999251417e-05, 'compilation': 0.0005396100000041315}, 'solver_start': '2025-12-15 15:14:37.702060+00:00', 'successful': True, 'stop_reason': 'Reached final time', 'solver_duration': '0:00:00.017690', 't_final': np.float64(1.0)}, 'package_version': 'unknown', 'solver': {'class': 'RungeKuttaSolver', 'pde_class': 'DiffusionPDE', 'dt_statistics': {'min': 0.001, 'max': np.float64(0.17014232769415882), 'mean': np.float64(0.08333333333333331), 'std': np.float64(0.051816802665857434), 'count': 12}, 'dt': 0.001, 'dt_adaptive': True, 'steps': 12, 'stochastic': False, 'post_step_data': None}}
Diagnostic information for implicit solver:
{'controller': {'mpi_run': False, 't_start': 0, 't_end': 1.0, 'profiler': {'solver': 1.6189871640000035, 'tracker': 3.6558999994440455e-05, 'compilation': 0.0004111709999961022}, 'solver_start': '2025-12-15 15:14:37.720505+00:00', 'successful': True, 'stop_reason': 'Reached final time', 'solver_duration': '0:00:01.619301', 't_final': 1.0}, 'package_version': 'unknown', 'solver': {'class': 'ImplicitSolver', 'pde_class': 'DiffusionPDE', 'dt_statistics': {'min': inf, 'max': -inf, 'mean': 0, 'std': np.float64(nan), 'count': 0}, 'function_evaluations': 0, 'scheme': 'implicit-euler', 'stochastic': False, 'dt': 0.001, 'dt_adaptive': False, 'steps': 1000, 'post_step_data': None}}
Diagnostic information for Crank-Nicolson solver:
{'controller': {'mpi_run': False, 't_start': 0, 't_end': 1.0, 'profiler': {'solver': 1.874377004000003, 'tracker': 5.786100000193528e-05, 'compilation': 0.00035571999999461923}, 'solver_start': '2025-12-15 15:14:39.340535+00:00', 'successful': True, 'stop_reason': 'Reached final time', 'solver_duration': '0:00:01.874656', 't_final': 1.0}, 'package_version': 'unknown', 'solver': {'class': 'CrankNicolsonSolver', 'pde_class': 'DiffusionPDE', 'dt_statistics': {'min': inf, 'max': -inf, 'mean': 0, 'std': np.float64(nan), 'count': 0}, 'function_evaluations': 0, 'stochastic': False, 'dt': 0.001, 'dt_adaptive': False, 'steps': 1000, 'post_step_data': None}}
Diagnostic information for Adam-Bashforth solver:
{'controller': {'mpi_run': False, 't_start': 0, 't_end': 1.0, 'profiler': {'solver': 0.47491094799999445, 'tracker': 3.7581000000841414e-05, 'compilation': 0.0003890099999992458}, 'solver_start': '2025-12-15 15:14:41.215975+00:00', 'successful': True, 'stop_reason': 'Reached final time', 'solver_duration': '0:00:00.474989', 't_final': 1.0}, 'package_version': 'unknown', 'solver': {'class': 'AdamsBashforthSolver', 'pde_class': 'DiffusionPDE', 'dt_statistics': {'min': inf, 'max': -inf, 'mean': 0, 'std': np.float64(nan), 'count': 0}, 'dt': 0.001, 'dt_adaptive': False, 'steps': 1000, 'post_step_data': None, 'stochastic': False}}
Diagnostic information for scipy solver:
{'controller': {'mpi_run': False, 't_start': 0, 't_end': 1.0, 'profiler': {'solver': 0.002853561999998533, 'tracker': 4.996999999917762e-05, 'compilation': 4.9078861250000045}, 'solver_start': '2025-12-15 15:14:46.606722+00:00', 'successful': True, 'stop_reason': 'Reached final time', 'solver_duration': '0:00:00.002896', 't_final': np.float64(1.0)}, 'package_version': 'unknown', 'solver': {'class': 'ScipySolver', 'pde_class': 'DiffusionPDE', 'dt': 0.001, 'steps': 61, 'stochastic': False}}
import pde
# initialize the grid, an initial condition, and the PDE
grid = pde.UnitGrid([32, 32])
field = pde.ScalarField.random_uniform(grid, -1, 1)
eq = pde.DiffusionPDE()
def run_solver(solver, label):
"""Helper function testing the solver."""
controller = pde.Controller(solver, t_range=1, tracker=None)
sol = controller.run(field, dt=1e-3)
sol.label = label + " solver"
print(f"Diagnostic information for {sol.label}:")
print(controller.diagnostics)
print()
return sol
# try different solvers
solutions = [
run_solver(pde.ExplicitSolver(eq), "explicit Euler"),
run_solver(
pde.ExplicitSolver(eq, scheme="runge-kutta", adaptive=True),
"explicit, adaptive Runge-Kutta",
),
run_solver(pde.ImplicitSolver(eq), "implicit"),
run_solver(pde.CrankNicolsonSolver(eq), "Crank-Nicolson"),
run_solver(pde.AdamsBashforthSolver(eq), "Adam-Bashforth"),
run_solver(pde.ScipySolver(eq), "scipy"),
]
# plot both fields and give the deviation as the title
deviations = [(solutions[0] - sol).fluctuations for sol in solutions]
title = "Deviation: " + ", ".join(f"{deviation:.2g}" for deviation in deviations[1:])
pde.FieldCollection(solutions).plot(title=title, arrangement=(2, 3))
Total running time of the script: (0 minutes 10.135 seconds)