// // ******************************************************************** // * DISCLAIMER * // * * // * The following disclaimer summarizes all the specific disclaimers * // * of contributors to this software. The specific disclaimers,which * // * govern, are listed with their locations in: * // * http://cern.ch/geant4/license * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. * // * * // * 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: G4MultipleScatteringx.icc,v 1.2.2.2 2001/06/28 20:19:51 gunter Exp $ // GEANT4 tag $Name: $ // // $Id: // ------------------------------------------------------------- // GEANT 4 class inlined methods file // // History: based on object model of // 2nd December 1995, G.Cosmo // ------- G4MultipleScatteringx physics process ------ // by Laszlo Urban, March 2001 //--------------------------------------------------------------- // New version of MSC model //--------------------------------------------------------------- // Modified: // 18/05/01 V.Ivanchenko Clean up againist Linux ANSI compilation // //--------------------------------------------------------------- inline G4double G4MultipleScatteringx::AlongStepGetPhysicalInteractionLength( const G4Track& track, G4double previousStepSize, G4double currentMinimumStep, G4double& currentSafety, G4GPILSelection* selection ) { // get Step limit proposed by the process G4double steplength = GetContinuousStepLimit(track,previousStepSize,currentMinimumStep, currentSafety); // set return value for G4GPILSelection *selection = valueGPILSelectionMSC; return steplength ; } inline G4double G4MultipleScatteringx::GetContinuousStepLimit( const G4Track& track, G4double, G4double currentMinimumStep, G4double&) { G4double zPathLength,tPathLength ; const G4DynamicParticle* aParticle ; G4Material* aMaterial ; G4double KineticEnergy,tau ; G4bool isOut ; static const G4double toler = 1.0e-6*mm ; static const G4double factlim = 0.10 ; G4double tlimit ; static G4double tausmall = 1.e-20 ; static G4double taulow = 1.e-10 ; static G4double clim=1./3. ; G4double etau,beta2,cc,ccc,u ; // this process is not a candidate for selection by default !!!!!!!! valueGPILSelectionMSC = NotCandidateForSelection; if(track.GetCurrentStepNumber() == 1) stepFlag = 0 ; tPathLength = currentMinimumStep ; aMaterial = track.GetMaterial() ; materialIndex = aMaterial->GetIndex() ; aParticle = track.GetDynamicParticle() ; KineticEnergy = aParticle->GetKineticEnergy() ; if((lastMaterial != aMaterial) || (lastKineticEnergy != KineticEnergy)) { lastKineticEnergy = KineticEnergy ; materialIndex = aMaterial->GetIndex() ; if((lastMaterial != aMaterial)||(KineticEnergy >= Tlimit)||(stepFlag != 1)) fTransportMeanFreePath = (*theTransportMeanFreePathTable) (materialIndex)->GetValue(KineticEnergy,isOut); lastMaterial = aMaterial; if(KineticEnergy < Tlimit) { stepFlag = 1 ; range = G4EnergyLossTables::GetRange(aParticle->GetDefinition(), KineticEnergy,aMaterial) ; alpha1 = range/fTransportMeanFreePath+1 ; } } // special treatment near boundaries ? if(boundary) { // step limitation at boundary ? if(track.GetCurrentStepNumber() > 1) { if(track.GetStep()->GetPreStepPoint()->GetSafety() < toler) { tlimit = factlim*fTransportMeanFreePath ; if(tPathLength > tlimit) { tPathLength = tlimit*G4UniformRand() ; valueGPILSelectionMSC = CandidateForSelection; } } } } // do the true -> geom transformation if( fTransportMeanFreePath > biglambda ) { zPathLength = tPathLength ; } else if(stepFlag == 0) { tau = tPathLength/fTransportMeanFreePath ; if(tau < tausmall) zPathLength = tPathLength*(1.-0.5*tau) ; else { // sample zPathLength etau = exp(-tau) ; if(scatteringparameter3 <= clim) { ccc = 1.-scatteringparameter3 ; } else { cc=0.5/scatteringparameter3-1.5 ; ccc=2.*scatteringparameter3*exp(cc) ; } if(tau < taulow) beta2 = (1.+scatteringparameter3)*(1.-2.*tau/3.)/tau ; else beta2 = 0.5*(1.+scatteringparameter3)*(1.-etau)/(tau-1+etau) ; do { u = -log(1.-G4UniformRand())/beta2 ; } while (G4UniformRand() > (1.-scatteringparameter3+ 2.*scatteringparameter3*beta2*u)*exp(-beta2*u)/ccc ) ; zPathLength = tPathLength/(1.+u) ; } } else { tau = tPathLength/range ; if(tautrue path transformation is performed { static const G4double tfacmx = 10. ; G4double tau,geomPathLength, truePathLength ; static G4double tausmall = 1.e-20 ; static G4double taulow = 1.e-10 ; static G4double clim=1./3. ; G4double ltau,cc,ccc,beta2,u ; fParticleChange.Initialize(track); geomPathLength = track.GetStepLength() ; if(geomPathLength == zLast) { truePathLength = tLast ; } else if( fTransportMeanFreePath > biglambda ) { truePathLength = geomPathLength ; } else if(stepFlag == 0) { tau = geomPathLength/fTransportMeanFreePath ; if(tau < tausmall) truePathLength = geomPathLength*(1.+0.5*tau) ; else if(tau < 1.) { // sample tPathLength ltau = -log(1.-tau) ; if(scatteringparameter3 <= clim) { ccc = 1.-scatteringparameter3 ; } else { cc=0.5/scatteringparameter3-1.5 ; ccc=2.*scatteringparameter3*exp(cc) ; } if(tau < taulow) beta2 = (1.+scatteringparameter3)*(1.-2.*tau/3.)/tau ; else beta2 = (1.+scatteringparameter3)*tau/(2.*(ltau-tau)) ; do { u = -log(1.-G4UniformRand())/beta2 ; } while (G4UniformRand() > (1.-scatteringparameter3+ 2.*scatteringparameter3*beta2*u)*exp(-beta2*u)/ccc ) ; truePathLength = geomPathLength*(1.+u) ; } else truePathLength = tfacmx*fTransportMeanFreePath ; } else { if(geomPathLength/range < perMillion) truePathLength = range*(1.-exp(-geomPathLength/range)) ; else truePathLength = range*(1.-exp(log(1.-alpha1*geomPathLength/range)/ alpha1)) ; } fParticleChange.SetTrueStepLength(truePathLength) ; return &fParticleChange ; } inline G4bool G4MultipleScatteringx::IsApplicable( const G4ParticleDefinition& particle) { return(particle.GetPDGCharge() != 0.); } inline G4double G4MultipleScatteringx::GetLambda( G4double KineticEnergy, G4Material* material) { G4bool isOut; G4double lambda = (*theTransportMeanFreePathTable) (material->GetIndex())-> GetValue(KineticEnergy,isOut); return lambda; }