Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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"
69#include "G4CollisionOutput.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}
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
static const G4CascadeChannel * GetTable(G4int initialState)
virtual G4bool useEPCollider(G4InuclParticle *bullet, G4InuclParticle *target) const
virtual void setVerboseLevel(G4int verbose=0)
virtual G4bool validateOutput(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
virtual G4bool inelasticInteractionPossible(G4InuclParticle *bullet, G4InuclParticle *target, G4double ekin) const
void boostToLabFrame(const G4LorentzConvertor &convertor)
void setOnShell(G4InuclParticle *bullet, G4InuclParticle *target)
const G4Fragment & getRecoilFragment() const
void setVerboseLevel(G4int verbose)
G4bool acceptable() const
void add(const G4CollisionOutput &right)
void trivialise(G4InuclParticle *bullet, G4InuclParticle *target)
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
G4double GetA() const
Definition: G4Fragment.hh:283
G4bool valid() const
G4InuclParticle * getBullet() const
void set(G4InuclParticle *part1, G4InuclParticle *part2)
G4bool hadNucleus() const
G4InuclParticle * getTarget() const
void rescatter(G4InuclParticle *bullet, G4KineticTrackVector *theSecondaries, G4V3DNucleus *theNucleus, G4CollisionOutput &globalOutput)
void setVerboseLevel(G4int verbose=0)
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &globalOutput)
virtual ~G4InuclCollider()
void useCascadeDeexcitation()
void deexcite(const G4Fragment &fragment, G4CollisionOutput &globalOutput)
void usePreCompoundDeexcitation()
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &globalOutput)
void rescatter(G4InuclParticle *bullet, G4KineticTrackVector *theSecondaries, G4V3DNucleus *theNucleus, G4CollisionOutput &globalOutput)
void setVerboseLevel(G4int verbose=0)
G4int getZ() const
G4int getA() const
G4ParticleDefinition * getDefinition() const
G4double getTRSMomentum() const
G4double getKinEnergyInTheTRS() const
const G4String & GetParticleName() const
virtual void collide(G4InuclParticle *, G4InuclParticle *target, G4CollisionOutput &globalOutput)=0