GCC Code Coverage Report


Directory: src/solver/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 97.2% 105 / 0 / 108
Functions: 100.0% 5 / 0 / 5
Branches: 73.0% 54 / 0 / 74

odesolve.c
Line Branch Exec Source
1 //-----------------------------------------------------------------------------
2 // odesolve.c
3 //
4 // Fifth-order Runge-Kutta integration with adaptive step size control
5 // based on code from Numerical Recipes in C (Cambridge University
6 // Press, 1992).
7 //
8 // Date: 11/15/06
9 // Author: L. Rossman
10 //-----------------------------------------------------------------------------
11
12 #include <stdlib.h>
13 #include <math.h>
14 #include "odesolve.h"
15
16 #define MAXSTP 10000
17 #define TINY 1.0e-30
18 #define SAFETY 0.9
19 #define PGROW -0.2
20 #define PSHRNK -0.25
21 #define ERRCON 1.89e-4 // = (5/SAFETY)^(1/PGROW)
22
23
24 //-----------------------------------------------------------------------------
25 // Local declarations
26 //-----------------------------------------------------------------------------
27 int nmax; // max. number of equations
28 double* y; // dependent variable
29 double* yscal; // scaling factors
30 double* yerr; // integration errors
31 double* ytemp; // temporary values of y
32 double* dydx; // derivatives of y
33 double* ak; // derivatives at intermediate points
34
35
36 // function that integrates over an error-controlled stepsize
37 int rkqs(double* x, int n, double htry, double eps, double* hdid,
38 double* hnext, void (*derivs)(double, double*, double*));
39
40 // function that performs the Runge-Kutta integration step
41 void rkck(double x, int n, double h, void (*derivs)(double, double*, double*));
42
43
44 //-----------------------------------------------------------------------------
45 // open the ODE solver to solve system of n equations
46 // (return 1 if successful, 0 if not)
47 //-----------------------------------------------------------------------------
48 37 int odesolve_open(int n)
49 {
50 37 int n5 = n*5;
51 37 nmax = 0;
52 37 y = (double *) calloc(n, sizeof(double));
53 37 yscal = (double *) calloc(n, sizeof(double));
54 37 dydx = (double *) calloc(n, sizeof(double));
55 37 yerr = (double *) calloc(n, sizeof(double));
56 37 ytemp = (double *) calloc(n, sizeof(double));
57 37 ak = (double *) calloc(n5, sizeof(double));
58
6/12
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 37 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 37 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 37 times.
37 if ( !y || !yscal || !dydx || !yerr || !ytemp || !ak ) return 0;
59 37 nmax = n;
60 37 return 1;
61 }
62
63
64 //-----------------------------------------------------------------------------
65 // close the ODE solver
66 //-----------------------------------------------------------------------------
67 37 void odesolve_close()
68 {
69
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if ( y ) free(y);
70 37 y = NULL;
71
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if ( yscal ) free(yscal);
72 37 yscal = NULL;
73
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if ( dydx ) free(dydx);
74 37 dydx = NULL;
75
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if ( yerr ) free(yerr);
76 37 yerr = NULL;
77
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if ( ytemp ) free(ytemp);
78 37 ytemp = NULL;
79
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if ( ak ) free(ak);
80 37 ak = NULL;
81 37 nmax = 0;
82 37 }
83
84
85 4706940 int odesolve_integrate(double ystart[], int n, double x1, double x2,
86 double eps, double h1, void (*derivs)(double, double*, double*))
87 //---------------------------------------------------------------
88 // Driver function for Runge-Kutta integration with adaptive
89 // stepsize control. Integrates starting n values in ystart[]
90 // from x1 to x2 with accuracy eps. h1 is the initial stepsize
91 // guess and derivs is a user-supplied function that computes
92 // derivatives dy/dx of y. On completion, ystart[] contains the
93 // new values of y at the end of the integration interval.
94 //---------------------------------------------------------------
95 {
96 int i, errcode, nstp;
97 double hdid, hnext;
98 4706940 double x = x1;
99 4706940 double h = h1;
100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4706940 times.
4706940 if (nmax < n) return 1;
101
2/2
✓ Branch 0 taken 7740486 times.
✓ Branch 1 taken 4706940 times.
12447426 for (i=0; i<n; i++) y[i] = ystart[i];
102
1/2
✓ Branch 0 taken 4723562 times.
✗ Branch 1 not taken.
4723562 for (nstp=1; nstp<=MAXSTP; nstp++)
103 {
104 4723562 derivs(x,y,dydx);
105
2/2
✓ Branch 0 taken 7757118 times.
✓ Branch 1 taken 4723562 times.
12480680 for (i=0; i<n; i++)
106 7757118 yscal[i] = fabs(y[i]) + fabs(dydx[i]*h) + TINY;
107
2/2
✓ Branch 0 taken 10184 times.
✓ Branch 1 taken 4713378 times.
4723562 if ((x+h-x2)*(x+h-x1) > 0.0) h = x2 - x;
108 4723562 errcode = rkqs(&x,n,h,eps,&hdid,&hnext,derivs);
109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4723562 times.
4723562 if (errcode) break;
110
2/2
✓ Branch 0 taken 4706940 times.
✓ Branch 1 taken 16622 times.
4723562 if ((x-x2)*(x2-x1) >= 0.0)
111 {
112
2/2
✓ Branch 0 taken 7740486 times.
✓ Branch 1 taken 4706940 times.
12447426 for (i=0; i<n; i++) ystart[i] = y[i];
113 4706940 return 0;
114 }
115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16622 times.
16622 if (fabs(hnext) <= 0.0) return 2;
116 16622 h = hnext;
117 }
118 return 3;
119 }
120
121
122 4723562 int rkqs(double* x, int n, double htry, double eps, double* hdid,
123 double* hnext, void (*derivs)(double, double*, double*))
124 //---------------------------------------------------------------
125 // Fifth-order Runge-Kutta integration step with monitoring of
126 // local truncation error to assure accuracy and adjust stepsize.
127 // Inputs are current value of x, trial step size (htry), and
128 // accuracy (eps). Outputs are stepsize taken (hdid) and estimated
129 // next stepsize (hnext). Also updated are the values of y[].
130 //---------------------------------------------------------------
131 {
132 int i;
133 4723562 double err, errmax, h, htemp, xnew, xold = *x;
134
135 // --- set initial stepsize
136 4723562 h = htry;
137 for (;;)
138 {
139 // --- take a Runge-Kutta-Cash-Karp step
140 4734080 rkck(xold, n, h, derivs);
141
142 // --- compute scaled maximum error
143 4734080 errmax = 0.0;
144
2/2
✓ Branch 0 taken 7767648 times.
✓ Branch 1 taken 4734080 times.
12501728 for (i=0; i<n; i++)
145 {
146 7767648 err = fabs(yerr[i]/yscal[i]);
147
2/2
✓ Branch 0 taken 6701576 times.
✓ Branch 1 taken 1066072 times.
7767648 if (err > errmax) errmax = err;
148 }
149 4734080 errmax /= eps;
150
151 // --- error too large; reduce stepsize & repeat
152
2/2
✓ Branch 0 taken 10518 times.
✓ Branch 1 taken 4723562 times.
4734080 if (errmax > 1.0)
153 {
154 10518 htemp = SAFETY*h*pow(errmax,PSHRNK);
155
1/2
✓ Branch 0 taken 10518 times.
✗ Branch 1 not taken.
10518 if (h >= 0)
156 {
157
2/2
✓ Branch 0 taken 10164 times.
✓ Branch 1 taken 354 times.
10518 if (htemp > 0.1*h) h = htemp;
158 354 else h = 0.1*h;
159 }
160 else
161 {
162 if (htemp < 0.1*h) h = htemp;
163 else h = 0.1*h;
164 }
165 10518 xnew = xold + h;
166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10518 times.
10518 if (xnew == xold) return 2;
167 10518 continue;
168 }
169
170 // --- step succeeded; compute size of next step
171 else
172 {
173
2/2
✓ Branch 0 taken 189032 times.
✓ Branch 1 taken 4534530 times.
4723562 if (errmax > ERRCON) *hnext = SAFETY*h*pow(errmax,PGROW);
174 4534530 else *hnext = 5.0*h;
175 4723562 *x += (*hdid=h);
176
2/2
✓ Branch 0 taken 7757118 times.
✓ Branch 1 taken 4723562 times.
12480680 for (i=0; i<n; i++) y[i] = ytemp[i];
177 4723562 return 0;
178 }
179 }
180 }
181
182
183 4734080 void rkck(double x, int n, double h, void (*derivs)(double, double*, double*))
184 //----------------------------------------------------------------------
185 // Uses the Runge-Kutta-Cash-Karp method to advance y[] at x
186 // over stepsize h.
187 //----------------------------------------------------------------------
188 {
189 4734080 double a2=0.2, a3=0.3, a4=0.6, a5=1.0, a6=0.875,
190 4734080 b21=0.2, b31=3.0/40.0, b32=9.0/40.0, b41=0.3, b42= -0.9, b43=1.2,
191 4734080 b51= -11.0/54.0, b52=2.5, b53= -70.0/27.0, b54=35.0/27.0,
192 4734080 b61=1631.0/55296.0, b62=175.0/512.0, b63=575.0/13824.0,
193 4734080 b64=44275.0/110592.0, b65=253.0/4096.0, c1=37.0/378.0,
194 4734080 c3=250.0/621.0, c4=125.0/594.0, c6=512.0/1771.0,
195 4734080 dc5= -277.0/14336.0;
196 4734080 double dc1=c1-2825.0/27648.0, dc3=c3-18575.0/48384.0,
197 4734080 dc4=c4-13525.0/55296.0, dc6=c6-0.25;
198 int i;
199 4734080 int n2 = n*2;
200 4734080 int n3 = n*3;
201 4734080 int n4 = n*4;
202 4734080 double *ak2 = (ak);
203 4734080 double *ak3 = ((ak)+(n));
204 4734080 double *ak4 = ((ak)+(n2));
205 4734080 double *ak5 = ((ak)+(n3));
206 4734080 double *ak6 = ((ak)+(n4));
207
208
2/2
✓ Branch 0 taken 7767648 times.
✓ Branch 1 taken 4734080 times.
12501728 for (i=0; i<n; i++)
209 7767648 ytemp[i] = y[i] + b21*h*dydx[i];
210 4734080 derivs(x+a2*h,ytemp,ak2);
211
212
2/2
✓ Branch 0 taken 7767648 times.
✓ Branch 1 taken 4734080 times.
12501728 for (i=0; i<n; i++)
213 7767648 ytemp[i] = y[i] + h*(b31*dydx[i]+b32*ak2[i]);
214 4734080 derivs(x+a3*h,ytemp,ak3);
215
216
2/2
✓ Branch 0 taken 7767648 times.
✓ Branch 1 taken 4734080 times.
12501728 for (i=0; i<n; i++)
217 7767648 ytemp[i] = y[i] + h*(b41*dydx[i]+b42*ak2[i] + b43*ak3[i]);
218 4734080 derivs(x+a4*h,ytemp,ak4);
219
220
2/2
✓ Branch 0 taken 7767648 times.
✓ Branch 1 taken 4734080 times.
12501728 for (i=0; i<n; i++)
221 7767648 ytemp[i] = y[i] + h*(b51*dydx[i]+b52*ak2[i] + b53*ak3[i] + b54*ak4[i]);
222 4734080 derivs(x+a5*h,ytemp,ak5);
223
224
2/2
✓ Branch 0 taken 7767648 times.
✓ Branch 1 taken 4734080 times.
12501728 for (i=0; i<n; i++)
225 7767648 ytemp[i] = y[i] + h*(b61*dydx[i]+b62*ak2[i] + b63*ak3[i] + b64*ak4[i]
226 7767648 + b65*ak5[i]);
227 4734080 derivs(x+a6*h,ytemp,ak6);
228
229
2/2
✓ Branch 0 taken 7767648 times.
✓ Branch 1 taken 4734080 times.
12501728 for (i=0; i<n; i++)
230 7767648 ytemp[i] = y[i] + h*(c1*dydx[i] + c3*ak3[i] + c4*ak4[i] + c6*ak6[i]);
231
232
2/2
✓ Branch 0 taken 7767648 times.
✓ Branch 1 taken 4734080 times.
12501728 for (i=0; i<n; i++)
233 7767648 yerr[i] = h*(dc1*dydx[i] +dc3*ak3[i] + dc4*ak4[i] + dc5*ak5[i] + dc6*ak6[i]);
234 4734080 }
235