Boost
C++ Libraries
...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
This is an older version of Boost and was released in 2023. The current version is 1.89.0.
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 |
|---|---|---|
|
|
|
ax=1, adxdt=1 |
|
|
|
ax=1, adxdt=1 |
|
|
|
a x=1, adxdt=1 |
|
|
|
- |
Table 1.8. Generation functions make_dense_output( abs_error , rel_error , stepper )
|
Stepper |
Result of make_dense_output |
Remarks |
|---|---|---|
|
|
|
a x=1, adxdt=1 |
|
|
|
- |