ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4InuclCollider.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4InuclCollider.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // 20100114 M. Kelsey -- Remove G4CascadeMomentum, use G4LorentzVector directly
28 // 20100309 M. Kelsey -- Eliminate some unnecessary std::pow()
29 // 20100413 M. Kelsey -- Pass G4CollisionOutput by ref to ::collide()
30 // 20100418 M. Kelsey -- Move lab-frame transformation code to G4CollisonOutput
31 // 20100429 M. Kelsey -- Change "photon()" to "isPhoton()"
32 // 20100517 M. Kelsey -- Inherit from common base class, make other colliders
33 // simple data members, consolidate code
34 // 20100620 M. Kelsey -- Reorganize top level if-blocks to reduce nesting,
35 // use new four-vector conservation check.
36 // 20100701 M. Kelsey -- Bug fix energy-conservation after equilibrium evap,
37 // pass verbosity through to G4CollisionOutput
38 // 20100714 M. Kelsey -- Move conservation checking to base class, report
39 // number of iterations at end
40 // 20100715 M. Kelsey -- Remove all the "Before xxx" and "After xxx"
41 // conservation checks, as the colliders now all do so. Move
42 // local buffers outside while() loop, use new "combined add()"
43 // interface for copying local buffers to global.
44 // 20100716 M. Kelsey -- Drop G4IntraNucleiCascader::setInteractionCase()
45 // 20100720 M. Kelsey -- Make all the collders pointer members (to reducde
46 // external compile dependences).
47 // 20100915 M. Kelsey -- Move post-cascade colliders to G4CascadeDeexcitation,
48 // simplify operational code somewhat
49 // 20100922 M. Kelsey -- Add functions to select de-excitation method;
50 // default is G4CascadeDeexcitation (i.e., built-in modules)
51 // 20100924 M. Kelsey -- Migrate to integer A and Z
52 // 20101019 M. Kelsey -- CoVerity report: check dynamic_cast<> for null
53 // 20110224 M. Kelsey -- Add ::rescatter() function which takes a list of
54 // pre-existing secondaries as input. Add setVerboseLevel().
55 // 20110301 M. Kelsey -- Pass verbosity to new or changed de-excitation
56 // 20110304 M. Kelsey -- Modify rescatter to use original Propagate() input
57 // 20110308 M. Kelsey -- Separate de-excitation block from collide(); check
58 // for single-nucleon "fragment", rather than for null fragment
59 // 20110413 M. Kelsey -- Modify diagnostic messages in ::rescatter() to be
60 // equivalent to those from ::collide().
61 // 20111003 M. Kelsey -- Prepare for gamma-N interactions by checking for
62 // final-state tables instead of particle "isPhoton()"
63 // 20130621 M. Kelsey -- Pass G4Fragment to de-excitation modules directly
64 // 20140929 M. Kelsey -- Make PreCompound the default de-excitation
65 // 20141111 M. Kelsey -- Revert default use of PreCompound; replace
66 // G4Fragment::GetA() call with GetA_asInt().
67 // 20150205 M. Kelsey -- New photonuclearOkay() filter to reject events
68 // around giant dipole resonance with no hadronic secondaries.
69 // Addresses bug #1680.
70 // 20150220 M. Kelsey -- Improve photonuclearOkay() filter by just checking
71 // final-state nucleus vs. target, rather than all secondaries.
72 // 20150608 M. Kelsey -- Label all while loops as terminating.
73 
74 #include "G4InuclCollider.hh"
76 #include "G4CascadeCheckBalance.hh"
77 #include "G4CascadeDeexcitation.hh"
78 #include "G4CollisionOutput.hh"
80 #include "G4IntraNucleiCascader.hh"
82 #include "G4InuclNuclei.hh"
83 #include "G4LorentzConvertor.hh"
85 
86 
88  : G4CascadeColliderBase("G4InuclCollider"),
89  theElementaryParticleCollider(new G4ElementaryParticleCollider),
90  theIntraNucleiCascader(new G4IntraNucleiCascader),
91  theDeexcitation(new G4PreCompoundDeexcitation) {}
92 
96  delete theDeexcitation;
97 }
98 
99 
100 // Set verbosity and pass on to member objects
103 
107 
110 }
111 
112 
113 // Select post-cascade processing (default will be CascadeDeexcitation)
114 
116  delete theDeexcitation;
119 }
120 
122  delete theDeexcitation;
125 }
126 
127 
128 // Main action
129 
131  G4CollisionOutput& globalOutput) {
132  if (verboseLevel) G4cout << " >>> G4InuclCollider::collide" << G4endl;
133 
134  const G4int itry_max = 100;
135 
136  // Particle-on-particle collision; no nucleus involved
137  if (useEPCollider(bullet,target)) {
138  if (verboseLevel > 2)
139  G4cout << " InuclCollider -> particle on particle collision" << G4endl;
140 
141  theElementaryParticleCollider->collide(bullet, target, globalOutput);
142  return;
143  }
144 
145  interCase.set(bullet,target); // Classify collision type
146  if (verboseLevel > 2) {
147  G4cout << " InuclCollider -> inter case " << interCase.code() << G4endl;
148  }
149 
150  if (!interCase.valid()) {
151  if (verboseLevel > 1)
152  G4cerr << " InuclCollider -> no collision possible " << G4endl;
153 
154  globalOutput.trivialise(bullet, target);
155  return;
156  }
157 
158  // Target must be a nucleus
159  G4InuclNuclei* ntarget = dynamic_cast<G4InuclNuclei*>(interCase.getTarget());
160  if (!ntarget) {
161  G4cerr << " InuclCollider -> ERROR target is not a nucleus " << G4endl;
162 
163  globalOutput.trivialise(bullet, target);
164  return;
165  }
166 
167  G4int btype = 0;
168  G4int ab = 0;
169  G4int zb = 0;
170 
171  if (interCase.hadNucleus()) { // particle with nuclei
172  G4InuclElementaryParticle* pbullet =
174 
175  if (!pbullet) {
176  G4cerr << " InuclCollider -> ERROR bullet is not a hadron " << G4endl;
177  globalOutput.trivialise(bullet, target);
178  return;
179  }
180 
181  if (!G4CascadeChannelTables::GetTable(pbullet->type())) {
182  G4cerr << " InuclCollider -> ERROR can not collide with "
183  << pbullet->getDefinition()->GetParticleName() << G4endl;
184  globalOutput.trivialise(bullet, target);
185  return;
186  }
187 
188  btype = pbullet->type();
189  } else { // nuclei with nuclei
190  G4InuclNuclei* nbullet =
191  dynamic_cast<G4InuclNuclei*>(interCase.getBullet());
192  if (!nbullet) {
193  G4cerr << " InuclCollider -> ERROR bullet is not a nucleus " << G4endl;
194  globalOutput.trivialise(bullet, target);
195  return;
196  }
197 
198  ab = nbullet->getA();
199  zb = nbullet->getZ();
200  }
201 
202  G4LorentzConvertor convertToTargetRestFrame(bullet, ntarget);
203  G4double ekin = convertToTargetRestFrame.getKinEnergyInTheTRS();
204 
205  if (verboseLevel > 3) G4cout << " ekin in trs " << ekin << G4endl;
206 
207  if (!inelasticInteractionPossible(bullet, target, ekin)) {
208  if (verboseLevel > 3)
209  G4cout << " InuclCollider -> inelastic interaction is impossible\n"
210  << " due to the coulomb barirer " << G4endl;
211 
212  globalOutput.trivialise(bullet, target);
213  return;
214  }
215 
216  // Generate interaction secondaries in rest frame of target nucleus
217  convertToTargetRestFrame.toTheTargetRestFrame();
218  if (verboseLevel > 3) {
219  G4cout << " degenerated? " << convertToTargetRestFrame.trivial()
220  << G4endl;
221  }
222 
223  G4LorentzVector bmom; // Bullet is along local Z
224  bmom.setZ(convertToTargetRestFrame.getTRSMomentum());
225 
226  // Need to make copy of bullet with momentum realigned
227  G4InuclParticle* zbullet = 0;
228  if (interCase.hadNucleus())
229  zbullet = new G4InuclElementaryParticle(bmom, btype);
230  else
231  zbullet = new G4InuclNuclei(bmom, ab, zb);
232 
233  G4int itry = 0;
234  while (itry < itry_max) { /* Loop checking 08.06.2015 MHK */
235  itry++;
236  if (verboseLevel > 2) G4cout << " InuclCollider itry " << itry << G4endl;
237 
238  globalOutput.reset(); // Clear buffers for this attempt
239  output.reset();
240 
241  theIntraNucleiCascader->collide(zbullet, target, output);
242 
243  if (verboseLevel > 1) G4cout << " After Cascade " << G4endl;
244 
247 
248  //*** TEMPORARY, USE ENVVAR TO ENABLE/DISABLE THIS TEST ***
249  if (std::getenv("G4CASCADE_CHECK_PHOTONUCLEAR"))
250  if (!photonuclearOkay(output)) continue;
251 
252  if (verboseLevel > 2)
253  G4cout << " itry " << itry << " finished, moving to lab frame" << G4endl;
254 
255  // convert to the LAB frame and add to final result
256  output.boostToLabFrame(convertToTargetRestFrame);
257 
258  globalOutput.add(output);
259 
260  // Adjust final state particles to balance momentum and energy
261  // FIXME: This should no longer be necessary!
262  globalOutput.setOnShell(bullet, target);
263  if (globalOutput.acceptable()) {
264  if (verboseLevel)
265  G4cout << " InuclCollider output after trials " << itry << G4endl;
266  delete zbullet;
267  return;
268  } else {
269  if (verboseLevel>2)
270  G4cerr << " InuclCollider setOnShell failed." << G4endl;
271  }
272  } // while (itry < itry_max)
273 
274  if (verboseLevel) {
275  G4cout << " InuclCollider -> can not generate acceptable inter. after "
276  << itry_max << " attempts " << G4endl;
277  }
278 
279  globalOutput.trivialise(bullet, target);
280 
281  delete zbullet;
282  return;
283 }
284 
285 
286 // For use with Propagate to preload a set of secondaries
287 
289  G4KineticTrackVector* theSecondaries,
290  G4V3DNucleus* theNucleus,
291  G4CollisionOutput& globalOutput) {
292  if (verboseLevel) G4cout << " >>> G4InuclCollider::rescatter" << G4endl;
293 
294  G4int itry=1; // For diagnostic post-processing only
295  if (verboseLevel > 2) G4cout << " InuclCollider itry " << itry << G4endl;
296 
297  globalOutput.reset(); // Clear buffers for this attempt
298  output.reset();
299 
300  theIntraNucleiCascader->rescatter(bullet, theSecondaries, theNucleus,
301  output);
302 
303  if (verboseLevel > 1) G4cout << " After Rescatter" << G4endl;
304 
307 
308  globalOutput.add(output); // Add local results to global output
309 
310  if (verboseLevel)
311  G4cout << " InuclCollider output after trials " << itry << G4endl;
312 }
313 
314 
315 // De-excite nuclear fragment to ground state
317  G4CollisionOutput& globalOutput) {
318  if (fragment.GetA_asInt() <= 1) return; // Nothing real to be de-excited
319 
320  if (verboseLevel) G4cout << " >>> G4InuclCollider::deexcite" << G4endl;
321 
322  const G4int itry_max = 10; // Maximum number of attempts
323  G4int itry = 0;
324  do { /* Loop checking 08.06.2015 MHK */
325  if (verboseLevel > 2) G4cout << " deexcite itry " << itry << G4endl;
326 
327  DEXoutput.reset();
328  theDeexcitation->deExcite(fragment, DEXoutput);
329 
330  } while (!validateOutput(fragment, DEXoutput) && (++itry < itry_max));
331  // Add de-excitation products to output buffer
332  globalOutput.add(DEXoutput);
333 }
334 
335 
336 // Looks for non-gamma final state in photonuclear or leptonuclear
337 
339  if (interCase.twoNuclei()) return true; // A-A is not photonuclear
340 
341  G4InuclElementaryParticle* bullet =
343  if (!bullet || !(bullet->isPhoton() || bullet->isElectron())) return true;
344 
345  if (verboseLevel>1)
346  G4cout << " >>> G4InuclCollider::photonuclearOkay" << G4endl;
347 
348  if (bullet->getKineticEnergy() > 0.050) return true;
349 
350  if (verboseLevel>2) {
351  if (checkOutput.numberOfOutgoingNuclei() > 0) {
352  G4cout << " comparing final nucleus with initial target:\n"
353  << checkOutput.getOutgoingNuclei()[0] << G4endl
354  << *(interCase.getTarget()) << G4endl;
355  } else {
356  G4cout << " no final nucleus remains when target was "
357  << *(interCase.getTarget()) << G4endl;
358  }
359  }
360 
361  // Hadron production changes target nucleus
362  G4double mfinalNuc = 0.0;
363  if (checkOutput.numberOfOutgoingNuclei() > 0)
364  mfinalNuc = checkOutput.getOutgoingNuclei()[0].getMass();
365  G4double mtargetNuc = interCase.getTarget()->getMass();
366  if (mfinalNuc != mtargetNuc) return true; // Mass from G4Ions is fixed
367 
368  if (verboseLevel>2)
369  G4cout << " photonuclear produced only gammas. Try again." << G4endl;
370 
371  return false; // Final state is entirely de-excitation photons
372 }