/home/nutarojj/adevs/trunk/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;
00037                 virtual void postStep(const double* q){};
00039                 virtual void internal_event(double* q,
00040                                 const bool* state_event) = 0;
00042                 virtual void external_event(double* q, double e,
00043                                 const Bag<X>& xb) = 0;
00045                 virtual void confluent_event(double *q, const bool* state_event,
00046                                 const Bag<X>& xb) = 0;
00048                 virtual void output_func(const double *q, const bool* state_event,
00049                                 Bag<X>& yb) = 0;
00051                 virtual void gc_output(Bag<X>& gb) = 0;
00053                 virtual ~ode_system(){}
00054         private:
00055                 const int N, M;
00056 };
00057 
00062 template <typename X> class ode_solver
00063 {
00064         public:
00069                 ode_solver(ode_system<X>* sys):sys(sys){}
00075                 virtual double integrate(double* q, double h_lim) = 0;
00079                 virtual void advance(double* q, double h) = 0;
00081                 virtual ~ode_solver(){}
00082         protected:
00083                 ode_system<X>* sys;
00084 };
00085 
00091 template <typename X> class event_locator
00092 {
00093         public:
00098                 event_locator(ode_system<X>* sys):sys(sys){}
00107                 virtual bool find_events(bool* events, const double *qstart, 
00108                                 double* qend, ode_solver<X>* solver, double& h) = 0;
00110                 virtual ~event_locator(){}
00111         protected:
00112                 ode_system<X>* sys;
00113 };
00114 
00123 template <typename X> class Hybrid:
00124         public Atomic<X>
00125 {
00126         public:
00131                 Hybrid(ode_system<X>* sys, ode_solver<X>* solver,
00132                                 event_locator<X>* event_finder):
00133                         sys(sys),solver(solver),event_finder(event_finder)
00134                 {
00135                         q = new double[sys->numVars()];
00136                         q_trial = new double[sys->numVars()];
00137                         event = new bool[sys->numEvents()+1];
00138                         event_exists = false;
00139                         sys->init(q_trial); // Get the initial state of the model
00140                         for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00141                         tentative_step(); // Take the first tentative step
00142                 }
00144                 double getState(int k) const { return q[k]; }
00146                 const double* getState() const { return q; }
00148                 ode_system<X>* getSystem() { return sys; }
00150                 bool eventHappened() const { return event_happened; }
00155                 void delta_int()
00156                 {
00157                         // Let the model adjust algebraic variables, etc. for the new state
00158                         sys->postStep(q_trial);
00159                         // Execute any discrete events
00160                         event_happened = event_exists;
00161                         if (event_exists) // Execute the internal event
00162                                 sys->internal_event(q_trial,event); 
00163                         // Copy the new state vector to q
00164                         for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00165                         tentative_step(); // Take a tentative step
00166                 }
00171                 void delta_ext(double e, const Bag<X>& xb)
00172                 {
00173                         event_happened = true;
00174                         solver->advance(q,e); // Advance the state q by e
00175                         // Let the model adjust algebraic variables, etc. for the new state
00176                         sys->postStep(q);
00177                         // Process the discrete input
00178                         sys->external_event(q,e,xb); 
00179                         // Copy the new state to the trial solution 
00180                         for (int i = 0; i < sys->numVars(); i++) q_trial[i] = q[i];
00181                         tentative_step(); // Take a tentative step
00182                 }
00187                 void delta_conf(const Bag<X>& xb)
00188                 {
00189                         // Let the model adjust algebraic variables, etc. for the new state
00190                         sys->postStep(q_trial);
00191                         // Execute any discrete events
00192                         event_happened = true;
00193                         if (event_exists) // Execute the confluent or external event
00194                                 sys->confluent_event(q_trial,event,xb); 
00195                         else sys->external_event(q_trial,ta(),xb);
00196                         // Copy the new state vector to q
00197                         for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00198                         tentative_step(); // Take a tentative step 
00199                 }
00201                 double ta() { return sigma; }
00203                 void output_func(Bag<X>& yb)
00204                 {
00205                         if (event_exists) sys->output_func(q_trial,event,yb);
00206                 }
00208                 void gc_output(Bag<X>& gb) { sys->gc_output(gb); }
00210                 virtual ~Hybrid()
00211                 {
00212                         delete [] q; delete [] q_trial; delete [] event;
00213                         delete event_finder; delete solver; delete sys;
00214                 }
00215         private:
00216                 ode_system<X>* sys; // The ODE system
00217                 ode_solver<X>* solver; // Integrator for the ode set
00218                 event_locator<X>* event_finder; // Event locator
00219                 double sigma; // Time to the next internal event
00220                 double *q, *q_trial; // Current and tentative states
00221                 bool* event; // Flags indicating the encountered event surfaces
00222                 bool event_exists; // True if there is at least one event
00223                 bool event_happened; // True if a discrete event in the ode_system took place
00224                 // Execute a tentative step and calculate the time advance function
00225                 void tentative_step()
00226                 {
00227                         // Check for a time event
00228                         double time_event = sys->time_event_func(q);
00229                         // Integrate up to that time at most
00230                         double step_size = solver->integrate(q_trial,time_event);
00231                         // Look for state events inside of the interval [0,step_size]
00232                         bool state_event_exists =
00233                                 event_finder->find_events(event,q,q_trial,solver,step_size);
00234                         // Find the time advance and set the time event flag
00235                         sigma = std::min(step_size,time_event);
00236                         event[sys->numEvents()] = time_event <= sigma;
00237                         event_exists = event[sys->numEvents()] || state_event_exists;
00238                 }
00239 };
00240 
00241 } // end of namespace
00242 
00243 #endif

Generated on Mon Sep 20 14:35:39 2010 for adevs by  doxygen 1.4.7