Import Geant4 0.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-01 15:25:35 +02:00
parent 54d6b71f95
commit b97f8d0df7
3237 changed files with 807095 additions and 0 deletions
@@ -0,0 +1,46 @@
# $Id: GNUmakefile,v 2.0 1998/07/02 16:27:15 gunter Exp $
# -----------------------------------------------------------
# GNUmakefile for hadronic library. Gabriele Cosmo, 18/9/96.
# -----------------------------------------------------------
name := G4hadronic_HE
ifndef G4INSTALL
G4INSTALL = ../../../../..
endif
include $(G4INSTALL)/config/architecture.gmk
G4TMPDIR = $(G4TMP)/$(G4SYSTEM)/$(name)
CPPFLAGS += -I$(G4BASE)/global/management/include \
-I$(G4BASE)/global/HEPRandom/include \
-I$(G4BASE)/global/HEPGeometry/include \
-I$(G4BASE)/track/include \
-I$(G4BASE)/geometry/volumes/include \
-I$(G4BASE)/geometry/management/include \
-I$(G4BASE)/processes/management/include \
-I$(G4BASE)/processes/hadronic/management/include/ \
-I$(G4BASE)/processes/hadronic/util/include \
-I$(G4BASE)/particles/management/include \
-I$(G4BASE)/particles/leptons/include \
-I$(G4BASE)/particles/bosons/include \
-I$(G4BASE)/particles/hadrons/mesons/include \
-I$(G4BASE)/particles/hadrons/barions/include \
-I$(G4BASE)/particles/hadrons/ions/include \
-I$(G4BASE)/materials/include
include $(G4INSTALL)/config/common.gmk
# Temporary fix for HP-CC compiler. It cannot handle full optimisation for
# the specified files ...
ifneq (,$(findstring HP,$(G4SYSTEM)))
CXXFLAGS_WITHOUT_O := $(filter-out +O% , $(CXXFLAGS))
$(G4TMPDIR)/G4GHEInelastic.o: src/G4GHEInelastic.cc
$(CXX) $(CXXFLAGS_WITHOUT_O) $(CPPFLAGS) -c -o $@ src/G4GHEInelastic.cc
$(G4TMPDIR)/G4GHEInelasticModel.o: src/G4GHEInelasticModel.cc
$(CXX) $(CXXFLAGS_WITHOUT_O) $(CPPFLAGS) -c -o $@ src/G4GHEInelasticModel.cc
endif
@@ -0,0 +1,39 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEAntiKaonZeroInelastic_h
#define G4HEAntiKaonZeroInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEAntiKaonZeroInelastic : public G4HEInelastic
{
public:
G4HEAntiKaonZeroInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEAntiKaonZeroInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasAntiKaonZero(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEAntiLambdaInelastic_h
#define G4HEAntiLambdaInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEAntiLambdaInelastic : public G4HEInelastic
{
public:
G4HEAntiLambdaInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEAntiLambdaInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasAntiLambda(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEAntiNeutronInelastic_h
#define G4HEAntiNeutronInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEAntiNeutronInelastic : public G4HEInelastic
{
public:
G4HEAntiNeutronInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEAntiNeutronInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasAntiNeutron(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEAntiOmegaMinusInelastic_h
#define G4HEAntiOmegaMinusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEAntiOmegaMinusInelastic : public G4HEInelastic
{
public:
G4HEAntiOmegaMinusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEAntiOmegaMinusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasAntiOmegaMinus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEAntiProtonInelastic_h
#define G4HEAntiProtonInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEAntiProtonInelastic : public G4HEInelastic
{
public:
G4HEAntiProtonInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEAntiProtonInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasAntiProton(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEAntiSigmaMinusInelastic_h
#define G4HEAntiSigmaMinusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEAntiSigmaMinusInelastic : public G4HEInelastic
{
public:
G4HEAntiSigmaMinusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEAntiSigmaMinusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasAntiSigmaMinus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEAntiSigmaPlusInelastic_h
#define G4HEAntiSigmaPlusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEAntiSigmaPlusInelastic : public G4HEInelastic
{
public:
G4HEAntiSigmaPlusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEAntiSigmaPlusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasAntiSigmaPlus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,35 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEAntiSigmaZeroInelastic_h
#define G4HEAntiSigmaZeroInelastic_h 1
#include "G4HEAntiLambdaInelastic.hh"
class G4HEAntiSigmaZeroInelastic : public G4HEInelastic
{
public:
G4HEAntiSigmaZeroInelastic() : G4HEInelastic()
{
}
~G4HEAntiSigmaZeroInelastic(){ };
G4int verboseLevel;
G4int MAXPART;
G4int vecLength;
void SetMaxNumberOfSecondaries(G4int maxnumber)
{ MAXPART = maxnumber; };
void SetVerboseLevel(G4int verbose)
{ verboseLevel = verbose;};
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEAntiXiMinusInelastic_h
#define G4HEAntiXiMinusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEAntiXiMinusInelastic : public G4HEInelastic
{
public:
G4HEAntiXiMinusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEAntiXiMinusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasAntiXiMinus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEAntiXiZeroInelastic_h
#define G4HEAntiXiZeroInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEAntiXiZeroInelastic : public G4HEInelastic
{
public:
G4HEAntiXiZeroInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEAntiXiZeroInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasAntiXiZero(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,196 @@
// G4 Gheisha High Energy (GHE) model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
// It includes all Physics Routines from Geant3,
// relevant for simulation of hadronic processes
// above approx. 20 GeV incident momentum.
// Not included are the Physics Routines for
// stopping particles, the low energy neutron
// slowing down description and the low energy
// nuclear reactions a(A,A')b.
// All routines pass the compiler and give
// some reasonable numbers as output.
// A statistically significant comparison
// with GEANT3 and experimental data has
// still to be done.
#ifndef G4HEInelastic_h
#define G4HEInelastic_h 1
#include "G4HEVector.hh"
#include "G4HadronicInteraction.hh"
class G4HEInelastic : public G4HadronicInteraction
{
public:
G4HEInelastic()
{
SetMinEnergy(20*GeV);
SetMaxEnergy(10*TeV);
MAXPART = 512;
verboseLevel = 0;
SetParticles();
};
~G4HEInelastic(){ };
void SetMaxNumberOfSecondaries( const G4int maxnumber )
{ MAXPART = maxnumber;}
void SetVerboseLevel( const G4int level)
{ verboseLevel = level;}
G4int verboseLevel;
G4int MAXPART;
void FillParticleChange(G4HEVector pv[], G4int aVecLength);
G4double pmltpc(G4int np, G4int nm, G4int nz, G4int n, G4double b, G4double c);
G4int Factorial(G4int n);
G4double NuclearInelasticity(G4double incidentKineticEnergy,
G4double atomicWeight,
G4double atomicNumber);
G4double NuclearExcitation(G4double incidentKineticEnergy,
G4double atomicWeight,
G4double atomicNumber,
G4double& excitationEnergyCascade,
G4double& excitationEnergyEvaporation);
void HighEnergyCascading(G4bool &successful,
G4HEVector pv[],
G4int &vecLen,
G4double &excitationEnergyGNP,
G4double &excitationEnergyDTA,
G4HEVector incidentParticle,
G4HEVector targetParticle,
G4double atomicWeight,
G4double atomicNumber);
void HighEnergyClusterProduction(G4bool &successful,
G4HEVector pv[],
G4int &vecLen,
G4double &excitationEnergyGNP,
G4double &excitationEnergyDTA,
G4HEVector incidentParticle,
G4HEVector targetParticle,
G4double atomicWeight,
G4double atomicNumber);
void TuningOfHighEnergyCascading( G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
G4double atomicWeight,
G4double atomicNumber);
void MediumEnergyCascading(G4bool &successful,
G4HEVector pv[],
G4int &vecLen,
G4double &excitationEnergyGNP,
G4double &excitationEnergyDTA,
G4HEVector incidentParticle,
G4HEVector targetParticle,
G4double atomicWeight,
G4double atomicNumber);
void MediumEnergyClusterProduction(G4bool &successful,
G4HEVector pv[],
G4int &vecLen,
G4double &excitationEnergyGNP,
G4double &excitationEnergyDTA,
G4HEVector incidentParticle,
G4HEVector targetParticle,
G4double atomicWeight,
G4double atomicNumber);
void QuasiElasticScattering(G4bool &successful,
G4HEVector pv[],
G4int &vecLen,
G4double &excitationEnergyGNP,
G4double &excitationEnergyDTA,
G4HEVector incidentParticle,
G4HEVector targetParticle,
G4double atomicWeight,
G4double atomicNumber);
void ElasticScattering(G4bool &successful,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4double atomicWeight,
G4double atomicNumber);
G4int rtmi(G4double *x, G4double xli, G4double xri, G4double eps,
G4int iend,
G4double aa, G4double bb, G4double cc, G4double dd, G4double rr);
G4double fctcos(G4double t, G4double aa, G4double bb,G4double cc, G4double dd,
G4double rr);
void StrangeParticlePairProduction(const G4double availableEnergy,
const G4double centerOfMassEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle);
G4double NBodyPhaseSpace(const G4double totalEnergy,
const G4bool constantCrossSection,
G4HEVector pv[],
G4int &vecLen);
G4double NBodyPhaseSpace(G4int npart,
G4HEVector pv[],
G4double wmax,
G4double wfcn,
G4int maxtrial,
G4int ntrial);
G4double gpdk(G4double a, G4double b, G4double c);
void QuickSort(G4double arr[], const G4int lidx, const G4int ridx);
G4double Alam(G4double a, G4double b, G4double c);
G4double CalculatePhaseSpaceWeight( G4int npart);
G4double normal(void);
G4double GammaRand(G4double avalue);
G4double Erlang(G4int mvalue);
G4int Poisson(G4double x);
void SetParticles(void);
G4HEVector PionPlus;
G4HEVector PionZero;
G4HEVector PionMinus;
G4HEVector KaonPlus;
G4HEVector KaonZero;
G4HEVector AntiKaonZero;
G4HEVector KaonMinus;
G4HEVector KaonZeroShort;
G4HEVector KaonZeroLong;
G4HEVector Proton;
G4HEVector AntiProton;
G4HEVector Neutron;
G4HEVector AntiNeutron;
G4HEVector Lambda;
G4HEVector AntiLambda;
G4HEVector SigmaPlus;
G4HEVector SigmaZero;
G4HEVector SigmaMinus;
G4HEVector AntiSigmaPlus;
G4HEVector AntiSigmaZero;
G4HEVector AntiSigmaMinus;
G4HEVector XiZero;
G4HEVector XiMinus;
G4HEVector AntiXiZero;
G4HEVector AntiXiMinus;
G4HEVector OmegaMinus;
G4HEVector AntiOmegaMinus;
G4HEVector Deuteron;
G4HEVector Triton;
G4HEVector Alpha;
G4HEVector Gamma;
};
#endif
@@ -0,0 +1,39 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEKaonMinusInelastic_h
#define G4HEKaonMinusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEKaonMinusInelastic : public G4HEInelastic
{
public:
G4HEKaonMinusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEKaonMinusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasKaonMinus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEKaonPlusInelastic_h
#define G4HEKaonPlusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEKaonPlusInelastic : public G4HEInelastic
{
public:
G4HEKaonPlusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEKaonPlusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasKaonPlus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEKaonZeroInelastic_h
#define G4HEKaonZeroInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEKaonZeroInelastic : public G4HEInelastic
{
public:
G4HEKaonZeroInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEKaonZeroInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasKaonZero(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,38 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEKaonZeroLongInelastic_h
#define G4HEKaonZeroLongInelastic_h 1
#include "G4HEKaonZeroInelastic.hh"
#include "G4HEAntiKaonZeroInelastic.hh"
class G4HEKaonZeroLongInelastic : public G4HEInelastic
{
public:
G4HEKaonZeroLongInelastic()
{
}
~G4HEKaonZeroLongInelastic(){ };
G4int verboseLevel;
G4int MAXPART;
G4int vecLength;
void SetMaxNumberOfSecondaries(G4int maxnumber)
{ MAXPART = maxnumber;};
void SetVerboseLevel(G4int verbose)
{ verboseLevel = verbose;};
G4int GetNumberOfSecondaries()
{ return vecLength;};
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
};
#endif
@@ -0,0 +1,36 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEKaonZeroShortInelastic_h
#define G4HEKaonZeroShortInelastic_h 1
#include "G4HEKaonZeroInelastic.hh"
#include "G4HEAntiKaonZeroInelastic.hh"
class G4HEKaonZeroShortInelastic : public G4HEInelastic
{
public:
G4HEKaonZeroShortInelastic()
{
}
~G4HEKaonZeroShortInelastic(){ };
G4int vecLength;
void SetMaxNumberOfSecondaries(G4int maxnumber)
{ MAXPART = maxnumber;};
void SetVerboseLevel(G4int verbose)
{ verboseLevel = verbose;};
G4int GetNumberOfSecondaries()
{ return vecLength;};
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HELambdaInelastic_h
#define G4HELambdaInelastic_h 1
#include "G4HEInelastic.hh"
class G4HELambdaInelastic : public G4HEInelastic
{
public:
G4HELambdaInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HELambdaInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasLambda(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HENeutronInelastic_h
#define G4HENeutronInelastic_h 1
#include "G4HEInelastic.hh"
class G4HENeutronInelastic : public G4HEInelastic
{
public:
G4HENeutronInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HENeutronInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasNeutron(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEOmegaMinusInelastic_h
#define G4HEOmegaMinusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEOmegaMinusInelastic : public G4HEInelastic
{
public:
G4HEOmegaMinusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEOmegaMinusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasOmegaMinus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,39 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEPionMinusInelastic_h
#define G4HEPionMinusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEPionMinusInelastic : public G4HEInelastic
{
public:
G4HEPionMinusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEPionMinusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasPionMinus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEPionPlusInelastic_h
#define G4HEPionPlusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEPionPlusInelastic : public G4HEInelastic
{
public:
G4HEPionPlusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEPionPlusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasPionPlus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,82 @@
// G4 Gheisha friend class G4HEPlot -- header file
// last modified: H. Fesefeldt 18-November-1996
#include <stdio.h>
#include "globals.hh"
class G4HEPlot
{
protected:
G4double Xstart;
G4double Xbin;
G4double Weight;
G4int Nbin;
G4int Entries;
G4int EntriesOverflow;
G4int EntriesUnderflow;
G4double WeightOverflow;
G4double WeightUnderflow;
G4double* Xvalue;
G4double* Yvalue;
public:
G4HEPlot(){ };
~G4HEPlot(){ };
G4double getWeight()
{ return Weight;};
G4double getWeightUnderflow()
{ return WeightUnderflow; };
G4double getWeightOverflow()
{ return WeightOverflow;};
G4int getNumberOfEntries()
{ return Entries;};
G4int getNumberOfEntriesOverflow()
{ return EntriesOverflow;};
G4int getNumberOfEntriesUnderflow()
{ return EntriesUnderflow;};
G4int getNumberOfBins()
{ return Nbin;};
G4double getBinsize()
{ return Xbin;};
G4double getXstart()
{ return Xstart;};
void Init(G4int nbin, G4double xstart, G4double Xbin);
void Add( G4double s1, G4double s2, const G4HEPlot & p1, const G4HEPlot & p2 );
void Multiply( G4double s1, G4double s2, const G4HEPlot & p1, const G4HEPlot & p2 );
void Divide( G4double s1, G4double s2, const G4HEPlot & p1, const G4HEPlot & p2 );
void Scale( G4double s, const G4HEPlot & p);
void XScale( G4double a, G4double b, const G4HEPlot & p);
void Log( G4double s, const G4HEPlot & p);
void Sqrt( G4double s, const G4HEPlot & p);
void Reset();
void Fill(G4double x, G4double w);
void Print(G4String name, G4int i);
void DumpToFile(G4int aPlot, G4String aName);
void GetFromFile(G4int aPlot, G4String aName);
};
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEProtonInelastic_h
#define G4HEProtonInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEProtonInelastic : public G4HEInelastic
{
public:
G4HEProtonInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEProtonInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasProton(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HESigmaMinusInelastic_h
#define G4HESigmaMinusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HESigmaMinusInelastic : public G4HEInelastic
{
public:
G4HESigmaMinusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HESigmaMinusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasSigmaMinus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HESigmaPlusInelastic_h
#define G4HESigmaPlusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HESigmaPlusInelastic : public G4HEInelastic
{
public:
G4HESigmaPlusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HESigmaPlusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasSigmaPlus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,35 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HESigmaZeroInelastic_h
#define G4HESigmaZeroInelastic_h 1
#include "G4HELambdaInelastic.hh"
class G4HESigmaZeroInelastic : public G4HEInelastic
{
public:
G4HESigmaZeroInelastic() : G4HEInelastic()
{
}
~G4HESigmaZeroInelastic(){ };
G4int verboseLevel;
G4int MAXPART;
G4int vecLength;
void SetMaxNumberOfSecondaries(G4int maxnumber)
{ MAXPART = maxnumber; };
void SetVerboseLevel(G4int verbose)
{ verboseLevel = verbose;};
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
};
#endif
@@ -0,0 +1,230 @@
// G4 Gheisha friend class G4KinematicParticle -- header file
// J.L. Chuma, TRIUMF, 22-Feb-1996
// last modified: H. Fesefeldt 18-November-1996
#ifndef G4HEVector_hh
#define G4HEVector_hh 1
#include "G4ParticleMomentum.hh"
#include "Randomize.hh"
#include "G4DynamicParticle.hh"
class G4HEVector
{
protected:
G4double px;
G4double py;
G4double pz;
G4double energy;
G4double kineticEnergy;
G4double mass;
G4double charge;
G4double timeOfFlight;
G4int side;
G4bool flag;
G4int code;
G4String particleName;
G4String particleType;
G4int baryon;
enum {NumberOfQuarkFlavor = 8};
G4int theQuarkContent[NumberOfQuarkFlavor];
G4int theAntiQuarkContent[NumberOfQuarkFlavor];
public:
G4HEVector(const G4DynamicParticle * aParticle)
{
G4ThreeVector aMom = 1./GeV*aParticle->GetMomentum();
px = aMom.x();
py = aMom.y();
pz = aMom.z();
energy = aParticle->GetTotalEnergy()/GeV;
kineticEnergy = aParticle->GetKineticEnergy()/GeV;
mass = aParticle->GetMass()/GeV;
charge = aParticle->GetDefinition()->GetPDGCharge()/eplus;
timeOfFlight = 0.0;
side = 0;
flag = false;
code = aParticle->GetDefinition()->GetPDGEncoding();
baryon = aParticle->GetDefinition()->GetBaryonNumber();
particleName = getParticleName(code, baryon);
particleType = aParticle->GetDefinition()->GetParticleType();
}
G4HEVector()
{
px = 0.0;
py = 0.0;
pz = 0.0;
energy = 0.0;
kineticEnergy = 0.0;
mass = 0.0;
charge = 0.0;
timeOfFlight = 0.0;
side = 0;
flag = false;
code = 0;
particleName = "";
particleType = "";
baryon = 0;
}
G4HEVector( const G4HEVector & p )
{
px = p.px;
py = p.py;
pz = p.pz;
energy = p.energy;
kineticEnergy = p.kineticEnergy;
mass = p.mass;
charge = p.charge;
timeOfFlight = p.timeOfFlight;
side = p.side;
flag = p.flag;
code = p.code;
particleName = p.particleName;
particleType = p.particleType;
baryon = 0;
}
G4HEVector & operator = ( const G4HEVector & p )
{
px = p.px;
py = p.py;
pz = p.pz;
energy = p.energy;
kineticEnergy = p.kineticEnergy;
mass = p.mass;
charge = p.charge;
timeOfFlight = p.timeOfFlight;
side = p.side;
flag = p.flag;
code = p.code;
particleName = p.particleName;
particleType = p.particleType;
baryon = p.baryon;
return *this;
}
~G4HEVector(){ };
G4String getParticleName(G4int code, G4int baryon);
void setMomentum( G4ParticleMomentum mom );
void setMomentumAndUpdate( G4ParticleMomentum mom );
const G4ParticleMomentum getMomentum() const ;
G4double getTotalMomentum();
void setMomentum( G4double x, G4double y, G4double z);
void setMomentumAndUpdate( G4double x, G4double y, G4double z );
void setMomentum( G4double x, G4double y );
void setMomentumAndUpdate( G4double x, G4double y );
void setMomentum( G4double z );
void setMomentumAndUpdate( G4double z );
void setEnergy( G4double e );
void setEnergyAndUpdate( G4double e );
void setKineticEnergy( G4double ekin );
void setKineticEnergyAndUpdate(G4double ekin);
G4double getEnergy();
G4double getKineticEnergy();
void setMass( G4double m );
void setMassAndUpdate( G4double m );
G4double getMass();
void setCharge( G4double c );
G4double getCharge();
void setTOF( G4double t );
G4double getTOF();
void setSide( G4int s );
G4int getSide();
void setFlag( G4bool f );
G4bool getFlag();
void setCode( G4int c );
G4int getCode();
G4String getName();
G4int getBaryonNumber();
G4int getQuarkContent(G4int flavor);
G4int getAntiQuarkContent(G4int flavor);
void setZero();
G4String getType();
void Add( const G4HEVector & p1, const G4HEVector & p2 );
void Sub( const G4HEVector & p1, const G4HEVector & p2 );
void Lor( const G4HEVector & p1, const G4HEVector & p2 );
G4double CosAng( const G4HEVector & p );
G4double Ang(const G4HEVector & p );
G4double Dot4( const G4HEVector & p1, const G4HEVector & p2);
G4double Impu( const G4HEVector & p1, const G4HEVector & p2);
void Add3( const G4HEVector & p1, const G4HEVector & p2);
void Sub3( const G4HEVector & p1, const G4HEVector & p2);
void Cross( const G4HEVector & p1, const G4HEVector & p2);
G4double Dot( const G4HEVector & p1, const G4HEVector & p2);
void Smul( const G4HEVector & p, G4double h);
void SmulAndUpdate( const G4HEVector & p, G4double h);
void Norz( const G4HEVector & p );
G4double Length();
void Exch( G4HEVector & p1);
void Defs1( const G4HEVector & p1, const G4HEVector & p2);
void Defs( const G4HEVector & p1, const G4HEVector & p2,
G4HEVector & my, G4HEVector & mz );
void Trac( const G4HEVector & p1, const G4HEVector & mx,
const G4HEVector & my, const G4HEVector & mz);
void setDefinition(G4String name);
G4int FillQuarkContent();
void Print( G4int L);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEXiMinusInelastic_h
#define G4HEXiMinusInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEXiMinusInelastic : public G4HEInelastic
{
public:
G4HEXiMinusInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEXiMinusInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasXiMinus(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,40 @@
// G4 Gheisha High Energy model class -- header file
// H. Fesefeldt, RWTH Aachen 23-October-1996
// Last modified: 10-December-1996
// A prototype of the Gheisha High Energy collision model.
#ifndef G4HEXiZeroInelastic_h
#define G4HEXiZeroInelastic_h 1
#include "G4HEInelastic.hh"
class G4HEXiZeroInelastic : public G4HEInelastic
{
public:
G4HEXiZeroInelastic() : G4HEInelastic()
{
G4int vecLen = 0;
}
~G4HEXiZeroInelastic(){ };
G4int vecLength;
G4VParticleChange * ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus );
G4int GetNumberOfSecondaries()
{ return vecLength; }
private:
void FirstIntInCasXiZero(G4bool &inElastic, const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight);
};
#endif
@@ -0,0 +1,593 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEAntiKaonZeroInelastic.hh"
G4VParticleChange * G4HEAntiKaonZeroInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double atomicWeight = targetNucleus.GetN();
const G4double atomicNumber = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEAntiKaonZeroInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEAntiKaonZeroInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasAntiKaonZero(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle );
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEAntiKaonZeroInelastic::FirstIntInCasAntiKaonZero( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle )
// AntiKaon0 undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int kaonMinusCode = KaonMinus.getCode();
G4int kaonZeroCode = KaonZero.getCode();
G4int antiKaonZeroCode = AntiKaonZero.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] =
pmltpc(np,nm,nz,nt,protb,c) ;
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] =
pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if (!inElastic || (availableEnergy <= PionPlus.getMass()))
return;
// inelastic scattering
np = 0, nm = 0, nz = 0;
G4double cech[] = { 1., 1., 1., 0.70, 0.60, 0.55, 0.35, 0.25, 0.18, 0.15};
G4int iplab = G4int( incidentTotalMomentum*5.);
if( (iplab < 10) && (G4UniformRand() < cech[iplab]) )
{
G4int iplab = min(19, G4int( incidentTotalMomentum*5.));
G4double cnk0[] = {0.17, 0.18, 0.17, 0.24, 0.26, 0.20, 0.22, 0.21, 0.34, 0.45,
0.58, 0.55, 0.36, 0.29, 0.29, 0.32, 0.32, 0.33, 0.33, 0.33};
if( G4UniformRand() < cnk0[iplab] )
{
if( targetCode == protonCode )
{
return;
}
else
{
pv[0] = KaonMinus;
pv[1] = Proton;
return;
}
}
G4double ran = G4UniformRand();
if( targetCode == protonCode ) // target is a proton
{
if( ran < 0.25 )
{
}
else if (ran < 0.50)
{
pv[0] = PionPlus;
pv[1] = SigmaZero;
}
else if (ran < 0.75)
{
}
else
{
pv[0] = PionPlus;
pv[1] = Lambda;
}
}
else
{ // target is a neutron
if( ran < 0.25 )
{
pv[0] = PionMinus;
pv[1] = SigmaPlus;
}
else if (ran < 0.50)
{
pv[0] = PionZero;
pv[1] = SigmaZero;
}
else if (ran < 0.75)
{
pv[0] = PionPlus;
pv[1] = SigmaMinus;
}
else
{
pv[0] = PionZero;
pv[1] = Lambda;
}
}
return;
}
else
{
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
}
outOfLoop: // <------------------------------------------------------------------------
if( targetCode == protonCode)
{
if( np == nm)
{
}
else if (np == (1+nm))
{
if( G4UniformRand() < 0.5)
{
pv[0] = KaonMinus;
}
else
{
pv[1] = Neutron;
}
}
else
{
pv[0] = KaonMinus;
pv[1] = Neutron;
}
}
else
{
if( np == nm)
{
if( G4UniformRand() < 0.75)
{
}
else
{
pv[0] = KaonMinus;
pv[1] = Proton;
}
}
else if ( np == (1+nm))
{
pv[0] = KaonMinus;
}
else
{
pv[1] = Proton;
}
}
if( G4UniformRand() < 0.5 )
{
if( ( (pv[0].getCode() == kaonMinusCode)
&& (pv[1].getCode() == neutronCode) )
|| ( (pv[0].getCode() == kaonZeroCode)
&& (pv[1].getCode() == protonCode) )
|| ( (pv[0].getCode() == antiKaonZeroCode)
&& (pv[1].getCode() == protonCode) ) )
{
G4double ran = G4UniformRand();
if( pv[1].getCode() == protonCode)
{
if(ran < 0.68)
{
pv[0] = PionPlus;
pv[1] = Lambda;
}
else if (ran < 0.84)
{
pv[0] = PionZero;
pv[1] = SigmaPlus;
}
else
{
pv[0] = PionPlus;
pv[1] = SigmaZero;
}
}
else
{
if(ran < 0.68)
{
pv[0] = PionMinus;
pv[1] = Lambda;
}
else if (ran < 0.84)
{
pv[0] = PionMinus;
pv[1] = SigmaZero;
}
else
{
pv[0] = PionZero;
pv[1] = SigmaMinus;
}
}
}
else
{
G4double ran = G4UniformRand();
if (ran < 0.67)
{
pv[0] = PionZero;
pv[1] = Lambda;
}
else if (ran < 0.78)
{
pv[0] = PionMinus;
pv[1] = SigmaPlus;
}
else if (ran < 0.89)
{
pv[0] = PionZero;
pv[1] = SigmaZero;
}
else
{
pv[0] = PionPlus;
pv[1] = SigmaMinus;
}
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,704 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEAntiLambdaInelastic.hh"
G4VParticleChange * G4HEAntiLambdaInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double atomicWeight = targetNucleus.GetN();
const G4double atomicNumber = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEAntiLambdaInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEAntiLambdaInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasAntiLambda(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEAntiLambdaInelastic::FirstIntInCasAntiLambda( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// AntiLambda undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numMulAn = 400;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double protmulAn[numMulAn],protnormAn[numSec];
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double neutmulAn[numMulAn],neutnormAn[numSec];
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul ; i++ ) protmul[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
// annihilation
for( i=0; i<numMulAn ; i++ ) protmulAn[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnormAn[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); np++ )
{
nm = max(0,np-1);
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
protmulAn[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnormAn[nt-1] += protmulAn[counter];
}
}
}
}
for( i=0; i<numMulAn; i++ ) neutmulAn[i] = 0.0;
for( i=0; i<numSec; i++ ) neutnormAn[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
neutmulAn[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnormAn[nt-1] += neutmulAn[counter];
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnormAn[i] > 0.0 )protnormAn[i] = 1.0/protnormAn[i];
if( neutnormAn[i] > 0.0 )neutnormAn[i] = 1.0/neutnormAn[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // some two-body reactions
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = min(9, G4int( incidentTotalMomentum*2.5));
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if ( targetCode == protonCode)
{
if(ran < 0.2)
{
pv[0] = AntiSigmaZero;
}
else if (ran < 0.4)
{
pv[0] = AntiSigmaMinus;
pv[1] = Neutron;
}
else if (ran < 0.6)
{
pv[0] = Proton;
pv[1] = AntiLambda;
}
else if (ran < 0.8)
{
pv[0] = Proton;
pv[1] = AntiSigmaZero;
}
else
{
pv[0] = Neutron;
pv[1] = AntiSigmaMinus;
}
}
else
{
if (ran < 0.2)
{
pv[0] = AntiSigmaZero;
}
else if (ran < 0.4)
{
pv[0] = AntiSigmaPlus;
pv[1] = Proton;
}
else if (ran < 0.6)
{
pv[0] = Neutron;
pv[1] = AntiLambda;
}
else if (ran < 0.8)
{
pv[0] = Neutron;
pv[1] = AntiSigmaZero;
}
else
{
pv[0] = Proton;
pv[1] = AntiSigmaPlus;
}
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
G4double anhl[] = {1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.97, 0.88,
0.85, 0.81, 0.75, 0.64, 0.64, 0.55, 0.55, 0.45, 0.47, 0.40,
0.39, 0.36, 0.33, 0.10, 0.01};
G4int iplab = G4int( incidentTotalMomentum*10.);
if ( iplab > 9) iplab = 10 + G4int( (incidentTotalMomentum -1.)*5. );
if ( iplab > 14) iplab = 15 + G4int( incidentTotalMomentum -2. );
if ( iplab > 22) iplab = 23 + G4int( (incidentTotalMomentum -10.)/10.);
iplab = min(24, iplab);
if ( G4UniformRand() > anhl[iplab] )
{ // non- annihilation channels
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
ran = G4UniformRand();
if( targetCode == protonCode)
{
if( np == nm)
{
if (ran < 0.40)
{
}
else if (ran < 0.8)
{
pv[0] = AntiSigmaZero;
}
else
{
pv[0] = AntiSigmaMinus;
pv[1] = Neutron;
}
}
else if (np == (nm+1))
{
if( ran < 0.25)
{
pv[1] = Neutron;
}
else if (ran < 0.5)
{
pv[0] = AntiSigmaZero;
pv[1] = Neutron;
}
else
{
pv[0] = AntiSigmaPlus;
}
}
else if (np == (nm-1))
{
pv[0] = AntiSigmaMinus;
}
else
{
pv[0] = AntiSigmaPlus;
pv[1] = Neutron;
}
}
else
{
if( np == nm)
{
if (ran < 0.4)
{
}
else if(ran < 0.8)
{
pv[0] = AntiSigmaZero;
}
else
{
pv[0] = AntiSigmaPlus;
pv[1] = Proton;
}
}
else if ( np == (nm-1))
{
if (ran < 0.5)
{
pv[0] = AntiSigmaMinus;
}
else if (ran < 0.75)
{
pv[1] = Proton;
}
else
{
pv[0] = AntiSigmaZero;
pv[1] = Proton;
}
}
else if (np == (nm+1))
{
pv[0] = AntiSigmaPlus;
}
else
{
pv[0] = AntiSigmaMinus;
pv[1] = Proton;
}
}
}
else // annihilation
{
if ( availableEnergy > 2. * PionPlus.getMass() )
{
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=2; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=1; np<numSec/3; np++ )
{
nm = np-1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmulAn[counter]*protnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; //----------------------->
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmulAn[counter]*neutnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; // -------------------------->
}
}
}
}
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoopAn: // <------------------------------------------------------------------
vecLen = 0;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,645 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEAntiNeutronInelastic.hh"
G4VParticleChange * G4HEAntiNeutronInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double atomicWeight = targetNucleus.GetN();
const G4double atomicNumber = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEAntiNeutronInelastic: incident energy < 1 GeV" << endl;;
}
if(verboseLevel > 1)
{
cout << "G4HEAntiNeutronInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasAntiNeutron(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEAntiNeutronInelastic::FirstIntInCasAntiNeutron( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// AntiNeutron undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numMulAn = 400;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double protmulAn[numMulAn],protnormAn[numSec];
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double neutmulAn[numMulAn],neutnormAn[numSec];
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul ; i++ ) protmul[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
// annihilation
for( i=0; i<numMulAn ; i++ ) protmulAn[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnormAn[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); np++ )
{
nm = max(0,np-1);
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
protmulAn[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnormAn[nt-1] += protmulAn[counter];
}
}
}
}
for( i=0; i<numMulAn; i++ ) neutmulAn[i] = 0.0;
for( i=0; i<numSec; i++ ) neutnormAn[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
neutmulAn[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnormAn[nt-1] += neutmulAn[counter];
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnormAn[i] > 0.0 )protnormAn[i] = 1.0/protnormAn[i];
if( neutnormAn[i] > 0.0 )neutnormAn[i] = 1.0/neutnormAn[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // nb n --> pb p
if( targetCode == neutronCode )
{
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = min(9, G4int( incidentTotalMomentum*2.5));
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
pv[0] = AntiProton;
pv[1] = Proton;
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0, nm = 0, nz = 0;
G4double anhl[] = {1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.97, 0.88,
0.85, 0.81, 0.75, 0.64, 0.64, 0.55, 0.55, 0.45, 0.47, 0.40,
0.39, 0.36, 0.33, 0.10, 0.01};
G4int iplab = G4int( incidentTotalMomentum*10.);
if ( iplab > 9) iplab = 10 + G4int( (incidentTotalMomentum -1.)*5. );
if ( iplab > 14) iplab = 15 + G4int( incidentTotalMomentum -2. );
if ( iplab > 22) iplab = 23 + G4int( (incidentTotalMomentum -10.)/10.);
iplab = min(24, iplab);
if ( G4UniformRand() > anhl[iplab] )
{
G4double eab = availableEnergy;
G4int ieab = G4int( eab*5.0 );
G4double supp[] = {0., 0.4, 0.55, 0.65, 0.75, 0.82, 0.86, 0.90, 0.94, 0.98};
if( (ieab <= 9) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one additional pion will be produced
G4double w0, wp, wm, wt, ran;
if( targetCode == protonCode ) // target is a proton
{
w0 = - sqr(1.+protb)/(2.*c*c);
w0 = wp = exp(w0);
if( G4UniformRand() < w0/(w0+wp) )
{ np = 0; nm = 0; nz = 1; }
else
{ np = 1; nm = 0; nz = 0; }
}
else
{ // target is a neutron
w0 = -sqr(1.+neutb)/(2.*c*c);
w0 = wp = exp(w0);
wm = -sqr(-1.+neutb)/(2.*c*c);
wm = exp(wm);
wt = w0+wp+wm;
wp = w0+wp;
ran = G4UniformRand();
if( ran < w0/wt)
{ np = 0; nm = 0; nz = 1; }
else if( ran < wp/wt)
{ np = 1; nm = 0; nz = 0; }
else
{ np = 0; nm = 1; nz = 0; }
}
}
else
{
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
}
outOfLoop: // <------------------------------------------------------------------------
if( targetCode == protonCode)
{
if( np == nm)
{
}
else if (np == (nm+1))
{
if( G4UniformRand() < 0.5)
{
pv[1] = Neutron;
}
else
{
pv[0] = AntiProton;
}
}
else
{
pv[0] = AntiProton;
pv[1] = Neutron;
}
}
else
{
if( np == nm)
{
if( G4UniformRand() < 0.25)
{
pv[0] = AntiProton;
pv[1] = Proton;
}
else
{
}
}
else if ( np == (nm-1))
{
pv[1] = Proton;
}
else
{
pv[0] = AntiProton;
}
}
}
else // annihilation
{
if ( availableEnergy > 2. * PionPlus.getMass() )
{
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=2; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=1; np<numSec/3; np++ )
{
nm = np-1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmulAn[counter]*protnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; //----------------------->
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmulAn[counter]*neutnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; // -------------------------->
}
}
}
}
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoopAn: // <------------------------------------------------------------------
vecLen = 0;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,700 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEAntiOmegaMinusInelastic.hh"
G4VParticleChange * G4HEAntiOmegaMinusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double atomicWeight = targetNucleus.GetN();
const G4double atomicNumber = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEAntiOmegaMinusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEAntiOmegaMinusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasAntiOmegaMinus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEAntiOmegaMinusInelastic::FirstIntInCasAntiOmegaMinus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight )
// AntiOmega undergoes interaction with nucleon within a nucleus.
// As in Geant3, we think that this routine has absolutely no influence
// on the whole performance of the program. Take AntiLambda instaed.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numMulAn = 400;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double protmulAn[numMulAn],protnormAn[numSec];
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double neutmulAn[numMulAn],neutnormAn[numSec];
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul ; i++ ) protmul[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
// annihilation
for( i=0; i<numMulAn ; i++ ) protmulAn[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnormAn[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); np++ )
{
nm = max(0,np-1);
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
protmulAn[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnormAn[nt-1] += protmulAn[counter];
}
}
}
}
for( i=0; i<numMulAn; i++ ) neutmulAn[i] = 0.0;
for( i=0; i<numSec; i++ ) neutnormAn[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
neutmulAn[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnormAn[nt-1] += neutmulAn[counter];
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnormAn[i] > 0.0 )protnormAn[i] = 1.0/protnormAn[i];
if( neutnormAn[i] > 0.0 )neutnormAn[i] = 1.0/neutnormAn[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // some two-body reactions
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = min(9, G4int( incidentTotalMomentum*2.5 ));
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if ( targetCode == protonCode)
{
if(ran < 0.2)
{
pv[0] = AntiSigmaZero;
}
else if (ran < 0.4)
{
pv[0] = AntiSigmaMinus;
pv[1] = Neutron;
}
else if (ran < 0.6)
{
pv[0] = Proton;
pv[1] = AntiLambda;
}
else if (ran < 0.8)
{
pv[0] = Proton;
pv[1] = AntiSigmaZero;
}
else
{
pv[0] = Neutron;
pv[1] = AntiSigmaMinus;
}
}
else
{
if (ran < 0.2)
{
pv[0] = AntiSigmaZero;
}
else if (ran < 0.4)
{
pv[0] = AntiSigmaPlus;
pv[1] = Proton;
}
else if (ran < 0.6)
{
pv[0] = Neutron;
pv[1] = AntiLambda;
}
else if (ran < 0.8)
{
pv[0] = Neutron;
pv[1] = AntiSigmaZero;
}
else
{
pv[0] = Proton;
pv[1] = AntiSigmaPlus;
}
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
G4double anhl[] = {1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.97, 0.88,
0.85, 0.81, 0.75, 0.64, 0.64, 0.55, 0.55, 0.45, 0.47, 0.40,
0.39, 0.36, 0.33, 0.10, 0.01};
G4int iplab = G4int( incidentTotalMomentum*10.);
if ( iplab > 9) iplab = 10 + G4int( (incidentTotalMomentum -1.)*5. );
if ( iplab > 14) iplab = 15 + G4int( incidentTotalMomentum -2. );
if ( iplab > 22) iplab = 23 + G4int( (incidentTotalMomentum -10.)/10.);
iplab = min(24, iplab);
if ( G4UniformRand() > anhl[iplab] )
{ // non- annihilation channels
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
ran = G4UniformRand();
if( targetCode == protonCode)
{
if( np == nm)
{
if (ran < 0.40)
{
}
else if (ran < 0.8)
{
pv[0] = AntiSigmaZero;
}
else
{
pv[0] = AntiSigmaMinus;
pv[1] = Neutron;
}
}
else if (np == (nm+1))
{
if( ran < 0.25)
{
pv[1] = Neutron;
}
else if (ran < 0.5)
{
pv[0] = AntiSigmaZero;
pv[1] = Neutron;
}
else
{
pv[0] = AntiSigmaPlus;
}
}
else if (np == (nm-1))
{
pv[0] = AntiSigmaMinus;
}
else
{
pv[0] = AntiSigmaPlus;
pv[1] = Neutron;
}
}
else
{
if( np == nm)
{
if (ran < 0.4)
{
}
else if(ran < 0.8)
{
pv[0] = AntiSigmaZero;
}
else
{
pv[0] = AntiSigmaPlus;
pv[1] = Proton;
}
}
else if ( np == (nm-1))
{
if (ran < 0.5)
{
pv[0] = AntiSigmaMinus;
}
else if (ran < 0.75)
{
pv[1] = Proton;
}
else
{
pv[0] = AntiSigmaZero;
pv[1] = Proton;
}
}
else if (np == (nm+1))
{
pv[0] = AntiSigmaPlus;
}
else
{
pv[0] = AntiSigmaMinus;
pv[1] = Proton;
}
}
}
else // annihilation
{
if ( availableEnergy > 2. * PionPlus.getMass() )
{
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=2; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=1; np<numSec/3; np++ )
{
nm = np-1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmulAn[counter]*protnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; //----------------------->
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmulAn[counter]*neutnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; // -------------------------->
}
}
}
}
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoopAn: // <------------------------------------------------------------------
vecLen = 0;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,650 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEAntiProtonInelastic.hh"
G4VParticleChange * G4HEAntiProtonInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double atomicWeight = targetNucleus.GetN();
const G4double atomicNumber = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEAntiProtonInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEAntiProtonInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasAntiProton(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEAntiProtonInelastic::FirstIntInCasAntiProton( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// AntiProton undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numMulAn = 400;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double protmulAn[numMulAn],protnormAn[numSec];
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double neutmulAn[numMulAn],neutnormAn[numSec];
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul ; i++ ) protmul[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
// annihilation
for( i=0; i<numMulAn ; i++ ) protmulAn[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnormAn[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmulAn[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnormAn[nt-1] += protmulAn[counter];
}
}
}
}
for( i=0; i<numMulAn; i++ ) neutmulAn[i] = 0.0;
for( i=0; i<numSec; i++ ) neutnormAn[i] = 0.0;
counter = -1;
for( np=1; np<numSec/3; np++ )
{
nm = np+1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmulAn[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnormAn[nt-1] += neutmulAn[counter];
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnormAn[i] > 0.0 )protnormAn[i] = 1.0/protnormAn[i];
if( neutnormAn[i] > 0.0 )neutnormAn[i] = 1.0/neutnormAn[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // pb p --> nb n
if( targetCode == protonCode )
{
G4double cech[] = {0.14, 0.170, 0.180, 0.180, 0.180, 0.170, 0.170, 0.160, 0.155, 0.145,
0.11, 0.082, 0.065, 0.050, 0.041, 0.035, 0.028, 0.024, 0.010, 0.000};
G4int iplab = G4int( incidentTotalMomentum*10.);
if (iplab > 9) iplab = min(19, G4int( incidentTotalMomentum) + 9);
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{ // charge exchange pi+ n -> pi0 p
pv[0] = AntiNeutron;
pv[1] = Neutron;
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
G4double anhl[] = {1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.90,
0.60, 0.52, 0.47, 0.44, 0.41, 0.39, 0.37, 0.35, 0.34, 0.24,
0.19, 0.15, 0.12, 0.10, 0.09, 0.07, 0.06, 0.05, 0.00};
G4int iplab = G4int( incidentTotalMomentum*10.);
if ( iplab > 9) iplab = 9 + G4int( incidentTotalMomentum);
if ( iplab > 18) iplab = 18 + G4int( incidentTotalMomentum*10.);
iplab = min(28, iplab);
if ( G4UniformRand() > anhl[iplab] )
{
G4double eab = availableEnergy;
G4int ieab = G4int( eab*5.0 );
G4double supp[] = {0., 0.4, 0.55, 0.65, 0.75, 0.82, 0.86, 0.90, 0.94, 0.98};
if( (ieab <= 9) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one additional pion will be produced
G4double w0, wp, wm, wt, ran;
if( targetCode == neutronCode ) // target is a neutron
{
w0 = - sqr(1.+neutb)/(2.*c*c);
w0 = exp(w0);
wm = - sqr(-1.+neutb)/(2.*c*c);
wm = exp(wm);
if( G4UniformRand() < w0/(w0+wm) )
{ np = 0; nm = 0; nz = 1; }
else
{ np = 0; nm = 1; nz = 0; }
}
else
{ // target is a proton
w0 = -sqr(1.+protb)/(2.*c*c);
w0 = exp(w0);
wp = w0;
wm = -sqr(-1.+protb)/(2.*c*c);
wm = exp(wm);
wt = w0+wp+wm;
wp = w0+wp;
ran = G4UniformRand();
if( ran < w0/wt)
{ np = 0; nm = 0; nz = 1; }
else if( ran < wp/wt)
{ np = 1; nm = 0; nz = 0; }
else
{ np = 0; nm = 1; nz = 0; }
}
}
else
{
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
}
outOfLoop: // <------------------------------------------------------------------------
if( targetCode == neutronCode)
{
if( np == nm)
{
}
else if (np == (nm-1))
{
if( G4UniformRand() < 0.5)
{
pv[1] = Proton;
}
else
{
pv[0] = AntiNeutron;
}
}
else
{
pv[0] = AntiNeutron;
pv[1] = Proton;
}
}
else
{
if( np == nm)
{
if( G4UniformRand() < 0.25)
{
pv[0] = AntiNeutron;
pv[1] = Neutron;
}
else
{
}
}
else if ( np == (1+nm))
{
pv[1] = Neutron;
}
else
{
pv[0] = AntiNeutron;
}
}
}
else // annihilation
{
if ( availableEnergy > 2. * PionPlus.getMass() )
{
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=2; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=1; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmulAn[counter]*protnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; //----------------------->
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=1; np<numSec/3; np++ )
{
nm = np+1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmulAn[counter]*neutnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; // -------------------------->
}
}
}
}
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoopAn: // <------------------------------------------------------------------
vecLen = 0;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,664 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEAntiSigmaMinusInelastic.hh"
G4VParticleChange * G4HEAntiSigmaMinusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double atomicWeight = targetNucleus.GetN();
const G4double atomicNumber = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEAntiSigmaMinusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEAntiSigmaMinusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasAntiSigmaMinus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEAntiSigmaMinusInelastic::FirstIntInCasAntiSigmaMinus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// AntiSigma- undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numMulAn = 400;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double protmulAn[numMulAn],protnormAn[numSec];
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double neutmulAn[numMulAn],neutnormAn[numSec];
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul ; i++ ) protmul[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
// annihilation
for( i=0; i<numMulAn ; i++ ) protmulAn[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnormAn[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); np++ )
{
nm = max(0,np-2);
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
protmulAn[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnormAn[nt-1] += protmulAn[counter];
}
}
}
}
for( i=0; i<numMulAn; i++ ) neutmulAn[i] = 0.0;
for( i=0; i<numSec; i++ ) neutnormAn[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np-1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
neutmulAn[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnormAn[nt-1] += neutmulAn[counter];
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnormAn[i] > 0.0 )protnormAn[i] = 1.0/protnormAn[i];
if( neutnormAn[i] > 0.0 )neutnormAn[i] = 1.0/neutnormAn[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // some two-body reactions
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = min(9, G4int( incidentTotalMomentum*2.5 ));
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if ( targetCode == neutronCode)
{
if(ran < 0.2)
{
pv[0] = AntiSigmaZero;
pv[1] = Proton;
}
else if (ran < 0.4)
{
pv[0] = AntiLambda;
pv[1] = Proton;
}
else if (ran < 0.6)
{
pv[0] = Proton;
pv[1] = AntiLambda;
}
else if (ran < 0.8)
{
pv[0] = Proton;
pv[1] = AntiSigmaZero;
}
else
{
pv[0] = Neutron;
pv[1] = AntiSigmaMinus;
}
}
else
{
pv[0] = Proton;
pv[1] = AntiSigmaMinus;
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
G4double anhl[] = {1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.97, 0.88,
0.85, 0.81, 0.75, 0.64, 0.64, 0.55, 0.55, 0.45, 0.47, 0.40,
0.39, 0.36, 0.33, 0.10, 0.01};
G4int iplab = G4int( incidentTotalMomentum*10.);
if ( iplab > 9) iplab = 10 + G4int( (incidentTotalMomentum -1.)*5. );
if ( iplab > 14) iplab = 15 + G4int( incidentTotalMomentum -2. );
if ( iplab > 22) iplab = 23 + G4int( (incidentTotalMomentum -10.)/10.);
iplab = min(24, iplab);
if ( G4UniformRand() > anhl[iplab] )
{ // non- annihilation channels
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
ran = G4UniformRand();
if( targetCode == protonCode)
{
if( np == nm)
{
}
else if (np == (nm+1))
{
if( ran < 0.50)
{
pv[1] = Neutron;
}
else if (ran < 0.75)
{
pv[0] = AntiSigmaZero;
}
else
{
pv[0] = AntiLambda;
}
}
else
{
if (ran < 0.5)
{
pv[0] = AntiSigmaZero;
pv[1] = Neutron;
}
else
{
pv[0] = AntiLambda;
pv[1] = Neutron;
}
}
}
else
{
if( np == nm)
{
if (ran < 0.5)
{
}
else if(ran < 0.75)
{
pv[0] = AntiSigmaZero;
pv[1] = Proton;
}
else
{
pv[0] = AntiLambda;
pv[1] = Proton;
}
}
else if ( np == (nm+1))
{
if (ran < 0.5)
{
pv[0] = AntiSigmaZero;
}
else
{
pv[0] = AntiLambda;
}
}
else
{
pv[1] = Proton;
}
}
}
else // annihilation
{
if ( availableEnergy > 2. * PionPlus.getMass() )
{
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=2; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=2; np<numSec/3; np++ )
{
nm = np-2;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmulAn[counter]*protnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; //----------------------->
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=1; np<numSec/3; np++ )
{
nm = np-1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmulAn[counter]*neutnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; // -------------------------->
}
}
}
}
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoopAn: // <------------------------------------------------------------------
vecLen = 0;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,664 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEAntiSigmaPlusInelastic.hh"
G4VParticleChange * G4HEAntiSigmaPlusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double atomicWeight = targetNucleus.GetN();
const G4double atomicNumber = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEAntiSigmaPlusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEAntiSigmaPlusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasAntiSigmaPlus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEAntiSigmaPlusInelastic::FirstIntInCasAntiSigmaPlus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// AntiSigma+ undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numMulAn = 400;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double protmulAn[numMulAn],protnormAn[numSec];
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double neutmulAn[numMulAn],neutnormAn[numSec];
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul ; i++ ) protmul[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
// annihilation
for( i=0; i<numMulAn ; i++ ) protmulAn[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnormAn[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
protmulAn[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnormAn[nt-1] += protmulAn[counter];
}
}
}
}
for( i=0; i<numMulAn; i++ ) neutmulAn[i] = 0.0;
for( i=0; i<numSec; i++ ) neutnormAn[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np+1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
neutmulAn[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnormAn[nt-1] += neutmulAn[counter];
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnormAn[i] > 0.0 )protnormAn[i] = 1.0/protnormAn[i];
if( neutnormAn[i] > 0.0 )neutnormAn[i] = 1.0/neutnormAn[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // some two-body reactions
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = min(9, G4int( incidentTotalMomentum*2.5));
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if ( targetCode == protonCode)
{
if(ran < 0.2)
{
pv[0] = Proton;
pv[1] = AntiSigmaPlus;
}
else if (ran < 0.4)
{
pv[0] = AntiLambda;
pv[1] = Neutron;
}
else if (ran < 0.6)
{
pv[0] = Neutron;
pv[1] = AntiLambda;
}
else if (ran < 0.8)
{
pv[0] = Neutron;
pv[1] = AntiSigmaZero;
}
else
{
pv[0] = AntiSigmaZero;
pv[1] = Neutron;
}
}
else
{
pv[0] = Neutron;
pv[1] = AntiSigmaPlus;
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
G4double anhl[] = {1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.97, 0.88,
0.85, 0.81, 0.75, 0.64, 0.64, 0.55, 0.55, 0.45, 0.47, 0.40,
0.39, 0.36, 0.33, 0.10, 0.01};
G4int iplab = G4int( incidentTotalMomentum*10.);
if ( iplab > 9) iplab = 10 + G4int( (incidentTotalMomentum -1.)*5. );
if ( iplab > 14) iplab = 15 + G4int( incidentTotalMomentum -2. );
if ( iplab > 22) iplab = 23 + G4int( (incidentTotalMomentum -10.)/10.);
iplab = min(24, iplab);
if ( G4UniformRand() > anhl[iplab] )
{ // non- annihilation channels
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
ran = G4UniformRand();
if( targetCode == protonCode)
{
if( np == nm)
{
if (ran < 0.50)
{
}
else if (ran < 0.75)
{
pv[0] = AntiSigmaZero;
pv[1] = Neutron;
}
else
{
pv[0] = AntiLambda;
pv[1] = Neutron;
}
}
else if (np == (nm-1))
{
if( ran < 0.50)
{
pv[0] = AntiLambda;
}
else
{
pv[0] = AntiSigmaZero;
}
}
else
{
pv[1] = Neutron;
}
}
else
{
if( np == nm)
{
}
else if ( np == (nm-1))
{
if (ran < 0.5)
{
pv[1] = Proton;
}
else if (ran < 0.75)
{
pv[0] = AntiLambda;
}
else
{
pv[0] = AntiSigmaZero;
}
}
else
{
if (ran < 0.5)
{
pv[0] = AntiLambda;
pv[1] = Proton;
}
else
{
pv[0] = AntiSigmaZero;
pv[1] = Proton;
}
}
}
}
else // annihilation
{
if ( availableEnergy > 2. * PionPlus.getMass() )
{
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=2; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=1; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmulAn[counter]*protnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; //----------------------->
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np+1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmulAn[counter]*neutnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; // -------------------------->
}
}
}
}
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoopAn: // <------------------------------------------------------------------
vecLen = 0;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,54 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEAntiSigmaZeroInelastic.hh"
#include "G4Gamma.hh"
G4VParticleChange * G4HEAntiSigmaZeroInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4HEVector incidentParticle(aParticle);
G4HEAntiLambdaInelastic theAntiLambdaInelastic;
theAntiLambdaInelastic.SetMaxNumberOfSecondaries(MAXPART);
theAntiLambdaInelastic.SetVerboseLevel(verboseLevel);
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double pgam = G4UniformRand()*incidentTotalMomentum*0.75;
G4HEVector incidentAntiLambda;
incidentAntiLambda.SmulAndUpdate( incidentParticle,
(incidentTotalMomentum - pgam)/incidentTotalMomentum);
G4DynamicParticle * aLambda = new G4DynamicParticle();
aLambda->SetDefinition(G4AntiLambda::AntiLambda());
G4Track aLambdaTrack(aLambda, 0, aTrack.GetPosition());
aLambda->SetMomentum(incidentAntiLambda.getMomentum());
G4VParticleChange * result = theAntiLambdaInelastic.ApplyYourself(aLambdaTrack, targetNucleus);
vecLength = theAntiLambdaInelastic.GetNumberOfSecondaries();
pv[vecLength] = Gamma;
pv[vecLength].setMomentum(incidentParticle.getMomentum());
pv[vecLength].SmulAndUpdate( pv[vecLength],pgam/incidentTotalMomentum);
G4DynamicParticle * aPhoton = new G4DynamicParticle();
aPhoton->SetDefinition(G4Gamma::Gamma());
aPhoton->SetMomentum(pv[vecLength].getMomentum());
G4Track * aGammaTrack = new G4Track(aPhoton, aTrack.GetGlobalTime(), aTrack.GetPosition());
result->AddSecondary(aGammaTrack);
delete [] pv;
return result;
}
@@ -0,0 +1,703 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEAntiXiMinusInelastic.hh"
G4VParticleChange * G4HEAntiXiMinusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEAntiXiMinusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEAntiXiMinusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasAntiXiMinus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles";
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEAntiXiMinusInelastic::FirstIntInCasAntiXiMinus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// AntiXi- undergoes interaction with nucleon within a nucleus.
// As in Geant3, we think that this routine has absolutely no influence
// on the whole performance of the program. Take AntiLambda instaed.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numMulAn = 400;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double protmulAn[numMulAn],protnormAn[numSec];
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double neutmulAn[numMulAn],neutnormAn[numSec];
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul ; i++ ) protmul[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
// annihilation
for( i=0; i<numMulAn ; i++ ) protmulAn[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnormAn[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); np++ )
{
nm = max(0,np-1);
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
protmulAn[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnormAn[nt-1] += protmulAn[counter];
}
}
}
}
for( i=0; i<numMulAn; i++ ) neutmulAn[i] = 0.0;
for( i=0; i<numSec; i++ ) neutnormAn[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
neutmulAn[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnormAn[nt-1] += neutmulAn[counter];
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnormAn[i] > 0.0 )protnormAn[i] = 1.0/protnormAn[i];
if( neutnormAn[i] > 0.0 )neutnormAn[i] = 1.0/neutnormAn[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // some two-body reactions
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = min(9, G4int( incidentTotalMomentum*2.5));
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if ( targetCode == protonCode)
{
if(ran < 0.2)
{
pv[0] = AntiSigmaZero;
}
else if (ran < 0.4)
{
pv[0] = AntiSigmaMinus;
pv[1] = Neutron;
}
else if (ran < 0.6)
{
pv[0] = Proton;
pv[1] = AntiLambda;
}
else if (ran < 0.8)
{
pv[0] = Proton;
pv[1] = AntiSigmaZero;
}
else
{
pv[0] = Neutron;
pv[1] = AntiSigmaMinus;
}
}
else
{
if (ran < 0.2)
{
pv[0] = AntiSigmaZero;
}
else if (ran < 0.4)
{
pv[0] = AntiSigmaPlus;
pv[1] = Proton;
}
else if (ran < 0.6)
{
pv[0] = Neutron;
pv[1] = AntiLambda;
}
else if (ran < 0.8)
{
pv[0] = Neutron;
pv[1] = AntiSigmaZero;
}
else
{
pv[0] = Proton;
pv[1] = AntiSigmaPlus;
}
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
G4double anhl[] = {1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.97, 0.88,
0.85, 0.81, 0.75, 0.64, 0.64, 0.55, 0.55, 0.45, 0.47, 0.40,
0.39, 0.36, 0.33, 0.10, 0.01};
G4int iplab = G4int( incidentTotalMomentum*10.);
if ( iplab > 9) iplab = 10 + G4int( (incidentTotalMomentum -1.)*5. );
if ( iplab > 14) iplab = 15 + G4int( incidentTotalMomentum -2. );
if ( iplab > 22) iplab = 23 + G4int( (incidentTotalMomentum -10.)/10.);
iplab = min(24, iplab);
if ( G4UniformRand() > anhl[iplab] )
{ // non- annihilation channels
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
ran = G4UniformRand();
if( targetCode == protonCode)
{
if( np == nm)
{
if (ran < 0.40)
{
}
else if (ran < 0.8)
{
pv[0] = AntiSigmaZero;
}
else
{
pv[0] = AntiSigmaMinus;
pv[1] = Neutron;
}
}
else if (np == (nm+1))
{
if( ran < 0.25)
{
pv[1] = Neutron;
}
else if (ran < 0.5)
{
pv[0] = AntiSigmaZero;
pv[1] = Neutron;
}
else
{
pv[0] = AntiSigmaPlus;
}
}
else if (np == (nm-1))
{
pv[0] = AntiSigmaMinus;
}
else
{
pv[0] = AntiSigmaPlus;
pv[1] = Neutron;
}
}
else
{
if( np == nm)
{
if (ran < 0.4)
{
}
else if(ran < 0.8)
{
pv[0] = AntiSigmaZero;
}
else
{
pv[0] = AntiSigmaPlus;
pv[1] = Proton;
}
}
else if ( np == (nm-1))
{
if (ran < 0.5)
{
pv[0] = AntiSigmaMinus;
}
else if (ran < 0.75)
{
pv[1] = Proton;
}
else
{
pv[0] = AntiSigmaZero;
pv[1] = Proton;
}
}
else if (np == (nm+1))
{
pv[0] = AntiSigmaPlus;
}
else
{
pv[0] = AntiSigmaMinus;
pv[1] = Proton;
}
}
}
else // annihilation
{
if ( availableEnergy > 2. * PionPlus.getMass() )
{
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=2; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=1; np<numSec/3; np++ )
{
nm = np-1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmulAn[counter]*protnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; //----------------------->
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmulAn[counter]*neutnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; // -------------------------->
}
}
}
}
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoopAn: // <------------------------------------------------------------------
vecLen = 0;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,704 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEAntiXiZeroInelastic.hh"
G4VParticleChange * G4HEAntiXiZeroInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEAntiXiZeroInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEAntiXiZeroInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasAntiXiZero(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEAntiXiZeroInelastic::FirstIntInCasAntiXiZero( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// AntiXi0 undergoes interaction with nucleon within a nucleus.
// As in Geant3, we think that this routine has absolutely no influence
// on the whole performance of the program. Take AntiLambda instaed.
// ( decay Xi0 -> L Pi > 99 % )
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numMulAn = 400;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double protmulAn[numMulAn],protnormAn[numSec];
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
static G4double neutmulAn[numMulAn],neutnormAn[numSec];
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul ; i++ ) protmul[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
// annihilation
for( i=0; i<numMulAn ; i++ ) protmulAn[i] = 0.0;
for( i=0; i<numSec ; i++ ) protnormAn[i] = 0.0;
counter = -1;
for( np=1; np<(numSec/3); np++ )
{
nm = max(0,np-1);
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
protmulAn[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnormAn[nt-1] += protmulAn[counter];
}
}
}
}
for( i=0; i<numMulAn; i++ ) neutmulAn[i] = 0.0;
for( i=0; i<numSec; i++ ) neutnormAn[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
neutmulAn[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnormAn[nt-1] += neutmulAn[counter];
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnormAn[i] > 0.0 )protnormAn[i] = 1.0/protnormAn[i];
if( neutnormAn[i] > 0.0 )neutnormAn[i] = 1.0/neutnormAn[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // some two-body reactions
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = min(9, G4int( incidentTotalMomentum*2.5 ));
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if ( targetCode == protonCode)
{
if(ran < 0.2)
{
pv[0] = AntiSigmaZero;
}
else if (ran < 0.4)
{
pv[0] = AntiSigmaMinus;
pv[1] = Neutron;
}
else if (ran < 0.6)
{
pv[0] = Proton;
pv[1] = AntiLambda;
}
else if (ran < 0.8)
{
pv[0] = Proton;
pv[1] = AntiSigmaZero;
}
else
{
pv[0] = Neutron;
pv[1] = AntiSigmaMinus;
}
}
else
{
if (ran < 0.2)
{
pv[0] = AntiSigmaZero;
}
else if (ran < 0.4)
{
pv[0] = AntiSigmaPlus;
pv[1] = Proton;
}
else if (ran < 0.6)
{
pv[0] = Neutron;
pv[1] = AntiLambda;
}
else if (ran < 0.8)
{
pv[0] = Neutron;
pv[1] = AntiSigmaZero;
}
else
{
pv[0] = Proton;
pv[1] = AntiSigmaPlus;
}
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
G4double anhl[] = {1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.97, 0.88,
0.85, 0.81, 0.75, 0.64, 0.64, 0.55, 0.55, 0.45, 0.47, 0.40,
0.39, 0.36, 0.33, 0.10, 0.01};
G4int iplab = G4int( incidentTotalMomentum*10.);
if ( iplab > 9) iplab = 10 + G4int( (incidentTotalMomentum -1.)*5. );
if ( iplab > 14) iplab = 15 + G4int( incidentTotalMomentum -2. );
if ( iplab > 22) iplab = 23 + G4int( (incidentTotalMomentum -10.)/10.);
iplab = min(24, iplab);
if ( G4UniformRand() > anhl[iplab] )
{ // non- annihilation channels
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
ran = G4UniformRand();
if( targetCode == protonCode)
{
if( np == nm)
{
if (ran < 0.40)
{
}
else if (ran < 0.8)
{
pv[0] = AntiSigmaZero;
}
else
{
pv[0] = AntiSigmaMinus;
pv[1] = Neutron;
}
}
else if (np == (nm+1))
{
if( ran < 0.25)
{
pv[1] = Neutron;
}
else if (ran < 0.5)
{
pv[0] = AntiSigmaZero;
pv[1] = Neutron;
}
else
{
pv[0] = AntiSigmaPlus;
}
}
else if (np == (nm-1))
{
pv[0] = AntiSigmaMinus;
}
else
{
pv[0] = AntiSigmaPlus;
pv[1] = Neutron;
}
}
else
{
if( np == nm)
{
if (ran < 0.4)
{
}
else if(ran < 0.8)
{
pv[0] = AntiSigmaZero;
}
else
{
pv[0] = AntiSigmaPlus;
pv[1] = Proton;
}
}
else if ( np == (nm-1))
{
if (ran < 0.5)
{
pv[0] = AntiSigmaMinus;
}
else if (ran < 0.75)
{
pv[1] = Proton;
}
else
{
pv[0] = AntiSigmaZero;
pv[1] = Proton;
}
}
else if (np == (nm+1))
{
pv[0] = AntiSigmaPlus;
}
else
{
pv[0] = AntiSigmaMinus;
pv[1] = Proton;
}
}
}
else // annihilation
{
if ( availableEnergy > 2. * PionPlus.getMass() )
{
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=2; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=1; np<numSec/3; np++ )
{
nm = np-1;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmulAn[counter]*protnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; //----------------------->
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
nm = np;
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMulAn )
{
nt = np+nm+nz;
if( (nt>1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmulAn[counter]*neutnormAn[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoopAn; // -------------------------->
}
}
}
}
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoopAn: // <------------------------------------------------------------------
vecLen = 0;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getCode() << " " ;
cout << pv[1].getCode() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getCode() << " " ;
}
cout << endl;
}
return;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,600 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEKaonMinusInelastic.hh"
G4VParticleChange * G4HEKaonMinusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEKaonMinusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEKaonMinusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasKaonMinus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEKaonMinusInelastic::FirstIntInCasKaonMinus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle)
// Kaon- undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int kaonMinusCode = KaonMinus.getCode();
G4int kaonZeroCode = KaonZero.getCode();
G4int antiKaonZeroCode = AntiKaonZero.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-1); nm<=np+1; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] =
pmltpc(np,nm,nz,nt,protb,c) ;
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] =
pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if (!inElastic || (availableEnergy <= PionPlus.getMass()))
return;
// inelastic scattering
np = 0, nm = 0, nz = 0;
G4double cech[] = { 1., 1., 1., 0.70, 0.60, 0.55, 0.35, 0.25, 0.18, 0.15};
G4int iplab = G4int( incidentTotalMomentum*5.);
if( (iplab < 10) && (G4UniformRand() < cech[iplab]))
{
G4int iplab = min(19, G4int( incidentTotalMomentum*5.));
G4double cnk0[] = {0.17, 0.18, 0.17, 0.24, 0.26, 0.20, 0.22, 0.21, 0.34, 0.45,
0.58, 0.55, 0.36, 0.29, 0.29, 0.32, 0.32, 0.33, 0.33, 0.33};
if( G4UniformRand() < cnk0[iplab] )
{
if( targetCode == protonCode )
{
pv[0] = AntiKaonZero;
pv[1] = Neutron;
return;
}
else
{
return;
}
}
G4double ran = G4UniformRand();
if( targetCode == protonCode ) // target is a proton
{
if( ran < 0.25 )
{
pv[0] = PionMinus;
pv[1] = SigmaPlus;
}
else if (ran < 0.50)
{
pv[0] = PionZero;
pv[1] = SigmaZero;
}
else if (ran < 0.75)
{
pv[0] = PionPlus;
pv[1] = SigmaMinus;
}
else
{
pv[0] = PionZero;
pv[1] = Lambda;
}
}
else
{ // target is a neutron
if( ran < 0.25 )
{
}
else if (ran < 0.50)
{
pv[0] = PionMinus;
pv[1] = SigmaZero;
}
else if (ran < 0.75)
{
pv[0] = PionZero;
pv[1] = SigmaMinus;
}
else
{
pv[0] = PionMinus;
pv[1] = Lambda;
}
}
return;
}
else
{
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=np+1; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
}
outOfLoop: // <------------------------------------------------------------------------
if( targetCode == protonCode)
{
if( np == (1+nm))
{
pv[1] = Neutron;
}
else if (np == nm)
{
if( G4UniformRand() < 0.75)
{
}
else
{
pv[0] = AntiKaonZero;
pv[1] = Neutron;
}
}
else
{
pv[0] = AntiKaonZero;
}
}
else
{
if( np == (nm-1))
{
if( G4UniformRand() < 0.5)
{
pv[1] = Proton;
}
else
{
pv[0] = AntiKaonZero;
}
}
else if ( np == nm)
{
}
else
{
pv[0] = AntiKaonZero;
pv[1] = Proton;
}
}
if( G4UniformRand() < 0.5 )
{
if( ( (pv[0].getCode() == kaonMinusCode)
&& (pv[1].getCode() == neutronCode) )
|| ( (pv[0].getCode() == kaonZeroCode)
&& (pv[1].getCode() == protonCode) )
|| ( (pv[0].getCode() == antiKaonZeroCode)
&& (pv[1].getCode() == protonCode) ) )
{
G4double ran = G4UniformRand();
if( pv[1].getCode() == protonCode)
{
if(ran < 0.68)
{
pv[0] = PionPlus;
pv[1] = Lambda;
}
else if (ran < 0.84)
{
pv[0] = PionZero;
pv[1] = SigmaPlus;
}
else
{
pv[0] = PionPlus;
pv[1] = SigmaZero;
}
}
else
{
if(ran < 0.68)
{
pv[0] = PionMinus;
pv[1] = Lambda;
}
else if (ran < 0.84)
{
pv[0] = PionMinus;
pv[1] = SigmaZero;
}
else
{
pv[0] = PionZero;
pv[1] = SigmaMinus;
}
}
}
else
{
G4double ran = G4UniformRand();
if (ran < 0.67)
{
pv[0] = PionZero;
pv[1] = Lambda;
}
else if (ran < 0.78)
{
pv[0] = PionMinus;
pv[1] = SigmaPlus;
}
else if (ran < 0.89)
{
pv[0] = PionZero;
pv[1] = SigmaZero;
}
else
{
pv[0] = PionPlus;
pv[1] = SigmaMinus;
}
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,508 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEKaonPlusInelastic.hh"
G4VParticleChange * G4HEKaonPlusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEKaonPlusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEKaonPlusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasKaonPlus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEKaonPlusInelastic::FirstIntInCasKaonPlus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Kaon+ undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] =
pmltpc(np,nm,nz,nt,protb,c) ;
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] =
pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
if( targetCode == neutronCode )
{
G4double cech[] = {0.33,0.27,0.29,0.31,0.27,0.18,0.13,0.10,0.09,0.07};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*5. ) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{ // charge exchange K+ n -> K0 p
pv[0] = KaonZero;
pv[1] = Proton;
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0, nm = 0, nz = 0;
G4double eab = availableEnergy;
G4int ieab = G4int( eab*5.0 );
G4double supp[] = {0., 0.4, 0.55, 0.65, 0.75, 0.82, 0.86, 0.90, 0.94, 0.98};
if( (ieab <= 9) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one additional pion will be produced
G4double w0, wp, wm, wt, ran;
if( targetCode == protonCode ) // target is a proton
{
w0 = - sqr(1.+protb)/(2.*c*c);
wp = w0 = exp(w0);
wp *= 2.;
if( G4UniformRand() < w0/(w0+wp) )
{ np = 0; nm = 0; nz = 1; }
else
{ np = 1; nm = 0; nz = 0; }
}
else
{ // target is a neutron
w0 = -sqr(1.+neutb)/(2.*c*c);
wp = w0 = exp(w0);
wm = -sqr(-1.+neutb)/(2.*c*c);
wm = exp(wm);
wt = w0+wp+wm;
wp = w0+wp;
ran = G4UniformRand();
if( ran < w0/wt)
{ np = 0; nm = 0; nz = 1; }
else if( ran < wp/wt)
{ np = 1; nm = 0; nz = 0; }
else
{ np = 0; nm = 1; nz = 0; }
}
}
else
{
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
}
outOfLoop: // <------------------------------------------------------------------------
if( targetCode == protonCode)
{
if( np == nm)
{
}
else if (np == (1+nm))
{
if( G4UniformRand() < 0.5)
{
pv[1] = Neutron;
}
else
{
pv[0] = KaonZero;
}
}
else
{
pv[0] = KaonZero;
pv[1] = Neutron;
}
}
else
{
if( np == nm)
{
if( G4UniformRand() < 0.25)
{
pv[0] = KaonZero;
pv[1] = Proton;
}
else
{
}
}
else if ( np == (1+nm))
{
pv[0] = KaonZero;
}
else
{
pv[1] = Proton;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,507 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEKaonZeroInelastic.hh"
G4VParticleChange * G4HEKaonZeroInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEKaonZeroInelastic: incident energy < 1 GeV" << endl;;
}
if(verboseLevel > 1)
{
cout << "G4HEKaonZeroInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasKaonZero(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEKaonZeroInelastic::FirstIntInCasKaonZero( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Kaon0 undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] =
pmltpc(np,nm,nz,nt,protb,c) ;
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] =
pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
if( targetCode == protonCode )
{
G4double cech[] = {0.33,0.27,0.29,0.31,0.27,0.18,0.13,0.10,0.09,0.07};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*5. ) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{ // charge exchange K+ n -> K0 p
pv[0] = KaonPlus;
pv[1] = Neutron;
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0, nm = 0, nz = 0;
G4double eab = availableEnergy;
G4int ieab = G4int( eab*5.0 );
G4double supp[] = {0., 0.4, 0.55, 0.65, 0.75, 0.82, 0.86, 0.90, 0.94, 0.98};
if( (ieab <= 9) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one additional pion will be produced
G4double w0, wp, wm, wt, ran;
if( targetCode == neutronCode ) // target is a neutron
{
w0 = - sqr(1.+protb)/(2.*c*c);
w0 = exp(w0);
wm = - sqr(-1.+protb)/(2.*c*c);
wm = exp(wm);
w0 = w0/2.;
wm = wm*1.5;
if( G4UniformRand() < w0/(w0+wm) ) { np = 0; nm = 0; nz = 1; }
else
{ np = 0; nm = 1; nz = 0; }
}
else
{ // target is a proton
w0 = -sqr(1.+neutb)/(2.*c*c);
wp = w0 = exp(w0);
wm = -sqr(-1.+neutb)/(2.*c*c);
wm = exp(wm);
wt = w0+wp+wm;
wp = w0+wp;
ran = G4UniformRand();
if( ran < w0/wt)
{ np = 0; nm = 0; nz = 1; }
else if( ran < wp/wt)
{ np = 1; nm = 0; nz = 0; }
else
{ np = 0; nm = 1; nz = 0; }
}
}
else
{
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
}
outOfLoop: // <------------------------------------------------------------------------
if( targetCode == neutronCode)
{
if( np == nm)
{
}
else if (np == (nm-1))
{
if( G4UniformRand() < 0.5)
{
pv[0] = KaonPlus;
}
else
{
pv[1] = Proton;
}
}
else
{
pv[0] = KaonPlus;
pv[1] = Proton;
}
}
else
{
if( np == nm )
{
if( G4UniformRand() < 0.25)
{
pv[0] = KaonPlus;
pv[1] = Neutron;
}
else
{
}
}
else if ( np == (nm+1))
{
pv[1] = Neutron;
}
else
{
pv[0] = KaonPlus;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return; }
@@ -0,0 +1,37 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEKaonZeroLongInelastic.hh"
G4VParticleChange * G4HEKaonZeroLongInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEKaonZeroInelastic theKaonZeroInelastic;
G4HEAntiKaonZeroInelastic theAntiKaonZeroInelastic;
theKaonZeroInelastic.SetVerboseLevel(verboseLevel);
theAntiKaonZeroInelastic.SetVerboseLevel(verboseLevel);
if(G4UniformRand() < 0.50)
{
return theKaonZeroInelastic.ApplyYourself(aTrack, targetNucleus);
}
else
{
return theAntiKaonZeroInelastic.ApplyYourself(aTrack, targetNucleus);
}
}
@@ -0,0 +1,37 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEKaonZeroShortInelastic.hh"
G4VParticleChange * G4HEKaonZeroShortInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEKaonZeroInelastic theKaonZeroInelastic;
G4HEAntiKaonZeroInelastic theAntiKaonZeroInelastic;
theKaonZeroInelastic.SetVerboseLevel(verboseLevel);
theAntiKaonZeroInelastic.SetVerboseLevel(verboseLevel);
if(G4UniformRand() < 0.50)
{
return theKaonZeroInelastic.ApplyYourself(aTrack, targetNucleus);
}
else
{
return theAntiKaonZeroInelastic.ApplyYourself(aTrack, targetNucleus);
}
}
@@ -0,0 +1,557 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HELambdaInelastic.hh"
G4VParticleChange * G4HELambdaInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHELambdaInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HELambdaInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasLambda(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HELambdaInelastic::FirstIntInCasLambda( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Lambda undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*2.5 ) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if( targetCode == protonCode)
{
if( ran < 0.2)
{
pv[0] = SigmaPlus;
pv[1] = Neutron;
}
else if(ran < 0.4)
{
pv[0] = SigmaZero;
}
else if(ran < 0.6)
{
pv[0] = Proton;
pv[1] = Lambda;
}
else if(ran < 0.8)
{
pv[0] = Proton;
pv[1] = SigmaZero;
}
else
{
pv[0] = Neutron;
pv[1] = SigmaPlus;
}
}
else
{
if(ran < 0.2)
{
pv[0] = SigmaZero;
}
else if(ran < 0.4)
{
pv[0] = SigmaMinus;
pv[1] = Proton;
}
else if(ran < 0.6)
{
pv[0] = Neutron;
pv[1] = Lambda;
}
else if(ran < 0.8)
{
pv[0] = Neutron;
pv[1] = SigmaZero;
}
else
{
pv[0] = Proton;
pv[1] = SigmaMinus;
}
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
ran = G4UniformRand();
if( targetCode == protonCode)
{
if( np == nm)
{
if (ran < 0.25)
{
}
else if(ran < 0.5)
{
pv[0] = SigmaZero;
}
else
{
pv[0] = SigmaPlus;
pv[1] = Neutron;
}
}
else if (np == (nm+1))
{
if( G4UniformRand() < 0.25)
{
pv[1] = Neutron;
}
else if(ran < 0.5)
{
pv[0] = SigmaZero;
pv[1] = Neutron;
}
else
{
pv[0] = SigmaMinus;
}
}
else if (np == (nm-1))
{
pv[0] = SigmaPlus;
}
else
{
pv[0] = SigmaMinus;
pv[1] = Neutron;
}
}
else
{
if (np == nm)
{
if(ran < 0.5)
{
}
else
{
pv[0] = SigmaMinus;
pv[1] = Proton;
}
}
else if (np == (nm-1))
{
if( ran < 0.25)
{
pv[1] = Proton;
}
else if(ran < 0.5)
{
pv[0] = SigmaZero;
pv[1] = Proton;
}
else
{
pv[1] = SigmaPlus;
}
}
else if (np == (1+nm))
{
pv[0] = SigmaMinus;
}
else
{
pv[0] = SigmaPlus;
pv[1] = Proton;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,507 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HENeutronInelastic.hh"
G4VParticleChange * G4HENeutronInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHENeutronInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HENeutronInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasNeutron(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HENeutronInelastic::FirstIntInCasNeutron( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Neutron undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.35;
static const G4double neutb = 0.35;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c)
/(Factorial(1-np+nm)*Factorial(1+np-nm)) ;
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c)
/(Factorial(-np+nm)*Factorial(2+np-nm));
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
if( targetCode == protonCode )
{
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*2.5) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{ // charge exchange n p -> p n
pv[0] = Proton;
pv[1] = Neutron;
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0, nm = 0, nz = 0;
G4double eab = availableEnergy;
G4int ieab = G4int( eab*5.0 );
G4double supp[] = {0., 0.4, 0.55, 0.65, 0.75, 0.82, 0.86, 0.90, 0.94, 0.98};
if( (ieab <= 9) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one additional pion will be produced
G4double w0, wp, wm, wt, ran;
if( targetCode == neutronCode ) // target is a neutron
{
w0 = - sqr(1.+neutb)/(2.*c*c);
wm = w0 = exp(w0);
w0 = w0/2.;
if( G4UniformRand() < w0/(w0+wm) )
{ np = 0; nm = 0; nz = 1; }
else
{ np = 0; nm = 1; nz = 0; }
}
else
{ // target is a proton
w0 = -sqr(1.+protb)/(2.*c*c);
w0 = exp(w0);
wp = w0/2.;
wm = -sqr(-1.+protb)/(2.*c*c);
wm = exp(wm)/2.;
wt = w0+wp+wm;
wp = w0+wp;
ran = G4UniformRand();
if( ran < w0/wt)
{ np = 0; nm = 0; nz = 1; }
else if( ran < wp/wt)
{ np = 1; nm = 0; nz = 0; }
else
{ np = 0; nm = 1; nz = 0; }
}
}
else
{
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
}
outOfLoop: // <------------------------------------------------------------------------
if( targetCode == neutronCode)
{
if( np == nm)
{
}
else if (np == (nm-1))
{
if( G4UniformRand() < 0.5)
{
pv[1] = Proton;
}
else
{
pv[0] = Proton;
}
}
else
{
pv[0] = Proton;
pv[1] = Proton;
}
}
else
{
if( np == nm)
{
if( G4UniformRand() < 0.25)
{
pv[0] = Proton;
pv[1] = Neutron;
}
else
{
}
}
else if ( np == (1+nm))
{
pv[1] = Neutron;
}
else
{
pv[0] = Proton;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,498 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEOmegaMinusInelastic.hh"
G4VParticleChange * G4HEOmegaMinusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEOmegaMinusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEOmegaMinusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasOmegaMinus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEOmegaMinusInelastic::FirstIntInCasOmegaMinus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Xi0 undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-1); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*2.5 ) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if( targetCode == protonCode)
{
if (ran < 0.2)
{
pv[0] = XiZero;
pv[1] = SigmaZero;
}
else if (ran < 0.4)
{
pv[0] = SigmaZero;
pv[1] = XiZero;
}
else if (ran < 0.6)
{
pv[0] = XiZero;
pv[1] = Lambda;
}
else if (ran < 0.8)
{
pv[0] = Lambda;
pv[1] = XiZero;
}
else
{
pv[0] = Proton;
pv[1] = OmegaMinus;
}
}
else
{
if (ran < 0.2)
{
pv[0] = Neutron;
pv[1] = OmegaMinus;
}
else if (ran < 0.4)
{
pv[0] = XiZero;
pv[1] = SigmaMinus;
}
else if (ran < 0.6)
{
pv[0] = SigmaMinus;
pv[1] = XiZero;
}
else if (ran < 0.8)
{
pv[0] = XiMinus;
pv[1] = Lambda;
}
else
{
pv[0] = Lambda;
pv[1] = XiMinus;
}
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
// in the following we do not consider
ran = G4UniformRand(); // strangeness transfer in high multiplicity
if( targetCode == protonCode) // events. YK combinations are added in
{ // StrangeParticlePairProduction
if( np == nm)
{
}
else
{
pv[1] = Neutron;
}
}
else
{
if (np == nm)
{
}
else
{
pv[1] = Proton;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,510 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEPionMinusInelastic.hh"
G4VParticleChange * G4HEPionMinusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEPionMinusInelastic: incident energy < 1 GeV" << endl ;
}
if(verboseLevel > 1)
{
cout << "G4HEPionMinusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasPionMinus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEPionMinusInelastic::FirstIntInCasPionMinus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle)
// Pion- undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] =
pmltpc(np,nm,nz,nt,protb,c) ;
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] =
pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if (!inElastic || (availableEnergy <= PionPlus.getMass()))
return;
// inelastic scattering
np = 0, nm = 0, nz = 0;
G4double eab = availableEnergy;
G4int ieab = G4int( eab*5.0 );
G4double supp[] = {0., 0.4, 0.55, 0.65, 0.75, 0.82, 0.86, 0.90, 0.94, 0.98};
if( (ieab <= 9) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one additional pion will be produced
G4double cech[] = {1., 0.95, 0.79, 0.32, 0.19, 0.16, 0.14, 0.12, 0.10, 0.08};
G4int iplab = max(9, G4int( incidentTotalMomentum*5.));
if( G4UniformRand() < cech[iplab] )
{
if( targetCode == protonCode )
{
pv[0] = PionZero;
pv[1] = Neutron;
return;
}
else
{
return;
}
}
G4double w0, wp, wm, wt, ran;
if( targetCode == protonCode ) // target is a proton
{
w0 = - sqr(1.+protb)/(2.*c*c);
wp = w0 = exp(w0);
wm = - sqr(-1.+protb)/(2.*c*c);
wm = exp(wm);
wp *= 10.;
wt = w0+wp+wm;
wp = w0+wp;
ran = G4UniformRand();
if( ran < w0/wt )
{ np = 0; nm = 0; nz = 1; }
else if ( ran < wp/wt )
{ np = 1; nm = 0; nz = 0; }
else
{ np = 0; nm = 1; nz = 0; }
}
else
{ // target is a neutron
w0 = -sqr(1.+neutb)/(2.*c*c);
wm = -sqr(-1.+neutb)/(2.*c*c);
w0 = exp(w0);
wm = exp(wm);
if( G4UniformRand() < w0/(w0+wm) )
{ np = 0; nm = 0; nz = 1; }
else
{ np = 0; nm = 1; nz = 0; }
}
}
else
{
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
}
outOfLoop: // <------------------------------------------------------------------------
if( targetCode == protonCode)
{
if( np == (1+nm))
{
pv[1] = Neutron;
}
else if (np == nm)
{
if( G4UniformRand() < 0.75)
{
}
else
{
pv[0] = PionZero;
pv[0] = Neutron;
}
}
else
{
pv[0] = PionZero;
}
}
else
{
if( np == (nm-1))
{
if( G4UniformRand() < 0.5)
{
pv[1] = Proton;
}
else
{
pv[0] = PionZero;
}
}
else if ( np == nm)
{
}
else
{
pv[0] = PionZero;
pv[1] = Proton;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,506 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEPionPlusInelastic.hh"
G4VParticleChange * G4HEPionPlusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "G4HEPionPlusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEPionPlusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasPionPlus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEPionPlusInelastic::FirstIntInCasPionPlus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Pion+ undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4double pionMass = PionPlus.getMass();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] =
pmltpc(np,nm,nz,nt,protb,c) ;
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] =
pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
if( targetCode == neutronCode )
{
G4double cech[] = {0.33,0.27,0.29,0.31,0.27,0.18,0.13,0.10,0.09,0.07};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*5. ) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{ // charge exchange pi+ n -> pi0 p
pv[0] = PionZero;
pv[1] = Proton;
}
}
return;
}
else if (availableEnergy <= pionMass)
return;
// inelastic scattering
np = 0, nm = 0, nz = 0;
G4double eab = availableEnergy;
G4int ieab = G4int( eab*5.0 );
G4double supp[] = {0., 0.2, 0.45, 0.55, 0.65, 0.75, 0.85, 0.90, 0.94, 0.98};
if( (ieab <= 9) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one additional pion will be produced
G4double w0, wp, wm, wt, ran;
if( targetCode == protonCode ) // target is a proton
{
w0 = - sqr(1.+protb)/(2.*c*c);
wp = w0 = exp(w0);
if( G4UniformRand() < w0/(w0+wp) )
{ np = 0; nm = 0; nz = 1; }
else
{ np = 1; nm = 0; nz = 0; }
}
else
{ // target is a neutron
w0 = -sqr(1.+neutb)/(2.*c*c);
wp = w0 = exp(w0);
wm = -sqr(-1.+neutb)/(2.*c*c);
wm = exp(wm);
wt = w0+wp+wm;
wp = w0+wp;
ran = G4UniformRand();
if( ran < w0/wt)
{ np = 0; nm = 0; nz = 1; }
else if( ran < wp/wt)
{ np = 1; nm = 0; nz = 0; }
else
{ np = 0; nm = 1; nz = 0; }
}
}
else
{
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
}
outOfLoop: // <------------------------------------------------------------------------
if( targetCode == protonCode)
{
if( np == nm)
{
}
else if (np == (1+nm))
{
if( G4UniformRand() < 0.5)
{
pv[1] = Neutron;
}
else
{
pv[0] = PionZero;
}
}
else
{
pv[0] = PionZero;
pv[1] = Neutron;
}
}
else
{
if( np == nm)
{
if( G4UniformRand() < 0.25)
{
pv[0] = PionZero;
pv[1] = Proton;
}
else
{
}
}
else if ( np == (1+nm))
{
pv[0] = PionZero;
}
else
{
pv[1] = Proton;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,336 @@
// G4 Gheisha friend class G4GHEPlot
// last modified: H. Fesefeldt 02-July--1998
#include "G4HEPlot.hh"
void
G4HEPlot::Init( G4int nbin, G4double xstart, G4double xbin )
{
Xbin = xbin;
Nbin = nbin;
Xstart = xstart;
Entries = 0;
EntriesOverflow = 0;
EntriesUnderflow = 0;
Weight = 0.;
WeightOverflow = 0.;
WeightUnderflow = 0.;
Xvalue = new G4double[Nbin];
Yvalue = new G4double[Nbin];
for(G4int i=0; i<Nbin; i++)
{
Xvalue[i] = Xstart + i*Xbin;
Yvalue[i] = 0.;
}
return;
}
void
G4HEPlot::Add( G4double s1, G4double s2,
const G4HEPlot & p1, const G4HEPlot & p2 )
{
if(p1.Nbin != p2.Nbin)
{
cout << "G4HEPlot::Add: Plots must have same number of bins !" << endl;
return;
}
if(Nbin != p1.Nbin)
{
cout << "G4HEPlot::Add: Plot must be initialized before using it !" << endl;
return;
}
for(G4int i=0; i<Nbin; i++)
{
Yvalue[i] = s1*p1.Yvalue[i] + s2*p2.Yvalue[i];
}
Entries = p1.Entries + p2.Entries;
EntriesOverflow = p1.EntriesOverflow + p2.EntriesOverflow;
EntriesUnderflow = p1.EntriesUnderflow + p2.EntriesUnderflow;
Weight = s1*p1.Weight + s2*p2.Weight;
WeightUnderflow = s1*p1.WeightUnderflow + s2*p2.WeightUnderflow;
WeightOverflow = s1*p1.WeightOverflow + s2*p2.WeightOverflow;
return;
}
void
G4HEPlot::Multiply( G4double s1, G4double s2,
const G4HEPlot & p1, const G4HEPlot & p2 )
{
if(p1.Nbin != p2.Nbin)
{
cout << "G4HEPlot::Multiply: Plots must have same number of bins !" << endl;
return;
}
if(Nbin != p1.Nbin)
{
cout << "G4HEPlot::Multiply: Plot must be initialized before using it !" << endl;
return;
}
for(G4int i=0; i<Nbin; i++)
{
Yvalue[i] = s1*p1.Yvalue[i]* s2*p2.Yvalue[i];
}
Entries = p1.Entries * p2.Entries;
EntriesOverflow = p1.EntriesOverflow * p2.EntriesOverflow;
EntriesUnderflow = p1.EntriesUnderflow * p2.EntriesUnderflow;
Weight = s1*p1.Weight * s2*p2.Weight;
WeightUnderflow = s1*p1.WeightUnderflow * s2*p2.WeightUnderflow;
WeightOverflow = s1*p1.WeightOverflow * s2*p2.WeightOverflow;
return;
}
void
G4HEPlot::Divide( G4double s1, G4double s2,
const G4HEPlot & p1, const G4HEPlot & p2 )
{
if(p1.Nbin != p2.Nbin)
{
cout << "G4HEPlot::Divide: Plots must have same number of bins !" << endl;
return;
}
if(Nbin != p1.Nbin)
{
cout << "G4HEPlot::Divide: Plot must be defined before using it !" << endl;
return;
}
for(G4int i=0; i<Nbin; i++)
{
if(p2.Yvalue[i] == 0.)
{
Yvalue[i] = 0.;
}
else
{
Yvalue[i] = (s1*p1.Yvalue[i]) / (s2*p2.Yvalue[i]);
}
}
if(p2.Entries > 0)
Entries = p1.Entries / p2.Entries;
if(p2.EntriesOverflow > 0)
EntriesOverflow = p1.EntriesOverflow / p2.EntriesOverflow;
if(p2.EntriesUnderflow > 0)
EntriesUnderflow = p1.EntriesUnderflow / p2.EntriesUnderflow;
if(p2.Weight != 0.)
Weight = s1*p1.Weight / s2*p2.Weight;
if(p2.WeightUnderflow != 0.)
WeightUnderflow = s1*p1.WeightUnderflow / s2*p2.WeightUnderflow;
if(p2.WeightOverflow != 0.)
WeightOverflow = s1*p1.WeightOverflow / s2*p2.WeightOverflow;
return;
}
void
G4HEPlot::Scale( G4double s, const G4HEPlot & p)
{
if(Nbin != p.Nbin)
{
cout << "G4HEPlot::Add: Plot must be defined before using it !" << endl;
return;
}
for(G4int i=0; i<Nbin; i++)
{
Yvalue[i] = s*p.Yvalue[i];
}
Entries = p.Entries ;
EntriesOverflow = p.EntriesOverflow;
EntriesUnderflow = p.EntriesUnderflow;
Weight = s*p.Weight;
WeightUnderflow = s*p.WeightUnderflow;
WeightOverflow = s*p.WeightOverflow;
return;
}
void
G4HEPlot::XScale(G4double a, G4double b, const G4HEPlot & p)
{
G4int i;
Entries = 0;
EntriesOverflow = 0;
EntriesUnderflow = 0;
Weight = 0.;
WeightOverflow = 0.;
WeightUnderflow = 0.;
Xstart = p.Xstart;
Xbin = p.Xbin;
Nbin = p.Nbin;
for(i=0; i<Nbin; i++)
{
Xvalue[i] = p.Yvalue[i];
Yvalue[i] = 0.;
}
G4double xval = Xstart - Xbin/2.;
for(i=0; i<Nbin; i++)
{
xval += Xbin;
Fill(xval*a + b, Xvalue[i]);
}
for(i=0; i<Nbin; i++)
{
Xvalue[i] = Xstart + i*Xbin;
}
}
void
G4HEPlot::Log( G4double s, const G4HEPlot & p)
{
if(Nbin != p.Nbin)
{
cout << "G4HEPlot::Log: Plot must be defined before using it !" << endl;
return;
}
for(G4int i=0; i<Nbin; i++)
{
if(s*p.Yvalue[i] <= 0.) Yvalue[i] = 0.;
else Yvalue[i] = log10(s*p.Yvalue[i]);
}
Entries = p.Entries ;
EntriesOverflow = p.EntriesOverflow;
EntriesUnderflow = p.EntriesUnderflow;
if(p.Weight > 0)
Weight = log10(s*p.Weight);
if(p.WeightUnderflow > 0)
WeightUnderflow = log10(s*p.WeightUnderflow);
if(p.WeightOverflow > 0)
WeightOverflow = log10(s*p.WeightOverflow);
return;
}
void
G4HEPlot::Sqrt(G4double s, const G4HEPlot & p)
{
if(Nbin != p.Nbin)
{
cout << " G4HEPlot::Sqrt: Plot must be defined before using it !" << endl;
return;
}
for (G4int i=0; i<Nbin; i++)
{
if(s*p.Yvalue[i] <= 0.) Yvalue[i] = 0.;
else Yvalue[i] = sqrt(s*p.Yvalue[i]);
}
Entries = p.Entries;
EntriesOverflow = p.EntriesOverflow;
EntriesUnderflow = p.EntriesUnderflow;
if(s*p.Weight > 0.) Weight = sqrt(s*p.Weight);
if(s*p.WeightUnderflow > 0.) WeightUnderflow = sqrt(s*p.WeightUnderflow);
if(s*p.WeightOverflow > 0.) WeightOverflow = sqrt(s*p.WeightOverflow);
return;
}
void
G4HEPlot::Reset()
{
for(G4int i=0; i<Nbin; i++)
{
Yvalue[i] = 0.;
}
Entries = 0;
EntriesOverflow = 0;
EntriesUnderflow = 0;
Weight = 0.;
WeightOverflow = 0.;
WeightUnderflow = 0.;
return;
}
void
G4HEPlot::Fill(G4double x, G4double weight)
{
G4int i = (int)((x - Xstart)/Xbin);
if(i < 0)
{
EntriesUnderflow++;
WeightUnderflow += weight;
}
else if(i >= Nbin)
{
EntriesOverflow++;
WeightOverflow += weight;
}
else
{
Entries++;
Weight += weight;
Yvalue[i] += weight;
}
return;
}
void
G4HEPlot::Print( G4String name, G4int iplot)
{
cout << name << iplot << " = new TH1F(" << '"' << iplot
<< '"' << "," << '"' << '"' << "," << Nbin << ","
<< Xstart << "," << Xstart+Nbin*Xbin << ");" << endl;
cout << "for(I=1; I<=" << Nbin <<"; I++) {" << endl;
cout << "Y[I] = 0.;" << endl;
cout << "}" << endl;
for (G4int i=0; i<Nbin; i++)
{
cout << "Y[" << i+1 << "] = " << Yvalue[i] << ";" << endl;
}
cout << "XA = " << Xstart << ";" << endl;
cout << "STEP2 = " << Xbin/2. << ";" << endl;
cout << "for(I=1; I<=" << Nbin << "; I++) {" << endl;
cout << "XA = XA + STEP2;" << endl;
cout << name << iplot << "->Fill(XA,Y[I]);" << endl;
cout << "XA = XA + STEP2;" << endl;
cout << "}" << endl;
return;
}
void
G4HEPlot::DumpToFile(G4int aPlot, G4String aName)
{
FILE* fz;
fz = fopen(aName, "a");
fprintf(fz,"%3d %3d %12.5e %12.5e \n",aPlot, Nbin, Xstart, Xbin);
G4double xval = Xstart - Xbin/2.;
for(G4int i=0; i<Nbin; i++)
{
xval += Xbin;
fprintf(fz,"%12.5e %12.5e \n", xval, Yvalue[i]);
}
fclose(fz);
}
void
G4HEPlot::GetFromFile(G4int aPlot, G4String aName)
{
FILE* fz;
G4int ip, nb;
G4double xs,xb,x,y;
if((fz = fopen(aName, "r")) != NULL)
{
while(fscanf(fz,"%ld %ld %le %le", &ip, &nb, &xs, &xb)==4)
{
if(ip == aPlot)
{
if(Nbin != nb) Init(nb, xs, xb);
}
for (G4int i=0; i<nb; i++)
{
fscanf(fz,"%le %le", &x, &y);
if(ip == aPlot) Fill(x,y);
}
if(ip == aPlot) break;
}
fclose(fz);
return;
}
else
{
cout << " File " << aName << " not found " << endl;
}
return;
}
@@ -0,0 +1,512 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998.
#include "G4HEProtonInelastic.hh"
G4VParticleChange * G4HEProtonInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
SetParticles();
if(verboseLevel > 1)
cout << "Z , A = " << atomicNumber << " " << atomicWeight << endl;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentParticle.getKineticEnergy();
if(incidentKineticEnergy < 1.)
{
cout << "GHEProtonInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEProtonInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName() << " "
<< "mass " << incidentMass << " "
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << " " << excitationEnergyGNP << " "
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasProton(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEProtonInelastic::FirstIntInCasProton( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Proton undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.35;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4double pionMass = PionPlus.getMass();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c)
/(Factorial(2-np+nm)*Factorial(np-nm)) ;
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c)
/(Factorial(1-np+nm)*Factorial(1+np-nm));
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
if( targetCode == neutronCode )
{
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*2.5 ) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{ // charge exchange pi+ n -> pi0 p
pv[0] = PionZero;
pv[1] = Proton;
}
}
return;
}
else if (availableEnergy <= pionMass)
return;
// inelastic scattering
np = 0, nm = 0, nz = 0;
G4double eab = availableEnergy;
G4int ieab = G4int( eab*5.0 );
G4double supp[] = {0., 0.4, 0.55, 0.65, 0.75, 0.82, 0.86, 0.90, 0.94, 0.98};
if( (ieab <= 9) && (G4UniformRand() >= supp[ieab]) )
{
// suppress high multiplicity events at low momentum
// only one additional pion will be produced
G4double w0, wp, wm, wt, ran;
if( targetCode == protonCode ) // target is a proton
{
w0 = - sqr(1.+protb)/(2.*c*c);
wp = w0 = exp(w0);
if( G4UniformRand() < w0/(w0+wp) )
{ np = 0; nm = 0; nz = 1; }
else
{ np = 1; nm = 0; nz = 0; }
}
else
{ // target is a neutron
w0 = -sqr(1.+neutb)/(2.*c*c);
w0 = exp(w0);
wp = w0/2.;
wm = -sqr(-1.+neutb)/(2.*c*c);
wm = exp(wm)/2.;
wt = w0+wp+wm;
wp = w0+wp;
ran = G4UniformRand();
if( ran < w0/wt)
{ np = 0; nm = 0; nz = 1; }
else if( ran < wp/wt)
{ np = 1; nm = 0; nz = 0; }
else
{ np = 0; nm = 1; nz = 0; }
}
}
else
{
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
}
outOfLoop: // <------------------------------------------------------------------------
if( targetCode == protonCode)
{
if( np == nm)
{
}
else if (np == (1+nm))
{
if( G4UniformRand() < 0.5)
{
pv[1] = Neutron;
}
else
{
pv[0] = Neutron;
}
}
else
{
pv[0] = Neutron;
pv[1] = Neutron;
}
}
else
{
if( np == nm)
{
if( G4UniformRand() < 0.25)
{
pv[0] = Neutron;
pv[1] = Proton;
}
else
{
}
}
else if ( np == (1+nm))
{
pv[0] = Neutron;
}
else
{
pv[1] = Proton;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,522 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HESigmaMinusInelastic.hh"
G4VParticleChange * G4HESigmaMinusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHESigmaMinusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HESigmaMinusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasSigmaMinus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HESigmaMinusInelastic::FirstIntInCasSigmaMinus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Sigma- undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*2.5 ) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if( targetCode == neutronCode)
{
pv[0] = Neutron;
pv[1] = SigmaMinus;
}
else
{
if(ran < 0.2)
{
pv[0] = SigmaZero;
pv[1] = Neutron;
}
else if(ran < 0.4)
{
pv[0] = Lambda;
pv[1] = Neutron;
}
else if(ran < 0.6)
{
pv[0] = Proton;
pv[1] = SigmaMinus;
}
else if(ran < 0.8)
{
pv[0] = Neutron;
pv[1] = SigmaZero;
}
else
{
pv[0] = Neutron;
pv[1] = Lambda;
}
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0, nm = 0, nz = 0;
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
ran = G4UniformRand();
if( targetCode == neutronCode)
{
if( np == nm)
{
}
else if (np == (nm-1))
{
if( ran < 0.25)
{
pv[0] = SigmaZero;
}
else if (ran < 0.5)
{
pv[0] = Lambda;
}
else
{
pv[1] = Proton;
}
}
else
{
if(ran < 0.5)
{
pv[0] = SigmaZero;
pv[1] = Proton;
}
else
{
pv[0] = Lambda;
pv[1] = Proton;
}
}
}
else
{
if (np == nm)
{
if (ran < 0.5)
{
}
else if (ran < 0.75)
{
pv[0] = SigmaZero;
pv[1] = Neutron;
}
else
{
pv[0] = Lambda;
pv[1] = Neutron;
}
}
else if (np == (nm+1))
{
pv[1] = Neutron;
}
else
{
if (ran < 0.5)
{
pv[0] = SigmaZero;
}
else
{
pv[0] = Lambda;
}
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getCode() << " " ;
cout << pv[1].getCode() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getCode() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,522 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HESigmaPlusInelastic.hh"
G4VParticleChange * G4HESigmaPlusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHESigmaPlusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HESigmaPlusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasSigmaPlus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HESigmaPlusInelastic::FirstIntInCasSigmaPlus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Sigma+ undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*2.5 ) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if( targetCode == protonCode)
{
pv[0] = Proton;
pv[1] = SigmaPlus;
}
else
{
if(ran < 0.2)
{
pv[0] = SigmaZero;
pv[1] = Proton;
}
else if(ran < 0.4)
{
pv[0] = Lambda;
pv[1] = Proton;
}
else if(ran < 0.6)
{
pv[0] = Neutron;
pv[1] = SigmaPlus;
}
else if(ran < 0.8)
{
pv[0] = Proton;
pv[1] = SigmaZero;
}
else
{
pv[0] = Proton;
pv[1] = Lambda;
}
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
ran = G4UniformRand();
if( targetCode == protonCode)
{
if( np == nm)
{
}
else if (np == (nm+1))
{
if( ran < 0.25)
{
pv[0] = SigmaZero;
}
else if(ran < 0.5)
{
pv[0] = Lambda;
}
else
{
pv[1] = Neutron;
}
}
else
{
if(ran < 0.5)
{
pv[0] = SigmaZero;
pv[1] = Neutron;
}
else
{
pv[0] = Lambda;
pv[1] = Neutron;
}
}
}
else
{
if (np == nm)
{
if (ran < 0.5)
{
}
else if (ran < 0.75)
{
pv[0] = SigmaZero;
pv[1] = Proton;
}
else
{
pv[0] = Lambda;
pv[1] = Proton;
}
}
else if (np == (nm-1))
{
pv[1] = Proton;
}
else
{
if (ran < 0.5)
{
pv[0] = SigmaZero;
}
else
{
pv[0] = Lambda;
}
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,57 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HESigmaZeroInelastic.hh"
#include "G4Gamma.hh"
G4VParticleChange * G4HESigmaZeroInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
G4HEVector incidentParticle(aParticle);
G4HELambdaInelastic theLambdaInelastic;
theLambdaInelastic.SetMaxNumberOfSecondaries(MAXPART);
theLambdaInelastic.SetVerboseLevel(verboseLevel);
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double pgam = G4UniformRand()*incidentTotalMomentum*0.75;
G4HEVector incidentLambda;
incidentLambda.SmulAndUpdate( incidentParticle,
(incidentTotalMomentum - pgam)/incidentTotalMomentum);
G4DynamicParticle * aLambda = new G4DynamicParticle();
aLambda->SetDefinition(G4Lambda::Lambda());
G4Track aLambdaTrack(aLambda, 0, aTrack.GetPosition());
aLambda->SetMomentum(incidentLambda.getMomentum());
G4VParticleChange * result = theLambdaInelastic.ApplyYourself(aLambdaTrack, targetNucleus);
vecLength = theLambdaInelastic.GetNumberOfSecondaries();
pv[vecLength] = Gamma;
pv[vecLength].setMomentum(incidentParticle.getMomentum());
pv[vecLength].SmulAndUpdate( pv[vecLength],pgam/incidentTotalMomentum);
G4DynamicParticle * aPhoton = new G4DynamicParticle();
aPhoton->SetDefinition(G4Gamma::Gamma());
aPhoton->SetMomentum(pv[vecLength].getMomentum());
G4Track * aGammaTrack = new G4Track(aPhoton, aTrack.GetGlobalTime(), aTrack.GetPosition());
result->AddSecondary(aGammaTrack);
delete [] pv;
return result;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,532 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEXiMinusInelastic.hh"
G4VParticleChange * G4HEXiMinusInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEXiMinusInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEXiMinusInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasXiMinus(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEXiMinusInelastic::FirstIntInCasXiMinus( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Xi0 undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*2.5 ) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if( targetCode == neutronCode)
{
if (ran < 0.2)
{
pv[0] = SigmaMinus;
pv[1] = SigmaZero;
}
else if (ran < 0.4)
{
pv[0] = SigmaZero;
pv[1] = SigmaMinus;
}
else if (ran < 0.6)
{
pv[0] = SigmaMinus;
pv[1] = Lambda;
}
else if (ran < 0.8)
{
pv[0] = Lambda;
pv[1] = SigmaMinus;
}
else
{
pv[0] = Neutron;
pv[1] = XiMinus;
}
}
else
{
if (ran < 0.2)
{
pv[0] = SigmaZero;
pv[1] = SigmaZero;
}
else if (ran < 0.3)
{
pv[0] = Lambda;
pv[1] = Lambda;
}
else if (ran < 0.4)
{
pv[0] = SigmaZero;
pv[1] = Lambda;
}
else if (ran < 0.5)
{
pv[0] = Lambda;
pv[1] = SigmaZero;
}
else if (ran < 0.7)
{
pv[0] = SigmaZero;
pv[1] = Neutron;
}
else if (ran < 0.8)
{
pv[0] = Neutron;
pv[1] = SigmaZero;
}
else
{
pv[0] = Proton;
pv[1] = XiMinus;
}
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=np; nm<=(np+2); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
// in the following we do not consider
ran = G4UniformRand(); // strangeness transfer in high multiplicity
if( targetCode == neutronCode) // events. YK combinations are added in
{ // StrangeParticlePairProduction
if( np == nm)
{
}
else if (np == (nm-1))
{
if( ran < 0.50)
{
pv[0] = XiZero;
}
else
{
pv[1] = Proton;
}
}
else
{
pv[0] = XiZero;
pv[1] = Proton;
}
}
else
{
if (np == nm)
{
if (ran < 0.5)
{
}
else
{
pv[0] = XiZero;
pv[1] = Neutron;
}
}
else if (np == (nm+1))
{
pv[1] = Neutron;
}
else
{
pv[0] = XiZero;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getName() << " " ;
cout << pv[1].getName() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getName() << " " ;
}
cout << endl;
}
return;
}
@@ -0,0 +1,542 @@
// G4 Process: Gheisha High Energy Collision model.
// This includes the high energy cascading model, the two-body-resonance model
// and the low energy two-body model. Not included are the low energy stuff like
// nuclear reactions, nuclear fission without any cascading and all processes for
// particles at rest.
// First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.
// H. Fesefeldt, RWTH-Aachen, 23-October-1996
// Last modified: 29-July-1998
#include "G4HEXiZeroInelastic.hh"
G4VParticleChange * G4HEXiZeroInelastic::
ApplyYourself( const G4Track &aTrack, G4Nucleus &targetNucleus )
{
G4HEVector * pv = new G4HEVector[MAXPART];
theParticleChange.Initialize( aTrack );
const G4DynamicParticle *aParticle = aTrack.GetDynamicParticle();
G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
const G4double A = targetNucleus.GetN();
const G4double Z = targetNucleus.GetZ();
G4HEVector incidentParticle(aParticle);
G4double atomicNumber = Z;
G4double atomicWeight = A;
G4int incidentCode = incidentParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentTotalEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
G4double incidentKineticEnergy = incidentTotalEnergy - incidentMass;
if(incidentKineticEnergy < 1.)
{
cout << "GHEXiZeroInelastic: incident energy < 1 GeV" << endl;
}
if(verboseLevel > 1)
{
cout << "G4HEXiZeroInelastic::ApplyYourself" << endl;
cout << "incident particle " << incidentParticle.getName()
<< "mass " << incidentMass
<< "kinetic energy " << incidentKineticEnergy
<< endl;
cout << "target material with (A,Z) = ("
<< atomicWeight << "," << atomicNumber << ")" << endl;
}
G4double inelasticity = NuclearInelasticity(incidentKineticEnergy,
atomicWeight, atomicNumber);
if(verboseLevel > 1)
cout << "nuclear inelasticity = " << inelasticity << endl;
incidentKineticEnergy -= inelasticity;
G4double excitationEnergyGNP = 0.;
G4double excitationEnergyDTA = 0.;
G4double excitation = NuclearExcitation(incidentKineticEnergy,
atomicWeight, atomicNumber,
excitationEnergyGNP,
excitationEnergyDTA);
if(verboseLevel > 1)
cout << "nuclear excitation = " << excitation << excitationEnergyGNP
<< excitationEnergyDTA << endl;
incidentKineticEnergy -= excitation;
incidentTotalEnergy = incidentKineticEnergy + incidentMass;
incidentTotalMomentum = sqrt( (incidentTotalEnergy-incidentMass)
*(incidentTotalEnergy+incidentMass));
G4HEVector targetParticle;
if(G4UniformRand() < atomicNumber/atomicWeight)
{
targetParticle.setDefinition("Proton");
}
else
{
targetParticle.setDefinition("Neutron");
}
G4double targetMass = targetParticle.getMass();
G4double centerOfMassEnergy = sqrt( incidentMass*incidentMass + targetMass*targetMass
+ 2.0*targetMass*incidentTotalEnergy);
G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
// this was the meaning of inElastic in the
// original Gheisha stand-alone version.
// G4bool inElastic = InElasticCrossSectionInFirstInt
// (availableEnergy, incidentCode, incidentTotalMomentum);
// by unknown reasons, it has been replaced
// to the following code in Geant???
G4bool inElastic = true;
// if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;
vecLength = 0;
if(verboseLevel > 1)
cout << "ApplyYourself: CallFirstIntInCascade for particle "
<< incidentCode << endl;
G4bool successful = false;
if(inElastic || (!inElastic && atomicWeight < 1.5))
{
FirstIntInCasXiZero(inElastic, availableEnergy, pv, vecLength,
incidentParticle, targetParticle, atomicWeight);
if(verboseLevel > 1)
cout << "ApplyYourself::StrangeParticlePairProduction" << endl;
if ((vecLength > 0) && (availableEnergy > 1.))
StrangeParticlePairProduction( availableEnergy, centerOfMassEnergy,
pv, vecLength,
incidentParticle, targetParticle);
HighEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
HighEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyCascading( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
MediumEnergyClusterProduction( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
if (!successful)
QuasiElasticScattering( successful, pv, vecLength,
excitationEnergyGNP, excitationEnergyDTA,
incidentParticle, targetParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
ElasticScattering( successful, pv, vecLength,
incidentParticle,
atomicWeight, atomicNumber);
}
if (!successful)
{
cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" << endl;
}
FillParticleChange(pv, vecLength);
delete [] pv;
theParticleChange.SetStatusChange(fStopAndKill);
return & theParticleChange;
}
void
G4HEXiZeroInelastic::FirstIntInCasXiZero( G4bool &inElastic,
const G4double availableEnergy,
G4HEVector pv[],
G4int &vecLen,
G4HEVector incidentParticle,
G4HEVector targetParticle,
const G4double atomicWeight)
// Xi0 undergoes interaction with nucleon within a nucleus. Check if it is
// energetically possible to produce pions/kaons. In not, assume nuclear excitation
// occurs and input particle is degraded in energy. No other particles are produced.
// If reaction is possible, find the correct number of pions/protons/neutrons
// produced using an interpolation to multiplicity data. Replace some pions or
// protons/neutrons by kaons or strange baryons according to the average
// multiplicity per inelastic reaction.
{
static const G4double expxu = log(MAXFLOAT); // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
static const G4double protb = 0.7;
static const G4double neutb = 0.7;
static const G4double c = 1.25;
static const G4int numMul = 1200;
static const G4int numSec = 60;
G4int neutronCode = Neutron.getCode();
G4int protonCode = Proton.getCode();
G4int targetCode = targetParticle.getCode();
G4double incidentMass = incidentParticle.getMass();
G4double incidentEnergy = incidentParticle.getEnergy();
G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
static G4bool first = true;
static G4double protmul[numMul], protnorm[numSec]; // proton constants
static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
// misc. local variables
// np = number of pi+, nm = number of pi-, nz = number of pi0
G4int i, counter, nt, np, nm, nz;
if( first )
{ // compute normalization constants, this will only be done once
first = false;
for( i=0; i<numMul; i++ )protmul[i] = 0.0;
for( i=0; i<numSec; i++ )protnorm[i] = 0.0;
counter = -1;
for( np=0; np<(numSec/3); np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
protmul[counter] = pmltpc(np,nm,nz,nt,protb,c);
protnorm[nt-1] += protmul[counter];
}
}
}
}
}
for( i=0; i<numMul; i++ )neutmul[i] = 0.0;
for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
neutmul[counter] = pmltpc(np,nm,nz,nt,neutb,c);
neutnorm[nt-1] += neutmul[counter];
}
}
}
}
}
for( i=0; i<numSec; i++ )
{
if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
}
} // end of initialization
// initialize the first two places
// the same as beam and target
pv[0] = incidentParticle;
pv[1] = targetParticle;
vecLen = 2;
if( !inElastic )
{ // quasi-elastic scattering, no pions produced
G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
G4int iplab = G4int( min( 9.0, incidentTotalMomentum*2.5 ) );
if( G4UniformRand() < cech[iplab]/pow(atomicWeight,0.42) )
{
G4double ran = G4UniformRand();
if( targetCode == protonCode)
{
if (ran < 0.2)
{
pv[0] = SigmaPlus;
pv[1] = SigmaZero;
}
else if (ran < 0.4)
{
pv[0] = SigmaZero;
pv[1] = SigmaPlus;
}
else if (ran < 0.6)
{
pv[0] = SigmaPlus;
pv[1] = Lambda;
}
else if (ran < 0.8)
{
pv[0] = Lambda;
pv[1] = SigmaPlus;
}
else
{
pv[0] = Proton;
pv[1] = XiZero;
}
}
else
{
if (ran < 0.2)
{
pv[0] = Neutron;
pv[1] = XiZero;
}
else if (ran < 0.3)
{
pv[0] = SigmaZero;
pv[1] = SigmaZero;
}
else if (ran < 0.4)
{
pv[0] = Lambda;
pv[1] = Lambda;
}
else if (ran < 0.5)
{
pv[0] = SigmaZero;
pv[1] = Lambda;
}
else if (ran < 0.6)
{
pv[0] = Lambda;
pv[1] = SigmaZero;
}
else if (ran < 0.7)
{
pv[0] = SigmaPlus;
pv[1] = SigmaMinus;
}
else if (ran < 0.8)
{
pv[0] = SigmaMinus;
pv[1] = SigmaPlus;
}
else if (ran < 0.9)
{
pv[0] = XiMinus;
pv[1] = Proton;
}
else
{
pv[0] = Proton;
pv[1] = XiMinus;
}
}
}
return;
}
else if (availableEnergy <= PionPlus.getMass())
return;
// inelastic scattering
np = 0; nm = 0; nz = 0;
// number of total particles vs. centre of mass Energy - 2*proton mass
G4double aleab = log(availableEnergy);
G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
+ aleab*(0.117712+0.0136912*aleab))) - 2.0;
// normalization constant for kno-distribution.
// calculate first the sum of all constants, check for numerical problems.
G4double test, dum, anpn = 0.0;
for( nt=1; nt<=numSec; nt++ )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = M_PI*nt/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )anpn += dum*test;
else
anpn += dum*test;
}
G4double ran = G4UniformRand();
G4double excs = 0.0;
if( targetCode == protonCode )
{
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-2); nm<=np; nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>0) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; //----------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering
return;
}
else
{ // target must be a neutron
counter = -1;
for( np=0; np<numSec/3; np++ )
{
for( nm=max(0,np-1); nm<=(np+1); nm++ )
{
for( nz=0; nz<numSec/3; nz++ )
{
if( ++counter < numMul )
{
nt = np+nm+nz;
if( (nt>=1) && (nt<=numSec) )
{
test = exp( min( expxu, max( expxl, -(M_PI/4.0)*(nt*nt)/(n*n) ) ) );
dum = (M_PI/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
if( fabs(dum) < 1.0 )
if( test >= 1.0e-10 )excs += dum*test;
else
excs += dum*test;
if (ran < excs) goto outOfLoop; // -------------------------->
}
}
}
}
}
// 3 previous loops continued to the end
inElastic = false; // quasi-elastic scattering.
return;
}
outOfLoop: // <------------------------------------------------------------------------
// in the following we do not consider
ran = G4UniformRand(); // strangeness transfer in high multiplicity
if( targetCode == protonCode) // events. YK combinations are added in
{ // StrangeParticlePairProduction
if( np == nm)
{
}
else if (np == (nm+1))
{
if( ran < 0.50)
{
pv[0] = XiMinus;
}
else
{
pv[1] = Neutron;
}
}
else
{
pv[0] = XiMinus;
pv[1] = Neutron;
}
}
else
{
if (np == nm)
{
if (ran < 0.5)
{
}
else
{
pv[0] = XiMinus;
pv[1] = Proton;
}
}
else if (np == (nm-1))
{
pv[1] = Proton;
}
else
{
pv[0] = XiMinus;
}
}
nt = np + nm + nz;
while ( nt > 0)
{
G4double ran = G4UniformRand();
if ( ran < (G4double)np/nt)
{
if( np > 0 )
{ pv[vecLen++] = PionPlus;
np--;
}
}
else if ( ran < (G4double)(np+nm)/nt)
{
if( nm > 0 )
{
pv[vecLen++] = PionMinus;
nm--;
}
}
else
{
if( nz > 0 )
{
pv[vecLen++] = PionZero;
nz--;
}
}
nt = np + nm + nz;
}
if (verboseLevel > 1)
{
cout << "Particles produced: " ;
cout << pv[0].getCode() << " " ;
cout << pv[1].getCode() << " " ;
for (i=2; i < vecLen; i++)
{
cout << pv[i].getCode() << " " ;
}
cout << endl;
}
return;
}