00001 /***************************************************************************
00002 odesystem.h - description
00003 -------------------
00004 begin : Tue Jul 11 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 ODESYSTEM_H
00019 #define ODESYSTEM_H
00020
00021 #include "rootscan.h"
00022
00023 #include "timeframe.h"
00024 #include "random.h"
00025 // #include "jacobian.h"
00026 // #include "debugmacro.h"
00027 #include "ticktock.h"
00028 #include "integrator.h"
00029 #include "cowner.h"
00030 #include "cycler.h"
00031 #include "numerictraits.h"
00032 #include "numerictypes.h"
00033
00034 namespace MODEL {
00035
00048 template<integer dims, typename nelem=number, class NT = NumericTraits<nelem,dims> >
00049 class ODESystem : public TickTock
00050 {
00051 public:
00052 typedef typename NT::number numT;
00053 typedef typename NT::vect vect;
00054 typedef typename NT::vf vf;
00055 typedef typename NT::matrix matrix;
00056
00057
00062 ODESystem( TimeFrame& T, vf& detpart, vf& stochpart, vect& initial,
00063 Integration it=Euler, time res=1E-3);
00064
00067 ODESystem( TimeFrame& T, vect& initial, Integrator<dims,nelem,NT>* i, time res=1e-3);
00068
00070 ODESystem( TimeFrame& T, vf& detpart, vect& initial,
00071 Integration it, time res);
00072
00073 virtual ~ODESystem();
00074
00077 virtual void tick()
00078 {
00079 step(); // Take care of the TimeFrame aspect (the modulators...)
00080 integ->step(current,dt); // Call the integrator
00081 }
00082
00084 const vect& get_current(void)
00085 {
00086 return current;
00087 }
00088
00089 void set_current(const vect& hereandnow)
00090 {
00091 current = hereandnow;
00092 }
00093
00098 const vect& operator()(void){return get_current();}
00099
00101 void reset(void)
00102 {
00103 reset(init);
00104 }
00105
00106
00108 void reset(const vect& fromhere)
00109 {
00110 current=fromhere;
00111 //Previously on MODEL:
00112 //relax_independent();
00113
00114 // But a much beter way to go is:
00115 RootScan<dims,nelem,NT> find(*deter);
00116 find.add_start(fromhere);
00117 ScanList<dims,nelem,NT> roots=find.scan(0.,1.,1);
00118 ScanList<dims,nelem,NT> goodone=roots.select(RootScan<dims>::stable);
00119
00120 if (goodone.get_data()[0.].size()>0)
00121 {
00122 current=goodone.get_data()[0.].front()[0];
00123 cerr << "ODESystem: started at " << current << endl;
00124 }
00125 else
00126 {
00127 current=fromhere;
00128 cerr << "ODEsystem - No stable starting point found @ " <<
00129 current << endl;
00130 }
00131 }
00132
00136 time relax(number goal=DEFAULT_RELAX);
00139 time relax_independent(number goal=DEFAULT_RELAX);
00140
00143 private:
00144 // Variables
00145 static const number DEFAULT_RELAX=1E-7;
00146
00148 vect init;
00149
00151 vect current;
00152
00154 Integrator<dims,nelem,NT>* integ;
00155
00157 vf* deter;
00159 vf* stoch;
00160 };
00161
00162 // Member Functions
00163 //--------------------------------------------------------------------------------
00164
00165 template<integer dims, typename nelem, class NT >
00166 ODESystem<dims,nelem,NT>::ODESystem( TimeFrame& T, vf& detpart, vf& stochpart, vect& initial,
00167 Integration it, time res) :
00168 TickTock(T,res), init(initial), integ(NULL), deter(&detpart), stoch(&stochpart)
00169 {
00170 // dt might have changed (because it has to fit integrally inside the top
00171 // TimeFrame)
00172
00173 // This is not needed: dt is a member !!!!
00174 // dt=get_dt();
00175 // relax to stable state to start if possible
00176
00177 current = init;
00178 reset();
00179
00180 // Initialize integrator
00181 switch(it)
00182 {
00183 case Euler: integ = new IEuler<dims,nelem,NT>(detpart,stochpart);
00184 break;
00185 case RungeKutta: integ = new IRungeKutta<dims,nelem,NT>(detpart,stochpart);
00186 break;
00187 case Milshtein: integ = new IMilshtein<dims,nelem,NT>(detpart,stochpart);
00188 break;
00189
00190 case Heun: integ = new IHeun<dims,nelem,NT>(detpart,stochpart);
00191 break;
00192
00193 default: throw std::logic_error("ODESystem::Integration method not implemented");
00194 break;
00195 }
00196 }
00197 //-------------------------------------------------------------------------------
00198
00201 template<integer dims, typename nelem, class NT >
00202 ODESystem<dims,nelem,NT>::ODESystem( TimeFrame& T, vect& initial, Integrator<dims,nelem,NT>* i, time res=1e-3):
00203 TickTock(T,res), init(initial), integ(NULL)
00204 {
00205 // dt might have changed (because it has to fit integrally inside the top
00206 // TimeFrame)
00207
00208 // This is not needed: dt is a member !!!!
00209 // dt=get_dt();
00210 // relax to stable state to start if possible
00211
00212 integ = i;
00213
00214 // get functions !!!
00215 deter = i->get_deterministic() ; stoch= i->get_stochastic();
00216
00217 current = init;
00218 reset();
00219 }
00220
00221 //--------------------------------------------------------------------------------
00222
00225 template<integer dims, typename nelem, class NT >
00226 ODESystem<dims,nelem,NT>::ODESystem( TimeFrame& T, vf& detpart, vect& initial,
00227 Integration it, time res) :
00228 TickTock(T,res), init(initial), integ(NULL), deter(&detpart)
00229 {
00230 // dt might have changed (because it has to fit integrally inside the top
00231 // TimeFrame)
00232
00233 // This is not needed: dt is a member !!!!
00234 // dt=get_dt();
00235 // relax to stable state to start if possible
00236
00237 current = init;
00238 reset();
00239
00240 // Initialize integrator
00241 switch(it)
00242 {
00243 case Euler: integ = new IEuler<dims,nelem,NT>(detpart,detpart);
00244 break;
00245 case RungeKutta: integ = new IRungeKutta<dims,nelem,NT>(detpart,detpart);
00246 break;
00247
00248 default: throw std::logic_error("ODESystem::Integration method not implemented");
00249 break;
00250 }
00251 }
00252
00253 //--------------------------------------------------------------------------------
00254
00255 template<integer dims, typename nelem, class NT >
00256 ODESystem<dims,nelem,NT>::~ODESystem()
00257 {
00258 delete integ;
00259 }
00260
00261 //--------------------------------------------------------------------------------
00262
00263 template<integer dims, typename nelem, class NT >
00264 time
00265 ODESystem<dims,nelem,NT>::relax_independent(number goal)
00266 {
00267 // This will become a RungeKutta
00268 IRungeKutta<dims,nelem,NT> massage(*deter,*stoch);
00269 ODESystem& system(*this); // alias for readability
00270 number change(0.);
00271 time chrono=0.;
00272 vect lastvalue(system());
00273
00274 do
00275 {
00276 // One step
00277 chrono+=dt;
00278 vect newvalue=massage.step(current,dt);
00279
00280 // Have we converged?
00281 change=0.;
00282 for (counter i=0;i<dims;i++)
00283 {
00284 number converge=abs((newvalue[i]-lastvalue[i])/lastvalue[i]);
00285 if(converge>change) change=converge; // find maximal change
00286 }
00287 lastvalue=newvalue;
00288 // cout << change << "\t" << newvalue << endl;
00289
00290 } while (change>goal);
00291
00292 return chrono; // return time spent
00293 }
00294
00295 //--------------------------------------------------------------------------------
00296 template<integer dims, typename nelem, class NT >
00297 time
00298 ODESystem<dims,nelem,NT>::relax(number goal)
00299 {
00300 ODESystem& system(*this); // alias for readability
00301 number change(0.);
00302 TimeFrame& t=get_timeframe();
00303 time init=t;
00304 vect converge(0.),lastvalue(system());
00305
00306 do
00307 {
00308 // One step
00309 ++t;
00310 vect newvalue=system();
00311
00312 // Have we converged?
00313 change=0.;
00314 for (counter i=0;i<dims;i++)
00315 {
00316 number converge=abs((newvalue[i]-lastvalue[i])/lastvalue[i]);
00317 if(converge>change) change=converge; // find maximal change
00318 }
00319 lastvalue=newvalue;
00320
00321
00322 // DEBUGSTREAM << change <<endl;
00323 } while (change>goal);
00324
00325 return t-init; // return time spent
00326 }
00327
00328 } // end namespace
00329 #endif
00330
00331 /*********************************************************************
00332 $Id: odesystem.h,v 1.2.2.2 2002/06/19 13:17:32 mpeeters Exp $
00333 **********************************************************************
00334
00335 $Log: odesystem.h,v $
00336 Revision 1.2.2.2 2002/06/19 13:17:32 mpeeters
00337 Possibility for custom integrator.
00338
00339 Revision 1.2.2.1 2001/10/15 15:08:24 mpeeters
00340 Added staring from a different point to make restarting easier.
00341
00342 Revision 1.2 2001/07/26 11:53:28 mpeeters
00343 Added constructor for non-stochastic case.
00344 Made sure the initial stat point is found correctly.
00345 Removed unneeded get_dt().
00346
00347 Revision 1.1 2001/05/22 10:54:55 mpeeters
00348 Moved sources and headers for libModel to model/ subdirectory, in an attempt to rationalize the source tree. This should make things "netter".
00349
00350 Revision 1.5 2001/05/21 11:53:16 mpeeters
00351 Removed Makefile.in, which is automatically generated anyway.
00352
00353 Revision 1.4 2000/09/29 08:55:07 mpeeters
00354 Inserted check for stable state. Removed bug where system would choose wrong starting point.
00355
00356 Revision 1.3 2000/09/22 08:56:04 mpeeters
00357 Bug fix: Rootscan was called for a 3D system always. Changed template
00358 parameter to RootScan<dims>, as it should be.
00359
00360 Revision 1.2 2000/09/15 10:26:31 mpeeters
00361 Cleaned out header and added CVS tails to files, removed superfuous
00362 @author comments, inserted dates
00363
00364 *********************************************************************/
More Info? Michael Peeters. Also, check our research website: www.alna.vub.ac.be
Last update: June 2002.