1 #include <../../nrnconf.h>
5 #include "../oc/nrnassrt.h"
45 const char* maxerr_str;
47 char deriv1_advance[256], deriv2_advance[256];
50 if (method && strcmp(method->
name,
"cnexp") == 0) {
75 if (method->
u.
i == 1) {
76 maxerr_str =
", maxerr";
86 if (strcmp(
STR(
q), fun->
name) == 0) {
92 "To use the derivimplicit method the SOLVE statement must precede the "
94 " and all SOLVEs using that block must use the derivimplicit method\n");
96 Sprintf(deriv1_advance,
"_deriv%d_advance = 1;\n", listnum);
97 Sprintf(deriv2_advance,
"_deriv%d_advance = 0;\n", listnum);
98 Sprintf(
buf,
"static int _deriv%d_advance = 0;\n", listnum);
101 "\n#define _deriv%d_advance _thread[%d].literal_value<int>()\n"
102 "#define _dith%d %d\n"
103 "#define _recurse _thread[%d].literal_value<int>()\n"
104 "#define _newtonspace%d _thread[%d].literal_value<NewtonSpace*>()\n",
113 Sprintf(
buf,
" _thread[_dith%d] = new double[%d]{};\n", listnum, 2 * numeqn);
115 Sprintf(
buf,
" _newtonspace%d = nrn_cons_newtonspace(%d);\n", listnum, numeqn);
117 Sprintf(
buf,
" delete[] _thread[_dith%d].get<double*>();\n", listnum);
119 Sprintf(
buf,
" nrn_destroy_newtonspace(_newtonspace%d);\n", listnum);
123 Strcpy(deriv1_advance,
"");
124 Strcpy(deriv2_advance,
"");
127 "%s %s%s(_ninits, %d, _slist%d, _dlist%d, neuron::scopmath::row_view{_ml, _iml}, "
128 "&%s, %s, %s, &_temp%d%s);\n%s",
144 "%s%s(&_sparseobj%d, %d, _slist%d, _dlist%d, "
145 "neuron::scopmath::row_view{_ml, _iml}, &%s, "
146 "%s, %s, &_coef%d, _linmat%d);\n",
163 "%s %s%s_thread(%d, _slist%d, _dlist%d, neuron::scopmath::row_view{_ml, _iml}, %s, "
164 "_ml, _iml, _ppvar, _thread, _globals, _nt);\n%s",
178 "%s%s_thread(&(_thread[_spth%d].literal_value<void*>()), %d, "
179 "_slist%d, _dlist%d, neuron::scopmath::row_view{_ml, _iml}, "
180 "&%s, %s, %s, _linmat%d, _threadargs_);\n",
196 " if (secondorder) {\n"
198 " for (_i = 0; _i < %d; ++_i) {\n"
199 " _ml->data(_iml, _slist%d[_i]) += dt*_ml->data(_iml, _dlist%d[_i]);\n"
283 #define FORALL(state, dstate) for (state = init_forderiv(dstate); state; state = next_forderiv())
297 if (isdigit(prime->
name[1])) {
299 diag(
"internal error in init_forderiv in init.c", (
char*) 0);
307 diag(
name,
"must be declared as a state variable");
319 static char name[256];
334 static char name[256];
338 if (sym->
type != PRIME) {
370 diag(
s->name,
"must have same dimension as associated state");
372 if (!(
s->subtype &
STAT)) {
462 int count = 0, deriv_implicit;
480 "(_internalthreadargsproto_) {\n"
482 " int error = 0;\n");
485 diag(
"DERIVATIVE merging not implemented", (
char*) 0);
492 if (strcmp(derfun->
name,
STR(
q)) == 0) {
501 diag(
"No derivative equations in DERIVATIVE block", (
char*) 0);
505 if (!(
s->subtype &
DEP) && !(
s->subtype &
STAT)) {
515 if (state->
type == PRIME) {
518 ": Since higher derivative is being used, this state \
519 is not allowed on the left hand side.");
525 int dim =
s->araydim;
527 "for(_i=0;_i<%d;_i++){_slist%d[%d+_i] = {%s_columnindex, _i};",
534 " _dlist%d[%d+_i] = {%s_columnindex, _i};}\n",
544 " _dlist%d[%d] = {%s_columnindex, 0};\n",
554 diag(
"DERIVATIVE contains no derivatives", (
char*) 0);
556 derfun->
used = count;
558 "static neuron::container::field_index _slist%d[%d], _dlist%d[%d];\n",
577 if (!
lookup(
"cvodematsol")) {
594 while (qextra != q1) {
603 qextra = qextra->
next;
611 while (qextra != q4) {
620 qextra = qextra->
next;
633 if (deriv_implicit) {
635 "static double _savstate%d[%d], *_temp%d = _savstate%d;\n",
653 if (deriv_implicit) {
659 "{int _id; for(_id=0; _id < %d; _id++) {\n\
660 if (_deriv%d_advance) {\n",
669 "_ml->data(_iml, _dlist%d[_id]) - (_ml->data(_iml, _slist%d[_id]) - "
670 "_savstate%d[_id])/d%s;\n",
678 "}else{\n_dlist%d[++_counte] = _ml->data(_iml, _slist%d[_id]) - _savstate%d[_id];}}}\n",
692 if (deriv_implicit) {
694 "for(int _id=0; _id < %d; _id++) {\n"
695 " _savstate%d[_id] = _ml->data(_iml, _slist%d[_id]);\n"
713 switch (
q->itemtype) {
730 for (
q = q2;
q != q1;
q =
q->prev) {
731 switch (
q->itemtype) {
751 for (
q = qbegin;
q != qend->
next;
q =
q->next) {
752 switch (
q->itemtype) {
801 for (
q = qbegin;
q != qend->
next;
q =
q->next) {
802 switch (
q->itemtype) {
820 for (
q = qbegin;
q != qend->
next;
q =
q->next) {
821 switch (
q->itemtype) {
843 Item *
q, *q3, *q4, *qeq;
870 if (strcmp(a,
"0.0") == 0) {
871 assert(b[strlen(b) - 9] ==
'/');
872 b[strlen(b) - 9] =
'\0';
873 Sprintf(
buf,
" __primary -= 0.5*dt*( %s )", b);
875 Sprintf(
buf,
" %s = %s - dt*(%s)",
s->name,
s->name, b);
878 " __primary += ( 1. - exp( 0.5*dt*( %s ) ) )*( %s - __primary )",
883 " %s = %s + (1. - exp(dt*(%s)))*(%s - %s)",
892 for (q3 = q1->
prev->
prev; q3 != q2; q3 = q4) {
909 fprintf(stderr,
"Could not translate using cnexp method; using derivimplicit\n");
#define FORALL(state, dstate)
List * thread_cleanup_list
static List * deriv_state_list
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
List * thread_mem_init_list
static List * cvode_diffeq_list
int cvode_cnexp_success(Item *q1, Item *q2)
void massagederiv(Item *q1, Item *q2, Item *q3, Item *q4)
static int cvode_linear_diffeq(Symbol *ds, Symbol *s, Item *qbegin, Item *qend)
static char Derivimplicit[]
void copyitems(Item *q1, Item *q2, Item *qdest)
void cvode_diffeq(Symbol *ds, Item *qbegin, Item *qend)
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()
static int cvode_cnexp_possible
static Symbol * init_forderiv(Symbol *prime)
void deriv_used(Symbol *s, Item *q1, Item *q2)
static char * name_forderiv(int i)
Symbol * ifnew_parminstall(const char *name, const char *num, const char *units, const char *limits)
void kinetic_intmethod(Symbol *fun, const char *meth)
void kinetic_implicit(Symbol *fun, const char *dt, const char *mname)
#define ITERATE(itm, lst)
Symbol * lookup(const char *)
Symbol * install(const char *, int)
char * stralloc(const char *buf, char *rel)
void movelist(Item *q1, Item *q2, List *s)
Item * linsertstr(List *list, const char *str)
void replacstr(Item *q, const char *s)
Item * lappenditem(List *list, Item *item)
Item * insertsym(Item *item, Symbol *sym)
Item * insertstr(Item *item, const char *str)
Item * lappendsym(List *list, Symbol *sym)
Item * lappendstr(List *list, const char *str)
void freelist(List *list)
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.
void depinstall(int type, Symbol *n, int index, const char *from, const char *to, const char *units, Item *qs, int makeconst, const char *abstol)
void slist_data(Symbol *s, int indx, int findx)
void vectorize_scan_for_func(Item *q1, Item *q2)
void cvode_parse(Symbol *s, List *e)
void decode_ustr(Symbol *sym, double *pg1, double *pg2, char *s)
void vectorize_substitute(Item *q, const char *str)
NMODL parser global flags / functions.
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
static double remove(void *v)
Item * mixed_eqns(Item *q2, Item *q3, Item *q4)