Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4ITTransportation.cc
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/// \brief This class is a slightly modified version of G4Transportation
28/// initially written by John Apostolakis and colleagues
29/// But it should use the exact same algorithm
30//
31// Contact : Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr)
32//
33// History :
34// -----------
35// =======================================================================
36// Modified:
37// 28 Oct 2011, P.Gumpl./J.Ap: Detect gravity field, use magnetic moment
38// 20 Nov 2008, J.Apostolakis: Push safety to helper - after ComputeSafety
39// 9 Nov 2007, J.Apostolakis: Flag for short steps, push safety to helper
40// 19 Jan 2006, P.MoraDeFreitas: Fix for suspended tracks (StartTracking)
41// 11 Aug 2004, M.Asai: Add G4VSensitiveDetector* for updating stepPoint.
42// 21 June 2003, J.Apostolakis: Calling field manager with
43// track, to enable it to configure its accuracy
44// 13 May 2003, J.Apostolakis: Zero field areas now taken into
45// account correclty in all cases (thanks to W Pokorski).
46// 29 June 2001, J.Apostolakis, D.Cote-Ahern, P.Gumplinger:
47// correction for spin tracking
48// 20 Febr 2001, J.Apostolakis: update for new FieldTrack
49// 22 Sept 2000, V.Grichine: update of Kinetic Energy
50// ---------------------------------------------------
51// 10 Oct 2011, M.Karamitros: G4ITTransportation created
52// Created: 19 March 1997, J. Apostolakis
53// =======================================================================
54//
55// -------------------------------------------------------------------
56
57#include "G4ITTransportation.hh"
58#include "G4IT.hh"
60#include "G4SystemOfUnits.hh"
64#include "G4ParticleTable.hh"
65#include "G4ITNavigator.hh"
67#include "G4FieldManager.hh"
68#include "G4ChordFinder.hh"
69#include "G4ITSafetyHelper.hh"
71
72#include "G4UnitsTable.hh"
73#include "G4ReferenceCast.hh"
74
76
77#ifndef PrepareState
78#define PrepareState() G4ITTransportationState* __state = this->GetState<G4ITTransportationState>();
79#endif
80
81#ifndef State
82#define State(theXInfo) (__state->theXInfo)
83#endif
84
85//#define DEBUG_MEM
86
87#ifdef DEBUG_MEM
88#include "G4MemStat.hh"
89using namespace G4MemStat;
91#endif
92
93//#define G4DEBUG_TRANSPORT 1
94
97 fThreshold_Warning_Energy(100 * MeV),
98 fThreshold_Important_Energy(250 * MeV),
99 fThresholdTrials(10),
100 fUnimportant_Energy(1 * MeV), // Not used
101 fSumEnergyKilled(0.0),
102 fMaxEnergyKilled(0.0),
103 fShortStepOptimisation(false), // Old default: true (=fast short steps)
104 fVerboseLevel(verbose)
105{
107 G4TransportationManager* transportMgr;
109 G4ITTransportationManager* ITtransportMgr;
111 fLinearNavigator = ITtransportMgr->GetNavigatorForTracking();
112 fFieldPropagator = transportMgr->GetPropagatorInField();
113 fpSafetyHelper = ITtransportMgr->GetSafetyHelper(); // New
114
115 // Cannot determine whether a field exists here, as it would
116 // depend on the relative order of creating the detector's
117 // field and this process. That order is not guaranted.
118 // Instead later the method DoesGlobalFieldExist() is called
119
120 enableAtRestDoIt = false;
121 enableAlongStepDoIt = true;
122 enablePostStepDoIt = true;
126 fInstantiateProcessState = true;
127
129 /*
130 if(fTransportationState == 0)
131 {
132 G4cout << "KILL in G4ITTransportation::G4ITTransportation" << G4endl;
133 abort();
134 }
135 */
136}
137
139 G4VITProcess(right)
140{
141 // Copy attributes
150
151 // Setup Navigators
152 G4TransportationManager* transportMgr;
154 G4ITTransportationManager* ITtransportMgr;
156 fLinearNavigator = ITtransportMgr->GetNavigatorForTracking();
157 fFieldPropagator = transportMgr->GetPropagatorInField();
158 fpSafetyHelper = ITtransportMgr->GetSafetyHelper(); // New
159
160 // Cannot determine whether a field exists here, as it would
161 // depend on the relative order of creating the detector's
162 // field and this process. That order is not guaranted.
163 // Instead later the method DoesGlobalFieldExist() is called
164
165 enableAtRestDoIt = false;
166 enableAlongStepDoIt = true;
167 enablePostStepDoIt = true;
168
172 fInstantiateProcessState = right.fInstantiateProcessState;
173}
174
175G4ITTransportation& G4ITTransportation::operator=(const G4ITTransportation& /*right*/)
176{
177// if (this == &right) return *this;
178 return *this;
179}
180
181//////////////////////////////////////////////////////////////////////////////
182/// Process State
183//////////////////////////////////////////////////////////////////////////////
185 G4ProcessState(), fCurrentTouchableHandle(0)
186{
191 fMomentumChanged = false;
192 fEnergyChanged = false;
195 fParticleIsLooping = false;
196
197 static G4ThreadLocal G4TouchableHandle *nullTouchableHandle = 0;
198 if (!nullTouchableHandle) nullTouchableHandle = new G4TouchableHandle;
199 // Points to (G4VTouchable*) 0
200
201 fCurrentTouchableHandle = *nullTouchableHandle;
202 fGeometryLimitedStep = false;
204 fPreviousSafety = 0.0;
205 fNoLooperTrials = false;
207}
208
210{
211 ;
212}
213
215{
216#ifdef G4VERBOSE
217 if ((fVerboseLevel > 0) && (fSumEnergyKilled > 0.0))
218 {
219 G4cout << " G4ITTransportation: Statistics for looping particles "
220 << G4endl;
221 G4cout << " Sum of energy of loopers killed: "
223 G4cout << " Max energy of loopers killed: "
225 }
226#endif
227}
228
230{
232}
233
235{
236 G4TransportationManager* transportMgr;
238
239 // fFieldExists= transportMgr->GetFieldManager()->DoesFieldExist();
240 // return fFieldExists;
241 return transportMgr->GetFieldManager()->DoesFieldExist();
242}
243
244//////////////////////////////////////////////////////////////////////////
245//
246// Responsibilities:
247// Find whether the geometry limits the Step, and to what length
248// Calculate the new value of the safety and return it.
249// Store the final time, position and momentum.
253 G4double,
254 G4double currentMinimumStep,
255 G4double& currentSafety,
256 G4GPILSelection* selection)
257{
259 G4double geometryStepLength(-1.0), newSafety(-1.0);
260
261 State(fParticleIsLooping) = false;
262 State(fEndGlobalTimeComputed) = false;
263 State(fGeometryLimitedStep) = false;
264
265 // Initial actions moved to StartTrack()
266 // --------------------------------------
267 // Note: in case another process changes touchable handle
268 // it will be necessary to add here (for all steps)
269 // State(fCurrentTouchableHandle) = track.GetTouchableHandle();
270
271 // GPILSelection is set to defaule value of CandidateForSelection
272 // It is a return value
273 //
274 *selection = CandidateForSelection;
275
276 // Get initial Energy/Momentum of the track
277 //
278 const G4DynamicParticle* pParticle = track.GetDynamicParticle();
279// const G4ParticleDefinition* pParticleDef = pParticle->GetDefinition() ;
280 G4ThreeVector startMomentumDir = pParticle->GetMomentumDirection();
281 G4ThreeVector startPosition = track.GetPosition();
282
283 // G4double theTime = track.GetGlobalTime() ;
284
285 // The Step Point safety can be limited by other geometries and/or the
286 // assumptions of any process - it's not always the geometrical safety.
287 // We calculate the starting point's isotropic safety here.
288 //
289 G4ThreeVector OriginShift = startPosition - State(fPreviousSftOrigin);
290 G4double MagSqShift = OriginShift.mag2();
291 if (MagSqShift >= sqr(State(fPreviousSafety)))
292 {
293 currentSafety = 0.0;
294 }
295 else
296 {
297 currentSafety = State(fPreviousSafety) - std::sqrt(MagSqShift);
298 }
299
300 // Is the particle charged ?
301 //
302 G4double particleCharge = pParticle->GetCharge();
303
304 // There is no need to locate the current volume. It is Done elsewhere:
305 // On track construction
306 // By the tracking, after all AlongStepDoIts, in "Relocation"
307
308 // Check whether the particle have an (EM) field force exerting upon it
309 //
310 G4FieldManager* fieldMgr = 0;
311 G4bool fieldExertsForce = false;
312 if ((particleCharge != 0.0))
313 {
315 if (fieldMgr != 0)
316 {
317 // Message the field Manager, to configure it for this track
318 fieldMgr->ConfigureForTrack(&track);
319 // Moved here, in order to allow a transition
320 // from a zero-field status (with fieldMgr->(field)0
321 // to a finite field status
322
323 // If the field manager has no field, there is no field !
324 fieldExertsForce = (fieldMgr->GetDetectorField() != 0);
325 }
326 }
327
328 // G4cout << " G4Transport: field exerts force= " << fieldExertsForce
329 // << " fieldMgr= " << fieldMgr << G4endl;
330
331 // Choose the calculation of the transportation: Field or not
332 //
333 if (!fieldExertsForce)
334 {
335 G4double linearStepLength;
336 if (fShortStepOptimisation && (currentMinimumStep <= currentSafety))
337 {
338 // The Step is guaranteed to be taken
339 //
340 geometryStepLength = currentMinimumStep;
341 State(fGeometryLimitedStep) = false;
342 }
343 else
344 {
345 // Find whether the straight path intersects a volume
346 //
347 // fLinearNavigator->SetNavigatorState(GetIT(track)->GetTrackingInfo()->GetNavigatorState());
348 linearStepLength = fLinearNavigator->ComputeStep(startPosition,
349 startMomentumDir,
350 currentMinimumStep,
351 newSafety);
352
353// G4cout << "linearStepLength : " << G4BestUnit(linearStepLength,"Length")
354// << " | currentMinimumStep: " << currentMinimumStep
355// << " | trackID: " << track.GetTrackID() << G4endl;
356
357 // Remember last safety origin & value.
358 //
359 State(fPreviousSftOrigin) = startPosition;
360 State(fPreviousSafety) = newSafety;
361
362 G4TrackStateManager& trackStateMan = GetIT(track)->GetTrackingInfo()
364 fpSafetyHelper->LoadTrackState(trackStateMan);
365 // fpSafetyHelper->SetTrackState(state);
367 State(fTransportEndPosition));
369
370 // The safety at the initial point has been re-calculated:
371 //
372 currentSafety = newSafety;
373
374 State(fGeometryLimitedStep) = (linearStepLength <= currentMinimumStep);
375 if (State(fGeometryLimitedStep))
376 {
377 // The geometry limits the Step size (an intersection was found.)
378 geometryStepLength = linearStepLength;
379 }
380 else
381 {
382 // The full Step is taken.
383 geometryStepLength = currentMinimumStep;
384 }
385 }
386 State(fEndPointDistance) = geometryStepLength;
387
388 // Calculate final position
389 //
390 State(fTransportEndPosition) = startPosition
391 + geometryStepLength * startMomentumDir;
392
393 // Momentum direction, energy and polarisation are unchanged by transport
394 //
395 State(fTransportEndMomentumDir) = startMomentumDir;
396 State(fTransportEndKineticEnergy) = track.GetKineticEnergy();
397 State(fTransportEndSpin) = track.GetPolarization();
398 State(fParticleIsLooping) = false;
399 State(fMomentumChanged) = false;
400 State(fEndGlobalTimeComputed) = true;
401 State(theInteractionTimeLeft) = State(fEndPointDistance)
402 / track.GetVelocity();
403 State(fCandidateEndGlobalTime) = State(theInteractionTimeLeft)
404 + track.GetGlobalTime();
405/*
406 G4cout << "track.GetVelocity() : "
407 << track.GetVelocity() << G4endl;
408 G4cout << "State(endpointDistance) : "
409 << G4BestUnit(State(endpointDistance),"Length") << G4endl;
410 G4cout << "State(theInteractionTimeLeft) : "
411 << G4BestUnit(State(theInteractionTimeLeft),"Time") << G4endl;
412 G4cout << "track.GetGlobalTime() : "
413 << G4BestUnit(track.GetGlobalTime(),"Time") << G4endl;
414*/
415 }
416 else // A field exerts force
417 {
418
419 G4ExceptionDescription exceptionDescription;
420 exceptionDescription
421 << "ITTransportation does not support external fields.";
422 exceptionDescription
423 << " If you are dealing with a tradiational MC simulation, ";
424 exceptionDescription << "please use G4Transportation.";
425
426 G4Exception("G4ITTransportation::AlongStepGetPhysicalInteractionLength",
427 "NoExternalFieldSupport", FatalException, exceptionDescription);
428 /*
429 G4double momentumMagnitude = pParticle->GetTotalMomentum() ;
430 // G4ThreeVector EndUnitMomentum ;
431 G4double lengthAlongCurve ;
432 G4double restMass = pParticleDef->GetPDGMass() ;
433
434 fFieldPropagator->SetChargeMomentumMass( particleCharge, // in e+ units
435 momentumMagnitude, // in Mev/c
436 restMass ) ;
437
438 G4ThreeVector spin = track.GetPolarization() ;
439 G4FieldTrack aFieldTrack = G4FieldTrack( startPosition,
440 track.GetMomentumDirection(),
441 0.0,
442 track.GetKineticEnergy(),
443 restMass,
444 track.GetVelocity(),
445 track.GetGlobalTime(), // Lab.
446 track.GetProperTime(), // Part.
447 &spin ) ;
448 if( currentMinimumStep > 0 )
449 {
450 // Do the Transport in the field (non recti-linear)
451 //
452 lengthAlongCurve = fFieldPropagator->ComputeStep( aFieldTrack,
453 currentMinimumStep,
454 currentSafety,
455 track.GetVolume() ) ;
456 State(fGeometryLimitedStep)= lengthAlongCurve < currentMinimumStep;
457 if( State(fGeometryLimitedStep) )
458 {
459 geometryStepLength = lengthAlongCurve ;
460 }
461 else
462 {
463 geometryStepLength = currentMinimumStep ;
464 }
465
466 // Remember last safety origin & value.
467 //
468 State(fPreviousSftOrigin) = startPosition ;
469 State(fPreviousSafety) = currentSafety ;
470 fpSafetyHelper->SetCurrentSafety( newSafety, startPosition);
471 }
472 else
473 {
474 geometryStepLength = lengthAlongCurve= 0.0 ;
475 State(fGeometryLimitedStep) = false ;
476 }
477
478 // Get the End-Position and End-Momentum (Dir-ection)
479 //
480 State(fTransportEndPosition) = aFieldTrack.GetPosition() ;
481
482 // Momentum: Magnitude and direction can be changed too now ...
483 //
484 State(fMomentumChanged) = true ;
485 State(fTransportEndMomentumDir) = aFieldTrack.GetMomentumDir() ;
486
487 State(fTransportEndKineticEnergy) = aFieldTrack.GetKineticEnergy() ;
488
489 if( fFieldPropagator->GetCurrentFieldManager()->DoesFieldChangeEnergy() )
490 {
491 // If the field can change energy, then the time must be integrated
492 // - so this should have been updated
493 //
494 State(fCandidateEndGlobalTime) = aFieldTrack.GetLabTimeOfFlight();
495 State(fEndGlobalTimeComputed) = true;
496
497 State(theInteractionTimeLeft) = State(fCandidateEndGlobalTime) -
498 track.GetGlobalTime() ;
499
500 // was ( State(fCandidateEndGlobalTime) != track.GetGlobalTime() );
501 // a cleaner way is to have FieldTrack knowing whether time is updated.
502 }
503 else
504 {
505 // The energy should be unchanged by field transport,
506 // - so the time changed will be calculated elsewhere
507 //
508 State(fEndGlobalTimeComputed) = false;
509
510 // Check that the integration preserved the energy
511 // - and if not correct this!
512 G4double startEnergy= track.GetKineticEnergy();
513 G4double endEnergy= State(fTransportEndKineticEnergy);
514
515 static G4int no_inexact_steps=0, no_large_ediff;
516 G4double absEdiff = std::fabs(startEnergy- endEnergy);
517 if( absEdiff > perMillion * endEnergy )
518 {
519 no_inexact_steps++;
520 // Possible statistics keeping here ...
521 }
522 #ifdef G4VERBOSE
523 if( fVerboseLevel > 1 )
524 {
525 if( std::fabs(startEnergy- endEnergy) > perThousand * endEnergy )
526 {
527 static G4int no_warnings= 0, warnModulo=1, moduloFactor= 10;
528 no_large_ediff ++;
529 if( (no_large_ediff% warnModulo) == 0 )
530 {
531 no_warnings++;
532 G4cout << "WARNING - G4Transportation::AlongStepGetPIL() "
533 << " Energy change in Step is above 1^-3 relative value. " << G4endl
534 << " Relative change in 'tracking' step = "
535 << std::setw(15) << (endEnergy-startEnergy)/startEnergy << G4endl
536 << " Starting E= " << std::setw(12) << startEnergy / MeV << " MeV "
537 << G4endl
538 << " Ending E= " << std::setw(12) << endEnergy / MeV << " MeV "
539 << G4endl;
540 G4cout << " Energy has been corrected -- however, review"
541 << " field propagation parameters for accuracy." << G4endl;
542 if( (fVerboseLevel > 2 ) || (no_warnings<4) ||
543 (no_large_ediff == warnModulo * moduloFactor) )
544 {
545 G4cout << " These include EpsilonStepMax(/Min) in G4FieldManager "
546 << " which determine fractional error per step for integrated quantities. "
547 << G4endl
548 << " Note also the influence of the permitted number of integration steps."
549 << G4endl;
550 }
551 G4cerr << "ERROR - G4Transportation::AlongStepGetPIL()" << G4endl
552 << " Bad 'endpoint'. Energy change detected"
553 << " and corrected. "
554 << " Has occurred already "
555 << no_large_ediff << " times." << G4endl;
556 if( no_large_ediff == warnModulo * moduloFactor )
557 {
558 warnModulo *= moduloFactor;
559 }
560 }
561 }
562 } // end of if (fVerboseLevel)
563 #endif
564 // Correct the energy for fields that conserve it
565 // This - hides the integration error
566 // - but gives a better physical answer
567 State(fTransportEndKineticEnergy)= track.GetKineticEnergy();
568 }
569
570 State(fTransportEndSpin) = aFieldTrack.GetSpin();
571 State(fParticleIsLooping) = fFieldPropagator->IsParticleLooping() ;
572 State(endpointDistance) = (State(fTransportEndPosition) -
573 startPosition).mag() ;
574 // State(theInteractionTimeLeft) =
575 track.GetVelocity()/State(endpointDistance) ;
576 */
577 }
578
579 // If we are asked to go a step length of 0, and we are on a boundary
580 // then a boundary will also limit the step -> we must flag this.
581 //
582 if (currentMinimumStep == 0.0)
583 {
584 if (currentSafety == 0.0)
585 {
586 State(fGeometryLimitedStep) = true;
587// G4cout << "!!!! Safety is NULL, on the Boundary !!!!!" << G4endl;
588// G4cout << " Track position : " << track.GetPosition() /nanometer
589// << G4endl;
590 }
591 }
592
593 // Update the safety starting from the end-point,
594 // if it will become negative at the end-point.
595 //
596 if (currentSafety < State(fEndPointDistance))
597 {
598 // if( particleCharge == 0.0 )
599 // G4cout << " Avoiding call to ComputeSafety : charge = 0.0 " << G4endl;
600
601 if (particleCharge != 0.0)
602 {
603
604 G4double endSafety = fLinearNavigator->ComputeSafety(
605 State(fTransportEndPosition));
606 currentSafety = endSafety;
607 State(fPreviousSftOrigin) = State(fTransportEndPosition);
608 State(fPreviousSafety) = currentSafety;
609
610 /*
611 G4VTrackStateHandle state =
612 GetIT(track)->GetTrackingInfo()->GetTrackState(fpSafetyHelper);
613 */
614 G4TrackStateManager& trackStateMan = GetIT(track)->GetTrackingInfo()
616 fpSafetyHelper->LoadTrackState(trackStateMan);
617 // fpSafetyHelper->SetTrackState(state);
618 fpSafetyHelper->SetCurrentSafety(currentSafety,
619 State(fTransportEndPosition));
621
622 // Because the Stepping Manager assumes it is from the start point,
623 // add the StepLength
624 //
625 currentSafety += State(fEndPointDistance);
626
627#ifdef G4DEBUG_TRANSPORT
628 G4cout.precision(12);
629 G4cout << "***G4Transportation::AlongStepGPIL ** " << G4endl;
630 G4cout << " Called Navigator->ComputeSafety at "
631 << State(fTransportEndPosition)
632 << " and it returned safety= " << endSafety << G4endl;
633 G4cout << " Adding endpoint distance " << State(fEndPointDistance)
634 << " to obtain pseudo-safety= " << currentSafety << G4endl;
635#endif
636 }
637 }
638
639 // fParticleChange.ProposeTrueStepLength(geometryStepLength) ;
640
641// G4cout << "G4ITTransportation::AlongStepGetPhysicalInteractionLength = "
642// << G4BestUnit(geometryStepLength,"Length") << G4endl;
643
644 return geometryStepLength;
645}
646
648 const G4Step& /*step*/,
649 const double timeStep,
650 double& oPhysicalStep)
651{
653 const G4DynamicParticle* pParticle = track.GetDynamicParticle();
654 G4ThreeVector startMomentumDir = pParticle->GetMomentumDirection();
655 G4ThreeVector startPosition = track.GetPosition();
656
657 track.CalculateVelocity();
658 G4double initialVelocity = track.GetVelocity();
659
660 State(fGeometryLimitedStep) = false;
661
662 /////////////////////////
663 // !!! CASE NO FIELD !!!
664 /////////////////////////
665 State(fCandidateEndGlobalTime) = timeStep + track.GetGlobalTime();
666 State(fEndGlobalTimeComputed) = true;
667
668 // Choose the calculation of the transportation: Field or not
669 //
670 if (!State(fMomentumChanged))
671 {
672 // G4cout << "Momentum has not changed" << G4endl;
673 fParticleChange.ProposeVelocity(initialVelocity);
674 oPhysicalStep = initialVelocity * timeStep;
675
676 // Calculate final position
677 //
678 State(fTransportEndPosition) = startPosition
679 + oPhysicalStep * startMomentumDir;
680 }
681}
682
683//////////////////////////////////////////////////////////////////////////
684//
685// Initialize ParticleChange (by setting all its members equal
686// to corresponding members in G4Track)
687#include "G4ParticleTable.hh"
689 const G4Step& stepData)
690{
691
692#if defined (DEBUG_MEM)
693 MemStat mem_first, mem_second, mem_diff;
694#endif
695
696#if defined (DEBUG_MEM)
697 mem_first = MemoryUsage();
698#endif
699
701
702 // G4cout << "G4ITTransportation::AlongStepDoIt" << G4endl;
703 // set pdefOpticalPhoton
704 // Andrea Dotti: the following statement should be in a single line:
705 // G4-MT transformation tools get confused if statement spans two lines
706 // If needed contact: [email protected]
707 static G4ThreadLocal G4ParticleDefinition* pdefOpticalPhoton = 0;
708 if (!pdefOpticalPhoton) pdefOpticalPhoton =
710
711 static G4ThreadLocal G4int noCalls = 0;
712 noCalls++;
713
715
716 // Code for specific process
717 //
718 fParticleChange.ProposePosition(State(fTransportEndPosition));
719 fParticleChange.ProposeMomentumDirection(State(fTransportEndMomentumDir));
720 fParticleChange.ProposeEnergy(State(fTransportEndKineticEnergy));
721 fParticleChange.SetMomentumChanged(State(fMomentumChanged));
722
723 fParticleChange.ProposePolarization(State(fTransportEndSpin));
724
725 G4double deltaTime = 0.0;
726
727 // Calculate Lab Time of Flight (ONLY if field Equations used it!)
728 // G4double endTime = State(fCandidateEndGlobalTime);
729 // G4double delta_time = endTime - startTime;
730
731 G4double startTime = track.GetGlobalTime();
732 ///___________________________________________________________________________
733 /// !!!!!!!
734 /// A REVOIR !!!!
735 if (State(fEndGlobalTimeComputed) == false)
736 {
737 // The time was not integrated .. make the best estimate possible
738 //
739 G4double initialVelocity = stepData.GetPreStepPoint()->GetVelocity();
740 G4double stepLength = track.GetStepLength();
741
742 deltaTime = 0.0; // in case initialVelocity = 0
743 if (track.GetParticleDefinition() == pdefOpticalPhoton)
744 {
745 // For only Optical Photon, final velocity is used
746 double finalVelocity = track.CalculateVelocityForOpticalPhoton();
747 fParticleChange.ProposeVelocity(finalVelocity);
748 deltaTime = stepLength / finalVelocity;
749 }
750 else if (initialVelocity > 0.0)
751 {
752 deltaTime = stepLength / initialVelocity;
753 }
754
755 State(fCandidateEndGlobalTime) = startTime + deltaTime;
756 }
757 else
758 {
759 deltaTime = State(fCandidateEndGlobalTime) - startTime;
760 }
761
762 fParticleChange.ProposeGlobalTime(State(fCandidateEndGlobalTime));
763 fParticleChange.ProposeLocalTime(track.GetLocalTime() + deltaTime);
764 /*
765 // Now Correct by Lorentz factor to get delta "proper" Time
766
767 G4double restMass = track.GetDynamicParticle()->GetMass() ;
768 G4double deltaProperTime = deltaTime*( restMass/track.GetTotalEnergy() ) ;
769
770 fParticleChange.ProposeProperTime(track.GetProperTime() + deltaProperTime) ;
771 */
772
774
775 ///___________________________________________________________________________
776 ///
777
778 // If the particle is caught looping or is stuck (in very difficult
779 // boundaries) in a magnetic field (doing many steps)
780 // THEN this kills it ...
781 //
782 if (State(fParticleIsLooping))
783 {
784 G4double endEnergy = State(fTransportEndKineticEnergy);
785
786 if ((endEnergy < fThreshold_Important_Energy) || (State(fNoLooperTrials)
788 {
789 // Kill the looping particle
790 //
791 // G4cout << "G4ITTransportation will killed the molecule"<< G4endl;
793
794 // 'Bare' statistics
795 fSumEnergyKilled += endEnergy;
796 if (endEnergy > fMaxEnergyKilled)
797 {
798 fMaxEnergyKilled = endEnergy;
799 }
800
801#ifdef G4VERBOSE
802 if ((fVerboseLevel > 1) || (endEnergy > fThreshold_Warning_Energy))
803 {
804 G4cout
805 << " G4ITTransportation is killing track that is looping or stuck "
806 << G4endl<< " This track has " << track.GetKineticEnergy() / MeV
807 << " MeV energy." << G4endl;
808 G4cout << " Number of trials = " << State(fNoLooperTrials)
809 << " No of calls to AlongStepDoIt = " << noCalls
810 << G4endl;
811 }
812#endif
813 State(fNoLooperTrials) = 0;
814 }
815 else
816 {
817 State(fNoLooperTrials)++;
818#ifdef G4VERBOSE
819 if ((fVerboseLevel > 2))
820 {
821 G4cout << " G4ITTransportation::AlongStepDoIt(): Particle looping - "
822 << " Number of trials = " << State(fNoLooperTrials)
823 << " No of calls to = " << noCalls << G4endl;
824 }
825#endif
826 }
827 }
828 else
829 {
830 State(fNoLooperTrials)=0;
831 }
832
833 // Another (sometimes better way) is to use a user-limit maximum Step size
834 // to alleviate this problem ..
835
836 // Introduce smooth curved trajectories to particle-change
837 //
840
841#if defined (DEBUG_MEM)
842 mem_second = MemoryUsage();
843 mem_diff = mem_second-mem_first;
844 G4cout << "\t || MEM || End of G4ITTransportation::AlongStepDoIt, diff is: "
845 << mem_diff << G4endl;
846#endif
847
848 return &fParticleChange;
849}
850
851//////////////////////////////////////////////////////////////////////////
852//
853// This ensures that the PostStep action is always called,
854// so that it can do the relocation if it is needed.
855//
856
860 G4double, // previousStepSize
861 G4ForceCondition* pForceCond)
862{
863 *pForceCond = Forced;
864 return DBL_MAX; // was kInfinity ; but convention now is DBL_MAX
865}
866
867/////////////////////////////////////////////////////////////////////////////
868//
869
871 const G4Step&)
872{
873 // G4cout << "G4ITTransportation::PostStepDoIt" << G4endl;
874
876 G4TouchableHandle retCurrentTouchable; // The one to return
877 G4bool isLastStep = false;
878
879 // Initialize ParticleChange (by setting all its members equal
880 // to corresponding members in G4Track)
881 fParticleChange.Initialize(track); // To initialise TouchableChange
882
884
885 // If the Step was determined by the volume boundary,
886 // logically relocate the particle
887
888 if (State(fGeometryLimitedStep))
889 {
890
891 if(fVerboseLevel)
892 {
893 G4cout << "Step is limited by geometry "
894 << "track ID : " << track.GetTrackID() << G4endl;
895 }
896
897 // fCurrentTouchable will now become the previous touchable,
898 // and what was the previous will be freed.
899 // (Needed because the preStepPoint can point to the previous touchable)
900
901 if ( State(fCurrentTouchableHandle)->GetVolume() == 0)
902 {
903 G4ExceptionDescription exceptionDescription;
904 exceptionDescription << "No current touchable found ";
905 G4Exception(" G4ITTransportation::PostStepDoIt", "G4ITTransportation001",
906 FatalErrorInArgument, exceptionDescription);
907 }
908
909 fLinearNavigator->SetGeometricallyLimitedStep();
910 fLinearNavigator->LocateGlobalPointAndUpdateTouchableHandle(
911 track.GetPosition(), track.GetMomentumDirection(),
912 State(fCurrentTouchableHandle), true);
913 // Check whether the particle is out of the world volume
914 // If so it has exited and must be killed.
915 //
916 if ( State(fCurrentTouchableHandle)->GetVolume() == 0)
917 {
918 // abort();
919#ifdef G4VERBOSE
920 if (fVerboseLevel > 0)
921 {
922 G4cout << "Track position : " << track.GetPosition() / nanometer
923 << " [nm]" << " Track ID : " << track.GetTrackID() << G4endl;
924 G4cout << "G4ITTransportation will killed the track because "
925 "State(fCurrentTouchableHandle)->GetVolume() == 0"<< G4endl;
926 }
927#endif
929 }
930
931 retCurrentTouchable = State(fCurrentTouchableHandle);
932
933// G4cout << "Current volume : " << track.GetVolume()->GetName()
934// << " Next volume : "
935// << (State(fCurrentTouchableHandle)->GetVolume() ?
936// State(fCurrentTouchableHandle)->GetVolume()->GetName():"OutWorld")
937// << " Position : " << track.GetPosition() / nanometer
938// << " track ID : " << track.GetTrackID()
939// << G4endl;
940
941 fParticleChange.SetTouchableHandle(State(fCurrentTouchableHandle));
942
943 // Update the Step flag which identifies the Last Step in a volume
944 isLastStep = fLinearNavigator->ExitedMotherVolume()
945 | fLinearNavigator->EnteredDaughterVolume();
946
947#ifdef G4DEBUG_TRANSPORT
948 // Checking first implementation of flagging Last Step in Volume
949 G4bool exiting = fLinearNavigator->ExitedMotherVolume();
950 G4bool entering = fLinearNavigator->EnteredDaughterVolume();
951
952 if( ! (exiting || entering) )
953 {
954 G4cout << " Transport> : Proposed isLastStep= " << isLastStep
955 << " Exiting " << fLinearNavigator->ExitedMotherVolume()
956 << " Entering " << fLinearNavigator->EnteredDaughterVolume()
957 << " Track position : " << track.GetPosition() /nanometer << " [nm]"
958 << G4endl;
959 G4cout << " Track position : " << track.GetPosition() /nanometer
960 << G4endl;
961 }
962#endif
963 }
964 else // fGeometryLimitedStep is false
965 {
966 // This serves only to move the Navigator's location
967 //
968// abort();
969 fLinearNavigator->LocateGlobalPointWithinVolume(track.GetPosition());
970
971 // The value of the track's current Touchable is retained.
972 // (and it must be correct because we must use it below to
973 // overwrite the (unset) one in particle change)
974 // It must be fCurrentTouchable too ??
975 //
977 retCurrentTouchable = track.GetTouchableHandle();
978
979 isLastStep = false;
980#ifdef G4DEBUG_TRANSPORT
981 // Checking first implementation of flagging Last Step in Volume
982 G4cout << " Transport> Proposed isLastStep= " << isLastStep
983 << " Geometry did not limit step. Position : "
984 << track.GetPosition()/ nanometer << G4endl;
985#endif
986 } // endif ( fGeometryLimitedStep )
987
989
990 const G4VPhysicalVolume* pNewVol = retCurrentTouchable->GetVolume();
991 const G4Material* pNewMaterial = 0;
992 const G4VSensitiveDetector* pNewSensitiveDetector = 0;
993
994 if (pNewVol != 0)
995 {
996 pNewMaterial = pNewVol->GetLogicalVolume()->GetMaterial();
997 pNewSensitiveDetector = pNewVol->GetLogicalVolume()->GetSensitiveDetector();
998 }
999
1000 // ( <const_cast> pNewMaterial ) ;
1001 // ( <const_cast> pNewSensitiveDetector) ;
1002
1005 (G4VSensitiveDetector *) pNewSensitiveDetector);
1006
1007 const G4MaterialCutsCouple* pNewMaterialCutsCouple = 0;
1008 if (pNewVol != 0)
1009 {
1010 pNewMaterialCutsCouple =
1012 }
1013
1014 if (pNewVol != 0 && pNewMaterialCutsCouple != 0
1015 && pNewMaterialCutsCouple->GetMaterial() != pNewMaterial)
1016 {
1017 // for parametrized volume
1018 //
1019 pNewMaterialCutsCouple = G4ProductionCutsTable::GetProductionCutsTable()
1020 ->GetMaterialCutsCouple(pNewMaterial,
1021 pNewMaterialCutsCouple->GetProductionCuts());
1022 }
1023 fParticleChange.SetMaterialCutsCoupleInTouchable(pNewMaterialCutsCouple);
1024
1025 // temporarily until Get/Set Material of ParticleChange,
1026 // and StepPoint can be made const.
1027 // Set the touchable in ParticleChange
1028 // this must always be done because the particle change always
1029 // uses this value to overwrite the current touchable pointer.
1030 //
1031 fParticleChange.SetTouchableHandle(retCurrentTouchable);
1032
1033 return &fParticleChange;
1034}
1035
1036// New method takes over the responsibility to reset the state of
1037// G4Transportation object at the start of a new track or the resumption of
1038// a suspended track.
1039
1041{
1043 if (fInstantiateProcessState)
1044 {
1045// G4VITProcess::fpState = new G4ITTransportationState();
1047 // Will set in the same time fTransportationState
1048 }
1049
1052 GetIT(track)->GetTrackingInfo()->GetTrackStateManager());
1053
1054 // The actions here are those that were taken in AlongStepGPIL
1055 // when track.GetCurrentStepNumber()==1
1056
1057 // reset safety value and center
1058 //
1059 // State(fPreviousSafety) = 0.0 ;
1060 // State(fPreviousSftOrigin) = G4ThreeVector(0.,0.,0.) ;
1061
1062 // reset looping counter -- for motion in field
1063 // State(fNoLooperTrials)= 0;
1064 // Must clear this state .. else it depends on last track's value
1065 // --> a better solution would set this from state of suspended track TODO ?
1066 // Was if( aTrack->GetCurrentStepNumber()==1 ) { .. }
1067
1068 // ChordFinder reset internal state
1069 //
1071 {
1073 // Resets all state of field propagator class (ONLY)
1074 // including safety values (in case of overlaps and to wipe for first track).
1075
1076 // G4ChordFinder* chordF= fFieldPropagator->GetChordFinder();
1077 // if( chordF ) chordF->ResetStepEstimate();
1078 }
1079
1080 // Make sure to clear the chord finders of all fields (ie managers)
1081 static G4ThreadLocal G4FieldManagerStore* fieldMgrStore = 0;
1082 if (!fieldMgrStore) fieldMgrStore = G4FieldManagerStore::GetInstance();
1083 fieldMgrStore->ClearAllChordFindersState();
1084
1085 // Update the current touchable handle (from the track's)
1086 //
1087 PrepareState()
1088 State(fCurrentTouchableHandle) = track->GetTouchableHandle();
1089
1091}
1092
1093#undef State
1094#undef PrepareState
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
G4ForceCondition
@ Forced
G4GPILSelection
@ CandidateForSelection
#define State(X)
#define fPreviousSftOrigin
#define fPreviousSafety
#define PrepareState()
G4IT * GetIT(const G4Track *track)
Definition: G4IT.cc:48
@ fTransportation
CLHEP::Hep3Vector G4ThreeVector
G4ReferenceCountedHandle< G4VTouchable > G4TouchableHandle
@ fStopAndKill
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
double mag2() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetCharge() const
static G4FieldManagerStore * GetInstance()
virtual void ConfigureForTrack(const G4Track *)
const G4Field * GetDetectorField() const
G4bool DoesFieldExist() const
void SetCurrentSafety(G4double val, const G4ThreeVector &pos)
static G4ITTransportationManager * GetTransportationManager()
G4ITNavigator * GetNavigatorForTracking() const
G4ITSafetyHelper * GetSafetyHelper() const
G4ParticleChangeForTransport fParticleChange
G4double fThreshold_Important_Energy
virtual void ComputeStep(const G4Track &, const G4Step &, const double timeStep, double &spaceStep)
virtual void BuildPhysicsTable(const G4ParticleDefinition &)
virtual G4double PostStepGetPhysicalInteractionLength(const G4Track &, G4double, G4ForceCondition *pForceCond)
void SetInstantiateProcessState(G4bool flag)
G4PropagatorInField * fFieldPropagator
virtual G4VParticleChange * AlongStepDoIt(const G4Track &track, const G4Step &stepData)
virtual G4double AlongStepGetPhysicalInteractionLength(const G4Track &track, G4double, G4double currentMinimumStep, G4double &currentSafety, G4GPILSelection *selection)
G4ITSafetyHelper * fpSafetyHelper
G4ITTransportation(const G4String &aName="ITTransportation", G4int verbosityLevel=0)
G4ITNavigator * fLinearNavigator
virtual G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &)
virtual void StartTracking(G4Track *aTrack)
G4TrackingInformation * GetTrackingInfo()
Definition: G4IT.hh:143
G4VSensitiveDetector * GetSensitiveDetector() const
G4Material * GetMaterial() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
const G4Material * GetMaterial() const
G4ProductionCuts * GetProductionCuts() const
void SetPointerToVectorOfAuxiliaryPoints(std::vector< G4ThreeVector > *vec)
void SetMaterialInTouchable(G4Material *fMaterial)
void SetTouchableHandle(const G4TouchableHandle &fTouchable)
void SetMaterialCutsCoupleInTouchable(const G4MaterialCutsCouple *fMaterialCutsCouple)
virtual void Initialize(const G4Track &)
void SetSensitiveDetectorInTouchable(G4VSensitiveDetector *fSensitiveDetector)
void SetMomentumChanged(G4bool b)
void ProposePolarization(G4double Px, G4double Py, G4double Pz)
void ProposePosition(G4double x, G4double y, G4double z)
void ProposeLocalTime(G4double t)
void ProposeVelocity(G4double finalVelocity)
void ProposeEnergy(G4double finalEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
void ProposeGlobalTime(G4double t)
G4ParticleDefinition * FindParticle(G4int PDGEncoding)
static G4ParticleTable * GetParticleTable()
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
static G4ProductionCutsTable * GetProductionCutsTable()
G4FieldManager * FindAndSetFieldManager(G4VPhysicalVolume *pCurrentPhysVol)
std::vector< G4ThreeVector > * GimmeTrajectoryVectorAndForgetIt() const
G4double GetVelocity() const
Definition: G4Step.hh:62
G4StepPoint * GetPreStepPoint() const
virtual void NewTrackState()
virtual void SaveTrackState(G4TrackStateManager &manager)
virtual void LoadTrackState(G4TrackStateManager &manager)
virtual void ResetTrackState()
G4TrackStatus GetTrackStatus() const
G4double GetVelocity() const
G4double CalculateVelocityForOpticalPhoton() const
Definition: G4Track.cc:149
G4int GetTrackID() const
const G4ParticleDefinition * GetParticleDefinition() const
G4VPhysicalVolume * GetVolume() const
const G4ThreeVector & GetPosition() const
G4double GetGlobalTime() const
G4double GetLocalTime() const
const G4DynamicParticle * GetDynamicParticle() const
const G4TouchableHandle & GetTouchableHandle() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
G4double CalculateVelocity() const
const G4ThreeVector & GetPolarization() const
G4double GetStepLength() const
G4TrackStateManager & GetTrackStateManager()
static G4TransportationManager * GetTransportationManager()
G4PropagatorInField * GetPropagatorInField() const
G4FieldManager * GetFieldManager() const
virtual void StartTracking(G4Track *)
Definition: G4VITProcess.cc:85
void SetInstantiateProcessState(G4bool flag)
G4shared_ptr< G4ProcessState > fpState
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLastStepInVolume(G4bool flag)
void ProposeTrueStepLength(G4double truePathLength)
G4LogicalVolume * GetLogicalVolume() const
G4bool enableAtRestDoIt
Definition: G4VProcess.hh:359
G4bool enableAlongStepDoIt
Definition: G4VProcess.hh:360
void SetProcessSubType(G4int)
Definition: G4VProcess.hh:406
virtual void StartTracking(G4Track *)
Definition: G4VProcess.cc:87
G4bool enablePostStepDoIt
Definition: G4VProcess.hh:361
G4VParticleChange * pParticleChange
Definition: G4VProcess.hh:321
virtual G4VPhysicalVolume * GetVolume(G4int depth=0) const
Definition: G4VTouchable.cc:41
T sqr(const T &x)
Definition: templates.hh:128
#define DBL_MAX
Definition: templates.hh:62
#define G4ThreadLocal
Definition: tls.hh:77