Source code for pathsim.solvers.esdirk32
########################################################################################
##
## EMBEDDED DIAGONALLY IMPLICIT RUNGE KUTTA METHOD
## (solvers/esdirk32.py)
##
## Milan Rother 2024
##
########################################################################################
# IMPORTS ==============================================================================
from ._rungekutta import DiagonallyImplicitRungeKutta
# SOLVERS ==============================================================================
[docs]
class ESDIRK32(DiagonallyImplicitRungeKutta):
"""Four-stage, 3rd order ESDIRK method with embedded 2nd order error
estimate. L-stable and stiffly accurate.
Characteristics
---------------
* Order: 3 (propagating) / 2 (embedded)
* Stages: 4 (1 explicit, 3 implicit)
* Adaptive timestep
* L-stable, stiffly accurate
* Stage order 2 (:math:`\\gamma = 1/2`)
Note
----
The cheapest adaptive implicit Runge-Kutta solver in this library,
yet remarkably robust. L-stability and stiff accuracy guarantee that
high-frequency parasitic modes are fully damped regardless of
timestep, and the optimal stage order of 2 (from :math:`\\gamma = 1/2`)
minimises order reduction on stiff problems. Three implicit stages
per step keeps the cost well below ``ESDIRK43`` while still providing
adaptive step-size control. For even lower per-step cost the
``GEAR`` multistep solvers require only one implicit solve per step.
Also used internally as the startup method for ``GEAR`` solvers.
References
----------
.. [1] Kennedy, C. A., & Carpenter, M. H. (2019). "Diagonally implicit
Runge-Kutta methods for stiff ODEs". Applied Numerical
Mathematics, 146, 221-244.
:doi:`10.1016/j.apnum.2019.07.008`
.. [2] Hairer, E., & Wanner, G. (1996). "Solving Ordinary Differential
Equations II: Stiff and Differential-Algebraic Problems". Springer
Series in Computational Mathematics, Vol. 14.
:doi:`10.1007/978-3-642-05221-7`
"""
def __init__(self, *solver_args, **solver_kwargs):
super().__init__(*solver_args, **solver_kwargs)
#number of stages in RK scheme
self.s = 4
#order of scheme and embedded method
self.n = 3
self.m = 2
#flag adaptive timestep solver
self.is_adaptive = True
#intermediate evaluation times
self.eval_stages = [0.0, 1.0, 3/2, 1.0]
#butcher table
self.BT = {
0: None, #explicit first stage
1: [1/2, 1/2],
2: [5/8, 3/8, 1/2],
3: [7/18, 1/3, -2/9, 1/2]
}
#coefficients for truncation error estimate
self.TR = [-1/9, -1/6, -2/9, 1/2]