Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-29 07:39:19

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 /// \file Hadr09.cc
0027 /// \brief Main program of the hadronic/Hadr09 example
0028 
0029 //------------------------------------------------------------------------
0030 // This program shows how to use the class Hadronic Generator.
0031 // The class HadronicGenerator is a kind of "hadronic generator", i.e.
0032 // provides Geant4 final states (i.e. secondary particles) produced by
0033 // hadron-nuclear inelastic collisions.
0034 // Please see the class itself for more information.
0035 //
0036 // The use of the class Hadronic Generator is very simple:
0037 // the constructor needs to be invoked only once - specifying the name
0038 // of the Geant4 "physics case" to consider ("FTFP_BERT" will be
0039 // considered as default is the name is not specified) - and then one
0040 // method needs to be called at each collision, specifying the type of
0041 // collision (hadron, energy, direction, material) to be simulated.
0042 // The class HadronicGenerator is expected to work also in a
0043 // multi-threaded environment with "external" threads (i.e. threads
0044 // that are not necessarily managed by Geant4 run-manager):
0045 // each thread should have its own instance of the class.
0046 //
0047 // See the string "***LOOKHERE***" below for the setting of parameters
0048 // of this example: the "physics case", the set of possibilities from
0049 // which to sample the projectile (i.e. whether the projectile is a
0050 // hadron or an ion - in the case of hadron projectile, a list of hadrons
0051 // is possible from which to sample at each collision; in the case of
0052 // ion projectile, only one type of ion needs to be specified),
0053 // the kinetic energy of the projectile (which can be sampled within
0054 // an interval), whether the direction of the projectile is fixed or
0055 // sampled at each collision, the target material (a list of materials
0056 // is possible, from which the target material can be sampled at each
0057 // collision, and then from this target material, the target nucleus
0058 // will be chosen randomly by Geant4 itself), and whether to print out
0059 // some information or not and how frequently.
0060 // Once a well-defined type of hadron-nucleus or nucleus-nucleus
0061 // inelastic collision has been chosen, the method
0062 //   HadronicGenerator::GenerateInteraction
0063 // returns the secondaries produced by that interaction (in the form
0064 // of a G4VParticleChange object).
0065 // Some information about this final-state is printed out as an example.
0066 //
0067 // Usage:  Hadr09
0068 //------------------------------------------------------------------------
0069 
0070 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0071 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0072 
0073 #include "CLHEP/Random/Randomize.h"
0074 #include "CLHEP/Random/Ranlux64Engine.h"
0075 #include "HadronicGenerator.hh"
0076 
0077 #include "G4GenericIon.hh"
0078 #include "G4HadronicParameters.hh"
0079 #include "G4IonTable.hh"
0080 #include "G4Material.hh"
0081 #include "G4NistManager.hh"
0082 #include "G4ParticleTable.hh"
0083 #include "G4PhysicalConstants.hh"
0084 #include "G4ProcessManager.hh"
0085 #include "G4SystemOfUnits.hh"
0086 #include "G4UnitsTable.hh"
0087 #include "G4VParticleChange.hh"
0088 #include "G4ios.hh"
0089 #include "globals.hh"
0090 
0091 #include <iomanip>
0092 
0093 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0094 
0095 int main(int, char**)
0096 {
0097   G4cout << "=== Test of the HadronicGenerator ===" << G4endl;
0098 
0099   // Enable light hypernuclei and anti-hypernuclei
0100   G4HadronicParameters::Instance()->SetEnableHyperNuclei(true);
0101 
0102   // See the HadronicGenerator class for the possibilities and meaning of the "physics cases".
0103   // ( In short, it is the name of the Geant4 hadronic model used for the simulation of
0104   //   the collision, with the possibility of having a transition between two models in
0105   //   a given energy interval, as in physics lists. )
0106   const G4String namePhysics = "FTFP_BERT";  //***LOOKHERE***  PHYSICS CASE
0107   // const G4String namePhysics = "FTFP_BERT_ATL";
0108   // const G4String namePhysics = "QGSP_BERT";
0109   // const G4String namePhysics = "QGSP_BIC";
0110   // const G4String namePhysics = "FTFP_INCLXX";
0111   // const G4String namePhysics = "FTFP";
0112   // const G4String namePhysics = "QGSP";
0113   // const G4String namePhysics = "BERT";
0114   // const G4String namePhysics = "BIC";
0115   // const G4String namePhysics = "IonBIC";
0116   // const G4String namePhysics = "INCL";
0117 
0118   // The kinetic energy of the projectile will be sampled randomly, with flat probability
0119   // in the interval [minEnergy, maxEnergy].
0120   G4double minEnergy = 1.0 * CLHEP::GeV;  //***LOOKHERE***  HADRON PROJECTILE MIN Ekin
0121   G4double maxEnergy = 30.0 * CLHEP::GeV;  //***LOOKHERE***  HADRON PROJECTILE MAX Ekin
0122 
0123   const G4int numCollisions = 1000;  //***LOOKHERE***  NUMBER OF COLLISIONS
0124 
0125   // Enable or disable the print out of this program: if enabled, the number of secondaries
0126   // produced in each collisions is printed out; moreover, once every "printingGap"
0127   // collisions, the list of secondaries is printed out.
0128   const G4bool isPrintingEnabled = true;  //***LOOKHERE***  PRINT OUT ON/OFF
0129   const G4int printingGap = 100;  //***LOOKHERE***  GAP IN PRINTING
0130 
0131   // Vector of Geant4 names of hadron projectiles: one of this will be sampled randomly
0132   // (with uniform probability) for each collision, when the projectile is not a generic ion
0133   // (note that the 6 light hypernuclei and anti-hypernuclei are treated here as for the
0134   // other hadrons, not as generic ions).
0135   // Note: comment out the corresponding line in order to exclude a particle.
0136   std::vector<G4String> vecProjectiles;  //***LOOKHERE***  POSSIBLE HADRON PROJECTILES
0137   vecProjectiles.push_back("pi-");
0138   // Note: vecProjectiles.push_back( "pi0" );               // Excluded because too short-lived
0139   vecProjectiles.push_back("pi+");
0140   vecProjectiles.push_back("kaon-");
0141   vecProjectiles.push_back("kaon+");
0142   vecProjectiles.push_back("kaon0L");
0143   vecProjectiles.push_back("kaon0S");
0144   // Note: vecProjectiles.push_back( "eta" );               // Excluded because too short-lived
0145   // Note: vecProjectiles.push_back( "eta_prime" );         // Excluded because too short-lived
0146   vecProjectiles.push_back("proton");
0147   vecProjectiles.push_back("neutron");
0148   vecProjectiles.push_back("deuteron");
0149   vecProjectiles.push_back("triton");
0150   vecProjectiles.push_back("He3");
0151   vecProjectiles.push_back("alpha");
0152   vecProjectiles.push_back("lambda");
0153   vecProjectiles.push_back("sigma-");
0154   // Note: vecProjectiles.push_back( "sigma0" );            // Excluded because too short-lived
0155   vecProjectiles.push_back("sigma+");
0156   vecProjectiles.push_back("xi-");
0157   vecProjectiles.push_back("xi0");
0158   vecProjectiles.push_back("omega-");
0159   vecProjectiles.push_back("anti_proton");
0160   vecProjectiles.push_back("anti_neutron");
0161   vecProjectiles.push_back("anti_lambda");
0162   vecProjectiles.push_back("anti_sigma-");
0163   // Note: vecProjectiles.push_back( "anti_sigma0" );       // Excluded because too short-lived
0164   vecProjectiles.push_back("anti_sigma+");
0165   vecProjectiles.push_back("anti_xi-");
0166   vecProjectiles.push_back("anti_xi0");
0167   vecProjectiles.push_back("anti_omega-");
0168   vecProjectiles.push_back("anti_deuteron");
0169   vecProjectiles.push_back("anti_triton");
0170   vecProjectiles.push_back("anti_He3");
0171   vecProjectiles.push_back("anti_alpha");
0172 
0173   // Only FTFP and QGSP can handle nuclear interaction of charm and bottom hadrons
0174   if (namePhysics == "FTFP_BERT" || namePhysics == "FTFP_BERT_ATL" || namePhysics == "QGSP_BERT"
0175       || namePhysics == "QGSP_BIC" || namePhysics == "FTFP" || namePhysics == "QGSP")
0176   {
0177     // Charm and bottom hadrons
0178     vecProjectiles.push_back("D+");
0179     vecProjectiles.push_back("D-");
0180     vecProjectiles.push_back("D0");
0181     vecProjectiles.push_back("anti_D0");
0182     vecProjectiles.push_back("Ds+");
0183     vecProjectiles.push_back("Ds-");
0184     // Note: vecProjectiles.push_back( "etac" );   // Excluded because too short-lived
0185     // Note: vecProjectiles.push_back( "J/psi" );  // Excluded because too short-lived
0186     vecProjectiles.push_back("B+");
0187     vecProjectiles.push_back("B-");
0188     vecProjectiles.push_back("B0");
0189     vecProjectiles.push_back("anti_B0");
0190     vecProjectiles.push_back("Bs0");
0191     vecProjectiles.push_back("anti_Bs0");
0192     vecProjectiles.push_back("Bc+");
0193     vecProjectiles.push_back("Bc-");
0194     // Note: vecProjectiles.push_back( "Upsilon" );         // Excluded because too short-lived
0195     vecProjectiles.push_back("lambda_c+");
0196     vecProjectiles.push_back("anti_lambda_c+");
0197     // Note: vecProjectiles.push_back( "sigma_c+" );        // Excluded because too short-lived
0198     // Note: vecProjectiles.push_back( "anti_sigma_c+" );   // Excluded because too short-lived
0199     // Note: vecProjectiles.push_back( "sigma_c0" );        // Excluded because too short-lived
0200     // Note: vecProjectiles.push_back( "anti_sigma_c0" );   // Excluded because too short-lived
0201     // Note: vecProjectiles.push_back( "sigma_c++" );       // Excluded because too short-lived
0202     // Note: vecProjectiles.push_back( "anti_sigma_c++" );  // Excluded because too short-lived
0203     vecProjectiles.push_back("xi_c+");
0204     vecProjectiles.push_back("anti_xi_c+");
0205     vecProjectiles.push_back("xi_c0");
0206     vecProjectiles.push_back("anti_xi_c0");
0207     vecProjectiles.push_back("omega_c0");
0208     vecProjectiles.push_back("anti_omega_c0");
0209     vecProjectiles.push_back("lambda_b");
0210     vecProjectiles.push_back("anti_lambda_b");
0211     // Note: vecProjectiles.push_back( "sigma_b+" );       // Excluded because too short-lived
0212     // Note: vecProjectiles.push_back( "anti_sigma_b+" );  // Excluded because too short-lived
0213     // Note: vecProjectiles.push_back( "sigma_b0" );       // Excluded because too short-lived
0214     // Note: vecProjectiles.push_back( "sigma_b0" );       // Excluded because too short-lived
0215     // Note: vecProjectiles.push_back( "sigma_b-" );       // Excluded because too short-lived
0216     // Note: vecProjectiles.push_back( "anti_sigma_b-" );  // Excluded because too short-lived
0217     vecProjectiles.push_back("xi_b0");
0218     vecProjectiles.push_back("anti_xi_b0");
0219     vecProjectiles.push_back("xi_b-");
0220     vecProjectiles.push_back("anti_xi_b-");
0221     vecProjectiles.push_back("omega_b-");
0222     vecProjectiles.push_back("anti_omega_b-");
0223   }
0224 
0225   // If the hadronic interactions of light hypernuclei and anti-hypernuclei
0226   // are swtiched on, then only FTFP and INCL can handle the nuclear interactions
0227   // of light hypernuclei, and only FTFP is capable of handling the nuclear
0228   // interactions of light anti-hypernuclei.
0229   if (G4HadronicParameters::Instance()->EnableHyperNuclei()) {
0230     if (namePhysics == "FTFP_BERT" || namePhysics == "FTFP_INCLXX" || namePhysics == "FTFP"
0231         || namePhysics == "INCL")
0232     {
0233       // Light hypernuclei
0234       vecProjectiles.push_back("hypertriton");
0235       vecProjectiles.push_back("hyperalpha");
0236       vecProjectiles.push_back("hyperH4");
0237       vecProjectiles.push_back("doublehyperH4");
0238       vecProjectiles.push_back("doublehyperdoubleneutron");
0239       vecProjectiles.push_back("hyperHe5");
0240     }
0241     if (namePhysics == "FTFP_BERT" || namePhysics == "FTFP_INCLXX" || namePhysics == "FTFP") {
0242       // Light anti-hypernuclei
0243       vecProjectiles.push_back("anti_hypertriton");
0244       vecProjectiles.push_back("anti_hyperalpha");
0245       vecProjectiles.push_back("anti_hyperH4");
0246       vecProjectiles.push_back("anti_doublehyperH4");
0247       vecProjectiles.push_back("anti_doublehyperdoubleneutron");
0248       vecProjectiles.push_back("anti_hyperHe5");
0249     }
0250   }
0251 
0252   G4ParticleDefinition* projectileNucleus = nullptr;
0253   G4GenericIon* gion = G4GenericIon::GenericIon();
0254   gion->SetProcessManager(new G4ProcessManager(gion));
0255   G4ParticleTable* partTable = G4ParticleTable::GetParticleTable();
0256   G4IonTable* ions = partTable->GetIonTable();
0257   partTable->SetReadiness();
0258   ions->CreateAllIon();
0259   ions->CreateAllIsomer();
0260 
0261   const G4bool isProjectileIon = false;  //***LOOKHERE***  HADRON (false) OR ION (true) PROJECTILE?
0262   if (isProjectileIon) {
0263     minEnergy = 40.0 * 13.0 * CLHEP::GeV;  //***LOOKHERE***  ION PROJECTILE MIN Ekin
0264     maxEnergy = 40.0 * 13.0 * CLHEP::GeV;  //***LOOKHERE***  ION PROJECTILE MAX Ekin
0265     G4int ionZ = 18, ionA = 40;  //***LOOKHERE***  ION PROJECTILE (Z, A)
0266     projectileNucleus = partTable->GetIonTable()->GetIon(ionZ, ionA, 0.0);
0267   }
0268 
0269   // Vector of Geant4 NIST names of materials: one of this will be sampled randomly
0270   // (with uniform probability) for each collision and used as target material.
0271   // Note: comment out the corresponding line in order to exclude a material;
0272   //       or, vice versa, add a new line to extend the list with another material.
0273   std::vector<G4String> vecMaterials;  //***LOOKHERE*** : NIST TARGET MATERIALS
0274   vecMaterials.push_back("G4_H");
0275   vecMaterials.push_back("G4_He");
0276   vecMaterials.push_back("G4_Be");
0277   vecMaterials.push_back("G4_C");
0278   vecMaterials.push_back("G4_Al");
0279   vecMaterials.push_back("G4_Si");
0280   // vecMaterials.push_back( "G4_Sc" );
0281   vecMaterials.push_back("G4_Ar");
0282   vecMaterials.push_back("G4_Fe");
0283   vecMaterials.push_back("G4_Cu");
0284   vecMaterials.push_back("G4_W");
0285   vecMaterials.push_back("G4_Pb");
0286 
0287   const G4int numProjectiles = vecProjectiles.size();
0288   const G4int numMaterials = vecMaterials.size();
0289 
0290   G4cout << G4endl << "=================  Configuration ==================" << G4endl
0291          << "Model: " << namePhysics << G4endl << "Ekin: [ " << minEnergy / CLHEP::GeV << " , "
0292          << maxEnergy / CLHEP::GeV << " ] GeV" << G4endl
0293          << "Number of collisions:  " << numCollisions << G4endl
0294          << "Number of hadron projectiles: " << numProjectiles << G4endl
0295          << "Number of materials:   " << numMaterials << G4endl
0296          << "IsIonProjectile: " << (projectileNucleus != nullptr ? "true \t" : "false")
0297          << (projectileNucleus != nullptr ? projectileNucleus->GetParticleName() : G4String(""))
0298          << G4endl << "===================================================" << G4endl << G4endl;
0299 
0300   CLHEP::Ranlux64Engine defaultEngine(1234567, 4);
0301   CLHEP::HepRandom::setTheEngine(&defaultEngine);
0302   G4int seed = time(NULL);
0303   CLHEP::HepRandom::setTheSeed(seed);
0304   G4cout << G4endl << " Initial seed = " << seed << G4endl << G4endl;
0305 
0306   // Instanciate the HadronicGenerator providing the name of the "physics case"
0307   HadronicGenerator* theHadronicGenerator = new HadronicGenerator(namePhysics);
0308   //****************************************************************************
0309 
0310   if (theHadronicGenerator == nullptr) {
0311     G4cerr << "ERROR: theHadronicGenerator is NULL !" << G4endl;
0312     return 1;
0313   }
0314   else if (!theHadronicGenerator->IsPhysicsCaseSupported()) {
0315     G4cerr << "ERROR: this physics case is NOT supported !" << G4endl;
0316     return 2;
0317   }
0318 
0319   // Loop over the collisions
0320   G4double rnd1, rnd2, rnd3, rnd4, rnd5, rnd6, normalization, projectileEnergy;
0321   G4VParticleChange* aChange = nullptr;
0322   for (G4int i = 0; i < numCollisions; ++i) {
0323     // Draw some random numbers to select the hadron-nucleus interaction:
0324     // projectile hadron, projectile kinetic energy, projectile direction, and target material.
0325     rnd1 = CLHEP::HepRandom::getTheEngine()->flat();
0326     rnd2 = CLHEP::HepRandom::getTheEngine()->flat();
0327     rnd3 = CLHEP::HepRandom::getTheEngine()->flat();
0328     rnd4 = CLHEP::HepRandom::getTheEngine()->flat();
0329     rnd5 = CLHEP::HepRandom::getTheEngine()->flat();
0330     rnd6 = CLHEP::HepRandom::getTheEngine()->flat();
0331     // Sample the projectile kinetic energy
0332     projectileEnergy = minEnergy + rnd1 * (maxEnergy - minEnergy);
0333     if (projectileEnergy <= 0.0) projectileEnergy = minEnergy;
0334     // Sample the projectile direction
0335     normalization = 1.0 / std::sqrt(rnd2 * rnd2 + rnd3 * rnd3 + rnd4 * rnd4);
0336     const G4bool isOnSmearingDirection = true;  //***LOOKHERE***
0337     G4ThreeVector aDirection = G4ThreeVector(0.0, 0.0, 1.0);  //***LOOKHERE***
0338     if (isOnSmearingDirection) {
0339       aDirection = G4ThreeVector(normalization * rnd2, normalization * rnd3, normalization * rnd4);
0340     }
0341     // Sample the projectile hadron from the vector vecProjectiles
0342     G4int index_projectile = std::trunc(rnd5 * numProjectiles);
0343     G4String nameProjectile = vecProjectiles[index_projectile];
0344     G4ParticleDefinition* projectile = partTable->FindParticle(nameProjectile);
0345     if (projectileNucleus) {
0346       nameProjectile = projectileNucleus->GetParticleName();
0347       projectile = projectileNucleus;
0348     }
0349     // Sample the target material from the vector vecMaterials
0350     // (Note: the target nucleus will be sampled by Geant4)
0351     G4int index_material = std::trunc(rnd6 * numMaterials);
0352     G4String nameMaterial = vecMaterials[index_material];
0353     G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(nameMaterial);
0354     if (material == nullptr) {
0355       G4cerr << "ERROR: Material " << nameMaterial << " is not found !" << G4endl;
0356       return 3;
0357     }
0358     if (isPrintingEnabled) {
0359       G4cout << "\t Collision " << i << " ; projectile=" << nameProjectile;
0360       if (projectileNucleus) {
0361         G4cout << " ; Ekin[MeV]/nucleon="
0362                << projectileEnergy
0363                     / static_cast<G4double>(std::abs(projectileNucleus->GetBaryonNumber()));
0364       }
0365       else {
0366         G4cout << " ; Ekin[MeV]=" << projectileEnergy;
0367       }
0368       G4cout << " ; direction=" << aDirection << " ; material=" << nameMaterial;
0369     }
0370 
0371     // Call here the "hadronic generator" to get the secondaries produced by the hadronic collision
0372     aChange = theHadronicGenerator->GenerateInteraction(
0373       projectile, projectileEnergy,
0374       /* ********************************************** */ aDirection, material);
0375 
0376     G4int nsec = aChange ? aChange->GetNumberOfSecondaries() : 0;
0377     G4bool isPrintingOfSecondariesEnabled = false;
0378     if (isPrintingEnabled) {
0379       G4cout << G4endl << "\t --> #secondaries=" << nsec
0380              << " ; impactParameter[fm]=" << theHadronicGenerator->GetImpactParameter() / fermi
0381              << " ; #projectileSpectatorNucleons="
0382              << theHadronicGenerator->GetNumberOfProjectileSpectatorNucleons()
0383              << " ; #targetSpectatorNucleons="
0384              << theHadronicGenerator->GetNumberOfTargetSpectatorNucleons()
0385              << " ; #NNcollisions=" << theHadronicGenerator->GetNumberOfNNcollisions() << G4endl;
0386       if (i % printingGap == 0) {
0387         isPrintingOfSecondariesEnabled = true;
0388         G4cout << "\t \t List of produced secondaries: " << G4endl;
0389       }
0390     }
0391     // Loop over produced secondaries and eventually print out some information.
0392     for (G4int j = 0; j < nsec; ++j) {
0393       const G4DynamicParticle* sec = aChange->GetSecondary(j)->GetDynamicParticle();
0394       if (isPrintingOfSecondariesEnabled) {
0395         G4cout << "\t \t \t j=" << j << "\t" << sec->GetDefinition()->GetParticleName()
0396                << "\t p=" << sec->Get4Momentum() << " MeV" << G4endl;
0397       }
0398       delete aChange->GetSecondary(j);
0399     }
0400     if (aChange) aChange->Clear();
0401   }
0402 
0403   G4cout << G4endl << " Final random number = " << CLHEP::HepRandom::getTheEngine()->flat()
0404          << G4endl << "=== End of test ===" << G4endl;
0405 }
0406 
0407 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......