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.
#includef1(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) { } ...
You can define as many of these functions as you want within one file. The parameters in are passed by XPP to the function. The parameters out are what the function computes and passes back to XPP. The integers nin,nout are junt the number of such passed parameters. I never use them. The array con contains all your parameters in the order you defined them in the ODE file starting with con[2] and the array var 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.
gcc -shared -fpic -o pp.so pp.cwhere pp.c is what I called the C file.
export {} {}
statement to send out and read in what
is needed.
y' = y(x-a)
Here is the ODE file:
# 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 doneThe parameters and current values of the variables are passed in via the first {} in the export statement. The second {} passes back values for the fixed variables, xp,yp which are the right-hand sides. You have to define these in XPP so I usually set them to zero.
Next I write the C code for the right-hand sides:
/* pp.c for DLL */ #includeI have added a few defines to make it easier to read and write./* 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); }
I compile this as
gcc -shared -fpic -o pp.so pp.cThis should give me a file called pp.so which is a shared labrary.
I run the ODE file with XPP. I click on File Edit Load-DLL and choose the file pp.so and pp for the function name (since that is what I called it in the C file).
Then let it rip to see the solution.
u0' = f(u0)+d(u1 - u0)
u80' = f(u80)+d(u79 - u80)
uj' = f(uj)+d(uj-1 - 2uj +uj+1 ) for j=1,...,79
Here is the ODE file
# 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
Note that only the parameters are exported and nothing is sent back throught the export statement. I have set the total to 400 and plot every other point.
Next, I write the C code:
#includedouble 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]); }
Note how I pass the inputs to the pointer x and the outputs to the pointer xp which respectively point to the elements var[1] and var[82]
Compile this
gcc -shared -fpic -o front.so front.c
Now run front.ode, click on File Edit Load DLL and load front.so choosing the function front. Let it rip.
I compared this to a normal ODE file
# 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 doneand get about a two-fold increase in speed.