![]() |
|
|||
File indexing completed on 2025-04-19 09:10:16
0001 #ifndef SHRIMPS_Tools_DEQ_Solver_H 0002 #define SHRIMPS_Tools_DEQ_Solver_H 0003 0004 #include <vector> 0005 #include <cstddef> 0006 0007 namespace SHRIMPS { 0008 /*! 0009 \class DEQ_Kernel_Base 0010 \brief The base class for possible kernels of systems of differential 0011 equations. The main method here is the purely virtual operator, 0012 DEQ_Kernel_Base::operator()(const std::vector<double> &input, 0013 const double param=0.). 0014 0015 Up to now this is only specified for differential equations of the form 0016 \f[ 0017 \frac{\mbox{\rm d}\vec x}{\mbox{\rm d}y} = \vec f(\vec x,\,y)\,, 0018 \f] 0019 where the kernels actually represent the \f$\vec f(\vec x,\,y)\f$ 0020 of the equation above. 0021 */ 0022 class DEQ_Kernel_Base { 0023 public: 0024 DEQ_Kernel_Base() {} 0025 virtual ~DEQ_Kernel_Base() {} 0026 virtual std::vector<double> & operator()(const std::vector<double> &input, 0027 const double param=0.)=0; 0028 }; 0029 0030 struct deqmode { 0031 enum code { 0032 RungeKutta4 = 4, 0033 RungeKutta2 = 2, 0034 SimpleEuler = 1 0035 }; 0036 }; 0037 0038 /*! 0039 \class DEQ_Solver 0040 \brief A class to solve simple systems of linear differential equations 0041 with Runge-Kutta methods of order 2 or 4 or with a simple Euler 0042 step method. 0043 0044 Specifically, linear differential equations of the type 0045 \f[ 0046 \frac{\mbox{\rm d}\vec x}{\mbox{\rm d}y} = \vec f(\vec x,\,y) 0047 \f] 0048 can be treated. The key method is 0049 DEQ_Solver::SolveSystem(const std::vector<double> & x0,const int & ysteps) 0050 which will produce a (two-dimensional) grid \f$\vec x(y_i)\f$ at finite 0051 values of \f$y\f$. This grid can be recovered through DEQ_Solver::X(). 0052 */ 0053 class DEQ_Solver { 0054 private: 0055 DEQ_Kernel_Base * p_kernel; 0056 size_t m_dim; 0057 std::vector<std::vector<double> > m_x, m_xsave; 0058 deqmode::code m_deqmode; 0059 double m_ystart, m_yend, m_stepsize; 0060 int m_test; 0061 0062 0063 0064 0065 void InitIteration(const std::vector<double> & x0,const int & steps); 0066 void RunIteration(const int & steps); 0067 void Rerun(const std::vector<double> & x0,const int & steps); 0068 bool CheckAccuracy(const double & accu,double & diffmax); 0069 void SaveResult(); 0070 void RestoreResult(); 0071 void IncreaseAccuracy(int & steps); 0072 0073 /*! 0074 \fn void DEQ_Solver::SimpleEuler(const std::vector<double> & x0, 0075 const int & steps) 0076 \brief The method to solve the differential equation with a simple Euler 0077 step algorithm. 0078 0079 Using \f$y_{i+1}=y_i+\Delta y\f$ with \f$\Delta y\f$ the stepsize of 0080 the algorithm and \f$\vec x_i\equiv \vec x(y_i)\f$ this algorithm reads: 0081 \f[ 0082 \vec x(y_{i+1}) = \vec x_i+\Delta y\cdot\vec f(\vec x_i,\,y_i)\,. 0083 \f] 0084 */ 0085 void SimpleEuler(const int & steps); 0086 /*! 0087 \fn void DEQ_Solver::RungeKutta2(const int & steps) 0088 \brief The method to solve the differential equation with a Runge-Kutta 0089 algorithm of order 2. 0090 0091 Using \f$y_{i+1}=y_i+\Delta y\f$ with \f$\Delta y\f$ the stepsize of 0092 the algorithm and \f$\vec x_i\equiv \vec x(y_i)\f$ this algorithm makes 0093 use of some auxiliary point \f$\vec x^{(1)}\f$ and \f$y^{(1)}\f$ given 0094 by 0095 \f[ 0096 \vec x^{(1)}_i = \vec x_i+\frac{\Delta y}{2}\cdot\vec f(\vec x_i,\,y_i) 0097 \;\;\;\mbox{\rm and}\;\;\; 0098 y^{(1)}_i = y_i+\frac{\Delta y}{2}\,. 0099 \f] 0100 With these two auxiliaries, the new point reads: 0101 \f[ 0102 \vec x_{i+1} = \vec x_i+\Delta y\cdot 0103 \vec f(\vec x_i^{(1)},\,y_i^{(1)})\,. 0104 \f] 0105 */ 0106 void RungeKutta2(const int & steps); 0107 /*! 0108 \fn void DEQ_Solver::RungeKutta4(const int & steps) 0109 \brief The method to solve the differential equation with a Runge-Kutta 0110 algorithm of order 4. 0111 0112 Using \f$y_{i+1}=y_i+\Delta y\f$ with \f$\Delta y\f$ the stepsize of 0113 the algorithm and \f$\vec x_i\equiv \vec x(y_i)\f$ this algorithm 0114 makes use of some auxiliary points \f$\vec x^{(1,2,3,4)}\f$ and 0115 \f$y^{(1,2,3,4)}\f$ given by 0116 \f[ 0117 \vec x^{(1)}_i = \vec x_i 0118 \;\;\;\mbox{\rm and}\;\;\; 0119 y^{(1)}_i = y_i 0120 \f] 0121 \f[ 0122 \vec x^{(2)}_i = \vec x_i+\frac{\Delta y}{2}\cdot 0123 \vec f(\vec x_i^{(1)},\,y_i^{(1)}) 0124 \;\;\;\mbox{\rm and}\;\;\; 0125 y^{(2)}_i = y_i+\frac{\Delta y}{2}\,. 0126 \f] 0127 \f[ 0128 \vec x^{(3)}_i = \vec x_i+\frac{\Delta y}{2}\cdot 0129 \vec f(\vec x_i^{(2)},\,y_i^{(2)}) 0130 \;\;\;\mbox{\rm and}\;\;\; 0131 y^{(3)}_i = y_i+\frac{\Delta y}{2}\,. 0132 \f] 0133 \f[ 0134 \vec x^{(4)}_i = \vec x_i+\Delta y\cdot\vec f(\vec x_i^{(3)},\,y_i^{(3)}) 0135 \;\;\;\mbox{\rm and}\;\;\; 0136 y^{(4)}_i = y_i+\Delta y\,. 0137 \f] 0138 With these two auxiliaries, the new point reads: 0139 \f[ 0140 \vec x_{i+1} = \vec x_i+\frac{\Delta y}{6}\cdot 0141 \left[\vec f(\vec x_i^{(1)},\,y_i^{(1)})+ 0142 2\vec f(\vec x_i^{(2)},\,y_i^{(2)})+ 0143 2\vec f(\vec x_i^{(3)},\,y_i^{(3)})+ 0144 \vec f(\vec x_i^{(4)},\,y_i^{(4)})\right]\,. 0145 \f] 0146 */ 0147 void RungeKutta4(const int & steps); 0148 public: 0149 DEQ_Solver(DEQ_Kernel_Base * kernel,const size_t & dim=2, 0150 const deqmode::code & deq=deqmode::RungeKutta4, 0151 const int & m_test=0); 0152 inline ~DEQ_Solver() {} 0153 0154 /*! 0155 \fn void DEQ_Solver::SolveSystem(const int & steps) 0156 \brief The method to solve the differential equation with one of the 0157 methods implemented so far. It will therefore call either 0158 DEQ_Solver::RungeKutta4(const int & steps), or 0159 DEQ_Solver::RungeKutta2(const int & steps), or 0160 DEQ_Solver::SimpleEuler(const int & steps). 0161 */ 0162 void SolveSystem(const std::vector<double> & x0,int & ysteps, 0163 const double & accu=-1); 0164 0165 inline void SetInterval(const double & ystart, const double & yend) { 0166 m_ystart = ystart; m_yend = yend; 0167 } 0168 0169 const std::vector<std::vector<double> > & X() const { return m_x; } 0170 }; 0171 } 0172 0173 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |