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: G4WilsonAblationModel. 38 // MODULE: G4WilsonAblationModel.cc 39 // 39 // 40 // Version: 1.0 << 40 // Version: B.1 41 // Date: 08/12/2009 << 41 // Date: 15/04/04 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 // 08 December 2009, P R Truscott, QinetiQ Ltd << 59 // Ver 1.0 << 60 // Updated as a result of changes in the G4Eva << 61 // affect mostly SelectSecondariesByEvaporatio << 62 // associated with the evaporation model which << 63 // OPTxs to select the inverse cross-sectio << 64 // OPTxs = 0 => Dostrovski's parameter << 65 // OPTxs = 1 or 2 => Chatterjee's paramater << 66 // OPTxs = 3 or 4 => Kalbach's parameteriza << 67 // useSICB => use superimposed Coulo << 68 // sections << 69 // Other problem found with G4Fragment definit << 70 // **G4ParticleDefinition**. This does not al << 71 // fragment for some reason. Now the fragment << 72 // G4Fragment *fragment = new G4Fragment(A, << 73 // to avoid this quirk. Bug found in SelectSe << 74 // equated to evapType[i] whereas previously i << 75 // << 76 // 06 August 2015, A. Ribon, CERN << 77 // Migrated std::exp and std::pow to the faste << 78 // << 79 // 09 June 2017, C. Mancini Terracciano, INFN << 80 // Fixed bug on the initialization of Photon E << 81 // << 82 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 83 ////////////////////////////////////////////// 59 //////////////////////////////////////////////////////////////////////////////// 84 // 60 // 85 #include <iomanip> << 86 #include <numeric> << 87 << 88 #include "G4WilsonAblationModel.hh" 61 #include "G4WilsonAblationModel.hh" 89 #include "G4PhysicalConstants.hh" << 90 #include "G4SystemOfUnits.hh" << 91 #include "Randomize.hh" 62 #include "Randomize.hh" 92 #include "G4ParticleTable.hh" 63 #include "G4ParticleTable.hh" 93 #include "G4IonTable.hh" 64 #include "G4IonTable.hh" 94 #include "G4Alpha.hh" 65 #include "G4Alpha.hh" 95 #include "G4He3.hh" 66 #include "G4He3.hh" 96 #include "G4Triton.hh" 67 #include "G4Triton.hh" 97 #include "G4Deuteron.hh" 68 #include "G4Deuteron.hh" 98 #include "G4Proton.hh" 69 #include "G4Proton.hh" 99 #include "G4Neutron.hh" 70 #include "G4Neutron.hh" 100 #include "G4AlphaEvaporationChannel.hh" 71 #include "G4AlphaEvaporationChannel.hh" 101 #include "G4He3EvaporationChannel.hh" 72 #include "G4He3EvaporationChannel.hh" 102 #include "G4TritonEvaporationChannel.hh" 73 #include "G4TritonEvaporationChannel.hh" 103 #include "G4DeuteronEvaporationChannel.hh" 74 #include "G4DeuteronEvaporationChannel.hh" 104 #include "G4ProtonEvaporationChannel.hh" 75 #include "G4ProtonEvaporationChannel.hh" 105 #include "G4NeutronEvaporationChannel.hh" 76 #include "G4NeutronEvaporationChannel.hh" 106 #include "G4PhotonEvaporation.hh" << 107 #include "G4LorentzVector.hh" 77 #include "G4LorentzVector.hh" 108 #include "G4VEvaporationChannel.hh" 78 #include "G4VEvaporationChannel.hh" 109 79 110 #include "G4Exp.hh" << 80 #include <iomanip> 111 #include "G4Pow.hh" << 81 #include <numeric> 112 << 113 #include "G4PhysicsModelCatalog.hh" << 114 << 115 ////////////////////////////////////////////// 82 //////////////////////////////////////////////////////////////////////////////// 116 // 83 // 117 G4WilsonAblationModel::G4WilsonAblationModel() 84 G4WilsonAblationModel::G4WilsonAblationModel() 118 { 85 { 119 // 86 // 120 // 87 // 121 // Send message to stdout to advise that the G 88 // Send message to stdout to advise that the G4Abrasion model is being used. 122 // 89 // 123 PrintWelcomeMessage(); 90 PrintWelcomeMessage(); 124 // 91 // 125 // 92 // 126 // Set the default verbose level to 0 - no out 93 // Set the default verbose level to 0 - no output. 127 // 94 // 128 verboseLevel = 0; 95 verboseLevel = 0; 129 // 96 // 130 // 97 // 131 // Set the binding energy per nucleon .... did 98 // Set the binding energy per nucleon .... did I mention that this is a crude 132 // model for nuclear de-excitation? 99 // model for nuclear de-excitation? 133 // 100 // 134 B = 10.0 * MeV; 101 B = 10.0 * MeV; 135 // 102 // 136 // 103 // 137 // It is possuble to switch off secondary part 104 // It is possuble to switch off secondary particle production (other than the 138 // final nuclear fragment). The default is on 105 // final nuclear fragment). The default is on. 139 // 106 // 140 produceSecondaries = true; 107 produceSecondaries = true; 141 // 108 // 142 // 109 // 143 // Now we need to define the decay modes. We' 110 // Now we need to define the decay modes. We're using the G4Evaporation model 144 // to help determine the kinematics of the dec 111 // to help determine the kinematics of the decay. 145 // 112 // 146 nFragTypes = 6; 113 nFragTypes = 6; 147 fragType[0] = G4Alpha::Alpha(); 114 fragType[0] = G4Alpha::Alpha(); 148 fragType[1] = G4He3::He3(); 115 fragType[1] = G4He3::He3(); 149 fragType[2] = G4Triton::Triton(); 116 fragType[2] = G4Triton::Triton(); 150 fragType[3] = G4Deuteron::Deuteron(); 117 fragType[3] = G4Deuteron::Deuteron(); 151 fragType[4] = G4Proton::Proton(); 118 fragType[4] = G4Proton::Proton(); 152 fragType[5] = G4Neutron::Neutron(); 119 fragType[5] = G4Neutron::Neutron(); 153 for(G4int i=0; i<200; ++i) { fSig[i] = 0.0; << 154 // 120 // 155 // 121 // 156 // Set verboseLevel default to no output. 122 // Set verboseLevel default to no output. 157 // 123 // 158 verboseLevel = 0; 124 verboseLevel = 0; 159 theChannelFactory = new G4EvaporationFactory << 160 theChannels = theChannelFactory->GetChannel( << 161 // << 162 // << 163 // Set defaults for evaporation classes. Thes << 164 // "set" methods. << 165 // << 166 OPTxs = 3; << 167 useSICB = false; << 168 fragmentVector = 0; << 169 << 170 secID = G4PhysicsModelCatalog::GetModelID("m << 171 } 125 } 172 ////////////////////////////////////////////// 126 //////////////////////////////////////////////////////////////////////////////// 173 // 127 // 174 G4WilsonAblationModel::~G4WilsonAblationModel( 128 G4WilsonAblationModel::~G4WilsonAblationModel() 175 {} << 129 {;} 176 << 177 ////////////////////////////////////////////// 130 //////////////////////////////////////////////////////////////////////////////// 178 // 131 // 179 G4FragmentVector *G4WilsonAblationModel::Break 132 G4FragmentVector *G4WilsonAblationModel::BreakItUp 180 (const G4Fragment &theNucleus) 133 (const G4Fragment &theNucleus) 181 { 134 { 182 // 135 // 183 // 136 // 184 // Initilise the pointer to the G4FragmentVect 137 // Initilise the pointer to the G4FragmentVector used to return the information 185 // about the breakup. 138 // about the breakup. 186 // 139 // 187 fragmentVector = new G4FragmentVector; 140 fragmentVector = new G4FragmentVector; 188 fragmentVector->clear(); 141 fragmentVector->clear(); 189 // 142 // 190 // 143 // 191 // Get the A, Z and excitation of the nucleus. 144 // Get the A, Z and excitation of the nucleus. 192 // 145 // 193 G4int A = theNucleus.GetA_asInt(); << 146 G4int A = (G4int) theNucleus.GetA(); 194 G4int Z = theNucleus.GetZ_asInt(); << 147 G4int Z = (G4int) theNucleus.GetZ(); 195 G4double ex = theNucleus.GetExcitationEnergy 148 G4double ex = theNucleus.GetExcitationEnergy(); 196 if (verboseLevel >= 2) 149 if (verboseLevel >= 2) 197 { 150 { 198 G4cout <<"oooooooooooooooooooooooooooooooo 151 G4cout <<"oooooooooooooooooooooooooooooooooooooooo" 199 <<"oooooooooooooooooooooooooooooooo 152 <<"oooooooooooooooooooooooooooooooooooooooo" 200 <<G4endl; 153 <<G4endl; 201 G4cout.precision(6); 154 G4cout.precision(6); 202 G4cout <<"IN G4WilsonAblationModel" <<G4en 155 G4cout <<"IN G4WilsonAblationModel" <<G4endl; 203 G4cout <<"Initial prefragment A=" <<A 156 G4cout <<"Initial prefragment A=" <<A 204 <<", Z=" <<Z 157 <<", Z=" <<Z 205 <<", excitation energy = " <<ex/MeV 158 <<", excitation energy = " <<ex/MeV <<" MeV" 206 <<G4endl; 159 <<G4endl; 207 } 160 } 208 // 161 // 209 // 162 // 210 // Check that there is a nucleus to speak of. 163 // Check that there is a nucleus to speak of. It's possible there isn't one 211 // or its just a proton or neutron. In either 164 // or its just a proton or neutron. In either case, the excitation energy 212 // (from the Lorentz vector) is not used. 165 // (from the Lorentz vector) is not used. 213 // 166 // 214 if (A == 0) 167 if (A == 0) 215 { 168 { 216 if (verboseLevel >= 2) 169 if (verboseLevel >= 2) 217 { 170 { 218 G4cout <<"No nucleus to decay" <<G4endl; 171 G4cout <<"No nucleus to decay" <<G4endl; 219 G4cout <<"oooooooooooooooooooooooooooooo 172 G4cout <<"oooooooooooooooooooooooooooooooooooooooo" 220 <<"oooooooooooooooooooooooooooooo 173 <<"oooooooooooooooooooooooooooooooooooooooo" 221 <<G4endl; 174 <<G4endl; 222 } 175 } 223 return fragmentVector; 176 return fragmentVector; 224 } 177 } 225 else if (A == 1) 178 else if (A == 1) 226 { 179 { 227 G4LorentzVector lorentzVector = theNucleus 180 G4LorentzVector lorentzVector = theNucleus.GetMomentum(); 228 lorentzVector.setE(lorentzVector.e()-ex+10 181 lorentzVector.setE(lorentzVector.e()-ex+10.0*eV); 229 if (Z == 0) 182 if (Z == 0) 230 { 183 { 231 G4Fragment *fragment = new G4Fragment(lo 184 G4Fragment *fragment = new G4Fragment(lorentzVector,G4Neutron::Neutron()); 232 if (fragment != nullptr) { fragment->Set << 233 fragmentVector->push_back(fragment); 185 fragmentVector->push_back(fragment); 234 } 186 } 235 else 187 else 236 { 188 { 237 G4Fragment *fragment = new G4Fragment(lo 189 G4Fragment *fragment = new G4Fragment(lorentzVector,G4Proton::Proton()); 238 if (fragment != nullptr) { fragment->Set << 239 fragmentVector->push_back(fragment); 190 fragmentVector->push_back(fragment); 240 } 191 } 241 if (verboseLevel >= 2) 192 if (verboseLevel >= 2) 242 { 193 { 243 G4cout <<"Final fragment is in fact only 194 G4cout <<"Final fragment is in fact only a nucleon) :" <<G4endl; 244 G4cout <<(*fragmentVector)[0] <<G4endl; 195 G4cout <<(*fragmentVector)[0] <<G4endl; 245 G4cout <<"oooooooooooooooooooooooooooooo 196 G4cout <<"oooooooooooooooooooooooooooooooooooooooo" 246 <<"oooooooooooooooooooooooooooooo 197 <<"oooooooooooooooooooooooooooooooooooooooo" 247 <<G4endl; 198 <<G4endl; 248 } 199 } 249 return fragmentVector; 200 return fragmentVector; 250 } 201 } 251 // 202 // 252 // 203 // 253 // Then the number of nucleons ablated (either 204 // Then the number of nucleons ablated (either as nucleons or light nuclear 254 // fragments) is based on a simple argument fo 205 // fragments) is based on a simple argument for the binding energy per nucleon. 255 // 206 // 256 G4int DAabl = (G4int) (ex / B); 207 G4int DAabl = (G4int) (ex / B); 257 if (DAabl > A) DAabl = A; 208 if (DAabl > A) DAabl = A; 258 // The following lines are no longer accurate << 209 if (verboseLevel >= 2) 259 // if (verboseLevel >= 2) << 210 G4cout <<"Number of nucleons ejected = " <<DAabl <<G4endl; 260 // G4cout <<"Number of nucleons ejected = " << 261 211 262 // 212 // 263 // 213 // 264 // Determine the nuclear fragment from the abl 214 // Determine the nuclear fragment from the ablation process by sampling the 265 // Rudstam equation. 215 // Rudstam equation. 266 // 216 // 267 G4int AF = A - DAabl; 217 G4int AF = A - DAabl; 268 G4int ZF = 0; 218 G4int ZF = 0; 269 << 270 if (AF > 0) 219 if (AF > 0) 271 { 220 { 272 G4Pow* g4calc = G4Pow::GetInstance(); << 221 G4double AFd = static_cast<G4double>(AF); 273 G4double AFd = (G4double) AF; << 222 G4double R = 11.8 / std::pow(AFd, 0.45); 274 G4double R = 11.8 / g4calc->powZ(AF, 0.45) << 223 G4int minZ = Z - DAabl; 275 G4int minZ = std::max(1, Z - DAabl); << 224 if (minZ <= 0) minZ = 1; 276 // 225 // 277 // 226 // 278 // Here we define an integral probability dist 227 // Here we define an integral probability distribution based on the Rudstam 279 // equation assuming a constant AF. 228 // equation assuming a constant AF. 280 // 229 // 281 G4int zmax = std::min(199, Z); << 230 G4double sig[100]; 282 G4double sum = 0.0; 231 G4double sum = 0.0; 283 for (ZF=minZ; ZF<=zmax; ++ZF) << 232 for (G4int ii=minZ; ii<= Z; ii++) 284 { 233 { 285 sum += G4Exp(-R*g4calc->powA(std::abs(ZF << 234 sum += std::exp(-R*std::pow(std::abs(ii - 0.486*AFd + 3.8E-04*AFd*AFd),1.5)); 286 fSig[ZF] = sum; << 235 sig[ii] = sum; 287 } 236 } 288 // 237 // 289 // 238 // 290 // Now sample that distribution to determine a 239 // Now sample that distribution to determine a value for ZF. 291 // 240 // 292 sum *= G4UniformRand(); << 241 G4double xi = G4UniformRand(); 293 for (ZF=minZ; ZF<=zmax; ++ZF) { << 242 G4int iz = minZ; 294 if(sum <= fSig[ZF]) { break; } << 243 G4bool found = false; 295 } << 244 while (iz <= Z && !found) >> 245 { >> 246 found = (xi <= sig[iz]/sum); >> 247 if (!found) iz++; >> 248 } >> 249 if (iz > Z) >> 250 ZF = Z; >> 251 else >> 252 ZF = iz; 296 } 253 } 297 G4int DZabl = Z - ZF; 254 G4int DZabl = Z - ZF; >> 255 if (verboseLevel >= 2) >> 256 G4cout <<"Final fragment A=" <<AF >> 257 <<", Z=" <<ZF >> 258 <<G4endl; 298 // 259 // 299 // 260 // 300 // Now determine the nucleons or nuclei which 261 // Now determine the nucleons or nuclei which have bee ablated. The preference 301 // is for the production of alphas, then other 262 // is for the production of alphas, then other nuclei in order of decreasing 302 // binding energy. The energies assigned to th 263 // binding energy. The energies assigned to the products of the decay are 303 // provisional for the moment (the 10eV is jus 264 // provisional for the moment (the 10eV is just to avoid errors with negative 304 // excitation energies due to rounding). 265 // excitation energies due to rounding). 305 // 266 // 306 G4double totalEpost = 0.0; 267 G4double totalEpost = 0.0; 307 evapType.clear(); 268 evapType.clear(); 308 for (G4int ift=0; ift<nFragTypes; ift++) 269 for (G4int ift=0; ift<nFragTypes; ift++) 309 { 270 { 310 G4ParticleDefinition *type = fragType[ift] 271 G4ParticleDefinition *type = fragType[ift]; 311 G4double n = std::floor((G4double) DAabl 272 G4double n = std::floor((G4double) DAabl / type->GetBaryonNumber() + 1.0E-10); 312 G4double n1 = 1.0E+10; 273 G4double n1 = 1.0E+10; 313 if (fragType[ift]->GetPDGCharge() > 0.0) 274 if (fragType[ift]->GetPDGCharge() > 0.0) 314 n1 = std::floor((G4double) DZabl / type- 275 n1 = std::floor((G4double) DZabl / type->GetPDGCharge() + 1.0E-10); 315 if (n > n1) n = n1; 276 if (n > n1) n = n1; 316 if (n > 0.0) 277 if (n > 0.0) 317 { 278 { 318 G4double mass = type->GetPDGMass(); 279 G4double mass = type->GetPDGMass(); 319 for (G4int j=0; j<(G4int) n; j++) 280 for (G4int j=0; j<(G4int) n; j++) 320 { 281 { 321 totalEpost += mass; 282 totalEpost += mass; 322 evapType.push_back(type); 283 evapType.push_back(type); 323 } 284 } 324 DAabl -= (G4int) (n * type->GetBaryonNum 285 DAabl -= (G4int) (n * type->GetBaryonNumber() + 1.0E-10); 325 DZabl -= (G4int) (n * type->GetPDGCharge 286 DZabl -= (G4int) (n * type->GetPDGCharge() + 1.0E-10); >> 287 if (verboseLevel >= 2) >> 288 G4cout <<"Particle type: " <<std::setw(10) <<type->GetParticleName() >> 289 <<", number of particles emitted = " <<n >> 290 <<G4endl; 326 } 291 } 327 } 292 } 328 // 293 // 329 // 294 // 330 // Determine the properties of the final nucle << 295 // Determine the properties of the final nuclear fragment. 331 // the final fragment is predicted to have a n << 332 // really it's the particle last in the vector << 333 // final fragment. Therefore delete this from << 334 // case. << 335 // 296 // 336 G4double massFinalFrag = 0.0; 297 G4double massFinalFrag = 0.0; 337 if (AF > 0) << 298 if (AF > 0.0) 338 massFinalFrag = G4ParticleTable::GetPartic 299 massFinalFrag = G4ParticleTable::GetParticleTable()->GetIonTable()-> 339 GetIonMass(ZF,AF); 300 GetIonMass(ZF,AF); 340 else << 341 { << 342 G4ParticleDefinition *type = evapType[evap << 343 AF = type->GetBary << 344 ZF = (G4int) (type << 345 evapType.erase(evapType.end()-1); << 346 } << 347 totalEpost += massFinalFrag; 301 totalEpost += massFinalFrag; 348 // 302 // 349 // 303 // 350 // Provide verbose output on the nuclear fragm << 351 // << 352 if (verboseLevel >= 2) << 353 { << 354 G4cout <<"Final fragment A=" <<AF << 355 <<", Z=" <<ZF << 356 <<G4endl; << 357 for (G4int ift=0; ift<nFragTypes; ift++) << 358 { << 359 G4ParticleDefinition *type = fragType[if << 360 G4long n = std::count(evapType.cbegin(), << 361 if (n > 0) << 362 G4cout <<"Particle type: " <<std::setw << 363 <<", number of particles emitte << 364 } << 365 } << 366 // << 367 // Add the total energy from the fragment. No 304 // Add the total energy from the fragment. Note that the fragment is assumed 368 // to be de-excited and does not undergo photo 305 // to be de-excited and does not undergo photo-evaporation .... I did mention 369 // this is a bit of a crude model? 306 // this is a bit of a crude model? 370 // 307 // 371 G4double massPreFrag = theNucleus.GetGr 308 G4double massPreFrag = theNucleus.GetGroundStateMass(); 372 G4double totalEpre = massPreFrag + ex 309 G4double totalEpre = massPreFrag + ex; 373 G4double excess = totalEpre - tota 310 G4double excess = totalEpre - totalEpost; 374 // G4Fragment *resultNucleus(theNucleus); 311 // G4Fragment *resultNucleus(theNucleus); 375 G4Fragment *resultNucleus = new G4Fragment(A 312 G4Fragment *resultNucleus = new G4Fragment(A, Z, theNucleus.GetMomentum()); 376 G4ThreeVector boost(0.0,0.0,0.0); 313 G4ThreeVector boost(0.0,0.0,0.0); 377 std::size_t nEvap = 0; << 314 G4int nEvap = 0; 378 if (produceSecondaries && evapType.size()>0) 315 if (produceSecondaries && evapType.size()>0) 379 { 316 { 380 if (excess > 0.0) 317 if (excess > 0.0) 381 { 318 { 382 SelectSecondariesByEvaporation (resultNu 319 SelectSecondariesByEvaporation (resultNucleus); 383 nEvap = fragmentVector->size(); 320 nEvap = fragmentVector->size(); 384 boost = resultNucleus->GetMomentum().fin 321 boost = resultNucleus->GetMomentum().findBoostToCM(); 385 if (evapType.size() > 0) 322 if (evapType.size() > 0) 386 SelectSecondariesByDefault (boost); 323 SelectSecondariesByDefault (boost); 387 } 324 } 388 else 325 else 389 SelectSecondariesByDefault(G4ThreeVector 326 SelectSecondariesByDefault(G4ThreeVector(0.0,0.0,0.0)); 390 } 327 } 391 << 392 if (AF > 0) 328 if (AF > 0) 393 { 329 { 394 G4double mass = G4ParticleTable::GetPartic 330 G4double mass = G4ParticleTable::GetParticleTable()->GetIonTable()-> 395 GetIonMass(ZF,AF); 331 GetIonMass(ZF,AF); 396 G4double e = mass + 10.0*eV; 332 G4double e = mass + 10.0*eV; 397 G4double p = std::sqrt(e*e-mass*mass); 333 G4double p = std::sqrt(e*e-mass*mass); 398 G4ThreeVector direction(0.0,0.0,1.0); 334 G4ThreeVector direction(0.0,0.0,1.0); 399 G4LorentzVector lorentzVector = G4LorentzV 335 G4LorentzVector lorentzVector = G4LorentzVector(direction*p, e); 400 lorentzVector.boost(-boost); 336 lorentzVector.boost(-boost); 401 G4Fragment* frag = new G4Fragment(AF, ZF, << 337 *resultNucleus = G4Fragment(AF, ZF, lorentzVector); 402 if (frag != nullptr) { frag->SetCreatorMod << 338 fragmentVector->push_back(resultNucleus); 403 fragmentVector->push_back(frag); << 404 } 339 } 405 delete resultNucleus; << 406 // 340 // 407 // 341 // 408 // Provide verbose output on the ablation prod 342 // Provide verbose output on the ablation products if requested. 409 // 343 // 410 if (verboseLevel >= 2) 344 if (verboseLevel >= 2) 411 { 345 { 412 if (nEvap > 0) 346 if (nEvap > 0) 413 { 347 { 414 G4cout <<"----------------------" <<G4en 348 G4cout <<"----------------------" <<G4endl; 415 G4cout <<"Evaporated particles :" <<G4en 349 G4cout <<"Evaporated particles :" <<G4endl; 416 G4cout <<"----------------------" <<G4en 350 G4cout <<"----------------------" <<G4endl; 417 } 351 } 418 std::size_t ie = 0; << 352 G4int ie = 0; 419 for (auto iter = fragmentVector->cbegin(); << 353 G4FragmentVector::iterator iter; 420 iter != fragmentVector->cend(); << 354 for (iter = fragmentVector->begin(); iter != fragmentVector->end(); ++iter) 421 { 355 { 422 if (ie == nEvap) 356 if (ie == nEvap) 423 { 357 { 424 // G4cout <<*iter <<G4endl; << 358 G4cout <<*iter <<G4endl; 425 G4cout <<"---------------------------- 359 G4cout <<"---------------------------------" <<G4endl; 426 G4cout <<"Particles from default emiss 360 G4cout <<"Particles from default emission :" <<G4endl; 427 G4cout <<"---------------------------- 361 G4cout <<"---------------------------------" <<G4endl; 428 } 362 } 429 G4cout <<*iter <<G4endl; 363 G4cout <<*iter <<G4endl; 430 } 364 } 431 G4cout <<"oooooooooooooooooooooooooooooooo 365 G4cout <<"oooooooooooooooooooooooooooooooooooooooo" 432 <<"oooooooooooooooooooooooooooooooo 366 <<"oooooooooooooooooooooooooooooooooooooooo" 433 <<G4endl; 367 <<G4endl; 434 } 368 } 435 369 436 return fragmentVector; 370 return fragmentVector; 437 } 371 } 438 ////////////////////////////////////////////// 372 //////////////////////////////////////////////////////////////////////////////// 439 // 373 // 440 void G4WilsonAblationModel::SelectSecondariesB 374 void G4WilsonAblationModel::SelectSecondariesByEvaporation 441 (G4Fragment *intermediateNucleus) 375 (G4Fragment *intermediateNucleus) 442 { 376 { 443 G4Fragment theResidualNucleus = *intermediat << 444 G4bool evaporate = true; 377 G4bool evaporate = true; 445 // Loop checking, 05-Aug-2015, Vladimir Ivan << 446 while (evaporate && evapType.size() != 0) 378 while (evaporate && evapType.size() != 0) 447 { 379 { 448 // 380 // 449 // 381 // 450 // Here's the cheaky bit. We're hijacking the 382 // Here's the cheaky bit. We're hijacking the G4Evaporation model, in order to 451 // more accurately sample to kinematics, but t 383 // more accurately sample to kinematics, but the species of the nuclear 452 // fragments will be the ones of our choosing 384 // fragments will be the ones of our choosing as above. 453 // 385 // 454 std::vector <G4VEvaporationChannel*> theC << 386 std::vector <G4VEvaporationChannel*> theChannels; 455 theChannels1.clear(); << 387 theChannels.clear(); 456 std::vector <G4VEvaporationChannel*>::iter << 457 VectorOfFragmentTypes::iterator iter; 388 VectorOfFragmentTypes::iterator iter; 458 std::vector <VectorOfFragmentTypes::iterat 389 std::vector <VectorOfFragmentTypes::iterator> iters; 459 iters.clear(); 390 iters.clear(); 460 iter = std::find(evapType.begin(), evapTyp 391 iter = std::find(evapType.begin(), evapType.end(), G4Alpha::Alpha()); 461 if (iter != evapType.end()) 392 if (iter != evapType.end()) 462 { 393 { 463 theChannels1.push_back(new G4AlphaEvapor << 394 theChannels.push_back(new G4AlphaEvaporationChannel); 464 i = theChannels1.end() - 1; << 465 (*i)->SetOPTxs(OPTxs); << 466 (*i)->UseSICB(useSICB); << 467 // (*i)->Initialize(theResidualNucleus); << 468 iters.push_back(iter); 395 iters.push_back(iter); 469 } 396 } 470 iter = std::find(evapType.begin(), evapTyp 397 iter = std::find(evapType.begin(), evapType.end(), G4He3::He3()); 471 if (iter != evapType.end()) 398 if (iter != evapType.end()) 472 { 399 { 473 theChannels1.push_back(new G4He3Evaporat << 400 theChannels.push_back(new G4He3EvaporationChannel); 474 i = theChannels1.end() - 1; << 475 (*i)->SetOPTxs(OPTxs); << 476 (*i)->UseSICB(useSICB); << 477 // (*i)->Initialize(theResidualNucleus); << 478 iters.push_back(iter); 401 iters.push_back(iter); 479 } 402 } 480 iter = std::find(evapType.begin(), evapTyp 403 iter = std::find(evapType.begin(), evapType.end(), G4Triton::Triton()); 481 if (iter != evapType.end()) 404 if (iter != evapType.end()) 482 { 405 { 483 theChannels1.push_back(new G4TritonEvapo << 406 theChannels.push_back(new G4TritonEvaporationChannel); 484 i = theChannels1.end() - 1; << 485 (*i)->SetOPTxs(OPTxs); << 486 (*i)->UseSICB(useSICB); << 487 // (*i)->Initialize(theResidualNucleus); << 488 iters.push_back(iter); 407 iters.push_back(iter); 489 } 408 } 490 iter = std::find(evapType.begin(), evapTyp 409 iter = std::find(evapType.begin(), evapType.end(), G4Deuteron::Deuteron()); 491 if (iter != evapType.end()) 410 if (iter != evapType.end()) 492 { 411 { 493 theChannels1.push_back(new G4DeuteronEva << 412 theChannels.push_back(new G4DeuteronEvaporationChannel); 494 i = theChannels1.end() - 1; << 495 (*i)->SetOPTxs(OPTxs); << 496 (*i)->UseSICB(useSICB); << 497 // (*i)->Initialize(theResidualNucleus); << 498 iters.push_back(iter); 413 iters.push_back(iter); 499 } 414 } 500 iter = std::find(evapType.begin(), evapTyp 415 iter = std::find(evapType.begin(), evapType.end(), G4Proton::Proton()); 501 if (iter != evapType.end()) 416 if (iter != evapType.end()) 502 { 417 { 503 theChannels1.push_back(new G4ProtonEvapo << 418 theChannels.push_back(new G4ProtonEvaporationChannel); 504 i = theChannels1.end() - 1; << 505 (*i)->SetOPTxs(OPTxs); << 506 (*i)->UseSICB(useSICB); << 507 // (*i)->Initialize(theResidualNucleus); << 508 iters.push_back(iter); 419 iters.push_back(iter); 509 } 420 } 510 iter = std::find(evapType.begin(), evapTyp 421 iter = std::find(evapType.begin(), evapType.end(), G4Neutron::Neutron()); 511 if (iter != evapType.end()) 422 if (iter != evapType.end()) 512 { 423 { 513 theChannels1.push_back(new G4NeutronEvap << 424 theChannels.push_back(new G4NeutronEvaporationChannel); 514 i = theChannels1.end() - 1; << 515 (*i)->SetOPTxs(OPTxs); << 516 (*i)->UseSICB(useSICB); << 517 // (*i)->Initialize(theResidualNucleus); << 518 iters.push_back(iter); 425 iters.push_back(iter); 519 } 426 } 520 std::size_t nChannels = theChannels1.size( << 427 G4int nChannels = theChannels.size(); 521 428 522 G4double totalProb = 0.0; << 429 std::vector<G4VEvaporationChannel*>::iterator iterEv; 523 G4int ich = 0; << 430 for (iterEv=theChannels.begin(); iterEv!=theChannels.end(); iterEv++) 524 G4double probEvapType[6] = {0.0}; << 431 (*iterEv)->Initialize(*intermediateNucleus); 525 for (auto iterEv=theChannels1.cbegin(); << 432 G4double totalProb = std::accumulate(theChannels.begin(), 526 iterEv!=theChannels1.cend(); ++i << 433 theChannels.end(), 0.0, SumProbabilities()); 527 totalProb += (*iterEv)->GetEmissionProba << 434 if (totalProb > 0.0) 528 probEvapType[ich] = totalProb; << 435 { 529 ++ich; << 530 } << 531 if (totalProb > 0.0) { << 532 // 436 // 533 // 437 // 534 // The emission probability for at least one o 438 // The emission probability for at least one of the evaporation channels is 535 // positive, therefore work out which one shou 439 // positive, therefore work out which one should be selected and decay 536 // the nucleus. 440 // the nucleus. 537 // 441 // 538 G4double xi = totalProb*G4UniformRand(); << 442 G4double totalProb1 = 0.0; 539 std::size_t ii = 0; << 443 G4double probEvapType[6] = {0.0}; 540 for (ii=0; ii<nChannels; ++ii) << 444 for (G4int ich=0; ich<nChannels; ich++) 541 { 445 { 542 if (xi < probEvapType[ii]) { break; } << 446 totalProb1 += theChannels[ich]->GetEmissionProbability(); 543 } << 447 probEvapType[ich] = totalProb1 / totalProb; 544 if (ii >= nChannels) { ii = nChannels - << 545 G4FragmentVector *evaporationResult = th << 546 BreakUpFragment(intermediateNucleus); << 547 if ((*evaporationResult)[0] != nullptr) << 548 { << 549 (*evaporationResult)[0]->SetCreatorMod << 550 } 448 } >> 449 G4double xi = G4UniformRand(); >> 450 G4int i = 0; >> 451 for (i=0; i<nChannels; i++) >> 452 if (xi < probEvapType[i]) break; >> 453 if (i > nChannels) i = nChannels - 1; >> 454 G4FragmentVector *evaporationResult = theChannels[i]-> >> 455 BreakUp(*intermediateNucleus); 551 fragmentVector->push_back((*evaporationR 456 fragmentVector->push_back((*evaporationResult)[0]); 552 intermediateNucleus = (*evaporationResul << 457 *intermediateNucleus = *(*evaporationResult)[1]; >> 458 delete evaporationResult->back(); 553 delete evaporationResult; 459 delete evaporationResult; >> 460 evapType.erase(iters[i]); 554 } 461 } 555 else 462 else 556 { 463 { 557 // 464 // 558 // 465 // 559 // Probability for further evaporation is nil 466 // Probability for further evaporation is nil so have to escape from this 560 // routine and set the energies of the seconda 467 // routine and set the energies of the secondaries to 10eV. 561 // 468 // 562 evaporate = false; 469 evaporate = false; 563 } 470 } 564 } 471 } 565 472 566 return; 473 return; 567 } 474 } 568 ////////////////////////////////////////////// 475 //////////////////////////////////////////////////////////////////////////////// 569 // 476 // 570 void G4WilsonAblationModel::SelectSecondariesB 477 void G4WilsonAblationModel::SelectSecondariesByDefault (G4ThreeVector boost) 571 { 478 { 572 for (std::size_t i=0; i<evapType.size(); ++i << 479 for (unsigned i=0; i<evapType.size(); i++) 573 { 480 { 574 G4ParticleDefinition *type = evapType[i]; << 481 G4ParticleDefinition *type = fragType[i]; 575 G4double mass = type->GetPDGM 482 G4double mass = type->GetPDGMass(); 576 G4double e = mass + 10.0*e 483 G4double e = mass + 10.0*eV; 577 G4double p = std::sqrt(e*e 484 G4double p = std::sqrt(e*e-mass*mass); 578 G4double costheta = 2.0*G4Uniform 485 G4double costheta = 2.0*G4UniformRand() - 1.0; 579 G4double sintheta = std::sqrt((1. 486 G4double sintheta = std::sqrt((1.0 - costheta)*(1.0 + costheta)); 580 G4double phi = twopi * G4Uni 487 G4double phi = twopi * G4UniformRand() * rad; 581 G4ThreeVector direction(sintheta*std::cos( 488 G4ThreeVector direction(sintheta*std::cos(phi),sintheta*std::sin(phi),costheta); 582 G4LorentzVector lorentzVector = G4LorentzV 489 G4LorentzVector lorentzVector = G4LorentzVector(direction*p, e); 583 lorentzVector.boost(-boost); 490 lorentzVector.boost(-boost); 584 // Possibility that the following line is not << 585 // from particle definition. Force values. P << 586 // G4Fragment *fragment = << 587 // new G4Fragment(lorentzVector, type); << 588 G4int A = type->GetBaryonNumber(); << 589 G4int Z = (G4int) (type->GetPDGCharge() + << 590 G4Fragment *fragment = 491 G4Fragment *fragment = 591 new G4Fragment(A, Z, lorentzVector); << 492 new G4Fragment(lorentzVector, type); 592 if (fragment != nullptr) { fragment->SetCr << 593 fragmentVector->push_back(fragment); 493 fragmentVector->push_back(fragment); 594 } 494 } 595 } 495 } 596 ////////////////////////////////////////////// 496 //////////////////////////////////////////////////////////////////////////////// 597 // 497 // 598 void G4WilsonAblationModel::PrintWelcomeMessag 498 void G4WilsonAblationModel::PrintWelcomeMessage () 599 { 499 { 600 G4cout <<G4endl; 500 G4cout <<G4endl; 601 G4cout <<" ********************************* 501 G4cout <<" *****************************************************************" 602 <<G4endl; 502 <<G4endl; 603 G4cout <<" Nuclear ablation model for nuclea 503 G4cout <<" Nuclear ablation model for nuclear-nuclear interactions activated" 604 <<G4endl; 504 <<G4endl; 605 G4cout <<" (Written by QinetiQ Ltd for the E 505 G4cout <<" (Written by QinetiQ Ltd for the European Space Agency)" 606 <<G4endl; << 607 G4cout <<" !!! WARNING: This model is not we << 608 <<G4endl; 506 <<G4endl; 609 G4cout <<" ********************************* 507 G4cout <<" *****************************************************************" 610 <<G4endl; 508 <<G4endl; 611 G4cout << G4endl; 509 G4cout << G4endl; 612 510 613 return; 511 return; 614 } 512 } 615 ////////////////////////////////////////////// 513 //////////////////////////////////////////////////////////////////////////////// 616 // 514 // 617 515