/home/nutarojj/adevs-2.3/include/adevs_hybrid.h

00001 #ifndef _adevs_hybrid_h_
00002 #define _adevs_hybrid_h_
00003 #include <algorithm>
00004 #include "adevs_models.h"
00005 
00006 namespace adevs
00007 {
00008 
00014 template <typename X> class ode_system
00015 {
00016         public:
00018                 ode_system(int N_vars, int M_event_funcs):
00019                         N(N_vars),M(M_event_funcs){}
00021                 int numVars() const { return N; }
00023                 int numEvents() const { return M; }
00025                 virtual void init(double* q) = 0;
00027                 virtual void der_func(const double* q, double* dq) = 0;
00029                 virtual void state_event_func(const double* q, double* z) = 0;
00031                 virtual double time_event_func(const double* q) = 0;
00033                 virtual void internal_event(double* q,
00034                                 const bool* state_event) = 0;
00036                 virtual void external_event(double* q, double e,
00037                                 const Bag<X>& xb) = 0;
00039                 virtual void confluent_event(double *q, const bool* state_event,
00040                                 const Bag<X>& xb) = 0;
00042                 virtual void output_func(const double *q, const bool* state_event,
00043                                 Bag<X>& yb) = 0;
00045                 virtual void gc_output(Bag<X>& gb) = 0;
00047                 virtual ~ode_system(){}
00048         private:
00049                 const int N, M;
00050 };
00051 
00056 template <typename X> class ode_solver
00057 {
00058         public:
00063                 ode_solver(ode_system<X>* sys):sys(sys){}
00069                 virtual double integrate(double* q, double h_lim) = 0;
00073                 virtual void advance(double* q, double h) = 0;
00075                 virtual ~ode_solver(){}
00076         protected:
00077                 ode_system<X>* sys;
00078 };
00079 
00085 template <typename X> class event_locator
00086 {
00087         public:
00092                 event_locator(ode_system<X>* sys):sys(sys){}
00101                 virtual bool find_events(bool* events, const double *qstart, 
00102                                 double* qend, ode_solver<X>* solver, double& h) = 0;
00104                 virtual ~event_locator(){}
00105         protected:
00106                 ode_system<X>* sys;
00107 };
00108 
00117 template <typename X> class Hybrid:
00118         public Atomic<X>
00119 {
00120         public:
00125                 Hybrid(ode_system<X>* sys, ode_solver<X>* solver,
00126                                 event_locator<X>* event_finder):
00127                         sys(sys),solver(solver),event_finder(event_finder)
00128                 {
00129                         q = new double[sys->numVars()];
00130                         q_trial = new double[sys->numVars()];
00131                         event = new bool[sys->numEvents()+1];
00132                         event_exists = false;
00133                         sys->init(q_trial); // Get the initial state of the model
00134                         for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00135                         tentative_step(); // Take the first tentative step
00136                 }
00138                 double getState(int k) const { return q[k]; }
00140                 const double* getState() const { return q; }
00142                 ode_system<X>* getSystem() { return sys; }
00147                 void delta_int()
00148                 {
00149                         if (event_exists) // Execute the internal event
00150                                 sys->internal_event(q_trial,event); 
00151                         // Copy the new state vector to q
00152                         for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00153                         tentative_step(); // Take a tentative step
00154                 }
00159                 void delta_ext(double e, const Bag<X>& xb)
00160                 {
00161                         solver->advance(q,e); // Advance the state q by e
00162                         sys->external_event(q,e,xb); // Compute the external event
00163                         // Copy the new state to the trial solution 
00164                         for (int i = 0; i < sys->numVars(); i++) q_trial[i] = q[i];
00165                         tentative_step(); // Take a tentative step
00166                 }
00171                 void delta_conf(const Bag<X>& xb)
00172                 {
00173                         if (event_exists) // Execute the confluent or external event
00174                                 sys->confluent_event(q_trial,event,xb); 
00175                         else sys->external_event(q_trial,ta(),xb);
00176                         // Copy the new state vector to q
00177                         for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00178                         tentative_step(); // Take a tentative step 
00179                 }
00181                 double ta() { return sigma; }
00183                 void output_func(Bag<X>& yb)
00184                 {
00185                         if (event_exists) sys->output_func(q_trial,event,yb);
00186                 }
00188                 void gc_output(Bag<X>& gb) { sys->gc_output(gb); }
00190                 virtual ~Hybrid()
00191                 {
00192                         delete [] q; delete [] q_trial; delete [] event;
00193                         delete event_finder; delete solver; delete sys;
00194                 }
00195         private:
00196                 ode_system<X>* sys; // The ODE system
00197                 ode_solver<X>* solver; // Integrator for the ode set
00198                 event_locator<X>* event_finder; // Event locator
00199                 double sigma; // Time to the next internal event
00200                 double *q, *q_trial; // Current and tentative states
00201                 bool* event; // Flags indicating the encountered event surfaces
00202                 bool event_exists; // True if there is at least one event
00203                 // Execute a tentative step and calculate the time advance function
00204                 void tentative_step()
00205                 {
00206                         // Check for a time event
00207                         double time_event = sys->time_event_func(q);
00208                         // Integrate up to that time at most
00209                         double step_size = solver->integrate(q_trial,time_event);
00210                         // Look for state events inside of the interval [0,step_size]
00211                         bool state_event_exists =
00212                                 event_finder->find_events(event,q,q_trial,solver,step_size);
00213                         // Find the time advance and set the time event flag
00214                         sigma = std::min(step_size,time_event);
00215                         event[sys->numEvents()] = time_event <= sigma;
00216                         event_exists = event[sys->numEvents()] || state_event_exists;
00217                 }
00218 };
00219 
00220 } // end of namespace
00221 
00222 #endif

Generated on Tue Oct 6 20:46:41 2009 for adevs by  doxygen 1.4.7