NEURON
cvodeobj.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 // solver interface to CVode
3 
4 #include "nrnmpi.h"
5 
7 extern void (*nrn_multisplit_setup_)();
8 
9 #include <cmath>
10 #include <cstdlib>
11 #include "classreg.h"
12 #include "code.h"
13 #include "nrnoc2iv.h"
14 #include "datapath.h"
15 #include "cvodeobj.h"
16 #include "netcvode.h"
17 #include "membfunc.h"
18 #include "nrn_ansi.h"
19 #include "nrncvode.h"
20 #include "nrndaspk.h"
21 #include "nrniv_mf.h"
22 #include "nrnpy.h"
23 #include "tqueue.hpp"
24 #include "mymath.h"
25 #include <nrnmutdec.h>
26 
27 #if NRN_ENABLE_THREADS
28 static MUTDEC
29 #endif
30 
31 // Use of the above static mutex was broken by changeset 7ffd95c in 2014
32 // when a MUTDEC was added explicitly to the NetCvode class namespace to
33 // handle interthread send events.
34 static void static_mutex_for_at_time(bool b) {
35  if (b) {
36  MUTCONSTRUCT(1)
37  } else {
39  }
40 }
41 
42 // I have no idea why this is necessary
43 // but it stops codewarrior from complaining
44 // about illegal overloading in math.h
45 // and math.h alone just moves the problem
46 // to these
47 //#include "shared/sundialstypes.h"
48 //#include "shared/nvector_serial.h"
49 #include "cvodes/cvodes.h"
50 #include "cvodes/cvodes_impl.h"
51 #include "cvodes/cvdense.h"
52 #include "cvodes/cvdiag.h"
53 #include "shared/dense.h"
54 #include "ida/ida.h"
55 #include "nonvintblock.h"
56 
57 extern double dt, t;
58 #define nt_dt nrn_threads->_dt
59 #define nt_t nrn_threads->_t
60 extern int secondorder;
62 extern int nrn_modeltype();
63 extern int nrn_use_selfqueue_;
64 extern void (*nrnthread_v_transfer_)(NrnThread*);
65 extern void (*nrnmpi_v_transfer_)();
66 
68 extern short* nrn_is_artificial_;
69 #if USENCS
70 extern void nrn2ncs_netcons();
71 #endif // USENCS
72 #if NRNMPI
73 extern "C" {
74 extern N_Vector N_VNew_Parallel(int comm, long int local_length, long int global_length);
75 extern N_Vector N_VNew_NrnParallelLD(int comm, long int local_length, long int global_length);
76 } // extern "C"
77 #endif
78 
79 extern bool nrn_use_fifo_queue_;
80 extern bool nrn_use_bin_queue_;
81 
82 #undef SUCCESS
83 #define SUCCESS CV_SUCCESS
84 
85 // interface to oc
86 
87 static double solve(void* v) {
88  NetCvode* d = (NetCvode*) v;
89  double tstop = -1.;
90  if (ifarg(1)) {
91  tstop = *getarg(1);
92  }
93  tstopunset;
94  int i = d->solve(tstop);
95  tstopunset;
96  if (i != SUCCESS) {
97  hoc_execerror("variable step integrator error", 0);
98  }
99  t = nt_t;
100  dt = nt_dt;
101  return double(i);
102 }
103 static double statistics(void* v) {
104  NetCvode* d = (NetCvode*) v;
105  int i = -1;
106  if (ifarg(1)) {
107  i = (int) chkarg(1, -1, 1e6);
108  }
109  d->statistics(i);
110  return 0.;
111 }
112 static double spikestat(void* v) {
113  NetCvode* d = (NetCvode*) v;
114  d->spike_stat();
115  return 0;
116 }
117 static double queue_mode(void* v) {
119  if (ifarg(1)) {
120  nrn_use_bin_queue_ = chkarg(1, 0, 1) ? true : false;
121  }
122  if (ifarg(2)) {
123 #if NRNMPI
124  nrn_use_selfqueue_ = chkarg(2, 0, 1) ? 1 : 0;
125 #else
126  if (chkarg(2, 0, 1)) {
127  hoc_warning("CVode.queue_mode with second arg == 1 requires",
128  "configuration --with-mpi or related");
129  }
130 #endif
131  }
132  return double(nrn_use_bin_queue_ + 2 * nrn_use_selfqueue_);
133  return 0.;
134 }
135 
136 void nrn_extra_scatter_gather(int direction, int tid);
137 
138 static double re_init(void* v) {
139  if (cvode_active_) {
140  NetCvode* d = (NetCvode*) v;
141  d->re_init(t);
142  } else {
144  }
145  return 0.;
146 }
147 static double rtol(void* v) {
148  NetCvode* d = (NetCvode*) v;
149  if (ifarg(1)) {
150  d->rtol(chkarg(1, 0., 1e9));
151  }
152  return d->rtol();
153 }
154 static double nrn_atol(void* v) {
155  NetCvode* d = (NetCvode*) v;
156  if (ifarg(1)) {
157  d->atol(chkarg(1, 0., 1e9));
158  d->structure_change();
159  }
160  return d->atol();
161 }
163 extern void hoc_symbol_tolerance(Symbol*, double);
164 
165 static double abstol(void* v) {
166  NetCvode* d = (NetCvode*) v;
167  Symbol* sym;
168  if (hoc_is_str_arg(1)) {
169  sym = d->name2sym(gargstr(1));
170  } else {
172  if (!sym) {
174  "Cannot find the symbol associated with the pointer when called from Python",
175  "Use a string instead of pointer argument");
176  }
177  if (nrn_vartype(sym) != STATE && sym->u.rng.type != VINDEX) {
178  hoc_execerror(sym->name, "is not a STATE");
179  }
180  }
181  if (ifarg(2)) {
182  hoc_symbol_tolerance(sym, chkarg(2, 1e-30, 1e30));
183  d->structure_change();
184  }
185  if (sym->extra && sym->extra->tolerance > 0.) {
186  return sym->extra->tolerance;
187  } else {
188  return 1.;
189  }
190 }
191 
192 static double active(void* v) {
193  if (ifarg(1)) {
194  cvode_active_ = (int) chkarg(1, 0, 1);
195  if (cvode_active_) {
196  static_cast<NetCvode*>(v)->re_init(nt_t);
197  }
198  }
200  return cvode_active_;
201 }
202 static double stiff(void* v) {
203  NetCvode* d = (NetCvode*) v;
204  if (ifarg(1)) {
205  d->stiff((int) chkarg(1, 0, 2));
206  }
208  return double(d->stiff());
209 }
210 static double maxorder(void* v) {
211  NetCvode* d = (NetCvode*) v;
212  if (ifarg(1)) {
213  d->maxorder((int) chkarg(1, 0, 5));
214  }
216  return d->maxorder();
217 }
218 static double order(void* v) {
219  NetCvode* d = (NetCvode*) v;
220  int i = 0;
222  if (ifarg(1)) {
223  // only thread 0
224  i = int(chkarg(1, 0, d->p->nlcv_ - 1));
225  }
226  int o = d->order(i);
227  return double(o);
228 }
229 static double minstep(void* v) {
230  NetCvode* d = (NetCvode*) v;
231  if (ifarg(1)) {
232  d->minstep(chkarg(1, 0., 1e9));
233  }
234  return d->minstep();
235 }
236 
237 static double maxstep(void* v) {
238  NetCvode* d = (NetCvode*) v;
239  if (ifarg(1)) {
240  d->maxstep(chkarg(1, 0., 1e9));
241  }
242  return d->maxstep();
243 }
244 
245 static double jacobian(void* v) {
246  NetCvode* d = (NetCvode*) v;
247  if (ifarg(1)) {
248  d->jacobian((int) chkarg(1, 0, 2));
249  }
251  return double(d->jacobian());
252 }
253 
254 static double states(void* v) {
255  NetCvode* d = (NetCvode*) v;
256  d->states();
257  return 0.;
258 }
259 
260 static double dstates(void* v) {
261  NetCvode* d = (NetCvode*) v;
262  d->dstates();
263  return 0.;
264 }
265 
266 extern double nrn_hoc2fun(void* v);
267 extern double nrn_hoc2scatter_y(void* v);
268 extern double nrn_hoc2gather_y(void* v);
269 extern double nrn_hoc2fixed_step(void* v);
270 
271 static double error_weights(void* v) {
272  NetCvode* d = (NetCvode*) v;
273  d->error_weights();
274  return 0.;
275 }
276 
277 static double acor(void* v) {
278  NetCvode* d = (NetCvode*) v;
279  d->acor();
280  return 0.;
281 }
282 
283 static double statename(void* v) {
284  NetCvode* d = (NetCvode*) v;
285  int i = (int) chkarg(1, 0, 1e9);
286  int style = 1;
287  if (ifarg(3)) {
288  style = (int) chkarg(3, 0, 2);
289  }
290  hoc_assign_str(hoc_pgargstr(2), d->statename(i, style).c_str());
291  return 0.;
292 }
293 
294 static double use_local_dt(void* v) {
295  NetCvode* d = (NetCvode*) v;
297  if (ifarg(1)) {
298  int i = (int) chkarg(1, 0, 1);
299  d->localstep(i);
300  }
301  return (double) d->localstep();
302 }
303 
304 static double use_daspk(void* v) {
305  NetCvode* d = (NetCvode*) v;
307  if (ifarg(1)) {
308  int i = (int) chkarg(1, 0, 1);
309  if ((i != 0) != d->use_daspk()) {
310  d->use_daspk(i);
311  }
312  }
313  return (double) d->use_daspk();
314 }
315 
316 static double dae_init_dteps(void* v) {
317  if (ifarg(1)) {
318  Daspk::dteps_ = chkarg(1, 1e-100, 1);
319  }
320  if (ifarg(2)) {
321  Daspk::init_failure_style_ = (int) chkarg(2, 0, 013);
322  }
323  return Daspk::dteps_;
324 }
325 
326 static double use_mxb(void* v) {
328  if (ifarg(1)) {
329  int i = (int) chkarg(1, 0, 1);
330  if (use_sparse13 != i) {
331  use_sparse13 = i;
332  recalc_diam();
333  }
334  }
335  return (double) use_sparse13;
336 }
337 
338 static double cache_efficient(void* v) {
339  // Perhaps a warning on cache_efficient(True) and an error on cache_efficient(False) would be
340  // justified.
342  return 1.0;
343 }
344 
345 static double use_long_double(void* v) {
346  NetCvode* d = (NetCvode*) v;
348  if (ifarg(1)) {
349  int i = (int) chkarg(1, 0, 1);
350  d->use_long_double_ = i;
351  d->structure_change();
352  }
353  return (double) d->use_long_double_;
354 }
355 
356 static double condition_order(void* v) {
357  NetCvode* d = (NetCvode*) v;
358  if (ifarg(1)) {
359  int i = (int) chkarg(1, 1, 2);
360  d->condition_order(i);
361  }
363  return (double) d->condition_order();
364 }
365 
366 static double debug_event(void* v) {
367  NetCvode* d = (NetCvode*) v;
368  if (ifarg(1)) {
369  int i = (int) chkarg(1, 0, 10);
370  d->print_event_ = i;
371  }
373  return (double) d->print_event_;
374 }
375 
376 static double n_record(void* v) {
377  NetCvode* d = (NetCvode*) v;
378  d->vecrecord_add();
379  return 0.;
380 }
381 
382 static double n_remove(void* v) {
383  NetCvode* d = (NetCvode*) v;
384  d->vec_remove();
385  return 0.;
386 }
387 
388 static double simgraph_remove(void* v) {
389  NetCvode* d = (NetCvode*) v;
390  d->simgraph_remove();
391  return 0.;
392 }
393 
394 static double state_magnitudes(void* v) {
395  NetCvode* d = (NetCvode*) v;
396  return d->state_magnitudes();
397 }
398 
399 static double tstop_event(void* v) {
400  NetCvode* d = (NetCvode*) v;
401  double x = *getarg(1);
402  if (!cvode_active_) { // watch out for fixed step roundoff if x
403  // close to n*dt
404  double y = x / nrn_threads->_dt;
405  if (y > 1 && fabs(floor(y + 1e-6) - y) < 1e-6) {
406  // printf("reduce %g to avoid fixed step roundoff\n", x);
407  x -= nrn_threads->_dt / 4.;
408  }
409  }
410  if (ifarg(2)) {
411  Object* ppobj = nullptr;
412  int reinit = 0;
413  if (ifarg(3)) {
414  ppobj = *hoc_objgetarg(3);
415  if (!ppobj || ppobj->ctemplate->is_point_ <= 0 ||
416  nrn_is_artificial_[ob2pntproc(ppobj)->prop->_type]) {
417  hoc_execerror(hoc_object_name(ppobj), "is not a POINT_PROCESS");
418  }
419  reinit = int(chkarg(4, 0, 1));
420  }
421  if (hoc_is_object_arg(2)) {
422  d->hoc_event(x, nullptr, ppobj, reinit, *hoc_objgetarg(2));
423  } else {
424  d->hoc_event(x, gargstr(2), ppobj, reinit);
425  }
426  } else {
427  d->hoc_event(x, 0, 0, 0);
428  }
429  return x;
430 }
431 
432 static double current_method(void* v) {
433  NetCvode* d = (NetCvode*) v;
435  int modeltype = nrn_modeltype();
436  int methodtype = secondorder; // 0, 1, or 2
437  int localtype = 0;
438  if (cvode_active_) {
439  methodtype = 3;
440  if (d->use_daspk()) {
441  methodtype = 4;
442  } else {
443  localtype = d->localstep();
444  }
445  }
446  return double(modeltype + 10 * use_sparse13 + 100 * methodtype + 1000 * localtype);
447 }
448 static double peq(void* v) {
449  NetCvode* d = (NetCvode*) v;
450  d->print_event_queue();
451  return 1.;
452 }
453 
454 static double event_queue_info(void* v) {
455  NetCvode* d = (NetCvode*) v;
456  d->event_queue_info();
457  return 1.;
458 }
459 
460 static double store_events(void* v) {
461  NetCvode* d = (NetCvode*) v;
462  d->vec_event_store();
463  return 1.;
464 }
465 
466 static Object** netconlist(void* v) {
467  NetCvode* d = (NetCvode*) v;
468  return d->netconlist();
469 }
470 
471 static double ncs_netcons(void* v) {
472 #if USENCS
473  nrn2ncs_netcons();
474 #endif
475  return 0.;
476 }
477 
478 // for testing when there is actually no pc.transfer or pc.multisplit present
479 // forces the global step to be truly global across processors.
480 static double use_parallel(void* v) {
481 #if NRNMPI
482  // assume single thread and global step
483  NetCvode* d = (NetCvode*) v;
484  assert(d->gcv_);
485  d->gcv_->use_partrans_ = true;
486  d->structure_change();
487  return 1.0;
488 #else
489  return 0.0;
490 #endif
491 }
492 
493 static double nrn_structure_change_count(void* v) {
495  return double(structure_change_cnt);
496 }
497 
498 static double nrn_diam_change_count(void* v) {
500  return double(diam_change_cnt);
501 }
502 
503 using ExtraScatterList = std::vector<Object*>;
504 static ExtraScatterList* extra_scatterlist[2]; // 0 scatter, 1 gather
505 
506 void nrn_extra_scatter_gather(int direction, int tid) {
507  ExtraScatterList* esl = extra_scatterlist[direction];
508  if (esl) {
509  nrn_thread_error("extra_scatter_gather not allowed with multiple threads");
510  for (Object* callable: *esl) {
511  if (!neuron::python::methods.hoccommand_exec(callable)) {
512  hoc_execerror("extra_scatter_gather runtime error", 0);
513  }
514  }
515  }
516 }
517 
518 static double extra_scatter_gather(void* v) {
519  int direction = int(chkarg(1, 0, 1));
520  Object* o = *hoc_objgetarg(2);
521  check_obj_type(o, "PythonObject");
522  ExtraScatterList* esl = extra_scatterlist[direction];
523  if (!esl) {
524  esl = new ExtraScatterList;
525  extra_scatterlist[direction] = esl;
526  }
527  esl->push_back(o);
528  hoc_obj_ref(o);
529  return 0.;
530 }
531 
532 static double extra_scatter_gather_remove(void* v) {
533  Object* o = *hoc_objgetarg(1);
534  for (int direction = 0; direction < 2; ++direction) {
535  ExtraScatterList* esl = extra_scatterlist[direction];
536  if (esl) {
537  for (auto it = esl->begin(); it != esl->end();) {
538  Object* o1 = *it;
539  // if esl exists then python exists
540  if (neuron::python::methods.pysame(o, o1)) {
541  it = esl->erase(it);
542  hoc_obj_unref(o1);
543  } else {
544  ++it;
545  }
546  }
547  }
548  }
549  return 0.;
550 }
551 
552 static double use_fast_imem(void* v) {
553  auto i = nrn_use_fast_imem;
555  if (ifarg(1)) {
556  nrn_use_fast_imem = chkarg(1, 0., 1.);
558  }
559  return i;
560 }
561 
562 static double poolshrink(void*) {
563  extern void nrn_poolshrink(int);
564  int i = 0;
565  if (ifarg(1)) {
566  i = int(chkarg(1, 0., 1.));
567  }
568  nrn_poolshrink(i);
569  return double(i);
570 }
571 
572 static double free_event_queues(void*) {
574  return 0;
575 }
576 
577 static Member_func members[] = {{"solve", solve},
578  {"atol", nrn_atol},
579  {"rtol", rtol},
580  {"re_init", re_init},
581  {"stiff", stiff},
582  {"active", active},
583  {"maxorder", maxorder},
584  {"minstep", minstep},
585  {"maxstep", maxstep},
586  {"jacobian", jacobian},
587  {"states", states},
588  {"dstates", dstates},
589  {"error_weights", error_weights},
590  {"acor", acor},
591  {"statename", statename},
592  {"atolscale", abstol},
593  {"use_local_dt", use_local_dt},
594  {"record", n_record},
595  {"record_remove", n_remove},
596  {"debug_event", debug_event},
597  {"order", order},
598  {"use_daspk", use_daspk},
599  {"event", tstop_event},
600  {"current_method", current_method},
601  {"use_mxb", use_mxb},
602  {"print_event_queue", peq},
603  {"event_queue_info", event_queue_info},
604  {"store_events", store_events},
605  {"condition_order", condition_order},
606  {"dae_init_dteps", dae_init_dteps},
607  {"simgraph_remove", simgraph_remove},
608  {"state_magnitudes", state_magnitudes},
609  {"ncs_netcons", ncs_netcons},
610  {"statistics", statistics},
611  {"spike_stat", spikestat},
612  {"queue_mode", queue_mode},
613  {"cache_efficient", cache_efficient},
614  {"use_long_double", use_long_double},
615  {"use_parallel", use_parallel},
616  {"f", nrn_hoc2fun},
617  {"yscatter", nrn_hoc2scatter_y},
618  {"ygather", nrn_hoc2gather_y},
619  {"fixed_step", nrn_hoc2fixed_step},
620  {"structure_change_count", nrn_structure_change_count},
621  {"diam_change_count", nrn_diam_change_count},
622  {"extra_scatter_gather", extra_scatter_gather},
623  {"extra_scatter_gather_remove", extra_scatter_gather_remove},
624  {"use_fast_imem", use_fast_imem},
625  {"poolshrink", poolshrink},
626  {"free_event_queues", free_event_queues},
627  {nullptr, nullptr}};
628 
629 static Member_ret_obj_func omembers[] = {{"netconlist", netconlist}, {nullptr, nullptr}};
630 
631 static void* cons(Object*) {
632 #if 0
633  NetCvode* d;
634  if (net_cvode_instance) {
635  hoc_execerror("Only one CVode instance allowed", 0);
636  }else{
637  d = new NetCvode(1);
638  net_cvode_instance = d;
639  }
640  active(nullptr);
641  return (void*) d;
642 #else
643  return (void*) net_cvode_instance;
644 #endif
645 }
646 static void destruct(void* v) {
647 #if 0
648  NetCvode* d = (NetCvode*)v;
649  cvode_active_ = 0;
650  delete d;
651 #endif
652 }
653 void Cvode_reg() {
654  class2oc("CVode", cons, destruct, members, omembers, nullptr);
655  net_cvode_instance = new NetCvode(1);
656  Daspk::dteps_ = 1e-9; // change with cvode.dae_init_dteps(newval)
657 }
658 
659 /* Functions Called by the CVODE Solver */
660 
661 static int minit(CVodeMem cv_mem);
662 static int msetup(CVodeMem cv_mem,
663  int convfail,
664  N_Vector ypred,
665  N_Vector fpred,
666  booleantype* jcurPtr,
667  N_Vector vtemp,
668  N_Vector vtemp2,
669  N_Vector vtemp3);
670 static int msolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, N_Vector ycur, N_Vector fcur);
671 static int msolve_lvardt(CVodeMem cv_mem,
672  N_Vector b,
673  N_Vector weight,
674  N_Vector ycur,
675  N_Vector fcur);
676 static void mfree(CVodeMem cv_mem);
677 static void f_gvardt(realtype t, N_Vector y, N_Vector ydot, void* f_data);
678 static void f_lvardt(realtype t, N_Vector y, N_Vector ydot, void* f_data);
679 static CVRhsFn pf_;
680 
682 static void* msolve_thread_part1(NrnThread*);
683 static void* msolve_thread_part2(NrnThread*);
684 static void* msolve_thread_part3(NrnThread*);
685 static void f_thread(neuron::model_sorted_token const&, NrnThread&);
688 static void* f_thread_ms_part1(NrnThread*);
689 static void* f_thread_ms_part2(NrnThread*);
690 static void* f_thread_ms_part3(NrnThread*);
691 static void* f_thread_ms_part4(NrnThread*);
692 static void* f_thread_ms_part34(NrnThread*);
693 
696  ncv_ = ncv;
697 }
700 }
702  nthsizes_ = nullptr;
703  nth_ = nullptr;
704  ncv_ = nullptr;
705  ctd_ = nullptr;
706  tqitem_ = nullptr;
707  mem_ = nullptr;
708  initialize_ = false;
709  can_retreat_ = false;
710  tstop_begin_ = 0.;
711  tstop_end_ = 0.;
712  use_daspk_ = false;
713  daspk_ = nullptr;
714 
715  mem_ = nullptr;
716  y_ = nullptr;
717  atolnvec_ = nullptr;
718  maxstate_ = nullptr;
719  maxacor_ = nullptr;
720  neq_ = 0;
721  structure_change_ = true;
722 #if NRNMPI
723  use_partrans_ = false;
724  global_neq_ = 0;
725  opmode_ = 0;
726 #endif
727 }
728 
729 double Cvode::gam() {
730  if (mem_) {
731  return ((CVodeMem) mem_)->cv_gamma;
732  } else {
733  return 1.;
734  }
735 }
736 
737 double Cvode::h() {
738  if (mem_) {
739  return ((CVodeMem) mem_)->cv_h;
740  } else {
741  return 0.;
742  }
743 }
744 
745 bool Cvode::at_time(double te, NrnThread* nt) {
746  if (initialize_) {
747  // printf("%d at_time initialize te=%g te-t0_=%g next_at_time_=%g\n", nt->id, te, te-t0_,
748  // next_at_time_);
749  MUTLOCK
750  if (t0_ < te && te < next_at_time_) {
751  // printf("%d next_at_time_=%g since te-t0_=%15.10g and next_at_time_-te=%g\n", nt->id,
752  // te, te-nt->_t, next_at_time_-te);
753  next_at_time_ = te;
754  }
755  MUTUNLOCK
756  if (MyMath::eq(te, t0_, NetCvode::eps(t0_))) {
757  // printf("at_time te=%g t-te=%g return 1\n", te, t - te);
758  return 1;
759  }
760  return 0;
761  }
762  // No at_time event is inside our allowed integration interval.
763  // such an event would be unhandled. It would be an error for
764  // a model description to dynamically compute such an event.
765  // The policy is strict that during at_time
766  // event handling the next at_time event is known so that
767  // the stop time can be set. This could be relaxed
768  // only to the extent that whatever at_time is computed is
769  // beyond the current step.
770  if (nt->_vcv) {
771  if (te <= tstop_ && te > t0_) {
772  Printf("te=%g t0_=%g tn_=%g t_=%g t=%g\n", te, t0_, tn_, t_, nt_t);
773  Printf("te-t0_=%g tstop_-te=%g\n", te - t0_, tstop_ - te);
774  }
775  assert(te > tstop_ || te <= t0_);
776  }
777  return 0;
778 }
779 
781  // printf("set_init_flag t_=%g prior2init_=%d\n", t_, prior2init_);
782  initialize_ = true;
783  if (cvode_active_ && ++prior2init_ == 1) {
785  }
786 }
787 
788 N_Vector Cvode::nvnew(long int n) {
789 #if NRNMPI
790  if (use_partrans_) {
792  return N_VNew_NrnParallelLD(0, n, global_neq_);
793  } else {
794  return N_VNew_Parallel(0, n, global_neq_);
795  }
796  }
797 #endif
798  if (nctd_ > 1) {
799  assert(n == neq_);
800  if (!nthsizes_) {
801  nthsizes_ = new long int[nrn_nthread];
802  for (int i = 0; i < nrn_nthread; ++i) {
803  nthsizes_[i] = ctd_[i].nvsize_;
804  }
805  }
806 #if 1
807  int sum = 0;
808  for (int i = 0; i < nctd_; ++i) {
809  sum += nthsizes_[i];
810  }
811  assert(sum == neq_);
812 #endif
815  } else {
816  return N_VNew_NrnThread(n, nctd_, nthsizes_);
817  }
818  }
820  return N_VNew_NrnSerialLD(n);
821  } else {
822  return N_VNew_Serial(n);
823  }
824 }
825 
827  if (i > 0) {
828  // too bad the machEnv has to be done here but this is
829  // the first and it depends on size
830  // the call chain is init_prepare (frees) -> init_eqn -> here
831  atolnvec_ = nvnew(i);
832  }
833 }
834 
836  if (daspk_) {
837  delete daspk_;
838  }
839  if (y_) {
840  N_VDestroy(y_);
841  }
842  if (atolnvec_) {
843  N_VDestroy(atolnvec_);
844  }
845  if (mem_) {
846  CVodeFree(mem_);
847  }
848  if (maxstate_) {
849  N_VDestroy(maxstate_);
850  N_VDestroy(maxacor_);
851  }
852  if (nthsizes_) {
853  delete[] nthsizes_;
854  }
855  // delete [] iopt_;
856  // delete [] ropt_;
857 }
858 
863 }
864 
866  if (init_global()) {
867  if (y_) {
868  N_VDestroy(y_);
869  y_ = nullptr;
870  }
871  if (mem_) {
872  CVodeFree(mem_);
873  mem_ = nullptr;
874  }
875  if (atolnvec_) {
876  N_VDestroy(atolnvec_);
877  atolnvec_ = nullptr;
878  }
879  if (daspk_) {
880  delete daspk_;
881  daspk_ = nullptr;
882  }
883  init_eqn();
884  if (neq_ > 0) {
885  y_ = nvnew(neq_);
886  if (use_daspk_) {
887  alloc_daspk();
888  } else {
889  alloc_cvode();
890  }
891  if (maxstate_) {
892  activate_maxstate(false);
893  activate_maxstate(true);
894  }
895  }
896  }
897 }
898 
900  if (maxstate_) {
901  N_VDestroy(maxstate_);
902  N_VDestroy(maxacor_);
903  maxstate_ = nullptr;
904  maxacor_ = nullptr;
905  }
906  if (on && neq_ > 0) {
907  maxstate_ = nvnew(neq_);
908  maxacor_ = nvnew(neq_);
909  N_VConst(0.0, maxstate_);
910  N_VConst(0.0, maxacor_);
911  }
912 }
913 
914 static bool maxstate_b;
916 static void* maxstate_thread(NrnThread* nt) {
918  return 0;
919 }
920 void Cvode::maxstate(bool b, NrnThread* nt) {
921  if (!maxstate_) {
922  return;
923  }
924  if (!nt) {
925  if (nrn_nthread > 1) {
926  maxstate_cv = this;
927  maxstate_b = b;
929  return;
930  }
931  nt = nrn_threads;
932  }
933  CvodeThreadData& z = ctd_[nt->id];
934  int i;
935  double x;
936  double* y = n_vector_data(y_, nt->id);
937  double* m = n_vector_data(maxstate_, nt->id);
938  for (i = 0; i < z.nvsize_; ++i) {
939  x = std::abs(y[i]);
940  if (m[i] < x) {
941  m[i] = x;
942  }
943  }
944  if (b) {
945  y = n_vector_data(acorvec(), nt->id);
946  m = n_vector_data(maxacor_, nt->id);
947  for (i = 0; i < z.nvsize_; ++i) {
948  x = std::abs(y[i]);
949  if (m[i] < x) {
950  m[i] = x;
951  }
952  }
953  }
954 }
955 
956 void Cvode::maxstate(double* pd) {
957  if (maxstate_) {
959  double* m = n_vector_data(maxstate_, nt->id);
960  int n = ctd_[nt->id].nvsize_;
961  int o = ctd_[nt->id].nvoffset_;
962  for (int i = 0; i < n; ++i) {
963  pd[i + o] = m[i];
964  }
965  }
966  }
967 }
968 
969 void Cvode::maxacor(double* pd) {
970  if (maxacor_) {
971  for (const NrnThread* nt: for_threads(nrn_threads, nrn_nthread)) {
972  double* m = n_vector_data(maxacor_, nt->id);
973  int n = ctd_[nt->id].nvsize_;
974  int o = ctd_[nt->id].nvoffset_;
975  for (int i = 0; i < n; ++i) {
976  pd[i + o] = m[i];
977  }
978  }
979  }
980 }
981 
983 
985  int i = 0;
986  if (use_daspk_) {
987  if (daspk_->mem_) {
988  IDAGetLastOrder(daspk_->mem_, &i);
989  }
990  } else {
991  if (mem_) {
992  CVodeGetLastOrder(mem_, &i);
993  }
994  }
995  return i;
996 }
997 void Cvode::maxorder(int maxord) {
998  if (use_daspk_) {
999  if (daspk_->mem_) {
1000  IDASetMaxOrd(daspk_->mem_, maxord);
1001  }
1002  } else {
1003  if (mem_) {
1004  CVodeSetMaxOrd(mem_, maxord);
1005  }
1006  }
1007 }
1008 void Cvode::minstep(double x) {
1009  if (mem_) {
1010  if (x > 0.) {
1011  CVodeSetMinStep(mem_, x);
1012  } else {
1013  // CVodeSetMinStep requires x > 0 but
1014  // HMIN_DEFAULT is ZERO in cvodes.cpp
1015  ((CVodeMem) mem_)->cv_hmin = 0.;
1016  }
1017  }
1018 }
1019 void Cvode::maxstep(double x) {
1020  if (use_daspk_) {
1021  if (daspk_->mem_) {
1022  IDASetMaxStep(daspk_->mem_, x);
1023  }
1024  } else {
1025  if (mem_) {
1026  CVodeSetMaxStep(mem_, x);
1027  }
1028  }
1029 }
1030 
1032  if (mem_) {
1033  CVodeFree(mem_);
1034  mem_ = nullptr;
1035  }
1036 }
1037 
1039  MUTDESTRUCT
1040  static_mutex_for_at_time(false);
1041  if (single_) {
1042  pf_ = f_gvardt;
1043  if (nrn_nthread > 1) {
1044  MUTCONSTRUCT(1)
1046  }
1047  } else {
1048  pf_ = f_lvardt;
1049  }
1050 }
1051 
1052 static Section* cv_rootsec(const Cvode* cv) {
1053  NrnThread* nt = cv->nth_ ? cv->nth_ : nrn_threads;
1054  return nt->_v_node[cv->ctd_[0].vnode_begin_index_]->sec;
1055 }
1056 
1057 int Cvode::cvode_init(double) {
1058  int err = SUCCESS;
1059  // note, a change in stiff_ due to call of stiff() destroys mem_
1060  gather_y(y_);
1061  // TODO: this needs changed if want to support more than one thread or local variable timestep
1062  nrn_nonvint_block_ode_reinit(neq_, N_VGetArrayPointer(y_), 0);
1063  if (mem_) {
1064  err = CVodeReInit(mem_, pf_, t0_, y_, CV_SV, &ncv_->rtol_, atolnvec_);
1065  // printf("CVodeReInit\n");
1066  if (err != SUCCESS) {
1067  Printf("Cvode %p %s CVReInit error %d\n",
1068  fmt::ptr(this),
1069  secname(cv_rootsec(this)),
1070  err);
1071  return err;
1072  }
1073  } else {
1074  mem_ = CVodeCreate(CV_BDF, ncv_->stiff() ? CV_NEWTON : CV_FUNCTIONAL);
1075  if (!mem_) {
1076  hoc_execerror("CVodeCreate error", 0);
1077  }
1078  maxorder(ncv_->maxorder()); // Memory Leak if changed after CVodeMalloc
1079  minstep(ncv_->minstep());
1080  maxstep(ncv_->maxstep());
1081  CVodeMalloc(mem_, pf_, t0_, y_, CV_SV, &ncv_->rtol_, atolnvec_);
1082  if (err != SUCCESS) {
1083  Printf("Cvode %p %s CVodeMalloc error %d\n",
1084  fmt::ptr(this),
1085  secname(cv_rootsec(this)),
1086  err);
1087  return err;
1088  }
1089  // CVodeSetInitStep(mem_, .01);
1090  }
1091  matmeth();
1092  ((CVodeMem) mem_)->cv_gamma = 0.;
1093  ((CVodeMem) mem_)->cv_h = 0.; // fun called before cvode sets this (though fun does not need it
1094  // really)
1095  // fun(t_, N_VGetArrayPointer(y_), nullptr);
1096  auto const sorted_token = nrn_ensure_model_data_are_sorted();
1097  std::pair<Cvode*, neuron::model_sorted_token const&> opaque{this, sorted_token};
1098  pf_(t_, y_, nullptr, &opaque);
1099  can_retreat_ = false;
1100  return err;
1101 }
1102 
1103 int Cvode::daspk_init(double tout) {
1104  return daspk_->init();
1105 }
1106 
1108  // printf("Cvode::alloc_daspk\n");
1109  daspk_ = new Daspk(this, neq_);
1110  // we do our own initialization since it is hard to
1111  // figure out which equations are algebraic and which
1112  // differential. eg. the no cap nodes can have a
1113  // circuit with capacitance connection. Extracellular
1114  // nodes may or may not have capacitors to ground.
1115 }
1116 
1118  int err = SUCCESS;
1119  if (neq_ == 0) {
1120  t_ += 1e9;
1121  if (nth_) {
1122  nth_->_t = t_;
1123  } else {
1124  nt_t = t_;
1125  }
1126  tn_ = t_;
1127  return err;
1128  }
1129  // printf("%d Cvode::advance_tn enter t_=%.20g t0_=%.20g tstop_=%.20g\n", nrnmpi_myid, t_, t0_,
1130  // tstop_);
1131  if (t_ >= tstop_ - NetCvode::eps(t_)) {
1132  // printf("init\n");
1133  ++ts_inits_;
1134  tstop_begin_ = tstop_;
1136  err = init(tstop_end_);
1137  // the above 1.5 is due to the fact that at_time will check
1138  // to see if the time is greater but not greater than eps*t0_
1139  // of the at_time for a return of 1.
1140  can_retreat_ = false;
1141  } else {
1142  ++advance_calls_;
1143  // SOLVE after_cvode now interpreted as before cvode since
1144  // a step may be abandoned in part by interpolate in response
1145  // to events. Now at least the value of t is monotonic
1146  if (nth_) {
1147  nth_->_t = t_;
1148  } else {
1149  nt_t = t_;
1150  }
1151  do_nonode(sorted_token, nth_);
1152 #if NRNMPI
1153  opmode_ = 1;
1154 #endif
1155  if (use_daspk_) {
1156  err = daspk_advance_tn();
1157  } else {
1158  err = cvode_advance_tn(sorted_token);
1159  }
1160  can_retreat_ = true;
1161  maxstate(true);
1162  }
1163  // printf("%d Cvode::advance_tn exit t_=%.20g t0_=%.20g tstop_=%.20g\n", nrnmpi_myid, t_, t0_,
1164  // tstop_);
1165  return err;
1166 }
1167 
1169  // printf("%d Cvode::solve %p initialize = %d current_time=%g tn=%g\n", nrnmpi_myid, this,
1170  // initialize_, t_, tn());
1171  int err = SUCCESS;
1172  if (initialize_) {
1173  if (t_ >= tstop_ - NetCvode::eps(t_)) {
1174  ++ts_inits_;
1175  tstop_begin_ = tstop_;
1177  err = init(tstop_end_);
1178  can_retreat_ = false;
1179  } else {
1180  err = init(t_);
1181  }
1182  } else {
1184  }
1185  // printf("Cvode::solve exit %p current_time=%g tn=%g\n", this, t_, tn());
1186  return err;
1187 }
1188 
1189 int Cvode::init(double tout) {
1190  int err = SUCCESS;
1191  ++init_calls_;
1192  // printf("%d Cvode_%p::init tout=%g\n", nrnmpi_myid, this, tout);
1193  initialize_ = true;
1194  t_ = tout;
1195  t0_ = t_;
1196  tn_ = t_;
1197  next_at_time_ = t_ + 1e5;
1198  init_prepare();
1199  if (neq_) {
1200 #if NRNMPI
1201  opmode_ = 3;
1202 #endif
1203  if (use_daspk_) {
1204  err = daspk_init(t_);
1205  } else {
1206  err = cvode_init(t_);
1207  }
1208  }
1210 #if NRNMPI
1211  if (use_partrans_) {
1212  tstop_ = nrnmpi_dbl_allmin(tstop_);
1213  }
1214 #endif
1215  // printf("Cvode::init next_at_time_=%g tstop_=%.15g\n", next_at_time_, tstop_);
1216  initialize_ = false;
1217  prior2init_ = 0;
1218  maxstate(false);
1219  return err;
1220 }
1221 
1222 int Cvode::interpolate(double tout) {
1223  if (neq_ == 0) {
1224  t_ = tout;
1225  if (nth_) {
1226  nth_->_t = t_;
1227  } else {
1229  _nt->_t = t_;
1230  }
1231  }
1232  return SUCCESS;
1233  }
1234  // printf("Cvode::interpolate t_=%.15g t0_=%.15g tn_=%.15g tstop_=%.15g\n", t_, t0_, tn_,
1235  // tstop_);
1236  if (!can_retreat_) {
1237  // but must be within the initialization domain
1238  assert(MyMath::le(tout, t_, 2. * NetCvode::eps(t_)));
1239  if (nth_) { // lvardt
1240  nth_->_t = tout;
1241  } else {
1243  _nt->_t = tout; // but leave t_ at the initialization point.
1244  }
1245  }
1246  // printf("no interpolation for event in the initialization interval t=%15g t_=%15g\n",
1247  // nrn_threads->t, t_);
1248  return SUCCESS;
1249  }
1250  if (MyMath::eq(tout, t_, NetCvode::eps(t_))) {
1251  t_ = tout;
1252  return SUCCESS;
1253  }
1254  // if (initialize_) {
1255  // printf("Cvode_%p::interpolate assert error when initialize_ is true.\n t_=%g tout=%g tout-t_
1256  // = %g\n", this, t_, tout, tout-t_);
1257  //}
1258  assert(initialize_ == false); // or state discontinuity can be lost
1259 // printf("interpolate t_=%g tout=%g delta t_-tout=%g\n", t_, tout, t_-tout);
1260 #if 1
1261  if (tout < t0_) {
1262  // if (tout < t0_ - NetCvode::eps(t0_)) { // t0_ not always == tn_ - h
1263  // after a CV_ONESTEP_TSTOP
1264  // so allow some fudge before printing error
1265  // The fudge case was avoided by returning from the
1266  // Cvode::handle_step when a first order condition check
1267  // puts an event on the queue equal to t_
1268  Printf("Cvode::interpolate assert error t0=%g tout-t0=%g eps*t_=%g\n",
1269  t0_,
1270  tout - t0_,
1271  NetCvode::eps(t_));
1272  // }
1273  tout = t0_;
1274  }
1275  if (tout > tn_) {
1276  Printf("Cvode::interpolate assert error tn=%g tn-tout=%g eps*t_=%g\n",
1277  tn_,
1278  tn_ - tout,
1279  NetCvode::eps(t_));
1280  tout = tn_;
1281  }
1282 #endif
1283  // if there is a problem here it may be due to the at_time skipping interval
1284  // since the integration will not go past tstop_ and will take up at tstop+2eps
1285  // see the Cvode::advance_tn() implementation
1286  assert(tout >= t0() && tout <= tn());
1287 
1289 #if NRNMPI
1290  opmode_ = 2;
1291 #endif
1292  if (use_daspk_) {
1293  return daspk_->interpolate(tout);
1294  } else {
1295  return cvode_interpolate(tout);
1296  }
1297 }
1298 
1300 #if PRINT_EVENT
1301  if (net_cvode_instance->print_event_ > 1) {
1302  Printf("Cvode::cvode_advance_tn %p %d initialize_=%d tstop=%.20g t_=%.20g to ",
1303  fmt::ptr(this),
1304  nth_ ? nth_->id : 0,
1305  initialize_,
1306  tstop_,
1307  t_);
1308  }
1309 #endif
1310  std::pair<Cvode*, neuron::model_sorted_token const&> opaque{this, sorted_token};
1311  CVodeSetFdata(mem_, &opaque);
1312  CVodeSetStopTime(mem_, tstop_);
1313  // printf("cvode_advance_tn begin t0_=%g t_=%g tn_=%g tstop=%g\n", t0_, t_, tn_, tstop_);
1314  int err = CVode(mem_, tstop_, y_, &t_, CV_ONE_STEP_TSTOP);
1315  CVodeSetFdata(mem_, nullptr);
1316 #if PRINT_EVENT
1317  if (net_cvode_instance->print_event_ > 1) {
1318  Printf("t_=%.20g\n", t_);
1319  }
1320 #endif
1321  if (err < 0) {
1322  Printf("CVode %p %s advance_tn failed, err=%d.\n",
1323  fmt::ptr(this),
1324  secname(cv_rootsec(this)),
1325  err);
1326  pf_(t_, y_, nullptr, &opaque);
1327  return err;
1328  }
1329  // this is very bad, performance-wise. However cvode modifies its states
1330  // after a call to fun with the proper t.
1331  pf_(t_, y_, nullptr, &opaque);
1332  tn_ = ((CVodeMem) mem_)->cv_tn;
1333  t0_ = tn_ - ((CVodeMem) mem_)->cv_h;
1334  // printf("t=%.15g t_=%.15g tn()=%.15g tstop_=%.15g t0_=%.15g\n", nrn_threads->t, t_, tn(),
1335  // tstop_, t0_); printf("t_=%g h=%g q=%d y=%g\n", t_, ((CVodeMem)mem_)->cv_h,
1336  //((CVodeMem)mem_)->cv_q, N_VIth(y_,0)); printf("cvode_advance_tn end t0_=%g t_=%g tn_=%g\n",
1337  // t0_, t_, tn_);
1338  return SUCCESS;
1339 }
1340 
1341 int Cvode::cvode_interpolate(double tout) {
1342 #if PRINT_EVENT
1343  if (net_cvode_instance->print_event_ > 1) {
1344  Printf("Cvode::cvode_interpolate %p %d initialize_%d t=%.20g to ",
1345  fmt::ptr(this),
1346  nth_ ? nth_->id : 0,
1347  initialize_,
1348  t_);
1349  }
1350 #endif
1351  // avoid CVode-- tstop = 0.5 is behind current t = 0.5
1352  // is this really necessary anymore. Maybe NORMAL mode ignores tstop
1353  auto const sorted_token = nrn_ensure_model_data_are_sorted();
1354  std::pair<Cvode*, neuron::model_sorted_token const&> opaque{this, sorted_token};
1355  CVodeSetFdata(mem_, &opaque);
1356  CVodeSetStopTime(mem_, tstop_ + tstop_);
1357  int err = CVode(mem_, tout, y_, &t_, CV_NORMAL);
1358  CVodeSetFdata(mem_, nullptr);
1359 #if PRINT_EVENT
1360  if (net_cvode_instance->print_event_ > 1) {
1361  Printf("%.20g\n", t_);
1362  }
1363 #endif
1364  if (err < 0) {
1365  Printf("CVode %p %s interpolate failed, err=%d.\n",
1366  fmt::ptr(this),
1367  secname(cv_rootsec(this)),
1368  err);
1369  return err;
1370  }
1371  pf_(t_, y_, nullptr, &opaque);
1372  // printf("t_=%g h=%g q=%d y=%g\n", t_, ((CVodeMem)mem_)->cv_h, ((CVodeMem)mem_)->cv_q,
1373  // N_VIth(y_,0));
1374  return SUCCESS;
1375 }
1376 
1378  int err;
1379  // printf("Cvode::solve test stop time t=%.20g tstop-t=%g\n", t, tstop_-t);
1380  // printf("in Cvode::solve t_=%g tstop=%g calling daspk_->solve(%g)\n", t_, tstop_,
1381  // daspk_->tout_);
1382  err = daspk_->advance_tn(tstop_);
1383  // printf("in Cvode::solve returning from daspk_->solve t_=%g initialize_=%d tstop=%g\n", t_,
1384  // initialize__, tstop_);
1385  if (err < 0) {
1386  return err;
1387  }
1388  return SUCCESS;
1389 }
1390 
1391 N_Vector Cvode::ewtvec() {
1392  if (use_daspk_) {
1393  return daspk_->ewtvec();
1394  } else {
1395  return ((CVodeMem) mem_)->cv_ewt;
1396  }
1397 }
1398 
1399 N_Vector Cvode::acorvec() {
1400  if (use_daspk_) {
1401  return daspk_->acorvec();
1402  } else {
1403  return ((CVodeMem) mem_)->cv_acor;
1404  }
1405 }
1406 
1408 #if 1
1409  Printf("\nCvode instance %p %s statistics : %d %s states\n",
1410  fmt::ptr(this),
1411  secname(cv_rootsec(this)),
1412  neq_,
1413  (use_daspk_ ? "IDA" : "CVode"));
1414  Printf(" %d advance_tn, %d interpolate, %d init (%d due to at_time)\n",
1417  init_calls_,
1418  ts_inits_);
1419  Printf(" %d function evaluations, %d mx=b solves, %d jacobian setups\n",
1420  f_calls_,
1421  mxb_calls_,
1422  jac_calls_);
1423  if (use_daspk_) {
1424  daspk_->statistics();
1425  return;
1426  }
1427 #else
1428  Printf("\nCVode Statistics.. \n\n");
1429  Printf("internal steps = %d\nfunction evaluations = %d\n", iopt_[NST], iopt_[NFE]);
1430  Printf(
1431  "newton iterations = %d setups = %d\n nonlinear convergence failures = %d\n\
1432  local error test failures = %ld\n",
1433  iopt_[NNI],
1434  iopt_[NSETUPS],
1435  iopt_[NCFN],
1436  iopt_[NETF]);
1437  Printf("order=%d stepsize=%g\n", iopt_[QU], h());
1438 #endif
1439 }
1440 
1442  switch (ncv_->jacobian()) {
1443  case 1:
1444  CVDense(mem_, neq_);
1445  break;
1446  case 2:
1447  CVDiag(mem_);
1448  break;
1449  default:
1450  // free previous method
1451  if (((CVodeMem) mem_)->cv_lfree) {
1452  ((CVodeMem) mem_)->cv_lfree((CVodeMem) mem_);
1453  ((CVodeMem) mem_)->cv_lfree = NULL;
1454  }
1455 
1456  ((CVodeMem) mem_)->cv_linit = minit;
1457  ((CVodeMem) mem_)->cv_lsetup = msetup;
1458  ((CVodeMem) mem_)->cv_setupNonNull = TRUE; // but since our's does not do anything...
1459  if (nth_) { // lvardt
1460  ((CVodeMem) mem_)->cv_lsolve = msolve_lvardt;
1461  } else {
1462  ((CVodeMem) mem_)->cv_lsolve = msolve;
1463  }
1464  ((CVodeMem) mem_)->cv_lfree = mfree;
1465  break;
1466  }
1467 }
1468 
1469 static int minit(CVodeMem) {
1470  // printf("minit\n");
1471  return CV_NO_FAILURES;
1472 }
1473 
1474 static int msetup(CVodeMem m,
1475  int convfail,
1476  N_Vector yp,
1477  N_Vector fp,
1478  booleantype* jcurPtr,
1479  N_Vector,
1480  N_Vector,
1481  N_Vector) {
1482  // printf("msetup\n");
1483  *jcurPtr = true;
1484  auto* const cv =
1485  static_cast<std::pair<Cvode*, neuron::model_sorted_token const&>*>(m->cv_f_data)->first;
1486  return cv->setup(yp, fp);
1487 }
1488 
1489 static N_Vector msolve_b_;
1490 static N_Vector msolve_ycur_;
1492 static int msolve(CVodeMem m, N_Vector b, N_Vector weight, N_Vector ycur, N_Vector fcur) {
1493  // printf("msolve gamma=%g gammap=%g gamrat=%g\n", m->cv_gamma, m->cv_gammap, m->cv_gamrat);
1494  // N_VIth(b, 0) /= (1. + m->cv_gamma);
1495  // N_VIth(b, 0) /= (1. + m->cv_gammap);
1496  // N_VIth(b,0) *= 2./(1. + m->cv_gamrat);
1497  auto* const f_typed_data = static_cast<std::pair<Cvode*, neuron::model_sorted_token const&>*>(
1498  m->cv_f_data);
1499  msolve_cv_ = f_typed_data->first;
1500  auto const& sorted_token = f_typed_data->second;
1501  Cvode& cv = *msolve_cv_;
1502  ++cv.mxb_calls_;
1503  if (cv.ncv_->stiff() == 0) {
1504  return 0;
1505  }
1506  if (cv.gam() == 0.) {
1507  return 0;
1508  } // i.e. (I - gamma * J)*x = b means x = b
1509  msolve_b_ = b;
1510  msolve_ycur_ = ycur;
1511  if (nrn_multisplit_setup_ && nrn_nthread > 1) {
1515  } else {
1516  nrn_multithread_job(sorted_token, msolve_thread);
1517  }
1518  return 0;
1519 }
1520 static int msolve_lvardt(CVodeMem m, N_Vector b, N_Vector weight, N_Vector ycur, N_Vector fcur) {
1521  auto* const f_typed_data = static_cast<std::pair<Cvode*, neuron::model_sorted_token const&>*>(
1522  m->cv_f_data);
1523  auto* const cv = f_typed_data->first;
1524  auto const& sorted_token = f_typed_data->second;
1525  ++cv->mxb_calls_;
1526  if (cv->ncv_->stiff() == 0) {
1527  return 0;
1528  }
1529  if (cv->gam() == 0.) {
1530  return 0;
1531  }
1532  cv->nth_->_vcv = cv;
1533  cv->solvex_thread(sorted_token, cv->n_vector_data(b, 0), cv->n_vector_data(ycur, 0), cv->nth_);
1534  cv->nth_->_vcv = 0;
1535  return 0;
1536 }
1537 static void msolve_thread(neuron::model_sorted_token const& sorted_token, NrnThread& nt) {
1538  int i = nt.id;
1539  Cvode* cv = msolve_cv_;
1540  nt._vcv = cv;
1541  cv->solvex_thread(sorted_token,
1542  cv->n_vector_data(msolve_b_, i),
1544  &nt);
1545  nt._vcv = 0;
1546 }
1547 static void* msolve_thread_part1(NrnThread* nt) {
1548  int i = nt->id;
1549  Cvode* cv = msolve_cv_;
1550  nt->_vcv = cv;
1552  return 0;
1553 }
1554 static void* msolve_thread_part2(NrnThread* nt) {
1555  Cvode* cv = msolve_cv_;
1556  cv->solvex_thread_part2(nt);
1557  return 0;
1558 }
1559 static void* msolve_thread_part3(NrnThread* nt) {
1560  int i = nt->id;
1561  Cvode* cv = msolve_cv_;
1563  nt->_vcv = 0;
1564  return 0;
1565 }
1566 
1567 static void mfree(CVodeMem) {
1568  // printf("mfree\n");
1569 }
1570 
1571 static realtype f_t_;
1572 static N_Vector f_y_;
1573 static N_Vector f_ydot_;
1574 static Cvode* f_cv_;
1575 static void f_gvardt(realtype t, N_Vector y, N_Vector ydot, void* f_data) {
1576  auto* const f_typed_data = static_cast<std::pair<Cvode*, neuron::model_sorted_token const&>*>(
1577  f_data);
1578  f_cv_ = f_typed_data->first;
1579  // ydot[0] = -y[0];
1580  // N_VIth(ydot, 0) = -N_VIth(y, 0);
1581  // printf("f(%g, %p, %p)\n", t, y, ydot);
1582  ++f_cv_->f_calls_;
1583  f_t_ = t;
1584  f_y_ = y;
1585  f_ydot_ = ydot;
1586  if (nrn_nthread > 1 || nrnmpi_numprocs > 1) {
1587  if (nrn_multisplit_setup_) {
1590  if (nrnthread_v_transfer_) {
1592  if (nrnmpi_v_transfer_) {
1593  (*nrnmpi_v_transfer_)();
1594  }
1596  } else {
1598  }
1599  } else if (nrnthread_v_transfer_) {
1600  nrn_multithread_job(f_typed_data->second, f_thread_transfer_part1);
1601  if (nrnmpi_v_transfer_) {
1602  (*nrnmpi_v_transfer_)();
1603  }
1604  nrn_multithread_job(f_typed_data->second, f_thread_transfer_part2);
1605  } else {
1606  nrn_multithread_job(f_typed_data->second, f_thread);
1607  }
1608  } else {
1609  nrn_multithread_job(f_typed_data->second, f_thread);
1610  }
1611 }
1612 static void f_lvardt(realtype t, N_Vector y, N_Vector ydot, void* f_data) {
1613  auto* const f_typed_data = static_cast<std::pair<Cvode*, neuron::model_sorted_token const&>*>(
1614  f_data);
1615  auto* const cv = f_typed_data->first;
1616  auto const& sorted_token = f_typed_data->second;
1617  ++cv->f_calls_;
1618  cv->nth_->_vcv = cv;
1619  cv->fun_thread(sorted_token, t, cv->n_vector_data(y, 0), cv->n_vector_data(ydot, 0), cv->nth_);
1620  cv->nth_->_vcv = 0;
1621 }
1622 
1623 static void f_thread(neuron::model_sorted_token const& sorted_token, NrnThread& ntr) {
1624  auto* const nt = &ntr;
1625  int i = nt->id;
1626  Cvode* cv = f_cv_;
1627  nt->_vcv = cv;
1628  cv->fun_thread(
1629  sorted_token, f_t_, cv->n_vector_data(f_y_, i), cv->n_vector_data(f_ydot_, i), &ntr);
1630  nt->_vcv = 0;
1631 }
1632 static void f_thread_transfer_part1(neuron::model_sorted_token const& sorted_token,
1633  NrnThread& ntr) {
1634  auto* const nt = &ntr;
1635  int i = nt->id;
1636  Cvode* cv = f_cv_;
1637  nt->_vcv = cv;
1638  cv->fun_thread_transfer_part1(sorted_token, f_t_, cv->n_vector_data(f_y_, i), nt);
1639 }
1640 static void f_thread_transfer_part2(neuron::model_sorted_token const& sorted_token,
1641  NrnThread& ntr) {
1642  auto* const nt = &ntr;
1643  int i = nt->id;
1644  Cvode* cv = f_cv_;
1645  cv->fun_thread_transfer_part2(sorted_token, cv->n_vector_data(f_ydot_, i), &ntr);
1646  nt->_vcv = 0;
1647 }
1648 static void* f_thread_ms_part1(NrnThread* nt) {
1649  int i = nt->id;
1650  Cvode* cv = f_cv_;
1651  nt->_vcv = cv;
1652  cv->fun_thread_ms_part1(f_t_, cv->n_vector_data(f_y_, i), nt);
1653  return 0;
1654 }
1655 static void* f_thread_ms_part2(NrnThread* nt) {
1656  Cvode* cv = f_cv_;
1657  cv->fun_thread_ms_part2(nt);
1658  return 0;
1659 }
1660 static void* f_thread_ms_part3(NrnThread* nt) {
1661  Cvode* cv = f_cv_;
1662  cv->fun_thread_ms_part3(nt);
1663  return 0;
1664 }
1665 static void* f_thread_ms_part4(NrnThread* nt) {
1666  int i = nt->id;
1667  Cvode* cv = f_cv_;
1668  cv->fun_thread_ms_part4(cv->n_vector_data(f_ydot_, i), nt);
1669  return 0;
1670 }
1671 static void* f_thread_ms_part34(NrnThread* nt) {
1672  int i = nt->id;
1673  Cvode* cv = f_cv_;
1675  nt->_vcv = 0;
1676  return 0;
1677 }
const char * secname(Section *sec)
name of section (for use in error messages)
Definition: cabcode.cpp:1674
Definition: cvodeobj.h:97
void fun_thread_transfer_part2(neuron::model_sorted_token const &, double *ydot, NrnThread *nt)
Definition: occvode.cpp:764
int init_calls_
Definition: cvodeobj.h:131
void fun_thread_ms_part2(NrnThread *nt)
Definition: occvode.cpp:823
int neq_
Definition: cvodeobj.h:245
void free_cvodemem()
Definition: cvodeobj.cpp:1031
void do_nonode(neuron::model_sorted_token const &, NrnThread *nt=0)
Definition: occvode.cpp:1005
double next_at_time_
Definition: cvodeobj.h:247
double t_
Definition: cvodeobj.h:126
int mxb_calls_
Definition: cvodeobj.h:132
long int * nthsizes_
Definition: cvodeobj.h:243
void maxstep(double)
Definition: cvodeobj.cpp:1019
double tstop_begin_
Definition: cvodeobj.h:249
void alloc_daspk()
Definition: cvodeobj.cpp:1107
void cvode_constructor()
Definition: cvodeobj.cpp:701
int solvex_thread_part2(NrnThread *nt)
Definition: occvode.cpp:677
void fun_thread_transfer_part1(neuron::model_sorted_token const &, double t, double *y, NrnThread *nt)
Definition: occvode.cpp:737
int advance_calls_
Definition: cvodeobj.h:131
void init_prepare()
Definition: cvodeobj.cpp:865
bool at_time(double, NrnThread *)
Definition: cvodeobj.cpp:745
int nctd_
Definition: cvodeobj.h:242
N_Vector atolnvec_
Definition: cvodeobj.h:232
void * mem_
Definition: cvodeobj.h:230
int solvex_thread(neuron::model_sorted_token const &, double *b, double *y, NrnThread *nt)
Definition: occvode.cpp:588
int cvode_init(double)
Definition: cvodeobj.cpp:1057
int jac_calls_
Definition: cvodeobj.h:132
bool init_global()
Definition: occvode.cpp:74
double tstop_end_
Definition: cvodeobj.h:249
TQItem * tqitem_
Definition: cvodeobj.h:267
CvodeThreadData * ctd_
Definition: cvodeobj.h:240
int prior2init_
Definition: cvodeobj.h:270
virtual double tn()
Definition: cvodeobj.h:107
void stat_init()
Definition: cvodeobj.cpp:859
virtual ~Cvode()
Definition: cvodeobj.cpp:835
void gather_y(N_Vector)
Definition: occvode.cpp:523
int ts_inits_
Definition: cvodeobj.h:132
void record_continuous()
Definition: occvode.cpp:1101
void statistics()
Definition: cvodeobj.cpp:1407
void fun_thread_ms_part4(double *ydot, NrnThread *nt)
Definition: occvode.cpp:834
N_Vector y_
Definition: cvodeobj.h:231
N_Vector maxstate_
Definition: cvodeobj.h:233
Daspk * daspk_
Definition: cvodeobj.h:209
void fun_thread_ms_part34(double *ydot, NrnThread *nt)
Definition: occvode.cpp:826
void fun_thread_ms_part1(double t, double *y, NrnThread *nt)
Definition: occvode.cpp:804
int solvex_thread_part3(double *b, NrnThread *nt)
Definition: occvode.cpp:681
void fun_thread(neuron::model_sorted_token const &, double t, double *y, double *ydot, NrnThread *nt)
Definition: occvode.cpp:715
bool structure_change_
Definition: cvodeobj.h:237
bool can_retreat_
Definition: cvodeobj.h:128
NetCvode * ncv_
Definition: cvodeobj.h:244
int interpolate_calls_
Definition: cvodeobj.h:131
void fun_thread_ms_part3(NrnThread *nt)
Definition: occvode.cpp:830
void matmeth()
Definition: cvodeobj.cpp:1441
Cvode()
Definition: cvodeobj.cpp:698
void maxstate(double *)
Definition: cvodeobj.cpp:956
int order()
Definition: cvodeobj.cpp:984
N_Vector acorvec()
Definition: cvodeobj.cpp:1399
void maxorder(int)
Definition: cvodeobj.cpp:997
double tstop_
Definition: cvodeobj.h:248
NrnThread * nth_
Definition: cvodeobj.h:241
virtual int init(double t)
Definition: cvodeobj.cpp:1189
double * n_vector_data(N_Vector, int)
Definition: occvode.cpp:485
virtual int interpolate(double t)
Definition: cvodeobj.cpp:1222
void init_eqn()
Definition: occvode.cpp:99
int daspk_advance_tn()
Definition: cvodeobj.cpp:1377
int cvode_advance_tn(neuron::model_sorted_token const &)
Definition: cvodeobj.cpp:1299
N_Vector ewtvec()
Definition: cvodeobj.cpp:1391
double h()
Definition: cvodeobj.cpp:737
void activate_maxstate(bool)
Definition: cvodeobj.cpp:899
void set_init_flag()
Definition: cvodeobj.cpp:780
double gam()
Definition: cvodeobj.cpp:729
bool use_daspk_
Definition: cvodeobj.h:208
void atolvec_alloc(int)
Definition: cvodeobj.cpp:826
int solvex_thread_part1(double *b, NrnThread *nt)
Definition: occvode.cpp:650
void maxacor(double *)
Definition: cvodeobj.cpp:969
double t0_
Definition: cvodeobj.h:126
double tn_
Definition: cvodeobj.h:126
virtual double t0()
Definition: cvodeobj.h:110
N_Vector nvnew(long)
Definition: cvodeobj.cpp:788
void alloc_cvode()
Definition: cvodeobj.cpp:982
int solve()
Definition: cvodeobj.cpp:1168
int cvode_interpolate(double)
Definition: cvodeobj.cpp:1341
int daspk_init(double)
Definition: cvodeobj.cpp:1103
int f_calls_
Definition: cvodeobj.h:132
N_Vector maxacor_
Definition: cvodeobj.h:234
bool initialize_
Definition: cvodeobj.h:127
void minstep(double)
Definition: cvodeobj.cpp:1008
virtual int advance_tn(neuron::model_sorted_token const &)
Definition: cvodeobj.cpp:1117
int vnode_begin_index_
Definition: cvodeobj.h:80
Definition: nrndaspk.h:10
void statistics()
Definition: nrndaspk.cpp:367
int init()
Definition: nrndaspk.cpp:224
static double dteps_
Definition: nrndaspk.h:35
int interpolate(double tout)
Definition: nrndaspk.cpp:349
static int first_try_init_failures_
Definition: nrndaspk.h:37
void * mem_
Definition: nrndaspk.h:26
int advance_tn(double tstop)
Definition: nrndaspk.cpp:323
N_Vector acorvec()
Definition: nrndaspk.cpp:673
N_Vector ewtvec()
Definition: nrndaspk.cpp:669
static int init_failure_style_
Definition: nrndaspk.h:34
static bool le(double x, double y, double e)
Definition: mymath.h:59
static bool eq(T x, T y, T e)
Definition: mymath.h:63
void dstates()
Definition: netcvode.cpp:4195
double state_magnitudes()
Definition: netcvode.cpp:6484
void set_CVRhsFn()
Definition: cvodeobj.cpp:1038
std::string statename(int, int style=1)
Definition: netcvode.cpp:4380
void states()
Definition: netcvode.cpp:4167
NetCvodeThreadData * p
Definition: netcvode.h:249
static double eps(double x)
Definition: netcvode.h:137
Cvode * gcv_
Definition: netcvode.h:243
void vec_remove()
Definition: netcvode.cpp:6311
void minstep(double)
Definition: netcvode.cpp:4515
void statistics(int)
Definition: netcvode.cpp:3837
void maxstep(double)
Definition: netcvode.cpp:4526
void vec_event_store()
Definition: netcvode.cpp:2485
void spike_stat()
Definition: netcvode.cpp:3900
void rtol(double)
Definition: netcvode.cpp:4469
void simgraph_remove()
Definition: glinerec.cpp:218
void localstep(bool)
Definition: netcvode.cpp:1176
int condition_order()
Definition: netcvode.h:140
void error_weights()
Definition: netcvode.cpp:4283
void jacobian(int)
Definition: netcvode.cpp:4537
Object ** netconlist()
Definition: netcvode.cpp:907
int use_long_double_
Definition: netcvode.h:251
void use_daspk(bool)
Definition: netcvode.cpp:1195
void atol(double)
Definition: netcvode.cpp:4472
int order(int)
Definition: netcvode.cpp:4501
void hoc_event(double, const char *hoc_stmt, Object *ppobj=nullptr, int reinit=0, Object *pyact=nullptr)
Definition: netcvode.cpp:2545
void re_init(double t0=0.)
Definition: netcvode.cpp:3958
void stiff(int)
Definition: netcvode.cpp:4475
void acor()
Definition: netcvode.cpp:4312
int print_event_
Definition: netcvode.h:181
void event_queue_info()
Definition: netcvode.cpp:2902
void vecrecord_add()
Definition: netcvode.cpp:6295
bool single_
Definition: netcvode.h:234
double rtol_
Definition: netcvode.h:158
int solve(double t)
Definition: netcvode.cpp:1949
Symbol * name2sym(const char *)
Definition: netcvode.cpp:4442
void maxorder(int)
Definition: netcvode.cpp:4488
void print_event_queue()
Definition: netcvode.cpp:2854
void structure_change()
Definition: netcvode.cpp:4540
MUTDEC int nlcv_
Definition: netcvode.h:58
void class2oc(const char *, ctor_f *cons, dtor_f *destruct, Member_func *, Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1631
char * gargstr(int narg)
Definition: code2.cpp:227
static Frame * fp
Definition: code.cpp:96
HocReturnType hoc_return_type_code
Definition: code.cpp:42
#define v
Definition: md1redef.h:11
#define i
Definition: md1redef.h:19
#define prop
Definition: md1redef.h:38
double dt
Definition: netcvode.cpp:70
void(* nrn_multisplit_setup_)()
Definition: treeset.cpp:50
static void mfree(CVodeMem cv_mem)
Definition: cvodeobj.cpp:1567
static void f_thread_transfer_part2(neuron::model_sorted_token const &, NrnThread &)
Definition: cvodeobj.cpp:1640
#define nt_dt
Definition: cvodeobj.cpp:58
double nrn_hoc2scatter_y(void *v)
Definition: netcvode.cpp:4253
static void f_lvardt(realtype t, N_Vector y, N_Vector ydot, void *f_data)
Definition: cvodeobj.cpp:1612
static double statistics(void *v)
Definition: cvodeobj.cpp:103
void(* nrnthread_v_transfer_)(NrnThread *)
Definition: fadvance.cpp:139
void Cvode_reg()
Definition: cvodeobj.cpp:653
static double n_remove(void *v)
Definition: cvodeobj.cpp:382
static double ncs_netcons(void *v)
Definition: cvodeobj.cpp:471
static bool maxstate_b
Definition: cvodeobj.cpp:914
static double extra_scatter_gather_remove(void *v)
Definition: cvodeobj.cpp:532
static double nrn_diam_change_count(void *v)
Definition: cvodeobj.cpp:498
static N_Vector f_ydot_
Definition: cvodeobj.cpp:1573
static void * f_thread_ms_part2(NrnThread *)
Definition: cvodeobj.cpp:1655
Symbol * hoc_get_last_pointer_symbol()
Definition: code.cpp:1789
static double solve(void *v)
Definition: cvodeobj.cpp:87
static double state_magnitudes(void *v)
Definition: cvodeobj.cpp:394
static double tstop_event(void *v)
Definition: cvodeobj.cpp:399
static double poolshrink(void *)
Definition: cvodeobj.cpp:562
static double store_events(void *v)
Definition: cvodeobj.cpp:460
static Cvode * msolve_cv_
Definition: cvodeobj.cpp:1491
static void * f_thread_ms_part1(NrnThread *)
Definition: cvodeobj.cpp:1648
static void f_thread(neuron::model_sorted_token const &, NrnThread &)
Definition: cvodeobj.cpp:1623
double nrn_hoc2gather_y(void *v)
Definition: netcvode.cpp:4269
static double debug_event(void *v)
Definition: cvodeobj.cpp:366
static Member_func members[]
Definition: cvodeobj.cpp:577
static void * cons(Object *)
Definition: cvodeobj.cpp:631
static N_Vector f_y_
Definition: cvodeobj.cpp:1572
static void * msolve_thread_part3(NrnThread *)
Definition: cvodeobj.cpp:1559
static double event_queue_info(void *v)
Definition: cvodeobj.cpp:454
static void f_thread_transfer_part1(neuron::model_sorted_token const &, NrnThread &)
Definition: cvodeobj.cpp:1632
bool nrn_use_bin_queue_
Definition: netcvode.cpp:225
static double condition_order(void *v)
Definition: cvodeobj.cpp:356
static Section * cv_rootsec(const Cvode *cv)
Definition: cvodeobj.cpp:1052
static void * msolve_thread_part1(NrnThread *)
Definition: cvodeobj.cpp:1547
static double error_weights(void *v)
Definition: cvodeobj.cpp:271
static double use_daspk(void *v)
Definition: cvodeobj.cpp:304
static void destruct(void *v)
Definition: cvodeobj.cpp:646
static double extra_scatter_gather(void *v)
Definition: cvodeobj.cpp:518
static int minit(CVodeMem cv_mem)
Definition: cvodeobj.cpp:1469
short * nrn_is_artificial_
Definition: cell_group.cpp:19
static double order(void *v)
Definition: cvodeobj.cpp:218
bool nrn_use_fifo_queue_
Definition: netcvode.cpp:223
static double nrn_atol(void *v)
Definition: cvodeobj.cpp:154
static ExtraScatterList * extra_scatterlist[2]
Definition: cvodeobj.cpp:504
static double use_local_dt(void *v)
Definition: cvodeobj.cpp:294
double nrn_hoc2fun(void *v)
Definition: netcvode.cpp:4234
static double states(void *v)
Definition: cvodeobj.cpp:254
static void * maxstate_thread(NrnThread *nt)
Definition: cvodeobj.cpp:916
int linmod_extra_eqn_count()
static double maxorder(void *v)
Definition: cvodeobj.cpp:210
static double acor(void *v)
Definition: cvodeobj.cpp:277
static double statename(void *v)
Definition: cvodeobj.cpp:283
static void msolve_thread(neuron::model_sorted_token const &, NrnThread &)
Definition: cvodeobj.cpp:1537
static double stiff(void *v)
Definition: cvodeobj.cpp:202
static double cache_efficient(void *v)
Definition: cvodeobj.cpp:338
static void * msolve_thread_part2(NrnThread *)
Definition: cvodeobj.cpp:1554
double nrn_hoc2fixed_step(void *v)
Definition: netcvode.cpp:4229
static double peq(void *v)
Definition: cvodeobj.cpp:448
static double use_long_double(void *v)
Definition: cvodeobj.cpp:345
static Member_ret_obj_func omembers[]
Definition: cvodeobj.cpp:629
double t
Definition: cvodeobj.cpp:57
static CVRhsFn pf_
Definition: cvodeobj.cpp:679
static double use_mxb(void *v)
Definition: cvodeobj.cpp:326
static int msolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, N_Vector ycur, N_Vector fcur)
Definition: cvodeobj.cpp:1492
void hoc_symbol_tolerance(Symbol *, double)
Definition: code2.cpp:111
static int msetup(CVodeMem cv_mem, int convfail, N_Vector ypred, N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp, N_Vector vtemp2, N_Vector vtemp3)
Definition: cvodeobj.cpp:1474
static void * f_thread_ms_part4(NrnThread *)
Definition: cvodeobj.cpp:1665
int secondorder
Definition: init.cpp:107
void cvode_finitialize()
static double abstol(void *v)
Definition: cvodeobj.cpp:165
static N_Vector msolve_ycur_
Definition: cvodeobj.cpp:1490
static double dstates(void *v)
Definition: cvodeobj.cpp:260
static Cvode * maxstate_cv
Definition: cvodeobj.cpp:915
static double minstep(void *v)
Definition: cvodeobj.cpp:229
static int msolve_lvardt(CVodeMem cv_mem, N_Vector b, N_Vector weight, N_Vector ycur, N_Vector fcur)
Definition: cvodeobj.cpp:1520
#define SUCCESS
Definition: cvodeobj.cpp:83
static void * f_thread_ms_part34(NrnThread *)
Definition: cvodeobj.cpp:1671
std::vector< Object * > ExtraScatterList
Definition: cvodeobj.cpp:503
static double nrn_structure_change_count(void *v)
Definition: cvodeobj.cpp:493
static N_Vector msolve_b_
Definition: cvodeobj.cpp:1489
static void static_mutex_for_at_time(bool b)
Definition: cvodeobj.cpp:34
static double jacobian(void *v)
Definition: cvodeobj.cpp:245
static double free_event_queues(void *)
Definition: cvodeobj.cpp:572
int nrn_modeltype()
Definition: treeset.cpp:1785
static double current_method(void *v)
Definition: cvodeobj.cpp:432
void nrn_extra_scatter_gather(int direction, int tid)
Definition: cvodeobj.cpp:506
static double use_parallel(void *v)
Definition: cvodeobj.cpp:480
static double re_init(void *v)
Definition: cvodeobj.cpp:138
NetCvode * net_cvode_instance
Definition: cvodestb.cpp:26
static double dae_init_dteps(void *v)
Definition: cvodeobj.cpp:316
static Object ** netconlist(void *v)
Definition: cvodeobj.cpp:466
static void f_gvardt(realtype t, N_Vector y, N_Vector ydot, void *f_data)
Definition: cvodeobj.cpp:1575
static void * f_thread_ms_part3(NrnThread *)
Definition: cvodeobj.cpp:1660
static double use_fast_imem(void *v)
Definition: cvodeobj.cpp:552
static double spikestat(void *v)
Definition: cvodeobj.cpp:112
static double n_record(void *v)
Definition: cvodeobj.cpp:376
static double active(void *v)
Definition: cvodeobj.cpp:192
static double simgraph_remove(void *v)
Definition: cvodeobj.cpp:388
#define nt_t
Definition: cvodeobj.cpp:59
static double queue_mode(void *v)
Definition: cvodeobj.cpp:117
static Cvode * f_cv_
Definition: cvodeobj.cpp:1574
static double rtol(void *v)
Definition: cvodeobj.cpp:147
int nrn_use_selfqueue_
Definition: netcvode.cpp:77
static double maxstep(void *v)
Definition: cvodeobj.cpp:237
static realtype f_t_
Definition: cvodeobj.cpp:1571
void(* nrnmpi_v_transfer_)()
Definition: fadvance.cpp:138
void nrn_poolshrink(int shrink)
Definition: cxprop.cpp:108
double chkarg(int, double low, double high)
Definition: code2.cpp:626
#define TRUE
Definition: grids.h:22
int hoc_is_object_arg(int narg)
Definition: code.cpp:876
int hoc_is_str_arg(int narg)
Definition: code.cpp:872
void hoc_assign_str(char **cpp, const char *buf)
Definition: code.cpp:2263
void check_obj_type(Object *obj, const char *type_name)
Definition: hoc_oop.cpp:2098
void hoc_obj_ref(Object *obj)
Definition: hoc_oop.cpp:1844
char * hoc_object_name(Object *ob)
Definition: hoc_oop.cpp:73
void hoc_obj_unref(Object *obj)
Definition: hoc_oop.cpp:1881
char ** hoc_pgargstr(int narg)
Definition: code.cpp:1623
#define assert(ex)
Definition: hocassrt.h:24
#define getarg
Definition: hocdec.h:17
Point_process * ob2pntproc(Object *ob)
Definition: hocmech.cpp:99
Object ** hoc_objgetarg(int)
Definition: code.cpp:1614
#define STATE
Definition: membfunc.hpp:65
#define VINDEX
Definition: membfunc.hpp:57
floor
Definition: extdef.h:4
fabs
Definition: extdef.h:3
auto for_threads(NrnThread *threads, int num_threads)
Definition: multicore.h:133
NrnThread * nrn_threads
Definition: multicore.cpp:56
int nrn_nthread
Definition: multicore.cpp:55
void nrn_fast_imem_alloc()
Definition: fast_imem.cpp:32
bool cvode_active_
Definition: netcvode.cpp:36
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
int structure_change_cnt
bool nrn_use_fast_imem
Definition: fast_imem.cpp:19
void nrn_multithread_job(F &&job, Args &&... args)
Definition: multicore.hpp:161
void hoc_warning(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:44
impl_ptrs methods
Collection of pointers to functions with python-version-specific implementations.
Definition: nrnpy.cpp:21
#define nrn_nonvint_block_ode_reinit(size, y, tid)
Definition: nonvintblock.h:58
void recalc_diam(void)
Definition: treeset.cpp:923
neuron::model_sorted_token nrn_ensure_model_data_are_sorted()
Ensure neuron::container::* data are sorted.
Definition: treeset.cpp:2182
#define tstopunset
Definition: nrnconf.h:45
int const size_t const size_t n
Definition: nrngsl.h:10
int diam_change_cnt
Definition: treeset.cpp:67
int ifarg(int)
Definition: code.cpp:1607
#define MUTCONSTRUCT(mkmut)
Definition: nrnmutdec.h:33
#define MUTDESTRUCT
Definition: nrnmutdec.h:34
#define MUTDEC
Definition: nrnmutdec.h:31
#define MUTLOCK
Definition: nrnmutdec.h:35
#define MUTUNLOCK
Definition: nrnmutdec.h:36
int nrn_vartype(const Symbol *sym)
Definition: eion.cpp:503
void nrn_thread_error(const char *s)
Definition: multicore.cpp:297
static int hoccommand_exec(Object *ho)
Definition: nrnpy_p2h.cpp:339
static int pysame(Object *o1, Object *o2)
Definition: nrnpy_p2h.cpp:69
N_Vector N_VNew_NrnParallelLD(MPI_Comm comm, long int local_length, long int global_length)
N_Vector N_VNew_NrnSerialLD(long int length)
N_Vector N_VNew_NrnThread(long int length, int nthread, long int *sizes)
N_Vector N_VNew_NrnThreadLD(long int length, int nthread, long int *sizes)
int use_sparse13
Definition: treeset.cpp:58
#define NULL
Definition: spdefs.h:105
float tolerance
Definition: hocdec.h:100
Section * sec
Definition: section.h:193
Represent main neuron object computed by single thread.
Definition: multicore.h:58
int id
Definition: multicore.h:66
void * _vcv
Definition: multicore.h:97
Node ** _v_node
Definition: multicore.h:90
double _t
Definition: multicore.h:59
Definition: hocdec.h:173
cTemplate * ctemplate
Definition: hocdec.h:180
Definition: model.h:47
union Symbol::@28 u
struct Symbol::@45::@46 rng
char * name
Definition: model.h:61
HocSymExtension * extra
Definition: hocdec.h:131
int is_point_
Definition: hocdec.h:150
int Printf(const char *fmt, Args... args)
Definition: logger.hpp:18