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