38G4double G4FieldManager::fDefault_Delta_One_Step_Value= 0.01 * millimeter;
39G4double G4FieldManager::fDefault_Delta_Intersection_Val= 0.001 * millimeter;
51 G4bool fieldChangesEnergy )
52 : fDetectorField(detectorField),
53 fChordFinder(pChordFinder),
54 fDelta_One_Step_Value( fDefault_Delta_One_Step_Value ),
55 fDelta_Intersection_Val( fDefault_Delta_Intersection_Val ),
56 fEpsilonMin( fEpsilonMinDefault ),
57 fEpsilonMax( fEpsilonMaxDefault)
59 if ( detectorField !=
nullptr )
65 fFieldChangesEnergy = fieldChangesEnergy;
70 G4cout <<
"G4FieldManager/ctor#1 fEpsilon Min/Max: eps_min = " << fEpsilonMin <<
" eps_max=" << fEpsilonMax <<
G4endl;
79 : fDetectorField(detectorField), fAllocatedChordFinder(true),
80 fDelta_One_Step_Value( fDefault_Delta_One_Step_Value ),
81 fDelta_Intersection_Val( fDefault_Delta_Intersection_Val ),
82 fEpsilonMin( fEpsilonMinDefault ),
83 fEpsilonMax( fEpsilonMaxDefault )
89 G4cout <<
"G4FieldManager/ctor#2 fEpsilon Min/Max: eps_min = " << fEpsilonMin <<
" eps_max=" << fEpsilonMax <<
G4endl;
102 if ( fDetectorField !=
nullptr )
104 aField = fDetectorField->
Clone();
110 aFM =
new G4FieldManager( aField ,
nullptr , fFieldChangesEnergy );
115 if ( fAllocatedChordFinder )
126 aFM->fChordFinder = aCF;
131 aFM->fEpsilonMax = fEpsilonMax;
132 aFM->fEpsilonMin = fEpsilonMin;
133 aFM->fDelta_Intersection_Val = fDelta_Intersection_Val;
134 aFM->fDelta_One_Step_Value = fDelta_One_Step_Value;
149 G4cout <<
"G4FieldManager/clone fEpsilon Min/Max: eps_min = " << fEpsilonMin <<
" eps_max=" << fEpsilonMax <<
G4endl;
160 if( fAllocatedChordFinder )
170 if ( fAllocatedChordFinder )
174 fAllocatedChordFinder =
false;
176 if( detectorMagField !=
nullptr )
179 fAllocatedChordFinder =
true;
183 fChordFinder =
nullptr;
187void G4FieldManager::InitialiseFieldChangesEnergy()
189 if ( fDetectorField !=
nullptr )
195 fFieldChangesEnergy =
false;
207 fDetectorField = pDetectorField;
208 InitialiseFieldChangesEnergy();
212 if( fChordFinder !=
nullptr )
214 failMode= std::max( failMode, 1) ;
218 if( driver !=
nullptr )
225 if( equation !=
nullptr )
233 if( !ableToSet && (failMode > 0) )
238 msg <<
"Unable to set the field in the dependent objects of G4FieldManager"
240 msg <<
"All the dependent classes must be fully initialised,"
241 <<
"before it is possible to call this method." <<
G4endl;
242 msg <<
"The problem encountered was the following: " <<
G4endl;
243 if( fChordFinder ==
nullptr ) { msg <<
" No ChordFinder. " ; }
244 else if( driver ==
nullptr ) { msg <<
" No Integration Driver set. ";}
245 else if( equation ==
nullptr ) { msg <<
" No Equation found. " ; }
247 else { msg <<
" Can NOT find reason for failure. ";}
251 G4Exception(
"G4FieldManager::SetDetectorField",
"Geometry001",
263 if(newEpsMax >= fEpsilonMin)
265 fEpsilonMax = newEpsMax;
269 G4cout <<
"G4FieldManager/SetEpsMax : eps_max = " << std::setw(10) << fEpsilonMax
270 <<
" ( Note: unchanged eps_min=" << std::setw(10) << fEpsilonMin <<
" )" <<
G4endl;
276 erm <<
" Call to set eps_max = " << newEpsMax <<
" . The problem is that"
277 <<
" its value must be at larger or equal to eps_min= " << fEpsilonMin <<
G4endl;
278 erm <<
" Modifying both to the same value " << newEpsMax <<
" to ensure consistency."
280 <<
" To avoid this warning, please set eps_min first, and ensure that "
283 fEpsilonMax = newEpsMax;
284 fEpsilonMin = newEpsMax;
308 fEpsilonMin = newEpsMin;
314 G4cout <<
"G4FieldManager/SetEpsMin : eps_min = "
315 << std::setw(10) << fEpsilonMin <<
G4endl;
317 if( fEpsilonMax < fEpsilonMin )
321 erm <<
"Setting eps_min = " << newEpsMin
322 <<
" For consistency set eps_max= " << fEpsilonMin
323 <<
" ( Old value = " << fEpsilonMax <<
" )" <<
G4endl;
324 fEpsilonMax = fEpsilonMin;
365 G4cout <<
"G4FieldManager::" << __func__
374 erm <<
"Proposed value for maximum-accepted-epsilon = " << maxAcceptValue
377 <<
"This may impact the robustness of integration of tracks in field."
380 <<
" , but future releases are expected " <<
G4endl
381 <<
" to tighten the limit of acceptable values to "
383 <<
"Suggestion: If you need better performance investigate using "
384 <<
"alternative, low-order RK integration methods or " <<
G4endl
385 <<
" helix-based methods (for pure B-fields) for low(er) energy tracks, "
386 <<
" especially electrons if you need better performance." <<
G4endl;
392 erm <<
" Proposed value for maximum accepted epsilon " << maxAcceptValue
397 erm <<
" Using the latter value instead." <<
G4endl;
404 erm <<
" NOTE: you can accept the ceiling value and turn this into a "
405 <<
" warning by using a 2nd argument " <<
G4endl
406 <<
" in your call to SetMaxAcceptedEpsilon: softFailure = true ";
414 G4Exception(methodName.c_str(),
"Geometry003", severity, erm);
424 erm <<
"Incorrect proposed value of " << name <<
" = " << value <<
G4endl
425 <<
" Its value is outside the permitted range from "
427 <<
" Clarification: " <<
G4endl;
428 G4long oldPrec = erm.precision();
431 erm <<
" a) The value must be positive and enough larger than the accuracy limit"
432 <<
" of the (G4)double type - ("
434 <<
" i.e. std::numeric_limits<G4double>::epsilon()= "
435 << std::numeric_limits<G4double>::epsilon()
436 <<
" to ensure that integration " <<
G4endl
437 <<
" could potentially achieve this acccuracy." <<
G4endl
442 erm <<
" b) It must be smaller than (or equal) " << std::setw(8)
444 <<
" to ensure robustness of integration - ("
449 G4bool badRoundoff = (std::fabs(1.0+value) == 1.0);
450 erm <<
" Unknown ERROR case -- extra check: " <<
G4endl;
451 erm <<
" c) as a floating point number (of type G4double) the sum (1+" << name
452 <<
" ) must be > 1 , ("
453 << (badRoundoff ?
"FAILED" :
"OK" ) <<
")" <<
G4endl
454 <<
" Now 1+eps_min = " << std::setw(20)
455 << std::setprecision(17) << (1+value) <<
G4endl
456 <<
" and (1.0+" << name <<
") - 1.0 = " << std::setw(20)
457 << std::setprecision(9) << (1.0+value)-1.0;
459 erm.precision(oldPrec);
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4GLOB_DLL std::ostream G4cout
G4VIntegrationDriver * GetIntegrationDriver()
void SetFieldObj(G4Field *pField)
static void DeRegister(G4FieldManager *pVolume)
static void Register(G4FieldManager *pVolume)
virtual G4FieldManager * Clone() const
static G4double GetMaxAcceptedEpsilon()
virtual ~G4FieldManager()
G4bool SetDetectorField(G4Field *detectorField, G4int failMode=0)
static constexpr G4double fMinAcceptedEpsilon
static constexpr G4double fMaxWarningEpsilon
void CreateChordFinder(G4MagneticField *detectorMagField)
G4bool SetMaximumEpsilonStep(G4double newEpsMax)
static G4double fMaxAcceptedEpsilon
void ReportBadEpsilonValue(G4ExceptionDescription &erm, G4double value, G4String &name) const
G4bool SetMinimumEpsilonStep(G4double newEpsMin)
virtual void ConfigureForTrack(const G4Track *)
G4FieldManager(G4Field *detectorField=nullptr, G4ChordFinder *pChordFinder=nullptr, G4bool b=true)
static G4bool fVerboseConstruction
static constexpr G4double fMaxFinalEpsilon
static G4bool SetMaxAcceptedEpsilon(G4double maxEps, G4bool softFail=false)
virtual G4bool DoesFieldChangeEnergy() const =0
virtual G4Field * Clone() const
virtual G4EquationOfMotion * GetEquationOfMotion()=0