NEURON
sens.cpp
Go to the documentation of this file.
1 #include <../../nmodlconf.h>
2 /* /local/src/master/nrn/src/nmodl/sens.c,v 4.2 1997/11/28 15:11:43 hines Exp */
3 /*
4 sens.c,v
5  * Revision 4.2 1997/11/28 15:11:43 hines
6  * absolute tolerance for CVODE on a per state basis.
7  * Interface is a spec of absolute tolerance within a .mod file for the
8  * declaration of a STATE as in
9  * state (units) <tolerance>
10  * Within nrniv, one specifies tolerance via
11  * tol = cvode.abstol(&var, tolerance) where var is any variable whose address
12  * can be taken (although only STATEs make use of a tolerance).
13  * The address aspect of the above is misleading since tolerances are the
14  * same for any single name, eg cvode.abstol(&v(.5)) changes tolerances for
15  * ALL membrane potentials globally. The only purpose of the address is
16  * to unambiguously identify the Symbol for the name. Perhaps string spec
17  * such as "TrigKSyn.G" will be incorporated in the future.
18  * when an absolute tolerance is changed, cvode will re-initialize the
19  * tolerances next time Cvode.re_init is called. The tolerance actually
20  * used for a STATE is the minimum between the value specified in the second
21  * arg of cvode.accuracy and the tolerance stored in the Symbol.
22  *
23  * Revision 4.1 1997/08/30 20:45:34 hines
24  * cvs problem with branches. Latest nmodl stuff should now be a top level
25  *
26  * Revision 4.0.1.1 1997/08/08 17:24:01 hines
27  * nocmodl version 4.0.1
28  *
29  * Revision 4.0 1997/08/08 17:06:28 hines
30  * proper nocmodl version number
31  *
32  * Revision 1.2 1995/09/05 17:57:58 hines
33  * allow domain limit in parameter spec. the syntax is of the form
34  * name '=' number units '[' number ',' number ']'
35  * The brackets may be changed to <...> if the syntax for arrays is ambiguous
36  *
37  * Revision 1.1.1.1 1994/10/12 17:21:37 hines
38  * NEURON 3.0 distribution
39  *
40  * Revision 9.76 90/12/07 09:27:25 hines
41  * new list structure that uses unions instead of void *element
42  *
43  * Revision 9.58 90/11/20 17:24:17 hines
44  * CONSTANT changed to PARAMETER
45  * CONSTANT now refers to variables that don't get put in .var file
46  *
47  * Revision 9.45 90/10/30 13:56:56 hines
48  * derivative blocks (this impacts kinetic and sens as well) now return
49  * _reset which can be set with RESET statement. _reset is static in the
50  * file and set to 0 on entry to a derivative or kinetic block.
51  *
52  * Revision 9.32 90/10/08 14:12:55 hines
53  * index vector instead of pointer vector for slist and dlist
54  *
55  * Revision 8.2 90/02/07 10:23:23 mlh
56  * It is important that blocks for derivative and sensitivity also
57  * be declared static before their possible use as arguments to other
58  * functions and that their body also be static to avoid multiple
59  * declaration errors.
60  *
61  * Revision 8.1 90/01/16 11:06:16 mlh
62  * error checking and cleanup after error and call to abort_run()
63  *
64  * Revision 8.0 89/09/22 17:26:57 nfh
65  * Freezing
66  *
67  * Revision 7.0 89/08/30 13:32:33 nfh
68  * Rev 7 is now Experimental; Rev 6 is Testing
69  *
70  * Revision 6.0 89/08/14 16:27:13 nfh
71  * Rev 6.0 is latest of 4.x; now the Experimental version
72  *
73  * Revision 4.1 89/08/07 15:35:26 mlh
74  * freelist now takes pointer to list pointer and 0's the list pointer.
75  * Not doing this is a bug for multiple sens blocks, etc.
76  *
77  * Revision 4.0 89/07/24 17:03:43 nfh
78  * Freezing rev 3. Rev 4 is now Experimental
79  *
80  * Revision 3.2 89/07/18 11:55:19 mlh
81  * first_time removed and MODEL_LEVEL used for declaration precedence
82  *
83  * Revision 1.2 89/07/18 11:22:19 mlh
84  * eliminate first_time, etc.
85  *
86  * Revision 1.1 89/07/06 14:50:34 mlh
87  * Initial revision
88  *
89 */
90 
91 #include "modl.h"
92 #include "parse1.hpp"
93 
94 static List *sensinfo; /* list of pairs: first is the block symbol where
95  the SENS statement appeared. The second is
96  a list of statements which goes after the
97  SOLVE statement. Used for NONLINEAR blocks.
98  So far sensmassage gets control when
99  massageblock is almost finished
100  */
101 static List *statelist;
102 static List *parmlist;
103 extern Symbol *indepsym;
104 int sens_parm = 0;
105 
106 void sensparm(Item* qparm)
107 {
108  if (!parmlist)
109  parmlist = newlist();
110  Lappendsym(parmlist, SYM(qparm));
111  sens_parm++;
112 }
113 
115 {
116  if (!statelist)
117  statelist = newlist();
118  Lappendsym(statelist, s);
119 }
120 
121 void sensmassage(int type, Item* qfun, int fn)
122 {
123 /*qfun is the list symbol for the name of the derivative block. It has
124 a count of the number of state variables used. A copy of this symbol
125 is made but with the name S_name and qfun is made to point to the new symbol
126 The old function name is then the name of a new created function which
127 contains the calls to trajecsens followed by a call to S_name to compute the
128 Note that trajecsens itself contains calls to S_name.
129 qfun->sym->used is then multiplied by the (1 + #sens parms used) so that
130 the solve code doesn't need to be changed.
131 
132 The slist needs to be augmented and that is done here also. However
133 since it is declared in solve.c it is necessary to access the number
134 of parameters being used.
135 */
136 
137 /* extending to nonlinear blocks. Differences:
138 Number of states remains the same. Statements built here but saved for output
139 when SOLVE is translated. No derivative variables constructed.
140 However, the full dlist is constructed since we need the last part
141 for use by EM variables
142 This has gotten much more difficult to understand since the nonlinear method
143 is merged into the code to take advantage of common code. It would be
144 conceptually simpler to merely repeat the whole process in a separate file*/
145 /* extending to linear blocks. Same as nonlinear except that
146 there is a linearsens call and we must be sure to keep proper state order */
147  int nstate, i, j, newjac;
148  char sname[256], dname[257];
149  Item *q, *q1;
150  List *senstmt; /* nonlinear sens statements (saved in sensinfo) */
151  Symbol *oldfun, *newfun, *s;
152 
153  oldfun = SYM(qfun);
154  Sprintf(buf, "S_%s", oldfun->name);
155  if (lookup(buf)) {
156  diag(buf, "is user defined and cant be used for SENS");
157  }
158  /*this is a time bomb*/
159  newfun = install(buf, oldfun->type);
160  newfun->subtype = oldfun->subtype;
161  newfun->u.i = oldfun->u.i; /*the listnum*/
162  newfun->used = oldfun->used; /*number of states*/
163  nstate = oldfun->used;
164  if (type == DERIVATIVE) {
165  oldfun->used *= (1 + sens_parm);
166  }
167 /* even derivatives need sensinfo since envelope statements go after the
168 SOLVE for statement */
169  if (!sensinfo) {
170  sensinfo = newlist();
171  }
172  Lappendsym(sensinfo, oldfun); /* newton will call oldfun
173  which will merely call newfun */
174  q = lappendsym(sensinfo, SYM0); /* the second element is a list
175  of statements to be constructed below */
176  senstmt = newlist();
177  LST(q) = senstmt;
178 
179  SYM(qfun) = newfun; /* the derivative equations alone are now
180  called newfun->name; oldfun will contain
181  the trajecsens calls */
182 
183  /* build the oldfun function */
184  /* In the nonlinear case all statements except call to newfun get
185  sent to senstmt */
186  /* in the derivative case envelope statements get sent to senstmt */
187  Sprintf(buf, "\nstatic int %s() {\n", oldfun->name);
189  Sprintf(buf, "\nstatic int %s();\n", newfun->name);
191  newjac = 1;
192  i=1;
193  ITERATE(q, parmlist) {
194 
195 if (type == DERIVATIVE) {
196  Sprintf(buf, "error=trajecsens(%d, _slist%d, _dlist%d,\
197 _p, &%s, %s, %s, %d, _slist%d+%d, _dlist%d+%d);\n if(error){abort_run(error);}\n",
198 nstate,
199 fn, fn,
200 SYM(q)->name, newfun->name, indepsym->name, newjac,
201 fn, nstate*i,
202 fn, nstate*i);
204 }else if (type == NONLINEAR) {
205  Sprintf(buf, "error=steadysens(%d, _slist%d, _p, &%s, %s,\
206  _dlist%d, %d, _slist%d+%d);\n if(error){abort_run(error);}\n",
207  nstate,
208  fn,
209  SYM(q)->name, newfun->name, fn, newjac,
210  fn, nstate*i);
211  Lappendstr(senstmt, buf);
212 }else if (type == LINEAR) {
213  Sprintf(buf, "error=linearsens(%d, _slist%d, _p, &%s, %s,\
214  _coef%d, %d, _slist%d+%d);\n if(error){abort_run(error);}\n",
215  nstate,
216  fn,
217  SYM(q)->name, newfun->name, fn, newjac,
218  fn, nstate*i);
219  Lappendstr(senstmt, buf);
220 }
221  newjac = 0;
222  /* define S_state_parm and DS_state_parm */
223  ITERATE(q1, statelist) {
224  j = SYM(q1)->varnum;
225  Sprintf(sname, "S_%s_%s", SYM(q1)->name, SYM(q)->name);
226  Sprintf(dname, "D%s", sname);
227  if ((s = lookup(sname)) == SYM0) {
228  s = install(sname, NAME);
229  }
230  if (SYM(q1)->subtype & ARRAY) {
231 depinstall(1, s, SYM(q1)->araydim, "0", "1", "", ITEM0, 0, "");
232  }else{
233  depinstall(1, s, 0, "0", "1", "", ITEM0, 0, "");
234  }
235  s->usage |= DEP;
236 if (type == DERIVATIVE) {
237  s = lookup(dname);
238  assert (s);
239  s->usage |= DEP;
240  /* initialize augmented _slist and _dlist */
241  if (SYM(q1)->subtype & ARRAY) {
242 Sprintf(buf, "for (_i=0;_i<%d;_i++){\
243 _slist%d[%d+_i] = (%s + _i) - _p; _dlist%d[%d+_i] = (%s + _i) - _p;}\n", SYM(q1)->araydim,
244 fn, j + nstate*i, sname, fn, j + nstate*i, dname);
245  }else{
246 Sprintf(buf, "_slist%d[%d] = &(%s) - _p; _dlist%d[%d] = &(%s) - _p;\n",
247 fn, j + nstate*i, sname, fn, j + nstate*i, dname);
248  }
249 }else if (type == NONLINEAR || type == LINEAR) {
250  if (SYM(q1)->subtype & ARRAY) {
251  Sprintf(buf, "for (_i=0;_i<%d;_i++){\
252 _slist%d[%d+_i] = (%s + _i) - _p;}\n", SYM(q1)->araydim,
253  fn, j + nstate*i, sname);
254  }else{
255  Sprintf(buf, "_slist%d[%d] = &(%s) - _p;\n",
256  fn, j + nstate*i, sname);
257  }
258 }
260  }
261  i++;
262  }
263 
264 /* addition of envelope calls by modifying copy of above code
265  create EP_state_parm, EM_state_parm using a new eplist and emlist
266  respectively. Also create U_parm with default value of .05 if it
267  doesn't already exist as a constant.
268  */
269 
270 Sprintf(buf, "static int _eplist%d[%d], _emlist%d[%d];\n",
271  fn, nstate*sens_parm, fn, nstate*sens_parm);
273  i = 0;
274  ITERATE(q, parmlist) {
275 
276  Sprintf(buf, "envelope(_p, _slist%d, %d, %s, U_%s,\
277 _slist%d+%d, _eplist%d + %d, _emlist%d + %d);\n",
278 fn, nstate,
279 SYM(q)->name, SYM(q)->name,
280 fn, nstate*(1 + i),
281 fn, nstate*i,
282 fn, nstate*i);
283  Lappendstr(senstmt, buf);
284 
285  /* define the uncertainty variables */
286  Sprintf(buf, "U_%s", SYM(q)->name);
287  IGNORE(ifnew_parminstall(buf, "0.05", "", ""));
288  /* define EP_state_parm and EM_state_parm */
289  ITERATE(q1, statelist) {
290  j = SYM(q1)->varnum;
291  Sprintf(sname, "EP_%s_%s", SYM(q1)->name, SYM(q)->name);
292  Sprintf(dname, "EM_%s_%s", SYM(q1)->name, SYM(q)->name);
293  if ((s = lookup(sname)) == SYM0) {
294  s = install(sname, NAME);
295  }
296  if (SYM(q1)->subtype & ARRAY) {
297 depinstall(0, s, SYM(q1)->araydim, "0", "1", "", ITEM0, 0, "");
298  }else{
299  depinstall(0, s, 0, "0", "1", "", ITEM0, 0, "");
300  }
301  s->usage |= DEP;
302 
303  if ((s = lookup(dname)) == SYM0) {
304  s = install(dname, NAME);
305  }
306  if (SYM(q1)->subtype & ARRAY) {
307 depinstall(0, s, SYM(q1)->araydim, "0", "1", "", ITEM0, 0, "");
308  }else{
309  depinstall(0, s, 0, "0", "1", "", ITEM0, 0, "");
310  }
311  s->usage |= DEP;
312 
313  /* initialize augmented _slist and _dlist */
314  if (SYM(q1)->subtype & ARRAY) {
315 Sprintf(buf, "for (_i=0;_i<%d;_i++){\
316 _eplist%d[%d+_i] = (%s + _i) - _p; _emlist%d[%d+_i] = (%s + _i) - _p;}\n", SYM(q1)->araydim,
317 fn, j + nstate*i, sname, fn, j + nstate*i, dname);
318  }else{
319 Sprintf(buf, "_eplist%d[%d] = &(%s) - _p; _emlist%d[%d] = &(%s) - _p;\n",
320 fn, j + nstate*i, sname, fn, j + nstate*i, dname);
321  }
323  }
324  i++;
325  }
326  if (type == DERIVATIVE) {
327  Sprintf(buf, "return %s();\n}\n", newfun->name);
328  }else{
329  Sprintf(buf, "%s();\n}\n", newfun->name);
330  }
332  freelist(&parmlist);
333  freelist(&statelist);
334  sens_parm = 0;
335 }
336 
338 {
339  /* find fun in the sensinfo list and insert its statements before q */
340 
341  Item *q1, *q2, *q3;
342 
343  if (!sensinfo) return;
344  ITERATE(q1, sensinfo) {
345  q2 = q1->next;
346  if (SYM(q1) == fun) {
347  ITERATE(q3, LST(q2)) {
348  Insertstr(q, STR(q3));
349  }
350  }
351  q1 = q2;
352  }
353 }
#define Lappendsym
Definition: model.h:259
#define assert(ex)
Definition: hocassrt.h:26
short type
Definition: cabvars.h:10
static List * sensinfo
Definition: sens.cpp:94
int usage
Definition: model.h:66
short type
Definition: model.h:58
#define diag(s)
Definition: fmenu.cpp:188
#define DEP
Definition: model.h:116
#define ITERATE(itm, lst)
Definition: model.h:25
#define SYM(q)
Definition: model.h:86
#define ITEM0
Definition: model.h:22
Item * lappendsym(List *list, Symbol *sym)
Definition: list.cpp:161
List * initlist
Definition: init.cpp:8
Symbol * indepsym
Definition: declare.cpp:11
char * name
Definition: model.h:72
void add_sens_statelist(Symbol *s)
Definition: sens.cpp:114
struct Item * next
Definition: model.h:19
int i
Definition: model.h:62
void sensparm(Item *qparm)
Definition: sens.cpp:106
#define IGNORE(arg)
Definition: model.h:262
Definition: model.h:15
Symbol * ifnew_parminstall(char *name, char *num, char *units, char *limits)
Definition: parsact.cpp:177
#define Insertstr
Definition: model.h:255
#define install
Definition: redef.h:82
_CONST char * s
Definition: system.cpp:74
#define ARRAY
Definition: model.h:118
List * procfunc
Definition: init.cpp:9
static int nstate
Definition: simultan.cpp:192
void depinstall(int type, Symbol *n, int index, char *from, char *to, char *units, Item *qs, int makeconst, char *abstol)
Definition: parsact.cpp:297
size_t j
Definition: model.h:57
char * name
Definition: init.cpp:16
#define LST(q)
Definition: model.h:90
List * newlist()
Definition: list.cpp:50
void sens_nonlin_out(Item *q, Symbol *fun)
Definition: sens.cpp:337
#define Lappendstr
Definition: model.h:260
NMODL parser global flags / functions.
#define lookup
Definition: redef.h:90
long subtype
Definition: model.h:59
int used
Definition: model.h:65
#define STR(q)
Definition: model.h:87
void freelist(List **plist)
Definition: list.cpp:61
long subtype
Definition: init.cpp:122
static List * parmlist
Definition: sens.cpp:102
#define i
Definition: md1redef.h:12
void sensmassage(int type, Item *qfun, int fn)
Definition: sens.cpp:121
#define Linsertstr
Definition: model.h:258
char buf[512]
Definition: init.cpp:13
#define Sprintf
Definition: model.h:248
union Symbol::@18 u
#define SYM0
Definition: model.h:74
size_t q
int sens_parm
Definition: sens.cpp:104
static List * statelist
Definition: sens.cpp:101