00001 #ifndef INDII_ML_ODE_ADAPTIVERUNGEKUTTA_HPP 00002 #define INDII_ML_ODE_ADAPTIVERUNGEKUTTA_HPP 00003 00004 #include "NumericalSolver.hpp" 00005 #include "DifferentialModel.hpp" 00006 #include "../aux/vector.hpp" 00007 00008 #include <gsl/gsl_odeiv.h> 00009 00010 namespace indii { 00011 namespace ml { 00012 namespace ode { 00013 00014 /** 00015 * Adaptive Runge-Kutta method for solving a system of ordinary 00016 * differential equations. 00017 * 00018 * @author Lawrence Murray <lawrence@indii.org> 00019 * @version $Rev: 448 $ 00020 * @date $Date: 2008-05-01 17:11:33 +0100 (Thu, 01 May 2008) $ 00021 * 00022 * This class numerically solves DifferentialModel models defining a 00023 * system of ordinary differential equations using an adaptive time 00024 * step 4th/5th order Runge--Kutta--Fehlberg method as implemented in 00025 * the @ref GSL "GSL". 00026 * 00027 * The general usage idiom is as follows. First begin by writing your 00028 * own class deriving from DifferentialModel to describe your model, 00029 * and instantiating an object of this class: 00030 * 00031 * @code 00032 * MyDifferentialModel model; 00033 * @endcode 00034 * 00035 * Construct the initial state of the system: 00036 * 00037 * @code 00038 * indii::ml::aux::vector y0(4); 00039 * y0(0) = 1.0; 00040 * y0(1) = 0.0; 00041 * y0(2) = 0.0; 00042 * y0(3) = 2.0; 00043 * @endcode 00044 * 00045 * Create an AdaptiveRungeKutta object, passing in the model to solve 00046 * and the initial state: 00047 * 00048 * @code 00049 * AdaptiveRungeKutta solver(&model, y0); 00050 * @endcode 00051 * 00052 * At this stage setErrorBounds() and setStepSize() may be used to 00053 * manipulate the Runge-Kutta to be appropriate for the model, 00054 * balancing speed versus accuracy. The defaults are often sufficient, 00055 * however. 00056 * 00057 * Now use step() to step through the system. The time step will vary 00058 * to maintain error bounds, so it is necessary to keep track of the 00059 * time after each step. 00060 * 00061 * @code 00062 * double end = 60.0; 00063 * double t = 0.0; 00064 * while (t < end) { 00065 * t = solver.step(end); 00066 * std::cout << solver.getState() << std::endl; 00067 * } 00068 * @endcode 00069 * 00070 * @c t is guaranteed to reach @c end at some point, although the 00071 * number of steps that this will take depends on the model, initial 00072 * state and error bounds. 00073 * 00074 * If you are only interested in the state of the system at a given 00075 * time, or wish to use fixed time steps, use stepTo() to jump 00076 * straight to the required time. Internally, stepTo() essentially 00077 * just performs the above loop for you, but its use can be more 00078 * convenient. 00079 * 00080 * For known discontinuities, it is usual to estimate the function 00081 * piecewise, stepping from start to finish through a continuous 00082 * piece, then calling setDiscontinuity() before proceeding onto the 00083 * next. 00084 * 00085 * @section AdaptiveRungeKutta_references References 00086 * 00087 * @anchor GSL 00088 * The GNU Scientific Library (GSL). http://www.gnu.org/software/gsl/. 00089 */ 00090 class AdaptiveRungeKutta : public NumericalSolver { 00091 public: 00092 /** 00093 * Constructor. 00094 * 00095 * @param model Model to estimate. 00096 * 00097 * The time is initialised to zero, but the state is uninitialised 00098 * and should be set with setVariable() or setState(). 00099 */ 00100 AdaptiveRungeKutta(DifferentialModel* model); 00101 00102 /** 00103 * Constructor. 00104 * 00105 * @param model Model to estimate. 00106 * @param y0 Initial state. 00107 * 00108 * The time is initialised to zero and the state to that given. 00109 */ 00110 AdaptiveRungeKutta(DifferentialModel* model, 00111 const indii::ml::aux::vector& y0); 00112 00113 /** 00114 * Destructor. 00115 */ 00116 virtual ~AdaptiveRungeKutta(); 00117 00118 virtual int calculateDerivativesForward(double t, const double y[], 00119 double dydt[]); 00120 00121 virtual int calculateDerivativesBackward(double t, const double y[], 00122 double dydt[]); 00123 00124 private: 00125 /** 00126 * Model. 00127 */ 00128 DifferentialModel* model; 00129 00130 /** 00131 * GSL ordinary differential equations step type. 00132 */ 00133 static const gsl_odeiv_step_type* gslStepType; 00134 00135 }; 00136 00137 } 00138 } 00139 } 00140 00141 #endif 00142
1.5.3