KaliVeda  1.13/01
Heavy-Ion Analysis Toolkit
KVRungeKutta.cpp
Go to the documentation of this file.
1 //Created by KVClassFactory on Thu Jun 24 11:04:34 2010
2 //Author: John Frankland,,,
3 
4 #include "KVRungeKutta.h"
5 #include "TMath.h"
6 
8 
9 
10 
17 Double_t KVRungeKutta::b31 = 3.0 / 40.0;
18 Double_t KVRungeKutta::b32 = 9.0 / 40.0;
22 Double_t KVRungeKutta::b51 = -11.0 / 54.0;
24 Double_t KVRungeKutta::b53 = -70.0 / 27.0;
25 Double_t KVRungeKutta::b54 = 35.0 / 27.0;
26 Double_t KVRungeKutta::b61 = 1631.0 / 55296.0;
27 Double_t KVRungeKutta::b62 = 175.0 / 512.0;
28 Double_t KVRungeKutta::b63 = 575.0 / 13824.0;
29 Double_t KVRungeKutta::b64 = 44275.0 / 110592.0;
30 Double_t KVRungeKutta::b65 = 253.0 / 4096.0;
31 Double_t KVRungeKutta::c1 = 37.0 / 378.0;
32 Double_t KVRungeKutta::c3 = 250.0 / 621.0;
33 Double_t KVRungeKutta::c4 = 125.0 / 594.0;
34 Double_t KVRungeKutta::c6 = 512.0 / 1771.0;
35 Double_t KVRungeKutta::dc5 = -277.00 / 14336.0;
36 
37 
42 
44  : KVBase("RK4NR", "Runge-Kutta ODE integrator with adaptive step-size control"),
45  nvar(N), eps(PREC), hmin(MINSTEP)
46 {
47  // Set up integrator for N independent variables
48  // PREC = required precision (default: 1.e-8)
49  // MINSTEP = minimum allowed stepsize (default: 0)
50 
51  y = new Double_t [N];
52  yscal = new Double_t [N];
53  dydx = new Double_t [N];
54  yerr = new Double_t [N];
55  yout = new Double_t [N];
56  ytemp = new Double_t [N];
57  ak2 = new Double_t [N];
58  ak3 = new Double_t [N];
59  ak4 = new Double_t [N];
60  ak5 = new Double_t [N];
61  ak6 = new Double_t [N];
62 
63  dc1 = c1 - 2825.0 / 27648.0;
64  dc3 = c3 - 18575.0 / 48384.0;
65  dc4 = c4 - 13525.0 / 55296.0;
66  dc6 = c6 - 0.25;
67 
69 }
70 
71 
72 
75 
77 {
78  // Destructor
79  delete [] y;
80  delete [] yscal;
81  delete [] dydx;
82  delete [] yerr;
83  delete [] yout;
84  delete [] ytemp;
85  delete [] ak2;
86  delete [] ak3;
87  delete [] ak4;
88  delete [] ak5;
89  delete [] ak6;
90 }
91 
92 
93 
101 
103 {
104  // Runge-Kutta driver with adaptive stepsize control.
105  // Integrate nvar starting values ystart[0,...,nvar-1] from x1 to x2 with accuracy eps.
106  // h1 should be set as a guessed first stepsize.
107  // after call, GetNGoodSteps() and GetNBadSteps() give the number of good
108  // and bad (but retried and fixed) steps taken,
109  // and ystart values are replaced by values at the end of the integration interval.
110 
111  x = x1;
112  Double_t h = TMath::Sign(h1, x2 - x1);
113  nok = nbad = 0;
114  fOK = kTRUE;
115 
116  for (int i = 0; i < nvar; i++) y[i] = ystart[i];
117 
118  for (int nstp = 1; nstp <= MAXSTP; nstp++) { //Take at most MAXSTP steps.
119 
120  // calculate derivatives before performing step
122  CalcDerivs(x, y, dydx);
124 
125  for (Int_t i = 0; i < nvar; i++)
126  yscal[i] = TMath::Abs(y[i]) + TMath::Abs(dydx[i] * h) + TINY;
127 
128  if ((x + h - x2) * (x + h - x1) > 0.0) h = x2 - x;
129 
130  rkqs(h);
131  if (!fOK) {
132  Error("Integrate", "integration stopped at x=%g", x);
133  return;
134  }
135 
136  if (hdid == h) ++nok;
137  else ++nbad;
138  if ((x - x2) * (x2 - x1) >= 0.0) {
139  for (int i = 0; i < nvar; i++) ystart[i] = y[i];
140  return;
141  }
142 
143  if (TMath::Abs(hnext) <= hmin) {
144  Error("Integrate", "Step size %g too small", hnext);
145  Error("Integrate", "integration stopped at x=%g", x);
146  return;
147  }
148  h = hnext;
149  }
150  Error("Integrate", "Too many steps");
151  Error("Integrate", "integration stopped at x=%g", x);
152 }
153 
154 
155 
164 
166 {
167  // Fifth-order Runge-Kutta step with monitoring of local truncation error to ensure accuracy and
168  // adjust stepsize. Input are the dependent variable vector y[1..n] and its derivative dydx[1..n]
169  // at the starting value of the independent variable x. Also input are the stepsize to be attempted
170  // htry, the required accuracy eps, and the vector yscal[1..n] against which the error is
171  // scaled. On output, y and x are replaced by their new values, hdid is the stepsize that was
172  // actually accomplished, and hnext is the estimated next stepsize. derivs is the user-supplied
173  // routine that computes the right-hand side derivatives.
174 
175  Double_t errmax, htemp, xnew;
176 
177  Double_t h = htry;
178  for (;;) {
179  rkck(h);
180  errmax = 0.0;
181  for (int i = 0; i < nvar; i++) errmax = TMath::Max(errmax, TMath::Abs(yerr[i] / yscal[i]));
182  errmax /= eps;
183  if (errmax <= 1.0) break;
184  htemp = SAFETY * h * TMath::Power(errmax, PSHRNK);
185  h = (h >= 0.0 ? TMath::Max(htemp, 0.1 * h) : TMath::Min(htemp, 0.1 * h));
186  xnew = x + h;
187  if (xnew == x) {
188  Error("rkqs", "stepsize underflow");
189  fOK = kFALSE;
190  return;
191  }
192  }
193  if (errmax > ERRCON) hnext = SAFETY * h * TMath::Power(errmax, PGROW);
194  else hnext = 5.0 * h;
195  x += (hdid = h);
196  for (int i = 0; i < nvar; i++) y[i] = yout[i];
197 }
198 
199 
200 
207 
209 {
210  // Given values for n variables y[1..n] and their derivatives dydx[1..n] known at x, use
211  // the fifth-order Cash-Karp Runge-Kutta method to advance the solution over an interval h
212  // and return the incremented variables as yout[1..n]. Also return an estimate of the local
213  // truncation error in yout using the embedded fourth-order method. The user supplies the routine
214  // derivs(x,y,dydx) , which returns derivatives dydx at x.
215 
216  for (int i = 0; i < nvar; i++)
217  ytemp[i] = y[i] + b21 * h * dydx[i];
218  CalcDerivs(x + a2 * h, ytemp, ak2);
219  for (int i = 0; i < nvar; i++)
220  ytemp[i] = y[i] + h * (b31 * dydx[i] + b32 * ak2[i]);
221  CalcDerivs(x + a3 * h, ytemp, ak3);
222  for (int i = 0; i < nvar; i++)
223  ytemp[i] = y[i] + h * (b41 * dydx[i] + b42 * ak2[i] + b43 * ak3[i]);
224  CalcDerivs(x + a4 * h, ytemp, ak4);
225  for (int i = 0; i < nvar; i++)
226  ytemp[i] = y[i] + h * (b51 * dydx[i] + b52 * ak2[i] + b53 * ak3[i] + b54 * ak4[i]);
227  CalcDerivs(x + a5 * h, ytemp, ak5);
228  for (int i = 0; i < nvar; i++)
229  ytemp[i] = y[i] + h * (b61 * dydx[i] + b62 * ak2[i] + b63 * ak3[i] + b64 * ak4[i] + b65 * ak5[i]);
230  CalcDerivs(x + a6 * h, ytemp, ak6);
231  for (int i = 0; i < nvar; i++)
232  yout[i] = y[i] + h * (c1 * dydx[i] + c3 * ak3[i] + c4 * ak4[i] + c6 * ak6[i]);
233  for (int i = 0; i < nvar; i++)
234  yerr[i] = h * (dc1 * dydx[i] + dc3 * ak3[i] + dc4 * ak4[i] + dc5 * ak5[i] + dc6 * ak6[i]);
235 }
236 
237 
int Int_t
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define MAXSTP
Definition: KVRungeKutta.h:13
#define SAFETY
Definition: KVRungeKutta.h:9
#define TINY
Definition: KVRungeKutta.h:14
#define ERRCON
Definition: KVRungeKutta.h:12
#define PSHRNK
Definition: KVRungeKutta.h:11
#define PGROW
Definition: KVRungeKutta.h:10
const Bool_t kFALSE
double Double_t
const Bool_t kTRUE
#define N
Base class for KaliVeda framework.
Definition: KVBase.h:141
Adaptive step-size 4th order Runge-Kutta ODE integrator from Numerical Recipes.
Definition: KVRungeKutta.h:49
static Double_t a3
Definition: KVRungeKutta.h:50
static Double_t b31
Definition: KVRungeKutta.h:51
virtual void rkck(Double_t h)
Int_t nvar
number of independent variables/equations
Definition: KVRungeKutta.h:58
static Double_t b54
Definition: KVRungeKutta.h:52
Bool_t fInitialDeriv
Definition: KVRungeKutta.h:69
virtual void CalcDerivs(Double_t X, Double_t *Y, Double_t *DYDX)=0
static Double_t dc5
Definition: KVRungeKutta.h:56
Double_t * dydx
Definition: KVRungeKutta.h:64
static Double_t a2
Definition: KVRungeKutta.h:50
Double_t * yout
Definition: KVRungeKutta.h:64
static Double_t b32
Definition: KVRungeKutta.h:51
Double_t eps
precision required
Definition: KVRungeKutta.h:59
static Double_t b52
Definition: KVRungeKutta.h:52
Double_t * ak5
Definition: KVRungeKutta.h:66
virtual void rkqs(Double_t htry)
Double_t * ak2
Definition: KVRungeKutta.h:66
static Double_t b51
Definition: KVRungeKutta.h:52
Double_t hdid
Definition: KVRungeKutta.h:65
Double_t * ak4
Definition: KVRungeKutta.h:66
Double_t hnext
Definition: KVRungeKutta.h:65
static Double_t b41
Definition: KVRungeKutta.h:51
Double_t * ytemp
Definition: KVRungeKutta.h:64
Double_t * yscal
Definition: KVRungeKutta.h:64
static Double_t b53
Definition: KVRungeKutta.h:52
static Double_t c4
Definition: KVRungeKutta.h:55
static Double_t b65
Definition: KVRungeKutta.h:54
Double_t hmin
minimum allowed step size
Definition: KVRungeKutta.h:60
static Double_t b63
Definition: KVRungeKutta.h:53
Double_t dc6
Definition: KVRungeKutta.h:67
static Double_t b42
Definition: KVRungeKutta.h:51
static Double_t c6
Definition: KVRungeKutta.h:55
static Double_t b61
Definition: KVRungeKutta.h:53
static Double_t b21
Definition: KVRungeKutta.h:50
static Double_t b64
Definition: KVRungeKutta.h:54
static Double_t b62
Definition: KVRungeKutta.h:53
Int_t nbad
number of bad steps taken
Definition: KVRungeKutta.h:62
Double_t dc4
Definition: KVRungeKutta.h:67
static Double_t a5
Definition: KVRungeKutta.h:50
Double_t * yerr
Definition: KVRungeKutta.h:64
static Double_t b43
Definition: KVRungeKutta.h:51
virtual ~KVRungeKutta()
Destructor.
static Double_t a6
Definition: KVRungeKutta.h:50
static Double_t c1
Definition: KVRungeKutta.h:54
virtual void Integrate(Double_t *ystart, Double_t x1, Double_t x2, Double_t h1)
Int_t nok
number of good steps taken
Definition: KVRungeKutta.h:61
static Double_t a4
Definition: KVRungeKutta.h:50
Double_t dc3
Definition: KVRungeKutta.h:67
Double_t * ak3
Definition: KVRungeKutta.h:66
Double_t dc1
Definition: KVRungeKutta.h:67
Double_t x
Definition: KVRungeKutta.h:65
Double_t * y
Definition: KVRungeKutta.h:64
Double_t * ak6
Definition: KVRungeKutta.h:66
static Double_t c3
Definition: KVRungeKutta.h:55
virtual void Error(const char *method, const char *msgfmt,...) const
TH1F * h1
TH1 * h
Double_t Min(Double_t a, Double_t b)
Double_t Sign(Double_t a, Double_t b)
Double_t Power(Double_t x, Double_t y)
Double_t Abs(Double_t d)
Double_t Max(Double_t a, Double_t b)