/************************************************************************* * Copyright (C) 2009-2010 Tavian Barnes * * * * This file is part of The vZ Library. * * * * The vZ Library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation; either version 3 of the * * License, or (at your option) any later version. * * * * The vZ Library is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this program. If not, see * * . * *************************************************************************/ #ifndef VZ_RK_HPP #define VZ_RK_HPP #include namespace vZ { // Base class for Runge-Kutta type algorithms template class GenericRKIntegrator : public GenericIntegrator { public: typedef typename GenericIntegrator::Scalar Scalar; typedef typename GenericIntegrator::Function Function; protected: // Coefficients in the tableau representation of the RK algorithm typedef std::vector > ACoefficients; typedef std::vector BCoefficients; // Result vectors typedef std::vector KVector; GenericRKIntegrator(Function f) : GenericIntegrator(f) { } virtual ~GenericRKIntegrator() { } // Perform the stages of an RK integration KVector calculateK(const ACoefficients& a) const; Y calculateY(const KVector& k, const BCoefficients& b) const; }; // Type alias typedef GenericRKIntegrator RKIntegrator; // Implementation template typename GenericRKIntegrator::KVector GenericRKIntegrator::calculateK(const ACoefficients& a) const { KVector k; k.reserve(a.size() + 1); // k1 k.push_back(this->f()(this->x(), this->y())); // k2..n for (typename ACoefficients::const_iterator i = a.begin(); i != a.end(); ++i) { Scalar c = 0; Y y = this->y(); for (typename std::vector::size_type j = 0; j < i->size(); ++j) { Scalar aij = i->at(j); c += aij; y += aij*this->h()*k.at(j); } k.push_back(this->f()(this->x() + c, y)); } return k; } template Y GenericRKIntegrator::calculateY(const KVector& k, const BCoefficients& b) const { Y y = this->y(); for (typename std::vector::size_type i = 0; i < k.size(); ++i) { y += this->h()*b.at(i)*k.at(i); } return y; } } #endif // VZ_RK_HPP