1 #include <../../nmodlconf.h>
31 static int cvode_flag;
32 static void cvode_kin_remove();
33 static Item *cvode_sbegin, *cvode_send;
34 static List* kin_items_;
35 #define CVODE_FLAG if (cvode_flag)
36 #define NOT_CVODE_FLAG if (!cvode_flag)
38 #define CVODE_FLAG if (0)
39 #define NOT_CVODE_FLAG if (1)
110 static char* instance_loop() {
111 extern char* cray_pragma();
113 Sprintf(buf1,
"\n#ifdef WANT_PRAGMA%s#endif\n _INSTANCE_LOOP {\n", cray_pragma());
126 char *cp, *ovrfl, *cs, *
n;
129 while (q1 != q2->
next) {
144 for (cs =
n; *cs; cs++) {
170 diag(s->
name,
"must be a STATE, CONSTANT, ASSIGNED, STEPPED, or INDEPENDENT");
179 diag(
"REACTION: MUST be scalar or array", (
char*) 0);
231 if (
SYM(qdir)->
name[0] ==
'-') {
238 diag(
"flux equations involve only one state", (
char*) 0);
250 if (s->nrntype & 02 ) {
262 "nrn_nernst_coef(_type_%s)*(%s _ion_d%sdv %s)",
273 diag(sr->
name,
"gets a flux from more than one current");
302 Item *
q, *qs, *afterbrace;
311 diag(
"Merging kinetic blocks not implemented", (
char*) 0);
325 "(void* _so, double* _rhs, double* _p, Datum* _ppvar, Datum* _thread, "
326 "NrnThread* _nt)\n");
334 afterbrace = q3->
next;
339 for (afterbrace = afterbrace->
next;
341 afterbrace = afterbrace->
next)
344 afterbrace = afterbrace->
next;
348 qv =
insertstr(afterbrace,
"double b_flux, f_flux, _term; int _i;\n");
396 diag(
"Failed to diagonalize the Kinetic matrix", (
char*) 0);
414 diag(
"KINETIC contains no reactions", (
char*) 0);
418 "static int _slist%d[%d], _dlist%d[%d]; static double *_temp%d;\n",
470 Item *
q, *qexp, *qb, *qend, *q1;
477 for (q1 = qb->
next; q1 != qend; q1 = q1->
next) {
494 for (
q = cvode_sbegin;
q != cvode_send->
next;
q =
q->next) {
520 Fprintf(stderr,
"%s method ignores conservation\n", meth);
523 Sprintf(
buf,
"{int _i; for(_i=0;_i<%d;_i++) _p[_dlist%d[_i]] = 0.0;}\n",
nstate, fun->
u.
i);
532 for (
i = 0;
i < rlst->
nsym;
i++) {
536 "for (_i=0; _i < %d; _i++) { _p[_dlist%d[_i + %d]] /= %s;}\n",
544 "_p[_dlist%d[%d]] /= %s;\n",
566 for (
j = 0;
j < 2;
j++) {
578 for (
i = 0;
i < rt->
num;
i++) {
589 for (
j = 0;
j < 2;
j++) {
638 diag(rt->
sym->
name,
"must be (solved) STATE in flux reaction");
643 diag(rt->
sym->
name,
"is conserved and has a flux");
698 int i,
nstate, flag, sparsedec, firsttrans, firsttrans1;
708 Sprintf(
buf,
"static void* _cvsparseobj%d;\n", fun->
u.
i);
712 sprintf(
buf,
" _nrn_destroy_sparseobj_thread(_thread[_cvspth%d]._pvoid);\n", fun->
u.
i);
739 sprintf(
buf,
" _nrn_destroy_sparseobj_thread(_thread[_spth%d]._pvoid);\n", fun->
u.
i);
744 diag(
" SENS unimplemented for default kinetic integration",
"method");
755 "{int _i; double _dt1 = 1.0/%s;\n\
756 for(_i=%d;_i<%d;_i++){\n",
770 _RHS%d(_i) = -_dt1*(_p[_slist%d[_i]] - _p[_dlist%d[_i]]);\n\
771 _MATELM%d(_i, _i) = _dt1;\n",
779 _RHS%d(_i) = -_dt1*(_p[_ix][_slist%d[_i]] - _p[_ix][_dlist%d[_i]]);\n\
780 _MATELM%d(_i, _i) = _dt1;\n",
781 fun->
u.
i, fun->
u.
i, fun->
u.
i, fun->
u.
i);
788 _RHS%d(_i) = _dt1*(_p[_dlist%d[_i]]);\n\
789 _MATELM%d(_i, _i) = _dt1;\n",
796 _RHS%d(_i) = _dt1*(_p[_ix][_dlist%d[_i]]);\n\
797 _MATELM%d(_i, _i) = _dt1;\n",
798 fun->
u.
i, fun->
u.
i, fun->
u.
i);
823 "\n_RHS%d(%d) *= %s",
829 ";\n_MATELM%d(%d, %d) *= %s;",
856 " _RHS%d(_i + %d) *= %s",
862 ";\n_MATELM%d(_i + %d, _i + %d) *= %s;",
906 if (strcmp(mname,
"_advance") == 0) {
908 buf,
"\n#define _RHS%d(arg) _coef%d[arg][%d]\n", fun->
u.
i, fun->
u.
i,
nstate);
911 "\n#define _MATELM%d(arg1,arg2) _coef%d[arg1][arg2]\n",
925 Sprintf(
buf,
"\n#define _RHS%d(_arg) _coef%d[_arg + 1]\n", fun->
u.
i, fun->
u.
i);
928 Sprintf(
buf,
"\n#define _RHS%d(_arg) _rhs[_arg+1]\n", fun->
u.
i);
932 "\n#define _MATELM%d(_row,_col)\
933 *(_getelm(_row + 1, _col + 1))\n",
938 "\n#define _MATELM%d(_row,_col) *(_nrn_thread_getelm(_so, _row + 1, _col + "
944 static int first = 1;
950 Sprintf(
buf,
"extern double *_nrn_thread_getelm(SparseObj*, int, int);\n");
971 for (
j = 0;
j < 2;
j++)
989 for (
i = 0;
i <
n;
i++) {
1001 for (j1 = 0; j1 < 2; j1++)
1002 for (rt1 = r->
rterm[j1]; rt1; rt1 = rt1->
rnext) {
1030 if (rt1->
num != 1) {
1085 Sprintf(eqstr,
"%d(%d + %s", fn, eqnum, rtdiag->
str);
1091 Sprintf(eqstr,
"%d(%d", fn, eqnum);
1104 diag(rt->
sym->
name,
": only (solved) STATE are allowed in CONSERVE equations.");
1112 "_MATELM%s, %d + %s) = %d%s;\n",
1153 for (
i = 0, istate = 0;
i < rlst->
nsym;
i++) {
1165 diag(
"too many solve blocks", (
char*) 0);
1181 for (
i = 0;
i < rlst->
nsym;
i++) {
1189 "for(_i=0;_i<%d;_i++){_slist%d[%d+_i] = %s_columnindex + _i;",
1196 buf,
" _dlist%d[%d+_i] = D%s_columnindex + _i;}\n", fun->
u.
i, s->
varnum, s->
name);
1210 if (standard != actual) {
1211 diag(mes,
"not allowed in this kind of block");
1246 for (
q = qexp;
q != qb1;
q =
q->next) {
1257 for (
q = qb1->
next;
q != qb2;
q = qs) {
1262 diag(
SYM(
q)->
name,
"must be a (solved) STATE in a COMPARTMENT statement");
1284 for (
q = qexp;
q != qb1;
q =
q->next) {
1298 for (
q = qb1->
next;
q != qb2;
q = qs) {
1304 diag(
SYM(
q)->
name,
"must be a (solved) STATE in a LONGITUDINAL_DIFFUSION statement");
1313 Item *qexp, *qb1, *qb2, *
q;
1319 for (
q = qb1;
q != qb2;
q =
q->next) {
1352 Item *
q, *q1, *q2, *q4;
1372 for (
q = q1;
q != q4->
next;
q =
q->next) {
1381 "\n#undef WANT_PRAGMA\n#define WANT_PRAGMA 1\
1382 \n#undef _INSTANCE_LOOP\n#define _INSTANCE_LOOP \
1383 for (_ix = _base; _ix < _bound; ++_ix) ");
1386 "\n#undef _RHS%d\n#define _RHS%d(arg) \
1387 _coef%d[arg][_ix]\n",
1393 "\n#undef _MATELM%d\n#define _MATELM%d(row,col) \
1394 _jacob%d[(row)*%d + (col)][_ix]\n",
1437 if (blocktype == KINETIC &&
vectorize) {
1439 fprintf(stderr,
"Notice: Can't vectorize a kinetic block if it contains\n\
1440 an if...else... statement.\n");
1446 static void cvode_kin_remove() {
1449 prn(kin_items_, kin_items_->
prev);
1450 prn(cvode_sbegin, cvode_send);
1454 while (
ITM(
q) != q2) {
1455 assert(q2 != cvode_send);
1465 for (qq = q1; qq != q2; qq = qq->
next) {
1472 switch (
q->itemtype) {
1483 fprintf(stderr,
"%p type %d\n",
q,
q->itemtype);
1493 Item *
q, *pbeg, *pend, *qnext;
1500 if (
SYM(
q) == fun) {
1506 sprintf(
buf,
"static int _ode_spec%d() {_reset=0;{\n", fun->
u.
i);
1509 "static int _ode_spec%d(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt) "
1510 "{int _reset=0;{\n",
1516 sprintf(
buf,
"static int _ode_matsol%d() {_reset=0;{\n", fun->
u.
i);
1519 "static int _ode_matsol%d(void* _so, double* _rhs, double* _p, Datum* _ppvar, Datum* "
1520 "_thread, NrnThread* _nt) {int _reset=0;{\n",
1531 for (
q = pbeg;
q != pend;
q = qnext) {
1534 (strcmp(
SYM(
q)->
name,
"f_flux") == 0 || strcmp(
SYM(
q)->
name,
"b_flux") == 0)) {
1538 switch (
q->itemtype) {
1540 if (strchr(
STR(
q),
';')) {
1576 Item *
q, *pbeg, *pend, *qnext;
1584 if (!r1->
rterm[0]) {
1588 if (!r1->
rterm[1]) {
1592 for (
i = 0;
i < 2; ++
i) {
1604 for (
i = 0;
i < rlst->
nsym; ++
i) {
1614 for (
i = 0;
i < 2; ++
i) {
1633 "static int _singlechan%d(_v, _pp, _ppd) double _v; double* _pp; Datum* _ppd;{\n\
1634 _p = _pp; _ppvar = _ppd; v = _v; _reset=0;\n{\n",
1642 for (
q = pbeg;
q != pend;
q = qnext) {
1645 (strcmp(
SYM(
q)->
name,
"f_flux") == 0 || strcmp(
SYM(
q)->
name,
"b_flux") == 0)) {
1649 switch (
q->itemtype) {
1651 if (strchr(
STR(
q),
';')) {
1679 "\nstatic _singlechan_declare%d() {\n\
1680 _singlechan_declare(_singlechan%d, _slist%d, %d);\n\
1689 singlechan_ = listnum;
static double order(void *v)
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)
void copyitems(Item *q1, Item *q2, Item *qdest)
void massagecompart(Item *qexp, Item *qb1, Item *qb2, Symbol *indx)
void reactname(Item *q1, Item *lastok, Item *q2)
static int nstate_[MAXKINBLK]
List * thread_cleanup_list
void massageconserve(Item *q1, Item *q3, Item *q5)
int number_states(Symbol *fun, Rlist **prlst, Rlist **pclst)
static Reaction * reactlist
void kinetic_intmethod(Symbol *fun, char *meth)
static int sparse_declared_[10]
void genfluxterm(Reaction *r, int type, int n)
char * qconcat(Item *q1, Item *q2)
void see_astmt(Item *q1, Item *q2)
void check_block(int standard, int actual, char *mes)
void massageldifus(Item *qexp, Item *qb1, Item *qb2, Symbol *indx)
void flux(Item *qREACTION, Item *qdir, Item *qlast)
void kinetic_implicit(Symbol *fun, char *dt, char *mname)
void vectorize_if_else_stmt(int blocktype)
void kinlist(Symbol *fun, Rlist *rlst)
static int sparsedeclared(int i)
void massagereaction(Item *qREACTION, Item *qREACT1, Item *qlpar, Item *qcomma, Item *qrpar)
void genderivterms(Reaction *r, int type, int n)
int genconservterms(int eqnum, Reaction *r, int fn, Rlist *rlst)
static Reaction * conslist
void massagekinetic(Item *q1, Item *q2, Item *q3, Item *q4, int sensused)
void kin_vect1(Item *q1, Item *q2, Item *q4)
void fixrlst(Rlist *rlst)
void kin_vect3(Item *q1, Item *q2, Item *q4)
void genmatterms(Reaction *r, int fn)
static List * compartlist
#define ITERATE(itm, lst)
NMODL parser global flags / functions.
Item * lappendstr(List *list, char *str)
Item * linsertstr(List *list, char *str)
void movelist(Item *q1, Item *q2, List *s)
void freelist(List **plist)
Item * insertstr(Item *item, char *str)
void replacstr(Item *q, char *s)
char * emalloc(unsigned n)
char * stralloc(char *buf, char *rel)
Item * lappenditem(List *list, Item *item)
Item * insertitem(Item *item, Item *itm)
Item * lappendsym(List *list, Symbol *sym)
void slist_data(Symbol *s, int indx, int findx)
void single_channel(Item *qsol, Symbol *fun, int numeqn, int listnum)
void vectorize_substitute(Item *q, char *str)
void prn(Item *q1, Item *q2)
void cvode_kinetic(Item *qsol, Symbol *fun, int numeqn, int listnum)
int in_solvefor(Symbol *)
void add_sens_statelist(Symbol *)
void sensmassage(int type, Item *qfun, int fn)
int const size_t const size_t n
static double remove(void *v)
struct Reaction * reactnext