home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 22 gnu
/
22-gnu.zip
/
c_lsode.zip
/
LSODE.H
< prev
next >
Wrap
Text File
|
1994-01-15
|
22KB
|
305 lines
/* --------------------------------------------------------------------- */
/* this is the may 18, 1993 version of clsode. (c version of lsode) */
/* this version is 100% ansi c compatible. */
/* */
/* for more information about clsode or mathpack++, */
/* contact.. Woon-Chul Choi */
/* choi2@chd1s0.engr.ccny.cuny.edu */
/* */
/* clsode was translated and modified from hindmarsh's lsode written */
/* in fortran. */
/* */
/* I did my best to avoid and, later, to find a bug, but there must */
/* be bugs as always. if you ever find any, please let me know. */
/* */
/* --------------------------------------------------------------------- */
/* file list */
/* ls0001.h - header file for fortran common block ls0001 */
/* lsode.h - main header for clsode */
/* cfode.c - c version of cfode */
/* cutil.c - utility routine module for odepack */
/* d1mach.c - c version of d1mach */
/* daxpy.c - c version of daxpy */
/* ddot.c - c version of ddot */
/* dgbfa.c - c version of dgbfa */
/* dgbsl.c - c version of dgbsl */
/* dgefa.c - c version of dgefa */
/* dgesl.c - c version of dgesl */
/* dscal.c - c version of dscal */
/* ewset.c - c version of ewset */
/* idamax.c - c version of idamax */
/* intdy.c - c version of intdy */
/* lsode.c - c version of lsode */
/* prepj.c - c version of prepj */
/* solsy.c - c version of solsy */
/* stode.c - c version of stode */
/* vnorm.c - c version of vnorm */
/* Xermsg.c - message handler for mathpack++ */
/* */
/* --------------------------------------------------------------------- */
/* argument transfer in clsode */
/* following the type of the argument transfer (i.e. a scalar to a */
/* vector array, or a vector to a matrix array) is not unusual in */
/* fortran version of lsode. but it is not allowed in c language */
/* as far as i know. thus i applied the array arithmatic to solve */
/* the problem. (in ansi fortran 77, a scalar is not the same as */
/* an array of length 1, too.) */
/* */
/* example : */
/* */
/* subroutine lsode(rwork, ....) */
/* dimension rwork(1) */
/* : */
/* ldf = 21 */
/* nr = 2 */
/* call stode(rwork(ldf), nr,...) <-- a vector array in */
/* : */
/* : */
/* end */
/* */
/* subroutine stode(yh, nr,.....) */
/* dimension yh(nr,1) <-- become a matrix array */
/* : */
/* : */
/* end */
/* */
/* in fortran, argument connection is following */
/* yh(1,1) = rwork(21) */
/* yh(2,1) = rwork(22) */
/* yh(1,2) = rwork(23) */
/* yh(2,2) = rwork(24) */
/* */
/* in c, using array arithmatic: yh(i,j) = yh[i+nr(j-1)]. */
/* again, matrix(i,j) = vector(i+nr*(j-1)) */
/* where nr is number of row of a matrix. */
/* yh[1] = yh(1,1) = rwork[21] */
/* yh[2] = yh(2,1) = rwork[22] */
/* yh[3] = yh(1,2) = rwork[23] */
/* yh[4] = yh(2,2) = rwork[24] */
/* */
/* unfortunately, it is not hidden to the end user of clsode. */
/* unlike pd(i,j) in fortran jac (routine for jacobian matrix), */
/* in clsode, pd is a vector, double pd[]. use following macro */
/* to avoid the confusion. */
/* */
/* array arithmatic macro */
/* #define pd(a,b) pd[a+nr*(b-1)] */
/* */
/* in fortran in c */
/* pd(1,1) pd(1,1) --> pd[1] */
/* pd(2,1) pd(2,1) --> pd[2] */
/* pd(1,2) pd(1,2) --> pd[1+nr] */
/* */
/* certain compiler may issue a warning for pd(i,1), such as */
/* "code has no effect", but don't worry about it. it is just from */
/* the macro, pd(a,nr*(1-1)). */
/* */
/* clsode has one more argument than flsode. the last argument, which */
/* is "stdout" in example program, is a predefined stream in c. */
/* stdout is generally ok. but if you want to print the error */
/* messages elsewhere, you could open a file, and connect to lsode. */
/* if you open it, don't forget to close it. */
/* */
/* possible choices */
/* stdout a standard output device. */
/* stderr a standard error output device. */
/* FILE * a file handle. */
/* */
/* in clsode, two of lsode()'s argument carry the address operators, */
/* &, to receive the the values, independent variable and istate. */
/* */
/* fortran: lsode(fcn,neq,y, t,tout,itol,rtol,atol, itask, istate, */
/* c(*): lsode(fcn,neq,y,&T,tout,itol,rtol,ATOLE,itask,&ISTATE, */
/* fortran: iopt,rwork,lrw,iwork,liw,jac,mf) */
/* c(*): iopt,rwork,lrw,iwork,liw,jac,mf,STDOUT); */
/* */
/* *. uppercases are used just for the purpose of emphasizing. */
/* */
/* --------------------------------------------------------------------- */
/* rtol = a relative error tolerance parameter, in fortran either a */
/* scalar or an array of length neq. in c, it is always a */
/* vector array, but size is depended on itol, either neq[1] */
/* or 1. (actually 2 including a zeroth component(*).) */
/* */
/* atole = an absolute error tolerance parameter, in fortran either */
/* a scalar or an array of length neq. in c, it is always a */
/* vector array, but size is depended on itol, either 1 or */
/* neq[1]. */
/* */
/* certain compiler generates an error with atol[], because */
/* atol() is a c function defined in stdlib.h. hence, i */
/* replaced atol[] by atole[]. this will be applied to the */
/* routines, lsode, ewset, and your main program. */
/* */
/* neq = the size of the ode system (number of first order */
/* ordinary differential equations). used only for input. */
/* */
/* always, neq is a vector array, with neq[1] set to the */
/* system size. (the clsode package accesses only neq[1].) */
/* this parameter is passed as the neq argument in all calls */
/* to f and jac. hence, locations neq[2],... may be used to */
/* store other integer data and pass it to f and/or jac. */
/* function fcn and/or jac must include neq[] instead of neq */
/* in a function argument. minimum size of neq array is 1. */
/* (actually 2 including a zeroth component(*).) */
/* */
/* *. all elements of the array are referenced from 0 */
/* instead of 1. (i.e. neq[0], neq[1], ...., neq[n]). */
/* */
/* ***. do not optimize the common subexpression. */
/* --------------------------------------------------------------------- */
/* */
/* example program. */
/* - it is the same one that f-lsode has in the comment statements. */
/* */
/* the following is a simple example problem, with the coding */
/* needed for its solution by lsode. the problem is from chemical */
/* kinetics, and consists of the following three rate equations.. */
/* dy1/dt = -.04*y1 + 1.e4*y2*y3 */
/* dy2/dt = .04*y1 - 1.e4*y2*y3 - 3.e7*y2**2 */
/* dy3/dt = 3.e7*y2**2 */
/* on the interval from t = 0.0 to t = 4.e10, with initial conditions */
/* y1 = 1.0, y2 = y3 = 0. the problem is stiff. */
/* */
/* the following coding solves this problem with lsode, using mf = 21 */
/* and printing results at t = .4, 4., ..., 4.e10. it uses */
/* itol = 2 and atol much smaller for y2 than y1 or y3 because */
/* y2 has much smaller values. */
/* at the end of the run, statistical quantities of interest are */
/* printed (see optional outputs in the full description). */
/* */
/* --------------------------------------------------------------------- */
/* #include <stdlib.h> */
/* #include <stdio.h> */
/* #include "lsode.h" */
/* */
/* */
/* void fcn(int[], double, double[], double[]); */
/* void jac(int[], double, double[], int, int, double[], int); */
/* */
/* */
/* int main() */
/* { */
/* double atole[3+1],rtol[2],*rwork,t,tout,*y ; */
/* int itol,itask,istate,iopt,lrw,liw,mf,*iwork,neq[2]; */
/* int i; */
/* */
/* itol = 2; */
/* lrw = 58; */
/* liw = 23; */
/* neq[1] = 3; */
/* */
/* iwork = ivector(liw); */
/* rwork = dvector(lrw); */
/* y = dvector(neq[1]); */
/* */
/* y[1] = 1.0e0; */
/* y[2] = 0.0e0; */
/* y[3] = 0.0e0; */
/* t = 0.0e0; */
/* tout = 0.40e0; */
/* */
/* rtol[1] = 1.e-4; */
/* atole[1] = 1.e-6; */
/* atole[2] = 1.e-10; */
/* atole[3] = 1.e-6; */
/* */
/* itask = 1; */
/* istate = 1; */
/* iopt = 0; */
/* mf = 21; */
/* */
/* for(i=1;i<=12;i++) { */
/* lsode(fcn,neq,y,&t,tout,itol,rtol,atole,itask,&istate, */
/* iopt,rwork,lrw,iwork,liw,jac,mf,stdout); */
/* printf("\n at t =%11.4e y =%14.6e %14.6e %14.6e", */
/* t, y[1], y[2], y[3]); */
/* if (istate < 0) { */
/* printf("\n\n error halt.. istate =%3d",istate); */
/* break; */
/* } */
/* tout *= 10.0e0; */
/* } */
/* */
/* printf("\n\n no. steps = %4d no. f-s = %4d no. j-s =%4d\n", */
/* iwork[11], iwork[12], iwork[13]); */
/* free(iwork); */
/* free(rwork); */
/* free(y); */
/* return 1; */
/* } */
/* */
/* */
/* void fcn(int neq[], double t, double y[], double ydot[]) */
/* { */
/* ydot[1] = -.04e0*y[1] + 1.e4*y[2]*y[3]; */
/* ydot[3] = 3.e7*y[2]*y[2]; */
/* ydot[2] = -ydot[1] - ydot[3]; */
/* return; */
/* } */
/* */
/* */
/* #define pd(a,b) pd[nr*(b-1)+a] */
/* void jac(int neq[], double t, double y[], int ml, */
/* int mu, double pd[], int nr) */
/* { */
/* pd(1,1) = -0.04e0; */
/* pd(1,2) = 1.e4*y[3]; */
/* pd(1,3) = 1.e4*y[2]; */
/* pd(2,1) = 0.04e0; */
/* pd(2,3) = -pd(1,3); */
/* pd(3,2) = 6.e7*y[2]; */
/* pd(2,2) = -pd(1,2) - pd(3,2); */
/* return; */
/* } */
/* */
/* --------------------------------------------------------------------- */
/* the output(*) of this program is as follows.. */
/* */
/* at t = 4.0000e-01 y = 9.851726e-01 3.386406e-05 1.479357e-02 */
/* at t = 4.0000e+00 y = 9.055142e-01 2.240418e-05 9.446344e-02 */
/* at t = 4.0000e+01 y = 7.158050e-01 9.184616e-06 2.841858e-01 */
/* at t = 4.0000e+02 y = 4.504846e-01 3.222434e-06 5.495122e-01 */
/* at t = 4.0000e+03 y = 1.831701e-01 8.940379e-07 8.168290e-01 */
/* at t = 4.0000e+04 y = 3.897016e-02 1.621193e-07 9.610297e-01 */
/* at t = 4.0000e+05 y = 4.935213e-03 1.983756e-08 9.950648e-01 */
/* at t = 4.0000e+06 y = 5.159269e-04 2.064759e-09 9.994841e-01 */
/* at t = 4.0000e+07 y = 5.306413e-05 2.122677e-10 9.999469e-01 */
/* at t = 4.0000e+08 y = 5.494530e-06 2.197824e-11 9.999945e-01 */
/* at t = 4.0000e+09 y = 5.129458e-07 2.051784e-12 9.999995e-01 */
/* at t = 4.0000e+10 y = -7.170561e-08 -2.868224e-13 1.000000e+00 */
/* */
/* no. steps = 330 no. f-s = 405 no. j-s = 69 */
/* */
/* *. the output is the same as that from f-lsode. (see teste.doc) */
/* however, it may vary slightly from compiler to compiler. */
/* */
/* --------------------------------------------------------------------- */
#include <stdio.h>
#define NOREF(a) (a=a)
#define FALSE 0
#define TRUE 1
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
extern void Xermsg(char*, char*, FILE*, int, int, char*, ...);
extern double d1mach(void);
extern
int lsode (void (*)(int [], double, double [], double []),
int [], double [], double*, double, int, double [],
double [], int, int*, int, double [], int, int [], int,
void (*)(int [],double,double [],int,int,double [],int),
int, FILE *);
extern double dsign(double, double);
extern void tol_array_size(int, int, int*, int*);
extern double* dvector(int);
extern int* ivector(int);
/*-------------------------- end of lsode.h ---------------------------- */