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 // G4ChordFinder implementation 26 // G4ChordFinder implementation 27 // 27 // 28 // Author: J.Apostolakis - Design and implemen 28 // Author: J.Apostolakis - Design and implementation - 25.02.1997 29 // ------------------------------------------- 29 // ------------------------------------------------------------------- 30 30 31 #include <iomanip> 31 #include <iomanip> 32 32 33 #include "G4ChordFinder.hh" 33 #include "G4ChordFinder.hh" 34 #include "G4SystemOfUnits.hh" 34 #include "G4SystemOfUnits.hh" 35 #include "G4MagneticField.hh" 35 #include "G4MagneticField.hh" 36 #include "G4Mag_UsualEqRhs.hh" 36 #include "G4Mag_UsualEqRhs.hh" 37 #include "G4MagIntegratorDriver.hh" 37 #include "G4MagIntegratorDriver.hh" 38 // #include "G4ClassicalRK4.hh" 38 // #include "G4ClassicalRK4.hh" 39 // #include "G4CashKarpRKF45.hh" 39 // #include "G4CashKarpRKF45.hh" 40 // #include "G4NystromRK4.hh" 40 // #include "G4NystromRK4.hh" 41 // #include "G4BogackiShampine23.hh" 41 // #include "G4BogackiShampine23.hh" 42 // #include "G4BogackiShampine45.hh" 42 // #include "G4BogackiShampine45.hh" 43 43 44 #include "G4DormandPrince745.hh" 44 #include "G4DormandPrince745.hh" 45 45 46 // New templated stepper(s) -- avoid virtual c 46 // New templated stepper(s) -- avoid virtual calls to equation rhs 47 #include "G4TDormandPrince45.hh" 47 #include "G4TDormandPrince45.hh" 48 48 49 // FSAL type driver / steppers ----- 49 // FSAL type driver / steppers ----- 50 #include "G4FSALIntegrationDriver.hh" 50 #include "G4FSALIntegrationDriver.hh" 51 #include "G4VFSALIntegrationStepper.hh" 51 #include "G4VFSALIntegrationStepper.hh" 52 #include "G4RK547FEq1.hh" 52 #include "G4RK547FEq1.hh" 53 // #include "G4RK547FEq2.hh" 53 // #include "G4RK547FEq2.hh" 54 // #include "G4RK547FEq3.hh" 54 // #include "G4RK547FEq3.hh" 55 // #include "G4FSALBogackiShampine45.hh" 55 // #include "G4FSALBogackiShampine45.hh" 56 // #include "G4FSALDormandPrince745.hh" 56 // #include "G4FSALDormandPrince745.hh" 57 57 58 // Templated type drivers ----- 58 // Templated type drivers ----- 59 #include "G4IntegrationDriver.hh" 59 #include "G4IntegrationDriver.hh" 60 #include "G4InterpolationDriver.hh" 60 #include "G4InterpolationDriver.hh" 61 61 62 #include "G4HelixHeum.hh" 62 #include "G4HelixHeum.hh" 63 #include "G4BFieldIntegrationDriver.hh" 63 #include "G4BFieldIntegrationDriver.hh" 64 64 65 #include "G4QSSDriverCreator.hh" << 66 << 67 #include "G4CachedMagneticField.hh" 65 #include "G4CachedMagneticField.hh" 68 66 69 #include <cassert> 67 #include <cassert> 70 #include <memory> << 71 68 72 G4bool G4ChordFinder::gVerboseCtor = false; << 69 static G4bool gVerboseCtor = false; // true; >> 70 73 // ........................................... 71 // .......................................................................... 74 72 75 G4ChordFinder::G4ChordFinder(G4VIntegrationDri 73 G4ChordFinder::G4ChordFinder(G4VIntegrationDriver* pIntegrationDriver) 76 : fDefaultDeltaChord(0.25 * mm), fIntgrDrive 74 : fDefaultDeltaChord(0.25 * mm), fIntgrDriver(pIntegrationDriver) 77 { 75 { 78 // Simple constructor -- it does not create 76 // Simple constructor -- it does not create equation 79 if( gVerboseCtor ) 77 if( gVerboseCtor ) 80 { << 81 G4cout << "G4ChordFinder: Simple construct 78 G4cout << "G4ChordFinder: Simple constructor -- it uses pre-existing driver." << G4endl; 82 } << 83 79 84 fDeltaChord = fDefaultDeltaChord; // P 80 fDeltaChord = fDefaultDeltaChord; // Parameters 85 } 81 } 86 82 >> 83 87 // ........................................... 84 // .......................................................................... 88 85 89 G4ChordFinder::G4ChordFinder( G4MagneticField* 86 G4ChordFinder::G4ChordFinder( G4MagneticField* theMagField, 90 G4double 87 G4double stepMinimum, 91 G4MagIntegratorS 88 G4MagIntegratorStepper* pItsStepper, 92 G4int 89 G4int stepperDriverId ) 93 : fDefaultDeltaChord(0.25 * mm) 90 : fDefaultDeltaChord(0.25 * mm) 94 { 91 { 95 // Construct the Chord Finder 92 // Construct the Chord Finder 96 // by creating in inverse order the Driver, 93 // by creating in inverse order the Driver, the Stepper and EqRhs ... 97 constexpr G4int nVar6 = 6; // Components i 94 constexpr G4int nVar6 = 6; // Components integrated in Usual Equation of motion 98 95 99 fDeltaChord = fDefaultDeltaChord; // P 96 fDeltaChord = fDefaultDeltaChord; // Parameters 100 97 101 G4cout << " G4ChordFinder: stepperDriverId: << 98 // stepperDriverId = 2; 102 << 99 103 G4bool useFSALstepper = (stepperDriverId << 100 G4bool useFSALstepper= (stepperDriverId == 1); 104 G4bool useTemplatedStepper= (stepperDriverId << 101 G4bool useTemplatedStepper= (stepperDriverId == 2); 105 G4bool useRegularStepper = (stepperDriverId << 102 G4bool useRegularStepper = (stepperDriverId == 3); 106 G4bool useBfieldDriver = (stepperDriverId << 103 // G4bool useBFieldDriver = !useRegularStepper && !useFSALstepper && !useTemplatedStepper; 107 G4bool useG4QSSDriver = (stepperDriverId << 104 108 << 105 // G4bool useRegularStepper = !stepperDriverId != 3) && !useFSALStepper && !useTemplatedStepper; 109 if( stepperDriverId == kQss3DriverType) << 106 // If it's not 0, 1 or 2 then 'BFieldDriver' which combines DoPri5 (short) and helix is used. 110 { << 107 111 stepperDriverId = kQss2DriverType; << 112 G4cout << " G4ChordFinder: QSS 3 is curren << 113 } << 114 << 115 using EquationType = G4Mag_UsualEqRhs; 108 using EquationType = G4Mag_UsualEqRhs; 116 109 117 using TemplatedStepperType = 110 using TemplatedStepperType = 118 G4TDormandPrince45<EquationType,nVar6 111 G4TDormandPrince45<EquationType,nVar6>; // 5th order embedded method. High efficiency. 119 const char* TemplatedStepperName = 112 const char* TemplatedStepperName = 120 "G4TDormandPrince745 (templated Dormand- 113 "G4TDormandPrince745 (templated Dormand-Prince45, aka DoPri5): 5th/4th Order 7-stage embedded"; 121 114 122 using RegularStepperType = 115 using RegularStepperType = 123 G4DormandPrince745; // 5th order embe 116 G4DormandPrince745; // 5th order embedded method. High efficiency. 124 // G4ClassicalRK4; // The old 117 // G4ClassicalRK4; // The old default 125 // G4CashKarpRKF45; // First em 118 // G4CashKarpRKF45; // First embedded method in G4 126 // G4BogackiShampine45; // High eff 119 // G4BogackiShampine45; // High efficiency 5th order embedded method 127 // G4NystromRK4; // Nystrom 120 // G4NystromRK4; // Nystrom stepper 4th order 128 // G4RK547FEq1; // or 2 or 3 121 // G4RK547FEq1; // or 2 or 3 129 const char* RegularStepperName = 122 const char* RegularStepperName = 130 "G4DormandPrince745 (aka DOPRI5): 5th/4t 123 "G4DormandPrince745 (aka DOPRI5): 5th/4th Order 7-stage embedded"; 131 // "BogackiShampine 45 (Embedded 5th/4th 124 // "BogackiShampine 45 (Embedded 5th/4th Order, 7-stage)"; 132 // "Nystrom stepper 4th order"; 125 // "Nystrom stepper 4th order"; 133 126 134 using NewFsalStepperType = G4DormandPrince74 127 using NewFsalStepperType = G4DormandPrince745; // Now works -- 2020.10.08 135 128 // Was G4RK547FEq1; // or 2 or 3 136 const char* NewFSALStepperName = 129 const char* NewFSALStepperName = 137 "G4RK574FEq1> FSAL 4th/5th order 7-stage 130 "G4RK574FEq1> FSAL 4th/5th order 7-stage 'Equilibrium-type' #1."; 138 131 139 #ifdef G4DEBUG_FIELD 132 #ifdef G4DEBUG_FIELD 140 static G4bool verboseDebug = true; 133 static G4bool verboseDebug = true; 141 if( verboseDebug ) 134 if( verboseDebug ) 142 { 135 { 143 G4cout << "G4ChordFinder 2nd Constructor 136 G4cout << "G4ChordFinder 2nd Constructor called. " << G4endl; 144 G4cout << " Arguments: " << G4endl 137 G4cout << " Arguments: " << G4endl 145 << " - min step = " << stepMinimum 138 << " - min step = " << stepMinimum << G4endl 146 << " - stepper ptr provided : " 139 << " - stepper ptr provided : " 147 << ( pItsStepper==nullptr ? " no 140 << ( pItsStepper==nullptr ? " no " : " yes " ) << G4endl; 148 if( pItsStepper==nullptr ) 141 if( pItsStepper==nullptr ) 149 G4cout << " - stepper/driver Id = " << 142 G4cout << " - stepper/driver Id = " << stepperDriverId << " i.e. " 150 << " useFSAL = " << useFSALste 143 << " useFSAL = " << useFSALstepper 151 << " , useTemplated = " << use 144 << " , useTemplated = " << useTemplatedStepper 152 << " , useRegular = " << useRe 145 << " , useRegular = " << useRegularStepper 153 << " , useFSAL = " << useFSALs 146 << " , useFSAL = " << useFSALstepper 154 << G4endl; 147 << G4endl; 155 } 148 } 156 #endif 149 #endif 157 150 158 // useHigherStepper = forceHigherEffiencySte 151 // useHigherStepper = forceHigherEffiencyStepper || useHigherStepper; 159 152 160 auto pEquation = new G4Mag_UsualEqRhs(theMa << 153 EquationType* pEquation = new G4Mag_UsualEqRhs(theMagField); 161 fEquation = pEquation; 154 fEquation = pEquation; 162 155 163 // G4MagIntegratorStepper* regularStepper = 156 // G4MagIntegratorStepper* regularStepper = nullptr; 164 // G4VFSALIntegrationStepper* fsalStepper = 157 // G4VFSALIntegrationStepper* fsalStepper = nullptr; // for FSAL steppers only 165 // G4MagIntegratorStepper* oldFSALStepper = 158 // G4MagIntegratorStepper* oldFSALStepper = nullptr; 166 159 167 G4bool errorInStepperCreation = false; 160 G4bool errorInStepperCreation = false; 168 161 169 std::ostringstream message; // In case of f 162 std::ostringstream message; // In case of failure, load with description ! 170 163 171 if( pItsStepper != nullptr ) 164 if( pItsStepper != nullptr ) 172 { 165 { 173 if( gVerboseCtor ) 166 if( gVerboseCtor ) 174 { << 175 G4cout << " G4ChordFinder: Creating G4I 167 G4cout << " G4ChordFinder: Creating G4IntegrationDriver<G4MagIntegratorStepper> with " 176 << " stepMinimum = " << stepMini 168 << " stepMinimum = " << stepMinimum 177 << " numVar= " << pItsStepper->G 169 << " numVar= " << pItsStepper->GetNumberOfVariables() << G4endl; 178 } << 179 << 180 // Stepper type is not known - so must us 170 // Stepper type is not known - so must use base class G4MagIntegratorStepper 181 if(pItsStepper->isQSS()) << 171 fIntgrDriver = new G4IntegrationDriver<G4MagIntegratorStepper>( 182 { << 172 stepMinimum, pItsStepper, pItsStepper->GetNumberOfVariables()); 183 // fIntgrDriver = pItsStepper->build_ << 173 184 G4Exception("G4ChordFinder::G4ChordFi << 185 "GeomField1001", FatalEx << 186 "Cannot provide QSS ste << 187 } << 188 else << 189 { << 190 fIntgrDriver = new G4IntegrationDrive << 191 pItsStepper, << 192 // Stepper type is not known - so mus << 193 // Non-interpolating driver used by d << 194 // WAS: fIntgrDriver = pItsStepper-> << 195 } << 196 // -- Older: 174 // -- Older: 197 // G4cout << " G4ChordFinder: Creating G4 175 // G4cout << " G4ChordFinder: Creating G4MagInt_Driver with " ... 198 // Type is not known - so must use old cl 176 // Type is not known - so must use old class 199 // fIntgrDriver = new G4MagInt_Driver( st 177 // fIntgrDriver = new G4MagInt_Driver( stepMinimum, pItsStepper, 200 // pItsSt 178 // pItsStepper->GetNumberOfVariables()); 201 } 179 } 202 else if ( useTemplatedStepper ) 180 else if ( useTemplatedStepper ) 203 { 181 { 204 if( gVerboseCtor ) 182 if( gVerboseCtor ) 205 { << 206 G4cout << " G4ChordFinder: Creating Te 183 G4cout << " G4ChordFinder: Creating Templated Stepper of type> " 207 << TemplatedStepperName << G4en 184 << TemplatedStepperName << G4endl; 208 } << 209 // RegularStepperType* regularStepper = n 185 // RegularStepperType* regularStepper = nullptr; // To check the exception 210 auto templatedStepper = new TemplatedStep 186 auto templatedStepper = new TemplatedStepperType(pEquation); 211 // *** *************** 187 // *** ****************** 212 // 188 // 213 // Alternative - for G4NystromRK4: 189 // Alternative - for G4NystromRK4: 214 // = new G4NystromRK4(pEquation, 0.1*mm ) 190 // = new G4NystromRK4(pEquation, 0.1*mm ); 215 fRegularStepperOwned = templatedStepper; 191 fRegularStepperOwned = templatedStepper; 216 if( templatedStepper == nullptr ) 192 if( templatedStepper == nullptr ) 217 { 193 { 218 message << "Templated Stepper instanti 194 message << "Templated Stepper instantiation FAILED." << G4endl; 219 message << "G4ChordFinder: Attempted t 195 message << "G4ChordFinder: Attempted to instantiate " 220 << TemplatedStepperName << " t 196 << TemplatedStepperName << " type stepper " << G4endl; 221 errorInStepperCreation = true; 197 errorInStepperCreation = true; 222 } 198 } 223 else 199 else 224 { 200 { 225 fIntgrDriver = new G4IntegrationDriver 201 fIntgrDriver = new G4IntegrationDriver<TemplatedStepperType>( 226 stepMinimum, templatedStepper, nVar 202 stepMinimum, templatedStepper, nVar6 ); 227 if( gVerboseCtor ) 203 if( gVerboseCtor ) 228 { << 229 G4cout << " G4ChordFinder: Using G4 204 G4cout << " G4ChordFinder: Using G4IntegrationDriver. " << G4endl; 230 } << 231 } 205 } 232 206 233 } 207 } 234 else if ( useRegularStepper ) // Plain st 208 else if ( useRegularStepper ) // Plain stepper -- not double ... 235 { 209 { 236 auto regularStepper = new RegularStepperT 210 auto regularStepper = new RegularStepperType(pEquation); 237 // *** *************** 211 // *** ****************** 238 fRegularStepperOwned = regularStepper; 212 fRegularStepperOwned = regularStepper; 239 213 240 if( gVerboseCtor ) 214 if( gVerboseCtor ) 241 { << 242 G4cout << " G4ChordFinder: Creating Dr 215 G4cout << " G4ChordFinder: Creating Driver for regular stepper."; 243 } << 244 216 245 if( regularStepper == nullptr ) 217 if( regularStepper == nullptr ) 246 { 218 { 247 message << "Regular Stepper instantiat 219 message << "Regular Stepper instantiation FAILED." << G4endl; 248 message << "G4ChordFinder: Attempted t 220 message << "G4ChordFinder: Attempted to instantiate " 249 << RegularStepperName << " typ 221 << RegularStepperName << " type stepper " << G4endl; 250 errorInStepperCreation = true; 222 errorInStepperCreation = true; 251 } 223 } 252 else 224 else 253 { 225 { 254 auto dp5= dynamic_cast<G4DormandPrince 226 auto dp5= dynamic_cast<G4DormandPrince745*>(regularStepper); 255 if( dp5 != nullptr ) << 227 if( dp5 ) { 256 { << 257 fIntgrDriver = new G4InterpolationD 228 fIntgrDriver = new G4InterpolationDriver<G4DormandPrince745>( 258 stepMinimum, 229 stepMinimum, dp5, nVar6 ); 259 if( gVerboseCtor ) 230 if( gVerboseCtor ) 260 { << 261 G4cout << " Using InterpolationD 231 G4cout << " Using InterpolationDriver<DoPri5> " << G4endl; 262 } << 232 } else { 263 } << 264 else << 265 { << 266 fIntgrDriver = new G4IntegrationDri 233 fIntgrDriver = new G4IntegrationDriver<RegularStepperType>( 267 stepMinimum, 234 stepMinimum, regularStepper, nVar6 ); 268 if( gVerboseCtor ) 235 if( gVerboseCtor ) 269 { << 270 G4cout << " Using IntegrationDri 236 G4cout << " Using IntegrationDriver<DoPri5> " << G4endl; 271 } << 272 } 237 } 273 } 238 } 274 } 239 } 275 else if ( useBfieldDriver ) << 240 else if ( !useFSALstepper ) 276 { 241 { 277 auto regularStepper = new G4DormandPrince 242 auto regularStepper = new G4DormandPrince745(pEquation); 278 // *** *************** 243 // *** ****************** 279 // 244 // 280 fRegularStepperOwned = regularStepper; 245 fRegularStepperOwned = regularStepper; 281 246 282 { 247 { 283 using SmallStepDriver = G4Interpolatio 248 using SmallStepDriver = G4InterpolationDriver<G4DormandPrince745>; 284 using LargeStepDriver = G4IntegrationD 249 using LargeStepDriver = G4IntegrationDriver<G4HelixHeum>; 285 250 286 fLongStepper = std::make_unique<G4Heli << 251 fLongStepper = std::unique_ptr<G4HelixHeum>(new G4HelixHeum(pEquation)); 287 252 288 fIntgrDriver = new G4BFieldIntegration 253 fIntgrDriver = new G4BFieldIntegrationDriver( 289 std::make_unique<SmallStepDriver>(st << 254 std::unique_ptr<SmallStepDriver>(new SmallStepDriver(stepMinimum, 290 regularStepper, regularStepper-> << 255 regularStepper, regularStepper->GetNumberOfVariables())), 291 std::make_unique<LargeStepDriver>(st << 256 std::unique_ptr<LargeStepDriver>(new LargeStepDriver(stepMinimum, 292 fLongStepper.get(), regularStepp << 257 fLongStepper.get(), regularStepper->GetNumberOfVariables())) ); 293 258 294 if( fIntgrDriver == nullptr) 259 if( fIntgrDriver == nullptr) 295 { 260 { 296 message << "Using G4BFieldIntegrati 261 message << "Using G4BFieldIntegrationDriver with " 297 << RegularStepperName << " 262 << RegularStepperName << " type stepper " << G4endl; 298 message << "Driver instantiation FA 263 message << "Driver instantiation FAILED." << G4endl; 299 G4Exception("G4ChordFinder::G4Chord 264 G4Exception("G4ChordFinder::G4ChordFinder()", 300 "GeomField1001", JustWa 265 "GeomField1001", JustWarning, message); 301 } 266 } 302 } 267 } 303 } 268 } 304 else if( useG4QSSDriver ) << 305 { << 306 if( stepperDriverId == kQss2DriverType ) << 307 { << 308 auto qssStepper2 = G4QSSDriverCreator:: << 309 if( gVerboseCtor ) << 310 { << 311 G4cout << "-- Created QSS-2 stepper" << 312 } << 313 fIntgrDriver = G4QSSDriverCreator::Crea << 314 } << 315 else << 316 { << 317 auto qssStepper3 = G4QSSDriverCreator:: << 318 if( gVerboseCtor ) << 319 { << 320 G4cout << "-- Created QSS-3 stepper" << 321 } << 322 fIntgrDriver = G4QSSDriverCreator::Crea << 323 } << 324 if( gVerboseCtor ) << 325 { << 326 G4cout << "-- G4ChordFinder: Using QSS << 327 } << 328 } << 329 else 269 else 330 { 270 { 331 auto fsalStepper= new NewFsalStepperType 271 auto fsalStepper= new NewFsalStepperType(pEquation); 332 // *** ****************** 272 // *** ****************** 333 fNewFSALStepperOwned = fsalStepper; 273 fNewFSALStepperOwned = fsalStepper; 334 274 335 if( fsalStepper == nullptr ) 275 if( fsalStepper == nullptr ) 336 { 276 { 337 message << "Stepper instantiation FAIL 277 message << "Stepper instantiation FAILED." << G4endl; 338 message << "Attempted to instantiate " 278 message << "Attempted to instantiate " 339 << NewFSALStepperName << " typ 279 << NewFSALStepperName << " type stepper " << G4endl; 340 G4Exception("G4ChordFinder::G4ChordFin 280 G4Exception("G4ChordFinder::G4ChordFinder()", 341 "GeomField1001", JustWarni 281 "GeomField1001", JustWarning, message); 342 errorInStepperCreation = true; 282 errorInStepperCreation = true; 343 } 283 } 344 else 284 else 345 { 285 { 346 fIntgrDriver = new 286 fIntgrDriver = new 347 G4FSALIntegrationDriver<NewFsalStep 287 G4FSALIntegrationDriver<NewFsalStepperType>(stepMinimum, fsalStepper, 348 fsal 288 fsalStepper->GetNumberOfVariables() ); 349 // ==== Create the driver which k 289 // ==== Create the driver which knows the class type 350 290 351 if( fIntgrDriver == nullptr ) 291 if( fIntgrDriver == nullptr ) 352 { 292 { 353 message << "Using G4FSALIntegration 293 message << "Using G4FSALIntegrationDriver with stepper type: " 354 << NewFSALStepperName << G4 294 << NewFSALStepperName << G4endl; 355 message << "Integration Driver inst 295 message << "Integration Driver instantiation FAILED." << G4endl; 356 G4Exception("G4ChordFinder::G4Chord 296 G4Exception("G4ChordFinder::G4ChordFinder()", 357 "GeomField1001", JustWa 297 "GeomField1001", JustWarning, message); 358 } 298 } 359 } 299 } 360 } 300 } 361 301 362 // -- Main work is now done 302 // -- Main work is now done 363 303 364 // Now check that no error occured, and r 304 // Now check that no error occured, and report it if one did. 365 305 366 // To test failure to create driver 306 // To test failure to create driver 367 // delete fIntgrDriver; 307 // delete fIntgrDriver; 368 // fIntgrDriver = nullptr; 308 // fIntgrDriver = nullptr; 369 309 370 // Detect and report Error conditions 310 // Detect and report Error conditions 371 // 311 // 372 if( errorInStepperCreation || (fIntgrDriver 312 if( errorInStepperCreation || (fIntgrDriver == nullptr )) 373 { 313 { 374 std::ostringstream errmsg; 314 std::ostringstream errmsg; 375 315 376 if( errorInStepperCreation ) 316 if( errorInStepperCreation ) 377 { 317 { 378 errmsg << "ERROR> Failure to create S 318 errmsg << "ERROR> Failure to create Stepper object." << G4endl 379 << " ------------------- 319 << " --------------------------------" << G4endl; 380 } 320 } 381 if (fIntgrDriver == nullptr ) 321 if (fIntgrDriver == nullptr ) 382 { 322 { 383 errmsg << "ERROR> Failure to create I 323 errmsg << "ERROR> Failure to create Integration-Driver object." 384 << G4endl 324 << G4endl 385 << " ------------------- 325 << " -------------------------------------------" 386 << G4endl; 326 << G4endl; 387 } 327 } 388 const std::string BoolName[2]= { "False", 328 const std::string BoolName[2]= { "False", "True" }; 389 errmsg << " Configuration: (constructor 329 errmsg << " Configuration: (constructor arguments) " << G4endl 390 << " provided Stepper = " << pI 330 << " provided Stepper = " << pItsStepper << G4endl 391 << " stepper/driver Id = " << step 331 << " stepper/driver Id = " << stepperDriverId << " i.e. " 392 << " useTemplated = " << BoolNam 332 << " useTemplated = " << BoolName[useTemplatedStepper] 393 << " useRegular = " << BoolName[ 333 << " useRegular = " << BoolName[useRegularStepper] 394 << " useFSAL = " << BoolName[use 334 << " useFSAL = " << BoolName[useFSALstepper] 395 << " using combo BField Driver = 335 << " using combo BField Driver = " << 396 BoolName[ ! (useFSALstepper 336 BoolName[ ! (useFSALstepper||useTemplatedStepper 397 || useRegularSt 337 || useRegularStepper ) ] 398 << G4endl; 338 << G4endl; 399 errmsg << message.str(); 339 errmsg << message.str(); 400 errmsg << "Aborting."; 340 errmsg << "Aborting."; 401 G4Exception("G4ChordFinder::G4ChordFinder 341 G4Exception("G4ChordFinder::G4ChordFinder() - constructor 2", 402 "GeomField0003", FatalExcepti 342 "GeomField0003", FatalException, errmsg); 403 } 343 } 404 344 405 assert( ( pItsStepper != nullptr ) 345 assert( ( pItsStepper != nullptr ) 406 || ( fRegularStepperOwned != nullptr 346 || ( fRegularStepperOwned != nullptr ) 407 || ( fNewFSALStepperOwned != nullptr 347 || ( fNewFSALStepperOwned != nullptr ) 408 || useG4QSSDriver << 409 ); 348 ); 410 assert( fIntgrDriver != nullptr ); 349 assert( fIntgrDriver != nullptr ); 411 } 350 } >> 351 412 352 413 // ........................................... 353 // ...................................................................... 414 354 415 G4ChordFinder::~G4ChordFinder() 355 G4ChordFinder::~G4ChordFinder() 416 { 356 { 417 delete fEquation; 357 delete fEquation; 418 delete fRegularStepperOwned; 358 delete fRegularStepperOwned; 419 delete fNewFSALStepperOwned; 359 delete fNewFSALStepperOwned; 420 delete fCachedField; 360 delete fCachedField; 421 delete fIntgrDriver; 361 delete fIntgrDriver; 422 } 362 } 423 363 424 // ........................................... 364 // ........................................................................... 425 365 426 G4FieldTrack 366 G4FieldTrack 427 G4ChordFinder::ApproxCurvePointS( const G4Fiel 367 G4ChordFinder::ApproxCurvePointS( const G4FieldTrack& CurveA_PointVelocity, 428 const G4Fiel 368 const G4FieldTrack& CurveB_PointVelocity, 429 const G4Fiel 369 const G4FieldTrack& ApproxCurveV, 430 const G4Thre 370 const G4ThreeVector& CurrentE_Point, 431 const G4Thre 371 const G4ThreeVector& CurrentF_Point, 432 const G4Thre 372 const G4ThreeVector& PointG, 433 G4bool 373 G4bool first, G4double eps_step) 434 { 374 { 435 // ApproxCurvePointS is 2nd implementation o 375 // ApproxCurvePointS is 2nd implementation of ApproxCurvePoint. 436 // Use Brent Algorithm (or InvParabolic) whe 376 // Use Brent Algorithm (or InvParabolic) when possible. 437 // Given a starting curve point A (CurveA_Po 377 // Given a starting curve point A (CurveA_PointVelocity), curve point B 438 // (CurveB_PointVelocity), a point E which i 378 // (CurveB_PointVelocity), a point E which is (generally) not on the curve 439 // and a point F which is on the curve (fir 379 // and a point F which is on the curve (first approximation), find new 440 // point S on the curve closer to point E. 380 // point S on the curve closer to point E. 441 // While advancing towards S utilise 'eps_st 381 // While advancing towards S utilise 'eps_step' as a measure of the 442 // relative accuracy of each Step. 382 // relative accuracy of each Step. 443 383 444 G4FieldTrack EndPoint(CurveA_PointVelocity); 384 G4FieldTrack EndPoint(CurveA_PointVelocity); 445 if(!first) { EndPoint = ApproxCurveV; } 385 if(!first) { EndPoint = ApproxCurveV; } 446 386 447 G4ThreeVector Point_A,Point_B; 387 G4ThreeVector Point_A,Point_B; 448 Point_A=CurveA_PointVelocity.GetPosition(); 388 Point_A=CurveA_PointVelocity.GetPosition(); 449 Point_B=CurveB_PointVelocity.GetPosition(); 389 Point_B=CurveB_PointVelocity.GetPosition(); 450 390 451 G4double xa,xb,xc,ya,yb,yc; 391 G4double xa,xb,xc,ya,yb,yc; 452 392 453 // InverseParabolic. AF Intersects (First Pa 393 // InverseParabolic. AF Intersects (First Part of Curve) 454 394 455 if(first) 395 if(first) 456 { 396 { 457 xa=0.; 397 xa=0.; 458 ya=(PointG-Point_A).mag(); 398 ya=(PointG-Point_A).mag(); 459 xb=(Point_A-CurrentF_Point).mag(); 399 xb=(Point_A-CurrentF_Point).mag(); 460 yb=-(PointG-CurrentF_Point).mag(); 400 yb=-(PointG-CurrentF_Point).mag(); 461 xc=(Point_A-Point_B).mag(); 401 xc=(Point_A-Point_B).mag(); 462 yc=-(CurrentE_Point-Point_B).mag(); 402 yc=-(CurrentE_Point-Point_B).mag(); 463 } 403 } 464 else 404 else 465 { 405 { 466 xa=0.; 406 xa=0.; 467 ya=(Point_A-CurrentE_Point).mag(); 407 ya=(Point_A-CurrentE_Point).mag(); 468 xb=(Point_A-CurrentF_Point).mag(); 408 xb=(Point_A-CurrentF_Point).mag(); 469 yb=(PointG-CurrentF_Point).mag(); 409 yb=(PointG-CurrentF_Point).mag(); 470 xc=(Point_A-Point_B).mag(); 410 xc=(Point_A-Point_B).mag(); 471 yc=-(Point_B-PointG).mag(); 411 yc=-(Point_B-PointG).mag(); 472 if(xb==0.) 412 if(xb==0.) 473 { 413 { 474 EndPoint = ApproxCurvePointV(CurveA_Poin 414 EndPoint = ApproxCurvePointV(CurveA_PointVelocity, CurveB_PointVelocity, 475 CurrentE_Po 415 CurrentE_Point, eps_step); 476 return EndPoint; 416 return EndPoint; 477 } 417 } 478 } 418 } 479 419 480 const G4double tolerance = 1.e-12; 420 const G4double tolerance = 1.e-12; 481 if(std::abs(ya)<=tolerance||std::abs(yc)<=to 421 if(std::abs(ya)<=tolerance||std::abs(yc)<=tolerance) 482 { 422 { 483 ; // What to do for the moment: return the 423 ; // What to do for the moment: return the same point as at start 484 // then PropagatorInField will take care 424 // then PropagatorInField will take care 485 } 425 } 486 else 426 else 487 { 427 { 488 G4double test_step = InvParabolic(xa,ya,xb 428 G4double test_step = InvParabolic(xa,ya,xb,yb,xc,yc); 489 G4double curve; 429 G4double curve; 490 if(first) 430 if(first) 491 { 431 { 492 curve=std::abs(EndPoint.GetCurveLength() 432 curve=std::abs(EndPoint.GetCurveLength() 493 -ApproxCurveV.GetCurveLeng 433 -ApproxCurveV.GetCurveLength()); 494 } 434 } 495 else 435 else 496 { 436 { 497 test_step = test_step - xb; 437 test_step = test_step - xb; 498 curve=std::abs(EndPoint.GetCurveLength() 438 curve=std::abs(EndPoint.GetCurveLength() 499 -CurveB_PointVelocity.GetC 439 -CurveB_PointVelocity.GetCurveLength()); 500 xb = (CurrentF_Point-Point_B).mag(); 440 xb = (CurrentF_Point-Point_B).mag(); 501 } 441 } 502 442 503 if(test_step<=0) { test_step=0.1*xb; } 443 if(test_step<=0) { test_step=0.1*xb; } 504 if(test_step>=xb) { test_step=0.5*xb; } 444 if(test_step>=xb) { test_step=0.5*xb; } 505 if(test_step>=curve){ test_step=0.5*curve; 445 if(test_step>=curve){ test_step=0.5*curve; } 506 446 507 if(curve*(1.+eps_step)<xb) // Similar to R 447 if(curve*(1.+eps_step)<xb) // Similar to ReEstimate Step from 508 { // G4VIntersect 448 { // G4VIntersectionLocator 509 test_step=0.5*curve; 449 test_step=0.5*curve; 510 } 450 } 511 451 512 fIntgrDriver->AccurateAdvance(EndPoint,tes 452 fIntgrDriver->AccurateAdvance(EndPoint,test_step, eps_step); 513 453 514 #ifdef G4DEBUG_FIELD 454 #ifdef G4DEBUG_FIELD 515 // Printing Brent and Linear Approximation 455 // Printing Brent and Linear Approximation 516 // 456 // 517 G4cout << "G4ChordFinder::ApproxCurvePoint 457 G4cout << "G4ChordFinder::ApproxCurvePointS() - test-step ShF = " 518 << test_step << " EndPoint = " << 458 << test_step << " EndPoint = " << EndPoint << G4endl; 519 459 520 // Test Track 460 // Test Track 521 // 461 // 522 G4FieldTrack TestTrack( CurveA_PointVeloci 462 G4FieldTrack TestTrack( CurveA_PointVelocity); 523 TestTrack = ApproxCurvePointV( CurveA_Poin 463 TestTrack = ApproxCurvePointV( CurveA_PointVelocity, 524 CurveB_Poin 464 CurveB_PointVelocity, 525 CurrentE_Po 465 CurrentE_Point, eps_step ); 526 G4cout.precision(14); 466 G4cout.precision(14); 527 G4cout << "G4ChordFinder::BrentApprox = " 467 G4cout << "G4ChordFinder::BrentApprox = " << EndPoint << G4endl; 528 G4cout << "G4ChordFinder::LinearApprox= " 468 G4cout << "G4ChordFinder::LinearApprox= " << TestTrack << G4endl; 529 #endif 469 #endif 530 } 470 } 531 return EndPoint; 471 return EndPoint; 532 } 472 } 533 473 534 474 535 // ........................................... 475 // ........................................................................... 536 476 537 G4FieldTrack G4ChordFinder:: 477 G4FieldTrack G4ChordFinder:: 538 ApproxCurvePointV( const G4FieldTrack& CurveA_ 478 ApproxCurvePointV( const G4FieldTrack& CurveA_PointVelocity, 539 const G4FieldTrack& CurveB_ 479 const G4FieldTrack& CurveB_PointVelocity, 540 const G4ThreeVector& Curren 480 const G4ThreeVector& CurrentE_Point, 541 G4double eps_step) 481 G4double eps_step) 542 { 482 { 543 // If r=|AE|/|AB|, and s=true path lenght (A 483 // If r=|AE|/|AB|, and s=true path lenght (AB) 544 // return the point that is r*s along the cu 484 // return the point that is r*s along the curve! 545 485 546 G4FieldTrack Current_PointVelocity = Curve 486 G4FieldTrack Current_PointVelocity = CurveA_PointVelocity; 547 487 548 G4ThreeVector CurveA_Point= CurveA_PointVel 488 G4ThreeVector CurveA_Point= CurveA_PointVelocity.GetPosition(); 549 G4ThreeVector CurveB_Point= CurveB_PointVel 489 G4ThreeVector CurveB_Point= CurveB_PointVelocity.GetPosition(); 550 490 551 G4ThreeVector ChordAB_Vector= CurveB_Point 491 G4ThreeVector ChordAB_Vector= CurveB_Point - CurveA_Point; 552 G4ThreeVector ChordAE_Vector= CurrentE_Poin 492 G4ThreeVector ChordAE_Vector= CurrentE_Point - CurveA_Point; 553 493 554 G4double ABdist= ChordAB_Vector.mag(); 494 G4double ABdist= ChordAB_Vector.mag(); 555 G4double curve_length; // A curve length 495 G4double curve_length; // A curve length of AB 556 G4double AE_fraction; 496 G4double AE_fraction; 557 497 558 curve_length= CurveB_PointVelocity.GetCurveL 498 curve_length= CurveB_PointVelocity.GetCurveLength() 559 - CurveA_PointVelocity.GetCurveL 499 - CurveA_PointVelocity.GetCurveLength(); 560 500 561 G4double integrationInaccuracyLimit= std::ma 501 G4double integrationInaccuracyLimit= std::max( perMillion, 0.5*eps_step ); 562 if( curve_length < ABdist * (1. - integratio 502 if( curve_length < ABdist * (1. - integrationInaccuracyLimit) ) 563 { 503 { 564 #ifdef G4DEBUG_FIELD 504 #ifdef G4DEBUG_FIELD 565 G4cerr << " Warning in G4ChordFinder::Appr 505 G4cerr << " Warning in G4ChordFinder::ApproxCurvePoint: " 566 << G4endl 506 << G4endl 567 << " The two points are further apa 507 << " The two points are further apart than the curve length " 568 << G4endl 508 << G4endl 569 << " Dist = " << ABdist 509 << " Dist = " << ABdist 570 << " curve length = " << curve_leng 510 << " curve length = " << curve_length 571 << " relativeDiff = " << (curve_len 511 << " relativeDiff = " << (curve_length-ABdist)/ABdist 572 << G4endl; 512 << G4endl; 573 if( curve_length < ABdist * (1. - 10*eps_s 513 if( curve_length < ABdist * (1. - 10*eps_step) ) 574 { 514 { 575 std::ostringstream message; 515 std::ostringstream message; 576 message << "Unphysical curve length." << 516 message << "Unphysical curve length." << G4endl 577 << "The size of the above differ 517 << "The size of the above difference exceeds allowed limits." 578 << G4endl 518 << G4endl 579 << "Aborting."; 519 << "Aborting."; 580 G4Exception("G4ChordFinder::ApproxCurveP 520 G4Exception("G4ChordFinder::ApproxCurvePointV()", "GeomField0003", 581 FatalException, message); 521 FatalException, message); 582 } 522 } 583 #endif 523 #endif 584 // Take default corrective action: adjust 524 // Take default corrective action: adjust the maximum curve length. 585 // NOTE: this case only happens for relati 525 // NOTE: this case only happens for relatively straight paths. 586 // curve_length = ABdist; 526 // curve_length = ABdist; 587 } 527 } 588 528 589 G4double new_st_length; 529 G4double new_st_length; 590 530 591 if ( ABdist > 0.0 ) 531 if ( ABdist > 0.0 ) 592 { 532 { 593 AE_fraction = ChordAE_Vector.mag() / ABdi 533 AE_fraction = ChordAE_Vector.mag() / ABdist; 594 } 534 } 595 else 535 else 596 { 536 { 597 AE_fraction = 0.5; 537 AE_fraction = 0.5; // Guess .. ?; 598 #ifdef G4DEBUG_FIELD 538 #ifdef G4DEBUG_FIELD 599 G4cout << "Warning in G4ChordFinder::Appr 539 G4cout << "Warning in G4ChordFinder::ApproxCurvePointV():" 600 << " A and B are the same point!" 540 << " A and B are the same point!" << G4endl 601 << " Chord AB length = " << ChordA 541 << " Chord AB length = " << ChordAE_Vector.mag() << G4endl 602 << G4endl; 542 << G4endl; 603 #endif 543 #endif 604 } 544 } 605 545 606 if( (AE_fraction> 1.0 + perMillion) || (AE_f 546 if( (AE_fraction> 1.0 + perMillion) || (AE_fraction< 0.) ) 607 { 547 { 608 #ifdef G4DEBUG_FIELD 548 #ifdef G4DEBUG_FIELD 609 G4cerr << " G4ChordFinder::ApproxCurvePoin 549 G4cerr << " G4ChordFinder::ApproxCurvePointV() - Warning:" 610 << " Anomalous condition:AE > AB or 550 << " Anomalous condition:AE > AB or AE/AB <= 0 " << G4endl 611 << " AE_fraction = " << AE_fract 551 << " AE_fraction = " << AE_fraction << G4endl 612 << " Chord AE length = " << Chord 552 << " Chord AE length = " << ChordAE_Vector.mag() << G4endl 613 << " Chord AB length = " << ABdis 553 << " Chord AB length = " << ABdist << G4endl << G4endl; 614 G4cerr << " OK if this condition occurs af 554 G4cerr << " OK if this condition occurs after a recalculation of 'B'" 615 << G4endl << " Otherwise it is an e 555 << G4endl << " Otherwise it is an error. " << G4endl ; 616 #endif 556 #endif 617 // This course can now result if B has be 557 // This course can now result if B has been re-evaluated, 618 // without E being recomputed (1 July 99) 558 // without E being recomputed (1 July 99). 619 // In this case this is not a "real error 559 // In this case this is not a "real error" - but it is undesired 620 // and we cope with it by a default corre 560 // and we cope with it by a default corrective action ... 621 // 561 // 622 AE_fraction = 0.5; 562 AE_fraction = 0.5; // Default value 623 } 563 } 624 564 625 new_st_length = AE_fraction * curve_length; 565 new_st_length = AE_fraction * curve_length; 626 566 627 if ( AE_fraction > 0.0 ) 567 if ( AE_fraction > 0.0 ) 628 { 568 { 629 fIntgrDriver->AccurateAdvance(Current_Poi 569 fIntgrDriver->AccurateAdvance(Current_PointVelocity, 630 new_st_leng 570 new_st_length, eps_step ); 631 // 571 // 632 // In this case it does not matter if it 572 // In this case it does not matter if it cannot advance the full distance 633 } 573 } 634 574 635 // If there was a memory of the step_length 575 // If there was a memory of the step_length actually required at the start 636 // of the integration Step, this could be re 576 // of the integration Step, this could be re-used ... 637 577 638 G4cout.precision(14); 578 G4cout.precision(14); 639 579 640 return Current_PointVelocity; 580 return Current_PointVelocity; 641 } 581 } 642 582 643 // ........................................... 583 // ........................................................................... 644 584 645 std::ostream& operator<<( std::ostream& os, co 585 std::ostream& operator<<( std::ostream& os, const G4ChordFinder& cf) 646 { 586 { 647 // Dumping the state of G4ChordFinder 587 // Dumping the state of G4ChordFinder 648 os << "State of G4ChordFinder : " << std::e 588 os << "State of G4ChordFinder : " << std::endl; 649 os << " delta_chord = " << cf.fDeltaCh 589 os << " delta_chord = " << cf.fDeltaChord; 650 os << " Default d_c = " << cf.fDefault 590 os << " Default d_c = " << cf.fDefaultDeltaChord; 651 591 652 os << " stats-verbose = " << cf.fStatsVe 592 os << " stats-verbose = " << cf.fStatsVerbose; 653 593 654 return os; 594 return os; 655 } 595 } 656 596