NEURON
nonlinz.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <stdio.h>
3 #include <math.h>
4 #include <InterViews/resource.h>
5 #include "nonlinz.h"
6 #include "nrnoc2iv.h"
7 #include "nrnmpi.h"
8 #include "cspmatrix.h"
9 #include "membfunc.h"
10 
11 extern "C" int structure_change_cnt;
12 extern void v_setup_vectors();
13 extern void nrn_rhs(NrnThread*);
14 extern int nrndae_extra_eqn_count();
17 extern spREAL *spGetElement(char*, int ,int);
18 
19 extern void pargap_jacobi_rhs(double*, double*);
20 extern void pargap_jacobi_setup(int mode);
21 
22 class NonLinImpRep {
23 public:
24  NonLinImpRep();
25  virtual ~NonLinImpRep();
26  void delta(double);
27  void didv();
28  void dids();
29  void dsdv();
30  void dsds();
31  int gapsolve();
32 
33  char* m_;
34  int scnt_; // structure_change
36  double** pv_;
37  double** pvdot_;
38  int* v_index_;
39  double* rv_;
40  double* jv_;
41  double** diag_;
42  double* deltavec_; // just like cvode.atol*cvode.atolscale for ode's
43  double delta_; // slightly more efficient and easier for v.
44  void current(int, Memb_list*, int);
45  void ode(int, Memb_list*);
46 
47  double omega_;
48  int iloc_; // current injection site of last solve
49  float* vsymtol_;
50  int maxiter_;
51 };
52 
54  rep_ = NULL;
55 }
57  if (rep_) {
58  delete rep_;
59  }
60 }
61 double NonLinImp::transfer_amp(int curloc, int vloc) {
62  if (nrnmpi_numprocs > 1 && nrnthread_v_transfer_ && curloc != rep_->iloc_) {
63  hoc_execerror("current injection site change not allowed with both gap junctions and nhost > 1", 0);
64  }
65  if (curloc != rep_->iloc_) {
66  solve(curloc);
67  }
68  double x = rep_->rv_[vloc];
69  double y = rep_->jv_[vloc];
70  return sqrt(x*x+y*y);
71 }
72 double NonLinImp::input_amp(int curloc) {
74  hoc_execerror("not allowed with both gap junctions and nhost>1", 0);
75  }
76  if (curloc != rep_->iloc_) {
77  solve(curloc);
78  }
79  if (curloc < 0) { return 0.0; }
80  double x = rep_->rv_[curloc];
81  double y = rep_->jv_[curloc];
82  return sqrt(x*x+y*y);
83 }
84 double NonLinImp::transfer_phase(int curloc, int vloc) {
85  if (nrnmpi_numprocs > 1 && nrnthread_v_transfer_ && curloc != rep_->iloc_) {
86  hoc_execerror("current injection site change not allowed with both gap junctions and nhost > 1", 0);
87  }
88  if (curloc != rep_->iloc_) {
89  solve(curloc);
90  }
91  double x = rep_->rv_[vloc];
92  double y = rep_->jv_[vloc];
93  return atan2(y, x);
94 }
95 double NonLinImp::input_phase(int curloc) {
97  hoc_execerror("not allowed with both gap junctions and nhost>1", 0);
98  }
99  if (curloc != rep_->iloc_) {
100  solve(curloc);
101  }
102  if (curloc < 0) { return 0.0; }
103  double x = rep_->rv_[curloc];
104  double y = rep_->jv_[curloc];
105  return atan2(y,x);
106 }
107 double NonLinImp::ratio_amp(int clmploc, int vloc) {
109  hoc_execerror("not allowed with both gap junctions and nhost>1", 0);
110  }
111  if (clmploc < 0) { return 0.0; }
112  if (clmploc != rep_->iloc_) {
113  solve(clmploc);
114  }
115  double ax,bx,cx, ay,by,cy,bb;
116  ax = rep_->rv_[vloc];
117  ay = rep_->jv_[vloc];
118  bx = rep_->rv_[clmploc];
119  by = rep_->jv_[clmploc];
120  bb = bx*bx + by*by;
121  cx = (ax*bx + ay*by)/bb;
122  cy = (ay*bx - ax*by)/bb;
123  return sqrt(cx*cx + cy*cy);
124 }
125 void NonLinImp::compute(double omega, double deltafac, int maxiter) {
126  v_setup_vectors();
128  if (rep_ && rep_->scnt_ != structure_change_cnt) {
129  delete rep_;
130  rep_ = NULL;
131  }
132  if (!rep_) {
133  rep_ = new NonLinImpRep();
134  }
135  rep_->maxiter_ = maxiter;
136  if (rep_->neq_ == 0) { return; }
137  if (nrndae_extra_eqn_count() > 0) {
138  hoc_execerror("Impedance calculation with LinearMechanism not implemented", 0);
139  }
141  hoc_execerror("Impedance calculation with extracellular not implemented", 0);
142  }
143 
144  rep_->omega_ = 1000.* omega;
145  rep_->delta(deltafac);
146  // fill matrix
147  cmplx_spClear(rep_->m_);
148  rep_->didv();
149  rep_->dsds();
150 #if 1 // when 0 equivalent to standard method
151  rep_->dids();
152  rep_->dsdv();
153 #endif
154 
155 // cmplx_spPrint(rep_->m_, 0, 1, 1);
156 // for (int i=0; i < rep_->neq_; ++i) {
157 // printf("i=%d %g %g\n", i, rep_->diag_[i][0], rep_->diag_[i][1]);
158 // }
159  int e = cmplx_spFactor(rep_->m_);
160  switch (e) {
161  case spZERO_DIAG:
162  hoc_execerror("cmplx_spFactor error:", "Zero Diagonal");
163  case spNO_MEMORY:
164  hoc_execerror("cmplx_spFactor error:", "No Memory");
165  case spSINGULAR:
166  hoc_execerror("cmplx_spFactor error:", "Singular");
167  }
168 
169  rep_->iloc_ = -2;
170 }
171 
172 int NonLinImp::solve(int curloc) {
173  int rval = 0;
174  NrnThread* _nt = nrn_threads;
175  if (!rep_) {
176  hoc_execerror("Must call Impedance.compute first", 0);
177  }
178  if (rep_->iloc_ != curloc) {
179  int i;
180  rep_->iloc_ = curloc;
181  for (i=0; i < rep_->neq_; ++i) {
182  rep_->rv_[i] = 0;
183  rep_->jv_[i] = 0;
184  }
185  if (curloc >= 0) {rep_->rv_[curloc] = 1.e2/NODEAREA(_nt->_v_node[curloc]);}
186  if (nrnthread_v_transfer_) {
187  rval = rep_->gapsolve();
188  }else{
189  assert(rep_->m_);
190  cmplx_spSolve(rep_->m_, rep_->rv_-1, rep_->rv_-1, rep_->jv_-1, rep_->jv_-1);
191  }
192  }
193  return rval;
194 }
195 
196 // too bad it is not easy to reuse the cvode/daspk structures. Most of
197 // mapping is already done there.
198 
200  int err;
201  int i, j, ieq, cnt;
202  NrnThread* _nt = nrn_threads;
203  maxiter_ = 500;
204  m_ = NULL;
205 
206  vsymtol_ = NULL;
207  Symbol* vsym = hoc_table_lookup("v", hoc_built_in_symlist);
208  if (vsym->extra) {
209  vsymtol_ = &vsym->extra->tolerance;
210  }
211  // the equation order is the same order as for the fixed step method
212  // for current balance. Remaining ode equation order is
213  // defined by the memb_list.
214 
215 
216  // how many equations
217  n_v_ = _nt->end;
218  n_ext_ = 0;
219  if (_nt->_ecell_memb_list) {
221  }
223  n_ode_ = 0;
224  for (NrnThreadMembList* tml = _nt->tml; tml; tml = tml->next) {
225  Memb_list* ml = tml->ml;
226  i = tml->index;
227  nrn_ode_count_t s = memb_func[i].ode_count;
228  if (s) {
229  cnt = (*s)(i);
230  n_ode_ += cnt * ml->nodecount;
231  }
232  }
233  neq_v_ = n_v_ + n_ext_ + n_lin_;
234  neq_ = neq_v_ + n_ode_;
235  if (neq_ == 0) { return; }
236  m_ = cmplx_spCreate(neq_, 1, &err);
237  assert(err == spOKAY);
238  pv_ = new double*[neq_];
239  pvdot_ = new double*[neq_];
240  v_index_ = new int[n_v_];
241  rv_ = new double[neq_+1];
242  rv_ += 1;
243  jv_ = new double[neq_+1];
244  jv_ += 1;
245  diag_ = new double*[neq_];
246  deltavec_ = new double[neq_];
247 
248  for (i=0; i < n_v_; ++i) {
249  // utilize nd->eqn_index in case of use_sparse13 later
250  Node* nd = _nt->_v_node[i];
251  pv_[i] = &NODEV(nd);
252  pvdot_[i] = nd->_rhs;
253  v_index_[i] = i+1;
254  }
255  for (i=0; i < n_v_; ++i) {
256  diag_[i] = cmplx_spGetElement(m_, v_index_[i], v_index_[i]);
257  }
258  for (i=neq_v_; i < neq_; ++i) {
259  diag_[i] = cmplx_spGetElement(m_, i+1, i+1);
260  }
262 }
263 
265  if (!m_) { return; }
266  cmplx_spDestroy(m_);
267  delete [] pv_;
268  delete [] pvdot_;
269  delete [] v_index_;
270  delete [] (rv_ - 1);
271  delete [] (jv_ - 1);
272  delete [] diag_;
273  delete [] deltavec_;
274 }
275 
276 void NonLinImpRep::delta(double deltafac){ // also defines pv_,pvdot_ map for ode
277  int i, j, nc, cnt, ieq;
278  NrnThread* nt = nrn_threads;
279  for (i=0; i < neq_; ++i) {
280  deltavec_[i] = deltafac; // all v's wasted but no matter.
281  }
282  ieq = neq_v_;
283  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next) {
284  Memb_list* ml = tml->ml;
285  i = tml->index;
286  nc = ml->nodecount;
287  nrn_ode_count_t s = memb_func[i].ode_count;
288  if (s && (cnt = (*s)(i)) > 0) {
289  nrn_ode_map_t m = memb_func[i].ode_map;
290  for (j=0; j < nc; ++j) {
291 (*m)(ieq, pv_ + ieq, pvdot_ + ieq, ml->data[j], ml->pdata[j], deltavec_ + ieq, i);
292  ieq += cnt;
293  }
294  }
295  }
296  delta_ = (vsymtol_ && (*vsymtol_ != 0.)) ? *vsymtol_ : 1.;
297  delta_ *= deltafac;
298 
299 }
300 
302  int i, j, ip;
303  Node* nd;
304  NrnThread* _nt = nrn_threads;
305  // d2v/dv2 terms
306  for (i=_nt->ncell; i < n_v_; ++i) {
307  nd = _nt->_v_node[i];
308  ip = _nt->_v_parent[i]->v_node_index;
309  double* a = cmplx_spGetElement(m_, v_index_[ip], v_index_[i]);
310  double* b = cmplx_spGetElement(m_, v_index_[i], v_index_[ip]);
311  *a += NODEA(nd);
312  *b += NODEB(nd);
313  *diag_[i] -= NODEB(nd);
314  *diag_[ip] -= NODEA(nd);
315  }
316  // jwC term
317  Memb_list* mlc = _nt->tml->ml;
318  int n = mlc->nodecount;
319  for (i=0; i < n; ++i) {
320  double* cd = mlc->data[i];
321  j = mlc->nodelist[i]->v_node_index;
322  diag_[v_index_[j]-1][1] += .001 * cd[0] * omega_;
323  }
324  // di/dv terms
325  // because there may be several point processes of the same type
326  // at the same location, we have to be careful to neither increment that
327  // nd->v multiple times nor count the rhs multiple times.
328  // So we can't take advantage of vectorized point processes.
329  // To avoid this we do each mechanism item separately.
330  // We assume there is no interaction between
331  // separate locations. Note that interactions such as gap junctions
332  // would not be handled in any case without computing a full jacobian.
333  // i.e. calling nrn_rhs varying every state one at a time (that would
334  // give the d2v/dv2 terms as well), but the expense is unwarranted.
335  for (NrnThreadMembList* tml = _nt->tml; tml; tml = tml->next) {
336  i = tml->index;
337  if (i == CAP) { continue; }
338  if (!memb_func[i].current) { continue; }
339  Memb_list* ml = tml->ml;
340  for (j = 0; j < ml->nodecount; ++j) { Node* nd = ml->nodelist[j];
341  double x1;
342  double x2;
343  // zero rhs
344  // save v
345  NODERHS(nd) = 0;
346  x1 = NODEV(nd);
347  // v+dv
348  NODEV(nd) += delta_;
349  current(i, ml, j);
350  // save rhs
351  // zero rhs
352  // restore v
353  x2 = NODERHS(nd);
354  NODERHS(nd) = 0;
355  NODEV(nd) = x1;
356  current(i, ml, j);
357  // conductance
358  // add to matrix
359  *diag_[v_index_[nd->v_node_index]-1] -= (x2 - NODERHS(nd))/delta_;
360  }
361  }
362 }
363 
365  // same strategy as didv but now the innermost loop is over
366  // every state but just for that compartment
367  // outer loop over ode mechanisms in same order as we created the pv_ map // so we can eas
368  int ieq, i, in, is, iis;
369  NrnThread* nt = nrn_threads;
370  ieq = neq_ - n_ode_;
371  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next) {
372  Memb_list* ml = tml->ml;
373  i = tml->index;
374  if (memb_func[i].ode_count && ml->nodecount) {
375  int nc = ml->nodecount;
376  nrn_ode_count_t s = memb_func[i].ode_count;
377  int cnt = (*s)(i);
378  if (memb_func[i].current) {
379  double* x1 = rv_; // use as temporary storage
380  double* x2 = jv_;
381  for (in = 0; in < ml->nodecount; ++in) { Node* nd = ml->nodelist[in];
382  // zero rhs
383  NODERHS(nd) = 0;
384  // compute rhs
385  current(i, ml, in);
386  // save rhs
387  x2[in] = NODERHS(nd);
388  // each state incremented separately and restored
389  for (iis = 0; iis < cnt; ++iis) {
390  is = ieq + in*cnt + iis;
391  // save s
392  x1[is] = *pv_[is];
393  // increment s and zero rhs
394  *pv_[is] += deltavec_[is];
395  NODERHS(nd) = 0;
396  current(i, ml, in);
397  *pv_[is] = x1[is]; // restore s
398  double g = (NODERHS(nd) - x2[in])/deltavec_[is];
399  if (g != 0.) {
400  double* elm = cmplx_spGetElement(m_, v_index_[nd->v_node_index], is+1);
401  elm[0] = -g;
402  }
403  }
404  // don't know if this is necessary but make sure last
405  // call with respect to original states
406  current(i, ml, in);
407  }
408  }
409  ieq += cnt*nc;
410  }
411  }
412 }
413 
415  int ieq, i, in, is, iis;
416  NrnThread* nt = nrn_threads;
417  ieq = neq_ - n_ode_;
418  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next) {
419  Memb_list* ml = tml->ml;
420  i = tml->index;
421  if (memb_func[i].ode_count && ml->nodecount) {
422  int nc = ml->nodecount;
423  nrn_ode_count_t s = memb_func[i].ode_count;
424  int cnt = (*s)(i);
425  if (memb_func[i].current) {
426  double* x1 = rv_; // use as temporary storage
427  double* x2 = jv_;
428  // zero rhs, save v
429  for (in = 0; in < ml->nodecount; ++in) { Node* nd = ml->nodelist[in];
430  for (is = ieq + in*cnt, iis = 0; iis < cnt; ++iis, ++is) {
431  *pvdot_[is] = 0.;
432  }
433  x1[in] = NODEV(nd);
434  }
435  // increment v only once in case there are multiple
436  // point processes at the same location
437  for (in = 0; in < ml->nodecount; ++in) { Node* nd = ml->nodelist[in];
438  if (x1[in] == NODEV(nd)) {
439  NODEV(nd) += delta_;
440  }
441  }
442  // compute rhs. this is the rhs(v+dv)
443  ode(i, ml);
444  // save rhs, restore v, and zero rhs
445  for (in = 0; in < ml->nodecount; ++in) { Node* nd = ml->nodelist[in];
446  for (is = ieq + in*cnt, iis = 0; iis < cnt; ++iis, ++is) {
447  x2[is] = *pvdot_[is];
448  *pvdot_[is] = 0;
449  }
450  NODEV(nd) = x1[in];
451  }
452  // compute the rhs(v)
453  ode(i, ml);
454  // fill the ds/dv elements
455  for (in = 0; in < ml->nodecount; ++in) { Node* nd = ml->nodelist[in];
456  for (is = ieq + in*cnt, iis = 0; iis < cnt; ++iis, ++is) {
457  double ds = (x2[is] - *pvdot_[is])/delta_;
458  if (ds != 0.) {
459  double* elm = cmplx_spGetElement(m_, is+1, v_index_[nd->v_node_index]);
460  elm[0] = -ds;
461  }
462  }
463  }
464  }
465  ieq += cnt*nc;
466  }
467  }
468 }
469 
471  int ieq, i, in, is, iis, ks, kks;
472  NrnThread* nt = nrn_threads;
473  // jw term
474  for (i = neq_v_; i < neq_; ++i) {
475  diag_[i][1] += omega_;
476  }
477  ieq = neq_v_;
478  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next) {
479  Memb_list* ml = tml->ml;
480  i = tml->index;
481  if (memb_func[i].ode_count && ml->nodecount) {
482  int nc = ml->nodecount;
483  nrn_ode_count_t s = memb_func[i].ode_count;
484  int cnt = (*s)(i);
485  double* x1 = rv_; // use as temporary storage
486  double* x2 = jv_;
487  // zero rhs, save s
488  for (in = 0; in < ml->nodecount; ++in) {
489  for (is = ieq + in*cnt, iis = 0; iis < cnt; ++iis, ++is) {
490  *pvdot_[is] = 0.;
491  x1[is] = *pv_[is];
492  }
493  }
494  // compute rhs. this is the rhs(s)
495  ode(i, ml);
496  // save rhs
497  for (in = 0; in < ml->nodecount; ++in) {
498  for (is = ieq + in*cnt, iis = 0; iis < cnt; ++iis, ++is) {
499  x2[is] = *pvdot_[is];
500  }
501  }
502  // iterate over the states
503  for (kks=0; kks < cnt; ++kks) {
504  // zero rhs, increment s(ks)
505  for (in = 0; in < ml->nodecount; ++in) {
506  ks = ieq + in*cnt + kks;
507  for (is = ieq + in*cnt, iis = 0; iis < cnt; ++iis, ++is) {
508  *pvdot_[is] = 0.;
509  }
510  *pv_[ks] += deltavec_[ks];
511  }
512  ode(i, ml);
513  // store element and restore s
514  // fill the ds/dv elements
515  for (in = 0; in < ml->nodecount; ++in) { Node* nd = ml->nodelist[in];
516  ks = ieq + in*cnt + kks;
517  for (is = ieq + in*cnt, iis = 0; iis < cnt; ++iis, ++is) {
518  double ds = ( *pvdot_[is] - x2[is])/deltavec_[is];
519  if (ds != 0.) {
520  double* elm = cmplx_spGetElement(m_, is+1, ks+1);
521  elm[0] = -ds;
522  }
523  *pv_[ks] = x1[ks];
524  }
525  }
526  // perhaps not necessary but ensures the last computation is with
527  // the base states.
528  ode(i, ml);
529  }
530  ieq += cnt*nc;
531  }
532  }
533 }
534 
535 void NonLinImpRep::current(int im, Memb_list* ml, int in) { // assume there is in fact a current
536  // method
537  Pvmi s = memb_func[im].current;
538  // fake a 1 element memb_list
539  Memb_list mfake;
540 #if CACHEVEC != 0
541  mfake.nodeindices = ml->nodeindices + in;
542 #endif
543  mfake.nodelist = ml->nodelist + in;
544  mfake.data = ml->data + in;
545  mfake.pdata = ml->pdata + in;
546  mfake.prop = ml->prop ? ml->prop + in : nullptr;
547  mfake.nodecount = 1;
548  mfake._thread = ml->_thread;
549  (*s)(nrn_threads, &mfake, im);
550 }
551 
552 void NonLinImpRep::ode(int im, Memb_list* ml) { // assume there is in fact an ode method
553  Pvmi s = memb_func[im].ode_spec;
554  (*s)(nrn_threads, ml, im);
555 }
556 
558  // On entry, rv_ and jv_ contain the complex b for A*x = b.
559  // On return rv_ and jv_ contain complex solution, x.
560  // m_ is the factored matrix for the trees without gap junctions
561  // Jacobi method (easy for parallel)
562  // A = D + R
563  // D*x_(k+1) = (b - R*x_(k))
564  // D is m_ (and includes the gap junction contribution to the diagonal)
565  // R is the off diagonal matrix of the gaps.
566 
567  // one and only one stimulus
568 #if NRNMPI
569  if (nrnmpi_numprocs > 1 && nrnmpi_int_sum_reduce(iloc_ >= 0 ? 1 : 0) != 1) {
570  if (nrnmpi_myid == 0) {
571  hoc_execerror("there can be one and only one impedance stimulus", 0);
572  }
573  }
574 #endif
575 
577 
578  double *rx, *jx, *rx1, *jx1, *rb, *jb;
579  if (neq_) {
580  rx = new double[neq_];
581  jx = new double[neq_];
582  rx1 = new double[neq_];
583  jx1 = new double[neq_];
584  rb = new double[neq_];
585  jb = new double[neq_];
586  }
587 
588  // initialize for first iteration
589  for (int i=0; i < neq_; ++i) {
590  rx[i] = jx[i] = 0.0;
591  rb[i] = rv_[i];
592  jb[i] = jv_[i];
593  }
594 
595  // iterate till change in x is small
596  double tol = 1e-9;
597  double delta;
598 
599  int success = 0;
600  int iter;
601 
602  for (iter = 1; iter <= maxiter_; ++iter) {
603  if (neq_) {
604  cmplx_spSolve(m_, rb-1, rx1-1, jb-1, jx1-1);
605  }
606 
607  // if any change in x > tol, then do another iteration.
608  success = 1;
609  delta = 0.0;
610  for (int i=0; i < neq_; ++i) {
611  double err = fabs(rx1[i] - rx[i]) + fabs(jx1[i] - jx[i]);
612  if (err > tol) {
613  success = 0;
614  }
615  if (delta < err) {
616  delta = err;
617  }
618  }
619 #if NRNMPI
620  if (nrnmpi_numprocs > 1) {
621  success = nrnmpi_int_sum_reduce(success) / nrnmpi_numprocs;
622  }
623 #endif
624  if (success) {
625  for (int i=0; i < neq_; ++i) {
626  rv_[i] = rx1[i];
627  jv_[i] = jx1[i];
628  }
629  break;
630  }
631 
632  // setup for next iteration
633  for (int i=0; i < neq_; ++i) {
634  rx[i] = rx1[i];
635  jx[i] = jx1[i];
636  rb[i] = rv_[i];
637  jb[i] = jv_[i];
638  }
639  pargap_jacobi_rhs(rb, rx);
640  pargap_jacobi_rhs(jb, jx);
641  }
642 
643  pargap_jacobi_setup(1); // tear down
644 
645  if (neq_) {
646  delete [] rx;
647  delete [] jx;
648  delete [] rx1;
649  delete [] jx1;
650  delete [] rb;
651  delete [] jb;
652  }
653 
654  if (!success) {
655  char buf[256];
656  sprintf(buf, "Impedance calculation did not converge in %d iterations. Max state change on last iteration was %g (Iterations stop at %g)\n",
657  maxiter_, delta, tol);
658  execerror(buf, 0);
659  }
660  return iter;
661 }
Definition: hocdec.h:84
#define assert(ex)
Definition: hocassrt.h:26
void delta(double)
Definition: nonlinz.cpp:276
char * m_
Definition: nonlinz.cpp:33
float tolerance
Definition: hocdec.h:113
#define NODEV(n)
Definition: section.h:114
struct NrnThreadMembList * next
Definition: multicore.h:34
double * jv_
Definition: nonlinz.cpp:40
void v_setup_vectors()
Definition: treeset.cpp:1623
void pargap_jacobi_rhs(double *, double *)
Definition: partrans.cpp:951
#define g
Definition: passive0.cpp:23
void
Node ** _v_parent
Definition: multicore.h:78
Pvmi current
Definition: membfunc.h:33
void didv()
Definition: nonlinz.cpp:301
Represent main neuron object computed by single thread.
Definition: multicore.h:58
int solve(int curloc)
Definition: nonlinz.cpp:172
#define spSINGULAR
Definition: spmatrix.h:100
Memb_func * memb_func
Definition: init.cpp:161
nd
Definition: treeset.cpp:893
static int ode_count(int type)
Definition: kschan.cpp:114
#define spOKAY
Definition: spmatrix.h:97
double transfer_amp(int curloc, int vloc)
Definition: nonlinz.cpp:61
double ** data
Definition: nrnoc_ml.h:14
virtual ~NonLinImp()
Definition: nonlinz.cpp:56
void ode(int, Memb_list *)
Definition: nonlinz.cpp:552
void nrn_rhs(NrnThread *)
Definition: treeset.cpp:355
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
Prop ** prop
Definition: nrnoc_ml.h:16
#define e
Definition: passive0.cpp:24
Datum * _thread
Definition: nrnoc_ml.h:17
int * v_index_
Definition: nonlinz.cpp:38
float * vsymtol_
Definition: nonlinz.cpp:49
int ncell
Definition: multicore.h:64
void solve(void)
Definition: nonlin.cpp:287
Node ** _v_node
Definition: multicore.h:77
atan2
Definition: extdef.h:3
int const size_t const size_t n
Definition: nrngsl.h:12
Memb_list * ml
Definition: multicore.h:35
Memb_list * _ecell_memb_list
Definition: multicore.h:80
int nodecount
Definition: nrnoc_ml.h:18
int nrnmpi_numprocs
_CONST char * s
Definition: system.cpp:74
NrnThread * nrn_threads
Definition: multicore.cpp:45
int gapsolve()
Definition: nonlinz.cpp:557
#define NODEA(n)
Definition: section.h:123
virtual ~NonLinImpRep()
Definition: nonlinz.cpp:264
void(* Pvmi)(struct NrnThread *, Memb_list *, int)
Definition: membfunc.h:18
void dsds()
Definition: nonlinz.cpp:470
int maxiter_
Definition: nonlinz.cpp:50
double * deltavec_
Definition: nonlinz.cpp:42
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
#define cnt
Definition: spt2queue.cpp:19
NonLinImp()
Definition: nonlinz.cpp:53
void dsdv()
Definition: nonlinz.cpp:414
static Symbol * vsym
Definition: occvode.cpp:49
size_t j
Datum ** pdata
Definition: nrnoc_ml.h:15
Definition: model.h:57
void pargap_jacobi_setup(int mode)
Definition: partrans.cpp:873
double * rv_
Definition: nonlinz.cpp:39
HocSymExtension * extra
Definition: hocdec.h:159
Symlist * hoc_built_in_symlist
Definition: symbol.cpp:39
double delta_
Definition: nonlinz.cpp:43
#define NODEB(n)
Definition: section.h:124
#define spREAL
Definition: spmatrix.h:127
#define CAP
Definition: membfunc.h:64
void dids()
Definition: nonlinz.cpp:364
void compute(double omega, double deltafac, int maxiter)
Definition: nonlinz.cpp:125
#define nlayer
Definition: section.h:187
spREAL * spGetElement(char *, int, int)
Definition: spbuild.c:195
int end
Definition: multicore.h:65
double ratio_amp(int clmploc, int vloc)
Definition: nonlinz.cpp:107
double input_amp(int curloc)
Definition: nonlinz.cpp:72
#define NODERHS(n)
Definition: section.h:104
double ** pv_
Definition: nonlinz.cpp:36
void current(int, Memb_list *, int)
Definition: nonlinz.cpp:535
Node ** nodelist
Definition: nrnoc_ml.h:5
double ** diag_
Definition: nonlinz.cpp:41
int v_node_index
Definition: section.h:174
sqrt
Definition: extdef.h:3
int nrnmpi_myid
int structure_change_cnt
Definition: nonlinz.cpp:11
Symbol * hoc_table_lookup(const char *, Symlist *)
Definition: symbol.cpp:60
#define i
Definition: md1redef.h:12
double ** pvdot_
Definition: nonlinz.cpp:37
void(* nrnthread_v_transfer_)(NrnThread *)
Definition: fadvance.cpp:148
#define execerror
Definition: section.h:36
char buf[512]
Definition: init.cpp:13
fabs
Definition: extdef.h:3
Definition: lineq.h:16
double * _rhs
Definition: section.h:145
NrnThreadMembList * tml
Definition: multicore.h:62
Definition: section.h:132
void(* nrn_ode_map_t)(int, double **, double **, double *, Datum *, double *, int)
Definition: membfunc.h:21
#define spNO_MEMORY
Definition: spmatrix.h:101
double input_phase(int curloc)
Definition: nonlinz.cpp:95
return NULL
Definition: cabcode.cpp:461
int(* nrn_ode_count_t)(int)
Definition: membfunc.h:20
#define spZERO_DIAG
Definition: spmatrix.h:99
double transfer_phase(int curloc, int vloc)
Definition: nonlinz.cpp:84
#define NODEAREA(n)
Definition: section.h:115
double omega_
Definition: nonlinz.cpp:47
int nrndae_extra_eqn_count()
Definition: nrndae.cpp:36
static double deltafac(void *v)
Definition: impedanc.cpp:132