NEURON
vrecord.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 #if HAVE_IV
4 #include "ivoc.h"
5 #endif
6 #include "nrniv_mf.h"
7 #include "nrnoc2iv.h"
8 #include "ocobserv.h"
9 #include "ivocvect.h"
10 #include <stdio.h>
11 
12 #include "ocpointer.h"
13 #include "vrecitem.h"
14 #include "netcvode.h"
15 #include "cvodeobj.h"
16 
17 extern double t;
19 
20 // Vector.play_remove()
21 void nrn_vecsim_remove(void* v) {
22  PlayRecord* pr;
23  while ((pr = net_cvode_instance->playrec_uses(v)) != 0) {
24  delete pr;
25  }
26 }
27 
28 void nrn_vecsim_add(void* v, bool record) {
29  IvocVect *yvec, *tvec, *dvec;
30  extern short* nrn_is_artificial_;
31  char* s = NULL;
32  double ddt;
33  Object* ppobj = NULL;
34  int iarg = 0;
35 
36  yvec = (IvocVect*) v;
37 
38  if (hoc_is_object_arg(1)) {
39  iarg = 1;
40  ppobj = *hoc_objgetarg(1);
41  if (!ppobj || ppobj->ctemplate->is_point_ <= 0 ||
42  nrn_is_artificial_[ob2pntproc(ppobj)->prop->_type]) {
43  hoc_execerror("Optional first arg is not a POINT_PROCESS", 0);
44  }
45  }
47  if (record == false && hoc_is_str_arg(iarg + 1)) { // statement involving $1
48  // Vector.play("proced($1)", ...)
49  s = gargstr(iarg + 1);
50  } else if (record == false && hoc_is_double_arg(iarg + 1)) { // play that element
51  // Vector.play(index)
52  // must be a VecPlayStep and nothing else
54  if (vps) {
55  int j = (int) chkarg(iarg + 1, 0., yvec->size() - 1);
56  if (vps->si_) {
57  vps->si_->play_one(yvec->elem(j));
58  }
59  }
60  return;
61  } else {
62  // Vector.play(&SEClamp[0].amp1, ...)
63  // Vector.record(&SEClamp[0].i, ...)
64  dh = hoc_hgetarg<double>(iarg + 1);
65  }
66  tvec = NULL;
67  dvec = NULL;
68  ddt = -1.;
69  int con = 0;
70  if (ifarg(iarg + 2)) {
71  if (hoc_is_object_arg(iarg + 2)) {
72  // Vector...(..., tvec)
73  tvec = vector_arg(iarg + 2);
74  } else {
75  // Vector...(..., Dt)
76  ddt = chkarg(iarg + 2, 1e-9, 1e10);
77  }
78  if (ifarg(iarg + 3)) {
79  if (hoc_is_double_arg(iarg + 3)) {
80  con = (int) chkarg(iarg + 3, 0., 1.);
81  } else {
82  dvec = vector_arg(iarg + 3);
83  con = 1;
84  }
85  }
86  }
87 
88  // tvec can be used for many record/play items
89  // if (tvec) { nrn_vecsim_remove(tvec); }
90  if (record) {
91  // yvec can be used only for one record (but many play)
92  if (yvec) {
93  nrn_vecsim_remove(yvec);
94  }
95  if (tvec) {
96  new VecRecordDiscrete(std::move(dh), yvec, tvec, ppobj);
97  } else if (ddt > 0.) {
98  new VecRecordDt(std::move(dh), yvec, ddt, ppobj);
99  } else if (static_cast<double const*>(dh) == &t) {
100  new TvecRecord(chk_access(), yvec, ppobj);
101  } else {
102  new YvecRecord(std::move(dh), yvec, ppobj);
103  }
104  } else {
105  if (con) {
106  if (!tvec) {
108  "Second argument of Vector.play in continuous mode must be a time vector", 0);
109  }
110  if (s) {
111  new VecPlayContinuous(s, yvec, tvec, dvec, ppobj);
112  } else {
113  new VecPlayContinuous(std::move(dh), yvec, tvec, dvec, ppobj);
114  }
115  } else {
116  if (!tvec && ddt == -1.) {
117  chkarg(iarg + 2, 1e-9, 1e10);
118  }
119  if (s) {
120  new VecPlayStep(s, yvec, tvec, ddt, ppobj);
121  } else {
122  new VecPlayStep(std::move(dh), yvec, tvec, ddt, ppobj);
123  }
124  }
125  }
126 }
127 
129  IvocVect* y,
130  IvocVect* t,
131  double dt,
132  Object* ppobj)
133  : PlayRecord(std::move(dh), ppobj) {
134  // printf("VecPlayStep\n");
135  init(y, t, dt);
136 }
137 
138 VecPlayStep::VecPlayStep(const char* s, IvocVect* y, IvocVect* t, double dt, Object* ppobj)
139  : PlayRecord(chk_access()->pnode[0]->v_handle(), ppobj) {
140  // printf("VecPlayStep\n");
141  init(y, t, dt);
142  si_ = new StmtInfo(s);
143 }
144 
145 void VecPlayStep::init(IvocVect* y, IvocVect* t, double dt) {
146  y_ = y;
147  t_ = t;
148  dt_ = dt;
149  ObjObservable::Attach(y_->obj_, this);
150  if (t_) {
151  ObjObservable::Attach(t_->obj_, this);
152  }
153  e_ = new PlayRecordEvent();
154  e_->plr_ = this;
155  si_ = NULL;
156 }
157 
158 
160  // printf("~VecPlayStep\n");
161  ObjObservable::Detach(y_->obj_, this);
162  if (t_) {
163  ObjObservable::Detach(t_->obj_, this);
164  }
165  delete e_;
166  if (si_) {
167  delete si_;
168  }
169 }
170 
172  // printf("%s VecPlayStep disconnect\n", hoc_object_name(y_->obj_));
173  delete this;
174 }
175 
177  play_add(cv);
178 }
179 
181  current_index_ = 0;
182  NrnThread* nt = nrn_threads;
183  if (cvode_ && cvode_->nth_) {
184  nt = cvode_->nth_;
185  }
186  if (t_) {
187  if (t_->size() > 0) {
188  e_->send(t_->elem(0), net_cvode_instance, nt);
189  }
190  } else {
191  e_->send(0., net_cvode_instance, nt);
192  }
193 }
194 
195 void VecPlayStep::deliver(double tt, NetCvode* ns) {
196  NrnThread* nt = nrn_threads + ith_;
197  if (cvode_) {
199  if (cvode_->nth_) {
200  nt = cvode_->nth_;
201  }
202  }
203  if (si_) {
204  t = tt;
205  nrn_hoc_lock();
207  nrn_hoc_unlock();
208  } else {
209  auto const val = y_->elem(current_index_++);
210  if (pd_) {
211  *pd_ = val;
212  } else {
213  std::ostringstream oss;
214  oss << "VecPlayStep::deliver: invalid " << pd_;
215  throw std::runtime_error(std::move(oss).str());
216  }
217  }
218  if (current_index_ < y_->size()) {
219  if (t_) {
220  if (current_index_ < t_->size()) {
221  e_->send(t_->elem(current_index_), ns, nt);
222  }
223  } else {
224  e_->send(tt + dt_, ns, nt);
225  }
226  }
227 }
228 
229 
231  Printf("VecPlayStep ");
232  Printf("%s.x[%d]\n", hoc_object_name(y_->obj_), current_index_);
233 }
234 
236  IvocVect* y,
237  IvocVect* t,
238  IvocVect* discon,
239  Object* ppobj)
240  : PlayRecord(std::move(pd), ppobj) {
241  // printf("VecPlayContinuous\n");
242  init(y, t, discon);
243 }
244 
246  IvocVect* y,
247  IvocVect* t,
248  IvocVect* discon,
249  Object* ppobj)
250  : PlayRecord(chk_access()->pnode[0]->v_handle(), ppobj) {
251  // printf("VecPlayContinuous\n");
252  init(y, t, discon);
253  si_ = new StmtInfo(s);
254 }
255 
257  y_ = y;
258  t_ = t;
259  discon_indices_ = discon;
260  ubound_index_ = 0;
261  last_index_ = 0;
262  ObjObservable::Attach(y_->obj_, this);
263  if (t_) {
264  ObjObservable::Attach(t_->obj_, this);
265  }
266  if (discon_indices_) {
268  }
269  e_ = new PlayRecordEvent();
270  e_->plr_ = this;
271  si_ = NULL;
272 }
273 
274 
276  // printf("~VecPlayContinuous\n");
277  ObjObservable::Detach(y_->obj_, this);
278  ObjObservable::Detach(t_->obj_, this);
279  if (discon_indices_) {
281  }
282  delete e_;
283  if (si_) {
284  delete si_;
285  }
286 }
287 
289  // printf("%s VecPlayContinuous disconnect\n", hoc_object_name(y_->obj_));
290  delete this;
291 }
292 
294  play_add(cv);
295 }
296 
298  NrnThread* nt = nrn_threads;
299  if (cvode_ && cvode_->nth_) {
300  nt = cvode_->nth_;
301  }
302  last_index_ = 0;
303  discon_index_ = 0;
304  if (discon_indices_) {
305  if (discon_indices_->size() > 0) {
307  // printf("play_init %d %g\n", ubound_index_, t_->elem(ubound_index_));
309  } else {
310  ubound_index_ = t_->size() - 1;
311  }
312  } else {
313  ubound_index_ = 0;
315  }
316 }
317 
318 void VecPlayContinuous::deliver(double tt, NetCvode* ns) {
319  NrnThread* nt = nrn_threads + ith_;
320  if (cvode_) {
322  if (cvode_->nth_) {
323  nt = cvode_->nth_;
324  }
325  }
327  if (discon_indices_) {
328  if (discon_index_ < discon_indices_->size()) {
330  // printf("after deliver:send %d %g\n", ubound_index_, t_->elem(ubound_index_));
331  e_->send(t_->elem(ubound_index_), ns, nt);
332  } else {
333  ubound_index_ = t_->size() - 1;
334  }
335  } else {
336  if (ubound_index_ < t_->size() - 1) {
337  ubound_index_++;
338  e_->send(t_->elem(ubound_index_), ns, nt);
339  }
340  }
341  continuous(tt);
342 }
343 
344 
346  if (si_) {
347  t = tt;
348  nrn_hoc_lock();
349  si_->play_one(interpolate(tt));
350  nrn_hoc_unlock();
351  } else {
352  *pd_ = interpolate(tt);
353  }
354 }
355 
357  if (tt >= t_->elem(ubound_index_)) {
359  if (last_index_ == 0) {
360  // printf("return last tt=%g ubound=%g y=%g\n", tt, t_->elem(ubound_index_),
361  // y_->elem(last_index_));
362  return y_->elem(last_index_);
363  }
364  } else if (tt <= t_->elem(0)) {
365  last_index_ = 0;
366  // printf("return elem(0) tt=%g t0=%g y=%g\n", tt, t_->elem(0), y_->elem(0));
367  return y_->elem(0);
368  } else {
369  search(tt);
370  }
371  double x0 = y_->elem(last_index_ - 1);
372  double x1 = y_->elem(last_index_);
373  double t0 = t_->elem(last_index_ - 1);
374  double t1 = t_->elem(last_index_);
375  // printf("IvocVectRecorder::continuous tt=%g t0=%g t1=%g theta=%g x0=%g x1=%g\n", tt, t0, t1,
376  // (tt - t0)/(t1 - t0), x0, x1);
377  if (t0 == t1) {
378  return (x0 + x1) / 2.;
379  }
380  return interp((tt - t0) / (t1 - t0), x0, x1);
381 #if 0
382  // dt
383  double theta = tt/dt_ - last_index_;
384  interp(theta, x0, x1);
385 #endif
386 }
387 
388 void VecPlayContinuous::search(double tt) {
389  // assert (tt > t_->elem(0) && tt < t_->elem(t_->size() - 1))
390  while (tt < t_->elem(last_index_)) {
391  --last_index_;
392  }
393  while (tt >= t_->elem(last_index_)) {
394  ++last_index_;
395  }
396 }
397 
399  printf("VecPlayContinuous ");
400  printf("%s.x[%d]\n", hoc_object_name(y_->obj_), last_index_);
401 }
402 
404  return new VecPlayStepSave(this);
405 }
406 
408  : PlayRecordSave(prl) {
409  curindex_ = ((VecPlayStep*) pr_)->current_index_;
410 }
413  check();
414  VecPlayStep* vps = (VecPlayStep*) pr_;
415  vps->current_index_ = curindex_;
416  if (curindex_ > 0) {
417  if (vps->si_) {
418  vps->si_->play_one(vps->y_->elem(curindex_ - 1));
419  } else {
420  *vps->pd_ = vps->y_->elem(curindex_ - 1);
421  }
422  }
423 }
425  fprintf(f, "%d\n", curindex_);
426 }
428  char buf[100];
429  nrn_assert(fgets(buf, 100, f));
430  nrn_assert(sscanf(buf, "%d\n", &curindex_) == 1);
431 }
432 
434  return new VecPlayContinuousSave(this);
435 }
436 
438  : PlayRecordSave(prl) {
440  last_index_ = vpc->last_index_;
443 }
446  check();
448  vpc->last_index_ = last_index_;
451  vpc->continuous(t);
452 }
454  fprintf(f, "%d %d %d\n", last_index_, discon_index_, ubound_index_);
455 }
457  char buf[100];
458  nrn_assert(fgets(buf, 100, f));
459  nrn_assert(sscanf(buf, "%d %d %d\n", &last_index_, &discon_index_, &ubound_index_) == 3);
460 }
Section * chk_access()
Definition: cabcode.cpp:449
Definition: cvodeobj.h:97
NrnThread * nth_
Definition: cvodeobj.h:241
void set_init_flag()
Definition: cvodeobj.cpp:780
virtual void send(double deliverytime, NetCvode *, NrnThread *)
Definition: netcvode.cpp:2920
size_t size() const
Definition: ivocvect.h:42
Object * obj_
Definition: ivocvect.h:101
double & elem(int n)
Definition: ivocvect.h:26
PlayRecord * playrec_uses(void *)
Definition: netcvode.cpp:6045
static void Detach(Object *, Observer *)
Definition: ocobserv.cpp:23
static void Attach(Object *, Observer *)
Definition: ocobserv.cpp:16
PlayRecord * plr_
Definition: vrecitem.h:38
Cvode * cvode_
Definition: vrecitem.h:92
neuron::container::data_handle< double > pd_
Definition: vrecitem.h:90
void play_add(Cvode *)
Definition: netcvode.cpp:6091
int ith_
Definition: vrecitem.h:93
PlayRecord * pr_
Definition: vrecitem.h:105
void play_one(double)
Definition: ocpointer.cpp:154
void continuous(double tt)
Definition: vrecord.cpp:345
virtual void play_init()
Definition: vrecord.cpp:297
virtual void pr()
Definition: vrecord.cpp:398
VecPlayContinuous(neuron::container::data_handle< double > pd, IvocVect *y, IvocVect *t, IvocVect *discon, Object *ppobj=nullptr)
Definition: vrecord.cpp:235
virtual ~VecPlayContinuous()
Definition: vrecord.cpp:275
StmtInfo * si_
Definition: vrecitem.h:317
PlayRecordEvent * e_
Definition: vrecitem.h:316
IvocVect * discon_indices_
Definition: vrecitem.h:311
double interp(double th, double x0, double x1)
Definition: vrecitem.h:295
virtual void install(Cvode *)
Definition: vrecord.cpp:293
IvocVect * y_
Definition: vrecitem.h:309
virtual PlayRecordSave * savestate_save()
Definition: vrecord.cpp:433
virtual void disconnect(Observable *)
Definition: vrecord.cpp:288
IvocVect * t_
Definition: vrecitem.h:310
double interpolate(double tt)
Definition: vrecord.cpp:356
virtual void deliver(double t, NetCvode *)
Definition: vrecord.cpp:318
void search(double tt)
Definition: vrecord.cpp:388
void init(IvocVect *y, IvocVect *t, IvocVect *tdiscon)
Definition: vrecord.cpp:256
virtual ~VecPlayContinuousSave()
Definition: vrecord.cpp:444
VecPlayContinuousSave(PlayRecord *)
Definition: vrecord.cpp:437
virtual void savestate_write(FILE *)
Definition: vrecord.cpp:453
virtual void savestate_restore()
Definition: vrecord.cpp:445
virtual void savestate_read(FILE *)
Definition: vrecord.cpp:456
double dt_
Definition: vrecitem.h:255
virtual void install(Cvode *)
Definition: vrecord.cpp:176
virtual ~VecPlayStep()
Definition: vrecord.cpp:159
PlayRecordEvent * e_
Definition: vrecitem.h:258
int current_index_
Definition: vrecitem.h:256
virtual void disconnect(Observable *)
Definition: vrecord.cpp:171
IvocVect * t_
Definition: vrecitem.h:254
virtual void pr()
Definition: vrecord.cpp:230
IvocVect * y_
Definition: vrecitem.h:253
virtual PlayRecordSave * savestate_save()
Definition: vrecord.cpp:403
VecPlayStep(neuron::container::data_handle< double >, IvocVect *y, IvocVect *t, double dt, Object *ppobj=nullptr)
Definition: vrecord.cpp:128
void init(IvocVect *y, IvocVect *t, double dt)
Definition: vrecord.cpp:145
virtual void deliver(double t, NetCvode *)
Definition: vrecord.cpp:195
virtual void play_init()
Definition: vrecord.cpp:180
StmtInfo * si_
Definition: vrecitem.h:259
virtual void savestate_write(FILE *)
Definition: vrecord.cpp:424
VecPlayStepSave(PlayRecord *)
Definition: vrecord.cpp:407
virtual ~VecPlayStepSave()
Definition: vrecord.cpp:411
virtual void savestate_read(FILE *)
Definition: vrecord.cpp:427
virtual void savestate_restore()
Definition: vrecord.cpp:412
char * gargstr(int narg)
Definition: code2.cpp:227
#define v
Definition: md1redef.h:11
#define prop
Definition: md1redef.h:38
short * nrn_is_artificial_
Definition: cell_group.cpp:19
double chkarg(int, double low, double high)
Definition: code2.cpp:626
char buf[512]
Definition: init.cpp:13
int hoc_is_object_arg(int narg)
Definition: code.cpp:876
void nrn_hoc_unlock()
Definition: multicore.cpp:827
int hoc_is_str_arg(int narg)
Definition: code.cpp:872
int hoc_is_double_arg(int narg)
Definition: code.cpp:864
IvocVect * vector_arg(int i)
Definition: ivocvect.cpp:265
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:73
void nrn_hoc_lock()
Definition: multicore.cpp:819
Point_process * ob2pntproc(Object *ob)
Definition: hocmech.cpp:99
Object ** hoc_objgetarg(int)
Definition: code.cpp:1614
#define con(arg1, arg2, arg3)
Definition: consist.cpp:15
printf
Definition: extdef.h:5
void move(Item *q1, Item *q2, Item *q3)
Definition: list.cpp:200
NrnThread * nrn_threads
Definition: multicore.cpp:56
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
size_t j
s
Definition: multisend.cpp:521
void nrn_vecsim_add(void *v, bool record)
Definition: vrecord.cpp:28
double t
Definition: cvodeobj.cpp:57
void nrn_vecsim_remove(void *v)
Definition: vrecord.cpp:21
NetCvode * net_cvode_instance
Definition: cvodestb.cpp:26
int ifarg(int)
Definition: code.cpp:1607
static void pr(N_Vector x)
static void pnode(Prop *)
Definition: psection.cpp:47
#define NULL
Definition: spdefs.h:105
Represent main neuron object computed by single thread.
Definition: multicore.h:58
Definition: hocdec.h:173
cTemplate * ctemplate
Definition: hocdec.h:180
int is_point_
Definition: hocdec.h:150
int Printf(const char *fmt, Args... args)
Definition: logger.hpp:18