NEURON
fadvance.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 #include <nrnmpi.h>
4 #include <stdlib.h>
5 #include <errno.h>
6 #include "neuron.h"
7 #include "section.h"
8 #include "nrniv_mf.h"
9 #include "multisplit.h"
10 #define nrnoc_fadvance_c
12 #include "nonvintblock.h"
13 #include "nrncvode.h"
14 #include "spmatrix.h"
15 #include <vector>
16 
17 /*
18  after an fadvance from t-dt to t, v is defined at t
19  states that depend on v are defined at t+dt/2
20  states, such as concentration that depend on current are defined at t
21  and currents are defined at t-dt/2.
22  */
23 /*
24  fcurrent is used to set up all assigned variables without changing any
25  states. It assumes all states have their values at time t which is
26  only first order correct. It determines the nonvint assignments first
27  so that ena, etc. are correct for the current determinations. We
28  demand that nonvint assignments can be done without changing states when
29  dt is temporarily set to 0.
30 
31  It turned out to be a bad idea to do this. Many methods (KINETIC, PROCEDURE)
32  for solving are not even called when dt =0. Also it plays havoc with tables
33  that are recomputed several times when dt is changed then changed back.
34  Therefore we are no longer trying to initialize assigned variables within
35  SOLVE'd blocks. Instead we are making initialization more convenient,
36  at least within the normal situations, by introducing a finitialize()
37  with an optional argument vinit. finitialize will call the INITIALIZE block
38  for all mechanisms in all segments. (Default initialization sets all states
39  to state0.) The user can set things up specially in a models INITIAL
40  block. INITIAL blocks can make use of v. With care they can make use of
41  ionic concentrations just like breakpoint and solve blocks. When the argument
42  is present, v for all segments are set to that value.
43  */
44 
45 #if !defined(NRNMPI) || NRNMPI == 0
46 extern double nrnmpi_wtime();
47 #endif
48 extern double* nrn_mech_wtime_;
49 extern double t, dt;
50 extern double chkarg(int, double low, double high);
51 extern void nrn_fixed_step();
52 extern void nrn_fixed_step_group(int);
53 static void* nrn_fixed_step_thread(NrnThread*);
54 static void* nrn_fixed_step_group_thread(NrnThread* nth);
55 static void* nrn_fixed_step_lastpart(NrnThread*);
56 extern void* setup_tree_matrix(NrnThread*);
57 extern void nrn_solve(NrnThread*);
58 extern void nonvint(NrnThread* nt);
59 extern void nrncvode_set_t(double t);
60 
62 static void* nrn_ms_reduce_solve(NrnThread*);
63 static void* nrn_ms_bksub(NrnThread*);
65 extern void* nrn_multisplit_triang(NrnThread*);
67 extern void* nrn_multisplit_bksub(NrnThread*);
68 extern void (*nrn_multisplit_setup_)();
70 
71 extern int tree_changed;
72 extern int diam_changed;
73 extern int state_discon_allowed_;
74 extern double hoc_epsilon;
75 
76 static void update(NrnThread*);
77 
78 #if 0
79 /*
80  1 to save space, but must worry about other uses of the memb_list
81  such as in netcvode.cpp in fornetcon_prepare
82 */
83 extern short* nrn_is_artificial_;
85 #endif
86 
87 #define NRNCTIME 1
88 #define NONVINT_ODE_COUNT 5
89 
90 #if NRNCTIME
91 #define CTBEGIN double wt = nrnmpi_wtime();
92 #define CTADD nth->_ctime += nrnmpi_wtime() - wt;
93 #else
94 #define CTBEGIN /**/
95 #define CTADD /**/
96 #endif
97 
98 #define ELIMINATE_T_ROUNDOFF 0
99 #if ELIMINATE_T_ROUNDOFF
100 /* in order to simplify and as much as possible avoid the handling
101 of round-off error due to repeated t += dt, we use
102 t = nrn_tbase_ + nrn_ndt_ * nrn_dt_;
103 to advance time. The problems that must be overcome are when the
104 user changes dt in the middle of a run or switches from cvode or
105 abruptly and arbitrarily sets a new value of t and continues from
106 there (hence nrn_tbase_)
107 */
108 double nrn_ndt_, nrn_tbase_, nrn_dt_;
109 void nrn_chk_ndt() {
110  if (dt != nrn_dt_ || t != nrn_tbase_ + nrn_ndt_ * nrn_dt_) {
111  if (nrnmpi_myid == 0)
112  Printf("nrn_chk_ndt t=%g dt=%g old nrn_tbase_=%g nrn_ndt_=%g nrn_dt_=%g\n",
113  t,
114  dt,
115  nrn_tbase_,
116  nrn_ndt_,
117  nrn_dt_);
118  nrn_dt_ = dt;
119  nrn_tbase_ = t;
120  nrn_ndt_ = 0.;
121  }
122 }
123 #endif /* ELIMINATE_T_ROUNDOFF */
124 
125 /*
126 There are (too) many variants of nrn_fixed_step depending on
127 nrnmpi_numprocs 1 or > 1, nrn_nthread 1 or > 1,
128 nrnmpi_v_transfer nil or callable, nrn_multisplit_setup nil or callable,
129 and whether one step with fadvance
130 or possibly many with ParallelContext.psolve before synchronizing with
131 NetParEvent. The combination of simultaneous nrnmpi_numprocs > 1 and
132 nrn_nthread > 1 with parallel transfer
133 requires some refactoring of the use of the old
134 (*nrnmpi_v_transfer_)() from within nonvint(nt) which handled either mpi
135 or threads but cannot handle both simultaneously. (Unless the first
136 thread that arrives in nrnmpi_v_transfer is the one that accomplishes
137 the mpi transfer). Instead, we replace with
138 nrnthread_v_transfer(nt) to handle the per thread copying of source
139 data into the target space owned by the thread. Between update (called by
140 nrn_fixed_step_thread and nrn_ms_bksub), and nonvint (called by
141 nrn_fixed_step_lastpart, we need to have thread 0 do the interprocessor
142 transfer of source voltages to a either a staging area for later
143 copying to the target by a thread (or directly to the target if only one
144 thread). This will happen with (*nrnmpi_v_transfer_)(). (Look Ma, no threads).
145 This deals properly with the necessary mpi synchronization. And leaves
146 thread handling where it was before. Also, writing to the staging area
147 is only done by thread 0. Fixed step and global variable step
148 logic is limited to the case where an nrnmpi_v_transfer requires
149 existence of nrnthread_v_transfer (even if one thread).
150 */
151 #if 1 || PARANEURON
152 void (*nrnmpi_v_transfer_)(); /* called by thread 0 */
154 /* if at least one gap junction has a source voltage with extracellular inserted */
156 #endif
157 
158 #if VECTORIZE
159 extern "C" int v_structure_change;
160 #endif
161 
162 #if CVODE
164 #endif
165 
168 
169 #define PROFILE 0
170 #include "profile.h"
171 
172 void fadvance(void) {
173  nrn::Instrumentor::phase p_fadvance("fadvance");
174  tstopunset;
175 #if CVODE
176  if (cvode_active_) {
177  cvode_fadvance(-1.);
178  tstopunset;
179  hoc_retpushx(1.);
180  return;
181  }
182 #endif
183  if (tree_changed) {
184  setup_topology();
185  }
186  if (v_structure_change) {
187  v_setup_vectors();
188  }
189  if (diam_changed) {
190  recalc_diam();
191  }
192  nrn_fixed_step();
193  tstopunset;
194  hoc_retpushx(1.);
195 }
196 
197 /*
198  batch_save() initializes list of variables
199  batch_save(&varname, ...) adds variable names to list for saving
200  batch_save("varname", ...) adds variable names to the list and name
201  will appear in header.
202  batch_run(tstop, tstep, "file") saves variables in file every tstep
203 */
204 
205 static void batch_out(), batch_open(), batch_close();
206 
207 static FILE* batch_file;
208 static int batch_size;
209 static int batch_n;
210 static double** batch_var;
211 
212 static void batch_open(char* name, double tstop, double tstep, char* comment) {
213  if (batch_file) {
214  batch_close();
215  }
216  if (!name) {
217  return;
218  }
219  batch_file = fopen(name, "w");
220  if (!batch_file) {
221  hoc_execerror("Couldn't open batch file", name);
222  }
224  "%s\nbatch_run from t = %g to %g in steps of %g with dt = %g\n",
225  comment,
226  t,
227  tstop,
228  tstep,
229  dt);
230 #if 0
231  fprintf(batch_file, "variable names --\n");
232  if (!batch_var) {
233  batch_var = hoc_newlist();
234  }
235  count = 0;
236  ITERATE(q, batch_varname) {
237  fprintf(batch_file, "%s\n", STR(q));
238  ++count;
239  }
240  if (count != batch_n) {
241  if (batch_var) {
242  free(batch_var);
243  }
244  batch_n = count;
245  batch_var = (double**)ecalloc(batch_n, sizeof(double*));
246  }
247  count = 0;
248  ITERATE(q, batch_varname) {
249  batch_var[count++] = hoc_val_pointer(STR(q));
250  }
251 #endif
252 }
253 
254 void batch_run(void) /* avoid interpreter overhead */
255 {
256  double tstop, tstep, tnext;
257  char* filename;
258  char* comment;
259 
260  tstopunset;
261  tstop = chkarg(1, 0., 1e20);
262  tstep = chkarg(2, 0., 1e20);
263  if (ifarg(3)) {
264  filename = gargstr(3);
265  } else {
266  filename = 0;
267  }
268  if (ifarg(4)) {
269  comment = gargstr(4);
270  } else {
271  comment = "";
272  }
273 
274  if (tree_changed) {
275  setup_topology();
276  }
277 #if VECTORIZE
278  if (v_structure_change) {
279  v_setup_vectors();
280  }
281 #endif
282  batch_open(filename, tstop, tstep, comment);
283  batch_out();
284  if (cvode_active_) {
285  while (t < tstop) {
286  cvode_fadvance(t + tstep);
287  batch_out();
288  }
289  } else {
290  tstep -= dt / 4.;
291  tstop -= dt / 4.;
292  tnext = t + tstep;
293  while (t < tstop) {
294  nrn_fixed_step();
295  if (t > tnext) {
296  batch_out();
297  tnext = t + tstep;
298  }
299  if (stoprun) {
300  tstopunset;
301  break;
302  }
303  }
304  }
305  batch_close();
306  hoc_retpushx(1.);
307 }
308 
309 static void dt2thread(double adt) {
310  if (adt != nrn_threads[0]._dt) {
311  int i;
312  for (i = 0; i < nrn_nthread; ++i) {
313  NrnThread* nt = nrn_threads + i;
314  nt->_t = t;
315  nt->_dt = dt;
316  if (secondorder) {
317  nt->cj = 2.0 / dt;
318  } else {
319  nt->cj = 1.0 / dt;
320  }
321  }
322  }
323 }
324 
325 static int _upd;
327  setup_tree_matrix(nt);
328  nrn_solve(nt);
329  if (_upd) {
330  update(nt);
331  }
332  return nullptr;
333 }
334 
335 void nrn_daspk_init_step(double tt, double dteps, int upd) {
336  int i;
337  double dtsav = nrn_threads->_dt;
338  int so = secondorder;
339  dt = dteps;
340  t = tt;
341  secondorder = 0;
342  dt2thread(dteps);
344  _upd = upd;
346  dt = dtsav;
347  secondorder = so;
348  dt2thread(dtsav);
350 }
351 
353  nrn::Instrumentor::phase p_timestep("timestep");
354  int i;
355 #if ELIMINATE_T_ROUNDOFF
356  nrn_chk_ndt();
357 #endif
358  if (t != nrn_threads->_t) {
359  dt2thread(-1.);
360  } else {
361  dt2thread(dt);
362  }
364  if (nrn_multisplit_setup_) {
366  // remove to avoid possible deadlock where some ranks do a
367  // v transfer and others do a spike exchange.
368  // i.e. must complete the full multisplit time step.
369  // if (!nrn_allthread_handle) {
372  /* see comment below */
373  if (nrnthread_v_transfer_) {
374  if (nrnmpi_v_transfer_) {
375  nrn::Instrumentor::phase p_gap("gap-v-transfer");
376  (*nrnmpi_v_transfer_)();
377  }
379  }
380  //}
381  } else {
383  /* if there is no nrnthread_v_transfer then there cannot be
384  a nrnmpi_v_transfer and lastpart
385  will be done in above call.
386  */
387  if (nrnthread_v_transfer_) {
388  if (nrnmpi_v_transfer_) {
389  nrn::Instrumentor::phase p_gap("gap-v-transfer");
390  (*nrnmpi_v_transfer_)();
391  }
393  }
394  }
395  t = nrn_threads[0]._t;
396  if (nrn_allthread_handle) {
397  (*nrn_allthread_handle)();
398  }
399 }
400 
401 /* better cache efficiency since a thread can do an entire minimum delay
402 integration interval before joining
403 */
404 static int step_group_n;
405 static int step_group_begin;
406 static int step_group_end;
407 
409  int i;
410 #if ELIMINATE_T_ROUNDOFF
411  nrn_chk_ndt();
412 #endif
413  dt2thread(dt);
415  if (nrn_multisplit_setup_) {
416  int b = 0;
418  step_group_n = 0; /* abort at bksub flag */
419  for (i = 1; i < n; ++i) {
422  if (step_group_n) {
423  step_group_n = 0;
424  if (nrn_allthread_handle) {
425  (*nrn_allthread_handle)();
426  }
427  /* aborted step at bksub, so if not stopped
428  must do the triang*/
429  b = 1;
430  if (!stoprun) {
432  }
433  }
434  if (stoprun) {
435  break;
436  }
437  b = 0;
438  }
439  if (!b) {
442  }
443  if (nrn_allthread_handle) {
444  (*nrn_allthread_handle)();
445  }
446  } else {
447  step_group_n = n;
448  step_group_begin = 0;
449  step_group_end = 0;
450  while (step_group_end < step_group_n) {
451  /*printf("step_group_end=%d step_group_n=%d\n", step_group_end, step_group_n);*/
453  if (nrn_allthread_handle) {
454  (*nrn_allthread_handle)();
455  }
456  if (stoprun) {
457  break;
458  }
460  }
461  }
462  t = nrn_threads[0]._t;
463 }
464 
466  int i;
467  nth->_stop_stepping = 0;
468  for (i = step_group_begin; i < step_group_n; ++i) {
469  nrn::Instrumentor::phase p_timestep("timestep");
471  if (nth->_stop_stepping) {
472  if (nth->id == 0) {
473  step_group_end = i + 1;
474  }
475  nth->_stop_stepping = 0;
476  return nullptr;
477  }
478  }
479  if (nth->id == 0) {
481  }
482  return nullptr;
483 }
484 
486  double wt;
487  {
488  nrn::Instrumentor::phase p("deliver-events");
489  deliver_net_events(nth);
490  }
491 
492  wt = nrnmpi_wtime();
493  nrn_random_play();
494 #if ELIMINATE_T_ROUNDOFF
495  nth->nrn_ndt_ += .5;
496  nth->_t = nrn_tbase_ + nth->nrn_ndt_ * nrn_dt_;
497 #else
498  nth->_t += .5 * nth->_dt;
499 #endif
501  setup_tree_matrix(nth);
502  {
503  nrn::Instrumentor::phase p("matrix-solver");
504  nrn_solve(nth);
505  }
506  {
507  nrn::Instrumentor::phase p("second-order-cur");
508  second_order_cur(nth);
509  }
510  {
511  nrn::Instrumentor::phase p("update");
512  update(nth);
513  }
514  CTADD
515  /*
516  To simplify the logic,
517  if there is no nrnthread_v_transfer then there cannot be an nrnmpi_v_transfer.
518  */
519  if (!nrnthread_v_transfer_) {
521  }
522  return nullptr;
523 }
524 
525 extern void nrn_extra_scatter_gather(int direction, int tid);
526 extern void nrn_ba(NrnThread*, int);
527 
529  CTBEGIN
530 #if ELIMINATE_T_ROUNDOFF
531  nth->nrn_ndt_ += .5;
532  nth->_t = nrn_tbase_ + nth->nrn_ndt_ * nrn_dt_;
533 #else
534  nth->_t += .5 * nth->_dt;
535 #endif
537  nrn_extra_scatter_gather(0, nth->id);
538  nonvint(nth);
539  nrn_ba(nth, AFTER_SOLVE);
541  CTADD {
542  nrn::Instrumentor::phase p("deliver-events");
543  nrn_deliver_events(nth); /* up to but not past texit */
544  }
545  return nullptr;
546 }
547 
548 /* nrn_fixed_step_thread is split into three pieces */
549 
551  double wt;
552  deliver_net_events(nth);
553  wt = nrnmpi_wtime();
554  nrn_random_play();
555 #if ELIMINATE_T_ROUNDOFF
556  nth->nrn_ndt_ += .5;
557  nth->_t = nrn_tbase_ + nth->nrn_ndt_ * nrn_dt_;
558 #else
559  nth->_t += .5 * nth->_dt;
560 #endif
562  setup_tree_matrix(nth);
564  CTADD
565  return nullptr;
566 }
569  return nullptr;
570 }
571 void* nrn_ms_bksub(NrnThread* nth) {
572  CTBEGIN
574  second_order_cur(nth);
575  update(nth);
576  CTADD
577  /* see above comment in nrn_fixed_step_thread */
578  if (!nrnthread_v_transfer_) {
580  }
581  return nullptr;
582 }
584  nrn_ms_bksub(nth);
585  if (nth->_stop_stepping) {
586  nth->_stop_stepping = 0;
587  if (nth == nrn_threads) {
588  step_group_n = 1;
589  }
590  return nullptr;
591  }
593  return nullptr;
594 }
595 
596 
597 static void update(NrnThread* _nt) {
598  int i, i1, i2;
599  i1 = 0;
600  i2 = _nt->end;
601 #if CACHEVEC
602  if (use_cachevec) {
603  /* do not need to worry about linmod or extracellular*/
604  if (secondorder) {
605  for (i = i1; i < i2; ++i) {
606  VEC_V(i) += 2. * VEC_RHS(i);
607  }
608  } else {
609  for (i = i1; i < i2; ++i) {
610  VEC_V(i) += VEC_RHS(i);
611  }
612  }
613  } else
614 #endif
615  { /* use original non-vectorized update */
616  if (secondorder) {
617 #if _CRAY
618 #pragma _CRI ivdep
619 #endif
620  for (i = i1; i < i2; ++i) {
621  NODEV(_nt->_v_node[i]) += 2. * NODERHS(_nt->_v_node[i]);
622  }
623  } else {
624 #if _CRAY
625 #pragma _CRI ivdep
626 #endif
627  for (i = i1; i < i2; ++i) {
628  NODEV(_nt->_v_node[i]) += NODERHS(_nt->_v_node[i]);
629  }
630  if (use_sparse13) {
631  nrndae_update();
632  }
633  }
634  } /* end of non-vectorized update */
635 
636 #if EXTRACELLULAR
637  nrn_update_2d(_nt);
638 #endif
639  if (nrnthread_vi_compute_) {
640  (*nrnthread_vi_compute_)(_nt);
641  }
642 #if I_MEMBRANE
643  if (_nt->tml) {
644  assert(_nt->tml->index == CAP);
645  nrn_capacity_current(_nt, _nt->tml->ml);
646  }
647 #endif
648  if (nrn_use_fast_imem) {
649  nrn_calc_fast_imem(_nt);
650  }
651 }
652 
654  int i;
655  int i1 = 0;
656  int i3 = _nt->end;
657  double* pd = _nt->_nrn_fast_imem->_nrn_sav_d;
658  double* prhs = _nt->_nrn_fast_imem->_nrn_sav_rhs;
659  if (use_cachevec) {
660  for (i = i1; i < i3; ++i) {
661  prhs[i] = (pd[i] * VEC_RHS(i) + prhs[i]) * VEC_AREA(i) * 0.01;
662  }
663  } else {
664  for (i = i1; i < i3; ++i) {
665  Node* nd = _nt->_v_node[i];
666  prhs[i] = (pd[i] * NODERHS(nd) + prhs[i]) * NODEAREA(nd) * 0.01;
667  }
668  }
669 }
670 
672  // nrn_rhs() is called near end of nrn_finitialize() via setup_tree_matrix()
673  // and nrn_rhs() sets up _nrn_sav_rhs as -total ionic_current (without
674  // ELECTRODE_CURRENT contributions) and RHS as axial + ionic + stim currents
675  // So sum, scaled by area, is i_membrane_ in nA.
676  // (Note: capacitance does not appear on rhs because delta_v is the
677  // variable in the current balance equations set up by setup_tree_matrix.)
678  // Warning: Have not thought deeply about extracellular or LinearMechanism.
679  // But there is a good chance things are ok. But needs testing.
680  // I don't believe this is used by Cvode or IDA.
681  int i;
682  int i1 = 0;
683  int i3 = _nt->end;
684  double* prhs = _nt->_nrn_fast_imem->_nrn_sav_rhs;
685  if (use_cachevec) {
686  for (i = i1; i < i3; ++i) {
687  prhs[i] = (VEC_RHS(i) + prhs[i]) * VEC_AREA(i) * 0.01;
688  }
689  } else {
690  for (i = i1; i < i3; ++i) {
691  Node* nd = _nt->_v_node[i];
692  prhs[i] = (NODERHS(nd) + prhs[i]) * NODEAREA(nd) * 0.01;
693  }
694  }
695 }
696 
697 void fcurrent(void) {
698  int i;
699  if (tree_changed) {
700  setup_topology();
701  }
702  if (v_structure_change) {
703  v_setup_vectors();
704  }
705  if (diam_changed) {
706  recalc_diam();
707  }
708 
709  dt2thread(-1.);
714  hoc_retpushx(1.);
715 }
716 
718  extern int section_count;
719  extern Section** secorder;
720  int isec, inode;
721  Section* sec;
722  Node* nd;
723  if (use_sparse13) {
724  if (ifarg(1) && chkarg(1, 0., 1.) == 0.) {
725  spPrint(_nt->_sp13mat, 1, 0, 1);
726  } else {
727  int i, n = spGetSize(_nt->_sp13mat, 0);
728  spPrint(_nt->_sp13mat, 1, 1, 1);
729  for (i = 1; i <= n; ++i) {
730  Printf("%d %g\n", i, _nt->_actual_rhs[i]);
731  }
732  }
733  } else if (_nt) {
734  for (inode = 0; inode < _nt->end; ++inode) {
735  nd = _nt->_v_node[inode];
736  Printf("%d %g %g %g %g\n",
737  inode,
738  ClassicalNODEB(nd),
739  ClassicalNODEA(nd),
740  NODED(nd),
741  NODERHS(nd));
742  }
743  } else {
744  for (isec = 0; isec < section_count; ++isec) {
745  sec = secorder[isec];
746  for (inode = 0; inode < sec->nnode; ++inode) {
747  nd = sec->pnode[inode];
748  Printf("%d %d %g %g %g %g\n",
749  isec,
750  inode,
751  ClassicalNODEB(nd),
752  ClassicalNODEA(nd),
753  NODED(nd),
754  NODERHS(nd));
755  }
756  }
757  }
758 }
759 
760 void fmatrix(void) {
761  if (ifarg(1)) {
762  double x;
763  Section* sec;
764  int id;
765  Node* nd;
766  NrnThread* _nt;
767  nrn_seg_or_x_arg(1, &sec, &x);
768  id = (int) chkarg(2, 1., 4.);
769  nd = node_exact(sec, x);
770  _nt = nd->_nt;
771  switch (id) {
772  case 1:
773  hoc_retpushx(NODEA(nd));
774  break;
775  case 2:
776  hoc_retpushx(NODED(nd));
777  break;
778  case 3:
779  hoc_retpushx(NODEB(nd));
780  break;
781  case 4:
782  hoc_retpushx(NODERHS(nd));
783  break;
784  }
785  return;
786  }
788  hoc_retpushx(1.);
789  return;
790 }
791 
792 void nonvint(NrnThread* _nt) {
793 #if VECTORIZE
794  int i = 0;
795  double w;
796  int measure = 0;
797  NrnThreadMembList* tml;
798 #if 1 || PARANEURON
799  /* nrnmpi_v_transfer if needed was done earlier */
800  if (nrnthread_v_transfer_) {
801  nrn::Instrumentor::phase p_gap("gap-v-transfer");
802  (*nrnthread_v_transfer_)(_nt);
803  }
804 #endif
805  nrn::Instrumentor::phase_begin("state-update");
806  if (_nt->id == 0 && nrn_mech_wtime_) {
807  measure = 1;
808  }
809  errno = 0;
810  for (tml = _nt->tml; tml; tml = tml->next)
811  if (memb_func[tml->index].state) {
812  std::string mechname("state-");
813  mechname += memb_func[tml->index].sym->name;
815  Pvmi s = memb_func[tml->index].state;
817  if (measure) {
818  w = nrnmpi_wtime();
819  }
820  (*s)(_nt, tml->ml, tml->index);
821  if (measure) {
822  nrn_mech_wtime_[tml->index] += nrnmpi_wtime() - w;
823  }
824  if (errno) {
825  if (nrn_errno_check(i)) {
826  hoc_warning("errno set during calculation of states", (char*) 0);
827  }
828  }
829  }
830  long_difus_solve(0, _nt); /* if any longitudinal diffusion */
832  nrn::Instrumentor::phase_end("state-update");
833 #endif
834 }
835 
836 #if VECTORIZE
837 int nrn_errno_check(int i) {
838  int ierr;
839  ierr = hoc_errno_check();
840  if (ierr) {
841  fprintf(stderr,
842  "%d errno=%d at t=%g during call to mechanism %s\n",
843  nrnmpi_myid,
844  ierr,
845  t,
846  memb_func[i].sym->name);
847  }
848  return ierr;
849 }
850 #else
851 int nrn_errno_check(Prop* p, int inode, Section* sec) {
852  int ierr;
853  char* secname();
854  ierr = hoc_errno_check();
855  if (ierr) {
856  fprintf(stderr,
857  "%d errno set at t=%g during call to mechanism %s at node %d in section %s\n",
858  nrnmpi_myid,
859  t,
860  memb_func[p->type].sym->name,
861  inode,
862  secname(sec));
863  }
864  return ierr;
865 }
866 #endif
867 
868 void frecord_init(void) { /* useful when changing states after an finitialize() */
869  int i;
870  dt2thread(-1);
871  nrn_record_init();
872  if (!cvode_active_) {
873  for (i = 0; i < nrn_nthread; ++i) {
875  }
876  }
877  hoc_retpushx(1.);
878 }
879 
880 void verify_structure(void) {
881  if (tree_changed) {
882  setup_topology();
883  }
884  if (v_structure_change) {
885  v_setup_vectors();
886  }
887  if (diam_changed) {
888  recalc_diam();
889  }
890  nrn_solver_prepare(); /* cvode ready to be used */
891 }
892 
893 void nrn_finitialize(int setv, double v) {
894  int iord, i;
895  NrnThread* _nt;
896  extern int _ninits;
897  extern short* nrn_is_artificial_;
898  ++_ninits;
899 
900  nrn::Instrumentor::phase_begin("finitialize");
901  nrn_fihexec(3); /* model structure changes can be made */
903 #if ELIMINATE_T_ROUNDOFF
904  nrn_ndt_ = 0.;
905  nrn_dt_ = dt;
906  nrn_tbase_ = 0.;
907 #else
908  t = 0.;
909  dt2thread(-1.);
910 #endif
911  if (cvode_active_) {
912  nrncvode_set_t(t);
913  }
917  nrn_random_play();
918 #if VECTORIZE
919  nrn_play_init(); /* Vector.play */
920  for (i = 0; i < nrn_nthread; ++i) {
921  nrn_deliver_events(nrn_threads + i); /* The play events at t=0 */
922  }
923  if (setv) {
924 #if _CRAY
925 #pragma _CRI ivdep
926 #endif
927  FOR_THREADS(_nt)
928  for (i = 0; i < _nt->end; ++i) {
929  NODEV(_nt->_v_node[i]) = v;
930  }
931  }
932 #if 1 || PARANEURON
934  FOR_THREADS(_nt) {
935  (*nrnthread_vi_compute_)(_nt);
936  }
937  {
938  nrn::Instrumentor::phase p_gap("gap-v-transfer");
939  if (nrnmpi_v_transfer_) {
940  (nrnmpi_v_transfer_)();
941  }
943  FOR_THREADS(_nt) {
944  (*nrnthread_v_transfer_)(_nt);
945  }
946  }
947 #endif
948  nrn_fihexec(0); /* after v is set but before INITIAL blocks are called*/
949  for (i = 0; i < nrn_nthread; ++i) {
951  }
952 #if _CRAY
953  cray_node_init();
954 #endif
955  /* the INITIAL blocks are ordered so that mechanisms that write
956  concentrations are after ions and before mechanisms that read
957  concentrations.
958  */
959  /* the memblist list in NrnThread is already so ordered */
960 #if MULTICORE
961  for (i = 0; i < nrn_nthread; ++i) {
962  NrnThread* nt = nrn_threads + i;
964  NrnThreadMembList* tml;
965  for (tml = nt->tml; tml; tml = tml->next) {
966  Pvmi s = memb_func[tml->index].initialize;
967  if (s) {
968  (*s)(nt, tml->ml, tml->index);
969  }
970  }
971  }
972 #endif
973  for (iord = 0; iord < n_memb_func; ++iord) {
974  i = memb_order_[iord];
975  /* first clause due to MULTICORE */
976  if (nrn_is_artificial_[i])
977  if (memb_func[i].initialize) {
978  Pvmi s = memb_func[i].initialize;
979 #if 0
980  if (nrn_is_artificial_[i]) {
981  /*
982  I hope the space saving of the memb_list arrays is worth
983  doing this specifically. And if art cells are needed
984  in the memb_list anywhere else we will have do do something
985  similar to this. This gives up vectorization but this is only
986  initialization and all the other use of artcell should be
987  event driven.
988  */
989  Prop* p;
990  hoc_Item* q;
991  hoc_List* list = nrn_pnt_template_[i]->olist;
992  ITERATE(q, list) {
993  Object* obj = OBJ(q);
994  Prop* p = ((Point_process*)obj->u.this_pointer)->prop;
995  (*s)((Node*)0, p->param, p->dparam);
996  }
997  }else if (memb_list[i].nodecount){
998 #else
999  if (memb_list[i].nodecount) {
1000 #endif
1001  (*s)(nrn_threads, memb_list + i, i);
1002  }
1003  if (errno) {
1004  if (nrn_errno_check(i)) {
1005  hoc_warning("errno set during call to INITIAL block", (char*) 0);
1006  }
1007  }
1008  }
1009 }
1010 #endif
1011 if (use_sparse13) {
1012  nrndae_init();
1013 }
1014 
1015 init_net_events();
1016 for (i = 0; i < nrn_nthread; ++i) {
1018 }
1019 nrn_fihexec(1); /* after INITIAL blocks, before fcurrent*/
1020 
1021 for (i = 0; i < nrn_nthread; ++i) {
1022  nrn_deliver_events(nrn_threads + i); /* The INITIAL sent events at t=0 */
1023 }
1024 if (cvode_active_) {
1026  nrn_record_init();
1027 } else {
1029  for (i = 0; i < nrn_nthread; ++i) {
1031  if (nrn_use_fast_imem) {
1033  }
1034  }
1036  nrn_record_init();
1037  for (i = 0; i < nrn_nthread; ++i) {
1039  }
1040 }
1041 for (i = 0; i < nrn_nthread; ++i) {
1042  nrn_deliver_events(nrn_threads + i); /* The record events at t=0 */
1043 }
1044 #if NRNMPI
1046 #endif
1047 if (nrn_allthread_handle) {
1048  (*nrn_allthread_handle)();
1049 }
1050 
1051 nrn_fihexec(2); /* just before return */
1052 nrn::Instrumentor::phase_end("finitialize");
1053 }
1054 
1055 void finitialize(void) {
1056  int setv;
1057  double v = 0.0;
1058  setv = 0;
1059  if (ifarg(1)) {
1060  v = *getarg(1);
1061  setv = 1;
1062  }
1063  tstopunset;
1064  nrn_finitialize(setv, v);
1065  tstopunset;
1066  hoc_retpushx(1.);
1067 }
1068 
1069 
1070 static void batch_close() {
1071  if (batch_file) {
1072  fclose(batch_file);
1073  batch_file = 0;
1074  }
1075 }
1076 
1077 static void batch_out() {
1078  if (batch_file) {
1079  int i;
1080  for (i = 0; i < batch_n; ++i) {
1081  fprintf(batch_file, " %g", *batch_var[i]);
1082  }
1083  fprintf(batch_file, "\n");
1084  }
1085 }
1086 
1087 void batch_save(void) {
1088  int i;
1089  if (!ifarg(1)) {
1090  batch_n = 0;
1091  } else {
1092  for (i = 1; ifarg(i); ++i) {
1093  if (batch_size <= batch_n) {
1094  batch_size += 20;
1095  batch_var = (double**) erealloc(batch_var, batch_size * sizeof(double*));
1096  }
1098  ++batch_n;
1099  }
1100  }
1101  hoc_retpushx(1.);
1102 }
1103 
1104 void nrn_ba(NrnThread* nt, int bat) {
1105  NrnThreadBAList* tbl;
1106  int i;
1107  for (tbl = nt->tbl[bat]; tbl; tbl = tbl->next) {
1108  nrn_bamech_t f = tbl->bam->f;
1109  int type = tbl->bam->type;
1110  Memb_list* ml = tbl->ml;
1111  for (i = 0; i < ml->nodecount; ++i) {
1112  (*f)(ml->nodelist[i], ml->data[i], ml->pdata[i], ml->_thread, nt);
1113  }
1114  }
1115 }
1116 
1117 typedef int (*NonVintBlockItem)(int method, int size, double* pd1, double* pd2, int tid);
1118 /* list to store the nrn_nonvint_block functions */
1119 static std::vector<NonVintBlockItem> nonvint_block_list;
1120 
1121 int nrn_nonvint_block_exe(int method, int size, double* pd1, double* pd2, int tid) {
1122  /* execute all functions in nonvint_block_list and return the sum of the
1123  * return values
1124  */
1125  int rval, sum = 0;
1126 
1127  for (auto& func: nonvint_block_list) {
1128  rval = (*func)(method, size, pd1, pd2, tid);
1129  if (rval == -1) {
1130  hoc_execerror("nrn_nonvint_block error", 0);
1131  } else {
1132  sum += rval;
1133  }
1134  if (method == NONVINT_ODE_COUNT) {
1135  size += rval;
1136  }
1137  }
1138 
1139  return sum;
1140 }
1141 
1143  /* store new_nrn_nonvint_block functions in a list */
1144  nonvint_block_list.push_back(func);
1145 
1146  /* could this be set directly in nrn_nonvint_block_helper? */
1148 
1149  return 0;
1150 }
1151 
1153  // remove new_nrn_nonvint_block functions from the list
1154  // in c++-20 one could say std::erase(nonvint_block_list, func);
1155  auto n = nonvint_block_list.size();
1156  for (size_t i = 0; i < n; ++i) {
1157  if (func == nonvint_block_list[i]) {
1158  nonvint_block_list.erase(nonvint_block_list.begin() + i);
1159  break;
1160  }
1161  }
1162  if (nonvint_block_list.empty()) {
1164  }
1165  return 0;
1166 }
1167 
1168 int nrn_nonvint_block_helper(int method, int size, double* pd1, double* pd2, int tid) {
1170  int rval = (*nrn_nonvint_block)(method, size, pd1, pd2, tid);
1171  if (rval == -1) {
1172  hoc_execerror("nrn_nonvint_block error", 0);
1173  }
1174  return rval;
1175 }
1176 
1177 /*
1178  Derived from scopmath/euler.cpp. Here because scopmath does not know
1179  about NrnThread
1180 */
1181 #include "nrniv_mf.h"
1182 
1183 #undef SUCCESS
1184 #define SUCCESS 0
1185 #define der_(arg) p[der[arg]]
1186 #define var_(arg) p[var[arg]]
1187 
1188 /* ARGSUSED */
1189 extern "C" int euler_thread(int neqn,
1190  int* var,
1191  int* der,
1192  double* p,
1193  int (*func)(double*, Datum*, Datum*, NrnThread*),
1194  Datum* ppvar,
1195  Datum* thread,
1196  NrnThread* nt) {
1197  int i;
1198  double dt = nt->_dt;
1199 
1200  /* Calculate the derivatives */
1201 
1202  (*func)(p, ppvar, thread, nt);
1203 
1204  /* Update dependent variables --- note defines in euler above*/
1205 
1206  for (i = 0; i < neqn; i++)
1207  var_(i) += dt * (der_(i));
1208 
1209  return (SUCCESS);
1210 }
Section ** secorder
Definition: solve.cpp:77
int section_count
Definition: solve.cpp:76
const char * secname(Section *sec)
Definition: cabcode.cpp:1776
Node * node_exact(Section *sec, double x)
Definition: cabcode.cpp:1940
Memb_func * memb_func
Definition: init.cpp:123
short type
Definition: cabvars.h:9
void nrn_capacity_current(NrnThread *_nt, Memb_list *ml)
Definition: capac.cpp:62
#define spPrint
Definition: cspredef.h:33
#define spGetSize
Definition: cspredef.h:23
short * nrn_is_artificial_
Definition: cell_group.cpp:18
int use_cachevec
Definition: treeset.cpp:63
int secondorder
Definition: init.cpp:96
void cvode_finitialize()
void cvode_fadvance()
void nrn_record_init()
Definition: cvodestb.cpp:69
void fixed_record_continuous(NrnThread *nt)
Definition: cvodestb.cpp:87
void nrn_play_init()
Definition: cvodestb.cpp:75
void init_net_events()
Definition: cvodestb.cpp:63
void deliver_net_events(NrnThread *)
Definition: cvodestb.cpp:40
void fixed_play_continuous(NrnThread *nt)
Definition: cvodestb.cpp:81
void nrn_solver_prepare()
Definition: cvodestb.cpp:93
void nrn_deliver_events(NrnThread *)
Definition: cvodestb.cpp:49
void clear_event_queue()
Definition: cvodestb.cpp:57
void second_order_cur(NrnThread *nt)
Definition: eion.cpp:649
void nrn_update_2d(NrnThread *nt)
Definition: extcelln.cpp:100
static void * nrn_fixed_step_group_thread(NrnThread *nth)
Definition: fadvance.cpp:465
double dt
Definition: fadvance.cpp:49
static void * nrn_ms_bksub_through_triang(NrnThread *)
Definition: fadvance.cpp:583
int diam_changed
Definition: cabcode.cpp:23
void(* nrnthread_vi_compute_)(NrnThread *nt)
Definition: fadvance.cpp:155
void(* nrn_multisplit_setup_)()
Definition: treeset.cpp:46
static std::vector< NonVintBlockItem > nonvint_block_list
Definition: fadvance.cpp:1119
static FILE * batch_file
Definition: fadvance.cpp:207
static double ** batch_var
Definition: fadvance.cpp:210
double chkarg(int, double low, double high)
Definition: code2.cpp:638
static void * nrn_fixed_step_lastpart(NrnThread *)
Definition: fadvance.cpp:528
static void batch_out()
Definition: fadvance.cpp:1077
static void update(NrnThread *)
Definition: fadvance.cpp:597
int euler_thread(int neqn, int *var, int *der, double *p, int(*func)(double *, Datum *, Datum *, NrnThread *), Datum *ppvar, Datum *thread, NrnThread *nt)
Definition: fadvance.cpp:1189
void finitialize(void)
Definition: fadvance.cpp:1055
void nrn_calc_fast_imem(NrnThread *_nt)
Definition: fadvance.cpp:653
static int step_group_end
Definition: fadvance.cpp:406
int unset_nonvint_block(NonVintBlockItem func)
Definition: fadvance.cpp:1152
static void * daspk_init_step_thread(NrnThread *nt)
Definition: fadvance.cpp:326
void * nrn_multisplit_reduce_solve(NrnThread *)
static int batch_size
Definition: fadvance.cpp:208
void fcurrent(void)
Definition: fadvance.cpp:697
void nrncvode_set_t(double t)
Definition: cvodestb.cpp:143
int set_nonvint_block(NonVintBlockItem func)
Definition: fadvance.cpp:1142
static void * nrn_ms_bksub(NrnThread *)
Definition: fadvance.cpp:571
double * nrn_mech_wtime_
Definition: treeset.cpp:29
#define CTADD
Definition: fadvance.cpp:92
void batch_save(void)
Definition: fadvance.cpp:1087
void nrn_print_matrix(NrnThread *_nt)
Definition: fadvance.cpp:717
void * setup_tree_matrix(NrnThread *)
Definition: treeset.cpp:621
int nrn_nonvint_block_exe(int method, int size, double *pd1, double *pd2, int tid)
Definition: fadvance.cpp:1121
void fadvance(void)
Definition: fadvance.cpp:172
void batch_run(void)
Definition: fadvance.cpp:254
void nrn_daspk_init_step(double tt, double dteps, int upd)
Definition: fadvance.cpp:335
static int batch_n
Definition: fadvance.cpp:209
int nrn_nonvint_block_helper(int method, int size, double *pd1, double *pd2, int tid)
Definition: fadvance.cpp:1168
int cvode_active_
Definition: fadvance.cpp:163
void(* nrn_allthread_handle)()
Definition: fadvance.cpp:69
static void * nrn_fixed_step_thread(NrnThread *)
Definition: fadvance.cpp:485
static int _upd
Definition: fadvance.cpp:325
void nrn_solve(NrnThread *)
Definition: solve.cpp:339
#define der_(arg)
Definition: fadvance.cpp:1185
#define var_(arg)
Definition: fadvance.cpp:1186
int state_discon_allowed_
Definition: init.cpp:97
double t
Definition: cvodeobj.cpp:59
int(* NonVintBlockItem)(int method, int size, double *pd1, double *pd2, int tid)
Definition: fadvance.cpp:1117
void nrn_fixed_step_group(int)
Definition: fadvance.cpp:408
void fmatrix(void)
Definition: fadvance.cpp:760
void * nrn_multisplit_triang(NrnThread *)
static int step_group_n
Definition: fadvance.cpp:404
#define CTBEGIN
Definition: fadvance.cpp:91
static void * nrn_ms_reduce_solve(NrnThread *)
Definition: fadvance.cpp:567
void nrn_fixed_step()
Definition: fadvance.cpp:352
void nrn_calc_fast_imem_fixedstep_init(NrnThread *_nt)
Definition: fadvance.cpp:671
static int step_group_begin
Definition: fadvance.cpp:405
void * nrn_multisplit_bksub(NrnThread *)
#define SUCCESS
Definition: fadvance.cpp:1184
int tree_changed
void nonvint(NrnThread *nt)
Definition: fadvance.cpp:792
void verify_structure(void)
Definition: fadvance.cpp:880
void nrn_finitialize(int setv, double v)
Definition: fadvance.cpp:893
void nrn_extra_scatter_gather(int direction, int tid)
Definition: cvodeobj.cpp:532
static void dt2thread(double adt)
Definition: fadvance.cpp:309
static void * nrn_ms_treeset_through_triang(NrnThread *)
Definition: fadvance.cpp:550
#define NONVINT_ODE_COUNT
Definition: fadvance.cpp:88
void frecord_init(void)
Definition: fadvance.cpp:868
static void batch_close()
Definition: fadvance.cpp:1070
void(* nrnthread_v_transfer_)(NrnThread *nt)
Definition: fadvance.cpp:153
double nrnmpi_wtime()
Definition: nrnmpi.cpp:171
int nrn_errno_check(int i)
Definition: fadvance.cpp:837
static void batch_open()
int nrn_use_fast_imem
Definition: fadvance.cpp:167
int v_structure_change
Definition: fadvance.cpp:159
double hoc_epsilon
Definition: hoc_init.cpp:396
void nrn_ba(NrnThread *, int)
Definition: fadvance.cpp:1104
void(* nrnmpi_v_transfer_)()
Definition: fadvance.cpp:152
void nrn_fihexec(int type)
Definition: finithnd.cpp:33
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:754
int stoprun
Definition: fadvance.cpp:166
int hoc_errno_check(void)
Definition: math.cpp:109
double * hoc_val_pointer(const char *s)
Definition: code2.cpp:727
void hoc_warning(const char *, const char *)
void hoc_retpushx(double x)
Definition: hocusr.cpp:154
double * hoc_pgetarg(int narg)
Definition: code.cpp:1623
double(* func)(double)
Definition: hoc_init.cpp:164
#define assert(ex)
Definition: hocassrt.h:32
void * erealloc(void *ptr, size_t n)
Definition: symbol.cpp:263
void * ecalloc(size_t n, size_t size)
Definition: symbol.cpp:215
#define getarg
Definition: hocdec.h:15
#define gargstr
Definition: hocdec.h:14
#define OBJ(q)
Definition: hoclist.h:67
void
int ifarg(int)
Definition: code.cpp:1581
double var(InputIterator begin, InputIterator end)
Definition: ivocvect.h:101
#define neqn
Definition: lineq.h:3
#define v
Definition: md1redef.h:4
#define sec
Definition: md1redef.h:13
#define nodecount
Definition: md1redef.h:30
#define id
Definition: md1redef.h:33
#define i
Definition: md1redef.h:12
#define AFTER_SOLVE
Definition: membfunc.h:76
void(* nrn_bamech_t)(Node *, double *, Datum *, Datum *, struct NrnThread *)
Definition: membfunc.h:24
#define CAP
Definition: membfunc.h:64
void(* Pvmi)(struct NrnThread *, Memb_list *, int)
Definition: membfunc.h:18
#define BEFORE_INITIAL
Definition: membfunc.h:73
#define AFTER_INITIAL
Definition: membfunc.h:74
#define STR(q)
Definition: model.h:87
#define ITERATE(itm, lst)
Definition: model.h:25
#define Printf
Definition: model.h:237
nrn_random_play
Definition: extdef.h:10
char * name
Definition: init.cpp:16
void nrn_multithread_job(void *(*job)(NrnThread *))
Definition: multicore.cpp:1136
int nrn_nthread
Definition: multicore.cpp:46
NrnThread * nrn_threads
Definition: multicore.cpp:47
void nrn_thread_table_check()
Definition: multicore.cpp:1106
#define FOR_THREADS(nt)
Definition: multicore.h:104
#define ClassicalNODEB(n)
Definition: multisplit.h:36
#define ClassicalNODEA(n)
Definition: multisplit.h:35
#define fprintf
Definition: mwprefix.h:30
static void phase_begin(const char *name)
static void phase_end(const char *name)
void setup_topology()
cTemplate ** nrn_pnt_template_
Definition: init.cpp:131
void v_setup_vectors()
Definition: treeset.cpp:1631
void nrn_spike_exchange_init()
Definition: netpar.cpp:458
static char * mechname
Definition: nocpout.cpp:151
nonvintblock_extern int(* nrn_nonvint_block)(int method, int length, double *pd1, double *pd2, int tid)
Definition: nonvintblock.h:31
#define nrn_nonvint_block_init(tid)
Definition: nonvintblock.h:41
#define nrn_nonvint_block_fixed_step_solve(tid)
Definition: nonvintblock.h:53
void nrn_seg_or_x_arg(int iarg, Section **psec, double *px)
Definition: point.cpp:185
void nrn_spike_exchange(struct NrnThread *nt)
void nrndae_update()
Definition: nrndae.cpp:44
void nrndae_init()
Definition: nrndae.cpp:64
int const size_t const size_t n
Definition: nrngsl.h:11
size_t q
size_t p
int nrnmpi_myid
Memb_list * memb_list
Definition: init.cpp:124
int _ninits
Definition: init.cpp:846
short * memb_order_
Definition: init.cpp:125
int n_memb_func
Definition: init.cpp:440
void long_difus_solve(int, NrnThread *)
Definition: ldifus.cpp:104
void recalc_diam()
Definition: treeset.cpp:953
#define NODEA(n)
Definition: section.h:124
#define NODEB(n)
Definition: section.h:125
int use_sparse13
Definition: treeset.cpp:71
#define VEC_RHS(i)
Definition: section.h:121
#define NODEV(n)
Definition: section.h:115
#define VEC_AREA(i)
Definition: section.h:123
#define NODEAREA(n)
Definition: section.h:116
#define NODERHS(n)
Definition: section.h:105
#define tstopunset
Definition: section.h:327
#define NODED(n)
Definition: section.h:104
#define VEC_V(i)
Definition: section.h:122
FILE * fopen()
#define NULL
Definition: sptree.h:16
double * _nrn_sav_rhs
Definition: multicore.h:46
double * _nrn_sav_d
Definition: multicore.h:47
nrn_bamech_t f
Definition: membfunc.h:80
int type
Definition: membfunc.h:81
Pvmi state
Definition: membfunc.h:35
Symbol * sym
Definition: membfunc.h:38
Pvmi initialize
Definition: membfunc.h:36
int nodecount
Definition: nrnoc_ml.h:18
Node ** nodelist
Definition: nrnoc_ml.h:5
double ** data
Definition: nrnoc_ml.h:14
Datum ** pdata
Definition: nrnoc_ml.h:15
Datum * _thread
Definition: nrnoc_ml.h:17
Definition: section.h:133
struct NrnThread * _nt
Definition: section.h:158
BAMech * bam
Definition: multicore.h:41
struct NrnThreadBAList * next
Definition: multicore.h:42
Memb_list * ml
Definition: multicore.h:40
Represent main neuron object computed by single thread.
Definition: multicore.h:58
double _dt
Definition: multicore.h:60
NrnThreadMembList * tml
Definition: multicore.h:62
char * _sp13mat
Definition: multicore.h:79
_nrn_Fast_Imem * _nrn_fast_imem
Definition: multicore.h:82
int id
Definition: multicore.h:66
NrnThreadBAList * tbl[BEFORE_AFTER_SIZE]
Definition: multicore.h:89
double cj
Definition: multicore.h:61
int _stop_stepping
Definition: multicore.h:67
int end
Definition: multicore.h:65
double * _actual_rhs
Definition: multicore.h:70
Node ** _v_node
Definition: multicore.h:77
double _t
Definition: multicore.h:59
struct NrnThreadMembList * next
Definition: multicore.h:34
Memb_list * ml
Definition: multicore.h:35
Definition: hocdec.h:227
void * this_pointer
Definition: hocdec.h:232
union Object::@39 u
Definition: section.h:214
char * name
Definition: model.h:72
hoc_List * olist
Definition: hocdec.h:204
Definition: hocdec.h:177