Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4HelixMixedStepper.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// class G4HelixMixedStepper
27//
28// Class description:
29//
30// G4HelixMixedStepper split the Method used for Integration in two:
31//
32// If Stepping Angle ( h / R_curve) < pi/3
33// use Stepper for small step(ClassicalRK4 by default)
34// Else use HelixExplicitEuler Stepper
35//
36// Author: Tatiana Nikitina (CERN), 18.05.2007
37// Derived from G4ExactHelicalStepper
38// -------------------------------------------------------------------------
39
42#include "G4ClassicalRK4.hh"
43#include "G4CashKarpRKF45.hh"
44#include "G4SimpleRunge.hh"
47#include "G4HelixSimpleRunge.hh"
49#include "G4ExplicitEuler.hh"
50#include "G4ImplicitEuler.hh"
51#include "G4SimpleHeum.hh"
52#include "G4RKG3_Stepper.hh"
53#include "G4NystromRK4.hh"
54
55// Additional potential steppers
56#include "G4DormandPrince745.hh"
59#include "G4TsitourasRK45.hh"
60
61#include "G4ThreeVector.hh"
62#include "G4LineSection.hh"
63
64// ---------------------------------------------------------------------------
67 G4int stepperNumber,
68 G4double angleThreshold)
69 : G4MagHelicalStepper(EqRhs)
70{
71 if( angleThreshold < 0.0 )
72 {
73 fAngle_threshold = (1.0/3.0)*pi;
74 }
75 else
76 {
77 fAngle_threshold = angleThreshold;
78 }
79
80 if(stepperNumber<0)
81 {
82 // stepperNumber = 4; // Default is RK4 (original)
83 stepperNumber = 745; // Default is DormandPrince745 (ie DoPri5)
84 // stepperNumber = 8; // Default is CashKarp
85 }
86
87 fStepperNumber = stepperNumber; // Store the choice
88 fRK4Stepper = SetupStepper(EqRhs, fStepperNumber);
89}
90
91// ---------------------------------------------------------------------------
93{
94 delete fRK4Stepper;
95 if (fVerbose>0) { PrintCalls(); }
96}
97
98// ---------------------------------------------------------------------------
99void G4HelixMixedStepper::Stepper( const G4double yInput[], // [7]
100 const G4double dydx[], // [7]
101 G4double Step,
102 G4double yOut[], // [7]
103 G4double yErr[])
104{
105 // Estimation of the Stepping Angle
106 //
107 G4ThreeVector Bfld;
108 MagFieldEvaluate(yInput, Bfld);
109
110 G4double Bmag = Bfld.mag();
111 const G4double* pIn = yInput+3;
112 G4ThreeVector initVelocity = G4ThreeVector( pIn[0], pIn[1], pIn[2] );
113 G4double velocityVal = initVelocity.mag();
114
115 const G4double R_1 = std::abs(GetInverseCurve(velocityVal,Bmag));
116 // curv = inverse Radius
117 G4double Ang_curve = R_1 * Step;
118 // SetAngCurve(Ang_curve);
119 // SetCurve(std::abs(1/R_1));
120
121 if(Ang_curve < fAngle_threshold)
122 {
123 ++fNumCallsRK4;
124 fRK4Stepper->Stepper(yInput,dydx,Step,yOut,yErr);
125 }
126 else
127 {
128 constexpr G4int nvar = 6 ;
129 constexpr G4int nvarMax = 8 ;
130 G4double yTemp[nvarMax], yIn[nvarMax], yTemp2[nvarMax];
131 G4ThreeVector Bfld_midpoint;
132
133 SetAngCurve(Ang_curve);
134 SetCurve(std::abs(1.0/R_1));
135 ++fNumCallsHelix;
136
137 // Saving yInput because yInput and yOut can be aliases for same array
138 //
139 for(G4int i=0; i<nvar; ++i)
140 {
141 yIn[i]=yInput[i];
142 }
143
144 G4double halfS = Step * 0.5;
145
146 // 1. Do first half step and full step
147 //
148 AdvanceHelix(yIn, Bfld, halfS, yTemp, yTemp2); // yTemp2 for s=2*h (halfS)
149
150 MagFieldEvaluate(yTemp, Bfld_midpoint) ;
151
152 // 2. Do second half step - with revised field
153 // NOTE: Could avoid this call if 'Bfld_midpoint == Bfld'
154 // or diff 'almost' zero
155 //
156 AdvanceHelix(yTemp, Bfld_midpoint, halfS, yOut);
157 // Not requesting y at s=2*h (halfS)
158
159 // 3. Estimate the integration error
160 // should be (nearly) zero if Bfield= constant
161 //
162 for(G4int i=0; i<nvar; ++i)
163 {
164 yErr[i] = yOut[i] - yTemp2[i];
165 }
166 }
167}
168
169// ---------------------------------------------------------------------------
171 G4ThreeVector Bfld,
172 G4double h,
173 G4double yOut[] )
174{
175 AdvanceHelix(yIn, Bfld, h, yOut);
176}
177
178// ---------------------------------------------------------------------------
180{
181 // Implementation : must check whether h/R > 2 pi !!
182 // If( h/R < pi) use G4LineSection::DistLine
183 // Else DistChord=R_helix
184 //
185 G4double distChord;
186 G4double Ang_curve=GetAngCurve();
187
188 if(Ang_curve<=pi)
189 {
190 distChord=GetRadHelix()*(1-std::cos(0.5*Ang_curve));
191 }
192 else
193 {
194 if(Ang_curve<twopi)
195 {
196 distChord=GetRadHelix()*(1+std::cos(0.5*(twopi-Ang_curve)));
197 }
198 else
199 {
200 distChord=2.*GetRadHelix();
201 }
202 }
203
204 return distChord;
205}
206
207// ---------------------------------------------------------------------------
209{
210 G4cout << "In HelixMixedStepper::Number of calls to smallStepStepper = "
211 << fNumCallsRK4
212 << " and Number of calls to Helix = " << fNumCallsHelix << G4endl;
213}
214
215// ---------------------------------------------------------------------------
218{
219 G4MagIntegratorStepper* pStepper;
220 if (fVerbose>0) { G4cout << " G4HelixMixedStepper: ";
221}
222 switch ( StepperNumber )
223 {
224 // Robust, classic method
225 case 4:
226 pStepper = new G4ClassicalRK4( pE );
227 if (fVerbose>0) { G4cout << "G4ClassicalRK4"; }
228 break;
229
230 // Steppers with embedded estimation of error
231 case 8:
232 pStepper = new G4CashKarpRKF45( pE );
233 if (fVerbose>0) { G4cout << "G4CashKarpRKF45"; }
234 break;
235 case 13:
236 pStepper = new G4NystromRK4( pE );
237 if (fVerbose>0) { G4cout << "G4NystromRK4"; }
238 break;
239
240 // Lowest order RK Stepper - experimental
241 case 1:
242 pStepper = new G4ImplicitEuler( pE );
243 if (fVerbose>0) { G4cout << "G4ImplicitEuler"; }
244 break;
245
246 // Lower order RK Steppers - ok overall, good for uneven fields
247 case 2:
248 pStepper = new G4SimpleRunge( pE );
249 if (fVerbose>0) { G4cout << "G4SimpleRunge"; }
250 break;
251 case 3:
252 pStepper = new G4SimpleHeum( pE );
253 if (fVerbose>0) { G4cout << "G4SimpleHeum"; }
254 break;
255 case 23:
256 pStepper = new G4BogackiShampine23( pE );
257 if (fVerbose>0) { G4cout << "G4BogackiShampine23"; }
258 break;
259
260 // Higher order RK Steppers
261 // for smoother fields and high accuracy requirements
262 case 45:
263 pStepper = new G4BogackiShampine45( pE );
264 if (fVerbose>0) { G4cout << "G4BogackiShampine45"; }
265 break;
266 case 145:
267 pStepper = new G4TsitourasRK45( pE );
268 if (fVerbose>0) { G4cout << "G4TsitourasRK45"; }
269 break;
270 case 745:
271 pStepper = new G4DormandPrince745( pE );
272 if (fVerbose>0) { G4cout << "G4DormandPrince745"; }
273 break;
274
275 // Helical Steppers
276 case 6:
277 pStepper = new G4HelixImplicitEuler( pE );
278 if (fVerbose>0) { G4cout << "G4HelixImplicitEuler"; }
279 break;
280 case 7:
281 pStepper = new G4HelixSimpleRunge( pE );
282 if (fVerbose>0) { G4cout << "G4HelixSimpleRunge"; }
283 break;
284 case 5:
285 pStepper = new G4HelixExplicitEuler( pE );
286 if (fVerbose>0) { G4cout << "G4HelixExplicitEuler"; }
287 break; // Since Helix Explicit is used for long steps,
288 // this is useful only to measure overhead.
289 // Exact Helix - likely good only for cases of
290 // i) uniform field (potentially over small distances)
291 // ii) segmented uniform field (maybe)
292 case 9:
293 pStepper = new G4ExactHelixStepper( pE );
294 if (fVerbose>0) { G4cout << "G4ExactHelixStepper"; }
295 break;
296 case 10:
297 pStepper = new G4RKG3_Stepper( pE );
298 if (fVerbose>0) { G4cout << "G4RKG3_Stepper"; }
299 break;
300
301 // Low Order Steppers - not good except for very weak fields
302 case 11:
303 pStepper = new G4ExplicitEuler( pE );
304 if (fVerbose>0) { G4cout << "G4ExplicitEuler"; }
305 break;
306 case 12:
307 pStepper = new G4ImplicitEuler( pE );
308 if (fVerbose>0) { G4cout << "G4ImplicitEuler"; }
309 break;
310
311 case 0:
312 case -1:
313 default:
314 pStepper = new G4DormandPrince745( pE ); // Was G4ClassicalRK4( pE );
315 if (fVerbose>0) { G4cout << "G4DormandPrince745 (Default)"; }
316 break;
317 }
318
319 if(fVerbose>0)
320 {
321 G4cout << " chosen as stepper for small steps in G4HelixMixedStepper."
322 << G4endl;
323 }
324
325 return pStepper;
326}
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
double mag() const
G4BogackiShampine23 is an integrator of particle's equation of motion based on the Bogacki-Shampine n...
G4BogackiShampine45 is an integrator of particle's equation of motion based on the Bogacki-Shampine m...
G4CashKarpRKF45 implements the Cash-Karp Runge-Kutta-Fehlberg 4/5 method, an embedded fourth order me...
G4ClassicalRK4 integrates the equations of the motion of a particle in a magnetic field using the cla...
G4DormandPrince745 implements the 5th order embedded Runge-Kutta method, non-FSAL definition of the s...
G4ExactHelixStepper is a concrete class for particle motion in constant magnetic field....
G4ExplicitEuler implements an Explicit Euler stepper for magnetic field: x_1 = x_0 + h * dx_0....
G4HelixExplicitEuler implements an Explicit Euler stepper for magnetic field: x_1 = x_0 + helix(h),...
G4HelixImplicitEuler implements a helix implicit Euler stepper for magnetic field with 2nd order solv...
G4HelixMixedStepper(G4Mag_EqRhs *EqRhs, G4int StepperNumber=-1, G4double Angle_threshold=-1.0)
void Stepper(const G4double y[], const G4double dydx[], G4double h, G4double yout[], G4double yerr[]) override
void DumbStepper(const G4double y[], G4ThreeVector Bfld, G4double h, G4double yout[]) override
G4double DistChord() const override
G4MagIntegratorStepper * SetupStepper(G4Mag_EqRhs *EqRhs, G4int StepperName)
G4HelixSimpleRunge implements a simple Helix stepper for magnetic field with 2nd order solver.
G4ImplicitEuler implements a Euler stepper for magnetic field with 2nd order solver.
void SetCurve(const G4double Curve)
G4double GetRadHelix() const
void MagFieldEvaluate(const G4double y[], G4ThreeVector &Bfield)
G4MagHelicalStepper(G4Mag_EqRhs *EqRhs)
G4double GetInverseCurve(const G4double Momentum, const G4double Bmag)
void AdvanceHelix(const G4double yIn[], const G4ThreeVector &Bfld, G4double h, G4double yHelix[], G4double yHelix2[]=nullptr)
void SetAngCurve(const G4double Ang)
G4double GetAngCurve() const
G4MagIntegratorStepper is an abstract base class for integrator of particle's equation of motion,...
G4MagIntegratorStepper(G4EquationOfMotion *Equation, G4int numIntegrationVariables, G4int numStateVariables=12, G4bool isFSAL=false)
G4Mag_EqRhs is the "standard" equation of motion of a particle in a pure magnetic field.
G4NystromRK4 integrates the equations of the motion of a particle in a magnetic field using 4th Runge...
G4RKG3_Stepper implements a Runga-Kutta integrator stepper used in Geant-3.
G4SimpleHeum implements a simple Heum stepper for magnetic field with 3rd order solver.
G4SimpleRunge implements a simple Runge stepper for magnetic field with 2nd order solver.
G4TsitourasRK45 is an implementation of the 5(4) Runge-Kutta stepper (non-FSAL version).