ATLAS Offline Software
Loading...
Searching...
No Matches
G4FieldManagerToolBase.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Primary include
7
8// Local includes
10
11// CLHEP includes
12#include "CLHEP/Units/SystemOfUnits.h"
13
14// Geant4 steppers
15#include "G4AtlasRK4.hh"
16#include "G4BogackiShampine23.hh"
17#include "G4BogackiShampine45.hh"
18#include "G4CashKarpRKF45.hh"
19#include "G4ClassicalRK4.hh"
20#include "G4DoLoMcPriRK34.hh"
21#include "G4DormandPrince745.hh"
22#include "G4DormandPrinceRK56.hh"
23#include "G4DormandPrinceRK78.hh"
24#include "G4FieldManager.hh"
25#include "G4HelixExplicitEuler.hh"
26#include "G4HelixImplicitEuler.hh"
27#include "G4HelixSimpleRunge.hh"
28#include "G4NystromRK4.hh"
29#include "G4RK547FEq1.hh"
30#include "G4RK547FEq2.hh"
31#include "G4RK547FEq3.hh"
32#include "G4RKG3_Stepper.hh"
33#include "G4TsitourasRK45.hh"
34
35// Geant4 includes
36#include "G4ChordFinder.hh"
37#include "G4IntegrationDriver.hh"
38#include "G4Mag_UsualEqRhs.hh"
39#include "G4MagIntegratorStepper.hh"
40#include "G4VIntegrationDriver.hh"
41
42//-----------------------------------------------------------------------------
43// Implementation file for class : G4FieldManagerToolBase
44//
45// 2015-11-17: Andrea Dell'Acqua
46//-----------------------------------------------------------------------------
47
48
49//=============================================================================
50// Standard constructor, initializes variables
51//=============================================================================
53 const std::string& name,
54 const IInterface* parent)
55 : base_class(type, name, parent)
56{
57}
58
59//=============================================================================
60// Initialize
61//=============================================================================
63{
64 ATH_MSG_DEBUG("G4FieldManagerToolBase::initialize()");
65
66 // Skip field svc retrieval if field disabled.
67 if(m_fieldOn) {
68 ATH_CHECK( m_fieldSvc.retrieve() );
69 }
70 else {
71 ATH_MSG_DEBUG("Field disabled. Not retrieving G4 field svc.");
72 }
73 if (!m_equationOfMotion.empty())
74 {
75 ATH_CHECK(m_equationOfMotion.retrieve());
76 }
77 return StatusCode::SUCCESS;
78}
79
80#if G4VERSION_NUMBER >= 1040
81//=============================================================================
82// Create the driver with a stepper (Geant4 >= 10.4)
83//=============================================================================
84G4VIntegrationDriver*
85G4FieldManagerToolBase::createDriverAndStepper(const std::string& name, G4MagneticField* field) const
86{
87 ATH_MSG_DEBUG("createDriverAndStepper");
88 G4Mag_EqRhs* eqRhs(nullptr);
89 if (!m_equationOfMotion.empty())
90 {
91 eqRhs = m_equationOfMotion->makeEquationOfMotion(field);
92 ATH_MSG_INFO("Configuring alternative equation of motion using " <<
93 m_equationOfMotion.name() );
94 }
95 else
96 {
97 ATH_MSG_VERBOSE("Using G4Mag_UsualEqRhs as the equation of motion.");
98 eqRhs = new G4Mag_UsualEqRhs(field);
99 }
100 // @TODO Add some way of confirming that the choices of Equation of
101 // motion and stepper are compatible.
102 G4VIntegrationDriver* driver = nullptr;
103 if (name=="HelixImplicitEuler") {
104 G4HelixImplicitEuler* stepper = new G4HelixImplicitEuler(eqRhs);
105 driver = new G4IntegrationDriver<G4HelixImplicitEuler>(
106 m_minStep, stepper, stepper->GetNumberOfVariables());
107 } else if (name=="HelixSimpleRunge") {
108 G4HelixSimpleRunge* stepper = new G4HelixSimpleRunge(eqRhs);
109 driver = new G4IntegrationDriver<G4HelixSimpleRunge>(
110 m_minStep, stepper, stepper->GetNumberOfVariables());
111 } else if (name=="HelixExplicitEuler") {
112 G4HelixExplicitEuler* stepper = new G4HelixExplicitEuler(eqRhs);
113 driver = new G4IntegrationDriver<G4HelixExplicitEuler>(
114 m_minStep, stepper, stepper->GetNumberOfVariables());
115 } else if (name=="NystromRK4") {
116 G4NystromRK4* stepper = new G4NystromRK4(eqRhs);
117 driver = new G4IntegrationDriver<G4NystromRK4>(
118 m_minStep, stepper, stepper->GetNumberOfVariables());
119 } else if (name=="ClassicalRK4") {
120 G4ClassicalRK4* stepper = new G4ClassicalRK4(eqRhs);
121 driver = new G4IntegrationDriver<G4ClassicalRK4>(
122 m_minStep, stepper, stepper->GetNumberOfVariables());
123 } else if (name=="AtlasRK4") {
124 G4AtlasRK4* stepper = new G4AtlasRK4(eqRhs);
125 driver = new G4IntegrationDriver<G4AtlasRK4>(
126 m_minStep, stepper, stepper->GetNumberOfVariables());
127 } else if (name=="BogackiShampine23") {
128 G4BogackiShampine23* stepper = new G4BogackiShampine23(eqRhs);
129 driver = new G4IntegrationDriver<G4BogackiShampine23>(
130 m_minStep, stepper, stepper->GetNumberOfVariables());
131 } else if (name=="BogackiShampine45") {
132 G4BogackiShampine45* stepper = new G4BogackiShampine45(eqRhs);
133 driver = new G4IntegrationDriver<G4BogackiShampine45>(
134 m_minStep, stepper, stepper->GetNumberOfVariables());
135 } else if (name=="CashKarpRKF45") {
136 G4CashKarpRKF45* stepper = new G4CashKarpRKF45(eqRhs);
137 driver = new G4IntegrationDriver<G4CashKarpRKF45>(
138 m_minStep, stepper, stepper->GetNumberOfVariables());
139 } else if (name=="DoLoMcPriRK34") {
140 G4DoLoMcPriRK34* stepper = new G4DoLoMcPriRK34(eqRhs);
141 driver = new G4IntegrationDriver<G4DoLoMcPriRK34>(
142 m_minStep, stepper, stepper->GetNumberOfVariables());
143 } else if (name=="DormandPrince745") {
144 G4DormandPrince745* stepper = new G4DormandPrince745(eqRhs);
145 driver = new G4IntegrationDriver<G4DormandPrince745>(
146 m_minStep, stepper, stepper->GetNumberOfVariables());
147 } else if (name=="DormandPrinceRK56") {
148 G4DormandPrinceRK56* stepper = new G4DormandPrinceRK56(eqRhs);
149 driver = new G4IntegrationDriver<G4DormandPrinceRK56>(
150 m_minStep, stepper, stepper->GetNumberOfVariables());
151 } else if (name=="DormandPrinceRK78") {
152 G4DormandPrinceRK78* stepper = new G4DormandPrinceRK78(eqRhs);
153 driver = new G4IntegrationDriver<G4DormandPrinceRK78>(
154 m_minStep, stepper, stepper->GetNumberOfVariables());
155 } else if (name=="RK547FEq1") {
156 G4RK547FEq1* stepper = new G4RK547FEq1(eqRhs);
157 driver = new G4IntegrationDriver<G4RK547FEq1>(
158 m_minStep, stepper, stepper->GetNumberOfVariables());
159 } else if (name=="RK547FEq2") {
160 G4RK547FEq2* stepper = new G4RK547FEq2(eqRhs);
161 driver = new G4IntegrationDriver<G4RK547FEq2>(
162 m_minStep, stepper, stepper->GetNumberOfVariables());
163 } else if (name=="RK547FEq3") {
164 G4RK547FEq3* stepper = new G4RK547FEq3(eqRhs);
165 driver = new G4IntegrationDriver<G4RK547FEq3>(
166 m_minStep, stepper, stepper->GetNumberOfVariables());
167 } else if (name=="RKG3_Stepper") {
168 G4RKG3_Stepper* stepper = new G4RKG3_Stepper(eqRhs);
169 driver = new G4IntegrationDriver<G4RKG3_Stepper>(
170 m_minStep, stepper, stepper->GetNumberOfVariables());
171 } else if (name=="TsitourasRK45") {
172 G4TsitourasRK45* stepper = new G4TsitourasRK45(eqRhs);
173 driver = new G4IntegrationDriver<G4TsitourasRK45>(
174 m_minStep, stepper, stepper->GetNumberOfVariables());
175 } else {
176 ATH_MSG_ERROR("Stepper " << name << " not available! returning NystromRK4!");
177 G4NystromRK4* stepper = new G4NystromRK4(eqRhs);
178 driver = new G4IntegrationDriver<G4NystromRK4>(
179 m_minStep, stepper, stepper->GetNumberOfVariables());
180 }
181 return driver;
182}
183#endif
184
185#if G4VERSION_NUMBER < 1040
186//=============================================================================
187// Create the stepper (Geant4 < 10.4)
188//=============================================================================
189G4MagIntegratorStepper*
190G4FieldManagerToolBase::getStepper(const std::string& name, G4MagneticField* field) const
191{
192 ATH_MSG_DEBUG("getStepper");
193 G4Mag_EqRhs* eqRhs(nullptr);
194 if (!m_equationOfMotion.empty())
195 {
196 eqRhs = m_equationOfMotion->makeEquationOfMotion(field);
197 ATH_MSG_INFO("Configuring alternative equation of motion using " <<
198 m_equationOfMotion.name() );
199 }
200 else
201 {
202 ATH_MSG_VERBOSE("Using G4Mag_UsualEqRhs as the equation of motion.");
203 eqRhs = new G4Mag_UsualEqRhs(field);
204 }
205 // @TODO Add some way of confirming that the choices of Equation of
206 // motion and stepper are compatible.
207 // @TODO consider moving the stepper choice into a tool as well?
208 // Only worthwhile if we envisage adding more stepper choices in the
209 // future.
210 if (name=="HelixImplicitEuler") return new G4HelixImplicitEuler(eqRhs);
211 else if (name=="HelixSimpleRunge") return new G4HelixSimpleRunge(eqRhs);
212 else if (name=="HelixExplicitEuler") return new G4HelixExplicitEuler(eqRhs);
213 else if (name=="NystromRK4") return new G4NystromRK4(eqRhs);
214 else if (name=="ClassicalRK4") return new G4ClassicalRK4(eqRhs);
215 else if (name=="AtlasRK4") return new G4AtlasRK4(eqRhs);
216 else if (name=="BogackiShampine23") return new G4BogackiShampine23(eqRhs);
217 else if (name=="BogackiShampine45") return new G4BogackiShampine45(eqRhs);
218 else if (name=="CashKarpRKF45") return new G4CashKarpRKF45(eqRhs);
219 else if (name=="DoLoMcPriRK34") return new G4DoLoMcPriRK34(eqRhs);
220 else if (name=="DormandPrince745") return new G4DormandPrince745(eqRhs);
221 else if (name=="DormandPrinceRK56") return new G4DormandPrinceRK56(eqRhs);
222 else if (name=="DormandPrinceRK78") return new G4DormandPrinceRK78(eqRhs);
223 else if (name=="RK547FEq1") return new G4RK547FEq1(eqRhs);
224 else if (name=="RK547FEq2") return new G4RK547FEq2(eqRhs);
225 else if (name=="RK547FEq3") return new G4RK547FEq3(eqRhs);
226 else if (name=="RKG3_Stepper") return new G4RKG3_Stepper(eqRhs);
227 else if (name=="TsitourasRK45") return new G4TsitourasRK45(eqRhs);
228 else {
229 ATH_MSG_ERROR("Stepper " << name << " not available! returning NystromRK4!");
230 return new G4NystromRK4(eqRhs);
231 }
232}
233#endif
234
235//=============================================================================
236// Create the stepper
237//=============================================================================
239setFieldParameters(G4FieldManager* fieldMgr) const
240{
241 ATH_MSG_DEBUG("setFieldParameters");
242 if (fieldMgr) {
243 if (m_deltaChord>0) fieldMgr->GetChordFinder()->SetDeltaChord(m_deltaChord);
244 if (m_deltaOneStep>0) fieldMgr->SetDeltaOneStep(m_deltaOneStep);
245 if (m_deltaIntersection>0) fieldMgr->SetDeltaIntersection(m_deltaIntersection);
246
247 auto minEps_actual = m_minEps > 0 ? m_minEps.value() : fieldMgr->GetMinimumEpsilonStep();
248 auto maxEps_actual = m_maxEps > 0 ? m_maxEps.value() : fieldMgr->GetMaximumEpsilonStep();
249 G4FieldManagerHelper::SetMinAndMaxEpsilonStep(fieldMgr, minEps_actual, maxEps_actual);
250 }
251 else {
252 ATH_MSG_ERROR("setFieldParameters received NULL field mgr!");
253 return StatusCode::FAILURE;
254 }
255 return StatusCode::SUCCESS;
256}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
Helper functions for G4FieldManager to adapt to changes in Geant4 interfaces since 10....
StatusCode setFieldParameters(G4FieldManager *fieldMgr) const
Common method to apply configuredfield parameters.
Gaudi::Property< double > m_deltaChord
G4MagIntegratorStepper * getStepper(const std::string &stepperType, G4MagneticField *field) const
Common method to construct a stepper of requested type.
ToolHandle< IEquationOfMotionTool > m_equationOfMotion
The type of equation of motion to use.
virtual StatusCode initialize() override
Initialize method.
Gaudi::Property< double > m_maxEps
Gaudi::Property< double > m_deltaIntersection
ServiceHandle< IG4FieldSvc > m_fieldSvc
Handle to the G4 field service.
Gaudi::Property< bool > m_fieldOn
Gaudi::Property< double > m_deltaOneStep
G4FieldManagerToolBase(const std::string &type, const std::string &name, const IInterface *parent)
Standard constructor.
Gaudi::Property< double > m_minStep
Gaudi::Property< double > m_minEps
G4bool SetMinAndMaxEpsilonStep(G4FieldManager *fieldMgr, double eps_min, double eps_max)
Set epsilon step range for a G4FieldManager instance accounting for Geant4 sanity checks.