Geant4 Cross Reference |
1 // 1 2 // ******************************************* 3 // * License and Disclaimer 4 // * 5 // * The Geant4 software is copyright of th 6 // * the Geant4 Collaboration. It is provided 7 // * conditions of the Geant4 Software License 8 // * LICENSE and available at http://cern.ch/ 9 // * include a list of copyright holders. 10 // * 11 // * Neither the authors of this software syst 12 // * institutes,nor the agencies providing fin 13 // * work make any representation or warran 14 // * regarding this software system or assum 15 // * use. Please see the license in the file 16 // * for the full disclaimer and the limitatio 17 // * 18 // * This code implementation is the result 19 // * technical work of the GEANT4 collaboratio 20 // * By using, copying, modifying or distri 21 // * any work based on the software) you ag 22 // * use in resulting scientific publicati 23 // * acceptance of all terms of the Geant4 Sof 24 // ******************************************* 25 // 26 // 27 // ------------------------------------------- 28 // 29 // GEANT4 source file 30 // 31 // File name: G4NuDEXNeutronCaptureMo 32 // 33 // Author: E.Mendoza & A.Ribon 34 // 35 // Creation date: 29 May 2024 36 // 37 // Description: This class (a proxy of 38 // the NuDEX model to prod 39 // conversion electrons fr 40 // Whenever NuDEX is not a 41 // is used. 42 // The implementation of t 43 // of the class G4NeutronR 44 // 45 // Modifications: 46 // 47 // ------------------------------------------- 48 // 49 50 #include "G4NuDEXNeutronCaptureModel.hh" 51 #include "G4NuDEXStatisticalNucleus.hh" 52 #include "Randomize.hh" 53 #include "G4SystemOfUnits.hh" 54 #include "G4PhysicalConstants.hh" 55 #include "G4LorentzVector.hh" 56 #include "G4Gamma.hh" 57 #include "G4Electron.hh" 58 #include "G4Positron.hh" 59 #include "G4Deuteron.hh" 60 #include "G4Triton.hh" 61 #include "G4He3.hh" 62 #include "G4Alpha.hh" 63 #include "G4NucleiProperties.hh" 64 #include "G4IonTable.hh" 65 #include "G4ParticleTable.hh" 66 #include "G4HadronicParameters.hh" 67 #include "G4DeexPrecoParameters.hh" 68 #include "G4NuclearLevelData.hh" 69 #include "G4PhotonEvaporation.hh" 70 #include "G4PhysicsModelCatalog.hh" 71 72 73 G4NuDEXNeutronCaptureModel::G4NuDEXNeutronCapt 74 for ( G4int i = 0; i < G4NUDEX_MAXZA; i++ ) 75 theStatisticalNucleus[i] = nullptr; 76 HasData[i] = 0; 77 } 78 BrOption = -1; 79 BandWidth = 0; 80 NuDEXLibDirectory = ""; 81 photonEvaporation = nullptr; 82 auto ch = G4FindDataDir( "G4NUDEXLIBDATA" ); 83 if ( ch == nullptr ) { 84 G4Exception( "G4NuDEXNeutronCaptureModel() 85 } else { 86 NuDEXLibDirectory = G4String(ch); 87 } 88 } 89 90 91 void G4NuDEXNeutronCaptureModel::InitialiseMod 92 if ( photonEvaporation != nullptr ) return; 93 G4DeexPrecoParameters* param = G4NuclearLeve 94 minExcitation = param->GetMinExcitation(); 95 photonEvaporation = new G4PhotonEvaporation; 96 photonEvaporation->Initialise(); 97 photonEvaporation->SetICM( true ); 98 secID = G4PhysicsModelCatalog::GetModelID( " 99 lowestEnergyLimit = 10.0*CLHEP::eV; 100 minExcitation = 0.1*CLHEP::keV; 101 } 102 103 104 G4NuDEXNeutronCaptureModel::~G4NuDEXNeutronCap 105 for ( G4int i = 0; i < G4NUDEX_MAXZA; i++ ) 106 if ( theStatisticalNucleus[i] ) delete the 107 } 108 } 109 110 111 G4HadFinalState* G4NuDEXNeutronCaptureModel::A 112 theParticleChange.Clear(); 113 theParticleChange.SetStatusChange( stopAndKi 114 G4int A = theNucleus.GetA_asInt(); 115 G4int Z = theNucleus.GetZ_asInt(); 116 G4double time = aTrack.GetGlobalTime(); // 117 // Create initial state 118 G4LorentzVector lab4mom( 0.0, 0.0, 0.0, G4Nu 119 lab4mom += aTrack.Get4Momentum(); 120 G4double systemMass = lab4mom.mag(); 121 ++A; // Compound nucleus: target nucleus + 122 G4double compoundMass = G4NucleiProperties:: 123 // If the energy available is to small to do 124 if ( systemMass - compoundMass <= lowestEne 125 G4ThreeVector boostFromCMtoLAB = lab4mom.boo 126 G4double neutronEnergy = aTrack.GetKineticEn 127 128 // Try to apply NuDEX 129 //G4int lspin = 0; // l-spin = 0, 1, 2 - 130 //G4int jspinx2 = -1; // A negative value o 131 //G4int initialLevel = SelectInitialLevel( Z 132 G4int initialLevel = -1; // thermal neutron 133 std::vector< char > pType; 134 std::vector< G4double > pEnergy, pTime; 135 G4int npar = GenerateNeutronCaptureCascade( 136 if ( npar > 0 ) { // NuDEX can be applied 137 138 G4LorentzVector remainingLab4mom = lab4mom 139 G4double latestEmission = time; 140 // Loop over the EM particles produced by 141 // theParticleChange as secondaries. These 142 for ( G4int i = 0; i < npar; i++ ) { 143 G4ParticleDefinition* particleDef = null 144 if ( pType.at(i) == 'g' ) { 145 particleDef = G4Gamma::Definition(); 146 } else if (pType.at(i) == 'e' ) { 147 particleDef = G4Electron::Definition() 148 } else if ( pType.at(i) == 'p' ) { 149 particleDef = G4Positron::Definition() 150 } else { 151 G4Exception( "G4NUDEXNeutronCaptureMod 152 } 153 G4double phi = G4UniformRand()*twopi; 154 G4double costheta = 2.0*G4UniformRand() 155 G4double sintheta = std::sqrt( 1.0 - cos 156 G4ThreeVector direction( sintheta*std::c 157 G4double mass = particleDef->GetPDGMass( 158 G4double particle3momMod = std::sqrt( pE 159 G4LorentzVector particle4mom( particle3m 160 particle4mom.boost( boostFromCMtoLAB ); 161 G4HadSecondary* secondary = new G4HadSec 162 remainingLab4mom -= particle4mom; 163 // For simplicity, we neglect below the 164 secondary->SetTime( time + pTime.at(i) ) 165 if ( latestEmission < time + pTime.at(i) 166 secondary->SetCreatorModelID( secID ); 167 theParticleChange.AddSecondary( *seconda 168 delete secondary; 169 } 170 // Treat now the residual nucleus (which i 171 const G4ParticleDefinition* resNuclDef = n 172 if ( Z == 1 && A == 2 ) resNuclDef 173 else if ( Z == 1 && A == 3 ) resNuclDef 174 else if ( Z == 2 && A == 3 ) resNuclDef 175 else if ( Z == 2 && A == 4 ) resNuclDef 176 else resNuclDef = G4ParticleTable::GetPart 177 if ( resNuclDef ) { 178 // To conserve energy-momentum, remainin 179 // Imposing the mass 'compoundMass' to t 180 // while keeping as low as possible the 181 // cannot be conserved, the residual nuc 182 G4double resNuclLabEkin = std::max( rema 183 G4double resNuclLab3momMod = 0.0; 184 G4ThreeVector resNuclLabDir( 0.0, 0.0, 0 185 if ( resNuclLabEkin > 0.0 ) { 186 resNuclLab3momMod = std::sqrt( resNucl 187 resNuclLabDir = remainingLab4mom.vect( 188 } 189 G4LorentzVector resNuclLab4mom( resNuclL 190 G4HadSecondary* secondary = new G4HadSec 191 secondary->SetTime( latestEmission ); 192 secondary->SetCreatorModelID( secID ); 193 theParticleChange.AddSecondary( *seconda 194 delete secondary; 195 } 196 197 } else { // NuDEX cannot be applied: use G4 198 199 // Code taken from G4NeutronRadCapture 200 201 G4Fragment* aFragment = new G4Fragment( A, 202 G4FragmentVector* fv = photonEvaporation-> 203 if ( fv == nullptr ) fv = new G4FragmentVe 204 fv->push_back( aFragment ); 205 size_t n = fv->size(); 206 for ( size_t i = 0; i < n; ++i ) { 207 G4Fragment* f = (*fv)[i]; 208 G4double etot = f->GetMomentum().e(); 209 Z = f->GetZ_asInt(); 210 A = f->GetA_asInt(); 211 const G4ParticleDefinition* theDef = nul 212 if ( Z == 0 && A == 0 ) { theDef = 213 else if ( Z == 1 && A == 2 ) { theDef = 214 else if ( Z == 1 && A == 3 ) { theDef = 215 else if ( Z == 2 && A == 3 ) { theDef = 216 else if ( Z == 2 && A == 4 ) { theDef = 217 else { 218 G4double eexc = f->GetExcitationEnergy 219 if ( eexc <= minExcitation ) eexc = 0. 220 theDef = G4ParticleTable::GetParticleT 221 } 222 G4double ekin = std::max( 0.0, etot - th 223 G4HadSecondary* news = new G4HadSecondar 224 G4double timeF = f->GetCreationTime(); 225 if ( timeF < 0.0 ) timeF = 0.0; 226 news->SetTime( time + timeF ); 227 news->SetCreatorModelID( secID ); 228 theParticleChange.AddSecondary( *news ); 229 delete news; 230 delete f; 231 } 232 delete fv; 233 } 234 235 return &theParticleChange; 236 } 237 238 239 G4int G4NuDEXNeutronCaptureModel::GenerateNeut 240 std::vector 241 std::vector 242 // Returns the number of emitted particles. 243 G4int theZA = 1000*theZ + theA; 244 G4int check = Init( theZA ); 245 if ( check < 0 ) return -1; 246 G4double Sn, I0; 247 theStatisticalNucleus[theZA]->GetSnAndI0( Sn 248 G4double ExcitationEnergy = Sn + (theA-1.0)/ 249 G4int nPar = theStatisticalNucleus[theZA]->G 250 for ( G4int i = 0; i < nPar; i++ ) { 251 pEnergy.at(i) *= MeV; 252 pTime.at(i) *= s; 253 } 254 return nPar; 255 } 256 257 258 G4int G4NuDEXNeutronCaptureModel::Init( G4int 259 if ( HasData[theZA] == -1 ) return -1; 260 if ( HasData[theZA] == 1 ) return 0; 261 if ( theStatisticalNucleus[theZA] == 0 ) { 262 G4int theZ = theZA/1000; 263 G4int theA = theZA-1000*theZ; 264 theStatisticalNucleus[theZA] = new G4NuDEX 265 if ( BandWidth != 0 ) theStatisticalNucleu 266 theStatisticalNucleus[theZA]->SetBrOption( 267 if ( seed1 > 0 ) theStatisticalNucleus[the 268 if ( seed2 > 0 ) theStatisticalNucleus[the 269 if ( seed3 > 0 ) theStatisticalNucleus[the 270 G4int check = theStatisticalNucleus[theZA] 271 if ( check < 0 ) { 272 HasData[theZA] = -1; 273 return -1; 274 } else { 275 HasData[theZA] = 1; 276 } 277 } 278 return 0; 279 } 280 281 282 G4int G4NuDEXNeutronCaptureModel::SelectInitia 283 // Initial level for neutron capture. If jsp 284 // l-spin = 0, 1, 2 --> s-wave, p-wave, d-wa 285 G4int theZ = theCompoundZ; 286 G4int theA = theCompoundA; 287 G4int theZA = 1000*theZ + theA; 288 G4int check = Init( theZA ); 289 if ( check < 0 ) return -1; 290 G4double Sn, I0; 291 theStatisticalNucleus[theZA]->GetSnAndI0( Sn 292 G4double ExcitationEnergy = Sn + (theA-1.0)/ 293 if ( lspin < 0 ) lspin = 0; 294 if ( jspinx2 < 0 ) jspinx2 = SampleJ( theZ, 295 G4bool parity = false; 296 if ( ( I0 >= 0 && (lspin%2) == 0 ) || ( I0 297 G4int InitialLevel = theStatisticalNucleus[t 298 return InitialLevel; 299 } 300 301 302 G4int G4NuDEXNeutronCaptureModel ::SampleJ( G4 303 // Samples J for this l-spin (l-spin = 0, 1, 304 // The probability will be proportional to 2 305 // Returns Jx2 306 G4int AllowedJx2[100]; 307 G4int NAllowedJvals = GetAllowedJx2values( t 308 G4double AllowedJx2CumulProb[100], TotalCumu 309 for ( G4int i = 0; i < NAllowedJvals; i++ ) 310 AllowedJx2CumulProb[i] = AllowedJx2[i] + 1 311 TotalCumul += AllowedJx2CumulProb[i]; 312 } 313 for ( G4int i = 0; i < NAllowedJvals; i++ ) 314 AllowedJx2CumulProb[i] /= TotalCumul; 315 if ( i > 0 ) AllowedJx2CumulProb[i] += All 316 } 317 G4double rand = G4UniformRand(); 318 G4int i_result = -1; 319 for ( G4int i = 0; i < NAllowedJvals; i++ ) 320 if ( rand < AllowedJx2CumulProb[i] ) { 321 i_result = i; break; 322 } 323 } 324 if ( i_result < 0 ) { 325 G4cerr << " ############ Error in " << __F 326 exit(1); 327 } 328 G4int jspinx2 = AllowedJx2[i_result]; 329 return jspinx2; 330 } 331 332 333 G4int G4NuDEXNeutronCaptureModel::GetAllowedJx 334 // Provides the allowed jx2 values in neutro 335 G4int theZA = 1000*theCompoundZ + theCompoun 336 G4int check = Init( theZA ); 337 if ( check < 0 ) return -1; 338 G4double Sn, I0; 339 theStatisticalNucleus[theZA]->GetSnAndI0( Sn 340 G4int Ix2 = (G4int)( ( std::fabs(I0) + 0.1 ) 341 G4int Jx2min = std::min( std::abs( Ix2-1-2*l 342 G4int Jx2max = Ix2 + 1 + 2*lspin; 343 G4int NAllowedJvals = 0; 344 for ( G4int Jx2 = Jx2min; Jx2 <= Jx2max; Jx2 345 if ( Jx2 >= 0 ) { 346 jx2vals[NAllowedJvals] = Jx2; 347 NAllowedJvals++; 348 } 349 } 350 return NAllowedJvals; 351 } 352