Generation functions

| Home | Libraries | People | FAQ | More

### Generation functions

In the Tutorial we have learned how we can use the generation functions `make_controlled` and `make_dense_output` to create controlled and dense output stepper from a simple stepper or an error stepper. The syntax of these two functions is very simple:

    auto stepper1 = make_controlled( 1.0e-6 , 1.0e-6 , stepper_type() );
    // or with max step size limit:
    // auto stepper1 = make_controlled( 1.0e-6 , 1.0e-6 , 0.01, stepper_type() );

    auto stepper2 = make_dense_output( 1.0e-6 , 1.0e-6 , stepper_type() );

The first two parameters are the absolute and the relative error tolerances and the third parameter is the stepper. Additionally, a second version exists where additionally a maximal step size is supplied which ensures the the step size is not increased above this value. In C++03 you can infer the type from the `result_of` mechanism:

    boost::numeric::odeint::result_of::make_controlled< stepper_type >::type stepper3 = make_controlled( 1.0e-6 , 1.0e-6 , stepper_type() );
    (void)stepper3;
    boost::numeric::odeint::result_of::make_dense_output< stepper_type >::type stepper4 = make_dense_output( 1.0e-6 , 1.0e-6 , stepper_type() );
    (void)stepper4;

To use your own steppers with the `make_controlled` or `make_dense_output` you need to specialize two class templates. Suppose your steppers are called `custom_stepper`, `custom_controller` and `custom_dense_output`. Then, the first class you need to specialize is `boost::numeric::get_controller`, a meta function returning the type of the controller:

    namespace boost { namespace numeric { namespace odeint {

    template<>
    struct get_controller< custom_stepper >
    {
        typedef custom_controller type;
    };

    } } }

The second one is a factory class `boost::numeric::odeint::controller_factory` which constructs the controller from the tolerances and the stepper. In our dummy implementation this class is

    namespace boost { namespace numeric { namespace odeint {

    template<>
    struct controller_factory< custom_stepper , custom_controller >
    {
        custom_controller operator()( double abs_tol , double rel_tol , const custom_stepper & ) const
        {
            return custom_controller();
        }

        custom_controller operator()( double abs_tol , double rel_tol , double max_dt ,
                                      const custom_stepper & ) const
        {
            // version with maximal allowed step size max_dt
            return custom_controller();
        }
    };

    } } }

This is all to use the `make_controlled` mechanism. Now you can use your controller via

    auto stepper5 = make_controlled( 1.0e-6 , 1.0e-6 , custom_stepper() );

For the dense_output_stepper everything works similar. Here you have to specialize `boost::numeric::odeint::get_dense_output` and `boost::numeric::odeint::dense_output_factory`. These two classes have the same syntax as their relatives `get_controller` and `controller_factory`.

All controllers and dense-output steppers in odeint can be used with these mechanisms. In the table below you will find, which steppers is constructed from `make_controlled` or `make_dense_output` if applied on a stepper from odeint:

Table 1.7. Generation functions make_controlled( abs_error , rel_error , stepper )

Stepper | Result of make_controlled | Remarks
--- | --- | ---
`runge_kutta_cash_karp54` | `controlled_runge_kutta< runge_kutta_cash_karp54 , default_error_checker<...> >` | ax=1, adxdt=1
`runge_kutta_fehlberg78` | `controlled_runge_kutta< runge_kutta_fehlberg78 , default_error_checker<...> >` | ax=1, adxdt=1
`runge_kutta_dopri5` | `controlled_runge_kutta< runge_kutta_dopri5 , default_error_checker<...> >` | a x=1, adxdt=1
`rosenbrock4` | `rosenbrock4_controlled< rosenbrock4 >` | -

Table 1.8. Generation functions make_dense_output( abs_error , rel_error , stepper )

Stepper | Result of make_dense_output | Remarks
--- | --- | ---
`runge_kutta_dopri5` | `dense_output_runge_kutta< controlled_runge_kutta< runge_kutta_dopri5 , default_error_checker<...> > >` | a x=1, adxdt=1
`rosenbrock4` | `rosenbrock4_dense_output< rosenbrock4_controller< rosenbrock4 > >` | -