NEURON
glinerec.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 // we want to plot correctly during the local step method when
3 // cvode.solve(tstop) is invoked. However, not all GraphLine are time graphs,
4 // so we assume that the time graphs will be added during stdinit
5 // during iteration over the graph lists of the stdrun implementation which
6 // calls Graph.simgraph(). Constantly updating during stdinit
7 // overcomes the problem of new addexpr, addval, and changed locations of
8 // point processes.
9 // Note: cvode.simgraph_remove() deletes all the GLineRecord instances.
10 
11 #include "hocparse.h"
12 #include "code.h"
13 #undef begin
14 #undef add
15 
16 #include "nrnoc2iv.h"
17 #include "vrecitem.h"
18 #include "netcvode.h"
19 #include "cvodeobj.h"
20 #include "utils/enumerate.h"
21 
22 #if HAVE_IV // to end of file
23 #include "graph.h"
24 #include "glinerec.h"
25 #include "ocjump.h"
26 
28 
29 static std::vector<GLineRecord*>* grl;
30 
31 // Since GraphLine is not an observable, its destructor calls this.
32 // So ivoc will work, a stub is placed in ivoc/datapath.cpp
33 void graphLineRecDeleted(GraphLine* gl) {
34  if (!grl) {
35  return;
36  }
37  for (auto& item: *grl) {
38  if (item->uses(gl)) {
39  delete item;
40  return;
41  }
42  }
43 }
44 
46  if (!grl) {
47  return;
48  }
49  for (auto& item: *grl) {
50  delete item;
51  }
52 }
53 
54 void Graph::simgraph() {
55  if (!grl) {
56  grl = new std::vector<GLineRecord*>();
57  }
58  for (auto& gl: line_list_) {
59  PlayRecord* pr = net_cvode_instance->playrec_uses(gl);
60  if (pr) {
61  delete pr;
62  }
63  GLineRecord* r = new GLineRecord(gl);
64  grl->push_back(r);
65  }
66 }
67 
68 void GLineRecord::fill_pd1() {
69  Inst* pcsav = hoc_pc;
70  for (hoc_pc = gl_->expr_->u.u_proc->defn.in;
71  hoc_pc->in != STOP;) { // run machine analogous to hoc_execute(inst);
72  double* pd = NULL;
73  Inst* pc1 = hoc_pc++; // must be incremented before the function return.
74  if (pc1->pf == rangepoint) {
75  hoc_pushx(0.5); // arc position
77  pd = hoc_pxpop();
78  hoc_pushx(*pd);
79  } else if (pc1->pf == rangevareval) {
81  pd = hoc_pxpop();
82  hoc_pushx(*pd);
83  } else if (pc1->pf == hoc_varpush) {
84  Symbol* sym = hoc_pc->sym;
85  if (strcmp(sym->name, "t") == 0) {
86  saw_t_ = true;
87  }
88  hoc_varpush();
89  } else {
90  (*((pc1)->pf))();
91  }
92  if (pd) {
93  pd_and_vec_.push_back(std::pair<double*, IvocVect*>(pd, NULL));
94  }
95  }
96  hoc_pc = pcsav;
97 
98 #if 0
99  Symbol* esym = gl_->expr_;
100  int sz = esym->u.u_proc->size;
101  Inst* inst = esym->u.u_proc->defn.in;
102  printf("\n%s\n", gl_->name());
103  for (int i = 0; i < sz; ++i) {
104  hoc_debugzz(inst + i);
105  }
106 #endif
107 }
108 
109 void GLineRecord::fill_pd() {
110  // Get rid of old pd_and_vec_ info.
111  for (auto& [_, elem]: pd_and_vec_) {
112  if (elem) {
113  delete elem;
114  }
115  }
116  pd_and_vec_.resize(0);
117  saw_t_ = false;
118  pd_ = gl_->pval_;
119  if (pd_) {
120  return;
121  }
122 
123  // Execute the expr Inst by Inst but when rangepoint or
124  // rangevareval are seen, execute a series of stack machine instructions
125  // that give us the pointer to the range variable (see the implementation
126  // in nrn/src/nrnoc/cabcode.cpp) but leaving the stack as though the
127  // original instruction was executed.
128  assert(gl_->expr_);
129  ObjectContext objc(gl_->obj_);
130  fill_pd1();
131 }
132 
134  : PlayRecord({}) {
135  // shouldnt be necessary but just in case
136  // printf("GLineRecord %p name=%s\n", this, gl->name());
137  gl_ = gl;
138  gl_->simgraph_activate(true);
139  v_ = NULL;
140  saw_t_ = false;
141 }
142 
144  : PlayRecord({})
145  , gv_{gv} {}
146 
148  new GVectorRecord(this);
149 }
150 
152 
154  if (v_) {
155  delete v_;
156  v_ = nullptr;
157  }
158 
159  for (auto& [_, vec]: pd_and_vec_) {
160  if (vec) {
161  delete vec;
162  }
163  }
164 
165  if (auto it = std::find(grl->rbegin(), grl->rend(), this); it != grl->rend()) {
166  gl_->simgraph_activate(false);
167  grl->erase(std::next(it).base()); // Reverse iterator need that
168  }
169 }
170 
172 
174  gl_->simgraph_init();
175 }
176 
178 
179 void GLineRecord::continuous(double t) {
181 }
182 
183 void GVectorRecord::continuous(double t) {}
184 
185 int GVectorRecord::count() {
186  return gv_->py_data()->count();
187 }
189  return gv_->py_data()->p(i);
190 }
191 
192 void GLineRecord::plot(int vecsz, double tstop) {
193  double dt = tstop / double(vecsz - 1);
194  DataVec* x = (DataVec*) gl_->x_data();
195  DataVec* y = (DataVec*) gl_->y_data();
196  if (v_) {
197  v_->resize(vecsz);
198  double* v = vector_vec(v_);
199  for (int i = 0; i < vecsz; ++i) {
200  x->add(dt * i);
201  y->add(v[i]);
202  }
203  } else if (gl_->expr_) {
204  // transfer elements to range variables and plot expression result
205  ObjectContext obc(NULL);
206  for (int i = 0; i < vecsz; ++i) {
207  x->add(dt * i);
208  for (auto& [pd, elem]: pd_and_vec_) {
209  *pd = elem->elem(i);
210  }
211  gl_->plot();
212  }
213  } else {
214  assert(0);
215  }
216 }
217 #else // do not HAVE_IV
219 #endif // HAVE_IV
void rangevareval(void)
Definition: cabcode.cpp:1373
void rangevarevalpointer()
Definition: cabcode.cpp:1339
void rangepoint(void)
Definition: cabcode.cpp:1382
std::size_t count()
Definition: graph.h:242
neuron::container::data_handle< double > p(std::size_t i)
Definition: graph.h:245
Definition: graph.h:196
void add(float)
void plot(int, double)
virtual void continuous(double t)
void fill_pd()
GLineRecord(GraphLine *)
virtual void record_init()
bool saw_t_
Definition: glinerec.h:35
GraphLine * gl_
Definition: glinerec.h:29
void fill_pd1()
IvocVect * v_
Definition: glinerec.h:30
GLineRecordEData pd_and_vec_
Definition: glinerec.h:34
virtual ~GLineRecord()
const DataVec * y_data() const
Definition: graph.h:294
const DataVec * x_data() const
Definition: graph.h:291
virtual void record_init()
GVectorRecord(GraphVector *)
virtual void continuous(double t)
neuron::container::data_handle< double > pdata(int)
GraphVector * gv_
Definition: glinerec.h:56
virtual ~GVectorRecord()
void simgraph()
std::vector< GraphLine * > line_list_
Definition: graph.h:166
neuron::container::data_handle< double > pval_
Definition: graph.h:366
void simgraph_init()
void plot()
const char * name() const
Object * obj_
Definition: graph.h:367
void simgraph_continuous(double)
void simgraph_activate(bool)
Symbol * expr_
Definition: graph.h:365
DataPointers * py_data()
Definition: graph.h:390
void record_uninstall()
void record_install()
void resize(size_t n)
Definition: ivocvect.h:46
void simgraph_remove()
Definition: glinerec.cpp:218
neuron::container::data_handle< double > pd_
Definition: vrecitem.h:90
void hoc_varpush()
Definition: code.cpp:994
#define v
Definition: md1redef.h:11
#define i
Definition: md1redef.h:19
double * hoc_pxpop()
Definition: code.cpp:922
#define assert(ex)
Definition: hocassrt.h:24
#define STOP
Definition: hocdec.h:57
void hoc_pushx(double)
Definition: code.cpp:779
printf
Definition: extdef.h:5
Item * next(Item *item)
Definition: list.cpp:89
double * vector_vec(IvocVect *v)
Definition: ivocvect.cpp:19
NetCvode * net_cvode_instance
Definition: netcvode.cpp:35
Inst * hoc_pc
Definition: code.cpp:78
static void pr(N_Vector x)
int find(const int, const int, const int, const int, const int)
#define NULL
Definition: spdefs.h:105
Inst defn
Definition: hocdec.h:67
unsigned long size
Definition: hocdec.h:68
Definition: model.h:47
Proc * u_proc
Definition: hocdec.h:120
union Symbol::@28 u
char * name
Definition: model.h:61
Definition: hocdec.h:42
Pfrv pf
Definition: hocdec.h:43
Symbol * sym
Definition: hocdec.h:52
Inst * in
Definition: hocdec.h:51