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  int i, ident;
86  Item* q;
87  Symbol* dspace;
88 
89  if ((dspace = lookup("delta_x")) == SYM0) {
90  dspace = install("delta_x", NAME);
91  parminstall(dspace, "1", "", "");
92  }
93  Sprintf(buf, "%s();\n", fun->name);
94  replacstr(qsol, buf);
96  ITERATE(q, parinfo) {
97  for (i = 0; i < 4; i++) {
98  pv[i] = SYM(q);
99  q = q->next;
100  }
101  partialcolon = ITM(q);
102  ident = q->itemtype;
103 
104  Sprintf(buf,
105  "if (error=crank(%d, %s, %s, %s, delta_%s, %s, %s, _pbound%d, &_parwork%d))return "
106  "error;\n",
107  pv[2]->araydim,
108  pv[2]->name,
109  pv[1]->name,
110  pv[3]->name,
111  indepsym->name,
112  dspace->name,
113  indepsym->name,
114  ident,
115  ident);
117  Sprintf(buf,
118  "static double *_pbound%d[4], _bnd%d_0, _bnd%d_N, *_parwork%d;\n",
119  ident,
120  ident,
121  ident,
122  ident);
124  }
125 }
126 
127 void partial_eqn(Item* q2, Item* q4, Item* q8, Item* q11) /*V' F V G*/
128 {
129  int i, dim;
130  Item* q;
131  static int ident = 1;
132 
133  if (!parinfo) {
134  parinfo = newlist();
135  }
136  pv[0] = SYM(q2);
137  pv[1] = SYM(q4);
138  pv[2] = SYM(q8);
139  pv[3] = SYM(q11);
140  ITERATE(q, parinfo) {
141  if (SYM(q) == SYM(q2)) {
142  diag("Two partial equations for same state: ", SYM(q8)->name);
143  }
144  q = q->next->next->next->next;
145  }
146  Lappendsym(parinfo, SYM(q2));
147  Lappendsym(parinfo, SYM(q4));
148  Lappendsym(parinfo, SYM(q8));
149  Lappendsym(parinfo, SYM(q11));
150  q = lappendsym(parinfo, SYM0);
151  ITM(q) = q2->prev;
152  q->itemtype = ident++;
153 
154  dim = pv[2]->araydim;
155  if (!(pv[2]->subtype & STAT)) {
156  diag(pv[2]->name, "is not a STATE");
157  }
158  if (strcmp(pv[2]->name, pv[0]->name + 1)) {
159  diag(pv[2]->name, "' must be the time derivative");
160  }
161  for (i = 0; i < 4; i++) {
162  if (!(pv[i]->subtype & ARRAY) || (pv[i]->araydim != dim)) {
163  diag(pv[i]->name, "dimension differs from STATE var");
164  }
165  }
166  replacstr(q2->prev, "\n/*where partial call goes*/\n");
167  partialcolon = q2->prev;
168  deltokens(q2, q11);
169 }
170 
171 static List* bndinfo; /* symbol, expression list with itemtype 0-3 */
172 static List* bnd[4]; /* for each condition consisting of
173  symbol, list of tokens for expression
174  in the order DEL y[0] DEL y[N] y[0] y[N]*/
175 
176 void massagepartial(Item* q1, Item* q2, Item* q3, Item* q6) /*PARTIAL NAME stmtlist '}'*/
177 {
178  int i, ident;
179  Item *q, *qb;
180  Symbol* s;
181 
182  static int seepartial = 0;
183  if (seepartial++) {
184  diag("Only one partial block currently allowed", (char*) 0);
185  }
186  if (!pv[0]) {
187  diag("within the PARTIAL block must occur at least one equation with the syntax ---\n",
188  "~ V' = F*DEL2(V) + G\n");
189  }
190 
191  if (!bndinfo) {
192  bndinfo = newlist();
193  }
194  ITERATE(q, parinfo) {
195  for (i = 0; i < 4; i++) {
196  pv[i] = SYM(q);
197  q = q->next;
198  bnd[i] = (List*) 0;
199  }
200  partialcolon = ITM(q);
201  ident = q->itemtype;
202  /*look through bndinfo list to reconstruct bnd*/
203  ITERATE(qb, bndinfo) {
204  s = SYM(qb);
205  qb = qb->next;
206  if (s == pv[2]) {
207  if (bnd[qb->itemtype]) {
208  diag("Duplicate boundary condition for ", s->name);
209  }
210  bnd[qb->itemtype] = LST(qb);
211  qb->itemtype = -1; /* mark used */
212  }
213  }
214 
215  /* ensure that there is one condition on each side */
216  for (i = 0; i < 2; i++) {
217  if (bnd[i]) { /* Neumann */
218  if (bnd[i + 2]) { /* and also dirichlet */
219  diag("Neumann and Dirichlet conditions", "specified on same side");
220  }
221  } else { /* Neumann not specified */
222  if (!bnd[i + 2]) { /* neither is dirichlet */
223  /* then default Neumann = 0 */
224  bnd[i] = newlist();
225  Lappendstr(bnd[i], "0");
226  }
227  }
228  }
229  /* place the boundary conditions before the call to crank */
230  /* and set up the pointers */
231  for (i = 0; i < 4; i++) {
232  if (bnd[i]) {
233  if (i % 2) {
234  Sprintf(buf, "_bnd%d_N = ", ident);
236  Sprintf(buf, "_pbound%d[%d] = &_bnd%d_N;\n", ident, i, ident);
237  } else {
238  Sprintf(buf, "_bnd%d_0 = ", ident);
240  Sprintf(buf, "_pbound%d[%d] = &_bnd%d_0;\n", ident, i, ident);
241  }
243  move(bnd[i]->next, bnd[i]->prev, partialcolon);
244  Insertstr(partialcolon, ";\n");
245  }
246  }
247  }
248  /* check that all boundary conditions have been used */
249  ITERATE(qb, bndinfo) {
250  s = SYM(qb);
251  qb = qb->next;
252  if (qb->itemtype != -1) {
253  diag("Boundary condition: No partial equation for ", s->name);
254  }
255  }
256  replacstr(q1, "int");
257  Insertstr(q3, "()\n");
258  SYM(q2)->subtype |= PARF;
259  SYM(q2)->u.i = 0; /* not used: but see listnum in solvhandler */
260  Insertstr(q6, "return 0;\n");
261  movelist(q1, q6, procfunc);
262 }
263 
264 /* ~ optionalDEL var[index] = expr */
265 /* type 0 Dirichlet (no DEL), type 1 Neumann (with DEL) */
266 void partial_bndry(int type, Item* qvar, Item* qfirstlast, Item* qexpr, Item* qlast) {
267  int indx;
268  Item* q;
269  List* l;
270 
271  if (!bndinfo) {
272  bndinfo = newlist();
273  }
274  if (SYM(qfirstlast)->type == FIRST) {
275  indx = type;
276  } else {
277  indx = type + 1;
278  }
279  Lappendsym(bndinfo, SYM(qvar));
280  q = lappendsym(bndinfo, SYM0);
281  q->itemtype = indx;
282  l = newlist();
283  LST(q) = l;
284 
285  if (indx < 2) { /* ~ DEL y [N] = */
286  deltokens(qvar->prev->prev, qexpr->prev);
287  } else { /* ~ ... = */
288  deltokens(qvar->prev, qexpr->prev);
289  }
290  movelist(qexpr, qlast, l);
291 }
short type
Definition: cabvars.h:9
static int indx
Definition: deriv.cpp:294
#define diag(s)
Definition: fmenu.cpp:192
char buf[512]
Definition: init.cpp:13
#define i
Definition: md1redef.h:12
#define SYM0
Definition: model.h:74
#define STAT
Definition: model.h:117
#define ITERATE(itm, lst)
Definition: model.h:25
#define Linsertstr
Definition: model.h:243
#define Lappendstr
Definition: model.h:245
#define Insertstr
Definition: model.h:240
#define PARF
Definition: model.h:130
#define ITM(q)
Definition: model.h:88
#define SYM(q)
Definition: model.h:86
#define Sprintf
Definition: model.h:233
#define LST(q)
Definition: model.h:90
#define Lappendsym
Definition: model.h:244
#define ARRAY
Definition: model.h:118
NMODL parser global flags / functions.
List * procfunc
Definition: init.cpp:9
char * name
Definition: init.cpp:16
List * initlist
Definition: init.cpp:8
long subtype
Definition: init.cpp:215
void movelist(Item *q1, Item *q2, List *s)
Definition: list.cpp:220
Item * prev(Item *item)
Definition: list.cpp:93
void replacstr(Item *q, char *s)
Definition: list.cpp:225
Item * next(Item *item)
Definition: list.cpp:88
void deltokens(Item *q1, Item *q2)
Definition: list.cpp:195
List * newlist()
Definition: list.cpp:47
Item * lappendsym(List *list, Symbol *sym)
Definition: list.cpp:142
void parminstall(Symbol *n, char *num, char *units, char *limits)
Definition: parsact.cpp:159
void save_dt(Item *)
Definition: solve.cpp:356
size_t q
virtual void move(const Event &e)
Definition: ocinput.h:26
static List * parinfo
Definition: partial.cpp:82
void solv_partial(Item *qsol, Symbol *fun)
Definition: partial.cpp:84
static List * bndinfo
Definition: partial.cpp:171
static Symbol * pv[4]
Definition: partial.cpp:80
void massagepartial(Item *q1, Item *q2, Item *q3, Item *q6)
Definition: partial.cpp:176
void partial_eqn(Item *q2, Item *q4, Item *q8, Item *q11)
Definition: partial.cpp:127
static Item * partialcolon
Definition: partial.cpp:81
void partial_bndry(int type, Item *qvar, Item *qfirstlast, Item *qexpr, Item *qlast)
Definition: partial.cpp:266
static List * bnd[4]
Definition: partial.cpp:172
Symbol * indepsym
Definition: declare.cpp:11
#define lookup
Definition: redef.h:90
#define install
Definition: redef.h:82
Definition: model.h:15
struct Item * prev
Definition: model.h:20
short itemtype
Definition: model.h:16
struct Item * next
Definition: model.h:19
Definition: model.h:57
int araydim
Definition: model.h:67
char * name
Definition: model.h:72
static Item * qexpr[3]
Definition: units1.cpp:66