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;
69 G4cout <<
"G4FieldManager/ctor#1 fEpsilon Min/Max: eps_min = " << fEpsilonMin <<
" eps_max=" << fEpsilonMax <<
G4endl;
77 : fDetectorField(detectorField), fAllocatedChordFinder(true),
78 fDelta_One_Step_Value( fDefault_Delta_One_Step_Value ),
79 fDelta_Intersection_Val( fDefault_Delta_Intersection_Val ),
80 fEpsilonMin( fEpsilonMinDefault ),
81 fEpsilonMax( fEpsilonMaxDefault )
86 G4cout <<
"G4FieldManager/ctor#2 fEpsilon Min/Max: eps_min = " << fEpsilonMin <<
" eps_max=" << fEpsilonMax <<
G4endl;
98 if ( fDetectorField !=
nullptr )
100 aField = fDetectorField->
Clone();
106 aFM =
new G4FieldManager( aField ,
nullptr , fFieldChangesEnergy );
111 if ( fAllocatedChordFinder )
122 aFM->fChordFinder = aCF;
127 aFM->fEpsilonMax = fEpsilonMax;
128 aFM->fEpsilonMin = fEpsilonMin;
129 aFM->fDelta_Intersection_Val = fDelta_Intersection_Val;
130 aFM->fDelta_One_Step_Value = fDelta_One_Step_Value;
145 G4cout <<
"G4FieldManager/clone fEpsilon Min/Max: eps_min = " << fEpsilonMin <<
" eps_max=" << fEpsilonMax <<
G4endl;
156 if( fAllocatedChordFinder )
166 if ( fAllocatedChordFinder )
170 fAllocatedChordFinder =
false;
172 if( detectorMagField !=
nullptr )
175 fAllocatedChordFinder =
true;
179 fChordFinder =
nullptr;
183void G4FieldManager::InitialiseFieldChangesEnergy()
185 if ( fDetectorField !=
nullptr )
191 fFieldChangesEnergy =
false;
203 fDetectorField = pDetectorField;
204 InitialiseFieldChangesEnergy();
208 if( fChordFinder !=
nullptr )
210 failMode= std::max( failMode, 1) ;
214 if( driver !=
nullptr )
221 if( equation !=
nullptr )
229 if( !ableToSet && (failMode > 0) )
234 msg <<
"Unable to set the field in the dependent objects of G4FieldManager"
236 msg <<
"All the dependent classes must be fully initialised,"
237 <<
"before it is possible to call this method." <<
G4endl;
238 msg <<
"The problem encountered was the following: " <<
G4endl;
239 if( fChordFinder ==
nullptr ) { msg <<
" No ChordFinder. " ; }
240 else if( driver ==
nullptr ) { msg <<
" No Integration Driver set. ";}
241 else if( equation ==
nullptr ) { msg <<
" No Equation found. " ; }
243 else { msg <<
" Can NOT find reason for failure. ";}
247 G4Exception(
"G4FieldManager::SetDetectorField",
"Geometry001",
259 if(newEpsMax >= fEpsilonMin){
260 fEpsilonMax = newEpsMax;
264 G4cout <<
"G4FieldManager/SetEpsMax : eps_max = " << std::setw(10) << fEpsilonMax
265 <<
" ( Note: unchanged eps_min=" << std::setw(10) << fEpsilonMin <<
" )" <<
G4endl;
269 erm <<
" Call to set eps_max = " << newEpsMax <<
" . The problem is that"
270 <<
" its value must be at larger or equal to eps_min= " << fEpsilonMin <<
G4endl;
271 erm <<
" Modifying both to the same value " << newEpsMax <<
" to ensure consistency."
273 <<
" To avoid this warning, please set eps_min first, and ensure that "
276 fEpsilonMax = newEpsMax;
277 fEpsilonMin = newEpsMax;
301 fEpsilonMin = newEpsMin;
307 G4cout <<
"G4FieldManager/SetEpsMin : eps_min = "
308 << std::setw(10) << fEpsilonMin <<
G4endl;
310 if( fEpsilonMax < fEpsilonMin ){
313 erm <<
"Setting eps_min = " << newEpsMin
314 <<
" For consistency set eps_max= " << fEpsilonMin
315 <<
" ( Old value = " << fEpsilonMax <<
" )" <<
G4endl;
316 fEpsilonMax = fEpsilonMin;
357 G4cout <<
"G4FieldManager::" << __func__
366 erm <<
"Proposed value for maximum-accepted-epsilon = " << maxAcceptValue
369 <<
"This may impact the robustness of integration of tracks in field."
372 <<
" , but future releases are expected " <<
G4endl
373 <<
" to tighten the limit of acceptable values to "
375 <<
"Suggestion: If you need better performance investigate using "
376 <<
"alternative, low-order RK integration methods or " <<
G4endl
377 <<
" helix-based methods (for pure B-fields) for low(er) energy tracks, "
378 <<
" especially electrons if you need better performance." <<
G4endl;
384 erm <<
" Proposed value for maximum accepted epsilon " << maxAcceptValue
388 erm <<
" Using the latter value instead." <<
G4endl;
392 if( softFailure ==
false )
393 erm <<
" NOTE: you can accept the ceiling value and turn this into a "
394 <<
" warning by using a 2nd argument " <<
G4endl
395 <<
" in your call to SetMaxAcceptedEpsilon: softFailure = true ";
402 G4Exception(methodName.c_str(),
"Geometry003", severity, erm);
412 erm <<
"Incorrect proposed value of " << name <<
" = " << value <<
G4endl
413 <<
" Its value is outside the permitted range from "
415 <<
" Clarification: " <<
G4endl;
416 G4long oldPrec = erm.precision();
419 erm <<
" a) The value must be positive and enough larger than the accuracy limit"
420 <<
" of the (G4)double type - ("
422 <<
" i.e. std::numeric_limits<G4double>::epsilon()= "
423 << std::numeric_limits<G4double>::epsilon()
424 <<
" to ensure that integration " <<
G4endl
425 <<
" could potentially achieve this acccuracy." <<
G4endl
430 erm <<
" b) It must be smaller than (or equal) " << std::setw(8)
432 <<
" to ensure robustness of integration - ("
437 G4bool badRoundoff = (std::fabs(1.0+value) == 1.0);
438 erm <<
" Unknown ERROR case -- extra check: " <<
G4endl;
439 erm <<
" c) as a floating point number (of type G4double) the sum (1+" << name
440 <<
" ) must be > 1 , ("
441 << (badRoundoff ?
"FAILED" :
"OK" ) <<
")" <<
G4endl
442 <<
" Now 1+eps_min = " << std::setw(20)
443 << std::setprecision(17) << (1+value) <<
G4endl
444 <<
" and (1.0+" << name <<
") - 1.0 = " << std::setw(20)
445 << std::setprecision(9) << (1.0+value)-1.0;
447 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