odeint is a header-only library, no linking against pre-compiled code is required. It can be included by #include <boost/numeric/odeint.hpp> which includes all headers of the library. All functions and classes from odeint live in the namespace using namespace boost::numeric::odeint; It is also possible to include only parts of the library. This is the recommended way since it saves a lot of compilation time. `#include <boost/numeric/odeint/stepper/XYZ.hpp>` - the include path for all steppers, XYZ is a placeholder for a stepper.`#include <boost/numeric/odeint/algebra/XYZ.hpp>` - all algebras.`#include <boost/numeric/odeint/util/XYZ.hpp>` - the utility functions like`is_resizeable` ,`same_size` , or`resize` .`#include <boost/numeric/odeint/integrate/XYZ.hpp>` - the integrate routines.`#include <boost/numeric/odeint/iterator/XYZ.hpp>` - the range and iterator functions.`#include <boost/numeric/odeint/external/XYZ.hpp>` - any binders to external libraries.
Imaging, you want to numerically integrate a harmonic oscillator with friction. The equations of motion are given by /* The type of container used to hold the state vector */ typedef std::vector< double > state_type; const double gam = 0.15; /* The rhs of x' = f(x) */ void harmonic_oscillator( const state_type &x , state_type &dxdt , const double /* t */ ) { dxdt[0] = x[1]; dxdt[1] = -x[0] - gam*x[1]; } Here we chose Now, we have to define the initial state from which the integration should start: state_type x(2); x[0] = 1.0; // start at x=1.0, p=0.0 x[1] = 0.0; For the integration itself we'll use the size_t steps = integrate( harmonic_oscillator , x , 0.0 , 10.0 , 0.1 ); The integrate function expects as parameters the rhs of the ode as defined above, the initial state It is also possible to represent the ode system as a class. The rhs must then be implemented as a functor - a class with an overloaded function call operator: /* The rhs of x' = f(x) defined as a class */ class harm_osc { double m_gam; public: harm_osc( double gam ) : m_gam(gam) { } void operator() ( const state_type &x , state_type &dxdt , const double /* t */ ) { dxdt[0] = x[1]; dxdt[1] = -x[0] - m_gam*x[1]; } }; which can be used via harm_osc ho(0.15); steps = integrate( ho , x , 0.0 , 10.0 , 0.1 ); In order to observe the solution during the integration steps all you have to do is to provide a reasonable observer. An example is struct push_back_state_and_time { std::vector< state_type >& m_states; std::vector< double >& m_times; push_back_state_and_time( std::vector< state_type > &states , std::vector< double > × ) : m_states( states ) , m_times( times ) { } void operator()( const state_type &x , double t ) { m_states.push_back( x ); m_times.push_back( t ); } }; which stores the intermediate steps in a container. Note, the argument structure of the ()-operator: odeint calls the observer exactly in this way, providing the current state and time. Now, you only have to pass this container to the integration function: vector<state_type> x_vec; vector<double> times; steps = integrate( harmonic_oscillator , x , 0.0 , 10.0 , 0.1 , push_back_state_and_time( x_vec , times ) ); /* output */ for( size_t i=0; i<=steps; i++ ) { cout << times[i] << '\t' << x_vec[i][0] << '\t' << x_vec[i][1] << '\n'; } That is all. You can use functional libraries like Boost.Lambda or Boost.Phoenix to ease the creation of observer functions. The full cpp file for this example can be found here: harmonic_oscillator.cpp |

pBook > Solver:: Integrator:: C++ >