NEURON
partial.cpp
Go to the documentation of this file.
1 #include <../../nmodlconf.h>
2 /* /local/src/master/nrn/src/nmodl/partial.c,v 4.1 1997/08/30 20:45:33 hines Exp */
3 /*
4 partial.c,v
5  * Revision 4.1 1997/08/30 20:45:33 hines
6  * cvs problem with branches. Latest nmodl stuff should now be a top level
7  *
8  * Revision 4.0.1.1 1997/08/08 17:24:00 hines
9  * nocmodl version 4.0.1
10  *
11  * Revision 4.0 1997/08/08 17:06:28 hines
12  * proper nocmodl version number
13  *
14  * Revision 1.1.1.1 1994/10/12 17:21:37 hines
15  * NEURON 3.0 distribution
16  *
17  * Revision 9.76 90/12/07 09:27:23 hines
18  * new list structure that uses unions instead of void *element
19  *
20  * Revision 9.67 90/11/27 12:10:07 hines
21  * bug in bnd introduced by change to partial
22  *
23  * Revision 9.66 90/11/27 10:47:26 hines
24  * allow multiple partial equations within a partial block
25  *
26  * Revision 9.58 90/11/20 17:24:15 hines
27  * CONSTANT changed to PARAMETER
28  * CONSTANT now refers to variables that don't get put in .var file
29  *
30  * Revision 9.20 90/08/15 15:16:16 hines
31  * need to pass error value from crank back through the
32  * block called by SOLVE.
33  *
34  * Revision 8.1 90/01/16 11:06:14 mlh
35  * error checking and cleanup after error and call to abort_run()
36  *
37  * Revision 8.0 89/09/22 17:26:54 nfh
38  * Freezing
39  *
40  * Revision 7.0 89/08/30 13:32:29 nfh
41  * Rev 7 is now Experimental; Rev 6 is Testing
42  *
43  * Revision 6.0 89/08/14 16:27:10 nfh
44  * Rev 6.0 is latest of 4.x; now the Experimental version
45  *
46  * Revision 4.1 89/07/27 13:27:30 mlh
47  * crank calling sequence sends indepsym as a sentinal value
48  * ugh!
49  *
50  * Revision 4.0 89/07/24 17:03:40 nfh
51  * Freezing rev 3. Rev 4 is now Experimental
52  *
53  * Revision 3.3 89/07/18 11:55:16 mlh
54  * first_time removed and MODEL_LEVEL used for declaration precedence
55  *
56  * Revision 1.4 89/07/18 11:22:16 mlh
57  * eliminate first_time, etc.
58  *
59  * Revision 1.3 89/07/11 16:51:58 mlh
60  * remove p array from calling sequence of crank
61  *
62  * Revision 1.2 89/07/07 08:55:01 mlh
63  * START field in INDEPENDENT block
64  * SWEEP keyword replaces SCOP in INDEPENDENT block
65  * FIRST and LAST keywords in PARTIAL block for boundaries rplace index
66  * y'0 etc. allowed for constants
67  *
68  * Revision 1.1 89/07/06 14:50:25 mlh
69  * Initial revision
70  *
71 */
72 
73 #include "modl.h"
74 #include "parse1.hpp"
75 #include "symbol.h"
76 
77 extern Symbol *indepsym;
78 
79 /* for partial block communication with solve */
80 static Symbol *pv[4]; /* DV, F, V, G */
82 static List *parinfo; /* DV, F, V, G, ~ with ident */
83 
84 void solv_partial(Item* qsol, Symbol* fun)
85 {
86  int i, ident;
87  Item *q;
88  Symbol *dspace;
89 
90  if ((dspace = lookup("delta_x")) == SYM0) {
91  dspace = install("delta_x", NAME);
92  parminstall(dspace, "1", "", "");
93  }
94  Sprintf(buf, "%s();\n", fun->name);
95  replacstr(qsol, buf);
96  save_dt(partialcolon);
97  ITERATE(q, parinfo) {
98  for (i=0; i<4; i++) {
99  pv[i] = SYM(q);
100  q = q->next;
101  }
102  partialcolon = ITM(q);
103  ident = q->itemtype;
104 
105 Sprintf(buf, "if (error=crank(%d, %s, %s, %s, delta_%s, %s, %s, _pbound%d, &_parwork%d))return error;\n",
106  pv[2]->araydim, pv[2]->name, pv[1]->name, pv[3]->name,
107  indepsym->name, dspace->name, indepsym->name, ident, ident);
108  replacstr(partialcolon, buf);
109  Sprintf(buf, "static double *_pbound%d[4], _bnd%d_0, _bnd%d_N, *_parwork%d;\n",
110  ident, ident, ident, ident);
112  }
113 }
114 
115 void partial_eqn(Item* q2, Item* q4, Item* q8, Item* q11) /*V' F V G*/
116 {
117  int i, dim;
118  Item *q;
119  static int ident=1;
120 
121  if (!parinfo) {
122  parinfo = newlist();
123  }
124  pv[0] = SYM(q2);
125  pv[1] = SYM(q4);
126  pv[2] = SYM(q8);
127  pv[3] = SYM(q11);
128  ITERATE(q, parinfo) {
129  if (SYM(q) == SYM(q2)) {
130 diag("Two partial equations for same state: ", SYM(q8)->name);
131  }
132  q = q->next->next->next->next;
133  }
134  Lappendsym(parinfo, SYM(q2));
135  Lappendsym(parinfo, SYM(q4));
136  Lappendsym(parinfo, SYM(q8));
137  Lappendsym(parinfo, SYM(q11));
138  q = lappendsym(parinfo, SYM0);
139  ITM(q) = q2->prev;
140  q->itemtype = ident++;
141 
142  dim = pv[2]->araydim;
143  if (!(pv[2]->subtype & STAT)){
144  diag(pv[2]->name, "is not a STATE");
145  }
146  if (strcmp(pv[2]->name, pv[0]->name + 1)) {
147  diag(pv[2]->name, "' must be the time derivative");
148  }
149  for (i=0; i<4; i++) {
150  if (!(pv[i]->subtype & ARRAY) || (pv[i]->araydim != dim)) {
151  diag(pv[i]->name, "dimension differs from STATE var");
152  }
153  }
154  replacstr(q2->prev, "\n/*where partial call goes*/\n");
155  partialcolon = q2->prev;
156  deltokens(q2, q11);
157 }
158 
159 static List *bndinfo; /* symbol, expression list with itemtype 0-3 */
160 static List *bnd[4]; /* for each condition consisting of
161  symbol, list of tokens for expression
162  in the order DEL y[0] DEL y[N] y[0] y[N]*/
163 
164 void massagepartial(Item* q1, Item* q2, Item* q3, Item* q6) /*PARTIAL NAME stmtlist '}'*/
165 {
166 
167  int i, ident;
168  Item *q, *qb;
169  Symbol *s;
170 
171  static int seepartial = 0;
172  if (seepartial++) {
173  diag("Only one partial block currently allowed", (char *)0);
174  }
175  if (!pv[0]) {
176 diag(
177  "within the PARTIAL block must occur at least one equation with the syntax ---\n",
178  "~ V' = F*DEL2(V) + G\n");
179  }
180 
181  if (!bndinfo) {
182  bndinfo = newlist();
183  }
184  ITERATE(q, parinfo) {
185  for (i=0; i<4; i++) {
186  pv[i] = SYM(q);
187  q = q->next;
188  bnd[i] = (List *)0;
189  }
190  partialcolon = ITM(q);
191  ident = q->itemtype;
192  /*look through bndinfo list to reconstruct bnd*/
193  ITERATE(qb, bndinfo) {
194  s = SYM(qb); qb = qb->next;
195  if (s == pv[2]) {
196  if (bnd[qb->itemtype]) {
197 diag("Duplicate boundary condition for ", s->name);
198  }
199  bnd[qb->itemtype] = LST(qb);
200  qb->itemtype = -1; /* mark used */
201  }
202  }
203 
204  /* ensure that there is one condition on each side */
205  for (i=0; i<2; i++) {
206  if (bnd[i]) { /* Neumann */
207  if (bnd[i+2]) { /* and also dirichlet */
208  diag("Neumann and Dirichlet conditions",
209  "specified on same side");
210  }
211  } else { /* Neumann not specified */
212  if (!bnd[i+2]) { /* neither is dirichlet */
213  /* then default Neumann = 0 */
214  bnd[i] = newlist();
215  Lappendstr(bnd[i], "0");
216  }
217  }
218  }
219  /* place the boundary conditions before the call to crank */
220  /* and set up the pointers */
221  for (i=0; i<4; i++) {
222  if (bnd[i]) {
223  if (i%2) {
224  Sprintf(buf, "_bnd%d_N = ", ident);
225  Insertstr(partialcolon, buf);
226  Sprintf(buf, "_pbound%d[%d] = &_bnd%d_N;\n",
227  ident, i, ident);
228  }else{
229  Sprintf(buf, "_bnd%d_0 = ", ident);
230  Insertstr(partialcolon, buf);
231  Sprintf(buf, "_pbound%d[%d] = &_bnd%d_0;\n",
232  ident, i, ident);
233  }
235  move(bnd[i]->next, bnd[i]->prev, partialcolon);
236  Insertstr(partialcolon, ";\n");
237  }
238  }
239  }
240  /* check that all boundary conditions have been used */
241  ITERATE(qb, bndinfo) {
242  s = SYM(qb);
243  qb = qb->next;
244  if (qb->itemtype != -1) {
245  diag("Boundary condition: No partial equation for ",
246  s->name);
247  }
248  }
249  replacstr(q1, "int");
250  Insertstr(q3, "()\n");
251  SYM(q2)->subtype |= PARF;
252  SYM(q2)->u.i = 0; /* not used: but see listnum in solvhandler */
253  Insertstr(q6, "return 0;\n");
254  movelist(q1, q6, procfunc);
255 }
256 
257 /* ~ optionalDEL var[index] = expr */
258 /* type 0 Dirichlet (no DEL), type 1 Neumann (with DEL) */
259 void partial_bndry(int type, Item* qvar, Item* qfirstlast, Item* qexpr, Item* qlast)
260 {
261  int indx;
262  Item *q;
263  List *l;
264 
265  if (!bndinfo) {
266  bndinfo = newlist();
267  }
268  if (SYM(qfirstlast)->type == FIRST) {
269  indx = type;
270  }else{
271  indx = type + 1;
272  }
273  Lappendsym(bndinfo, SYM(qvar));
274  q = lappendsym(bndinfo, SYM0);
275  q->itemtype = indx;
276  l = newlist();
277  LST(q) = l;
278 
279  if (indx < 2) { /* ~ DEL y [N] = */
280  deltokens(qvar->prev->prev, qexpr->prev);
281  }else{ /* ~ ... = */
282  deltokens(qvar->prev, qexpr->prev);
283  }
284  movelist(qexpr, qlast, l);
285 }
void deltokens(Item *q1, Item *q2)
Definition: list.cpp:219
#define Lappendsym
Definition: model.h:259
short itemtype
Definition: model.h:16
short type
Definition: cabvars.h:10
void massagepartial(Item *q1, Item *q2, Item *q3, Item *q6)
Definition: partial.cpp:164
#define diag(s)
Definition: fmenu.cpp:188
#define ITERATE(itm, lst)
Definition: model.h:25
#define SYM(q)
Definition: model.h:86
Item * lappendsym(List *list, Symbol *sym)
Definition: list.cpp:161
List * initlist
Definition: init.cpp:8
char * name
Definition: model.h:72
struct Item * prev
Definition: model.h:20
Item * next(Item *item)
Definition: list.cpp:95
struct Item * next
Definition: model.h:19
Definition: model.h:15
static List * bnd[4]
Definition: partial.cpp:160
Item * prev(Item *item)
Definition: list.cpp:101
#define Insertstr
Definition: model.h:255
#define install
Definition: redef.h:82
void parminstall(Symbol *n, char *num, char *units, char *limits)
Definition: parsact.cpp:161
void movelist(Item *q1, Item *q2, List *s)
Definition: list.cpp:245
_CONST char * s
Definition: system.cpp:74
#define ARRAY
Definition: model.h:118
static int indx
Definition: deriv.cpp:240
List * procfunc
Definition: init.cpp:9
void partial_eqn(Item *q2, Item *q4, Item *q8, Item *q11)
Definition: partial.cpp:115
#define PARF
Definition: model.h:130
static List * bndinfo
Definition: partial.cpp:159
void solv_partial(Item *qsol, Symbol *fun)
Definition: partial.cpp:84
Definition: model.h:57
char * name
Definition: init.cpp:16
#define LST(q)
Definition: model.h:90
static List * parinfo
Definition: partial.cpp:82
List * newlist()
Definition: list.cpp:50
virtual void move(const Event &e)
Definition: ocinput.h:19
#define Lappendstr
Definition: model.h:260
NMODL parser global flags / functions.
#define lookup
Definition: redef.h:90
static Item * partialcolon
Definition: partial.cpp:81
void save_dt(Item *)
Definition: solve.cpp:352
int araydim
Definition: model.h:67
long subtype
Definition: init.cpp:122
#define i
Definition: md1redef.h:12
void partial_bndry(int type, Item *qvar, Item *qfirstlast, Item *qexpr, Item *qlast)
Definition: partial.cpp:259
#define Linsertstr
Definition: model.h:258
char buf[512]
Definition: init.cpp:13
#define STAT
Definition: model.h:117
void replacstr(Item *q, char *s)
Definition: list.cpp:250
static Item * qexpr[3]
Definition: units1.cpp:69
#define Sprintf
Definition: model.h:248
#define SYM0
Definition: model.h:74
static Symbol * pv[4]
Definition: partial.cpp:80
size_t q
#define ITM(q)
Definition: model.h:88
Symbol * indepsym
Definition: declare.cpp:11