Geant4  10.01.p02
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: G4InuclCollider.cc 71769 2013-06-21 21:23:50Z mkelsey $
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 // 20130621 M. Kelsey -- Pass G4Fragment to de-excitation modules directly
65 // 20140929 M. Kelsey -- Make PreCompound the default de-excitation
66 // 20141111 M. Kelsey -- Revert default use of PreCompound; replace
67 // G4Fragment::GetA() call with GetA_asInt().
68 
69 #include "G4InuclCollider.hh"
71 #include "G4CascadeCheckBalance.hh"
72 #include "G4CascadeDeexcitation.hh"
73 #include "G4CollisionOutput.hh"
75 #include "G4IntraNucleiCascader.hh"
77 #include "G4InuclNuclei.hh"
78 #include "G4LorentzConvertor.hh"
80 
81 
83  : G4CascadeColliderBase("G4InuclCollider"),
84  theElementaryParticleCollider(new G4ElementaryParticleCollider),
85  theIntraNucleiCascader(new G4IntraNucleiCascader),
86  theDeexcitation(new G4PreCompoundDeexcitation) {}
87 
91  delete theDeexcitation;
92 }
93 
94 
95 // Set verbosity and pass on to member objects
98 
102 
105 }
106 
107 
108 // Select post-cascade processing (default will be CascadeDeexcitation)
109 
111  delete theDeexcitation;
114 }
115 
117  delete theDeexcitation;
120 }
121 
122 
123 // Main action
124 
126  G4CollisionOutput& globalOutput) {
127  if (verboseLevel) G4cout << " >>> G4InuclCollider::collide" << G4endl;
128 
129  const G4int itry_max = 100;
130 
131  // Particle-on-particle collision; no nucleus involved
132  if (useEPCollider(bullet,target)) {
133  if (verboseLevel > 2)
134  G4cout << " InuclCollider -> particle on particle collision" << G4endl;
135 
136  theElementaryParticleCollider->collide(bullet, target, globalOutput);
137  return;
138  }
139 
140  interCase.set(bullet,target); // Classify collision type
141  if (verboseLevel > 2) {
142  G4cout << " InuclCollider -> inter case " << interCase.code() << G4endl;
143  }
144 
145  if (!interCase.valid()) {
146  if (verboseLevel > 1)
147  G4cerr << " InuclCollider -> no collision possible " << G4endl;
148 
149  globalOutput.trivialise(bullet, target);
150  return;
151  }
152 
153  // Target must be a nucleus
154  G4InuclNuclei* ntarget = dynamic_cast<G4InuclNuclei*>(interCase.getTarget());
155  if (!ntarget) {
156  G4cerr << " InuclCollider -> ERROR target is not a nucleus " << G4endl;
157 
158  globalOutput.trivialise(bullet, target);
159  return;
160  }
161 
162  G4int btype = 0;
163  G4int ab = 0;
164  G4int zb = 0;
165 
166  if (interCase.hadNucleus()) { // particle with nuclei
167  G4InuclElementaryParticle* pbullet =
169 
170  if (!pbullet) {
171  G4cerr << " InuclCollider -> ERROR bullet is not a hadron " << G4endl;
172  globalOutput.trivialise(bullet, target);
173  return;
174  }
175 
176  if (!G4CascadeChannelTables::GetTable(pbullet->type())) {
177  G4cerr << " InuclCollider -> ERROR can not collide with "
178  << pbullet->getDefinition()->GetParticleName() << G4endl;
179  globalOutput.trivialise(bullet, target);
180  return;
181  }
182 
183  btype = pbullet->type();
184  } else { // nuclei with nuclei
185  G4InuclNuclei* nbullet =
186  dynamic_cast<G4InuclNuclei*>(interCase.getBullet());
187  if (!nbullet) {
188  G4cerr << " InuclCollider -> ERROR bullet is not a nucleus " << G4endl;
189  globalOutput.trivialise(bullet, target);
190  return;
191  }
192 
193  ab = nbullet->getA();
194  zb = nbullet->getZ();
195  }
196 
197  G4LorentzConvertor convertToTargetRestFrame(bullet, ntarget);
198  G4double ekin = convertToTargetRestFrame.getKinEnergyInTheTRS();
199 
200  if (verboseLevel > 3) G4cout << " ekin in trs " << ekin << G4endl;
201 
202  if (!inelasticInteractionPossible(bullet, target, ekin)) {
203  if (verboseLevel > 3)
204  G4cout << " InuclCollider -> inelastic interaction is impossible\n"
205  << " due to the coulomb barirer " << G4endl;
206 
207  globalOutput.trivialise(bullet, target);
208  return;
209  }
210 
211  // Generate interaction secondaries in rest frame of target nucleus
212  convertToTargetRestFrame.toTheTargetRestFrame();
213  if (verboseLevel > 3) {
214  G4cout << " degenerated? " << convertToTargetRestFrame.trivial()
215  << G4endl;
216  }
217 
218  G4LorentzVector bmom; // Bullet is along local Z
219  bmom.setZ(convertToTargetRestFrame.getTRSMomentum());
220 
221  // Need to make copy of bullet with momentum realigned
222  G4InuclParticle* zbullet = 0;
223  if (interCase.hadNucleus())
224  zbullet = new G4InuclElementaryParticle(bmom, btype);
225  else
226  zbullet = new G4InuclNuclei(bmom, ab, zb);
227 
228  G4int itry = 0;
229  while (itry < itry_max) {
230  itry++;
231  if (verboseLevel > 2)
232  G4cout << " InuclCollider itry " << itry << G4endl;
233 
234  globalOutput.reset(); // Clear buffers for this attempt
235  output.reset();
236 
237  theIntraNucleiCascader->collide(zbullet, target, output);
238 
239  if (verboseLevel > 1) G4cout << " After Cascade " << G4endl;
240 
243 
244  if (verboseLevel > 2)
245  G4cout << " itry " << itry << " finished, moving to lab frame" << G4endl;
246 
247  // convert to the LAB frame and add to final result
248  output.boostToLabFrame(convertToTargetRestFrame);
249 
250  globalOutput.add(output);
251 
252  // Adjust final state particles to balance momentum and energy
253  // FIXME: This should no longer be necessary!
254  globalOutput.setOnShell(bullet, target);
255  if (globalOutput.acceptable()) {
256  if (verboseLevel)
257  G4cout << " InuclCollider output after trials " << itry << G4endl;
258  delete zbullet;
259  return;
260  } else {
261  if (verboseLevel>2)
262  G4cerr << " InuclCollider setOnShell failed." << G4endl;
263  }
264  } // while (itry < itry_max)
265 
266  if (verboseLevel) {
267  G4cout << " InuclCollider -> can not generate acceptable inter. after "
268  << itry_max << " attempts " << G4endl;
269  }
270 
271  globalOutput.trivialise(bullet, target);
272 
273  delete zbullet;
274  return;
275 }
276 
277 
278 // For use with Propagate to preload a set of secondaries
279 
281  G4KineticTrackVector* theSecondaries,
282  G4V3DNucleus* theNucleus,
283  G4CollisionOutput& globalOutput) {
284  if (verboseLevel) G4cout << " >>> G4InuclCollider::rescatter" << G4endl;
285 
286  G4int itry=1; // For diagnostic post-processing only
287  if (verboseLevel > 2) G4cout << " InuclCollider itry " << itry << G4endl;
288 
289  globalOutput.reset(); // Clear buffers for this attempt
290  output.reset();
291 
292  theIntraNucleiCascader->rescatter(bullet, theSecondaries, theNucleus,
293  output);
294 
295  if (verboseLevel > 1) G4cout << " After Rescatter" << G4endl;
296 
299 
300  globalOutput.add(output); // Add local results to global output
301 
302  if (verboseLevel)
303  G4cout << " InuclCollider output after trials " << itry << G4endl;
304 }
305 
306 
307 // De-excite nuclear fragment to ground state
308 
310  G4CollisionOutput& globalOutput) {
311  if (fragment.GetA_asInt() <= 1) return; // Nothing real to be de-excited
312 
313  if (verboseLevel) G4cout << " >>> G4InuclCollider::deexcite" << G4endl;
314 
315  const G4int itry_max = 10; // Maximum number of attempts
316  G4int itry = 0;
317  do {
318  if (verboseLevel > 2) G4cout << " deexcite itry " << itry << G4endl;
319 
320  DEXoutput.reset();
321  theDeexcitation->deExcite(fragment, DEXoutput);
322  } while (!validateOutput(fragment, DEXoutput) && (++itry < itry_max));
323 
324  // Add de-excitation products to output buffer
325  globalOutput.add(DEXoutput);
326 }
G4bool hadNucleus() const
G4CollisionOutput output
void trivialise(G4InuclParticle *bullet, G4InuclParticle *target)
void rescatter(G4InuclParticle *bullet, G4KineticTrackVector *theSecondaries, G4V3DNucleus *theNucleus, G4CollisionOutput &globalOutput)
void setVerboseLevel(G4int verbose)
static const G4CascadeChannel * GetTable(G4int initialState)
G4int getZ() const
G4double getTRSMomentum() const
G4CollisionOutput DEXoutput
virtual G4bool useEPCollider(G4InuclParticle *bullet, G4InuclParticle *target) const
void removeRecoilFragment(G4int index=-1)
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
G4bool valid() const
const G4ParticleDefinition * getDefinition() const
G4int code() const
virtual G4bool inelasticInteractionPossible(G4InuclParticle *bullet, G4InuclParticle *target, G4double ekin) const
virtual ~G4InuclCollider()
void deexcite(const G4Fragment &fragment, G4CollisionOutput &globalOutput)
G4ElementaryParticleCollider * theElementaryParticleCollider
int G4int
Definition: G4Types.hh:78
G4bool trivial() const
const G4String & GetParticleName() const
G4bool acceptable() const
virtual void setVerboseLevel(G4int verbose=0)
virtual void deExcite(const G4Fragment &fragment, G4CollisionOutput &output)=0
void add(const G4CollisionOutput &right)
void useCascadeDeexcitation()
G4GLOB_DLL std::ostream G4cout
G4int GetA_asInt() const
Definition: G4Fragment.hh:243
G4int getA() const
void setVerboseLevel(G4int verbose=0)
void rescatter(G4InuclParticle *bullet, G4KineticTrackVector *theSecondaries, G4V3DNucleus *theNucleus, G4CollisionOutput &globalOutput)
void boostToLabFrame(const G4LorentzConvertor &convertor)
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &globalOutput)
G4double getKinEnergyInTheTRS() const
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &globalOutput)
void set(G4InuclParticle *part1, G4InuclParticle *part2)
static const G4double ab
virtual G4bool validateOutput(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
G4IntraNucleiCascader * theIntraNucleiCascader
G4InuclParticle * getBullet() const
#define G4endl
Definition: G4ios.hh:61
virtual void setVerboseLevel(G4int verbose=0)
void setVerboseLevel(G4int verbose=0)
const G4Fragment & getRecoilFragment(G4int index=0) const
double G4double
Definition: G4Types.hh:76
G4InuclParticle * getTarget() const
void usePreCompoundDeexcitation()
G4VCascadeDeexcitation * theDeexcitation
void setOnShell(G4InuclParticle *bullet, G4InuclParticle *target)
G4GLOB_DLL std::ostream G4cerr
CLHEP::HepLorentzVector G4LorentzVector