Source code for riccati.stepsize

import numpy as np

[docs]def choose_nonosc_stepsize(info, x0, h, epsh = 0.2): """ Chooses the stepsize for spectral Chebyshev steps, based on the variation of 1/w, the approximate timescale over which the solution changes. If over the suggested interval h 1/w changes by a fraction of :math:`\pm``epsh` or more, the interval is halved, otherwise it's accepted. Parameters ---------- info: Solverinfo object Solverinfo object which is used to retrieve Solverinfo.xp, the (p+1) Chebyshev nodes used for interpolation to determine the stepsize. x0: float Current value of the independent variable. h: float Initial estimate of the stepsize. epsh: float Tolerance parameter defining how much 1/w(x) is allowed to change over the course of the step. Returns ------- h: float Refined stepsize over which 1/w(x) does not change by more than epsh/w(x). """ xscaled = x0 + h/2 + h/2*info.xp ws = info.w(xscaled) if max(ws) > (1 + epsh)/abs(h): return choose_nonosc_stepsize(info, x0, h/2, epsh = epsh) else: return h
[docs]def choose_osc_stepsize(info, x0, h, epsh = 1e-12): """ Chooses the stepsize `h` over which the functions w(x), g(x) can be represented sufficiently accurately. Evaluations of w(x) and g(x) at (p+1) Chebyshev nodes (given by `info.xp`) between [`x0`, `x0+h`] are used to infer w(x), g(x) values at p points halfway between the (p+1) nodes on the half circle, .. math:: x_{p,\mathrm{interp}} = \cos\left( \\frac{\pi(2n+1)}{2p} \\right), \quad n = 0, 1, \ldots, p-1. These target nodes given by `info.xpinterp`. The same (p+1) points will then be used to compute a Riccati step. The interpolated values are then compared to the actual values of w(x), g(x) at `info.xpinterp`. If the largest relative error in w, g exceeds `epsh`, `h` is halved. Parameters ---------- info: Solverinfo object `Solverinfo` object used for two purposes: `info.xpinterp`, `info.xp` are looked up to determine the source and target points to determine whether Chebyshev interpolation of w(x), g(x) is accurate enough over the step; and `info.wn`, `info.gn` may be used to read off the w, g values at the source points. x0: float Current value of the independent variable. h: float Initial estimate of the stepsize. epsh: float Tolerance parameter defining the maximum relative error Chebyshev interpolation of w, g is allowed to have over the course of the proposed step [`x0`, `x0+h`]. Returns ------- h: float Refined stepsize over which Chebyshev interpolation of w, g has a relative error no larger than epsh. """ w, g, L = info.w, info.g, info.L t = x0 + h/2 + h/2*info.xpinterp s = x0 + h/2 + h/2*info.xp if info.p == info.n: info.wn = w(s) info.gn = g(s) ws = info.wn gs = info.gn else: info.wn = w(x0 + h/2 + h/2*info.xn) info.gn = g(x0 + h/2 + h/2*info.xn) ws = w(s) gs = g(s) wana = w(t) west = L @ ws gana = g(t) gest = L @ gs maxwerr = max(np.abs((west - wana)/wana)) maxgerr = max(np.abs((gest - gana)/gana)) maxerr = max(maxwerr, maxgerr) if maxerr > epsh: return choose_osc_stepsize(info, x0, h*min(0.7, 0.9*(epsh/maxerr)**(1/(info.p-1))), epsh = epsh) else: return h
#TODO: what if h is too small to begin with?