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