Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4CashKarpRKF45.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4CashKarpRKF45 implementation
27//
28// The Cash-Karp Runge-Kutta-Fehlberg 4/5 method is an embedded fourth
29// order method (giving fifth-order accuracy) for the solution of an ODE.
30// Two different fourth order estimates are calculated; their difference
31// gives an error estimate. [ref. Numerical Recipes in C, 2nd Edition]
32// It is used to integrate the equations of the motion of a particle
33// in a magnetic field.
34//
35// [ref. Numerical Recipes in C, 2nd Edition]
36//
37// Authors: J.Apostolakis, V.Grichine (CERN), 30.01.1997
38// -------------------------------------------------------------------
39
40#include "G4CashKarpRKF45.hh"
41#include "G4LineSection.hh"
42
43/////////////////////////////////////////////////////////////////////
44//
45// Constructor
46//
48 G4int noIntegrationVariables,
49 G4bool primary)
50 : G4MagIntegratorStepper(EqRhs, noIntegrationVariables)
51{
52 const G4int numberOfVariables =
53 std::max( noIntegrationVariables,
54 ( ( (noIntegrationVariables-1)/4 + 1 ) * 4 ) );
55 // For better alignment with cache-line
56
57 ak2 = new G4double[numberOfVariables] ;
58 ak3 = new G4double[numberOfVariables] ;
59 ak4 = new G4double[numberOfVariables] ;
60 ak5 = new G4double[numberOfVariables] ;
61 ak6 = new G4double[numberOfVariables] ;
62
63 // Must ensure space extra 'state' variables exists - i.e. yIn[7]
64 const G4int numStateMax = std::max(GetNumberOfStateVariables(), 8);
65 const G4int numStateVars = std::max(noIntegrationVariables,
66 numStateMax );
67 // GetNumberOfStateVariables() );
68
69 yTemp = new G4double[numStateVars] ;
70 yIn = new G4double[numStateVars] ;
71
72 fLastInitialVector = new G4double[numStateVars] ;
73 fLastFinalVector = new G4double[numStateVars] ;
74 fLastDyDx = new G4double[numberOfVariables];
75
76 fMidVector = new G4double[numStateVars];
77 fMidError = new G4double[numStateVars];
78 if( primary )
79 {
80 fAuxStepper = new G4CashKarpRKF45(EqRhs, numberOfVariables, !primary);
81 }
82}
83
84/////////////////////////////////////////////////////////////////////
85//
86// Destructor
87//
89{
90 delete [] ak2;
91 delete [] ak3;
92 delete [] ak4;
93 delete [] ak5;
94 delete [] ak6;
95
96 delete [] yTemp;
97 delete [] yIn;
98
99 delete [] fLastInitialVector;
100 delete [] fLastFinalVector;
101 delete [] fLastDyDx;
102 delete [] fMidVector;
103 delete [] fMidError;
104
105 delete fAuxStepper;
106}
107
108//////////////////////////////////////////////////////////////////////
109//
110// Given values for n = 6 variables yIn[0,...,n-1]
111// known at x, use the fifth-order Cash-Karp Runge-
112// Kutta-Fehlberg-4-5 method to advance the solution over an interval
113// Step and return the incremented variables as yOut[0,...,n-1]. Also
114// return an estimate of the local truncation error yErr[] using the
115// embedded 4th-order method. The user supplies routine
116// RightHandSide(y,dydx), which returns derivatives dydx for y .
117//
118void
120 const G4double dydx[],
121 G4double Step,
122 G4double yOut[],
123 G4double yErr[])
124{
125 // const G4int nvar = 6 ;
126 // const G4double a2 = 0.2 , a3 = 0.3 , a4 = 0.6 , a5 = 1.0 , a6 = 0.875;
127 G4int i;
128
129 const G4double b21 = 0.2 ,
130 b31 = 3.0/40.0 , b32 = 9.0/40.0 ,
131 b41 = 0.3 , b42 = -0.9 , b43 = 1.2 ,
132
133 b51 = -11.0/54.0 , b52 = 2.5 , b53 = -70.0/27.0 ,
134 b54 = 35.0/27.0 ,
135
136 b61 = 1631.0/55296.0 , b62 = 175.0/512.0 ,
137 b63 = 575.0/13824.0 , b64 = 44275.0/110592.0 ,
138 b65 = 253.0/4096.0 ,
139
140 c1 = 37.0/378.0 , c3 = 250.0/621.0 , c4 = 125.0/594.0 ,
141 c6 = 512.0/1771.0 , dc5 = -277.0/14336.0 ;
142
143 const G4double dc1 = c1 - 2825.0/27648.0 , dc3 = c3 - 18575.0/48384.0 ,
144 dc4 = c4 - 13525.0/55296.0 , dc6 = c6 - 0.25 ;
145
146 // Initialise time to t0, needed when it is not updated by the integration.
147 // [ Note: Only for time dependent fields (usually electric)
148 // is it neccessary to integrate the time.]
149 yOut[7] = yTemp[7] = yIn[7] = yInput[7];
150
151 const G4int numberOfVariables= this->GetNumberOfVariables();
152 // The number of variables to be integrated over
153
154 // Saving yInput because yInput and yOut can be aliases for same array
155
156 for(i=0; i<numberOfVariables; ++i)
157 {
158 yIn[i]=yInput[i];
159 }
160 // RightHandSide(yIn, dydx) ; // 1st Step
161
162 for(i=0; i<numberOfVariables; ++i)
163 {
164 yTemp[i] = yIn[i] + b21*Step*dydx[i] ;
165 }
166 RightHandSide(yTemp, ak2) ; // 2nd Step
167
168 for(i=0; i<numberOfVariables; ++i)
169 {
170 yTemp[i] = yIn[i] + Step*(b31*dydx[i] + b32*ak2[i]) ;
171 }
172 RightHandSide(yTemp, ak3) ; // 3rd Step
173
174 for(i=0; i<numberOfVariables; ++i)
175 {
176 yTemp[i] = yIn[i] + Step*(b41*dydx[i] + b42*ak2[i] + b43*ak3[i]) ;
177 }
178 RightHandSide(yTemp, ak4) ; // 4th Step
179
180 for(i=0; i<numberOfVariables; ++i)
181 {
182 yTemp[i] = yIn[i] + Step*(b51*dydx[i]
183 + b52*ak2[i] + b53*ak3[i] + b54*ak4[i]) ;
184 }
185 RightHandSide(yTemp, ak5) ; // 5th Step
186
187 for(i=0; i<numberOfVariables; ++i)
188 {
189 yTemp[i] = yIn[i] + Step*(b61*dydx[i]
190 + b62*ak2[i] + b63*ak3[i] + b64*ak4[i] + b65*ak5[i]) ;
191 }
192 RightHandSide(yTemp, ak6) ; // 6th Step
193
194 for(i=0; i<numberOfVariables; ++i)
195 {
196 // Accumulate increments with proper weights
197 //
198 yOut[i] = yIn[i] + Step*(c1*dydx[i] + c3*ak3[i] + c4*ak4[i] + c6*ak6[i]) ;
199
200 // Estimate error as difference between 4th and 5th order methods
201 //
202 yErr[i] = Step*(dc1*dydx[i]
203 + dc3*ak3[i] + dc4*ak4[i] + dc5*ak5[i] + dc6*ak6[i]) ;
204
205 // Store Input and Final values, for possible use in calculating chord
206 //
207 fLastInitialVector[i] = yIn[i] ;
208 fLastFinalVector[i] = yOut[i];
209 fLastDyDx[i] = dydx[i];
210 }
211 // NormaliseTangentVector( yOut ); // Not wanted
212
213 fLastStepLength = Step;
214
215 return;
216}
217
218/////////////////////////////////////////////////////////////////
219//
221{
222 G4double distLine, distChord;
223 G4ThreeVector initialPoint, finalPoint, midPoint;
224
225 // Store last initial and final points
226 // (they will be overwritten in self-Stepper call!)
227 //
228 initialPoint = G4ThreeVector( fLastInitialVector[0],
229 fLastInitialVector[1], fLastInitialVector[2]);
230 finalPoint = G4ThreeVector( fLastFinalVector[0],
231 fLastFinalVector[1], fLastFinalVector[2]);
232
233 // Do half a step using StepNoErr
234 //
235 fAuxStepper->Stepper( fLastInitialVector, fLastDyDx,
236 0.5 * fLastStepLength, fMidVector, fMidError );
237
238 midPoint = G4ThreeVector( fMidVector[0], fMidVector[1], fMidVector[2]);
239
240 // Use stored values of Initial and Endpoint + new Midpoint to evaluate
241 // distance of Chord
242 //
243 if (initialPoint != finalPoint)
244 {
245 distLine = G4LineSection::Distline( midPoint, initialPoint, finalPoint );
246 distChord = distLine;
247 }
248 else
249 {
250 distChord = (midPoint-initialPoint).mag();
251 }
252 return distChord;
253}
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
~G4CashKarpRKF45() override
void Stepper(const G4double y[], const G4double dydx[], G4double h, G4double yout[], G4double yerr[]) override
G4CashKarpRKF45(G4EquationOfMotion *EqRhs, G4int numberOfVariables=6, G4bool primary=true)
G4double DistChord() const override
G4EquationOfMotion is the abstract base class for the right hand size of the equation of motion of a ...
static G4double Distline(const G4ThreeVector &OtherPnt, const G4ThreeVector &LinePntA, const G4ThreeVector &LinePntB)
G4MagIntegratorStepper(G4EquationOfMotion *Equation, G4int numIntegrationVariables, G4int numStateVariables=12, G4bool isFSAL=false)
G4int GetNumberOfVariables() const
void RightHandSide(const G4double y[], G4double dydx[]) const
G4int GetNumberOfStateVariables() const