Files
geant4/source/processes/hadronic/models/rpg/src/G4RPGStrangeProduction.cc
T
2018-12-07 15:15:39 +01:00

470 lines
16 KiB
C++

//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
#include <iostream>
#include <signal.h>
#include "G4RPGStrangeProduction.hh"
#include "G4Log.hh"
#include "Randomize.hh"
#include "G4SystemOfUnits.hh"
#include "G4HadReentrentException.hh"
G4RPGStrangeProduction::G4RPGStrangeProduction()
: G4RPGReaction() {}
G4bool G4RPGStrangeProduction::
ReactionStage(const G4HadProjectile* /*originalIncident*/,
G4ReactionProduct& modifiedOriginal,
G4bool& incidentHasChanged,
const G4DynamicParticle* originalTarget,
G4ReactionProduct& targetParticle,
G4bool& targetHasChanged,
const G4Nucleus& /*targetNucleus*/,
G4ReactionProduct& currentParticle,
G4FastVector<G4ReactionProduct,256>& vec,
G4int& vecLen,
G4bool /*leadFlag*/,
G4ReactionProduct& /*leadingStrangeParticle*/)
{
// Derived from H. Fesefeldt's original FORTRAN code STPAIR
//
// Choose charge combinations K+ K-, K+ K0B, K0 K0B, K0 K-,
// K+ Y0, K0 Y+, K0 Y-
// For antibaryon induced reactions half of the cross sections KB YB
// pairs are produced. Charge is not conserved, no experimental data available
// for exclusive reactions, therefore some average behaviour assumed.
// The ratio L/SIGMA is taken as 3:1 (from experimental low energy)
//
if( vecLen == 0 )return true;
//
// the following protects against annihilation processes
//
if( currentParticle.GetMass() == 0.0 || targetParticle.GetMass() == 0.0 )return true;
const G4double etOriginal = modifiedOriginal.GetTotalEnergy()/GeV;
const G4double mOriginal = modifiedOriginal.GetDefinition()->GetPDGMass()/GeV;
G4double targetMass = originalTarget->GetDefinition()->GetPDGMass()/GeV;
G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
targetMass*targetMass +
2.0*targetMass*etOriginal ); // GeV
G4double currentMass = currentParticle.GetMass()/GeV;
G4double availableEnergy = centerofmassEnergy-(targetMass+currentMass);
if( availableEnergy <= 1.0 )return true;
G4ParticleDefinition *aProton = G4Proton::Proton();
G4ParticleDefinition *anAntiProton = G4AntiProton::AntiProton();
G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
G4ParticleDefinition *anAntiNeutron = G4AntiNeutron::AntiNeutron();
G4ParticleDefinition *aSigmaMinus = G4SigmaMinus::SigmaMinus();
G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
G4ParticleDefinition *aSigmaZero = G4SigmaZero::SigmaZero();
G4ParticleDefinition *anAntiSigmaMinus = G4AntiSigmaMinus::AntiSigmaMinus();
G4ParticleDefinition *anAntiSigmaPlus = G4AntiSigmaPlus::AntiSigmaPlus();
G4ParticleDefinition *anAntiSigmaZero = G4AntiSigmaZero::AntiSigmaZero();
G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
G4ParticleDefinition *aKaonPlus = G4KaonPlus::KaonPlus();
G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
G4ParticleDefinition *aKaonZS = G4KaonZeroShort::KaonZeroShort();
G4ParticleDefinition *aLambda = G4Lambda::Lambda();
G4ParticleDefinition *anAntiLambda = G4AntiLambda::AntiLambda();
const G4double protonMass = aProton->GetPDGMass()/GeV;
const G4double sigmaMinusMass = aSigmaMinus->GetPDGMass()/GeV;
//
// determine the center of mass energy bin
//
const G4double avrs[] = {3.,4.,5.,6.,7.,8.,9.,10.,20.,30.,40.,50.};
G4int ibin, i3, i4;
G4double avk, avy, avn, ran;
G4int i = 1;
G4int loop = 0;
G4ExceptionDescription ed;
ed << " While count exceeded " << G4endl;
while ((i<12) && (centerofmassEnergy>avrs[i]) ) { /* Loop checking, 01.09.2015, D.Wright */
i++;
loop++;
if (loop > 1000) {
G4Exception("G4RPGStrangeProduction::ReactionStage()", "HAD_RPG_100", JustWarning, ed);
break;
}
}
if( i == 12 )
ibin = 11;
else
ibin = i;
//
// the fortran code chooses a random replacement of produced kaons
// but does not take into account charge conservation
//
if (vecLen == 1) { // we know that vecLen > 0
i3 = 0;
i4 = 1; // note that we will be adding a new secondary particle in this case only
} else { // otherwise 0 <= i3,i4 < vecLen
G4double rnd = G4UniformRand();
while (rnd == 1.0) rnd = G4UniformRand(); /* Loop checking, 01.09.2015, D.Wright */
i4 = i3 = G4int(vecLen*rnd);
while(i3 == i4) { /* Loop checking, 01.09.2015, D.Wright */
rnd = G4UniformRand();
while( rnd == 1.0 ) rnd = G4UniformRand(); /* Loop checking, 01.09.2015, D.Wright */
i4 = G4int(vecLen*rnd);
}
}
// use linear interpolation or extrapolation by y=centerofmassEnergy*x+b
//
const G4double avkkb[] = { 0.0015, 0.005, 0.012, 0.0285, 0.0525, 0.075,
0.0975, 0.123, 0.28, 0.398, 0.495, 0.573 };
const G4double avky[] = { 0.005, 0.03, 0.064, 0.095, 0.115, 0.13,
0.145, 0.155, 0.20, 0.205, 0.210, 0.212 };
const G4double avnnb[] = { 0.00001, 0.0001, 0.0006, 0.0025, 0.01, 0.02,
0.04, 0.05, 0.12, 0.15, 0.18, 0.20 };
avk = (G4Log(avkkb[ibin])-G4Log(avkkb[ibin-1]))*(centerofmassEnergy-avrs[ibin-1])
/(avrs[ibin]-avrs[ibin-1]) + G4Log(avkkb[ibin-1]);
avk = G4Exp(avk);
avy = (G4Log(avky[ibin])-G4Log(avky[ibin-1]))*(centerofmassEnergy-avrs[ibin-1])
/(avrs[ibin]-avrs[ibin-1]) + G4Log(avky[ibin-1]);
avy = G4Exp(avy);
avn = (G4Log(avnnb[ibin])-G4Log(avnnb[ibin-1]))*(centerofmassEnergy-avrs[ibin-1])
/(avrs[ibin]-avrs[ibin-1]) + G4Log(avnnb[ibin-1]);
avn = G4Exp(avn);
if( avk+avy+avn <= 0.0 )return true;
if( currentMass < protonMass )avy /= 2.0;
if( targetMass < protonMass )avy = 0.0;
avy += avk+avn;
avk += avn;
ran = G4UniformRand();
if( ran < avn )
{
if( availableEnergy < 2.0 )return true;
if( vecLen == 1 ) // add a new secondary
{
G4ReactionProduct *p1 = new G4ReactionProduct;
if( G4UniformRand() < 0.5 )
{
vec[0]->SetDefinition( aNeutron );
p1->SetDefinition( anAntiNeutron );
(G4UniformRand() < 0.5) ? p1->SetSide( -1 ) : p1->SetSide( 1 );
vec[0]->SetMayBeKilled(false);
p1->SetMayBeKilled(false);
}
else
{
vec[0]->SetDefinition( aProton );
p1->SetDefinition( anAntiProton );
(G4UniformRand() < 0.5) ? p1->SetSide( -1 ) : p1->SetSide( 1 );
vec[0]->SetMayBeKilled(false);
p1->SetMayBeKilled(false);
}
vec.SetElement( vecLen++, p1 );
// DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
}
else
{ // replace two secondaries
if( G4UniformRand() < 0.5 )
{
vec[i3]->SetDefinition( aNeutron );
vec[i4]->SetDefinition( anAntiNeutron );
vec[i3]->SetMayBeKilled(false);
vec[i4]->SetMayBeKilled(false);
}
else
{
vec[i3]->SetDefinition( aProton );
vec[i4]->SetDefinition( anAntiProton );
vec[i3]->SetMayBeKilled(false);
vec[i4]->SetMayBeKilled(false);
}
}
}
else if( ran < avk )
{
if( availableEnergy < 1.0 )return true;
const G4double kkb[] = { 0.2500, 0.3750, 0.5000, 0.5625, 0.6250,
0.6875, 0.7500, 0.8750, 1.000 };
const G4int ipakkb1[] = { 10, 10, 10, 11, 11, 12, 12, 11, 12 };
const G4int ipakkb2[] = { 13, 11, 12, 11, 12, 11, 12, 13, 13 };
ran = G4UniformRand();
i = 0;
loop = 0;
G4ExceptionDescription eda;
eda << " While count exceeded " << G4endl;
while( (i<9) && (ran>=kkb[i]) ) { /* Loop checking, 01.09.2015, D.Wright */
++i;
loop++;
if (loop > 1000) {
G4Exception("G4RPGStrangeProduction::ReactionStage()", "HAD_RPG_100", JustWarning, eda);
break;
}
}
if( i == 9 )return true;
//
// ipakkb[] = { 10,13, 10,11, 10,12, 11,11, 11,12, 12,11, 12,12, 11,13, 12,13 };
// charge + - + 0 + 0 0 0 0 0 0 0 0 0 0 - 0 -
//
switch( ipakkb1[i] )
{
case 10:
vec[i3]->SetDefinition( aKaonPlus );
vec[i3]->SetMayBeKilled(false);
break;
case 11:
vec[i3]->SetDefinition( aKaonZS );
vec[i3]->SetMayBeKilled(false);
break;
case 12:
vec[i3]->SetDefinition( aKaonZL );
vec[i3]->SetMayBeKilled(false);
break;
}
if( vecLen == 1 ) // add a secondary
{
G4ReactionProduct *p1 = new G4ReactionProduct;
switch( ipakkb2[i] )
{
case 11:
p1->SetDefinition( aKaonZS );
p1->SetMayBeKilled(false);
break;
case 12:
p1->SetDefinition( aKaonZL );
p1->SetMayBeKilled(false);
break;
case 13:
p1->SetDefinition( aKaonMinus );
p1->SetMayBeKilled(false);
break;
}
(G4UniformRand() < 0.5) ? p1->SetSide( -1 ) : p1->SetSide( 1 );
vec.SetElement( vecLen++, p1 );
}
else // replace
{
switch( ipakkb2[i] )
{
case 11:
vec[i4]->SetDefinition( aKaonZS );
vec[i4]->SetMayBeKilled(false);
break;
case 12:
vec[i4]->SetDefinition( aKaonZL );
vec[i4]->SetMayBeKilled(false);
break;
case 13:
vec[i4]->SetDefinition( aKaonMinus );
vec[i4]->SetMayBeKilled(false);
break;
}
}
} else if( ran < avy ) {
if( availableEnergy < 1.6 )return true;
const G4double ky[] = { 0.200, 0.300, 0.400, 0.550, 0.625, 0.700,
0.800, 0.850, 0.900, 0.950, 0.975, 1.000 };
const G4int ipaky1[] = { 18, 18, 18, 20, 20, 20, 21, 21, 21, 22, 22, 22 };
const G4int ipaky2[] = { 10, 11, 12, 10, 11, 12, 10, 11, 12, 10, 11, 12 };
const G4int ipakyb1[] = { 19, 19, 19, 23, 23, 23, 24, 24, 24, 25, 25, 25 };
const G4int ipakyb2[] = { 13, 12, 11, 13, 12, 11, 13, 12, 11, 13, 12, 11 };
ran = G4UniformRand();
i = 0;
loop = 0;
G4ExceptionDescription edb;
edb << " While count exceeded " << G4endl;
while( (i<12) && (ran>ky[i]) ) { /* Loop checking, 01.09.2015, D.Wright */
++i;
loop++;
if (loop > 1000) {
G4Exception("G4RPGStrangeProduction::ReactionStage()", "HAD_RPG_100", JustWarning, edb);
break;
}
}
if( i == 12 )return true;
if ( (currentMass<protonMass) || (G4UniformRand()<0.5) ) {
// ipaky[] = { 18,10, 18,11, 18,12, 20,10, 20,11, 20,12,
// 0 + 0 0 0 0 + + + 0 + 0
//
// 21,10, 21,11, 21,12, 22,10, 22,11, 22,12 }
// 0 + 0 0 0 0 - + - 0 - 0
switch( ipaky1[i] )
{
case 18:
targetParticle.SetDefinition( aLambda );
break;
case 20:
targetParticle.SetDefinition( aSigmaPlus );
break;
case 21:
targetParticle.SetDefinition( aSigmaZero );
break;
case 22:
targetParticle.SetDefinition( aSigmaMinus );
break;
}
targetHasChanged = true;
switch( ipaky2[i] )
{
case 10:
vec[i3]->SetDefinition( aKaonPlus );
vec[i3]->SetMayBeKilled(false);
break;
case 11:
vec[i3]->SetDefinition( aKaonZS );
vec[i3]->SetMayBeKilled(false);
break;
case 12:
vec[i3]->SetDefinition( aKaonZL );
vec[i3]->SetMayBeKilled(false);
break;
}
} else { // (currentMass >= protonMass) && (G4UniformRand() >= 0.5)
// ipakyb[] = { 19,13, 19,12, 19,11, 23,13, 23,12, 23,11,
// 24,13, 24,12, 24,11, 25,13, 25,12, 25,11 };
if ( (currentParticle.GetDefinition() == anAntiProton) ||
(currentParticle.GetDefinition() == anAntiNeutron) ||
(currentParticle.GetDefinition() == anAntiLambda) ||
(currentMass > sigmaMinusMass) ) {
switch( ipakyb1[i] )
{
case 19:
currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
break;
case 23:
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaPlus );
break;
case 24:
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
break;
case 25:
currentParticle.SetDefinitionAndUpdateE( anAntiSigmaMinus );
break;
}
incidentHasChanged = true;
switch( ipakyb2[i] )
{
case 11:
vec[i3]->SetDefinition( aKaonZS );
vec[i3]->SetMayBeKilled(false);
break;
case 12:
vec[i3]->SetDefinition( aKaonZL );
vec[i3]->SetMayBeKilled(false);
break;
case 13:
vec[i3]->SetDefinition( aKaonMinus );
vec[i3]->SetMayBeKilled(false);
break;
}
} else {
switch( ipaky1[i] )
{
case 18:
currentParticle.SetDefinitionAndUpdateE( aLambda );
break;
case 20:
currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
break;
case 21:
currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
break;
case 22:
currentParticle.SetDefinitionAndUpdateE( aSigmaMinus );
break;
}
incidentHasChanged = true;
switch( ipaky2[i] )
{
case 10:
vec[i3]->SetDefinition( aKaonPlus );
vec[i3]->SetMayBeKilled(false);
break;
case 11:
vec[i3]->SetDefinition( aKaonZS );
vec[i3]->SetMayBeKilled(false);
break;
case 12:
vec[i3]->SetDefinition( aKaonZL );
vec[i3]->SetMayBeKilled(false);
break;
}
}
}
}
else return true;
//
// check the available energy
// if there is not enough energy for kkb/ky pair production
// then reduce the number of secondary particles
// NOTE:
// the number of secondaries may have been changed
// the incident and/or target particles may have changed
// charge conservation is ignored (as well as strangness conservation)
//
currentMass = currentParticle.GetMass()/GeV;
targetMass = targetParticle.GetMass()/GeV;
G4double energyCheck = centerofmassEnergy-(currentMass+targetMass);
for( i=0; i<vecLen; ++i )
{
energyCheck -= vec[i]->GetMass()/GeV;
if( energyCheck < 0.0 ) // chop off the secondary List
{
vecLen = std::max( 0, --i ); // looks like a memory leak @@@@@@@@@@@@
G4int j;
for(j=i; j<vecLen; j++) delete vec[j];
break;
}
}
return true;
}
/* end of file */