Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4BorisDriver.cc
Go to the documentation of this file.
1// ********************************************************************
2// * License and Disclaimer *
3// * *
4// * The Geant4 software is copyright of the Copyright Holders of *
5// * the Geant4 Collaboration. It is provided under the terms and *
6// * conditions of the Geant4 Software License, included in the file *
7// * LICENSE and available at http://cern.ch/geant4/license . These *
8// * include a list of copyright holders. *
9// * *
10// * Neither the authors of this software system, nor their employing *
11// * institutes,nor the agencies providing financial support for this *
12// * work make any representation or warranty, express or implied, *
13// * regarding this software system or assume any liability for its *
14// * use. Please see the license in the file LICENSE and URL above *
15// * for the full disclaimer and the limitation of liability. *
16// * *
17// * This code implementation is the result of the scientific and *
18// * technical work of the GEANT4 collaboration. *
19// * By using, copying, modifying or distributing the software (or *
20// * any work based on the software) you agree to acknowledge its *
21// * use in resulting scientific publications, and indicate your *
22// * acceptance of all terms of the Geant4 Software license. *
23// ********************************************************************
24//
25// G4BorisDriver implementation
26//
27// Author: Divyansh Tiwari (CERN, Google Summer of Code 2022), 05.11.2022
28// Supervision: John Apostolakis (CERN), Renee Fatemi, Soon Yung Jun (FNAL)
29// --------------------------------------------------------------------
30#include <cassert>
31
32#include "G4BorisDriver.hh"
33
34#include "G4SystemOfUnits.hh"
35#include "G4LineSection.hh"
36#include "G4FieldUtils.hh"
37
38const G4double G4BorisDriver::fErrorConstraintShrink = std::pow(
39 fMaxSteppingDecrease / fSafetyFactor, 1. / fPowerShrink);
40
41const G4double G4BorisDriver::fErrorConstraintGrow = std::pow(
42 fMaxSteppingIncrease / fSafetyFactor, 1. / fPowerGrow);
43
44// --------------------------------------------------------------------------
45
47G4BorisDriver( G4double hminimum, G4BorisScheme* Boris,
48 G4int numberOfComponents, G4bool verbosity )
49 : fMinimumStep(hminimum),
50 fVerbosity(verbosity),
51 boris(Boris)
52 // , interval_sequence{2,4}
53{
54 assert(boris->GetNumberOfVariables() == numberOfComponents);
55
56 if(boris->GetNumberOfVariables() != numberOfComponents)
57 {
58 std::ostringstream msg;
59 msg << "Disagreement in number of variables = "
60 << boris->GetNumberOfVariables()
61 << " vs no of components = " << numberOfComponents;
62 G4Exception("G4BorisDriver Constructor:",
63 "GeomField1001", FatalException, msg);
64 }
65
66}
67
68// --------------------------------------------------------------------------
69
71 G4double hstep,
73 G4double hinitial )
74{
75 // Specification: Driver with adaptive stepsize control.
76 // Integrate starting values at y_current over hstep x2 with (relative) accuracy 'eps'.
77 // On output 'track' is replaced by values at the end of the integration interval.
78
79 // Ensure that hstep > 0
80 if(hstep == 0)
81 {
82 std::ostringstream message;
83 message << "Proposed step is zero; hstep = " << hstep << " !";
84 G4Exception("G4BorisDriver::AccurateAdvance()",
85 "GeomField1001", JustWarning, message);
86 return true;
87 }
88 if(hstep < 0)
89 {
90 std::ostringstream message;
91 message << "Invalid run condition." << G4endl
92 << "Proposed step is negative; hstep = " << hstep << G4endl
93 << "Requested step cannot be negative! Aborting event.";
94 G4Exception("G4BorisDriver::AccurateAdvance()",
95 "GeomField0003", EventMustBeAborted, message);
96 return false;
97 }
98
99 if( hinitial == 0.0 ) { hinitial = hstep; }
100 if( hinitial < 0.0 ) { hinitial = std::fabs( hinitial ); }
101 // G4double htrial = std::min( hstep, hinitial );
102 G4double htrial = hstep;
103 // Decide first step size
104
105 // G4int noOfSteps = h/hstep;
106
107 // integration variables
108 //
109 track.DumpToArray(yCurrent);
110
111 const G4double restMass = track.GetRestMass();
112 const G4double charge = track.GetCharge()*e_SI;
113 const G4int nvar= GetNumberOfVariables();
114
115 // copy non-integration variables to out array
116 //
117 std::memcpy(yOut + nvar,
118 yCurrent + nvar,
119 sizeof(G4double)*(G4FieldTrack::ncompSVEC-nvar));
120
121 G4double curveLength = track.GetCurveLength(); // starting value
122 const G4double endCurveLength = curveLength + hstep;
123
124 // -- Initial version: Did it in one step -- did not account for errors !!!
125 // G4FieldTrack yFldTrk(track);
126 // yFldTrk.LoadFromArray(yCurrent, G4FieldTrack::ncompSVEC);
127 // yFldTrk.SetCurveLength(curveLength);
128 // G4double dchord_step, dyerr_len;
129 // QuickAdvance(yFldTrk, dydxCurrent, htrial, dchord_step, dyerr_len);
130
131 const G4double hThreshold =
132 std::max(epsilon * hstep, fSmallestFraction * curveLength);
133
134 G4double htry= htrial;
135
136 for (G4int nstp = 0; nstp < fMaxNoSteps; ++nstp)
137 {
138 G4double hdid= 0.0, hnext=0.0;
139
140 OneGoodStep(yCurrent, curveLength, htry, epsilon, restMass, charge, hdid, hnext);
141 //*********
142
143 // Simple check: move (distance of displacement) is smaller than length along curve!
146 CheckStep(EndPos, StartPos, hdid);
147
148 // Check 1. for finish and 2. *avoid* numerous small last steps
149 if (curveLength >= endCurveLength || htry < hThreshold)
150 {
151 break;
152 }
153
154 htry = std::max(hnext, fMinimumStep);
155 if (curveLength + htry > endCurveLength)
156 {
157 htry = endCurveLength - curveLength;
158 }
159 }
160
161 // upload new state
162 track.LoadFromArray(yCurrent, G4FieldTrack::ncompSVEC);
163 track.SetCurveLength(curveLength);
164
165 return true;
166}
167
168// --------------------------------------------------------------------------
169
171 G4double& curveLength, // InOut
172 G4double htry,
173 G4double epsilon_rel,
174 G4double restMass,
175 G4double charge,
176 G4double& hdid, // Out
177 G4double& hnext) // Out
178{
179 G4double error2 = DBL_MAX;
181
182 G4double h = htry;
183
184 const G4int max_trials = 100;
185
186 for (G4int iter = 0; iter < max_trials; ++iter)
187 {
188 boris->StepWithErrorEstimate(y, restMass, charge, h, ytemp, yerr);
189
190 error2 = field_utils::relativeError2(y, yerr, std::max(h, fMinimumStep),
191 epsilon_rel);
192 if (error2 <= 1.0)
193 {
194 break;
195 }
196
197 h = ShrinkStepSize2(h, error2);
198
199 G4double xnew = curveLength + h;
200 if(xnew == curveLength)
201 {
202 std::ostringstream message;
203 message << "Stepsize underflow in Stepper !" << G4endl
204 << "- Step's start x=" << curveLength
205 << " and end x= " << xnew
206 << " are equal !! " << G4endl
207 << " Due to step-size= " << h
208 << ". Note that input step was " << htry;
209 G4Exception("G4IntegrationDriver::OneGoodStep()",
210 "GeomField1001", JustWarning, message);
211 break;
212 }
213 }
214
215 hnext = GrowStepSize2(h, error2);
216 curveLength += (hdid = h);
217
218 field_utils::copy(y, ytemp, GetNumberOfVariables());
219}
220
221// ===========------------------------------------------------------===========
222
224QuickAdvance( G4FieldTrack& track, const G4double /*dydx*/[],
225 G4double hstep, G4double& missDist, G4double& dyerr)
226{
227 const auto nvar = boris->GetNumberOfVariables();
228
229 track.DumpToArray(yIn);
230 const G4double curveLength = track.GetCurveLength();
231
232 // call the boris method for step length hstep
233 G4double restMass = track.GetRestMass();
234 G4double charge = track.GetCharge()*e_SI;
235
236 // boris->DoStep(restMass, charge, yIn, yMid, hstep*0.5);
237 // boris->DoStep(restMass, charge, yMid, yOut, hstep*0.5); // Use mid-point !!
238 boris->StepWithMidAndErrorEstimate(yIn, restMass, charge, hstep,
239 yMid, yOut, yError);
240 // Same, and also return mid-point evaluation
241
242 // How to calculate chord length??
243 const auto mid = field_utils::makeVector(yMid,
245 const auto in = field_utils::makeVector(yIn,
247 const auto out = field_utils::makeVector(yOut,
249
250 missDist = G4LineSection::Distline(mid, in, out);
251
252 dyerr = field_utils::absoluteError(yOut, yError, hstep);
253
254 // copy non-integrated variables to output array
255 //
256 std::memcpy(yOut + nvar, yIn + nvar,
257 sizeof(G4double) * (G4FieldTrack::ncompSVEC - nvar));
258
259 // set new state
260 //
262 track.SetCurveLength(curveLength + hstep);
263
264 return true;
265}
266
267// --------------------------------------------------------------------------------
268
270GetDerivatives( const G4FieldTrack& yTrack, G4double dydx[]) const
271{
272 G4double EBfieldValue[6];
273 GetDerivatives(yTrack, dydx, EBfieldValue);
274}
275
276// --------------------------------------------------------------------------------
277
279GetDerivatives( const G4FieldTrack& yTrack, G4double dydx[],
280 G4double EBfieldValue[]) const
281{
282 // G4Exception("G4BorisDriver::GetDerivatives()",
283 // "GeomField0003", FatalException, "This method is not implemented.");
285 yTrack.DumpToArray(ytemp);
286 GetEquationOfMotion()->EvaluateRhsReturnB(ytemp, dydx, EBfieldValue);
287}
288
289// --------------------------------------------------------------------------------
290
292{
293 if (error2 > fErrorConstraintShrink * fErrorConstraintShrink)
294 {
295 return fMaxSteppingDecrease * h;
296 }
297 return fSafetyFactor * h * std::pow(error2, 0.5 * fPowerShrink);
298}
299
300// --------------------------------------------------------------------------------
301
303// Given the square of the relative error,
304{
305 if (error2 < fErrorConstraintGrow * fErrorConstraintGrow)
306 {
307 return fMaxSteppingIncrease * h;
308 }
309 return fSafetyFactor * h * std::pow(error2, 0.5 * fPowerGrow);
310}
311
312// --------------------------------------------------------------------------------
313
315{
316 G4Exception("G4BorisDriver::SetEquationOfMotion()", "GeomField0003", FatalException,
317 "This method is not implemented. BorisDriver/Stepper should keep its equation");
318}
319
320// --------------------------------------------------------------------------------
321
322void
323G4BorisDriver::StreamInfo( std::ostream& os ) const
324{
325 os << "State of G4BorisDriver: " << std::endl;
326 os << " Method is implemented, but gives no information. " << std::endl;
327}
G4double epsilon(G4double density, G4double temperature)
@ JustWarning
@ FatalException
@ EventMustBeAborted
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
void OneGoodStep(G4double yCurrentState[], G4double &curveLength, G4double htry, G4double epsilon_rel, G4double restMass, G4double charge, G4double &hdid, G4double &hnext)
G4EquationOfMotion * GetEquationOfMotion() override
void StreamInfo(std::ostream &os) const override
G4double ShrinkStepSize2(G4double h, G4double error2) const
void GetDerivatives(const G4FieldTrack &track, G4double dydx[]) const override
G4BorisDriver(G4double hminimum, G4BorisScheme *Boris, G4int numberOfComponents=6, G4bool verbosity=false)
void SetEquationOfMotion(G4EquationOfMotion *equation) override
G4bool AccurateAdvance(G4FieldTrack &track, G4double stepLen, G4double eps, G4double beginStep=0) override
G4bool QuickAdvance(G4FieldTrack &y_val, const G4double dydx[], G4double hstep, G4double &missDist, G4double &dyerr) override
G4double GrowStepSize2(G4double h, G4double error2) const
The G4BorisScheme class implements of the Boris algorithm for advancing charged particles in an elect...
G4EquationOfMotion is the abstract base class for the right hand size of the equation of motion of a ...
void EvaluateRhsReturnB(const G4double y[], G4double dydx[], G4double Field[]) const
G4FieldTrack defines a data structure bringing together a magnetic track's state (position,...
G4double GetCurveLength() const
G4double GetCharge() const
void SetCurveLength(G4double nCurve_s)
G4double GetRestMass() const
void DumpToArray(G4double valArr[ncompSVEC]) const
void LoadFromArray(const G4double valArr[ncompSVEC], G4int noVarsIntegrated)
static G4double Distline(const G4ThreeVector &OtherPnt, const G4ThreeVector &LinePntA, const G4ThreeVector &LinePntB)
G4double absoluteError(const G4double y[], const G4double yerr[], G4double hstep)
G4double relativeError2(const G4double y[], const G4double yerr[], G4double hstep, G4double errorTolerance)
G4ThreeVector makeVector(const ArrayType &array, Value3D value)
void copy(G4double dst[], const G4double src[], std::size_t size=G4FieldTrack::ncompSVEC)
#define DBL_MAX
Definition templates.hh:62