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);
00134 for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00135 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)
00150 sys->internal_event(q_trial,event);
00151
00152 for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00153 tentative_step();
00154 }
00159 void delta_ext(double e, const Bag<X>& xb)
00160 {
00161 solver->advance(q,e);
00162 sys->external_event(q,e,xb);
00163
00164 for (int i = 0; i < sys->numVars(); i++) q_trial[i] = q[i];
00165 tentative_step();
00166 }
00171 void delta_conf(const Bag<X>& xb)
00172 {
00173 if (event_exists)
00174 sys->confluent_event(q_trial,event,xb);
00175 else sys->external_event(q_trial,ta(),xb);
00176
00177 for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00178 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;
00197 ode_solver<X>* solver;
00198 event_locator<X>* event_finder;
00199 double sigma;
00200 double *q, *q_trial;
00201 bool* event;
00202 bool event_exists;
00203
00204 void tentative_step()
00205 {
00206
00207 double time_event = sys->time_event_func(q);
00208
00209 double step_size = solver->integrate(q_trial,time_event);
00210
00211 bool state_event_exists =
00212 event_finder->find_events(event,q,q_trial,solver,step_size);
00213
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 }
00221
00222 #endif