File indexing completed on 2026-04-29 07:39:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
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
0094
0095 int main(int, char**)
0096 {
0097 G4cout << "=== Test of the HadronicGenerator ===" << G4endl;
0098
0099
0100 G4HadronicParameters::Instance()->SetEnableHyperNuclei(true);
0101
0102
0103
0104
0105
0106 const G4String namePhysics = "FTFP_BERT";
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 G4double minEnergy = 1.0 * CLHEP::GeV;
0121 G4double maxEnergy = 30.0 * CLHEP::GeV;
0122
0123 const G4int numCollisions = 1000;
0124
0125
0126
0127
0128 const G4bool isPrintingEnabled = true;
0129 const G4int printingGap = 100;
0130
0131
0132
0133
0134
0135
0136 std::vector<G4String> vecProjectiles;
0137 vecProjectiles.push_back("pi-");
0138
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
0145
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
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
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
0174 if (namePhysics == "FTFP_BERT" || namePhysics == "FTFP_BERT_ATL" || namePhysics == "QGSP_BERT"
0175 || namePhysics == "QGSP_BIC" || namePhysics == "FTFP" || namePhysics == "QGSP")
0176 {
0177
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
0185
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
0195 vecProjectiles.push_back("lambda_c+");
0196 vecProjectiles.push_back("anti_lambda_c+");
0197
0198
0199
0200
0201
0202
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
0212
0213
0214
0215
0216
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
0226
0227
0228
0229 if (G4HadronicParameters::Instance()->EnableHyperNuclei()) {
0230 if (namePhysics == "FTFP_BERT" || namePhysics == "FTFP_INCLXX" || namePhysics == "FTFP"
0231 || namePhysics == "INCL")
0232 {
0233
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
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;
0262 if (isProjectileIon) {
0263 minEnergy = 40.0 * 13.0 * CLHEP::GeV;
0264 maxEnergy = 40.0 * 13.0 * CLHEP::GeV;
0265 G4int ionZ = 18, ionA = 40;
0266 projectileNucleus = partTable->GetIonTable()->GetIon(ionZ, ionA, 0.0);
0267 }
0268
0269
0270
0271
0272
0273 std::vector<G4String> vecMaterials;
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
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
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
0320 G4double rnd1, rnd2, rnd3, rnd4, rnd5, rnd6, normalization, projectileEnergy;
0321 G4VParticleChange* aChange = nullptr;
0322 for (G4int i = 0; i < numCollisions; ++i) {
0323
0324
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
0332 projectileEnergy = minEnergy + rnd1 * (maxEnergy - minEnergy);
0333 if (projectileEnergy <= 0.0) projectileEnergy = minEnergy;
0334
0335 normalization = 1.0 / std::sqrt(rnd2 * rnd2 + rnd3 * rnd3 + rnd4 * rnd4);
0336 const G4bool isOnSmearingDirection = true;
0337 G4ThreeVector aDirection = G4ThreeVector(0.0, 0.0, 1.0);
0338 if (isOnSmearingDirection) {
0339 aDirection = G4ThreeVector(normalization * rnd2, normalization * rnd3, normalization * rnd4);
0340 }
0341
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
0350
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
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
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