Main method to apply the INCL physics model.
179{
180 G4ParticleDefinition
const *
const trackDefinition = aTrack.
GetDefinition();
188
189
190 if((isIonTrack && ((trackZ<=0 && trackL==0) || trackA<=trackZ)) ||
191 (nucleusA>1 && (nucleusZ<=0 || nucleusA<=nucleusZ))) {
192 theResult.Clear();
193 theResult.SetStatusChange(
isAlive);
196 return &theResult;
197 }
198
199
200
201 if(trackA<=1 && nucleusA<=1 && (trackPDG!=-2212 && trackPDG!=-2112)) {
202 return theBackupModelNucleon->ApplyYourself(aTrack, theNucleus);
203 }
204
205
206
207 const G4int theMaxProjMassINCL = theInterfaceStore->GetMaxProjMassINCL();
208 if(trackA > theMaxProjMassINCL && nucleusA > theMaxProjMassINCL) {
209 if(!complainedAboutBackupModel) {
210 complainedAboutBackupModel = true;
211 std::stringstream ss;
212 ss << "INCL++ refuses to handle reactions between nuclei with A>"
213 << theMaxProjMassINCL
214 << ". A backup model ("
215 << theBackupModel->GetModelName()
216 << ") will be used instead.";
217 theInterfaceStore->EmitBigWarning(ss.str());
218 }
219 return theBackupModel->ApplyYourself(aTrack, theNucleus);
220 }
221
222
223 const G4double cascadeMinEnergyPerNucleon = theInterfaceStore->GetCascadeMinEnergyPerNucleon();
226 && trackKinE < cascadeMinEnergyPerNucleon) {
227 if(!complainedAboutPreCompound) {
228 complainedAboutPreCompound = true;
229 std::stringstream ss;
230 ss << "INCL++ refuses to handle nucleon-induced reactions below "
231 << cascadeMinEnergyPerNucleon / MeV
232 << " MeV. A PreCoumpound model ("
233 << thePreCompoundModel->GetModelName()
234 << ") will be used instead.";
235 theInterfaceStore->EmitBigWarning(ss.str());
236 }
237 return thePreCompoundModel->ApplyYourself(aTrack, theNucleus);
238 }
239
240
241 const G4double theNucleusMass = theIonTable->GetIonMass(nucleusZ, nucleusA);
243 const G4double theTrackEnergy = trackKinE + theTrackMass;
244 const G4double theTrackMomentumAbs2 = theTrackEnergy*theTrackEnergy - theTrackMass*theTrackMass;
245 const G4double theTrackMomentumAbs = ((theTrackMomentumAbs2>0.0) ? std::sqrt(theTrackMomentumAbs2) : 0.0);
247
250 fourMomentumIn.
setE(theTrackEnergy + theNucleusMass);
251 fourMomentumIn.
setVect(theTrackMomentum);
252
253
254 const G4bool inverseKinematics = AccurateProjectile(aTrack, theNucleus);
255
256
259 G4HadProjectile const *aProjectileTrack = &aTrack;
260 G4Nucleus *theTargetNucleus = &theNucleus;
261 if(inverseKinematics) {
262 G4ParticleDefinition *oldTargetDef = theIonTable->GetIon(nucleusZ, nucleusA, 0);
263 const G4ParticleDefinition *oldProjectileDef = trackDefinition;
264
265 if(oldProjectileDef != 0 && oldTargetDef != 0) {
269 if(newTargetA > 0 && newTargetZ > 0) {
270
271 theTargetNucleus = new G4Nucleus(newTargetA, newTargetZ, newTargetL);
274 G4DynamicParticle swappedProjectileParticle(oldTargetDef, (*toInverseKinematics) * theProjectile4Momentum);
275 aProjectileTrack = new G4HadProjectile(swappedProjectileParticle);
276 } else {
277 G4String message = "badly defined target after swapping. Falling back to normal (non-swapped) mode.";
278 theInterfaceStore->EmitWarning(message);
280 }
281 } else {
282 G4String message = "oldProjectileDef or oldTargetDef was null";
283 theInterfaceStore->EmitWarning(message);
285 }
286 }
287
288
289
290
291
293
294
295
296
297
298
299
300
301
307
308
309
310
311
312
313
314
315 theResult.Clear();
317
318 std::list<G4Fragment> remnants;
319
320 const G4int maxTries = 200;
322
323
324
326 do {
327 const G4INCL::ParticleSpecies theSpecies = toINCLParticleSpecies(*aProjectileTrack);
328 const G4double kineticEnergy = toINCLKineticEnergy(*aProjectileTrack);
329
330
332
333 const G4INCL::EventInfo eventInfo = theINCLModel->
processEvent(theSpecies, kineticEnergy,
336 -theTargetNucleus->
GetL());
337
339 if(eventIsOK) {
340
341
342
343 if(inverseKinematics) {
345 }
346
348
358 G4DynamicParticle *p = toG4Particle(
A, Z,
S, PDGCode, kinE, px, py, pz);
359 if(p != 0) {
361
362
363 momentum *= toLabFrame;
364
365 if(inverseKinematics) {
366 momentum *= *toDirectKinematics;
368 }
369
370
372 fourMomentumOut += momentum;
373
374
375 G4HadSecondary secondary(p, 1.0, secID);
376 G4ParticleDefinition* parentResonanceDef = nullptr;
379 }
380 secondary.SetParentResonanceDef(parentResonanceDef);
382
383 theResult.AddSecondary(secondary);
384
385 } else {
386 G4String message = "the model produced a particle that couldn't be converted to Geant4 particle.";
387 theInterfaceStore->EmitWarning(message);
388 }
389 }
390
395
396 if(( Z == 0 &&
S == 0 &&
A > 1 ) ||
397 ( Z == 0 &&
S != 0 &&
A < 4 ) ||
398 ( Z != 0 &&
S != 0 &&
A == Z + std::abs(
S) )) {
399 std::stringstream ss;
400 ss <<
"unphysical residual fragment : Z=" << Z <<
" S=" <<
S <<
" A=" <<
A
401 << " skipping it and resampling the collision";
402 theInterfaceStore->EmitWarning(ss.str());
403 eventIsOK = false;
404 continue;
405 }
411 eventInfo.
jxRem[i]*hbar_Planck,
412 eventInfo.
jyRem[i]*hbar_Planck,
413 eventInfo.
jzRem[i]*hbar_Planck
414 );
417
420 } else {
421
423 }
424 const G4double scaling = remnant4MomentumScaling(nuclearMass, kinE, px, py, pz);
426 nuclearMass + kinE);
427 if(std::abs(scaling - 1.0) > 0.01) {
428 std::stringstream ss;
429 ss << "momentum scaling = " << scaling
430 << "\n Lorentz vector = " << fourMomentum
431 <<
")\n A = " <<
A <<
", Z = " << Z <<
", S = " <<
S
432 << "\n E* = " << excitationE << ", nuclearMass = " << nuclearMass
433 <<
"\n remnant i=" << i <<
", nRemnants=" << eventInfo.
nRemnants
437 << ", in " << (inverseKinematics ? "inverse" : "direct") << " kinematics.";
438 theInterfaceStore->EmitWarning(ss.str());
439 }
440
441
442 fourMomentum *= toLabFrame;
443 spin *= toLabFrame3;
444
445 if(inverseKinematics) {
446 fourMomentum *= *toDirectKinematics;
447 fourMomentum.setVect(-fourMomentum.vect());
448 }
449
450 fourMomentumOut += fourMomentum;
451 G4Fragment remnant(
A, Z, std::abs(
S), fourMomentum);
452 remnant.SetAngularMomentum(spin);
453 remnant.SetCreatorModelID(secID);
454 if(dumpRemnantInfo) {
455 G4cerr <<
"G4INCLXX_DUMP_REMNANT: " << remnant <<
" spin: " << spin <<
G4endl;
456 }
457 remnants.push_back(remnant);
458 }
459
460
461 if(!eventIsOK) {
462 const G4int nSecondaries = (
G4int)theResult.GetNumberOfSecondaries();
463 for(
G4int j=0; j<nSecondaries; ++j)
delete theResult.GetSecondary(j)->GetParticle();
464 theResult.Clear();
466 remnants.clear();
467 } else {
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485 const G4LorentzVector violation4Momentum = fourMomentumOut - fourMomentumIn;
486 const G4double energyViolation = std::abs(violation4Momentum.
e());
487 const G4double momentumViolation = violation4Momentum.
rho();
489 std::stringstream ss;
490 ss << "energy conservation violated by " << energyViolation/MeV << " MeV in "
493 << " inelastic reaction, in " << (inverseKinematics ? "inverse" : "direct") << " kinematics. Will resample.";
494 theInterfaceStore->EmitWarning(ss.str());
495 eventIsOK = false;
496 const G4int nSecondaries = (
G4int)theResult.GetNumberOfSecondaries();
497 for(
G4int j=0; j<nSecondaries; ++j)
delete theResult.GetSecondary(j)->GetParticle();
498 theResult.Clear();
500 remnants.clear();
502 std::stringstream ss;
503 ss << "momentum conservation violated by " << momentumViolation/MeV << " MeV in "
506 << " inelastic reaction, in " << (inverseKinematics ? "inverse" : "direct") << " kinematics. Will resample.";
507 theInterfaceStore->EmitWarning(ss.str());
508 eventIsOK = false;
509 const G4int nSecondaries = (
G4int)theResult.GetNumberOfSecondaries();
510 for(
G4int j=0; j<nSecondaries; ++j)
delete theResult.GetSecondary(j)->GetParticle();
511 theResult.Clear();
513 remnants.clear();
514 }
515 }
516 }
517 nTries++;
518 } while(!eventIsOK && nTries < maxTries);
519
520
521 if(inverseKinematics) {
522 delete aProjectileTrack;
523 delete theTargetNucleus;
524 delete toInverseKinematics;
525 delete toDirectKinematics;
526 }
527
528 if(!eventIsOK) {
529 std::stringstream ss;
530 ss << "maximum number of tries exceeded for the proposed "
532 << " + " << theIonTable->GetIonName(nucleusZ, nucleusA, 0)
533 << " inelastic reaction, in " << (inverseKinematics ? "inverse" : "direct") << " kinematics.";
534 theInterfaceStore->EmitWarning(ss.str());
535 theResult.SetStatusChange(
isAlive);
538 return &theResult;
539 }
540
541
542
544 for(std::list<G4Fragment>::iterator i = remnants.begin();
545 i != remnants.end(); ++i) {
547
548 for(G4ReactionProductVector::iterator fragment = deExcitationResult->begin();
549 fragment != deExcitationResult->end(); ++fragment) {
550 const G4ParticleDefinition *def = (*fragment)->GetDefinition();
551 if(def != 0) {
552 G4DynamicParticle *theFragment = new G4DynamicParticle(def, (*fragment)->GetMomentum());
553 theResult.AddSecondary(theFragment, (*fragment)->GetCreatorModelID());
554 }
555 }
556
557 for(G4ReactionProductVector::iterator fragment = deExcitationResult->begin();
558 fragment != deExcitationResult->end(); ++fragment) {
559 delete (*fragment);
560 }
561 deExcitationResult->clear();
562 delete deExcitationResult;
563 }
564 }
565
566 remnants.clear();
567
568 if((theTally = theInterfaceStore->GetTally()))
569 theTally->Tally(aTrack, theNucleus, theResult);
570
571 return &theResult;
572}
G4double S(G4double temp)
CLHEP::HepLorentzRotation G4LorentzRotation
CLHEP::HepLorentzVector G4LorentzVector
std::vector< G4ReactionProduct * > G4ReactionProductVector
CLHEP::HepRotation G4RotationMatrix
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cerr
HepLorentzRotation inverse() const
void setVect(const Hep3Vector &)
HepRotation inverse() const
HepRotation & rotateZ(double delta)
HepRotation & rotateY(double delta)
G4LorentzVector Get4Momentum() const
void Set4Momentum(const G4LorentzVector &momentum)
static G4GenericIon * GenericIon()
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4LorentzVector & Get4Momentum() const
static G4double GetNuclearMass(G4int A, G4int Z, G4int L)
G4INCL::INCL * GetINCLModel()
Get the cached INCL model engine.
const EventInfo & processEvent()
static G4Neutron * NeutronDefinition()
static G4double GetNuclearMass(const G4double A, const G4double Z)
G4int GetAtomicNumber() const
const G4String & GetParticleType() const
G4double GetPDGMass() const
G4int GetAtomicMass() const
G4int GetPDGEncoding() const
G4double GetPDGCharge() const
G4int GetNumberOfLambdasInHypernucleus() const
const G4String & GetParticleName() const
G4ParticleDefinition * FindParticle(G4int PDGEncoding)
static G4ParticleTable * GetParticleTable()
static G4Proton * ProtonDefinition()
Short_t S[maxSizeParticles]
Particle strangeness number.
Int_t parentResonancePDGCode[maxSizeParticles]
Particle's parent resonance PDG code.
Short_t nRemnants
Number of remnants.
Bool_t transparent
True if the event is transparent.
Short_t A[maxSizeParticles]
Particle mass number.
Float_t EKinRem[maxSizeRemnants]
Remnant kinetic energy [MeV].
Int_t parentResonanceID[maxSizeParticles]
Particle's parent resonance unique ID identifier.
Float_t jzRem[maxSizeRemnants]
Remnant angular momentum, z component [ ].
Float_t EStarRem[maxSizeRemnants]
Remnant excitation energy [MeV].
Short_t Z[maxSizeParticles]
Particle charge number.
Float_t EKin[maxSizeParticles]
Particle kinetic energy [MeV].
Short_t nParticles
Number of particles in the final state.
Float_t jxRem[maxSizeRemnants]
Remnant angular momentum, x component [ ].
Float_t px[maxSizeParticles]
Particle momentum, x component [MeV/c].
Short_t SRem[maxSizeRemnants]
Remnant strangeness number.
Float_t pxRem[maxSizeRemnants]
Remnant momentum, x component [MeV/c].
Float_t pyRem[maxSizeRemnants]
Remnant momentum, y component [MeV/c].
Float_t pzRem[maxSizeRemnants]
Remnant momentum, z component [MeV/c].
Float_t pz[maxSizeParticles]
Particle momentum, z component [MeV/c].
Int_t PDGCode[maxSizeParticles]
PDG numbering of the particles.
Float_t jyRem[maxSizeRemnants]
Remnant angular momentum, y component [ ].
Float_t py[maxSizeParticles]
Particle momentum, y component [MeV/c].
Short_t ARem[maxSizeRemnants]
Remnant mass number.
Short_t ZRem[maxSizeRemnants]
Remnant charge number.