/****************************************************** * UNIT Equa_dif.cpp * * --------------------------------------------------- * * Integration procedure odeint1 used by program * * planets.cpp * * --------------------------------------------------- * * From a pascal version by Jean-Pierre Dumont, France * * * * C++ version by J-P Moreau, Paris.* * (www.jpmoreau.fr) * ******************************************************/ #include #include #define Nvar_max 32 // Cf. Planets.cpp #define Ncorps 8 #define DtSave 0.02 typedef double Vecteur_etat[Nvar_max+1]; typedef int Pointers[Nvar_max]; typedef double Colonne[Nvar_max+1]; Pointers ipt; Colonne Masse,q1d,q2d,q1,q2; double sqr(double x) { return x*x; } void Derivs (double t, double *XT, double *XF) { double xi,xdi,xj, yi,ydi,yj, dxij,dyij,rij, xsm,ysm; int i,ipti,iptj,j; for (i=1; i<=Ncorps; i++) { //Calculate intermediate scalar values ipti = ipt[i]; xdi = XT[ipti+1]; ydi = XT[ipti+2]; xi = XT[ipti+3]; yi = XT[ipti+4]; //Calculate second members XF[ipti+3] = xdi; XF[ipti+4] = ydi; xsm = 0; ysm = 0; if (i != 1) for (j=1; jtiny) temp = fabs(ytemp[i]/yscal[i]); if (errmax < temp) errmax = temp; } // i loop errmax = errmax/eps; // real error / requirement if (errmax > un) { // Error too big, reduce h h = safety*h*exp(pshrnk*log(errmax)); goto e1; // start again } else { // the step has been a success! *hdid = h; // Calculate next time step if (errmax > errcon) *hnext = safety*h*exp(pgrow*log(errmax)); else *hnext = 4.0*h; } for (i=1; i<=n; i++) y[i] += ytemp[i]*fcor; } // rkqc() /////////////////////////////////////////////////////////////////////// void odeint1(double *ystart, int nvar, double t1, double t2, double eps, double h1, double hmin, int *nok, int *nbad) { /*================================================================= | This procedure integrates the 1st order differential system: | dy/dt = F(y,t) | where y and F are vectors of size nvar, between times | t1 and t2. | | INPUTS: | ystart= begin coordinates vector and speeds | nvar = number of equations | t1 = begin integration time | t2 = end integration time | t2 may be > or < t1 | eps = absolute required precision for solution | h1 = time increment proposed at beginning (try value) | hmin = minimum time increment | | OUTPUTS: | ystart= end coordinates vector and speeds | nok = number of unchanged time steps | nbad = number of modified time steps ==================================================================== | Programs using procedure RKQC must provide access to function: | | Derivs(double t, Vecteur_etat y, Vecteur_etat dydt) | which returns the values of derivatives dydt at point t, knowing | both t and the values of functions y. | | Also define the type: | | double Vecteur_etat[Nvar_max+1] in calling program, where Nvar_max | is the maximal number of equations of the system: n <= Nvar_max. | | Also define: double dtsave | | Initialize: dtsave / ===================================================================*/ int maxstp = 10000; double two = 2, zero = 0, tiny = 1e-20; int nstp,i; double tsav,t,hnext,hdid,h; Vecteur_etat yscal,y,dydt; extern double dtsave; t = t1; if (t2 > t1) h = fabs(h1); else h = -fabs(h1); *nok = 0; *nbad = 0; for (i=1; i<=nvar; i++) y[i] = ystart[i]; tsav = t - dtsave*two; for (nstp=1; nstp<=maxstp; nstp++) { Derivs(t,y,dydt); for (i=1; i<=nvar; i++) yscal[i] = fabs(y[i])+fabs(dydt[i]*h); //+tiny if (((t+h-t2)*(t+h-t1)) > zero) h = t2 - t; rkqc(y,dydt,nvar,&t,h,eps,yscal,&hdid,&hnext); if (hdid == h) *nok = *nok + 1; else *nbad = *nbad + 1; if (((t-t2)*(t2-t1)) >= zero) { for (i=1; i<=nvar; i++) ystart[i] = y[i]; return; } if (fabs(hnext) < hmin) { printf(" Time step too small!\n"); *nok =-1 ; // error flag return; } h = hnext; } // nstp loop printf(" Pause in ODEINT1 procedure: too many time steps!\n"); } // odeint1() // end of file equa_dif.cpp