31 #ifndef _adevs_hybrid_h_
32 #define _adevs_hybrid_h_
35 #include "adevs_models.h"
50 N(N_vars),M(M_event_funcs){}
56 virtual void init(
double* q) = 0;
58 virtual void der_func(
const double* q,
double* dq) = 0;
71 const bool* state_event) = 0;
79 virtual void output_func(
const double *q,
const bool* state_event,
114 double err_tol = 1E-10,
int max_iters = 30,
double alpha = -1.0):
117 max_iters(max_iters),
124 atmp =
new double[A];
126 f[1] =
new double[A];
127 f[0] =
new double[A];
137 virtual void init(
double* q,
double* a) = 0;
144 virtual void alg_func(
const double* q,
const double* a,
double* af) = 0;
149 virtual void der_func(
const double* q,
const double* a,
double* dq) = 0;
153 virtual void state_event_func(
const double* q,
const double* a,
double* z) = 0;
161 virtual void postStep(
double* q,
double* a) = 0;
164 const bool* state_event) = 0;
167 double e,
const Bag<X>& xb) = 0;
170 const bool* state_event,
const Bag<X>& xb) = 0;
172 virtual void output_func(
const double *q,
const double* a,
173 const bool* state_event,
Bag<X>& yb) = 0;
264 void solve(
const double* q);
266 const int A, max_iters;
267 const double err_tol, alpha;
280 template <
typename X>
283 int iter_count = 0, alt, good;
284 double prev_err, err = 0.0, ee, beta, g2, alpha_tmp = alpha;
290 _adevs_dae_se_1_system_solve_try_it_again:
295 alg_func(q,a,f[alt]);
296 for (
int i = 0; i < A; i++)
304 a[i] += alpha_tmp*d[i];
308 while (iter_count < max_iters)
313 alg_func(q,a,f[good]);
315 for (
int i = 0; i < A; i++)
320 ee = fabs(f[good][i]);
321 if (ee > err) err = ee;
324 if (err < err_tol)
return;
329 for (
int i = 0; i < A; i++)
332 if (alpha_tmp < 0.0) alpha_tmp = -alpha_tmp;
333 else alpha_tmp *= -0.5;
334 goto _adevs_dae_se_1_system_solve_try_it_again;
340 for (
int i = 0; i < A; i++)
341 g2 += f[alt][i]*f[alt][i];
342 for (
int i = 0; i < A; i++)
343 beta += f[good][i]*(f[good][i]-f[alt][i]);
346 for (
int i = 0; i < A; i++)
348 d[i] = beta*d[i]-f[good][i];
350 a[i] += alpha_tmp*d[i];
380 virtual double integrate(
double* q,
double h_lim) = 0;
384 virtual void advance(
double* q,
double h) = 0;
414 virtual bool find_events(
bool* events,
const double *qstart,
430 template <
typename X,
class T =
double>
class Hybrid:
440 sys(sys),solver(solver),event_finder(event_finder),
443 q =
new double[sys->
numVars()];
444 q_trial =
new double[sys->
numVars()];
446 event_exists =
false;
448 for (
int i = 0; i < sys->
numVars(); i++) q[i] = q_trial[i];
465 if (!missedOutput.
empty())
467 missedOutput.
clear();
472 event_happened = event_exists;
475 sys->internal_event(q_trial,event);
479 for (
int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
488 bool state_event_exists =
false;
489 event_happened =
true;
493 for (
int i = 0; i < sys->numVars(); i++)
495 solver->advance(q_trial,e);
497 event_finder->find_events(event,q,q_trial,solver,e);
499 if (state_event_exists)
502 sys->confluent_event(q_trial,event,xb);
503 for (
int i = 0; i < sys->numVars(); i++)
507 if (!state_event_exists)
509 solver->advance(q,e);
513 sys->external_event(q,e+e_accum,xb);
517 for (
int i = 0; i < sys->numVars(); i++) q_trial[i] = q[i];
526 if (!missedOutput.
empty())
528 missedOutput.
clear();
529 if (sigma > 0.0) event_exists =
false;
532 event_happened =
true;
534 sys->confluent_event(q_trial,event,xb);
535 else sys->external_event(q_trial,e_accum+
ta(),xb);
538 for (
int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
544 if (missedOutput.
empty())
return sigma;
550 if (!missedOutput.
empty())
553 for (; iter != missedOutput.
end(); iter++)
556 sys->output_func(q_trial,event,yb);
561 sys->postStep(q_trial);
563 sys->output_func(q_trial,event,yb);
571 delete [] q;
delete [] q_trial;
delete [] event;
572 delete event_finder;
delete solver;
delete sys;
586 void tentative_step()
589 double time_event = sys->time_event_func(q);
591 double step_size = solver->integrate(q_trial,time_event);
593 bool state_event_exists =
594 event_finder->find_events(event,q,q_trial,solver,step_size);
596 sigma = std::min(step_size,time_event);
597 event[sys->numEvents()] = time_event <= sigma;
598 event_exists =
event[sys->numEvents()] || state_event_exists;