NEURON
nrndaspk.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 // differential algebraic system solver interface to DDASPK
3 
4 // DDASPK is translated from fortran with f2c. Hence all args are
5 // call by reference
6 
7 #include <stdio.h>
8 #include <math.h>
9 #include <InterViews/resource.h>
10 #include "spmatrix.h"
11 #include "nrnoc2iv.h"
12 #include "cvodeobj.h"
13 #include "nrndaspk.h"
14 #include "netcvode.h"
15 #include "ida/ida.h"
16 #include "ida/ida_impl.h"
17 #include "mymath.h"
18 
19 // the state of the g - d2/dx2 matrix for voltages
20 #define INVALID 0
21 #define NO_CAP 1
22 #define SETUP 2
23 #define FACTORED 3
24 static int solve_state_;
25 
26 // prototypes
27 
28 double Daspk::dteps_;
29 
30 
31 extern void nrndae_dkres(double*, double*, double*);
32 extern void nrndae_dkpsol(double);
33 extern void nrn_rhs(NrnThread*);
34 extern void nrn_lhs(NrnThread*);
35 extern void nrn_solve(NrnThread*);
36 void nrn_daspk_init_step(double, double, int);
37 // this is private in ida.cpp but we want to check if our initialization
38 // is good. Unfortunately ewt is set on the first call to solve which
39 // is too late for us.
40 extern "C" {
41 extern booleantype IDAEwtSet(IDAMem IDA_mem, N_Vector ycur);
42 } // extern "C"
43 
44 //extern double t, dt;
45 #define nt_dt nrn_threads->_dt
46 #define nt_t nrn_threads->_t
47 
48 static void daspk_nrn_solve(NrnThread* nt) {
49  nrn_solve(nt);
50 }
51 
52 static int res_gvardt(
53  realtype t, N_Vector y, N_Vector yp, N_Vector delta,
54  void* rdata
55 );
56 
57 static int minit(IDAMem);
58 
59 static int msetup(IDAMem mem, N_Vector y, N_Vector ydot, N_Vector delta,
60  N_Vector tempv1, N_Vector tempv2, N_Vector tempv3
61 );
62 
63 static int msolve(IDAMem mem, N_Vector b, N_Vector ycur, N_Vector ypcur,
64  N_Vector deltacur
65 );
66 
67 static int mfree(IDAMem);
68 
69 
70 
71 // at least in DARWIN the following is already declared so avoid conflict
72 #define thread_t nrn_thread_t
73 
74 // residual
75 static N_Vector nvec_y;
76 static N_Vector nvec_yp;
77 static N_Vector nvec_delta;
78 static double thread_t;
79 static double thread_cj;
80 static int thread_ier;
81 static Cvode* thread_cv;
82 static void* res_thread(NrnThread* nt) {
83  int i = nt->id;
84  Cvode* cv = thread_cv;
85  int ier = cv->res(thread_t, cv->n_vector_data(nvec_y, i),
86  cv->n_vector_data(nvec_yp, i), cv->n_vector_data(nvec_delta, i), nt);
87  if (ier != 0) {
88  thread_ier = ier;
89  }
90  return 0;
91 }
92 static int res_gvardt(
93  realtype t, N_Vector y, N_Vector yp, N_Vector delta,
94  void* rdata
95 ){
96  thread_cv = (Cvode*)rdata;
97  nvec_y = y;
98  nvec_yp = yp;
99  nvec_delta = delta;
100  thread_t = t;
101  thread_ier = 0;
103  return thread_ier;
104 }
105 
106 // linear solver specific allocation and initialization
107 static int minit(IDAMem) {
108  return IDA_SUCCESS;
109 }
110 
111 // linear solver preparation for subsequent calls to msolve
112 // approximation to jacobian. Everything necessary for solving P*x = b
113 static int msetup(IDAMem mem, N_Vector y, N_Vector yp, N_Vector,
114  N_Vector, N_Vector, N_Vector
115 ){
116  Cvode* cv = (Cvode*)mem->ida_rdata;
117  ++cv->jac_calls_;
118  return 0;
119 }
120 
121 /* solve P*x = b */
122 static void* msolve_thread(NrnThread* nt) {
123  int i = nt->id;
124  Cvode* cv = thread_cv;
125  int ier = cv->psol(thread_t, cv->n_vector_data(nvec_y, i),
126  cv->n_vector_data(nvec_yp, i), thread_cj, nt);
127  if (ier != 0) {
128  thread_ier = ier;
129  }
130  return 0;
131 }
132 static int msolve(IDAMem mem, N_Vector b, N_Vector w, N_Vector ycur, N_Vector, N_Vector){
133  thread_cv = (Cvode*)mem->ida_rdata;
134  thread_t = mem->ida_tn;
135  nvec_y = ycur;
136  nvec_yp = b;
137  thread_cj = mem->ida_cj;
139  return thread_ier;
140 }
141 
142 static int mfree(IDAMem) {return IDA_SUCCESS;}
143 
144 Daspk::Daspk(Cvode* cv, int neq) {
145 // printf("Daspk::Daspk\n");
146  cv_ = cv;
147  yp_ = cv->nvnew(neq);
148  delta_ = cv->nvnew(neq);
149  parasite_ = cv->nvnew(neq);
150  use_parasite_ = false;
151  spmat_ = nil;
152  mem_ = nil;
153 }
154 
156 // printf("Daspk::~Daspk\n");
157  N_VDestroy(delta_);
158  N_VDestroy(yp_);
159  if (mem_) {
160  IDAFree((IDAMem)mem_);
161  }
162 }
163 
165  int ier;
166  if (mem_) {
167  ier = IDAReInit(mem_, res_gvardt, cv_->t_, cv_->y_, yp_,
168  IDA_SV, &cv_->ncv_->rtol_, cv_->atolnvec_
169  );
170  if (ier < 0) {
171  hoc_execerror("IDAReInit error", 0);
172  }
173  }else{
174  IDAMem mem = (IDAMem) IDACreate();
175  if (!mem) {
176  hoc_execerror("IDAMalloc error", 0);
177  }
178  IDASetRdata(mem, cv_);
179  ier = IDAMalloc(mem, res_gvardt, cv_->t_, cv_->y_, yp_,
180  IDA_SV, &cv_->ncv_->rtol_, cv_->atolnvec_
181  );
182  mem->ida_linit = minit;
183  mem->ida_lsetup = msetup;
184  mem->ida_lsolve = msolve;
185  mem->ida_lfree = mfree;
186  mem->ida_setupNonNull = false;
187  mem_ = mem;
188  }
189 }
190 
191 void Daspk::info() {
192 }
193 
194 
195 // last two bits, 0 error, 1 warning, 2 apply parasitic
196 // if init_failure_style & 010, then use the original method
200 
201 static void* do_ode_thread(NrnThread* nt) {
202  int i;
203  Cvode* cv = thread_cv;
204  nt->_t = cv->t_;
205  cv->do_ode(nt);
206  CvodeThreadData& z = cv->ctd_[nt->id];
207  double* yp = cv->n_vector_data(nvec_yp, nt->id);
208  for (i=z.neq_v_; i < z.nvsize_; ++i) {
209  yp[i] = *(z.pvdot_[i]);
210  }
211  return 0;
212 }
213 
214 static double check(double t, Daspk* ida) {
215  res_gvardt(t, ida->cv_->y_, ida->yp_, ida->delta_, ida->cv_);
216  double norm = N_VWrmsNorm(ida->delta_, ((IDAMem)(ida->mem_))->ida_ewt);
217  Printf("ida check t=%.15g norm=%g\n", t, norm);
218 #if 0
219  for (int i=0; i < ida->cv_->neq_; ++i) {
220  printf(" %3d %22.15g %22.15g %22.15g\n", i,
221 N_VGetArrayPointer(ida->cv_->y_)[i],
222 N_VGetArrayPointer(ida->yp_)[i],
223 N_VGetArrayPointer(ida->delta_)[i]);
224  }
225 #endif
226  return norm;
227 }
228 
229 int Daspk::init() {
230  extern double t;
231  int i;
232 #if 0
233 printf("Daspk_init t_=%20.12g t-t_=%g t0_-t_=%g\n",
234 cv_->t_, t-cv_->t_, cv_->t0_-cv_->t_);
235 #endif
236  N_VConst(0., yp_);
237 
238  // the new initial condition is based on a dteps_ step backward euler
239  // linear solution with respect to the old state in order to
240  // start the following initial condition calculation with a "valid"
241  // (in a linear system sense) initial state.
242 
243  double tt = cv_->t_;
244  double dtinv = 1./dteps_;
245  if (init_failure_style_ & 010) {
246  cv_->play_continuous(tt);
247  nrn_daspk_init_step(tt, dteps_, 1);
248  nrn_daspk_init_step(tt, dteps_, 1);
250  cv_->play_continuous(tt);
251  nrn_daspk_init_step(tt, dteps_, 1);
253  N_VLinearSum(dtinv, cv_->y_, -dtinv, yp_, yp_);
254  }else{
255 #if 0
256  cv_->play_continuous(tt);
257  nrn_daspk_init_step(tt, dteps_, 1);
259  tt = cv_->t_ + dteps_;
260  cv_->play_continuous(tt);
261  nrn_daspk_init_step(tt, dteps_, 1);
263  N_VLinearSum(dtinv, yp_, -dtinv, cv_->y_, yp_);
265 #else
266  cv_->play_continuous(tt);
267  nrn_daspk_init_step(tt, dteps_, 1); // first approx to y (and maybe good enough)
268  nrn_daspk_init_step(tt, dteps_, 1); // 2nd approx to y (trouble with 2sramp.hoc)
269 
271  tt = cv_->t_ + dteps_;
272  cv_->play_continuous(tt);
273  nrn_daspk_init_step(tt, dteps_, 0); // rhs contains delta y (for v, vext, linmod
274  cv_->gather_ydot(yp_);
275  N_VScale(dtinv, yp_, yp_);
276 #endif
277  }
278  thread_cv = cv_;
279  nvec_yp = yp_;
281  ida_init();
282  t = cv_->t_;
283 #if 1
284  // test
285 //printf("test\n");
286  if (!IDAEwtSet((IDAMem)mem_, cv_->y_)) {
287  hoc_execerror("Bad Ida error weight vector", 0);
288  }
289  use_parasite_ = false;
290 // check(cv_->t_, this);
292  double norm = N_VWrmsNorm(parasite_, ((IDAMem)mem_)->ida_ewt);
293 //printf("norm=%g at t=%g\n", norm, t);
294  if (norm > 1.) {
295  switch (init_failure_style_ & 03) {
296  case 0:
297  Printf("IDA initialization failure, weighted norm of residual=%g\n", norm);
298  return IDA_ERR_FAIL;
299  break;
300  case 1:
301  Printf("IDA initialization warning, weighted norm of residual=%g\n", norm);
302  break;
303  case 2:
304  Printf("IDA initialization warning, weighted norm of residual=%g\n", norm);
305  use_parasite_ = true;
306  t_parasite_ = nt_t;
307  Printf(" subtracting (for next 1e-6 ms): f(y', y, %g)*exp(-1e7*(t-%g))\n", nt_t, nt_t);
308  break;
309  }
310 #if 0
311 for (i=0; i < cv_->neq_; ++i) {
312  printf(" %d %g %g %g %g\n", i, nt_t, N_VGetArrayPointer(cv_->y_)[i], N_VGetArrayPointer(yp_)[i], N_VGetArrayPointer(delta_)[i]);
313 }
314 #endif
315  if (init_try_again_ < 0) {
317  init_try_again_ += 1;
318  int err = init();
319  init_try_again_ = 0;
320  return err;
321  }
322 return 0;
323  }
324 #endif
325 
326  return 0;
327 }
328 
329 int Daspk::advance_tn(double tstop) {
330  //printf("Daspk::advance_tn(%g)\n", tstop);
331  double tn = cv_->tn_;
332  IDASetStopTime(mem_, tstop);
333  int ier = IDASolve(mem_, tstop, &cv_->t_, cv_->y_, yp_, IDA_ONE_STEP_TSTOP);
334  if (ier < 0) {
335  //printf("DASPK advance_tn error\n");
336  return ier;
337  }
338 #if 0
339  if (ier > 0 && t < cv_->t_) {
340  // interpolation to tstop does not call res. So we have to.
341  cv_->res(cv_->t_, N_VGetArrayPointer(cv_->y_), N_VGetArrayPointer(yp_), N_VGetArrayPointer(delta_));
343  }
344 #else
345  // this is very bad, performance-wise. However ida modifies its states
346  // after a call to fun with the proper t.
347  res_gvardt(cv_->t_, cv_->y_, yp_, delta_, cv_);
348 #endif
349  cv_->t0_ = tn;
350  cv_->tn_ = cv_->t_;
351  //printf("Daspk::advance_tn complete.\n");
352  return ier;
353 }
354 
355 int Daspk::interpolate(double tt) {
356 //printf("Daspk::interpolate %.15g\n", tt);
357  assert (tt >= cv_->t0_ && tt <= cv_->tn_);
358  IDASetStopTime(mem_, tt);
359  int ier = IDASolve(mem_, tt, &cv_->t_, cv_->y_, yp_, IDA_NORMAL);
360  if (ier < 0) {
361  Printf("DASPK interpolate error\n");
362  return ier;
363  }
365  // interpolation does not call res. So we have to.
366  res_gvardt(cv_->t_, cv_->y_, yp_, delta_, cv_);
367 //if(MyMath::eq(t, cv_->t_, NetCvode::eps(cv_->t_))) {
368 //printf("t=%.15g t_=%.15g\n", t, cv_->t_);
369 //}
370 // assert(MyMath::eq(t, cv_->t_, NetCvode::eps(cv_->t_)));
371  return ier;
372 }
373 
375 #if 0
376  printf("rwork size = %d\n", iwork_[18-1]);
377  printf("iwork size = %d\n", iwork_[17-1]);
378  printf("Number of time steps = %d\n", iwork_[11-1]);
379  printf("Number of residual evaluations = %d\n", iwork_[12-1]);
380  printf("Number of Jac evaluations = %d\n", iwork_[13-1]);
381  printf("Number of preconditioner solves = %d\n", iwork_[21-1]);
382  printf("Number of nonlinear iterations = %d\n", iwork_[19-1]);
383  printf("Number of linear iterations = %d\n", iwork_[20-1]);
384  double avlin = double(iwork_[20-1])/double(iwork_[19-1]);
385  printf("Average Krylov subspace dimension = %g\n", avlin);
386  printf("nonlinear conv. failures = %d\n", iwork_[15-1]);
387  printf("linear conv. failures = %d\n", iwork_[16-1]);
388 #endif
390  Printf(" %d First try Initialization failures\n", first_try_init_failures_);
391  }
392 }
393 
394 static void* daspk_scatter_thread(NrnThread* nt) {
395  thread_cv->daspk_scatter_y(thread_cv->n_vector_data(nvec_y, nt->id), nt->id);
396  return 0;
397 }
398 void Cvode::daspk_scatter_y(N_Vector y) {
399  thread_cv = this;
400  nvec_y = y;
402 }
403 void Cvode::daspk_scatter_y(double* y, int tid) {
404  // the dependent variables in daspk are vi,vx,etc
405  // whereas in the node structure we need vm, vx
406  // note that a corresponding transformation for gather_ydot is
407  // not needed since the matrix solve is already with respect to vi,vx
408  // in all cases. (i.e. the solution vector is in the right hand side
409  // and refers to vi, vx.
410  scatter_y(y, tid);
411  // transform the vm+vext to vm
412  CvodeThreadData& z = ctd_[tid];
413  if (z.cmlext_) {
414  Memb_list* ml = z.cmlext_->ml;
415  int i, n = ml->nodecount;
416  for (i=0; i < n; ++i) {
417  Node* nd = ml->nodelist[i];
418  NODEV(nd) -= nd->extnode->v[0];
419  }
420  }
421 }
422 static void* daspk_gather_thread(NrnThread* nt) {
423  thread_cv->daspk_gather_y(thread_cv->n_vector_data(nvec_y, nt->id), nt->id);
424  return 0;
425 }
426 void Cvode::daspk_gather_y(N_Vector y) {
427  thread_cv = this;
428  nvec_y = y;
430 }
431 void Cvode::daspk_gather_y(double* y, int tid) {
432  gather_y(y, tid);
433  // transform vm to vm+vext
434  CvodeThreadData& z = ctd_[tid];
435  if (z.cmlext_) {
436  Memb_list* ml = z.cmlext_->ml;
437  int i, n = ml->nodecount;
438  for (i=0; i < n; ++i) {
439  Node* nd = ml->nodelist[i];
440  int j = nd->eqn_index_;
441  y[j-1] += y[j];
442  }
443  }
444 }
445 
446 // for res and psol the equations for c*yp = f(y) are
447 // cast in the form G(t,y,yp) = f(y) - c*yp
448 // So res calculates delta = f(y) - c*yp
449 // and psol solves (c*cj - df/dy)*x = -b
450 // Note that since cvode uses J = 1 - gam*df/dy and
451 // ida uses J = df/dy - cj*df/dyp that is the origin of the use of -b in our
452 // psol and also why all the non-voltage odes are scaled by dt at the
453 // end of it.
454 
455 int Cvode::res(double tt, double* y, double* yprime, double* delta, NrnThread* nt) {
456  CvodeThreadData& z = ctd_[nt->id];
457  ++f_calls_;
458  static int res_;
459  int i;
460  nt->_t = tt;
461  res_++;
462 
463 #if 0
464 printf("Cvode::res enter tt=%g\n", tt);
465 for (i=0; i < z.nvsize_; ++i) {
466  printf(" %d %g %g %g\n", i, y[i], yprime[i], delta[i]);
467 }
468 #endif
469  nt->_vcv = this; // some models may need to know this
470  daspk_scatter_y(y, nt->id); // vi, vext, channel states, linmod non-node y.
471  // rhs of cy' = f(y)
472  play_continuous_thread(tt, nt);
473  nrn_rhs(nt);
474  do_ode(nt);
475  // accumulate into delta
476  gather_ydot(delta, nt->id);
477 
478  // now calculate -c*yp. i.e.
479  // cm*vm' + c_linmod*vi' internal current balance
480  // cx*vx' + c_linmod*vx' external current balance
481  // c_linmod*y' non-node linmod states
482  // y' mechanism states
483 
484  // this can be accumulated into delta in several stages
485  // -cm*vm'and -cx*vx for current balance equation delta's
486  // -c_linmod*yp (but note that the node yp yp(vm)+yp(vx))
487  // subtract yp from mechanism state delta's
488 
489 #if 0
490 printf("Cvode::res after ode and gather_ydot into delta\n");
491 for (i=0; i < z.nvsize_; ++i) {
492  printf(" %d %g %g %g\n", i, y[i], yprime[i], delta[i]);
493 }
494 #endif
495  // the cap nodes : see nrnoc/capac.cpp for location of cm, etc.
496  // these are not in same order as for cvode but are in
497  // spmatrix order mixed with nocap nodes and extracellular
498  // therefore we use the Node.eqn_index to calculate the delta index.
499 // assert(use_sparse13 == true && nlayer <= 1);
500  assert(use_sparse13 == true);
501  if (z.cmlcap_) {
502  Memb_list* ml = z.cmlcap_->ml;
503  int n = ml->nodecount;
504  double* p = NULL;
505  if (nt->_nrn_fast_imem) {
506  p = nt->_nrn_fast_imem->_nrn_sav_rhs;
507  }
508  for (i=0; i < n; ++i) {
509  double* cd = ml->data[i];
510  Node* nd = ml->nodelist[i];
511  int j = nd->eqn_index_ - 1;
512  Extnode* nde = nd->extnode;
513  double cdvm;
514  if (nde) {
515  cdvm = 1e-3 * cd[0] * (yprime[j] - yprime[j+1]);
516  delta[j] -= cdvm;
517  delta[j+1] += cdvm;
518  // i_cap
519  cd[1] = cdvm;
520 #if I_MEMBRANE
521  // add i_cap to i_ion which is in sav_g
522  // this will be copied to i_membrane below
523  nde->param[3+3*nlayer] += cdvm;
524 #endif
525  }else{
526  cdvm = 1e-3 * cd[0] * yprime[j];
527  delta[j] -= cdvm;
528  cd[1] = cdvm;
529  }
530  if (p) {
531  int i = nd->v_node_index;
532  p[i] += cdvm;
533  p[i] *= NODEAREA(nd) * 0.01;
534  }
535  }
536  }
537  // See nrnoc/excelln.cpp for location of cx.
538  if (z.cmlext_) {
539  Memb_list* ml = z.cmlext_->ml;
540  int n = ml->nodecount;
541  for (i=0; i < n; ++i) {
542  double* cd = ml->data[i];
543  Node* nd = ml->nodelist[i];
544  int j = nd->eqn_index_;
545 #if EXTRACELLULAR
546 #if I_MEMBRANE
547  // i_membrane = sav_rhs --- even for zero area nodes
548  cd[1+3*nlayer] = cd[3+3*nlayer];
549 #endif /*I_MEMBRANE*/
550  if (nlayer == 1) {
551  // only works for one layer
552  // otherwise loop over layer,
553  // xc is (pd + 2*(nlayer))[layer]
554  // and deal with yprime[i+layer]-yprime[i+layer+1]
555  delta[j] -= 1e-3 * cd[2] * yprime[j];
556  }else{
557  int k, jj;
558  double x;
559  k = nlayer-1;
560  jj = j+k;
561  delta[jj] -= 1e-3*cd[2*nlayer+k]*(yprime[jj]);
562  for (k=nlayer-2; k >= 0; --k) {
563  // k=0 refers to stuff between layer 0 and 1
564  // j is for vext[0]
565  jj = j+k;
566  x = 1e-3*cd[2*nlayer+k]*(yprime[jj] - yprime[jj+1]);
567  delta[jj] -= x;
568  delta[jj+1] += x; // last one in iteration is nlayer-1
569  }
570 
571  }
572 #endif /*EXTRACELLULAR*/
573  }
574  }
575 
576  nrndae_dkres(y, yprime, delta);
577 
578  // the ode's
579  for (i=z.neq_v_; i < z.nvsize_; ++i) {
580  delta[i] -= yprime[i];
581  }
582 
583  for (i=0; i < z.nvsize_; ++i) {
584  delta[i] *= -1.;
585  }
586  if (daspk_->use_parasite_ && tt - daspk_->t_parasite_ < 1e-6) {
587  double fac = exp(1e7*(daspk_->t_parasite_ - tt));
588  double* tps = n_vector_data(daspk_->parasite_, nt->id);
589  for (i=0; i < z.nvsize_; ++i) {
590  delta[i] -= tps[i]*fac;
591  }
592  }
593  before_after(z.after_solve_, nt);
594 #if 0
595 printf("Cvode::res exit res_=%d tt=%20.12g\n", res_, tt);
596 for (i=0; i < z.nvsize_; ++i) {
597  printf(" %d %g %g %g\n", i, y[i], yprime[i], delta[i]);
598 }
599 #endif
600  nt->_vcv = 0;
601 #if 0
602 double e = 0;
603 for (i=0; i < z.nvsize_; ++i) {
604  e += delta[i]*delta[i];
605 }
606 printf("Cvode::res %d e=%g t=%.15g\n", res_, e, tt);
607 #endif
608  return 0;
609 }
610 
611 int Cvode::psol(double tt, double* y, double* b, double cj, NrnThread* _nt) {
612  CvodeThreadData& z = ctd_[_nt->id];
613  ++mxb_calls_;
614  int i;
615  _nt->_t = tt;
616 
617 #if 0
618 printf("Cvode::psol tt=%g solvestate=%d \n", tt, solve_state_);
619 for (i=0; i < z.nvsize_; ++i) {
620 printf(" %g", b[i]);
621 }
622 printf("\n");
623 #endif
624 
625  _nt->cj = cj;
626  _nt->_dt = 1./cj;
627 
628  _nt->_vcv = this;
629  daspk_scatter_y(y, _nt->id); // I'm not sure this is necessary.
630  if (solve_state_ == INVALID) {
631  nrn_lhs(_nt); // designed to setup M*[dvm+dvext, dvext, dy] = ...
633  }
634  if (solve_state_ == SETUP) {
635  // if using sparse 13 then should factor
637  }
638  scatter_ydot(b, _nt->id);
639 #if 0
640 printf("before nrn_solve matrix cj=%g\n", cj);
641 spPrint(sp13mat_, 1,1,1);
642 printf("before nrn_solve actual_rhs=\n");
643 for (i=0; i < z.neq_v_; ++i) {
644  printf("%d %g\n", i+1, actual_rhs[i+1]);
645 }
646 #endif
647  daspk_nrn_solve(_nt); // not the cvode one
648 #if 0
649 //printf("after nrn_solve matrix\n");
650 //spPrint(sp13mat_, 1,1,1);
651 printf("after nrn_solve actual_rhs=\n");
652 for (i=0; i < neq_v_; ++i) {
653  printf("%d %g\n", i+1, actual_rhs[i+1]);
654 }
655 #endif
656  solve_state_ = INVALID; // but not if using sparse13
657  solvemem(_nt);
658  gather_ydot(b, _nt->id);
659  // the ode's of the form m' = (minf - m)/mtau in model descriptions compute
660  // b = b/(1 + dt*mtau) since cvode required J = 1 - gam*df/dy
661  // so we need to scale those results by 1/cj.
662  for (i=z.neq_v_; i < z.nvsize_; ++i) {
663  b[i] *= _nt->_dt;
664  }
665 #if 0
666 for (i=0; i < z.nvsize_; ++i) {
667 printf(" %g", b[i]);
668 }
669 printf("\n");
670 #endif
671  _nt->_vcv = 0;
672  return 0;
673 }
674 
675 N_Vector Daspk::ewtvec() {
676  return ((IDAMem)mem_)->ida_ewt;
677 }
678 
679 N_Vector Daspk::acorvec() {
680  return ((IDAMem)mem_)->ida_delta;
681 }
682 
683 
#define Printf
Definition: model.h:252
double * v
Definition: section.h:195
#define SETUP
Definition: nrndaspk.cpp:22
void daspk_gather_y(N_Vector)
Definition: nrndaspk.cpp:426
#define assert(ex)
Definition: hocassrt.h:26
void nrn_multithread_job(void *(*job)(NrnThread *))
Definition: multicore.cpp:1081
#define NODEV(n)
Definition: section.h:114
static void daspk_nrn_solve(NrnThread *nt)
Definition: nrndaspk.cpp:48
int init()
Definition: nrndaspk.cpp:229
N_Vector acorvec()
Definition: nrndaspk.cpp:679
bool use_parasite_
Definition: nrndaspk.h:31
double * n_vector_data(N_Vector, int)
Definition: occvode.cpp:434
CvodeThreadData * ctd_
Definition: cvodeobj.h:199
double rtol_
Definition: netcvode.h:137
void * mem_
Definition: nrndaspk.h:25
size_t p
Represent main neuron object computed by single thread.
Definition: multicore.h:58
#define FACTORED
Definition: nrndaspk.cpp:23
void ida_init()
Definition: nrndaspk.cpp:164
int neq_
Definition: cvodeobj.h:204
CvMembList * cmlext_
Definition: cvodeobj.h:53
nd
Definition: treeset.cpp:893
void nrn_rhs(NrnThread *)
Definition: treeset.cpp:355
double ** data
Definition: nrnoc_ml.h:14
NetCvode * ncv_
Definition: cvodeobj.h:203
static int init_failure_style_
Definition: nrndaspk.h:33
static philox4x32_key_t k
Definition: nrnran123.cpp:11
BAMechList * after_solve_
Definition: cvodeobj.h:56
booleantype IDAEwtSet(IDAMem IDA_mem, N_Vector ycur)
#define INVALID
Definition: nrndaspk.cpp:20
#define e
Definition: passive0.cpp:24
_nrn_Fast_Imem * _nrn_fast_imem
Definition: multicore.h:82
static double dteps_
Definition: nrndaspk.h:34
static int res_gvardt(realtype t, N_Vector y, N_Vector yp, N_Vector delta, void *rdata)
Definition: nrndaspk.cpp:92
int use_sparse13
Definition: treeset.cpp:69
int id
Definition: multicore.h:66
static N_Vector nvec_yp
Definition: nrndaspk.cpp:76
double _dt
Definition: multicore.h:60
static N_Vector nvec_delta
Definition: nrndaspk.cpp:77
CvMembList * cmlcap_
Definition: cvodeobj.h:52
int jac_calls_
Definition: cvodeobj.h:103
void nrn_solve(NrnThread *)
Definition: solve.cpp:328
void nrn_daspk_init_step(double, double, int)
Definition: fadvance.cpp:321
Cvode * cv_
Definition: nrndaspk.h:26
int const size_t const size_t n
Definition: nrngsl.h:12
int res(double, double *, double *, double *, NrnThread *)
Definition: nrndaspk.cpp:455
static double check(double t, Daspk *ida)
Definition: nrndaspk.cpp:214
int nodecount
Definition: nrnoc_ml.h:18
static int minit(IDAMem)
Definition: nrndaspk.cpp:107
Definition: nrndaspk.h:11
double * _nrn_sav_rhs
Definition: multicore.h:46
int advance_tn(double tstop)
Definition: nrndaspk.cpp:329
double t_
Definition: cvodeobj.h:97
#define printf
Definition: mwprefix.h:26
#define spPrint
Definition: cspredef.h:33
virtual ~Daspk()
Definition: nrndaspk.cpp:155
#define thread_t
Definition: nrndaspk.cpp:72
static int thread_ier
Definition: nrndaspk.cpp:80
N_Vector atolnvec_
Definition: cvodeobj.h:190
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
double t0_
Definition: cvodeobj.h:97
static void * msolve_thread(NrnThread *nt)
Definition: nrndaspk.cpp:122
size_t j
exp
Definition: extdef.h:3
void do_ode(NrnThread *)
Definition: occvode.cpp:863
N_Vector delta_
Definition: nrndaspk.h:28
#define nil
Definition: enter-scope.h:36
N_Vector yp_
Definition: nrndaspk.h:27
static bool eq(double x, double y, double e)
Definition: mymath.h:80
#define nlayer
Definition: section.h:187
static void * res_thread(NrnThread *nt)
Definition: nrndaspk.cpp:82
static int mfree(IDAMem)
Definition: nrndaspk.cpp:142
static double thread_cj
Definition: nrndaspk.cpp:79
double * param
Definition: section.h:189
double ** pvdot_
Definition: cvodeobj.h:65
Node ** nodelist
Definition: nrnoc_ml.h:5
double _t
Definition: multicore.h:59
#define nt_t
Definition: nrndaspk.cpp:46
static double eps(double x)
Definition: netcvode.h:128
int v_node_index
Definition: section.h:174
static void * daspk_gather_thread(NrnThread *nt)
Definition: nrndaspk.cpp:422
void play_continuous(double t)
Definition: occvode.cpp:1030
Definition: cvodeobj.h:75
void nrn_lhs(NrnThread *)
Definition: treeset.cpp:484
static int solve_state_
Definition: nrndaspk.cpp:24
void * _vcv
Definition: multicore.h:83
static int init_try_again_
Definition: nrndaspk.h:35
N_Vector y_
Definition: cvodeobj.h:189
#define i
Definition: md1redef.h:12
double tn_
Definition: cvodeobj.h:97
void nrndae_dkres(double *, double *, double *)
Definition: nrndae.cpp:92
double cj
Definition: multicore.h:61
double t_parasite_
Definition: nrndaspk.h:30
N_Vector ewtvec()
Definition: nrndaspk.cpp:675
char * spmat_
Definition: nrndaspk.h:32
static void * do_ode_thread(NrnThread *nt)
Definition: nrndaspk.cpp:201
N_Vector nvnew(long)
Definition: cvodeobj.cpp:798
static int msetup(IDAMem mem, N_Vector y, N_Vector ydot, N_Vector delta, N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
Definition: nrndaspk.cpp:113
int psol(double, double *, double *, double, NrnThread *)
Definition: nrndaspk.cpp:611
Daspk(Cvode *, int neq)
Definition: nrndaspk.cpp:144
double t
Definition: init.cpp:123
Definition: section.h:132
int eqn_index_
Definition: section.h:148
void statistics()
Definition: nrndaspk.cpp:374
static int msolve(IDAMem mem, N_Vector b, N_Vector ycur, N_Vector ypcur, N_Vector deltacur)
void nrndae_dkpsol(double)
void gather_ydot(N_Vector)
Definition: occvode.cpp:502
static int first_try_init_failures_
Definition: nrndaspk.h:36
Memb_list * ml
Definition: cvodeobj.h:27
return NULL
Definition: cabcode.cpp:461
N_Vector parasite_
Definition: nrndaspk.h:29
static void * daspk_scatter_thread(NrnThread *nt)
Definition: nrndaspk.cpp:394
static Cvode * thread_cv
Definition: nrndaspk.cpp:81
void info()
Definition: nrndaspk.cpp:191
static N_Vector nvec_y
Definition: nrndaspk.cpp:75
struct Extnode * extnode
Definition: section.h:160
int interpolate(double tout)
Definition: nrndaspk.cpp:355
#define NODEAREA(n)
Definition: section.h:115
void daspk_scatter_y(N_Vector)
Definition: nrndaspk.cpp:398