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);
00140 for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00141 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
00158 sys->postStep(q_trial);
00159
00160 event_happened = event_exists;
00161 if (event_exists)
00162 sys->internal_event(q_trial,event);
00163
00164 for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00165 tentative_step();
00166 }
00171 void delta_ext(double e, const Bag<X>& xb)
00172 {
00173 event_happened = true;
00174 solver->advance(q,e);
00175
00176 sys->postStep(q);
00177
00178 sys->external_event(q,e,xb);
00179
00180 for (int i = 0; i < sys->numVars(); i++) q_trial[i] = q[i];
00181 tentative_step();
00182 }
00187 void delta_conf(const Bag<X>& xb)
00188 {
00189
00190 sys->postStep(q_trial);
00191
00192 event_happened = true;
00193 if (event_exists)
00194 sys->confluent_event(q_trial,event,xb);
00195 else sys->external_event(q_trial,ta(),xb);
00196
00197 for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
00198 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;
00217 ode_solver<X>* solver;
00218 event_locator<X>* event_finder;
00219 double sigma;
00220 double *q, *q_trial;
00221 bool* event;
00222 bool event_exists;
00223 bool event_happened;
00224
00225 void tentative_step()
00226 {
00227
00228 double time_event = sys->time_event_func(q);
00229
00230 double step_size = solver->integrate(q_trial,time_event);
00231
00232 bool state_event_exists =
00233 event_finder->find_events(event,q,q_trial,solver,step_size);
00234
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 }
00242
00243 #endif