File indexing completed on 2025-01-18 09:59:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 #ifndef G4T_CASH_KARP_RKF45_HH
0055 #define G4T_CASH_KARP_RKF45_HH
0056
0057 #include <cassert>
0058
0059 #include "G4LineSection.hh"
0060 #include "G4MagIntegratorStepper.hh"
0061
0062 template <class T_Equation, unsigned int N = 6 >
0063 class G4TCashKarpRKF45 : public G4MagIntegratorStepper
0064 {
0065 public:
0066
0067 G4TCashKarpRKF45(T_Equation* EqRhs,
0068 G4bool primary = true);
0069
0070 virtual ~G4TCashKarpRKF45();
0071
0072 inline void
0073 StepWithError(const G4double yInput[],
0074 const G4double dydx[],
0075 G4double Step,
0076 G4double yOut[],
0077 G4double yErr[] );
0078
0079 virtual void Stepper(const G4double yInput[],
0080 const G4double dydx[],
0081 G4double hstep,
0082 G4double yOutput[],
0083 G4double yError[]) override final;
0084
0085
0086 void RightHandSideInl( const G4double y[],
0087 G4double dydx[] )
0088 {
0089 fEquation_Rhs->T_Equation::RightHandSide(y, dydx);
0090 }
0091
0092 inline G4double DistChord() const override;
0093
0094 inline G4int IntegratorOrder() const override { return 4; }
0095
0096 private:
0097 G4TCashKarpRKF45(const G4TCashKarpRKF45&);
0098 G4TCashKarpRKF45& operator=(const G4TCashKarpRKF45&);
0099
0100
0101 private:
0102 G4double ak2[N], ak3[N], ak4[N], ak5[N], ak6[N], ak7[N], yTemp[N], yIn[N];
0103
0104
0105 G4double fLastStepLength= 0.0;
0106 G4double* fLastInitialVector;
0107 G4double* fLastFinalVector;
0108 G4double* fLastDyDx;
0109 G4double* fMidVector;
0110 G4double* fMidError;
0111
0112
0113 G4TCashKarpRKF45* fAuxStepper = nullptr;
0114
0115 T_Equation* fEquation_Rhs;
0116 };
0117
0118
0119
0120
0121
0122 template <class T_Equation, unsigned int N >
0123 G4TCashKarpRKF45<T_Equation,N>::G4TCashKarpRKF45(T_Equation* EqRhs,
0124 G4bool primary)
0125 : G4MagIntegratorStepper(dynamic_cast<G4EquationOfMotion*>(EqRhs), N )
0126 , fEquation_Rhs(EqRhs)
0127 {
0128 if( dynamic_cast<G4EquationOfMotion*>(EqRhs) == nullptr )
0129 {
0130 G4Exception("G4TCashKarpRKF45: constructor", "GeomField0001",
0131 FatalException, "Equation is not an G4EquationOfMotion.");
0132 }
0133
0134 fLastInitialVector = new G4double[N];
0135 fLastFinalVector = new G4double[N];
0136 fLastDyDx = new G4double[N];
0137
0138 fMidVector = new G4double[N];
0139 fMidError = new G4double[N];
0140
0141 if(primary)
0142 {
0143 fAuxStepper = new G4TCashKarpRKF45<T_Equation, N> (EqRhs, !primary);
0144 }
0145 }
0146
0147 template <class T_Equation, unsigned int N >
0148 G4TCashKarpRKF45<T_Equation,N>::~G4TCashKarpRKF45()
0149 {
0150 delete[] fLastInitialVector;
0151 delete[] fLastFinalVector;
0152 delete[] fLastDyDx;
0153 delete[] fMidVector;
0154 delete[] fMidError;
0155
0156 delete fAuxStepper;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 template <class T_Equation, unsigned int N >
0170 inline void
0171 G4TCashKarpRKF45<T_Equation,N>::StepWithError(const G4double* yInput,
0172 const G4double* dydx,
0173 G4double Step,
0174 G4double * yOut,
0175 G4double * yErr)
0176 {
0177
0178
0179 const G4double b21 = 0.2, b31 = 3.0 / 40.0, b32 = 9.0 / 40.0, b41 = 0.3,
0180 b42 = -0.9, b43 = 1.2,
0181
0182 b51 = -11.0 / 54.0, b52 = 2.5, b53 = -70.0 / 27.0,
0183 b54 = 35.0 / 27.0,
0184
0185 b61 = 1631.0 / 55296.0, b62 = 175.0 / 512.0,
0186 b63 = 575.0 / 13824.0, b64 = 44275.0 / 110592.0,
0187 b65 = 253.0 / 4096.0,
0188
0189 c1 = 37.0 / 378.0, c3 = 250.0 / 621.0, c4 = 125.0 / 594.0,
0190 c6 = 512.0 / 1771.0, dc5 = -277.0 / 14336.0;
0191
0192 const G4double dc1 = c1 - 2825.0 / 27648.0, dc3 = c3 - 18575.0 / 48384.0,
0193 dc4 = c4 - 13525.0 / 55296.0, dc6 = c6 - 0.25;
0194
0195
0196
0197
0198
0199
0200
0201 for(unsigned int i = 0; i < N; ++i)
0202 {
0203 yIn[i] = yInput[i];
0204 }
0205
0206
0207 for(unsigned int i = 0; i < N; ++i)
0208 {
0209 yTemp[i] = yIn[i] + b21 * Step * dydx[i];
0210 }
0211 this->RightHandSideInl(yTemp, ak2);
0212
0213 for(unsigned int i = 0; i < N; ++i)
0214 {
0215 yTemp[i] = yIn[i] + Step * (b31 * dydx[i] + b32 * ak2[i]);
0216 }
0217 this->RightHandSideInl(yTemp, ak3);
0218
0219 for(unsigned int i = 0; i < N; ++i)
0220 {
0221 yTemp[i] = yIn[i] + Step * (b41 * dydx[i] + b42 * ak2[i] + b43 * ak3[i]);
0222 }
0223 this->RightHandSideInl(yTemp, ak4);
0224
0225 for(unsigned int i = 0; i < N; ++i)
0226 {
0227 yTemp[i] = yIn[i] + Step * (b51 * dydx[i] + b52 * ak2[i] + b53 * ak3[i] +
0228 b54 * ak4[i]);
0229 }
0230 this->RightHandSideInl(yTemp, ak5);
0231
0232 for(unsigned int i = 0; i < N; ++i)
0233 {
0234 yTemp[i] = yIn[i] + Step * (b61 * dydx[i] + b62 * ak2[i] + b63 * ak3[i] +
0235 b64 * ak4[i] + b65 * ak5[i]);
0236 }
0237 this->RightHandSideInl(yTemp, ak6);
0238
0239 for(unsigned int i = 0; i < N; ++i)
0240 {
0241
0242
0243 yOut[i] = yIn[i] +
0244 Step * (c1 * dydx[i] + c3 * ak3[i] + c4 * ak4[i] + c6 * ak6[i]);
0245 }
0246 for(unsigned int i = 0; i < N; ++i)
0247 {
0248
0249
0250
0251 yErr[i] = Step * (dc1 * dydx[i] + dc3 * ak3[i] + dc4 * ak4[i] +
0252 dc5 * ak5[i] + dc6 * ak6[i]);
0253 }
0254 for(unsigned int i = 0; i < N; ++i)
0255 {
0256
0257 fLastInitialVector[i] = yIn[i];
0258 fLastFinalVector[i] = yOut[i];
0259 fLastDyDx[i] = dydx[i];
0260 }
0261
0262
0263 fLastStepLength = Step;
0264
0265 return;
0266 }
0267
0268 template <class T_Equation, unsigned int N >
0269 inline G4double
0270 G4TCashKarpRKF45<T_Equation,N>::DistChord() const
0271 {
0272 G4double distLine, distChord;
0273 G4ThreeVector initialPoint, finalPoint, midPoint;
0274
0275
0276
0277 initialPoint = G4ThreeVector(fLastInitialVector[0], fLastInitialVector[1],
0278 fLastInitialVector[2]);
0279 finalPoint = G4ThreeVector(fLastFinalVector[0], fLastFinalVector[1],
0280 fLastFinalVector[2]);
0281
0282
0283
0284 fAuxStepper->G4TCashKarpRKF45::Stepper(fLastInitialVector, fLastDyDx,
0285 0.5 * fLastStepLength, fMidVector,
0286 fMidError);
0287
0288 midPoint = G4ThreeVector(fMidVector[0], fMidVector[1], fMidVector[2]);
0289
0290
0291
0292
0293 if(initialPoint != finalPoint)
0294 {
0295 distLine = G4LineSection::Distline(midPoint, initialPoint, finalPoint);
0296 distChord = distLine;
0297 }
0298 else
0299 {
0300 distChord = (midPoint - initialPoint).mag();
0301 }
0302 return distChord;
0303 }
0304
0305 template <class T_Equation, unsigned int N >
0306 inline void
0307 G4TCashKarpRKF45<T_Equation,N>::Stepper(const G4double yInput[],
0308 const G4double dydx[],
0309 G4double Step,
0310 G4double yOutput[],
0311 G4double yError[])
0312 {
0313 assert( yOutput != yInput );
0314 assert( yError != yInput );
0315
0316 StepWithError( yInput, dydx, Step, yOutput, yError);
0317 }
0318
0319
0320
0321 #endif