Main method to apply the INCL physics model.
177{
185
186
187 if((isIonTrack && ((trackZ<=0 && trackL==0) || trackA<=trackZ)) ||
188 (nucleusA>1 && (nucleusZ<=0 || nucleusA<=nucleusZ))) {
193 return &theResult;
194 }
195
196
197
198 if(trackA<=1 && nucleusA<=1 && (trackZ>=0 || trackA==0)) {
199 return theBackupModelNucleon->
ApplyYourself(aTrack, theNucleus);
200 }
201
202
203
205 if(trackA > theMaxProjMassINCL && nucleusA > theMaxProjMassINCL) {
206 if(!complainedAboutBackupModel) {
207 complainedAboutBackupModel = true;
208 std::stringstream ss;
209 ss << "INCL++ refuses to handle reactions between nuclei with A>"
210 << theMaxProjMassINCL
211 << ". A backup model ("
213 << ") will be used instead.";
215 }
217 }
218
219
223 && trackKinE < cascadeMinEnergyPerNucleon) {
224 if(!complainedAboutPreCompound) {
225 complainedAboutPreCompound = true;
226 std::stringstream ss;
227 ss << "INCL++ refuses to handle nucleon-induced reactions below "
228 << cascadeMinEnergyPerNucleon / MeV
229 << " MeV. A PreCoumpound model ("
231 << ") will be used instead.";
233 }
234 return thePreCompoundModel->
ApplyYourself(aTrack, theNucleus);
235 }
236
237
240 const G4double theTrackEnergy = trackKinE + theTrackMass;
241 const G4double theTrackMomentumAbs2 = theTrackEnergy*theTrackEnergy - theTrackMass*theTrackMass;
242 const G4double theTrackMomentumAbs = ((theTrackMomentumAbs2>0.0) ? std::sqrt(theTrackMomentumAbs2) : 0.0);
244
247 fourMomentumIn.
setE(theTrackEnergy + theNucleusMass);
248 fourMomentumIn.
setVect(theTrackMomentum);
249
250
251 const G4bool inverseKinematics = AccurateProjectile(aTrack, theNucleus);
252
253
257 G4Nucleus *theTargetNucleus = &theNucleus;
258 if(inverseKinematics) {
261
262 if(oldProjectileDef != 0 && oldTargetDef != 0) {
266 if(newTargetA > 0 && newTargetZ > 0) {
267
268 theTargetNucleus =
new G4Nucleus(newTargetA, newTargetZ, newTargetL);
271 G4DynamicParticle swappedProjectileParticle(oldTargetDef, (*toInverseKinematics) * theProjectile4Momentum);
273 } else {
274 G4String message =
"badly defined target after swapping. Falling back to normal (non-swapped) mode.";
277 }
278 } else {
279 G4String message =
"oldProjectileDef or oldTargetDef was null";
282 }
283 }
284
285
286
287
288
290
291
292
293
294
295
296
297
298
304
305
306
307
308
309
310
311
314
315 std::list<G4Fragment> remnants;
316
317 const G4int maxTries = 200;
319
320
321
323 do {
325 const G4double kineticEnergy = toINCLKineticEnergy(*aProjectileTrack);
326
327
329
333 -theTargetNucleus->
GetL());
334
336 if(eventIsOK) {
337
338
339
340 if(inverseKinematics) {
342 }
343
345
356 if(p != 0) {
358
359
360 momentum *= toLabFrame;
361
362 if(inverseKinematics) {
363 momentum *= *toDirectKinematics;
365 }
366
367
369 fourMomentumOut += momentum;
370
371
376 }
377 secondary.SetParentResonanceDef(parentResonanceDef);
379
381
382 } else {
383 G4String message =
"the model produced a particle that couldn't be converted to Geant4 particle.";
385 }
386 }
387
392
393 if(( Z == 0 &&
S == 0 &&
A > 1 ) ||
394 ( Z == 0 &&
S != 0 &&
A < 4 ) ||
395 ( Z != 0 &&
S != 0 &&
A == Z + std::abs(
S) )) {
396 std::stringstream ss;
397 ss <<
"unphysical residual fragment : Z=" << Z <<
" S=" <<
S <<
" A=" <<
A
398 << " skipping it and resampling the collision";
400 eventIsOK = false;
401 continue;
402 }
408 eventInfo.
jxRem[i]*hbar_Planck,
409 eventInfo.
jyRem[i]*hbar_Planck,
410 eventInfo.
jzRem[i]*hbar_Planck
411 );
416 } else {
417
419 }
420 const G4double scaling = remnant4MomentumScaling(nuclearMass, kinE, px, py, pz);
422 nuclearMass + kinE);
423 if(std::abs(scaling - 1.0) > 0.01) {
424 std::stringstream ss;
425 ss << "momentum scaling = " << scaling
426 << "\n Lorentz vector = " << fourMomentum
427 <<
")\n A = " <<
A <<
", Z = " << Z <<
", S = " <<
S
428 << "\n E* = " << excitationE << ", nuclearMass = " << nuclearMass
429 <<
"\n remnant i=" << i <<
", nRemnants=" << eventInfo.
nRemnants
433 << ", in " << (inverseKinematics ? "inverse" : "direct") << " kinematics.";
435 }
436
437
438 fourMomentum *= toLabFrame;
439 spin *= toLabFrame3;
440
441 if(inverseKinematics) {
442 fourMomentum *= *toDirectKinematics;
443 fourMomentum.setVect(-fourMomentum.vect());
444 }
445
446 fourMomentumOut += fourMomentum;
448 remnant.SetAngularMomentum(spin);
449 remnant.SetCreatorModelID(secID);
450 if(dumpRemnantInfo) {
451 G4cerr <<
"G4INCLXX_DUMP_REMNANT: " << remnant <<
" spin: " << spin <<
G4endl;
452 }
453 remnants.push_back(remnant);
454 }
455
456
457 if(!eventIsOK) {
462 remnants.clear();
463 } else {
464
465 const G4LorentzVector violation4Momentum = fourMomentumOut - fourMomentumIn;
466 const G4double energyViolation = std::abs(violation4Momentum.
e());
467 const G4double momentumViolation = violation4Momentum.
rho();
469 std::stringstream ss;
470 ss << "energy conservation violated by " << energyViolation/MeV << " MeV in "
473 << " inelastic reaction, in " << (inverseKinematics ? "inverse" : "direct") << " kinematics. Will resample.";
475 eventIsOK = false;
480 remnants.clear();
482 std::stringstream ss;
483 ss << "momentum conservation violated by " << momentumViolation/MeV << " MeV in "
486 << " inelastic reaction, in " << (inverseKinematics ? "inverse" : "direct") << " kinematics. Will resample.";
488 eventIsOK = false;
493 remnants.clear();
494 }
495 }
496 }
497 nTries++;
498 } while(!eventIsOK && nTries < maxTries);
499
500
501 if(inverseKinematics) {
502 delete aProjectileTrack;
503 delete theTargetNucleus;
504 delete toInverseKinematics;
505 delete toDirectKinematics;
506 }
507
508 if(!eventIsOK) {
509 std::stringstream ss;
510 ss << "maximum number of tries exceeded for the proposed "
512 <<
" + " << theIonTable->
GetIonName(nucleusZ, nucleusA, 0)
513 << " inelastic reaction, in " << (inverseKinematics ? "inverse" : "direct") << " kinematics.";
518 return &theResult;
519 }
520
521
522
524 for(std::list<G4Fragment>::iterator i = remnants.begin();
525 i != remnants.end(); ++i) {
527
528 for(G4ReactionProductVector::iterator fragment = deExcitationResult->begin();
529 fragment != deExcitationResult->end(); ++fragment) {
531 if(def != 0) {
533 theResult.
AddSecondary(theFragment, (*fragment)->GetCreatorModelID());
534 }
535 }
536
537 for(G4ReactionProductVector::iterator fragment = deExcitationResult->begin();
538 fragment != deExcitationResult->end(); ++fragment) {
539 delete (*fragment);
540 }
541 deExcitationResult->clear();
542 delete deExcitationResult;
543 }
544 }
545
546 remnants.clear();
547
548 if((theTally = theInterfaceStore->
GetTally()))
549 theTally->
Tally(aTrack, theNucleus, theResult);
550
551 return &theResult;
552}
G4double S(G4double temp)
CLHEP::HepLorentzRotation G4LorentzRotation
std::vector< G4ReactionProduct * > G4ReactionProductVector
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()
void SetStatusChange(G4HadFinalStateStatus aS)
void AddSecondary(G4DynamicParticle *aP, G4int mod=-1)
std::size_t GetNumberOfSecondaries() const
void SetEnergyChange(G4double anEnergy)
G4HadSecondary * GetSecondary(size_t i)
void SetMomentumChange(const G4ThreeVector &aV)
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4LorentzVector & Get4Momentum() const
G4DynamicParticle * GetParticle()
virtual G4HadFinalState * ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus &targetNucleus)
const G4String & GetModelName() const
static G4double GetNuclearMass(G4int A, G4int Z, G4int L)
G4int GetMaxProjMassINCL() const
Getter for theMaxProjMassINCL.
G4INCL::INCL * GetINCLModel()
Get the cached INCL model engine.
G4double GetCascadeMinEnergyPerNucleon() const
Getter for cascadeMinEnergyPerNucleon.
G4INCLXXVInterfaceTally * GetTally() const
Getter for the interface tally.
virtual void Tally(G4HadProjectile const &aTrack, G4Nucleus const &theNucleus, G4HadFinalState const &result)=0
const EventInfo & processEvent()
G4ParticleDefinition * GetIon(G4int Z, G4int A, G4int lvl=0)
G4String GetIonName(G4int Z, G4int A, G4int lvl=0) const
G4double GetIonMass(G4int Z, G4int A, G4int nL=0, G4int lvl=0) const
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
G4double GetPDGCharge() const
G4int GetNumberOfLambdasInHypernucleus() const
const G4String & GetParticleName() const
G4ParticleDefinition * FindParticle(G4int PDGEncoding)
static G4ParticleTable * GetParticleTable()
static G4Proton * ProtonDefinition()
virtual G4ReactionProductVector * DeExcite(G4Fragment &aFragment)=0
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.