Click here to Skip to main content
15,895,084 members
Articles / Programming Languages / C++

Solving ordinary differential equations in C++

Rate me:
Please Sign up or sign in to vote.
4.82/5 (36 votes)
19 Oct 2011CPOL8 min read 312.4K   3.8K   97  
This article explains a framework for solving ordinary differential equations, which is based on template metaprogramming.
/* Boost odeint/detail/accumulators.hpp header file
 
 Copyright 2009 Karsten Ahnert
 Copyright 2009 Mario Mulansky
 Copyright 2009 Andre Bergner
 
 Some algebraic operations for iterators

 Distributed under the Boost Software License, Version 1.0.
 (See accompanying file LICENSE_1_0.txt or
 copy at http://www.boost.org/LICENSE_1_0.txt)
*/

#ifndef BOOST_NUMERIC_ODEINT_DETAIL_ACCUMULATORS_HPP
#define BOOST_NUMERIC_ODEINT_DETAIL_ACCUMULATORS_HPP

#include <cmath>

#include <iostream>

namespace boost {
namespace numeric {
namespace odeint {
namespace detail {
namespace it_algebra { // iterator algebra


    // computes y += alpha * x1
    template <
        class InOutIterator ,
        class InputIterator ,
        class T
        >
    void increment(
                   InOutIterator first1 ,
                   InOutIterator last1 ,
                   InputIterator first2 ,
                   T alpha
                   )
    {
        while( first1 != last1 )
            (*first1++) += alpha * (*first2++);
    }


    // computes y = alpha1 * ( x1 + x2 + alpha2*x3 )
    template <
        class OutputIterator ,
        class InputIterator1 ,
        class InputIterator2 ,
        class InputIterator3 ,
        class T
        >
    void increment_sum_sum(
                           OutputIterator first1 ,
                           OutputIterator last1 ,
                           InputIterator1 first2 ,
                           InputIterator2 first3 ,
                           InputIterator3 first4 ,
                           T alpha1 ,
                           T alpha2
                           )
    {
        while( first1 != last1 )
            (*first1++) += alpha1 *
                ( (*first2++) + (*first3++) + alpha2 * (*first4++) );
    }




    // computes y = alpha1*x1 + alpha2*x2
    template <
        class OutputIterator ,
        class InputIterator1 ,
        class InputIterator2 ,
        class T
        >
    inline void scale_sum( OutputIterator y_begin ,
                           OutputIterator y_end ,
                           T alpha1 ,
                           InputIterator1 x1_begin ,
                           T alpha2 ,
                           InputIterator2 x2_begin )
    {
        while( y_begin != y_end )
        {
            (*y_begin++) = alpha1 * (*x1_begin++) +
                alpha2 * (*x2_begin++);
        }
    }


    // computes y = x1 + alpha2*x2 + alpha3*x3
    template <
        class OutputIterator ,
        class InputIterator1 ,
        class InputIterator2 ,
        class InputIterator3 ,
        class T
        >
    inline void scale_sum( OutputIterator y_begin ,
                           OutputIterator y_end ,
                           T alpha1 ,
                           InputIterator1 x1_begin ,
                           T alpha2 ,
                           InputIterator2 x2_begin ,
                           T alpha3 ,
                           InputIterator3 x3_begin )
    {
        while( y_begin != y_end )
            (*y_begin++) = 
                alpha1 * (*x1_begin++) + 
                alpha2 * (*x2_begin++) + 
                alpha3 * (*x3_begin++);
    }

    // computes y = x1 + alpha2*x2 + alpha3*x3 + alpha4*x4
    template <
        class OutputIterator ,
        class InputIterator1 ,
        class InputIterator2 ,
        class InputIterator3 ,
        class InputIterator4 ,
        class T
        >
    inline void scale_sum( OutputIterator y_begin ,
                           OutputIterator y_end ,
                           T alpha1 ,
                           InputIterator1 x1_begin ,
                           T alpha2 ,
                           InputIterator2 x2_begin ,
                           T alpha3 ,
                           InputIterator3 x3_begin ,
                           T alpha4 ,
                           InputIterator4 x4_begin )
    {
        while( y_begin != y_end )
            (*y_begin++) = 
                alpha1 * (*x1_begin++) + 
                alpha2 * (*x2_begin++) + 
                alpha3 * (*x3_begin++) +
                alpha4 * (*x4_begin++);
    }

