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;
49 char *maxerr_str, dindepname[256];
50 char deriv1_advance[256], deriv2_advance[256];
53 if (method && strcmp(method->
name,
"cnexp") == 0) {
78 if (method->
u.
i == 1) {
79 maxerr_str =
", maxerr";
89 if (strcmp(
STR(
q), fun->
name) == 0) {
95 "To use the derivimplicit method the SOLVE statement must precede the "
97 " and all SOLVEs using that block must use the derivimplicit method\n");
99 Sprintf(deriv1_advance,
"_deriv%d_advance = 1;\n", listnum);
100 Sprintf(deriv2_advance,
"_deriv%d_advance = 0;\n", listnum);
101 Sprintf(
buf,
"static int _deriv%d_advance = 0;\n", listnum);
104 "\n#define _deriv%d_advance _thread[%d]._i\n"
105 "#define _dith%d %d\n"
106 "#define _recurse _thread[%d]._i\n"
107 "#define _newtonspace%d _thread[%d]._pvoid\n",
117 " _thread[_dith%d]._pval = (double*)ecalloc(%d, sizeof(double));\n",
121 Sprintf(
buf,
" _newtonspace%d = nrn_cons_newtonspace(%d);\n", listnum, numeqn);
123 Sprintf(
buf,
" free((void*)(_thread[_dith%d]._pval));\n", listnum);
125 Sprintf(
buf,
" nrn_destroy_newtonspace(_newtonspace%d);\n", listnum);
129 Strcpy(deriv1_advance,
"");
130 Strcpy(deriv2_advance,
"");
133 "%s %s%s(_ninits, %d, _slist%d, _dlist%d, _p, &%s, %s, %s, &_temp%d%s);\n%s",
148 "%s%s(&_sparseobj%d, %d, _slist%d, _dlist%d, _p, &%s, %s, %s\
149 ,&_coef%d, _linmat%d);\n",
166 "%s %s%s_thread(%d, _slist%d, _dlist%d, _p, %s, _ppvar, _thread, _nt);\n%s",
179 "%s%s_thread(&_thread[_spth%d]._pvoid, %d, _slist%d, _dlist%d, _p, &%s, %s, %s\
180 , _linmat%d, _ppvar, _thread, _nt);\n",
197 " if (secondorder) {\n"
199 " for (_i = 0; _i < %d; ++_i) {\n"
200 " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n"
288 #define FORALL(state, dstate) for (state = init_forderiv(dstate); state; state = next_forderiv())
302 if (isdigit(prime->
name[1])) {
304 diag(
"internal error in init_forderiv in init.c", (
char*) 0);
312 diag(
name,
"must be declared as a state variable");
324 static char name[256];
339 static char name[256];
343 if (sym->
type != PRIME) {
375 diag(s->
name,
"must have same dimension as associated state");
458 if (!cvode_diffeq_list) {
470 int count = 0, deriv_implicit, solve_seen;
473 Symbol *s, *derfun, *state;
488 "(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt) {int "
489 "_reset=0; int error = 0;\n");
492 diag(
"DERIVATIVE merging not implemented", (
char*) 0);
499 if (strcmp(derfun->
name,
STR(
q)) == 0) {
508 diag(
"No derivative equations in DERIVATIVE block", (
char*) 0);
522 if (state->
type == PRIME) {
525 ": Since higher derivative is being used, this state \
526 is not allowed on the left hand side.");
540 "for(_i=0;_i<%d;_i++){_slist%d[%d+_i] = %s_columnindex + _i;",
547 " _dlist%d[%d+_i] = %s_columnindex + _i;}\n",
557 " _dlist%d[%d] = %s_columnindex;\n",
567 diag(
"DERIVATIVE contains no derivatives", (
char*) 0);
569 derfun->
used = count;
571 "static int _slist%d[%d], _dlist%d[%d];\n",
587 "(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt) {int _reset = 0;");
593 if (!
lookup(
"cvodematsol")) {
599 "(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt) {\n");
601 cvode_cnexp_possible = 1;
611 while (qextra != q1) {
620 qextra = qextra->
next;
623 cvode_diffeq(s, q1, q2);
628 while (qextra != q4) {
637 qextra = qextra->
next;
651 if (deriv_implicit) {
653 "static double _savstate%d[%d], *_temp%d = _savstate%d;\n",
677 if (deriv_implicit) {
683 "{int _id; for(_id=0; _id < %d; _id++) {\n\
684 if (_deriv%d_advance) {\n",
693 "_p[_dlist%d[_id]] - (_p[_slist%d[_id]] - _savstate%d[_id])/d%s;\n",
700 "}else{\n_dlist%d[++_counte] = _p[_slist%d[_id]] - _savstate%d[_id];}}}\n",
714 if (deriv_implicit) {
716 "{int _id; for(_id=0; _id < %d; _id++) { _savstate%d[_id] = _p[_slist%d[_id]];}}\n",
752 if (s->
name[strlen(s->
name) - 1] ==
'0') {
754 buf[strlen(
buf) - 1] =
'\0';
762 diag(s->
name,
"must be an initial state parameter");
777 diag(state->
name,
"is not a state");
780 diag(state->
name,
"must have an index for the implicit loop");
783 diag(state->
name,
"is not an array");
804 if (blocktype != DERIVATIVE) {
805 diag(
"MATCH block can only be in DERIVATIVE block", (
char*) 0);
809 diag(
"Only one MATCH block allowed", (
char*) 0);
812 diag(
"INDEPENDENT variable must be declared before MATCH",
"statement");
819 int count, nunknown,
j;
820 Item *
q, *q1, *setup;
822 List *tmatch, *vmatch;
886 nunknown = nderiv - count;
888 diag(
"Nothing to match", (
char*) 0);
897 "\n_init_match(_save) double _save;{ int _i;\nif (_match_recurse) {_match_recurse = 0;\n");
898 Sprintf(
buf,
"for (_i=0; _i<%d; _i++) _found_init[_i] = _p[_state_get[_i]];\n", nunknown);
901 "error=shoot(%d, &(%s) - _p, _pmatch_time, _pmatch_value, _state_match,\
902 _found_init, _p, &(d%s));\n if(error){abort_run(error);}; %s = _save;",
910 Sprintf(
buf,
"for (_i=0; _i<%d; _i++) _p[_state_get[_i]] = _found_init[_i];", nunknown);
921 "for (_i=0; _i<%d; _i++) {_state_get[%d+_i] = %s_columnindex + _i;}\n",
934 "static int _state_get[%d], _state_match[%d];\n\
935 static double _match_time[%d], _match_value[%d], _found_init[%d];\n",
942 Sprintf(
buf,
"static double *_pmatch_time[%d], *_pmatch_value[%d];\n", nunknown, nunknown);
952 tmatch =
LST(
q =
q->next);
953 vmatch =
LST(
q =
q->next);
955 imatch =
STR(
q =
q->next);
957 "for (_i=0; _i<%d; _i++) {_state_match[%d+_i] = %s_columnindex + _i;}\n",
963 "{int %s; for (%s=0; %s<%d; %s++) {\n",
970 Sprintf(
buf,
"_match_time[%s + %d] = ", imatch,
j);
973 Sprintf(
buf,
";\n _match_value[%s + %d] = ", imatch,
j);
994 Sprintf(
buf,
"for(_i=0; _i<%d; _i++) { _pmatch_time[_i] = _match_time + _i;\n", nunknown);
997 if (count != nderiv) {
998 Sprintf(
buf,
"%d equations != %d MATCH specs", nderiv, count);
1009 switch (
q->itemtype) {
1026 for (
q = q2;
q != q1;
q =
q->prev) {
1027 switch (
q->itemtype) {
1048 for (
q = qbegin;
q != qend->
next;
q =
q->next) {
1049 switch (
q->itemtype) {
1057 cvode_cnexp_possible = 0;
1075 cvode_cnexp_possible = 0;
1093 if (cvode_linear_diffeq(ds, s, qbegin, qend)) {
1098 for (
q = qbegin;
q != qend->
next;
q =
q->next) {
1099 switch (
q->itemtype) {
1117 for (
q = qbegin;
q != qend->
next;
q =
q->next) {
1118 switch (
q->itemtype) {
1140 Item *
q, *q3, *q4, *qeq;
1141 if (cvode_cnexp_possible) {
1148 qeq = cvode_eqn->
next;
1167 if (strcmp(a,
"0.0") == 0) {
1168 assert(b[strlen(b) - 9] ==
'/');
1169 b[strlen(b) - 9] =
'\0';
1170 sprintf(
buf,
" __primary -= 0.5*dt*( %s )", b);
1175 " __primary += ( 1. - exp( 0.5*dt*( %s ) ) )*( %s - __primary )",
1180 " %s = %s + (1. - exp(dt*(%s)))*(%s - %s)",
1189 for (q3 = q1->
prev->
prev; q3 != q2; q3 = q4) {
1201 "(double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt) {");
1207 fprintf(stderr,
"Could not translate using cnexp method; using derivimplicit\n");
insertstr(qsol->next, buf)
#define FORALL(state, dstate)
static List * deriv_state_list
void massagederiv(Item *q1, Item *q2, Item *q3, Item *q4, int sensused)
char * reprime(Symbol *sym)
void solv_diffeq(Item *qsol, Symbol *fun, Symbol *method, int numeqn, int listnum, int steadystate, int btype)
static List * deriv_imp_list
void matchbound(Item *q1, Item *q2, Item *q3, Item *q4, Item *q5, Symbol *sindex)
void matchinitial(Item *q1)
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)
static char Derivimplicit[]
void copyitems(Item *q1, Item *q2, Item *qdest)
static List * deriv_used_list
static char base_units[256]
void add_deriv_imp_list(char *name)
void copylist(List *, Item *)
static Symbol * next_forderiv()
void matchmassage(int nderiv)
void checkmatch(int blocktype)
static Symbol * init_forderiv(Symbol *prime)
void deriv_used(Symbol *s, Item *q1, Item *q2)
static char * name_forderiv(int i)
Symbol * ifnew_parminstall(char *name, char *num, char *units, char *limits)
List * thread_cleanup_list
void kinetic_intmethod(Symbol *fun, char *meth)
void kinetic_implicit(Symbol *fun, char *dt, char *mname)
#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)
void replacstr(Item *q, char *s)
char * stralloc(char *buf, char *rel)
Item * lappenditem(List *list, Item *item)
Item * insertsym(Item *item, Symbol *sym)
Item * lappendsym(List *list, Symbol *sym)
void slist_data(Symbol *s, int indx, int findx)
void vectorize_substitute(Item *q, char *str)
void vectorize_scan_for_func(Item *q1, Item *q2)
void depinstall(int type, Symbol *n, int index, char *from, char *to, char *units, Item *qs, int makeconst, char *abstol)
int cvode_cnexp_success(Item *q1, Item *q2)
void cvode_parse(Symbol *s, List *e)
void decode_ustr(Symbol *sym, double *pg1, double *pg2, char *s)
void add_sens_statelist(Symbol *)
void sensmassage(int type, Item *qfun, int fn)
List * thread_mem_init_list
static double remove(void *v)
Item * mixed_eqns(Item *q2, Item *q3, Item *q4)