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 // G4MagInt_Driver implementation 26 // G4MagInt_Driver implementation 27 // 27 // 28 // V.Grichine, 07.10.1996 - Created 28 // V.Grichine, 07.10.1996 - Created 29 // W.Wander, 28.01.1998 - Added ability for lo 29 // W.Wander, 28.01.1998 - Added ability for low order integrators 30 // J.Apostolakis, 08.11.2001 - Respect minimum 30 // J.Apostolakis, 08.11.2001 - Respect minimum step in AccurateAdvance 31 // ------------------------------------------- 31 // -------------------------------------------------------------------- 32 32 33 #include <iomanip> 33 #include <iomanip> 34 34 35 #include "globals.hh" 35 #include "globals.hh" 36 #include "G4SystemOfUnits.hh" 36 #include "G4SystemOfUnits.hh" 37 #include "G4GeometryTolerance.hh" 37 #include "G4GeometryTolerance.hh" 38 #include "G4MagIntegratorDriver.hh" 38 #include "G4MagIntegratorDriver.hh" 39 #include "G4FieldTrack.hh" 39 #include "G4FieldTrack.hh" 40 40 41 #ifdef G4DEBUG_FIELD 41 #ifdef G4DEBUG_FIELD 42 #include "G4DriverReporter.hh" 42 #include "G4DriverReporter.hh" 43 #endif 43 #endif 44 44 45 // ------------------------------------------- 45 // --------------------------------------------------------- 46 46 47 // Constructor 47 // Constructor 48 // 48 // 49 G4MagInt_Driver::G4MagInt_Driver( G4double 49 G4MagInt_Driver::G4MagInt_Driver( G4double hminimum, 50 G4MagIntegra 50 G4MagIntegratorStepper* pStepper, 51 G4int 51 G4int numComponents, 52 G4int 52 G4int statisticsVerbose) 53 : fNoIntegrationVariables(numComponents), 53 : fNoIntegrationVariables(numComponents), 54 fNoVars( std::max( fNoIntegrationVariables 54 fNoVars( std::max( fNoIntegrationVariables, fMinNoVars )), 55 fStatisticsVerboseLevel(statisticsVerbose) 55 fStatisticsVerboseLevel(statisticsVerbose) 56 { 56 { 57 // In order to accomodate "Laboratory Time", 57 // In order to accomodate "Laboratory Time", which is [7], fMinNoVars=8 58 // is required. For proper time of flight an 58 // is required. For proper time of flight and spin, fMinNoVars must be 12 59 59 60 RenewStepperAndAdjust( pStepper ); 60 RenewStepperAndAdjust( pStepper ); 61 fMinimumStep = hminimum; 61 fMinimumStep = hminimum; 62 62 63 fMaxNoSteps = fMaxStepBase / pIntStepper->In 63 fMaxNoSteps = fMaxStepBase / pIntStepper->IntegratorOrder(); 64 #ifdef G4DEBUG_FIELD 64 #ifdef G4DEBUG_FIELD 65 fVerboseLevel=2; 65 fVerboseLevel=2; 66 #endif 66 #endif 67 67 68 if( (fVerboseLevel > 0) || (fStatisticsVerbo 68 if( (fVerboseLevel > 0) || (fStatisticsVerboseLevel > 1) ) 69 { 69 { 70 G4cout << "MagIntDriver version: Accur-Adv 70 G4cout << "MagIntDriver version: Accur-Adv: " 71 << "invE_nS, QuickAdv-2sqrt with St 71 << "invE_nS, QuickAdv-2sqrt with Statistics " 72 #ifdef G4FLD_STATS 72 #ifdef G4FLD_STATS 73 << " enabled " 73 << " enabled " 74 #else 74 #else 75 << " disabled " 75 << " disabled " 76 #endif 76 #endif 77 << G4endl; 77 << G4endl; 78 } 78 } 79 } 79 } 80 80 81 // ------------------------------------------- 81 // --------------------------------------------------------- 82 82 83 // Destructor 83 // Destructor 84 // 84 // 85 G4MagInt_Driver::~G4MagInt_Driver() 85 G4MagInt_Driver::~G4MagInt_Driver() 86 { 86 { 87 if( fStatisticsVerboseLevel > 1 ) 87 if( fStatisticsVerboseLevel > 1 ) 88 { 88 { 89 PrintStatisticsReport(); 89 PrintStatisticsReport(); 90 } 90 } 91 } 91 } 92 92 93 // ------------------------------------------- 93 // --------------------------------------------------------- 94 94 95 G4bool 95 G4bool 96 G4MagInt_Driver::AccurateAdvance(G4FieldTrack& 96 G4MagInt_Driver::AccurateAdvance(G4FieldTrack& y_current, 97 G4double 97 G4double hstep, 98 G4double 98 G4double eps, 99 G4double 99 G4double hinitial ) 100 { 100 { 101 // Runge-Kutta driver with adaptive stepsize 101 // Runge-Kutta driver with adaptive stepsize control. Integrate starting 102 // values at y_current over hstep x2 with ac 102 // values at y_current over hstep x2 with accuracy eps. 103 // On output ystart is replaced by values at 103 // On output ystart is replaced by values at the end of the integration 104 // interval. RightHandSide is the right-hand 104 // interval. RightHandSide is the right-hand side of ODE system. 105 // The source is similar to odeint routine f 105 // The source is similar to odeint routine from NRC p.721-722 . 106 106 107 G4int nstp, i; << 107 G4int nstp, i, no_warnings = 0; 108 G4double x, hnext, hdid, h; 108 G4double x, hnext, hdid, h; 109 109 110 #ifdef G4DEBUG_FIELD 110 #ifdef G4DEBUG_FIELD 111 G4int no_warnings = 0; << 112 static G4int dbg = 1; 111 static G4int dbg = 1; 113 static G4int nStpPr = 50; // For debug pri 112 static G4int nStpPr = 50; // For debug printing of long integrations 114 G4double ySubStepStart[G4FieldTrack::ncompSV 113 G4double ySubStepStart[G4FieldTrack::ncompSVEC]; 115 G4FieldTrack yFldTrkStart(y_current); 114 G4FieldTrack yFldTrkStart(y_current); 116 #endif 115 #endif 117 116 118 G4double y[G4FieldTrack::ncompSVEC] = {0., 0 << 117 G4double y[G4FieldTrack::ncompSVEC], dydx[G4FieldTrack::ncompSVEC]; 119 G4double dydx[G4FieldTrack::ncompSVEC] = {0. << 118 G4double ystart[G4FieldTrack::ncompSVEC], yEnd[G4FieldTrack::ncompSVEC]; 120 G4double ystart[G4FieldTrack::ncompSVEC] = { << 121 G4double yEnd[G4FieldTrack::ncompSVEC] = {0. << 122 G4double x1, x2; 119 G4double x1, x2; 123 G4bool succeeded = true; << 120 G4bool succeeded = true, lastStepSucceeded; 124 121 125 G4double startCurveLength; 122 G4double startCurveLength; 126 123 >> 124 G4int noFullIntegr = 0, noSmallIntegr = 0; >> 125 static G4ThreadLocal G4int noGoodSteps = 0; // Bad = chord > curve-len 127 const G4int nvar = fNoVars; 126 const G4int nvar = fNoVars; 128 127 129 G4FieldTrack yStartFT(y_current); 128 G4FieldTrack yStartFT(y_current); 130 129 131 // Ensure that hstep > 0 130 // Ensure that hstep > 0 132 // 131 // 133 if( hstep <= 0.0 ) 132 if( hstep <= 0.0 ) 134 { 133 { 135 if( hstep == 0.0 ) 134 if( hstep == 0.0 ) 136 { 135 { 137 std::ostringstream message; 136 std::ostringstream message; 138 message << "Proposed step is zero; hstep 137 message << "Proposed step is zero; hstep = " << hstep << " !"; 139 G4Exception("G4MagInt_Driver::AccurateAd 138 G4Exception("G4MagInt_Driver::AccurateAdvance()", 140 "GeomField1001", JustWarning 139 "GeomField1001", JustWarning, message); 141 return succeeded; 140 return succeeded; 142 } 141 } 143 << 142 else 144 std::ostringstream message; << 143 { 145 message << "Invalid run condition." << G4e << 144 std::ostringstream message; 146 << "Proposed step is negative; hst << 145 message << "Invalid run condition." << G4endl 147 << "Requested step cannot be negat << 146 << "Proposed step is negative; hstep = " << hstep << "." << G4endl 148 G4Exception("G4MagInt_Driver::AccurateAdva << 147 << "Requested step cannot be negative! Aborting event."; 149 "GeomField0003", EventMustBeAb << 148 G4Exception("G4MagInt_Driver::AccurateAdvance()", 150 return false; << 149 "GeomField0003", EventMustBeAborted, message); >> 150 return false; >> 151 } 151 } 152 } 152 153 153 y_current.DumpToArray( ystart ); 154 y_current.DumpToArray( ystart ); 154 155 155 startCurveLength= y_current.GetCurveLength() 156 startCurveLength= y_current.GetCurveLength(); 156 x1= startCurveLength; 157 x1= startCurveLength; 157 x2= x1 + hstep; 158 x2= x1 + hstep; 158 159 159 if ( (hinitial > 0.0) && (hinitial < hstep) 160 if ( (hinitial > 0.0) && (hinitial < hstep) 160 && (hinitial > perMillion * hstep) ) 161 && (hinitial > perMillion * hstep) ) 161 { 162 { 162 h = hinitial; 163 h = hinitial; 163 } 164 } 164 else // Initial Step size "h" defaults to 165 else // Initial Step size "h" defaults to the full interval 165 { 166 { 166 h = hstep; 167 h = hstep; 167 } 168 } 168 169 169 x = x1; 170 x = x1; 170 171 171 for ( i=0; i<nvar; ++i) { y[i] = ystart[i]; 172 for ( i=0; i<nvar; ++i) { y[i] = ystart[i]; } 172 173 173 G4bool lastStep= false; 174 G4bool lastStep= false; 174 nstp = 1; 175 nstp = 1; 175 176 176 do 177 do 177 { 178 { 178 G4ThreeVector StartPos( y[0], y[1], y[2] ) 179 G4ThreeVector StartPos( y[0], y[1], y[2] ); 179 180 180 #ifdef G4DEBUG_FIELD 181 #ifdef G4DEBUG_FIELD 181 G4double xSubStepStart= x; 182 G4double xSubStepStart= x; 182 for (i=0; i<nvar; ++i) { ySubStepStart[i] 183 for (i=0; i<nvar; ++i) { ySubStepStart[i] = y[i]; } 183 yFldTrkStart.LoadFromArray(y, fNoIntegrati 184 yFldTrkStart.LoadFromArray(y, fNoIntegrationVariables); 184 yFldTrkStart.SetCurveLength(x); 185 yFldTrkStart.SetCurveLength(x); 185 #endif 186 #endif 186 187 187 pIntStepper->RightHandSide( y, dydx ); 188 pIntStepper->RightHandSide( y, dydx ); 188 ++fNoTotalSteps; 189 ++fNoTotalSteps; 189 190 190 // Perform the Integration 191 // Perform the Integration 191 // 192 // 192 if( h > fMinimumStep ) 193 if( h > fMinimumStep ) 193 { 194 { 194 OneGoodStep(y,dydx,x,h,eps,hdid,hnext) ; 195 OneGoodStep(y,dydx,x,h,eps,hdid,hnext) ; 195 //-------------------------------------- 196 //-------------------------------------- >> 197 lastStepSucceeded = (hdid == h); 196 #ifdef G4DEBUG_FIELD 198 #ifdef G4DEBUG_FIELD 197 if (dbg>2) 199 if (dbg>2) 198 { 200 { 199 // PrintStatus( ySubStepStart, xSubSt 201 // PrintStatus( ySubStepStart, xSubStepStart, y, x, h, nstp); // Only 200 G4DriverReporter::PrintStatus( ySubSte 202 G4DriverReporter::PrintStatus( ySubStepStart, xSubStepStart, y, x, h, nstp, nvar); 201 } 203 } 202 #endif 204 #endif 203 } 205 } 204 else 206 else 205 { 207 { 206 G4FieldTrack yFldTrk( G4ThreeVector(0,0, 208 G4FieldTrack yFldTrk( G4ThreeVector(0,0,0), 207 G4ThreeVector(0,0, 209 G4ThreeVector(0,0,0), 0., 0., 0., 0. ); 208 G4double dchord_step, dyerr, dyerr_len; 210 G4double dchord_step, dyerr, dyerr_len; // What to do with these ? 209 yFldTrk.LoadFromArray(y, fNoIntegrationV 211 yFldTrk.LoadFromArray(y, fNoIntegrationVariables); 210 yFldTrk.SetCurveLength( x ); 212 yFldTrk.SetCurveLength( x ); 211 213 212 QuickAdvance( yFldTrk, dydx, h, dchord_s 214 QuickAdvance( yFldTrk, dydx, h, dchord_step, dyerr_len ); 213 //-------------------------------------- 215 //----------------------------------------------------- 214 216 215 yFldTrk.DumpToArray(y); 217 yFldTrk.DumpToArray(y); 216 218 217 #ifdef G4FLD_STATS 219 #ifdef G4FLD_STATS 218 ++fNoSmallSteps; 220 ++fNoSmallSteps; 219 if ( dyerr_len > fDyerr_max ) { fDyerr_ 221 if ( dyerr_len > fDyerr_max ) { fDyerr_max = dyerr_len; } 220 fDyerrPos_smTot += dyerr_len; 222 fDyerrPos_smTot += dyerr_len; 221 fSumH_sm += h; // Length total for 'sma 223 fSumH_sm += h; // Length total for 'small' steps 222 if (nstp==1) { ++fNoInitialSmallSteps; 224 if (nstp==1) { ++fNoInitialSmallSteps; } 223 #endif 225 #endif 224 #ifdef G4DEBUG_FIELD 226 #ifdef G4DEBUG_FIELD 225 if (dbg>1) 227 if (dbg>1) 226 { 228 { 227 if(fNoSmallSteps<2) { PrintStatus(ySub 229 if(fNoSmallSteps<2) { PrintStatus(ySubStepStart, x1, y, x, h, -nstp); } 228 G4cout << "Another sub-min step, no " 230 G4cout << "Another sub-min step, no " << fNoSmallSteps 229 << " of " << fNoTotalSteps << " 231 << " of " << fNoTotalSteps << " this time " << nstp << G4endl; 230 PrintStatus( ySubStepStart, x1, y, x, 232 PrintStatus( ySubStepStart, x1, y, x, h, nstp); // Only this 231 G4cout << " dyerr= " << dyerr_len << " 233 G4cout << " dyerr= " << dyerr_len << " relative = " << dyerr_len / h 232 << " epsilon= " << eps << " hst 234 << " epsilon= " << eps << " hstep= " << hstep 233 << " h= " << h << " hmin= " << 235 << " h= " << h << " hmin= " << fMinimumStep << G4endl; 234 } 236 } 235 #endif 237 #endif 236 if( h == 0.0 ) 238 if( h == 0.0 ) 237 { 239 { 238 G4Exception("G4MagInt_Driver::Accurate 240 G4Exception("G4MagInt_Driver::AccurateAdvance()", 239 "GeomField0003", FatalExce 241 "GeomField0003", FatalException, 240 "Integration Step became Z 242 "Integration Step became Zero!"); 241 } 243 } 242 dyerr = dyerr_len / h; 244 dyerr = dyerr_len / h; 243 hdid = h; 245 hdid = h; 244 x += hdid; 246 x += hdid; 245 247 246 // Compute suggested new step 248 // Compute suggested new step 247 hnext = ComputeNewStepSize( dyerr/eps, h 249 hnext = ComputeNewStepSize( dyerr/eps, h); >> 250 >> 251 // .. hnext= ComputeNewStepSize_WithinLimits( dyerr/eps, h); >> 252 lastStepSucceeded = (dyerr<= eps); 248 } 253 } 249 254 >> 255 if (lastStepSucceeded) { ++noFullIntegr; } >> 256 else { ++noSmallIntegr; } >> 257 250 G4ThreeVector EndPos( y[0], y[1], y[2] ); 258 G4ThreeVector EndPos( y[0], y[1], y[2] ); 251 259 252 #ifdef G4DEBUG_FIELD 260 #ifdef G4DEBUG_FIELD 253 if( (dbg>0) && (dbg<=2) && (nstp>nStpPr)) 261 if( (dbg>0) && (dbg<=2) && (nstp>nStpPr)) 254 { 262 { 255 if( nstp==nStpPr ) { G4cout << "***** M 263 if( nstp==nStpPr ) { G4cout << "***** Many steps ****" << G4endl; } 256 G4cout << "MagIntDrv: " ; 264 G4cout << "MagIntDrv: " ; 257 G4cout << "hdid=" << std::setw(12) << h 265 G4cout << "hdid=" << std::setw(12) << hdid << " " 258 << "hnext=" << std::setw(12) << h 266 << "hnext=" << std::setw(12) << hnext << " " 259 << "hstep=" << std::setw(12) << h 267 << "hstep=" << std::setw(12) << hstep << " (requested) " 260 << G4endl; 268 << G4endl; 261 PrintStatus( ystart, x1, y, x, h, (nstp= 269 PrintStatus( ystart, x1, y, x, h, (nstp==nStpPr) ? -nstp: nstp); 262 } 270 } 263 #endif 271 #endif 264 272 265 // Check the endpoint 273 // Check the endpoint 266 G4double endPointDist= (EndPos-StartPos).m 274 G4double endPointDist= (EndPos-StartPos).mag(); 267 if ( endPointDist >= hdid*(1.+perMillion) 275 if ( endPointDist >= hdid*(1.+perMillion) ) 268 { 276 { 269 ++fNoBadSteps; 277 ++fNoBadSteps; 270 278 271 // Issue a warning only for gross differ 279 // Issue a warning only for gross differences - 272 // we understand how small difference oc 280 // we understand how small difference occur. 273 if ( endPointDist >= hdid*(1.+perThousan 281 if ( endPointDist >= hdid*(1.+perThousand) ) 274 { 282 { 275 #ifdef G4DEBUG_FIELD 283 #ifdef G4DEBUG_FIELD 276 if (dbg) 284 if (dbg) 277 { 285 { 278 WarnEndPointTooFar ( endPointDist, h 286 WarnEndPointTooFar ( endPointDist, hdid, eps, dbg ); 279 G4cerr << " Total steps: bad " << 287 G4cerr << " Total steps: bad " << fNoBadSteps 280 << " current h= " << hdid << << 288 << " good " << noGoodSteps << " current h= " << hdid >> 289 << G4endl; 281 PrintStatus( ystart, x1, y, x, hstep 290 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp); 282 } 291 } 283 ++no_warnings; << 284 #endif 292 #endif >> 293 ++no_warnings; 285 } 294 } 286 } 295 } >> 296 else >> 297 { >> 298 ++noGoodSteps; >> 299 } >> 300 // #endif 287 301 288 // Avoid numerous small last steps 302 // Avoid numerous small last steps 289 if( (h < eps * hstep) || (h < fSmallestFra 303 if( (h < eps * hstep) || (h < fSmallestFraction * startCurveLength) ) 290 { 304 { 291 // No more integration -- the next step 305 // No more integration -- the next step will not happen 292 lastStep = true; 306 lastStep = true; 293 } 307 } 294 else 308 else 295 { 309 { 296 // Check the proposed next stepsize 310 // Check the proposed next stepsize 297 if(std::fabs(hnext) <= Hmin()) 311 if(std::fabs(hnext) <= Hmin()) 298 { 312 { 299 #ifdef G4DEBUG_FIELD 313 #ifdef G4DEBUG_FIELD 300 // If simply a very small interval is 314 // If simply a very small interval is being integrated, do not warn 301 if( (x < x2 * (1-eps) ) && // T 315 if( (x < x2 * (1-eps) ) && // The last step can be small: OK 302 (std::fabs(hstep) > Hmin()) ) // a 316 (std::fabs(hstep) > Hmin()) ) // and if we are asked, it's OK 303 { 317 { 304 if(dbg>0) 318 if(dbg>0) 305 { 319 { 306 WarnSmallStepSize( hnext, hstep, h 320 WarnSmallStepSize( hnext, hstep, h, x-x1, nstp ); 307 PrintStatus( ystart, x1, y, x, hst 321 PrintStatus( ystart, x1, y, x, hstep, no_warnings?nstp:-nstp); 308 } 322 } 309 ++no_warnings; 323 ++no_warnings; 310 } 324 } 311 #endif 325 #endif 312 // Make sure that the next step is at 326 // Make sure that the next step is at least Hmin. 313 h = Hmin(); 327 h = Hmin(); 314 } 328 } 315 else 329 else 316 { 330 { 317 h = hnext; 331 h = hnext; 318 } 332 } 319 333 320 // Ensure that the next step does not o 334 // Ensure that the next step does not overshoot 321 if ( x+h > x2 ) 335 if ( x+h > x2 ) 322 { // When stepsize oversh 336 { // When stepsize overshoots, decrease it! 323 h = x2 - x ; // Must cope with diffi 337 h = x2 - x ; // Must cope with difficult rounding-error 324 } // issues if hstep << x 338 } // issues if hstep << x2 325 339 326 if ( h == 0.0 ) 340 if ( h == 0.0 ) 327 { 341 { 328 // Cannot progress - accept this as la 342 // Cannot progress - accept this as last step - by default 329 lastStep = true; 343 lastStep = true; 330 #ifdef G4DEBUG_FIELD 344 #ifdef G4DEBUG_FIELD 331 if (dbg>2) 345 if (dbg>2) 332 { 346 { 333 int prec= G4cout.precision(12); 347 int prec= G4cout.precision(12); 334 G4cout << "Warning: G4MagIntegratorD 348 G4cout << "Warning: G4MagIntegratorDriver::AccurateAdvance" 335 << G4endl 349 << G4endl 336 << " Integration step 'h' be 350 << " Integration step 'h' became " 337 << h << " due to roundoff. " 351 << h << " due to roundoff. " << G4endl 338 << " Calculated as difference 352 << " Calculated as difference of x2= "<< x2 << " and x=" << x 339 << " Forcing termination of 353 << " Forcing termination of advance." << G4endl; 340 G4cout.precision(prec); 354 G4cout.precision(prec); 341 } 355 } 342 #endif 356 #endif 343 } 357 } 344 } 358 } 345 } while ( ((++nstp)<=fMaxNoSteps) && (x < x2 359 } while ( ((++nstp)<=fMaxNoSteps) && (x < x2) && (!lastStep) ); 346 // Loop checking, 07.10.2016, J. Apostolakis 360 // Loop checking, 07.10.2016, J. Apostolakis 347 361 348 // Have we reached the end ? 362 // Have we reached the end ? 349 // --> a better test might be x-x2 > an_e 363 // --> a better test might be x-x2 > an_epsilon 350 364 351 succeeded = (x>=x2); // If it was a "forced 365 succeeded = (x>=x2); // If it was a "forced" last step 352 366 353 for (i=0; i<nvar; ++i) { yEnd[i] = y[i]; } 367 for (i=0; i<nvar; ++i) { yEnd[i] = y[i]; } 354 368 355 // Put back the values. 369 // Put back the values. 356 y_current.LoadFromArray( yEnd, fNoIntegratio 370 y_current.LoadFromArray( yEnd, fNoIntegrationVariables ); 357 y_current.SetCurveLength( x ); 371 y_current.SetCurveLength( x ); 358 372 359 if(nstp > fMaxNoSteps) 373 if(nstp > fMaxNoSteps) 360 { 374 { >> 375 ++no_warnings; 361 succeeded = false; 376 succeeded = false; 362 #ifdef G4DEBUG_FIELD 377 #ifdef G4DEBUG_FIELD 363 ++no_warnings; << 364 if (dbg) 378 if (dbg) 365 { 379 { 366 WarnTooManyStep( x1, x2, x ); // Issue 380 WarnTooManyStep( x1, x2, x ); // Issue WARNING 367 PrintStatus( yEnd, x1, y, x, hstep, -nst 381 PrintStatus( yEnd, x1, y, x, hstep, -nstp); 368 } 382 } 369 #endif 383 #endif 370 } 384 } 371 385 372 #ifdef G4DEBUG_FIELD 386 #ifdef G4DEBUG_FIELD 373 if( dbg && no_warnings ) 387 if( dbg && no_warnings ) 374 { 388 { 375 G4cerr << "G4MagIntegratorDriver exit stat 389 G4cerr << "G4MagIntegratorDriver exit status: no-steps " << nstp << G4endl; 376 PrintStatus( yEnd, x1, y, x, hstep, nstp); 390 PrintStatus( yEnd, x1, y, x, hstep, nstp); 377 } 391 } 378 #endif 392 #endif 379 393 380 return succeeded; 394 return succeeded; 381 } // end of AccurateAdvance ................. 395 } // end of AccurateAdvance ........................... 382 396 383 // ------------------------------------------- 397 // --------------------------------------------------------- 384 398 385 void 399 void 386 G4MagInt_Driver::WarnSmallStepSize( G4double h 400 G4MagInt_Driver::WarnSmallStepSize( G4double hnext, G4double hstep, 387 G4double h 401 G4double h, G4double xDone, 388 G4int nstp 402 G4int nstp) 389 { 403 { 390 static G4ThreadLocal G4int noWarningsIssued 404 static G4ThreadLocal G4int noWarningsIssued = 0; 391 const G4int maxNoWarnings = 10; // Number 405 const G4int maxNoWarnings = 10; // Number of verbose warnings 392 std::ostringstream message; 406 std::ostringstream message; 393 if( (noWarningsIssued < maxNoWarnings) || fV 407 if( (noWarningsIssued < maxNoWarnings) || fVerboseLevel > 10 ) 394 { 408 { 395 message << "The stepsize for the next iter 409 message << "The stepsize for the next iteration, " << hnext 396 << ", is too small - in Step numbe 410 << ", is too small - in Step number " << nstp << "." << G4endl 397 << "The minimum for the driver is 411 << "The minimum for the driver is " << Hmin() << G4endl 398 << "Requested integr. length was " 412 << "Requested integr. length was " << hstep << " ." << G4endl 399 << "The size of this sub-step was 413 << "The size of this sub-step was " << h << " ." << G4endl 400 << "The integrations has already g 414 << "The integrations has already gone " << xDone; 401 } 415 } 402 else 416 else 403 { 417 { 404 message << "Too small 'next' step " << hne 418 message << "Too small 'next' step " << hnext 405 << ", step-no: " << nstp << G4endl 419 << ", step-no: " << nstp << G4endl 406 << ", this sub-step: " << h 420 << ", this sub-step: " << h 407 << ", req_tot_len: " << hstep 421 << ", req_tot_len: " << hstep 408 << ", done: " << xDone << ", min: 422 << ", done: " << xDone << ", min: " << Hmin(); 409 } 423 } 410 G4Exception("G4MagInt_Driver::WarnSmallStepS 424 G4Exception("G4MagInt_Driver::WarnSmallStepSize()", "GeomField1001", 411 JustWarning, message); 425 JustWarning, message); 412 ++noWarningsIssued; 426 ++noWarningsIssued; 413 } 427 } 414 428 415 // ------------------------------------------- 429 // --------------------------------------------------------- 416 430 417 void 431 void 418 G4MagInt_Driver::WarnTooManyStep( G4double x1s 432 G4MagInt_Driver::WarnTooManyStep( G4double x1start, 419 G4double x2e 433 G4double x2end, 420 G4double xCu 434 G4double xCurrent ) 421 { 435 { 422 std::ostringstream message; 436 std::ostringstream message; 423 message << "The number of steps used in the 437 message << "The number of steps used in the Integration driver" 424 << " (Runge-Kutta) is too many." << 438 << " (Runge-Kutta) is too many." << G4endl 425 << "Integration of the interval was 439 << "Integration of the interval was not completed !" << G4endl 426 << "Only a " << (xCurrent-x1start)* 440 << "Only a " << (xCurrent-x1start)*100/(x2end-x1start) 427 << " % fraction of it was done."; 441 << " % fraction of it was done."; 428 G4Exception("G4MagInt_Driver::WarnTooManySt 442 G4Exception("G4MagInt_Driver::WarnTooManyStep()", "GeomField1001", 429 JustWarning, message); 443 JustWarning, message); 430 } 444 } 431 445 432 // ------------------------------------------- 446 // --------------------------------------------------------- 433 447 434 void 448 void 435 G4MagInt_Driver::WarnEndPointTooFar (G4double 449 G4MagInt_Driver::WarnEndPointTooFar (G4double endPointDist, 436 G4double 450 G4double h , 437 G4double 451 G4double eps, 438 G4int 452 G4int dbg) 439 { 453 { 440 static G4ThreadLocal G4double maxRelError = 454 static G4ThreadLocal G4double maxRelError = 0.0; 441 G4bool isNewMax, prNewMax; 455 G4bool isNewMax, prNewMax; 442 456 443 isNewMax = endPointDist > (1.0 + maxRelError 457 isNewMax = endPointDist > (1.0 + maxRelError) * h; 444 prNewMax = endPointDist > (1.0 + 1.05 * maxR 458 prNewMax = endPointDist > (1.0 + 1.05 * maxRelError) * h; 445 if( isNewMax ) { maxRelError= endPointDist / 459 if( isNewMax ) { maxRelError= endPointDist / h - 1.0; } 446 460 447 if( (dbg != 0) && (h > G4GeometryTolerance:: << 461 if( dbg && (h > G4GeometryTolerance::GetInstance()->GetSurfaceTolerance()) 448 && ( (dbg>1) || prNewMax || (endPoin 462 && ( (dbg>1) || prNewMax || (endPointDist >= h*(1.+eps) ) ) ) 449 { 463 { 450 static G4ThreadLocal G4int noWarnings = 0; 464 static G4ThreadLocal G4int noWarnings = 0; 451 std::ostringstream message; 465 std::ostringstream message; 452 if( (noWarnings++ < 10) || (dbg>2) ) 466 if( (noWarnings++ < 10) || (dbg>2) ) 453 { 467 { 454 message << "The integration produced an 468 message << "The integration produced an end-point which " << G4endl 455 << "is further from the start-po 469 << "is further from the start-point than the curve length." 456 << G4endl; 470 << G4endl; 457 } 471 } 458 message << " Distance of endpoints = " << 472 message << " Distance of endpoints = " << endPointDist 459 << ", curve length = " << h << G4e 473 << ", curve length = " << h << G4endl 460 << " Difference (curveLen-endpDis 474 << " Difference (curveLen-endpDist)= " << (h - endPointDist) 461 << ", relative = " << (h-endPointD 475 << ", relative = " << (h-endPointDist) / h 462 << ", epsilon = " << eps; 476 << ", epsilon = " << eps; 463 G4Exception("G4MagInt_Driver::WarnEndPoint 477 G4Exception("G4MagInt_Driver::WarnEndPointTooFar()", "GeomField1001", 464 JustWarning, message); 478 JustWarning, message); 465 } 479 } 466 } 480 } 467 481 468 // ------------------------------------------- 482 // --------------------------------------------------------- 469 483 470 void 484 void 471 G4MagInt_Driver::OneGoodStep( G4double y[ 485 G4MagInt_Driver::OneGoodStep( G4double y[], // InOut 472 const G4double dy 486 const G4double dydx[], 473 G4double& x 487 G4double& x, // InOut 474 G4double ht 488 G4double htry, 475 G4double ep 489 G4double eps_rel_max, 476 G4double& h 490 G4double& hdid, // Out 477 G4double& h 491 G4double& hnext ) // Out 478 492 479 // Driver for one Runge-Kutta Step with monito 493 // Driver for one Runge-Kutta Step with monitoring of local truncation error 480 // to ensure accuracy and adjust stepsize. Inp 494 // to ensure accuracy and adjust stepsize. Input are dependent variable 481 // array y[0,...,5] and its derivative dydx[0, 495 // array y[0,...,5] and its derivative dydx[0,...,5] at the 482 // starting value of the independent variable 496 // starting value of the independent variable x . Also input are stepsize 483 // to be attempted htry, and the required accu 497 // to be attempted htry, and the required accuracy eps. On output y and x 484 // are replaced by their new values, hdid is t 498 // are replaced by their new values, hdid is the stepsize that was actually 485 // accomplished, and hnext is the estimated ne 499 // accomplished, and hnext is the estimated next stepsize. 486 // This is similar to the function rkqs from t 500 // This is similar to the function rkqs from the book: 487 // Numerical Recipes in C: The Art of Scientif 501 // Numerical Recipes in C: The Art of Scientific Computing (NRC), Second 488 // Edition, by William H. Press, Saul A. Teuko 502 // Edition, by William H. Press, Saul A. Teukolsky, William T. 489 // Vetterling, and Brian P. Flannery (Cambridg 503 // Vetterling, and Brian P. Flannery (Cambridge University Press 1992), 490 // 16.2 Adaptive StepSize Control for Runge-Ku 504 // 16.2 Adaptive StepSize Control for Runge-Kutta, p. 719 491 505 492 { 506 { 493 G4double errmax_sq; 507 G4double errmax_sq; 494 G4double h, htemp, xnew ; 508 G4double h, htemp, xnew ; 495 509 496 G4double yerr[G4FieldTrack::ncompSVEC], ytem 510 G4double yerr[G4FieldTrack::ncompSVEC], ytemp[G4FieldTrack::ncompSVEC]; 497 511 498 h = htry ; // Set stepsize to the initial tr 512 h = htry ; // Set stepsize to the initial trial value 499 513 500 G4double inv_eps_vel_sq = 1.0 / (eps_rel_max 514 G4double inv_eps_vel_sq = 1.0 / (eps_rel_max*eps_rel_max); 501 515 502 G4double errpos_sq = 0.0; // square of di 516 G4double errpos_sq = 0.0; // square of displacement error 503 G4double errvel_sq = 0.0; // square of mo 517 G4double errvel_sq = 0.0; // square of momentum vector difference 504 G4double errspin_sq = 0.0; // square of sp 518 G4double errspin_sq = 0.0; // square of spin vector difference 505 519 >> 520 static G4ThreadLocal G4int tot_no_trials=0; 506 const G4int max_trials=100; 521 const G4int max_trials=100; 507 522 508 G4ThreeVector Spin(y[9],y[10],y[11]); 523 G4ThreeVector Spin(y[9],y[10],y[11]); 509 G4double spin_mag2 = Spin.mag2(); 524 G4double spin_mag2 = Spin.mag2(); 510 G4bool hasSpin = (spin_mag2 > 0.0); 525 G4bool hasSpin = (spin_mag2 > 0.0); 511 526 512 for (G4int iter=0; iter<max_trials; ++iter) 527 for (G4int iter=0; iter<max_trials; ++iter) 513 { 528 { >> 529 ++tot_no_trials; 514 pIntStepper-> Stepper(y,dydx,h,ytemp,yerr) 530 pIntStepper-> Stepper(y,dydx,h,ytemp,yerr); 515 // ******* 531 // ******* 516 G4double eps_pos = eps_rel_max * std::max( 532 G4double eps_pos = eps_rel_max * std::max(h, fMinimumStep); 517 G4double inv_eps_pos_sq = 1.0 / (eps_pos*e 533 G4double inv_eps_pos_sq = 1.0 / (eps_pos*eps_pos); 518 534 519 // Evaluate accuracy 535 // Evaluate accuracy 520 // 536 // 521 errpos_sq = sqr(yerr[0]) + sqr(yerr[1]) + 537 errpos_sq = sqr(yerr[0]) + sqr(yerr[1]) + sqr(yerr[2]) ; 522 errpos_sq *= inv_eps_pos_sq; // Scale rela 538 errpos_sq *= inv_eps_pos_sq; // Scale relative to required tolerance 523 539 524 // Accuracy for momentum 540 // Accuracy for momentum 525 G4double magvel_sq= sqr(y[3]) + sqr(y[4]) 541 G4double magvel_sq= sqr(y[3]) + sqr(y[4]) + sqr(y[5]) ; 526 G4double sumerr_sq = sqr(yerr[3]) + sqr(y 542 G4double sumerr_sq = sqr(yerr[3]) + sqr(yerr[4]) + sqr(yerr[5]) ; 527 if( magvel_sq > 0.0 ) 543 if( magvel_sq > 0.0 ) 528 { 544 { 529 errvel_sq = sumerr_sq / magvel_sq; 545 errvel_sq = sumerr_sq / magvel_sq; 530 } 546 } 531 else 547 else 532 { 548 { 533 std::ostringstream message; 549 std::ostringstream message; 534 message << "Found case of zero momentum 550 message << "Found case of zero momentum." << G4endl 535 << "- iteration= " << iter << " 551 << "- iteration= " << iter << "; h= " << h; 536 G4Exception("G4MagInt_Driver::OneGoodSt 552 G4Exception("G4MagInt_Driver::OneGoodStep()", 537 "GeomField1001", JustWarnin 553 "GeomField1001", JustWarning, message); 538 errvel_sq = sumerr_sq; 554 errvel_sq = sumerr_sq; 539 } 555 } 540 errvel_sq *= inv_eps_vel_sq; 556 errvel_sq *= inv_eps_vel_sq; 541 errmax_sq = std::max( errpos_sq, errvel_sq 557 errmax_sq = std::max( errpos_sq, errvel_sq ); // Square of maximum error 542 558 543 if( hasSpin ) 559 if( hasSpin ) 544 { 560 { 545 // Accuracy for spin 561 // Accuracy for spin 546 errspin_sq = ( sqr(yerr[9]) + sqr(yerr[ 562 errspin_sq = ( sqr(yerr[9]) + sqr(yerr[10]) + sqr(yerr[11]) ) 547 / spin_mag2; // ( sqr(y[9 563 / spin_mag2; // ( sqr(y[9]) + sqr(y[10]) + sqr(y[11]) ); 548 errspin_sq *= inv_eps_vel_sq; 564 errspin_sq *= inv_eps_vel_sq; 549 errmax_sq = std::max( errmax_sq, errspin 565 errmax_sq = std::max( errmax_sq, errspin_sq ); 550 } 566 } 551 567 552 if ( errmax_sq <= 1.0 ) { break; } // Ste 568 if ( errmax_sq <= 1.0 ) { break; } // Step succeeded. 553 569 554 // Step failed; compute the size of retria 570 // Step failed; compute the size of retrial Step. 555 htemp = GetSafety() * h * std::pow( errmax 571 htemp = GetSafety() * h * std::pow( errmax_sq, 0.5*GetPshrnk() ); 556 572 557 if (htemp >= 0.1*h) { h = htemp; } // Tr 573 if (htemp >= 0.1*h) { h = htemp; } // Truncation error too large, 558 else { h = 0.1*h; } // re 574 else { h = 0.1*h; } // reduce stepsize, but no more 559 // th 575 // than a factor of 10 560 xnew = x + h; 576 xnew = x + h; 561 if(xnew == x) 577 if(xnew == x) 562 { 578 { 563 std::ostringstream message; 579 std::ostringstream message; 564 message << "Stepsize underflow in Steppe 580 message << "Stepsize underflow in Stepper !" << G4endl 565 << "- Step's start x=" << x << " 581 << "- Step's start x=" << x << " and end x= " << xnew 566 << " are equal !! " << G4endl 582 << " are equal !! " << G4endl 567 << " Due to step-size= " << h 583 << " Due to step-size= " << h 568 << ". Note that input step was " 584 << ". Note that input step was " << htry; 569 G4Exception("G4MagInt_Driver::OneGoodSte 585 G4Exception("G4MagInt_Driver::OneGoodStep()", 570 "GeomField1001", JustWarning 586 "GeomField1001", JustWarning, message); 571 break; 587 break; 572 } 588 } 573 } 589 } 574 590 575 // Compute size of next Step 591 // Compute size of next Step 576 if (errmax_sq > errcon*errcon) 592 if (errmax_sq > errcon*errcon) 577 { 593 { 578 hnext = GetSafety()*h*std::pow(errmax_sq, 594 hnext = GetSafety()*h*std::pow(errmax_sq, 0.5*GetPgrow()); 579 } 595 } 580 else 596 else 581 { 597 { 582 hnext = max_stepping_increase*h ; // No mo 598 hnext = max_stepping_increase*h ; // No more than a factor of 5 increase 583 } 599 } 584 x += (hdid = h); 600 x += (hdid = h); 585 601 586 for(G4int k=0; k<fNoIntegrationVariables; ++ 602 for(G4int k=0; k<fNoIntegrationVariables; ++k) { y[k] = ytemp[k]; } 587 603 588 return; 604 return; 589 } 605 } 590 606 591 //-------------------------------------------- 607 //---------------------------------------------------------------------- 592 608 593 // QuickAdvance just tries one Step - it does 609 // QuickAdvance just tries one Step - it does not ensure accuracy 594 // 610 // 595 G4bool G4MagInt_Driver::QuickAdvance(G4FieldTr 611 G4bool G4MagInt_Driver::QuickAdvance(G4FieldTrack& y_posvel, // INOUT 596 const G4double 612 const G4double dydx[], 597 G4double 613 G4double hstep, // In 598 G4double& 614 G4double& dchord_step, 599 G4double& 615 G4double& dyerr_pos_sq, 600 G4double& 616 G4double& dyerr_mom_rel_sq ) 601 { 617 { 602 G4Exception("G4MagInt_Driver::QuickAdvance() 618 G4Exception("G4MagInt_Driver::QuickAdvance()", "GeomField0001", 603 FatalException, "Not yet impleme 619 FatalException, "Not yet implemented."); 604 620 605 // Use the parameters of this method, to ple 621 // Use the parameters of this method, to please compiler 606 // 622 // 607 dchord_step = dyerr_pos_sq = hstep * hstep * 623 dchord_step = dyerr_pos_sq = hstep * hstep * dydx[0]; 608 dyerr_mom_rel_sq = y_posvel.GetPosition().ma 624 dyerr_mom_rel_sq = y_posvel.GetPosition().mag2(); 609 return true; 625 return true; 610 } 626 } 611 627 612 //-------------------------------------------- 628 //---------------------------------------------------------------------- 613 629 614 G4bool G4MagInt_Driver::QuickAdvance(G4FieldTr 630 G4bool G4MagInt_Driver::QuickAdvance(G4FieldTrack& y_posvel, // INOUT 615 const G4double 631 const G4double dydx[], 616 G4double 632 G4double hstep, // In 617 G4double& 633 G4double& dchord_step, 618 G4double& 634 G4double& dyerr ) 619 { 635 { 620 G4double dyerr_pos_sq, dyerr_mom_rel_sq; 636 G4double dyerr_pos_sq, dyerr_mom_rel_sq; 621 G4double yerr_vec[G4FieldTrack::ncompSVEC], 637 G4double yerr_vec[G4FieldTrack::ncompSVEC], 622 yarrin[G4FieldTrack::ncompSVEC], ya 638 yarrin[G4FieldTrack::ncompSVEC], yarrout[G4FieldTrack::ncompSVEC]; 623 G4double s_start; 639 G4double s_start; 624 G4double dyerr_mom_sq, vel_mag_sq, inv_vel_m 640 G4double dyerr_mom_sq, vel_mag_sq, inv_vel_mag_sq; 625 641 >> 642 static G4ThreadLocal G4int no_call = 0; >> 643 ++no_call; >> 644 626 // Move data into array 645 // Move data into array 627 y_posvel.DumpToArray( yarrin ); // yar 646 y_posvel.DumpToArray( yarrin ); // yarrin <== y_posvel 628 s_start = y_posvel.GetCurveLength(); 647 s_start = y_posvel.GetCurveLength(); 629 648 630 // Do an Integration Step 649 // Do an Integration Step 631 pIntStepper-> Stepper(yarrin, dydx, hstep, y 650 pIntStepper-> Stepper(yarrin, dydx, hstep, yarrout, yerr_vec) ; 632 651 633 // Estimate curve-chord distance 652 // Estimate curve-chord distance 634 dchord_step= pIntStepper-> DistChord(); 653 dchord_step= pIntStepper-> DistChord(); 635 654 636 // Put back the values. yarrout ==> y_posve 655 // Put back the values. yarrout ==> y_posvel 637 y_posvel.LoadFromArray( yarrout, fNoIntegrat 656 y_posvel.LoadFromArray( yarrout, fNoIntegrationVariables ); 638 y_posvel.SetCurveLength( s_start + hstep ); 657 y_posvel.SetCurveLength( s_start + hstep ); 639 658 640 #ifdef G4DEBUG_FIELD 659 #ifdef G4DEBUG_FIELD 641 if(fVerboseLevel>2) 660 if(fVerboseLevel>2) 642 { 661 { 643 G4cout << "G4MagIntDrv: Quick Advance" << 662 G4cout << "G4MagIntDrv: Quick Advance" << G4endl; 644 PrintStatus( yarrin, s_start, yarrout, s_s 663 PrintStatus( yarrin, s_start, yarrout, s_start+hstep, hstep, 1); 645 } 664 } 646 #endif 665 #endif 647 666 648 // A single measure of the error 667 // A single measure of the error 649 // TO-DO : account for energy, spin, 668 // TO-DO : account for energy, spin, ... ? 650 vel_mag_sq = ( sqr(yarrout[3])+sqr(yarrout 669 vel_mag_sq = ( sqr(yarrout[3])+sqr(yarrout[4])+sqr(yarrout[5]) ); 651 inv_vel_mag_sq = 1.0 / vel_mag_sq; 670 inv_vel_mag_sq = 1.0 / vel_mag_sq; 652 dyerr_pos_sq = ( sqr(yerr_vec[0])+sqr(yerr_v 671 dyerr_pos_sq = ( sqr(yerr_vec[0])+sqr(yerr_vec[1])+sqr(yerr_vec[2])); 653 dyerr_mom_sq = ( sqr(yerr_vec[3])+sqr(yerr_v 672 dyerr_mom_sq = ( sqr(yerr_vec[3])+sqr(yerr_vec[4])+sqr(yerr_vec[5])); 654 dyerr_mom_rel_sq = dyerr_mom_sq * inv_vel_ma 673 dyerr_mom_rel_sq = dyerr_mom_sq * inv_vel_mag_sq; 655 674 656 // Calculate also the change in the momentum 675 // Calculate also the change in the momentum squared also ??? 657 // G4double veloc_square = y_posvel.GetVeloc 676 // G4double veloc_square = y_posvel.GetVelocity().mag2(); 658 // ... 677 // ... 659 678 660 #ifdef RETURN_A_NEW_STEP_LENGTH 679 #ifdef RETURN_A_NEW_STEP_LENGTH 661 // The following step cannot be done here be 680 // The following step cannot be done here because "eps" is not known. 662 dyerr_len = std::sqrt( dyerr_len_sq ); 681 dyerr_len = std::sqrt( dyerr_len_sq ); 663 dyerr_len_sq /= eps ; 682 dyerr_len_sq /= eps ; 664 683 665 // Look at the velocity deviation ? 684 // Look at the velocity deviation ? 666 // sqr(yerr_vec[3])+sqr(yerr_vec[4])+sqr(ye 685 // sqr(yerr_vec[3])+sqr(yerr_vec[4])+sqr(yerr_vec[5])); 667 686 668 // Set suggested new step 687 // Set suggested new step 669 hstep = ComputeNewStepSize( dyerr_len, hstep 688 hstep = ComputeNewStepSize( dyerr_len, hstep); 670 #endif 689 #endif 671 690 672 if( dyerr_pos_sq > ( dyerr_mom_rel_sq * sqr( 691 if( dyerr_pos_sq > ( dyerr_mom_rel_sq * sqr(hstep) ) ) 673 { 692 { 674 dyerr = std::sqrt(dyerr_pos_sq); 693 dyerr = std::sqrt(dyerr_pos_sq); 675 } 694 } 676 else 695 else 677 { 696 { 678 // Scale it to the current step size - for 697 // Scale it to the current step size - for now 679 dyerr = std::sqrt(dyerr_mom_rel_sq) * hste 698 dyerr = std::sqrt(dyerr_mom_rel_sq) * hstep; 680 } 699 } 681 700 682 return true; 701 return true; 683 } 702 } 684 703 685 // ------------------------------------------- 704 // -------------------------------------------------------------------------- 686 705 687 #ifdef QUICK_ADV_ARRAY_IN_AND_OUT 706 #ifdef QUICK_ADV_ARRAY_IN_AND_OUT 688 G4bool G4MagInt_Driver::QuickAdvance(G4double 707 G4bool G4MagInt_Driver::QuickAdvance(G4double yarrin[], // In 689 const G4double 708 const G4double dydx[], 690 G4double 709 G4double hstep, // In 691 G4double 710 G4double yarrout[], 692 G4double 711 G4double& dchord_step, 693 G4double 712 G4double& dyerr ) // In length 694 { 713 { 695 G4Exception("G4MagInt_Driver::QuickAdvance() 714 G4Exception("G4MagInt_Driver::QuickAdvance()", "GeomField0001", 696 FatalException, "Not yet impleme 715 FatalException, "Not yet implemented."); 697 dyerr = dchord_step = hstep * yarrin[0] * dy 716 dyerr = dchord_step = hstep * yarrin[0] * dydx[0]; 698 yarrout[0]= yarrin[0]; 717 yarrout[0]= yarrin[0]; 699 } 718 } 700 #endif 719 #endif 701 720 702 // ------------------------------------------- 721 // -------------------------------------------------------------------------- 703 722 704 // This method computes new step sizes - but d 723 // This method computes new step sizes - but does not limit changes to 705 // within certain factors 724 // within certain factors 706 // 725 // 707 G4double G4MagInt_Driver:: 726 G4double G4MagInt_Driver:: 708 ComputeNewStepSize_WithoutReductionLimit(G4dou 727 ComputeNewStepSize_WithoutReductionLimit(G4double errMaxNorm, // max error (normalised) 709 G4double hstepCurrent) // 728 G4double hstepCurrent) // current step size 710 { 729 { 711 G4double hnew; 730 G4double hnew; 712 731 713 // Compute size of next Step for a failed st 732 // Compute size of next Step for a failed step 714 if(errMaxNorm > 1.0 ) 733 if(errMaxNorm > 1.0 ) 715 { 734 { 716 // Step failed; compute the size of retria 735 // Step failed; compute the size of retrial Step. 717 hnew = GetSafety()*hstepCurrent*std::pow(e 736 hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPshrnk()) ; 718 } 737 } 719 else if(errMaxNorm > 0.0 ) 738 else if(errMaxNorm > 0.0 ) 720 { 739 { 721 // Compute size of next Step for a success 740 // Compute size of next Step for a successful step 722 hnew = GetSafety()*hstepCurrent*std::pow(e 741 hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPgrow()) ; 723 } 742 } 724 else 743 else 725 { 744 { 726 // if error estimate is zero (possible) or 745 // if error estimate is zero (possible) or negative (dubious) 727 hnew = max_stepping_increase * hstepCurren 746 hnew = max_stepping_increase * hstepCurrent; 728 } 747 } 729 748 730 return hnew; 749 return hnew; 731 } 750 } 732 751 733 // ------------------------------------------- 752 // --------------------------------------------------------------------------- 734 753 735 G4double 754 G4double 736 G4MagInt_Driver::ComputeNewStepSize( 755 G4MagInt_Driver::ComputeNewStepSize( 737 G4double errMaxNorm 756 G4double errMaxNorm, // max error (normalised) 738 G4double hstepCurre 757 G4double hstepCurrent) // current step size 739 { 758 { 740 // Legacy behaviour: 759 // Legacy behaviour: 741 return ComputeNewStepSize_WithoutReductionL 760 return ComputeNewStepSize_WithoutReductionLimit( errMaxNorm, hstepCurrent ); 742 // 'Improved' behaviour - at least more con 761 // 'Improved' behaviour - at least more consistent with other step estimates: 743 // return ComputeNewStepSize_WithinLimits( 762 // return ComputeNewStepSize_WithinLimits( errMaxNorm, hstepCurrent ); 744 } 763 } 745 764 746 // This method computes new step sizes limitin 765 // This method computes new step sizes limiting changes within certain factors 747 // 766 // 748 // It shares its logic with AccurateAdvance. 767 // It shares its logic with AccurateAdvance. 749 // They are kept separate currently for optimi 768 // They are kept separate currently for optimisation. 750 // 769 // 751 G4double 770 G4double 752 G4MagInt_Driver::ComputeNewStepSize_WithinLimi 771 G4MagInt_Driver::ComputeNewStepSize_WithinLimits( 753 G4double errMaxNorm 772 G4double errMaxNorm, // max error (normalised) 754 G4double hstepCurre 773 G4double hstepCurrent) // current step size 755 { 774 { 756 G4double hnew; 775 G4double hnew; 757 776 758 // Compute size of next Step for a failed st 777 // Compute size of next Step for a failed step 759 if (errMaxNorm > 1.0 ) 778 if (errMaxNorm > 1.0 ) 760 { 779 { 761 // Step failed; compute the size of retria 780 // Step failed; compute the size of retrial Step. 762 hnew = GetSafety()*hstepCurrent*std::pow(e 781 hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPshrnk()) ; 763 782 764 if (hnew < max_stepping_decrease*hstepCurr 783 if (hnew < max_stepping_decrease*hstepCurrent) 765 { 784 { 766 hnew = max_stepping_decrease*hstepCurren 785 hnew = max_stepping_decrease*hstepCurrent ; 767 // reduce stepsize, b 786 // reduce stepsize, but no more 768 // than this factor ( 787 // than this factor (value= 1/10) 769 } 788 } 770 } 789 } 771 else 790 else 772 { 791 { 773 // Compute size of next Step for a success 792 // Compute size of next Step for a successful step 774 if (errMaxNorm > errcon) 793 if (errMaxNorm > errcon) 775 { hnew = GetSafety()*hstepCurrent*std::po 794 { hnew = GetSafety()*hstepCurrent*std::pow(errMaxNorm,GetPgrow()); } 776 else // No more than a factor of 5 increa 795 else // No more than a factor of 5 increase 777 { hnew = max_stepping_increase * hstepCur 796 { hnew = max_stepping_increase * hstepCurrent; } 778 } 797 } 779 return hnew; 798 return hnew; 780 } 799 } 781 800 782 // ------------------------------------------- 801 // --------------------------------------------------------------------------- 783 802 784 void G4MagInt_Driver::PrintStatus( const G4dou 803 void G4MagInt_Driver::PrintStatus( const G4double* StartArr, 785 G4dou 804 G4double xstart, 786 const G4dou 805 const G4double* CurrentArr, 787 G4dou 806 G4double xcurrent, 788 G4dou 807 G4double requestStep, 789 G4int 808 G4int subStepNo ) 790 // Potentially add as arguments: 809 // Potentially add as arguments: 791 // <dydx> 810 // <dydx> - as Initial Force 792 // stepTaken 811 // stepTaken(hdid) - last step taken 793 // nextStep 812 // nextStep (hnext) - proposal for size 794 { 813 { 795 G4FieldTrack StartFT(G4ThreeVector(0,0,0), 814 G4FieldTrack StartFT(G4ThreeVector(0,0,0), 796 G4ThreeVector(0,0,0), 0., 0., 815 G4ThreeVector(0,0,0), 0., 0., 0., 0. ); 797 G4FieldTrack CurrentFT (StartFT); 816 G4FieldTrack CurrentFT (StartFT); 798 817 799 StartFT.LoadFromArray( StartArr, fNoIntegra 818 StartFT.LoadFromArray( StartArr, fNoIntegrationVariables); 800 StartFT.SetCurveLength( xstart); 819 StartFT.SetCurveLength( xstart); 801 CurrentFT.LoadFromArray( CurrentArr, fNoInt 820 CurrentFT.LoadFromArray( CurrentArr, fNoIntegrationVariables); 802 CurrentFT.SetCurveLength( xcurrent ); 821 CurrentFT.SetCurveLength( xcurrent ); 803 822 804 PrintStatus(StartFT, CurrentFT, requestStep 823 PrintStatus(StartFT, CurrentFT, requestStep, subStepNo ); 805 } 824 } 806 825 807 // ------------------------------------------- 826 // --------------------------------------------------------------------------- 808 827 809 void G4MagInt_Driver::PrintStatus(const G4Fiel 828 void G4MagInt_Driver::PrintStatus(const G4FieldTrack& StartFT, 810 const G4Fiel 829 const G4FieldTrack& CurrentFT, 811 G4doub 830 G4double requestStep, 812 G4int 831 G4int subStepNo) 813 { 832 { 814 G4int verboseLevel= fVerboseLevel; 833 G4int verboseLevel= fVerboseLevel; 815 const G4int noPrecision = 5; 834 const G4int noPrecision = 5; 816 G4long oldPrec= G4cout.precision(noPrecisi << 835 G4int oldPrec= G4cout.precision(noPrecision); 817 // G4cout.setf(ios_base::fixed,ios_base::f 836 // G4cout.setf(ios_base::fixed,ios_base::floatfield); 818 837 819 const G4ThreeVector StartPosition= S 838 const G4ThreeVector StartPosition= StartFT.GetPosition(); 820 const G4ThreeVector StartUnitVelocity= S 839 const G4ThreeVector StartUnitVelocity= StartFT.GetMomentumDir(); 821 const G4ThreeVector CurrentPosition= C 840 const G4ThreeVector CurrentPosition= CurrentFT.GetPosition(); 822 const G4ThreeVector CurrentUnitVelocity= C 841 const G4ThreeVector CurrentUnitVelocity= CurrentFT.GetMomentumDir(); 823 842 824 G4double DotStartCurrentVeloc= StartUnitV 843 G4double DotStartCurrentVeloc= StartUnitVelocity.dot(CurrentUnitVelocity); 825 844 826 G4double step_len= CurrentFT.GetCurveLengt 845 G4double step_len= CurrentFT.GetCurveLength() - StartFT.GetCurveLength(); 827 G4double subStepSize = step_len; 846 G4double subStepSize = step_len; 828 847 829 if( (subStepNo <= 1) || (verboseLevel > 3) 848 if( (subStepNo <= 1) || (verboseLevel > 3) ) 830 { 849 { 831 subStepNo = - subStepNo; // To a 850 subStepNo = - subStepNo; // To allow printing banner 832 851 833 G4cout << std::setw( 6) << " " << std: 852 G4cout << std::setw( 6) << " " << std::setw( 25) 834 << " G4MagInt_Driver: Current Po 853 << " G4MagInt_Driver: Current Position and Direction" << " " 835 << G4endl; 854 << G4endl; 836 G4cout << std::setw( 5) << "Step#" << " 855 G4cout << std::setw( 5) << "Step#" << " " 837 << std::setw( 7) << "s-curve" << 856 << std::setw( 7) << "s-curve" << " " 838 << std::setw( 9) << "X(mm)" << " 857 << std::setw( 9) << "X(mm)" << " " 839 << std::setw( 9) << "Y(mm)" << " 858 << std::setw( 9) << "Y(mm)" << " " 840 << std::setw( 9) << "Z(mm)" << " 859 << std::setw( 9) << "Z(mm)" << " " 841 << std::setw( 8) << " N_x " << " 860 << std::setw( 8) << " N_x " << " " 842 << std::setw( 8) << " N_y " << " 861 << std::setw( 8) << " N_y " << " " 843 << std::setw( 8) << " N_z " << " 862 << std::setw( 8) << " N_z " << " " 844 << std::setw( 8) << " N^2-1 " << 863 << std::setw( 8) << " N^2-1 " << " " 845 << std::setw(10) << " N(0).N " < 864 << std::setw(10) << " N(0).N " << " " 846 << std::setw( 7) << "KinEner " < 865 << std::setw( 7) << "KinEner " << " " 847 << std::setw(12) << "Track-l" << 866 << std::setw(12) << "Track-l" << " " // Add the Sub-step ?? 848 << std::setw(12) << "Step-len" < 867 << std::setw(12) << "Step-len" << " " 849 << std::setw(12) << "Step-len" < 868 << std::setw(12) << "Step-len" << " " 850 << std::setw( 9) << "ReqStep" << 869 << std::setw( 9) << "ReqStep" << " " 851 << G4endl; 870 << G4endl; 852 } 871 } 853 872 854 if( (subStepNo <= 0) ) 873 if( (subStepNo <= 0) ) 855 { 874 { 856 PrintStat_Aux( StartFT, requestStep, 0. 875 PrintStat_Aux( StartFT, requestStep, 0., 857 0, 0.0, 876 0, 0.0, 1.0); 858 } 877 } 859 878 860 if( verboseLevel <= 3 ) 879 if( verboseLevel <= 3 ) 861 { 880 { 862 G4cout.precision(noPrecision); 881 G4cout.precision(noPrecision); 863 PrintStat_Aux( CurrentFT, requestStep, s 882 PrintStat_Aux( CurrentFT, requestStep, step_len, 864 subStepNo, subStepSize, D 883 subStepNo, subStepSize, DotStartCurrentVeloc ); 865 } 884 } 866 885 867 G4cout.precision(oldPrec); 886 G4cout.precision(oldPrec); 868 } 887 } 869 888 870 // ------------------------------------------- 889 // --------------------------------------------------------------------------- 871 890 872 void G4MagInt_Driver::PrintStat_Aux(const G4Fi 891 void G4MagInt_Driver::PrintStat_Aux(const G4FieldTrack& aFieldTrack, 873 G4do 892 G4double requestStep, 874 G4do 893 G4double step_len, 875 G4in 894 G4int subStepNo, 876 G4do 895 G4double subStepSize, 877 G4do 896 G4double dotVeloc_StartCurr) 878 { 897 { 879 const G4ThreeVector Position = aFieldTrack 898 const G4ThreeVector Position = aFieldTrack.GetPosition(); 880 const G4ThreeVector UnitVelocity = aFieldT 899 const G4ThreeVector UnitVelocity = aFieldTrack.GetMomentumDir(); 881 900 882 if( subStepNo >= 0) 901 if( subStepNo >= 0) 883 { 902 { 884 G4cout << std::setw( 5) << subStepNo << 903 G4cout << std::setw( 5) << subStepNo << " "; 885 } 904 } 886 else 905 else 887 { 906 { 888 G4cout << std::setw( 5) << "Start" << " 907 G4cout << std::setw( 5) << "Start" << " "; 889 } 908 } 890 G4double curveLen= aFieldTrack.GetCurveLen 909 G4double curveLen= aFieldTrack.GetCurveLength(); 891 G4cout << std::setw( 7) << curveLen; 910 G4cout << std::setw( 7) << curveLen; 892 G4cout << std::setw( 9) << Position.x() << 911 G4cout << std::setw( 9) << Position.x() << " " 893 << std::setw( 9) << Position.y() << 912 << std::setw( 9) << Position.y() << " " 894 << std::setw( 9) << Position.z() << 913 << std::setw( 9) << Position.z() << " " 895 << std::setw( 8) << UnitVelocity.x( 914 << std::setw( 8) << UnitVelocity.x() << " " 896 << std::setw( 8) << UnitVelocity.y( 915 << std::setw( 8) << UnitVelocity.y() << " " 897 << std::setw( 8) << UnitVelocity.z( 916 << std::setw( 8) << UnitVelocity.z() << " "; 898 G4long oldprec= G4cout.precision(3); << 917 G4int oldprec= G4cout.precision(3); 899 G4cout << std::setw( 8) << UnitVelocity.ma 918 G4cout << std::setw( 8) << UnitVelocity.mag2()-1.0 << " "; 900 G4cout.precision(6); 919 G4cout.precision(6); 901 G4cout << std::setw(10) << dotVeloc_StartC 920 G4cout << std::setw(10) << dotVeloc_StartCurr << " "; 902 G4cout.precision(oldprec); 921 G4cout.precision(oldprec); 903 G4cout << std::setw( 7) << aFieldTrack.Get 922 G4cout << std::setw( 7) << aFieldTrack.GetKineticEnergy(); 904 G4cout << std::setw(12) << step_len << " " 923 G4cout << std::setw(12) << step_len << " "; 905 924 906 static G4ThreadLocal G4double oldCurveLeng 925 static G4ThreadLocal G4double oldCurveLength = 0.0; 907 static G4ThreadLocal G4double oldSubStepLe 926 static G4ThreadLocal G4double oldSubStepLength = 0.0; 908 static G4ThreadLocal G4int oldSubStepNo = 927 static G4ThreadLocal G4int oldSubStepNo = -1; 909 928 910 G4double subStep_len = 0.0; 929 G4double subStep_len = 0.0; 911 if( curveLen > oldCurveLength ) 930 if( curveLen > oldCurveLength ) 912 { 931 { 913 subStep_len= curveLen - oldCurveLength; 932 subStep_len= curveLen - oldCurveLength; 914 } 933 } 915 else if (subStepNo == oldSubStepNo) 934 else if (subStepNo == oldSubStepNo) 916 { 935 { 917 subStep_len= oldSubStepLength; 936 subStep_len= oldSubStepLength; 918 } 937 } 919 oldCurveLength= curveLen; 938 oldCurveLength= curveLen; 920 oldSubStepLength= subStep_len; 939 oldSubStepLength= subStep_len; 921 940 922 G4cout << std::setw(12) << subStep_len << 941 G4cout << std::setw(12) << subStep_len << " "; 923 G4cout << std::setw(12) << subStepSize << 942 G4cout << std::setw(12) << subStepSize << " "; 924 if( requestStep != -1.0 ) 943 if( requestStep != -1.0 ) 925 { 944 { 926 G4cout << std::setw( 9) << requestStep < 945 G4cout << std::setw( 9) << requestStep << " "; 927 } 946 } 928 else 947 else 929 { 948 { 930 G4cout << std::setw( 9) << " InitialSte 949 G4cout << std::setw( 9) << " InitialStep " << " "; 931 } 950 } 932 G4cout << G4endl; 951 G4cout << G4endl; 933 } 952 } 934 953 935 // ------------------------------------------- 954 // --------------------------------------------------------------------------- 936 955 937 void G4MagInt_Driver::PrintStatisticsReport() 956 void G4MagInt_Driver::PrintStatisticsReport() 938 { 957 { 939 G4int noPrecBig = 6; 958 G4int noPrecBig = 6; 940 G4long oldPrec = G4cout.precision(noPrecBig) << 959 G4int oldPrec = G4cout.precision(noPrecBig); 941 960 942 G4cout << "G4MagInt_Driver Statistics of ste 961 G4cout << "G4MagInt_Driver Statistics of steps undertaken. " << G4endl; 943 G4cout << "G4MagInt_Driver: Number of Steps: 962 G4cout << "G4MagInt_Driver: Number of Steps: " 944 << " Total= " << fNoTotalSteps 963 << " Total= " << fNoTotalSteps 945 << " Bad= " << fNoBadSteps 964 << " Bad= " << fNoBadSteps 946 << " Small= " << fNoSmallSteps 965 << " Small= " << fNoSmallSteps 947 << " Non-initial small= " << (fNoSmal 966 << " Non-initial small= " << (fNoSmallSteps-fNoInitialSmallSteps) 948 << G4endl; 967 << G4endl; 949 G4cout.precision(oldPrec); 968 G4cout.precision(oldPrec); 950 } 969 } 951 970 952 // ------------------------------------------- 971 // --------------------------------------------------------------------------- 953 972 954 void G4MagInt_Driver::SetSmallestFraction(G4do 973 void G4MagInt_Driver::SetSmallestFraction(G4double newFraction) 955 { 974 { 956 if( (newFraction > 1.e-16) && (newFraction < 975 if( (newFraction > 1.e-16) && (newFraction < 1e-8) ) 957 { 976 { 958 fSmallestFraction= newFraction; 977 fSmallestFraction= newFraction; 959 } 978 } 960 else 979 else 961 { 980 { 962 std::ostringstream message; 981 std::ostringstream message; 963 message << "Smallest Fraction not changed. 982 message << "Smallest Fraction not changed. " << G4endl 964 << " Proposed value was " << newF 983 << " Proposed value was " << newFraction << G4endl 965 << " Value must be between 1.e-8 984 << " Value must be between 1.e-8 and 1.e-16"; 966 G4Exception("G4MagInt_Driver::SetSmallestF 985 G4Exception("G4MagInt_Driver::SetSmallestFraction()", 967 "GeomField1001", JustWarning, 986 "GeomField1001", JustWarning, message); 968 } 987 } 969 } 988 } 970 989 971 void G4MagInt_Driver:: 990 void G4MagInt_Driver:: 972 GetDerivatives(const G4FieldTrack& y_curr, G4d 991 GetDerivatives(const G4FieldTrack& y_curr, G4double* dydx) const 973 { 992 { 974 G4double ytemp[G4FieldTrack::ncompSVEC]; 993 G4double ytemp[G4FieldTrack::ncompSVEC]; 975 y_curr.DumpToArray(ytemp); 994 y_curr.DumpToArray(ytemp); 976 pIntStepper->RightHandSide(ytemp, dydx); 995 pIntStepper->RightHandSide(ytemp, dydx); 977 // Avoid virtual call for GetStepper 996 // Avoid virtual call for GetStepper 978 // Was: GetStepper()->ComputeRightHandSi 997 // Was: GetStepper()->ComputeRightHandSide(ytemp, dydx); 979 } 998 } 980 999 981 void G4MagInt_Driver::GetDerivatives(const G4F 1000 void G4MagInt_Driver::GetDerivatives(const G4FieldTrack& track, 982 G4double 1001 G4double dydx[], 983 G4double 1002 G4double field[]) const 984 { 1003 { 985 G4double ytemp[G4FieldTrack::ncompSVEC]; 1004 G4double ytemp[G4FieldTrack::ncompSVEC]; 986 track.DumpToArray(ytemp); 1005 track.DumpToArray(ytemp); 987 pIntStepper->RightHandSide(ytemp, dydx, fi 1006 pIntStepper->RightHandSide(ytemp, dydx, field); 988 } 1007 } 989 1008 990 G4EquationOfMotion* G4MagInt_Driver::GetEquati 1009 G4EquationOfMotion* G4MagInt_Driver::GetEquationOfMotion() 991 { 1010 { 992 return pIntStepper->GetEquationOfMotion(); 1011 return pIntStepper->GetEquationOfMotion(); 993 } 1012 } 994 1013 995 void G4MagInt_Driver::SetEquationOfMotion(G4Eq 1014 void G4MagInt_Driver::SetEquationOfMotion(G4EquationOfMotion *equation) 996 { 1015 { 997 pIntStepper->SetEquationOfMotion(equation) 1016 pIntStepper->SetEquationOfMotion(equation); 998 } 1017 } 999 1018 1000 const G4MagIntegratorStepper* G4MagInt_Driver 1019 const G4MagIntegratorStepper* G4MagInt_Driver::GetStepper() const 1001 { 1020 { 1002 return pIntStepper; 1021 return pIntStepper; 1003 } 1022 } 1004 1023 1005 G4MagIntegratorStepper* G4MagInt_Driver::GetS 1024 G4MagIntegratorStepper* G4MagInt_Driver::GetStepper() 1006 { 1025 { 1007 return pIntStepper; 1026 return pIntStepper; 1008 } 1027 } 1009 1028 1010 void G4MagInt_Driver:: 1029 void G4MagInt_Driver:: 1011 RenewStepperAndAdjust(G4MagIntegratorStepper* 1030 RenewStepperAndAdjust(G4MagIntegratorStepper* pItsStepper) 1012 { 1031 { 1013 pIntStepper = pItsStepper; 1032 pIntStepper = pItsStepper; 1014 ReSetParameters(); 1033 ReSetParameters(); 1015 } 1034 } 1016 1035 1017 void G4MagInt_Driver::StreamInfo( std::ostrea 1036 void G4MagInt_Driver::StreamInfo( std::ostream& os ) const 1018 { 1037 { 1019 os << "State of G4MagInt_Driver: " << std 1038 os << "State of G4MagInt_Driver: " << std::endl; 1020 os << " Max number of Steps = " << fMaxN 1039 os << " Max number of Steps = " << fMaxNoSteps 1021 << " (base # = " << fMaxStepBase << 1040 << " (base # = " << fMaxStepBase << " )" << std::endl; 1022 os << " Safety factor = " << safet 1041 os << " Safety factor = " << safety << std::endl; 1023 os << " Power - shrink = " << pshrn 1042 os << " Power - shrink = " << pshrnk << std::endl; 1024 os << " Power - grow = " << pgrow 1043 os << " Power - grow = " << pgrow << std::endl; 1025 os << " threshold (errcon) = " << errco 1044 os << " threshold (errcon) = " << errcon << std::endl; 1026 1045 1027 os << " fMinimumStep = " << fMini 1046 os << " fMinimumStep = " << fMinimumStep << std::endl; 1028 os << " Smallest Fraction = " << fSmal 1047 os << " Smallest Fraction = " << fSmallestFraction << std::endl; 1029 1048 1030 os << " No Integrat Vars = " << fNoIn 1049 os << " No Integrat Vars = " << fNoIntegrationVariables << std::endl; 1031 os << " Min No Vars = " << fMinN 1050 os << " Min No Vars = " << fMinNoVars << std::endl; 1032 os << " Num-Vars = " << fNoVa 1051 os << " Num-Vars = " << fNoVars << std::endl; 1033 1052 1034 os << " verbose level = " << fVerb 1053 os << " verbose level = " << fVerboseLevel << std::endl; 1035 os << " Reintegrates = " << DoesR 1054 os << " Reintegrates = " << DoesReIntegrate() << std::endl; 1036 } 1055 } 1037 1056 1038 void PrintInfo( const G4MagInt_Driver & magDr 1057 void PrintInfo( const G4MagInt_Driver & magDrv, std::ostream& os ) 1039 { 1058 { 1040 os << "State of G4MagInt_Driver: " << std 1059 os << "State of G4MagInt_Driver: " << std::endl; 1041 os << " Max number of Steps = " << magDr 1060 os << " Max number of Steps = " << magDrv.GetMaxNoSteps(); 1042 // << " (base # = " << magDrv.fMaxSt 1061 // << " (base # = " << magDrv.fMaxStepBase << " )" << std::endl; 1043 os << " Safety factor = " << magDr 1062 os << " Safety factor = " << magDrv.GetSafety() << std::endl; 1044 os << " Power - shrink = " << magDr 1063 os << " Power - shrink = " << magDrv.GetPshrnk() << std::endl; 1045 os << " Power - grow = " << magDr 1064 os << " Power - grow = " << magDrv.GetPgrow() << std::endl; 1046 os << " threshold (errcon) = " << magDr 1065 os << " threshold (errcon) = " << magDrv.GetErrcon() << std::endl; 1047 1066 1048 os << " fMinimumStep = " << magDr 1067 os << " fMinimumStep = " << magDrv.GetHmin() << std::endl; 1049 os << " Smallest Fraction = " << magDr 1068 os << " Smallest Fraction = " << magDrv.GetSmallestFraction() << std::endl; 1050 1069 1051 /***** 1070 /***** 1052 os << " No Integrat Vars = " << magDr 1071 os << " No Integrat Vars = " << magDrv.GetNoIntegrationVariables << std::endl; 1053 os << " Min No Vars = " << magDr 1072 os << " Min No Vars = " << magDrv.GetMinNoVars << std::endl; 1054 os << " Num-Vars = " << magDr 1073 os << " Num-Vars = " << magDrv.GetNoVars << std::endl; 1055 *****/ 1074 *****/ 1056 os << " verbose level = " << magDr 1075 os << " verbose level = " << magDrv.GetVerboseLevel() << std::endl; 1057 os << " Reintegrates = " << magDr 1076 os << " Reintegrates = " << magDrv.DoesReIntegrate() << std::endl; 1058 } 1077 } 1059 1078