File: xppdll.html

package info (click to toggle)
xppaut 8.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,332 kB
  • sloc: ansic: 74,690; makefile: 127; sh: 92
file content (228 lines) | stat: -rwxr-xr-x 5,965 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
<html>
<head>
<title>XPP - DLL</title>
</head>
<body bgcolor="#ffffff" link="#330099" alink="#FF3300" vlink="#330099">

 <a href="xpphelp.html">Contents</a>
<hr>
<h1>Using DLLs</h1>

<p>

For compilers which allow dynamic linking, it is possible to use
external C programs to speed up the right-hand sides etc. This also
lets you create complicated right-hand sides that would be difficult
to do with the XPP parser. Here are the steps you need to do this. 
<ol>
<li> Write some C-code for the right-hand sides. Here is the form of
the code:
<p>
<font color=#CC33CC> <pre>
#include <math.h>
f1(double *in,double *out,int nin,int nout,double *var,double *con)
{


}
f2(double *in,double *out,int nin,int nout,double *var,double *con)
{

}

...
</pre></font>
<p>
You can define as many of these functions as you want within one
file. The parameters <b> in </b> are passed by XPP to the
function. The parameters <b> out </b> are what the function computes
and passes back to XPP. The integers <b> nin,nout </b> are junt the
number of such passed parameters. I never use them. 
The array <b> con </b> contains all your parameters in the order you
defined them in the ODE file
starting with <b> con[2] </b> and the array <b> var </b>  contains the time
variable, followed by the state variables, and then the fixed
variables.  Thus, you could directly communicate with all the
variables or parameters.  
<li> Next compile to code into a shared library. Here is what I type
<font color=#CC33CC>
<pre>
gcc -shared -fpic -o pp.so pp.c 
</pre> </font>
where <b> pp.c </b> is what I called the C file.
<li> Next write an ODE file that can take advantage of this using
the <code> export {} {} </code> statement to send out and read in what
is needed. 
<li> Run XPP and use the <b> File Edit Load-DLL </b> command to load
in the library and tell XPP which function to call. For the latter,
typing <b> f1 </b> would implement the first bit of code while typing
<b>f2</b> uses the second. You can change both the function and the
library while XPP is running. 
<li> If all goes well, then XPP will run with the hard-coded RHS.
</ol>
<p>
<hr>
<h3> Example 1 </h3>

I will implement a predator-prey model:
<p><i>
<center>
 x' = x((x+c)(1-x)-y) <p>
 y' = y(x-a) <p>
</center>
</i>

I will pass in the value of the parameters and the variables and get
back the values of the right-hand sides. 
<p>
Here is the ODE file:
<font color=#CC33CC> <pre>
# pp.ode with dlls
#
# xp,yp are the right-hand sides
x'=xp
y'=yp
# a,b are parameters
par a=.4,c=0
init x=.1,y=.2
# dummies to allocate storage
xp=0
yp=0
# here is the main communication
export {a,c,x,y} {xp,yp}
@ total=50
done

</pre></font>
The parameters and current values of the variables are passed in via
the first <b> {} </b> in the export statement.  The second <b> {} </b>
passes back values for the fixed variables, <b> xp,yp </b> which are
the right-hand sides. You have to define these in XPP so I usually set
them to zero. 
<p>
Next I write the C code for the right-hand sides: 
<font color=#CC33CC>
<pre>
/* pp.c for DLL
 */
#include <math.h>

/* some defines for readability */

#define a in[0]
#define c in[1]
#define x in[2]
#define y in[3]

#define xp out[0]
#define yp out[1]

pp(double * in,double *out, int nin,int nout, double *var,double *con)
{
  xp=x*((x+c)*(1-x)-y);
  yp=y*(x-a);
}

</pre>
</font>
I have added a few defines to make it easier to read and write. 
<p>

I compile this as
<font color=#CC33CC><pre>
gcc -shared -fpic -o pp.so pp.c
</pre></font>

This should give me a file called <b> pp.so </b> which is a shared
labrary. 
<p>
I run the ODE file with XPP. I click on <b> File Edit Load-DLL </b>
and choose the file <b> pp.so </b> and <b> pp </b> for the function
name (since that is what I called it in the C file).
<p>
Then let it rip to see the solution.

<hr>

<h3> Example 2 - an array </h3>

This next example reads the variables and passes the right-hand side
directly to the array <b> var </b> since the <b> export </b> directive
cannot pass arrays in any simple manner.  The equation is the
discretization of the bistable front: <p>  <i>
u<sub>0</sub>' = f(u<sub>0</sub>)+d(u<sub>1</sub> - u<sub>0</sub>) <p>
u<sub>80</sub>' = f(u<sub>80</sub>)+d(u<sub>79</sub> - u<sub>80</sub>)
<p>
u<sub>j</sub>' = f(u<sub>j</sub>)+d(u<sub>j-1</sub> - 2u<sub>j</sub>
+u<sub>j+1</sub> ) </i> for <i> j=1,...,79 <p> </i>  

<p>

Here is the ODE file
<font color=#CC33CC> <pre>
# wave front in bistable RD model
u[0..80]'=up[j]
up[0..80]=0
par a=.1,d=.25,n=80
init u[0..4]=1
export {a,d}
@ total=400,nout=2
done
</pre> </font>
<p>
Note that only the parameters are exported and nothing is sent back
throught the <b> export </b> statement.  I have set the total to 400
and plot every other point.
<p>
Next, I write the C code:
<font color=#CC33CC> <pre>
#include <math.h>

double f(double x,double a)
{
  return  x*(1-x)*(x-a);
}

front(double *in,double *out, int nin, int nout, double *var, double *con)
{
  int i;
  double a=in[0];
  double d=in[1];
  double *x=var+1;
  double *xp=x+81;
  xp[0]=f(x[0],a)+d*(x[1]-x[0]);
  xp[80]=f(x[80],a)+d*(x[79]-x[80]);
  for(i=1;i<80;i++)
    xp[i]=f(x[i],a)+d*(x[i+1]-2*x[i]+x[i-1]);
}
</pre>
</font>
<p>
Note how I pass the inputs to the pointer <b>x</b> and the outputs to
the pointer <b>xp</b> which respectively point to the elements
<b>var[1]</b> and <b>var[82]</b>  
<p>
Compile this  
<font color=#CC33CC><pre>
gcc -shared -fpic -o front.so front.c
</pre></font>

<p> Now run <b> front.ode</b>, click on <b> File Edit Load DLL </b>
and load <b> front.so </b> choosing the function <b> front</b>. Let it
rip.  
<p>
I compared this to a normal ODE file 
<font color=#CC33CC> <pre>
# wave front in bistable RD model
f(u)=u*(1-u)*(u-a)
u[0..80]'=up[j]
up0=f(u0)+d*(u1-u0)
up[1..79]=f(u[j])+d*(u[j-1]+u[j+1]-2*u[j])
up80=f(u80)+d*(u79-u80)
par a=.1,d=.25,n=81
init u[0..4]=1
@ total=400,nout=2
done
</pre> </font>
and get about a two-fold increase in speed.