ATLAS Offline Software
Loading...
Searching...
No Matches
G4mplAtlasTransportation.cxx
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// GEANT4 tag $Name: geant4-09-03-patch-01 $
28//
29// ------------------------------------------------------------
30// GEANT 4 include file implementation
31//
32// ------------------------------------------------------------
33//
34// This class is a process responsible for the transportation of
35// a particle, ie the geometrical propagation that encounters the
36// geometrical sub-volumes of the detectors.
37//
38// It is also tasked with the key role of proposing the "isotropic safety",
39// which will be used to update the post-step point's safety.
40//
41// =======================================================================
42// Modified:
43//
44// 20 Aug 2013, W. Taylor, J.Apostolakis: Calculate monopole time by
45// integrating over the velocity
46// 19 Sep 2010, S. Burdin (Adopted for ATLAS)
47//
48// 20 Nov 2008, J.Apostolakis: Push safety to helper - after ComputeSafety
49// 9 Nov 2007, J.Apostolakis: Flag for short steps, push safety to helper
50// 19 Jan 2006, P.MoraDeFreitas: Fix for suspended tracks (StartTracking)
51// 11 Aug 2004, M.Asai: Add G4VSensitiveDetector* for updating stepPoint.
52// 21 June 2003, J.Apostolakis: Calling field manager with
53// track, to enable it to configure its accuracy
54// 13 May 2003, J.Apostolakis: Zero field areas now taken into
55// account correclty in all cases (thanks to W Pokorski).
56// 29 June 2001, J.Apostolakis, D.Cote-Ahern, P.Gumplinger:
57// correction for spin tracking
58// 20 Febr 2001, J.Apostolakis: update for new FieldTrack
59// 22 Sept 2000, V.Grichine: update of Kinetic Energy
60// Created: 19 March 1997, J. Apostolakis
61// =======================================================================
62
63// class header
65
66// package headers
67#include "CustomMonopole.h"
68
69// Geant4 headers
70#include "G4ProductionCutsTable.hh"
71#include "G4ParticleTable.hh"
72#include "G4ChordFinder.hh"
73#include "G4SafetyHelper.hh"
74#include "G4FieldManagerStore.hh"
75#include "G4EquationOfMotion.hh"
76#include "G4MagIntegratorDriver.hh"
77#include "G4MagIntegratorStepper.hh"
78#include "G4Version.hh"
79// CLHEP headers
80#include "CLHEP/Units/SystemOfUnits.h"
81#include "CLHEP/Units/PhysicalConstants.h"
82
83class G4VSensitiveDetector;
84
86//
87// Constructor
88
90 : G4VProcess( G4String("mplAtlasTransportation"), fTransportation ),
92 fMomentumChanged( false ),
93 //fEnergyChanged( false ), // Not used?
94 fParticleIsLooping( false ),
95 fCurrentTouchableHandle(), // Points to (G4VTouchable*) 0
96 fGeometryLimitedStep( false ),
97 fPreviousSftOrigin (0.,0.,0.),
98 fPreviousSafety ( 0.0 ),
99 endpointDistance ( 0.0 ),
100 fThreshold_Warning_Energy( 100 * CLHEP::MeV ),
102 fThresholdTrials( 10 ),
103 //fUnimportant_Energy( 1 * CLHEP::MeV ), // Not used?
105 fSumEnergyKilled( 0.0 ), fMaxEnergyKilled( 0.0 ),
106 fShortStepOptimisation(false), // Old default: true (=fast short steps)
107 fVerboseLevel( verboseLevel ),
108 accumLength (0.0)
109{
110
111 mplParticle = mpl;
112
113 G4TransportationManager* transportMgr ;
114
115 G4cout << "!!! G4mplAtlasTransportation constructor " << G4endl;
116
117 transportMgr = G4TransportationManager::GetTransportationManager() ;
118
119 fLinearNavigator = transportMgr->GetNavigatorForTracking() ;
120
121 fFieldPropagator = transportMgr->GetPropagatorInField() ;
122
123 fpSafetyHelper = transportMgr->GetSafetyHelper(); // New
124
125 // Cannot determine whether a field exists here,
126 // because it would only work if the field manager has informed
127 // about the detector's field before this transportation process
128 // is constructed.
129 // Instead later the method DoesGlobalFieldExist() is called
130
131 // Create object which sets up the equation of motion for monopole
132 // or usual matter
133 fEquationSetup= G4mplEquationSetup::GetInstance();
134
137}
138
140
142{
143 G4cout << "!!! G4mplAtlasTransportation destructor " << G4endl;
144
145 if( (fVerboseLevel > 0) && (fSumEnergyKilled > 0.0 ) ){
146 G4cout << " G4mplAtlasTransportation: Statistics for looping particles " << G4endl;
147 G4cout << " Sum of energy of loopers killed: " << fSumEnergyKilled << G4endl;
148 G4cout << " Max energy of loopers killed: " << fMaxEnergyKilled << G4endl;
149 }
150}
151
153//
154// Responsibilities:
155// Find whether the geometry limits the Step, and to what length
156// Calculate the new value of the safety and return it.
157// Store the final time, position and momentum.
158
160AlongStepGetPhysicalInteractionLength( const G4Track& track,
161 G4double, // previousStepSize
162 G4double currentMinimumStep,
163 G4double& currentSafety,
164 G4GPILSelection* selection )
165{
166 G4double geometryStepLength, newSafety ;
167 fParticleIsLooping = false ;
168
169 // Initial actions moved to StartTrack()
170 // --------------------------------------
171 // Note: in case another process changes touchable handle
172 // it will be necessary to add here (for all steps)
173 // fCurrentTouchableHandle = aTrack->GetTouchableHandle();
174
175 // GPILSelection is set to defaule value of CandidateForSelection
176 // It is a return value
177 //
178 *selection = CandidateForSelection ;
179
180 // Get initial Energy/Momentum of the track
181 //
182 const G4DynamicParticle* pParticle = track.GetDynamicParticle() ;
183 const G4ParticleDefinition* pParticleDef = pParticle->GetDefinition() ;
184 const G4ThreeVector& startMomentumDir = pParticle->GetMomentumDirection() ;
185 G4ThreeVector startPosition = track.GetPosition() ;
186
187 // G4double theTime = track.GetGlobalTime() ;
188
189 // The Step Point safety can be limited by other geometries and/or the
190 // assumptions of any process - it's not always the geometrical safety.
191 // We calculate the starting point's isotropic safety here.
192 //
193 G4ThreeVector OriginShift = startPosition - fPreviousSftOrigin ;
194 G4double MagSqShift = OriginShift.mag2() ;
195 if( MagSqShift >= sqr(fPreviousSafety) )
196 {
197 currentSafety = 0.0 ;
198 }
199 else
200 {
201 currentSafety = fPreviousSafety - std::sqrt(MagSqShift) ;
202 }
203
204 // Is the particle charged ?
205 //
206 G4double particleMagCharge = mplParticle->MagneticCharge();
207 G4double particleElCharge = pParticle->GetCharge() ;
208
209// G4cout << "SB: G4mplAtlasTransportation: charge=" << particleCharge
210// << " mass=" << pParticle->GetMass()
211// << " PDG=" << pParticle->GetPDGcode() << G4endl;
212
213 fGeometryLimitedStep = false ;
214 // fEndGlobalTimeComputed = false ;
215
216 // There is no need to locate the current volume. It is Done elsewhere:
217 // On track construction
218 // By the tracking, after all AlongStepDoIts, in "Relocation"
219
220 // Check whether the particle has an (EM) field force exerting upon it
221 //
222 G4FieldManager* fieldMgr=0;
223 G4bool fieldExertsForce = false ;
224 if( (particleElCharge != 0.0) || (particleMagCharge!=0.0) ) // SB
225 {
226 G4FieldManager* oldFieldMgr= fFieldPropagator->GetCurrentFieldManager();
227
228 fieldMgr= fFieldPropagator->FindAndSetFieldManager( track.GetVolume() );
229
230 // if fieldMgr changed, need to flush it's association with our ChordFinder
231 // and then below to update stepper and chord finder
232 if (fieldMgr != oldFieldMgr) {
233 fEquationSetup->ResetIntegration( oldFieldMgr );
234 // Now ensure that it is configured for the new field-manager
235 fEquationSetup->InitialiseForField( fieldMgr );
236 }
237
238 if (fieldMgr != nullptr) {
239 // Message the field Manager, to configure it for this track
240 fieldMgr->ConfigureForTrack( &track );
241 // Moved here, in order to allow a transition
242 // from a zero-field status (with fieldMgr->(field)0
243 // to a finite field status
244
245 if (particleMagCharge!=0.0) fieldMgr->SetFieldChangesEnergy(true);
246
247 // If the field manager has no field, there is no field !
248 fieldExertsForce = (fieldMgr->GetDetectorField() != nullptr);
249
250 if( fieldExertsForce)
251 fEquationSetup->SwitchStepperAndChordFinder( (particleMagCharge != 0.0), fieldMgr );
252 // else ...
253 // Is there extra safety measure to take if the fieldMgr has no field attached ??
254 }
255 // oldFieldMgr= fieldMgr;
256 }
257
258 // Choose the calculation of the transportation: Field or not
259 //
260 if( !fieldExertsForce )
261 {
262 G4double linearStepLength ;
263 if( fShortStepOptimisation && (currentMinimumStep <= currentSafety) )
264 {
265 // The Step is guaranteed to be taken
266 //
267 geometryStepLength = currentMinimumStep ;
268 fGeometryLimitedStep = false ;
269 }
270 else
271 {
272 // Find whether the straight path intersects a volume
273 //
274 linearStepLength = fLinearNavigator->ComputeStep( startPosition,
275 startMomentumDir,
276 currentMinimumStep,
277 newSafety) ;
278 // Remember last safety origin & value.
279 //
280 fPreviousSftOrigin = startPosition ;
281 fPreviousSafety = newSafety ;
282 // fpSafetyHelper->SetCurrentSafety( newSafety, startPosition);
283
284 // The safety at the initial point has been re-calculated:
285 //
286 currentSafety = newSafety ;
287
288 fGeometryLimitedStep= (linearStepLength <= currentMinimumStep);
290 {
291 // The geometry limits the Step size (an intersection was found.)
292 geometryStepLength = linearStepLength ;
293 }
294 else
295 {
296 // The full Step is taken.
297 geometryStepLength = currentMinimumStep ;
298 }
299 }
300 endpointDistance = geometryStepLength ;
301
302 // Calculate final position
303 //
304 fTransportEndPosition = startPosition+geometryStepLength*startMomentumDir ;
305
306 // Momentum direction, energy and polarisation are unchanged by transport
307 //
308 fTransportEndMomentumDir = startMomentumDir ;
309 fTransportEndKineticEnergy = track.GetKineticEnergy() ;
310 fTransportEndSpin = track.GetPolarization();
311 fParticleIsLooping = false ;
312 fMomentumChanged = false ;
313 fEndGlobalTimeComputed = false ;
314 }
315 else // A field exerts force
316 {
317 G4ThreeVector EndUnitMomentum ;
318 G4double lengthAlongCurve ;
319 G4double restMass = pParticleDef->GetPDGMass() ;
320#if G4VERSION_NUMBER > 1009
321 G4double momentumMagnitude = pParticle->GetTotalMomentum();
322 G4ChargeState chargeState(particleElCharge, // in e+ units
323 pParticleDef->GetPDGSpin(),
324 0,
325 0,
326 particleMagCharge); // in e+ units
327 G4EquationOfMotion* equationOfMotion = (fFieldPropagator->GetChordFinder()->GetIntegrationDriver()->GetStepper())->GetEquationOfMotion();
328 equationOfMotion->SetChargeMomentumMass(chargeState,
329 momentumMagnitude,
330 -restMass ); // to distinguish between the monopoles and ordinary particles
331#else
332 fFieldPropagator->SetChargeMomentumMass( particleElCharge, // in e+ units
333 particleMagCharge, // in e+ units
334 -restMass ); // to distinguish between the monopoles and ordinary particles
335#endif
336
337 G4ThreeVector spin = track.GetPolarization() ;
338 G4FieldTrack aFieldTrack = G4FieldTrack( startPosition,
339 track.GetMomentumDirection(),
340 0.0,
341 track.GetKineticEnergy(),
342 restMass,
343 track.GetVelocity(),
344 track.GetGlobalTime(), // Lab.
345 track.GetProperTime(), // Part.
346 &spin ) ;
347 if( currentMinimumStep > 0 )
348 {
349 // Do the Transport in the field (non recti-linear)
350 //
351
352 lengthAlongCurve = fFieldPropagator->ComputeStep( aFieldTrack,
353 currentMinimumStep,
354 currentSafety,
355 track.GetVolume() ) ;
356 fGeometryLimitedStep= lengthAlongCurve < currentMinimumStep;
358 geometryStepLength = lengthAlongCurve ;
359 } else {
360 geometryStepLength = currentMinimumStep ;
361 }
362 }
363 else
364 {
365 geometryStepLength = lengthAlongCurve= 0.0 ;
366 fGeometryLimitedStep = false ;
367 }
368 accumLength += lengthAlongCurve;
369
370 // Remember last safety origin & value.
371 //
372 fPreviousSftOrigin = startPosition ;
373
374 fPreviousSafety = currentSafety ;
375 // fpSafetyHelper->SetCurrentSafety( newSafety, startPosition);
376
377 // Get the End-Position and End-Momentum (Dir-ection)
378 //
379 fTransportEndPosition = aFieldTrack.GetPosition() ;
380
381 // Momentum: Magnitude and direction can be changed too now ...
382 //
383 fMomentumChanged = true ;
384 fTransportEndMomentumDir = aFieldTrack.GetMomentumDir() ;
385
386 fTransportEndKineticEnergy = aFieldTrack.GetKineticEnergy() ;
387
388 if( fFieldPropagator->GetCurrentFieldManager()->DoesFieldChangeEnergy())
389 {
390 // If the field can change energy, then the time must be integrated
391 // - so this should have been updated
392 //
393 fCandidateEndGlobalTime = aFieldTrack.GetLabTimeOfFlight();
395
396 // was ( fCandidateEndGlobalTime != track.GetGlobalTime() );
397 // a cleaner way is to have FieldTrack knowing whether time is updated.
398 }
399 else
400 { // The energy should be unchanged by field transport,
401 // - so the time changed will be calculated elsewhere
402 //
404
405 // Check that the integration preserved the energy
406 // - and if not correct this!
407 G4double startEnergy= track.GetKineticEnergy();
408 G4double endEnergy= fTransportEndKineticEnergy;
409
410 static std::atomic<G4int> no_inexact_steps=0, no_large_ediff;
411 G4double absEdiff = std::fabs(startEnergy- endEnergy);
412 if( absEdiff > CLHEP::perMillion * endEnergy )
413 {
414 no_inexact_steps++;
415 // Possible statistics keeping here ...
416 }
417 if( fVerboseLevel > 1 )
418 {
419 if( std::fabs(startEnergy- endEnergy) > CLHEP::perThousand * endEnergy )
420 {
421 static std::atomic<G4int> no_warnings= 0, warnModulo=1, moduloFactor= 10;
422 no_large_ediff ++;
423 if( (no_large_ediff% warnModulo) == 0 )
424 {
425 no_warnings++;
426 G4cout << "WARNING - G4mplAtlasTransportation::AlongStepGetPIL() "
427 << " Energy change in Step is above 1^-3 relative value. " << G4endl
428 << " Relative change in 'tracking' step = "
429 << std::setw(15) << (endEnergy-startEnergy)/startEnergy << G4endl
430 << " Starting E= " << std::setw(12) << startEnergy / CLHEP::MeV << " MeV " << G4endl
431 << " Ending E= " << std::setw(12) << endEnergy / CLHEP::MeV << " MeV " << G4endl;
432 G4cout << " Energy has been corrected -- however, review"
433 << " field propagation parameters for accuracy." << G4endl;
434 if( (fVerboseLevel > 2 ) || (no_warnings<4) || (no_large_ediff == warnModulo * moduloFactor) ){
435 G4cout << " These include EpsilonStepMax(/Min) in G4FieldManager "
436 << " which determine fractional error per step for integrated quantities. " << G4endl
437 << " Note also the influence of the permitted number of integration steps."
438 << G4endl;
439 }
440 G4cerr << "ERROR - G4mplAtlasTransportation::AlongStepGetPIL()" << G4endl
441 << " Bad 'endpoint'. Energy change detected"
442 << " and corrected. "
443 << " Has occurred already "
444 << no_large_ediff << " times." << G4endl;
445 if( no_large_ediff == warnModulo * moduloFactor )
446 {
447 warnModulo = warnModulo * moduloFactor;
448 }
449 }
450 }
451 } // end of if (fVerboseLevel)
452
453 // Correct the energy for fields that conserve it
454 // This - hides the integration error
455 // - but gives a better physical answer
456 fTransportEndKineticEnergy= track.GetKineticEnergy();
457 }
458
459 fTransportEndSpin = aFieldTrack.GetSpin();
460 fParticleIsLooping = fFieldPropagator->IsParticleLooping() ;
461 endpointDistance = (fTransportEndPosition - startPosition).mag() ;
462
463 fieldMgr->SetFieldChangesEnergy(false);
464
465 }
466
467 // If we are asked to go a step length of 0, and we are on a boundary
468 // then a boundary will also limit the step -> we must flag this.
469 //
470 if( currentMinimumStep == 0.0 )
471 {
472 if( currentSafety == 0.0 ) fGeometryLimitedStep = true ;
473 }
474
475 // Update the safety starting from the end-point,
476 // if it will become negative at the end-point.
477 //
478 if( currentSafety < endpointDistance )
479 {
480 // if( particleCharge == 0.0 )
481 // G4cout << " Avoiding call to ComputeSafety : charge = 0.0 " << G4endl;
482
483// if( particleCharge != 0.0 ) {
484
485 G4double endSafety =
486 fLinearNavigator->ComputeSafety( fTransportEndPosition) ;
487 currentSafety = endSafety ;
489 fPreviousSafety = currentSafety ;
490 fpSafetyHelper->SetCurrentSafety( currentSafety, fTransportEndPosition);
491
492 // Because the Stepping Manager assumes it is from the start point,
493 // add the StepLength
494 //
495 currentSafety += endpointDistance ;
496
497#ifdef G4DEBUG_TRANSPORT
498 G4cout.precision(12) ;
499 G4cout << "***G4mplAtlasTransportation::AlongStepGPIL ** " << G4endl ;
500 G4cout << " Called Navigator->ComputeSafety at " << fTransportEndPosition
501 << " and it returned safety= " << endSafety << G4endl ;
502 G4cout << " Adding endpoint distance " << endpointDistance
503 << " to obtain pseudo-safety= " << currentSafety << G4endl ;
504#endif
505// }
506 }
507
508 // if (accumLength > 10.0){
509 if (accumLength > 1.0){
510 // if (fCandidateEndGlobalTime > 7.5){
511 // G4cout<<fCandidateEndGlobalTime<<" "
512
513// to<<fCandidateEndGlobalTime<<" "
514// <<fTransportEndKineticEnergy<<" "
515// << startPosition[0]<< " "
516// << startPosition[1] << " "
517// << startPosition[2] << " "
518// <<fTransportEndMomentumDir[0]<<" "
519// <<fTransportEndMomentumDir[1]<<" "
520// <<fTransportEndMomentumDir[2]<<" "
521// << fTransportEndPosition[0]<< " "
522// << fTransportEndPosition[1] << " "
523// << fTransportEndPosition[2] << " "
524// << (track.GetVolume())->GetName()
525// << std::endl;
526 // << G4endl;
527
528 accumLength = 0.0;
529 }
530 fParticleChange.ProposeTrueStepLength(geometryStepLength) ;
531
532 return geometryStepLength ;
533}
534
536//
537// Initialize ParticleChange (by setting all its members equal
538// to corresponding members in G4Track)
539
540G4VParticleChange* G4mplAtlasTransportation::AlongStepDoIt( const G4Track& track,
541 const G4Step& stepData )
542{
543#ifdef G4VERBOSE
544 static std::atomic<G4int> noCalls=0;
545 noCalls++;
546#endif
547
548 static const G4ParticleDefinition* const fOpticalPhoton =
549 G4ParticleTable::GetParticleTable()->FindParticle("opticalphoton");
550
551 // G4cout << "SB: G4mplAtlasTransportation: AlongStepDoIt" << G4endl;
552
553 fParticleChange.Initialize(track) ;
554
555 // Code for specific process
556 //
557 fParticleChange.ProposePosition(fTransportEndPosition) ;
558 fParticleChange.ProposeMomentumDirection(fTransportEndMomentumDir) ;
560 fParticleChange.SetMomentumChanged(fMomentumChanged) ;
561
562 fParticleChange.ProposePolarization(fTransportEndSpin);
563
564 G4double deltaTime = 0.0 ;
565
566 // Calculate Lab Time of Flight (ONLY if field Equations used it!)
567 // G4double endTime = fCandidateEndGlobalTime;
568 // G4double delta_time = endTime - startTime;
569
570 G4double startTime = track.GetGlobalTime() ;
571// G4cout << "SB: G4mplAtlasTransportation: startTime=" << startTime
572// <<" fEndGlobalTimeComputed="<< fEndGlobalTimeComputed
573// <<" fCandidateEndGlobalTime="<< fCandidateEndGlobalTime
574// << G4endl;
575
577 {
578 // The time was not integrated .. make the best estimate possible
579 //
580 G4double finalVelocity = track.GetVelocity() ;
581 G4double initialVelocity = stepData.GetPreStepPoint()->GetVelocity() ;
582 G4double stepLength = track.GetStepLength() ;
583
584 deltaTime= 0.0; // in case initialVelocity = 0
585 const G4DynamicParticle* fpDynamicParticle = track.GetDynamicParticle();
586 if (fpDynamicParticle->GetDefinition()== fOpticalPhoton)
587 {
588 // A photon is in the medium of the final point
589 // during the step, so it has the final velocity.
590 deltaTime = stepLength/finalVelocity ;
591 }
592 else if (finalVelocity > 0.0)
593 {
594 G4double meanInverseVelocity ;
595 // deltaTime = stepLength/finalVelocity ;
596 meanInverseVelocity = 0.5
597 * ( 1.0 / initialVelocity + 1.0 / finalVelocity ) ;
598 deltaTime = stepLength * meanInverseVelocity ;
599 }
600 else if( initialVelocity > 0.0 )
601 {
602 deltaTime = stepLength/initialVelocity ;
603 }
604 fCandidateEndGlobalTime = startTime + deltaTime ;
605 }
606 else
607 {
608 deltaTime = fCandidateEndGlobalTime - startTime ;
609 }
610
611 fParticleChange.ProposeGlobalTime( fCandidateEndGlobalTime ) ;
612
613 // Now Correct by Lorentz factor to get "proper" deltaTime
614
615 G4double restMass = track.GetDynamicParticle()->GetMass() ;
616 G4double deltaProperTime = deltaTime*( restMass/track.GetTotalEnergy() ) ;
617
618// G4cout << "SB: G4mplAtlasTransportation: deltaTime=" << deltaTime
619// <<" deltaProperTime="<< deltaProperTime
620// <<" fCandidateEndGlobalTime="<< fCandidateEndGlobalTime
621// <<" fParticleIsLooping="<< fParticleIsLooping
622// << G4endl;
623
624 fParticleChange.ProposeProperTime(track.GetProperTime() + deltaProperTime) ;
625 //fParticleChange. ProposeTrueStepLength( track.GetStepLength() ) ;
626
627 // If the particle is caught looping or is stuck (in very difficult
628 // boundaries) in a magnetic field (doing many steps)
629 // THEN this kills it ...
630 //
631// fParticleIsLooping = true;
632
633 if ( fParticleIsLooping )
634 {
635 G4double endEnergy= fTransportEndKineticEnergy;
636
637 if( (endEnergy < fThreshold_Important_Energy)
639 // Kill the looping particle
640 //
641 fParticleChange.ProposeTrackStatus( fStopAndKill ) ;
642
643 // 'Bare' statistics
644 fSumEnergyKilled += endEnergy;
645 if( endEnergy > fMaxEnergyKilled) { fMaxEnergyKilled= endEnergy; }
646
647#ifdef G4VERBOSE
648 if( (fVerboseLevel > 1) ||
649 ( endEnergy > fThreshold_Warning_Energy ) ) {
650 G4cout << " G4mplAtlasTransportation is killing track that is looping or stuck "
651 << G4endl
652 << " This track has " << track.GetKineticEnergy() / CLHEP::MeV
653 << " MeV energy." << G4endl;
654 G4cout << " Number of trials = " << fNoLooperTrials
655 << " No of calls to AlongStepDoIt = " << noCalls
656 << G4endl;
657 }
658#endif
660 }
661 else{
663#ifdef G4VERBOSE
664 if( (fVerboseLevel > 2) ){
665 G4cout << " G4mplAtlasTransportation::AlongStepDoIt(): Particle looping - "
666 << " Number of trials = " << fNoLooperTrials
667 << " No of calls to = " << noCalls
668 << G4endl;
669 }
670#endif
671 }
672 }else{
674 }
675
676 // Another (sometimes better way) is to use a user-limit maximum Step size
677 // to alleviate this problem ..
678
679 // Introduce smooth curved trajectories to particle-change
680 //
681 fParticleChange.SetPointerToVectorOfAuxiliaryPoints
682 (fFieldPropagator->GimmeTrajectoryVectorAndForgetIt() );
683
684 if (track.GetStepLength() < 0){ // Issue with interpolation in Geant4 range table can cause negative step lengths specifically for dyons
685 fParticleChange.ProposeTrackStatus( fStopAndKill ) ; // to avoid crash, kill particle before this happens since negative step length has no physical meaning
686 G4cout << "Warning HIP Killed due to negative step length" << G4endl;
687 }
688 return &fParticleChange ;
689}
690
692//
693// This ensures that the PostStep action is always called,
694// so that it can do the relocation if it is needed.
695//
696
699 G4double, // previousStepSize
700 G4ForceCondition* pForceCond )
701{
702 *pForceCond = Forced ;
703 return DBL_MAX ; // was kInfinity ; but convention now is DBL_MAX
704}
705
707//
708
709G4VParticleChange* G4mplAtlasTransportation::PostStepDoIt( const G4Track& track,
710 const G4Step& )
711{
712 G4TouchableHandle retCurrentTouchable ; // The one to return
713
714 // G4cout << "SB: G4mplAtlasTransportation: PostStepDoIt" << G4endl;
715
716
717 // Initialize ParticleChange (by setting all its members equal
718 // to corresponding members in G4Track)
719 // fParticleChange.Initialize(track) ; // To initialise TouchableChange
720
721 fParticleChange.ProposeTrackStatus(track.GetTrackStatus()) ;
722
723 // If the Step was determined by the volume boundary,
724 // logically relocate the particle
725
727 {
728 // fCurrentTouchable will now become the previous touchable,
729 // and what was the previous will be freed.
730 // (Needed because the preStepPoint can point to the previous touchable)
731
732 fLinearNavigator->SetGeometricallyLimitedStep() ;
734 LocateGlobalPointAndUpdateTouchableHandle( track.GetPosition(),
735 track.GetMomentumDirection(),
737 true ) ;
738 // Check whether the particle is out of the world volume
739 // If so it has exited and must be killed.
740 //
741 if( fCurrentTouchableHandle->GetVolume() == 0 )
742 {
743 fParticleChange.ProposeTrackStatus( fStopAndKill ) ;
744 }
745 retCurrentTouchable = fCurrentTouchableHandle ;
746 fParticleChange.SetTouchableHandle( fCurrentTouchableHandle ) ;
747 }
748 else // fGeometryLimitedStep is false
749 {
750 // This serves only to move the Navigator's location
751 //
752 fLinearNavigator->LocateGlobalPointWithinVolume( track.GetPosition() ) ;
753
754 // The value of the track's current Touchable is retained.
755 // (and it must be correct because we must use it below to
756 // overwrite the (unset) one in particle change)
757 // It must be fCurrentTouchable too ??
758 //
759 fParticleChange.SetTouchableHandle( track.GetTouchableHandle() ) ;
760 retCurrentTouchable = track.GetTouchableHandle() ;
761 } // endif ( fGeometryLimitedStep )
762
763 const G4VPhysicalVolume* pNewVol = retCurrentTouchable->GetVolume() ;
764 G4Material* pNewMaterial = 0 ;
765 G4VSensitiveDetector* pNewSensitiveDetector = 0 ;
766
767 if( pNewVol != 0 )
768 {
769 pNewMaterial= pNewVol->GetLogicalVolume()->GetMaterial();
770 pNewSensitiveDetector= pNewVol->GetLogicalVolume()->GetSensitiveDetector();
771 }
772
773 // ( <const_cast> pNewMaterial ) ;
774 // ( <const_cast> pNewSensitiveDetector) ;
775
776 fParticleChange.SetMaterialInTouchable( pNewMaterial ) ;
777 fParticleChange.SetSensitiveDetectorInTouchable( pNewSensitiveDetector ) ;
778
779 const G4MaterialCutsCouple* pNewMaterialCutsCouple = 0;
780 if( pNewVol != 0 )
781 {
782 pNewMaterialCutsCouple=pNewVol->GetLogicalVolume()->GetMaterialCutsCouple();
783 }
784
785 if( pNewVol!=0 && pNewMaterialCutsCouple!=0 && pNewMaterialCutsCouple->GetMaterial()!=pNewMaterial )
786 {
787 // for parametrized volume
788 //
789 pNewMaterialCutsCouple =
790 G4ProductionCutsTable::GetProductionCutsTable()
791 ->GetMaterialCutsCouple(pNewMaterial,
792 pNewMaterialCutsCouple->GetProductionCuts());
793 }
794 fParticleChange.SetMaterialCutsCoupleInTouchable( pNewMaterialCutsCouple );
795
796 // temporarily until Get/Set Material of ParticleChange,
797 // and StepPoint can be made const.
798 // Set the touchable in ParticleChange
799 // this must always be done because the particle change always
800 // uses this value to overwrite the current touchable pointer.
801 //
802 fParticleChange.SetTouchableHandle(retCurrentTouchable) ;
803
804 return &fParticleChange ;
805}
806
807// New method takes over the responsibility to reset the state of G4mplAtlasTransportation
808// object at the start of a new track or the resumption of a suspended track.
809
810void
812{
813 G4VProcess::StartTracking(aTrack);
814
815 // G4cout << "SB: G4mplAtlasTransportation: StartTracking" << G4endl;
816
817 // reset safety value and center
818 //
819 fPreviousSafety = 0.0 ;
820 fPreviousSftOrigin = G4ThreeVector(0.,0.,0.) ;
821
822 // reset looping counter -- for motion in field
824 // Must clear this state .. else it depends on last track's value
825 // --> a better solution would set this from state of suspended track TODO ?
826 // Was if( aTrack->GetCurrentStepNumber()==1 ) { .. }
827
828 // ChordFinder reset internal state
829 //
830 if( DoesGlobalFieldExist() ) {
831 fFieldPropagator->ClearPropagatorState();
832 // Resets all state of field propagator class (ONLY)
833 // including safety values (in case of overlaps and to wipe for first track).
834
835 // G4ChordFinder* chordF= fFieldPropagator->GetChordFinder();
836 // if( chordF ) chordF->ResetStepEstimate();
837 }
838
839 // Make sure to clear the chord finders of all fields (ie managers)
840 G4FieldManagerStore::GetInstance()->ClearAllChordFindersState();
841
842 // Set up the Field Propagation to integrate time in case of magnetic charge
843 G4double particleMagCharge = mplParticle->MagneticCharge();
844
845 // To be certain that equations etc are created *after* the field managers (global + other/s)
846 // are constructed and registered, we initialise here.
847 G4FieldManager* fieldMgr= fFieldPropagator->GetCurrentFieldManager();
848
849 // Set up the equation of motion for monopole
850 fEquationSetup->InitialiseForField( fieldMgr );
851
852 fEquationSetup->SwitchStepperAndChordFinder( (particleMagCharge != 0.0), fieldMgr );
853 // If local fields exist, this done again for each local field manager,
854 // when the track enters a volume which has it.
855
856 // Update the current touchable handle (from the track's)
857 //
858 fCurrentTouchableHandle = aTrack->GetTouchableHandle();
859}
860
861void
863{
864 G4VProcess::EndTracking();
865 fEquationSetup->ResetIntegration( fFieldPropagator->GetCurrentFieldManager() );
866}
Scalar mag() const
mag method
double spin(const T &p)
Definition AtlasPID.h:1147
#define sqr(t)
G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &stepData)
G4PropagatorInField * fFieldPropagator
G4ParticleChangeForTransport fParticleChange
G4double AlongStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double &currentSafety, G4GPILSelection *selection)
G4double PostStepGetPhysicalInteractionLength(const G4Track &, G4double previousStepSize, G4ForceCondition *pForceCond)
const CustomMonopole * mplParticle
G4mplAtlasTransportation(const CustomMonopole *p, G4int verbosityLevel=1)
G4VParticleChange * AlongStepDoIt(const G4Track &track, const G4Step &stepData)
const std::string selection