openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
timer_utils.cc
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // openCARP is an open cardiac electrophysiology simulator.
3 //
4 // Copyright (C) 2020 openCARP project
5 //
6 // This program is licensed under the openCARP Academic Public License (APL)
7 // v1.0: You can use and redistribute it and/or modify it in non-commercial
8 // academic environments under the terms of APL as published by the openCARP
9 // project v1.0, or (at your option) any later version. Commercial use requires
10 // a commercial license (info@opencarp.org).
11 //
12 // This program is distributed without any warranty; see the openCARP APL for
13 // more details.
14 //
15 // You should have received a copy of the openCARP APL along with this program
16 // and can find it online: http://www.opencarp.org/license
17 // ----------------------------------------------------------------------------
18 
28 #include "timer_utils.h"
29 #include "basics.h"
30 
31 #include <algorithm>
32 
33 namespace opencarp {
34 
35 
36 void timer_manager::setup(double inp_dt, double inp_start, double inp_end)
37 {
38  // pick closest index as start index
39  time_step = inp_dt;
40  d_time = lround(inp_start/time_step);
41  time = d_time * time_step;
42  d_start = d_time;
43  start = time;
44  d_end = lround(inp_end/time_step);
45  end = d_end * time_step;
46 }
47 
48 void timer_manager::initialize_eq_timer(double istart, double iend, int ntrig, double iintv,
49  double idur, int ID, const char *iname, const char* poolname)
50 {
51  timer_eq* tm = new timer_eq();
52  tm->initialize(this, istart, iend, ntrig, iintv, idur, iname);
53 
54  if(poolname) tm->assign_pool(poolname);
55 
56  if(int(timers.size()) <= ID)
57  timers.resize(ID + 1, nullptr);
58 
59  timers[ID] = tm;
60 }
61 
62 
63 void timer_manager::initialize_neq_timer(const std::vector<double> & itrig, double idur, int ID,
64  const char *iname, const char *poolname)
65 {
66  timer_neq* tm = new timer_neq();
67  tm->initialize(this, itrig, idur, iname);
68 
69  if(poolname) tm->assign_pool(poolname);
70 
71  if(int(timers.size()) <= ID)
72  timers.resize(ID + 1, nullptr);
73 
74  timers[ID] = tm;
75 }
76 
77 
78 int timer_manager::add_eq_timer(double istart, double iend, int ntrig, double iintv,
79  double idur, const char *iname, const char *poolname)
80 {
81  timer_eq* tm = new timer_eq();
82  tm->initialize(this, istart, iend, ntrig, iintv, idur, iname);
83 
84  int ret_idx = timers.size();
85  timers.push_back(tm);
86 
87  if(poolname) timers[ret_idx]->assign_pool(poolname);
88 
89  return ret_idx;
90 }
91 
92 int timer_manager::add_neq_timer(const std::vector<double> & itrig, double idur, const char *iname,
93  const char *poolname)
94 {
95  timer_neq* tm = new timer_neq();
96  tm->initialize(this, itrig, idur, iname);
97 
98  int ret_idx = timers.size();
99  timers.push_back(tm);
100 
101  if(poolname) timers[ret_idx]->assign_pool(poolname);
102 
103  return ret_idx;
104 }
105 
106 void timer_eq::initialize(const timer_manager* t, double istart, double iend, int ntrig,
107  double iintv, double idur, const char *iname)
108 {
109  mng = t;
110  type = EQUDIST;
111  name = dupstr(iname);
112  trigger_count = 0;
113  trigger_dur = idur;
114  d_trigger_dur = t->time_step > 0. ? lround(idur/t->time_step) : 0.;
115  active = 0;
116 
117  d_start = t->time_step > 0. ? lround(istart/t->time_step) : 0.;
118  d_intv = iintv ? lround(iintv/t->time_step) : 1;
119 
120  if(ntrig)
121  d_end = d_start + d_intv * ntrig - 1;
122  else
123  d_end = t->time_step > 0. ? lround(iend/t->time_step) : 0.;
124 
125  // move start past current time
126  int num_skipped = 0;
127  while ((d_start + d_trigger_dur) < t->d_time) {
128  d_start += d_intv;
129  num_skipped++;
130  }
131 
132  // if new start is past end of trigger period of interest
133  if (d_start>d_end) {
134  // disable trigger
135  d_start = t->d_end + 1;
136  d_nxt = t->d_end + 1;
137  numIOs = 0;
138  return;
139  }
140 
141  //figure out where in the pulse cycle we are.
142  if (d_start < t->d_time) {
143  d_nxt = d_start+d_intv;
144  if ( d_start + d_trigger_dur > t->d_time) {
145  active = d_start + d_trigger_dur - t->d_time;
146  }
147  } else {
148  d_nxt = d_start;
149  }
150 
151  // re-determine number of trigger events
152  numIOs = (d_end-d_start)/d_intv+1;
153  start = d_start*t->time_step;
154  intv = d_intv*t->time_step;
155  end = d_end*t->time_step;
156  nxt = d_nxt*t->time_step;
157 
158  update();
159 }
160 
162 {
163  triggered = false;
164 
165  if (mng->d_time == d_nxt) {
166  triggered = true;
167  active = d_trigger_dur;
168  d_nxt += d_intv;
169  if (d_nxt > d_end) d_nxt += mng->d_end; // move beyond end of simulation
170  nxt = d_nxt * mng->time_step;
171  }
172 
173  if (triggered) trigger_count++;
174 
175  // count down to end of trigger event with duration
176  if (active) {
177  --active;
178  triggered = true;
179  }
180 }
181 
183  // end has been already adjusted during the first initialization. As such,
184  // I dont think that we need to pass the number of trigger events again. -Aurel
185  initialize(mng, start, end, 0, intv, trigger_dur, name);
186 }
187 
188 
189 void timer_neq::initialize(const timer_manager* t, const std::vector<double> & itrig,
190  const double idur, const char *iname)
191 {
192  mng = t;
193  trig = itrig;
194  type = NONEQUDIST;
195  name = dupstr(iname);
196 
197  trigger_count = 0;
198  trigger_dur = idur;
199  d_trigger_dur = mng->time_step > 0. ? lround(idur/mng->time_step) : 0.;
200  active = 0;
201 
202  d_trig.resize(trig.size());
203  int used_triggers = 0;
204  int max_time_less_than_current_time = 0;
205  int found_time_less_than_current_time = 0;
206 
207  for (size_t ii=0; ii < trig.size(); ii++) {
208  long this_d_tm = lround(trig[ii] / mng->time_step);
209  if (this_d_tm >= mng->d_time) {
210  d_trig[used_triggers++] = this_d_tm;
211  }
212  else {
213  if (!found_time_less_than_current_time || this_d_tm > max_time_less_than_current_time) {
214  found_time_less_than_current_time = 1;
215  max_time_less_than_current_time = this_d_tm;
216  }
217  }
218  }
219  d_trig.resize(used_triggers);
220 
221  std::sort(d_trig.begin(), d_trig.end());
222  std::unique(d_trig.begin(), d_trig.end());
223 
224  //fill the time list.
225  trig.resize(d_trig.size());
226  for (size_t ii=0; ii<d_trig.size(); ii++) {
227  trig[ii] = d_trig[ii] * mng->time_step;
228  }
229  numIOs = trig.size();
230 
231  //Find out if we are in the middle of a pulse
232  if (found_time_less_than_current_time && max_time_less_than_current_time + d_trigger_dur > mng->d_time) {
233  active = max_time_less_than_current_time + d_trigger_dur - mng->d_time;
234  }
235 
236  update();
237 }
238 
240 {
241  triggered = 0;
242 
243  if (trigger_count < int(trig.size())) {
244  if (mng->d_time == d_trig[trigger_count]) {
245  triggered = 1;
246  active = d_trigger_dur;
247  }
248  }
249 
250  if (triggered) trigger_count++;
251 
252  // count down to end of trigger event with duration
253  if (active) {
254  --active;
255  triggered = 1 ;
256  }
257 }
258 
260 {
261  std::vector<double> btrig(trig);
262  initialize(mng, btrig, trigger_dur, name);
263 }
264 
265 } // namespace opencarp
266 
char * dupstr(const char *old_str)
Definition: basics.cc:44
void assign_pool(const char *poolname)
Definition: timer_utils.h:65
void initialize_eq_timer(double istart, double iend, int ntrig, double iintv, double idur, int ID, const char *iname, const char *poolname=nullptr)
Definition: timer_utils.cc:48
void initialize(const timer_manager *t, const std::vector< double > &itrig, const double idur, const char *iname)
Definition: timer_utils.cc:189
int add_eq_timer(double istart, double iend, int ntrig, double iintv, double idur, const char *iname, const char *poolname=nullptr)
Add a equidistant step timer to the array of timers.
Definition: timer_utils.cc:78
double time_step
global reference time step
Definition: timer_utils.h:78
double end
final time
Definition: timer_utils.h:81
void setup(double inp_dt, double inp_start, double inp_end)
Initialize the timer_manager.
Definition: timer_utils.cc:36
Timers and timer manager.
void initialize(const timer_manager *t, double istart, double iend, int ntrig, double iintv, double idur, const char *iname)
Definition: timer_utils.cc:106
double time
current time
Definition: timer_utils.h:76
long d_time
current time instance index
Definition: timer_utils.h:77
long d_start
initial index in multiples of dt
Definition: timer_utils.h:80
int add_neq_timer(const std::vector< double > &itrig, double idur, const char *iname, const char *poolname=nullptr)
Definition: timer_utils.cc:92
std::vector< base_timer * > timers
vector containing individual timers
Definition: timer_utils.h:84
void initialize_neq_timer(const std::vector< double > &itrig, double idur, int ID, const char *iname, const char *poolname=nullptr)
Definition: timer_utils.cc:63
Basic utility structs and functions, mostly IO related.
double start
initial time (nonzero when restarting)
Definition: timer_utils.h:79
centralize time managment and output triggering
Definition: timer_utils.h:73
long d_end
final index in multiples of dt
Definition: timer_utils.h:82