scijit.integrate.OdeSolution

class scijit.integrate.OdeSolution(*args, **kwargs)

Bases: OdeSolution

Continuous solution over the integrated span, res.sol.

solve_ivp(..., dense_output=True) returns one as res.sol, which is how most callers meet it. Building one by hand is for a step history obtained some other way.

sol(t) evaluates it, from Python and from inside @njit. A float gives (n_states,); a float64 array of k times gives (n_states, k). A Python list raises; wrap it in np.array.

Parameters:
t, hfloat64 array, shape (s,)

Start time and signed step size of each accepted step.

ysfloat64 array, shape (s, n)

State at the start of each accepted step.

Cfloat64 array, shape (s, 7, n)

Interpolation coefficients per step.

methodint

METHOD_RK45, METHOD_RK23 or METHOD_DOP853, the method the history was produced with. A mismatch reads the coefficients under the wrong polynomial and returns wrong values silently.

Attributes:
tfloat64 array, shape (s,)

Start time of each accepted step.

hfloat64 array, shape (s,)

Signed step size of each accepted step.

ysfloat64 array, shape (s, n)

State at the start of each accepted step.

Cfloat64 array, shape (s, 7, n)

Interpolation coefficients per step.

methodint

The method the history was produced with.

Raises:
ValueError

If t is not strictly increasing or strictly decreasing, or if h, ys and C do not all carry one entry per time stamp. A two-entry t whose ends are equal is a zero-length span and is accepted.

See also

scipy.integrate._ivp.common.OdeSolution

The scipy routine this mirrors.

Notes

The constructor takes different arguments from scipy’s. scipy builds one as OdeSolution(ts, interpolants, alt_segment=False) from a list of DenseOutput objects; this one takes a step history as five arrays, and no parameter name is shared.

A constructor default is Python-only. Inside @njit every argument is passed explicitly, so a scipy-shaped OdeSolution(ts, interpolants), which leaves alt_segment to its default, has no compiled spelling.

The attribute sets are disjoint. A scipy instance carries ts, interpolants, n_segments, t_min, t_max, ascending, side and ts_sorted. This one carries t, h, ys, C and method.

sol(t) takes a float or a 1-D float64 array. scipy runs np.asarray(t) and accepts any array_like, a list included. On an empty array sol(np.array([])) returns shape (n, 0) and scipy raises ValueError('need at least one array to concatenate').

One scipy class covers every method. Here solve_ivp(method='LSODA', dense_output=True) returns a different type, _LsodaSolution built from a Nordsieck history, and a complex y0 returns a third, _OdeSolutionC.

Examples

>>> import numpy as np
>>> from numba import njit
>>> import scijit.integrate as si
>>> from scijit.integrate import OdeSolution
>>> @njit
... def rhs(t, y):
...     out = np.empty(2)
...     out[0] = y[1]
...     out[1] = -4.0 * y[0]
...     return out
>>> res = si.solve_ivp(rhs, (0.0, 1.0), np.array([1.0, 0.0]),
...                    'RK45', None, True)
>>> isinstance(res.sol, OdeSolution)
True
>>> res.sol(0.5)
array([ 0.54038693, -1.68337531])
__init__(t, h, ys, C, method)

Validate the step history and store it. Every argument is required; see the class docstring.

Methods

__init__(t, h, ys, C, method)

Validate the step history and store it.

ev(tt)

Evaluate at an array of times.

ev_one(tt)

Evaluate at a single time.

Attributes

class_type = jitclass.OdeSolution#7fad13b53250<t:array(float64, 1d, A),h:array(float64, 1d, A),ys:array(float64, 2d, A),C:array(float64, 3d, A),method:int64>