Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4InuclCollider.cc
Go to the documentation of this file.
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 // $Id$
27 //
28 // 20100114 M. Kelsey -- Remove G4CascadeMomentum, use G4LorentzVector directly
29 // 20100309 M. Kelsey -- Eliminate some unnecessary std::pow()
30 // 20100413 M. Kelsey -- Pass G4CollisionOutput by ref to ::collide()
31 // 20100418 M. Kelsey -- Move lab-frame transformation code to G4CollisonOutput
32 // 20100429 M. Kelsey -- Change "photon()" to "isPhoton()"
33 // 20100517 M. Kelsey -- Inherit from common base class, make other colliders
34 // simple data members, consolidate code
35 // 20100620 M. Kelsey -- Reorganize top level if-blocks to reduce nesting,
36 // use new four-vector conservation check.
37 // 20100701 M. Kelsey -- Bug fix energy-conservation after equilibrium evap,
38 // pass verbosity through to G4CollisionOutput
39 // 20100714 M. Kelsey -- Move conservation checking to base class, report
40 // number of iterations at end
41 // 20100715 M. Kelsey -- Remove all the "Before xxx" and "After xxx"
42 // conservation checks, as the colliders now all do so. Move
43 // local buffers outside while() loop, use new "combined add()"
44 // interface for copying local buffers to global.
45 // 20100716 M. Kelsey -- Drop G4IntraNucleiCascader::setInteractionCase()
46 // 20100720 M. Kelsey -- Make all the collders pointer members (to reducde
47 // external compile dependences).
48 // 20100915 M. Kelsey -- Move post-cascade colliders to G4CascadeDeexcitation,
49 // simplify operational code somewhat
50 // 20100922 M. Kelsey -- Add functions to select de-excitation method;
51 // default is G4CascadeDeexcitation (i.e., built-in modules)
52 // 20100924 M. Kelsey -- Migrate to integer A and Z
53 // 20101019 M. Kelsey -- CoVerity report: check dynamic_cast<> for null
54 // 20110224 M. Kelsey -- Add ::rescatter() function which takes a list of
55 // pre-existing secondaries as input. Add setVerboseLevel().
56 // 20110301 M. Kelsey -- Pass verbosity to new or changed de-excitation
57 // 20110304 M. Kelsey -- Modify rescatter to use original Propagate() input
58 // 20110308 M. Kelsey -- Separate de-excitation block from collide(); check
59 // for single-nucleon "fragment", rather than for null fragment
60 // 20110413 M. Kelsey -- Modify diagnostic messages in ::rescatter() to be
61 // equivalent to those from ::collide().
62 // 20111003 M. Kelsey -- Prepare for gamma-N interactions by checking for
63 // final-state tables instead of particle "isPhoton()"
64 
65 #include "G4InuclCollider.hh"
67 #include "G4CascadeCheckBalance.hh"
68 #include "G4CascadeDeexcitation.hh"
69 #include "G4CollisionOutput.hh"
71 #include "G4IntraNucleiCascader.hh"
73 #include "G4InuclNuclei.hh"
74 #include "G4LorentzConvertor.hh"
76 
77 
79  : G4CascadeColliderBase("G4InuclCollider"),
80  theElementaryParticleCollider(new G4ElementaryParticleCollider),
81  theIntraNucleiCascader(new G4IntraNucleiCascader),
82  theDeexcitation(new G4CascadeDeexcitation) {}
83 
85  delete theElementaryParticleCollider;
86  delete theIntraNucleiCascader;
87  delete theDeexcitation;
88 }
89 
90 
91 // Set verbosity and pass on to member objects
94 
95  theElementaryParticleCollider->setVerboseLevel(verboseLevel);
96  theIntraNucleiCascader->setVerboseLevel(verboseLevel);
97  theDeexcitation->setVerboseLevel(verboseLevel);
98 
100  DEXoutput.setVerboseLevel(verboseLevel);
101 }
102 
103 
104 // Select post-cascade processing (default will be CascadeDeexcitation)
105 
107  delete theDeexcitation;
108  theDeexcitation = new G4CascadeDeexcitation;
109  theDeexcitation->setVerboseLevel(verboseLevel);
110 }
111 
113  delete theDeexcitation;
114  theDeexcitation = new G4PreCompoundDeexcitation;
115  theDeexcitation->setVerboseLevel(verboseLevel);
116 }
117 
118 
119 // Main action
120 
122  G4CollisionOutput& globalOutput) {
123  if (verboseLevel) G4cout << " >>> G4InuclCollider::collide" << G4endl;
124 
125  const G4int itry_max = 100;
126 
127  // Particle-on-particle collision; no nucleus involved
128  if (useEPCollider(bullet,target)) {
129  if (verboseLevel > 2)
130  G4cout << " InuclCollider -> particle on particle collision" << G4endl;
131 
132  theElementaryParticleCollider->collide(bullet, target, globalOutput);
133  return;
134  }
135 
136  interCase.set(bullet,target); // Classify collision type
137  if (verboseLevel > 2) {
138  G4cout << " InuclCollider -> inter case " << interCase.code() << G4endl;
139  }
140 
141  if (!interCase.valid()) {
142  if (verboseLevel > 1)
143  G4cerr << " InuclCollider -> no collision possible " << G4endl;
144 
145  globalOutput.trivialise(bullet, target);
146  return;
147  }
148 
149  // Target must be a nucleus
150  G4InuclNuclei* ntarget = dynamic_cast<G4InuclNuclei*>(interCase.getTarget());
151  if (!ntarget) {
152  G4cerr << " InuclCollider -> ERROR target is not a nucleus " << G4endl;
153 
154  globalOutput.trivialise(bullet, target);
155  return;
156  }
157 
158  G4int btype = 0;
159  G4int ab = 0;
160  G4int zb = 0;
161 
162  if (interCase.hadNucleus()) { // particle with nuclei
163  G4InuclElementaryParticle* pbullet =
165 
166  if (!pbullet) {
167  G4cerr << " InuclCollider -> ERROR bullet is not a hadron " << G4endl;
168  globalOutput.trivialise(bullet, target);
169  return;
170  }
171 
172  if (!G4CascadeChannelTables::GetTable(pbullet->type())) {
173  G4cerr << " InuclCollider -> ERROR can not collide with "
174  << pbullet->getDefinition()->GetParticleName() << G4endl;
175  globalOutput.trivialise(bullet, target);
176  return;
177  }
178 
179  btype = pbullet->type();
180  } else { // nuclei with nuclei
181  G4InuclNuclei* nbullet =
182  dynamic_cast<G4InuclNuclei*>(interCase.getBullet());
183  if (!nbullet) {
184  G4cerr << " InuclCollider -> ERROR bullet is not a nucleus " << G4endl;
185  globalOutput.trivialise(bullet, target);
186  return;
187  }
188 
189  ab = nbullet->getA();
190  zb = nbullet->getZ();
191  }
192 
193  G4LorentzConvertor convertToTargetRestFrame(bullet, ntarget);
194  G4double ekin = convertToTargetRestFrame.getKinEnergyInTheTRS();
195 
196  if (verboseLevel > 3) G4cout << " ekin in trs " << ekin << G4endl;
197 
198  if (!inelasticInteractionPossible(bullet, target, ekin)) {
199  if (verboseLevel > 3)
200  G4cout << " InuclCollider -> inelastic interaction is impossible\n"
201  << " due to the coulomb barirer " << G4endl;
202 
203  globalOutput.trivialise(bullet, target);
204  return;
205  }
206 
207  // Generate interaction secondaries in rest frame of target nucleus
208  convertToTargetRestFrame.toTheTargetRestFrame();
209  if (verboseLevel > 3) {
210  G4cout << " degenerated? " << convertToTargetRestFrame.trivial()
211  << G4endl;
212  }
213 
214  G4LorentzVector bmom; // Bullet is along local Z
215  bmom.setZ(convertToTargetRestFrame.getTRSMomentum());
216 
217  // Need to make copy of bullet with momentum realigned
218  G4InuclParticle* zbullet = 0;
219  if (interCase.hadNucleus())
220  zbullet = new G4InuclElementaryParticle(bmom, btype);
221  else
222  zbullet = new G4InuclNuclei(bmom, ab, zb);
223 
224  G4int itry = 0;
225  while (itry < itry_max) {
226  itry++;
227  if (verboseLevel > 2)
228  G4cout << " InuclCollider itry " << itry << G4endl;
229 
230  globalOutput.reset(); // Clear buffers for this attempt
231  output.reset();
232 
233  theIntraNucleiCascader->collide(zbullet, target, output);
234 
235  if (verboseLevel > 1) G4cout << " After Cascade " << G4endl;
236 
237  deexcite(output.getRecoilFragment(), output);
238  output.removeRecoilFragment();
239 
240  if (verboseLevel > 2)
241  G4cout << " itry " << itry << " finished, moving to lab frame" << G4endl;
242 
243  // convert to the LAB frame and add to final result
244  output.boostToLabFrame(convertToTargetRestFrame);
245 
246  globalOutput.add(output);
247 
248  // Adjust final state particles to balance momentum and energy
249  // FIXME: This should no longer be necessary!
250  globalOutput.setOnShell(bullet, target);
251  if (globalOutput.acceptable()) {
252  if (verboseLevel)
253  G4cout << " InuclCollider output after trials " << itry << G4endl;
254  delete zbullet;
255  return;
256  } else {
257  if (verboseLevel>2)
258  G4cerr << " InuclCollider setOnShell failed." << G4endl;
259  }
260  } // while (itry < itry_max)
261 
262  if (verboseLevel) {
263  G4cout << " InuclCollider -> can not generate acceptable inter. after "
264  << itry_max << " attempts " << G4endl;
265  }
266 
267  globalOutput.trivialise(bullet, target);
268 
269  delete zbullet;
270  return;
271 }
272 
273 
274 // For use with Propagate to preload a set of secondaries
275 
277  G4KineticTrackVector* theSecondaries,
278  G4V3DNucleus* theNucleus,
279  G4CollisionOutput& globalOutput) {
280  if (verboseLevel) G4cout << " >>> G4InuclCollider::rescatter" << G4endl;
281 
282  G4int itry=1; // For diagnostic post-processing only
283  if (verboseLevel > 2) G4cout << " InuclCollider itry " << itry << G4endl;
284 
285  globalOutput.reset(); // Clear buffers for this attempt
286  output.reset();
287 
288  theIntraNucleiCascader->rescatter(bullet, theSecondaries, theNucleus,
289  output);
290 
291  if (verboseLevel > 1) G4cout << " After Rescatter" << G4endl;
292 
293  deexcite(output.getRecoilFragment(), output);
294  output.removeRecoilFragment();
295 
296  globalOutput.add(output); // Add local results to global output
297 
298  if (verboseLevel)
299  G4cout << " InuclCollider output after trials " << itry << G4endl;
300 }
301 
302 
303 // De-excite nuclear fragment to ground state
304 
306  G4CollisionOutput& globalOutput) {
307  if (fragment.GetA() <= 1) return; // Nothing real to be de-excited
308 
309  if (verboseLevel) G4cout << " >>> G4InuclCollider::deexcite" << G4endl;
310 
311  G4InuclNuclei frag(fragment); // Eventually unnecessary
312 
313  const G4int itry_max = 10; // Maximum number of attempts
314  G4int itry = 0;
315  do {
316  if (verboseLevel > 2) G4cout << " deexcite itry " << itry << G4endl;
317 
318  DEXoutput.reset();
319  theDeexcitation->collide(0, &frag, DEXoutput);
320  } while (!validateOutput(0, &frag, DEXoutput) && (++itry < itry_max));
321 
322  // Add de-excitation products to output buffer
323  globalOutput.add(DEXoutput);
324 }