ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4CascadeRecoilMaker.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4CascadeRecoilMaker.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 // Collects generated cascade data (using Collider::collide() interface)
28 // and computes the nuclear recoil kinematics needed to balance the event.
29 //
30 // 20100909 M. Kelsey -- Inspired by G4CascadeCheckBalance
31 // 20100909 M. Kelsey -- Move G4IntraNucleiCascader::goodCase() here, add
32 // tolerance for "almost zero" excitation energy
33 // 20100910 M. Kelsey -- Drop getRecoilFragment() in favor of user calling
34 // makeRecoilFragment() with returned non-const pointer. Drop
35 // handling of excitons.
36 // 20100921 M. Kelsey -- Return G4InuclNuclei using "makeRecoilNuclei()".
37 // Repurpose "makeRecoilFragment()" to return G4Fragment.
38 // 20100924 M. Kelsey -- Remove unusable G4Fragment::SetExcitationEnergy().
39 // Add deltaM to compute mass difference, use excitationEnergy
40 // to force G4Fragment four-vector to match.
41 // 20110214 M. Kelsey -- Follow G4InuclParticle::Model enumerator migration
42 // 20110303 M. Kelsey -- Add diagnostic messages to goodNucleus().
43 // 20110308 M. Kelsey -- Follow new G4Fragment interface for hole types
44 // 20110722 M. Kelsey -- For IntraNucleiCascader, take G4CollOut as argument
45 
46 #include <vector>
47 
48 #include "G4CascadeRecoilMaker.hh"
49 #include "globals.hh"
50 #include "G4SystemOfUnits.hh"
51 #include "G4CascadParticle.hh"
52 #include "G4CascadeCheckBalance.hh"
53 #include "G4CollisionOutput.hh"
54 #include "G4Fragment.hh"
56 #include "G4InuclNuclei.hh"
57 #include "G4InuclParticle.hh"
59 #include "G4LorentzVector.hh"
60 
61 using namespace G4InuclSpecialFunctions;
62 
63 
64 // Constructor and destructor
65 
67  : G4VCascadeCollider("G4CascadeRecoilMaker"),
68  excTolerance(tolerance), inputEkin(0.),
69  recoilA(0), recoilZ(0), excitationEnergy(0.) {
70  balance = new G4CascadeCheckBalance(tolerance, tolerance, theName);
71 }
72 
74  delete balance;
75 }
76 
77 
78 // Standard Collider interface (non-const output "buffer")
79 
82  G4CollisionOutput& output) {
83  if (verboseLevel > 1)
84  G4cout << " >>> G4CascadeRecoilMaker::collide" << G4endl;
85 
86  // Available energy needed for "goodNucleus()" test at end
87  inputEkin = bullet ? bullet->getKineticEnergy() : 0.;
88 
90  balance->collide(bullet, target, output);
91  fillRecoil();
92 }
93 
94 // This is for use with G4IntraNucleiCascader
95 
98  G4CollisionOutput& output,
99  const std::vector<G4CascadParticle>& cparticles) {
100  if (verboseLevel > 1)
101  G4cout << " >>> G4CascadeRecoilMaker::collide(<EP>,<CP>)" << G4endl;
102 
103  // Available energy needed for "goodNucleus()" test at end
104  inputEkin = bullet ? bullet->getKineticEnergy() : 0.;
105 
107  balance->collide(bullet, target, output, cparticles);
108  fillRecoil();
109 }
110 
111 
112 // Used current event configuration to construct recoil nucleus
113 // NOTE: CheckBalance uses "final-initial", we want "initial-final"
114 
116  recoilZ = -(balance->deltaQ()); // Charge "non-conservation"
117  recoilA = -(balance->deltaB()); // Baryon "non-conservation"
119 
120  theExcitons.clear(); // Discard previous exciton configuraiton
121 
122  // Bertini uses MeV for excitation energy
123  if (!goodFragment()) excitationEnergy = 0.;
124  else excitationEnergy = deltaM() * GeV;
125 
126  // Allow for very small negative mass difference, and round to zero
128 
129  if (verboseLevel > 2) {
130  G4cout << " recoil px " << recoilMomentum.px()
131  << " py " << recoilMomentum.py() << " pz " << recoilMomentum.pz()
132  << " E " << recoilMomentum.e() << " baryon " << recoilA
133  << " charge " << recoilZ
134  << "\n recoil mass " << recoilMomentum.m()
135  << " 'excitation' energy " << excitationEnergy << G4endl;
136  }
137 }
138 
139 
140 // Construct physical nucleus from recoil parameters, if reasonable
141 
144  if (verboseLevel > 1)
145  G4cout << " >>> G4CascadeRecoilMaker::makeRecoilNuclei" << G4endl;
146 
147  if (!goodRecoil()) {
148  if (verboseLevel > 2 && !wholeEvent())
149  G4cout << theName << ": event recoil is not a physical nucleus" << G4endl;
150 
151  return 0; // Null pointer means no fragment
152  }
153 
155  excitationEnergy, model);
157 
158  return &theRecoilNuclei;
159 }
160 
161 
162 // Construct pre-compound nuclear fragment from recoil parameters
163 
165  if (verboseLevel > 1)
166  G4cout << " >>> G4CascadeRecoilMaker::makeRecoilFragment" << G4endl;
167 
168  if (!goodRecoil()) {
169  if (verboseLevel > 2 && !wholeEvent())
170  G4cout << theName << ": event recoil is not a physical nucleus" << G4endl;
171 
172  return 0; // Null pointer means no fragment
173  }
174 
175  theRecoilFragment.SetZandA_asInt(recoilZ, recoilA); // Note convention!
176 
177  // User may have overridden excitation energy; force four-momentum to match
178  G4double fragMass =
180 
181  G4LorentzVector fragMom; fragMom.setVectM(recoilMomentum.vect(), fragMass);
182  theRecoilFragment.SetMomentum(fragMom*GeV); // Bertini uses GeV!
183 
184  // Note: exciton configuration has to be set piece by piece
185  // (arguments are Ntotal,Nproton in both cases)
188 
193 
194  return &theRecoilFragment;
195 }
196 
197 
198 // Compute raw mass difference from recoil parameters
199 
202  return (recoilMomentum.m() - nucMass);
203 }
204 
205 
206 // Data quality checks
207 
209  return (recoilA>0 && recoilZ>=0 && recoilA >= recoilZ);
210 }
211 
213  return (goodFragment() && excitationEnergy > -excTolerance);
214 }
215 
217  if (verboseLevel > 2) {
218  G4cout << " >>> G4CascadeRecoilMaker::wholeEvent:"
219  << " A " << recoilA << " Z " << recoilZ
220  << " P " << recoilMomentum.rho() << " E " << recoilMomentum.e()
221  << "\n wholeEvent returns "
222  << (recoilA==0 && recoilZ==0 &&
225  }
226 
227  return (recoilA==0 && recoilZ==0 &&
230 }
231 
232 // Determine whether desired nuclear fragment is constructable outcome
233 
235  if (verboseLevel > 2) {
236  G4cout << " >>> G4CascadeRecoilMaker::goodNucleus" << G4endl;
237  }
238 
239  const G4double minExcitation = 0.1*keV;
240  const G4double reasonableExcitation = 7.0; // Multiple of binding energy
241  const G4double fractionalExcitation = 0.2; // Fraction of input to excite
242 
243  if (!goodRecoil()) {
244  if (verboseLevel>2) {
245  if (!goodFragment()) G4cerr << " goodNucleus: invalid A/Z" << G4endl;
246  else if (excitationEnergy < -excTolerance)
247  G4cerr << " goodNucleus: negative excitation" << G4endl;
248  }
249  return false; // Not a sensible nucleus
250  }
251 
252  if (excitationEnergy <= minExcitation) return true; // Effectively zero
253 
254  // Maximum possible excitation energy determined by initial energy
256  G4double exc_max0z = fractionalExcitation * inputEkin*GeV;
257  G4double exc_dm = reasonableExcitation * dm;
258  G4double exc_max = (exc_max0z > exc_dm) ? exc_max0z : exc_dm;
259 
260  if (verboseLevel > 3) {
261  G4cout << " eexs " << excitationEnergy << " max " << exc_max
262  << " dm " << dm << G4endl;
263  }
264 
265  if (verboseLevel > 2 && excitationEnergy >= exc_max)
266  G4cerr << " goodNucleus: too much excitation" << G4endl;
267 
268  return (excitationEnergy < exc_max); // Below maximum possible
269 }