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