openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
timer_utils.cc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) NumeriCor GmbH
2 // SPDX-License-Identifier: Apache-2.0
3 
13 #include "timer_utils.h"
14 #include "basics.h"
15 
16 #include <algorithm>
17 
18 namespace opencarp {
19 
20 
21 void timer_manager::setup(double inp_dt, double inp_start, double inp_end)
22 {
23  // pick closest index as start index
24  time_step = inp_dt;
25  d_time = lround(inp_start/time_step);
26  time = d_time * time_step;
27  d_start = d_time;
28  start = time;
29  d_end = lround(inp_end/time_step);
30  end = d_end * time_step;
31 }
32 
33 void timer_manager::initialize_eq_timer(double istart, double iend, int ntrig, double iintv,
34  double idur, int ID, const char *iname, const char* poolname)
35 {
36  timer_eq* tm = new timer_eq();
37  tm->initialize(this, istart, iend, ntrig, iintv, idur, iname);
38 
39  if(poolname) tm->assign_pool(poolname);
40 
41  if(int(timers.size()) <= ID)
42  timers.resize(ID + 1, nullptr);
43 
44  timers[ID] = tm;
45 }
46 
47 
48 void timer_manager::initialize_neq_timer(const std::vector<double> & itrig, double idur, int ID,
49  const char *iname, const char *poolname)
50 {
51  timer_neq* tm = new timer_neq();
52  tm->initialize(this, itrig, 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 int timer_manager::add_eq_timer(double istart, double iend, int ntrig, double iintv,
64  double idur, const char *iname, const char *poolname)
65 {
66  timer_eq* tm = new timer_eq();
67  tm->initialize(this, istart, iend, ntrig, iintv, idur, iname);
68 
69  int ret_idx = timers.size();
70  timers.push_back(tm);
71 
72  if(poolname) timers[ret_idx]->assign_pool(poolname);
73 
74  return ret_idx;
75 }
76 
77 int timer_manager::add_neq_timer(const std::vector<double> & itrig, double idur, const char *iname,
78  const char *poolname)
79 {
80  timer_neq* tm = new timer_neq();
81  tm->initialize(this, itrig, idur, iname);
82 
83  int ret_idx = timers.size();
84  timers.push_back(tm);
85 
86  if(poolname) timers[ret_idx]->assign_pool(poolname);
87 
88  return ret_idx;
89 }
90 
91 void timer_eq::initialize(const timer_manager* t, double istart, double iend, int ntrig,
92  double iintv, double idur, const char *iname)
93 {
94  mng = t;
95  type = EQUDIST;
96  name = dupstr(iname);
97  trigger_count = 0;
98  trigger_dur = idur;
99  d_trigger_dur = t->time_step > 0. ? lround(idur/t->time_step) : 0.;
100  active = 0;
101 
102  d_start = t->time_step > 0. ? lround(istart/t->time_step) : 0.;
103  d_intv = iintv ? lround(iintv/t->time_step) : 1;
104 
105  if(ntrig)
106  d_end = d_start + d_intv * ntrig - 1;
107  else
108  d_end = t->time_step > 0. ? lround(iend/t->time_step) : 0.;
109 
110  // move start past current time
111  int num_skipped = 0;
112  while ((d_start + d_trigger_dur) < t->d_time) {
113  d_start += d_intv;
114  num_skipped++;
115  }
116 
117  // if new start is past end of trigger period of interest
118  if (d_start>d_end) {
119  // disable trigger
120  d_start = t->d_end + 1;
121  d_nxt = t->d_end + 1;
122  numIOs = 0;
123  return;
124  }
125 
126  //figure out where in the pulse cycle we are.
127  if (d_start < t->d_time) {
128  d_nxt = d_start+d_intv;
129  if ( d_start + d_trigger_dur > t->d_time) {
131  }
132  } else {
133  d_nxt = d_start;
134  }
135 
136  // re-determine number of trigger events
137  numIOs = (d_end-d_start)/d_intv+1;
138  start = d_start*t->time_step;
139  intv = d_intv*t->time_step;
140  end = d_end*t->time_step;
141  nxt = d_nxt*t->time_step;
142 
143  update();
144 }
145 
147 {
148  triggered = false;
149 
150  if (mng->d_time == d_nxt) {
151  triggered = true;
153  d_nxt += d_intv;
154  if (d_nxt > d_end) d_nxt += mng->d_end; // move beyond end of simulation
155  nxt = d_nxt * mng->time_step;
156  }
157 
158  if (triggered) trigger_count++;
159 
160  // count down to end of trigger event with duration
161  if (active) {
162  --active;
163  triggered = true;
164  }
165 }
166 
168  // end has been already adjusted during the first initialization. As such,
169  // I dont think that we need to pass the number of trigger events again. -Aurel
171 }
172 
173 
174 void timer_neq::initialize(const timer_manager* t, const std::vector<double> & itrig,
175  const double idur, const char *iname)
176 {
177  mng = t;
178  trig = itrig;
179  type = NONEQUDIST;
180  name = dupstr(iname);
181 
182  trigger_count = 0;
183  trigger_dur = idur;
184  d_trigger_dur = mng->time_step > 0. ? lround(idur/mng->time_step) : 0.;
185  active = 0;
186 
187  d_trig.resize(trig.size());
188  int used_triggers = 0;
189  int max_time_less_than_current_time = 0;
190  int found_time_less_than_current_time = 0;
191 
192  for (size_t ii=0; ii < trig.size(); ii++) {
193  long this_d_tm = lround(trig[ii] / mng->time_step);
194  if (this_d_tm >= mng->d_time) {
195  d_trig[used_triggers++] = this_d_tm;
196  }
197  else {
198  if (!found_time_less_than_current_time || this_d_tm > max_time_less_than_current_time) {
199  found_time_less_than_current_time = 1;
200  max_time_less_than_current_time = this_d_tm;
201  }
202  }
203  }
204  d_trig.resize(used_triggers);
205 
206  std::sort(d_trig.begin(), d_trig.end());
207  d_trig.erase(std::unique(d_trig.begin(), d_trig.end()), d_trig.end()); // remove duplicates
208 
209  //fill the time list.
210  trig.resize(d_trig.size());
211  for (size_t ii=0; ii<d_trig.size(); ii++) {
212  trig[ii] = d_trig[ii] * mng->time_step;
213  }
214  numIOs = trig.size();
215 
216  //Find out if we are in the middle of a pulse
217  if (found_time_less_than_current_time && max_time_less_than_current_time + d_trigger_dur > mng->d_time) {
218  active = max_time_less_than_current_time + d_trigger_dur - mng->d_time;
219  }
220 
221  update();
222 }
223 
225 {
226  triggered = 0;
227 
228  if (trigger_count < int(trig.size())) {
229  if (mng->d_time == d_trig[trigger_count]) {
230  triggered = 1;
232  }
233  }
234 
235  if (triggered) trigger_count++;
236 
237  // count down to end of trigger event with duration
238  if (active) {
239  --active;
240  triggered = 1 ;
241  }
242 }
243 
245 {
246  std::vector<double> btrig(trig);
247  initialize(mng, btrig, trigger_dur, name);
248 }
249 
250 } // namespace opencarp
251 
Basic utility structs and functions, mostly IO related.
centralize time managment and output triggering
Definition: timer_utils.h:58
void setup(double inp_dt, double inp_start, double inp_end)
Initialize the timer_manager.
Definition: timer_utils.cc:21
void initialize_neq_timer(const std::vector< double > &itrig, double idur, int ID, const char *iname, const char *poolname=nullptr)
Definition: timer_utils.cc:48
double end
final time
Definition: timer_utils.h:66
long d_time
current time instance index
Definition: timer_utils.h:62
long d_start
initial index in multiples of dt
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:33
double time_step
global reference time step
Definition: timer_utils.h:63
int add_neq_timer(const std::vector< double > &itrig, double idur, const char *iname, const char *poolname=nullptr)
Definition: timer_utils.cc:77
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:63
double start
initial time (nonzero when restarting)
Definition: timer_utils.h:64
long d_end
final index in multiples of dt
Definition: timer_utils.h:67
std::vector< base_timer * > timers
vector containing individual timers
Definition: timer_utils.h:69
double time
current time
Definition: timer_utils.h:61
char * dupstr(const char *old_str)
Definition: basics.cc:29
@ NONEQUDIST
Definition: timer_utils.h:34
long d_trigger_dur
discrete duration
Definition: timer_utils.h:43
int trigger_count
count number of triggered IO events
Definition: timer_utils.h:40
t_timer type
type of timer, continuous equidistant, or non-equidistant
Definition: timer_utils.h:37
const char * name
timer name
Definition: timer_utils.h:38
double trigger_dur
triggered event duration (e.g.,stim duration)
Definition: timer_utils.h:42
bool triggered
flag indicating trigger at current time step
Definition: timer_utils.h:39
void assign_pool(const char *poolname)
Definition: timer_utils.h:50
int numIOs
total number of triggers during simulation
Definition: timer_utils.h:41
int active
count down to end of a trigger with duration
Definition: timer_utils.h:44
long d_intv
discrete io interval in multiples of dt
Definition: timer_utils.h:210
double start
Time when we start I/O in mode _EQUDIST.
Definition: timer_utils.h:205
void initialize(const timer_manager *t, double istart, double iend, int ntrig, double iintv, double idur, const char *iname)
Definition: timer_utils.cc:91
double nxt
next output time in ms
Definition: timer_utils.h:211
double end
Time when we stop I/O in mode _EQUDIST.
Definition: timer_utils.h:207
const timer_manager * mng
Definition: timer_utils.h:203
long d_end
discrete stop index in multiples of dt
Definition: timer_utils.h:208
long d_start
discrete start in multiples of dt
Definition: timer_utils.h:206
long d_nxt
next output index
Definition: timer_utils.h:212
double intv
io interval in ms
Definition: timer_utils.h:209
std::vector< double > trig
the times that the timer will trigger
Definition: timer_utils.h:224
void initialize(const timer_manager *t, const std::vector< double > &itrig, const double idur, const char *iname)
Definition: timer_utils.cc:174
const timer_manager * mng
Definition: timer_utils.h:222
std::vector< long > d_trig
the discrete times associated to trig
Definition: timer_utils.h:225
Timers and timer manager.