Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * 20 // * * 21 // * Parts of this code which have been devel 21 // * Parts of this code which have been developed by QinetiQ Ltd * 22 // * under contract to the European Space Agen 22 // * under contract to the European Space Agency (ESA) are the * 23 // * intellectual property of ESA. Rights to u 23 // * intellectual property of ESA. Rights to use, copy, modify and * 24 // * redistribute this software for general pu 24 // * redistribute this software for general public use are granted * 25 // * in compliance with any licensing, distrib 25 // * in compliance with any licensing, distribution and development * 26 // * policy adopted by the Geant4 Collaboratio 26 // * policy adopted by the Geant4 Collaboration. This code has been * 27 // * written by QinetiQ Ltd for the European S 27 // * written by QinetiQ Ltd for the European Space Agency, under ESA * 28 // * contract 17191/03/NL/LvH (Aurora Programm 28 // * contract 17191/03/NL/LvH (Aurora Programme). * 29 // * 29 // * * 30 // * By using, copying, modifying or distri 30 // * By using, copying, modifying or distributing the software (or * 31 // * any work based on the software) you ag 31 // * any work based on the software) you agree to acknowledge its * 32 // * use in resulting scientific publicati 32 // * use in resulting scientific publications, and indicate your * 33 // * acceptance of all terms of the Geant4 Sof 33 // * acceptance of all terms of the Geant4 Software license. * 34 // ******************************************* 34 // ******************************************************************** 35 // 35 // 36 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% << 36 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37 // 37 // 38 // MODULE: G4WilsonAbrasionModel. 38 // MODULE: G4WilsonAbrasionModel.cc 39 // 39 // 40 // Version: 1.0 40 // Version: 1.0 41 // Date: 08/12/2009 41 // Date: 08/12/2009 42 // Author: P R Truscott 42 // Author: P R Truscott 43 // Organisation: QinetiQ Ltd, UK 43 // Organisation: QinetiQ Ltd, UK 44 // Customer: ESA/ESTEC, NOORDWIJK 44 // Customer: ESA/ESTEC, NOORDWIJK 45 // Contract: 17191/03/NL/LvH 45 // Contract: 17191/03/NL/LvH 46 // 46 // 47 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% << 47 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 48 // 48 // 49 // CHANGE HISTORY 49 // CHANGE HISTORY 50 // -------------- 50 // -------------- 51 // 51 // 52 // 6 October 2003, P R Truscott, QinetiQ Ltd, 52 // 6 October 2003, P R Truscott, QinetiQ Ltd, UK 53 // Created. 53 // Created. 54 // 54 // 55 // 15 March 2004, P R Truscott, QinetiQ Ltd, U 55 // 15 March 2004, P R Truscott, QinetiQ Ltd, UK 56 // Beta release 56 // Beta release 57 // 57 // 58 // 18 January 2005, M H Mendenhall, Vanderbilt 58 // 18 January 2005, M H Mendenhall, Vanderbilt University, US 59 // Pointers to theAbrasionGeometry and product 59 // Pointers to theAbrasionGeometry and products generated by the deexcitation 60 // handler deleted to prevent memory leaks. A 60 // handler deleted to prevent memory leaks. Also particle change of projectile 61 // fragment previously not properly defined. 61 // fragment previously not properly defined. 62 // 62 // 63 // 08 December 2009, P R Truscott, QinetiQ Ltd 63 // 08 December 2009, P R Truscott, QinetiQ Ltd, Ltd 64 // ver 1.0 64 // ver 1.0 65 // There was originally a possibility of the m 65 // There was originally a possibility of the minimum impact parameter AFTER 66 // considering Couloumb repulsion, rm, being t 66 // considering Couloumb repulsion, rm, being too large. Now if: 67 // rm >= fradius * (rP + rT) 67 // rm >= fradius * (rP + rT) 68 // where fradius is currently 0.99, then it is 68 // where fradius is currently 0.99, then it is assumed the primary track is 69 // unchanged. Additional conditions to escape 69 // unchanged. Additional conditions to escape from while-loop over impact 70 // parameter: if the loop counter evtcnt reach 70 // parameter: if the loop counter evtcnt reaches 1000, the primary track is 71 // continued. 71 // continued. 72 // Additional clauses have been included in 72 // Additional clauses have been included in 73 // G4WilsonAbrasionModel::GetNucleonInduced 73 // G4WilsonAbrasionModel::GetNucleonInducedExcitation 74 // Previously it was possible to get sqrt of n << 74 // Previously it was possible to get sqrt of negative number as Wilson algorithm 75 // algorithm not properly defined if either: << 75 // not properly defined if either: 76 // rT > rP && rsq < rTsq - rPsq) or (rP > r 76 // rT > rP && rsq < rTsq - rPsq) or (rP > rT && rsq < rPsq - rTsq) 77 // 77 // 78 // 12 June 2012, A. Ribon, CERN, Switzerland << 78 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79 // Fixing trivial warning errors of shadowed v << 79 //////////////////////////////////////////////////////////////////////////////// 80 // << 81 // 4 August 2015, A. Ribon, CERN, Switzerland << 82 // Replacing std::exp and std::pow with the fa << 83 // << 84 // 7 August 2015, A. Ribon, CERN, Switzerland << 85 // Checking of 'while' loops. << 86 // 80 // 87 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% << 88 ////////////////////////////////////////////// << 89 << 90 #include "G4WilsonAbrasionModel.hh" 81 #include "G4WilsonAbrasionModel.hh" 91 #include "G4WilsonRadius.hh" 82 #include "G4WilsonRadius.hh" 92 #include "G4NuclearAbrasionGeometry.hh" 83 #include "G4NuclearAbrasionGeometry.hh" 93 #include "G4WilsonAblationModel.hh" 84 #include "G4WilsonAblationModel.hh" 94 85 95 #include "G4PhysicalConstants.hh" << 96 #include "G4SystemOfUnits.hh" << 97 #include "G4ExcitationHandler.hh" 86 #include "G4ExcitationHandler.hh" 98 #include "G4Evaporation.hh" 87 #include "G4Evaporation.hh" >> 88 #include "G4FermiBreakUp.hh" >> 89 #include "G4StatMF.hh" 99 #include "G4ParticleDefinition.hh" 90 #include "G4ParticleDefinition.hh" 100 #include "G4DynamicParticle.hh" 91 #include "G4DynamicParticle.hh" 101 #include "Randomize.hh" 92 #include "Randomize.hh" 102 #include "G4Fragment.hh" 93 #include "G4Fragment.hh" >> 94 #include "G4VNuclearDensity.hh" >> 95 #include "G4NuclearShellModelDensity.hh" >> 96 #include "G4NuclearFermiDensity.hh" >> 97 #include "G4FermiMomentum.hh" 103 #include "G4ReactionProductVector.hh" 98 #include "G4ReactionProductVector.hh" 104 #include "G4LorentzVector.hh" 99 #include "G4LorentzVector.hh" 105 #include "G4ParticleMomentum.hh" 100 #include "G4ParticleMomentum.hh" 106 #include "G4Poisson.hh" 101 #include "G4Poisson.hh" 107 #include "G4ParticleTable.hh" 102 #include "G4ParticleTable.hh" 108 #include "G4IonTable.hh" 103 #include "G4IonTable.hh" 109 #include "globals.hh" 104 #include "globals.hh" 110 << 105 //////////////////////////////////////////////////////////////////////////////// 111 #include "G4Exp.hh" << 106 // 112 #include "G4Pow.hh" << 107 G4WilsonAbrasionModel::G4WilsonAbrasionModel (G4bool useAblation1) 113 << 108 :G4HadronicInteraction("G4WilsonAbrasion") 114 #include "G4PhysicsModelCatalog.hh" << 115 << 116 << 117 G4WilsonAbrasionModel::G4WilsonAbrasionModel(G << 118 : G4HadronicInteraction("G4WilsonAbrasion"), << 119 { 109 { 120 // Send message to stdout to advise that the << 110 // >> 111 // >> 112 // Send message to stdout to advise that the G4Abrasion model is being used. >> 113 // 121 PrintWelcomeMessage(); 114 PrintWelcomeMessage(); 122 << 115 // 123 // Set the default verbose level to 0 - no o << 116 // >> 117 // Set the default verbose level to 0 - no output. >> 118 // 124 verboseLevel = 0; 119 verboseLevel = 0; 125 useAblation = useAblation1; 120 useAblation = useAblation1; 126 theAblation = nullptr; << 121 // 127 << 122 // 128 // No de-excitation handler has been supplie << 123 // No de-excitation handler has been supplied - define the default handler. 129 << 124 // 130 theExcitationHandler = new G4ExcitationHandl << 125 theExcitationHandler = new G4ExcitationHandler; >> 126 theExcitationHandlerx = new G4ExcitationHandler; 131 if (useAblation) 127 if (useAblation) 132 { 128 { 133 theAblation = new G4WilsonAblationModel; 129 theAblation = new G4WilsonAblationModel; 134 theAblation->SetVerboseLevel(verboseLevel) 130 theAblation->SetVerboseLevel(verboseLevel); 135 theExcitationHandler->SetEvaporation(theAb << 131 theExcitationHandler->SetEvaporation(theAblation); >> 132 theExcitationHandlerx->SetEvaporation(theAblation); 136 } 133 } 137 << 134 else 138 // Set the minimum and maximum range for the << 135 { 139 // this is in energy per nucleon number). << 136 theAblation = NULL; 140 << 137 G4Evaporation * theEvaporation = new G4Evaporation; >> 138 G4FermiBreakUp * theFermiBreakUp = new G4FermiBreakUp; >> 139 G4StatMF * theMF = new G4StatMF; >> 140 theExcitationHandler->SetEvaporation(theEvaporation); >> 141 theExcitationHandler->SetFermiModel(theFermiBreakUp); >> 142 theExcitationHandler->SetMultiFragmentation(theMF); >> 143 theExcitationHandler->SetMaxAandZForFermiBreakUp(12, 6); >> 144 theExcitationHandler->SetMinEForMultiFrag(5.0*MeV); >> 145 >> 146 theEvaporation = new G4Evaporation; >> 147 theFermiBreakUp = new G4FermiBreakUp; >> 148 theExcitationHandlerx->SetEvaporation(theEvaporation); >> 149 theExcitationHandlerx->SetFermiModel(theFermiBreakUp); >> 150 theExcitationHandlerx->SetMaxAandZForFermiBreakUp(12, 6); >> 151 } >> 152 // >> 153 // >> 154 // Set the minimum and maximum range for the model (despite nomanclature, this >> 155 // is in energy per nucleon number). >> 156 // 141 SetMinEnergy(70.0*MeV); 157 SetMinEnergy(70.0*MeV); 142 SetMaxEnergy(10.1*GeV); 158 SetMaxEnergy(10.1*GeV); 143 isBlocked = false; 159 isBlocked = false; 144 << 160 // 145 // npK, when mutiplied by the nuclear Fermi << 161 // 146 // momentum over which the secondary nucleon << 162 // npK, when mutiplied by the nuclear Fermi momentum, determines the range of 147 << 163 // momentum over which the secondary nucleon momentum is sampled. 148 r0sq = 0.0; << 164 // 149 npK = 5.0; << 165 npK = 5.0; 150 B = 10.0 * MeV; << 166 B = 10.0 * MeV; 151 third = 1.0 / 3.0; << 167 third = 1.0 / 3.0; 152 fradius = 0.99; << 168 fradius = 0.99; 153 conserveEnergy = false; << 169 conserveEnergy = false; 154 conserveMomentum = true; 170 conserveMomentum = true; 155 << 156 // Creator model ID for the secondaries crea << 157 secID = G4PhysicsModelCatalog::GetModelID( " << 158 } 171 } 159 << 172 //////////////////////////////////////////////////////////////////////////////// 160 void G4WilsonAbrasionModel::ModelDescription(s << 173 // 161 { << 174 G4WilsonAbrasionModel::G4WilsonAbrasionModel (G4ExcitationHandler *aExcitationHandler) 162 outFile << "G4WilsonAbrasionModel is a macro << 163 << "nucleus-nucleus collisions using << 164 << "The smaller projectile nucleus g << 165 << "target nucleus, leaving a residu << 166 << "region where the projectile and << 167 << "is then treated as a highly exci << 168 << "model is based on the NUCFRG2 mo << 169 << "projectile energies between 70 M << 170 } << 171 << 172 G4WilsonAbrasionModel::G4WilsonAbrasionModel(G << 173 G4HadronicInteraction("G4WilsonAbrasion"), se << 174 { 175 { >> 176 // >> 177 // 175 // Send message to stdout to advise that the G 178 // Send message to stdout to advise that the G4Abrasion model is being used. 176 << 179 // 177 PrintWelcomeMessage(); 180 PrintWelcomeMessage(); 178 << 181 // >> 182 // 179 // Set the default verbose level to 0 - no out 183 // Set the default verbose level to 0 - no output. 180 << 184 // 181 verboseLevel = 0; 185 verboseLevel = 0; 182 << 186 // 183 theAblation = nullptr; //A.R. 26-Jul-2012 << 184 useAblation = false; //A.R. 14-Aug-2012 << 185 << 186 // 187 // 187 // The user is able to provide the excitation 188 // The user is able to provide the excitation handler as well as an argument 188 // which is provided in this instantiation is 189 // which is provided in this instantiation is used to determine 189 // whether the spectators of the interaction a 190 // whether the spectators of the interaction are free following the abrasion. 190 // 191 // 191 theExcitationHandler = aExcitationHandler; << 192 theExcitationHandler = aExcitationHandler; >> 193 theExcitationHandlerx = new G4ExcitationHandler; >> 194 G4Evaporation * theEvaporation = new G4Evaporation; >> 195 G4FermiBreakUp * theFermiBreakUp = new G4FermiBreakUp; >> 196 theExcitationHandlerx->SetEvaporation(theEvaporation); >> 197 theExcitationHandlerx->SetFermiModel(theFermiBreakUp); >> 198 theExcitationHandlerx->SetMaxAandZForFermiBreakUp(12, 6); 192 // 199 // 193 // 200 // 194 // Set the minimum and maximum range for the m 201 // Set the minimum and maximum range for the model (despite nomanclature, this 195 // is in energy per nucleon number). 202 // is in energy per nucleon number). 196 // 203 // 197 SetMinEnergy(70.0*MeV); 204 SetMinEnergy(70.0*MeV); 198 SetMaxEnergy(10.1*GeV); 205 SetMaxEnergy(10.1*GeV); 199 isBlocked = false; 206 isBlocked = false; 200 // 207 // 201 // 208 // 202 // npK, when mutiplied by the nuclear Fermi mo 209 // npK, when mutiplied by the nuclear Fermi momentum, determines the range of 203 // momentum over which the secondary nucleon m 210 // momentum over which the secondary nucleon momentum is sampled. 204 // 211 // 205 r0sq = 0.0; << 206 npK = 5.0; 212 npK = 5.0; 207 B = 10.0 * MeV; 213 B = 10.0 * MeV; 208 third = 1.0 / 3.0; 214 third = 1.0 / 3.0; 209 fradius = 0.99; 215 fradius = 0.99; 210 conserveEnergy = false; 216 conserveEnergy = false; 211 conserveMomentum = true; 217 conserveMomentum = true; 212 << 213 // Creator model ID for the secondaries crea << 214 secID = G4PhysicsModelCatalog::GetModelID( " << 215 } 218 } 216 ////////////////////////////////////////////// 219 //////////////////////////////////////////////////////////////////////////////// 217 // 220 // 218 G4WilsonAbrasionModel::~G4WilsonAbrasionModel( << 221 G4WilsonAbrasionModel::~G4WilsonAbrasionModel () 219 { 222 { 220 delete theExcitationHandler; << 223 // >> 224 // >> 225 // The destructor doesn't have to do a great deal! >> 226 // >> 227 if (theExcitationHandler) delete theExcitationHandler; >> 228 if (theExcitationHandlerx) delete theExcitationHandlerx; >> 229 if (useAblation) delete theAblation; >> 230 // delete theExcitationHandler; >> 231 // delete theExcitationHandlerx; 221 } 232 } 222 ////////////////////////////////////////////// 233 //////////////////////////////////////////////////////////////////////////////// 223 // 234 // 224 G4HadFinalState *G4WilsonAbrasionModel::ApplyY 235 G4HadFinalState *G4WilsonAbrasionModel::ApplyYourself ( 225 const G4HadProjectile &theTrack, G4Nucleus & 236 const G4HadProjectile &theTrack, G4Nucleus &theTarget) 226 { 237 { 227 // 238 // 228 // 239 // 229 // The secondaries will be returned in G4HadFi 240 // The secondaries will be returned in G4HadFinalState &theParticleChange - 230 // initialise this. The original track will a 241 // initialise this. The original track will always be discontinued and 231 // secondaries followed. 242 // secondaries followed. 232 // 243 // 233 theParticleChange.Clear(); 244 theParticleChange.Clear(); 234 theParticleChange.SetStatusChange(stopAndKil 245 theParticleChange.SetStatusChange(stopAndKill); 235 // 246 // 236 // 247 // 237 // Get relevant information about the projecti 248 // Get relevant information about the projectile and target (A, Z, energy/nuc, 238 // momentum, etc). 249 // momentum, etc). 239 // 250 // 240 const G4ParticleDefinition *definitionP = th 251 const G4ParticleDefinition *definitionP = theTrack.GetDefinition(); 241 const G4double AP = definitionP->GetBaryonN << 252 const G4double AP = definitionP->GetBaryonNumber(); 242 const G4double ZP = definitionP->GetPDGChar << 253 const G4double ZP = definitionP->GetPDGCharge(); 243 G4LorentzVector pP = theTrack.Get4Momentum() << 254 G4LorentzVector pP = theTrack.Get4Momentum(); 244 G4double E = theTrack.GetKineticEner << 255 G4double E = theTrack.GetKineticEnergy()/AP; 245 G4double AT = theTarget.GetA_asInt(); << 256 G4double AT = theTarget.GetN(); 246 G4double ZT = theTarget.GetZ_asInt(); << 257 G4double ZT = theTarget.GetZ(); 247 G4double TotalEPre = theTrack.GetTotalEnergy << 258 G4double TotalEPre = theTrack.GetTotalEnergy() + 248 theTarget.AtomicMass(AT, ZT) + theTarget.G 259 theTarget.AtomicMass(AT, ZT) + theTarget.GetEnergyDeposit(); 249 G4double TotalEPost = 0.0; 260 G4double TotalEPost = 0.0; 250 // 261 // 251 // 262 // 252 // Determine the radii of the projectile and t 263 // Determine the radii of the projectile and target nuclei. 253 // 264 // 254 G4WilsonRadius aR; 265 G4WilsonRadius aR; 255 G4double rP = aR.GetWilsonRadius(AP); 266 G4double rP = aR.GetWilsonRadius(AP); 256 G4double rT = aR.GetWilsonRadius(AT); 267 G4double rT = aR.GetWilsonRadius(AT); 257 G4double rPsq = rP * rP; 268 G4double rPsq = rP * rP; 258 G4double rTsq = rT * rT; 269 G4double rTsq = rT * rT; 259 if (verboseLevel >= 2) 270 if (verboseLevel >= 2) 260 { 271 { 261 G4cout <<"################################ 272 G4cout <<"########################################" 262 <<"################################ 273 <<"########################################" 263 <<G4endl; 274 <<G4endl; 264 G4cout.precision(6); 275 G4cout.precision(6); 265 G4cout <<"IN G4WilsonAbrasionModel" <<G4en 276 G4cout <<"IN G4WilsonAbrasionModel" <<G4endl; 266 G4cout <<"Initial projectile A=" <<AP 277 G4cout <<"Initial projectile A=" <<AP 267 <<", Z=" <<ZP 278 <<", Z=" <<ZP 268 <<", radius = " <<rP/fermi <<" fm" 279 <<", radius = " <<rP/fermi <<" fm" 269 <<G4endl; 280 <<G4endl; 270 G4cout <<"Initial target A=" <<AT 281 G4cout <<"Initial target A=" <<AT 271 <<", Z=" <<ZT 282 <<", Z=" <<ZT 272 <<", radius = " <<rT/fermi <<" fm" 283 <<", radius = " <<rT/fermi <<" fm" 273 <<G4endl; 284 <<G4endl; 274 G4cout <<"Projectile momentum and Energy/n 285 G4cout <<"Projectile momentum and Energy/nuc = " <<pP <<" ," <<E <<G4endl; 275 } 286 } 276 // 287 // 277 // 288 // 278 // The following variables are used to determi 289 // The following variables are used to determine the impact parameter in the 279 // near-field (i.e. taking into consideration 290 // near-field (i.e. taking into consideration the electrostatic repulsion). 280 // 291 // 281 G4double rm = ZP * ZT * elm_coupling / (E 292 G4double rm = ZP * ZT * elm_coupling / (E * AP); 282 G4double r = 0.0; 293 G4double r = 0.0; 283 G4double rsq = 0.0; 294 G4double rsq = 0.0; 284 // 295 // 285 // 296 // 286 // Initialise some of the variables which wll 297 // Initialise some of the variables which wll be used to calculate the chord- 287 // length for nucleons in the projectile and t 298 // length for nucleons in the projectile and target, and hence calculate the 288 // number of abraded nucleons and the excitati 299 // number of abraded nucleons and the excitation energy. 289 // 300 // 290 G4NuclearAbrasionGeometry *theAbrasionGeomet << 301 G4NuclearAbrasionGeometry *theAbrasionGeometry = NULL; 291 G4double CT = 0.0; 302 G4double CT = 0.0; 292 G4double F = 0.0; 303 G4double F = 0.0; 293 G4int Dabr = 0; 304 G4int Dabr = 0; 294 // 305 // 295 // 306 // 296 // The following loop is performed until the n 307 // The following loop is performed until the number of nucleons which are 297 // abraded by the process is >1, i.e. an inter 308 // abraded by the process is >1, i.e. an interaction MUST occur. 298 // 309 // 299 G4bool skipInteraction = false; // It will << 310 while (Dabr == 0) 300 const G4int maxNumberOfLoops = 1000; << 301 G4int loopCounter = -1; << 302 while (Dabr == 0 && ++loopCounter < maxNumbe << 303 { 311 { >> 312 // Added by MHM 20050119 to fix leaking memory on second pass through this loop >> 313 if (theAbrasionGeometry) >> 314 { >> 315 delete theAbrasionGeometry; >> 316 theAbrasionGeometry = NULL; >> 317 } 304 // 318 // 305 // 319 // 306 // Sample the impact parameter. For the momen 320 // Sample the impact parameter. For the moment, this class takes account of 307 // electrostatic effects on the impact paramet 321 // electrostatic effects on the impact parameter, but (like HZETRN AND NUCFRG2) 308 // does not make any correction for the effect 322 // does not make any correction for the effects of nuclear-nuclear repulsion. 309 // 323 // 310 G4double rPT = rP + rT; 324 G4double rPT = rP + rT; 311 G4double rPTsq = rPT * rPT; 325 G4double rPTsq = rPT * rPT; 312 // 326 // 313 // 327 // 314 // This is a "catch" to make sure we don't go 328 // This is a "catch" to make sure we don't go into an infinite loop because the 315 // energy is too low to overcome nuclear repul 329 // energy is too low to overcome nuclear repulsion. PRT 20091023. If the 316 // value of rm < fradius * rPT then we're unli 330 // value of rm < fradius * rPT then we're unlikely to sample a small enough 317 // impact parameter (energy of incident partic << 331 // impact parameter (energy of incident particle is too low). Return primary >> 332 // and don't complete nuclear interaction analysis. 318 // 333 // 319 if (rm >= fradius * rPT) { 334 if (rm >= fradius * rPT) { 320 skipInteraction = true; << 335 theParticleChange.SetStatusChange(isAlive); >> 336 theParticleChange.SetEnergyChange(theTrack.GetKineticEnergy()); >> 337 theParticleChange.SetMomentumChange(theTrack.Get4Momentum().vect().unit()); >> 338 if (verboseLevel >= 2) { >> 339 G4cout <<"Particle energy too low to overcome repulsion." <<G4endl; >> 340 G4cout <<"Event rejected and original track maintained" <<G4endl; >> 341 G4cout <<"########################################" >> 342 <<"########################################" >> 343 <<G4endl; >> 344 } >> 345 return &theParticleChange; 321 } 346 } 322 // 347 // 323 // 348 // 324 // Now sample impact parameter until the crite 349 // Now sample impact parameter until the criterion is met that projectile 325 // and target overlap, but repulsion is taken 350 // and target overlap, but repulsion is taken into consideration. 326 // 351 // 327 G4int evtcnt = 0; 352 G4int evtcnt = 0; 328 r = 1.1 * rPT; 353 r = 1.1 * rPT; 329 while (r > rPT && ++evtcnt < 1000) /* Loo << 354 while (r > rPT && ++evtcnt < 1000) 330 { 355 { 331 G4double bsq = rPTsq * G4UniformRand(); 356 G4double bsq = rPTsq * G4UniformRand(); 332 r = (rm + std::sqrt(rm*rm + 4 357 r = (rm + std::sqrt(rm*rm + 4.0*bsq)) / 2.0; 333 } 358 } 334 // 359 // 335 // 360 // 336 // We've tried to sample this 1000 times, but << 361 // We've tried to sample this 1000 times, but failed. Assume nuclei do not >> 362 // collide. 337 // 363 // 338 if (evtcnt >= 1000) { 364 if (evtcnt >= 1000) { 339 skipInteraction = true; << 365 theParticleChange.SetStatusChange(isAlive); >> 366 theParticleChange.SetEnergyChange(theTrack.GetKineticEnergy()); >> 367 theParticleChange.SetMomentumChange(theTrack.Get4Momentum().vect().unit()); >> 368 if (verboseLevel >= 2) { >> 369 G4cout <<"Particle energy too low to overcome repulsion." <<G4endl; >> 370 G4cout <<"Event rejected and original track maintained" <<G4endl; >> 371 G4cout <<"########################################" >> 372 <<"########################################" >> 373 <<G4endl; >> 374 } >> 375 return &theParticleChange; 340 } 376 } 341 377 >> 378 342 rsq = r * r; 379 rsq = r * r; 343 // 380 // 344 // 381 // 345 // Now determine the chord-length through the 382 // Now determine the chord-length through the target nucleus. 346 // 383 // 347 if (rT > rP) 384 if (rT > rP) 348 { 385 { 349 G4double x = (rPsq + rsq - rTsq) / 2.0 / 386 G4double x = (rPsq + rsq - rTsq) / 2.0 / r; 350 if (x > 0.0) CT = 2.0 * std::sqrt(rTsq - 387 if (x > 0.0) CT = 2.0 * std::sqrt(rTsq - x*x); 351 else CT = 2.0 * std::sqrt(rTsq - 388 else CT = 2.0 * std::sqrt(rTsq - rsq); 352 } 389 } 353 else 390 else 354 { 391 { 355 G4double x = (rTsq + rsq - rPsq) / 2.0 / 392 G4double x = (rTsq + rsq - rPsq) / 2.0 / r; 356 if (x > 0.0) CT = 2.0 * std::sqrt(rTsq - 393 if (x > 0.0) CT = 2.0 * std::sqrt(rTsq - x*x); 357 else CT = 2.0 * rT; 394 else CT = 2.0 * rT; 358 } 395 } 359 // 396 // 360 // 397 // 361 // Determine the number of abraded nucleons. 398 // Determine the number of abraded nucleons. Note that the mean number of 362 // abraded nucleons is used to sample the Pois 399 // abraded nucleons is used to sample the Poisson distribution. The Poisson 363 // distribution is sampled only ten times with 400 // distribution is sampled only ten times with the current impact parameter, 364 // and if it fails after this to find a case f 401 // and if it fails after this to find a case for which the number of abraded 365 // nucleons >1, the impact parameter is re-sam 402 // nucleons >1, the impact parameter is re-sampled. 366 // 403 // 367 delete theAbrasionGeometry; << 368 theAbrasionGeometry = new G4NuclearAbrasio 404 theAbrasionGeometry = new G4NuclearAbrasionGeometry(AP,AT,r); 369 F = theAbrasionGeometry- 405 F = theAbrasionGeometry->F(); 370 G4double lambda = 16.6*fermi / G4Pow:: << 406 G4double lambda = 16.6*fermi / std::pow(E/MeV,0.26); 371 G4double Mabr = F * AP * (1.0 - G4Ex << 407 G4double Mabr = F * AP * (1.0 - std::exp(-CT/lambda)); 372 G4long n = 0; 408 G4long n = 0; 373 for (G4int i = 0; i<10; ++i) << 409 for (G4int i = 0; i<10; i++) 374 { 410 { 375 n = G4Poisson(Mabr); 411 n = G4Poisson(Mabr); 376 if (n > 0) 412 if (n > 0) 377 { 413 { 378 if (n>AP) Dabr = (G4int) AP; 414 if (n>AP) Dabr = (G4int) AP; 379 else Dabr = (G4int) n; 415 else Dabr = (G4int) n; 380 break; 416 break; 381 } 417 } 382 } 418 } 383 } // End of while loop << 384 << 385 if ( loopCounter >= maxNumberOfLoops || skip << 386 // Assume nuclei do not collide and return << 387 theParticleChange.SetStatusChange(isAlive) << 388 theParticleChange.SetEnergyChange(theTrack << 389 theParticleChange.SetMomentumChange(theTra << 390 if (verboseLevel >= 2) { << 391 G4cout <<"Particle energy too low to ove << 392 G4cout <<"Event rejected and original tr << 393 G4cout <<"############################## << 394 <<"############################## << 395 <<G4endl; << 396 } << 397 delete theAbrasionGeometry; << 398 return &theParticleChange; << 399 } 419 } 400 << 401 if (verboseLevel >= 2) 420 if (verboseLevel >= 2) 402 { 421 { 403 G4cout <<G4endl; 422 G4cout <<G4endl; 404 G4cout <<"Impact parameter = " <<r/ferm 423 G4cout <<"Impact parameter = " <<r/fermi <<" fm" <<G4endl; 405 G4cout <<"# Abraded nucleons = " <<Dabr < 424 G4cout <<"# Abraded nucleons = " <<Dabr <<G4endl; 406 } 425 } 407 // 426 // 408 // 427 // 409 // The number of abraded nucleons must be no g 428 // The number of abraded nucleons must be no greater than the number of 410 // nucleons in either the projectile or the ta 429 // nucleons in either the projectile or the target. If AP - Dabr < 2 or 411 // AT - Dabr < 2 then either we have only a nu 430 // AT - Dabr < 2 then either we have only a nucleon left behind in the 412 // projectile/target or we've tried to abrade 431 // projectile/target or we've tried to abrade too many nucleons - and Dabr 413 // should be limited. 432 // should be limited. 414 // 433 // 415 if (AP - (G4double) Dabr < 2.0) Dabr = (G4in 434 if (AP - (G4double) Dabr < 2.0) Dabr = (G4int) AP; 416 if (AT - (G4double) Dabr < 2.0) Dabr = (G4in 435 if (AT - (G4double) Dabr < 2.0) Dabr = (G4int) AT; 417 // 436 // 418 // 437 // 419 // Determine the abraded secondary nucleons fr 438 // Determine the abraded secondary nucleons from the projectile. *fragmentP 420 // is a pointer to the prefragment from the pr 439 // is a pointer to the prefragment from the projectile and nSecP is the number 421 // of nucleons in theParticleChange which have 440 // of nucleons in theParticleChange which have been abraded. The total energy 422 // from these is determined. 441 // from these is determined. 423 // 442 // 424 G4ThreeVector boost = pP.findBoostToCM(); 443 G4ThreeVector boost = pP.findBoostToCM(); 425 G4Fragment *fragmentP = GetAbradedNucleons ( 444 G4Fragment *fragmentP = GetAbradedNucleons (Dabr, AP, ZP, rP); 426 G4int nSecP = (G4int)theParticleCh << 445 G4int nSecP = theParticleChange.GetNumberOfSecondaries(); 427 G4int i = 0; 446 G4int i = 0; 428 for (i=0; i<nSecP; ++i) << 447 for (i=0; i<nSecP; i++) 429 { 448 { 430 TotalEPost += theParticleChange.GetSeconda 449 TotalEPost += theParticleChange.GetSecondary(i)-> 431 GetParticle()->GetTotalEnergy(); 450 GetParticle()->GetTotalEnergy(); 432 } 451 } 433 // 452 // 434 // 453 // 435 // Determine the number of spectators in the i 454 // Determine the number of spectators in the interaction region for the 436 // projectile. 455 // projectile. 437 // 456 // 438 G4int DspcP = (G4int) (AP*F) - Dabr; 457 G4int DspcP = (G4int) (AP*F) - Dabr; 439 if (DspcP <= 0) DspcP = 0; 458 if (DspcP <= 0) DspcP = 0; 440 else if (DspcP > AP-Dabr) DspcP = ((G4int) A 459 else if (DspcP > AP-Dabr) DspcP = ((G4int) AP) - Dabr; 441 // 460 // 442 // 461 // 443 // Determine excitation energy associated with 462 // Determine excitation energy associated with excess surface area of the 444 // projectile (EsP) and the excitation due to 463 // projectile (EsP) and the excitation due to scattering of nucleons which are 445 // retained within the projectile (ExP). Add 464 // retained within the projectile (ExP). Add the total energy from the excited 446 // nucleus to the total energy of the secondar 465 // nucleus to the total energy of the secondaries. 447 // 466 // 448 G4bool excitationAbsorbedByProjectile = fals 467 G4bool excitationAbsorbedByProjectile = false; 449 if (fragmentP != nullptr) << 468 if (fragmentP != NULL) 450 { 469 { 451 G4double EsP = theAbrasionGeometry->GetExc 470 G4double EsP = theAbrasionGeometry->GetExcitationEnergyOfProjectile(); 452 G4double ExP = 0.0; 471 G4double ExP = 0.0; 453 if (Dabr < AT) 472 if (Dabr < AT) 454 excitationAbsorbedByProjectile = G4Unifo 473 excitationAbsorbedByProjectile = G4UniformRand() < 0.5; 455 if (excitationAbsorbedByProjectile) 474 if (excitationAbsorbedByProjectile) 456 ExP = GetNucleonInducedExcitation(rP, rT 475 ExP = GetNucleonInducedExcitation(rP, rT, r); 457 G4double xP = EsP + ExP; 476 G4double xP = EsP + ExP; 458 if (xP > B*(AP-Dabr)) xP = B*(AP-Dabr); 477 if (xP > B*(AP-Dabr)) xP = B*(AP-Dabr); 459 G4LorentzVector lorentzVector = fragmentP- 478 G4LorentzVector lorentzVector = fragmentP->GetMomentum(); 460 lorentzVector.setE(lorentzVector.e()+xP); 479 lorentzVector.setE(lorentzVector.e()+xP); 461 fragmentP->SetMomentum(lorentzVector); 480 fragmentP->SetMomentum(lorentzVector); 462 TotalEPost += lorentzVector.e(); 481 TotalEPost += lorentzVector.e(); 463 } 482 } 464 G4double EMassP = TotalEPost; 483 G4double EMassP = TotalEPost; 465 // 484 // 466 // 485 // 467 // Determine the abraded secondary nucleons fr 486 // Determine the abraded secondary nucleons from the target. Note that it's 468 // assumed that the same number of nucleons ar 487 // assumed that the same number of nucleons are abraded from the target as for 469 // the projectile, and obviously no boost is a 488 // the projectile, and obviously no boost is applied to the products. *fragmentT 470 // is a pointer to the prefragment from the ta 489 // is a pointer to the prefragment from the target and nSec is the total number 471 // of nucleons in theParticleChange which have 490 // of nucleons in theParticleChange which have been abraded. The total energy 472 // from these is determined. 491 // from these is determined. 473 // 492 // 474 G4Fragment *fragmentT = GetAbradedNucleons ( 493 G4Fragment *fragmentT = GetAbradedNucleons (Dabr, AT, ZT, rT); 475 G4int nSec = (G4int)theParticleChange.GetNum << 494 G4int nSec = theParticleChange.GetNumberOfSecondaries(); 476 for (i=nSecP; i<nSec; ++i) << 495 for (i=nSecP; i<nSec; i++) 477 { 496 { 478 TotalEPost += theParticleChange.GetSeconda 497 TotalEPost += theParticleChange.GetSecondary(i)-> 479 GetParticle()->GetTotalEnergy(); 498 GetParticle()->GetTotalEnergy(); 480 } 499 } 481 // 500 // 482 // 501 // 483 // Determine the number of spectators in the i 502 // Determine the number of spectators in the interaction region for the 484 // target. 503 // target. 485 // 504 // 486 G4int DspcT = (G4int) (AT*F) - Dabr; 505 G4int DspcT = (G4int) (AT*F) - Dabr; 487 if (DspcT <= 0) DspcT = 0; 506 if (DspcT <= 0) DspcT = 0; 488 else if (DspcT > AP-Dabr) DspcT = ((G4int) A 507 else if (DspcT > AP-Dabr) DspcT = ((G4int) AT) - Dabr; 489 // 508 // 490 // 509 // 491 // Determine excitation energy associated with 510 // Determine excitation energy associated with excess surface area of the 492 // target (EsT) and the excitation due to scat 511 // target (EsT) and the excitation due to scattering of nucleons which are 493 // retained within the target (ExT). Add the 512 // retained within the target (ExT). Add the total energy from the excited 494 // nucleus to the total energy of the secondar 513 // nucleus to the total energy of the secondaries. 495 // 514 // 496 if (fragmentT != nullptr) << 515 if (fragmentT != NULL) 497 { 516 { 498 G4double EsT = theAbrasionGeometry->GetExc 517 G4double EsT = theAbrasionGeometry->GetExcitationEnergyOfTarget(); 499 G4double ExT = 0.0; 518 G4double ExT = 0.0; 500 if (!excitationAbsorbedByProjectile) 519 if (!excitationAbsorbedByProjectile) 501 ExT = GetNucleonInducedExcitation(rT, rP 520 ExT = GetNucleonInducedExcitation(rT, rP, r); 502 G4double xT = EsT + ExT; 521 G4double xT = EsT + ExT; 503 if (xT > B*(AT-Dabr)) xT = B*(AT-Dabr); 522 if (xT > B*(AT-Dabr)) xT = B*(AT-Dabr); 504 G4LorentzVector lorentzVector = fragmentT- 523 G4LorentzVector lorentzVector = fragmentT->GetMomentum(); 505 lorentzVector.setE(lorentzVector.e()+xT); 524 lorentzVector.setE(lorentzVector.e()+xT); 506 fragmentT->SetMomentum(lorentzVector); 525 fragmentT->SetMomentum(lorentzVector); 507 TotalEPost += lorentzVector.e(); 526 TotalEPost += lorentzVector.e(); 508 } 527 } 509 // 528 // 510 // 529 // 511 // Now determine the difference between the pr 530 // Now determine the difference between the pre and post interaction 512 // energy - this will be used to determine the 531 // energy - this will be used to determine the Lorentz boost if conservation 513 // of energy is to be imposed/attempted. 532 // of energy is to be imposed/attempted. 514 // 533 // 515 G4double deltaE = TotalEPre - TotalEPost; 534 G4double deltaE = TotalEPre - TotalEPost; 516 if (deltaE > 0.0 && conserveEnergy) 535 if (deltaE > 0.0 && conserveEnergy) 517 { 536 { 518 G4double beta = std::sqrt(1.0 - EMassP*EMa << 537 G4double beta = std::sqrt(1.0 - EMassP*EMassP/std::pow(deltaE+EMassP,2.0)); 519 boost = boost / boost.mag() * beta; 538 boost = boost / boost.mag() * beta; 520 } 539 } 521 // 540 // 522 // 541 // 523 // Now boost the secondaries from the projecti 542 // Now boost the secondaries from the projectile. 524 // 543 // 525 G4ThreeVector pBalance = pP.vect(); 544 G4ThreeVector pBalance = pP.vect(); 526 for (i=0; i<nSecP; ++i) << 545 for (i=0; i<nSecP; i++) 527 { 546 { 528 G4DynamicParticle *dynamicP = theParticleC 547 G4DynamicParticle *dynamicP = theParticleChange.GetSecondary(i)-> 529 GetParticle(); 548 GetParticle(); 530 G4LorentzVector lorentzVector = dynamicP-> 549 G4LorentzVector lorentzVector = dynamicP->Get4Momentum(); 531 lorentzVector.boost(-boost); 550 lorentzVector.boost(-boost); 532 dynamicP->Set4Momentum(lorentzVector); 551 dynamicP->Set4Momentum(lorentzVector); 533 pBalance -= lorentzVector.vect(); 552 pBalance -= lorentzVector.vect(); 534 } 553 } 535 // 554 // 536 // 555 // 537 // Set the boost for the projectile prefragmen 556 // Set the boost for the projectile prefragment. This is now based on the 538 // conservation of momentum. However, if the 557 // conservation of momentum. However, if the user selected momentum of the 539 // prefragment is not to be conserved this sim 558 // prefragment is not to be conserved this simply boosted to the velocity of the 540 // original projectile times the ratio of the 559 // original projectile times the ratio of the unexcited to the excited mass 541 // of the prefragment (the excitation increase 560 // of the prefragment (the excitation increases the effective mass of the 542 // prefragment, and therefore modifying the bo 561 // prefragment, and therefore modifying the boost is an attempt to prevent 543 // the momentum of the prefragment being exces 562 // the momentum of the prefragment being excessive). 544 // 563 // 545 if (fragmentP != nullptr) << 564 if (fragmentP != NULL) 546 { 565 { 547 G4LorentzVector lorentzVector = fragmentP- 566 G4LorentzVector lorentzVector = fragmentP->GetMomentum(); 548 G4double fragmentM = lorentzVec << 567 G4double m = lorentzVector.m(); 549 if (conserveMomentum) 568 if (conserveMomentum) 550 fragmentP->SetMomentum 569 fragmentP->SetMomentum 551 (G4LorentzVector(pBalance,std::sqrt(pB << 570 (G4LorentzVector(pBalance,std::sqrt(pBalance.mag2()+m*m+1.0*eV*eV))); 552 else 571 else 553 { 572 { 554 G4double fragmentGroundStateM = fragment << 573 G4double mg = fragmentP->GetGroundStateMass(); 555 fragmentP->SetMomentum(lorentzVector.boo << 574 fragmentP->SetMomentum(lorentzVector.boost(-boost * mg/m)); 556 } 575 } 557 } 576 } 558 // 577 // 559 // 578 // 560 // Output information to user if verbose infor 579 // Output information to user if verbose information requested. 561 // 580 // 562 if (verboseLevel >= 2) 581 if (verboseLevel >= 2) 563 { 582 { 564 G4cout <<G4endl; 583 G4cout <<G4endl; 565 G4cout <<"-------------------------------- 584 G4cout <<"-----------------------------------" <<G4endl; 566 G4cout <<"Secondary nucleons from projecti 585 G4cout <<"Secondary nucleons from projectile:" <<G4endl; 567 G4cout <<"-------------------------------- 586 G4cout <<"-----------------------------------" <<G4endl; 568 G4cout.precision(7); 587 G4cout.precision(7); 569 for (i=0; i<nSecP; ++i) << 588 for (i=0; i<nSecP; i++) 570 { 589 { 571 G4cout <<"Particle # " <<i <<G4endl; 590 G4cout <<"Particle # " <<i <<G4endl; 572 theParticleChange.GetSecondary(i)->GetPa 591 theParticleChange.GetSecondary(i)->GetParticle()->DumpInfo(); 573 G4DynamicParticle *dyn = theParticleChan 592 G4DynamicParticle *dyn = theParticleChange.GetSecondary(i)->GetParticle(); 574 G4cout <<"New nucleon (P) " <<dyn->GetDe 593 G4cout <<"New nucleon (P) " <<dyn->GetDefinition()->GetParticleName() 575 <<" : " <<dyn->Get4M 594 <<" : " <<dyn->Get4Momentum() 576 <<G4endl; 595 <<G4endl; 577 } 596 } 578 G4cout <<"---------------------------" <<G 597 G4cout <<"---------------------------" <<G4endl; 579 G4cout <<"The projectile prefragment:" <<G 598 G4cout <<"The projectile prefragment:" <<G4endl; 580 G4cout <<"---------------------------" <<G 599 G4cout <<"---------------------------" <<G4endl; 581 if (fragmentP != nullptr) << 600 if (fragmentP != NULL) 582 G4cout <<*fragmentP <<G4endl; 601 G4cout <<*fragmentP <<G4endl; 583 else 602 else 584 G4cout <<"(No residual prefragment)" <<G 603 G4cout <<"(No residual prefragment)" <<G4endl; 585 G4cout <<G4endl; 604 G4cout <<G4endl; 586 G4cout <<"-------------------------------" 605 G4cout <<"-------------------------------" <<G4endl; 587 G4cout <<"Secondary nucleons from target:" 606 G4cout <<"Secondary nucleons from target:" <<G4endl; 588 G4cout <<"-------------------------------" 607 G4cout <<"-------------------------------" <<G4endl; 589 G4cout.precision(7); 608 G4cout.precision(7); 590 for (i=nSecP; i<nSec; ++i) << 609 for (i=nSecP; i<nSec; i++) 591 { 610 { 592 G4cout <<"Particle # " <<i <<G4endl; 611 G4cout <<"Particle # " <<i <<G4endl; 593 theParticleChange.GetSecondary(i)->GetPa 612 theParticleChange.GetSecondary(i)->GetParticle()->DumpInfo(); 594 G4DynamicParticle *dyn = theParticleChan 613 G4DynamicParticle *dyn = theParticleChange.GetSecondary(i)->GetParticle(); 595 G4cout <<"New nucleon (T) " <<dyn->GetDe 614 G4cout <<"New nucleon (T) " <<dyn->GetDefinition()->GetParticleName() 596 <<" : " <<dyn->Get4M 615 <<" : " <<dyn->Get4Momentum() 597 <<G4endl; 616 <<G4endl; 598 } 617 } 599 G4cout <<"-----------------------" <<G4end 618 G4cout <<"-----------------------" <<G4endl; 600 G4cout <<"The target prefragment:" <<G4end 619 G4cout <<"The target prefragment:" <<G4endl; 601 G4cout <<"-----------------------" <<G4end 620 G4cout <<"-----------------------" <<G4endl; 602 if (fragmentT != nullptr) << 621 if (fragmentT != NULL) 603 G4cout <<*fragmentT <<G4endl; 622 G4cout <<*fragmentT <<G4endl; 604 else 623 else 605 G4cout <<"(No residual prefragment)" <<G 624 G4cout <<"(No residual prefragment)" <<G4endl; 606 } 625 } 607 // 626 // 608 // 627 // 609 // Now we can decay the nuclear fragments if p 628 // Now we can decay the nuclear fragments if present. The secondaries are 610 // collected and boosted as well. This is per 629 // collected and boosted as well. This is performed first for the projectile... 611 // 630 // 612 if (fragmentP !=nullptr) << 631 if (fragmentP !=NULL) 613 { 632 { 614 G4ReactionProductVector *products = nullpt << 633 G4ReactionProductVector *products = NULL; 615 // if (fragmentP->GetZ_asInt() != fragm << 634 if (fragmentP->GetZ() != fragmentP->GetA()) 616 products = theExcitationHandler->BreakItUp << 635 products = theExcitationHandler->BreakItUp(*fragmentP); 617 // else << 636 else 618 // products = theExcitationHandlerx->Bre << 637 products = theExcitationHandlerx->BreakItUp(*fragmentP); 619 delete fragmentP; 638 delete fragmentP; 620 fragmentP = nullptr; << 639 fragmentP = NULL; 621 640 622 G4ReactionProductVector::iterator iter; 641 G4ReactionProductVector::iterator iter; 623 for (iter = products->begin(); iter != pro 642 for (iter = products->begin(); iter != products->end(); ++iter) 624 { 643 { 625 G4DynamicParticle *secondary = 644 G4DynamicParticle *secondary = 626 new G4DynamicParticle((*iter)->GetDefi 645 new G4DynamicParticle((*iter)->GetDefinition(), 627 (*iter)->GetTotalEnergy(), (*iter)->Ge 646 (*iter)->GetTotalEnergy(), (*iter)->GetMomentum()); 628 theParticleChange.AddSecondary (secondar << 647 theParticleChange.AddSecondary (secondary); // Added MHM 20050118 629 G4String particleName = (*iter)->GetDefi 648 G4String particleName = (*iter)->GetDefinition()->GetParticleName(); 630 delete (*iter); // get rid of leftover p << 649 delete (*iter); // get rid of leftover particle def! // Added MHM 20050118 631 if (verboseLevel >= 2 && particleName.fi 650 if (verboseLevel >= 2 && particleName.find("[",0) < particleName.size()) 632 { 651 { 633 G4cout <<"------------------------" << 652 G4cout <<"------------------------" <<G4endl; 634 G4cout <<"The projectile fragment:" << 653 G4cout <<"The projectile fragment:" <<G4endl; 635 G4cout <<"------------------------" << 654 G4cout <<"------------------------" <<G4endl; 636 G4cout <<" fragmentP = " <<particleNam 655 G4cout <<" fragmentP = " <<particleName 637 <<" Energy = " <<secondary-> 656 <<" Energy = " <<secondary->GetKineticEnergy() 638 <<G4endl; 657 <<G4endl; 639 } 658 } 640 } 659 } 641 delete products; << 660 delete products; // Added MHM 20050118 642 } 661 } 643 // 662 // 644 // 663 // 645 // Now decay the target nucleus - no boost is 664 // Now decay the target nucleus - no boost is applied since in this 646 // approximation it is assumed that there is n 665 // approximation it is assumed that there is negligible momentum transfer from 647 // the projectile. 666 // the projectile. 648 // 667 // 649 if (fragmentT != nullptr) << 668 if (fragmentT != NULL) 650 { 669 { 651 G4ReactionProductVector *products = nullpt << 670 G4ReactionProductVector *products = NULL; 652 // if (fragmentT->GetZ_asInt() != fragm << 671 if (fragmentT->GetZ() != fragmentT->GetA()) 653 products = theExcitationHandler->BreakIt 672 products = theExcitationHandler->BreakItUp(*fragmentT); 654 // else << 673 else 655 // products = theExcitationHandlerx->Bre << 674 products = theExcitationHandlerx->BreakItUp(*fragmentT); 656 // delete fragmentT; << 675 delete fragmentT; 657 fragmentT = nullptr; << 676 fragmentT = NULL; 658 677 659 G4ReactionProductVector::iterator iter; 678 G4ReactionProductVector::iterator iter; 660 for (iter = products->begin(); iter != pro 679 for (iter = products->begin(); iter != products->end(); ++iter) 661 { 680 { 662 G4DynamicParticle *secondary = 681 G4DynamicParticle *secondary = 663 new G4DynamicParticle((*iter)->GetDefi 682 new G4DynamicParticle((*iter)->GetDefinition(), 664 (*iter)->GetTotalEnergy(), (*iter)->Ge 683 (*iter)->GetTotalEnergy(), (*iter)->GetMomentum()); 665 theParticleChange.AddSecondary (secondar << 684 theParticleChange.AddSecondary (secondary); 666 G4String particleName = (*iter)->GetDefi 685 G4String particleName = (*iter)->GetDefinition()->GetParticleName(); 667 delete (*iter); // get rid of leftover p << 686 delete (*iter); // get rid of leftover particle def! // Added MHM 20050118 668 if (verboseLevel >= 2 && particleName.fi 687 if (verboseLevel >= 2 && particleName.find("[",0) < particleName.size()) 669 { 688 { 670 G4cout <<"--------------------" <<G4en 689 G4cout <<"--------------------" <<G4endl; 671 G4cout <<"The target fragment:" <<G4en 690 G4cout <<"The target fragment:" <<G4endl; 672 G4cout <<"--------------------" <<G4en 691 G4cout <<"--------------------" <<G4endl; 673 G4cout <<" fragmentT = " <<particleNam 692 G4cout <<" fragmentT = " <<particleName 674 <<" Energy = " <<secondary-> 693 <<" Energy = " <<secondary->GetKineticEnergy() 675 <<G4endl; 694 <<G4endl; 676 } 695 } 677 } 696 } 678 delete products; << 697 delete products; // Added MHM 20050118 679 } 698 } 680 699 681 if (verboseLevel >= 2) 700 if (verboseLevel >= 2) 682 G4cout <<"############################### 701 G4cout <<"########################################" 683 <<"############################### 702 <<"########################################" 684 <<G4endl; 703 <<G4endl; 685 704 686 delete theAbrasionGeometry; 705 delete theAbrasionGeometry; >> 706 687 return &theParticleChange; 707 return &theParticleChange; 688 } 708 } 689 ////////////////////////////////////////////// 709 //////////////////////////////////////////////////////////////////////////////// 690 // 710 // 691 G4Fragment *G4WilsonAbrasionModel::GetAbradedN 711 G4Fragment *G4WilsonAbrasionModel::GetAbradedNucleons (G4int Dabr, G4double A, 692 G4double Z, G4double r) 712 G4double Z, G4double r) 693 { 713 { 694 // 714 // 695 // 715 // 696 // Initialise variables. tau is the Fermi rad 716 // Initialise variables. tau is the Fermi radius of the nucleus. The variables 697 // p..., C... and gamma are used to help sampl << 717 // p..., C... and g(amma) are used to help sample the secondary nucleon 698 // spectrum. 718 // spectrum. 699 // 719 // 700 720 701 G4double pK = hbarc * G4Pow::GetInstance() << 721 G4double pK = hbarc * std::pow(9.0 * pi / 4.0 * A, third) / (1.29 * r); 702 if (A <= 24.0) pK *= -0.229*G4Pow::GetInstan << 722 if (A <= 24.0) pK *= -0.229*std::pow(A,third) + 1.62; 703 G4double pKsq = pK * pK; 723 G4double pKsq = pK * pK; 704 G4double p1sq = 2.0/5.0 * pKsq; 724 G4double p1sq = 2.0/5.0 * pKsq; 705 G4double p2sq = 6.0/5.0 * pKsq; 725 G4double p2sq = 6.0/5.0 * pKsq; 706 G4double p3sq = 500.0 * 500.0; 726 G4double p3sq = 500.0 * 500.0; 707 G4double C1 = 1.0; 727 G4double C1 = 1.0; 708 G4double C2 = 0.03; 728 G4double C2 = 0.03; 709 G4double C3 = 0.0002; 729 G4double C3 = 0.0002; 710 G4double gamma = 90.0 * MeV; << 730 G4double g = 90.0 * MeV; 711 G4double maxn = C1 + C2 + C3; 731 G4double maxn = C1 + C2 + C3; 712 // 732 // 713 // 733 // 714 // initialise the number of secondary nucleons 734 // initialise the number of secondary nucleons abraded to zero, and initially set 715 // the type of nucleon abraded to proton ... j 735 // the type of nucleon abraded to proton ... just for now. 716 // 736 // 717 G4double Aabr = 0.0; 737 G4double Aabr = 0.0; 718 G4double Zabr = 0.0; 738 G4double Zabr = 0.0; 719 G4ParticleDefinition *typeNucleon = G4Proton 739 G4ParticleDefinition *typeNucleon = G4Proton::ProtonDefinition(); 720 G4DynamicParticle *dynamicNucleon = nullptr; << 740 G4DynamicParticle *dynamicNucleon = NULL; 721 G4ParticleMomentum pabr(0.0, 0.0, 0.0); 741 G4ParticleMomentum pabr(0.0, 0.0, 0.0); 722 // 742 // 723 // 743 // 724 // Now go through each abraded nucleon and sam 744 // Now go through each abraded nucleon and sample type, spectrum and angle. 725 // 745 // 726 G4bool isForLoopExitAnticipated = false; << 746 for (G4int i=0; i<Dabr; i++) 727 for (G4int i=0; i<Dabr; ++i) << 728 { 747 { 729 // 748 // 730 // 749 // 731 // Sample the nucleon momentum distribution by 750 // Sample the nucleon momentum distribution by simple rejection techniques. We 732 // reject values of p == 0.0 since this causes 751 // reject values of p == 0.0 since this causes bad behaviour in the sinh term. 733 // 752 // 734 G4double p = 0.0; 753 G4double p = 0.0; 735 G4bool found = false; 754 G4bool found = false; 736 const G4int maxNumberOfLoops = 100000; << 755 while (!found) 737 G4int loopCounter = -1; << 738 while (!found && ++loopCounter < maxNumber << 739 { 756 { 740 while (p <= 0.0) p = npK * pK * G4Unifor << 757 while (p <= 0.0) p = npK * pK * G4UniformRand(); 741 G4double psq = p * p; 758 G4double psq = p * p; 742 found = maxn * G4UniformRand() < C1*G4Ex << 759 found = maxn * G4UniformRand() < C1*std::exp(-psq/p1sq/2.0) + 743 C2*G4Exp(-psq/p2sq/2.0) + C3*G4Exp(-ps << 760 C2*std::exp(-psq/p2sq/2.0) + C3*std::exp(-psq/p3sq/2.0) + p/g/std::sinh(p/g); 744 } << 745 if ( loopCounter >= maxNumberOfLoops ) << 746 { << 747 isForLoopExitAnticipated = true; << 748 break; << 749 } 761 } 750 // 762 // 751 // 763 // 752 // Determine the type of particle abraded. Ca 764 // Determine the type of particle abraded. Can only be proton or neutron, 753 // and the probability is determine to be prop 765 // and the probability is determine to be proportional to the ratio as found 754 // in the nucleus at each stage. 766 // in the nucleus at each stage. 755 // 767 // 756 G4double prob = (Z-Zabr)/(A-Aabr); 768 G4double prob = (Z-Zabr)/(A-Aabr); 757 if (G4UniformRand()<prob) 769 if (G4UniformRand()<prob) 758 { 770 { 759 Zabr++; 771 Zabr++; 760 typeNucleon = G4Proton::ProtonDefinition 772 typeNucleon = G4Proton::ProtonDefinition(); 761 } 773 } 762 else 774 else 763 typeNucleon = G4Neutron::NeutronDefiniti 775 typeNucleon = G4Neutron::NeutronDefinition(); 764 Aabr++; 776 Aabr++; 765 // 777 // 766 // 778 // 767 // The angular distribution of the secondary n 779 // The angular distribution of the secondary nucleons is approximated to an 768 // isotropic distribution in the rest frame of 780 // isotropic distribution in the rest frame of the nucleus (this will be Lorentz 769 // boosted later. 781 // boosted later. 770 // 782 // 771 G4double costheta = 2.*G4UniformRand()-1.0 783 G4double costheta = 2.*G4UniformRand()-1.0; 772 G4double sintheta = std::sqrt((1.0 - costh 784 G4double sintheta = std::sqrt((1.0 - costheta)*(1.0 + costheta)); 773 G4double phi = 2.0*pi*G4UniformRand() 785 G4double phi = 2.0*pi*G4UniformRand()*rad; 774 G4ThreeVector direction(sintheta*std::cos( 786 G4ThreeVector direction(sintheta*std::cos(phi),sintheta*std::sin(phi),costheta); 775 G4double nucleonMass = typeNucleon->GetPDG 787 G4double nucleonMass = typeNucleon->GetPDGMass(); 776 G4double E = std::sqrt(p*p + nuc 788 G4double E = std::sqrt(p*p + nucleonMass*nucleonMass)-nucleonMass; 777 dynamicNucleon = new G4DynamicParticle(typ 789 dynamicNucleon = new G4DynamicParticle(typeNucleon,direction,E); 778 theParticleChange.AddSecondary (dynamicNuc << 790 theParticleChange.AddSecondary (dynamicNucleon); 779 pabr += p*direction; 791 pabr += p*direction; 780 } 792 } 781 // 793 // 782 // 794 // 783 // Next determine the details of the nuclear p 795 // Next determine the details of the nuclear prefragment .. that is if there 784 // is one or more protons in the residue. (No 796 // is one or more protons in the residue. (Note that the 1 eV in the total 785 // energy is a safety factor to avoid any poss 797 // energy is a safety factor to avoid any possibility of negative rest mass 786 // energy.) 798 // energy.) 787 // 799 // 788 G4Fragment *fragment = nullptr; << 800 G4Fragment *fragment = NULL; 789 if ( ! isForLoopExitAnticipated && Z-Zabr>=1 << 801 if (Z-Zabr>=1.0) 790 { 802 { 791 G4double ionMass = G4ParticleTable::GetPar 803 G4double ionMass = G4ParticleTable::GetParticleTable()->GetIonTable()-> 792 GetIonMass(G4lrint(Z-Za 804 GetIonMass(G4lrint(Z-Zabr),G4lrint(A-Aabr)); 793 G4double E = std::sqrt(pabr.mag2() + 805 G4double E = std::sqrt(pabr.mag2() + ionMass*ionMass); 794 G4LorentzVector lorentzVector = G4LorentzV 806 G4LorentzVector lorentzVector = G4LorentzVector(-pabr, E + 1.0*eV); 795 fragment = 807 fragment = 796 new G4Fragment((G4int) (A-Aabr), (G4int) 808 new G4Fragment((G4int) (A-Aabr), (G4int) (Z-Zabr), lorentzVector); 797 } 809 } 798 810 799 return fragment; 811 return fragment; 800 } 812 } 801 ////////////////////////////////////////////// 813 //////////////////////////////////////////////////////////////////////////////// 802 // 814 // 803 G4double G4WilsonAbrasionModel::GetNucleonIndu 815 G4double G4WilsonAbrasionModel::GetNucleonInducedExcitation 804 (G4double rP, G4double rT, G4double r) 816 (G4double rP, G4double rT, G4double r) 805 { 817 { 806 // 818 // 807 // 819 // 808 // Initialise variables. 820 // Initialise variables. 809 // 821 // 810 G4double Cl = 0.0; 822 G4double Cl = 0.0; 811 G4double rPsq = rP * rP; 823 G4double rPsq = rP * rP; 812 G4double rTsq = rT * rT; 824 G4double rTsq = rT * rT; 813 G4double rsq = r * r; 825 G4double rsq = r * r; 814 // 826 // 815 // 827 // 816 // Depending upon the impact parameter, a diff 828 // Depending upon the impact parameter, a different form of the chord length is 817 // is used. 829 // is used. 818 // 830 // 819 if (r > rT) Cl = 2.0*std::sqrt(rPsq + 2.0*r* 831 if (r > rT) Cl = 2.0*std::sqrt(rPsq + 2.0*r*rT - rsq - rTsq); 820 else Cl = 2.0*rP; 832 else Cl = 2.0*rP; 821 // 833 // 822 // 834 // 823 // The next lines have been changed to include 835 // The next lines have been changed to include a "catch" to make sure if the 824 // projectile and target are too close, Ct is 836 // projectile and target are too close, Ct is set to twice rP or twice rT. 825 // Otherwise the standard Wilson algorithm sho 837 // Otherwise the standard Wilson algorithm should work fine. 826 // PRT 20091023. 838 // PRT 20091023. 827 // 839 // 828 G4double Ct = 0.0; 840 G4double Ct = 0.0; 829 if (rT > rP && rsq < rTsq - rPsq) Ct = 841 if (rT > rP && rsq < rTsq - rPsq) Ct = 2.0 * rP; 830 else if (rP > rT && rsq < rPsq - rTsq) Ct = 842 else if (rP > rT && rsq < rPsq - rTsq) Ct = 2.0 * rT; 831 else { 843 else { 832 G4double bP = (rPsq+rsq-rTsq)/2.0/r; 844 G4double bP = (rPsq+rsq-rTsq)/2.0/r; 833 G4double x = rPsq - bP*bP; 845 G4double x = rPsq - bP*bP; 834 if (x < 0.0) { 846 if (x < 0.0) { 835 G4cerr <<"############################## 847 G4cerr <<"########################################" 836 <<"############################## 848 <<"########################################" 837 <<G4endl; 849 <<G4endl; 838 G4cerr <<"ERROR IN G4WilsonAbrasionModel 850 G4cerr <<"ERROR IN G4WilsonAbrasionModel::GetNucleonInducedExcitation" 839 <<G4endl; 851 <<G4endl; 840 G4cerr <<"rPsq - bP*bP < 0.0 and cannot 852 G4cerr <<"rPsq - bP*bP < 0.0 and cannot be square-rooted" <<G4endl; 841 G4cerr <<"Set to zero instead" <<G4endl; 853 G4cerr <<"Set to zero instead" <<G4endl; 842 G4cerr <<"############################## 854 G4cerr <<"########################################" 843 <<"############################## 855 <<"########################################" 844 <<G4endl; 856 <<G4endl; 845 } 857 } 846 Ct = 2.0*std::sqrt(x); 858 Ct = 2.0*std::sqrt(x); 847 } 859 } 848 860 849 G4double Ex = 13.0 * Cl / fermi; 861 G4double Ex = 13.0 * Cl / fermi; 850 if (Ct > 1.5*fermi) 862 if (Ct > 1.5*fermi) 851 Ex += 13.0 * Cl / fermi /3.0 * (Ct/fermi - 863 Ex += 13.0 * Cl / fermi /3.0 * (Ct/fermi - 1.5); 852 864 853 return Ex; 865 return Ex; 854 } 866 } 855 ////////////////////////////////////////////// 867 //////////////////////////////////////////////////////////////////////////////// 856 // 868 // 857 void G4WilsonAbrasionModel::SetUseAblation (G4 869 void G4WilsonAbrasionModel::SetUseAblation (G4bool useAblation1) 858 { 870 { 859 if (useAblation != useAblation1) 871 if (useAblation != useAblation1) 860 { 872 { 861 useAblation = useAblation1; 873 useAblation = useAblation1; >> 874 delete theExcitationHandler; >> 875 delete theExcitationHandlerx; >> 876 theExcitationHandler = new G4ExcitationHandler; >> 877 theExcitationHandlerx = new G4ExcitationHandler; 862 if (useAblation) 878 if (useAblation) 863 { 879 { 864 theAblation = new G4WilsonAblationModel; 880 theAblation = new G4WilsonAblationModel; 865 theAblation->SetVerboseLevel(verboseLeve 881 theAblation->SetVerboseLevel(verboseLevel); 866 theExcitationHandler->SetEvaporation(the 882 theExcitationHandler->SetEvaporation(theAblation); >> 883 theExcitationHandlerx->SetEvaporation(theAblation); 867 } 884 } 868 else 885 else 869 { 886 { 870 delete theExcitationHandler; << 887 theAblation = NULL; 871 theAblation = nullp << 888 G4Evaporation * theEvaporation = new G4Evaporation; 872 theExcitationHandler = new G4Excitation << 889 G4FermiBreakUp * theFermiBreakUp = new G4FermiBreakUp; >> 890 G4StatMF * theMF = new G4StatMF; >> 891 theExcitationHandler->SetEvaporation(theEvaporation); >> 892 theExcitationHandler->SetFermiModel(theFermiBreakUp); >> 893 theExcitationHandler->SetMultiFragmentation(theMF); >> 894 theExcitationHandler->SetMaxAandZForFermiBreakUp(12, 6); >> 895 theExcitationHandler->SetMinEForMultiFrag(5.0*MeV); >> 896 >> 897 theEvaporation = new G4Evaporation; >> 898 theFermiBreakUp = new G4FermiBreakUp; >> 899 theExcitationHandlerx->SetEvaporation(theEvaporation); >> 900 theExcitationHandlerx->SetFermiModel(theFermiBreakUp); >> 901 theExcitationHandlerx->SetMaxAandZForFermiBreakUp(12, 6); 873 } 902 } 874 } 903 } 875 return; 904 return; 876 } 905 } 877 ////////////////////////////////////////////// 906 //////////////////////////////////////////////////////////////////////////////// 878 // 907 // 879 void G4WilsonAbrasionModel::PrintWelcomeMessag 908 void G4WilsonAbrasionModel::PrintWelcomeMessage () 880 { 909 { 881 G4cout <<G4endl; 910 G4cout <<G4endl; 882 G4cout <<" ********************************* 911 G4cout <<" *****************************************************************" 883 <<G4endl; 912 <<G4endl; 884 G4cout <<" Nuclear abrasion model for nuclea 913 G4cout <<" Nuclear abrasion model for nuclear-nuclear interactions activated" 885 <<G4endl; 914 <<G4endl; 886 G4cout <<" (Written by QinetiQ Ltd for the E 915 G4cout <<" (Written by QinetiQ Ltd for the European Space Agency)" 887 <<G4endl; 916 <<G4endl; 888 G4cout <<" ********************************* 917 G4cout <<" *****************************************************************" 889 <<G4endl; 918 <<G4endl; 890 G4cout << G4endl; 919 G4cout << G4endl; 891 920 892 return; 921 return; 893 } 922 } 894 ////////////////////////////////////////////// 923 //////////////////////////////////////////////////////////////////////////////// 895 // 924 // 896 925