// This code implementation is the intellectual property of // the GEANT4 collaboration. // // By copying, distributing or modifying the Program (or any work // based on the Program) you indicate your acceptance of this statement, // and all its terms. // // $Id: G4IMultipleScattering.icc,v 1.1 2000/03/20 14:44:03 maire Exp $ // GEANT4 tag $Name: geant4-03-00 $ // // $Id: // ------------------------------------------------------------- // GEANT 4 class inlined methods file // // For information related to this code contact: // CERN, IT Division, ASD Group // History: based on object model of // 2nd December 1995, G.Cosmo // ------- G4IMultipleScattering physics process ------ // by Laszlo Urban, October 1997 // ************************************************************** // 25/11/97: mods for KinEnergy > HighestLimit //--------------------------------------------------------------- // ***************************************************************** // It is the first implementation of the multiple scattering process // using an INTEGRAL APPROACH instead of the differential // one used in the standard implementation . // ***************************************************************** // by Laszlo Urban, 23 June 1998 // ----------------------------------------------------------------- // 27/10/98: cleanup , L.Urban inline G4double G4IMultipleScattering::TrueToGeomTransformation( const G4DynamicParticle *aParticle, G4Material *aMaterial, G4double truePathLength) // it sets the data member fTransportMeanFreePath and // performs the true path length -> geometrical path length // transformation { const G4double factt=1.-1.e-6,tausmall=5.e-5,taubig=50., minim=1.e-6,smalldroverr=1.e-2,smalldToverT=2.e-2 ; G4double KineticEnergy,Tfinal,tau,etau,geomPathLength,range,w1,w2,ww1,ww2 ; G4int materialIndex ; G4bool isOut ; KineticEnergy = aParticle->GetKineticEnergy() ; if((lastMaterial == aMaterial) && (lastKineticEnergy == KineticEnergy)) { ; } else { lastMaterial=aMaterial; lastKineticEnergy=KineticEnergy; materialIndex = aMaterial->GetIndex() ; if(KineticEnergyGetValue(LowestKineticEnergy,isOut); } else { if(KineticEnergy>HighestKineticEnergy) KineticEnergy=HighestKineticEnergy; fTransportMeanFreePath = (*theTransportMeanFreePathTable) (materialIndex)->GetValue(KineticEnergy,isOut); } } // do the true -> geom transformation if( fTransportMeanFreePath > biglambda ) { geomPathLength = truePathLength ; CosTheta = 1. ; } else { const G4ParticleDefinition *theParticle = aParticle->GetDefinition() ; G4double range = G4EnergyLossTables::GetPreciseRangeFromEnergy( theParticle,KineticEnergy,aMaterial) ; if(truePathLength > factt*range) { geomPathLength = GetIntegralJ(theParticle, KineticEnergy,aMaterial) ; CosTheta = 0. ; } else { if(truePathLength/range < smalldroverr) { Tfinal = KineticEnergy - truePathLength* G4EnergyLossTables::GetPreciseDEDX( theParticle,KineticEnergy,aMaterial) ; } else { Tfinal = G4EnergyLossTables::GetPreciseEnergyFromRange( theParticle,range-truePathLength, aMaterial) ; } if((KineticEnergy-Tfinal)> smalldToverT) { w1 = GetIntegralI(theParticle,KineticEnergy,aMaterial) ; w2 = GetIntegralI(theParticle,Tfinal ,aMaterial) ; CosTheta = exp(w2-w1) ; if( CosTheta < minim) CosTheta = 0. ; ww1 = GetIntegralJ(theParticle,KineticEnergy,aMaterial) ; ww2 = GetIntegralJ(theParticle,Tfinal ,aMaterial) ; geomPathLength = ww1 - ww2*CosTheta ; } else { tau = truePathLength/fTransportMeanFreePath ; if(tautaubig) etau = 1. ; else etau = 1.-exp(-tau) ; } geomPathLength = fTransportMeanFreePath*etau ; CosTheta = exp(-truePathLength/fTransportMeanFreePath) ; } } } if(geomPathLength>truePathLength) geomPathLength = truePathLength ; tLast = truePathLength ; zLast = geomPathLength ; return geomPathLength ; } inline G4double G4IMultipleScattering::GetContinuousStepLimit( const G4Track& track, G4double, G4double currentMinimumStep, G4double&) { G4double zPathLength,tPathLength ; const G4DynamicParticle* aParticle ; // this process is not a candidate for selection!!!!!!!!! SetGPILSelection(NotCandidateForSelection) ; tPathLength = currentMinimumStep ; aParticle = track.GetDynamicParticle() ; zPathLength = TrueToGeomTransformation(aParticle, track.GetMaterial(),tPathLength); return zPathLength ; } inline G4double G4IMultipleScattering::GetMeanFreePath(const G4Track&, G4double, G4ForceCondition* condition) // it does not limit the Step size , but it sets condition to // Forced , because the PostStepDoIt always has to be called { *condition = Forced ; return DBL_MAX ; } inline G4VParticleChange* G4IMultipleScattering::AlongStepDoIt( const G4Track& track,const G4Step& Step) // only a geom path->true path transformation is performed { const G4double Tlowlimit=100.*keV ; const G4double fact = 1.-1.e-10 ; //!! const G4double tausmall=5.e-5,taubig=0.9999,trueBig=5. ; const G4double tausmall=5.e-5,taubig=0.9999,trueBig=9.21034 ; G4double tau ,geomPathLength, truePathLength ; aParticleChange.Initialize(track); geomPathLength = track.GetStepLength() ; //Store this value for later use in PostStepDoIt GeomStepFinal = geomPathLength ; if(geomPathLength == zLast) { truePathLength = tLast ; } else { if( fTransportMeanFreePath > biglambda ) { truePathLength = track.GetStepLength() ; CosTheta = 1. ; } else { G4double T = track.GetDynamicParticle()->GetKineticEnergy() ; if(T < Tlowlimit) { // spec. low energy msc code G4double range = G4EnergyLossTables::GetPreciseRangeFromEnergy( track.GetDynamicParticle()->GetDefinition(), T,track.GetMaterial()) ; G4double alfa = 1.+range/fTransportMeanFreePath ; G4double z = geomPathLength ; //protection: z can not be greater than zmax !!!!!!! G4double zmax = fact*range/alfa ; if(z > zmax) z = zmax ; if(z == zmax) { truePathLength = range ; CosTheta = 0. ; } else { truePathLength = range* (1.-exp(log(1.-alfa*z/range)/alfa)) ; CosTheta = (1.-alfa*z/range)/(1.-truePathLength/range) ; } } else { tau = geomPathLength/fTransportMeanFreePath ; if(tau