    // computes y = x1 + alpha2*x2 + alpha3*x3 + alpha4*x4 + alpha5*x5
    template <
        class OutputIterator ,
        class InputIterator1 ,
        class InputIterator2 ,
        class InputIterator3 ,
        class InputIterator4 ,
        class InputIterator5 ,
        class T
        >
    inline void scale_sum( OutputIterator y_begin ,
                           OutputIterator y_end ,
                           T alpha1 ,
                           InputIterator1 x1_begin ,
                           T alpha2 ,
                           InputIterator2 x2_begin ,
                           T alpha3 ,
                           InputIterator3 x3_begin ,
                           T alpha4 ,
                           InputIterator4 x4_begin ,
                           T alpha5 ,
                           InputIterator5 x5_begin )
    {
        while( y_begin != y_end )
            (*y_begin++) = 
                alpha1 * (*x1_begin++) + 
                alpha2 * (*x2_begin++) + 
                alpha3 * (*x3_begin++) +
                alpha4 * (*x4_begin++) +
                alpha5 * (*x5_begin++);
    }


    // computes y = x1 + alpha2*x2 + alpha3*x3 + alpha4*x4 + alpha5*x5
    // + alpha6*x6
    template <
        class OutputIterator ,
        class InputIterator1 ,
        class InputIterator2 ,
        class InputIterator3 ,
        class InputIterator4 ,
        class InputIterator5 ,
        class InputIterator6 ,
        class T
        >
    inline void scale_sum( OutputIterator y_begin ,
                           OutputIterator y_end ,
                           T alpha1 ,
                           InputIterator1 x1_begin ,
                           T alpha2 ,
                           InputIterator2 x2_begin ,
                           T alpha3 ,
                           InputIterator3 x3_begin ,
                           T alpha4 ,
                           InputIterator4 x4_begin ,
                           T alpha5 ,
                           InputIterator5 x5_begin ,
                           T alpha6 ,
                           InputIterator6 x6_begin )
    {
        while( y_begin != y_end )
            (*y_begin++) = 
                alpha1 * (*x1_begin++) + 
                alpha2 * (*x2_begin++) + 
                alpha3 * (*x3_begin++) +
                alpha4 * (*x4_begin++) +
                alpha5 * (*x5_begin++) +
                alpha6 * (*x6_begin++);
    }


    // computes y = x1 + alpha2*x2 + alpha3*x3 + alpha4*x4 + alpha5*x5
    // + alpha6*x6 + alpha7*x7
    template <
        class OutputIterator ,
        class InputIterator1 ,
        class InputIterator2 ,
        class InputIterator3 ,
        class InputIterator4 ,
        class InputIterator5 ,
        class InputIterator6 ,
        class InputIterator7 ,
        class T
        >
    inline void scale_sum( OutputIterator y_begin ,
                           OutputIterator y_end ,
                           T alpha1 ,
                           InputIterator1 x1_begin ,
                           T alpha2 ,
                           InputIterator2 x2_begin ,
                           T alpha3 ,
                           InputIterator3 x3_begin ,
                           T alpha4 ,
                           InputIterator4 x4_begin ,
                           T alpha5 ,
                           InputIterator5 x5_begin ,
                           T alpha6 ,
                           InputIterator6 x6_begin ,
                           T alpha7 ,
                           InputIterator7 x7_begin )

    {
        while( y_begin != y_end )
            (*y_begin++) = 
                alpha1 * (*x1_begin++) + 
                alpha2 * (*x2_begin++) + 
                alpha3 * (*x3_begin++) +
                alpha4 * (*x4_begin++) +
                alpha5 * (*x5_begin++) +
                alpha6 * (*x6_begin++) +
                alpha7 * (*x7_begin++) ;
    }



    // computes y = x1 + alpha2*x2 + alpha3*x3 + alpha4*x4 + alpha5*x5
    // + alpha6*x6 + alpha7*x7 + alpha8*x8
    template <
        class OutputIterator ,
        class InputIterator1 ,
        class InputIterator2 ,
        class InputIterator3 ,
        class InputIterator4 ,
        class InputIterator5 ,
        class InputIterator6 ,
        class InputIterator7 ,
        class InputIterator8 ,
        class T
        >
    inline void scale_sum( OutputIterator y_begin ,
                           OutputIterator y_end ,
                           T alpha1 ,
                           InputIterator1 x1_begin ,
                           T alpha2 ,
                           InputIterator2 x2_begin ,
                           T alpha3 ,
                           InputIterator3 x3_begin ,
                           T alpha4 ,
                           InputIterator4 x4_begin ,
                           T alpha5 ,
                           InputIterator5 x5_begin ,
                           T alpha6 ,
                           InputIterator6 x6_begin ,
                           T alpha7 ,
                           InputIterator7 x7_begin ,
                           T alpha8 ,
                           InputIterator8 x8_begin )
    {
        while( y_begin != y_end )
            (*y_begin++) = 
                alpha1 * (*x1_begin++) + 
                alpha2 * (*x2_begin++) + 
                alpha3 * (*x3_begin++) +
                alpha4 * (*x4_begin++) +
                alpha5 * (*x5_begin++) +
                alpha6 * (*x6_begin++) +
                alpha7 * (*x7_begin++) +
                alpha8 * (*x8_begin++);
    }

