NEURON
savstate.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #undef check
3 #include <InterViews/resource.h>
4 #include <stdio.h>
5 #include <inttypes.h>
6 #include "ocfile.h"
7 #include "nrncvode.h"
8 #include "nrnoc2iv.h"
9 #include "classreg.h"
10 #include "nrniv_mf.h"
11 
12 #include "tqueue.hpp"
13 #include "netcon.h"
14 #include "vrecitem.h"
15 #include "utils/enumerate.h"
16 
17 typedef void (*ReceiveFunc)(Point_process*, double*, double);
18 
19 #include "membfunc.h"
20 extern int section_count;
21 extern "C" void nrn_shape_update();
22 extern Section** secorder;
23 extern ReceiveFunc* pnt_receive;
26 extern std::vector<PreSyn*>* net_cvode_instance_psl();
27 extern std::vector<PlayRecord*>* net_cvode_instance_prl();
28 extern double t;
29 extern short* nrn_is_artificial_;
30 static void tqcallback(const TQItem* tq, int i);
31 void (*nrnpy_restore_savestate)(int64_t, char*) = NULL;
32 void (*nrnpy_store_savestate)(char** save_data, uint64_t* save_data_size) = NULL;
33 
34 #define ASSERTfgets(a, b, c) nrn_assert(fgets(a, b, c) != 0)
35 #define ASSERTfread(a, b, c, d) nrn_assert(fread(a, b, c, d) == c)
36 #define ASSERTfwrite(a, b, c, d) nrn_assert(fwrite(a, b, c, d) == c)
37 
38 class SaveState: public Resource {
39  public:
40  SaveState();
41  ~SaveState();
42  virtual void save();
43  virtual void restore(int type);
44  virtual void read(OcFile*, bool close);
45  virtual void write(OcFile*, bool close);
46  struct NodeState {
47  double v;
48  int nmemb;
49  int* type;
50  int nstate;
51  double* state;
52  };
53  struct SecState {
55  int nnode;
56  struct NodeState* ns;
57  struct NodeState* root; // non-zero for rootnode
58  };
59  struct StateStructInfo {
60  int offset;
61  int size;
62  };
63  struct ACellState {
64  int type;
65  int ncell;
66  double* state;
67  };
68  struct NetConState {
69  int object_index; // for checking
70  int nstate;
71  double* state;
72  };
73  struct PreSynState {
74  bool flag; // is it firing?
75  double valthresh, valold, told;
76  };
77  struct TQState {
78  int nstate;
79  double* tdeliver;
81  };
82 
83  private:
84  bool check(bool warn);
85  void alloc();
86  void ssfree();
87  void ssi_def();
88 
89  private:
90  void fread_NodeState(NodeState*, int, FILE*);
91  void fwrite_NodeState(NodeState*, int, FILE*);
92  void fread_SecState(SecState*, int, FILE*);
93  void fwrite_SecState(SecState*, int, FILE*);
94 
95  private:
96  double t_;
97  int nroot_;
98  int nsec_;
100  int nacell_; // number of types
102  int nncs_;
104  int npss_;
107  int tqcnt_; // volatile for index of forall_callback
108  int nprs_;
113  uint64_t plugin_size_;
114 
115  private:
116  void savenode(NodeState&, Node*);
117  void restorenode(NodeState&, Node*);
118  bool checknode(NodeState&, Node*, bool);
119  void allocnode(NodeState&, Node*);
120 
121  void saveacell(ACellState&, int type);
122  void restoreacell(ACellState&, int type);
123  bool checkacell(ACellState&, int type, bool);
124  void allocacell(ACellState&, int type);
125 
126  void savenet();
127  void restorenet();
128  void readnet(FILE*);
129  void writenet(FILE*);
130  bool checknet(bool);
131  void allocnet();
132  void free_tq();
133  void alloc_tq();
134 
135  public:
136  void tqcount(const TQItem*, int);
137  void tqsave(const TQItem*, int);
138 };
139 
141 static int callback_mode;
142 
143 void tqcallback(const TQItem* tq, int i) {
144  if (callback_mode == 0) {
145  this_savestate->tqcount(tq, i);
146  } else {
147  this_savestate->tqsave(tq, i);
148  }
149 }
150 
152  int i, j;
153  nct = NULL;
154  ssi_def();
155  nroot_ = 0;
156  ss_ = NULL;
157  nsec_ = 0;
158  nncs_ = 0;
159  ncs_ = NULL;
160  npss_ = 0;
161  pss_ = NULL;
162  tqs_ = new TQState();
163  tqs_->nstate = 0;
164  nprs_ = 0;
165  prs_ = NULL;
166  nacell_ = 0;
167  plugin_data_ = NULL;
168  plugin_size_ = 0;
169  for (i = 0; i < n_memb_func; ++i)
170  if (nrn_is_artificial_[i]) {
171  ++nacell_;
172  }
173  acell_ = new ACellState[nacell_];
174  for (i = 0; i < nacell_; ++i) {
175  acell_[i].ncell = 0;
176  acell_[i].state = 0;
177  }
178  for (i = 0, j = 0; i < n_memb_func; ++i)
179  if (nrn_is_artificial_[i]) {
180  acell_[j].type = i;
181  ++j;
182  }
183 }
184 
186  ssfree();
187  delete tqs_;
188  delete[] acell_;
189  delete[] ssi;
190 }
191 
192 void SaveState::fread_NodeState(NodeState* ns, int cnt, FILE* f) {
193  for (int i = 0; i < cnt; ++i) {
194  ASSERTfread(&ns[i].v, sizeof(double), 1, f);
195  ASSERTfread(&ns[i].nmemb, sizeof(int), 1, f);
196  ASSERTfread(&ns[i].nstate, sizeof(int), 1, f);
197  }
198 }
199 void SaveState::fwrite_NodeState(NodeState* ns, int cnt, FILE* f) {
200  for (int i = 0; i < cnt; ++i) {
201  ASSERTfwrite(&ns[i].v, sizeof(double), 1, f);
202  ASSERTfwrite(&ns[i].nmemb, sizeof(int), 1, f);
203  ASSERTfwrite(&ns[i].nstate, sizeof(int), 1, f);
204  }
205 }
206 void SaveState::fread_SecState(SecState* ss, int cnt, FILE* f) {
207  int b;
208  for (int i = 0; i < cnt; ++i) {
209  ASSERTfread(&ss[i].nnode, sizeof(int), 1, f);
210  ASSERTfread(&b, sizeof(int), 1, f);
211  if (b) {
212  ss[i].root = new NodeState;
213  } else {
214  ss[i].root = 0;
215  }
216  }
217 }
218 void SaveState::fwrite_SecState(SecState* ss, int cnt, FILE* f) {
219  int b;
220  for (int i = 0; i < cnt; ++i) {
221  ASSERTfwrite(&ss[i].nnode, sizeof(int), 1, f);
222  b = ss[i].root ? 1 : 0;
223  ASSERTfwrite(&b, sizeof(int), 1, f);
224  }
225 }
226 
228  if (nct) {
229  return;
230  }
231  Symbol* s = hoc_lookup("NetCon");
232  nct = s->u.ctemplate;
234  for (int im = 0; im < n_memb_func; ++im) {
235  ssi[im].offset = -1;
236  ssi[im].size = 0;
237  if (!memb_func[im].sym) {
238  continue;
239  }
240  // generally we only save STATE variables. However for
241  // models containing a NET_RECEIVE block, we also need to
242  // save everything except the parameters
243  // because they often contain
244  // logic and analytic state values. Unfortunately, it is often
245  // the case that the ASSIGNED variables are not declared as
246  // RANGE variables so to avoid missing state, save the whole
247  // param array including PARAMETERs.
248  if (pnt_receive[im]) {
249  ssi[im].offset = 0;
250  ssi[im].size = nrn_prop_param_size_[im];
251  } else {
252  int type = STATE;
253  const Symbol* msym = memb_func[im].sym;
254  for (int i = 0; i < msym->s_varn; ++i) {
255  Symbol* sym = msym->u.ppsym[i];
256  int vartype = nrn_vartype(sym);
257  if (vartype == type || vartype == STATE || vartype == _AMBIGUOUS) {
258  if (ssi[im].offset < 0) {
259  ssi[im].offset = sym->u.rng.index;
260  } else {
261  // assert what we assume: that after this code the variables we want are
262  // `size` contiguous legacy indices starting at `offset`
263  assert(ssi[im].offset + ssi[im].size == sym->u.rng.index);
264  }
265  ssi[im].size += hoc_total_array_data(sym, 0);
266  }
267  }
268  }
269  }
270 }
271 
272 bool SaveState::check(bool warn) {
273  hoc_Item* qsec;
274  int isec;
275  if (nsec_ != section_count) {
276  if (warn) {
277  fprintf(stderr,
278  "SaveState warning: %d sections exist but saved %d\n",
280  nsec_);
281  }
282  return false;
283  }
284  if (nroot_ != nrn_global_ncell) {
285  if (warn) {
286  fprintf(stderr,
287  "SaveState warning: %d cells exist but saved %d\n",
289  nroot_);
290  }
291  return false;
292  }
293  if (nsec_ && ss_[0].sec == NULL) { // got the data from a read
294  isec = 0;
295  // ForAllSections(sec)
296  ITERATE(qsec, section_list) {
297  Section* sec = hocSEC(qsec);
298  ss_[isec].sec = sec;
299  section_ref(ss_[isec].sec);
300  ++isec;
301  }
302  }
303  for (int i = 0, j = 0; i < n_memb_func; ++i)
304  if (nrn_is_artificial_[i]) {
305  if (!checkacell(acell_[j], i, warn)) {
306  return false;
307  }
308  ++j;
309  }
310  for (int isec = 0; isec < nsec_; ++isec) {
311  SecState& ss = ss_[isec];
312  Section* sec = ss.sec;
313  if (!sec->prop || sec->nnode != ss.nnode) {
314  if (warn) {
315  if (!sec->prop) {
316  fprintf(stderr, "SaveState warning: saved section no longer exists\n");
317  } else {
318  fprintf(stderr,
319  "SaveState warning: %s has %d nodes but saved %d\n",
320  secname(sec),
321  sec->nnode,
322  ss.nnode);
323  }
324  }
325  return false;
326  }
327  for (int inode = 0; inode < ss.nnode; ++inode) {
328  NodeState& ns = ss.ns[inode];
329  Node* nd = sec->pnode[inode];
330  int i = 0;
331  Prop* p;
332  for (p = nd->prop; p; p = p->next) {
333  if (ssi[p->_type].size == 0) {
334  continue;
335  }
336  if (i >= ns.nmemb) {
337  if (warn) {
338  fprintf(stderr,
339  "SaveState warning: \
340 fewer mechanisms saved than exist at node %d of %s\n",
341  inode,
342  secname(sec));
343  }
344  return false;
345  }
346  if (p->_type != ns.type[i]) {
347  if (warn) {
348  fprintf(stderr,
349  "SaveState warning: mechanisms out of order at node %d of %s\n\
350 saved %s but need %s\n",
351  inode,
352  secname(sec),
353  memb_func[i].sym->name,
354  memb_func[p->_type].sym->name);
355  }
356  return false;
357  }
358  ++i;
359  }
360  if (i != ns.nmemb) {
361  if (warn) {
362  fprintf(
363  stderr,
364  "SaveState warning: more mechanisms saved than exist at node %d of %s\n",
365  inode,
366  secname(sec));
367  }
368  return false;
369  }
370  }
371  if (!sec->parentsec || ss.root) {
372  if (sec->parentsec || !ss.root) {
373  if (warn) {
374  fprintf(stderr,
375  "SaveState warning: Saved section and %s are not both root sections.\n",
376  secname(sec));
377  }
378  }
379  if (!checknode(*ss.root, sec->parentnode, warn)) {
380  return false;
381  }
382  }
383  }
384  if (!checknet(warn)) {
385  return false;
386  }
387  return true;
388 }
389 
390 bool SaveState::checknode(NodeState& ns, Node* nd, bool warn) {
391  int i = 0;
392  Prop* p;
393  for (p = nd->prop; p; p = p->next) {
394  if (ssi[p->_type].size == 0) {
395  continue;
396  }
397  if (i >= ns.nmemb) {
398  if (warn) {
399  fprintf(stderr,
400  "SaveState warning: \
401 fewer mechanisms saved than exist at a root node\n");
402  }
403  return false;
404  }
405  if (p->_type != ns.type[i]) {
406  if (warn) {
407  fprintf(stderr,
408  "SaveState warning: mechanisms out of order at a rootnode\n\
409 saved %s but need %s\n",
410  memb_func[i].sym->name,
411  memb_func[p->_type].sym->name);
412  }
413  return false;
414  }
415  ++i;
416  }
417  if (i != ns.nmemb) {
418  if (warn) {
419  fprintf(stderr, "SaveState warning: more mechanisms saved than exist at a rootnode\n");
420  }
421  return false;
422  }
423  return true;
424 }
425 
426 bool SaveState::checkacell(ACellState& ac, int type, bool warn) {
427  if (memb_list[type].nodecount != ac.ncell) {
428  if (warn) {
429  fprintf(stderr,
430  "SaveState warning: different number of %s saved than exist.\n",
431  memb_func[type].sym->name);
432  }
433  return false;
434  }
435  return true;
436 }
437 
439  ssfree();
440  int inode, isec;
441  hoc_Item* qsec;
443  if (nsec_) {
444  ss_ = new SecState[nsec_];
445  }
446  nroot_ = 0;
447  isec = 0;
448  // ForAllSections(sec)
449  ITERATE(qsec, section_list) {
450  Section* sec = hocSEC(qsec);
451  SecState& ss = ss_[isec];
452  ss.sec = sec;
453  section_ref(ss.sec);
454  ss.nnode = ss.sec->nnode;
455  ss.ns = new NodeState[ss.nnode];
456  for (inode = 0; inode < ss.nnode; ++inode) {
457  Node* nd = ss.sec->pnode[inode];
458  NodeState& ns = ss.ns[inode];
459  allocnode(ns, nd);
460  }
461  if (!sec->parentsec) {
462  assert(sec->parentnode);
463  ss.root = new NodeState;
464  allocnode(*ss.root, sec->parentnode);
465  ++nroot_;
466  } else {
467  ss.root = 0;
468  }
469  ++isec;
470  }
471  assert(isec == section_count);
473  for (int i = 0, j = 0; i < n_memb_func; ++i)
474  if (nrn_is_artificial_[i]) {
475  allocacell(acell_[j], i);
476  ++j;
477  }
478  std::vector<PlayRecord*>* prl = net_cvode_instance_prl();
479  nprs_ = prl->size();
480  if (nprs_) {
481  prs_ = new PlayRecordSave*[nprs_];
482  }
483  allocnet();
484 }
485 
487  ns.nmemb = 0;
488  ns.type = NULL;
489  ns.state = NULL;
490  ns.nstate = 0;
491  Prop* p;
492  for (p = nd->prop; p; p = p->next) {
493  if (ssi[p->_type].size == 0) {
494  continue;
495  }
496  ++ns.nmemb;
497  ns.nstate += ssi[p->_type].size;
498  }
499  if (ns.nmemb) {
500  ns.type = new int[ns.nmemb];
501  }
502  if (ns.nstate) {
503  ns.state = new double[ns.nstate];
504  }
505  int i = 0;
506  for (p = nd->prop; p; p = p->next) {
507  if (ssi[p->_type].size == 0) {
508  continue;
509  }
510  ns.type[i] = p->_type;
511  ++i;
512  }
513 }
514 
516  Memb_list& ml = memb_list[type];
517  ac.type = type;
518  ac.ncell = ml.nodecount;
519  if (ac.ncell) {
520  ac.state = new double[ac.ncell * ssi[type].size];
521  }
522 }
523 
525  int i, isec, inode;
526  for (isec = 0; isec < nsec_; ++isec) {
527  SecState& ss = ss_[isec];
528  for (inode = 0; inode < ss.nnode; ++inode) {
529  NodeState& ns = ss.ns[inode];
530  if (ns.nmemb) {
531  delete[] ns.type;
532  }
533  if (ns.nstate) {
534  delete[] ns.state;
535  }
536  }
537  if (ss.root) {
538  NodeState& ns = *ss.root;
539  if (ns.nmemb) {
540  delete[] ns.type;
541  }
542  if (ns.nstate) {
543  delete[] ns.state;
544  }
545  delete ss.root;
546  }
547  if (ss.nnode) {
548  delete[] ss.ns;
549  }
550  if (ss.sec) { // got info from an fread but never checked it
551  section_unref(ss.sec);
552  }
553  }
554  if (nsec_) {
555  delete[] ss_;
556  }
557  nsec_ = 0;
558  ss_ = NULL;
559  for (i = 0; i < nacell_; ++i) {
560  if (acell_[i].ncell) {
561  delete[] acell_[i].state;
562  acell_[i].state = 0;
563  acell_[i].ncell = 0;
564  }
565  } // note we do not destroy the acell_.
566  if (nncs_) {
567  for (i = 0; i < nncs_; ++i) {
568  if (ncs_[i].nstate) {
569  delete[] ncs_[i].state;
570  }
571  }
572  delete[] ncs_;
573  }
574  nncs_ = 0;
575  ncs_ = NULL;
576  if (npss_) {
577  delete[] pss_;
578  }
579  npss_ = 0;
580  pss_ = NULL;
581  free_tq();
582  if (nprs_) {
583  for (i = 0; i < nprs_; ++i) {
584  delete prs_[i];
585  }
586  delete[] prs_;
587  }
588  nprs_ = 0;
589  if (plugin_data_) {
590  delete[] plugin_data_;
591  plugin_data_ = NULL;
592  plugin_size_ = 0;
593  }
594 }
595 
597  if (!check(false)) {
598  alloc();
599  }
600  for (const NrnThread* nt: for_threads(nrn_threads, nrn_nthread)) {
601  assert(t == nt->_t);
602  }
603  t_ = t;
604  for (int isec = 0; isec < nsec_; ++isec) {
605  SecState& ss = ss_[isec];
606  Section* sec = ss.sec;
607  for (int inode = 0; inode < ss.nnode; ++inode) {
608  NodeState& ns = ss.ns[inode];
609  Node* nd = sec->pnode[inode];
610  savenode(ns, nd);
611  }
612  if (ss.root) {
613  NodeState& ns = *ss.root;
614  Node* nd = sec->parentnode;
615  savenode(ns, nd);
616  }
617  }
618  for (int i = 0, j = 0; i < n_memb_func; ++i)
619  if (nrn_is_artificial_[i]) {
620  saveacell(acell_[j], i);
621  ++j;
622  }
623  if (nprs_) {
624  std::vector<PlayRecord*>* prl = net_cvode_instance_prl();
625  assert(nprs_ == prl->size());
626  for (auto&& [i, e]: enumerate(*prl)) {
627  prs_[i] = e->savestate_save();
628  }
629  }
630  savenet();
631  if (nrnpy_store_savestate) {
633  } else {
634  plugin_size_ = 0;
635  plugin_data_ = NULL;
636  }
637 }
638 
640  ns.v = NODEV(nd);
641  int istate = 0;
642  for (Prop* p = nd->prop; p; p = p->next) {
643  if (ssi[p->_type].size == 0) {
644  continue;
645  }
646  int type = p->_type;
647  int max = ssi[type].offset + ssi[type].size;
648 #if EXTRACELLULAR
649  if (type == EXTRACELL) {
650  for (int i = 0; i < nlayer; ++i) {
651  ns.state[istate++] = nd->extnode->v[i];
652  }
653  } else
654 #endif
655  {
656  for (int ip = ssi[type].offset; ip < max; ++ip) {
657  ns.state[istate++] = p->param_legacy(ip);
658  }
659  }
660  }
661 }
662 
664  Memb_list& ml = memb_list[type];
665  int sz = ssi[type].size;
666  double* p = ac.state;
667  for (int i = 0; i < ml.nodecount; ++i) {
668  for (int j = 0; j < sz; ++j) {
669  (*p++) = ml.data(i, j);
670  }
671  }
672 }
673 
675  if (!check(true)) {
676  hoc_execerror("SaveState:", "Stored state inconsistent with current neuron structure");
677  }
678  t = t_;
680  nt->_t = t_;
681  }
682  for (int isec = 0; isec < nsec_; ++isec) {
683  SecState& ss = ss_[isec];
684  Section* sec = ss.sec;
685  for (int inode = 0; inode < ss.nnode; ++inode) {
686  NodeState& ns = ss.ns[inode];
687  Node* nd = sec->pnode[inode];
688  restorenode(ns, nd);
689  }
690  if (ss.root) {
691  NodeState& ns = *ss.root;
692  Node* nd = sec->parentnode;
693  restorenode(ns, nd);
694  }
695  }
696  for (int i = 0, j = 0; i < n_memb_func; ++i)
697  if (nrn_is_artificial_[i]) {
698  restoreacell(acell_[j], i);
699  ++j;
700  }
701  if (type == 1) {
702  return;
703  }
704  std::vector<PlayRecord*>* prl = net_cvode_instance_prl();
705  // during a local step prl is augmented with GLineRecord
706  // assert(nprs_ == prl->count());
707  assert(nprs_ <= prl->size());
708  for (int i = 0; i < nprs_; ++i) {
710  }
711  restorenet();
712  if (plugin_size_) {
714  hoc_execerror("SaveState:", "This state requires Python to unpack.");
715  }
717  }
718 }
719 
721  nd->v() = ns.v;
722  int istate = 0;
723  for (Prop* p = nd->prop; p; p = p->next) {
724  if (ssi[p->_type].size == 0) {
725  continue;
726  }
727  int type = p->_type;
728  int max = ssi[type].offset + ssi[type].size;
729 #if EXTRACELLULAR
730  if (type == EXTRACELL) {
731  for (int i = 0; i < nlayer; ++i) {
732  nd->extnode->v[i] = ns.state[istate++];
733  }
734  } else
735 #endif
736  {
737  for (int ip = ssi[type].offset; ip < max; ++ip) {
738  p->param_legacy(ip) = ns.state[istate++];
739  }
740  }
741  }
742 }
743 
745  Memb_list& ml = memb_list[type];
746  int sz = ssi[type].size;
747  double* p = ac.state;
748  for (int i = 0; i < ml.nodecount; ++i) {
749  for (int j = 0; j < sz; ++j) {
750  ml.data(i, j) = (*p++);
751  }
752  }
753 }
754 
755 void SaveState::read(OcFile* ocf, bool close) {
756  int version = 6;
757  if (!ocf->open(ocf->get_name(), "r")) {
758  hoc_execerror("Couldn't open file for reading:", ocf->get_name());
759  }
761  BinaryMode(ocf) FILE* f = ocf->file();
762  ssfree();
763  char buf[200];
764  ASSERTfgets(buf, 200, f);
765  if (strcmp(buf, "SaveState binary file version 6.0\n") != 0) {
766  if (strcmp(buf, "SaveState binary file version 7.0\n") == 0) {
767  version = 7;
768  } else {
769  ocf->close();
770  hoc_execerror("Bad SaveState binary file", " Neither version 6.0 or 7.0");
771  }
772  }
773  ASSERTfread(&t_, sizeof(double), 1, f);
774  // fscanf(f, "%d %d\n", &nsec_, &nrootnode_);
775  // on some os's fscanf leaves file pointer at wrong place for next fread
776  // can check it with ftell(f)
777  ASSERTfgets(buf, 200, f);
778  sscanf(buf, "%d %d\n", &nsec_, &nroot_);
779  // to enable comparison of SaveState files, we avoid
780  // putting pointers in the files and instead explicitly read/write
781  // structure elements.
782  if (nsec_) {
783  ss_ = new SecState[nsec_];
784  fread_SecState(ss_, nsec_, f);
785  }
786  for (int isec = 0; isec < nsec_; ++isec) {
787  SecState& ss = ss_[isec];
788  ss.sec = NULL;
789  ss.ns = new NodeState[ss.nnode];
790  fread_NodeState(ss.ns, ss.nnode, f);
791  for (int inode = 0; inode < ss.nnode; ++inode) {
792  NodeState& ns = ss.ns[inode];
793  if (ns.nmemb) {
794  ns.type = new int[ns.nmemb];
795  ASSERTfread(ns.type, sizeof(int), ns.nmemb, f);
796  }
797  if (ns.nstate) {
798  ns.state = new double[ns.nstate];
799  ASSERTfread(ns.state, sizeof(double), ns.nstate, f);
800  }
801  }
802  if (ss.root) {
803  fread_NodeState(ss.root, 1, f);
804  NodeState& ns = *ss.root;
805  if (ns.nmemb) {
806  ns.type = new int[ns.nmemb];
807  ASSERTfread(ns.type, sizeof(int), ns.nmemb, f);
808  }
809  if (ns.nstate) {
810  ns.state = new double[ns.nstate];
811  ASSERTfread(ns.state, sizeof(double), ns.nstate, f);
812  }
813  }
814  }
815  int n = 0;
816  ASSERTfgets(buf, 20, f);
817  sscanf(buf, "%d\n", &n);
818  assert(n == nacell_);
819  for (int i = 0, j = 0; i < n_memb_func; ++i)
820  if (nrn_is_artificial_[i]) {
821  int nt = 0, nc = 0, ns = 0;
822  ASSERTfgets(buf, 200, f);
823  nrn_assert(sscanf(buf, "%d %d %d\n", &nt, &nc, &ns) == 3);
824  assert(nt == i && nc == memb_list[i].nodecount);
825  assert(ns == nc * ssi[i].size);
826  acell_[j].ncell = nc;
827  if (nc) {
828  acell_[j].state = new double[ns];
829  ASSERTfread(acell_[j].state, sizeof(double), ns, f);
830  }
831  ++j;
832  }
833  ASSERTfgets(buf, 20, f);
834  sscanf(buf, "%d\n", &nprs_);
835  if (nprs_) {
836  prs_ = new PlayRecordSave*[nprs_];
837  for (int i = 0; i < nprs_; ++i) {
839  }
840  }
841  readnet(f);
842  // any old plugin information is no longer relevant regardless of what version
843  if (plugin_data_) {
844  delete[] plugin_data_;
845  plugin_data_ = NULL;
846  }
847  plugin_size_ = 0;
848  // if version 7, load new plugin data
849  if (version == 7) {
850  ASSERTfread(&plugin_size_, sizeof(int64_t), 1, f);
851  try {
852  plugin_data_ = new char[plugin_size_];
853  } catch (const std::bad_alloc& e) {
854  ocf->close();
855  hoc_execerror("SaveState:", "Failed to allocate memory.");
856  }
857  if (plugin_data_ == NULL) {
858  ocf->close();
859  hoc_execerror("SaveState:", "Failed to allocate memory.");
860  }
861  ASSERTfread(plugin_data_, sizeof(char), plugin_size_, f);
862  }
863  if (close) {
864  ocf->close();
865  }
866 }
867 
868 void SaveState::write(OcFile* ocf, bool close) {
869  if (!ocf->open(ocf->get_name(), "w")) {
870  hoc_execerror("Couldn't open file for writing:", ocf->get_name());
871  }
872  BinaryMode(ocf) FILE* f = ocf->file();
873  int version = plugin_size_ ? 7 : 6;
874  fprintf(f, "SaveState binary file version %d.0\n", version);
875  ASSERTfwrite(&t_, sizeof(double), 1, f);
876  fprintf(f, "%d %d\n", nsec_, nroot_);
878  for (int isec = 0; isec < nsec_; ++isec) {
879  SecState& ss = ss_[isec];
880  fwrite_NodeState(ss.ns, ss.nnode, f);
881  for (int inode = 0; inode < ss.nnode; ++inode) {
882  NodeState& ns = ss.ns[inode];
883  if (ns.nmemb) {
884  ASSERTfwrite(ns.type, sizeof(int), ns.nmemb, f);
885  }
886  if (ns.nstate) {
887  ASSERTfwrite(ns.state, sizeof(double), ns.nstate, f);
888  }
889  }
890  if (ss.root) {
891  fwrite_NodeState(ss.root, 1, f);
892  NodeState& ns = *ss.root;
893  if (ns.nmemb) {
894  ASSERTfwrite(ns.type, sizeof(int), ns.nmemb, f);
895  }
896  if (ns.nstate) {
897  ASSERTfwrite(ns.state, sizeof(double), ns.nstate, f);
898  }
899  }
900  }
901  fprintf(f, "%d\n", nacell_);
902  for (int i = 0, j = 0; i < n_memb_func; ++i)
903  if (nrn_is_artificial_[i]) {
904  int sz = acell_[j].ncell * ssi[i].size;
905  fprintf(f, "%d %d %d\n", acell_[j].type, acell_[j].ncell, sz);
906  ASSERTfwrite(acell_[j].state, sizeof(double), sz, f);
907  ++j;
908  }
909  fprintf(f, "%d\n", nprs_);
910  for (int i = 0; i < nprs_; ++i) {
911  fprintf(f, "%d %d\n", prs_[i]->pr_->type(), i);
912  prs_[i]->savestate_write(f);
913  }
914  writenet(f);
915  if (version == 7) {
916  ASSERTfwrite(&plugin_size_, sizeof(int64_t), 1, f);
918  }
919  if (close) {
920  ocf->close();
921  }
922 }
923 
925  hoc_Item* q;
926  int i = 0;
927  ITERATE(q, nct->olist) {
928  Object* ob = OBJ(q);
929  const NetCon* d = (NetCon*) ob->u.this_pointer;
930  int n = ncs_[i].nstate;
931  double* w = ncs_[i].state;
932  for (int j = 0; j < n; ++j) {
933  w[j] = d->weight_[j];
934  }
935  ++i;
936  }
937  if (int i = 0; net_cvode_instance_psl()) {
938  for (PreSyn* ps: *net_cvode_instance_psl()) {
939  ps->hi_index_ = i;
940  pss_[i].flag = ps->flag_;
941  pss_[i].valthresh = ps->valthresh_;
942  pss_[i].valold = ps->valold_;
943  pss_[i].told = ps->told_;
944  ++i;
945  }
946  }
947  alloc_tq();
948  tqcnt_ = 0;
951  this_savestate = this;
952  callback_mode = 1;
954  }
955 }
956 
957 void SaveState::tqcount(const TQItem*, int) {
958  ++tqcnt_;
959 }
960 
961 void SaveState::tqsave(const TQItem* q, int) {
962  DiscreteEvent* de = (DiscreteEvent*) q->data_;
963  tqs_->tdeliver[tqcnt_] = q->t_;
964  tqs_->items[tqcnt_] = de->savestate_save();
965  ++tqcnt_;
966 }
967 
969  // NetCon's
970  int i = 0;
971  hoc_Item* q;
972  ITERATE(q, nct->olist) {
973  Object* ob = OBJ(q);
974  NetCon* d = (NetCon*) ob->u.this_pointer;
975  int n = ncs_[i].nstate;
976  const double* w = ncs_[i].state;
977  for (int j = 0; j < n; ++j) {
978  d->weight_[j] = w[j];
979  }
980  ++i;
981  }
982  // PreSyn's
983  if (int i = 0; net_cvode_instance_psl())
984  for (PreSyn* ps: *net_cvode_instance_psl()) {
985  ps->hi_index_ = i;
986  ps->flag_ = pss_[i].flag;
987  ps->valthresh_ = pss_[i].valthresh;
988  ps->valold_ = pss_[i].valold;
989  ps->told_ = pss_[i].told;
990  ++i;
991  }
992 
993  // event queue
994  // clear it
996  // restore it
997  for (int i = 0; i < tqs_->nstate; ++i) {
999  }
1000 }
1001 
1002 void SaveState::readnet(FILE* f) {
1003  free_tq();
1004  char buf[200];
1005  ASSERTfgets(buf, 200, f);
1006  sscanf(buf, "%d\n", &nncs_);
1007  if (nncs_ != 0) {
1008  ncs_ = new NetConState[nncs_];
1009  }
1010  for (int i = 0; i < nncs_; ++i) {
1011  ASSERTfgets(buf, 200, f);
1012  sscanf(buf, "%d %d\n", &ncs_[i].object_index, &ncs_[i].nstate);
1013  if (ncs_[i].nstate) {
1014  ncs_[i].state = new double[ncs_[i].nstate];
1015  ASSERTfread(ncs_[i].state, sizeof(double), ncs_[i].nstate, f);
1016  }
1017  }
1018  // PreSyn's
1019  ASSERTfgets(buf, 200, f);
1020  sscanf(buf, "%d\n", &npss_);
1021  if (npss_ != 0) {
1022  pss_ = new PreSynState[npss_];
1023  ASSERTfread(pss_, sizeof(PreSynState), npss_, f);
1024  int i = 0;
1025  if (net_cvode_instance_psl())
1026  for (PreSyn* ps: *net_cvode_instance_psl()) {
1027  ps->hi_index_ = i;
1028  ++i;
1029  }
1030  assert(npss_ == i);
1031  }
1032 
1033  int n = 0;
1034  ASSERTfgets(buf, 200, f);
1035  sscanf(buf, "%d\n", &n);
1036  tqs_->nstate = n;
1037  if (n) {
1038  tqs_->items = new DiscreteEvent*[n];
1039  tqs_->tdeliver = new double[n];
1040  ASSERTfread(tqs_->tdeliver, sizeof(double), n, f);
1041  for (int i = 0; i < n; ++i) {
1042  DiscreteEvent* de = NULL;
1043  ASSERTfgets(buf, 200, f);
1044  int type = 0;
1045  sscanf(buf, "%d\n", &type);
1046  switch (type) {
1047  case DiscreteEventType:
1049  break;
1050  case NetConType:
1051  de = NetCon::savestate_read(f);
1052  break;
1053  case SelfEventType:
1054  de = SelfEvent::savestate_read(f);
1055  break;
1056  case PreSynType:
1057  de = PreSyn::savestate_read(f);
1058  break;
1059  case HocEventType:
1060  de = HocEvent::savestate_read(f);
1061  break;
1062  case PlayRecordEventType:
1064  break;
1065  case NetParEventType:
1067  break;
1068  default:
1069  hoc_execerror("SaveState::readnet", "Unimplemented DiscreteEvent type");
1070  break;
1071  }
1072  tqs_->items[i] = de;
1073  }
1074  }
1075 }
1076 
1077 void SaveState::writenet(FILE* f) {
1078  fprintf(f, "%d\n", nncs_);
1079  for (int i = 0; i < nncs_; ++i) {
1080  fprintf(f, "%d %d\n", ncs_[i].object_index, ncs_[i].nstate);
1081  if (ncs_[i].nstate) {
1082  ASSERTfwrite(ncs_[i].state, sizeof(double), ncs_[i].nstate, f);
1083  }
1084  }
1085  fprintf(f, "%d\n", npss_);
1086  if (npss_) {
1087  ASSERTfwrite(pss_, sizeof(PreSynState), npss_, f);
1088  }
1089  int n = tqs_->nstate;
1090  fprintf(f, "%d\n", n);
1091  if (n) {
1092  ASSERTfwrite(tqs_->tdeliver, sizeof(double), n, f);
1093  for (int i = 0; i < n; ++i) {
1094  tqs_->items[i]->savestate_write(f);
1095  }
1096  }
1097 }
1098 
1099 bool SaveState::checknet(bool warn) {
1100  if (nncs_ != nct->count) {
1101  if (warn) {
1102  fprintf(stderr,
1103  "SaveState warning: There are %d NetCon but %d saved\n",
1104  nct->count,
1105  nncs_);
1106  }
1107  return false;
1108  }
1109  hoc_Item* q;
1110  int i = 0;
1111  ITERATE(q, nct->olist) {
1112  Object* ob = OBJ(q);
1113  const auto* d = static_cast<NetCon*>(ob->u.this_pointer);
1114  if (ob->index != ncs_[i].object_index) {
1115  if (warn) {
1116  fprintf(stderr,
1117  "SaveState warning: %s is matched with NetCon[%d]\n",
1118  hoc_object_name(ob),
1119  ncs_[i].object_index);
1120  }
1121  return false;
1122  }
1123  if (d->cnt_ != ncs_[i].nstate) {
1124  if (warn) {
1125  fprintf(stderr,
1126  "SaveState warning: %s has %d weight states but saved %d\n",
1127  hoc_object_name(ob),
1128  d->cnt_,
1129  ncs_[i].nstate);
1130  }
1131  return false;
1132  }
1133  ++i;
1134  }
1135  // PreSyn's
1136  i = 0;
1137  if (net_cvode_instance_psl()) {
1138  i = net_cvode_instance_psl()->size();
1139  }
1140  if (npss_ != i) {
1141  if (warn) {
1142  fprintf(stderr,
1143  "SaveState warning: There are %d internal PreSyn but %d saved\n",
1144  i,
1145  npss_);
1146  }
1147  return false;
1148  }
1149  return true;
1150 }
1151 
1153  nncs_ = nct->count;
1154  if (nncs_ != 0) {
1155  ncs_ = new NetConState[nncs_];
1156  }
1157  hoc_Item* q;
1158  int i = 0;
1159  ITERATE(q, nct->olist) {
1160  Object* ob = OBJ(q);
1161  const auto* d = static_cast<NetCon*>(ob->u.this_pointer);
1162  ncs_[i].object_index = ob->index;
1163  ncs_[i].nstate = d->cnt_;
1164  if (d->cnt_) {
1165  ncs_[i].state = new double[d->cnt_];
1166  }
1167  ++i;
1168  }
1169  npss_ = 0;
1170  if (net_cvode_instance_psl())
1171  for (PreSyn* ps: *net_cvode_instance_psl()) {
1172  ps->hi_index_ = npss_;
1173  ++npss_;
1174  }
1175  if (npss_ != 0) {
1176  pss_ = new PreSynState[npss_];
1177  }
1178 }
1179 
1180 // The event TQueue is highly volatile so it needs to be freed and allocated
1181 // on every save and fread
1183  if (tqs_->nstate) {
1184  for (int i = 0; i < tqs_->nstate; ++i) {
1185  delete tqs_->items[i];
1186  }
1187  tqs_->nstate = 0;
1188  delete[] tqs_->items;
1189  delete[] tqs_->tdeliver;
1190  }
1191 }
1193  free_tq();
1194  tqcnt_ = 0;
1197  this_savestate = this;
1198  callback_mode = 0;
1200  }
1201  int n = tqcnt_;
1202  tqs_->nstate = n;
1203  if (n) {
1204  tqs_->items = new DiscreteEvent*[n];
1205  tqs_->tdeliver = new double[n];
1206  }
1207 }
1208 
1209 static void* cons(Object*) {
1210  SaveState* ss = new SaveState();
1211  ss->ref();
1212  return (void*) ss;
1213 }
1214 
1215 static void destruct(void* v) {
1216  SaveState* ss = (SaveState*) v;
1217  Resource::unref(ss);
1218 }
1219 
1220 static double save(void* v) {
1221  SaveState* ss = (SaveState*) v;
1222  ss->save();
1223  return 1.;
1224 }
1225 
1226 static double restore(void* v) {
1227  SaveState* ss = (SaveState*) v;
1228  int type = 0;
1229  if (ifarg(1)) {
1230  type = (int) chkarg(1, 0, 1);
1231  }
1232  ss->restore(type);
1233  return 1.;
1234 }
1235 
1236 static double ssread(void* v) {
1237  bool close = true;
1238  SaveState* ss = (SaveState*) v;
1239  Object* obj = *hoc_objgetarg(1);
1240  check_obj_type(obj, "File");
1241  if (ifarg(2)) {
1242  close = chkarg(2, 0, 1) ? true : false;
1243  }
1244  OcFile* f = (OcFile*) obj->u.this_pointer;
1245  ss->read(f, close);
1246  return 1.;
1247 }
1248 
1249 static double sswrite(void* v) {
1250  bool close = true;
1251  SaveState* ss = (SaveState*) v;
1252  Object* obj = *hoc_objgetarg(1);
1253  check_obj_type(obj, "File");
1254  if (ifarg(2)) {
1255  close = chkarg(2, 0, 1) ? true : false;
1256  }
1257  OcFile* f = (OcFile*) obj->u.this_pointer;
1258  ss->write(f, close);
1259  return 1.;
1260 }
1261 
1262 static Member_func members[] = {{"save", save},
1263  {"restore", restore},
1264  {"fread", ssread},
1265  {"fwrite", sswrite},
1266  {nullptr, nullptr}};
1267 
1269  class2oc("SaveState", cons, destruct, members, nullptr, nullptr);
1270 }
const char * secname(Section *sec)
name of section (for use in error messages)
Definition: cabcode.cpp:1674
virtual DiscreteEvent * savestate_save()
Definition: netcvode.cpp:4679
virtual void savestate_write(FILE *)
Definition: netcvode.cpp:4698
static DiscreteEvent * savestate_read(FILE *)
Definition: netcvode.cpp:4694
virtual void savestate_restore(double deliverytime, NetCvode *)
Definition: netcvode.cpp:4688
static DiscreteEvent * savestate_read(FILE *)
Definition: netcvode.cpp:3469
Definition: netcon.h:87
double * weight_
Definition: netcon.h:116
static DiscreteEvent * savestate_read(FILE *)
Definition: netcvode.cpp:4799
static DiscreteEvent * savestate_read(FILE *)
Definition: netpar.cpp:292
Definition: ocfile.h:7
void close()
Definition: ocfile.cpp:307
FILE * file()
Definition: ocfile.cpp:345
const char * get_name()
Definition: ocfile.h:13
bool open(const char *filename, const char *type)
Definition: ocfile.cpp:335
static DiscreteEvent * savestate_read(FILE *)
Definition: netcvode.cpp:311
static PlayRecordSave * savestate_read(FILE *)
Definition: netcvode.cpp:325
virtual void savestate_restore()
Definition: vrecitem.h:100
virtual void savestate_write(FILE *)
Definition: vrecitem.h:101
Definition: netcon.h:258
static DiscreteEvent * savestate_read(FILE *)
Definition: netcvode.cpp:5023
virtual void ref() const
Definition: resource.cpp:42
virtual void unref() const
Definition: resource.cpp:47
virtual void write(OcFile *, bool close)
Definition: savstate.cpp:868
void readnet(FILE *)
Definition: savstate.cpp:1002
void restorenode(NodeState &, Node *)
Definition: savstate.cpp:720
void ssi_def()
Definition: savstate.cpp:227
virtual void restore(int type)
Definition: savstate.cpp:674
void restoreacell(ACellState &, int type)
Definition: savstate.cpp:744
int nacell_
Definition: savstate.cpp:100
void allocnet()
Definition: savstate.cpp:1152
void saveacell(ACellState &, int type)
Definition: savstate.cpp:663
int nsec_
Definition: savstate.cpp:98
StateStructInfo * ssi
Definition: savstate.cpp:110
bool checknode(NodeState &, Node *, bool)
Definition: savstate.cpp:390
void fwrite_SecState(SecState *, int, FILE *)
Definition: savstate.cpp:218
void alloc_tq()
Definition: savstate.cpp:1192
bool checknet(bool)
Definition: savstate.cpp:1099
void restorenet()
Definition: savstate.cpp:968
void tqsave(const TQItem *, int)
Definition: savstate.cpp:961
void fread_SecState(SecState *, int, FILE *)
Definition: savstate.cpp:206
void fread_NodeState(NodeState *, int, FILE *)
Definition: savstate.cpp:192
void free_tq()
Definition: savstate.cpp:1182
NetConState * ncs_
Definition: savstate.cpp:103
void savenet()
Definition: savstate.cpp:924
PreSynState * pss_
Definition: savstate.cpp:105
TQState * tqs_
Definition: savstate.cpp:106
SecState * ss_
Definition: savstate.cpp:99
virtual void read(OcFile *, bool close)
Definition: savstate.cpp:755
void writenet(FILE *)
Definition: savstate.cpp:1077
uint64_t plugin_size_
Definition: savstate.cpp:113
ACellState * acell_
Definition: savstate.cpp:101
void savenode(NodeState &, Node *)
Definition: savstate.cpp:639
void alloc()
Definition: savstate.cpp:438
virtual void save()
Definition: savstate.cpp:596
void ssfree()
Definition: savstate.cpp:524
double t_
Definition: savstate.cpp:96
bool checkacell(ACellState &, int type, bool)
Definition: savstate.cpp:426
void allocnode(NodeState &, Node *)
Definition: savstate.cpp:486
bool check(bool warn)
Definition: savstate.cpp:272
cTemplate * nct
Definition: savstate.cpp:111
int nroot_
Definition: savstate.cpp:97
int tqcnt_
Definition: savstate.cpp:107
void tqcount(const TQItem *, int)
Definition: savstate.cpp:957
char * plugin_data_
Definition: savstate.cpp:112
PlayRecordSave ** prs_
Definition: savstate.cpp:109
void fwrite_NodeState(NodeState *, int, FILE *)
Definition: savstate.cpp:199
void allocacell(ACellState &, int type)
Definition: savstate.cpp:515
static DiscreteEvent * savestate_read(FILE *)
Definition: netcvode.cpp:3175
void forall_callback(void(*)(const TQItem *, int))
Definition: tqueue.cpp:103
void class2oc(const char *, ctor_f *cons, dtor_f *destruct, Member_func *, Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1631
#define cnt
Definition: tqueue.hpp:44
#define v
Definition: md1redef.h:11
#define sec
Definition: md1redef.h:20
#define nodecount
Definition: md1redef.h:39
#define i
Definition: md1redef.h:19
#define PlayRecordEventType
Definition: vrecitem.h:18
constexpr auto enumerate(T &&iterable)
Definition: enumerate.h:90
double chkarg(int, double low, double high)
Definition: code2.cpp:626
char buf[512]
Definition: init.cpp:13
size_t hoc_total_array_data(const Symbol *s, Objectdata *obd)
Definition: hoc_oop.cpp:95
void check_obj_type(Object *obj, const char *type_name)
Definition: hoc_oop.cpp:2098
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:73
Symbol * hoc_lookup(const char *)
Definition: symbol.cpp:59
#define assert(ex)
Definition: hocassrt.h:24
#define hocSEC(q)
Definition: hoclist.h:87
#define OBJ(q)
Definition: hoclist.h:88
Object ** hoc_objgetarg(int)
Definition: code.cpp:1614
#define _AMBIGUOUS
Definition: membfunc.hpp:86
#define STATE
Definition: membfunc.hpp:65
#define EXTRACELL
Definition: membfunc.hpp:61
#define ITERATE(itm, lst)
Definition: model.h:18
auto for_threads(NrnThread *threads, int num_threads)
Definition: multicore.h:133
NrnThread * nrn_threads
Definition: multicore.cpp:56
void clear_event_queue()
Definition: cvodestb.cpp:47
int nrn_nthread
Definition: multicore.cpp:55
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
icycle< ncycle;++icycle) { int istride=stride[icycle];nrn_pragma_acc(loop vector) nrn_pragma_omp(loop bind(parallel)) for(int icore=0;icore< warpsize;++icore) { int i=ii+icore;if(icore< istride) { int ip=GPU_PARENT(i);GPU_RHS(i) -=GPU_B(i) *GPU_RHS(ip);GPU_RHS(i)/=GPU_D(i);} i+=istride;} ii+=istride;} }}void solve_interleaved2(int ith) { NrnThread *nt=nrn_threads+ith;InterleaveInfo &ii=interleave_info[ith];int nwarp=ii.nwarp;if(nwarp==0) return;int ncore=nwarp *warpsize;int *ncycles=ii.cellsize;int *stridedispl=ii.stridedispl;int *strides=ii.stride;int *rootbegin=ii.firstnode;int *nodebegin=ii.lastnode;if(0) { nrn_pragma_acc(parallel loop gang present(nt[0:1], strides[0:nstride], ncycles[0:nwarp], stridedispl[0:nwarp+1], rootbegin[0:nwarp+1], nodebegin[0:nwarp+1]) async(nt->stream_id)) nrn_pragma_omp(target teams loop map(present, alloc:nt[:1], strides[:nstride], ncycles[:nwarp], stridedispl[:nwarp+1], rootbegin[:nwarp+1], nodebegin[:nwarp+1])) for(int icore=0;icore< ncore;icore+=warpsize) { solve_interleaved2_loop_body(nt, icore, ncycles, strides, stridedispl, rootbegin, nodebegin);} nrn_pragma_acc(wait(nt->stream_id)) } else { for(int icore=0;icore< ncore;icore+=warpsize) { solve_interleaved2_loop_body(nt, icore, ncycles, strides, stridedispl, rootbegin, nodebegin);} }}void solve_interleaved1(int ith) { NrnThread *nt=nrn_threads+ith;int ncell=nt-> ncell
Definition: cellorder.cpp:784
#define HocEventType
Definition: netcon.h:48
#define NetParEventType
Definition: netcon.hpp:27
#define PreSynType
Definition: netcon.hpp:26
#define DiscreteEventType
Definition: netcon.hpp:22
#define SelfEventType
Definition: netcon.hpp:25
#define NetConType
Definition: netcon.hpp:24
void section_ref(Section *)
Definition: solve.cpp:520
void section_unref(Section *)
Definition: solve.cpp:509
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
int const size_t const size_t n
Definition: nrngsl.h:10
size_t q
for(i=0;i< n;i++)
size_t p
size_t j
s
Definition: multisend.cpp:521
int * nrn_prop_param_size_
Definition: init.cpp:162
int ifarg(int)
Definition: code.cpp:1607
std::vector< Memb_func > memb_func
Definition: init.cpp:145
short type
Definition: cabvars.h:10
int nrn_vartype(const Symbol *sym)
Definition: eion.cpp:503
hoc_List * section_list
Definition: init.cpp:113
std::vector< Memb_list > memb_list
Definition: init.cpp:146
int nrn_global_ncell
Definition: init.cpp:114
int n_memb_func
Definition: init.cpp:448
#define BinaryMode(ocfile)
Definition: ocfile.h:61
std::vector< PreSyn * > * net_cvode_instance_psl()
Definition: netcvode.cpp:274
Section ** secorder
Definition: solve.cpp:82
short * nrn_is_artificial_
Definition: init.cpp:214
static double ssread(void *v)
Definition: savstate.cpp:1236
#define ASSERTfread(a, b, c, d)
Definition: savstate.cpp:35
ReceiveFunc * pnt_receive
Definition: init.cpp:155
static SaveState * this_savestate
Definition: savstate.cpp:140
static Member_func members[]
Definition: savstate.cpp:1262
static void * cons(Object *)
Definition: savstate.cpp:1209
#define ASSERTfgets(a, b, c)
Definition: savstate.cpp:34
static void destruct(void *v)
Definition: savstate.cpp:1215
void(* ReceiveFunc)(Point_process *, double *, double)
Definition: savstate.cpp:17
static double sswrite(void *v)
Definition: savstate.cpp:1249
double t
Definition: cvodeobj.cpp:57
std::vector< PlayRecord * > * net_cvode_instance_prl()
Definition: netcvode.cpp:278
int section_count
Definition: solve.cpp:81
void(* nrnpy_restore_savestate)(int64_t, char *)
Definition: savstate.cpp:31
static double save(void *v)
Definition: savstate.cpp:1220
#define ASSERTfwrite(a, b, c, d)
Definition: savstate.cpp:36
static int callback_mode
Definition: savstate.cpp:141
static void tqcallback(const TQItem *tq, int i)
Definition: savstate.cpp:143
void nrn_shape_update()
Definition: treeset.cpp:915
TQueue * net_cvode_instance_event_queue(NrnThread *)
Definition: netcvode.cpp:270
NetCvode * net_cvode_instance
Definition: cvodestb.cpp:26
void SaveState_reg()
Definition: savstate.cpp:1268
static double restore(void *v)
Definition: savstate.cpp:1226
void(* nrnpy_store_savestate)(char **save_data, uint64_t *save_data_size)
Definition: savstate.cpp:32
#define NODEV(n)
Definition: section_fwd.hpp:60
#define nlayer
Definition: section_fwd.hpp:31
static int nstate
Definition: simultan.cpp:226
#define NULL
Definition: spdefs.h:105
double * v
Definition: section_fwd.hpp:40
A view into a set of mechanism instances.
Definition: nrnoc_ml.h:34
int nodecount
Definition: nrnoc_ml.h:78
std::vector< double * > data()
Get a vector of double* representing the model data.
Definition: memblist.cpp:64
Definition: section.h:105
Extnode * extnode
Definition: section.h:199
auto & v()
Definition: section.h:141
Prop * prop
Definition: section.h:190
Represent main neuron object computed by single thread.
Definition: multicore.h:58
Definition: hocdec.h:173
void * this_pointer
Definition: hocdec.h:178
int index
Definition: hocdec.h:175
union Object::@47 u
A point process is computed just like regular mechanisms.
Definition: section_fwd.hpp:77
Definition: section.h:231
struct NodeState * ns
Definition: savstate.cpp:56
struct NodeState * root
Definition: savstate.cpp:57
double * tdeliver
Definition: savstate.cpp:79
DiscreteEvent ** items
Definition: savstate.cpp:80
short nnode
Definition: section.h:52
Node ** pnode
Definition: section.h:59
Definition: model.h:47
union Symbol::@28 u
Symbol ** ppsym
Definition: hocdec.h:125
struct Symbol::@45::@46 rng
unsigned s_varn
Definition: hocdec.h:129
Definition: tqitem.hpp:3
hoc_List * olist
Definition: hocdec.h:155
int count
Definition: hocdec.h:154