EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RungeKuttaRequest.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RungeKuttaRequest.cxx
1 
2 #include <cassert>
3 
4 #include <htclib.h>
5 
6 #include <MediaBank.h>
7 #include <MediaSliceArray.h>
8 
9 #include <KalmanNode.h>
10 #include <RungeKuttaRequest.h>
11 
12 // Cash-Karp coefficients for Runge-Kutta 5-th order embedded algorithm;
13 // well, prefer to avoid array creation since numerical recipes use 1-based
14 // indices and eventually code would loose readability completely;
15  double a2 = 1./5., a3 = 3./10., a4 = 3./5., a5 = 1., a6 = 7./8.;
16 
17 static double b21 = 1./5.;
18 static double b31 = 3./40., b32 = 9./40.;
19 static double b41 = 3./10., b42 = -9./10., b43 = 6./5.;
20 static double b51 = -11./54., b52 = 5./2., b53 = -70./27., b54 = 35./27.;
21 
22 static double b61 = 1631./55296., b62 = 175./512., b63 = 575./13824.;
23 static double b64 = 44275./110592., b65 = 253./4096.;
24 
25 static double c1 = 37./378., c2 = 0., c3 = 250./621.;
26 static double c4 = 125./594., c5 = 0., c6 = 512./1771.;
27 
28 static double s1 = 2825./27648., s2 = 0., s3 = 18575./48384.;
29 static double s4 = 13525./55296., s5 = 277./14336., s6 = 1./4.;
30 
31 // A hack variable to easily switch Runge-Kutta algorithm order; do it better later;
32 //unsigned forced_order;
33 
34 /* ========================================================================== */
35 
36 int RungeKuttaRequest::kk(MgridSlice *slice, double z, double x[4], double k[4])
37 {
38  int ret = 0;
39  //TVector3 xx = TVector3(x[0], x[1], z), BB;
40  TVector3 xx(x[0], x[1], z), BB;
41  double tx = x[2], ty = x[3], slope = sqrt(1.+SQR(tx)+SQR(ty));
42  double qv = q*_LIGHT_SPEED_*1E-14;
43 
44  assert(slice);
45 
46  if (slice->mGrid)
47  {
48  // Repetition mode (derivatives) makes no sense if a former call
49  // at "nominal" values failed --> check on that; caused a day of
50  // debugging in Jan'2009;
52  ret = slice->mLastUnboundCallStatus;
53  else
54  {
56 
57  ret = slice->mGrid->getCartesianFieldValue(xx, BB);
58 
59  // Record last repetition_flag=0 call status at this Z;
60  if (!repetition_flag) slice->mLastUnboundCallStatus = ret;
61  } /*if*/
62  } /*if*/
63 
64  // Yes, if no field or field routine failed, continue
65  // execution (show must go on!), but set a bit indicating that
66  // something bad happened;
67  if (!slice->mGrid || ret) VZERO(BB);
68 
69  k[0] = h*tx;
70  k[1] = h*ty;
71  k[2] = h*qv*slope*( ty*(tx*BB[_X_]+BB[_Z_]) - (1.+SQR(tx))*BB[_Y_]);
72  k[3] = h*qv*slope*(-tx*(ty*BB[_Y_]+BB[_Z_]) + (1.+SQR(ty))*BB[_X_]);
73 
74  return ret;
75 } /* RungeKuttaRequest::kk */
76 
77 /* -------------------------------------------------------------------------- */
78 
79 int RungeKuttaRequest::serveRequest(double in[], double _q, double out[],
80  int _repetition_flag)
81 {
82  int ret = 0;
83  //RungeKutta *rk = rq->rk;
84  double k1[4], k2[4], k3[4], k4[4], k5[4], k6[4], yy[4], bff[4];
85 
86  q = _q;
87  repetition_flag = _repetition_flag;
88 
89  // Start with k1[]; same for all 3 Runge-Kutta cases;
90  if (kk(rk->m1, z0, in, k1)) ret = -1;
91 
92  // A hack for now; fix later;
93  //unsigned order = forced_order ? forced_order : rk->_order;
94  // Well, at least some safety check;
95  //if (forced_order) assert(forced_order <= rk->_order);
96 
97  //switch (order)
98  switch (rk->_order)
99  {
100  case _RK_ORDER_2_:
101  // Then k2[];
102  for(int iq=0; iq<4; iq++)
103  yy[iq] = in[iq] + k1[iq]/2.;
104  if (kk(rk->m2, z0 + h/2., yy, k2)) ret = -1;
105 
106  // Sum up and obtain out[];
107  for(int iq=0; iq<4; iq++)
108  out[iq] = in[iq] + k2[iq];
109 
110  break;
111  case _RK_ORDER_4_:
112  // Then k2[];
113  for(int iq=0; iq<4; iq++)
114  yy[iq] = in[iq] + k1[iq]/2.;
115  if (kk(rk->m2, z0 + h/2., yy, k2)) ret = -1;
116 
117  // Then k3[];
118  for(int iq=0; iq<4; iq++)
119  yy[iq] = in[iq] + k2[iq]/2.;
120  if (kk(rk->m3, z0 + h/2., yy, k3)) ret = -1;
121 
122  // Then k4[];
123  for(int iq=0; iq<4; iq++)
124  yy[iq] = in[iq] + k3[iq];
125  if (kk(rk->m4, z0 + h, yy, k4)) ret = -1;
126 
127  // Sum up and obtain out[];
128  for(int iq=0; iq<4; iq++)
129  out[iq] = in[iq] + k1[iq]/6. + k2[iq]/3. + k3[iq]/3. + k4[iq]/6.;
130 
131  break;
132  case _RK_ORDER_5_:
133  // Then k2[];
134  for(int iq=0; iq<4; iq++)
135  yy[iq] = in[iq] + b21*k1[iq];
136  if (kk(rk->m2, z0 + a2*h, yy, k2)) ret = -1;
137 
138  // Then k3[];
139  for(int iq=0; iq<4; iq++)
140  yy[iq] = in[iq] + b31*k1[iq] + b32*k2[iq];
141  if (kk(rk->m3, z0 + a3*h, yy, k3)) ret = -1;
142 
143  // Then k4[];
144  for(int iq=0; iq<4; iq++)
145  yy[iq] = in[iq] + b41*k1[iq] + b42*k2[iq] + b43*k3[iq];
146  if (kk(rk->m4, z0 + a4*h, yy, k4)) ret = -1;
147 
148  // Then k5[];
149  for(int iq=0; iq<4; iq++)
150  yy[iq] = in[iq] + b51*k1[iq] + b52*k2[iq] + b53*k3[iq] + b54*k4[iq];
151  if (kk(rk->m5, z0 + a5*h, yy, k5)) ret = -1;
152 
153  // Eventually k6[];
154  for(int iq=0; iq<4; iq++)
155  yy[iq] = in[iq] + b61*k1[iq] + b62*k2[iq] + b63*k3[iq] + b64*k4[iq]
156  + b65*k5[iq];
157  if (kk(rk->m6, z0 + a6*h, yy, k6)) ret = -1;
158 
159  // Sum up and obtain out[];
160  for(int iq=0; iq<4; iq++)
161  out[iq] = in[iq] + c1*k1[iq] + c2*k2[iq] + c3*k3[iq] + c4*k4[iq] +
162  c5*k5[iq] + c6*k6[iq];
163 
164 #if _LATER_
165  // Same way get 4-th order estimate and consequently truncation error estimate;
166  for(int iq=0; iq<4; iq++)
167  bff[iq] = in[iq] + s1*k1[iq] + s2*k2[iq] + s3*k3[iq] + s4*k4[iq] +
168  s5*k5[iq] + s6*k6[iq];
169  for(int iq=0; iq<4; iq++)
170  rq->dlt[iq] = out[iq] - bff[iq];
171 #endif
172 
173  break;
174  } /*switch*/
175 
176  return ret;
177 } /* RungeKuttaRequest::serveRequest */
178 
179 /* ========================================================================== */
180