Import Geant4 10.6.0 source tree

This commit is contained in:
Gabriele Cosmo
2019-12-06 15:12:28 +01:00
parent b2a62ae692
commit 5baee230e9
2997 changed files with 141580 additions and 98673 deletions
@@ -14,6 +14,17 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
7 November 2019 Dennis Wright (hadr-casc-V10-05-02)
-----------------------------------------------------
- G4LightTargetCollider: fix crash when gamma energy below deuteron
disintegration threshold and improve exception handling
5 November 2019 Dennis Wright (hadr-casc-V10-05-01)
-----------------------------------------------------
- new class G4LightTargetCollider to more accurately handle collisons
on p, d, t, 3He. Currently only gamma on protons and deuterons is
implemented.
29 May 2019 Dennis Wright (hadr-casc-V10-05-00)
------------------------------------------------
- fix bug found in biasing/B03 example due to FPE from unprotected sqrt
@@ -79,6 +79,7 @@ class G4CollisionOutput;
class G4DynamicParticle;
class G4HadFinalState;
class G4InuclCollider;
class G4LightTargetCollider;
class G4InuclParticle;
class G4ParticleDefinition;
class G4V3DNucleus;
@@ -166,6 +167,8 @@ private:
G4InuclCollider* collider;
G4CascadeCheckBalance* balance;
G4LightTargetCollider* ltcollider;
G4InuclParticle* bullet; // Pointers to last filled versions
G4InuclParticle* target;
@@ -0,0 +1,89 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// //
// File: G4LightTargetCollider.hh //
// Date: 30 September 2019 //
// Author: Dennis Wright (SLAC) //
// //
// Description: model for collision of elementary particles with light //
// targets (H, D, T, 3He) //
// //
////////////////////////////////////////////////////////////////////////////////
#ifndef G4LIGHT_TARGET_COLLIDER_HH
#define G4LIGHT_TARGET_COLLIDER_HH
#include "G4CascadeColliderBase.hh"
#include "G4CascadeFinalStateGenerator.hh"
#include "G4CollisionOutput.hh"
class G4CascadParticle;
class G4ElementaryParticleCollider;
class G4InuclParticle;
class G4KineticTrackVector;
typedef std::pair<G4InuclElementaryParticle, G4InuclElementaryParticle> NucleonPair;
typedef std::vector<G4InuclElementaryParticle> ScatteringProducts;
class G4LightTargetCollider : public G4CascadeColliderBase {
public:
G4LightTargetCollider();
virtual ~G4LightTargetCollider();
void collide(G4InuclParticle* bullet, G4InuclParticle* target,
G4CollisionOutput& globalOutput);
void setVerboseLevel(G4int verbose=0);
private:
G4ElementaryParticleCollider* theElementaryParticleCollider;
G4CollisionOutput output; // Secondaries from main cascade
private:
// Copying of modules is forbidden
G4LightTargetCollider(const G4LightTargetCollider&);
G4LightTargetCollider& operator=(const G4LightTargetCollider&);
G4double GammaDCrossSection(G4double /*kineticEnergy*/);
G4CascadeFinalStateGenerator fsGen;
NucleonPair AbsorptionOnDeuteron(G4InuclParticle* bullet);
ScatteringProducts SingleNucleonScattering(const G4InuclElementaryParticle& projectile,
const G4InuclElementaryParticle& targetNucleon);
G4double mP; // proton mass
G4double mN; // neutron mass
G4double mD; // deuteron mass
G4double pFermiD; // deuteron Fermi momentum (GeV/c)
};
#endif /* G4LIGHT_TARGET_COLLIDER_HH */
@@ -161,6 +161,7 @@ GEANT4_DEFINE_MODULE(NAME G4hadronic_bert_cascade
G4InteractionCase.hh
G4IntraNucleiCascader.hh
G4InuclCollider.hh
G4LightTargetCollider.hh
G4InuclElementaryParticle.hh
G4InuclEvaporation.hh
G4InuclNuclei.hh
@@ -274,6 +275,7 @@ GEANT4_DEFINE_MODULE(NAME G4hadronic_bert_cascade
G4InteractionCase.cc
G4IntraNucleiCascader.cc
G4InuclCollider.cc
G4LightTargetCollider.cc
G4InuclElementaryParticle.cc
G4InuclEvaporation.cc
G4InuclNuclei.cc
@@ -116,6 +116,7 @@
#include "G4DynamicParticle.hh"
#include "G4HadronicException.hh"
#include "G4InuclCollider.hh"
#include "G4LightTargetCollider.hh"
#include "G4InuclElementaryParticle.hh"
#include "G4InuclNuclei.hh"
#include "G4InuclParticle.hh"
@@ -143,11 +144,13 @@ typedef std::vector<G4InuclNuclei>::const_iterator nucleiIterator;
// Constructor and destrutor
G4CascadeInterface::G4CascadeInterface(const G4String& name)
: G4VIntraNuclearTransportModel(name),
randomFile(G4CascadeParameters::randomFile()),
maximumTries(20), numberOfTries(0),
collider(new G4InuclCollider), balance(new G4CascadeCheckBalance(name)),
bullet(0), target(0), output(new G4CollisionOutput) {
: G4VIntraNuclearTransportModel(name),
randomFile(G4CascadeParameters::randomFile()),
maximumTries(20), numberOfTries(0),
collider(new G4InuclCollider), balance(new G4CascadeCheckBalance(name)),
ltcollider(new G4LightTargetCollider),
bullet(0), target(0), output(new G4CollisionOutput)
{
// Set up global objects for master thread or sequential build
if (G4Threading::IsMasterThread()) Initialize();
@@ -278,55 +281,71 @@ G4CascadeInterface::ApplyYourself(const G4HadProjectile& aTrack,
return NoInteraction(aTrack, theNucleus);
}
// Make conversion between native Geant4 and Bertini cascade classes.
if (!createBullet(aTrack)) {
if (verboseLevel) G4cerr << " Unable to create usable bullet" << G4endl;
return NoInteraction(aTrack, theNucleus);
}
// If target A < 3 skip all cascade machinery and do scattering on
// nucleons
if (!createTarget(theNucleus)) {
if (verboseLevel) G4cerr << " Unable to create usable target" << G4endl;
return NoInteraction(aTrack, theNucleus);
}
// Different retry conditions for proton target vs. nucleus
const G4bool isHydrogen = (theNucleus.GetA_asInt() == 1);
numberOfTries = 0;
do { // we try to create inelastic interaction
if (verboseLevel > 1)
G4cout << " Generating cascade attempt " << numberOfTries << G4endl;
if (aTrack.GetDefinition() == G4Gamma::Gamma() &&
theNucleus.GetA_asInt() < 3) {
output->reset();
collider->collide(bullet, target, *output);
balance->collide(bullet, target, *output);
createBullet(aTrack);
createTarget(theNucleus);
// Due to binning, gamma-p cross sections between 130 MeV and the inelastic threshold
// (144 for pi0 p, 152 for pi+ n) are non-zero, causing energy non-conservation
// So, if Egamma is between 144 and 152, only pi0 p is allowed.
// Also, inelastic gamma-p cross section from G4PhotoNuclearCrossSection seems to be
// non-zero below between pi0 mass (135 MeV) and threshold (144 MeV)
ltcollider->collide(bullet, target, *output);
} else {
// Make conversion between native Geant4 and Bertini cascade classes.
if (!createBullet(aTrack)) {
if (verboseLevel) G4cerr << " Unable to create usable bullet" << G4endl;
return NoInteraction(aTrack, theNucleus);
}
if (!createTarget(theNucleus)) {
if (verboseLevel) G4cerr << " Unable to create usable target" << G4endl;
return NoInteraction(aTrack, theNucleus);
}
// Different retry conditions for proton target vs. nucleus
const G4bool isHydrogen = (theNucleus.GetA_asInt() == 1);
numberOfTries = 0;
do { // we try to create inelastic interaction
if (verboseLevel > 1)
G4cout << " Generating cascade attempt " << numberOfTries << G4endl;
numberOfTries++;
/* Loop checking 08.06.2015 MHK */
} while ( isHydrogen ? retryInelasticProton() : retryInelasticNucleus() );
output->reset();
collider->collide(bullet, target, *output);
balance->collide(bullet, target, *output);
numberOfTries++;
/* Loop checking 08.06.2015 MHK */
} while ( isHydrogen ? retryInelasticProton() : retryInelasticNucleus() );
// Null event if unsuccessful
if (numberOfTries >= maximumTries) {
if (verboseLevel)
G4cout << " Cascade aborted after trials " << numberOfTries << G4endl;
return NoInteraction(aTrack, theNucleus);
}
// Null event if unsuccessful
if (numberOfTries >= maximumTries) {
if (verboseLevel)
G4cout << " Cascade aborted after trials " << numberOfTries << G4endl;
return NoInteraction(aTrack, theNucleus);
}
// Abort job if energy or momentum are not conserved
if (!balance->okay()) {
throwNonConservationFailure();
return NoInteraction(aTrack, theNucleus);
}
// Abort job if energy or momentum are not conserved
if (!balance->okay()) {
throwNonConservationFailure();
return NoInteraction(aTrack, theNucleus);
}
// Successful cascade -- clean up and return
if (verboseLevel) {
G4cout << " Cascade output after trials " << numberOfTries << G4endl;
if (verboseLevel > 1) output->printCollisionOutput();
}
// Successful cascade -- clean up and return
if (verboseLevel) {
G4cout << " Cascade output after trials " << numberOfTries << G4endl;
if (verboseLevel > 1) output->printCollisionOutput();
}
// Rotate event to put Z axis along original projectile direction
// Removed by DHW to fix bug #1990
// output->rotateEvent(bulletInLabFrame);
} // end cascade-style collisions
copyOutputToHadronicResult();
@@ -84,27 +84,27 @@ const G4CascadeParameters* G4CascadeParameters::Instance() {
//#define OLD_RADIUS_UNITS (3.3836/1.2) // Used with NucModel params
G4CascadeParameters::G4CascadeParameters()
: G4CASCADE_VERBOSE(getenv("G4CASCADE_VERBOSE")),
G4CASCADE_CHECK_ECONS(getenv("G4CASCADE_CHECK_ECONS")),
G4CASCADE_USE_PRECOMPOUND(getenv("G4CASCADE_USE_PRECOMPOUND")),
G4CASCADE_DO_COALESCENCE(getenv("G4CASCADE_DO_COALESCENCE")),
G4CASCADE_SHOW_HISTORY(getenv("G4CASCADE_SHOW_HISTORY")),
G4CASCADE_USE_3BODYMOM(getenv("G4CASCADE_USE_3BODYMOM")),
G4CASCADE_USE_PHASESPACE(getenv("G4CASCADE_USE_PHASESPACE")),
G4CASCADE_PIN_ABSORPTION(getenv("G4CASCADE_PIN_ABSORPTION")),
G4CASCADE_RANDOM_FILE(getenv("G4CASCADE_RANDOM_FILE")),
G4NUCMODEL_USE_BEST(getenv("G4NUCMODEL_USE_BEST")),
G4NUCMODEL_RAD_2PAR(getenv("G4NUCMODEL_RAD_2PAR")),
G4NUCMODEL_RAD_SCALE(getenv("G4NUCMODEL_RAD_SCALE")),
G4NUCMODEL_RAD_SMALL(getenv("G4NUCMODEL_RAD_SMALL")),
G4NUCMODEL_RAD_ALPHA(getenv("G4NUCMODEL_RAD_ALPHA")),
G4NUCMODEL_RAD_TRAILING(getenv("G4NUCMODEL_RAD_TRAILING")),
G4NUCMODEL_FERMI_SCALE(getenv("G4NUCMODEL_FERMI_SCALE")),
G4NUCMODEL_XSEC_SCALE(getenv("G4NUCMODEL_XSEC_SCALE")),
G4NUCMODEL_GAMMAQD(getenv("G4NUCMODEL_GAMMAQD")),
DPMAX_2CLUSTER(getenv("DPMAX_2CLUSTER")),
DPMAX_3CLUSTER(getenv("DPMAX_3CLUSTER")),
DPMAX_4CLUSTER(getenv("DPMAX_4CLUSTER")),
: G4CASCADE_VERBOSE(std::getenv("G4CASCADE_VERBOSE")),
G4CASCADE_CHECK_ECONS(std::getenv("G4CASCADE_CHECK_ECONS")),
G4CASCADE_USE_PRECOMPOUND(std::getenv("G4CASCADE_USE_PRECOMPOUND")),
G4CASCADE_DO_COALESCENCE(std::getenv("G4CASCADE_DO_COALESCENCE")),
G4CASCADE_SHOW_HISTORY(std::getenv("G4CASCADE_SHOW_HISTORY")),
G4CASCADE_USE_3BODYMOM(std::getenv("G4CASCADE_USE_3BODYMOM")),
G4CASCADE_USE_PHASESPACE(std::getenv("G4CASCADE_USE_PHASESPACE")),
G4CASCADE_PIN_ABSORPTION(std::getenv("G4CASCADE_PIN_ABSORPTION")),
G4CASCADE_RANDOM_FILE(std::getenv("G4CASCADE_RANDOM_FILE")),
G4NUCMODEL_USE_BEST(std::getenv("G4NUCMODEL_USE_BEST")),
G4NUCMODEL_RAD_2PAR(std::getenv("G4NUCMODEL_RAD_2PAR")),
G4NUCMODEL_RAD_SCALE(std::getenv("G4NUCMODEL_RAD_SCALE")),
G4NUCMODEL_RAD_SMALL(std::getenv("G4NUCMODEL_RAD_SMALL")),
G4NUCMODEL_RAD_ALPHA(std::getenv("G4NUCMODEL_RAD_ALPHA")),
G4NUCMODEL_RAD_TRAILING(std::getenv("G4NUCMODEL_RAD_TRAILING")),
G4NUCMODEL_FERMI_SCALE(std::getenv("G4NUCMODEL_FERMI_SCALE")),
G4NUCMODEL_XSEC_SCALE(std::getenv("G4NUCMODEL_XSEC_SCALE")),
G4NUCMODEL_GAMMAQD(std::getenv("G4NUCMODEL_GAMMAQD")),
DPMAX_2CLUSTER(std::getenv("DPMAX_2CLUSTER")),
DPMAX_3CLUSTER(std::getenv("DPMAX_3CLUSTER")),
DPMAX_4CLUSTER(std::getenv("DPMAX_4CLUSTER")),
messenger(0) {
messenger = new G4CascadeParamMessenger(this);
Initialize();
@@ -246,7 +246,7 @@ void G4InuclCollider::collide(G4InuclParticle* bullet, G4InuclParticle* target,
output.removeRecoilFragment();
//*** TEMPORARY, USE ENVVAR TO ENABLE/DISABLE THIS TEST ***
if (getenv("G4CASCADE_CHECK_PHOTONUCLEAR"))
if (std::getenv("G4CASCADE_CHECK_PHOTONUCLEAR"))
if (!photonuclearOkay(output)) continue;
if (verboseLevel > 2)
@@ -0,0 +1,369 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
////////////////////////////////////////////////////////////////////////////////
// //
// File: G4LightTargetCollider.cc //
// Date: 30 September 2019 //
// Author: Dennis Wright (SLAC) //
// //
// Description: model for collision of elementary particles with light //
// targets (H, D, T, 3He) //
// //
////////////////////////////////////////////////////////////////////////////////
#include "G4LightTargetCollider.hh"
#include "G4CascadeChannel.hh"
#include "G4CascadeChannelTables.hh"
#include "G4CascadeCheckBalance.hh"
#include "G4CollisionOutput.hh"
#include "G4ElementaryParticleCollider.hh"
#include "G4InuclElementaryParticle.hh"
#include "G4InuclNuclei.hh"
#include "G4NucleiModel.hh"
#include "G4LorentzConvertor.hh"
#include "G4Deuteron.hh"
#include "G4Gamma.hh"
#include "G4PionZero.hh"
#include "G4PionPlus.hh"
#include "G4PionMinus.hh"
#include "G4RandomDirection.hh"
G4LightTargetCollider::G4LightTargetCollider()
: G4CascadeColliderBase("G4LightTargetCollider"),
theElementaryParticleCollider(new G4ElementaryParticleCollider)
{
mP = G4Proton::Proton()->GetPDGMass()/CLHEP::GeV;
mN = G4Neutron::Neutron()->GetPDGMass()/CLHEP::GeV;
mD = G4Deuteron::Deuteron()->GetPDGMass()/CLHEP::GeV;
pFermiD = 0.045; // Fermi momentum of nucleon in deuteron Hulthen potential
}
G4LightTargetCollider::~G4LightTargetCollider() {
delete theElementaryParticleCollider;
}
// Set verbosity and pass on to member objects
void G4LightTargetCollider::setVerboseLevel(G4int verbose) {
G4CascadeColliderBase::setVerboseLevel(verbose);
theElementaryParticleCollider->setVerboseLevel(verboseLevel);
output.setVerboseLevel(verboseLevel);
}
void G4LightTargetCollider::collide(G4InuclParticle* bullet,
G4InuclParticle* target,
G4CollisionOutput& globalOutput)
{
if (verboseLevel) {
G4cout << " >>> G4LightTargetCollider::collide" << G4endl;
G4cout << " Projectile: " << bullet->getDefinition()->GetParticleName() << G4endl;
G4cout << " Target: " << target->getDefinition()->GetParticleName() << G4endl;
}
// Particle-on-particle collision
// No nucleus involved, just a proton in this case
if (useEPCollider(bullet,target)) {
if (verboseLevel > 2)
G4cout << " InuclCollider -> particle on particle collision" << G4endl;
theElementaryParticleCollider->collide(bullet, target, globalOutput);
return;
}
G4double ke = bullet->getKineticEnergy();
if (target->getDefinition() == G4Deuteron::Deuteron()) {
if (ke < mP + mN - mD) {
// Should not happen as long as inelastic cross section is zero
G4Exception("G4LightTargetCollider::collide()","HAD_BERT_201",
JustWarning, "Projectile energy below reaction threshold");
globalOutput.trivialise(bullet, target);
} else {
// Get p, n and deuteron cross sections; use lab energy to access
G4double gammaPXS = G4CascadeChannelTables::GetTable(9)->getCrossSection(ke);
G4double gammaNXS = G4CascadeChannelTables::GetTable(18)->getCrossSection(ke);
G4double gammaDXS = GammaDCrossSection(ke);
G4double probP = 0.0;
G4double probN = 0.0;
// Highest threshold is 0.152 (for gamma p -> n pi+)
// Because of Fermi momentum in deuteron, raise this to 0.159
if (ke > 0.159) {
G4double totalDXS = gammaPXS + gammaNXS + gammaDXS;
probP = gammaPXS/totalDXS;
probN = (gammaPXS+gammaNXS)/totalDXS;
}
G4double rndm = G4UniformRand();
if (rndm < probP) {
// Generate Fermi momenta of bullet and target
G4ThreeVector fermiMomentum = pFermiD*G4RandomDirection();
G4LorentzVector protonMomentum(fermiMomentum, std::sqrt(mP*mP + pFermiD*pFermiD) );
G4LorentzVector neutronMomentum(-fermiMomentum, std::sqrt(mN*mN + pFermiD*pFermiD) );
G4LorentzVector bulletMomentum = bullet->getMomentum();
G4ThreeVector betacm = bulletMomentum.findBoostToCM(protonMomentum);
// First boost bullet and target so that target is at rest
G4ThreeVector toProtonRest = -protonMomentum.boostVector();
protonMomentum.boost(toProtonRest);
bulletMomentum.boost(toProtonRest);
G4InuclElementaryParticle projectile(bulletMomentum, bullet->getDefinition() );
G4InuclElementaryParticle targetNucleon(protonMomentum, G4Proton::Proton() );
G4InuclElementaryParticle spectatorNucleon(neutronMomentum, G4Neutron::Neutron() );
ScatteringProducts products = SingleNucleonScattering(projectile, targetNucleon);
// Particles from SingleNucleonScattering are in CM frame of projectile
// and moving proton. Transform back to lab frame with -betacm, then
// add them to outgoing list.
globalOutput.reset();
G4LorentzVector temp;
for (G4int i = 0; i < G4int(products.size()); i++) {
temp = products[i].getMomentum();
temp.boost(-betacm);
products[i].setMomentum(temp);
globalOutput.addOutgoingParticle(products[i]);
}
// Add the recoil nucleon unmodified
globalOutput.addOutgoingParticle(spectatorNucleon);
} else if (rndm < probN) {
G4ThreeVector fermiMomentum = pFermiD*G4RandomDirection();
G4LorentzVector protonMomentum(fermiMomentum, std::sqrt(mP*mP + pFermiD*pFermiD) );
G4LorentzVector neutronMomentum(-fermiMomentum, std::sqrt(mN*mN + pFermiD*pFermiD) );
G4LorentzVector bulletMomentum = bullet->getMomentum();
G4ThreeVector betacm = bulletMomentum.findBoostToCM(neutronMomentum);
// First boost bullet and target so that target is at rest
G4ThreeVector toNeutronRest = -neutronMomentum.boostVector();
neutronMomentum.boost(toNeutronRest);
bulletMomentum.boost(toNeutronRest);
G4InuclElementaryParticle projectile(bulletMomentum, bullet->getDefinition() );
G4InuclElementaryParticle targetNucleon(neutronMomentum, G4Neutron::Neutron() );
G4InuclElementaryParticle spectatorNucleon(protonMomentum, G4Proton::Proton() );
ScatteringProducts products = SingleNucleonScattering(projectile, targetNucleon);
// Particles from SingleNucleonScattering are in CM frame of projectile
// and moving neutron. Transform back to lab frame with -betacm, then add
// them to outgoing list
globalOutput.reset();
G4LorentzVector temp;
for (G4int i = 0; i < G4int(products.size()); i++) {
temp = products[i].getMomentum();
temp.boost(-betacm);
products[i].setMomentum(temp);
globalOutput.addOutgoingParticle(products[i]);
}
// Add the recoil nucleon unmodified
globalOutput.addOutgoingParticle(spectatorNucleon);
} else {
NucleonPair products = AbsorptionOnDeuteron(bullet);
globalOutput.reset();
globalOutput.addOutgoingParticle(products.first);
globalOutput.addOutgoingParticle(products.second);
}
} // Energy above threshold ?
// Test code
// G4int numPart = globalOutput.numberOfOutgoingParticles();
// std::vector<G4InuclElementaryParticle> testList = globalOutput.getOutgoingParticles();
// G4LorentzVector sumP;
// G4cout << " Global output " << G4endl;
// for (G4int i = 0; i < numPart; i++) {
// sumP += testList[i].getMomentum();
// G4cout << testList[i] << G4endl;
// }
// G4cout << " Global 4-momentum sum = " << sumP << G4endl;
// G4cout << " Initial lab energy = " << mD + bullet->getEnergy() << G4endl;
} else {
G4Exception("G4LightTargetCollider::collide()","HAD_BERT_203",
FatalException, "Scattering from this target not implemented");
}
return;
}
G4double G4LightTargetCollider::GammaDCrossSection(G4double gammaEnergy)
{
// Gamma deuteron cross section in mb parameterized from JLab data
// No parameterization needed below pi0 threshold where cross section
// is 100% disintegration
G4double sigma = 1000.0;
G4double term = 0.;
if (gammaEnergy > 0.144 && gammaEnergy < 0.42) {
term = (gammaEnergy - 0.24)/0.155;
sigma = 0.065*std::exp(-term*term);
} else if (gammaEnergy >= 0.42) {
sigma = 0.000526/gammaEnergy/gammaEnergy/gammaEnergy/gammaEnergy;
}
return sigma;
}
NucleonPair G4LightTargetCollider::AbsorptionOnDeuteron(G4InuclParticle* bullet)
{
// Do break-up in center of mass, convert to lab frame before returning
// particles
G4double bulletMass = bullet->getMass();
G4double bulletE = bullet->getEnergy();
G4double S = bulletMass*bulletMass + mD*mD + 2.*mD*bulletE;
G4double qcm = 0.;
G4int outType1 = 0;
G4int outType2 = 0;
G4LorentzVector Mom1;
G4LorentzVector Mom2;
// Set up outgoing particle types
if (bullet->getDefinition() == G4Gamma::Gamma() ||
bullet->getDefinition() == G4PionZero::PionZero() ) {
qcm = std::sqrt( (S - (mP + mN)*(mP + mN)) * (S - (mP - mN)*(mP - mN))/S/4.);
Mom1.setE(std::sqrt(mP*mP + qcm*qcm) );
outType1 = G4InuclParticleNames::proton;
Mom2.setE(std::sqrt(mN*mN + qcm*qcm) );
outType2 = G4InuclParticleNames::neutron;
} else if (bullet->getDefinition() == G4PionPlus::PionPlus() ) {
qcm = std::sqrt( (S - 4.*mP*mP)/4.);
Mom1.setE(std::sqrt(mP*mP + qcm*qcm) );
outType1 = G4InuclParticleNames::proton;
Mom2.setE(std::sqrt(mP*mP + qcm*qcm) );
outType2 = G4InuclParticleNames::proton;
} else if (bullet->getDefinition() == G4PionMinus::PionMinus() ) {
qcm = std::sqrt( (S - 4.*mN*mN)/4.);
Mom1.setE(std::sqrt(mN*mN + qcm*qcm) );
outType1 = G4InuclParticleNames::neutron;
Mom2.setE(std::sqrt(mN*mN + qcm*qcm) );
outType2 = G4InuclParticleNames::neutron;
} else {
G4Exception("G4LightTargetCollider::collide()","HAD_BERT_204",
FatalException, "Illegal bullet type");
}
// Sample angular distribution, assuming 100% S wave (no D-wave)
G4ThreeVector qVect = qcm*G4RandomDirection();
Mom1.setVect(qVect);
Mom2.setVect(-qVect);
// Boost to lab frame
G4ThreeVector betacm(0., 0., bullet->getMomModule()/(bulletE + mD) );
Mom1.boost(betacm);
Mom2.boost(betacm);
G4InuclElementaryParticle particle1(Mom1, outType1);
G4InuclElementaryParticle particle2(Mom2, outType2);
NucleonPair nucleon_pair(particle1, particle2);
// if pion, use parameterization of B.G. Ritchie, PRC 44, 533 (1991)
// Total cross section: 1/E + Lorentzian
return nucleon_pair;
}
ScatteringProducts
G4LightTargetCollider::SingleNucleonScattering(const G4InuclElementaryParticle& projectile,
const G4InuclElementaryParticle& nucleon)
{
// At this point projectile and nucleon momenta are in nucleon rest frame
G4int reactionIndex = G4InuclElementaryParticle::type(projectile.getDefinition() )
* G4InuclElementaryParticle::type(nucleon.getDefinition() );
const G4CascadeChannel* xsecTable = G4CascadeChannelTables::GetTable(reactionIndex);
G4double ke = projectile.getKineticEnergy();
G4int mult = xsecTable->getMultiplicity(ke);
std::vector<G4double> masses;
G4double mass = 0.0;
G4LorentzVector totalMom = projectile.getMomentum() + nucleon.getMomentum();
G4double Ecm = totalMom.mag();
std::vector<G4LorentzVector> cmMomenta;
std::vector<G4int> particle_kinds;
G4int itry = 0;
G4int itry_max = 200;
G4bool generate = true;
while (mult > 1) {
itry = 0;
generate = true;
while (generate && itry < itry_max) {
particle_kinds.clear();
xsecTable->getOutgoingParticleTypes(particle_kinds, mult, ke);
masses.clear();
for (G4int i = 0; i < mult; i++) {
mass = G4InuclElementaryParticle::getParticleMass(particle_kinds[i]);
masses.push_back(mass);
}
fsGen.Configure(const_cast<G4InuclElementaryParticle*>(&projectile),
const_cast<G4InuclElementaryParticle*>(&nucleon),
particle_kinds);
// Generate final state in CM of projectile and at-rest nucleon
cmMomenta.clear();
generate = !fsGen.Generate(Ecm, masses, cmMomenta);
itry++;
} // while
if (itry == itry_max) mult--;
else break;
} // while mult
ScatteringProducts finalState;
if (mult < 2) {
G4Exception("G4LightTargetCollider::SingleNucleonScattering()","HAD_BERT_202",
JustWarning, "Failed to generate final state");
// Final state particles not in CM - just using them as dummies
finalState.push_back(projectile);
finalState.push_back(nucleon);
} else {
for (G4int i = 0; i < mult; i++) {
G4InuclElementaryParticle fsPart(cmMomenta[i], particle_kinds[i]);
finalState.push_back(fsPart);
}
}
return finalState;
}