19 #ifndef CMSTDORMAND_PRINCE_45_HH 20 #define CMSTDORMAND_PRINCE_45_HH 23 #include "G4MagIntegratorStepper.hh" 24 #include "G4FieldUtils.hh" 26 template <
class T_Equation,
unsigned int N = 6>
33 const G4double yInput[],
const G4double dydx[], G4double hstep, G4double yOutput[], G4double
yError[]);
36 const G4double yInput[],
const G4double dydx[], G4double hstep, G4double yOutput[], G4double
yError[])
final;
39 const G4double dydx[],
43 G4double dydxOutput[]);
54 const field_utils::ShortState<N>&
GetYOut()
const {
return fyOut; }
62 void RightHandSideInl(
const G4double
y[], G4double inv_momentum_magnitude, G4double dydx[]) {
63 fEquation_Rhs->T_Equation::TRightHandSide(
y, inv_momentum_magnitude, dydx);
66 inline void Stepper(
const G4double yInput[],
67 const G4double dydx[],
71 G4double dydxOutput[]) {
81 field_utils::ShortState<N8>
fyIn;
119 #include "G4LineSection.hh" 128 template <
class T_Equation,
unsigned int N>
130 : G4MagIntegratorStepper(dynamic_cast<G4EquationOfMotion*>(equation),
N), fEquation_Rhs(equation) {
132 if (dynamic_cast<G4EquationOfMotion*>(equation) ==
nullptr) {
133 G4Exception(
"G4TDormandPrince745CMS: constructor",
136 "T_Equation is not an G4EquationOfMotion.");
151 template <
class T_Equation,
unsigned int N>
154 if (numVar != G4int(
N)) {
155 G4ExceptionDescription
msg;
156 msg <<
"Equation has an incompatible number of variables.";
157 msg <<
" template N = " <<
N <<
" argument numVar = " << numVar;
159 G4Exception(
"G4TCashKarpRKF45CMS: constructor",
"GeomField0001", FatalErrorInArgument,
msg);
164 template <
class T_Equation,
unsigned int N>
166 const G4double dydx[],
170 G4double dydxOutput[]) {
171 StepWithError(yInput, dydx, hstep, yOutput,
yError);
181 template <
class T_Equation,
unsigned int N>
183 const G4double yInput[],
const G4double dydx[], G4double hstep, G4double yOut[], G4double yErr[]) {
186 constexpr G4double b21 = 0.2, b31 = 3.0 / 40.0, b32 = 9.0 / 40.0, b41 = 44.0 / 45.0, b42 = -56.0 / 15.0,
189 b51 = 19372.0 / 6561.0, b52 = -25360.0 / 2187.0, b53 = 64448.0 / 6561.0, b54 = -212.0 / 729.0,
191 b61 = 9017.0 / 3168.0, b62 = -355.0 / 33.0, b63 = 46732.0 / 5247.0,
b64 = 49.0 / 176.0,
192 b65 = -5103.0 / 18656.0,
194 b71 = 35.0 / 384.0, b72 = 0., b73 = 500.0 / 1113.0, b74 = 125.0 / 192.0, b75 = -2187.0 / 6784.0,
209 dc1 = -(b71 - 5179.0 / 57600.0), dc2 = -(b72 - .0), dc3 = -(b73 - 7571.0 / 16695.0), dc4 = -(b74 - 393.0 / 640.0),
210 dc5 = -(b75 + 92097.0 / 339200.0), dc6 = -(b76 - 187.0 / 2100.0), dc7 = -(-1.0 / 40.0);
214 field_utils::ShortState<N8> yTemp;
216 yOut[7] = yTemp[7] = fyIn[7] = yInput[7];
220 for (
unsigned int i = 0;
i <
N; ++
i) {
222 yTemp[
i] = yInput[
i] + b21 * hstep * dydx[
i];
224 G4double momentum_mag_square = yTemp[3] * yTemp[3] + yTemp[4] * yTemp[4] + yTemp[5] * yTemp[5];
225 G4double inv_momentum_magnitude = 1.0 /
std::sqrt(momentum_mag_square);
226 RightHandSideInl(yTemp, inv_momentum_magnitude, ak2);
228 for (
unsigned int i = 0;
i <
N; ++
i) {
229 yTemp[
i] = fyIn[
i] + hstep * (b31 * dydx[
i] + b32 * ak2[
i]);
231 RightHandSideInl(yTemp, inv_momentum_magnitude, ak3);
233 for (
unsigned int i = 0;
i <
N; ++
i) {
234 yTemp[
i] = fyIn[
i] + hstep * (b41 * dydx[
i] + b42 * ak2[
i] + b43 * ak3[
i]);
236 RightHandSideInl(yTemp, inv_momentum_magnitude, ak4);
238 for (
unsigned int i = 0;
i <
N; ++
i) {
239 yTemp[
i] = fyIn[
i] + hstep * (b51 * dydx[
i] + b52 * ak2[
i] + b53 * ak3[
i] + b54 * ak4[
i]);
241 RightHandSideInl(yTemp, inv_momentum_magnitude, ak5);
243 for (
unsigned int i = 0;
i <
N; ++
i) {
244 yTemp[
i] = fyIn[
i] + hstep * (b61 * dydx[
i] + b62 * ak2[
i] + b63 * ak3[
i] +
b64 * ak4[
i] + b65 * ak5[
i]);
246 RightHandSideInl(yTemp, inv_momentum_magnitude, ak6);
248 for (
unsigned int i = 0;
i <
N; ++
i) {
250 fyIn[
i] + hstep * (b71 * dydx[
i] + b72 * ak2[
i] + b73 * ak3[
i] + b74 * ak4[
i] + b75 * ak5[
i] + b76 * ak6[
i]);
252 RightHandSideInl(yOut, inv_momentum_magnitude, ak7);
254 for (
unsigned int i = 0;
i <
N; ++
i) {
255 yErr[
i] = hstep * (dc1 * dydx[
i] + dc2 * ak2[
i] + dc3 * ak3[
i] + dc4 * ak4[
i] + dc5 * ak5[
i] + dc6 * ak6[
i] +
262 fdydxIn[
i] = dydx[
i];
265 fLastStepLength = hstep;
268 template <
class T_Equation,
unsigned int N>
270 const G4double yInput[],
const G4double dydx[], G4double
Step, G4double yOutput[], G4double
yError[]) {
271 assert(yOutput != yInput);
274 StepWithError(yInput, dydx,
Step, yOutput,
yError);
277 template <
class T_Equation,
unsigned int N>
282 const G4double
hf1 = 6025192743.0 / 30085553152.0, hf3 = 51252292925.0 / 65400821598.0,
283 hf4 = -2691868925.0 / 45128329728.0, hf5 = 187940372067.0 / 1594534317056.0,
284 hf6 = -1776094331.0 / 19743644256.0, hf7 = 11237099.0 / 235043384.0;
288 for (
unsigned int i = 0;
i < 3; ++
i) {
290 fyIn[
i] + 0.5 * fLastStepLength *
291 (
hf1 * fdydxIn[
i] + hf3 * ak3[
i] + hf4 * ak4[
i] + hf5 * ak5[
i] + hf6 * ak6[
i] + hf7 * ak7[
i]);
297 return G4LineSection::Distline(mid,
begin,
end);
305 template <
class T_Equation,
unsigned int N>
312 1.0 / 11282082432.0 *
313 (157015080.0 *
tau4 - 13107642775.0 *
tau3 + 34969693132.0 *
tau2 - 32272833064.0 *
tau + 11282082432.0);
316 -100.0 / 32700410799.0 *
tau * (15701508.0 *
tau3 - 914128567.0 *
tau2 + 2074956840.0 *
tau - 1323431896.0);
319 25.0 / 5641041216.0 *
tau * (94209048.0 *
tau3 - 1518414297.0 *
tau2 + 2460397220.0 *
tau - 889289856.0);
322 -2187.0 / 199316789632.0 *
tau * (52338360.0 *
tau3 - 451824525.0 *
tau2 + 687873124.0 *
tau - 259006536.0);
325 11.0 / 2467955532.0 *
tau * (106151040.0 *
tau3 - 661884105.0 *
tau2 + 946554244.0 *
tau - 361440756.0);
327 const G4double bf7 = 1.0 / 29380423.0 *
tau * (1.0 -
tau) * (8293050.0 *
tau2 - 82437520.0 *
tau + 44764047.0);
329 for (
unsigned int i = 0;
i <
N; ++
i) {
331 fyIn[
i] + fLastStepLength *
tau *
332 (bf1 * fdydxIn[
i] + bf3 * ak3[
i] + bf4 * ak4[
i] + bf5 * ak5[
i] + bf6 * ak6[
i] + bf7 * ak7[
i]);
343 template <
class T_Equation,
unsigned int N>
347 const G4double b81 = 6245.0 / 62208.0, b82 = 0.0, b83 = 8875.0 / 103032.0, b84 = -125.0 / 1728.0,
348 b85 = 801.0 / 13568.0, b86 = -13519.0 / 368064.0, b87 = 11105.0 / 368064.0,
350 b91 = 632855.0 / 4478976.0, b92 = 0.0, b93 = 4146875.0 / 6491016.0, b94 = 5490625.0 / 14183424.0,
351 b95 = -15975.0 / 108544.0, b96 = 8295925.0 / 220286304.0, b97 = -1779595.0 / 62938944.0,
352 b98 = -805.0 / 4104.0;
355 field_utils::ShortState<N> yTemp;
359 for (
unsigned int i = 0;
i <
N; ++
i) {
360 yTemp[
i] = fyIn[
i] + fLastStepLength * (b81 * fdydxIn[
i] + b82 * ak2[
i] + b83 * ak3[
i] + b84 * ak4[
i] +
361 b85 * ak5[
i] + b86 * ak6[
i] + b87 * ak7[
i]);
363 G4double momentum_mag_square = yTemp[3] * yTemp[3] + yTemp[4] * yTemp[4] + yTemp[5] * yTemp[5];
364 G4double inv_momentum_magnitude = 1.0 /
std::sqrt(momentum_mag_square);
365 RightHandSideInl(yTemp, inv_momentum_magnitude, ak8);
367 for (
unsigned int i = 0;
i <
N; ++
i) {
368 yTemp[
i] = fyIn[
i] + fLastStepLength * (b91 * fdydxIn[
i] + b92 * ak2[
i] + b93 * ak3[
i] + b94 * ak4[
i] +
369 b95 * ak5[
i] + b96 * ak6[
i] + b97 * ak7[
i] + b98 * ak8[
i]);
371 RightHandSideInl(yTemp, inv_momentum_magnitude, ak9);
376 template <
class T_Equation,
unsigned int N>
383 bi[1][0] = 1.0, bi[1][1] = -38039.0 / 7040.0, bi[1][2] = 125923.0 / 10560.0, bi[1][3] = -19683.0 / 1760.0,
384 bi[1][4] = 3303.0 / 880.0,
388 bi[2][0] = 0.0, bi[2][1] = 0.0, bi[2][2] = 0.0, bi[2][3] = 0.0, bi[2][4] = 0.0,
392 bi[3][0] = 0.0, bi[3][1] = -12500.0 / 4081.0, bi[3][2] = 205000.0 / 12243.0, bi[3][3] = -90000.0 / 4081.0,
393 bi[3][4] = 36000.0 / 4081.0,
397 bi[4][0] = 0.0, bi[4][1] = -3125.0 / 704.0, bi[4][2] = 25625.0 / 1056.0, bi[4][3] = -5625.0 / 176.0,
398 bi[4][4] = 1125.0 / 88.0,
402 bi[5][0] = 0.0, bi[5][1] = 164025.0 / 74624.0, bi[5][2] = -448335.0 / 37312.0, bi[5][3] = 295245.0 / 18656.0,
403 bi[5][4] = -59049.0 / 9328.0,
407 bi[6][0] = 0.0, bi[6][1] = -25.0 / 28.0, bi[6][2] = 205.0 / 42.0, bi[6][3] = -45.0 / 7.0, bi[6][4] = 18.0 / 7.0,
411 bi[7][0] = 0.0, bi[7][1] = -2.0 / 11.0, bi[7][2] = 73.0 / 55.0, bi[7][3] = -171.0 / 55.0, bi[7][4] = 108.0 / 55.0,
415 bi[8][0] = 0.0, bi[8][1] = 189.0 / 22.0, bi[8][2] = -1593.0 / 55.0, bi[8][3] = 3537.0 / 110.0,
416 bi[8][4] = -648.0 / 55.0,
420 bi[9][0] = 0.0, bi[9][1] = 351.0 / 110.0, bi[9][2] = -999.0 / 55.0, bi[9][3] = 2943.0 / 110.0,
421 bi[9][4] = -648.0 / 55.0;
427 std::memset(
b, 0.0,
sizeof(
b));
429 G4double tauPower = 1.0;
430 for (G4int
j = 0;
j <= 4; ++
j) {
431 for (G4int iStage = 1; iStage <= 9; ++iStage) {
432 b[iStage] += bi[iStage][
j] * tauPower;
438 const G4double stepLen = fLastStepLength *
tau;
439 for (G4int
i = 0;
i <
N; ++
i) {
440 yOut[
i] = fyIn[
i] + stepLen * (
b[1] * fdydxIn[
i] +
b[2] * ak2[
i] +
b[3] * ak3[
i] +
b[4] * ak4[
i] +
b[5] * ak5[
i] +
441 b[6] * ak6[
i] +
b[7] * ak7[
i] +
b[8] * ak8[
i] +
b[9] * ak9[
i]);
void Stepper(const G4double yInput[], const G4double dydx[], G4double hstep, G4double yOutput[], G4double yError[], G4double dydxOutput[])
static const signed char b64[0x100]
field_utils::ShortState< N > ak7
const field_utils::ShortState< N > & GetYOut() const
field_utils::ShortState< N > ak3
void SetupInterpolation5thOrder()
field_utils::ShortState< N > fyOut
void RightHandSideInl(const G4double y[], G4double inv_momentum_magnitude, G4double dydx[])
T_Equation * GetSpecificEquation()
field_utils::ShortState< N > ak9
G4double DistChord() const final
void Interpolate(G4double tau, G4double yOut[]) const
field_utils::ShortState< N > ak5
void StepWithFinalDerivate(const G4double yInput[], const G4double dydx[], G4double hstep, G4double yOutput[], G4double yError[], G4double dydxOutput[])
CMSTDormandPrince45(T_Equation *equation)
field_utils::ShortState< N > ak8
G4int IntegratorOrder() const override
T_Equation * fEquation_Rhs
void StepWithError(const G4double yInput[], const G4double dydx[], G4double hstep, G4double yOutput[], G4double yError[])
void Interpolate5thOrder(G4double yOut[], G4double tau) const
field_utils::ShortState< N > ak4
void Interpolate4thOrder(G4double yOut[], G4double tau) const
field_utils::ShortState< N > fdydxIn
void SetupInterpolation()
field_utils::ShortState< N8 > fyIn
field_utils::ShortState< N > ak2
field_utils::ShortState< N > ak6
void Stepper(const G4double yInput[], const G4double dydx[], G4double hstep, G4double yOutput[], G4double yError[]) final