1 #include <../../nrnconf.h>
10 #define P(arg) fputs(arg, fcout)
53 P(
"#if EXTRACELLULAR\n");
54 P(
" _nd = _ml_arg->_nodelist[_iml];\n");
55 P(
" if (auto* const _extnode = _nrn_mechanism_access_extnode(_nd); _extnode) {\n");
56 P(
" _v = NODEV(_nd) + _extnode->_v[0];\n");
60 P(
" _v = _vec_v[_ni[_iml]];\n");
63 P(
" _v = _vec_v[_ni[_iml]];\n");
81 P(
"/* NOT VECTORIZED */\n#define NRN_VECTORIZED 0\n");
84 P(
"#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include \"mech_api.h\"\n");
87 P(
"#define _pval pval\n");
88 P(
"// clang-format off\n");
89 P(
"#include \"md1redef.h\"\n");
90 P(
"#include \"section_fwd.hpp\"\n");
91 P(
"#include \"nrniv_mf.h\"\n");
92 P(
"#include \"md2redef.h\"\n");
93 P(
"#include \"nrnconf.h\"\n");
94 P(
"// clang-format on\n");
95 P(
"#include \"neuron/cache/mechanism_range.hpp\"\n");
96 P(
"#include <vector>\n");
99 P(
"using std::size_t;\n");
100 P(
"static auto& std_cerr_stream = std::cerr;\n");
104 P(
"static int _reset;\n");
113 P(
"static int error;\n");
115 P(
"int _ninits = 0;\n");
116 P(
"static int _match_recurse=1;\n");
118 P(
"_modl_cleanup(){ _match_recurse=1;}\n");
138 P(
"\nstatic void initmodel() {\n int _i; double _save;");
148 P(
"\nstatic void nrn_init(_nrn_model_sorted_token const& _sorted_token, NrnThread* _nt, "
149 "Memb_list* _ml_arg, int _type){\n");
150 P(
"Node *_nd; double _v; int* _ni; int _cntml;\n");
151 P(
"_nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml_arg, _type};\n");
152 P(
"auto* const _vec_v = _nt->node_voltage_storage();\n");
154 P(
"_ni = _ml_arg->_nodeindices;\n");
155 P(
"_cntml = _ml_arg->_nodecount;\n");
156 P(
"for (_iml = 0; _iml < _cntml; ++_iml) {\n");
157 P(
" _ppvar = _ml_arg->_pdata[_iml];\n");
159 P(
" _tsav = -1e20;\n");
168 P(
" initmodel();\n");
173 P(
"\nstatic double _nrn_current(double _v){double _current=0.;v=_v;");
185 P(
"\n} return _current;\n}\n");
191 P(
"\nstatic void nrn_cur(_nrn_model_sorted_token const& _sorted_token, NrnThread* _nt, "
192 "Memb_list* _ml_arg, int _type){\n");
193 P(
"_nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml_arg, _type};\n");
194 P(
"auto const _vec_rhs = _nt->node_rhs_storage();\n");
195 P(
"auto const _vec_sav_rhs = _nt->node_sav_rhs_storage();\n");
196 P(
"auto const _vec_v = _nt->node_voltage_storage();\n");
197 P(
"Node *_nd; int* _ni; double _rhs, _v; int _cntml;\n");
199 P(
"_ni = _ml_arg->_nodeindices;\n");
200 P(
"_cntml = _ml_arg->_nodecount;\n");
201 P(
"for (_iml = 0; _iml < _cntml; ++_iml) {\n");
202 P(
" _ppvar = _ml_arg->_pdata[_iml];\n");
213 P(
" auto const _g_local = _nrn_current(_v + .001);\n");
216 P(
" state_discon_flag_ = 1; _rhs = _nrn_current(_v); state_discon_flag_ = 0;\n");
218 P(
" _rhs = _nrn_current(_v);\n");
221 P(
" _g = (_g_local - _rhs)/.001;\n");
225 P(
" _g *= 1.e2/(_nd_area);\n");
226 P(
" _rhs *= 1.e2/(_nd_area);\n");
229 P(
" _vec_rhs[_ni[_iml]] += _rhs;\n");
230 P(
" if (_vec_sav_rhs) {\n");
231 P(
" _vec_sav_rhs[_ni[_iml]] += _rhs;\n");
233 P(
"#if EXTRACELLULAR\n");
234 P(
" if (auto* const _extnode = _nrn_mechanism_access_extnode(_nd); _extnode) {\n");
235 P(
" *_extnode->_rhs[0] += _rhs;\n");
239 P(
" _vec_rhs[_ni[_iml]] -= _rhs;\n");
246 P(
"\nstatic void nrn_jacob(_nrn_model_sorted_token const& _sorted_token, NrnThread* "
247 "_nt, Memb_list* _ml_arg, int _type) {\n");
248 P(
"_nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml_arg, _type};\n");
249 P(
"auto const _vec_d = _nt->node_d_storage();\n");
250 P(
"auto const _vec_sav_d = _nt->node_sav_d_storage();\n");
251 P(
"auto* const _ml = &_lmr;\n");
252 P(
"Node *_nd; int* _ni; int _iml, _cntml;\n");
253 P(
"_ni = _ml_arg->_nodeindices;\n");
254 P(
"_cntml = _ml_arg->_nodecount;\n");
255 P(
"for (_iml = 0; _iml < _cntml; ++_iml) {\n");
257 P(
" _nd = _ml_arg->_nodelist[_iml];\n");
258 P(
" _vec_d[_ni[_iml]] -= _g;\n");
259 P(
" if (_vec_sav_d) {\n");
260 P(
" _vec_sav_d[_ni[_iml]] -= _g;\n");
262 P(
"#if EXTRACELLULAR\n");
263 P(
" if (auto* const _extnode = _nrn_mechanism_access_extnode(_nd); _extnode) {\n");
264 P(
" *_extnode->_d[0] += _g;\n");
268 P(
" _vec_d[_ni[_iml]] += _g;\n");
275 P(
"\nstatic void nrn_state(_nrn_model_sorted_token const& _sorted_token, NrnThread* _nt, "
276 "Memb_list* _ml_arg, int _type){\n");
278 P(
"Node *_nd; double _v = 0.0; int* _ni; int _cntml;\n");
280 P(
"double _dtsav = dt;\n"
281 "if (secondorder) { dt *= 0.5; }\n");
283 P(
"_nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml_arg, _type};\n");
284 P(
"auto* const _vec_v = _nt->node_voltage_storage();\n");
286 P(
"_ni = _ml_arg->_nodeindices;\n");
287 P(
"_cntml = _ml_arg->_nodecount;\n");
288 P(
"for (_iml = 0; _iml < _cntml; ++_iml) {\n");
289 P(
" _ppvar = _ml_arg->_pdata[_iml];\n");
290 P(
" _nd = _ml_arg->_nodelist[_iml];\n");
308 P(
"\nstatic void terminal(){}\n");
311 P(
"\nstatic void _initlists() {\n");
312 P(
" int _i; static int _first = 1;\n");
313 P(
" if (!_first) return;\n");
315 P(
"_first = 0;\n}\n");
331 #define IONCONC 010000
344 " for (_i=0; _i<%d; _i++) %s[_i] = %s0;\n",
380 }
else if (
q->itemtype == VERBATIM) {
382 }
else if (
q->itemtype ==
ITEM) {
392 }
else if (
q->itemtype == VERBATIM) {
394 }
else if (
q->itemtype ==
ITEM) {
406 for (
q = q1;
q != q2;
q =
q->next) {
407 if (
buf[0] !=
'\0') {
412 }
else if (
q->itemtype ==
STRING) {
482 P(
"/* VECTORIZED */\n#define NRN_VECTORIZED 1\n");
483 P(
"#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include \"mech_api.h\"\n");
485 P(
"#define nil 0\n");
486 P(
"#define _pval pval\n");
487 P(
"// clang-format off\n");
488 P(
"#include \"md1redef.h\"\n");
489 P(
"#include \"section_fwd.hpp\"\n");
490 P(
"#include \"nrniv_mf.h\"\n");
491 P(
"#include \"md2redef.h\"\n");
492 P(
"#include \"nrnconf.h\"\n");
493 P(
"// clang-format on\n");
494 P(
"#include \"neuron/cache/mechanism_range.hpp\"\n");
497 P(
"static int _reset;\n");
501 Fprintf(
fcout,
"static const char *modelname = \"\";\n\n");
505 P(
"static int error;\n");
506 P(
"static int _ninits = 0;\n");
507 P(
"static int _match_recurse=1;\n");
508 P(
"static void _modl_cleanup(){ _match_recurse=1;}\n");
522 P(
"\nstatic void initmodel(_internalthreadargsproto_) {\n int "
523 "_i; double _save;");
531 P(
"\nstatic void nrn_init(_nrn_model_sorted_token const& _sorted_token, NrnThread* _nt, "
532 "Memb_list* _ml_arg, int _type){\n");
533 P(
"_nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml_arg, _type};\n");
534 P(
"auto* const _vec_v = _nt->node_voltage_storage();\n");
535 P(
"auto* const _ml = &_lmr;\n");
536 P(
"Datum* _ppvar; Datum* _thread;\n");
537 P(
"Node *_nd; double _v; int* _ni; int _iml, _cntml;\n");
538 P(
"_ni = _ml_arg->_nodeindices;\n");
539 P(
"_cntml = _ml_arg->_nodecount;\n");
540 P(
"_thread = _ml_arg->_thread;\n");
541 P(
"double* _globals = nullptr;\n");
542 P(
"if (gind != 0 && _thread != nullptr) { _globals = _thread[_gth].get<double*>(); }\n");
544 P(
"for (_iml = 0; _iml < _cntml; ++_iml) {\n");
545 P(
" _ppvar = _ml_arg->_pdata[_iml];\n");
548 P(
" _tsav = -1e20;\n");
557 P(
" initmodel(_threadargs_);\n");
564 P(
"\nstatic double _nrn_current(_internalthreadargsprotocomma_ "
566 "double _current=0.; v=_v;\n");
569 "if (cvode_active_) { %s(_threadargs_); }\n",
579 "current can only be LOCAL in a BREAKPOINT if CONDUCTANCE statements are "
586 P(
"\n} return _current;\n}\n");
593 P(
"\nstatic void nrn_cur(_nrn_model_sorted_token const& _sorted_token, NrnThread* _nt, "
594 "Memb_list* _ml_arg, int _type) {\n");
595 P(
"_nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml_arg, _type};\n");
596 P(
"auto const _vec_rhs = _nt->node_rhs_storage();\n");
597 P(
"auto const _vec_sav_rhs = _nt->node_sav_rhs_storage();\n");
598 P(
"auto const _vec_v = _nt->node_voltage_storage();\n");
599 P(
"auto* const _ml = &_lmr;\n");
600 P(
"Datum* _ppvar; Datum* _thread;\n");
601 P(
"Node *_nd; int* _ni; double _rhs, _v; int _iml, _cntml;\n");
602 P(
"_ni = _ml_arg->_nodeindices;\n");
603 P(
"_cntml = _ml_arg->_nodecount;\n");
604 P(
"_thread = _ml_arg->_thread;\n");
605 P(
"double* _globals = nullptr;\n");
606 P(
"if (gind != 0 && _thread != nullptr) { _globals = _thread[_gth].get<double*>(); }\n");
607 P(
"for (_iml = 0; _iml < _cntml; ++_iml) {\n");
608 P(
" _ppvar = _ml_arg->_pdata[_iml];\n");
617 "if (cvode_active_) { %s(_threadargs_); }\n",
627 P(
" auto const _g_local = _nrn_current(_threadargscomma_ _v + .001);\n");
630 P(
" state_discon_flag_ = 1; _rhs = _nrn_current(_v); state_discon_flag_ = "
633 P(
" _rhs = _nrn_current(_threadargscomma_ _v);\n");
636 P(
" _g = (_g_local - _rhs)/.001;\n");
641 P(
" _g *= 1.e2/(_nd_area);\n");
642 P(
" _rhs *= 1.e2/(_nd_area);\n");
645 P(
" _vec_rhs[_ni[_iml]] += _rhs;\n");
646 P(
" if (_vec_sav_rhs) {\n");
647 P(
" _vec_sav_rhs[_ni[_iml]] += _rhs;\n");
649 P(
"#if EXTRACELLULAR\n");
650 P(
" if (auto* const _extnode = _nrn_mechanism_access_extnode(_nd); _extnode) {\n");
651 P(
" *_extnode->_rhs[0] += _rhs;\n");
655 P(
" _vec_rhs[_ni[_iml]] -= _rhs;\n");
662 P(
"\nstatic void nrn_jacob(_nrn_model_sorted_token const& _sorted_token, NrnThread* "
663 "_nt, Memb_list* _ml_arg, int _type) {\n");
664 P(
"_nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml_arg, _type};\n");
665 P(
"auto const _vec_d = _nt->node_d_storage();\n");
666 P(
"auto const _vec_sav_d = _nt->node_sav_d_storage();\n");
667 P(
"auto* const _ml = &_lmr;\n");
668 P(
"Datum* _ppvar; Datum* _thread;\n");
669 P(
"Node *_nd; int* _ni; int _iml, _cntml;\n");
670 P(
"_ni = _ml_arg->_nodeindices;\n");
671 P(
"_cntml = _ml_arg->_nodecount;\n");
672 P(
"_thread = _ml_arg->_thread;\n");
673 P(
"double* _globals = nullptr;\n");
674 P(
"if (gind != 0 && _thread != nullptr) { _globals = _thread[_gth].get<double*>(); }\n");
675 P(
"for (_iml = 0; _iml < _cntml; ++_iml) {\n");
677 P(
" _nd = _ml_arg->_nodelist[_iml];\n");
678 P(
" _vec_d[_ni[_iml]] -= _g;\n");
679 P(
" if (_vec_sav_d) {\n");
680 P(
" _vec_sav_d[_ni[_iml]] -= _g;\n");
682 P(
"#if EXTRACELLULAR\n");
683 P(
" if (auto* const _extnode = _nrn_mechanism_access_extnode(_nd); _extnode) {\n");
684 P(
" *_extnode->_d[0] += _g;\n");
688 P(
" _vec_d[_ni[_iml]] += _g;\n");
696 P(
"\nstatic void nrn_state(_nrn_model_sorted_token const& _sorted_token, NrnThread* _nt, "
697 "Memb_list* _ml_arg, int _type) {\n");
698 P(
"_nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml_arg, _type};\n");
699 P(
"auto* const _vec_v = _nt->node_voltage_storage();\n");
700 P(
"auto* const _ml = &_lmr;\n");
702 P(
"Datum* _ppvar; Datum* _thread;\n");
703 P(
"Node *_nd; double _v = 0.0; int* _ni;\n");
705 P(
"double _dtsav = dt;\n"
706 "if (secondorder) { dt *= 0.5; }\n");
708 P(
"_ni = _ml_arg->_nodeindices;\n");
709 P(
"size_t _cntml = _ml_arg->_nodecount;\n");
710 P(
"_thread = _ml_arg->_thread;\n");
711 P(
"double* _globals = nullptr;\n");
712 P(
"if (gind != 0 && _thread != nullptr) { _globals = _thread[_gth].get<double*>(); }\n");
713 P(
"for (size_t _iml = 0; _iml < _cntml; ++_iml) {\n");
714 P(
" _ppvar = _ml_arg->_pdata[_iml];\n");
715 P(
" _nd = _ml_arg->_nodelist[_iml];\n");
733 P(
"\nstatic void terminal(){}\n");
741 P(
"\nstatic void _initlists(){\n");
742 P(
" int _i; static int _first = 1;\n");
743 P(
" if (!_first) return;\n");
745 P(
"_first = 0;\n}\n");
788 if (strcmp(
SYM(
q)->
name,
"v") == 0) {
793 }
else if (
q->itemtype ==
STRING) {
796 diag(
"modelfunc contains item which is not a SYMBOL or STRING", (
char*) 0);
802 if (strcmp(
SYM(
q)->
name,
"{") == 0) {
809 for (
q = m->
prev;
q != m;
q =
q->prev) {
811 if (strcmp(
SYM(
q)->
name,
"}") == 0) {
853 P(
"* 1.e2/(_nd_area)");
void verbatim_adjust(char *q)
#define ITERATE(itm, lst)
Symbol * lookup(const char *)
void replacstr(Item *q, const char *s)
Item * lappenditem(List *list, Item *item)
Item * lappendsym(List *list, Symbol *sym)
Item * lappendstr(List *list, const char *str)
List * newlist()
The following routines support the concept of a list.
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.
Symbol * breakpoint_current(Symbol *s)
void cvode_rw_cur(char(&b)[NRN_BUFSIZE])
Item * vectorize_replacement_item(Item *q)
List * get_ion_variables(int)
void vectorize_do_substitute()
Symbol * cvode_nrn_current_solve_
List * state_discon_list_
List * set_ion_variables(int)
Symbol * cvode_nrn_cur_solve_
const char * nmodl_version_
List * end_dion_stmt(const char *)
static void conductance_cout()
void debugprintitem(Item *q)
static List * vectorize_replacements
void vectorize_substitute(Item *q, const char *str)
char * items_as_string(Item *q1, Item *q2)
NMODL parser global flags / functions.
static double remove(void *v)
int Fprintf(FILE *stream, const char *fmt, Args... args)