Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // neutron_hp -- source file 27 // J.P. Wellisch, Nov-1996 28 // A prototype of the low energy neutron transport model. 29 // 30 // 070523 bug fix for G4FPE_DEBUG on by A. Howard ( and T. Koi) 31 // 071031 bug fix T. Koi on behalf of A. Howard 32 // 081203 bug fix in Register method by T. Koi 33 // 34 // P. Arce, June-2014 Conversion neutron_hp to particle_hp 35 // 36 // June-2019 - E. Mendoza --> Modification to allow using an incomplete 37 // data library if the G4NEUTRONHP_SKIP_MISSING_ISOTOPES environmental 38 // flag is defined. The missing XS are set to 0. 39 40 #include "G4ParticleHPChannel.hh" 41 42 #include "G4HadTmpUtil.hh" 43 #include "G4ParticleHPElasticFS.hh" 44 #include "G4ParticleHPFinalState.hh" 45 #include "G4ParticleHPReactionWhiteBoard.hh" 46 #include "G4ParticleHPThermalBoost.hh" 47 #include "G4SystemOfUnits.hh" 48 #include "globals.hh" 49 50 #include <cstdlib> 51 52 G4ParticleHPChannel::G4ParticleHPChannel(G4ParticleDefinition* p) 53 { 54 fManager = G4ParticleHPManager::GetInstance(); 55 if (fManager->GetUseWendtFissionModel()) { 56 wendtFissionGenerator = G4WendtFissionFragmentGenerator::GetInstance(); 57 // Make sure both fission fragment models are not active at same time 58 fManager->SetProduceFissionFragments(false); 59 } 60 theProjectile = (nullptr == p) ? G4Neutron::Neutron() : p; 61 theChannelData = new G4ParticleHPVector; 62 } 63 64 G4ParticleHPChannel::~G4ParticleHPChannel() 65 { 66 delete theChannelData; 67 // Following statement disabled to avoid SEGV 68 // theBuffer is also deleted as "theChannelData" in 69 delete[] theIsotopeWiseData; 70 if (theFinalStates != nullptr) { 71 for (G4int i = 0; i < niso; i++) { 72 delete theFinalStates[i]; 73 } 74 delete[] theFinalStates; 75 } 76 delete[] active; 77 } 78 79 G4double G4ParticleHPChannel::GetXsec(G4double energy) const 80 { 81 return std::max(0., theChannelData->GetXsec(energy)); 82 } 83 84 G4double G4ParticleHPChannel::GetWeightedXsec(G4double energy, 85 G4int isoNumber) const 86 { 87 return theIsotopeWiseData[isoNumber].GetXsec(energy); 88 } 89 90 G4double G4ParticleHPChannel::GetFSCrossSection(G4double energy, 91 G4int isoNumber) const 92 { 93 return theFinalStates[isoNumber]->GetXsec(energy); 94 } 95 96 void G4ParticleHPChannel::Init(G4Element* anElement, 97 const G4String& dirName, const G4String& aFSType) 98 { 99 theFSType = aFSType; 100 Init(anElement, dirName); 101 } 102 103 void G4ParticleHPChannel::Init(G4Element* anElement, const G4String& dirName) 104 { 105 theDir = dirName; 106 theElement = anElement; 107 } 108 109 G4bool G4ParticleHPChannel::Register(G4ParticleHPFinalState* theFS) 110 { 111 ++registerCount; 112 G4int Z = theElement->GetZasInt(); 113 114 niso = (G4int)theElement->GetNumberOfIsotopes(); 115 const std::size_t nsize = niso > 0 ? niso : 1; 116 117 delete[] theIsotopeWiseData; 118 theIsotopeWiseData = new G4ParticleHPIsoData[nsize]; 119 delete[] active; 120 active = new G4bool[nsize]; 121 122 delete[] theFinalStates; 123 theFinalStates = new G4ParticleHPFinalState*[nsize]; 124 delete theChannelData; 125 theChannelData = new G4ParticleHPVector; 126 for (G4int i = 0; i < niso; ++i) { 127 theFinalStates[i] = theFS->New(); 128 theFinalStates[i]->SetProjectile(theProjectile); 129 } 130 if (niso != 0 && registerCount == 0) { 131 for (G4int i1 = 0; i1 < niso; ++i1) { 132 G4int A = theElement->GetIsotope(i1)->GetN(); 133 G4int M = theElement->GetIsotope(i1)->Getm(); 134 //G4cout <<" Init: normal case i=" << i1 135 // << " Z=" << Z << " A=" << A << G4endl; 136 G4double frac = theElement->GetRelativeAbundanceVector()[i1] / perCent; 137 theFinalStates[i1]->SetA_Z(A, Z, M); 138 UpdateData(A, Z, M, i1, frac, theProjectile); 139 } 140 } 141 G4bool result = HasDataInAnyFinalState(); 142 143 // To avoid issuing hash by worker threads 144 if (result) theChannelData->Hash(); 145 146 return result; 147 } 148 149 void G4ParticleHPChannel::UpdateData(G4int A, G4int Z, G4int M, G4int index, 150 G4double abundance, 151 G4ParticleDefinition* projectile) 152 { 153 // Initialze the G4FissionFragment generator for this isomer if needed 154 if (wendtFissionGenerator != nullptr) { 155 wendtFissionGenerator->InitializeANucleus(A, Z, M, theDir); 156 } 157 158 theFinalStates[index]->Init(A, Z, M, theDir, theFSType, projectile); 159 if (!theFinalStates[index]->HasAnyData()) return; 160 // nothing there for exactly this isotope. 161 162 // the above has put the X-sec into the FS 163 theBuffer = nullptr; 164 if (theFinalStates[index]->HasXsec()) { 165 theBuffer = theFinalStates[index]->GetXsec(); 166 theBuffer->Times(abundance / 100.); 167 theIsotopeWiseData[index].FillChannelData(theBuffer); 168 } 169 else // get data from CrossSection directory 170 { 171 const G4String& tString = "/CrossSection"; 172 active[index] = theIsotopeWiseData[index].Init(A, Z, M, abundance, 173 theDir, tString); 174 if (active[index]) theBuffer = theIsotopeWiseData[index].MakeChannelData(); 175 } 176 if (theBuffer != nullptr) Harmonise(theChannelData, theBuffer); 177 } 178 179 void G4ParticleHPChannel::Harmonise(G4ParticleHPVector*& theStore, 180 G4ParticleHPVector* theNew) 181 { 182 G4int s_tmp = 0, n = 0, m_tmp = 0; 183 auto theMerge = new G4ParticleHPVector; 184 G4ParticleHPVector* anActive = theStore; 185 G4ParticleHPVector* aPassive = theNew; 186 G4ParticleHPVector* tmp; 187 G4int a = s_tmp, p = n, t; 188 while (a < anActive->GetVectorLength() && p < aPassive->GetVectorLength()) 189 // Loop checking, 11.05.2015, T. Koi 190 { 191 if (anActive->GetEnergy(a) <= aPassive->GetEnergy(p)) { 192 G4double xa = anActive->GetEnergy(a); 193 theMerge->SetData(m_tmp, xa, anActive->GetXsec(a) + std::max(0., aPassive->GetXsec(xa))); 194 m_tmp++; 195 a++; 196 G4double xp = aPassive->GetEnergy(p); 197 if (std::abs(std::abs(xp - xa) / xa) < 0.001) { 198 ++p; 199 } 200 } 201 else { 202 tmp = anActive; 203 t = a; 204 anActive = aPassive; 205 a = p; 206 aPassive = tmp; 207 p = t; 208 } 209 } 210 while (a != anActive->GetVectorLength()) // Loop checking, 11.05.2015, T. Koi 211 { 212 theMerge->SetData(m_tmp++, anActive->GetEnergy(a), anActive->GetXsec(a)); 213 ++a; 214 } 215 while (p != aPassive->GetVectorLength()) // Loop checking, 11.05.2015, T. Koi 216 { 217 if (std::abs(theMerge->GetEnergy(std::max(0, m_tmp - 1)) - 218 aPassive->GetEnergy(p)) / aPassive->GetEnergy(p) > 0.001) 219 theMerge->SetData(m_tmp++, aPassive->GetEnergy(p), aPassive->GetXsec(p)); 220 ++p; 221 } 222 delete theStore; 223 theStore = theMerge; 224 } 225 226 G4WendtFissionFragmentGenerator* G4ParticleHPChannel::GetWendtFissionGenerator() const { 227 if ( wendtFissionGenerator ) return wendtFissionGenerator; 228 else return nullptr; 229 } 230 231 G4HadFinalState* 232 G4ParticleHPChannel::ApplyYourself(const G4HadProjectile& theTrack, 233 G4int anIsotope, G4bool isElastic) 234 { 235 //G4cout << "G4ParticleHPChannel::ApplyYourself niso=" << niso 236 // << " ni=" << anIsotope << " isElastic=" << isElastic <<G4endl; 237 if (anIsotope != -1 && anIsotope != -2) { 238 // Inelastic Case 239 //G4cout << "G4ParticleHPChannel Inelastic Case" 240 //<< " Z= " << GetZ(anIsotope) << " A = " << GetN(anIsotope) << G4endl; 241 fManager->GetReactionWhiteBoard()->SetTargA((G4int)GetN(anIsotope)); 242 fManager->GetReactionWhiteBoard()->SetTargZ((G4int)GetZ(anIsotope)); 243 return theFinalStates[anIsotope]->ApplyYourself(theTrack); 244 } 245 G4double sum = 0; 246 G4int it = 0; 247 auto xsec = new G4double[niso]; 248 G4ParticleHPThermalBoost aThermalE; 249 for (G4int i = 0; i < niso; i++) { 250 if (theFinalStates[i]->HasAnyData()) { 251 /* 252 G4cout << "FS: " << i << theTrack.GetDefinition()->GetParticleName() 253 << " Z=" << theFinalStates[i]->GetZ() 254 << " A=" << theFinalStates[i]->GetN() 255 << G4endl; 256 */ 257 xsec[i] = theIsotopeWiseData[i].GetXsec( 258 aThermalE.GetThermalEnergy(theTrack, theFinalStates[i]->GetN(), 259 theFinalStates[i]->GetZ(), 260 theTrack.GetMaterial()->GetTemperature())); 261 sum += xsec[i]; 262 } 263 else { 264 xsec[i] = 0; 265 } 266 } 267 if (sum == 0) { 268 it = G4lrint(niso * G4UniformRand()); 269 } 270 else { 271 G4double random = G4UniformRand(); 272 G4double running = 0; 273 for (G4int ix = 0; ix < niso; ix++) { 274 running += xsec[ix]; 275 if (sum == 0 || random <= running / sum) { 276 it = ix; 277 break; 278 } 279 } 280 if (it == niso) it--; 281 } 282 delete[] xsec; 283 G4HadFinalState* theFinalState = nullptr; 284 const auto A = (G4int)this->GetN(it); 285 const auto Z = (G4int)this->GetZ(it); 286 const auto M = (G4int)this->GetM(it); 287 288 //-2:Marker for Fission 289 if ((wendtFissionGenerator != nullptr) && anIsotope == -2) { 290 theFinalState = wendtFissionGenerator->ApplyYourself(theTrack, Z, A); 291 } 292 293 // Use the standard procedure if the G4FissionFragmentGenerator model fails 294 if (theFinalState == nullptr) { 295 G4int icounter = 0; 296 G4int icounter_max = 1024; 297 while (theFinalState == nullptr) // Loop checking, 11.05.2015, T. Koi 298 { 299 icounter++; 300 if (icounter > icounter_max) { 301 G4cout << "Loop-counter exceeded the threshold value at " 302 << __LINE__ << "th line of " << __FILE__ << "." << G4endl; 303 break; 304 } 305 if (isElastic) { 306 // Register 0 K cross-section for DBRC for Doppler broadened elastic scattering kernel 307 G4ParticleHPVector* xsforFS = theIsotopeWiseData[it].MakeChannelData(); 308 // Only G4ParticleHPElasticFS has the RegisterCrossSection method 309 static_cast<G4ParticleHPElasticFS*>(theFinalStates[it])->RegisterCrossSection(xsforFS); 310 } 311 theFinalState = theFinalStates[it]->ApplyYourself(theTrack); 312 } 313 } 314 315 // G4cout <<"THE IMPORTANT RETURN"<<G4endl; 316 // G4cout << "TK G4ParticleHPChannel Elastic, Capture and Fission Cases " 317 //<< " Z= " << this->GetZ(it) << " A = " << this->GetN(it) << G4endl; 318 fManager->GetReactionWhiteBoard()->SetTargA(A); 319 fManager->GetReactionWhiteBoard()->SetTargZ(Z); 320 fManager->GetReactionWhiteBoard()->SetTargM(M); 321 322 return theFinalState; 323 } 324 325 void G4ParticleHPChannel::DumpInfo() const 326 { 327 G4cout << " Element: " << theElement->GetName() << G4endl; 328 G4cout << " Directory name: " << theDir << G4endl; 329 G4cout << " FS name: " << theFSType << G4endl; 330 G4cout << " Number of Isotopes: " << niso << G4endl; 331 G4cout << " Have cross sections: " << G4endl; 332 for (int i = 0; i < niso; i++) { 333 G4cout << theFinalStates[i]->HasXsec() << " "; 334 } 335 G4cout << G4endl; 336 if (theChannelData != nullptr) { 337 G4cout << " Cross Section (total for this channel):" << G4endl; 338 int np = theChannelData->GetVectorLength(); 339 G4cout << np << G4endl; 340 for (int i = 0; i < np; i++) { 341 G4cout << theChannelData->GetEnergy(i) / eV << " " << theChannelData->GetXsec(i) << G4endl; 342 } 343 } 344 } 345