NEURON
occvode.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #define VECTORIZE 1
3 #include <errno.h>
4 #include <InterViews/resource.h>
5 #include <OS/string.h>
6 #include "nrnoc2iv.h"
7 #include "nrndaspk.h"
8 #include "cvodeobj.h"
9 #include "netcvode.h"
10 #include "ivocvect.h"
11 #include "vrecitem.h"
12 #include "membfunc.h"
13 #include "nonvintblock.h"
15 extern void nrn_mul_capacity(NrnThread*, Memb_list*);
16 extern void nrn_div_capacity(NrnThread*, Memb_list*);
17 extern int diam_changed;
18 extern void recalc_diam();
19 extern int nrn_errno_check(int);
20 // extern double t, dt;
21 #define nt_dt nrn_threads->_dt
22 #define nt_t nrn_threads->_t
23 
24 extern void long_difus_solve(int, NrnThread*);
26 
27 #include "spmatrix.h"
28 extern void nrndae_dkmap(double**, double**);
29 extern double* sp13mat;
30 
31 #if 1 || PARANEURON
33 extern void (*nrnmpi_v_transfer_)();
34 #endif
35 
36 extern void (*nrn_multisplit_setup_)();
37 extern void* nrn_multisplit_triang(NrnThread*);
39 extern void* nrn_multisplit_bksub(NrnThread*);
40 extern void nrn_multisplit_nocap_v();
45 #if PARANEURON
46 extern void (*nrn_multisplit_solve_)();
47 #endif
48 
49 static Symbol* vsym; // for absolute tolerance
50 #define SETUP 1
51 #define USED 2
52 /*
53 CVODE expects dy/dt = f(y) and solve (I - gamma*J)*x = b with approx to
54 J=df/dy.
55 
56 The NEURON fixed step method sets up C*dv/dt = F(v)
57 by first calculating F(v) and storing it on the right hand side of
58 the matrix equation ( see src/nrnoc/treeset.cpp nrn_rhs() ).
59 It then sets up the left hand side of the matrix equation using
60 nrn_set_cj(1./dt); setup1_tree_matrix(); setup2_tree_matrix();
61 to form
62 (C/dt - J(F))*dv = F(v)
63 After a nrn_solve() the answer, dv, is stored in the right hand side
64 vector.
65 
66 However, one must be aware of the fact that the cvode state vector
67 y is not the vector y for the fixed step in two ways. 1) the cvode
68 state vector includes ALL states, including channel states.
69 2) the cvode state vector does NOT include the zero area nodes
70 (since the capacitance for those nodes are 0). Furthermore, cvode
71 cannot work with the extracellular mechanism (both because extracellular
72 capacitance is often 0 and because more than one dv/dt is involved
73 in some of the current balance equations) or LinearMechanism (same reasons).
74 In that case the current balance equations are of the differential
75 algebraic form c*dv/dt = f(v) where c is non-diagonal and may have empty rows.
76 The variable step method for these cases is handled by daspk.
77 
78 */
79 
80 // determine neq_ and vector of pointers to scatter/gather y
81 // as well as algebraic nodes (no_cap)
82 
84 #if PARANEURON
85  if (!use_partrans_ && nrnmpi_numprocs > 1 && (nrnmpi_v_transfer_ || nrn_multisplit_solve_)) {
86  assert(nrn_nthread == 1); // we lack an NVector class for both
87  // threads and mpi together
88  // could be a lot better.
89  use_partrans_ = true;
90  } else
91 #endif
92  if (!structure_change_) {
93  return false;
94  }
95  if (ctd_[0].cv_memb_list_ == nil) {
96  neq_ = 0;
97  if (use_daspk_) {
98  return true;
99  }
100  if (nrn_nonvint_block_ode_count(0, 0)) {
101  return true;
102  }
103  return false;
104  }
105  return true;
106 }
107 
109  double vtol;
110 
111  NrnThread* _nt;
112  CvMembList* cml;
113  Memb_list* ml;
114  Memb_func* mf;
115  int i, j, zneq, zneq_v, zneq_cap_v;
116  // printf("Cvode::init_eqn\n");
117  if (nthsizes_) {
118  delete[] nthsizes_;
119  nthsizes_ = 0;
120  }
121  neq_ = 0;
122  for (int id = 0; id < nctd_; ++id) {
123  CvodeThreadData& z = ctd_[id];
124  z.cmlcap_ = nil;
125  z.cmlext_ = nil;
126  for (cml = z.cv_memb_list_; cml; cml = cml->next) {
127  if (cml->index == CAP) {
128  z.cmlcap_ = cml;
129  }
130  if (cml->index == EXTRACELL) {
131  z.cmlext_ = cml;
132  }
133  }
134  }
135  if (use_daspk_) {
136  daspk_init_eqn();
137  return;
138  }
139  FOR_THREADS(_nt) {
140  // for lvardt, this body done only once and for ctd_[0]
141  CvodeThreadData& z = ctd_[_nt->id];
142  // how many ode's are there? First ones are non-zero capacitance
143  // nodes with non-zero capacitance
144  zneq_cap_v = z.cmlcap_ ? z.cmlcap_->ml->nodecount : 0;
145  zneq = zneq_cap_v;
146  z.neq_v_ = z.nonvint_offset_ = zneq;
147  // now add the membrane mechanism ode's to the count
148  for (cml = z.cv_memb_list_; cml; cml = cml->next) {
149  nrn_ode_count_t s = memb_func[cml->index].ode_count;
150  if (s) {
151  zneq += cml->ml->nodecount * (*s)(cml->index);
152  }
153  }
154  z.nonvint_extra_offset_ = zneq;
155  if (z.pv_) {
156  delete[] z.pv_;
157  delete[] z.pvdot_;
158  z.pv_ = 0;
159  z.pvdot_ = 0;
160  }
161  if (z.nonvint_extra_offset_) {
162  z.pv_ = new double*[z.nonvint_extra_offset_];
163  z.pvdot_ = new double*[z.nonvint_extra_offset_];
164  }
165  zneq += nrn_nonvint_block_ode_count(zneq, _nt->id);
166  z.nvsize_ = zneq;
167  z.nvoffset_ = neq_;
168  neq_ += zneq;
169 #if 0
170 printf("%d Cvode::init_eqn id=%d neq_v_=%d #nonvint=%d #nonvint_extra=%d nvsize=%d\n",
173 #endif
174  if (nth_) {
175  break;
176  } // lvardt
177  }
178 #if PARANEURON
179  if (use_partrans_) {
180  global_neq_ = nrnmpi_int_sum_reduce(neq_);
181  // printf("%d global_neq_=%d neq=%d\n", nrnmpi_myid, global_neq_, neq_);
182  }
183 #endif
185  for (int id = 0; id < nctd_; ++id) {
186  CvodeThreadData& z = ctd_[id];
187  double* atv = n_vector_data(atolnvec_, id);
188  zneq_cap_v = z.cmlcap_ ? z.cmlcap_->ml->nodecount : 0;
189  zneq = z.nvsize_;
190  zneq_v = zneq_cap_v;
191 
192  for (i = 0; i < zneq; ++i) {
193  atv[i] = ncv_->atol();
194  }
195  vtol = 1.;
196  if (!vsym) {
198  }
199  if (vsym->extra) {
200  double x;
201  x = vsym->extra->tolerance;
202  if (x != 0 && x < vtol) {
203  vtol = x;
204  }
205  }
206  for (i = 0; i < zneq_cap_v; ++i) {
207  atv[i] *= vtol;
208  }
209 
210  // deal with voltage nodes
211  // only cap nodes for cvode
212  for (i = 0; i < z.v_node_count_; ++i) {
213  // sentinal values for determining no_cap
214  NODERHS(z.v_node_[i]) = 1.;
215  }
216  for (i = 0; i < zneq_cap_v; ++i) {
217  ml = z.cmlcap_->ml;
218  z.pv_[i] = &NODEV(ml->nodelist[i]);
219  z.pvdot_[i] = &(NODERHS(ml->nodelist[i]));
220  *z.pvdot_[i] = 0.; // only ones = 1 are no_cap
221  }
222 
223  // the remainder are no_cap nodes
224  if (z.no_cap_node_) {
225  delete[] z.no_cap_node_;
226  delete[] z.no_cap_child_;
227  }
228  z.no_cap_node_ = new Node*[z.v_node_count_ - zneq_cap_v];
229  z.no_cap_child_ = new Node*[z.v_node_count_ - zneq_cap_v];
230  z.no_cap_count_ = 0;
231  j = 0;
232  for (i = 0; i < z.v_node_count_; ++i) {
233  if (NODERHS(z.v_node_[i]) > .5) {
234  z.no_cap_node_[z.no_cap_count_++] = z.v_node_[i];
235  }
236  if (z.v_parent_[i] && NODERHS(z.v_parent_[i]) > .5) {
237  z.no_cap_child_[j++] = z.v_node_[i];
238  }
239  }
241 
242  // use the sentinal values in NODERHS to construct a new no cap membrane list
243  new_no_cap_memb(z, _nt);
244 
245  // map the membrane mechanism ode state and dstate pointers
246  int ieq = zneq_v;
247  for (cml = z.cv_memb_list_; cml; cml = cml->next) {
248  int n;
249  ml = cml->ml;
250  mf = memb_func + cml->index;
251  nrn_ode_count_t sc = mf->ode_count;
252  if (sc && ((n = (*sc)(cml->index)) > 0)) {
253  // Note: if mf->hoc_mech then all cvode related
254  // callbacks are NULL (including ode_count)
255  // See src/nrniv/hocmech.cpp. That won't change but
256  // if it does, hocmech.cpp must follow all the
257  // nrn_ode_..._t prototypes to avoid segfault
258  // with Apple M1.
259  nrn_ode_map_t s = mf->ode_map;
260  for (j = 0; j < ml->nodecount; ++j) {
261  (*s)(ieq,
262  z.pv_ + ieq,
263  z.pvdot_ + ieq,
264  ml->data[j],
265  ml->pdata[j],
266  atv + ieq,
267  cml->index);
268  ieq += n;
269  }
270  }
271  }
273  }
274  structure_change_ = false;
275 }
276 
278  int i, n;
279  CvMembList *cml, *ncm;
280  Memb_list* ml;
282  z.no_cap_memb_ = nil;
283  for (cml = z.cv_memb_list_; cml; cml = cml->next) {
284  Memb_list* ml = cml->ml;
285  Memb_func* mf = memb_func + cml->index;
286  // only point processes with currents are possibilities
287  if (!mf->is_point || !mf->current) {
288  continue;
289  }
290  // count how many at no cap nodes
291  n = 0;
292  for (i = 0; i < ml->nodecount; ++i) {
293  if (NODERHS(ml->nodelist[i]) > .5) {
294  ++n;
295  }
296  }
297  if (n == 0)
298  continue;
299  // keep same order
300  if (z.no_cap_memb_ == nil) {
301  z.no_cap_memb_ = new CvMembList();
302  ncm = z.no_cap_memb_;
303  } else {
304  ncm->next = new CvMembList();
305  ncm = ncm->next;
306  }
307  ncm->next = nil;
308  ncm->index = cml->index;
309  ncm->ml->nodecount = n;
310  // allocate
311  ncm->ml->nodelist = new Node*[n];
312 #if CACHEVEC
313  ncm->ml->nodeindices = new int[n];
314 #endif
315  if (mf->hoc_mech) {
316  ncm->ml->prop = new Prop*[n];
317  } else {
318  ncm->ml->data = new double*[n];
319  ncm->ml->pdata = new Datum*[n];
320  }
321  ncm->ml->_thread = ml->_thread; // can share this
322  // fill
323  n = 0;
324  for (i = 0; i < ml->nodecount; ++i) {
325  if (NODERHS(ml->nodelist[i]) > .5) {
326  ncm->ml->nodelist[n] = ml->nodelist[i];
327 #if CACHEVEC
328  ncm->ml->nodeindices[n] = ml->nodeindices[i];
329 #endif
330  if (mf->hoc_mech) {
331  ncm->ml->prop[n] = ml->prop[i];
332  } else {
333  ncm->ml->data[n] = ml->data[i];
334  ncm->ml->pdata[n] = ml->pdata[i];
335  }
336  ++n;
337  }
338  }
339  }
340 }
341 
343  // DASPK equation order is exactly the same order as the
344  // fixed step method for current balance (including
345  // extracellular nodes) and linear mechanism. Remaining ode
346  // equations are same order as for Cvode. Thus, daspk differs from
347  // cvode order primarily in that cap and no-cap nodes are not
348  // distinguished.
349  // note that only one thread is allowed for sparse right now.
350  NrnThread* _nt = nrn_threads;
351  CvodeThreadData& z = ctd_[0];
352  double vtol;
353  // printf("Cvode::daspk_init_eqn\n");
354  int i, j, in, ie, k, zneq;
355 
356  // how many equations are there?
357  neq_ = 0;
358  Memb_func* mf;
359  CvMembList* cml;
360  // start with all the equations for the fixed step method.
361  if (use_sparse13 == 0 || diam_changed != 0) {
362  recalc_diam();
363  }
364  zneq = spGetSize(_nt->_sp13mat, 0);
365  z.neq_v_ = z.nonvint_offset_ = zneq;
366  // now add the membrane mechanism ode's to the count
367  for (cml = z.cv_memb_list_; cml; cml = cml->next) {
368  nrn_ode_count_t s = memb_func[cml->index].ode_count;
369  if (s) {
370  zneq += cml->ml->nodecount * (*s)(cml->index);
371  }
372  }
373  z.nonvint_extra_offset_ = zneq;
374  zneq += nrn_nonvint_block_ode_count(zneq, _nt->id);
375  z.nvsize_ = zneq;
376  z.nvoffset_ = neq_;
377  neq_ = z.nvsize_;
378  // printf("Cvode::daspk_init_eqn: neq_v_=%d neq_=%d\n", neq_v_, neq_);
379  if (z.pv_) {
380  delete[] z.pv_;
381  delete[] z.pvdot_;
382  }
383  z.pv_ = new double*[z.nonvint_extra_offset_];
384  z.pvdot_ = new double*[z.nonvint_extra_offset_];
386  double* atv = n_vector_data(atolnvec_, 0);
387  for (i = 0; i < neq_; ++i) {
388  atv[i] = ncv_->atol();
389  }
390  vtol = 1.;
391  if (!vsym) {
393  }
394  if (vsym->extra) {
395  double x;
396  x = vsym->extra->tolerance;
397  if (x != 0 && x < vtol) {
398  vtol = x;
399  }
400  }
401  // deal with voltage and extracellular and linear circuit nodes
402  // for daspk the order is the same
404  if (use_sparse13) {
405  for (in = 0; in < _nt->end; ++in) {
406  Node* nd;
407  Extnode* nde;
408  nd = _nt->_v_node[in];
409  nde = nd->extnode;
410  i = nd->eqn_index_ - 1; // the sparse matrix index starts at 1
411  z.pv_[i] = &NODEV(nd);
412  z.pvdot_[i] = nd->_rhs;
413  if (nde) {
414  for (ie = 0; ie < nlayer; ++ie) {
415  k = i + ie + 1;
416  z.pv_[k] = nde->v + ie;
417  z.pvdot_[k] = nde->_rhs[ie];
418  }
419  }
420  }
421  nrndae_dkmap(z.pv_, z.pvdot_);
422  for (i = 0; i < z.neq_v_; ++i) {
423  atv[i] *= vtol;
424  }
425  }
426 
427  // map the membrane mechanism ode state and dstate pointers
428  int ieq = z.neq_v_;
429  for (cml = z.cv_memb_list_; cml; cml = cml->next) {
430  int n;
431  mf = memb_func + cml->index;
432  nrn_ode_count_t sc = mf->ode_count;
433  if (sc && ((n = (*sc)(cml->index)) > 0)) {
434  Memb_list* ml = cml->ml;
435  nrn_ode_map_t s = mf->ode_map;
436  for (j = 0; j < ml->nodecount; ++j) {
437  (*s)(ieq,
438  z.pv_ + ieq,
439  z.pvdot_ + ieq,
440  ml->data[j],
441  ml->pdata[j],
442  atv + ieq,
443  cml->index);
444  ieq += n;
445  }
446  }
447  }
448  structure_change_ = false;
449 }
450 
451 double* Cvode::n_vector_data(N_Vector v, int tid) {
452  if (!v) {
453  return 0;
454  }
455  if (nctd_ > 1) {
456  N_Vector subvec = ((N_Vector*) N_VGetArrayPointer(v))[tid];
457  return N_VGetArrayPointer(subvec);
458  }
459  return N_VGetArrayPointer(v);
460 }
461 
462 extern void nrn_extra_scatter_gather(int, int);
463 
464 void Cvode::scatter_y(double* y, int tid) {
465  int i;
466  CvodeThreadData& z = CTD(tid);
467  for (i = 0; i < z.nonvint_extra_offset_; ++i) {
468  *(z.pv_[i]) = y[i];
469  // printf("%d scatter_y %d %d %g\n", nrnmpi_myid, tid, i, y[i]);
470  }
471  CvMembList* cml;
472  for (cml = z.cv_memb_list_; cml; cml = cml->next) {
473  Memb_func* mf = memb_func + cml->index;
474  if (mf->ode_synonym) {
475  nrn_ode_synonym_t s = mf->ode_synonym;
476  Memb_list* ml = cml->ml;
477  (*s)(ml->nodecount, ml->data, ml->pdata);
478  }
479  }
480  nrn_extra_scatter_gather(0, tid);
481 }
482 
483 static Cvode* gather_cv;
484 static N_Vector gather_vec;
485 static void* gather_y_thread(NrnThread* nt) {
486  Cvode* cv = gather_cv;
487  cv->gather_y(cv->n_vector_data(gather_vec, nt->id), nt->id);
488  return 0;
489 }
490 void Cvode::gather_y(N_Vector y) {
491  if (nth_) {
492  gather_y(N_VGetArrayPointer(y), nth_->id);
493  return;
494  }
495  gather_cv = this;
496  gather_vec = y;
498 }
499 void Cvode::gather_y(double* y, int tid) {
500  int i;
501  CvodeThreadData& z = CTD(tid);
502  nrn_extra_scatter_gather(1, tid);
503  for (i = 0; i < z.nonvint_extra_offset_; ++i) {
504  y[i] = *(z.pv_[i]);
505  // printf("gather_y %d %d %g\n", tid, i, y[i]);
506  }
507 }
508 void Cvode::scatter_ydot(double* ydot, int tid) {
509  int i;
510  CvodeThreadData& z = CTD(tid);
511  for (i = 0; i < z.nonvint_extra_offset_; ++i) {
512  *(z.pvdot_[i]) = ydot[i];
513  // printf("scatter_ydot %d %d %g\n", tid, i, ydot[i]);
514  }
515 }
516 static void* gather_ydot_thread(NrnThread* nt) {
517  Cvode* cv = gather_cv;
518  cv->gather_ydot(cv->n_vector_data(gather_vec, nt->id), nt->id);
519  return 0;
520 }
521 void Cvode::gather_ydot(N_Vector y) {
522  if (nth_) {
523  gather_ydot(N_VGetArrayPointer(y), nth_->id);
524  return;
525  }
526  gather_cv = this;
527  gather_vec = y;
529 }
530 void Cvode::gather_ydot(double* ydot, int tid) {
531  int i;
532  if (ydot) {
533  CvodeThreadData& z = CTD(tid);
534  for (i = 0; i < z.nonvint_extra_offset_; ++i) {
535  ydot[i] = *(z.pvdot_[i]);
536  // printf("%d gather_ydot %d %d %g\n", nrnmpi_myid, tid, i, ydot[i]);
537  }
538  }
539 }
540 
541 int Cvode::setup(N_Vector ypred, N_Vector fpred) {
542  // printf("Cvode::setup\n");
543  if (nth_) {
544  return 0;
545  }
546  ++jac_calls_;
547  CvodeThreadData& z = CTD(0);
548  double gamsave = nrn_threads->_dt;
549  nrn_threads->_dt = gam();
551  nrn_threads->_dt = gamsave;
552  return 0;
553 }
554 
555 int Cvode::solvex_thread(double* b, double* y, NrnThread* nt) {
556  // printf("Cvode::solvex_thread %d t=%g t_=%g\n", nt->id, nt->t, t_);
557  // printf("Cvode::solvex_thread %d %g\n", nt->id, gam());
558  // printf("\tenter b\n");
559  // for (int i=0; i < neq_; ++i) { printf("\t\t%d %g\n", i, b[i]);}
560  int i;
561  CvodeThreadData& z = CTD(nt->id);
562  nt->cj = 1. / gam();
563  nt->_dt = gam();
564  if (z.nvsize_ == 0) {
565  return 0;
566  }
567  lhs(nt); // special version for cvode.
568  scatter_ydot(b, nt->id);
569  if (z.cmlcap_)
570  nrn_mul_capacity(nt, z.cmlcap_->ml);
571  for (i = 0; i < z.no_cap_count_; ++i) {
572  NODERHS(z.no_cap_node_[i]) = 0.;
573  }
574  // solve it
575 #if PARANEURON
576  if (nrn_multisplit_solve_) {
577  (*nrn_multisplit_solve_)();
578  } else
579 #endif
580  {
581  triang(nt);
582  bksub(nt);
583  }
584  // for (i=0; i < v_node_count; ++i) {
585  // printf("%d rhs %d %g t=%g\n", nrnmpi_myid, i, VEC_RHS(i), t);
586  //}
587  if (ncv_->stiff() == 2) {
588  solvemem(nt);
589  } else {
590  // bug here should multiply by gam
591  }
592  gather_ydot(b, nt->id);
593  // printf("\texit b\n");
594  // for (i=0; i < neq_; ++i) { printf("\t\t%d %g\n", i, b[i]);}
595  nrn_nonvint_block_ode_solve(z.nvsize_, b, y, nt->id);
596  return 0;
597 }
598 
600  // printf("Cvode::solvex_thread %d t=%g t_=%g\n", nt->id, nt->t, t_);
601  // printf("Cvode::solvex_thread %d %g\n", nt->id, gam());
602  // printf("\tenter b\n");
603  // for (int i=0; i < neq_; ++i) { printf("\t\t%d %g\n", i, b[i]);}
604  int i;
605  CvodeThreadData& z = ctd_[nt->id];
606  nt->cj = 1. / gam();
607  nt->_dt = gam();
608  if (z.nvsize_ == 0) {
609  return 0;
610  }
611  lhs(nt); // special version for cvode.
612  scatter_ydot(b, nt->id);
613  if (z.cmlcap_)
614  nrn_mul_capacity(nt, z.cmlcap_->ml);
615  for (i = 0; i < z.no_cap_count_; ++i) {
616  NODERHS(z.no_cap_node_[i]) = 0.;
617  }
618  // solve it
620  return 0;
621 }
624  return 0;
625 }
628  // for (i=0; i < v_node_count; ++i) {
629  // printf("%d rhs %d %g t=%g\n", nrnmpi_myid, i, VEC_RHS(i), t);
630  //}
631  if (ncv_->stiff() == 2) {
632  solvemem(nt);
633  } else {
634  // bug here should multiply by gam
635  }
636  gather_ydot(b, nt->id);
637  // printf("\texit b\n");
638  // for (i=0; i < neq_; ++i) { printf("\t\t%d %g\n", i, b[i]);}
639  return 0;
640 }
641 
643  // all the membrane mechanism matrices
644  CvodeThreadData& z = CTD(nt->id);
645  CvMembList* cml;
646  for (cml = z.cv_memb_list_; cml; cml = cml->next) { // probably can start at 6 or hh
647  Memb_func* mf = memb_func + cml->index;
648  if (mf->ode_matsol) {
649  Memb_list* ml = cml->ml;
650  Pvmi s = mf->ode_matsol;
651  (*s)(nt, ml, cml->index);
652  if (errno) {
653  if (nrn_errno_check(cml->index)) {
654  hoc_warning("errno set during ode jacobian solve", (char*) 0);
655  }
656  }
657  }
658  }
659  long_difus_solve(2, nt);
660 }
661 
662 void Cvode::fun_thread(double tt, double* y, double* ydot, NrnThread* nt) {
663  CvodeThreadData& z = CTD(nt->id);
664  fun_thread_transfer_part1(tt, y, nt);
665  nrn_nonvint_block_ode_fun(z.nvsize_, y, ydot, nt->id);
666  fun_thread_transfer_part2(ydot, nt);
667 }
668 
669 void Cvode::fun_thread_transfer_part1(double tt, double* y, NrnThread* nt) {
670  CvodeThreadData& z = CTD(nt->id);
671  nt->_t = tt;
672 
673  // fix this!!!
674  nt->_dt = h(); // really does not belong here but dt is needed for events
675  if (nt->_dt == 0.) {
676  nt->_dt = 1e-8;
677  }
678 
679  // printf("%p fun %d %.15g %g\n", this, neq_, _t, _dt);
680  play_continuous_thread(tt, nt);
681  if (z.nvsize_ == 0) {
682  return;
683  }
684  scatter_y(y, nt->id);
685 #if PARANEURON
686  if (use_partrans_) {
687  nrnmpi_assert_opstep(opmode_, nt->_t);
688  }
689 #endif
690  nocap_v(nt); // vm at nocap nodes consistent with adjacent vm
691 }
692 
694  CvodeThreadData& z = CTD(nt->id);
695  if (z.nvsize_ == 0) {
696  return;
697  }
698 #if 1 || PARANEURON
699  if (nrnthread_v_transfer_) {
700  (*nrnthread_v_transfer_)(nt);
701  }
702 #endif
704  rhs(nt); // similar to nrn_rhs in treeset.cpp
705 #if PARANEURON
706  if (nrn_multisplit_solve_) { // non-zero area nodes need an adjustment
708  }
709 #endif
710  do_ode(nt);
711  // divide by cm and compute capacity current
712  if (z.cmlcap_)
713  nrn_div_capacity(nt, z.cmlcap_->ml);
714  if (nt->_nrn_fast_imem) {
715  double* p = nt->_nrn_fast_imem->_nrn_sav_rhs;
716  for (int i = 0; i < z.v_node_count_; ++i) {
717  Node* nd = z.v_node_[i];
718  p[nd->v_node_index] *= NODEAREA(nd) * 0.01;
719  }
720  }
721  gather_ydot(ydot, nt->id);
722  before_after(z.after_solve_, nt);
723  // for (int i=0; i < z.neq_; ++i) { printf("\t%d %g %g\n", i, y[i], ydot?ydot[i]:-1e99);}
724 }
725 
726 void Cvode::fun_thread_ms_part1(double tt, double* y, NrnThread* nt) {
727  CvodeThreadData& z = ctd_[nt->id];
728  nt->_t = tt;
729 
730  // fix this!!!
731  nt->_dt = h(); // really does not belong here but dt is needed for events
732  if (nt->_dt == 0.) {
733  nt->_dt = 1e-8;
734  }
735 
736  // printf("%p fun %d %.15g %g\n", this, neq_, _t, _dt);
737  play_continuous_thread(tt, nt);
738  scatter_y(y, nt->id);
739 #if PARANEURON
740  if (use_partrans_) {
741  nrnmpi_assert_opstep(opmode_, nt->_t);
742  }
743 #endif
744  nocap_v_part1(nt); // vm at nocap nodes consistent with adjacent vm
745 }
747  nocap_v_part2(nt); // vm at nocap nodes consistent with adjacent vm
748 }
749 void Cvode::fun_thread_ms_part34(double* ydot, NrnThread* nt) {
751  fun_thread_ms_part4(ydot, nt);
752 }
754  nocap_v_part3(nt); // should be by itself in fun_thread_part2_5 if
755  // following is true and a gap is in 0 area node
756 }
757 void Cvode::fun_thread_ms_part4(double* ydot, NrnThread* nt) {
758 #if 1 || PARANEURON
759  if (nrnthread_v_transfer_) {
760  (*nrnthread_v_transfer_)(nt);
761  }
762 #endif
763  CvodeThreadData& z = ctd_[nt->id];
764  if (z.nvsize_ == 0) {
765  return;
766  }
768  rhs(nt); // similar to nrn_rhs in treeset.cpp
770  do_ode(nt);
771  // divide by cm and compute capacity current
772  nrn_div_capacity(nt, z.cmlcap_->ml);
773  gather_ydot(ydot, nt->id);
774  before_after(z.after_solve_, nt);
775  // for (int i=0; i < z.neq_; ++i) { printf("\t%d %g %g\n", i, y[i], ydot?ydot[i]:-1e99);}
776 }
777 
779  BAMechList* ba;
780  int i, j;
781  for (ba = baml; ba; ba = ba->next) {
782  nrn_bamech_t f = ba->bam->f;
783  Memb_list* ml = ba->ml;
784  for (i = 0; i < ml->nodecount; ++i) {
785  (*f)(ml->nodelist[i], ml->data[i], ml->pdata[i], ml->_thread, nt);
786  }
787  }
788 }
789 
790 /*
791 v at nodes with capacitance is correct (from scatter v) however
792 v at no-cap nodes is out of date since the values are from the
793 previous call. v would merely be the weighted average of
794 the adjacent v's except for the possibility of membrane
795 currents at branch points. We thus need to calculate both i(v)
796 and di/dv at those zero area nodes so that we can solve the
797 algebraic equation (di/dv + a_j)*vmnew = - i(vmold) + a_j*v_j.
798 The simplest case is no membrane current and root or leaf. In that
799 case vmnew = v_j. The next simplest case is no membrane current.
800 In that case, vm is the weighted sum (via the axial coefficients)
801 of v_j.
802 For now we handle only the general case when there are membrane currents
803 This was done by constructing a list of membrane mechanisms that
804 contribute to the membrane current at the nocap nodes.
805 */
806 
808  int i;
809  CvodeThreadData& z = CTD(_nt->id);
810 
811  for (i = 0; i < z.no_cap_count_; ++i) { // initialize storage
812  Node* nd = z.no_cap_node_[i];
813  NODED(nd) = 0;
814  NODERHS(nd) = 0;
815  }
816  // compute the i(vmold) and di/dv
817  rhs_memb(z.no_cap_memb_, _nt);
818  lhs_memb(z.no_cap_memb_, _nt);
819 
820  for (i = 0; i < z.no_cap_count_; ++i) { // parent axial current
821  Node* nd = z.no_cap_node_[i];
822  // following from global v_parent
823  NODERHS(nd) += NODED(nd) * NODEV(nd);
824  Node* pnd = _nt->_v_parent[nd->v_node_index];
825  if (pnd) {
826  NODERHS(nd) -= NODEB(nd) * NODEV(pnd);
827  NODED(nd) -= NODEB(nd);
828  }
829  }
830 
831  for (i = 0; i < z.no_cap_child_count_; ++i) { // child axial current
832  Node* nd = z.no_cap_child_[i];
833  // following from global v_parent
834  Node* pnd = _nt->_v_parent[nd->v_node_index];
835  NODERHS(pnd) -= NODEA(nd) * NODEV(nd);
836  NODED(pnd) -= NODEA(nd);
837  }
838 
839 #if PARANEURON
840  if (nrn_multisplit_solve_) { // add up the multisplit equations
842  }
843 #endif
844 
845  for (i = 0; i < z.no_cap_count_; ++i) {
846  Node* nd = z.no_cap_node_[i];
847  NODEV(nd) = NODERHS(nd) / NODED(nd);
848  // printf("%d %d %g v=%g\n", nrnmpi_myid, i, _nt->_t, NODEV(nd));
849  }
850  // no_cap v's are now consistent with adjacent v's
851 }
852 
854  int i;
855  CvodeThreadData& z = ctd_[_nt->id];
856 
857  for (i = 0; i < z.no_cap_count_; ++i) { // initialize storage
858  Node* nd = z.no_cap_node_[i];
859  NODED(nd) = 0;
860  NODERHS(nd) = 0;
861  }
862  // compute the i(vmold) and di/dv
863  rhs_memb(z.no_cap_memb_, _nt);
864  lhs_memb(z.no_cap_memb_, _nt);
865 
866  for (i = 0; i < z.no_cap_count_; ++i) { // parent axial current
867  Node* nd = z.no_cap_node_[i];
868  // following from global v_parent
869  NODERHS(nd) += NODED(nd) * NODEV(nd);
870  Node* pnd = _nt->_v_parent[nd->v_node_index];
871  if (pnd) {
872  NODERHS(nd) -= NODEB(nd) * NODEV(pnd);
873  NODED(nd) -= NODEB(nd);
874  }
875  }
876 
877  for (i = 0; i < z.no_cap_child_count_; ++i) { // child axial current
878  Node* nd = z.no_cap_child_[i];
879  // following from global v_parent
880  Node* pnd = _nt->_v_parent[nd->v_node_index];
881  NODERHS(pnd) -= NODEA(nd) * NODEV(nd);
882  NODED(pnd) -= NODEA(nd);
883  }
885 }
888 }
890  int i;
892  CvodeThreadData& z = ctd_[_nt->id];
893  for (i = 0; i < z.no_cap_count_; ++i) {
894  Node* nd = z.no_cap_node_[i];
895  NODEV(nd) = NODERHS(nd) / NODED(nd);
896  // printf("%d %d %g v=%g\n", nrnmpi_myid, i, t, NODEV(nd));
897  }
898  // no_cap v's are now consistent with adjacent v's
899 }
900 
902  // all the membrane mechanism ode's
903  CvodeThreadData& z = CTD(_nt->id);
904  CvMembList* cml;
905  Memb_func* mf;
906  for (cml = z.cv_memb_list_; cml; cml = cml->next) { // probably can start at 6 or hh
907  mf = memb_func + cml->index;
908  if (mf->ode_spec) {
909  Pvmi s = mf->ode_spec;
910  Memb_list* ml = cml->ml;
911  (*s)(_nt, ml, cml->index);
912  if (errno) {
913  if (nrn_errno_check(cml->index)) {
914  hoc_warning("errno set during ode evaluation", (char*) 0);
915  }
916  }
917  }
918  }
919  long_difus_solve(1, _nt);
920 }
921 
922 static Cvode* nonode_cv;
923 static void* nonode_thread(NrnThread* nt) {
924  nonode_cv->do_nonode(nt);
925  return 0;
926 }
927 void Cvode::do_nonode(NrnThread* _nt) { // all the hacked integrators, etc, in SOLVE procedure
928  // almost a verbatim copy of nonvint in fadvance.cpp
929  if (!_nt) {
930  if (nrn_nthread > 1) {
931  nonode_cv = this;
933  return;
934  }
935  _nt = nrn_threads;
936  }
937  CvodeThreadData& z = CTD(_nt->id);
938  CvMembList* cml;
939  for (cml = z.cv_memb_list_; cml; cml = cml->next) {
940  Memb_func* mf = memb_func + cml->index;
941  if (mf->state) {
942  Memb_list* ml = cml->ml;
943  if (!mf->ode_spec) {
944  Pvmi s = mf->state;
945  (*s)(_nt, ml, cml->index);
946 #if 0
947  if (errno) {
948  if (nrn_errno_check(cml->index)) {
949 hoc_warning("errno set during calculation of states", (char*)0);
950  }
951  }
952 #endif
953  } else if (mf->singchan_) {
954  Pvmi s = mf->singchan_;
955  (*s)(_nt, ml, cml->index);
956  }
957  }
958  }
959 }
960 
961 void Cvode::states(double* pd) {
962  int i, id;
963  for (id = 0; id < nctd_; ++id) {
964  CvodeThreadData& z = ctd_[id];
965  double* s = n_vector_data(y_, id);
966  for (i = 0; i < z.nvsize_; ++i) {
967  pd[i + z.nvoffset_] = s[i];
968  }
969  }
970 }
971 
972 void Cvode::dstates(double* pd) {
973  int i, id;
974  for (id = 0; id < nctd_; ++id) {
975  CvodeThreadData& z = ctd_[id];
976  for (i = 0; i < z.nonvint_extra_offset_; ++i) {
977  pd[i + z.nvoffset_] = *z.pvdot_[i];
978  }
980  }
981 }
982 
983 void Cvode::error_weights(double* pd) {
984  int i, id;
985  for (id = 0; id < nctd_; ++id) {
986  CvodeThreadData& z = ctd_[id];
987  double* s = n_vector_data(ewtvec(), id);
988  for (i = 0; i < z.nvsize_; ++i) {
989  pd[i + z.nvoffset_] = s[i];
990  }
991  }
992 }
993 
994 void Cvode::acor(double* pd) {
995  int i, id;
996  NrnThread* nt;
997  for (id = 0; id < nctd_; ++id) {
998  CvodeThreadData& z = ctd_[id];
999  double* s = n_vector_data(acorvec(), id);
1000  for (i = 0; i < z.nvsize_; ++i) {
1001  pd[i + z.nvoffset_] = s[i];
1002  }
1003  }
1004 }
1005 
1007  int i;
1008  for (i = 0; i < nctd_; ++i) {
1009  CvodeThreadData& z = ctd_[i];
1010  if (z.play_) {
1011  delete z.play_;
1012  }
1013  z.play_ = nil;
1014  if (z.record_) {
1015  delete z.record_;
1016  }
1017  z.record_ = nil;
1018  }
1019 }
1020 
1022  CvodeThreadData& z = CTD(pr->ith_);
1023  if (!z.record_) {
1024  z.record_ = new PlayRecList(1);
1025  }
1026  z.record_->append(pr);
1027 }
1028 
1030  if (nth_) { // lvardt
1032  } else {
1033  for (int i = 0; i < nrn_nthread; ++i) {
1034  NrnThread* nt = nrn_threads + i;
1035  CvodeThreadData& z = ctd_[i];
1036  if (z.before_step_) {
1037  before_after(z.before_step_, nt);
1038  }
1039  if (z.record_) {
1040  for (long i = 0; i < z.record_->count(); ++i) {
1041  z.record_->item(i)->continuous(t_);
1042  }
1043  }
1044  }
1045  }
1046 }
1047 
1049  CvodeThreadData& z = CTD(nt->id);
1050  if (z.before_step_) {
1051  before_after(z.before_step_, nt);
1052  }
1053  if (z.record_) {
1054  for (long i = 0; i < z.record_->count(); ++i) {
1055  z.record_->item(i)->continuous(t_);
1056  }
1057  }
1058 }
1059 
1061  CvodeThreadData& z = CTD(pr->ith_);
1062  if (!z.play_) {
1063  z.play_ = new PlayRecList(1);
1064  }
1065  z.play_->append(pr);
1066 }
1067 
1068 void Cvode::play_continuous(double tt) {
1069  if (nth_) { // lvardt
1071  } else {
1072  for (int i = 0; i < nrn_nthread; ++i) {
1073  CvodeThreadData& z = ctd_[i];
1074  if (z.play_) {
1075  for (long i = 0; i < z.play_->count(); ++i) {
1076  z.play_->item(i)->continuous(tt);
1077  }
1078  }
1079  }
1080  }
1081 }
1083  CvodeThreadData& z = CTD(nt->id);
1084  if (z.play_) {
1085  for (long i = 0; i < z.play_->count(); ++i) {
1086  z.play_->item(i)->continuous(tt);
1087  }
1088  }
1089 }
#define nil
Definition: enter-scope.h:36
Memb_func * memb_func
Definition: init.cpp:123
static Node * pnd
Definition: clamp.cpp:33
Memb_list * ml
Definition: cvodeobj.h:37
BAMechList * next
Definition: cvodeobj.h:35
BAMech * bam
Definition: cvodeobj.h:36
Memb_list * ml
Definition: cvodeobj.h:28
int index
Definition: cvodeobj.h:29
CvMembList * next
Definition: cvodeobj.h:27
Definition: cvodeobj.h:76
void rhs_memb(CvMembList *, NrnThread *)
Definition: cvtrset.cpp:62
void fun_thread_ms_part2(NrnThread *nt)
Definition: occvode.cpp:746
int neq_
Definition: cvodeobj.h:219
double t_
Definition: cvodeobj.h:105
long int * nthsizes_
Definition: cvodeobj.h:217
void do_nonode(NrnThread *nt=0)
Definition: occvode.cpp:927
int solvex_thread_part2(NrnThread *nt)
Definition: occvode.cpp:622
void rhs(NrnThread *)
Definition: cvtrset.cpp:16
void lhs_memb(CvMembList *, NrnThread *)
Definition: cvtrset.cpp:109
void play_continuous_thread(double t, NrnThread *)
Definition: occvode.cpp:1082
void nocap_v(NrnThread *)
Definition: occvode.cpp:807
int nctd_
Definition: cvodeobj.h:216
void states(double *)
Definition: occvode.cpp:961
N_Vector atolnvec_
Definition: cvodeobj.h:204
int jac_calls_
Definition: cvodeobj.h:111
void dstates(double *)
Definition: occvode.cpp:972
bool init_global()
Definition: occvode.cpp:83
void triang(NrnThread *)
Definition: cvtrset.cpp:130
void fun_thread_transfer_part1(double t, double *y, NrnThread *nt)
Definition: occvode.cpp:669
void record_add(PlayRecord *)
Definition: occvode.cpp:1021
CvodeThreadData * ctd_
Definition: cvodeobj.h:214
void play_add(PlayRecord *)
Definition: occvode.cpp:1060
void gather_y(N_Vector)
Definition: occvode.cpp:490
void daspk_init_eqn()
Definition: occvode.cpp:342
int setup(N_Vector ypred, N_Vector fpred)
Definition: occvode.cpp:541
void play_continuous(double t)
Definition: occvode.cpp:1068
void record_continuous()
Definition: occvode.cpp:1029
void lhs(NrnThread *)
Definition: cvtrset.cpp:83
void fun_thread_ms_part4(double *ydot, NrnThread *nt)
Definition: occvode.cpp:757
N_Vector y_
Definition: cvodeobj.h:203
void nocap_v_part2(NrnThread *)
Definition: occvode.cpp:886
void fun_thread_transfer_part2(double *ydot, NrnThread *nt)
Definition: occvode.cpp:693
void new_no_cap_memb(CvodeThreadData &, NrnThread *)
Definition: occvode.cpp:277
void fun_thread_ms_part34(double *ydot, NrnThread *nt)
Definition: occvode.cpp:749
void fun_thread_ms_part1(double t, double *y, NrnThread *nt)
Definition: occvode.cpp:726
void record_continuous_thread(NrnThread *)
Definition: occvode.cpp:1048
int solvex_thread_part3(double *b, NrnThread *nt)
Definition: occvode.cpp:626
bool structure_change_
Definition: cvodeobj.h:209
void nocap_v_part3(NrnThread *)
Definition: occvode.cpp:889
NetCvode * ncv_
Definition: cvodeobj.h:218
void fun_thread(double t, double *y, double *ydot, NrnThread *nt)
Definition: occvode.cpp:662
void before_after(BAMechList *, NrnThread *)
Definition: occvode.cpp:778
void fun_thread_ms_part3(NrnThread *nt)
Definition: occvode.cpp:753
N_Vector acorvec()
Definition: cvodeobj.cpp:1425
void scatter_y(double *, int)
Definition: occvode.cpp:464
NrnThread * nth_
Definition: cvodeobj.h:215
void acor(double *)
Definition: occvode.cpp:994
double * n_vector_data(N_Vector, int)
Definition: occvode.cpp:451
void bksub(NrnThread *)
Definition: cvtrset.cpp:146
void init_eqn()
Definition: occvode.cpp:108
N_Vector ewtvec()
Definition: cvodeobj.cpp:1417
double h()
Definition: cvodeobj.cpp:760
void nocap_v_part1(NrnThread *)
Definition: occvode.cpp:853
void delete_prl()
Definition: occvode.cpp:1006
void solvemem(NrnThread *)
Definition: occvode.cpp:642
double gam()
Definition: cvodeobj.cpp:752
bool use_daspk_
Definition: cvodeobj.h:180
void atolvec_alloc(int)
Definition: cvodeobj.cpp:849
int solvex_thread_part1(double *b, NrnThread *nt)
Definition: occvode.cpp:599
void scatter_ydot(double *, int)
Definition: occvode.cpp:508
void gather_ydot(N_Vector)
Definition: occvode.cpp:521
void do_ode(NrnThread *)
Definition: occvode.cpp:901
int solvex_thread(double *b, double *y, NrnThread *nt)
Definition: occvode.cpp:555
void error_weights(double *)
Definition: occvode.cpp:983
int nonvint_extra_offset_
Definition: cvodeobj.h:71
int nonvint_offset_
Definition: cvodeobj.h:70
PlayRecList * play_
Definition: cvodeobj.h:73
double ** pvdot_
Definition: cvodeobj.h:66
CvMembList * cv_memb_list_
Definition: cvodeobj.h:52
void delete_memb_list(CvMembList *)
Definition: netcvode.cpp:1500
CvMembList * no_cap_memb_
Definition: cvodeobj.h:55
double ** pv_
Definition: cvodeobj.h:65
BAMechList * before_breakpoint_
Definition: cvodeobj.h:56
CvMembList * cmlext_
Definition: cvodeobj.h:54
int v_node_count_
Definition: cvodeobj.h:60
BAMechList * after_solve_
Definition: cvodeobj.h:57
Node ** no_cap_node_
Definition: cvodeobj.h:50
CvMembList * cmlcap_
Definition: cvodeobj.h:53
Node ** v_parent_
Definition: cvodeobj.h:62
int no_cap_count_
Definition: cvodeobj.h:48
PlayRecList * record_
Definition: cvodeobj.h:72
Node ** v_node_
Definition: cvodeobj.h:61
Node ** no_cap_child_
Definition: cvodeobj.h:51
BAMechList * before_step_
Definition: cvodeobj.h:58
int no_cap_child_count_
Definition: cvodeobj.h:49
void atol(double)
Definition: netcvode.cpp:4604
void stiff(int)
Definition: netcvode.cpp:4607
Symbol * hoc_table_lookup(const char *, Symlist *)
Definition: symbol.cpp:61
#define spGetSize
Definition: cspredef.h:23
#define CTD(i)
Definition: cvodeobj.h:41
void hoc_warning(const char *, const char *)
#define assert(ex)
Definition: hocassrt.h:32
void
#define v
Definition: md1redef.h:4
#define id
Definition: md1redef.h:33
#define i
Definition: md1redef.h:12
void(* nrn_bamech_t)(Node *, double *, Datum *, Datum *, struct NrnThread *)
Definition: membfunc.h:24
#define CAP
Definition: membfunc.h:64
void(* nrn_ode_map_t)(int, double **, double **, double *, Datum *, double *, int)
Definition: membfunc.h:21
int(* nrn_ode_count_t)(int)
Definition: membfunc.h:20
void(* nrn_ode_synonym_t)(int, double **, Datum **)
Definition: membfunc.h:22
void(* Pvmi)(struct NrnThread *, Memb_list *, int)
Definition: membfunc.h:18
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
#define FOR_THREADS(nt)
Definition: multicore.h:104
void(* nrn_multisplit_solve_)()
Definition: solve.cpp:71
#define printf
Definition: mwprefix.h:26
#define nrn_nonvint_block_ode_fun(size, y, ydot, tid)
Definition: nonvintblock.h:62
#define nrn_nonvint_block_ode_count(offset, tid)
Definition: nonvintblock.h:56
#define nrn_nonvint_block_jacobian(size, ypred, ydot, tid)
Definition: nonvintblock.h:71
#define nrn_nonvint_block_ode_abstol(size, y, tid)
Definition: nonvintblock.h:74
#define nrn_nonvint_block_ode_solve(size, b, y, tid)
Definition: nonvintblock.h:67
int const size_t const size_t n
Definition: nrngsl.h:11
size_t p
size_t j
int nrnmpi_myid
int nrnmpi_numprocs
static philox4x32_key_t k
Definition: nrnran123.cpp:11
static void pr(N_Vector x)
void nrn_extra_scatter_gather(int, int)
Definition: cvodeobj.cpp:532
int diam_changed
Definition: cabcode.cpp:23
void(* nrn_multisplit_setup_)()
Definition: treeset.cpp:46
void(* nrnthread_v_transfer_)(NrnThread *)
Definition: fadvance.cpp:153
void long_difus_solve(int, NrnThread *)
Definition: ldifus.cpp:104
static void * gather_y_thread(NrnThread *nt)
Definition: occvode.cpp:485
void nrn_mul_capacity(NrnThread *, Memb_list *)
Definition: capac.cpp:88
void nrn_multisplit_nocap_v_part1(NrnThread *)
static N_Vector gather_vec
Definition: occvode.cpp:484
void nrndae_dkmap(double **, double **)
Definition: nrndae.cpp:86
static void * gather_ydot_thread(NrnThread *nt)
Definition: occvode.cpp:516
void * nrn_multisplit_triang(NrnThread *)
void nrn_multisplit_adjust_rhs(NrnThread *)
void setup_topology()
void nrn_multisplit_nocap_v()
double * sp13mat
static Symbol * vsym
Definition: occvode.cpp:49
void * nrn_multisplit_bksub(NrnThread *)
void nrn_multisplit_nocap_v_part2(NrnThread *)
void v_setup_vectors()
Definition: treeset.cpp:1631
static void * nonode_thread(NrnThread *nt)
Definition: occvode.cpp:923
void nrn_div_capacity(NrnThread *, Memb_list *)
Definition: capac.cpp:109
void recalc_diam()
Definition: treeset.cpp:953
static Cvode * nonode_cv
Definition: occvode.cpp:922
static Cvode * gather_cv
Definition: occvode.cpp:483
Symlist * hoc_built_in_symlist
Definition: ivocmac.cpp:76
int nrn_errno_check(int)
Definition: fadvance.cpp:837
void * nrn_multisplit_reduce_solve(NrnThread *)
void(* nrnmpi_v_transfer_)()
Definition: fadvance.cpp:152
void nrn_multisplit_nocap_v_part3(NrnThread *)
#define e
Definition: passive0.cpp:22
#define NODEA(n)
Definition: section.h:124
#define NODEB(n)
Definition: section.h:125
int use_sparse13
Definition: treeset.cpp:71
#define NODEV(n)
Definition: section.h:115
#define NODEAREA(n)
Definition: section.h:116
#define NODERHS(n)
Definition: section.h:105
#define nlayer
Definition: section.h:188
#define NODED(n)
Definition: section.h:104
double * _nrn_sav_rhs
Definition: multicore.h:46
nrn_bamech_t f
Definition: membfunc.h:80
double * v
Definition: section.h:196
double ** _rhs
Definition: section.h:200
float tolerance
Definition: hocdec.h:113
void * hoc_mech
Definition: membfunc.h:54
int is_point
Definition: membfunc.h:53
Pvmi current
Definition: membfunc.h:33
Pvmi state
Definition: membfunc.h:35
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
Prop ** prop
Definition: nrnoc_ml.h:16
Datum * _thread
Definition: nrnoc_ml.h:17
Definition: section.h:133
struct Extnode * extnode
Definition: section.h:161
double * _rhs
Definition: section.h:146
int eqn_index_
Definition: section.h:149
int v_node_index
Definition: section.h:175
Represent main neuron object computed by single thread.
Definition: multicore.h:58
double _dt
Definition: multicore.h:60
char * _sp13mat
Definition: multicore.h:79
_nrn_Fast_Imem * _nrn_fast_imem
Definition: multicore.h:82
int id
Definition: multicore.h:66
double cj
Definition: multicore.h:61
int end
Definition: multicore.h:65
Node ** _v_parent
Definition: multicore.h:78
Node ** _v_node
Definition: multicore.h:77
double _t
Definition: multicore.h:59
Definition: section.h:214
Definition: model.h:57
HocSymExtension * extra
Definition: hocdec.h:160
Definition: hocdec.h:84
Definition: hocdec.h:177