Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

integrator.h

00001 /***************************************************************************
00002                           integrator.h  -  description
00003                              -------------------
00004     begin                : Tue Aug 12 2000
00005     copyright            : (C) 2000 by Michael Peeters
00006     email                : Michael.Peeters@vub.ac.be
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #ifndef INTEGRATOR_H
00019 #define INTEGRATOR_H 
00020 
00021 #include "numerictypes.h"
00022 #include "numerictraits.h"
00023 #include "vectorfunction.h"
00024 // #include "odesystem.h"
00025 #include "random.h"
00026 #include "jacobian.h"
00027 
00028 namespace MODEL {
00029 
00030   // predef
00031   template<integer dims, typename nelem, class NT>
00032   class ODESystem;
00033 
00035   enum Integration {Euler, RungeKutta, Milshtein,Heun};
00036 
00038   template<integer dims, typename nelem=number, class NT = NumericTraits<nelem,dims> >
00039   class Integrator
00040   {
00041         friend class ODESystem<dims,nelem,NT>;
00042 
00043   public:
00044         typedef typename NT::number                                     numT;
00045         typedef typename NT::vect                                       vect;
00046         typedef typename NT::vf                                         vf;
00047         typedef typename NT::matrix                                     matrix;
00048 
00058         Integrator(vf& d, vf& s)
00059           :  deter(&d), stoch(&s){}
00060         
00061         virtual ~Integrator(){};
00062 
00070         virtual vect& step(vect& current, time& dt)=0;
00071 
00073         vect&   currentpoint(void) {return current;}
00074                 
00075   private:
00077         vf* get_deterministic(void)
00078         {
00079           return deter;
00080         }
00081 
00082         vf* get_stochastic(void)
00083         {
00084           return stoch;
00085         }
00086 
00087   protected:
00089         vf* deter;
00091         vf* stoch;
00092         
00093   };    
00094   //------------------------------------------------------------
00095 
00100   template<integer dims, typename nelem=number, class NT = NumericTraits<nelem,dims> >
00101   class IEuler : public Integrator<dims,nelem,NT>
00102   {
00103   public:
00105         IEuler(vf& d, vf& s) 
00106           : Integrator<dims,nelem,NT>(d,s) {}
00107 
00109         virtual vect& step(vect& current, time& dt)
00110         {
00111           vect noise;
00112           for(counter i=0;i<dims;i++) noise[i]=rnd();
00113           vect g=(*stoch)(current);
00114           for(counter i=0;i<dims;i++) g[i]*=noise[i];
00115 
00116           return current+=dt*(*deter)(current)+sqrt(dt)*g;
00117         }
00118 
00119   private:
00121         Normal rnd; // will be seeded with time()
00122 
00123   };
00124 
00125         
00126   //-------------------------------------------------------------------------
00130   template<integer dims, typename nelem=number, class NT = NumericTraits<nelem,dims> >
00131   class IRungeKutta : public Integrator<dims,nelem,NT>
00132   {
00133   public:
00134         IRungeKutta(vf& d, vf& s) 
00135           : Integrator<dims,nelem,NT>(d,s) {}
00136 
00137         virtual vect& step(vect& current, time& dt)
00138         {
00139           // Runge-Kutta needs 4 evaluations:
00140           // 1) at the current point
00141           // 2) at a halfway point, using the values of 1)
00142           // 3) at a halfway point, using the values of 2)
00143           // 4) at the end point, using the values of 3)
00144           
00145           vect k1,k2,k3,k4;
00146           number dt2=dt/2.;
00147 
00148           // Step 1) 
00149 
00150           k1=(*deter)(current);
00151           k1*=dt2;
00152 
00153           // Step 2)
00154           // halfway in t
00155 
00156           vect pos(k1);
00157           pos+=current; //halfway in u
00158  
00159           k2=(*deter)(pos);
00160           k2*=dt2;
00161 
00162           // Step 3)
00163           pos=k2;
00164           pos+=current;
00165 
00166           k3=(*deter)(pos);
00167           k3*=dt2;
00168           // Step 4)
00169           //another half step
00170 
00171           pos=k3; pos+=current; // BUG FIX: Forgot to add current point
00172           k4=(*deter)(pos);
00173           k4*=dt2;
00174 
00175           // Now calculate next point. Caveat
00176           // emptor, this is very slow (compared to what it could be).
00177           return current+=(k1+2.*k2+2.*k3+k4)/3.;
00178         }
00179 
00180   };
00181 
00182   //----------------------------------------------------------------------              
00186   template<integer dims, typename nelem=number, class NT = NumericTraits<nelem,dims> >
00187   class IMilshtein : public Integrator<dims,nelem,NT> 
00188   {
00189   public:
00190         IMilshtein(vf& d, vf& s) 
00191           : Integrator<dims,nelem,NT>(d,s){}
00192 
00193         virtual vect& step(vect& current, time& dt)
00194         {
00195           // The Milshtein method is the basic algo for noisy problems
00196           // => Needs a random number generator !
00197 
00198           vect oldcurrent(current);
00199 
00200           // Deterministix q
00201           vect q=(*deter)(oldcurrent);
00202           current+=dt*q;
00203                   
00204           // Stochastix g
00205           // Generate numbers: noise is _NOT_ correlated between modes.
00206           vect noise;
00207           for(counter i=0;i<dims;i++) noise[i]=rnd();
00208                   
00209           // Additive component (Euler)
00210           number sqdt=sqrt(dt);
00211           vect g=(*stoch)(oldcurrent);
00212                   
00213           // Multiply each component with its noise
00214           vect ng(g);
00215           for(counter i=0;i<dims;i++) ng[i]*=noise[i]; 
00216                   
00217           // Result
00218           current+=sqdt*ng;
00219 
00220           // Extra Millstein 
00221           Jacobian<dims,NT> J(*stoch);
00222           matrix dgdy=J.calculate(oldcurrent,g);
00223                   
00224           vect dgs(0.);
00225           for(counter i=0;i<dims;i++)
00226                 for (counter j=0;j<dims;j++)
00227                   dgs[i]+=0.5*dgdy[i][j]*g[j]*noise[i]*noise[j];
00228         
00229           current+=dt*dgs;
00230           return current;
00231         }
00232 
00233   private:              
00235         Normal rnd; // will be seeded with time()
00236   };
00237 
00238   template<integer dims, typename nelem=number, class NT = NumericTraits<nelem,dims> >
00239   class IHeun : public Integrator<dims,nelem,NT> 
00240   {
00241   public:
00242         IHeun(vf& d, vf& s) 
00243           : Integrator<dims,nelem,NT>(d,s){}
00244 
00245         virtual vect& step(vect& current, time& dt)
00246         {
00247           // The Heun method is the best easy algo for noisy problems
00248           // => Needs a random number generator !
00249           
00250           // u is N(0,1)
00251 
00252           // k=h.q(t,x)
00253           // l=sqrth.u.g(t,x)
00254           //
00255           // qavg = (1/2)*( q(t,x) + q(t+h,x+k+l) )
00256           // gavg = (1/2)*( g(t,x) + g(t+h,x+k+l) )
00257           //
00258           // Watch out: we might have to take a step for the modulators
00259           //
00260           // xnew = x + h*qavg + sqrth*u*gavg
00261 
00262           vect oldcurrent(current);
00263 
00264           // Some to be optimized out temps
00265           const number h=dt;
00266           const number sh=sqrt(dt);
00267 
00268           vect q = (*deter)(oldcurrent);
00269           vect g = (*stoch)(oldcurrent);
00270 
00271           // Generate numbers: noise is _NOT_ correlated between modes.
00272           vect u;
00273           for(counter i=0;i<dims;i++) u[i]=rnd();
00274           
00279           // uneff: vect k=h*q;
00280           // uneff: vect l=sh*g;
00281 
00282           // generate next point
00283           for(counter i=0;i<dims;i++)
00284                 {
00285                   oldcurrent[i]+=h*q[i]+sh*g[i]*u[i];
00286                   // The stochastic part should be sqrt(2D) when the autocorrelation
00287                   // is given by <F,F>=2D.delta; 2D is the variance (in fact)
00288                 }
00289 
00290           // uneff:               l[i]*=u[i];
00291 
00292           // uneff: oldcurrent+=k;
00293           // uneff: oldcurrent+=l;
00294           
00295           // vect qavg=0.5* h * ( q + (*deter)(oldcurrent) );
00296           // vect gavg=0.5* sh * ( g + (*stoch)(oldcurrent) );
00297 
00298           vect qn=(*deter)(oldcurrent);
00299           vect gn=(*stoch)(oldcurrent);
00300 
00301           for(counter i=0;i<dims;i++) 
00302                 {
00303                   current[i]+=0.5*( h*( q[i] + qn[i]) + sh*u[i]*(g[i]+gn[i]));
00304                   
00305                   // uneff:  gavg[i]*=u[i];
00306                 }
00307 
00308           // uneff: current += qavg;
00309           // uneff: current += gavg;
00310           
00311           return current;
00312         }
00313 
00314   private:              
00316         Normal rnd; // will be seeded with time()
00317   };
00318 
00321   template<integer dims, typename nelem=number, class NT = NumericTraits<nelem,dims> >
00322   class IHeunSimpleCorr : public Integrator<dims,nelem,NT> 
00323   {
00324   public:
00325         IHeunSimpleCorr(vf& d, vf& s, vf& transform) 
00326           : Integrator<dims,nelem,NT>(d,s), trans(&transform){}
00327 
00328         virtual vect& step(vect& current, time& dt)       
00329         {         
00330         // The Heun method is the best easy algo for noisy problems
00331           // => Needs a random number generator !
00332           
00333           // u is N(0,1)
00334 
00335           // k=h.q(t,x)
00336           // l=sqrth.u.g(t,x)
00337           //
00338           // qavg = (1/2)*( q(t,x) + q(t+h,x+k+l) )
00339           // gavg = (1/2)*( g(t,x) + g(t+h,x+k+l) )
00340           //
00341           // Watch out: we might have to take a step for the modulators
00342           //
00343           // xnew = x + h*qavg + sqrth*u*gavg
00344 
00345           vect oldcurrent(current);
00346 
00347           // Some to be optimized out temps
00348           const number h=dt;
00349           const number sh=sqrt(dt);
00350 
00351           vect q = (*deter)(oldcurrent);
00352           vect g = (*stoch)(oldcurrent);
00353 
00354           // Generate numbers: noise is _NOT_ correlated between modes.
00355           vect u,u0;
00356           for(counter i=0;i<dims;i++) u0[i]=rnd();
00357 
00358           // Do transform for eventual correlation
00359           trans->function(u,u0);
00360           
00361           // uneff: vect k=h*q;
00362           // uneff: vect l=sh*g;
00363 
00364           // generate next point
00365           for(counter i=0;i<dims;i++)
00366                 {
00367                   oldcurrent[i]+=h*q[i]+sh*g[i]*u[i];
00368                 }
00369 
00370           // uneff:               l[i]*=u[i];
00371 
00372           // uneff: oldcurrent+=k;
00373           // uneff: oldcurrent+=l;
00374           
00375           // vect qavg=0.5* h * ( q + (*deter)(oldcurrent) );
00376           // vect gavg=0.5* sh * ( g + (*stoch)(oldcurrent) );
00377 
00378           vect qn=(*deter)(oldcurrent);
00379           vect gn=(*stoch)(oldcurrent);
00380 
00381           for(counter i=0;i<dims;i++) 
00382                 {
00383                   current[i]+=0.5*( h*( q[i] + qn[i]) + sh*u[i]*(g[i]+gn[i]));
00384                   
00385                   // uneff:  gavg[i]*=u[i];
00386                 }
00387 
00388           // uneff: current += qavg;
00389           // uneff: current += gavg;
00390           
00391           return current;
00392         }
00393 
00394   private:              
00396         Normal rnd; // will be seeded with time()
00397 
00399         vf* trans;
00400   };
00401 
00402 } // end namespace
00403 #endif
00404 
00405 /*********************************************************************
00406 $Id: integrator.h,v 1.1.2.1 2002/06/19 13:15:47 mpeeters Exp $
00407 **********************************************************************
00408 
00409 $Log: integrator.h,v $
00410 Revision 1.1.2.1  2002/06/19 13:15:47  mpeeters
00411 New integrator manipulators, Euler-Maryuama, transforms.
00412 
00413 Revision 1.1  2001/05/22 10:54:55  mpeeters
00414 Moved sources and headers for libModel to model/ subdirectory, in an attempt to rationalize the source tree. This should make things "netter".
00415 
00416 Revision 1.4  2001/05/21 11:53:16  mpeeters
00417 Removed Makefile.in, which is automatically generated anyway.
00418 
00419 Revision 1.3  2000/09/22 08:50:03  mpeeters
00420 Changed dependencies causing trouble.
00421 
00422 Revision 1.2  2000/09/15 10:26:31  mpeeters
00423 Cleaned out header and added CVS tails to files, removed superfuous
00424 @author comments, inserted dates
00425 
00426 *********************************************************************/

To get the sources or tarballs, please go to SourceForge or you can use the CVS repository.

More Info? Michael Peeters. Also, check our research website: www.alna.vub.ac.be

Last update: June 2002.


Looking for Open Source? Check out SourceForge Logo !