    // computes y = x1 + alpha2*x2 + alpha3*x3 + alpha4*x4 + alpha5*x5
    // + alpha6*x6 + alpha7*x7 + alpha8*x8 + alpha9*x9
    template <
        class OutputIterator ,
        class InputIterator1 ,
        class InputIterator2 ,
        class InputIterator3 ,        
        class InputIterator4 ,
        class InputIterator5 ,
        class InputIterator6 ,
        class InputIterator7 ,
        class InputIterator8 ,
        class InputIterator9 ,
        class T
        >
    inline void scale_sum( OutputIterator y_begin ,
                           OutputIterator y_end ,
                           T alpha1 ,
                           InputIterator1 x1_begin ,
                           T alpha2 ,
                           InputIterator2 x2_begin ,
                           T alpha3 ,
                           InputIterator3 x3_begin ,
                           T alpha4 ,
                           InputIterator4 x4_begin ,
                           T alpha5 ,
                           InputIterator5 x5_begin ,
                           T alpha6 ,
                           InputIterator6 x6_begin ,
                           T alpha7 ,
                           InputIterator7 x7_begin ,
                           T alpha8 ,
                           InputIterator8 x8_begin ,
                           T alpha9 ,
                           InputIterator9 x9_begin )
    {
        while( y_begin != y_end )
            (*y_begin++) = 
                alpha1 * (*x1_begin++) + 
                alpha2 * (*x2_begin++) + 
                alpha3 * (*x3_begin++) +
                alpha4 * (*x4_begin++) +
                alpha5 * (*x5_begin++) +
                alpha6 * (*x6_begin++) +
                alpha7 * (*x7_begin++) +
                alpha8 * (*x8_begin++) +
                alpha9 * (*x9_begin++);
    }




    // computes y = x1 + alpha2*x2 + alpha3*x3 + alpha4*x4 + alpha5*x5
    // + alpha6*x6 + alpha7*x7 + alpha8*x8 + alpha9*x9 + alpha10*x10
    template <
        class OutputIterator ,
        class InputIterator1 ,
        class InputIterator2 ,
        class InputIterator3 ,
        class InputIterator4 ,
        class InputIterator5 ,
        class InputIterator6 ,
        class InputIterator7 ,
        class InputIterator8 ,
        class InputIterator9 ,
        class InputIterator10 ,
        class T
        >
    inline void scale_sum( OutputIterator y_begin ,
                           OutputIterator y_end ,
                           T alpha1 ,
                           InputIterator1 x1_begin ,
                           T alpha2 ,
                           InputIterator2 x2_begin ,
                           T alpha3 ,
                           InputIterator3 x3_begin ,
                           T alpha4 ,
                           InputIterator4 x4_begin ,
                           T alpha5 ,
                           InputIterator5 x5_begin ,
                           T alpha6 ,
                           InputIterator6 x6_begin ,
                           T alpha7 ,
                           InputIterator7 x7_begin ,
                           T alpha8 ,
                           InputIterator8 x8_begin ,
                           T alpha9 ,
                           InputIterator9 x9_begin ,
                           T alpha10 ,
                           InputIterator10 x10_begin 
        )
    {
        while( y_begin != y_end )
            (*y_begin++) = 
                alpha1 * (*x1_begin++) + 
                alpha2 * (*x2_begin++) + 
                alpha3 * (*x3_begin++) +
                alpha4 * (*x4_begin++) +
                alpha5 * (*x5_begin++) +
                alpha6 * (*x6_begin++) +
                alpha7 * (*x7_begin++) +
                alpha8 * (*x8_begin++) +
                alpha9 * (*x9_begin++) +
                alpha10 * (*x10_begin++);
    }







