The basic idea is that
- You use the estimated error given to you (cheaply) by the embedded methods;
- You use a metric to define acceptance using a user-defined relative and absolute tolerance;
- Based on the order properties of the code and this metric, a new step size is computed;
- You avoid large differences in step sizes from one step to the next by limiting the maximum increase and maximum decrease.
From "Solving Ordinary Differential Equations, part I" by Hairer, Norsett and Wanner :
For two approximations to the solution $y_{1i}$ (using the lower order) and $\hat{y}_{1i}$ (using the higher order), we want the error to satisfy (componentwise) $$|y_{1i} - \hat{y}_{1i}| \leq sc_i|, \quad sc_i = Atol_i + \max\left(|y_{0i}|,|y_{1i}|\right)\cdot Rtol_i.$$
As a measure of the error, one takes $$err = \sqrt{\frac{1}{n}\sum_{i=1}^n\left(\frac{y_{1i}-\hat{y}_{1i}}{sc_i}\right)^{2}}$$ and this value is compared to one. From the expected error behaviour $err \propto C\cdot h^{q+1}$ the optimal step size is obtained as $$h_{\text{opt}} = h\cdot\left(\frac{1}{err}\right)^{\frac{1}{q+1}}$$ where $h$ is the previous step size.
Typically, one would add a kind of safety factor so that the probability of having selected a good step size is increased. Typically this safety factor $fac$ is taken $fac = 0.8$ or some power of the order like $fac = \left(0.25\right)^{\frac{1}{q+1}}$ so that $$h_{\text{opt}} = fac\cdot h\cdot\left(\frac{1}{err}\right)^{\frac{1}{q+1}}$$ .
As a second measure of safety, one wants to prohibit the stepsize to vary too much from one step to the next. Typically, one limits the new stepsize to be less than a factor five of the previous stepsize. And in some codes, a stepsize increase is forbidden if the previous step was rejected (so if in a previous step, $h$ was decreased, it can only increase again if a step with that step size is accepted).
The initial step size for the algorithm can be set by the user or it could be estimated using a procedure based on the order of the method. Hindmarsch and Shampine have developed methods to do so.
ode45
and SciPy'srk45
. I get that there might be more than one option, in that case I am interested in the most common way for dopri54 (what is the consensus). I could have asked the question. If you needed to implement this dopir5, how would YOU have decided the step sizes $\endgroup$