def integrate_auto_switch(odes, kw, x, y0, params=(), **kwargs):
    """ Auto-switching between formulations of ODE system.

    In case one has a formulation of a system of ODEs which is preferential in
    the beginning of the integration, this function allows the user to run the
    integration with this system where it takes a user-specified maximum number
    of steps before switching to another formulation (unless final value of the
    independent variables has been reached). Number of systems used i returned
    as ``nsys`` in info dict.

    Parameters
    ----------
    odes : iterable of :class:`OdeSy` instances
    kw : dict mapping kwarg to iterables of same legnth as ``odes``
    x : array_like
    y0 : array_like
    params : array_like
    \*\*kwargs:
        See :meth:`ODESys.integrate`

    Notes
    -----
    Plays particularly well with :class:`symbolic.TransformedSys`.

    """
    x_arr = np.asarray(x)
    if x_arr.shape[-1] > 2:
        raise NotImplementedError("Only adaptive support return_on_error for now")
    multimode = False if x_arr.ndim < 2 else x_arr.shape[0]
    nfo_keys = ('nfev', 'njev', 'time_cpu', 'time_wall')

    next_autonomous = getattr(odes[0], 'autonomous_interface', False) == True  # noqa (np.True_)
    if multimode:
        tot_x = [np.array([0] if next_autonomous else [x[_][0]]) for _ in range(multimode)]
        tot_y = [np.asarray([y0[_]]) for _ in range(multimode)]
        tot_nfo = [defaultdict(int) for _ in range(multimode)]
        glob_x = [_[0] for _ in x] if next_autonomous else [0.0]*multimode
    else:
        tot_x, tot_y, tot_nfo = np.array([0 if next_autonomous else x[0]]), np.asarray([y0]), defaultdict(int)
        glob_x = x[0] if next_autonomous else 0.0

    for oi in range(len(odes)):
        if oi < len(odes) - 1:
            next_autonomous = getattr(odes[oi+1], 'autonomous_interface', False) == True  # noqa (np.True_)
        _int_kw = kwargs.copy()
        for k, v in kw.items():
            _int_kw[k] = v[oi]
        res = odes[oi].integrate(x, y0, params, **_int_kw)

        if multimode:
            for idx in range(multimode):
                tot_x[idx] = np.concatenate((tot_x[idx], res[idx].xout[1:] + glob_x[idx]))
                tot_y[idx] = np.concatenate((tot_y[idx], res[idx].yout[1:, :]))
                for k in nfo_keys:
                    if k in res[idx].info:
                        tot_nfo[idx][k] += res[idx].info[k]
                tot_nfo[idx]['success'] = res[idx].info['success']
        else:
            tot_x = np.concatenate((tot_x, res.xout[1:] + glob_x))
            tot_y = np.concatenate((tot_y, res.yout[1:, :]))
            for k in nfo_keys:
                if k in res.info:
                    tot_nfo[k] += res.info[k]
            tot_nfo['success'] = res.info['success']

        if multimode:
            if all([r.info['success'] for r in res]):
                break
        else:
            if res.info['success']:
                break
        if oi < len(odes) - 1:
            if multimode:
                _x, y0 = [], []
                for idx in range(multimode):
                    _x.append(_new_x(res[idx].xout, x[idx], next_autonomous))
                    y0.append(res[idx].yout[-1, :])
                    if next_autonomous:
                        glob_x[idx] += res[idx].xout[-1]
                x = _x
            else:
                x = _new_x(res.xout, x, next_autonomous)
                y0 = res.yout[-1, :]
                if next_autonomous:
                    glob_x += res.xout[-1]
    if multimode:  # don't return defaultdict
        tot_nfo = [dict(nsys=oi+1, **_nfo) for _nfo in tot_nfo]
        return [Result(tot_x[idx], tot_y[idx], res[idx].params, tot_nfo[idx], odes[0])
                for idx in range(len(res))]
    else:
        tot_nfo = dict(nsys=oi+1, **tot_nfo)
        return Result(tot_x, tot_y, res.params, tot_nfo, odes[0])