    // generic version for n values
    template <
        class OutputIterator ,
        class InputIterator ,
        class InputIteratorIterator ,
        class FactorIterator ,
        class T
        >
    inline void scale_sum_generic( OutputIterator y_begin ,
                                   OutputIterator y_end ,
                                   FactorIterator alpha_begin ,
                                   FactorIterator alpha_end ,
                                   T beta ,
                                   InputIterator x_begin ,
                                   InputIteratorIterator x_iter_begin )
    {
        FactorIterator alpha_iter;
        InputIteratorIterator x_iter_iter;
        while( y_begin != y_end )
	{
            x_iter_iter = x_iter_begin;
            alpha_iter = alpha_begin;
            *y_begin = *x_begin++;
            //std::clog<<(*y_begin);
            while( alpha_iter != alpha_end )
	    {
                //std::clog<< " + " <<beta<<" * "<<*alpha_iter<<"*"<<(*(*(x_iter_iter)));
                (*y_begin) += beta * (*alpha_iter++) * (*(*x_iter_iter++)++);
            }
            //std::clog<<" = "<<*y_begin<<std::endl;
            y_begin++;
        }
        //std::clog<<std::endl;
    }


    // computes y += alpha1*x1 + alpha2*x2 + alpha3*x3 + alpha4*x4
    template <
        class OutputIterator,
        class InputIterator1,
        class InputIterator2,
        class InputIterator3,
        class InputIterator4,
        class T
        >
    inline void scale_sum_inplace(
            OutputIterator y_begin,
            OutputIterator y_end,
            T alpha1,
            InputIterator1 x1_begin,
            T alpha2,
            InputIterator2 x2_begin,
            T alpha3,
            InputIterator3 x3_begin,
            T alpha4,
            InputIterator4 x4_begin )
    {   
        while( y_begin != y_end )
            (*y_begin++) += 
                alpha1 * (*x1_begin++) + 
                alpha2 * (*x2_begin++) + 
                alpha3 * (*x3_begin++) +
                alpha4 * (*x4_begin++);
    }

    /* calculates tmp = y, y = x1 + alpha*x2, x1 = tmp */
    template <
        class OutputIterator,
        class InputIterator,
        class T
        >
    inline void scale_sum_swap(
            OutputIterator y_begin,
            OutputIterator y_end,
            OutputIterator x1_begin,
            T alpha,
            InputIterator x2_begin )
    {
        T swap;
        while( y_begin != y_end )
        {
            swap = (*x1_begin) + alpha*(*x2_begin++);
            *x1_begin++ = *y_begin;
            *y_begin++ = swap;
        }
    }


    // computes y = x1 + alpha2 * x2 ; x2 += x3
    template<
        class OutputIterator ,
        class InputIterator1 ,
        class InOutIterator ,
        class InputIterator2 ,
        class T
        >
    void assign_sum_increment(
                              OutputIterator first1 ,
                              OutputIterator last1 ,
                              InputIterator1 first2 ,
                              InOutIterator first3 ,
                              InputIterator2 first4 ,
                              T alpha
                              )
    {
        while( first1 != last1 )
          {
                (*first1++) = (*first2++) + alpha * (*first3);
                (*first3++) += (*first4++);
          }
    }

    template<
        class OutputIterator,
        class InputIterator1,
        class InputIterator2,
        class T >
    void weighted_scale( OutputIterator y_begin,
                         OutputIterator y_end,
                         InputIterator1 x1_begin,
                         InputIterator2 x2_begin,
                         T eps_abs,
                         T eps_rel,
                         T a_x,
                         T a_dxdt )
    {
	using std::abs;

        while( y_begin != y_end ) 
        {
            *y_begin++ = eps_abs + 
                eps_rel * ( a_x * abs(*x1_begin++) + 
                            a_dxdt * abs(*x2_begin++) );
        }
    }

    
    template<
        class InputIterator1,
        class InputIterator2,
        class T >
    T max_ratio( InputIterator1 x1_begin,
                 InputIterator1 x1_end,
                 InputIterator2 x2_begin,
                 T initial_max )
    {
	using std::abs;

        while( x1_begin != x1_end ) 
        {
            initial_max = std::max(
		static_cast<T>( abs(*x1_begin++) / abs(*x2_begin++) ) ,
		initial_max );
        }
        return initial_max;
    }
    

    
    




}
}
}
}
}


#endif //BOOST_NUMERIC_ODEINT_DETAIL_ACCUMULATORS_HPP

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions