PrevUpHomeNext

Using boost::range

Most steppers in odeint also accept the state give as a range. A range is sequence of values modeled by a range concept. See Boost.Range for an overview over existing concepts and examples of ranges. This means that the state_type of the stepper need not necessarily be used to call the do_step method.

One use-case for Boost.Range in odeint has been shown in Chaotic System where the state consists of two parts: one for the original system and one for the perturbations. The ranges are used to initialize (solve) only the system part where the perturbation part is not touched, that is a range consisting only of the system part is used. After that the complete state including the perturbations is solved.

Another use case is a system consisting of coupled units where you want to initialize each unit separately with the ODE of the uncoupled unit. An example is a chain of coupled van-der-Pol-oscillators which are initialized uniformly from the uncoupled van-der-Pol-oscillator. Then you can use Boost.Range to solve only one individual oscillator in the chain.

In short, you can Boost.Range to use one state within two system functions which expect states with different sizes.

An example was given in the Chaotic System tutorial. Using Boost.Range usually means that your system function needs to adapt to the iterators of Boost.Range. That is, your function is called with a range and you need to get the iterators from that range. This can easily be done. You have to implement your system as a class or a struct and you have to templatize the operator(). Then you can use the range_iterator-meta function and boost::begin and boost::end to obtain the iterators of your range:

class sys
{
    template< class State , class Deriv >
    void operator()( const State &x_ , Deriv &dxdt_ , double t ) const
    {
         typename boost::range_iterator< const State >::type x = boost::begin( x_ );
         typename boost::range_iterator< Deriv >::type dxdt = boost::begin( dxdt_ );

         // fill dxdt
    }
};

If your range is a random access-range you can also apply the bracket operator to the iterator to access the elements in the range:

class sys
{
    template< class State , class Deriv >
    void operator()( const State &x_ , Deriv &dxdt_ , double t ) const
    {
         typename boost::range_iterator< const State >::type x = boost::begin( x_ );
         typename boost::range_iterator< Deriv >::type dxdt = boost::begin( dxdt_ );

         dxdt[0] = f1( x[0] , x[1] );
         dxdt[1] = f2( x[0] , x[1] );
    }
};

The following two tables show which steppers and which algebras are compatible with Boost.Range.

Table 1.9. Steppers supporting Boost.Range

Stepper

adams_bashforth_moulton

bulirsch_stoer_dense_out

bulirsch_stoer

controlled_runge_kutta

dense_output_runge_kutta

euler

explicit_error_generic_rk

explicit_generic_rk

rosenbrock4_controller

rosenbrock4_dense_output

rosenbrock4

runge_kutta4_classic

runge_kutta4

runge_kutta_cash_karp54_classic

runge_kutta_cash_karp54

runge_kutta_dopri5

runge_kutta_fehlberg78

symplectic_euler

symplectic_rkn_sb3a_mclachlan


Table 1.10. Algebras supporting Boost.Range

algebra

range_algebra

thrust_algebra



PrevUpHomeNext