c++boostodeintboost-units

Is boost odeint supporting dimensional analysis via Boost.Units?


I was trying to implement a simple ode to test whether boost.odeint is supporting the usage of boost.units. However my example is failing at compilation. Is it my code, or doesn't boost.odeint support boost.Units for dimensional analysis?

#include<boost/units/systems/si.hpp>
#include<boost/numeric/odeint.hpp>

typedef boost::units::quantity<boost::units::si::length,double> state_type;
typedef boost::units::quantity<velocity,double> dev_type;
typedef boost::units::quantity<boost::units::si::time,double> time_type;


using namespace boost::units::si;

void exponential_decay(const state_type &x, dev_type &dxdt, time_type t){
    dxdt = -0.0001*x/second;
}

int main(){
    state_type startValue = 10*meter;

    using namespace boost::numeric::odeint;
    auto steps = integrate(exponential_decay, startValue, 0.0*second,
            10.0*second, 0.1*second);

    return 0;
}

Solution

  • Use boost::fusion to fix the problem.

    #include <iostream>
    #include <vector>
    
    #include <boost/numeric/odeint.hpp>
    #include <boost/numeric/odeint/algebra/fusion_algebra.hpp>
    #include <boost/numeric/odeint/algebra/fusion_algebra_dispatcher.hpp>
    
    #include <boost/units/systems/si/length.hpp>
    #include <boost/units/systems/si/time.hpp>
    #include <boost/units/systems/si/velocity.hpp>
    #include <boost/units/systems/si/acceleration.hpp>
    #include <boost/units/systems/si/io.hpp>
    
    #include <boost/fusion/container.hpp>
    
    using namespace std;
    using namespace boost::numeric::odeint;
    namespace fusion = boost::fusion;
    namespace units = boost::units;
    namespace si = boost::units::si;
    
    typedef units::quantity< si::time , double > time_type;
    typedef units::quantity< si::length , double > length_type;
    typedef units::quantity< si::velocity , double > velocity_type;
    typedef units::quantity< si::acceleration , double > acceleration_type;
    typedef units::quantity< si::frequency , double > frequency_type;
    
    typedef fusion::vector< length_type  > state_type;
    typedef fusion::vector< velocity_type > deriv_type;
    
    void exponential_decay( const state_type &x , deriv_type &dxdt , time_type t )
    {
        fusion::at_c< 0 >( dxdt ) = (-0.0001/si::second)* fusion::at_c< 0 >( x );
    }
    
    void observer(const state_type &x,const time_type &t )
    {
    }
    
    int main( int argc , char**argv )
    {
        typedef runge_kutta_dopri5< state_type , double , deriv_type , time_type > stepper_type;
    
        state_type startValue( 1.0 * si::meter );
    
        auto steps=integrate_adaptive(
            make_dense_output( 1.0e-6 , 1.0e-6 , stepper_type()),
            exponential_decay,
            startValue , 0.0 * si::second , 100.0 * si::second , 0.1 * si::second , observer);
    
        std::cout<<"steps: "<<steps<<std::endl;
    
        return 0;
    }