NEURON
noccout.cpp
Go to the documentation of this file.
1 #include <../../nmodlconf.h>
2 
3 /* print the .c file from the lists */
4 #include "modl.h"
5 #include "parse1.hpp"
6 #include "symbol.h"
7 
8 #define CACHEVEC 1
9 
10 extern char* nmodl_version_;
11 
12 #define P(arg) fputs(arg, fcout)
14 /* firstlist gets statements that must go before anything else */
15 
16 #if NMODL
17 List *nrnstate;
18 extern List *currents, *set_ion_variables(int), *get_ion_variables(int);
19 extern List *begin_dion_stmt(), *end_dion_stmt(char*);
20 extern List* conductance_;
21 static void conductance_cout();
22 #endif
23 
24 extern Symbol *indepsym;
25 extern List *indeplist;
26 extern List *match_bound;
27 extern List *defs_list;
28 extern char *saveindep;
29 char *modelline;
30 extern int brkpnt_exists;
31 extern int artificial_cell;
32 extern int net_receive_;
33 extern int debugging_;
34 extern int point_process;
35 extern int dtsav_for_nrn_state;
36 
37 #if CVODE
38 extern Symbol* cvode_nrn_cur_solve_;
39 extern Symbol* cvode_nrn_current_solve_;
40 extern List* state_discon_list_;
41 #endif
42 
43 /* VECTORIZE has not been optional for years. We leave the define there but */
44 /* we no longer update the #else clauses. */
45 #if VECTORIZE
46 extern int vectorize;
47 static List *vectorize_replacements; /* pairs of item pointer, strings */
48 extern char* cray_pragma();
49 extern int electrode_current; /* 1 means we should watch out for extracellular
50  and handle it correctly */
51 #endif
52 
53 #if __TURBOC__ || SYSV || VMS
54 #define index strchr
55 #endif
56 
57 static void initstates();
58 static void funcdec();
59 
60 static void ext_vdef() {
61  if (artificial_cell) { return; }
62  if (electrode_current) {
63  P("#if EXTRACELLULAR\n");
64  P(" _nd = _ml->_nodelist[_iml];\n");
65  P(" if (_nd->_extnode) {\n");
66  P(" _v = NODEV(_nd) +_nd->_extnode->_v[0];\n");
67  P(" }else\n");
68  P("#endif\n");
69  P(" {\n");
70 #if CACHEVEC == 0
71  P(" _v = NODEV(_nd);\n");
72 #else
73  P("#if CACHEVEC\n");
74  P(" if (use_cachevec) {\n");
75  P(" _v = VEC_V(_ni[_iml]);\n");
76  P(" }else\n");
77  P("#endif\n");
78  P(" {\n");
79  P(" _nd = _ml->_nodelist[_iml];\n");
80  P(" _v = NODEV(_nd);\n");
81  P(" }\n");
82 #endif
83 
84  P(" }\n");
85  }else{
86 #if CACHEVEC == 0
87  P(" _nd = _ml->_nodelist[_iml];\n");
88  P(" _v = NODEV(_nd);\n");
89 #else
90  P("#if CACHEVEC\n");
91  P(" if (use_cachevec) {\n");
92  P(" _v = VEC_V(_ni[_iml]);\n");
93  P(" }else\n");
94  P("#endif\n");
95  P(" {\n");
96  P(" _nd = _ml->_nodelist[_iml];\n");
97  P(" _v = NODEV(_nd);\n");
98  P(" }\n");
99 #endif
100  }
101 }
102 
103 
104 /* when vectorize = 0 */
105 void c_out()
106 {
107 #if NMODL
108  Item *q;
109 #endif
110 
111  Fprintf(fcout, "/* Created by Language version: %s */\n", nmodl_version_);
112  Fflush(fcout);
113 
114 #if VECTORIZE
115  if (vectorize) {
117  kin_vect2(); /* heh, heh.. bet you can't guess what this is */
118  c_out_vectorize();
119  return;
120  }
121 #endif
122 #if VECTORIZE
123  P("/* NOT VECTORIZED */\n#define NRN_VECTORIZED 0\n");
124 #endif
125  Fflush(fcout);
126  /* things which must go first and most declarations */
127 #if SIMSYS
128  P("#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include \"mathlib.h\"\n");
129  P("#include \"common.h\"\n#include \"softbus.h\"\n");
130  P("#include \"sbtypes.h\"\n#include \"Solver.h\"\n");
131 #else
132  P("#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include \"scoplib.h\"\n");
133  P("#undef PI\n");
134  P("#define nil 0\n");
135 P("#include \"md1redef.h\"\n");
136 P("#include \"section.h\"\n");
137 P("#include \"nrniv_mf.h\"\n");
138 P("#include \"md2redef.h\"\n");
139 
140 #endif
141  printlist(defs_list);
142  printlist(firstlist);
143  P("static int _reset;\n");
144 #if NMODL
145  P("static ");
146 #endif
147  if (modelline) {
148  Fprintf(fcout, "char *modelname = \"%s\";\n\n", modelline);
149  } else {
150  Fprintf(fcout, "char *modelname = \"\";\n\n");
151  }
152  Fflush(fcout); /* on certain internal errors partial output
153  * is helpful */
154  P("static int error;\n");
155 #if NMODL
156  P("static ");
157 #endif
158  P("int _ninits = 0;\n");
159  P("static int _match_recurse=1;\n");
160 #if NMODL
161  P("static void ");
162 #endif
163  P("_modl_cleanup(){ _match_recurse=1;}\n");
164  /*
165  * many machinations are required to make the infinite number of
166  * definitions involving _p in defs.h to be invisible to the user
167  */
168  /*
169  * This one allows scop variables in functions which do not have the
170  * p array as an argument
171  */
172 #if SIMSYS || HMODL || NMODL
173 #else
174  P("static double *_p;\n\n");
175 #endif
176  funcdec();
177  Fflush(fcout);
178 
179  /*
180  * translations of named blocks into functions, procedures, etc. Also
181  * some special declarations used by some blocks
182  */
183  printlist(procfunc);
184  Fflush(fcout);
185 
186  /* Initialization function must always be present */
187 #if NMODL
188  P("\nstatic void initmodel() {\n int _i; double _save;");
189 #endif
190 #if SIMSYS || HMODL
191  P("\ninitmodel() {\n int _i; double _save;");
192 #endif
193 #if (!(SIMSYS || HMODL || NMODL))
194  P("\ninitmodel(_pp) double _pp[]; {\n int _i; double _save; _p = _pp;");
195 #endif
196 #if !NMODL
197  P("_initlists();\n");
198 #endif
199  P("_ninits++;\n");
200  P(saveindep); /*see solve.c; blank if not a time dependent process*/
201  P("{\n");
202  initstates();
203  printlist(initfunc);
204  if (match_bound) {
205  P("\n_init_match(_save);");
206  }
207  P("\n}\n}\n");
208  Fflush(fcout);
209 
210 #if NMODL
211  /* generation of initmodel interface */
212 #if VECTORIZE
213  P("\nstatic void nrn_init(NrnThread* _nt, _Memb_list* _ml, int _type){\n");
214  P("Node *_nd; double _v; int* _ni; int _iml, _cntml;\n");
215  P("#if CACHEVEC\n");
216  P(" _ni = _ml->_nodeindices;\n");
217  P("#endif\n");
218  P("_cntml = _ml->_nodecount;\n");
219  P("for (_iml = 0; _iml < _cntml; ++_iml) {\n");
220  P(" _p = _ml->_data[_iml]; _ppvar = _ml->_pdata[_iml];\n");
221 #else
222  P("\nstatic nrn_init(_prop, _v) Prop *_prop; double _v; {\n");
223  P(" _p = _prop->param; _ppvar = _prop->dparam;\n");
224 #endif
225  if (debugging_ && net_receive_) {
226  P(" _tsav = -1e20;\n");
227  }
228  if (!artificial_cell) {ext_vdef();}
229  if (!artificial_cell) {P(" v = _v;\n");}
231  P(" initmodel();\n");
233 #if VECTORIZE
234  P("}}\n");
235 #else
236  P("}\n");
237 #endif
238 
239  /* standard modl EQUATION without solve computes current */
240  P("\nstatic double _nrn_current(double _v){double _current=0.;v=_v;");
241 #if CVODE
242  if (cvode_nrn_current_solve_) {
243  fprintf(fcout, "if (cvode_active_) { %s(); }\n", cvode_nrn_current_solve_->name);
244  }
245 #endif
246  P("{");
247  if (currents->next != currents) {
248  printlist(modelfunc);
249  }
250  ITERATE(q, currents) {
251  Sprintf(buf, " _current += %s;\n", SYM(q)->name);
252  P(buf);
253  }
254  P("\n} return _current;\n}\n");
255 
256  /* For the classic BREAKPOINT block, the neuron current also has to compute the dcurrent/dv as well
257  as make sure all currents accumulated properly (currents list) */
258 
259  if (brkpnt_exists) {
260  P("\nstatic void nrn_cur(NrnThread* _nt, _Memb_list* _ml, int _type){\n");
261  P("Node *_nd; int* _ni; double _rhs, _v; int _iml, _cntml;\n");
262  P("#if CACHEVEC\n");
263  P(" _ni = _ml->_nodeindices;\n");
264  P("#endif\n");
265  P("_cntml = _ml->_nodecount;\n");
266  P("for (_iml = 0; _iml < _cntml; ++_iml) {\n");
267  P(" _p = _ml->_data[_iml]; _ppvar = _ml->_pdata[_iml];\n");
268  ext_vdef();
269  if (currents->next != currents) {
271 #if CVODE
272  cvode_rw_cur(buf);
273  P(buf);
274  }
275  if (cvode_nrn_cur_solve_) {
276  fprintf(fcout, "if (cvode_active_) { %s(); }\n", cvode_nrn_cur_solve_->name);
277  }
278  if (currents->next != currents) {
279 #endif
280  P(" _g = _nrn_current(_v + .001);\n");
282  if (state_discon_list_) {
283  P(" state_discon_flag_ = 1; _rhs = _nrn_current(_v); state_discon_flag_ = 0;\n");
284  }else{
285  P(" _rhs = _nrn_current(_v);\n");
286  }
287  printlist(end_dion_stmt(".001"));
288  P(" _g = (_g - _rhs)/.001;\n");
289  /* set the ion variable values */
291  if (point_process) {
292  P(" _g *= 1.e2/(_nd_area);\n");
293  P(" _rhs *= 1.e2/(_nd_area);\n");
294  }
295  if (electrode_current) {
296 #if CACHEVEC == 0
297  P(" NODERHS(_nd) += _rhs;\n");
298 #else
299  P("#if CACHEVEC\n");
300  P(" if (use_cachevec) {\n");
301  P(" VEC_RHS(_ni[_iml]) += _rhs;\n");
302  P(" }else\n");
303  P("#endif\n");
304  P(" {\n");
305  P(" NODERHS(_nd) += _rhs;\n");
306  P(" }\n");
307  P(" if (_nt->_nrn_fast_imem) { _nt->_nrn_fast_imem->_nrn_sav_rhs[_ni[_iml]] += _rhs; }\n");
308 #endif
309  P("#if EXTRACELLULAR\n");
310  P(" if (_nd->_extnode) {\n");
311  P(" *_nd->_extnode->_rhs[0] += _rhs;\n");
312  P(" }\n");
313  P("#endif\n");
314  }else{
315 #if CACHEVEC == 0
316  P(" NODERHS(_nd) -= _rhs;\n");
317 #else
318  P("#if CACHEVEC\n");
319  P(" if (use_cachevec) {\n");
320  P(" VEC_RHS(_ni[_iml]) -= _rhs;\n");
321  P(" }else\n");
322  P("#endif\n");
323  P(" {\n");
324  P(" NODERHS(_nd) -= _rhs;\n");
325  P(" }\n");
326 #endif
327  }
328  }
329  P(" \n}}\n");
330 
331  /* for the classic breakpoint block, nrn_cur computed the conductance, _g,
332  and now the jacobian calculation merely returns that */
333  P("\nstatic void nrn_jacob(NrnThread* _nt, _Memb_list* _ml, int _type){\n");
334  P("Node *_nd; int* _ni; int _iml, _cntml;\n");
335  P("#if CACHEVEC\n");
336  P(" _ni = _ml->_nodeindices;\n");
337  P("#endif\n");
338  P("_cntml = _ml->_nodecount;\n");
339  P("for (_iml = 0; _iml < _cntml; ++_iml) {\n");
340  P(" _p = _ml->_data[_iml];\n");
341  if (electrode_current) {
342  P(" _nd = _ml->_nodelist[_iml];\n");
343 #if CACHEVEC == 0
344  P(" NODED(_nd) -= _g;\n");
345 #else
346  P("#if CACHEVEC\n");
347  P(" if (use_cachevec) {\n");
348  P(" VEC_D(_ni[_iml]) -= _g;\n");
349  P(" }else\n");
350  P("#endif\n");
351  P(" {\n");
352  P(" NODED(_nd) -= _g;\n");
353  P(" }\n");
354  P(" if (_nt->_nrn_fast_imem) { _nt->_nrn_fast_imem->_nrn_sav_d[_ni[_iml]] -= _g; }\n");
355 #endif
356  P("#if EXTRACELLULAR\n");
357  P(" if (_nd->_extnode) {\n");
358  P(" *_nd->_extnode->_d[0] += _g;\n");
359  P(" }\n");
360  P("#endif\n");
361  }else{
362 #if CACHEVEC == 0
363  P(" NODED(_nd) += _g;\n");
364 #else
365  P("#if CACHEVEC\n");
366  P(" if (use_cachevec) {\n");
367  P(" VEC_D(_ni[_iml]) += _g;\n");
368  P(" }else\n");
369  P("#endif\n");
370  P(" {\n");
371  P(" _nd = _ml->_nodelist[_iml];\n");
372  P(" NODED(_nd) += _g;\n");
373  P(" }\n");
374 #endif
375  }
376  P(" \n}}\n");
377  }
378 
379  /* nrnstate list contains the EQUATION solve statement so this
380  advances states by dt */
381 #if VECTORIZE
382  P("\nstatic void nrn_state(NrnThread* _nt, _Memb_list* _ml, int _type){\n");
383 #else
384  P("\nstatic nrn_state(_prop, _v) Prop *_prop; double _v; {\n");
385 #endif
386  if (nrnstate || currents->next == currents) {
387 #if VECTORIZE
388  P("Node *_nd; double _v = 0.0; int* _ni; int _iml, _cntml;\n");
389  if (dtsav_for_nrn_state && nrnstate) {
390  P("double _dtsav = dt;\n"
391  "if (secondorder) { dt *= 0.5; }\n");
392  }
393  P("#if CACHEVEC\n");
394  P(" _ni = _ml->_nodeindices;\n");
395  P("#endif\n");
396  P("_cntml = _ml->_nodecount;\n");
397  P("for (_iml = 0; _iml < _cntml; ++_iml) {\n");
398  P(" _p = _ml->_data[_iml]; _ppvar = _ml->_pdata[_iml];\n");
399  P(" _nd = _ml->_nodelist[_iml];\n");
400  ext_vdef();
401 #else
402  P(" _p = _prop->param; _ppvar = _prop->dparam;\n");
403 #endif
404  P(" v=_v;\n{\n");
406  if (nrnstate) {
407  printlist(nrnstate);
408  }
409  if (currents->next == currents) {
410  printlist(modelfunc);
411  }
413 #if VECTORIZE
414  P("}}\n");
415 #else
416  P("}\n");
417 #endif
418  if (dtsav_for_nrn_state && nrnstate) {
419  P(" dt = _dtsav;");
420  }
421  }
422  P("\n}\n");
423 #else
424  /* Model function must always be present */
425 #if SIMSYS
426  P("\nmodel() {\n");
427  P("double _break, _save;\n{\n");
428 #else
429  P("\nmodel(_pp, _indepindex) double _pp[]; int _indepindex; {\n");
430  P("double _break, _save;");
431 #if HMODL
432  P("\n{\n");
433 #else
434  P("_p = _pp;\n{\n");
435 #endif
436 #endif
437  printlist(modelfunc);
438  P("\n}\n}\n");
439  Fflush(fcout);
440 #endif
441 
442 #if NMODL
443  P("\nstatic void terminal(){}\n");
444 #else
445  /* Terminal function must always be present */
446 #if SIMSYS || HMODL
447  P("\nterminal() {");
448  P("\n{\n");
449 #else
450  P("\nterminal(_pp) double _pp[];{");
451  P("_p = _pp;\n{\n");
452 #endif
453  printlist(termfunc);
454  P("\n}\n}\n");
455  Fflush(fcout);
456 #endif
457 
458  /* initlists() is called once to setup slist and dlist pointers */
459 #if NMODL || SIMSYS || HMODL
460  P("\nstatic void _initlists() {\n");
461 #else
462  P("\n_initlists() {\n");
463 #endif
464  P(" int _i; static int _first = 1;\n");
465  P(" if (!_first) return;\n");
466  printlist(initlist);
467  P("_first = 0;\n}\n");
468 }
469 
470 /*
471  * One of the things initmodel() must do is initialize all states to the
472  * value of state0. This generated code goes before any explicit initialize
473  * code written by the user.
474  */
475 static void initstates()
476 {
477  int i;
478  Item *qs;
479  Symbol *s;
480 
481 
482  SYMITER_STAT {
483 #if NMODL
484  /* ioni and iono should not have initialization lines */
485 #define IONCONC 010000
486  if (s->nrntype & IONCONC) {
487  continue;
488  }
489 #endif
490  Sprintf(buf, "%s0", s->name);
491  if (lookup(buf)) { /* if no constant associated
492  * with a state such as the
493  * ones automattically
494  * generated by SENS then
495  * there is no initialization
496  * line */
497  if (s->subtype & ARRAY) {
498  Fprintf(fcout,
499  " for (_i=0; _i<%d; _i++) %s[_i] = %s0;\n",
500  s->araydim, s->name, s->name);
501  } else {
502  Fprintf(fcout, " %s = %s0;\n",
503  s->name, s->name);
504  }
505  }
506  }
507 }
508 
509 /*
510  * here is the only place as of 18-apr-89 where we don't explicitly know the
511  * type of a list element
512  */
513 
514 static int newline, indent;
515 
516 void printitem(Item* q) {
517  if (q->itemtype == SYMBOL) {
518  if (SYM(q)->type == SPECIAL) {
519  switch (SYM(q)->subtype) {
520 
521  case SEMI:
522  newline = 1;
523  break;
524  case BEGINBLK:
525  newline = 1;
526  indent++;
527  break;
528  case ENDBLK:
529  newline = 1;
530  indent--;
531  break;
532  }
533  }
534  Fprintf(fcout, " %s", SYM(q)->name);
535  } else if (q->itemtype == VERBATIM) {
536  verbatim_adjust(STR(q));
537  } else if (q->itemtype == ITEM) {
538  printitem(ITM(q));
539  }else {
540  Fprintf(fcout, " %s", STR(q));
541  }
542 }
543 
545  if (q->itemtype == SYMBOL) {
546  printf("SYM %s\n", SYM(q)->name);
547  } else if (q->itemtype == VERBATIM) {
548  printf("VERB %s\n",STR(q));
549  } else if (q->itemtype == ITEM) {
550  printf("ITM ");
551  debugprintitem(ITM(q));
552  }else {
553  printf("STR %s\n", STR(q));
554  }
555 }
556 
557 /* does not include q2 */
558 char* items_as_string(Item* q1, Item* q2) {
559  Item* q;
560  buf[0] = '\0';
561  for (q = q1; q != q2; q = q->next) {
562  if (buf[0] != '\0') {
563  strcat(buf, " ");
564  }
565  if (q->itemtype == SYMBOL) {
566  strcat(buf, SYM(q)->name);
567  }else if (q->itemtype == STRING) {
568  strcat(buf, STR(q));
569  }else{
570  assert(0);
571  }
572  }
573  return strdup(buf);
574 }
575 
577 {
578  Item *q;
579  int i;
580  newline = 0, indent = 0;
581  /*
582  * most of this is merely to decide where newlines and indentation
583  * goes so that the .c file can be read if something goes wrong
584  */
585  if (!s) {
586  return;
587  }
588  ITERATE(q, s) {
589  printitem(q);
590  if (newline) {
591  newline = 0;
592  Fprintf(fcout, "\n");
593  for (i = 0; i < indent; i++) {
594  Fprintf(fcout, " ");
595  }
596  }
597  }
598 }
599 
600 static void funcdec()
601 {
602  int i;
603  Symbol *s;
604  List *qs;
605  int j, narg, more;
606 
607  SYMITER(NAME) {
608  more = 0;
609  /*EMPTY*/ /*maybe*/
610  if (s->subtype & FUNCT) {
611 #define GLOBFUNCT 1
612 #if GLOBFUNCT && NMODL
613 #else
614  Fprintf(fcout, "static double %s(", s->name);
615  more = 1;
616 #endif
617  }
618  if (s->subtype & PROCED) {
619  Fprintf(fcout, "static int %s(", s->name);
620  more = 1;
621  }
622  if (more) {
623  narg = s->varnum;
624 if (vectorize) {
625  if (narg) {
626  Fprintf(fcout, "_threadargsprotocomma_ ");
627  }else{
628  Fprintf(fcout, "_threadargsproto_");
629  }
630 }
631  /*loop over argcount and add ,double */
632  if (narg > 0) { Fprintf(fcout, "double"); }
633  for (j=1; j < narg; ++j) {
634  Fprintf(fcout, ", double");
635  }
636  Fprintf(fcout,");\n");
637  }
638  }
639 }
640 
641 #if VECTORIZE
642 /* when vectorize = 1 */
643 void c_out_vectorize()
644 {
645  Item *q;
646 
647  /* things which must go first and most declarations */
648  P("/* VECTORIZED */\n#define NRN_VECTORIZED 1\n");
649  P("#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include \"scoplib.h\"\n");
650  P("#undef PI\n");
651  P("#define nil 0\n");
652 P("#include \"md1redef.h\"\n");
653 P("#include \"section.h\"\n");
654 P("#include \"nrniv_mf.h\"\n");
655 P("#include \"md2redef.h\"\n");
656  printlist(defs_list);
657  printlist(firstlist);
658  P("static int _reset;\n");
659  if (modelline) {
660  Fprintf(fcout, "static char *modelname = \"%s\";\n\n", modelline);
661  } else {
662  Fprintf(fcout, "static char *modelname = \"\";\n\n");
663  }
664  Fflush(fcout); /* on certain internal errors partial output
665  * is helpful */
666  P("static int error;\n");
667  P("static int _ninits = 0;\n");
668  P("static int _match_recurse=1;\n");
669  P("static void _modl_cleanup(){ _match_recurse=1;}\n");
670 
671  funcdec();
672  Fflush(fcout);
673 
674  /*
675  * translations of named blocks into functions, procedures, etc. Also
676  * some special declarations used by some blocks
677  */
678  printlist(procfunc);
679  Fflush(fcout);
680 
681  /* Initialization function must always be present */
682 
683  P("\nstatic void initmodel(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt) {\n int _i; double _save;");
684  P("{\n");
685  initstates();
686  printlist(initfunc);
687  if (match_bound) {
688  assert(!vectorize);
689  P("\n_init_match(_save);");
690  }
691  P("\n}\n}\n");
692  Fflush(fcout);
693 
694  /* generation of initmodel interface */
695  P("\nstatic void nrn_init(NrnThread* _nt, _Memb_list* _ml, int _type){\n");
696  P("double* _p; Datum* _ppvar; Datum* _thread;\n");
697  P("Node *_nd; double _v; int* _ni; int _iml, _cntml;\n");
698  P("#if CACHEVEC\n");
699  P(" _ni = _ml->_nodeindices;\n");
700  P("#endif\n");
701  P("_cntml = _ml->_nodecount;\n");
702  P("_thread = _ml->_thread;\n");
703  /*check_tables();*/
704  P("for (_iml = 0; _iml < _cntml; ++_iml) {\n");
705  P(" _p = _ml->_data[_iml]; _ppvar = _ml->_pdata[_iml];\n");
706  check_tables();
707  if (debugging_ && net_receive_) {
708  P(" _tsav = -1e20;\n");
709  }
710  if (!artificial_cell) {ext_vdef();}
711  if (!artificial_cell) {P(" v = _v;\n");}
713  P(" initmodel(_p, _ppvar, _thread, _nt);\n");
715  P("}\n");
716  P("}\n");
717 
718  /* standard modl EQUATION without solve computes current */
719  if (!conductance_) {
720  P("\nstatic double _nrn_current(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt, double _v){double _current=0.;v=_v;");
721 #if CVODE
722  if (cvode_nrn_current_solve_) {
723  fprintf(fcout, "if (cvode_active_) { %s(_p, _ppvar, _thread, _nt); }\n", cvode_nrn_current_solve_->name);
724  }
725 #endif
726  P("{");
727  if (currents->next != currents) {
728  printlist(modelfunc);
729  }
730  ITERATE(q, currents) {
731  if (SYM(q) != breakpoint_current(SYM(q))) {
732 diag("current can only be LOCAL in a BREAKPOINT if CONDUCTANCE statements are used. ", SYM(q)->name);
733  }
734  Sprintf(buf, " _current += %s;\n", SYM(q)->name);
735  P(buf);
736  }
737  P("\n} return _current;\n}\n");
738  }
739 
740  /* For the classic BREAKPOINT block, the neuron current also has to compute the dcurrent/dv as well
741  as make sure all currents accumulated properly (currents list) */
742 
743  if (brkpnt_exists) {
744  P("\nstatic void nrn_cur(NrnThread* _nt, _Memb_list* _ml, int _type) {\n");
745  P("double* _p; Datum* _ppvar; Datum* _thread;\n");
746  P("Node *_nd; int* _ni; double _rhs, _v; int _iml, _cntml;\n");
747  P("#if CACHEVEC\n");
748  P(" _ni = _ml->_nodeindices;\n");
749  P("#endif\n");
750  P("_cntml = _ml->_nodecount;\n");
751  P("_thread = _ml->_thread;\n");
752  P("for (_iml = 0; _iml < _cntml; ++_iml) {\n");
753  P(" _p = _ml->_data[_iml]; _ppvar = _ml->_pdata[_iml];\n");
754  ext_vdef();
755  if (currents->next != currents) {
757 #if CVODE
758  cvode_rw_cur(buf);
759  P(buf);
760  }
761  if (cvode_nrn_cur_solve_) {
762  fprintf(fcout, "if (cvode_active_) { %s(_p, _ppvar, _thread, _nt); }\n", cvode_nrn_cur_solve_->name);
763  }
764  if (currents->next != currents) {
765 #endif
766  if (conductance_) {
767  P(" {\n");
770  P(" }\n");
771  }else{
772  P(" _g = _nrn_current(_p, _ppvar, _thread, _nt, _v + .001);\n");
774  if (state_discon_list_) {
775  P(" state_discon_flag_ = 1; _rhs = _nrn_current(_v); state_discon_flag_ = 0;\n");
776  }else{
777  P(" _rhs = _nrn_current(_p, _ppvar, _thread, _nt, _v);\n");
778  }
779  printlist(end_dion_stmt(".001"));
780  P(" _g = (_g - _rhs)/.001;\n");
781  /* set the ion variable values */
783  } /* end of not conductance */
784  if (point_process) {
785  P(" _g *= 1.e2/(_nd_area);\n");
786  P(" _rhs *= 1.e2/(_nd_area);\n");
787  }
788  if (electrode_current) {
789 #if CACHEVEC == 0
790  P(" NODERHS(_nd) += _rhs;\n");
791 #else
792  P("#if CACHEVEC\n");
793  P(" if (use_cachevec) {\n");
794  P(" VEC_RHS(_ni[_iml]) += _rhs;\n");
795  P(" }else\n");
796  P("#endif\n");
797  P(" {\n");
798  P(" NODERHS(_nd) += _rhs;\n");
799  P(" }\n");
800  P(" if (_nt->_nrn_fast_imem) { _nt->_nrn_fast_imem->_nrn_sav_rhs[_ni[_iml]] += _rhs; }\n");
801 #endif
802  P("#if EXTRACELLULAR\n");
803  P(" if (_nd->_extnode) {\n");
804  P(" *_nd->_extnode->_rhs[0] += _rhs;\n");
805  P(" }\n");
806  P("#endif\n");
807  }else{
808 #if CACHEVEC == 0
809  P(" NODERHS(_nd) -= _rhs;\n");
810 #else
811  P("#if CACHEVEC\n");
812  P(" if (use_cachevec) {\n");
813  P(" VEC_RHS(_ni[_iml]) -= _rhs;\n");
814  P(" }else\n");
815  P("#endif\n");
816  P(" {\n");
817  P(" NODERHS(_nd) -= _rhs;\n");
818  P(" }\n");
819 #endif
820  }
821  }
822  P(" \n}\n");
823  P(" \n}\n");
824  /* for the classic breakpoint block, nrn_cur computed the conductance, _g,
825  and now the jacobian calculation merely returns that */
826  P("\nstatic void nrn_jacob(NrnThread* _nt, _Memb_list* _ml, int _type) {\n");
827  P("double* _p; Datum* _ppvar; Datum* _thread;\n");
828  P("Node *_nd; int* _ni; int _iml, _cntml;\n");
829  P("#if CACHEVEC\n");
830  P(" _ni = _ml->_nodeindices;\n");
831  P("#endif\n");
832  P("_cntml = _ml->_nodecount;\n");
833  P("_thread = _ml->_thread;\n");
834  P("for (_iml = 0; _iml < _cntml; ++_iml) {\n");
835  P(" _p = _ml->_data[_iml];\n");
836  if (electrode_current) {
837  P(" _nd = _ml->_nodelist[_iml];\n");
838 #if CACHEVEC == 0
839  P(" NODED(_nd) -= _g;\n");
840 #else
841  P("#if CACHEVEC\n");
842  P(" if (use_cachevec) {\n");
843  P(" VEC_D(_ni[_iml]) -= _g;\n");
844  P(" }else\n");
845  P("#endif\n");
846  P(" {\n");
847  P(" NODED(_nd) -= _g;\n");
848  P(" }\n");
849  P(" if (_nt->_nrn_fast_imem) { _nt->_nrn_fast_imem->_nrn_sav_d[_ni[_iml]] -= _g; }\n");
850 #endif
851  P("#if EXTRACELLULAR\n");
852  P(" if (_nd->_extnode) {\n");
853  P(" *_nd->_extnode->_d[0] += _g;\n");
854  P(" }\n");
855  P("#endif\n");
856  }else{
857 #if CACHEVEC == 0
858  P(" NODED(_nd) += _g;\n");
859 #else
860  P("#if CACHEVEC\n");
861  P(" if (use_cachevec) {\n");
862  P(" VEC_D(_ni[_iml]) += _g;\n");
863  P(" }else\n");
864  P("#endif\n");
865  P(" {\n");
866  P(" _nd = _ml->_nodelist[_iml];\n");
867  P(" NODED(_nd) += _g;\n");
868  P(" }\n");
869 #endif
870  }
871  P(" \n}\n");
872  P(" \n}\n");
873  }
874 
875  /* nrnstate list contains the EQUATION solve statement so this
876  advances states by dt */
877  P("\nstatic void nrn_state(NrnThread* _nt, _Memb_list* _ml, int _type) {\n");
878  if (nrnstate || currents->next == currents) {
879  P("double* _p; Datum* _ppvar; Datum* _thread;\n");
880  P("Node *_nd; double _v = 0.0; int* _ni; int _iml, _cntml;\n");
881  if (dtsav_for_nrn_state && nrnstate) {
882  P("double _dtsav = dt;\n"
883  "if (secondorder) { dt *= 0.5; }\n");
884  }
885  P("#if CACHEVEC\n");
886  P(" _ni = _ml->_nodeindices;\n");
887  P("#endif\n");
888  P("_cntml = _ml->_nodecount;\n");
889  P("_thread = _ml->_thread;\n");
890  P("for (_iml = 0; _iml < _cntml; ++_iml) {\n");
891  P(" _p = _ml->_data[_iml]; _ppvar = _ml->_pdata[_iml];\n");
892  P(" _nd = _ml->_nodelist[_iml];\n");
893  ext_vdef();
894  P(" v=_v;\n{\n");
896  if (nrnstate) {
897  printlist(nrnstate);
898  }
899  if (currents->next == currents) {
900  printlist(modelfunc);
901  }
903  P("}}\n");
904  if (dtsav_for_nrn_state && nrnstate) {
905  P(" dt = _dtsav;");
906  }
907  }
908  P("\n}\n");
909 
910  P("\nstatic void terminal(){}\n");
911 
912  /* vectorized: data must have own copies of slist and dlist
913  for now we don't vectorize if slist or dlist exists. Eventually
914  must separate initialization of static things from vectorized
915  things.
916  */
917  /* initlists() is called once to setup slist and dlist pointers */
918  P("\nstatic void _initlists(){\n");
919  P(" double _x; double* _p = &_x;\n");
920  P(" int _i; static int _first = 1;\n");
921  P(" if (!_first) return;\n");
922  printlist(initlist);
923  P("_first = 0;\n}\n");
924  P("\n#if defined(__cplusplus)\n} /* extern \"C\" */\n#endif\n");
925 }
926 
927 void vectorize_substitute(Item* q, char* str)
928 {
929  if (!vectorize_replacements) {
930  vectorize_replacements = newlist();
931  }
932  lappenditem(vectorize_replacements, q);
933  lappendstr(vectorize_replacements, str);
934 }
935 
937  Item* q1;
938  if (vectorize_replacements) {
939  ITERATE(q1, vectorize_replacements) {
940  if (ITM(q1) == q) {
941  return q1->next;
942  }
943  }
944  }
945  return (Item*)0;
946 }
947 
949  Item *q, *q1;
950  if (vectorize_replacements) {
951  ITERATE(q, vectorize_replacements) {
952  q1 = ITM(q);
953  q = q->next;
954  replacstr(q1, STR(q));
955  }
956  }
957 }
958 
959 char* cray_pragma() {
960  static char buf[] = "\
961 \n#if _CRAY\
962 \n#pragma _CRI ivdep\
963 \n#endif\
964 \n";
965  return buf;
966 }
967 
968 #endif /*VECTORIZE*/
969 
970 static void conductance_cout() {
971  int i=0;
972  Item* q;
973  List* m;
974 
975  /* replace v with _v */
976  m = newlist();
977  ITERATE(q, modelfunc) {
978  if (q->itemtype == SYMBOL) {
979  if (strcmp(SYM(q)->name, "v") == 0) {
980  lappendstr(m, "_v");
981  }else{
982  lappendsym(m, SYM(q));
983  }
984  }else if (q->itemtype == STRING) {
985  lappendstr(m, STR(q));
986  }else{
987  diag("modelfunc contains item which is not a SYMBOL or STRING", (char*)0);
988  }
989  }
990  /* eliminate first { */
991  ITERATE(q, m) {
992  if (q->itemtype == SYMBOL) {
993  if (strcmp(SYM(q)->name, "{") == 0) {
994  remove(q);
995  break;
996  }
997  }
998  }
999  /* eliminate last } */
1000  for (q = m->prev; q != m; q = q->prev) {
1001  if (q->itemtype == SYMBOL) {
1002  if (strcmp(SYM(q)->name, "}") == 0) {
1003  remove(q);
1004  break;
1005  }
1006  }
1007  }
1008 
1009  printlist(m);
1010 
1011  ITERATE(q, currents) {
1012  if (i == 0) {
1013  sprintf(buf, " _rhs = %s", breakpoint_current(SYM(q))->name);
1014  }else{
1015  sprintf(buf, " + %s", breakpoint_current(SYM(q))->name);
1016  }
1017  P(buf);
1018  i += 1;
1019  }
1020  if (i > 0) {
1021  P(";\n");
1022  }
1023 
1024  i = 0;
1025  ITERATE(q, conductance_) {
1026  if (i == 0) {
1027  sprintf(buf, " _g = %s", SYM(q)->name);
1028  }else{
1029  sprintf(buf, " + %s", SYM(q)->name);
1030  }
1031  P(buf);
1032  i += 1;
1033  q = q->next;
1034  }
1035  if (i > 0) {
1036  P(";\n");
1037  }
1038 
1039  ITERATE(q, conductance_) {
1040  if (SYM(q->next)) {
1041  sprintf(buf, " _ion_di%sdv += %s", SYM(q->next)->name, SYM(q)->name);
1042  P(buf);
1043  if (point_process) {
1044  P("* 1.e2/(_nd_area)");
1045  }
1046  P(";\n");
1047  }
1048  q = q->next;
1049  }
1050 }
Symbol * indepsym
Definition: declare.cpp:11
List * currents
Definition: nocpout.cpp:140
short itemtype
Definition: model.h:16
#define assert(ex)
Definition: hocassrt.h:26
List * get_ion_variables(int)
Definition: nocpout.cpp:1949
short type
Definition: cabvars.h:10
char * modelline
Definition: noccout.cpp:29
void c_out_vectorize(const char *)
void vectorize_do_substitute()
List * indeplist
Definition: parsact.cpp:15
char * items_as_string(Item *q1, Item *q2)
Definition: noccout.cpp:558
#define PROCED
Definition: model.h:120
List * initfunc
Definition: noccout.cpp:13
#define diag(s)
Definition: fmenu.cpp:188
#define ITERATE(itm, lst)
Definition: model.h:25
#define SYM(q)
Definition: model.h:86
#define SYMITER_STAT
Definition: symbol.h:14
#define P(arg)
Definition: noccout.cpp:12
Item * lappendsym(List *list, Symbol *sym)
Definition: list.cpp:161
#define SPECIAL
Definition: model.h:100
List * initlist
Definition: noccout.cpp:13
char * name
Definition: model.h:72
List * match_bound
Definition: deriv.cpp:637
struct Item * prev
Definition: model.h:20
static int narg()
Definition: ivocvect.cpp:135
#define Fprintf
Definition: model.h:249
#define SYMBOL
Definition: model.h:102
struct Item * next
Definition: model.h:19
List * set_ion_variables(int)
Definition: nocpout.cpp:1883
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
void c_out()
Definition: noccout.cpp:105
char * nmodl_version_
Definition: nocpout.cpp:11
Definition: model.h:15
int artificial_cell
Definition: nocpout.cpp:153
int net_receive_
static int indent
Definition: noccout.cpp:514
static void conductance_cout()
Definition: noccout.cpp:970
Symbol * breakpoint_current(Symbol *s)
Definition: nocpout.cpp:2770
_CONST char * s
Definition: system.cpp:74
#define ARRAY
Definition: model.h:118
void debugprintitem(Item *q)
Definition: noccout.cpp:544
List * defs_list
Definition: nocpout.cpp:124
Item * lappendstr(List *list, char *str)
Definition: list.cpp:149
#define printf
Definition: mwprefix.h:26
List * procfunc
Definition: noccout.cpp:13
static void initstates()
Definition: noccout.cpp:475
int point_process
Definition: nocpout.cpp:152
void vectorize_substitute(Item *q, char *str)
int electrode_current
Definition: nocpout.cpp:125
#define STRING
Definition: bbslsrv.cpp:9
List * conductance_
Definition: nocpout.cpp:142
#define ITEM
Definition: model.h:103
void kin_vect2()
Definition: kinetic.cpp:1335
static void ext_vdef()
Definition: noccout.cpp:60
static int newline
Definition: noccout.cpp:514
size_t j
fprintf(stderr, "Don't know the location of params at %p\, pp)
Definition: model.h:57
#define Fflush
Definition: model.h:251
int debugging_
char * name
Definition: init.cpp:16
void printitem(Item *q)
Definition: noccout.cpp:516
List * newlist()
Definition: list.cpp:50
#define ENDBLK
Definition: model.h:124
#define FUNCT
Definition: model.h:119
List * begin_dion_stmt()
Definition: nocpout.cpp:2123
char * saveindep
Definition: solve.cpp:369
NMODL parser global flags / functions.
int dtsav_for_nrn_state
Definition: deriv.cpp:17
#define lookup
Definition: redef.h:90
long subtype
Definition: model.h:59
Item * lappenditem(List *list, Item *item)
Definition: list.cpp:167
void check_tables()
Definition: parsact.cpp:538
static void funcdec()
Definition: noccout.cpp:600
void verbatim_adjust(char *q)
Definition: modl.cpp:362
#define STR(q)
Definition: model.h:87
int vectorize
int araydim
Definition: model.h:67
long subtype
Definition: init.cpp:122
#define i
Definition: md1redef.h:12
void printlist(List *s)
Definition: noccout.cpp:576
int brkpnt_exists
List * firstlist
Definition: noccout.cpp:13
char buf[512]
Definition: init.cpp:13
List * modelfunc
Definition: noccout.cpp:13
void replacstr(Item *q, char *s)
Definition: list.cpp:250
void cvode_rw_cur(char *)
#define Sprintf
Definition: model.h:248
#define SEMI
Definition: model.h:122
size_t q
#define IONCONC
Definition: nocpout.cpp:101
List * termfunc
Definition: noccout.cpp:13
List * end_dion_stmt(char *strdel)
Definition: nocpout.cpp:2149
int varnum
Definition: model.h:69
FILE * fcout
Definition: model.cpp:33
#define BEGINBLK
Definition: model.h:123
Item * vectorize_replacement_item(Item *)
#define ITM(q)
Definition: model.h:88
#define SYMITER(arg1)
Definition: symbol.h:9