ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4NystromRK4.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4NystromRK4.cc
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 // G4NystromRK4 implmentation
27 //
28 // Created: I.Gavrilenko, 15.05.2009 (as G4AtlasRK4)
29 // Adaptations: J.Apostolakis, November 2009
30 // -------------------------------------------------------------------
31 
32 #include "G4NystromRK4.hh"
33 
34 #include "G4Exception.hh"
35 #include "G4SystemOfUnits.hh"
36 #include "G4FieldUtils.hh"
37 #include "G4LineSection.hh"
38 
39 using namespace field_utils;
40 
41 namespace
42 {
43  G4bool notEquals(G4double p1, G4double p2)
44  {
45  return std::fabs(p1 - p2) > perMillion * p2;
46  }
47  constexpr G4int INTEGRATED_COMPONENTS = 6;
48 } // namespace
49 
50 
51 G4NystromRK4::G4NystromRK4(G4Mag_EqRhs* equation, G4double distanceConstField)
52  : G4MagIntegratorStepper(equation, INTEGRATED_COMPONENTS)
53 {
54  if (distanceConstField > 0)
55  {
56  SetDistanceForConstantField(distanceConstField);
57  }
58 }
59 
61  const G4double dydx[],
62  G4double hstep,
63  G4double yOut[],
64  G4double yError[])
65 {
66  fInitialPoint = { y[0], y[1], y[2] };
67 
68  G4double field[3];
69 
70  constexpr G4double one_sixth= 1./6.;
71  const G4double S5 = 0.5 * hstep;
72  const G4double S4 = .25 * hstep;
73  const G4double S6 = hstep * one_sixth;
74 
75  const G4double momentum2 = getValue2(y, Value3D::Momentum);
76  if (notEquals(momentum2, fMomentum2))
77  {
78  fMomentum = std::sqrt(momentum2);
79  fMomentum2 = momentum2;
82  }
83 
84  // Point 1
85  const G4double K1[3] = {
86  fInverseMomentum * dydx[3],
87  fInverseMomentum * dydx[4],
88  fInverseMomentum * dydx[5]
89  };
90 
91  // Point2
92  G4double p[4] = {
93  y[0] + S5 * (dydx[0] + S4 * K1[0]),
94  y[1] + S5 * (dydx[1] + S4 * K1[1]),
95  y[2] + S5 * (dydx[2] + S4 * K1[2]),
96  y[7]
97  };
98 
99  GetFieldValue(p, field);
100 
101  const G4double A2[3] = {
102  dydx[0] + S5 * K1[0],
103  dydx[1] + S5 * K1[1],
104  dydx[2] + S5 * K1[2]
105  };
106 
107  const G4double K2[3] = {
108  (A2[1] * field[2] - A2[2] * field[1]) * fCoefficient,
109  (A2[2] * field[0] - A2[0] * field[2]) * fCoefficient,
110  (A2[0] * field[1] - A2[1] * field[0]) * fCoefficient
111  };
112 
113  fMidPoint = { p[0], p[1], p[2] };
114 
115  // Point 3 with the same magnetic field
116  const G4double A3[3] = {
117  dydx[0] + S5 * K2[0],
118  dydx[1] + S5 * K2[1],
119  dydx[2] + S5 * K2[2]
120  };
121 
122  const G4double K3[3] = {
123  (A3[1] * field[2] - A3[2] * field[1]) * fCoefficient,
124  (A3[2] * field[0] - A3[0] * field[2]) * fCoefficient,
125  (A3[0] * field[1] - A3[1] * field[0]) * fCoefficient
126  };
127 
128  // Point 4
129  p[0] = y[0] + hstep * (dydx[0] + S5 * K3[0]);
130  p[1] = y[1] + hstep * (dydx[1] + S5 * K3[1]);
131  p[2] = y[2] + hstep * (dydx[2] + S5 * K3[2]);
132 
133  GetFieldValue(p, field);
134 
135  const G4double A4[3] = {
136  dydx[0] + hstep * K3[0],
137  dydx[1] + hstep * K3[1],
138  dydx[2] + hstep * K3[2]
139  };
140 
141  const G4double K4[3] = {
142  (A4[1] * field[2] - A4[2] * field[1]) * fCoefficient,
143  (A4[2] * field[0] - A4[0] * field[2]) * fCoefficient,
144  (A4[0] * field[1] - A4[1] * field[0]) * fCoefficient
145  };
146 
147  // New position
148  yOut[0] = y[0] + hstep * (dydx[0] + S6 * (K1[0] + K2[0] + K3[0]));
149  yOut[1] = y[1] + hstep * (dydx[1] + S6 * (K1[1] + K2[1] + K3[1]));
150  yOut[2] = y[2] + hstep * (dydx[2] + S6 * (K1[2] + K2[2] + K3[2]));
151  // New direction
152  yOut[3] = dydx[0] + S6 * (K1[0] + K4[0] + 2. * (K2[0] + K3[0]));
153  yOut[4] = dydx[1] + S6 * (K1[1] + K4[1] + 2. * (K2[1] + K3[1]));
154  yOut[5] = dydx[2] + S6 * (K1[2] + K4[2] + 2. * (K2[2] + K3[2]));
155  // Pass Energy, time unchanged -- time is not integrated !!
156  yOut[6] = y[6];
157  yOut[7] = y[7];
158 
159  fEndPoint = { yOut[0], yOut[1], yOut[2] };
160 
161  // Errors
162  yError[3] = hstep * std::fabs(K1[0] - K2[0] - K3[0] + K4[0]);
163  yError[4] = hstep * std::fabs(K1[1] - K2[1] - K3[1] + K4[1]);
164  yError[5] = hstep * std::fabs(K1[2] - K2[2] - K3[2] + K4[2]);
165  yError[0] = hstep * yError[3];
166  yError[1] = hstep * yError[4];
167  yError[2] = hstep * yError[5];
168  yError[3] *= fMomentum;
169  yError[4] *= fMomentum;
170  yError[5] *= fMomentum;
171 
172  // Normalize momentum
173  const G4double normF = fMomentum / getValue(yOut, Value3D::Momentum);
174  yOut[3] *= normF;
175  yOut[4] *= normF;
176  yOut[5] *= normF;
177 
178  // My trial code:
179  // G4double endMom2 = yOut[3]*yOut[3]+yOut[4]*yOut[4]+yOut[5]*yOut[5];
180  // G4double normF = std::sqrt( startMom2 / endMom2 );
181 }
182 
184 {
185  return G4LineSection::Distline(fMidPoint, fInitialPoint, fEndPoint);
186 }
187 
189 {
190  if (GetField() == nullptr)
191  {
192  G4Exception("G4NystromRK4::SetDistanceForConstantField",
193  "Nystrom 001", JustWarning,
194  "Provided field is not G4CachedMagneticField. Changing field type.");
195 
196  fCachedField = std::unique_ptr<G4CachedMagneticField>(
198  dynamic_cast<G4MagneticField*>(GetEquationOfMotion()->GetFieldObj()),
199  length));
200 
202  }
203  GetField()->SetConstDistance(length);
204 }
205 
207 {
208  if (GetField() == nullptr)
209  {
210  return 0.0;
211  }
212  return GetField()->GetConstDistance();
213 }
214 
216 {
217  return dynamic_cast<G4CachedMagneticField*>(GetEquationOfMotion()->GetFieldObj());
218 }
219 
221 {
222  return const_cast<G4NystromRK4*>(this)->GetField();
223 }