def integrate_auto_switch ( odes , kw , x , y0 , params = ( ) , ** kwargs ) : x_arr = np . asarray ( x ) if x_arr . shape [ - 1 ] > 2 : raise NotImplementedError ( "Only adaptive support return_on_error for now" ) multimode = False if x_arr . ndim < 2 else x_arr . shape [ 0 ] nfo_keys = ( 'nfev' , 'njev' , 'time_cpu' , 'time_wall' ) next_autonomous = getattr ( odes [ 0 ] , 'autonomous_interface' , False ) == True if multimode : tot_x = [ np . array ( [ 0 ] if next_autonomous else [ x [ _ ] [ 0 ] ] ) for _ in range ( multimode ) ] tot_y = [ np . asarray ( [ y0 [ _ ] ] ) for _ in range ( multimode ) ] tot_nfo = [ defaultdict ( int ) for _ in range ( multimode ) ] glob_x = [ _ [ 0 ] for _ in x ] if next_autonomous else [ 0.0 ] * multimode else : tot_x , tot_y , tot_nfo = np . array ( [ 0 if next_autonomous else x [ 0 ] ] ) , np . asarray ( [ y0 ] ) , defaultdict ( int ) glob_x = x [ 0 ] if next_autonomous else 0.0 for oi in range ( len ( odes ) ) : if oi < len ( odes ) - 1 : next_autonomous = getattr ( odes [ oi + 1 ] , 'autonomous_interface' , False ) == True _int_kw = kwargs . copy ( ) for k , v in kw . items ( ) : _int_kw [ k ] = v [ oi ] res = odes [ oi ] . integrate ( x , y0 , params , ** _int_kw ) if multimode : for idx in range ( multimode ) : tot_x [ idx ] = np . concatenate ( ( tot_x [ idx ] , res [ idx ] . xout [ 1 : ] + glob_x [ idx ] ) ) tot_y [ idx ] = np . concatenate ( ( tot_y [ idx ] , res [ idx ] . yout [ 1 : , : ] ) ) for k in nfo_keys : if k in res [ idx ] . info : tot_nfo [ idx ] [ k ] += res [ idx ] . info [ k ] tot_nfo [ idx ] [ 'success' ] = res [ idx ] . info [ 'success' ] else : tot_x = np . concatenate ( ( tot_x , res . xout [ 1 : ] + glob_x ) ) tot_y = np . concatenate ( ( tot_y , res . yout [ 1 : , : ] ) ) for k in nfo_keys : if k in res . info : tot_nfo [ k ] += res . info [ k ] tot_nfo [ 'success' ] = res . info [ 'success' ] if multimode : if all ( [ r . info [ 'success' ] for r in res ] ) : break else : if res . info [ 'success' ] : break if oi < len ( odes ) - 1 : if multimode : _x , y0 = [ ] , [ ] for idx in range ( multimode ) : _x . append ( _new_x ( res [ idx ] . xout , x [ idx ] , next_autonomous ) ) y0 . append ( res [ idx ] . yout [ - 1 , : ] ) if next_autonomous : glob_x [ idx ] += res [ idx ] . xout [ - 1 ] x = _x else : x = _new_x ( res . xout , x , next_autonomous ) y0 = res . yout [ - 1 , : ] if next_autonomous : glob_x += res . xout [ - 1 ] if multimode : tot_nfo = [ dict ( nsys = oi + 1 , ** _nfo ) for _nfo in tot_nfo ] return [ Result ( tot_x [ idx ] , tot_y [ idx ] , res [ idx ] . params , tot_nfo [ idx ] , odes [ 0 ] ) for idx in range ( len ( res ) ) ] else : tot_nfo = dict ( nsys = oi + 1 , ** tot_nfo ) return Result ( tot_x , tot_y , res . params , tot_nfo , odes [ 0 ] )
Auto-switching between formulations of ODE system.

    In case one has a formulation of a system of ODEs which is preferential in
    the beginning of the integration, this function allows the user to run the
    integration with this system where it takes a user-specified maximum number
    of steps before switching to another formulation (unless final value of the
    independent variables has been reached). Number of systems used i returned
    as ``nsys`` in info dict.

    Parameters
    ----------
    odes : iterable of :class:`OdeSy` instances
    kw : dict mapping kwarg to iterables of same legnth as ``odes``
    x : array_like
    y0 : array_like
    params : array_like
    \*\*kwargs:
        See :meth:`ODESys.integrate`

    Notes
    -----
    Plays particularly well with :class:`symbolic.TransformedSys`.