Back to home page

EIC code displayed by LXR

 
 

    


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