Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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//
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"
78#include "G4CollisionOutput.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
94 delete theElementaryParticleCollider;
95 delete theIntraNucleiCascader;
96 delete theDeexcitation;
97}
98
99
100// Set verbosity and pass on to member objects
103
104 theElementaryParticleCollider->setVerboseLevel(verboseLevel);
105 theIntraNucleiCascader->setVerboseLevel(verboseLevel);
106 theDeexcitation->setVerboseLevel(verboseLevel);
107
109 DEXoutput.setVerboseLevel(verboseLevel);
110}
111
112
113// Select post-cascade processing (default will be CascadeDeexcitation)
114
116 delete theDeexcitation;
117 theDeexcitation = new G4CascadeDeexcitation;
118 theDeexcitation->setVerboseLevel(verboseLevel);
119}
120
122 delete theDeexcitation;
123 theDeexcitation = new G4PreCompoundDeexcitation;
124 theDeexcitation->setVerboseLevel(verboseLevel);
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
245 deexcite(output.getRecoilFragment(), output);
246 output.removeRecoilFragment();
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
305 deexcite(output.getRecoilFragment(), output);
306 output.removeRecoilFragment();
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
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}
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL 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 removeRecoilFragment(G4int index=-1)
const std::vector< G4InuclNuclei > & getOutgoingNuclei() const
void boostToLabFrame(const G4LorentzConvertor &convertor)
const G4Fragment & getRecoilFragment(G4int index=0) const
void setOnShell(G4InuclParticle *bullet, G4InuclParticle *target)
void setVerboseLevel(G4int verbose)
G4int numberOfOutgoingNuclei() const
G4bool acceptable() const
void add(const G4CollisionOutput &right)
void trivialise(G4InuclParticle *bullet, G4InuclParticle *target)
void collide(G4InuclParticle *bullet, G4InuclParticle *target, G4CollisionOutput &output)
G4int GetA_asInt() const
Definition: G4Fragment.hh:284
G4bool twoNuclei() const
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()
G4bool photonuclearOkay(G4CollisionOutput &checkOutput) const
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
const G4ParticleDefinition * getDefinition() const
G4double getKineticEnergy() const
G4double getMass() const
G4double getTRSMomentum() const
G4double getKinEnergyInTheTRS() const
const G4String & GetParticleName() const
virtual void setVerboseLevel(G4int verbose=0)
virtual void deExcite(const G4Fragment &fragment, G4CollisionOutput &output)=0