KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
KVRungeKutta.cpp
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
17Double_t KVRungeKutta::b31 = 3.0 / 40.0;
18Double_t KVRungeKutta::b32 = 9.0 / 40.0;
22Double_t KVRungeKutta::b51 = -11.0 / 54.0;
24Double_t KVRungeKutta::b53 = -70.0 / 27.0;
25Double_t KVRungeKutta::b54 = 35.0 / 27.0;
26Double_t KVRungeKutta::b61 = 1631.0 / 55296.0;
27Double_t KVRungeKutta::b62 = 175.0 / 512.0;
28Double_t KVRungeKutta::b63 = 575.0 / 13824.0;
29Double_t KVRungeKutta::b64 = 44275.0 / 110592.0;
30Double_t KVRungeKutta::b65 = 253.0 / 4096.0;
31Double_t KVRungeKutta::c1 = 37.0 / 378.0;
32Double_t KVRungeKutta::c3 = 250.0 / 621.0;
33Double_t KVRungeKutta::c4 = 125.0 / 594.0;
34Double_t KVRungeKutta::c6 = 512.0 / 1771.0;
35Double_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;
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
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
#define N
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t hmin
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Base class for KaliVeda framework.
Definition KVBase.h:142
Adaptive step-size 4th order Runge-Kutta ODE integrator from Numerical Recipes.
static Double_t a3
static Double_t b31
virtual void rkck(Double_t h)
Int_t nvar
number of independent variables/equations
static Double_t b54
Bool_t fInitialDeriv
virtual void CalcDerivs(Double_t X, Double_t *Y, Double_t *DYDX)=0
static Double_t dc5
Double_t * dydx
static Double_t a2
Double_t * yout
static Double_t b32
Double_t eps
precision required
static Double_t b52
Double_t * ak5
virtual void rkqs(Double_t htry)
Double_t * ak2
static Double_t b51
Double_t hdid
Double_t * ak4
Double_t hnext
static Double_t b41
Double_t * ytemp
Double_t * yscal
static Double_t b53
static Double_t c4
static Double_t b65
Double_t hmin
minimum allowed step size
static Double_t b63
Double_t dc6
static Double_t b42
static Double_t c6
static Double_t b61
static Double_t b21
static Double_t b64
static Double_t b62
Int_t nbad
number of bad steps taken
Double_t dc4
static Double_t a5
Double_t * yerr
static Double_t b43
virtual ~KVRungeKutta()
Destructor.
static Double_t a6
static Double_t c1
virtual void Integrate(Double_t *ystart, Double_t x1, Double_t x2, Double_t h1)
Int_t nok
number of good steps taken
static Double_t a4
Double_t dc3
Double_t * ak3
Double_t dc1
Double_t * y
Double_t * ak6
static Double_t c3
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)
ClassImp(TPyArg)