1 /* This file is part of StepCore library.
2    Copyright (C) 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
3 
4    StepCore library is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8 
9    StepCore library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with StepCore; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18 
19 /** \file gslsolver.h
20  *  \brief GslGenericSolver, GslSolver and GslAdaptiveSolver classes
21  */
22 
23 #ifndef STEPCORE_GSLSOLVER_H
24 #define STEPCORE_GSLSOLVER_H
25 
26 // HACK: CMake does not passes definitions to moc
27 #if defined(STEPCORE_WITH_GSL) || defined(Q_MOC_RUN)
28 
29 #include "solver.h"
30 #include "object.h"
31 
32 #include <gsl/gsl_odeiv.h>
33 
34 namespace StepCore
35 {
36 
37 /** \ingroup solvers
38  *  \brief Adaptive and non-adaptive solvers from GSL library
39  *
40  *  See https://www.gnu.org/software/gsl/manual/html_node/Ordinary-Differential-Equations.html#Ordinary-Differential-Equations
41  *  and https://en.wikipedia.org/wiki/Numerical_ordinary_differential_equations
42  *
43  */
44 class GslGenericSolver: public Solver
45 {
STEPCORE_OBJECT(GslGenericSolver)46     STEPCORE_OBJECT(GslGenericSolver)
47 
48 public:
49     /** Constructs GslSolver */
50     GslGenericSolver(double stepSize, bool adaptive, const gsl_odeiv_step_type* gslStepType)
51         : Solver(stepSize), _adaptive(adaptive), _gslStepType(gslStepType) { init(); }
52     /** Constructs GslSolver */
GslGenericSolver(int dimension,Function function,void * params,double stepSize,bool adaptive,const gsl_odeiv_step_type * gslStepType)53     GslGenericSolver(int dimension, Function function, void* params, double stepSize,
54                 bool adaptive, const gsl_odeiv_step_type* gslStepType)
55         : Solver(dimension, function, params, stepSize),
56             _adaptive(adaptive), _gslStepType(gslStepType) { init(); }
57     /** Copy constructor */
GslGenericSolver(const GslGenericSolver & gslSolver)58     GslGenericSolver(const GslGenericSolver& gslSolver)
59         : Solver(gslSolver), _adaptive(gslSolver._adaptive),
60             _gslStepType(gslSolver._gslStepType) { init(); }
61 
~GslGenericSolver()62     ~GslGenericSolver() { fini(); }
63 
setDimension(int dimension)64     void setDimension(int dimension) { fini(); _dimension = dimension; init(); }
setToleranceAbs(double toleranceAbs)65     void setToleranceAbs(double toleranceAbs) { fini(); _toleranceAbs = toleranceAbs; init(); }
setToleranceRel(double toleranceRel)66     void setToleranceRel(double toleranceRel) { fini(); _toleranceRel = toleranceRel; init(); }
67 
68     int doCalcFn(double* t, const VectorXd* y, const VectorXd* yvar,
69                             VectorXd* f = 0, VectorXd* fvar = 0);
70     int doEvolve(double* t, double t1, VectorXd* y, VectorXd* yvar);
71 
72 protected:
73     static int gslFunction(double t, const double* y, double* f, void* params);
74     void init();
75     void fini();
76 
77     bool   _adaptive;
78 
79     //gsl_odeiv_control*  _gslControl;
80     //gsl_odeiv_evolve*   _gslEvolve;
81     VectorXd _yerr;
82     VectorXd _ytemp;
83     VectorXd _ydiff;
84     VectorXd _dydt_in;
85     VectorXd _dydt_out;
86 
87     const gsl_odeiv_step_type* _gslStepType;
88     gsl_odeiv_system   _gslSystem;
89     gsl_odeiv_step*    _gslStep;
90     gsl_odeiv_control* _gslControl;
91     gsl_odeiv_evolve*  _gslEvolve;
92 };
93 
94 /** \ingroup solvers
95  *  \brief Non-adaptive solvers from GSL library
96  */
97 class GslSolver: public GslGenericSolver
98 {
STEPCORE_OBJECT(GslSolver)99     STEPCORE_OBJECT(GslSolver)
100 public:
101     GslSolver(double stepSize, const gsl_odeiv_step_type* gslStepType):
102                             GslGenericSolver(stepSize, false, gslStepType) {}
GslSolver(int dimension,Function function,void * params,double stepSize,const gsl_odeiv_step_type * gslStepType)103     GslSolver(int dimension, Function function, void* params, double stepSize,
104                             const gsl_odeiv_step_type* gslStepType)
105                     : GslGenericSolver(dimension, function, params, stepSize, false, gslStepType) {}
GslSolver(const GslSolver & gslSolver)106     GslSolver(const GslSolver& gslSolver): GslGenericSolver(gslSolver) {}
107 };
108 
109 /** \ingroup solvers
110  *  \brief Adaptive solvers from GSL library
111  */
112 class GslAdaptiveSolver: public GslGenericSolver
113 {
STEPCORE_OBJECT(GslAdaptiveSolver)114     STEPCORE_OBJECT(GslAdaptiveSolver)
115 public:
116     explicit GslAdaptiveSolver(const gsl_odeiv_step_type* gslStepType):
117                             GslGenericSolver(1, true, gslStepType) {}
GslAdaptiveSolver(int dimension,Function function,void * params,const gsl_odeiv_step_type * gslStepType)118     GslAdaptiveSolver(int dimension, Function function, void* params,
119                             const gsl_odeiv_step_type* gslStepType)
120                     : GslGenericSolver(dimension, function, params, 1, true, gslStepType) {}
GslAdaptiveSolver(const GslAdaptiveSolver & gslSolver)121     GslAdaptiveSolver(const GslAdaptiveSolver& gslSolver): GslGenericSolver(gslSolver) {}
122 };
123 
124 #define STEPCORE_DECLARE_GSLSOLVER(Class, type) \
125 class Gsl##Class##Solver: public GslSolver { \
126     STEPCORE_OBJECT(Gsl##Class##Solver) \
127 public: \
128     Gsl##Class##Solver(double stepSize = 0.01): GslSolver(stepSize, gsl_odeiv_step_##type) {} \
129     Gsl##Class##Solver(int dimension, Function function, void* params, double stepSize) \
130                  : GslSolver(dimension, function, params, stepSize, gsl_odeiv_step_##type) {} \
131     Gsl##Class##Solver(const Gsl##Class##Solver& gslSolver): GslSolver(gslSolver) {} \
132 };
133 
134 #define STEPCORE_DECLARE_GSLASOLVER(Class, type) \
135 class GslAdaptive##Class##Solver: public GslAdaptiveSolver { \
136     STEPCORE_OBJECT(GslAdaptive##Class##Solver) \
137 public: \
138     GslAdaptive##Class##Solver(): GslAdaptiveSolver(gsl_odeiv_step_##type) {} \
139     GslAdaptive##Class##Solver(int dimension, Function function, void* params) \
140                     : GslAdaptiveSolver(dimension, function, params, gsl_odeiv_step_##type) {} \
141     GslAdaptive##Class##Solver(const GslAdaptive##Class##Solver& gslSolver): GslAdaptiveSolver(gslSolver) {} \
142 };
143 
144 /** \ingroup solvers
145  *  \class GslRK2Solver
146  *  \brief Runge-Kutta second-order solver from GSL library
147  */
148 STEPCORE_DECLARE_GSLSOLVER(RK2, rk2)
149 
150 /** \ingroup solvers
151  *  \class GslAdaptiveRK2Solver
152  *  \brief Adaptive Runge-Kutta second-order solver from GSL library
153  */
154 STEPCORE_DECLARE_GSLASOLVER(RK2, rk2)
155 
156 /** \ingroup solvers
157  *  \class GslRK4Solver
158  *  \brief Runge-Kutta classical fourth-order solver from GSL library
159  */
160 STEPCORE_DECLARE_GSLSOLVER(RK4, rk4)
161 
162 /** \ingroup solvers
163  *  \class GslAdaptiveRK4Solver
164  *  \brief Adaptive Runge-Kutta classical fourth-order solver from GSL library
165  */
166 STEPCORE_DECLARE_GSLASOLVER(RK4, rk4)
167 
168 /** \ingroup solvers
169  *  \class GslRKF45Solver
170  *  \brief Runge-Kutta-Fehlberg (4,5) solver from GSL library
171  */
172 STEPCORE_DECLARE_GSLSOLVER(RKF45, rkf45)
173 
174 /** \ingroup solvers
175  *  \class AdaptiveGslRKF45Solver
176  *  \brief Adaptive Runge-Kutta-Fehlberg (4,5) solver from GSL library
177  */
178 STEPCORE_DECLARE_GSLASOLVER(RKF45, rkf45)
179 
180 /** \ingroup solvers
181  *  \class GslRKCKSolver
182  *  \brief Runge-Kutta Cash-Karp (4,5) solver from GSL library
183  */
184 STEPCORE_DECLARE_GSLSOLVER(RKCK, rkck)
185 
186 /** \ingroup solvers
187  *  \class AdaptiveGslRKCKSolver
188  *  \brief Adaptive Runge-Kutta Cash-Karp (4,5) solver from GSL library
189  */
190 STEPCORE_DECLARE_GSLASOLVER(RKCK, rkck)
191 
192 /** \ingroup solvers
193  *  \class GslRK8PDSolver
194  *  \brief Runge-Kutta Prince-Dormand (8,9) solver from GSL library
195  */
196 STEPCORE_DECLARE_GSLSOLVER(RK8PD, rk8pd)
197 
198 /** \ingroup solvers
199  *  \class GslAdaptiveRK8PDSolver
200  *  \brief Adaptive Runge-Kutta Prince-Dormand (8,9) solver from GSL library
201  */
202 STEPCORE_DECLARE_GSLASOLVER(RK8PD, rk8pd)
203 
204 /** \ingroup solvers
205  *  \class GslRK2IMPSolver
206  *  \brief Runge-Kutta implicit second-order solver from GSL library
207  */
208 STEPCORE_DECLARE_GSLSOLVER(RK2IMP, rk2imp)
209 
210 /** \ingroup solvers
211  *  \class GslAdaptiveRK2IMPSolver
212  *  \brief Adaptive Runge-Kutta Prince-Dormand (8,9) solver from GSL library
213  */
214 STEPCORE_DECLARE_GSLASOLVER(RK2IMP, rk2imp)
215 
216 /** \ingroup solvers
217  *  \class GslRK4IMPSolver
218  *  \brief Runge-Kutta implicit fourth-order solver from GSL library
219  */
220 STEPCORE_DECLARE_GSLSOLVER(RK4IMP, rk4imp)
221 
222 /** \ingroup solvers
223  *  \class GslAdaptiveRK4IMPSolver
224  *  \brief Runge-Kutta implicit fourth-order solver from GSL library
225  */
226 STEPCORE_DECLARE_GSLASOLVER(RK4IMP, rk4imp)
227 
228 } // namespace StepCore
229 
230 #endif // defined(STEPCORE_WITH_GSL) || defined(Q_MOC_RUN)
231 
232 #endif // STEPCORE_GSLSOLVER_H
233 
234