/************************************************************************* * Copyright (C) 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; KVector calculateK(Y& y, const ACoefficients& a) const; KVector calculateK(Y k1, Y& y, 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 { Y ytemp; // Ignored return calculateK(ytemp, a); } template typename GenericRKIntegrator::KVector GenericRKIntegrator::calculateK(Y& y, const ACoefficients& a) const { return calculateK(this->f()(this->x(), this->y()), y, a); } template typename GenericRKIntegrator::KVector GenericRKIntegrator::calculateK(Y k1, Y& y, const ACoefficients& a) const { KVector k; k.reserve(a.size() + 1); // k1 k.push_back(k1); // k2..n Scalar h(this->h()); for (typename ACoefficients::const_iterator i = a.begin(); i != a.end(); ++i) { Scalar c(0); y = this->y(); for (typename std::vector::size_type j = 0; j < i->size(); ++j) { Scalar aij = i->at(j); c += aij; y += h*aij*k.at(j); } k.push_back(this->f()(this->x() + h*c, y)); } return k; } template Y GenericRKIntegrator::calculateY(const KVector& k, const BCoefficients& b) const { Y y(this->y()); Scalar h(this->h()); for (typename std::vector::size_type i = 0; i < k.size(); ++i) { y += h*b.at(i)*k.at(i); } return y; } } #endif // VZ_RK_HPP