File indexing completed on 2024-04-21 03:51:21

0001 /*
0002     SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 /** \file eulersolver.h
0008  *  \brief GenericEulerSolver, EulerSolver and AdaptiveEulerSolver classes
0009  */
0010 
0011 #ifndef STEPCORE_EULERSOLVER_H
0012 #define STEPCORE_EULERSOLVER_H
0013 
0014 #include "solver.h"
0015 #include "object.h"
0016 
0017 namespace StepCore {
0018 
0019 /** \ingroup solvers
0020  *  \brief Adaptive and non-adaptive Euler solver with error estimation
0021  *  
0022  *  See https://en.wikipedia.org/wiki/Numerical_ordinary_differential_equations#The_Euler_method
0023  *  and https://en.wikipedia.org/wiki/Adaptive_step_size
0024  *
0025  *  \todo tests
0026  */
0027 class GenericEulerSolver: public Solver
0028 {
0029     STEPCORE_OBJECT(GenericEulerSolver)
0030 
0031 public:
0032     /** Constructs GenericEulerSolver */
0033     GenericEulerSolver(double stepSize, bool adaptive)
0034         : Solver(stepSize), _adaptive(adaptive) { init(); }
0035     /** Constructs GenericEulerSolver */
0036     GenericEulerSolver(int dimension, Function function,
0037             void* params, double stepSize, bool adaptive)
0038         : Solver(dimension, function, params, stepSize),
0039             _adaptive(adaptive) { init(); }
0040     /** Copy constructor */
0041     GenericEulerSolver(const GenericEulerSolver& eulerSolver)
0042         : Solver(eulerSolver), _adaptive(eulerSolver._adaptive) { init(); }
0043 
0044     ~GenericEulerSolver() { fini(); }
0045 
0046     void setDimension(int dimension) override { fini(); _dimension = dimension; init(); }
0047 
0048     int doCalcFn(double* t, const VectorXd* y, const VectorXd* yvar = nullptr,
0049                         VectorXd* f = nullptr, VectorXd* fvar = nullptr) override;
0050     int doEvolve(double* t, double t1, VectorXd* y, VectorXd* yvar) override;
0051 
0052 protected:
0053     int doStep(double t, double stepSize, VectorXd* y, VectorXd* yvar);
0054     void init();
0055     void fini();
0056 
0057     bool    _adaptive;
0058     VectorXd _yerr;
0059     VectorXd _ytemp;
0060     VectorXd _ydiff;
0061     VectorXd _ytempvar;
0062     VectorXd _ydiffvar;
0063 };
0064 
0065 /** \ingroup solvers
0066  *  \brief Non-adaptive Euler solver
0067  */
0068 class EulerSolver: public GenericEulerSolver
0069 {
0070     STEPCORE_OBJECT(EulerSolver)
0071 public:
0072     EulerSolver(double stepSize = 0.01): GenericEulerSolver(stepSize, false) {}
0073     EulerSolver(int dimension, Function function, void* params, double stepSize)
0074                     : GenericEulerSolver(dimension, function, params, stepSize, false) {}
0075     EulerSolver(const EulerSolver& eulerSolver): GenericEulerSolver(eulerSolver) {}
0076 };
0077 
0078 /** \ingroup solvers
0079  *  \brief Adaptive Euler solver
0080  */
0081 class AdaptiveEulerSolver: public GenericEulerSolver
0082 {
0083     STEPCORE_OBJECT(AdaptiveEulerSolver)
0084 public:
0085     AdaptiveEulerSolver(): GenericEulerSolver(1, true) {}
0086     AdaptiveEulerSolver(int dimension, Function function, void* params)
0087                     : GenericEulerSolver(dimension, function, params, 1, true) {}
0088     AdaptiveEulerSolver(const AdaptiveEulerSolver& eulerSolver)
0089                     : GenericEulerSolver(eulerSolver) {}
0090 };
0091 
0092 } // namespace StepCore
0093 
0094 #endif
0095