1 #include <../../nmodlconf.h> 5 #include "../oc/nrnassrt.h" 35 extern char* cvode_deriv(), *cvode_eqnrhs();
36 extern Item* cvode_cnexp_solve;
38 static List* cvode_diffeq_list, *cvode_eqn;
39 static int cvode_cnexp_possible;
44 char *maxerr_str, dindepname[256];
45 char deriv1_advance[256], deriv2_advance[256];
48 if (method && strcmp(method->
name,
"cnexp") == 0) {
73 if (method->
u.
i == 1) {
74 maxerr_str =
", maxerr";
83 if (strcmp(
STR(q), fun->
name) == 0) {
88 diag(
"To use the derivimplicit method the SOLVE statement must precede the DERIVATIVE block\n",
89 " and all SOLVEs using that block must use the derivimplicit method\n");
91 Sprintf(deriv1_advance,
"_deriv%d_advance = 1;\n", listnum);
92 Sprintf(deriv2_advance,
"_deriv%d_advance = 0;\n", listnum);
93 Sprintf(
buf,
"static int _deriv%d_advance = 0;\n", listnum);
96 "\n#define _deriv%d_advance _thread[%d]._i\n" 97 "#define _dith%d %d\n" 98 "#define _recurse _thread[%d]._i\n" 99 "#define _newtonspace%d _thread[%d]._pvoid\n",
103 Sprintf(
buf,
" _thread[_dith%d]._pval = (double*)ecalloc(%d, sizeof(double));\n", listnum, 2*numeqn);
105 Sprintf(
buf,
" _newtonspace%d = nrn_cons_newtonspace(%d);\n", listnum, numeqn);
107 Sprintf(
buf,
" free((void*)(_thread[_dith%d]._pval));\n", listnum);
109 Sprintf(
buf,
" nrn_destroy_newtonspace(_newtonspace%d);\n", listnum);
113 Strcpy(deriv1_advance,
"");
114 Strcpy(deriv2_advance,
"");
116 Sprintf(
buf,
"%s %s%s(_ninits, %d, _slist%d, _dlist%d, _p, &%s, %s, %s, &_temp%d%s);\n%s",
117 deriv1_advance, ssprefix,
118 method->
name, numeqn, listnum, listnum, indepsym->
name, dindepname, fun->
name, listnum, maxerr_str,
121 Sprintf(
buf,
"%s%s(&_sparseobj%d, %d, _slist%d, _dlist%d, _p, &%s, %s, %s\ 122 ,&_coef%d, _linmat%d);\n",
123 ssprefix, method->
name, listnum, numeqn, listnum, listnum, indepsym->
name,
124 dindepname, fun->
name, listnum, listnum);
129 Sprintf(
buf,
"%s %s%s_thread(%d, _slist%d, _dlist%d, _p, %s, _ppvar, _thread, _nt);\n%s",
130 deriv1_advance, ssprefix, method->
name,
131 numeqn, listnum, listnum, fun->
name,
136 Sprintf(
buf,
"%s%s_thread(&_thread[_spth%d]._pvoid, %d, _slist%d, _dlist%d, _p, &%s, %s, %s\ 137 , _linmat%d, _ppvar, _thread, _nt);\n",
138 ssprefix, method->
name, listnum, numeqn, listnum, listnum, indepsym->
name,
139 dindepname, fun->
name, listnum);
147 " for (_i = 0; _i < %d; ++_i) {\n" 148 " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n" 149 " }}\n", numeqn, listnum, listnum);
233 #define FORALL(state,dstate) \ 234 for (state = init_forderiv(dstate); state; state = next_forderiv()) 249 if (isdigit(prime->
name[1])) {
250 if(sscanf(prime->
name + 1,
"%d%s", &
maxindx, name) != 2) {
251 diag(
"internal error in init_forderiv in init.c", (
char *)0);
259 diag(name,
"must be declared as a state variable");
262 Sprintf(
buf,
"%s and %s have different dimensions",
273 static char name[256];
275 assert(i > 0 && forderiv);
289 static char name[256];
293 if (sym->
type != PRIME) {
301 cp = name + strlen(name);
326 diag(s->
name,
"must have same dimension as associated state");
393 if (!deriv_imp_list) {
404 if (!deriv_used_list) {
410 if (!cvode_diffeq_list) {
423 int count = 0, deriv_implicit, solve_seen;
429 if (!massage_list_) { massage_list_ =
newlist(); }
437 vectorize_substitute(q,
"(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt) {int _reset=0; int error = 0;\n");
440 diag(
"DERIVATIVE merging not implemented", (
char *)0);
445 if (deriv_imp_list)
ITERATE(q, deriv_imp_list) {
446 if (strcmp(derfun->
name,
STR(q)) == 0) {
454 if (!deriv_used_list) {
455 diag(
"No derivative equations in DERIVATIVE block", (
char*)0);
468 if (state->
type == PRIME) {
469 ITERATE(q, deriv_used_list)
if (state ==
SYM(q)) {
470 diag(state->
name,
": Since higher derivative is being used, this state \ 471 is not allowed on the left hand side.");
483 Sprintf(
buf,
"for(_i=0;_i<%d;_i++){_slist%d[%d+_i] = (%s + _i) - _p;" 486 Sprintf(
buf,
" _dlist%d[%d+_i] = (%s + _i) - _p;}\n" 502 diag(
"DERIVATIVE contains no derivatives", (
char *)0);
504 derfun->
used = count;
505 Sprintf(
buf,
"static int _slist%d[%d], _dlist%d[%d];\n",
521 if (!
lookup(
"cvodematsol")) {
528 cvode_cnexp_possible = 1;
529 ITERATE(q, cvode_diffeq_list) {
533 while (qextra != q1) {
542 qextra = qextra->
next;
545 cvode_diffeq(s, q1, q2);
550 while (qextra != q4) {
559 qextra = qextra->
next;
573 if (deriv_implicit) {
574 Sprintf(
buf,
"static double _savstate%d[%d], *_temp%d = _savstate%d;\n",
595 if (deriv_implicit) {
600 Sprintf(
buf,
"{int _id; for(_id=0; _id < %d; _id++) {\n\ 601 if (_deriv%d_advance) {\n", count,
numlist);
608 "_p[_dlist%d[_id]] - (_p[_slist%d[_id]] - _savstate%d[_id])/d%s;\n",
612 "}else{\n_dlist%d[++_counte] = _p[_slist%d[_id]] - _savstate%d[_id];}}}\n",
624 if (deriv_implicit) {
626 "{int _id; for(_id=0; _id < %d; _id++) { _savstate%d[_id] = _p[_slist%d[_id]];}}\n",
627 count, derfun->
u.
i, derfun->
u.
i);
660 if (s->
name[strlen(s->
name) - 1] ==
'0') {
662 buf[strlen(
buf) - 1] =
'\0';
665 || (state->
type == PRIME)) {
671 diag(s->
name,
"must be an initial state parameter");
684 diag(state->
name,
"is not a state");
687 diag(state->
name,
"must have an index for the implicit loop");
690 diag(state->
name,
"is not an array");
711 if (blocktype != DERIVATIVE) {
712 diag(
"MATCH block can only be in DERIVATIVE block", (
char *)0);
715 if (match_bound || match_init) {
716 diag(
"Only one MATCH block allowed", (
char *)0);
719 diag(
"INDEPENDENT variable must be declared before MATCH",
728 int count, nunknown,
j;
729 Item *
q, *q1, *setup;
731 List *tmatch, *vmatch;
780 ITERATE(q1, deriv_state_list) {
795 nunknown = nderiv - count;
797 diag(
"Nothing to match", (
char *)0);
804 Lappendstr(
procfunc,
"\n_init_match(_save) double _save;{ int _i;\nif (_match_recurse) {_match_recurse = 0;\n");
805 Sprintf(
buf,
"for (_i=0; _i<%d; _i++) _found_init[_i] = _p[_state_get[_i]];\n",
808 Sprintf(
buf,
"error=shoot(%d, &(%s) - _p, _pmatch_time, _pmatch_value, _state_match,\ 809 _found_init, _p, &(d%s));\n if(error){abort_run(error);}; %s = _save;",
810 nunknown, indepsym->
name, indepsym->
name, indepsym->
name);
814 Sprintf(
buf,
"for (_i=0; _i<%d; _i++) _p[_state_get[_i]] = _found_init[_i];",
825 Sprintf(
buf,
"for (_i=0; _i<%d; _i++) {_state_get[%d+_i] = (%s + _i) - _p;}\n",
835 Sprintf(
buf,
"static int _state_get[%d], _state_match[%d];\n\ 836 static double _match_time[%d], _match_value[%d], _found_init[%d];\n",
837 nunknown, nunknown, nunknown, nunknown, nunknown);
839 Sprintf(
buf,
"static double *_pmatch_time[%d], *_pmatch_value[%d];\n",
854 Sprintf(
buf,
"for (_i=0; _i<%d; _i++) {_state_match[%d+_i] = (%s + _i) - _p;}\n",
857 Sprintf(
buf,
"{int %s; for (%s=0; %s<%d; %s++) {\n",
858 imatch, imatch, imatch, s->
araydim, imatch);
860 Sprintf(
buf,
"_match_time[%s + %d] = ", imatch, j);
863 Sprintf(
buf,
";\n _match_value[%s + %d] = ", imatch, j);
884 Sprintf(
buf,
"for(_i=0; _i<%d; _i++) { _pmatch_time[_i] = _match_time + _i;\n",
888 if (count != nderiv) {
889 Sprintf(
buf,
"%d equations != %d MATCH specs", nderiv, count);
919 for (q = q2; q != q1; q = q->
prev) {
943 for (q = qbegin; q != qend->
next; q = q->
next) {
952 cvode_cnexp_possible = 0;
970 cvode_cnexp_possible = 0;
988 if (cvode_linear_diffeq(ds, s, qbegin, qend)) {
993 for (q = qbegin; q != qend->
next; q = q->
next) {
1012 for (q = qbegin; q != qend->
next; q = q->
next) {
1035 Item*
q, *q3, *q4, *qeq;
1036 if ( cvode_cnexp_possible) {
1040 remove(deriv_imp_list->
next);
1043 qeq = cvode_eqn->
next;
1044 ITERATE(q, cvode_diffeq_list) {
1049 if (!netrec_cnexp) { netrec_cnexp =
newlist(); }
1051 if (strcmp(a,
"0.0") == 0) {
1052 assert(b[strlen(b) - 9] ==
'/');
1053 b[strlen(b) - 9] =
'\0';
1054 sprintf(
buf,
" __primary -= 0.5*dt*( %s )", b);
1058 sprintf(
buf,
" __primary += ( 1. - exp( 0.5*dt*( %s ) ) )*( %s - __primary )",
1062 sprintf(
buf,
" %s = %s + (1. - exp(dt*(%s)))*(%s - %s)",
1070 for(q3=q1->
prev->
prev; q3 != q2; q3 = q4) {
1086 fprintf(stderr,
"Could not translate using cnexp method; using derivimplicit\n");
char * reprime(Symbol *sym)
void copylist(List *, Item *)
static char * name_forderiv(int i)
char * stralloc(char *buf, char *rel)
void add_deriv_imp_list(char *name)
void matchbound(Item *q1, Item *q2, Item *q3, Item *q4, Item *q5, Symbol *sindex)
Item * mixed_eqns(Item *q2, Item *q3, Item *q4)
void solv_diffeq(Item *qsol, Symbol *fun, Symbol *method, int numeqn, int listnum, int steadystate, int btype)
#define FORALL(state, dstate)
#define ITERATE(itm, lst)
Item * lappendsym(List *list, Symbol *sym)
void massagederiv(Item *q1, Item *q2, Item *q3, Item *q4, int sensused)
void kinetic_implicit(Symbol *fun, char *dt, char *mname)
static char Derivimplicit[]
static char base_units[256]
void sensmassage(int type, Item *qfun, int fn)
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
static Symbol * init_forderiv(Symbol *prime)
Item * insertsym(Item *item, Symbol *sym)
void decode_ustr(Symbol *sym, double *pg1, double *pg2, char *s)
static List * deriv_imp_list
Symbol * ifnew_parminstall(char *name, char *num, char *units, char *limits)
void movelist(Item *q1, Item *q2, List *s)
Item * lappendstr(List *list, char *str)
void vectorize_scan_for_func(Item *q1, Item *q2)
void cvode_parse(Symbol *s, List *e)
void vectorize_substitute(Item *q, char *str)
List * thread_mem_init_list
static List * deriv_state_list
void depinstall(int type, Symbol *n, int index, char *from, char *to, char *units, Item *qs, int makeconst, char *abstol)
Item * linsertstr(List *list, char *str)
fprintf(stderr, "Don't know the location of params at %p\, pp)
void checkmatch(int blocktype)
static Symbol * next_forderiv()
NMODL parser global flags / functions.
Item * lappenditem(List *list, Item *item)
void matchinitial(Item *q1)
int cvode_cnexp_success(Item *q1, Item *q2)
List * thread_cleanup_list
void freelist(List **plist)
void deriv_used(Symbol *s, Item *q1, Item *q2)
static List * deriv_used_list
void copyitems(Item *q1, Item *q2, Item *qdest)
void replacstr(Item *q, char *s)
void slist_data(Symbol *s, int indx, int findx)
void matchmassage(int nderiv)
void add_sens_statelist(Symbol *)
insertstr(qsol->next, buf)
void kinetic_intmethod(Symbol *fun, char *meth)