Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // class G4HelixMixedStepper 26 // class G4HelixMixedStepper 27 // 27 // 28 // Class description: 28 // Class description: 29 // 29 // 30 // G4HelixMixedStepper split the Method used f 30 // G4HelixMixedStepper split the Method used for Integration in two: 31 // 31 // 32 // If Stepping Angle ( h / R_curve) < pi/3 32 // If Stepping Angle ( h / R_curve) < pi/3 33 // use Stepper for small step(Classical 33 // use Stepper for small step(ClassicalRK4 by default) 34 // Else use HelixExplicitEuler Stepper 34 // Else use HelixExplicitEuler Stepper 35 // 35 // 36 // Created: T.Nikitina, CERN - 18.05.2007, der << 36 // History: >> 37 // Derived from ExactHelicalStepper 18/05/07 >> 38 // 37 // ------------------------------------------- 39 // ------------------------------------------------------------------------- 38 40 39 #include "G4HelixMixedStepper.hh" 41 #include "G4HelixMixedStepper.hh" 40 #include "G4PhysicalConstants.hh" 42 #include "G4PhysicalConstants.hh" 41 #include "G4ClassicalRK4.hh" 43 #include "G4ClassicalRK4.hh" 42 #include "G4CashKarpRKF45.hh" 44 #include "G4CashKarpRKF45.hh" 43 #include "G4SimpleRunge.hh" 45 #include "G4SimpleRunge.hh" 44 #include "G4HelixImplicitEuler.hh" 46 #include "G4HelixImplicitEuler.hh" 45 #include "G4HelixExplicitEuler.hh" 47 #include "G4HelixExplicitEuler.hh" 46 #include "G4HelixSimpleRunge.hh" 48 #include "G4HelixSimpleRunge.hh" 47 #include "G4ExactHelixStepper.hh" 49 #include "G4ExactHelixStepper.hh" 48 #include "G4ExplicitEuler.hh" 50 #include "G4ExplicitEuler.hh" 49 #include "G4ImplicitEuler.hh" 51 #include "G4ImplicitEuler.hh" 50 #include "G4SimpleHeum.hh" 52 #include "G4SimpleHeum.hh" 51 #include "G4RKG3_Stepper.hh" 53 #include "G4RKG3_Stepper.hh" 52 #include "G4NystromRK4.hh" 54 #include "G4NystromRK4.hh" 53 << 55 // Additional potential stepper 54 // Additional potential steppers << 55 #include "G4DormandPrince745.hh" 56 #include "G4DormandPrince745.hh" 56 #include "G4BogackiShampine23.hh" 57 #include "G4BogackiShampine23.hh" 57 #include "G4BogackiShampine45.hh" 58 #include "G4BogackiShampine45.hh" 58 #include "G4TsitourasRK45.hh" 59 #include "G4TsitourasRK45.hh" 59 60 60 #include "G4ThreeVector.hh" 61 #include "G4ThreeVector.hh" 61 #include "G4LineSection.hh" 62 #include "G4LineSection.hh" 62 63 63 // ------------------------------------------- << 64 G4HelixMixedStepper:: 64 G4HelixMixedStepper:: 65 G4HelixMixedStepper(G4Mag_EqRhs* EqRhs, << 65 G4HelixMixedStepper(G4Mag_EqRhs *EqRhs, 66 G4int stepperNumber 66 G4int stepperNumber, 67 G4double angleThreshol 67 G4double angleThreshold) 68 : G4MagHelicalStepper(EqRhs) << 68 : G4MagHelicalStepper(EqRhs), fNumCallsRK4(0), fNumCallsHelix(0) 69 { 69 { 70 if( angleThreshold < 0.0 ) << 70 SetVerbose(1); 71 { << 71 if( angleThreshold < 0.0 ){ 72 fAngle_threshold = (1.0/3.0)*pi; << 72 fAngle_threshold= (1.0/3.0)*pi; 73 } << 73 }else{ 74 else << 74 fAngle_threshold= angleThreshold; 75 { << 76 fAngle_threshold = angleThreshold; << 77 } 75 } 78 76 79 if(stepperNumber<0) 77 if(stepperNumber<0) 80 { << 78 stepperNumber=4; // Default is RK4 (original) 81 // stepperNumber = 4; // Default is RK4 << 79 // stepperNumber=745; // Default is DormandPrince745 (ie DoPri5) 82 stepperNumber = 745; // Default is Dorm << 80 // stepperNumber=8; // Default is CashKarp 83 // stepperNumber = 8; // Default is Cash << 84 } << 85 81 86 fStepperNumber = stepperNumber; // Store th 82 fStepperNumber = stepperNumber; // Store the choice 87 fRK4Stepper = SetupStepper(EqRhs, fStepper 83 fRK4Stepper = SetupStepper(EqRhs, fStepperNumber); 88 } 84 } 89 85 90 // ------------------------------------------- << 91 G4HelixMixedStepper::~G4HelixMixedStepper() 86 G4HelixMixedStepper::~G4HelixMixedStepper() 92 { 87 { 93 delete fRK4Stepper; << 88 delete(fRK4Stepper); 94 if (fVerbose>0) { PrintCalls(); } << 89 if (fVerbose>0){ PrintCalls();}; 95 } 90 } 96 91 97 // ------------------------------------------- << 92 void G4HelixMixedStepper::Stepper( const G4double yInput[7], 98 void G4HelixMixedStepper::Stepper( const G4do << 93 const G4double dydx[7], 99 const G4do << 94 G4double Step, 100 G4do << 95 G4double yOut[7], 101 G4do << 96 G4double yErr[]) 102 G4do << 103 { 97 { 104 // Estimation of the Stepping Angle << 98 //Estimation of the Stepping Angle 105 // << 106 G4ThreeVector Bfld; 99 G4ThreeVector Bfld; 107 MagFieldEvaluate(yInput, Bfld); 100 MagFieldEvaluate(yInput, Bfld); 108 101 109 G4double Bmag = Bfld.mag(); 102 G4double Bmag = Bfld.mag(); 110 const G4double* pIn = yInput+3; << 103 const G4double *pIn = yInput+3; 111 G4ThreeVector initVelocity = G4ThreeVector( << 104 G4ThreeVector initVelocity= G4ThreeVector( pIn[0], pIn[1], pIn[2]); 112 G4double velocityVal = initVelocity.mag(); << 105 G4double velocityVal = initVelocity.mag(); 113 << 114 const G4double R_1 = std::abs(GetInverseCurv << 115 // curv = inverse Radius << 116 G4double Ang_curve = R_1 * Step; << 117 // SetAngCurve(Ang_curve); << 118 // SetCurve(std::abs(1/R_1)); << 119 106 120 if(Ang_curve < fAngle_threshold) << 107 const G4double R_1=std::abs(GetInverseCurve(velocityVal,Bmag)); // curv= inverse Radius >> 108 G4double Ang_curve= R_1 * Step; >> 109 // SetAngCurve(Ang_curve); >> 110 // SetCurve(std::abs(1/R_1)); // Move below, to avoid un-needed division if RK used >> 111 >> 112 if(Ang_curve< fAngle_threshold) 121 { 113 { 122 ++fNumCallsRK4; << 114 fNumCallsRK4++; 123 fRK4Stepper->Stepper(yInput,dydx,Step,yOut 115 fRK4Stepper->Stepper(yInput,dydx,Step,yOut,yErr); 124 } 116 } 125 else 117 else 126 { 118 { 127 constexpr G4int nvar = 6 ; << 119 constexpr G4int nvar = 6 ; 128 constexpr G4int nvarMax = 8 ; << 120 constexpr G4int nvarMax = 8 ; 129 G4double yTemp[nvarMax], yIn[nvarMax] << 121 G4double yTemp[nvarMax], yIn[nvarMax], yTemp2[nvarMax]; 130 G4ThreeVector Bfld_midpoint; << 122 G4ThreeVector Bfld_midpoint; 131 123 132 SetAngCurve(Ang_curve); 124 SetAngCurve(Ang_curve); 133 SetCurve(std::abs(1.0/R_1)); 125 SetCurve(std::abs(1.0/R_1)); 134 ++fNumCallsHelix; << 126 fNumCallsHelix++; 135 127 136 // Saving yInput because yInput and yOut c << 128 // Saving yInput because yInput and yOut can be aliases for same array 137 // << 129 for(G4int i=0;i<nvar;i++) yIn[i]=yInput[i]; 138 for(G4int i=0; i<nvar; ++i) << 139 { << 140 yIn[i]=yInput[i]; << 141 } << 142 130 143 G4double halfS = Step * 0.5; 131 G4double halfS = Step * 0.5; 144 << 145 // 1. Do first half step and full step 132 // 1. Do first half step and full step 146 // << 147 AdvanceHelix(yIn, Bfld, halfS, yTemp, yTem 133 AdvanceHelix(yIn, Bfld, halfS, yTemp, yTemp2); // yTemp2 for s=2*h (halfS) >> 134 //********** 148 135 149 MagFieldEvaluate(yTemp, Bfld_midpoint) ; 136 MagFieldEvaluate(yTemp, Bfld_midpoint) ; 150 137 151 // 2. Do second half step - with revised f 138 // 2. Do second half step - with revised field 152 // NOTE: Could avoid this call if 'Bfld_m 139 // NOTE: Could avoid this call if 'Bfld_midpoint == Bfld' 153 // or diff 'almost' zero 140 // or diff 'almost' zero 154 // << 155 AdvanceHelix(yTemp, Bfld_midpoint, halfS, 141 AdvanceHelix(yTemp, Bfld_midpoint, halfS, yOut); 156 // Not requesting y at s=2*h (halfS) << 142 // Not requesting y at s=2*h (halfS) >> 143 //********** 157 144 158 // 3. Estimate the integration error 145 // 3. Estimate the integration error 159 // should be (nearly) zero if Bfield= c 146 // should be (nearly) zero if Bfield= constant 160 // << 147 for(G4int i=0;i<nvar;i++) { 161 for(G4int i=0; i<nvar; ++i) << 148 yErr[i] = yOut[i] - yTemp2[i] ; 162 { << 163 yErr[i] = yOut[i] - yTemp2[i]; << 164 } 149 } 165 } 150 } 166 } 151 } 167 152 168 // ------------------------------------------- << 153 void 169 void G4HelixMixedStepper::DumbStepper( const G << 154 G4HelixMixedStepper::DumbStepper( const G4double yIn[], 170 G << 155 G4ThreeVector Bfld, 171 G << 156 G4double h, 172 G << 157 G4double yOut[]) 173 { 158 { 174 AdvanceHelix(yIn, Bfld, h, yOut); 159 AdvanceHelix(yIn, Bfld, h, yOut); 175 } 160 } 176 161 177 // ------------------------------------------- << 162 G4double G4HelixMixedStepper::DistChord() const 178 G4double G4HelixMixedStepper::DistChord() cons << 179 { 163 { 180 // Implementation : must check whether h/R > 164 // Implementation : must check whether h/R > 2 pi !! 181 // If( h/R < pi) use G4LineSection::DistL 165 // If( h/R < pi) use G4LineSection::DistLine 182 // Else DistChord=R_helix 166 // Else DistChord=R_helix 183 // 167 // 184 G4double distChord; 168 G4double distChord; 185 G4double Ang_curve=GetAngCurve(); 169 G4double Ang_curve=GetAngCurve(); 186 170 187 if(Ang_curve<=pi) << 171 if(Ang_curve<=pi){ 188 { << 189 distChord=GetRadHelix()*(1-std::cos(0.5*An 172 distChord=GetRadHelix()*(1-std::cos(0.5*Ang_curve)); 190 } 173 } 191 else 174 else 192 { 175 { 193 if(Ang_curve<twopi) << 176 if(Ang_curve<twopi){ 194 { << 195 distChord=GetRadHelix()*(1+std::cos(0.5* 177 distChord=GetRadHelix()*(1+std::cos(0.5*(twopi-Ang_curve))); 196 } 178 } 197 else << 179 else{ 198 { << 199 distChord=2.*GetRadHelix(); 180 distChord=2.*GetRadHelix(); 200 } 181 } 201 } 182 } 202 183 203 return distChord; 184 return distChord; 204 } 185 } 205 186 206 // ------------------------------------------- 187 // --------------------------------------------------------------------------- 207 void G4HelixMixedStepper::PrintCalls() 188 void G4HelixMixedStepper::PrintCalls() 208 { 189 { 209 G4cout << "In HelixMixedStepper::Number of c 190 G4cout << "In HelixMixedStepper::Number of calls to smallStepStepper = " 210 << fNumCallsRK4 191 << fNumCallsRK4 211 << " and Number of calls to Helix = 192 << " and Number of calls to Helix = " << fNumCallsHelix << G4endl; 212 } 193 } 213 194 214 // ------------------------------------------- << 215 G4MagIntegratorStepper* 195 G4MagIntegratorStepper* 216 G4HelixMixedStepper::SetupStepper(G4Mag_EqRhs* 196 G4HelixMixedStepper::SetupStepper(G4Mag_EqRhs* pE, G4int StepperNumber) 217 { 197 { 218 G4MagIntegratorStepper* pStepper; 198 G4MagIntegratorStepper* pStepper; 219 if (fVerbose>0) { G4cout << " G4HelixMixedSt << 199 if (fVerbose>0) G4cout << " G4HelixMixedStepper: "; 220 } << 221 switch ( StepperNumber ) 200 switch ( StepperNumber ) 222 { << 201 { 223 // Robust, classic method 202 // Robust, classic method 224 case 4: 203 case 4: 225 pStepper = new G4ClassicalRK4( pE ); 204 pStepper = new G4ClassicalRK4( pE ); 226 if (fVerbose>0) { G4cout << "G4Classic << 205 if (fVerbose>0) G4cout << "G4ClassicalRK4"; 227 break; 206 break; 228 207 229 // Steppers with embedded estimation of 208 // Steppers with embedded estimation of error 230 case 8: 209 case 8: 231 pStepper = new G4CashKarpRKF45( pE ); 210 pStepper = new G4CashKarpRKF45( pE ); 232 if (fVerbose>0) { G4cout << "G4CashKar << 211 if (fVerbose>0) G4cout << "G4CashKarpRKF45"; 233 break; 212 break; 234 case 13: 213 case 13: 235 pStepper = new G4NystromRK4( pE ); 214 pStepper = new G4NystromRK4( pE ); 236 if (fVerbose>0) { G4cout << "G4Nystrom << 215 if (fVerbose>0) G4cout << "G4NystromRK4"; 237 break; 216 break; 238 217 239 // Lowest order RK Stepper - experimenta 218 // Lowest order RK Stepper - experimental 240 case 1: 219 case 1: 241 pStepper = new G4ImplicitEuler( pE ); 220 pStepper = new G4ImplicitEuler( pE ); 242 if (fVerbose>0) { G4cout << "G4Implici << 221 if (fVerbose>0) G4cout << "G4ImplicitEuler"; 243 break; 222 break; 244 223 245 // Lower order RK Steppers - ok overall, 224 // Lower order RK Steppers - ok overall, good for uneven fields 246 case 2: 225 case 2: 247 pStepper = new G4SimpleRunge( pE ); 226 pStepper = new G4SimpleRunge( pE ); 248 if (fVerbose>0) { G4cout << "G4SimpleR << 227 if (fVerbose>0) G4cout << "G4SimpleRunge"; 249 break; 228 break; 250 case 3: 229 case 3: 251 pStepper = new G4SimpleHeum( pE ); 230 pStepper = new G4SimpleHeum( pE ); 252 if (fVerbose>0) { G4cout << "G4SimpleH << 231 if (fVerbose>0) G4cout << "G4SimpleHeum"; 253 break; 232 break; 254 case 23: 233 case 23: 255 pStepper = new G4BogackiShampine23( pE 234 pStepper = new G4BogackiShampine23( pE ); 256 if (fVerbose>0) { G4cout << "G4Bogacki << 235 if (fVerbose>0) G4cout << "G4BogackiShampine23"; 257 break; 236 break; 258 237 259 // Higher order RK Steppers 238 // Higher order RK Steppers 260 // for smoother fields and high accuracy 239 // for smoother fields and high accuracy requirements 261 case 45: 240 case 45: 262 pStepper = new G4BogackiShampine45( pE 241 pStepper = new G4BogackiShampine45( pE ); 263 if (fVerbose>0) { G4cout << "G4Bogacki << 242 if (fVerbose>0) G4cout << "G4BogackiShampine45"; 264 break; 243 break; 265 case 145: 244 case 145: 266 pStepper = new G4TsitourasRK45( pE ); 245 pStepper = new G4TsitourasRK45( pE ); 267 if (fVerbose>0) { G4cout << "G4Tsitour << 246 if (fVerbose>0) G4cout << "G4TsitourasRK45"; 268 break; 247 break; 269 case 745: 248 case 745: 270 pStepper = new G4DormandPrince745( pE 249 pStepper = new G4DormandPrince745( pE ); 271 if (fVerbose>0) { G4cout << "G4Dormand << 250 if (fVerbose>0) G4cout << "G4DormandPrince745"; 272 break; 251 break; 273 252 274 // Helical Steppers 253 // Helical Steppers 275 case 6: 254 case 6: 276 pStepper = new G4HelixImplicitEuler( p 255 pStepper = new G4HelixImplicitEuler( pE ); 277 if (fVerbose>0) { G4cout << "G4HelixIm << 256 if (fVerbose>0) G4cout << "G4HelixImplicitEuler"; 278 break; 257 break; 279 case 7: 258 case 7: 280 pStepper = new G4HelixSimpleRunge( pE 259 pStepper = new G4HelixSimpleRunge( pE ); 281 if (fVerbose>0) { G4cout << "G4HelixSi << 260 if (fVerbose>0) G4cout << "G4HelixSimpleRunge"; 282 break; 261 break; 283 case 5: 262 case 5: 284 pStepper = new G4HelixExplicitEuler( p 263 pStepper = new G4HelixExplicitEuler( pE ); 285 if (fVerbose>0) { G4cout << "G4HelixEx << 264 if (fVerbose>0) G4cout << "G4HelixExplicitEuler"; 286 break; // Since Helix Explicit is use 265 break; // Since Helix Explicit is used for long steps, 287 // this is useful only to measu 266 // this is useful only to measure overhead. 288 // Exact Helix - likely good only for ca 267 // Exact Helix - likely good only for cases of 289 // i) uniform field (potentia 268 // i) uniform field (potentially over small distances) 290 // ii) segmented uniform field 269 // ii) segmented uniform field (maybe) 291 case 9: 270 case 9: 292 pStepper = new G4ExactHelixStepper( pE 271 pStepper = new G4ExactHelixStepper( pE ); 293 if (fVerbose>0) { G4cout << "G4ExactHe << 272 if (fVerbose>0) G4cout << "G4ExactHelixStepper"; 294 break; 273 break; 295 case 10: 274 case 10: 296 pStepper = new G4RKG3_Stepper( pE ); 275 pStepper = new G4RKG3_Stepper( pE ); 297 if (fVerbose>0) { G4cout << "G4RKG3_St << 276 if (fVerbose>0) G4cout << "G4RKG3_Stepper"; 298 break; 277 break; 299 278 300 // Low Order Steppers - not good except 279 // Low Order Steppers - not good except for very weak fields 301 case 11: 280 case 11: 302 pStepper = new G4ExplicitEuler( pE ); 281 pStepper = new G4ExplicitEuler( pE ); 303 if (fVerbose>0) { G4cout << "G4Explici << 282 if (fVerbose>0) G4cout << "G4ExplicitEuler"; 304 break; 283 break; 305 case 12: 284 case 12: 306 pStepper = new G4ImplicitEuler( pE ); 285 pStepper = new G4ImplicitEuler( pE ); 307 if (fVerbose>0) { G4cout << "G4Implici << 286 if (fVerbose>0) G4cout << "G4ImplicitEuler"; 308 break; 287 break; 309 288 310 case 0: 289 case 0: 311 case -1: 290 case -1: 312 default: 291 default: 313 pStepper = new G4DormandPrince745( pE 292 pStepper = new G4DormandPrince745( pE ); // Was G4ClassicalRK4( pE ); 314 if (fVerbose>0) { G4cout << "G4Dormand << 293 if (fVerbose>0) G4cout << "G4DormandPrince745 (Default)"; 315 break; 294 break; 316 } << 295 } 317 << 318 if(fVerbose>0) 296 if(fVerbose>0) 319 { << 320 G4cout << " chosen as stepper for small st 297 G4cout << " chosen as stepper for small steps in G4HelixMixedStepper." 321 << G4endl; 298 << G4endl; 322 } << 323 299 324 return pStepper; 300 return pStepper; 325 } 301 } 326 302