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