NEURON
nonlin.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include "hoc.h"
5 #include "parse.hpp"
6 #include "hocparse.h"
7 #include "equation.h"
8 #include "lineq.h"
9 #include "code.h"
10 
11 
12 int do_equation; /* switch for determining access to dep vars */
13 int* hoc_access; /* links to next accessed variables */
14 int var_access; /* variable number as pointer into access array */
15 
16 
17 static double** varble; /* pointer to symbol values */
18 typedef struct elm* Elm;
19 
20 #define diag(s) hoc_execerror(s, (char*) 0);
21 
22 void dep_make(void) /* tag the variable as dependent with a variable number */
23 {
24 #if !OCSMALL
25  Symbol* sym;
26  unsigned* numpt = 0;
27 #if defined(__TURBOC__)
28  Inst* pcsav = pc;
29 #endif
30 
31  sym = spop();
32 #if defined(__TURBOC__)
33  pc = pcsav;
34 #endif
35  switch (sym->type) {
36  case UNDEF:
37  hoc_execerror(sym->name, "undefined in dep_make");
38  sym->type = VAR;
39  OPVAL(sym) = (double*) emalloc(sizeof(double));
40  *(OPVAL(sym)) = 0.;
41  case VAR:
42  if (sym->subtype != NOTUSER) {
43  execerror(sym->name, "can't be a dependent variable");
44  }
45  if (!ISARRAY(sym)) {
46  numpt = &(sym->s_varn);
47  } else {
48  Arrayinfo* aray = OPARINFO(sym);
49  if (sym->s_varn == 0) /* allocate varnum array */
50  {
51  int total = 1;
52  int i;
53  for (i = 0; i < aray->nsub; i++)
54  total *= (aray->sub)[i];
55  aray->a_varn = (unsigned*) ecalloc((unsigned) total, sizeof(unsigned));
56  sym->s_varn = (unsigned) total; /* set_varble() uses this */
57  }
58  numpt = &((aray->a_varn)[araypt(sym, OBJECTVAR)]);
59  }
60  break;
61 
62  default:
63  execerror(sym->name, "can't be a dependent variable");
64  }
65  if (*numpt > 0)
66  execerror(sym->name, "made dependent twice");
67  *numpt = ++neqn;
68 #endif
69 }
70 
71 
72 void init_access(void) /* zero the access array */
73 {
74 #if !OCSMALL
75  if (hoc_access != (int*) 0)
76  free((char*) hoc_access);
77  hoc_access = (int*) ecalloc((neqn + 1), sizeof(int));
78  var_access = -1;
79 #endif
80 }
81 
82 static void eqn_space(void); /* reallocate space for matrix */
83 static void set_varble(void); /* set up varble array by searching for tags */
84 static void eqn_side(int lhs);
85 static unsigned row;
86 static unsigned maxeqn;
87 
88 void eqn_name(void) /* save row number for lhs and/or rhs */
89 {
90 #if !OCSMALL
91 
92  if (maxeqn != neqn) /* discard equations and reallocate space */
93  {
94  eqn_space();
95  set_varble();
96  }
97  init_access();
98  do_equation = 1;
99  eval();
100  do_equation = 0;
101  if (var_access < 1)
102  execerror("illegal equation name", (pc - 2)->sym->name);
103  row = var_access;
104  nopop();
105 #endif
106 }
107 
108 static void set_varble(void) { /* set up varble array by searching for tags */
109 #if !OCSMALL
110  Symbol* sp;
111 
112  for (sp = symlist->first; sp != (Symbol*) 0; sp = sp->next) {
113  if (sp->s_varn != 0) {
114  if (sp->type == VAR) {
115  if (!ISARRAY(sp)) {
116  varble[sp->s_varn] = OPVAL(sp);
117  } else {
118  int i;
119  Arrayinfo* aray = OPARINFO(sp);
120  for (i = 0; i < sp->s_varn; i++)
121  if ((aray->a_varn)[i] > 0)
122  varble[(aray->a_varn)[i]] = OPVAL(sp) + i;
123  }
124  }
125  }
126  }
127 #endif
128 }
129 
130 static double Delta = .001; /* variable variation */
131 
132 void eqinit(void) /* built in function to initialize equation solver */
133 {
134 #if !OCSMALL
135  Symbol* sp;
136 
137  if (ifarg(1))
138  Delta = *getarg(1);
139  for (sp = symlist->first; sp != (Symbol*) 0; sp = sp->next) {
140  if (sp->s_varn != 0) {
141  if (ISARRAY(sp)) {
142  if (OPARINFO(sp)->a_varn != (unsigned*) 0)
143  free((char*) (OPARINFO(sp)->a_varn));
144  }
145  sp->s_varn = 0;
146  }
147  }
148  neqn = 0;
149  eqn_space();
150 #endif
151  ret();
152  pushx(0.);
153 }
154 
155 void eqn_init(void) /* initialize equation row */
156 {
157 #if !OCSMALL
158  struct elm* el;
159 
160  for (el = rowst[row]; el != (struct elm*) 0; el = el->c_right)
161  el->value = 0.;
162  rhs[row] = 0.;
163 #endif
164 }
165 
166 void eqn_lhs(void) /* add terms to left hand side */
167 {
168  eqn_side(1);
169 }
170 
171 void eqn_rhs(void) /* add terms to right hand side */
172 {
173  eqn_side(0);
174 }
175 
176 
177 static void eqn_side(int lhs) {
178 #if !OCSMALL
179  int i;
180  struct elm* el;
181  double f0, f1;
182  Inst* savepc = pc;
183 #if defined(__TURBOC__)
184  Inst* pc1;
185 #endif
186 
187  init_access();
188  do_equation = 1;
189  execute(savepc);
190 #if defined(__TURBOC__)
191  pc1 = pc;
192 #endif
193  do_equation = 0;
194 
195  if (lhs) {
196  f0 = xpop();
197  } else {
198  f0 = -xpop();
199  }
200 
201  rhs[row] -= f0;
202  for (i = var_access; i > 0; i = hoc_access[i]) {
203  *varble[i] += Delta;
204  execute(savepc);
205  *varble[i] -= Delta;
206  if (lhs) {
207  f1 = xpop();
208  } else {
209  f1 = -xpop();
210  }
211  el = getelm((struct elm*) 0, row, (unsigned) i);
212  el->value += (f1 - f0) / Delta;
213  }
214 #if defined(__TURBOC__)
215  pc = pc1;
216 #endif
217  pc++;
218 #endif
219 }
220 
221 static void eqn_space(void) { /* reallocate space for matrix */
222 #if !OCSMALL
223  int i;
224  struct elm* el;
225 
226  if (maxeqn > 0 && rowst == (Elm*) 0)
227  diag("matrix coefficients cannot be released");
228  for (i = 1; i <= maxeqn; i++)
229  for (el = rowst[i]; el; el = el->c_right)
230  free((char*) el);
231  maxeqn = neqn;
232  if (varble)
233  free((char*) varble);
234  if (rowst)
235  free((char*) rowst);
236  if (colst)
237  free((char*) colst);
238  if (eqord)
239  free((char*) eqord);
240  if (varord)
241  free((char*) varord);
242  if (rhs)
243  free((char*) rhs);
244  varble = (double**) 0;
245  rowst = colst = (Elm*) 0;
246  eqord = varord = (unsigned*) 0;
247  rhs = (double*) 0;
248  rowst = (Elm*) ecalloc((maxeqn + 1), sizeof(struct elm*));
249  varble = (double**) emalloc((maxeqn + 1) * sizeof(double*));
250  colst = (Elm*) ecalloc((maxeqn + 1), sizeof(struct elm*));
251  eqord = (unsigned*) emalloc((maxeqn + 1) * sizeof(unsigned));
252  varord = (unsigned*) emalloc((maxeqn + 1) * sizeof(unsigned));
253  rhs = (double*) emalloc((maxeqn + 1) * sizeof(double));
254  for (i = 1; i <= maxeqn; i++) {
255  eqord[i] = i;
256  varord[i] = i;
257  }
258 #endif
259 }
260 
261 void hoc_Prmat(void) {
262 #if !OCSMALL
263  prmat();
264 #endif
265  ret();
266  pushx(1.);
267 }
268 
269 void solve(void) {
270 #if !OCSMALL
271  /* Sum is a measure of the dependent variable accuracy
272  and how well the equations are solved */
273 
274  int i;
275  double sum;
276  struct elm* el;
277 
278  sum = 0.;
279  for (i = 1; i <= neqn; i++)
280  sum += fabs(rhs[i]);
281  if (!matsol())
282  diag("indeterminate system");
283  for (i = 1; i <= neqn; i++) {
284  *varble[varord[i]] += rhs[eqord[i]];
285  sum += fabs(rhs[i]);
286  }
287  /* free all elements */
288  for (i = 1; i <= neqn; i++) {
289  struct elm* el2;
290  for (el = rowst[i]; el != (struct elm*) 0; el = el2) {
291  el2 = el->c_right;
292  free(el);
293  }
294  rowst[i] = colst[i] = (struct elm*) 0;
295  }
296 #else
297  double sum = 0;
298 #endif
299  ret();
300  pushx(sum);
301 }
#define symlist
Definition: cabcode.cpp:17
double xpop(void)
Definition: code.cpp:788
void pushx(double d)
Definition: code.cpp:658
Symbol * spop(void)
Definition: code.cpp:846
int araypt(Symbol *sp, int type)
Definition: code.cpp:2416
Inst * pc
Definition: code.cpp:145
void execute(Inst *p)
Definition: code.cpp:2661
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:754
void * ecalloc(size_t n, size_t size)
Definition: symbol.cpp:215
#define ISARRAY(arg)
Definition: hocdec.h:164
#define NOTUSER
Definition: hocdec.h:91
#define getarg
Definition: hocdec.h:15
#define OPARINFO(sym)
Definition: hocdec.h:311
#define OPVAL(sym)
Definition: hocdec.h:306
int ifarg(int)
Definition: code.cpp:1581
int matsol(void)
Definition: lineq.cpp:15
#define colst
Definition: lineq.h:2
#define rhs
Definition: lineq.h:6
#define getelm
Definition: lineq.h:8
#define varord
Definition: lineq.h:5
#define eqord
Definition: lineq.h:4
#define neqn
Definition: lineq.h:3
#define rowst
Definition: lineq.h:1
#define i
Definition: md1redef.h:12
fabs
Definition: extdef.h:3
char * emalloc(unsigned n)
Definition: list.cpp:166
static void eqn_side(int lhs)
Definition: nonlin.cpp:177
void init_access(void)
Definition: nonlin.cpp:72
static unsigned row
Definition: nonlin.cpp:85
void eqn_lhs(void)
Definition: nonlin.cpp:166
void eqinit(void)
Definition: nonlin.cpp:132
void eqn_rhs(void)
Definition: nonlin.cpp:171
void eqn_init(void)
Definition: nonlin.cpp:155
void dep_make(void)
Definition: nonlin.cpp:22
int * hoc_access
Definition: nonlin.cpp:13
static void eqn_space(void)
Definition: nonlin.cpp:221
static unsigned maxeqn
Definition: nonlin.cpp:86
static double Delta
Definition: nonlin.cpp:130
struct elm * Elm
Definition: nonlin.cpp:18
void eqn_name(void)
Definition: nonlin.cpp:88
void solve(void)
Definition: nonlin.cpp:269
void hoc_Prmat(void)
Definition: nonlin.cpp:261
#define diag(s)
Definition: nonlin.cpp:20
static void set_varble(void)
Definition: nonlin.cpp:108
int do_equation
Definition: nonlin.cpp:12
int var_access
Definition: nonlin.cpp:14
static double ** varble
Definition: nonlin.cpp:17
void prmat(void)
Definition: prmat.cpp:10
#define eval
Definition: redef.h:57
#define nopop
Definition: redef.h:106
#define ret
Definition: redef.h:123
#define execerror
Definition: section.h:36
unsigned * a_varn
Definition: hocdec.h:69
int nsub
Definition: hocdec.h:70
int sub[1]
Definition: hocdec.h:72
Definition: model.h:57
short type
Definition: model.h:58
long subtype
Definition: model.h:59
HocStruct Symbol * next
Definition: hocdec.h:162
unsigned s_varn
Definition: hocdec.h:158
char * name
Definition: model.h:72
Definition: lineq.h:17
double value
Definition: lineq.h:20
struct elm * c_right
Definition: lineq.h:24
Definition: hocdec.h:51